From 7ef28c8097374e154d1bfc59cb421dc7d6e010c2 Mon Sep 17 00:00:00 2001 From: Truecrypt Foundation Date: Wed, 21 Oct 2009 18:58:48 +0200 Subject: [PATCH] TrueCrypt Source Version 6.3 --- Boot/Windows/Bios.h | 56 +- Boot/Windows/BootCommon.h | 145 +- Boot/Windows/BootConfig.cpp | 164 +- Boot/Windows/BootConfig.h | 83 +- Boot/Windows/BootConsoleIo.cpp | 649 +- Boot/Windows/BootConsoleIo.h | 132 +- Boot/Windows/BootCrt.asm | 2 +- Boot/Windows/BootDebug.cpp | 354 +- Boot/Windows/BootDebug.h | 112 +- Boot/Windows/BootDefs.h | 370 +- Boot/Windows/BootDiskIo.cpp | 939 +- Boot/Windows/BootDiskIo.h | 228 +- Boot/Windows/BootEncryptedIo.cpp | 256 +- Boot/Windows/BootEncryptedIo.h | 36 +- Boot/Windows/BootMain.cpp | 2239 +- Boot/Windows/BootMain.h | 60 +- Boot/Windows/BootMemory.cpp | 164 +- Boot/Windows/BootMemory.h | 48 +- Boot/Windows/BootSector.asm | 6 +- Boot/Windows/BootStrings.h | 31 +- Boot/Windows/Decompressor.c | 872 +- Boot/Windows/IntFilter.cpp | 1292 +- Boot/Windows/IntFilter.h | 32 +- Boot/Windows/Makefile | 366 +- Boot/Windows/Platform.cpp | 452 +- Boot/Windows/Platform.h | 224 +- Build/Include/Makefile.inc | 108 +- Build/Resources/MacOSX/Info.plist.xml | 88 +- Common/APIDRVR.H | 596 +- Common/BaseCom.cpp | 425 +- Common/BaseCom.h | 227 +- Common/BootEncryption.cpp | 4454 ++-- Common/BootEncryption.h | 454 +- Common/CACHE.C | 200 +- Common/CACHE.H | 46 +- Common/CMDLINE.C | 534 +- Common/CMDLINE.H | 82 +- Common/COMBO.C | 424 +- Common/COMBO.H | 54 +- Common/CRC.C | 266 +- Common/CRC.H | 70 +- Common/CRYPTO.C | 3434 +-- Common/CRYPTO.H | 640 +- Common/Common.h | 129 +- Common/Common.rc | 2 +- Common/DLGCODE.C | 18314 ++++++++-------- Common/DLGCODE.H | 1008 +- Common/Dictionary.c | 185 +- Common/Dictionary.h | 67 +- Common/ENDIAN.C | 114 +- Common/ENDIAN.H | 294 +- Common/EncryptionThreadPool.c | 991 +- Common/EncryptionThreadPool.h | 74 +- Common/Exception.h | 162 +- Common/FAT.C | 841 +- Common/FAT.H | 132 +- Common/FORMAT.C | 1977 +- Common/FORMAT.H | 139 +- Common/GfMul.c | 1784 +- Common/GfMul.h | 152 +- Common/Inflate.c | 2614 +-- Common/Inflate.h | 102 +- Common/Keyfiles.c | 1320 +- Common/Keyfiles.h | 92 +- Common/Language.c | 1030 +- Common/Language.h | 74 +- Common/Language.xml | 2542 +-- Common/Makefile | 2 +- Common/PASSWORD.C | 850 +- Common/PASSWORD.H | 92 +- Common/PKCS5.C | 1284 +- Common/PKCS5.H | 82 +- Common/PROGRESS.C | 260 +- Common/PROGRESS.H | 44 +- Common/RANDOM.C | 1557 +- Common/RANDOM.H | 122 +- Common/Registry.c | 474 +- Common/Registry.h | 58 +- Common/SecurityToken.cpp | 1522 +- Common/SecurityToken.h | 432 +- Common/TCDEFS.H | 652 +- Common/Tests.c | 3352 +-- Common/Tests.h | 60 +- Common/VOLUMES.C | 2057 +- Common/VOLUMES.H | 272 +- Common/Wipe.c | 374 +- Common/Wipe.h | 80 +- Common/Xml.c | 438 +- Common/Xml.h | 48 +- Common/Xts.c | 881 +- Common/Xts.h | 152 +- Common/resource.h | 335 +- Core/Core.h | 40 +- Core/Core.make | 54 +- Core/CoreBase.cpp | 406 +- Core/CoreBase.h | 194 +- Core/CoreException.cpp | 58 +- Core/CoreException.h | 101 +- Core/FatFormatter.cpp | 690 +- Core/FatFormatter.h | 58 +- Core/HostDevice.cpp | 94 +- Core/HostDevice.h | 90 +- Core/MountOptions.cpp | 252 +- Core/MountOptions.h | 136 +- Core/RandomNumberGenerator.cpp | 420 +- Core/RandomNumberGenerator.h | 110 +- Core/Unix/CoreService.cpp | 1046 +- Core/Unix/CoreService.h | 124 +- Core/Unix/CoreServiceProxy.h | 294 +- Core/Unix/CoreServiceRequest.cpp | 496 +- Core/Unix/CoreServiceRequest.h | 250 +- Core/Unix/CoreServiceResponse.cpp | 208 +- Core/Unix/CoreServiceResponse.h | 150 +- Core/Unix/CoreUnix.cpp | 1184 +- Core/Unix/CoreUnix.h | 136 +- Core/Unix/FreeBSD/CoreFreeBSD.cpp | 404 +- Core/Unix/FreeBSD/CoreFreeBSD.h | 74 +- Core/Unix/FreeBSD/System.h | 24 +- Core/Unix/Linux/CoreLinux.cpp | 931 +- Core/Unix/Linux/CoreLinux.h | 78 +- Core/Unix/Linux/System.h | 24 +- Core/Unix/MacOSX/CoreMacOSX.cpp | 418 +- Core/Unix/MacOSX/CoreMacOSX.h | 72 +- Core/Unix/MacOSX/System.h | 24 +- Core/Unix/MountedFilesystem.h | 54 +- Core/Unix/Solaris/CoreSolaris.cpp | 348 +- Core/Unix/Solaris/CoreSolaris.h | 74 +- Core/Unix/Solaris/System.h | 24 +- Core/Unix/System.h | 24 +- Core/VolumeCreator.cpp | 658 +- Core/VolumeCreator.h | 234 +- Crypto/Aes.h | 430 +- Crypto/AesSmall.c | 1906 +- Crypto/AesSmall.h | 338 +- Crypto/Aes_x64.asm | 11 +- Crypto/Aes_x86.asm | 8 +- Crypto/Aescrypt.c | 622 +- Crypto/Aeskey.c | 1146 +- Crypto/Aesopt.h | 1468 +- Crypto/Aestab.c | 856 +- Crypto/Aestab.h | 348 +- Crypto/BLOWFISH.H | 44 +- Crypto/Blowfish.c | 758 +- Crypto/CAST.H | 46 +- Crypto/Cast.c | 1400 +- Crypto/Crypto.vcproj | 10 +- Crypto/DES.C | 808 +- Crypto/DES.H | 54 +- Crypto/Makefile | 2 +- Crypto/Makefile.inc | 18 +- Crypto/Rmd160.c | 979 +- Crypto/Rmd160.h | 66 +- Crypto/SHA1.C | 564 +- Crypto/SHA1.H | 160 +- Crypto/Serpent.c | 1886 +- Crypto/Serpent.h | 38 +- Crypto/Sha2.c | 1540 +- Crypto/Sha2.h | 310 +- Crypto/Twofish.c | 1096 +- Crypto/Twofish.h | 110 +- Crypto/Whirlpool.c | 2116 +- Crypto/Whirlpool.h | 302 +- Driver/BuildDriver.cmd | 14 +- Driver/DriveFilter.c | 3746 ++-- Driver/DriveFilter.h | 154 +- Driver/Driver.rc | 9 +- Driver/EncryptedIoQueue.c | 2064 +- Driver/EncryptedIoQueue.h | 325 +- Driver/Fuse/Driver.make | 32 +- Driver/Fuse/FuseService.cpp | 1184 +- Driver/Fuse/FuseService.h | 146 +- Driver/MAKEFILE | 2 +- Driver/NTDRIVER.C | 6319 +++--- Driver/NTDRIVER.H | 347 +- Driver/NTVOL.C | 1678 +- Driver/NTVOL.H | 38 +- Driver/VolumeFilter.c | 543 +- Driver/VolumeFilter.h | 38 +- Driver/resource.h | 32 +- Format/Format.manifest | 13 +- Format/Format.rc | 11 +- Format/Format.vcproj | 40 +- Format/FormatCom.cpp | 429 +- Format/FormatCom.h | 62 +- Format/FormatCom.idl | 9 +- Format/InPlace.c | 3380 +-- Format/InPlace.h | 90 +- Format/TCFORMAT.C | 17609 +++++++-------- Format/TCFORMAT.H | 205 +- Format/resource.h | 302 +- License.html | 354 +- License.txt | 1064 +- Main/Application.cpp | 196 +- Main/Application.h | 80 +- Main/CommandLineInterface.cpp | 1127 +- Main/CommandLineInterface.h | 183 +- Main/FatalErrorHandler.cpp | 548 +- Main/FatalErrorHandler.h | 66 +- Main/FavoriteVolume.cpp | 188 +- Main/FavoriteVolume.h | 106 +- Main/Forms/AboutDialog.cpp | 124 +- Main/Forms/AboutDialog.h | 52 +- Main/Forms/ChangePasswordDialog.cpp | 382 +- Main/Forms/ChangePasswordDialog.h | 96 +- Main/Forms/DeviceSelectionDialog.cpp | 240 +- Main/Forms/DeviceSelectionDialog.h | 92 +- Main/Forms/EncryptionOptionsWizardPage.cpp | 268 +- Main/Forms/EncryptionOptionsWizardPage.h | 82 +- Main/Forms/EncryptionTestDialog.cpp | 454 +- Main/Forms/EncryptionTestDialog.h | 80 +- Main/Forms/FavoriteVolumesDialog.cpp | 236 +- Main/Forms/FavoriteVolumesDialog.h | 90 +- Main/Forms/Forms.cpp | 6065 +++-- Main/Forms/Forms.h | 2026 +- Main/Forms/InfoWizardPage.cpp | 66 +- Main/Forms/InfoWizardPage.h | 64 +- Main/Forms/KeyfileGeneratorDialog.cpp | 236 +- Main/Forms/KeyfileGeneratorDialog.h | 68 +- Main/Forms/KeyfilesDialog.cpp | 88 +- Main/Forms/KeyfilesDialog.h | 66 +- Main/Forms/KeyfilesPanel.cpp | 320 +- Main/Forms/KeyfilesPanel.h | 74 +- Main/Forms/LegalNoticesDialog.cpp | 56 +- Main/Forms/LegalNoticesDialog.h | 46 +- Main/Forms/MainFrame.cpp | 3026 ++- Main/Forms/MainFrame.h | 341 +- Main/Forms/MountOptionsDialog.cpp | 348 +- Main/Forms/MountOptionsDialog.h | 84 +- Main/Forms/NewSecurityTokenKeyfileDialog.cpp | 90 +- Main/Forms/NewSecurityTokenKeyfileDialog.h | 60 +- Main/Forms/PreferencesDialog.cpp | 992 +- Main/Forms/PreferencesDialog.h | 118 +- Main/Forms/ProgressWizardPage.cpp | 160 +- Main/Forms/ProgressWizardPage.h | 84 +- Main/Forms/RandomPoolEnrichmentDialog.cpp | 186 +- Main/Forms/RandomPoolEnrichmentDialog.h | 66 +- Main/Forms/SecurityTokenKeyfilesDialog.cpp | 394 +- Main/Forms/SecurityTokenKeyfilesDialog.h | 94 +- Main/Forms/SelectDirectoryWizardPage.cpp | 64 +- Main/Forms/SelectDirectoryWizardPage.h | 66 +- Main/Forms/SingleChoiceWizardPage.h | 232 +- Main/Forms/TrueCrypt.fbp | 630 - .../VolumeCreationProgressWizardPage.cpp | 366 +- Main/Forms/VolumeCreationProgressWizardPage.h | 106 +- Main/Forms/VolumeCreationWizard.cpp | 1870 +- Main/Forms/VolumeCreationWizard.h | 168 +- Main/Forms/VolumeFormatOptionsWizardPage.cpp | 158 +- Main/Forms/VolumeFormatOptionsWizardPage.h | 72 +- Main/Forms/VolumeLocationWizardPage.cpp | 196 +- Main/Forms/VolumeLocationWizardPage.h | 80 +- Main/Forms/VolumePasswordPanel.cpp | 620 +- Main/Forms/VolumePasswordPanel.h | 108 +- Main/Forms/VolumePasswordWizardPage.cpp | 78 +- Main/Forms/VolumePasswordWizardPage.h | 74 +- Main/Forms/VolumePropertiesDialog.cpp | 194 +- Main/Forms/VolumePropertiesDialog.h | 52 +- Main/Forms/VolumeSizeWizardPage.cpp | 252 +- Main/Forms/VolumeSizeWizardPage.h | 98 +- Main/Forms/WizardFrame.cpp | 378 +- Main/Forms/WizardFrame.h | 116 +- Main/Forms/WizardPage.h | 82 +- Main/GraphicUserInterface.cpp | 3305 +-- Main/GraphicUserInterface.h | 319 +- Main/Hotkey.cpp | 482 +- Main/Hotkey.h | 126 +- Main/LanguageStrings.cpp | 172 +- Main/LanguageStrings.h | 80 +- Main/Main.h | 34 +- Main/Main.make | 288 +- Main/Resources.cpp | 368 +- Main/Resources.h | 66 +- Main/StringFormatter.cpp | 176 +- Main/StringFormatter.h | 128 +- Main/System.cpp | 18 +- Main/System.h | 138 +- Main/SystemPrecompiled.h | 58 +- Main/TextUserInterface.cpp | 2899 +-- Main/TextUserInterface.h | 155 +- Main/Unix/Main.cpp | 254 +- Main/UserInterface.cpp | 2891 +-- Main/UserInterface.h | 221 +- Main/UserInterfaceException.h | 72 +- Main/UserInterfaceType.h | 50 +- Main/UserPreferences.cpp | 466 +- Main/UserPreferences.h | 206 +- Main/VolumeHistory.cpp | 304 +- Main/VolumeHistory.h | 90 +- Main/Xml.cpp | 356 +- Main/Xml.h | 150 +- Makefile | 523 +- Mount/Hotkeys.c | 1050 +- Mount/Hotkeys.h | 96 +- Mount/MainCom.cpp | 473 +- Mount/MainCom.h | 62 +- Mount/MainCom.idl | 9 +- Mount/Mount.c | 15810 ++++++------- Mount/Mount.h | 209 +- Mount/Mount.manifest | 13 +- Mount/Mount.rc | 38 +- Mount/Mount.vcproj | 40 +- Mount/resource.h | 418 +- Platform/Buffer.cpp | 284 +- Platform/Buffer.h | 230 +- Platform/Directory.h | 58 +- Platform/Event.cpp | 94 +- Platform/Event.h | 172 +- Platform/Exception.cpp | 104 +- Platform/Exception.h | 220 +- Platform/File.h | 220 +- Platform/FileCommon.cpp | 174 +- Platform/FileStream.h | 116 +- Platform/FilesystemPath.h | 146 +- Platform/Finally.h | 92 +- Platform/ForEach.h | 236 +- Platform/Functor.h | 58 +- Platform/Memory.cpp | 114 +- Platform/Memory.h | 348 +- Platform/MemoryStream.cpp | 94 +- Platform/MemoryStream.h | 72 +- Platform/Mutex.h | 122 +- Platform/Platform.h | 56 +- Platform/Platform.make | 70 +- Platform/PlatformBase.h | 260 +- Platform/PlatformTest.cpp | 700 +- Platform/PlatformTest.h | 86 +- Platform/Serializable.cpp | 78 +- Platform/Serializable.h | 164 +- Platform/Serializer.cpp | 598 +- Platform/Serializer.h | 148 +- Platform/SerializerFactory.cpp | 108 +- Platform/SerializerFactory.h | 186 +- Platform/SharedPtr.h | 302 +- Platform/SharedVal.h | 142 +- Platform/Stream.h | 68 +- Platform/StringConverter.cpp | 734 +- Platform/StringConverter.h | 120 +- Platform/SyncEvent.h | 94 +- Platform/System.h | 32 +- Platform/SystemException.h | 92 +- Platform/SystemInfo.h | 54 +- Platform/SystemLog.h | 84 +- Platform/TextReader.cpp | 74 +- Platform/TextReader.h | 70 +- Platform/Thread.h | 148 +- Platform/Time.h | 60 +- Platform/Unix/Directory.cpp | 124 +- Platform/Unix/File.cpp | 691 +- Platform/Unix/FilesystemPath.cpp | 192 +- Platform/Unix/Mutex.cpp | 124 +- Platform/Unix/Pipe.cpp | 130 +- Platform/Unix/Pipe.h | 76 +- Platform/Unix/Poller.cpp | 114 +- Platform/Unix/Poller.h | 66 +- Platform/Unix/Process.cpp | 398 +- Platform/Unix/Process.h | 80 +- Platform/Unix/SyncEvent.cpp | 136 +- Platform/Unix/System.h | 24 +- Platform/Unix/SystemException.cpp | 132 +- Platform/Unix/SystemInfo.cpp | 110 +- Platform/Unix/SystemLog.cpp | 54 +- Platform/Unix/Thread.cpp | 108 +- Platform/Unix/Time.cpp | 46 +- Platform/User.h | 64 +- Readme.txt | 413 +- Release/Setup Files/License.txt | 1064 +- Release/Setup Files/TrueCrypt User Guide.pdf | Bin 880233 -> 1066371 bytes Resources/Texts/License.rtf | 166 +- Volume/Cipher.cpp | 424 +- Volume/Cipher.h | 216 +- Volume/Crc32.h | 88 +- Volume/EncryptionAlgorithm.cpp | 690 +- Volume/EncryptionAlgorithm.h | 186 +- Volume/EncryptionMode.cpp | 126 +- Volume/EncryptionMode.h | 122 +- Volume/EncryptionModeCBC.cpp | 670 +- Volume/EncryptionModeCBC.h | 94 +- Volume/EncryptionModeLRW.cpp | 390 +- Volume/EncryptionModeLRW.h | 100 +- Volume/EncryptionModeXTS.cpp | 660 +- Volume/EncryptionModeXTS.h | 100 +- Volume/EncryptionTest.cpp | 1722 +- Volume/EncryptionTest.h | 98 +- Volume/EncryptionThreadPool.cpp | 642 +- Volume/EncryptionThreadPool.h | 174 +- Volume/Hash.cpp | 276 +- Volume/Hash.h | 270 +- Volume/Keyfile.cpp | 328 +- Volume/Keyfile.h | 92 +- Volume/Pkcs5Kdf.cpp | 192 +- Volume/Pkcs5Kdf.h | 254 +- Volume/Version.h | 50 +- Volume/Volume.cpp | 752 +- Volume/Volume.h | 252 +- Volume/Volume.make | 100 +- Volume/VolumeException.cpp | 64 +- Volume/VolumeException.h | 82 +- Volume/VolumeHeader.cpp | 608 +- Volume/VolumeHeader.h | 248 +- Volume/VolumeInfo.cpp | 236 +- Volume/VolumeInfo.h | 132 +- Volume/VolumeLayout.cpp | 508 +- Volume/VolumeLayout.h | 306 +- Volume/VolumePassword.cpp | 334 +- Volume/VolumePassword.h | 184 +- Volume/VolumePasswordCache.cpp | 86 +- Volume/VolumePasswordCache.h | 72 +- Volume/VolumeSlot.h | 38 +- 407 files changed, 111858 insertions(+), 111251 deletions(-) diff --git a/Boot/Windows/Bios.h b/Boot/Windows/Bios.h index e52c751..bd62cb4 100644 --- a/Boot/Windows/Bios.h +++ b/Boot/Windows/Bios.h @@ -1,28 +1,28 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_Bios -#define TC_HEADER_Boot_Bios - -#include "Platform.h" - -#define TC_LB_SIZE_BIT_SHIFT_DIVISOR 9 - -#define TC_FIRST_BIOS_DRIVE 0x80 -#define TC_LAST_BIOS_DRIVE 0x8f -#define TC_INVALID_BIOS_DRIVE (TC_FIRST_BIOS_DRIVE - 1) - -enum -{ - BiosResultSuccess = 0x00, - BiosResultInvalidFunction = 0x01 -}; - -typedef byte BiosResult; - -#endif // TC_HEADER_Boot_Bios +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_Bios +#define TC_HEADER_Boot_Bios + +#include "Platform.h" + +#define TC_LB_SIZE_BIT_SHIFT_DIVISOR 9 + +#define TC_FIRST_BIOS_DRIVE 0x80 +#define TC_LAST_BIOS_DRIVE 0x8f +#define TC_INVALID_BIOS_DRIVE (TC_FIRST_BIOS_DRIVE - 1) + +enum +{ + BiosResultSuccess = 0x00, + BiosResultInvalidFunction = 0x01 +}; + +typedef byte BiosResult; + +#endif // TC_HEADER_Boot_Bios diff --git a/Boot/Windows/BootCommon.h b/Boot/Windows/BootCommon.h index 2625cdd..252ac21 100644 --- a/Boot/Windows/BootCommon.h +++ b/Boot/Windows/BootCommon.h @@ -1,68 +1,77 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootCommon -#define TC_HEADER_Boot_BootCommon - -#include "Common/Password.h" -#include "BootDefs.h" - - -#define TC_BOOT_LOADER_AREA_SIZE (TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE) - -#define TC_BOOT_VOLUME_HEADER_SECTOR (TC_BOOT_LOADER_AREA_SECTOR_COUNT - 1) -#define TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET (TC_BOOT_VOLUME_HEADER_SECTOR * SECTOR_SIZE) - -#define TC_CD_BOOTSECTOR_OFFSET 0xd000 -#define TC_CD_BOOT_LOADER_SECTOR 26 - -#define TC_ORIG_BOOT_LOADER_BACKUP_SECTOR TC_BOOT_LOADER_AREA_SECTOR_COUNT -#define TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET (TC_ORIG_BOOT_LOADER_BACKUP_SECTOR * SECTOR_SIZE) - -#define TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR (TC_ORIG_BOOT_LOADER_BACKUP_SECTOR + TC_BOOT_LOADER_AREA_SECTOR_COUNT) -#define TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET (TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR * SECTOR_SIZE) - -#define TC_MBR_SECTOR 0 -#define TC_MAX_MBR_BOOT_CODE_SIZE 440 - - -#pragma pack (1) - -typedef struct -{ - byte Flags; -} BootSectorConfiguration; - - -// Modifying this value can introduce incompatibility with previous versions -#define TC_BOOT_LOADER_ARGS_OFFSET 0x10 - -typedef struct -{ - // Modifying this structure can introduce incompatibility with previous versions - char Signature[8]; - uint16 BootLoaderVersion; - uint16 CryptoInfoOffset; - uint16 CryptoInfoLength; - uint32 HeaderSaltCrc32; - Password BootPassword; - uint64 HiddenSystemPartitionStart; - uint64 DecoySystemPartitionStart; - uint32 BootArgumentsCrc32; - -} BootArguments; - -#pragma pack () - -// Boot arguments signature should not be defined as a static string -// Modifying these values can introduce incompatibility with previous versions -#define TC_SET_BOOT_ARGUMENTS_SIGNATURE(SG) do { SG[0] = 'T'; SG[1] = 'R'; SG[2] = 'U'; SG[3] = 'E'; SG[4] = 0x11; SG[5] = 0x23; SG[6] = 0x45; SG[7] = 0x66; } while (FALSE) -#define TC_IS_BOOT_ARGUMENTS_SIGNATURE(SG) (SG[0] == 'T' && SG[1] == 'R' && SG[2] == 'U' && SG[3] == 'E' && SG[4] == 0x11 && SG[5] == 0x23 && SG[6] == 0x45 && SG[7] == 0x66) - - -#endif // TC_HEADER_Boot_BootCommon +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootCommon +#define TC_HEADER_Boot_BootCommon + +#include "Common/Password.h" +#include "BootDefs.h" + +// The user will be advised to upgrade the rescue disk if upgrading from the following or any previous version +#define TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION 0x060a + +#define TC_BOOT_LOADER_AREA_SIZE (TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE) + +#define TC_BOOT_VOLUME_HEADER_SECTOR (TC_BOOT_LOADER_AREA_SECTOR_COUNT - 1) +#define TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET (TC_BOOT_VOLUME_HEADER_SECTOR * SECTOR_SIZE) + +#define TC_CD_BOOTSECTOR_OFFSET 0xd000 +#define TC_CD_BOOT_LOADER_SECTOR 26 + +#define TC_ORIG_BOOT_LOADER_BACKUP_SECTOR TC_BOOT_LOADER_AREA_SECTOR_COUNT +#define TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET (TC_ORIG_BOOT_LOADER_BACKUP_SECTOR * SECTOR_SIZE) + +#define TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR (TC_ORIG_BOOT_LOADER_BACKUP_SECTOR + TC_BOOT_LOADER_AREA_SECTOR_COUNT) +#define TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET (TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR * SECTOR_SIZE) + +#define TC_MBR_SECTOR 0 +#define TC_MAX_MBR_BOOT_CODE_SIZE 440 + +#define TC_MAX_EXTRA_BOOT_PARTITION_SIZE (256UL * 1024UL * 1024UL) + + +#pragma pack (1) + +typedef struct +{ + byte Flags; +} BootSectorConfiguration; + + +// Modifying this value can introduce incompatibility with previous versions +#define TC_BOOT_LOADER_ARGS_OFFSET 0x10 + +typedef struct +{ + // Modifying this structure can introduce incompatibility with previous versions + char Signature[8]; + uint16 BootLoaderVersion; + uint16 CryptoInfoOffset; + uint16 CryptoInfoLength; + uint32 HeaderSaltCrc32; + Password BootPassword; + uint64 HiddenSystemPartitionStart; + uint64 DecoySystemPartitionStart; + uint32 Flags; + + uint32 BootArgumentsCrc32; + +} BootArguments; + +// Modifying these values can introduce incompatibility with previous versions +#define TC_BOOT_ARGS_FLAG_EXTRA_BOOT_PARTITION 0x1 + +#pragma pack () + +// Boot arguments signature should not be defined as a static string +// Modifying these values can introduce incompatibility with previous versions +#define TC_SET_BOOT_ARGUMENTS_SIGNATURE(SG) do { SG[0] = 'T'; SG[1] = 'R'; SG[2] = 'U'; SG[3] = 'E'; SG[4] = 0x11; SG[5] = 0x23; SG[6] = 0x45; SG[7] = 0x66; } while (FALSE) +#define TC_IS_BOOT_ARGUMENTS_SIGNATURE(SG) (SG[0] == 'T' && SG[1] == 'R' && SG[2] == 'U' && SG[3] == 'E' && SG[4] == 0x11 && SG[5] == 0x23 && SG[6] == 0x45 && SG[7] == 0x66) + + +#endif // TC_HEADER_Boot_BootCommon diff --git a/Boot/Windows/BootConfig.cpp b/Boot/Windows/BootConfig.cpp index f1dbf8c..06382e4 100644 --- a/Boot/Windows/BootConfig.cpp +++ b/Boot/Windows/BootConfig.cpp @@ -1,82 +1,82 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "BootConfig.h" - -byte BootSectorFlags; - -byte BootLoaderDrive; -byte BootDrive; -bool BootDriveGeometryValid = false; -bool PreventNormalSystemBoot = false; -bool PreventBootMenu = false; -char CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; -uint32 OuterVolumeBackupHeaderCrc; - -bool BootStarted = false; - -DriveGeometry BootDriveGeometry; - -CRYPTO_INFO *BootCryptoInfo; -Partition EncryptedVirtualPartition; - -Partition ActivePartition; -Partition PartitionFollowingActive; -uint64 HiddenVolumeStartUnitNo; -uint64 HiddenVolumeStartSector; - - -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - -void ReadBootSectorUserConfiguration () -{ - byte userConfig; - - AcquireSectorBuffer(); - - if (ReadWriteMBR (false, BootLoaderDrive, true) != BiosResultSuccess) - goto ret; - - userConfig = SectorBuffer[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; - PreventBootMenu = (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_ESC); - - memcpy (CustomUserMessage, SectorBuffer + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); - CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0; - - if (userConfig & TC_BOOT_USER_CFG_FLAG_SILENT_MODE) - { - if (CustomUserMessage[0]) - Print (CustomUserMessage); - - DisableScreenOutput(); - } - - OuterVolumeBackupHeaderCrc = *(uint32 *) (SectorBuffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET); - -ret: - ReleaseSectorBuffer(); -} - - -BiosResult UpdateBootSectorConfiguration (byte drive) -{ - AcquireSectorBuffer(); - - BiosResult result = ReadWriteMBR (false, drive); - if (result != BiosResultSuccess) - goto ret; - - SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] = BootSectorFlags; - result = ReadWriteMBR (true, drive); - -ret: - ReleaseSectorBuffer(); - return result; -} - -#endif // !TC_WINDOWS_BOOT_RESCUE_DISK_MODE +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "BootConfig.h" + +byte BootSectorFlags; + +byte BootLoaderDrive; +byte BootDrive; +bool BootDriveGeometryValid = false; +bool PreventNormalSystemBoot = false; +bool PreventBootMenu = false; +char CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; +uint32 OuterVolumeBackupHeaderCrc; + +bool BootStarted = false; + +DriveGeometry BootDriveGeometry; + +CRYPTO_INFO *BootCryptoInfo; +Partition EncryptedVirtualPartition; + +Partition ActivePartition; +Partition PartitionFollowingActive; +bool ExtraBootPartitionPresent = false; +uint64 HiddenVolumeStartUnitNo; +uint64 HiddenVolumeStartSector; + +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + +void ReadBootSectorUserConfiguration () +{ + byte userConfig; + + AcquireSectorBuffer(); + + if (ReadWriteMBR (false, BootLoaderDrive, true) != BiosResultSuccess) + goto ret; + + userConfig = SectorBuffer[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; + PreventBootMenu = (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_ESC); + + memcpy (CustomUserMessage, SectorBuffer + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); + CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0; + + if (userConfig & TC_BOOT_USER_CFG_FLAG_SILENT_MODE) + { + if (CustomUserMessage[0]) + Print (CustomUserMessage); + + DisableScreenOutput(); + } + + OuterVolumeBackupHeaderCrc = *(uint32 *) (SectorBuffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET); + +ret: + ReleaseSectorBuffer(); +} + + +BiosResult UpdateBootSectorConfiguration (byte drive) +{ + AcquireSectorBuffer(); + + BiosResult result = ReadWriteMBR (false, drive); + if (result != BiosResultSuccess) + goto ret; + + SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] = BootSectorFlags; + result = ReadWriteMBR (true, drive); + +ret: + ReleaseSectorBuffer(); + return result; +} + +#endif // !TC_WINDOWS_BOOT_RESCUE_DISK_MODE diff --git a/Boot/Windows/BootConfig.h b/Boot/Windows/BootConfig.h index 26c62ae..f0cca96 100644 --- a/Boot/Windows/BootConfig.h +++ b/Boot/Windows/BootConfig.h @@ -1,41 +1,42 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootConfig -#define TC_HEADER_Boot_BootConfig - -#include "Crypto.h" -#include "Platform.h" -#include "BootDiskIo.h" - -extern byte BootSectorFlags; - -extern byte BootLoaderDrive; -extern byte BootDrive; -extern bool BootDriveGeometryValid; -extern DriveGeometry BootDriveGeometry; -extern bool PreventNormalSystemBoot; -extern bool PreventBootMenu; -extern char CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; -extern uint32 OuterVolumeBackupHeaderCrc; - -extern bool BootStarted; - -extern CRYPTO_INFO *BootCryptoInfo; -extern Partition EncryptedVirtualPartition; - -extern Partition ActivePartition; -extern Partition PartitionFollowingActive; -extern uint64 HiddenVolumeStartUnitNo; -extern uint64 HiddenVolumeStartSector; - - -void ReadBootSectorUserConfiguration (); -BiosResult UpdateBootSectorConfiguration (byte drive); - -#endif // TC_HEADER_Boot_BootConfig +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootConfig +#define TC_HEADER_Boot_BootConfig + +#include "Crypto.h" +#include "Platform.h" +#include "BootDiskIo.h" + +extern byte BootSectorFlags; + +extern byte BootLoaderDrive; +extern byte BootDrive; +extern bool BootDriveGeometryValid; +extern DriveGeometry BootDriveGeometry; +extern bool PreventNormalSystemBoot; +extern bool PreventBootMenu; +extern char CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; +extern uint32 OuterVolumeBackupHeaderCrc; + +extern bool BootStarted; + +extern CRYPTO_INFO *BootCryptoInfo; +extern Partition EncryptedVirtualPartition; + +extern Partition ActivePartition; +extern Partition PartitionFollowingActive; +extern bool ExtraBootPartitionPresent; +extern uint64 HiddenVolumeStartUnitNo; +extern uint64 HiddenVolumeStartSector; + + +void ReadBootSectorUserConfiguration (); +BiosResult UpdateBootSectorConfiguration (byte drive); + +#endif // TC_HEADER_Boot_BootConfig diff --git a/Boot/Windows/BootConsoleIo.cpp b/Boot/Windows/BootConsoleIo.cpp index f8af3b8..9e102db 100644 --- a/Boot/Windows/BootConsoleIo.cpp +++ b/Boot/Windows/BootConsoleIo.cpp @@ -1,319 +1,330 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform.h" -#include "Bios.h" -#include "BootConsoleIo.h" -#include "BootDebug.h" - - -static int ScreenOutputDisabled = 0; - -void DisableScreenOutput () -{ - ++ScreenOutputDisabled; -} - - -void EnableScreenOutput () -{ - --ScreenOutputDisabled; -} - - -void PrintChar (char c) -{ -#ifdef TC_BOOT_TRACING_ENABLED - WriteDebugPort (c); -#endif - - if (ScreenOutputDisabled) - return; - - __asm - { - mov bx, 7 - mov al, c - mov ah, 0xe - int 0x10 - } -} - - -void PrintCharAtCursor (char c) -{ - if (ScreenOutputDisabled) - return; - - __asm - { - mov bx, 7 - mov al, c - mov cx, 1 - mov ah, 0xa - int 0x10 - } -} - - -void Print (const char *str) -{ - char c; - while (c = *str++) - PrintChar (c); -} - - -void Print (uint32 number) -{ - char str[12]; - int pos = 0; - while (number >= 10) - { - str[pos++] = (number % 10) + '0'; - number /= 10; - } - str[pos] = (number % 10) + '0'; - - while (pos >= 0) - PrintChar (str[pos--]); -} - - -void Print (const uint64 &number) -{ - if (number.HighPart == 0) - Print (number.LowPart); - else - PrintHex (number); -} - - -void PrintHex (byte b) -{ - PrintChar (((b >> 4) >= 0xA ? 'A' - 0xA : '0') + (b >> 4)); - PrintChar (((b & 0xF) >= 0xA ? 'A' - 0xA : '0') + (b & 0xF)); -} - - -void PrintHex (uint16 data) -{ - PrintHex (byte (data >> 8)); - PrintHex (byte (data)); -} - - -void PrintHex (uint32 data) -{ - PrintHex (uint16 (data >> 16)); - PrintHex (uint16 (data)); -} - - -void PrintHex (const uint64 &data) -{ - PrintHex (data.HighPart); - PrintHex (data.LowPart); -} - -void PrintRepeatedChar (char c, int n) -{ - while (n-- > 0) - PrintChar (c); -} - - -void PrintEndl () -{ - Print ("\r\n"); -} - - -void PrintEndl (int cnt) -{ - while (cnt-- > 0) - PrintEndl (); -} - - -void Beep () -{ - PrintChar (7); -} - - -void InitVideoMode () -{ - if (ScreenOutputDisabled) - return; - - __asm - { - // Text mode 80x25 - mov ax, 3 - int 0x10 - - // Page 0 - mov ax, 0x500 - int 0x10 - } -} - - -void ClearScreen () -{ - if (ScreenOutputDisabled) - return; - - __asm - { - // White text on black - mov bh, 7 - xor cx, cx - mov dx, 0x184f - mov ax, 0x600 - int 0x10 - - // Cursor at 0,0 - xor bh, bh - xor dx, dx - mov ah, 2 - int 0x10 - } -} - - -void PrintBackspace () -{ - PrintChar (TC_BIOS_CHAR_BACKSPACE); - PrintCharAtCursor (' '); -} - - -void PrintError (const char *message, bool beep, bool newLine) -{ - Print ("Error: "); - Print (message); - - if (newLine) - PrintEndl(); - - if (beep) - Beep(); -} - - -byte GetShiftFlags () -{ - byte flags; - __asm - { - mov ah, 2 - int 0x16 - mov flags, al - } - - return flags; -} - - -byte GetKeyboardChar (byte *scanCode) -{ - // Work around a bug in the Apple BIOS - while (!IsKeyboardCharAvailable()); - - byte asciiCode; - byte scan; - __asm - { - mov ah, 0 - int 0x16 - mov asciiCode, al - mov scan, ah - } - - if (scanCode) - *scanCode = scan; - - return asciiCode; -} - - -bool IsKeyboardCharAvailable () -{ - bool available = false; - __asm - { - mov ah, 1 - int 0x16 - jz not_avail - mov available, true - not_avail: - } - - return available; -} - - -bool EscKeyPressed () -{ - if (IsKeyboardCharAvailable ()) - { - byte keyScanCode; - GetKeyboardChar (&keyScanCode); - return keyScanCode == TC_BIOS_KEY_ESC; - } - - return false; -} - - -void ClearBiosKeystrokeBuffer () -{ - __asm - { - push es - xor ax, ax - mov es, ax - mov di, 0x41e - mov cx, 32 - cld - rep stosb - pop es - } -} - - -bool IsPrintable (char c) -{ - return c >= ' ' && c <= '~'; -} - - -int GetString (char *buffer, size_t bufferSize) -{ - byte c; - byte scanCode; - size_t pos = 0; - - while (pos < bufferSize) - { - c = GetKeyboardChar (&scanCode); - - if (scanCode == TC_BIOS_KEY_ENTER) - break; - - if (scanCode == TC_BIOS_KEY_ESC) - return 0; - - buffer[pos++] = c; - PrintChar (IsPrintable (c) ? c : ' '); - } - - return pos; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform.h" +#include "Bios.h" +#include "BootConsoleIo.h" +#include "BootDebug.h" +#include "BootStrings.h" + + +static int ScreenOutputDisabled = 0; + +void DisableScreenOutput () +{ + ++ScreenOutputDisabled; +} + + +void EnableScreenOutput () +{ + --ScreenOutputDisabled; +} + + +void PrintChar (char c) +{ +#ifdef TC_BOOT_TRACING_ENABLED + WriteDebugPort (c); +#endif + + if (ScreenOutputDisabled) + return; + + __asm + { + mov bx, 7 + mov al, c + mov ah, 0xe + int 0x10 + } +} + + +void PrintCharAtCursor (char c) +{ + if (ScreenOutputDisabled) + return; + + __asm + { + mov bx, 7 + mov al, c + mov cx, 1 + mov ah, 0xa + int 0x10 + } +} + + +void Print (const char *str) +{ + char c; + while (c = *str++) + PrintChar (c); +} + + +void Print (uint32 number) +{ + char str[12]; + int pos = 0; + while (number >= 10) + { + str[pos++] = (char) (number % 10) + '0'; + number /= 10; + } + str[pos] = (char) (number % 10) + '0'; + + while (pos >= 0) + PrintChar (str[pos--]); +} + + +void Print (const uint64 &number) +{ + if (number.HighPart == 0) + Print (number.LowPart); + else + PrintHex (number); +} + + +void PrintHex (byte b) +{ + PrintChar (((b >> 4) >= 0xA ? 'A' - 0xA : '0') + (b >> 4)); + PrintChar (((b & 0xF) >= 0xA ? 'A' - 0xA : '0') + (b & 0xF)); +} + + +void PrintHex (uint16 data) +{ + PrintHex (byte (data >> 8)); + PrintHex (byte (data)); +} + + +void PrintHex (uint32 data) +{ + PrintHex (uint16 (data >> 16)); + PrintHex (uint16 (data)); +} + + +void PrintHex (const uint64 &data) +{ + PrintHex (data.HighPart); + PrintHex (data.LowPart); +} + +void PrintRepeatedChar (char c, int n) +{ + while (n-- > 0) + PrintChar (c); +} + + +void PrintEndl () +{ + Print ("\r\n"); +} + + +void PrintEndl (int cnt) +{ + while (cnt-- > 0) + PrintEndl (); +} + + +void Beep () +{ + PrintChar (7); +} + + +void InitVideoMode () +{ + if (ScreenOutputDisabled) + return; + + __asm + { + // Text mode 80x25 + mov ax, 3 + int 0x10 + + // Page 0 + mov ax, 0x500 + int 0x10 + } +} + + +void ClearScreen () +{ + if (ScreenOutputDisabled) + return; + + __asm + { + // White text on black + mov bh, 7 + xor cx, cx + mov dx, 0x184f + mov ax, 0x600 + int 0x10 + + // Cursor at 0,0 + xor bh, bh + xor dx, dx + mov ah, 2 + int 0x10 + } +} + + +void PrintBackspace () +{ + PrintChar (TC_BIOS_CHAR_BACKSPACE); + PrintCharAtCursor (' '); +} + + +void PrintError (const char *message) +{ + Print (TC_BOOT_STR_ERROR); + Print (message); + PrintEndl(); + Beep(); +} + + +void PrintErrorNoEndl (const char *message) +{ + Print (TC_BOOT_STR_ERROR); + Print (message); + Beep(); +} + + +byte GetShiftFlags () +{ + byte flags; + __asm + { + mov ah, 2 + int 0x16 + mov flags, al + } + + return flags; +} + + +byte GetKeyboardChar () +{ + return GetKeyboardChar (nullptr); +} + + +byte GetKeyboardChar (byte *scanCode) +{ + // Work around potential BIOS bugs (Windows boot manager polls the keystroke buffer) + while (!IsKeyboardCharAvailable()); + + byte asciiCode; + byte scan; + __asm + { + mov ah, 0 + int 0x16 + mov asciiCode, al + mov scan, ah + } + + if (scanCode) + *scanCode = scan; + + return asciiCode; +} + + +bool IsKeyboardCharAvailable () +{ + bool available = false; + __asm + { + mov ah, 1 + int 0x16 + jz not_avail + mov available, true + not_avail: + } + + return available; +} + + +bool EscKeyPressed () +{ + if (IsKeyboardCharAvailable ()) + { + byte keyScanCode; + GetKeyboardChar (&keyScanCode); + return keyScanCode == TC_BIOS_KEY_ESC; + } + + return false; +} + + +void ClearBiosKeystrokeBuffer () +{ + __asm + { + push es + xor ax, ax + mov es, ax + mov di, 0x41e + mov cx, 32 + cld + rep stosb + pop es + } +} + + +bool IsPrintable (char c) +{ + return c >= ' ' && c <= '~'; +} + + +int GetString (char *buffer, size_t bufferSize) +{ + byte c; + byte scanCode; + size_t pos = 0; + + while (pos < bufferSize) + { + c = GetKeyboardChar (&scanCode); + + if (scanCode == TC_BIOS_KEY_ENTER) + break; + + if (scanCode == TC_BIOS_KEY_ESC) + return 0; + + buffer[pos++] = c; + PrintChar (IsPrintable (c) ? c : ' '); + } + + return pos; +} diff --git a/Boot/Windows/BootConsoleIo.h b/Boot/Windows/BootConsoleIo.h index 471519c..f5a0a26 100644 --- a/Boot/Windows/BootConsoleIo.h +++ b/Boot/Windows/BootConsoleIo.h @@ -1,65 +1,67 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootConsoleIo -#define TC_HEADER_Boot_BootConsoleIo - -#include "Platform.h" - -#define TC_DEBUG_PORT 0 - -#define TC_BIOS_KEY_ESC 1 -#define TC_BIOS_KEY_BACKSPACE 14 -#define TC_BIOS_KEY_ENTER 28 -#define TC_BIOS_KEY_F1 0x3b -#define TC_BIOS_KEY_F2 0x3c -#define TC_BIOS_KEY_F3 0x3d -#define TC_BIOS_KEY_F4 0x3e -#define TC_BIOS_KEY_F5 0x3f -#define TC_BIOS_KEY_F6 0x40 -#define TC_BIOS_KEY_F7 0x41 -#define TC_BIOS_KEY_F8 0x42 -#define TC_BIOS_KEY_F9 0x43 -#define TC_BIOS_KEY_F10 0x44 - -#define TC_BIOS_SHIFTMASK_CAPSLOCK (1 << 6) -#define TC_BIOS_SHIFTMASK_LSHIFT (1 << 1) -#define TC_BIOS_SHIFTMASK_RSHIFT (1 << 0) - -#define TC_BIOS_CHAR_BACKSPACE 8 - -#define TC_BIOS_MAX_CHARS_PER_LINE 80 - -void Beep (); -void ClearBiosKeystrokeBuffer (); -void ClearScreen (); -void DisableScreenOutput (); -void EnableScreenOutput (); -bool EscKeyPressed (); -byte GetKeyboardChar (byte *scanCode = nullptr); -byte GetShiftFlags (); -int GetString (char *buffer, size_t bufferSize); -void InitVideoMode (); -bool IsKeyboardCharAvailable (); -bool IsPrintable (char c); -void Print (const char *str); -void Print (uint32 number); -void Print (const uint64 &number); -void PrintBackspace (); -void PrintChar (char c); -void PrintCharAtCursor (char c); -void PrintEndl (); -void PrintEndl (int cnt); -void PrintRepeatedChar (char c, int n); -void PrintError (const char *message, bool beep = true, bool newLine = true); -void PrintHex (byte b); -void PrintHex (uint16 data); -void PrintHex (uint32 data); -void PrintHex (const uint64 &data); - -#endif // TC_HEADER_Boot_BootConsoleIo +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootConsoleIo +#define TC_HEADER_Boot_BootConsoleIo + +#include "Platform.h" + +#define TC_DEBUG_PORT 0 + +#define TC_BIOS_KEY_ESC 1 +#define TC_BIOS_KEY_BACKSPACE 14 +#define TC_BIOS_KEY_ENTER 28 +#define TC_BIOS_KEY_F1 0x3b +#define TC_BIOS_KEY_F2 0x3c +#define TC_BIOS_KEY_F3 0x3d +#define TC_BIOS_KEY_F4 0x3e +#define TC_BIOS_KEY_F5 0x3f +#define TC_BIOS_KEY_F6 0x40 +#define TC_BIOS_KEY_F7 0x41 +#define TC_BIOS_KEY_F8 0x42 +#define TC_BIOS_KEY_F9 0x43 +#define TC_BIOS_KEY_F10 0x44 + +#define TC_BIOS_SHIFTMASK_CAPSLOCK (1 << 6) +#define TC_BIOS_SHIFTMASK_LSHIFT (1 << 1) +#define TC_BIOS_SHIFTMASK_RSHIFT (1 << 0) + +#define TC_BIOS_CHAR_BACKSPACE 8 + +#define TC_BIOS_MAX_CHARS_PER_LINE 80 + +void Beep (); +void ClearBiosKeystrokeBuffer (); +void ClearScreen (); +void DisableScreenOutput (); +void EnableScreenOutput (); +bool EscKeyPressed (); +byte GetKeyboardChar (); +byte GetKeyboardChar (byte *scanCode); +byte GetShiftFlags (); +int GetString (char *buffer, size_t bufferSize); +void InitVideoMode (); +bool IsKeyboardCharAvailable (); +bool IsPrintable (char c); +void Print (const char *str); +void Print (uint32 number); +void Print (const uint64 &number); +void PrintBackspace (); +void PrintChar (char c); +void PrintCharAtCursor (char c); +void PrintEndl (); +void PrintEndl (int cnt); +void PrintRepeatedChar (char c, int n); +void PrintError (const char *message); +void PrintErrorNoEndl (const char *message); +void PrintHex (byte b); +void PrintHex (uint16 data); +void PrintHex (uint32 data); +void PrintHex (const uint64 &data); + +#endif // TC_HEADER_Boot_BootConsoleIo diff --git a/Boot/Windows/BootCrt.asm b/Boot/Windows/BootCrt.asm index 7cada2e..7c28e41 100644 --- a/Boot/Windows/BootCrt.asm +++ b/Boot/Windows/BootCrt.asm @@ -1,7 +1,7 @@ ; ; Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. ; -; Governed by the TrueCrypt License 2.7 the full text of which is contained +; Governed by the TrueCrypt License 2.8 the full text of which is contained ; in the file License.txt included in TrueCrypt binary and source code ; distribution packages. ; diff --git a/Boot/Windows/BootDebug.cpp b/Boot/Windows/BootDebug.cpp index 0d48958..fd4255c 100644 --- a/Boot/Windows/BootDebug.cpp +++ b/Boot/Windows/BootDebug.cpp @@ -1,177 +1,177 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform.h" -#include "Bios.h" -#include "BootConsoleIo.h" -#include "BootDefs.h" -#include "BootDiskIo.h" -#include "BootDebug.h" - - -#ifdef TC_BOOT_TRACING_ENABLED - -void InitDebugPort () -{ - __asm - { - mov dx, TC_DEBUG_PORT - mov ah, 1 - int 0x17 - mov dx, TC_DEBUG_PORT - mov ah, 0xe2 - int 0x17 - } -} - - -void WriteDebugPort (byte dataByte) -{ - __asm - { - mov al, dataByte - mov dx, TC_DEBUG_PORT - mov ah, 0 - int 0x17 - } -} - -#endif // TC_BOOT_TRACING_ENABLED - - -#ifdef TC_BOOT_DEBUG_ENABLED - -extern "C" void PrintDebug (uint32 debugVal) -{ - Print (debugVal); - PrintEndl(); -} - - -void PrintVal (const char *message, const uint32 value, bool newLine, bool hex) -{ - Print (message); - Print (": "); - - if (hex) - PrintHex (value); - else - Print (value); - - if (newLine) - PrintEndl(); -} - - -void PrintVal (const char *message, const uint64 &value, bool newLine, bool hex) -{ - Print (message); - Print (": "); - PrintHex (value); - if (newLine) - PrintEndl(); -} - - -void PrintHexDump (byte *mem, size_t size, uint16 *memSegment) -{ - const size_t width = 16; - for (size_t pos = 0; pos < size; ) - { - for (int pass = 1; pass <= 2; ++pass) - { - size_t i; - for (i = 0; i < width && pos < size; ++i) - { - byte dataByte; - if (memSegment) - { - __asm - { - push es - mov si, ss:memSegment - mov es, ss:[si] - mov si, ss:mem - add si, pos - mov al, es:[si] - mov dataByte, al - pop es - } - pos++; - } - else - dataByte = mem[pos++]; - - if (pass == 1) - { - PrintHex (dataByte); - PrintChar (' '); - } - else - PrintChar (IsPrintable (dataByte) ? dataByte : '.'); - } - - if (pass == 1) - { - pos -= i; - PrintChar (' '); - } - } - - PrintEndl (); - } -} - - -void PrintHexDump (uint16 memSegment, uint16 memOffset, size_t size) -{ - PrintHexDump ((byte *) memOffset, size, &memSegment); -} - -#endif // TC_BOOT_DEBUG_ENABLED - - -#ifdef TC_BOOT_STACK_CHECKING_ENABLED - -extern "C" char end[]; - -static void PrintStackInfo () -{ - uint16 spReg; - __asm mov spReg, sp - - Print ("Stack: "); Print (TC_BOOT_LOADER_STACK_TOP - spReg); - Print ("/"); Print (TC_BOOT_LOADER_STACK_TOP - (uint16) end); -} - - -void CheckStack () -{ - uint16 spReg; - __asm mov spReg, sp - - if (*(uint32 *) end != 0x12345678UL || spReg < (uint16) end) - { - __asm cli - __asm mov sp, TC_BOOT_LOADER_STACK_TOP - - PrintError ("Stack overflow"); - TC_THROW_FATAL_EXCEPTION; - } -} - - -void InitStackChecker () -{ - *(uint32 *) end = 0x12345678UL; - - PrintStackInfo(); - PrintEndl(); -} - -#endif // TC_BOOT_STACK_CHECKING_ENABLED +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform.h" +#include "Bios.h" +#include "BootConsoleIo.h" +#include "BootDefs.h" +#include "BootDiskIo.h" +#include "BootDebug.h" + + +#ifdef TC_BOOT_TRACING_ENABLED + +void InitDebugPort () +{ + __asm + { + mov dx, TC_DEBUG_PORT + mov ah, 1 + int 0x17 + mov dx, TC_DEBUG_PORT + mov ah, 0xe2 + int 0x17 + } +} + + +void WriteDebugPort (byte dataByte) +{ + __asm + { + mov al, dataByte + mov dx, TC_DEBUG_PORT + mov ah, 0 + int 0x17 + } +} + +#endif // TC_BOOT_TRACING_ENABLED + + +#ifdef TC_BOOT_DEBUG_ENABLED + +extern "C" void PrintDebug (uint32 debugVal) +{ + Print (debugVal); + PrintEndl(); +} + + +void PrintVal (const char *message, const uint32 value, bool newLine, bool hex) +{ + Print (message); + Print (": "); + + if (hex) + PrintHex (value); + else + Print (value); + + if (newLine) + PrintEndl(); +} + + +void PrintVal (const char *message, const uint64 &value, bool newLine, bool hex) +{ + Print (message); + Print (": "); + PrintHex (value); + if (newLine) + PrintEndl(); +} + + +void PrintHexDump (byte *mem, size_t size, uint16 *memSegment) +{ + const size_t width = 16; + for (size_t pos = 0; pos < size; ) + { + for (int pass = 1; pass <= 2; ++pass) + { + size_t i; + for (i = 0; i < width && pos < size; ++i) + { + byte dataByte; + if (memSegment) + { + __asm + { + push es + mov si, ss:memSegment + mov es, ss:[si] + mov si, ss:mem + add si, pos + mov al, es:[si] + mov dataByte, al + pop es + } + pos++; + } + else + dataByte = mem[pos++]; + + if (pass == 1) + { + PrintHex (dataByte); + PrintChar (' '); + } + else + PrintChar (IsPrintable (dataByte) ? dataByte : '.'); + } + + if (pass == 1) + { + pos -= i; + PrintChar (' '); + } + } + + PrintEndl (); + } +} + + +void PrintHexDump (uint16 memSegment, uint16 memOffset, size_t size) +{ + PrintHexDump ((byte *) memOffset, size, &memSegment); +} + +#endif // TC_BOOT_DEBUG_ENABLED + + +#ifdef TC_BOOT_STACK_CHECKING_ENABLED + +extern "C" char end[]; + +static void PrintStackInfo () +{ + uint16 spReg; + __asm mov spReg, sp + + Print ("Stack: "); Print (TC_BOOT_LOADER_STACK_TOP - spReg); + Print ("/"); Print (TC_BOOT_LOADER_STACK_TOP - (uint16) end); +} + + +void CheckStack () +{ + uint16 spReg; + __asm mov spReg, sp + + if (*(uint32 *) end != 0x12345678UL || spReg < (uint16) end) + { + __asm cli + __asm mov sp, TC_BOOT_LOADER_STACK_TOP + + PrintError ("Stack overflow"); + TC_THROW_FATAL_EXCEPTION; + } +} + + +void InitStackChecker () +{ + *(uint32 *) end = 0x12345678UL; + + PrintStackInfo(); + PrintEndl(); +} + +#endif // TC_BOOT_STACK_CHECKING_ENABLED diff --git a/Boot/Windows/BootDebug.h b/Boot/Windows/BootDebug.h index 19148e4..bed4de2 100644 --- a/Boot/Windows/BootDebug.h +++ b/Boot/Windows/BootDebug.h @@ -1,56 +1,56 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootDebug -#define TC_HEADER_Boot_BootDebug - -#include "Platform.h" -#include "BootConsoleIo.h" - -#if 0 -# define TC_BOOT_DEBUG_ENABLED -#endif - -#if 0 || defined (TC_BOOT_DEBUG_ENABLED) -# define TC_BOOT_STACK_CHECKING_ENABLED - extern "C" void CheckStack (); -#else -# define CheckStack() -#endif - -#if 0 -# define TC_BOOT_TRACING_ENABLED -# if 1 -# define TC_TRACE_INT13 -# endif -# if 0 -# define TC_TRACE_INT15 -# endif -#endif - -#ifdef TC_BOOT_DEBUG_ENABLED -# define trace_point do { Print(__FILE__); PrintChar (':'); Print (TC_TO_STRING (__LINE__)); PrintEndl(); } while (false) -# define trace_val(VAL) PrintVal (#VAL, VAL); -# define trace_hex(VAL) do { Print (#VAL), PrintChar (':'); PrintHex (VAL); PrintEndl(); } while (false) -# define assert(COND) do { if (!(COND)) { trace_point; __asm jmp $ } } while (false) -#else -# define trace_point -# define trace_val(VAL) -# define trace_hex(VAL) -# define assert(COND) -#endif - -void InitDebugPort (); -void InitStackChecker (); -void WriteDebugPort (byte dataByte); -void PrintHexDump (byte *mem, size_t size, uint16 *memSegment = nullptr); -void PrintHexDump (uint16 memSegment, uint16 memOffset, size_t size); -void PrintVal (const char *message, const uint32 value, bool newLine = true, bool hex = false); -void PrintVal (const char *message, const uint64 &value, bool newLine = true, bool hex = false); - -#endif // TC_HEADER_Boot_BootDebug +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootDebug +#define TC_HEADER_Boot_BootDebug + +#include "Platform.h" +#include "BootConsoleIo.h" + +#if 0 +# define TC_BOOT_DEBUG_ENABLED +#endif + +#if 0 || defined (TC_BOOT_DEBUG_ENABLED) +# define TC_BOOT_STACK_CHECKING_ENABLED + extern "C" void CheckStack (); +#else +# define CheckStack() +#endif + +#if 0 +# define TC_BOOT_TRACING_ENABLED +# if 1 +# define TC_TRACE_INT13 +# endif +# if 0 +# define TC_TRACE_INT15 +# endif +#endif + +#ifdef TC_BOOT_DEBUG_ENABLED +# define trace_point do { Print(__FILE__); PrintChar (':'); Print (TC_TO_STRING (__LINE__)); PrintEndl(); } while (false) +# define trace_val(VAL) PrintVal (#VAL, VAL); +# define trace_hex(VAL) do { Print (#VAL), PrintChar (':'); PrintHex (VAL); PrintEndl(); } while (false) +# define assert(COND) do { if (!(COND)) { trace_point; __asm jmp $ } } while (false) +#else +# define trace_point +# define trace_val(VAL) +# define trace_hex(VAL) +# define assert(COND) +#endif + +void InitDebugPort (); +void InitStackChecker (); +void WriteDebugPort (byte dataByte); +void PrintHexDump (byte *mem, size_t size, uint16 *memSegment = nullptr); +void PrintHexDump (uint16 memSegment, uint16 memOffset, size_t size); +void PrintVal (const char *message, const uint32 value, bool newLine = true, bool hex = false); +void PrintVal (const char *message, const uint64 &value, bool newLine = true, bool hex = false); + +#endif // TC_HEADER_Boot_BootDebug diff --git a/Boot/Windows/BootDefs.h b/Boot/Windows/BootDefs.h index c7b447b..80ba9f7 100644 --- a/Boot/Windows/BootDefs.h +++ b/Boot/Windows/BootDefs.h @@ -1,185 +1,185 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootDefs -#define TC_HEADER_Boot_BootDefs - -// Total memory required (CODE + DATA + BSS + STACK + 0x100) in KBytes - determined from linker map. -#define TC__BOOT_MEMORY_REQUIRED 42 - -#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE -# undef TC__BOOT_MEMORY_REQUIRED - -# ifdef TC_WINDOWS_BOOT_AES -# ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE -# define TC__BOOT_MEMORY_REQUIRED 29 -# else -# define TC__BOOT_MEMORY_REQUIRED 27 -# endif -# elif defined (TC_WINDOWS_BOOT_SERPENT) -# define TC__BOOT_MEMORY_REQUIRED 32 -# elif defined (TC_WINDOWS_BOOT_TWOFISH) -# define TC__BOOT_MEMORY_REQUIRED 40 -# endif - -#if 0 -# undef TC__BOOT_MEMORY_REQUIRED -# define TC__BOOT_MEMORY_REQUIRED 60 -#endif - -#endif - -// Modifying this value can introduce incompatibility with previous versions -#define TC__BOOT_LOADER_SEGMENT TC_HEX (9000) // Memory reserved in the segment 8000 is always destroyed by Vista with no SP - -#if TC__BOOT_MEMORY_REQUIRED <= 32 -# define TC__BOOT_LOADER_SEGMENT_LOW (TC__BOOT_LOADER_SEGMENT - 32 * 1024 / 16) -#else -# define TC__BOOT_LOADER_SEGMENT_LOW (TC__BOOT_LOADER_SEGMENT - 64 * 1024 / 16) -#endif - -#define TC__COM_EXECUTABLE_OFFSET TC_HEX (100) - -#define TC__BOOT_LOADER_LOWMEM_SEGMENT TC_HEX (2000) -#define TC__BOOT_LOADER_BUFFER_SEGMENT TC_HEX (4000) -#define TC__BOOT_LOADER_ALT_SEGMENT TC_HEX (6000) - -#define TC__BOOT_LOADER_STACK_TOP (TC_BOOT_MEMORY_REQUIRED * TC_UNSIGNED (1024) - 4) - -#define TC__LB_SIZE 512 -#define TC__BOOT_LOADER_AREA_SECTOR_COUNT 63 - -#define TC__BOOT_SECTOR_VERSION_OFFSET 430 -#define TC__BOOT_SECTOR_LOADER_LENGTH_OFFSET 432 -#define TC__BOOT_SECTOR_LOADER_CHECKSUM_OFFSET 434 -#define TC__BOOT_SECTOR_USER_CONFIG_OFFSET 438 -#define TC__BOOT_SECTOR_CONFIG_OFFSET 439 // The last byte that is reserved for the boot loader - -#define TC__BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH 24 -#define TC__BOOT_SECTOR_USER_MESSAGE_OFFSET (TC__BOOT_SECTOR_VERSION_OFFSET - TC__BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH) - -#define TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE 4 -#define TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET (TC__BOOT_SECTOR_USER_MESSAGE_OFFSET - TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE) - -#define TC__BOOT_LOADER_DECOMPRESSOR_START_SECTOR 2 -#define TC__BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT 4 -#define TC__BOOT_LOADER_DECOMPRESSOR_MEMORY_SIZE 32768 -#define TC__BOOT_LOADER_COMPRESSED_BUFFER_OFFSET (TC_COM_EXECUTABLE_OFFSET + 3072) - -#define TC__BOOT_LOADER_START_SECTOR (TC_BOOT_LOADER_DECOMPRESSOR_START_SECTOR + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT) -#define TC__MAX_BOOT_LOADER_SECTOR_COUNT (TC_BOOT_LOADER_AREA_SECTOR_COUNT - TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT - 2) -#define TC__MAX_BOOT_LOADER_DECOMPRESSED_SIZE ((TC_BOOT_LOADER_AREA_SECTOR_COUNT - 2) * TC_LB_SIZE) - -#define TC__BOOT_LOADER_BACKUP_SECTOR_COUNT 30 - -#define TC__GZIP_HEADER_SIZE 10 - -#define TC__BOOT_CFG_FLAG_AREA_SIZE 1 // In bytes - -// If you add more flags, revise TC__BOOT_CFG_FLAG_AREA_SIZE -#define TC__BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE TC_HEX (02) -#define TC__BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER TC_HEX (04) -#define TC__BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER TC_HEX (20) - -#define TC__BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE (TC_HEX (40) + TC_HEX (80)) - -// Modifying the following values can introduce incompatibility with previous versions -#define TC__BOOT_USER_CFG_FLAG_SILENT_MODE TC_HEX (01) -#define TC__BOOT_USER_CFG_FLAG_DISABLE_ESC TC_HEX (02) - -// The following items are treated as a 2-bit value (apply TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE to obtain the value) -#define TC__HIDDEN_OS_CREATION_PHASE_NONE 0 -#define TC__HIDDEN_OS_CREATION_PHASE_CLONING TC_HEX (40) // The boot loader is to copy the content of the system partition to the hidden volume -#define TC__HIDDEN_OS_CREATION_PHASE_WIPING TC_HEX (80) // The boot loader has successfully copied the content of the system partition to the hidden volume. The original OS is to be wiped now. -#define TC__HIDDEN_OS_CREATION_PHASE_WIPED (TC_HEX (40) + TC_HEX (80)) // The original OS has been wiped. The user is required to install a new OS (decoy OS) on the system partition now. - - -#ifdef TC_ASM_PREPROCESS - -#define TC_HEX(N) 0##N##h -#define TC_UNSIGNED(N) N - -TC_BOOT_MEMORY_REQUIRED = TC__BOOT_MEMORY_REQUIRED -TC_BOOT_LOADER_SEGMENT = TC__BOOT_LOADER_SEGMENT -TC_BOOT_LOADER_SEGMENT_LOW = TC__BOOT_LOADER_SEGMENT_LOW -TC_COM_EXECUTABLE_OFFSET = TC__COM_EXECUTABLE_OFFSET -TC_BOOT_LOADER_LOWMEM_SEGMENT = TC__BOOT_LOADER_LOWMEM_SEGMENT -TC_BOOT_LOADER_BUFFER_SEGMENT = TC__BOOT_LOADER_BUFFER_SEGMENT -TC_BOOT_LOADER_ALT_SEGMENT = TC__BOOT_LOADER_ALT_SEGMENT -TC_BOOT_LOADER_STACK_TOP = TC__BOOT_LOADER_STACK_TOP -TC_LB_SIZE = TC__LB_SIZE -TC_BOOT_LOADER_AREA_SECTOR_COUNT = TC__BOOT_LOADER_AREA_SECTOR_COUNT -TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET = TC__BOOT_SECTOR_LOADER_LENGTH_OFFSET -TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET = TC__BOOT_SECTOR_LOADER_CHECKSUM_OFFSET -TC_BOOT_SECTOR_CONFIG_OFFSET = TC__BOOT_SECTOR_CONFIG_OFFSET -TC_BOOT_SECTOR_USER_CONFIG_OFFSET = TC__BOOT_SECTOR_USER_CONFIG_OFFSET -TC_BOOT_LOADER_DECOMPRESSOR_START_SECTOR = TC__BOOT_LOADER_DECOMPRESSOR_START_SECTOR -TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT = TC__BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT -TC_BOOT_LOADER_DECOMPRESSOR_MEMORY_SIZE = TC__BOOT_LOADER_DECOMPRESSOR_MEMORY_SIZE -TC_BOOT_LOADER_COMPRESSED_BUFFER_OFFSET = TC__BOOT_LOADER_COMPRESSED_BUFFER_OFFSET -TC_BOOT_LOADER_START_SECTOR = TC__BOOT_LOADER_START_SECTOR -TC_MAX_BOOT_LOADER_SECTOR_COUNT = TC__MAX_BOOT_LOADER_SECTOR_COUNT -TC_MAX_BOOT_LOADER_DECOMPRESSED_SIZE = TC__MAX_BOOT_LOADER_DECOMPRESSED_SIZE -TC_BOOT_LOADER_BACKUP_SECTOR_COUNT = TC__BOOT_LOADER_BACKUP_SECTOR_COUNT -TC_GZIP_HEADER_SIZE = TC__GZIP_HEADER_SIZE -TC_BOOT_CFG_FLAG_AREA_SIZE = TC__BOOT_CFG_FLAG_AREA_SIZE -TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE = TC__BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE -TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER = TC__BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER -TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER = TC__BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER -TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE = TC__BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE -TC_BOOT_USER_CFG_FLAG_SILENT_MODE = TC__BOOT_USER_CFG_FLAG_SILENT_MODE -TC_HIDDEN_OS_CREATION_PHASE_NONE = TC__HIDDEN_OS_CREATION_PHASE_NONE -TC_HIDDEN_OS_CREATION_PHASE_CLONING = TC__HIDDEN_OS_CREATION_PHASE_CLONING -TC_HIDDEN_OS_CREATION_PHASE_WIPING = TC__HIDDEN_OS_CREATION_PHASE_WIPING -TC_HIDDEN_OS_CREATION_PHASE_WIPED = TC__HIDDEN_OS_CREATION_PHASE_WIPED - -#else // TC_ASM_PREPROCESS - -#define TC_HEX(N) 0x##N -#define TC_UNSIGNED(N) N##U - -#define TC_BOOT_MEMORY_REQUIRED TC__BOOT_MEMORY_REQUIRED -#define TC_BOOT_LOADER_SEGMENT TC__BOOT_LOADER_SEGMENT -#define TC_COM_EXECUTABLE_OFFSET TC__COM_EXECUTABLE_OFFSET -#define TC_BOOT_LOADER_LOWMEM_SEGMENT TC__BOOT_LOADER_LOWMEM_SEGMENT -#define TC_BOOT_LOADER_BUFFER_SEGMENT TC__BOOT_LOADER_BUFFER_SEGMENT -#define TC_BOOT_LOADER_ALT_SEGMENT TC__BOOT_LOADER_ALT_SEGMENT -#define TC_BOOT_LOADER_STACK_TOP (TC__BOOT_LOADER_STACK_TOP) -#define TC_BOOT_LOADER_AREA_SECTOR_COUNT TC__BOOT_LOADER_AREA_SECTOR_COUNT -#define TC_BOOT_SECTOR_USER_MESSAGE_OFFSET TC__BOOT_SECTOR_USER_MESSAGE_OFFSET -#define TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE -#define TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET -#define TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH TC__BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH -#define TC_BOOT_SECTOR_VERSION_OFFSET TC__BOOT_SECTOR_VERSION_OFFSET -#define TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET TC__BOOT_SECTOR_LOADER_LENGTH_OFFSET -#define TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET TC__BOOT_SECTOR_LOADER_CHECKSUM_OFFSET -#define TC_BOOT_LOADER_DECOMPRESSOR_START_SECTOR TC__BOOT_LOADER_DECOMPRESSOR_START_SECTOR -#define TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT TC__BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT -#define TC_BOOT_SECTOR_CONFIG_OFFSET TC__BOOT_SECTOR_CONFIG_OFFSET -#define TC_BOOT_SECTOR_USER_CONFIG_OFFSET TC__BOOT_SECTOR_USER_CONFIG_OFFSET -#define TC_BOOT_LOADER_START_SECTOR TC__BOOT_LOADER_START_SECTOR -#define TC_LB_SIZE TC__LB_SIZE -#define TC_MAX_BOOT_LOADER_SECTOR_COUNT TC__MAX_BOOT_LOADER_SECTOR_COUNT -#define TC_MAX_BOOT_LOADER_DECOMPRESSED_SIZE TC__MAX_BOOT_LOADER_DECOMPRESSED_SIZE -#define TC_BOOT_LOADER_BACKUP_SECTOR_COUNT TC__BOOT_LOADER_BACKUP_SECTOR_COUNT -#define TC_GZIP_HEADER_SIZE TC__GZIP_HEADER_SIZE -#define TC_BOOT_CFG_FLAG_AREA_SIZE TC__BOOT_CFG_FLAG_AREA_SIZE -#define TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE TC__BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE -#define TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER TC__BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER -#define TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER TC__BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER -#define TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE TC__BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE -#define TC_BOOT_USER_CFG_FLAG_SILENT_MODE TC__BOOT_USER_CFG_FLAG_SILENT_MODE -#define TC_BOOT_USER_CFG_FLAG_DISABLE_ESC TC__BOOT_USER_CFG_FLAG_DISABLE_ESC -#define TC_HIDDEN_OS_CREATION_PHASE_NONE TC__HIDDEN_OS_CREATION_PHASE_NONE -#define TC_HIDDEN_OS_CREATION_PHASE_CLONING TC__HIDDEN_OS_CREATION_PHASE_CLONING -#define TC_HIDDEN_OS_CREATION_PHASE_WIPING TC__HIDDEN_OS_CREATION_PHASE_WIPING -#define TC_HIDDEN_OS_CREATION_PHASE_WIPED TC__HIDDEN_OS_CREATION_PHASE_WIPED - -#endif // TC_ASM_PREPROCESS - -#endif // TC_HEADER_Boot_BootDefs +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootDefs +#define TC_HEADER_Boot_BootDefs + +// Total memory required (CODE + DATA + BSS + STACK + 0x100) in KBytes - determined from linker map. +#define TC__BOOT_MEMORY_REQUIRED 42 + +#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE +# undef TC__BOOT_MEMORY_REQUIRED + +# ifdef TC_WINDOWS_BOOT_AES +# ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE +# define TC__BOOT_MEMORY_REQUIRED 29 +# else +# define TC__BOOT_MEMORY_REQUIRED 27 +# endif +# elif defined (TC_WINDOWS_BOOT_SERPENT) +# define TC__BOOT_MEMORY_REQUIRED 32 +# elif defined (TC_WINDOWS_BOOT_TWOFISH) +# define TC__BOOT_MEMORY_REQUIRED 40 +# endif + +#if 0 +# undef TC__BOOT_MEMORY_REQUIRED +# define TC__BOOT_MEMORY_REQUIRED 60 +#endif + +#endif + +// Modifying this value can introduce incompatibility with previous versions +#define TC__BOOT_LOADER_SEGMENT TC_HEX (9000) // Memory reserved in the segment 8000 is always destroyed by Vista with no SP + +#if TC__BOOT_MEMORY_REQUIRED <= 32 +# define TC__BOOT_LOADER_SEGMENT_LOW (TC__BOOT_LOADER_SEGMENT - 32 * 1024 / 16) +#else +# define TC__BOOT_LOADER_SEGMENT_LOW (TC__BOOT_LOADER_SEGMENT - 64 * 1024 / 16) +#endif + +#define TC__COM_EXECUTABLE_OFFSET TC_HEX (100) + +#define TC__BOOT_LOADER_LOWMEM_SEGMENT TC_HEX (2000) +#define TC__BOOT_LOADER_BUFFER_SEGMENT TC_HEX (4000) +#define TC__BOOT_LOADER_ALT_SEGMENT TC_HEX (6000) + +#define TC__BOOT_LOADER_STACK_TOP (TC_BOOT_MEMORY_REQUIRED * TC_UNSIGNED (1024) - 4) + +#define TC__LB_SIZE 512 +#define TC__BOOT_LOADER_AREA_SECTOR_COUNT 63 + +#define TC__BOOT_SECTOR_VERSION_OFFSET 430 +#define TC__BOOT_SECTOR_LOADER_LENGTH_OFFSET 432 +#define TC__BOOT_SECTOR_LOADER_CHECKSUM_OFFSET 434 +#define TC__BOOT_SECTOR_USER_CONFIG_OFFSET 438 +#define TC__BOOT_SECTOR_CONFIG_OFFSET 439 // The last byte that is reserved for the boot loader + +#define TC__BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH 24 +#define TC__BOOT_SECTOR_USER_MESSAGE_OFFSET (TC__BOOT_SECTOR_VERSION_OFFSET - TC__BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH) + +#define TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE 4 +#define TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET (TC__BOOT_SECTOR_USER_MESSAGE_OFFSET - TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE) + +#define TC__BOOT_LOADER_DECOMPRESSOR_START_SECTOR 2 +#define TC__BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT 4 +#define TC__BOOT_LOADER_DECOMPRESSOR_MEMORY_SIZE 32768 +#define TC__BOOT_LOADER_COMPRESSED_BUFFER_OFFSET (TC_COM_EXECUTABLE_OFFSET + 3072) + +#define TC__BOOT_LOADER_START_SECTOR (TC_BOOT_LOADER_DECOMPRESSOR_START_SECTOR + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT) +#define TC__MAX_BOOT_LOADER_SECTOR_COUNT (TC_BOOT_LOADER_AREA_SECTOR_COUNT - TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT - 2) +#define TC__MAX_BOOT_LOADER_DECOMPRESSED_SIZE ((TC_BOOT_LOADER_AREA_SECTOR_COUNT - 2) * TC_LB_SIZE) + +#define TC__BOOT_LOADER_BACKUP_SECTOR_COUNT 30 + +#define TC__GZIP_HEADER_SIZE 10 + +#define TC__BOOT_CFG_FLAG_AREA_SIZE 1 // In bytes + +// If you add more flags, revise TC__BOOT_CFG_FLAG_AREA_SIZE +#define TC__BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE TC_HEX (02) +#define TC__BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER TC_HEX (04) +#define TC__BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER TC_HEX (20) + +#define TC__BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE (TC_HEX (40) + TC_HEX (80)) + +// Modifying the following values can introduce incompatibility with previous versions +#define TC__BOOT_USER_CFG_FLAG_SILENT_MODE TC_HEX (01) +#define TC__BOOT_USER_CFG_FLAG_DISABLE_ESC TC_HEX (02) + +// The following items are treated as a 2-bit value (apply TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE to obtain the value) +#define TC__HIDDEN_OS_CREATION_PHASE_NONE 0 +#define TC__HIDDEN_OS_CREATION_PHASE_CLONING TC_HEX (40) // The boot loader is to copy the content of the system partition to the hidden volume +#define TC__HIDDEN_OS_CREATION_PHASE_WIPING TC_HEX (80) // The boot loader has successfully copied the content of the system partition to the hidden volume. The original OS is to be wiped now. +#define TC__HIDDEN_OS_CREATION_PHASE_WIPED (TC_HEX (40) + TC_HEX (80)) // The original OS has been wiped. The user is required to install a new OS (decoy OS) on the system partition now. + + +#ifdef TC_ASM_PREPROCESS + +#define TC_HEX(N) 0##N##h +#define TC_UNSIGNED(N) N + +TC_BOOT_MEMORY_REQUIRED = TC__BOOT_MEMORY_REQUIRED +TC_BOOT_LOADER_SEGMENT = TC__BOOT_LOADER_SEGMENT +TC_BOOT_LOADER_SEGMENT_LOW = TC__BOOT_LOADER_SEGMENT_LOW +TC_COM_EXECUTABLE_OFFSET = TC__COM_EXECUTABLE_OFFSET +TC_BOOT_LOADER_LOWMEM_SEGMENT = TC__BOOT_LOADER_LOWMEM_SEGMENT +TC_BOOT_LOADER_BUFFER_SEGMENT = TC__BOOT_LOADER_BUFFER_SEGMENT +TC_BOOT_LOADER_ALT_SEGMENT = TC__BOOT_LOADER_ALT_SEGMENT +TC_BOOT_LOADER_STACK_TOP = TC__BOOT_LOADER_STACK_TOP +TC_LB_SIZE = TC__LB_SIZE +TC_BOOT_LOADER_AREA_SECTOR_COUNT = TC__BOOT_LOADER_AREA_SECTOR_COUNT +TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET = TC__BOOT_SECTOR_LOADER_LENGTH_OFFSET +TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET = TC__BOOT_SECTOR_LOADER_CHECKSUM_OFFSET +TC_BOOT_SECTOR_CONFIG_OFFSET = TC__BOOT_SECTOR_CONFIG_OFFSET +TC_BOOT_SECTOR_USER_CONFIG_OFFSET = TC__BOOT_SECTOR_USER_CONFIG_OFFSET +TC_BOOT_LOADER_DECOMPRESSOR_START_SECTOR = TC__BOOT_LOADER_DECOMPRESSOR_START_SECTOR +TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT = TC__BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT +TC_BOOT_LOADER_DECOMPRESSOR_MEMORY_SIZE = TC__BOOT_LOADER_DECOMPRESSOR_MEMORY_SIZE +TC_BOOT_LOADER_COMPRESSED_BUFFER_OFFSET = TC__BOOT_LOADER_COMPRESSED_BUFFER_OFFSET +TC_BOOT_LOADER_START_SECTOR = TC__BOOT_LOADER_START_SECTOR +TC_MAX_BOOT_LOADER_SECTOR_COUNT = TC__MAX_BOOT_LOADER_SECTOR_COUNT +TC_MAX_BOOT_LOADER_DECOMPRESSED_SIZE = TC__MAX_BOOT_LOADER_DECOMPRESSED_SIZE +TC_BOOT_LOADER_BACKUP_SECTOR_COUNT = TC__BOOT_LOADER_BACKUP_SECTOR_COUNT +TC_GZIP_HEADER_SIZE = TC__GZIP_HEADER_SIZE +TC_BOOT_CFG_FLAG_AREA_SIZE = TC__BOOT_CFG_FLAG_AREA_SIZE +TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE = TC__BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE +TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER = TC__BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER +TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER = TC__BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER +TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE = TC__BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE +TC_BOOT_USER_CFG_FLAG_SILENT_MODE = TC__BOOT_USER_CFG_FLAG_SILENT_MODE +TC_HIDDEN_OS_CREATION_PHASE_NONE = TC__HIDDEN_OS_CREATION_PHASE_NONE +TC_HIDDEN_OS_CREATION_PHASE_CLONING = TC__HIDDEN_OS_CREATION_PHASE_CLONING +TC_HIDDEN_OS_CREATION_PHASE_WIPING = TC__HIDDEN_OS_CREATION_PHASE_WIPING +TC_HIDDEN_OS_CREATION_PHASE_WIPED = TC__HIDDEN_OS_CREATION_PHASE_WIPED + +#else // TC_ASM_PREPROCESS + +#define TC_HEX(N) 0x##N +#define TC_UNSIGNED(N) N##U + +#define TC_BOOT_MEMORY_REQUIRED TC__BOOT_MEMORY_REQUIRED +#define TC_BOOT_LOADER_SEGMENT TC__BOOT_LOADER_SEGMENT +#define TC_COM_EXECUTABLE_OFFSET TC__COM_EXECUTABLE_OFFSET +#define TC_BOOT_LOADER_LOWMEM_SEGMENT TC__BOOT_LOADER_LOWMEM_SEGMENT +#define TC_BOOT_LOADER_BUFFER_SEGMENT TC__BOOT_LOADER_BUFFER_SEGMENT +#define TC_BOOT_LOADER_ALT_SEGMENT TC__BOOT_LOADER_ALT_SEGMENT +#define TC_BOOT_LOADER_STACK_TOP (TC__BOOT_LOADER_STACK_TOP) +#define TC_BOOT_LOADER_AREA_SECTOR_COUNT TC__BOOT_LOADER_AREA_SECTOR_COUNT +#define TC_BOOT_SECTOR_USER_MESSAGE_OFFSET TC__BOOT_SECTOR_USER_MESSAGE_OFFSET +#define TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE +#define TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET TC__BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET +#define TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH TC__BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH +#define TC_BOOT_SECTOR_VERSION_OFFSET TC__BOOT_SECTOR_VERSION_OFFSET +#define TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET TC__BOOT_SECTOR_LOADER_LENGTH_OFFSET +#define TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET TC__BOOT_SECTOR_LOADER_CHECKSUM_OFFSET +#define TC_BOOT_LOADER_DECOMPRESSOR_START_SECTOR TC__BOOT_LOADER_DECOMPRESSOR_START_SECTOR +#define TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT TC__BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT +#define TC_BOOT_SECTOR_CONFIG_OFFSET TC__BOOT_SECTOR_CONFIG_OFFSET +#define TC_BOOT_SECTOR_USER_CONFIG_OFFSET TC__BOOT_SECTOR_USER_CONFIG_OFFSET +#define TC_BOOT_LOADER_START_SECTOR TC__BOOT_LOADER_START_SECTOR +#define TC_LB_SIZE TC__LB_SIZE +#define TC_MAX_BOOT_LOADER_SECTOR_COUNT TC__MAX_BOOT_LOADER_SECTOR_COUNT +#define TC_MAX_BOOT_LOADER_DECOMPRESSED_SIZE TC__MAX_BOOT_LOADER_DECOMPRESSED_SIZE +#define TC_BOOT_LOADER_BACKUP_SECTOR_COUNT TC__BOOT_LOADER_BACKUP_SECTOR_COUNT +#define TC_GZIP_HEADER_SIZE TC__GZIP_HEADER_SIZE +#define TC_BOOT_CFG_FLAG_AREA_SIZE TC__BOOT_CFG_FLAG_AREA_SIZE +#define TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE TC__BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE +#define TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER TC__BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER +#define TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER TC__BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER +#define TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE TC__BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE +#define TC_BOOT_USER_CFG_FLAG_SILENT_MODE TC__BOOT_USER_CFG_FLAG_SILENT_MODE +#define TC_BOOT_USER_CFG_FLAG_DISABLE_ESC TC__BOOT_USER_CFG_FLAG_DISABLE_ESC +#define TC_HIDDEN_OS_CREATION_PHASE_NONE TC__HIDDEN_OS_CREATION_PHASE_NONE +#define TC_HIDDEN_OS_CREATION_PHASE_CLONING TC__HIDDEN_OS_CREATION_PHASE_CLONING +#define TC_HIDDEN_OS_CREATION_PHASE_WIPING TC__HIDDEN_OS_CREATION_PHASE_WIPING +#define TC_HIDDEN_OS_CREATION_PHASE_WIPED TC__HIDDEN_OS_CREATION_PHASE_WIPED + +#endif // TC_ASM_PREPROCESS + +#endif // TC_HEADER_Boot_BootDefs diff --git a/Boot/Windows/BootDiskIo.cpp b/Boot/Windows/BootDiskIo.cpp index ce797b7..f7f565e 100644 --- a/Boot/Windows/BootDiskIo.cpp +++ b/Boot/Windows/BootDiskIo.cpp @@ -1,470 +1,469 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Bios.h" -#include "BootConsoleIo.h" -#include "BootConfig.h" -#include "BootDebug.h" -#include "BootDefs.h" -#include "BootDiskIo.h" -#include "BootStrings.h" - - -byte SectorBuffer[TC_LB_SIZE]; - -#ifdef TC_BOOT_DEBUG_ENABLED -static bool SectorBufferInUse = false; - -void AcquireSectorBuffer () -{ - if (SectorBufferInUse) - TC_THROW_FATAL_EXCEPTION; - - SectorBufferInUse = true; -} - - -void ReleaseSectorBuffer () -{ - SectorBufferInUse = false; -} - -#endif - - -bool IsLbaSupported (byte drive) -{ - static byte CachedDrive = TC_INVALID_BIOS_DRIVE; - static bool CachedStatus; - uint16 result = 0; - - if (CachedDrive == drive) - goto ret; - - __asm - { - mov bx, 0x55aa - mov dl, drive - mov ah, 0x41 - int 0x13 - jc err - mov result, bx - err: - } - - CachedDrive = drive; - CachedStatus = (result == 0xaa55); -ret: - return CachedStatus; -} - - -void PrintDiskError (BiosResult error, bool write, byte drive, const uint64 *sector, const ChsAddress *chs) -{ - PrintEndl(); - Print (write ? "Write" : "Read"); Print (" error:"); - Print (error); - Print (" Drive:"); - Print (drive < TC_FIRST_BIOS_DRIVE ? drive : drive - TC_FIRST_BIOS_DRIVE); - - if (sector) - { - Print (" Sector:"); - Print (*sector); - } - - if (chs) - { - Print (" CHS:"); - Print (*chs); - } - - PrintEndl(); - Beep(); -} - - -void Print (const ChsAddress &chs) -{ - Print (chs.Cylinder); - PrintChar ('/'); - Print (chs.Head); - PrintChar ('/'); - Print (chs.Sector); -} - - -void PrintSectorCountInMB (const uint64 §orCount) -{ - Print (sectorCount >> (TC_LB_SIZE_BIT_SHIFT_DIVISOR + 2)); Print (" MB "); -} - - -BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) -{ - CheckStack(); - - byte cylinderLow = (byte) chs.Cylinder; - byte sector = chs.Sector; - sector |= byte (chs.Cylinder >> 2) & 0xc0; - byte function = write ? 0x03 : 0x02; - - BiosResult result = BiosResultSuccess; - __asm - { - push es - mov ax, bufferSegment - mov es, ax - mov bx, bufferOffset - mov dl, drive - mov ch, cylinderLow - mov si, chs - mov dh, [si].Head - mov cl, sector - mov al, sectorCount - mov ah, function - int 0x13 - jnc ok // Ignore AH if CF=0 to prevent potential bugs in BIOSes - mov result, ah - ok: - pop es - } - - if (result == BiosResultEccCorrected) - result = BiosResultSuccess; - - if (!silent && result != BiosResultSuccess) - PrintDiskError (result, write, drive, nullptr, &chs); - - return result; -} - - -BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) -{ - uint16 codeSeg; - __asm mov codeSeg, cs - return ReadWriteSectors (write, codeSeg, (uint16) buffer, drive, chs, sectorCount, silent); -} - - -BiosResult ReadSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) -{ - return ReadWriteSectors (false, buffer, drive, chs, sectorCount, silent); -} - - -BiosResult WriteSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) -{ - return ReadWriteSectors (true, buffer, drive, chs, sectorCount, silent); -} - - -static BiosResult ReadWriteSectors (bool write, BiosLbaPacket &dapPacket, byte drive, const uint64 §or, uint16 sectorCount, bool silent) -{ - CheckStack(); - - if (!IsLbaSupported (drive)) - { - DriveGeometry geometry; - - BiosResult result = GetDriveGeometry (drive, geometry, silent); - if (result != BiosResultSuccess) - return result; - - ChsAddress chs; - LbaToChs (geometry, sector, chs); - return ReadWriteSectors (write, (uint16) (dapPacket.Buffer >> 16), (uint16) dapPacket.Buffer, drive, chs, sectorCount, silent); - } - - dapPacket.Size = sizeof (dapPacket); - dapPacket.Reserved = 0; - dapPacket.SectorCount = sectorCount; - dapPacket.Sector = sector; - - byte function = write ? 0x43 : 0x42; - - BiosResult result = BiosResultSuccess; - __asm - { - mov bx, 0x55aa - mov dl, drive - mov si, [dapPacket] - mov ah, function - xor al, al - int 0x13 - jnc ok // Ignore AH if CF=0 to prevent potential bugs in BIOSes - mov result, ah - ok: - } - - if (result == BiosResultEccCorrected) - result = BiosResultSuccess; - - if (!silent && result != BiosResultSuccess) - PrintDiskError (result, write, drive, §or); - - return result; -} - - -static BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) -{ - BiosLbaPacket dapPacket; - dapPacket.Buffer = (uint32) buffer; - return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); -} - - -BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent) -{ - BiosLbaPacket dapPacket; - dapPacket.Buffer = ((uint32) bufferSegment << 16) | bufferOffset; - return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); -} - -BiosResult ReadSectors (uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent) -{ - return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, sector, sectorCount, silent); -} - - -BiosResult ReadSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) -{ - BiosResult result; - uint16 codeSeg; - __asm mov codeSeg, cs - - result = ReadSectors (BootStarted ? codeSeg : TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, drive, sector, sectorCount, silent); - - // Alternative segment is used to prevent memory corruption caused by buggy BIOSes - if (!BootStarted) - CopyMemory (TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, buffer, sectorCount * TC_LB_SIZE); - - return result; -} - - -BiosResult WriteSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) -{ - return ReadWriteSectors (true, buffer, drive, sector, sectorCount, silent); -} - - -BiosResult GetDriveGeometry (byte drive, DriveGeometry &geometry, bool silent) -{ - CheckStack(); - - byte maxCylinderLow, maxHead, maxSector; - BiosResult result; - __asm - { - push es - mov dl, drive - mov ah, 0x08 - int 0x13 - - mov result, ah - mov maxCylinderLow, ch - mov maxSector, cl - mov maxHead, dh - pop es - } - - if (result == BiosResultSuccess) - { - geometry.Cylinders = (maxCylinderLow | (uint16 (maxSector & 0xc0) << 2)) + 1; - geometry.Heads = maxHead + 1; - geometry.Sectors = maxSector & ~0xc0; - } - else if (!silent) - { - PrintError ("Cannot get geometry of drive ", true, false); - PrintHex (drive); - PrintEndl(); - } - - return result; -} - - -void ChsToLba (const DriveGeometry &geometry, const ChsAddress &chs, uint64 &lba) -{ - lba.HighPart = 0; - lba.LowPart = (uint32 (chs.Cylinder) * geometry.Heads + chs.Head) * geometry.Sectors + chs.Sector - 1; -} - - -void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs) -{ - chs.Sector = (lba.LowPart % geometry.Sectors) + 1; - uint32 ch = lba.LowPart / geometry.Sectors; - chs.Head = ch % geometry.Heads; - chs.Cylinder = ch / geometry.Heads; -} - - -void PartitionEntryMBRToPartition (const PartitionEntryMBR &partEntry, Partition &partition) -{ - partition.Active = partEntry.BootIndicator == 0x80; - partition.EndSector.HighPart = 0; - partition.EndSector.LowPart = partEntry.StartLBA + partEntry.SectorCountLBA - 1; - partition.SectorCount.HighPart = 0; - partition.SectorCount.LowPart = partEntry.SectorCountLBA; - partition.StartSector.HighPart = 0; - partition.StartSector.LowPart = partEntry.StartLBA; - partition.Type = partEntry.Type; -} - - -BiosResult ReadWriteMBR (bool write, byte drive, bool silent) -{ - uint64 mbrSector; - mbrSector.HighPart = 0; - mbrSector.LowPart = 0; - - if (write) - return WriteSectors (SectorBuffer, drive, mbrSector, 1, silent); - - return ReadSectors (SectorBuffer, drive, mbrSector, 1, silent); // Uses alternative segment -} - - -BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly, Partition *findPartitionFollowingThis, bool silent) -{ - Partition *followingPartition; - Partition tmpPartition; - - if (findPartitionFollowingThis) - { - assert (partitionArrayCapacity == 1); - partitionArrayCapacity = 0xff; - followingPartition = partitionArray; - partitionArray = &tmpPartition; - - followingPartition->Drive = TC_INVALID_BIOS_DRIVE; - followingPartition->StartSector.LowPart = 0xFFFFffffUL; - } - - AcquireSectorBuffer(); - BiosResult result = ReadWriteMBR (false, drive, silent); - ReleaseSectorBuffer(); - - partitionCount = 0; - - MBR *mbr = (MBR *) SectorBuffer; - if (result != BiosResultSuccess || mbr->Signature != 0xaa55) - return result; - - PartitionEntryMBR mbrPartitions[4]; - memcpy (mbrPartitions, mbr->Partitions, sizeof (mbrPartitions)); - size_t partitionArrayPos = 0, partitionNumber; - - for (partitionNumber = 0; - partitionNumber < array_capacity (mbrPartitions) && partitionArrayPos < partitionArrayCapacity; - ++partitionNumber) - { - const PartitionEntryMBR &partEntry = mbrPartitions[partitionNumber]; - - if (partEntry.SectorCountLBA > 0) - { - Partition &partition = partitionArray[partitionArrayPos]; - PartitionEntryMBRToPartition (partEntry, partition); - - if (activeOnly && !partition.Active) - continue; - - partition.Drive = drive; - partition.Number = partitionNumber; - - if (partEntry.Type == 0x5 || partEntry.Type == 0xf) // Extended partition - { - if (IsLbaSupported (drive)) - { - // Find all extended partitions - uint64 firstExtStartLBA = partition.StartSector; - uint64 extStartLBA = partition.StartSector; - MBR *extMbr = (MBR *) SectorBuffer; - - while (partitionArrayPos < partitionArrayCapacity && - (result = ReadSectors ((byte *) extMbr, drive, extStartLBA, 1, silent)) == BiosResultSuccess - && extMbr->Signature == 0xaa55) - { - if (extMbr->Partitions[0].SectorCountLBA > 0) - { - Partition &logPart = partitionArray[partitionArrayPos]; - PartitionEntryMBRToPartition (extMbr->Partitions[0], logPart); - logPart.Drive = drive; - - logPart.Number = partitionNumber++; - logPart.Primary = false; - - logPart.StartSector.LowPart += extStartLBA.LowPart; - logPart.EndSector.LowPart += extStartLBA.LowPart; - - if (findPartitionFollowingThis) - { - if (logPart.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart - && logPart.StartSector.LowPart < followingPartition->StartSector.LowPart) - { - *followingPartition = logPart; - } - } - else - ++partitionArrayPos; - } - - // Secondary extended - if (extMbr->Partitions[1].Type != 0x5 && extMbr->Partitions[1].Type == 0xf - || extMbr->Partitions[1].SectorCountLBA == 0) - break; - - extStartLBA.LowPart = extMbr->Partitions[1].StartLBA + firstExtStartLBA.LowPart; - } - } - } - else - { - partition.Primary = true; - - if (findPartitionFollowingThis) - { - if (partition.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart - && partition.StartSector.LowPart < followingPartition->StartSector.LowPart) - { - *followingPartition = partition; - } - } - else - ++partitionArrayPos; - } - } - } - - partitionCount = partitionArrayPos; - return result; -} - - -bool GetActiveAndFollowingPartition (byte drive) -{ - size_t partCount; - - // Find active partition - if (GetDrivePartitions (drive, &ActivePartition, 1, partCount, true) != BiosResultSuccess || partCount < 1) - { - ActivePartition.Drive = TC_INVALID_BIOS_DRIVE; - PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); - return false; - } - - // Find partition following the active one - GetDrivePartitions (drive, &PartitionFollowingActive, 1, partCount, false, &ActivePartition); - - return true; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Bios.h" +#include "BootConsoleIo.h" +#include "BootConfig.h" +#include "BootDebug.h" +#include "BootDefs.h" +#include "BootDiskIo.h" +#include "BootStrings.h" + + +byte SectorBuffer[TC_LB_SIZE]; + +#ifdef TC_BOOT_DEBUG_ENABLED +static bool SectorBufferInUse = false; + +void AcquireSectorBuffer () +{ + if (SectorBufferInUse) + TC_THROW_FATAL_EXCEPTION; + + SectorBufferInUse = true; +} + + +void ReleaseSectorBuffer () +{ + SectorBufferInUse = false; +} + +#endif + + +bool IsLbaSupported (byte drive) +{ + static byte CachedDrive = TC_INVALID_BIOS_DRIVE; + static bool CachedStatus; + uint16 result = 0; + + if (CachedDrive == drive) + goto ret; + + __asm + { + mov bx, 0x55aa + mov dl, drive + mov ah, 0x41 + int 0x13 + jc err + mov result, bx + err: + } + + CachedDrive = drive; + CachedStatus = (result == 0xaa55); +ret: + return CachedStatus; +} + + +void PrintDiskError (BiosResult error, bool write, byte drive, const uint64 *sector, const ChsAddress *chs) +{ + PrintEndl(); + Print (write ? "Write" : "Read"); Print (" error:"); + Print (error); + Print (" Drive:"); + Print (drive ^ 0x80); + + if (sector) + { + Print (" Sector:"); + Print (*sector); + } + + if (chs) + { + Print (" CHS:"); + Print (*chs); + } + + PrintEndl(); + Beep(); +} + + +void Print (const ChsAddress &chs) +{ + Print (chs.Cylinder); + PrintChar ('/'); + Print (chs.Head); + PrintChar ('/'); + Print (chs.Sector); +} + + +void PrintSectorCountInMB (const uint64 §orCount) +{ + Print (sectorCount >> (TC_LB_SIZE_BIT_SHIFT_DIVISOR + 2)); Print (" MB "); +} + + +BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) +{ + CheckStack(); + + byte cylinderLow = (byte) chs.Cylinder; + byte sector = chs.Sector; + sector |= byte (chs.Cylinder >> 2) & 0xc0; + byte function = write ? 0x03 : 0x02; + + BiosResult result = BiosResultSuccess; + __asm + { + push es + mov ax, bufferSegment + mov es, ax + mov bx, bufferOffset + mov dl, drive + mov ch, cylinderLow + mov si, chs + mov dh, [si].Head + mov cl, sector + mov al, sectorCount + mov ah, function + int 0x13 + jnc ok // If CF=0, ignore AH to prevent issues caused by potential bugs in BIOSes + mov result, ah + ok: + pop es + } + + if (result == BiosResultEccCorrected) + result = BiosResultSuccess; + + if (!silent && result != BiosResultSuccess) + PrintDiskError (result, write, drive, nullptr, &chs); + + return result; +} + + +BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) +{ + uint16 codeSeg; + __asm mov codeSeg, cs + return ReadWriteSectors (write, codeSeg, (uint16) buffer, drive, chs, sectorCount, silent); +} + + +BiosResult ReadSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) +{ + return ReadWriteSectors (false, buffer, drive, chs, sectorCount, silent); +} + + +BiosResult WriteSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) +{ + return ReadWriteSectors (true, buffer, drive, chs, sectorCount, silent); +} + + +static BiosResult ReadWriteSectors (bool write, BiosLbaPacket &dapPacket, byte drive, const uint64 §or, uint16 sectorCount, bool silent) +{ + CheckStack(); + + if (!IsLbaSupported (drive)) + { + DriveGeometry geometry; + + BiosResult result = GetDriveGeometry (drive, geometry, silent); + if (result != BiosResultSuccess) + return result; + + ChsAddress chs; + LbaToChs (geometry, sector, chs); + return ReadWriteSectors (write, (uint16) (dapPacket.Buffer >> 16), (uint16) dapPacket.Buffer, drive, chs, sectorCount, silent); + } + + dapPacket.Size = sizeof (dapPacket); + dapPacket.Reserved = 0; + dapPacket.SectorCount = sectorCount; + dapPacket.Sector = sector; + + byte function = write ? 0x43 : 0x42; + + BiosResult result = BiosResultSuccess; + __asm + { + mov bx, 0x55aa + mov dl, drive + mov si, [dapPacket] + mov ah, function + xor al, al + int 0x13 + jnc ok // If CF=0, ignore AH to prevent issues caused by potential bugs in BIOSes + mov result, ah + ok: + } + + if (result == BiosResultEccCorrected) + result = BiosResultSuccess; + + if (!silent && result != BiosResultSuccess) + PrintDiskError (result, write, drive, §or); + + return result; +} + + +static BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) +{ + BiosLbaPacket dapPacket; + dapPacket.Buffer = (uint32) buffer; + return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); +} + + +BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent) +{ + BiosLbaPacket dapPacket; + dapPacket.Buffer = ((uint32) bufferSegment << 16) | bufferOffset; + return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); +} + +BiosResult ReadSectors (uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent) +{ + return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, sector, sectorCount, silent); +} + + +BiosResult ReadSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) +{ + BiosResult result; + uint16 codeSeg; + __asm mov codeSeg, cs + + result = ReadSectors (BootStarted ? codeSeg : TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, drive, sector, sectorCount, silent); + + // Alternative segment is used to prevent memory corruption caused by buggy BIOSes + if (!BootStarted) + CopyMemory (TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, buffer, sectorCount * TC_LB_SIZE); + + return result; +} + + +BiosResult WriteSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) +{ + return ReadWriteSectors (true, buffer, drive, sector, sectorCount, silent); +} + + +BiosResult GetDriveGeometry (byte drive, DriveGeometry &geometry, bool silent) +{ + CheckStack(); + + byte maxCylinderLow, maxHead, maxSector; + BiosResult result; + __asm + { + push es + mov dl, drive + mov ah, 0x08 + int 0x13 + + mov result, ah + mov maxCylinderLow, ch + mov maxSector, cl + mov maxHead, dh + pop es + } + + if (result == BiosResultSuccess) + { + geometry.Cylinders = (maxCylinderLow | (uint16 (maxSector & 0xc0) << 2)) + 1; + geometry.Heads = maxHead + 1; + geometry.Sectors = maxSector & ~0xc0; + } + else if (!silent) + { + Print ("Drive "); + Print (drive ^ 0x80); + Print (" not found: "); + PrintErrorNoEndl (""); + Print (result); + PrintEndl(); + } + + return result; +} + + +void ChsToLba (const DriveGeometry &geometry, const ChsAddress &chs, uint64 &lba) +{ + lba.HighPart = 0; + lba.LowPart = (uint32 (chs.Cylinder) * geometry.Heads + chs.Head) * geometry.Sectors + chs.Sector - 1; +} + + +void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs) +{ + chs.Sector = (byte) ((lba.LowPart % geometry.Sectors) + 1); + uint32 ch = lba.LowPart / geometry.Sectors; + chs.Head = (byte) (ch % geometry.Heads); + chs.Cylinder = (uint16) (ch / geometry.Heads); +} + + +void PartitionEntryMBRToPartition (const PartitionEntryMBR &partEntry, Partition &partition) +{ + partition.Active = partEntry.BootIndicator == 0x80; + partition.EndSector.HighPart = 0; + partition.EndSector.LowPart = partEntry.StartLBA + partEntry.SectorCountLBA - 1; + partition.SectorCount.HighPart = 0; + partition.SectorCount.LowPart = partEntry.SectorCountLBA; + partition.StartSector.HighPart = 0; + partition.StartSector.LowPart = partEntry.StartLBA; + partition.Type = partEntry.Type; +} + + +BiosResult ReadWriteMBR (bool write, byte drive, bool silent) +{ + uint64 mbrSector; + mbrSector.HighPart = 0; + mbrSector.LowPart = 0; + + if (write) + return WriteSectors (SectorBuffer, drive, mbrSector, 1, silent); + + return ReadSectors (SectorBuffer, drive, mbrSector, 1, silent); // Uses alternative segment +} + + +BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly, Partition *findPartitionFollowingThis, bool silent) +{ + Partition *followingPartition; + Partition tmpPartition; + + if (findPartitionFollowingThis) + { + assert (partitionArrayCapacity == 1); + partitionArrayCapacity = 0xff; + followingPartition = partitionArray; + partitionArray = &tmpPartition; + + followingPartition->Drive = TC_INVALID_BIOS_DRIVE; + followingPartition->StartSector.LowPart = 0xFFFFffffUL; + } + + AcquireSectorBuffer(); + BiosResult result = ReadWriteMBR (false, drive, silent); + ReleaseSectorBuffer(); + + partitionCount = 0; + + MBR *mbr = (MBR *) SectorBuffer; + if (result != BiosResultSuccess || mbr->Signature != 0xaa55) + return result; + + PartitionEntryMBR mbrPartitions[4]; + memcpy (mbrPartitions, mbr->Partitions, sizeof (mbrPartitions)); + size_t partitionArrayPos = 0, partitionNumber; + + for (partitionNumber = 0; + partitionNumber < array_capacity (mbrPartitions) && partitionArrayPos < partitionArrayCapacity; + ++partitionNumber) + { + const PartitionEntryMBR &partEntry = mbrPartitions[partitionNumber]; + + if (partEntry.SectorCountLBA > 0) + { + Partition &partition = partitionArray[partitionArrayPos]; + PartitionEntryMBRToPartition (partEntry, partition); + + if (activeOnly && !partition.Active) + continue; + + partition.Drive = drive; + partition.Number = partitionNumber; + + if (partEntry.Type == 0x5 || partEntry.Type == 0xf) // Extended partition + { + if (IsLbaSupported (drive)) + { + // Find all extended partitions + uint64 firstExtStartLBA = partition.StartSector; + uint64 extStartLBA = partition.StartSector; + MBR *extMbr = (MBR *) SectorBuffer; + + while (partitionArrayPos < partitionArrayCapacity && + (result = ReadSectors ((byte *) extMbr, drive, extStartLBA, 1, silent)) == BiosResultSuccess + && extMbr->Signature == 0xaa55) + { + if (extMbr->Partitions[0].SectorCountLBA > 0) + { + Partition &logPart = partitionArray[partitionArrayPos]; + PartitionEntryMBRToPartition (extMbr->Partitions[0], logPart); + logPart.Drive = drive; + + logPart.Number = partitionNumber++; + logPart.Primary = false; + + logPart.StartSector.LowPart += extStartLBA.LowPart; + logPart.EndSector.LowPart += extStartLBA.LowPart; + + if (findPartitionFollowingThis) + { + if (logPart.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart + && logPart.StartSector.LowPart < followingPartition->StartSector.LowPart) + { + *followingPartition = logPart; + } + } + else + ++partitionArrayPos; + } + + // Secondary extended + if (extMbr->Partitions[1].Type != 0x5 && extMbr->Partitions[1].Type == 0xf + || extMbr->Partitions[1].SectorCountLBA == 0) + break; + + extStartLBA.LowPart = extMbr->Partitions[1].StartLBA + firstExtStartLBA.LowPart; + } + } + } + else + { + partition.Primary = true; + + if (findPartitionFollowingThis) + { + if (partition.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart + && partition.StartSector.LowPart < followingPartition->StartSector.LowPart) + { + *followingPartition = partition; + } + } + else + ++partitionArrayPos; + } + } + } + + partitionCount = partitionArrayPos; + return result; +} + + +bool GetActivePartition (byte drive) +{ + size_t partCount; + + if (GetDrivePartitions (drive, &ActivePartition, 1, partCount, true) != BiosResultSuccess || partCount < 1) + { + ActivePartition.Drive = TC_INVALID_BIOS_DRIVE; + PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); + return false; + } + + return true; +} diff --git a/Boot/Windows/BootDiskIo.h b/Boot/Windows/BootDiskIo.h index be0b14a..a36190b 100644 --- a/Boot/Windows/BootDiskIo.h +++ b/Boot/Windows/BootDiskIo.h @@ -1,114 +1,114 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootDiskIo -#define TC_HEADER_Boot_BootDiskIo - -#include "Bios.h" -#include "BootDebug.h" -#include "BootDefs.h" - -enum -{ - BiosResultEccCorrected = 0x11 -}; - -#pragma pack(1) - -struct PartitionEntryMBR -{ - byte BootIndicator; - - byte StartHead; - byte StartCylSector; - byte StartCylinder; - - byte Type; - - byte EndHead; - byte EndSector; - byte EndCylinder; - - uint32 StartLBA; - uint32 SectorCountLBA; -}; - -struct MBR -{ - byte Code[446]; - PartitionEntryMBR Partitions[4]; - uint16 Signature; -}; - -struct BiosLbaPacket -{ - byte Size; - byte Reserved; - uint16 SectorCount; - uint32 Buffer; - uint64 Sector; -}; - -#pragma pack() - - -struct ChsAddress -{ - uint16 Cylinder; - byte Head; - byte Sector; -}; - -struct Partition -{ - byte Number; - byte Drive; - bool Active; - uint64 EndSector; - bool Primary; - uint64 SectorCount; - uint64 StartSector; - byte Type; -}; - -struct DriveGeometry -{ - uint16 Cylinders; - byte Heads; - byte Sectors; -}; - - -#ifdef TC_BOOT_DEBUG_ENABLED -void AcquireSectorBuffer (); -void ReleaseSectorBuffer (); -#else -# define AcquireSectorBuffer() -# define ReleaseSectorBuffer() -#endif - -void ChsToLba (const DriveGeometry &geometry, const ChsAddress &chs, uint64 &lba); -bool GetActiveAndFollowingPartition (byte drive); -BiosResult GetDriveGeometry (byte drive, DriveGeometry &geometry, bool silent = false); -BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly = false, Partition *findPartitionFollowingThis = nullptr, bool silent = false); -bool IsLbaSupported (byte drive); -void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs); -void Print (const ChsAddress &chs); -void PrintDiskError (BiosResult error, bool write, byte drive, const uint64 *sector, const ChsAddress *chs = nullptr); -void PrintSectorCountInMB (const uint64 §orCount); -BiosResult ReadWriteMBR (bool write, byte drive, bool silent = false); -BiosResult ReadSectors (uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent = false); -BiosResult ReadSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent = false); -BiosResult ReadSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent = false); -BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent); -BiosResult WriteSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent = false); -BiosResult WriteSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent = false); - -extern byte SectorBuffer[TC_LB_SIZE]; - -#endif // TC_HEADER_Boot_BootDiskIo +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootDiskIo +#define TC_HEADER_Boot_BootDiskIo + +#include "Bios.h" +#include "BootDebug.h" +#include "BootDefs.h" + +enum +{ + BiosResultEccCorrected = 0x11 +}; + +#pragma pack(1) + +struct PartitionEntryMBR +{ + byte BootIndicator; + + byte StartHead; + byte StartCylSector; + byte StartCylinder; + + byte Type; + + byte EndHead; + byte EndSector; + byte EndCylinder; + + uint32 StartLBA; + uint32 SectorCountLBA; +}; + +struct MBR +{ + byte Code[446]; + PartitionEntryMBR Partitions[4]; + uint16 Signature; +}; + +struct BiosLbaPacket +{ + byte Size; + byte Reserved; + uint16 SectorCount; + uint32 Buffer; + uint64 Sector; +}; + +#pragma pack() + + +struct ChsAddress +{ + uint16 Cylinder; + byte Head; + byte Sector; +}; + +struct Partition +{ + byte Number; + byte Drive; + bool Active; + uint64 EndSector; + bool Primary; + uint64 SectorCount; + uint64 StartSector; + byte Type; +}; + +struct DriveGeometry +{ + uint16 Cylinders; + byte Heads; + byte Sectors; +}; + + +#ifdef TC_BOOT_DEBUG_ENABLED +void AcquireSectorBuffer (); +void ReleaseSectorBuffer (); +#else +# define AcquireSectorBuffer() +# define ReleaseSectorBuffer() +#endif + +void ChsToLba (const DriveGeometry &geometry, const ChsAddress &chs, uint64 &lba); +bool GetActivePartition (byte drive); +BiosResult GetDriveGeometry (byte drive, DriveGeometry &geometry, bool silent = false); +BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly = false, Partition *findPartitionFollowingThis = nullptr, bool silent = false); +bool IsLbaSupported (byte drive); +void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs); +void Print (const ChsAddress &chs); +void PrintDiskError (BiosResult error, bool write, byte drive, const uint64 *sector, const ChsAddress *chs = nullptr); +void PrintSectorCountInMB (const uint64 §orCount); +BiosResult ReadWriteMBR (bool write, byte drive, bool silent = false); +BiosResult ReadSectors (uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent = false); +BiosResult ReadSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent = false); +BiosResult ReadSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent = false); +BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent); +BiosResult WriteSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent = false); +BiosResult WriteSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent = false); + +extern byte SectorBuffer[TC_LB_SIZE]; + +#endif // TC_HEADER_Boot_BootDiskIo diff --git a/Boot/Windows/BootEncryptedIo.cpp b/Boot/Windows/BootEncryptedIo.cpp index 957ce65..93b6c3f 100644 --- a/Boot/Windows/BootEncryptedIo.cpp +++ b/Boot/Windows/BootEncryptedIo.cpp @@ -1,128 +1,128 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Crypto.h" -#include "Platform.h" -#include "BootConfig.h" -#include "BootDebug.h" -#include "BootDefs.h" -#include "BootDiskIo.h" -#include "BootEncryptedIo.h" - - -BiosResult ReadEncryptedSectors (uint16 destSegment, uint16 destOffset, byte drive, uint64 sector, uint16 sectorCount) -{ - BiosResult result; - bool decrypt = true; - - if (BootCryptoInfo->hiddenVolume) - { - if (ReadWritePartiallyCoversEncryptedArea (sector, sectorCount)) - return BiosResultInvalidFunction; - - if (sector >= EncryptedVirtualPartition.StartSector && sector <= EncryptedVirtualPartition.EndSector) - { - // Remap the request to the hidden volume - sector -= EncryptedVirtualPartition.StartSector; - sector += HiddenVolumeStartSector; - } - else - decrypt = false; - } - - result = ReadSectors (destSegment, destOffset, drive, sector, sectorCount); - - if (result != BiosResultSuccess || !decrypt) - return result; - - if (BootCryptoInfo->hiddenVolume) - { - // Convert sector number to data unit number of the hidden volume - sector -= HiddenVolumeStartSector; - sector += HiddenVolumeStartUnitNo; - } - - if (drive == EncryptedVirtualPartition.Drive) - { - while (sectorCount-- > 0) - { - if (BootCryptoInfo->hiddenVolume - || (sector >= EncryptedVirtualPartition.StartSector && sector <= EncryptedVirtualPartition.EndSector)) - { - AcquireSectorBuffer(); - CopyMemory (destSegment, destOffset, SectorBuffer, TC_LB_SIZE); - - DecryptDataUnits (SectorBuffer, §or, 1, BootCryptoInfo); - - CopyMemory (SectorBuffer, destSegment, destOffset, TC_LB_SIZE); - ReleaseSectorBuffer(); - } - - ++sector; - destOffset += TC_LB_SIZE; - } - } - - return result; -} - - -BiosResult WriteEncryptedSectors (uint16 sourceSegment, uint16 sourceOffset, byte drive, uint64 sector, uint16 sectorCount) -{ - BiosResult result; - AcquireSectorBuffer(); - uint64 dataUnitNo; - uint64 writeOffset; - - dataUnitNo = sector; - writeOffset.HighPart = 0; - writeOffset.LowPart = 0; - - if (BootCryptoInfo->hiddenVolume) - { - if (ReadWritePartiallyCoversEncryptedArea (sector, sectorCount)) - return BiosResultInvalidFunction; - - // Remap the request to the hidden volume - writeOffset = HiddenVolumeStartSector; - writeOffset -= EncryptedVirtualPartition.StartSector; - dataUnitNo -= EncryptedVirtualPartition.StartSector; - dataUnitNo += HiddenVolumeStartUnitNo; - } - - while (sectorCount-- > 0) - { - CopyMemory (sourceSegment, sourceOffset, SectorBuffer, TC_LB_SIZE); - - if (drive == EncryptedVirtualPartition.Drive && sector >= EncryptedVirtualPartition.StartSector && sector <= EncryptedVirtualPartition.EndSector) - { - EncryptDataUnits (SectorBuffer, &dataUnitNo, 1, BootCryptoInfo); - } - - result = WriteSectors (SectorBuffer, drive, sector + writeOffset, 1); - - if (result != BiosResultSuccess) - break; - - ++sector; - ++dataUnitNo; - sourceOffset += TC_LB_SIZE; - } - - ReleaseSectorBuffer(); - return result; -} - - -static bool ReadWritePartiallyCoversEncryptedArea (const uint64 §or, uint16 sectorCount) -{ - uint64 readWriteEnd = sector + --sectorCount; - - return ((sector < EncryptedVirtualPartition.StartSector && readWriteEnd >= EncryptedVirtualPartition.StartSector) - || (sector >= EncryptedVirtualPartition.StartSector && readWriteEnd > EncryptedVirtualPartition.EndSector)); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Crypto.h" +#include "Platform.h" +#include "BootConfig.h" +#include "BootDebug.h" +#include "BootDefs.h" +#include "BootDiskIo.h" +#include "BootEncryptedIo.h" + + +BiosResult ReadEncryptedSectors (uint16 destSegment, uint16 destOffset, byte drive, uint64 sector, uint16 sectorCount) +{ + BiosResult result; + bool decrypt = true; + + if (BootCryptoInfo->hiddenVolume) + { + if (ReadWritePartiallyCoversEncryptedArea (sector, sectorCount)) + return BiosResultInvalidFunction; + + if (sector >= EncryptedVirtualPartition.StartSector && sector <= EncryptedVirtualPartition.EndSector) + { + // Remap the request to the hidden volume + sector -= EncryptedVirtualPartition.StartSector; + sector += HiddenVolumeStartSector; + } + else + decrypt = false; + } + + result = ReadSectors (destSegment, destOffset, drive, sector, sectorCount); + + if (result != BiosResultSuccess || !decrypt) + return result; + + if (BootCryptoInfo->hiddenVolume) + { + // Convert sector number to data unit number of the hidden volume + sector -= HiddenVolumeStartSector; + sector += HiddenVolumeStartUnitNo; + } + + if (drive == EncryptedVirtualPartition.Drive) + { + while (sectorCount-- > 0) + { + if (BootCryptoInfo->hiddenVolume + || (sector >= EncryptedVirtualPartition.StartSector && sector <= EncryptedVirtualPartition.EndSector)) + { + AcquireSectorBuffer(); + CopyMemory (destSegment, destOffset, SectorBuffer, TC_LB_SIZE); + + DecryptDataUnits (SectorBuffer, §or, 1, BootCryptoInfo); + + CopyMemory (SectorBuffer, destSegment, destOffset, TC_LB_SIZE); + ReleaseSectorBuffer(); + } + + ++sector; + destOffset += TC_LB_SIZE; + } + } + + return result; +} + + +BiosResult WriteEncryptedSectors (uint16 sourceSegment, uint16 sourceOffset, byte drive, uint64 sector, uint16 sectorCount) +{ + BiosResult result; + AcquireSectorBuffer(); + uint64 dataUnitNo; + uint64 writeOffset; + + dataUnitNo = sector; + writeOffset.HighPart = 0; + writeOffset.LowPart = 0; + + if (BootCryptoInfo->hiddenVolume) + { + if (ReadWritePartiallyCoversEncryptedArea (sector, sectorCount)) + return BiosResultInvalidFunction; + + // Remap the request to the hidden volume + writeOffset = HiddenVolumeStartSector; + writeOffset -= EncryptedVirtualPartition.StartSector; + dataUnitNo -= EncryptedVirtualPartition.StartSector; + dataUnitNo += HiddenVolumeStartUnitNo; + } + + while (sectorCount-- > 0) + { + CopyMemory (sourceSegment, sourceOffset, SectorBuffer, TC_LB_SIZE); + + if (drive == EncryptedVirtualPartition.Drive && sector >= EncryptedVirtualPartition.StartSector && sector <= EncryptedVirtualPartition.EndSector) + { + EncryptDataUnits (SectorBuffer, &dataUnitNo, 1, BootCryptoInfo); + } + + result = WriteSectors (SectorBuffer, drive, sector + writeOffset, 1); + + if (result != BiosResultSuccess) + break; + + ++sector; + ++dataUnitNo; + sourceOffset += TC_LB_SIZE; + } + + ReleaseSectorBuffer(); + return result; +} + + +static bool ReadWritePartiallyCoversEncryptedArea (const uint64 §or, uint16 sectorCount) +{ + uint64 readWriteEnd = sector + --sectorCount; + + return ((sector < EncryptedVirtualPartition.StartSector && readWriteEnd >= EncryptedVirtualPartition.StartSector) + || (sector >= EncryptedVirtualPartition.StartSector && readWriteEnd > EncryptedVirtualPartition.EndSector)); +} diff --git a/Boot/Windows/BootEncryptedIo.h b/Boot/Windows/BootEncryptedIo.h index 52d1c30..0a18846 100644 --- a/Boot/Windows/BootEncryptedIo.h +++ b/Boot/Windows/BootEncryptedIo.h @@ -1,18 +1,18 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootEncryptionIo -#define TC_HEADER_Boot_BootEncryptionIo - -#include "Platform.h" - -BiosResult ReadEncryptedSectors (uint16 destSegment, uint16 destOffset, byte drive, uint64 sector, uint16 sectorCount); -BiosResult WriteEncryptedSectors (uint16 sourceSegment, uint16 sourceOffset, byte drive, uint64 sector, uint16 sectorCount); -static bool ReadWritePartiallyCoversEncryptedArea (const uint64 §or, uint16 sectorCount); - -#endif // TC_HEADER_Boot_BootEncryptionIo +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootEncryptionIo +#define TC_HEADER_Boot_BootEncryptionIo + +#include "Platform.h" + +BiosResult ReadEncryptedSectors (uint16 destSegment, uint16 destOffset, byte drive, uint64 sector, uint16 sectorCount); +BiosResult WriteEncryptedSectors (uint16 sourceSegment, uint16 sourceOffset, byte drive, uint64 sector, uint16 sectorCount); +static bool ReadWritePartiallyCoversEncryptedArea (const uint64 §or, uint16 sectorCount); + +#endif // TC_HEADER_Boot_BootEncryptionIo diff --git a/Boot/Windows/BootMain.cpp b/Boot/Windows/BootMain.cpp index 6900df7..b83efec 100644 --- a/Boot/Windows/BootMain.cpp +++ b/Boot/Windows/BootMain.cpp @@ -1,1095 +1,1144 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Crc.h" -#include "Crypto.h" -#include "Password.h" -#include "Volumes.h" - -#include "Platform.h" -#include "Bios.h" -#include "BootConfig.h" -#include "BootMain.h" -#include "BootDefs.h" -#include "BootCommon.h" -#include "BootConsoleIo.h" -#include "BootDebug.h" -#include "BootDiskIo.h" -#include "BootEncryptedIo.h" -#include "BootMemory.h" -#include "BootStrings.h" -#include "IntFilter.h" - - -static void InitScreen () -{ - ClearScreen(); - - const char *title = -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - " TrueCrypt Boot Loader " -#else - " TrueCrypt Rescue Disk " -#endif - VERSION_STRING; - - Print (title); - PrintRepeatedChar (' ', title[26] ? 8 : 9); - Print ("Copyright (C) 2008-2009 TrueCrypt Foundation\r\n"); - - PrintRepeatedChar ('\xDC', TC_BIOS_MAX_CHARS_PER_LINE); - -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - if (CustomUserMessage[0]) - { - PrintEndl(); - Print (CustomUserMessage); - } -#endif - - PrintEndl (2); -} - - -static void PrintMainMenu () -{ - if (PreventBootMenu) - return; - - Print (" Keyboard Controls:\r\n"); - Print (" [Esc] "); - -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - Print ((BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE - ? "Boot Non-Hidden System (Boot Manager)" - : "Skip Authentication (Boot Manager)"); - -#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - Print ("Skip Authentication (Boot Manager)"); - Print ("\r\n [F8] "); Print ("Repair Options"); - -#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - PrintEndl (3); -} - - -static bool IsMenuKey (byte scanCode) -{ -#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - return scanCode == TC_MENU_KEY_REPAIR; -#else - return false; -#endif -} - - -static bool AskYesNo (const char *message) -{ - Print (message); - Print ("? (y/n): "); - while (true) - { - switch (GetKeyboardChar()) - { - case 'y': - case 'Y': - case 'z': - case 'Z': - Print ("y\r\n"); - return true; - - case 'n': - case 'N': - Print ("n\r\n"); - return false; - - default: - Beep(); - } - } -} - - -static int AskSelection (const char *options[], size_t optionCount) -{ - for (int i = 0; i < optionCount; ++i) - { - Print ("["); Print (i + 1); Print ("] "); - Print (options[i]); - PrintEndl(); - } - Print ("[Esc] Cancel\r\n\r\n"); - - Print ("To select, press 1-9: "); - - char str; - - while (true) - { - if (GetString (&str, 1) == 0) - return 0; - - if (str >= '1' && str <= optionCount + '0') - return str - '0'; - - Beep(); - PrintBackspace(); - } -} - - -static byte AskPassword (Password &password) -{ - size_t pos = 0; - byte scanCode; - byte asciiCode; - - Print ("Enter password"); - Print (PreventNormalSystemBoot ? " for hidden system:\r\n" : ": "); - - while (true) - { - asciiCode = GetKeyboardChar (&scanCode); - - switch (scanCode) - { - case TC_BIOS_KEY_ENTER: - ClearBiosKeystrokeBuffer(); - PrintEndl(); - - password.Length = pos; - return scanCode; - - case TC_BIOS_KEY_BACKSPACE: - if (pos > 0) - { - if (pos < MAX_PASSWORD) - PrintBackspace(); - else - PrintCharAtCursor (' '); - - --pos; - } - continue; - - default: - if (scanCode == TC_BIOS_KEY_ESC || IsMenuKey (scanCode)) - { - burn (password.Text, sizeof (password.Text)); - ClearBiosKeystrokeBuffer(); - - PrintEndl(); - return scanCode; - } - } - - if (!IsPrintable (asciiCode) || pos == MAX_PASSWORD) - { - Beep(); - continue; - } - - password.Text[pos++] = asciiCode; - if (pos < MAX_PASSWORD) - PrintChar ('*'); - else - PrintCharAtCursor ('*'); - } -} - - -static void ExecuteBootSector (byte drive, byte *sectorBuffer) -{ - Print ("Booting...\r\n"); - CopyMemory (sectorBuffer, 0x0000, 0x7c00, TC_LB_SIZE); - - BootStarted = true; - - uint32 addr = 0x7c00; - __asm - { - cli - mov dl, drive // Boot drive - mov dh, 0 - xor ax, ax - mov si, ax - mov ds, ax - mov es, ax - mov ss, ax - mov sp, 0x7c00 - sti - - jmp cs:addr - } -} - - -static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headerSaltCrc32, bool skipNormal, bool skipHidden) -{ - int volumeType; - bool hiddenVolume; - uint64 headerSec; - - AcquireSectorBuffer(); - - for (volumeType = 1; volumeType <= 2; ++volumeType) - { - hiddenVolume = (volumeType == 2); - - if (hiddenVolume) - { - if (skipHidden || PartitionFollowingActive.Drive != drive || PartitionFollowingActive.SectorCount <= ActivePartition.SectorCount) - continue; - - headerSec = PartitionFollowingActive.StartSector + TC_HIDDEN_VOLUME_HEADER_OFFSET / TC_LB_SIZE; - } - else - { - if (skipNormal) - continue; - - headerSec.HighPart = 0; - headerSec.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR; - } - - if (ReadSectors (SectorBuffer, drive, headerSec, 1) != BiosResultSuccess) - continue; - - if (ReadVolumeHeader (!hiddenVolume, (char *) SectorBuffer, &password, cryptoInfo, nullptr) == ERR_SUCCESS) - { - // Prevent opening a non-system hidden volume - if (hiddenVolume && !((*cryptoInfo)->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)) - { - crypto_close (*cryptoInfo); - continue; - } - - if (headerSaltCrc32) - *headerSaltCrc32 = GetCrc32 (SectorBuffer, PKCS5_SALT_SIZE); - - break; - } - } - - ReleaseSectorBuffer(); - return volumeType != 3; -} - - -static bool CheckMemoryRequirements () -{ - uint16 codeSeg; - __asm mov codeSeg, cs - if (codeSeg == TC_BOOT_LOADER_LOWMEM_SEGMENT) - { - PrintError ("BIOS reserved too much memory: ", true, false); - - uint16 memFree; - __asm - { - push es - xor ax, ax - mov es, ax - mov ax, es:[0x413] - mov memFree, ax - pop es - } - - Print (memFree); - PrintEndl(); - Print (TC_BOOT_STR_UPGRADE_BIOS); - - return false; - } - - return true; -} - - -static bool MountVolume (byte drive, byte &exitKey, bool skipNormal, bool skipHidden) -{ - BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; - int incorrectPasswordCount = 0; - - EraseMemory (bootArguments, sizeof (*bootArguments)); - - // Open volume header - while (true) - { - exitKey = AskPassword (bootArguments->BootPassword); - - if (exitKey != TC_BIOS_KEY_ENTER) - return false; - - if (OpenVolume (BootDrive, bootArguments->BootPassword, &BootCryptoInfo, &bootArguments->HeaderSaltCrc32, skipNormal, skipHidden)) - break; - - if (GetShiftFlags() & TC_BIOS_SHIFTMASK_CAPSLOCK) - Print ("Warning: Caps Lock is on.\r\n"); - - Print ("Incorrect password.\r\n\r\n"); - - if (++incorrectPasswordCount == 4) - { -#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - Print ("The key data may be damaged. Use 'Repair Options' > 'Restore key data'.\r\n\r\n"); -#else - Print ("If you are sure the password is correct, the key data may be damaged. Boot your\r\n" - "TrueCrypt Rescue Disk and select 'Repair Options' > 'Restore key data'.\r\n\r\n"); -#endif - } - } - - // Setup boot arguments - bootArguments->BootLoaderVersion = VERSION_NUM; - bootArguments->CryptoInfoOffset = (uint16) BootCryptoInfo; - bootArguments->CryptoInfoLength = sizeof (*BootCryptoInfo); - - if (BootCryptoInfo->hiddenVolume) - bootArguments->HiddenSystemPartitionStart = PartitionFollowingActive.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; - - TC_SET_BOOT_ARGUMENTS_SIGNATURE (bootArguments->Signature); - - // Setup virtual encrypted partition - if (BootCryptoInfo->EncryptedAreaLength.HighPart != 0 || BootCryptoInfo->EncryptedAreaLength.LowPart != 0) - { - EncryptedVirtualPartition.Drive = BootDrive; - - EncryptedVirtualPartition.StartSector = BootCryptoInfo->EncryptedAreaStart >> TC_LB_SIZE_BIT_SHIFT_DIVISOR; - - HiddenVolumeStartUnitNo = EncryptedVirtualPartition.StartSector; - HiddenVolumeStartSector = PartitionFollowingActive.StartSector; - HiddenVolumeStartSector += EncryptedVirtualPartition.StartSector; - - EncryptedVirtualPartition.SectorCount = BootCryptoInfo->EncryptedAreaLength >> TC_LB_SIZE_BIT_SHIFT_DIVISOR; - - EncryptedVirtualPartition.EndSector = EncryptedVirtualPartition.SectorCount - 1; - EncryptedVirtualPartition.EndSector += EncryptedVirtualPartition.StartSector; - } - else - { - // Drive not encrypted - EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE; - } - - return true; -} - - -static byte BootEncryptedDrive () -{ - BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; - byte exitKey; - BootCryptoInfo = NULL; - - if (!GetActiveAndFollowingPartition (BootDrive)) - goto err; - - if (!MountVolume (BootDrive, exitKey, PreventNormalSystemBoot, false)) - return exitKey; - - if (!CheckMemoryRequirements ()) - goto err; - - if (BootCryptoInfo->hiddenVolume) - { - EncryptedVirtualPartition = ActivePartition; - bootArguments->DecoySystemPartitionStart = ActivePartition.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; - } - - if (!InstallInterruptFilters()) - goto err; - - bootArguments->BootArgumentsCrc32 = GetCrc32 ((byte *) bootArguments, (byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments); - - while (true) - { - // Execute boot sector of the active partition - if (ReadSectors (SectorBuffer, ActivePartition.Drive, ActivePartition.StartSector, 1) == BiosResultSuccess) - { - if (*(uint16 *) (SectorBuffer + 510) != 0xaa55) - { - PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); - GetKeyboardChar(); - } - - ExecuteBootSector (ActivePartition.Drive, SectorBuffer); - } - - GetKeyboardChar(); - } - -err: - if (BootCryptoInfo) - { - crypto_close (BootCryptoInfo); - BootCryptoInfo = NULL; - } - - EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE; - EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments)); - - byte scanCode; - GetKeyboardChar (&scanCode); - return scanCode; -} - - -static void BootMenu () -{ - BiosResult result; - Partition partitions[16]; - Partition bootablePartitions[9]; - size_t partitionCount; - size_t bootablePartitionCount = 0; - - for (byte drive = TC_FIRST_BIOS_DRIVE; drive <= TC_LAST_BIOS_DRIVE; ++drive) - { - if (GetDrivePartitions (drive, partitions, array_capacity (partitions), partitionCount, false, nullptr, true) == BiosResultSuccess) - { - for (size_t i = 0; i < partitionCount; ++i) - { - const Partition &partition = partitions[i]; - result = ReadSectors (SectorBuffer, drive, partition.StartSector, 1); - - if (result == BiosResultSuccess && *(uint16 *) (SectorBuffer + TC_LB_SIZE - 2) == 0xaa55) - { - // Windows writes boot loader on all NTFS/FAT filesytems it creates and, therefore, - // NTFS/FAT partitions must have the boot indicator set to be considered bootable. - if (!partition.Active - && (*(uint32 *) (SectorBuffer + 3) == 0x5346544e // 'NTFS' - || *(uint32 *) (SectorBuffer + 3) == 0x41465845 && SectorBuffer[7] == 'T' // 'exFAT' - || *(uint16 *) (SectorBuffer + 54) == 0x4146 && SectorBuffer[56] == 'T' // 'FAT' - || *(uint16 *) (SectorBuffer + 82) == 0x4146 && SectorBuffer[84] == 'T')) - { - continue; - } - - // Bootable sector found - if (bootablePartitionCount < array_capacity (bootablePartitions)) - bootablePartitions[bootablePartitionCount++] = partition; - } - } - } - } - - if (bootablePartitionCount < 1) - { - PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); - GetKeyboardChar(); - return; - } - - char partChar; - while (true) - { - InitScreen(); - Print ("Bootable Partitions:\r\n"); - PrintRepeatedChar ('\xC4', 20); - Print ("\r\n"); - - for (size_t i = 0; i < bootablePartitionCount; ++i) - { - const Partition &partition = bootablePartitions[i]; - Print ("["); Print (i + 1); Print ("] "); - Print ("Drive: "); Print (partition.Drive - TC_FIRST_BIOS_DRIVE); - Print (", Partition: "); Print (partition.Number + 1); - Print (", Size: "); PrintSectorCountInMB (partition.SectorCount); PrintEndl(); - } - - if (bootablePartitionCount == 1) - { - // There's only one bootable partition so we'll boot it directly instead of showing boot manager - partChar = '1'; - } - else - { - Print ("[Esc] Cancel\r\n\r\n"); - Print ("Press 1-9 to select partition: "); - - if (GetString (&partChar, 1) == 0) - return; - - PrintEndl(); - - if (partChar < '1' || partChar > '0' + bootablePartitionCount) - { - Beep(); - continue; - } - } - - const Partition &partition = bootablePartitions[partChar - '0' - 1]; - - if (ReadSectors (SectorBuffer, partition.Drive, partition.StartSector, 1) == BiosResultSuccess) - { - ExecuteBootSector (partition.Drive, SectorBuffer); - } - } -} - - -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - -static bool CopyActivePartitionToHiddenVolume (byte drive, byte &exitKey) -{ - bool status = false; - - uint64 sectorsRemaining; - uint64 sectorOffset; - sectorOffset.LowPart = 0; - sectorOffset.HighPart = 0; - - int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS - int statCount; - - if (!CheckMemoryRequirements ()) - goto err; - - if (!GetActiveAndFollowingPartition (drive)) - goto err; - - if (PartitionFollowingActive.Drive == TC_INVALID_BIOS_DRIVE) - TC_THROW_FATAL_EXCEPTION; - - // Check if BIOS can read the last sector of the hidden system - AcquireSectorBuffer(); - - if (ReadSectors (SectorBuffer, PartitionFollowingActive.Drive, PartitionFollowingActive.EndSector - (TC_VOLUME_HEADER_GROUP_SIZE / TC_LB_SIZE - 2), 1) != BiosResultSuccess - || GetCrc32 (SectorBuffer, sizeof (SectorBuffer)) != OuterVolumeBackupHeaderCrc) - { - if (!IsLbaSupported (PartitionFollowingActive.Drive)) - Print ("BIOS: LBA N/A\r\n"); - - PrintError ("Your BIOS does not support large drives"); - Print (TC_BOOT_STR_UPGRADE_BIOS); - - ReleaseSectorBuffer(); - goto err; - } - - ReleaseSectorBuffer(); - - if (!MountVolume (drive, exitKey, true, false)) - return false; - - sectorsRemaining = EncryptedVirtualPartition.SectorCount; - - if (!(sectorsRemaining == ActivePartition.SectorCount)) - TC_THROW_FATAL_EXCEPTION; - - InitScreen(); - Print ("\r\nCopying system to hidden volume. To abort, press Esc.\r\n\r\n"); - - while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0) - { - if (EscKeyPressed()) - { - Print ("\rIf aborted, copying will have to start from the beginning (if attempted again).\r\n"); - if (AskYesNo ("Abort")) - break; - } - - if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) - fragmentSectorCount = sectorsRemaining.LowPart; - - if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, ActivePartition.StartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) - { - Print ("To fix bad sectors: 1) Terminate 2) Encrypt and decrypt sys partition 3) Retry\r\n"); - crypto_close (BootCryptoInfo); - goto err; - } - - AcquireSectorBuffer(); - - for (int i = 0; i < fragmentSectorCount; ++i) - { - CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE); - - uint64 s = HiddenVolumeStartUnitNo + sectorOffset + i; - EncryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo); - - CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE); - } - - ReleaseSectorBuffer(); - - if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, HiddenVolumeStartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) - { - crypto_close (BootCryptoInfo); - goto err; - } - - sectorsRemaining = sectorsRemaining - fragmentSectorCount; - sectorOffset = sectorOffset + fragmentSectorCount; - - if (!(statCount++ & 0xf)) - { - Print ("\rRemaining: "); - PrintSectorCountInMB (sectorsRemaining); - } - } - - crypto_close (BootCryptoInfo); - - if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0) - { - status = true; - Print ("\rCopying completed."); - } - - PrintEndl (2); - goto ret; - -err: - exitKey = TC_BIOS_KEY_ESC; - GetKeyboardChar(); - -ret: - EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments)); - return status; -} - - -#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - -static void DecryptDrive (byte drive) -{ - byte exitKey; - if (!MountVolume (drive, exitKey, false, true)) - return; - - BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; - - bool headerUpdateRequired = false; - uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector; - uint64 sector = EncryptedVirtualPartition.EndSector + 1; - - int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS - int statCount; - - bool skipBadSectors = false; - - Print ("\r\nUse only if Windows cannot start. Decryption under Windows is much faster\r\n" - "(in TrueCrypt, select 'System' > 'Permanently Decrypt').\r\n\r\n"); - - if (!AskYesNo ("Decrypt now")) - { - crypto_close (BootCryptoInfo); - goto ret; - } - - if (EncryptedVirtualPartition.Drive == TC_INVALID_BIOS_DRIVE) - { - // Drive already decrypted - sectorsRemaining.HighPart = 0; - sectorsRemaining.LowPart = 0; - } - else - { - Print ("\r\nTo safely interrupt and defer decryption, press Esc.\r\n" - "WARNING: You can turn off power only after you press Esc.\r\n\r\n"); - } - - while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0) - { - if (EscKeyPressed()) - break; - - if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) - fragmentSectorCount = sectorsRemaining.LowPart; - - sector = sector - fragmentSectorCount; - - if (!(statCount++ & 0xf)) - { - Print ("\rRemaining: "); - PrintSectorCountInMB (sectorsRemaining); - } - - if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) == BiosResultSuccess) - { - AcquireSectorBuffer(); - - for (int i = 0; i < fragmentSectorCount; ++i) - { - CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE); - - uint64 s = sector + i; - DecryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo); - - CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE); - } - - ReleaseSectorBuffer(); - - if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) != BiosResultSuccess && !skipBadSectors) - goto askBadSectorSkip; - } - else if (!skipBadSectors) - goto askBadSectorSkip; - - sectorsRemaining = sectorsRemaining - fragmentSectorCount; - headerUpdateRequired = true; - continue; - -askBadSectorSkip: - if (!AskYesNo ("Skip all bad sectors")) - break; - - skipBadSectors = true; - sector = sector + fragmentSectorCount; - fragmentSectorCount = 1; - } - - crypto_close (BootCryptoInfo); - - if (headerUpdateRequired) - { - AcquireSectorBuffer(); - uint64 headerSector; - headerSector.HighPart = 0; - headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR; - - // Update encrypted area size in volume header - - CRYPTO_INFO *headerCryptoInfo = crypto_open(); - while (ReadSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess); - - if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0) - { - DecryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); - - uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR; - - for (int i = 7; i >= 0; --i) - { - SectorBuffer[TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH + i] = (byte) encryptedAreaLength.LowPart; - encryptedAreaLength = encryptedAreaLength >> 8; - } - - uint32 headerCrc32 = GetCrc32 (SectorBuffer + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); - - for (i = 3; i >= 0; --i) - { - SectorBuffer[TC_HEADER_OFFSET_HEADER_CRC + i] = (byte) headerCrc32; - headerCrc32 >>= 8; - } - - EncryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); - } - - crypto_close (headerCryptoInfo); - - while (WriteSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess); - ReleaseSectorBuffer(); - } - - if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0) - Print ("\rDrive decrypted.\r\n"); - else - Print ("\r\nDecryption deferred.\r\n"); - - GetKeyboardChar(); -ret: - EraseMemory (bootArguments, sizeof (*bootArguments)); -} - - -static void RepairMenu () -{ - DriveGeometry bootLoaderDriveGeometry; - - if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry, true) != BiosResultSuccess) - { - // Some BIOSes may fail to get the geometry of an emulated floppy drive - bootLoaderDriveGeometry.Cylinders = 80; - bootLoaderDriveGeometry.Heads = 2; - bootLoaderDriveGeometry.Sectors = 18; - } - - while (true) - { - InitScreen(); - Print ("Available "); Print ("Repair Options"); Print (":\r\n"); - PrintRepeatedChar ('\xC4', 25); - PrintEndl(); - - enum - { - RestoreNone = 0, - DecryptVolume, - RestoreTrueCryptLoader, - RestoreVolumeHeader, - RestoreOriginalSystemLoader - }; - - static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" }; - - int selection = AskSelection (options, - (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER) ? array_capacity (options) : array_capacity (options) - 1); - - PrintEndl(); - - switch (selection) - { - case RestoreNone: - return; - - case DecryptVolume: - DecryptDrive (BootDrive); - continue; - - case RestoreOriginalSystemLoader: - if (!AskYesNo ("Is the system partition/drive decrypted")) - { - Print ("Please decrypt it first.\r\n"); - GetKeyboardChar(); - continue; - } - break; - } - - bool writeConfirmed = false; - BiosResult result; - - uint64 sector; - sector.HighPart = 0; - ChsAddress chs; - - byte mbrPartTable[TC_LB_SIZE - TC_MAX_MBR_BOOT_CODE_SIZE]; - AcquireSectorBuffer(); - - for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR); - i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i) - { - sector.LowPart = i; - - if (selection == RestoreOriginalSystemLoader) - sector.LowPart += TC_ORIG_BOOT_LOADER_BACKUP_SECTOR; - else if (selection == RestoreTrueCryptLoader) - sector.LowPart += TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR; - - // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used. - // Therefore, only CHS addressing can be used. - LbaToChs (bootLoaderDriveGeometry, sector, chs); - sector.LowPart = i; - - if (i == TC_MBR_SECTOR) - { - // Read current partition table - result = ReadSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1); - if (result != BiosResultSuccess) - goto err; - - memcpy (mbrPartTable, SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbrPartTable)); - } - - result = ReadSectors (SectorBuffer, BootLoaderDrive, chs, 1); - if (result != BiosResultSuccess) - goto err; - - if (i == TC_MBR_SECTOR) - { - // Preserve current partition table - memcpy (SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, mbrPartTable, sizeof (mbrPartTable)); - } - - // Volume header - if (i == TC_BOOT_VOLUME_HEADER_SECTOR) - { - if (selection == RestoreTrueCryptLoader) - continue; - - if (selection == RestoreVolumeHeader) - { - while (true) - { - Password password; - byte exitKey = AskPassword (password); - - if (exitKey != TC_BIOS_KEY_ENTER) - goto abort; - - CRYPTO_INFO *cryptoInfo; - - CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, TC_LB_SIZE); - ReleaseSectorBuffer(); - - // Restore volume header only if the current one cannot be used - if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo, nullptr, false, true)) - { - Print ("Original header preserved.\r\n"); - crypto_close (cryptoInfo); - goto err; - } - - AcquireSectorBuffer(); - CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, 0, SectorBuffer, TC_LB_SIZE); - - if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0) - { - crypto_close (cryptoInfo); - break; - } - - Print ("Incorrect password.\r\n\r\n"); - } - } - } - - if (!writeConfirmed && !AskYesNo ("Modify drive 0")) - goto abort; - writeConfirmed = true; - - if (WriteSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess) - goto err; - } -done: - switch (selection) - { - case RestoreTrueCryptLoader: - Print ("TrueCrypt Boot Loader"); - break; - - case RestoreVolumeHeader: - Print ("Header"); - break; - - case RestoreOriginalSystemLoader: - Print ("System loader"); - break; - } - Print (" restored.\r\n"); - -err: GetKeyboardChar(); -abort: ReleaseSectorBuffer(); - } -} - -#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - -#ifndef DEBUG -extern "C" void _acrtused () { } // Required by linker -#endif - - -void main () -{ - __asm mov BootLoaderDrive, dl - __asm mov BootSectorFlags, dh - -#ifdef TC_BOOT_TRACING_ENABLED - InitDebugPort(); -#endif - -#ifdef TC_BOOT_STACK_CHECKING_ENABLED - InitStackChecker(); -#endif - -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - ReadBootSectorUserConfiguration(); -#endif - - InitVideoMode(); - InitScreen(); - - // Determine boot drive - BootDrive = BootLoaderDrive; - if (BootDrive < TC_FIRST_BIOS_DRIVE) - BootDrive = TC_FIRST_BIOS_DRIVE; - - // Query boot drive geometry - if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess) - { - BootDrive = TC_FIRST_BIOS_DRIVE; - if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess) - BootDriveGeometryValid = TRUE; - } - else - BootDriveGeometryValid = TRUE; - - -#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - // Check whether the user is not using the Rescue Disk to create a hidden system - - if (ReadWriteMBR (false, BootDrive, true) == BiosResultSuccess - && *(uint32 *) (SectorBuffer + 6) == 0x65757254 - && *(uint32 *) (SectorBuffer + 10) == 0x70797243 - && (SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE) - { - PrintError ("It appears you are creating a hidden OS."); - if (AskYesNo ("Is this correct")) - { - Print ("Please remove the Rescue Disk from the drive and restart."); - while (true); - } - } - -#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - - // Main menu - - while (true) - { - byte exitKey; - InitScreen(); - -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - // Hidden system setup - byte hiddenSystemCreationPhase = BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; - - if (hiddenSystemCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE) - { - PreventNormalSystemBoot = true; - PrintMainMenu(); - - if (hiddenSystemCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_CLONING) - { - if (CopyActivePartitionToHiddenVolume (BootDrive, exitKey)) - { - BootSectorFlags = (BootSectorFlags & ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) | TC_HIDDEN_OS_CREATION_PHASE_WIPING; - UpdateBootSectorConfiguration (BootLoaderDrive); - } - else if (exitKey == TC_BIOS_KEY_ESC) - goto bootMenu; - else - continue; - } - } - else - PrintMainMenu(); - - exitKey = BootEncryptedDrive(); - -#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - PrintMainMenu(); - exitKey = BootEncryptedDrive(); - - if (exitKey == TC_MENU_KEY_REPAIR) - { - RepairMenu(); - continue; - } - -#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE - -bootMenu: - if (!PreventBootMenu) - BootMenu(); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Crc.h" +#include "Crypto.h" +#include "Password.h" +#include "Volumes.h" + +#include "Platform.h" +#include "Bios.h" +#include "BootConfig.h" +#include "BootMain.h" +#include "BootDefs.h" +#include "BootCommon.h" +#include "BootConsoleIo.h" +#include "BootDebug.h" +#include "BootDiskIo.h" +#include "BootEncryptedIo.h" +#include "BootMemory.h" +#include "BootStrings.h" +#include "IntFilter.h" + + +static void InitScreen () +{ + ClearScreen(); + + const char *title = +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + " TrueCrypt Boot Loader " +#else + " TrueCrypt Rescue Disk " +#endif + VERSION_STRING "\r\n"; + + Print (title); + + PrintRepeatedChar ('\xDC', TC_BIOS_MAX_CHARS_PER_LINE); + +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + if (CustomUserMessage[0]) + { + PrintEndl(); + Print (CustomUserMessage); + } +#endif + + PrintEndl (2); +} + + +static void PrintMainMenu () +{ + if (PreventBootMenu) + return; + + Print (" Keyboard Controls:\r\n"); + Print (" [Esc] "); + +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + Print ((BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE + ? "Boot Non-Hidden System (Boot Manager)" + : "Skip Authentication (Boot Manager)"); + +#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + Print ("Skip Authentication (Boot Manager)"); + Print ("\r\n [F8] "); Print ("Repair Options"); + +#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + PrintEndl (3); +} + + +static bool IsMenuKey (byte scanCode) +{ +#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + return scanCode == TC_MENU_KEY_REPAIR; +#else + return false; +#endif +} + + +static bool AskYesNo (const char *message) +{ + Print (message); + Print ("? (y/n): "); + while (true) + { + switch (GetKeyboardChar()) + { + case 'y': + case 'Y': + case 'z': + case 'Z': + Print ("y\r\n"); + return true; + + case 'n': + case 'N': + Print ("n\r\n"); + return false; + + default: + Beep(); + } + } +} + + +static int AskSelection (const char *options[], size_t optionCount) +{ + for (int i = 0; i < optionCount; ++i) + { + Print ("["); Print (i + 1); Print ("] "); + Print (options[i]); + PrintEndl(); + } + Print ("[Esc] Cancel\r\n\r\n"); + + Print ("To select, press 1-9: "); + + char str; + + while (true) + { + if (GetString (&str, 1) == 0) + return 0; + + if (str >= '1' && str <= optionCount + '0') + return str - '0'; + + Beep(); + PrintBackspace(); + } +} + + +static byte AskPassword (Password &password) +{ + size_t pos = 0; + byte scanCode; + byte asciiCode; + + Print ("Enter password"); + Print (PreventNormalSystemBoot ? " for hidden system:\r\n" : ": "); + + while (true) + { + asciiCode = GetKeyboardChar (&scanCode); + + switch (scanCode) + { + case TC_BIOS_KEY_ENTER: + ClearBiosKeystrokeBuffer(); + PrintEndl(); + + password.Length = pos; + return scanCode; + + case TC_BIOS_KEY_BACKSPACE: + if (pos > 0) + { + if (pos < MAX_PASSWORD) + PrintBackspace(); + else + PrintCharAtCursor (' '); + + --pos; + } + continue; + + default: + if (scanCode == TC_BIOS_KEY_ESC || IsMenuKey (scanCode)) + { + burn (password.Text, sizeof (password.Text)); + ClearBiosKeystrokeBuffer(); + + PrintEndl(); + return scanCode; + } + } + + if (!IsPrintable (asciiCode) || pos == MAX_PASSWORD) + { + Beep(); + continue; + } + + password.Text[pos++] = asciiCode; + if (pos < MAX_PASSWORD) + PrintChar ('*'); + else + PrintCharAtCursor ('*'); + } +} + + +static void ExecuteBootSector (byte drive, byte *sectorBuffer) +{ + Print ("Booting...\r\n"); + CopyMemory (sectorBuffer, 0x0000, 0x7c00, TC_LB_SIZE); + + BootStarted = true; + + uint32 addr = 0x7c00; + __asm + { + cli + mov dl, drive // Boot drive + mov dh, 0 + xor ax, ax + mov si, ax + mov ds, ax + mov es, ax + mov ss, ax + mov sp, 0x7c00 + sti + + jmp cs:addr + } +} + + +static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headerSaltCrc32, bool skipNormal, bool skipHidden) +{ + int volumeType; + bool hiddenVolume; + uint64 headerSec; + + AcquireSectorBuffer(); + + for (volumeType = 1; volumeType <= 2; ++volumeType) + { + hiddenVolume = (volumeType == 2); + + if (hiddenVolume) + { + if (skipHidden || PartitionFollowingActive.Drive != drive || PartitionFollowingActive.SectorCount <= ActivePartition.SectorCount) + continue; + + headerSec = PartitionFollowingActive.StartSector + TC_HIDDEN_VOLUME_HEADER_OFFSET / TC_LB_SIZE; + } + else + { + if (skipNormal) + continue; + + headerSec.HighPart = 0; + headerSec.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR; + } + + if (ReadSectors (SectorBuffer, drive, headerSec, 1) != BiosResultSuccess) + continue; + + if (ReadVolumeHeader (!hiddenVolume, (char *) SectorBuffer, &password, cryptoInfo, nullptr) == ERR_SUCCESS) + { + // Prevent opening a non-system hidden volume + if (hiddenVolume && !((*cryptoInfo)->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)) + { + crypto_close (*cryptoInfo); + continue; + } + + if (headerSaltCrc32) + *headerSaltCrc32 = GetCrc32 (SectorBuffer, PKCS5_SALT_SIZE); + + break; + } + } + + ReleaseSectorBuffer(); + return volumeType != 3; +} + + +static bool CheckMemoryRequirements () +{ + uint16 codeSeg; + __asm mov codeSeg, cs + if (codeSeg == TC_BOOT_LOADER_LOWMEM_SEGMENT) + { + PrintErrorNoEndl ("BIOS reserved too much memory: "); + + uint16 memFree; + __asm + { + push es + xor ax, ax + mov es, ax + mov ax, es:[0x413] + mov memFree, ax + pop es + } + + Print (memFree); + PrintEndl(); + Print (TC_BOOT_STR_UPGRADE_BIOS); + + return false; + } + + return true; +} + + +static bool MountVolume (byte drive, byte &exitKey, bool skipNormal, bool skipHidden) +{ + BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; + int incorrectPasswordCount = 0; + + EraseMemory (bootArguments, sizeof (*bootArguments)); + + // Open volume header + while (true) + { + exitKey = AskPassword (bootArguments->BootPassword); + + if (exitKey != TC_BIOS_KEY_ENTER) + return false; + + if (OpenVolume (BootDrive, bootArguments->BootPassword, &BootCryptoInfo, &bootArguments->HeaderSaltCrc32, skipNormal, skipHidden)) + break; + + if (GetShiftFlags() & TC_BIOS_SHIFTMASK_CAPSLOCK) + Print ("Warning: Caps Lock is on.\r\n"); + + Print ("Incorrect password.\r\n\r\n"); + + if (++incorrectPasswordCount == 4) + { +#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + Print ("If you are sure the password is correct, the key data may be damaged.\r\n" + "If so, use 'Repair Options' > 'Restore key data'.\r\n\r\n"); +#else + Print ("If you are sure the password is correct, the key data may be damaged. Boot your\r\n" + "TrueCrypt Rescue Disk and select 'Repair Options' > 'Restore key data'.\r\n\r\n"); +#endif + } + } + + // Setup boot arguments + bootArguments->BootLoaderVersion = VERSION_NUM; + bootArguments->CryptoInfoOffset = (uint16) BootCryptoInfo; + bootArguments->CryptoInfoLength = sizeof (*BootCryptoInfo); + + if (BootCryptoInfo->hiddenVolume) + bootArguments->HiddenSystemPartitionStart = PartitionFollowingActive.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; + + if (ExtraBootPartitionPresent) + bootArguments->Flags |= TC_BOOT_ARGS_FLAG_EXTRA_BOOT_PARTITION; + + TC_SET_BOOT_ARGUMENTS_SIGNATURE (bootArguments->Signature); + + // Setup virtual encrypted partition + if (BootCryptoInfo->EncryptedAreaLength.HighPart != 0 || BootCryptoInfo->EncryptedAreaLength.LowPart != 0) + { + EncryptedVirtualPartition.Drive = BootDrive; + + EncryptedVirtualPartition.StartSector = BootCryptoInfo->EncryptedAreaStart >> TC_LB_SIZE_BIT_SHIFT_DIVISOR; + + HiddenVolumeStartUnitNo = EncryptedVirtualPartition.StartSector; + HiddenVolumeStartSector = PartitionFollowingActive.StartSector; + HiddenVolumeStartSector += EncryptedVirtualPartition.StartSector; + + EncryptedVirtualPartition.SectorCount = BootCryptoInfo->EncryptedAreaLength >> TC_LB_SIZE_BIT_SHIFT_DIVISOR; + + EncryptedVirtualPartition.EndSector = EncryptedVirtualPartition.SectorCount - 1; + EncryptedVirtualPartition.EndSector += EncryptedVirtualPartition.StartSector; + } + else + { + // Drive not encrypted + EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE; + } + + return true; +} + + +static bool GetSystemPartitions (byte drive) +{ + size_t partCount; + + if (!GetActivePartition (drive)) + return false; + + // Find partition following the active one + GetDrivePartitions (drive, &PartitionFollowingActive, 1, partCount, false, &ActivePartition); + + // If there is an extra boot partition, use the partitions following it. + // The real boot partition is determined in BootEncryptedDrive(). + if (ActivePartition.SectorCount.HighPart == 0 && ActivePartition.SectorCount.LowPart <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE / TC_LB_SIZE + && PartitionFollowingActive.Drive != TC_INVALID_BIOS_DRIVE) + { + ExtraBootPartitionPresent = true; + + ActivePartition = PartitionFollowingActive; + GetDrivePartitions (drive, &PartitionFollowingActive, 1, partCount, false, &ActivePartition); + } + + return true; +} + + +static byte BootEncryptedDrive () +{ + BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; + byte exitKey; + BootCryptoInfo = NULL; + + if (!GetSystemPartitions (BootDrive)) + goto err; + + if (!MountVolume (BootDrive, exitKey, PreventNormalSystemBoot, false)) + return exitKey; + + if (!CheckMemoryRequirements ()) + goto err; + + if (BootCryptoInfo->hiddenVolume) + { + EncryptedVirtualPartition = ActivePartition; + bootArguments->DecoySystemPartitionStart = ActivePartition.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR; + } + + if (ExtraBootPartitionPresent && !GetActivePartition (BootDrive)) + goto err; + + if (!InstallInterruptFilters()) + goto err; + + bootArguments->BootArgumentsCrc32 = GetCrc32 ((byte *) bootArguments, (byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments); + + while (true) + { + // Execute boot sector of the active partition + if (ReadSectors (SectorBuffer, ActivePartition.Drive, ActivePartition.StartSector, 1) == BiosResultSuccess) + { + if (*(uint16 *) (SectorBuffer + 510) != 0xaa55) + { + PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); + GetKeyboardChar(); + } + + ExecuteBootSector (ActivePartition.Drive, SectorBuffer); + } + + GetKeyboardChar(); + } + +err: + if (BootCryptoInfo) + { + crypto_close (BootCryptoInfo); + BootCryptoInfo = NULL; + } + + EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE; + EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments)); + + byte scanCode; + GetKeyboardChar (&scanCode); + return scanCode; +} + + +static void BootMenu () +{ + BiosResult result; + Partition partitions[16]; + Partition bootablePartitions[9]; + size_t partitionCount; + size_t bootablePartitionCount = 0; + + for (byte drive = TC_FIRST_BIOS_DRIVE; drive <= TC_LAST_BIOS_DRIVE; ++drive) + { + if (GetDrivePartitions (drive, partitions, array_capacity (partitions), partitionCount, false, nullptr, true) == BiosResultSuccess) + { + for (size_t i = 0; i < partitionCount; ++i) + { + const Partition &partition = partitions[i]; + result = ReadSectors (SectorBuffer, drive, partition.StartSector, 1); + + if (result == BiosResultSuccess && *(uint16 *) (SectorBuffer + TC_LB_SIZE - 2) == 0xaa55) + { + // Windows writes boot loader on all NTFS/FAT filesytems it creates and, therefore, + // NTFS/FAT partitions must have the boot indicator set to be considered bootable. + if (!partition.Active + && (*(uint32 *) (SectorBuffer + 3) == 0x5346544e // 'NTFS' + || *(uint32 *) (SectorBuffer + 3) == 0x41465845 && SectorBuffer[7] == 'T' // 'exFAT' + || *(uint16 *) (SectorBuffer + 54) == 0x4146 && SectorBuffer[56] == 'T' // 'FAT' + || *(uint16 *) (SectorBuffer + 82) == 0x4146 && SectorBuffer[84] == 'T')) + { + continue; + } + + // Bootable sector found + if (bootablePartitionCount < array_capacity (bootablePartitions)) + bootablePartitions[bootablePartitionCount++] = partition; + } + } + } + } + + if (bootablePartitionCount < 1) + { + PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); + GetKeyboardChar(); + return; + } + + char partChar; + while (true) + { + InitScreen(); + Print ("Bootable Partitions:\r\n"); + PrintRepeatedChar ('\xC4', 20); + Print ("\r\n"); + + for (size_t i = 0; i < bootablePartitionCount; ++i) + { + const Partition &partition = bootablePartitions[i]; + Print ("["); Print (i + 1); Print ("] "); + Print ("Drive: "); Print (partition.Drive - TC_FIRST_BIOS_DRIVE); + Print (", Partition: "); Print (partition.Number + 1); + Print (", Size: "); PrintSectorCountInMB (partition.SectorCount); PrintEndl(); + } + + if (bootablePartitionCount == 1) + { + // There's only one bootable partition so we'll boot it directly instead of showing boot manager + partChar = '1'; + } + else + { + Print ("[Esc] Cancel\r\n\r\n"); + Print ("Press 1-9 to select partition: "); + + if (GetString (&partChar, 1) == 0) + return; + + PrintEndl(); + + if (partChar < '1' || partChar > '0' + bootablePartitionCount) + { + Beep(); + continue; + } + } + + const Partition &partition = bootablePartitions[partChar - '0' - 1]; + + if (ReadSectors (SectorBuffer, partition.Drive, partition.StartSector, 1) == BiosResultSuccess) + { + ExecuteBootSector (partition.Drive, SectorBuffer); + } + } +} + + +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + +static bool CopySystemPartitionToHiddenVolume (byte drive, byte &exitKey) +{ + bool status = false; + + uint64 sectorsRemaining; + uint64 sectorOffset; + sectorOffset.LowPart = 0; + sectorOffset.HighPart = 0; + + int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS + int statCount; + + if (!CheckMemoryRequirements ()) + goto err; + + if (!GetSystemPartitions (drive)) + goto err; + + if (PartitionFollowingActive.Drive == TC_INVALID_BIOS_DRIVE) + TC_THROW_FATAL_EXCEPTION; + + // Check if BIOS can read the last sector of the hidden system + AcquireSectorBuffer(); + + if (ReadSectors (SectorBuffer, PartitionFollowingActive.Drive, PartitionFollowingActive.EndSector - (TC_VOLUME_HEADER_GROUP_SIZE / TC_LB_SIZE - 2), 1) != BiosResultSuccess + || GetCrc32 (SectorBuffer, sizeof (SectorBuffer)) != OuterVolumeBackupHeaderCrc) + { + PrintErrorNoEndl ("Your BIOS does not support large drives"); + Print (IsLbaSupported (PartitionFollowingActive.Drive) ? " due to a bug" : "\r\n- Enable LBA in BIOS"); + PrintEndl(); + Print (TC_BOOT_STR_UPGRADE_BIOS); + + ReleaseSectorBuffer(); + goto err; + } + + ReleaseSectorBuffer(); + + if (!MountVolume (drive, exitKey, true, false)) + return false; + + sectorsRemaining = EncryptedVirtualPartition.SectorCount; + + if (!(sectorsRemaining == ActivePartition.SectorCount)) + TC_THROW_FATAL_EXCEPTION; + + InitScreen(); + Print ("\r\nCopying system to hidden volume. To abort, press Esc.\r\n\r\n"); + + while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0) + { + if (EscKeyPressed()) + { + Print ("\rIf aborted, copying will have to start from the beginning (if attempted again).\r\n"); + if (AskYesNo ("Abort")) + break; + } + + if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) + fragmentSectorCount = (int) sectorsRemaining.LowPart; + + if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, ActivePartition.StartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) + { + Print ("To fix bad sectors: 1) Terminate 2) Encrypt and decrypt sys partition 3) Retry\r\n"); + crypto_close (BootCryptoInfo); + goto err; + } + + AcquireSectorBuffer(); + + for (int i = 0; i < fragmentSectorCount; ++i) + { + CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE); + + uint64 s = HiddenVolumeStartUnitNo + sectorOffset + i; + EncryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo); + + CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE); + } + + ReleaseSectorBuffer(); + + if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, HiddenVolumeStartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess) + { + crypto_close (BootCryptoInfo); + goto err; + } + + sectorsRemaining = sectorsRemaining - fragmentSectorCount; + sectorOffset = sectorOffset + fragmentSectorCount; + + if (!(statCount++ & 0xf)) + { + Print ("\rRemaining: "); + PrintSectorCountInMB (sectorsRemaining); + } + } + + crypto_close (BootCryptoInfo); + + if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0) + { + status = true; + Print ("\rCopying completed."); + } + + PrintEndl (2); + goto ret; + +err: + exitKey = TC_BIOS_KEY_ESC; + GetKeyboardChar(); + +ret: + EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments)); + return status; +} + + +#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + +static void DecryptDrive (byte drive) +{ + byte exitKey; + if (!MountVolume (drive, exitKey, false, true)) + return; + + BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET; + + bool headerUpdateRequired = false; + uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector; + uint64 sector = EncryptedVirtualPartition.EndSector + 1; + + int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS + int statCount; + + bool skipBadSectors = false; + + Print ("\r\nUse only if Windows cannot start. Decryption under Windows is much faster\r\n" + "(in TrueCrypt, select 'System' > 'Permanently Decrypt').\r\n\r\n"); + + if (!AskYesNo ("Decrypt now")) + { + crypto_close (BootCryptoInfo); + goto ret; + } + + if (EncryptedVirtualPartition.Drive == TC_INVALID_BIOS_DRIVE) + { + // Drive already decrypted + sectorsRemaining.HighPart = 0; + sectorsRemaining.LowPart = 0; + } + else + { + Print ("\r\nTo safely interrupt and defer decryption, press Esc.\r\n" + "WARNING: You can turn off power only after you press Esc.\r\n\r\n"); + } + + while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0) + { + if (EscKeyPressed()) + break; + + if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount) + fragmentSectorCount = (int) sectorsRemaining.LowPart; + + sector = sector - fragmentSectorCount; + + if (!(statCount++ & 0xf)) + { + Print ("\rRemaining: "); + PrintSectorCountInMB (sectorsRemaining); + } + + if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) == BiosResultSuccess) + { + AcquireSectorBuffer(); + + for (int i = 0; i < fragmentSectorCount; ++i) + { + CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE); + + uint64 s = sector + i; + DecryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo); + + CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE); + } + + ReleaseSectorBuffer(); + + if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) != BiosResultSuccess && !skipBadSectors) + goto askBadSectorSkip; + } + else if (!skipBadSectors) + goto askBadSectorSkip; + + sectorsRemaining = sectorsRemaining - fragmentSectorCount; + headerUpdateRequired = true; + continue; + +askBadSectorSkip: + if (!AskYesNo ("Skip all bad sectors")) + break; + + skipBadSectors = true; + sector = sector + fragmentSectorCount; + fragmentSectorCount = 1; + } + + crypto_close (BootCryptoInfo); + + if (headerUpdateRequired) + { + AcquireSectorBuffer(); + uint64 headerSector; + headerSector.HighPart = 0; + headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR; + + // Update encrypted area size in volume header + + CRYPTO_INFO *headerCryptoInfo = crypto_open(); + while (ReadSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess); + + if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0) + { + DecryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); + + uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR; + + for (int i = 7; i >= 0; --i) + { + SectorBuffer[TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH + i] = (byte) encryptedAreaLength.LowPart; + encryptedAreaLength = encryptedAreaLength >> 8; + } + + uint32 headerCrc32 = GetCrc32 (SectorBuffer + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); + + for (i = 3; i >= 0; --i) + { + SectorBuffer[TC_HEADER_OFFSET_HEADER_CRC + i] = (byte) headerCrc32; + headerCrc32 >>= 8; + } + + EncryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); + } + + crypto_close (headerCryptoInfo); + + while (WriteSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess); + ReleaseSectorBuffer(); + } + + if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0) + Print ("\rDrive decrypted.\r\n"); + else + Print ("\r\nDecryption deferred.\r\n"); + + GetKeyboardChar(); +ret: + EraseMemory (bootArguments, sizeof (*bootArguments)); +} + + +static void RepairMenu () +{ + DriveGeometry bootLoaderDriveGeometry; + + if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry, true) != BiosResultSuccess) + { + // Some BIOSes may fail to get the geometry of an emulated floppy drive + bootLoaderDriveGeometry.Cylinders = 80; + bootLoaderDriveGeometry.Heads = 2; + bootLoaderDriveGeometry.Sectors = 18; + } + + while (true) + { + InitScreen(); + Print ("Available "); Print ("Repair Options"); Print (":\r\n"); + PrintRepeatedChar ('\xC4', 25); + PrintEndl(); + + enum + { + RestoreNone = 0, + DecryptVolume, + RestoreTrueCryptLoader, + RestoreVolumeHeader, + RestoreOriginalSystemLoader + }; + + static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" }; + + int selection = AskSelection (options, + (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER) ? array_capacity (options) : array_capacity (options) - 1); + + PrintEndl(); + + switch (selection) + { + case RestoreNone: + return; + + case DecryptVolume: + DecryptDrive (BootDrive); + continue; + + case RestoreOriginalSystemLoader: + if (!AskYesNo ("Is the system partition/drive decrypted")) + { + Print ("Please decrypt it first.\r\n"); + GetKeyboardChar(); + continue; + } + break; + } + + bool writeConfirmed = false; + BiosResult result; + + uint64 sector; + sector.HighPart = 0; + ChsAddress chs; + + byte mbrPartTable[TC_LB_SIZE - TC_MAX_MBR_BOOT_CODE_SIZE]; + AcquireSectorBuffer(); + + for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR); + i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i) + { + sector.LowPart = i; + + if (selection == RestoreOriginalSystemLoader) + sector.LowPart += TC_ORIG_BOOT_LOADER_BACKUP_SECTOR; + else if (selection == RestoreTrueCryptLoader) + sector.LowPart += TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR; + + // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used. + // Therefore, only CHS addressing can be used. + LbaToChs (bootLoaderDriveGeometry, sector, chs); + sector.LowPart = i; + + if (i == TC_MBR_SECTOR) + { + // Read current partition table + result = ReadSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1); + if (result != BiosResultSuccess) + goto err; + + memcpy (mbrPartTable, SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbrPartTable)); + } + + result = ReadSectors (SectorBuffer, BootLoaderDrive, chs, 1); + if (result != BiosResultSuccess) + goto err; + + if (i == TC_MBR_SECTOR) + { + // Preserve current partition table + memcpy (SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, mbrPartTable, sizeof (mbrPartTable)); + } + + // Volume header + if (i == TC_BOOT_VOLUME_HEADER_SECTOR) + { + if (selection == RestoreTrueCryptLoader) + continue; + + if (selection == RestoreVolumeHeader) + { + while (true) + { + bool validHeaderPresent = false; + uint32 masterKeyScheduleCrc; + + Password password; + byte exitKey = AskPassword (password); + + if (exitKey != TC_BIOS_KEY_ENTER) + goto abort; + + CRYPTO_INFO *cryptoInfo; + + CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, TC_LB_SIZE); + ReleaseSectorBuffer(); + + // Restore volume header only if the current one cannot be used + if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo, nullptr, false, true)) + { + validHeaderPresent = true; + masterKeyScheduleCrc = GetCrc32 (cryptoInfo->ks, sizeof (cryptoInfo->ks)); + crypto_close (cryptoInfo); + } + + AcquireSectorBuffer(); + CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, 0, SectorBuffer, TC_LB_SIZE); + + if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0) + { + if (validHeaderPresent) + { + if (masterKeyScheduleCrc == GetCrc32 (cryptoInfo->ks, sizeof (cryptoInfo->ks))) + { + Print ("Original header preserved.\r\n"); + goto err; + } + + Print ("WARNING: Drive 0 contains a valid header!\r\n"); + } + + crypto_close (cryptoInfo); + break; + } + + Print ("Incorrect password.\r\n\r\n"); + } + } + } + + if (!writeConfirmed && !AskYesNo ("Modify drive 0")) + goto abort; + writeConfirmed = true; + + if (WriteSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess) + goto err; + } +done: + switch (selection) + { + case RestoreTrueCryptLoader: + Print ("TrueCrypt Boot Loader"); + break; + + case RestoreVolumeHeader: + Print ("Header"); + break; + + case RestoreOriginalSystemLoader: + Print ("System loader"); + break; + } + Print (" restored.\r\n"); + +err: GetKeyboardChar(); +abort: ReleaseSectorBuffer(); + } +} + +#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + +#ifndef DEBUG +extern "C" void _acrtused () { } // Required by linker +#endif + + +void main () +{ + __asm mov BootLoaderDrive, dl + __asm mov BootSectorFlags, dh + +#ifdef TC_BOOT_TRACING_ENABLED + InitDebugPort(); +#endif + +#ifdef TC_BOOT_STACK_CHECKING_ENABLED + InitStackChecker(); +#endif + +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + ReadBootSectorUserConfiguration(); +#endif + + InitVideoMode(); + InitScreen(); + + // Determine boot drive + BootDrive = BootLoaderDrive; + if (BootDrive < TC_FIRST_BIOS_DRIVE) + BootDrive = TC_FIRST_BIOS_DRIVE; + + // Query boot drive geometry + if (GetDriveGeometry (BootDrive, BootDriveGeometry) != BiosResultSuccess) + { + BootDrive = TC_FIRST_BIOS_DRIVE; + if (GetDriveGeometry (BootDrive, BootDriveGeometry) != BiosResultSuccess) + { +#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + Print ("- Connect system drive to (SATA) port 1\r\n"); +#endif + GetKeyboardChar(); + } + else + BootDriveGeometryValid = true; + } + else + BootDriveGeometryValid = true; + +#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + // Check whether the user is not using the Rescue Disk to create a hidden system + + if (ReadWriteMBR (false, BootDrive, true) == BiosResultSuccess + && *(uint32 *) (SectorBuffer + 6) == 0x65757254 + && *(uint32 *) (SectorBuffer + 10) == 0x70797243 + && (SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE) + { + PrintError ("It appears you are creating a hidden OS."); + if (AskYesNo ("Is this correct")) + { + Print ("Please remove the Rescue Disk from the drive and restart."); + while (true); + } + } + +#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + + // Main menu + + while (true) + { + byte exitKey; + InitScreen(); + +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + // Hidden system setup + byte hiddenSystemCreationPhase = BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; + + if (hiddenSystemCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE) + { + PreventNormalSystemBoot = true; + PrintMainMenu(); + + if (hiddenSystemCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_CLONING) + { + if (CopySystemPartitionToHiddenVolume (BootDrive, exitKey)) + { + BootSectorFlags = (BootSectorFlags & ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) | TC_HIDDEN_OS_CREATION_PHASE_WIPING; + UpdateBootSectorConfiguration (BootLoaderDrive); + } + else if (exitKey == TC_BIOS_KEY_ESC) + goto bootMenu; + else + continue; + } + } + else + PrintMainMenu(); + + exitKey = BootEncryptedDrive(); + +#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + PrintMainMenu(); + exitKey = BootEncryptedDrive(); + + if (exitKey == TC_MENU_KEY_REPAIR) + { + RepairMenu(); + continue; + } + +#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE + +bootMenu: + if (!PreventBootMenu) + BootMenu(); + } +} diff --git a/Boot/Windows/BootMain.h b/Boot/Windows/BootMain.h index 899f1b1..51f5aad 100644 --- a/Boot/Windows/BootMain.h +++ b/Boot/Windows/BootMain.h @@ -1,30 +1,30 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootMain -#define TC_HEADER_Boot_BootMain - -#include "TCdefs.h" -#include "Platform.h" - -static byte AskPassword (Password &password); -static int AskSelection (const char *options[], size_t optionCount); -static bool AskYesNo (const char *message); -static byte BootEncryptedDrive (); -static void BootMenu (); -static void ExecuteBootSector (byte drive, byte *sectorBuffer); -static void InitScreen (); -static bool IsMenuKey (byte scanCode); -static bool MountVolume (byte drive, byte &exitKey); -static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headerSaltCrc32 = nullptr, bool skipNormal = false, bool skipHidden = false); -static void PrintMainMenu (); -static void RepairMenu (); - -#define TC_MENU_KEY_REPAIR TC_BIOS_KEY_F8 - -#endif // TC_HEADER_Boot_BootMain +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootMain +#define TC_HEADER_Boot_BootMain + +#include "TCdefs.h" +#include "Platform.h" + +static byte AskPassword (Password &password); +static int AskSelection (const char *options[], size_t optionCount); +static bool AskYesNo (const char *message); +static byte BootEncryptedDrive (); +static void BootMenu (); +static void ExecuteBootSector (byte drive, byte *sectorBuffer); +static void InitScreen (); +static bool IsMenuKey (byte scanCode); +static bool MountVolume (byte drive, byte &exitKey); +static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headerSaltCrc32 = nullptr, bool skipNormal = false, bool skipHidden = false); +static void PrintMainMenu (); +static void RepairMenu (); + +#define TC_MENU_KEY_REPAIR TC_BIOS_KEY_F8 + +#endif // TC_HEADER_Boot_BootMain diff --git a/Boot/Windows/BootMemory.cpp b/Boot/Windows/BootMemory.cpp index 481e42b..11a0555 100644 --- a/Boot/Windows/BootMemory.cpp +++ b/Boot/Windows/BootMemory.cpp @@ -1,82 +1,82 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "BootDefs.h" -#include "BootMemory.h" - -static uint32 MemoryMapContValue; - -static bool GetMemoryMapEntry (BiosMemoryMapEntry &entry) -{ - static const uint32 function = 0x0000E820UL; - static const uint32 magic = 0x534D4150UL; - static const uint32 bufferSize = sizeof (BiosMemoryMapEntry); - - bool carry = false; - uint32 resultMagic; - uint32 resultSize; - - __asm - { - push es - - lea di, function - TC_ASM_MOV_EAX_DI - lea di, MemoryMapContValue - TC_ASM_MOV_EBX_DI - lea di, bufferSize - TC_ASM_MOV_ECX_DI - lea di, magic - TC_ASM_MOV_EDX_DI - lea di, MemoryMapContValue - TC_ASM_MOV_DI_ECX - - // Use alternative segment to prevent memory corruption caused by buggy BIOSes - push TC_BOOT_LOADER_ALT_SEGMENT - pop es - mov di, 0 - - int 0x15 - jnc no_carry - mov carry, true - no_carry: - - lea di, resultMagic - TC_ASM_MOV_DI_EAX - lea di, MemoryMapContValue - TC_ASM_MOV_DI_EBX - lea di, resultSize - TC_ASM_MOV_DI_ECX - - pop es - } - - CopyMemory (TC_BOOT_LOADER_ALT_SEGMENT, 0, &entry, sizeof (entry)); - - // BIOS may set CF at the end of the list - if (carry) - MemoryMapContValue = 0; - - return resultMagic == magic && resultSize == bufferSize; -} - - -bool GetFirstBiosMemoryMapEntry (BiosMemoryMapEntry &entry) -{ - MemoryMapContValue = 0; - return GetMemoryMapEntry (entry); -} - - -bool GetNextBiosMemoryMapEntry (BiosMemoryMapEntry &entry) -{ - if (MemoryMapContValue == 0) - return false; - - return GetMemoryMapEntry (entry); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "BootDefs.h" +#include "BootMemory.h" + +static uint32 MemoryMapContValue; + +static bool GetMemoryMapEntry (BiosMemoryMapEntry &entry) +{ + static const uint32 function = 0x0000E820UL; + static const uint32 magic = 0x534D4150UL; + static const uint32 bufferSize = sizeof (BiosMemoryMapEntry); + + bool carry = false; + uint32 resultMagic; + uint32 resultSize; + + __asm + { + push es + + lea di, function + TC_ASM_MOV_EAX_DI + lea di, MemoryMapContValue + TC_ASM_MOV_EBX_DI + lea di, bufferSize + TC_ASM_MOV_ECX_DI + lea di, magic + TC_ASM_MOV_EDX_DI + lea di, MemoryMapContValue + TC_ASM_MOV_DI_ECX + + // Use alternative segment to prevent memory corruption caused by buggy BIOSes + push TC_BOOT_LOADER_ALT_SEGMENT + pop es + mov di, 0 + + int 0x15 + jnc no_carry + mov carry, true + no_carry: + + lea di, resultMagic + TC_ASM_MOV_DI_EAX + lea di, MemoryMapContValue + TC_ASM_MOV_DI_EBX + lea di, resultSize + TC_ASM_MOV_DI_ECX + + pop es + } + + CopyMemory (TC_BOOT_LOADER_ALT_SEGMENT, 0, &entry, sizeof (entry)); + + // BIOS may set CF at the end of the list + if (carry) + MemoryMapContValue = 0; + + return resultMagic == magic && resultSize == bufferSize; +} + + +bool GetFirstBiosMemoryMapEntry (BiosMemoryMapEntry &entry) +{ + MemoryMapContValue = 0; + return GetMemoryMapEntry (entry); +} + + +bool GetNextBiosMemoryMapEntry (BiosMemoryMapEntry &entry) +{ + if (MemoryMapContValue == 0) + return false; + + return GetMemoryMapEntry (entry); +} diff --git a/Boot/Windows/BootMemory.h b/Boot/Windows/BootMemory.h index da8db20..6a39a36 100644 --- a/Boot/Windows/BootMemory.h +++ b/Boot/Windows/BootMemory.h @@ -1,24 +1,24 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform.h" -#include "Bios.h" - -#pragma pack(1) - -struct BiosMemoryMapEntry -{ - uint64 BaseAddress; - uint64 Length; - uint32 Type; -}; - -#pragma pack() - -bool GetFirstBiosMemoryMapEntry (BiosMemoryMapEntry &entry); -bool GetNextBiosMemoryMapEntry (BiosMemoryMapEntry &entry); +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform.h" +#include "Bios.h" + +#pragma pack(1) + +struct BiosMemoryMapEntry +{ + uint64 BaseAddress; + uint64 Length; + uint32 Type; +}; + +#pragma pack() + +bool GetFirstBiosMemoryMapEntry (BiosMemoryMapEntry &entry); +bool GetNextBiosMemoryMapEntry (BiosMemoryMapEntry &entry); diff --git a/Boot/Windows/BootSector.asm b/Boot/Windows/BootSector.asm index 6c88d22..7d3a036 100644 --- a/Boot/Windows/BootSector.asm +++ b/Boot/Windows/BootSector.asm @@ -1,7 +1,7 @@ ; ; Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. ; -; Governed by the TrueCrypt License 2.7 the full text of which is contained +; Governed by the TrueCrypt License 2.8 the full text of which is contained ; in the file License.txt included in TrueCrypt binary and source code ; distribution packages. ; @@ -230,8 +230,8 @@ backup_loader_used db 0 disk_error_msg db 'Disk error', 13, 10, 7, 0 loader_damaged_msg db 7, 'Loader damaged! Use Rescue Disk: Repair Options > Restore', 0 -ORG 7C00h + 508 - dw 0, 0AA55h ; Boot sector signature +ORG 7C00h + 510 + dw 0AA55h ; Boot sector signature _TEXT ENDS END start diff --git a/Boot/Windows/BootStrings.h b/Boot/Windows/BootStrings.h index 9dc5a18..ec3734f 100644 --- a/Boot/Windows/BootStrings.h +++ b/Boot/Windows/BootStrings.h @@ -1,15 +1,16 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_BootStrings -#define TC_HEADER_Boot_BootStrings - -#define TC_BOOT_STR_NO_BOOT_PARTITION "No bootable partition found" -#define TC_BOOT_STR_UPGRADE_BIOS "- Upgrade BIOS\r\n- Use a different motherboard model/brand\r\n" - -#endif // TC_HEADER_Boot_BootStrings +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_BootStrings +#define TC_HEADER_Boot_BootStrings + +#define TC_BOOT_STR_ERROR "Error: " +#define TC_BOOT_STR_NO_BOOT_PARTITION "No bootable partition found" +#define TC_BOOT_STR_UPGRADE_BIOS "- Upgrade BIOS\r\n- Use a different motherboard model/brand\r\n" + +#endif // TC_HEADER_Boot_BootStrings diff --git a/Boot/Windows/Decompressor.c b/Boot/Windows/Decompressor.c index a46918b..b27efb7 100644 --- a/Boot/Windows/Decompressor.c +++ b/Boot/Windows/Decompressor.c @@ -1,436 +1,436 @@ -/* - puff.c - Copyright (C) 2002-2004 Mark Adler, all rights reserved - version 1.8, 9 Jan 2004 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu -*/ - -/* Adapted by TrueCrypt Foundation */ - - -#define local static /* for local function definitions */ -#define NIL ((unsigned char *)0) /* for no output option */ - -/* - * Maximums for allocations and loops. It is not useful to change these -- - * they are fixed by the deflate format. - */ -#define MAXBITS 15 /* maximum bits in a code */ -#define MAXLCODES 286 /* maximum number of literal/length codes */ -#define MAXDCODES 30 /* maximum number of distance codes */ -#define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ -#define FIXLCODES 288 /* number of fixed literal/length codes */ - -/* input and output state */ -struct state { - /* output state */ - unsigned char *out; /* output buffer */ - unsigned int outlen; /* available space at out */ - unsigned int outcnt; /* bytes written to out so far */ - - /* input state */ - unsigned char *in; /* input buffer */ - unsigned int incnt; /* bytes read so far */ - int bitbuf; /* bit buffer */ - int bitcnt; /* number of bits in bit buffer */ -}; - - -local int bits(struct state *s, int need) -{ - long val; /* bit accumulator (can use up to 20 bits) */ - - /* load at least need bits into val */ - val = s->bitbuf; - while (s->bitcnt < need) { - val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ - s->bitcnt += 8; - } - - /* drop need bits and update buffer, always zero to seven bits left */ - s->bitbuf = (int)(val >> need); - s->bitcnt -= need; - - /* return need bits, zeroing the bits above that */ - return (int)(val & ((1L << need) - 1)); -} - - -local int stored(struct state *s) -{ - unsigned len; /* length of stored block */ - - /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ - s->bitbuf = 0; - s->bitcnt = 0; - - /* get length and check against its one's complement */ - len = s->in[s->incnt++]; - len |= s->in[s->incnt++] << 8; - if (s->in[s->incnt++] != (~len & 0xff) || - s->in[s->incnt++] != ((~len >> 8) & 0xff)) - return -2; /* didn't match complement! */ - - /* copy len bytes from in to out */ - if (s->out != NIL) { - if (s->outcnt + len > s->outlen) - return 1; /* not enough output space */ - while (len--) - s->out[s->outcnt++] = s->in[s->incnt++]; - } - else { /* just scanning */ - s->outcnt += len; - s->incnt += len; - } - - /* done with a valid stored block */ - return 0; -} - - -struct huffman { - short *count; /* number of symbols of each length */ - short *symbol; /* canonically ordered symbols */ -}; - - -#ifdef SLOW -local int decode(struct state *s, struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - - code = first = index = 0; - for (len = 1; len <= MAXBITS; len++) { - code |= bits(s, 1); /* get next bit */ - count = h->count[len]; - if (code < first + count) /* if length len, return symbol */ - return h->symbol[index + (code - first)]; - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - } - return -9; /* ran out of codes */ -} - -/* - * A faster version of decode() for real applications of this code. It's not - * as readable, but it makes puff() twice as fast. And it only makes the code - * a few percent larger. - */ -#else /* !SLOW */ -local int decode(struct state *s, struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - int bitbuf; /* bits from stream */ - int left; /* bits left in next or left to process */ - short *next; /* next number of codes */ - - bitbuf = s->bitbuf; - left = s->bitcnt; - code = first = index = 0; - len = 1; - next = h->count + 1; - while (1) { - while (left--) { - code |= bitbuf & 1; - bitbuf >>= 1; - count = *next++; - if (code < first + count) { /* if length len, return symbol */ - s->bitbuf = bitbuf; - s->bitcnt = (s->bitcnt - len) & 7; - return h->symbol[index + (code - first)]; - } - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - len++; - } - left = (MAXBITS+1) - len; - if (left == 0) break; - bitbuf = s->in[s->incnt++]; - if (left > 8) left = 8; - } - return -9; /* ran out of codes */ -} -#endif /* SLOW */ - - -local int construct(struct huffman *h, short *length, int n) -{ - int symbol; /* current symbol when stepping through length[] */ - int len; /* current length when stepping through h->count[] */ - int left; /* number of possible codes left of current length */ - short offs[MAXBITS+1]; /* offsets in symbol table for each length */ - - /* count number of codes of each length */ - for (len = 0; len <= MAXBITS; len++) - h->count[len] = 0; - for (symbol = 0; symbol < n; symbol++) - (h->count[length[symbol]])++; /* assumes lengths are within bounds */ - if (h->count[0] == n) /* no codes! */ - return 0; /* complete, but decode() will fail */ - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; /* one possible code of zero length */ - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; /* one more bit, double codes left */ - left -= h->count[len]; /* deduct count from possible codes */ - if (left < 0) return left; /* over-subscribed--return negative */ - } /* left > 0 means incomplete */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + h->count[len]; - - /* - * put symbols in table sorted by length, by symbol order within each - * length - */ - for (symbol = 0; symbol < n; symbol++) - if (length[symbol] != 0) - h->symbol[offs[length[symbol]]++] = symbol; - - /* return zero for complete set, positive for incomplete set */ - return left; -} - - -local int codes(struct state *s, - struct huffman *lencode, - struct huffman *distcode) -{ - int symbol; /* decoded symbol */ - int len; /* length for copy */ - unsigned dist; /* distance for copy */ - static const short lens[29] = { /* Size base for length codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; - static const short lext[29] = { /* Extra bits for length codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; - static const short dists[30] = { /* Offset base for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; - static const short dext[30] = { /* Extra bits for distance codes 0..29 */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - - /* decode literals and length/distance pairs */ - do { - symbol = decode(s, lencode); - if (symbol < 0) return symbol; /* invalid symbol */ - if (symbol < 256) { /* literal: symbol is the byte */ - /* write out the literal */ - if (s->out != NIL) { - if (s->outcnt == s->outlen) return 1; - s->out[s->outcnt] = symbol; - } - s->outcnt++; - } - else if (symbol > 256) { /* length */ - /* get and compute length */ - symbol -= 257; - if (symbol >= 29) return -9; /* invalid fixed code */ - len = lens[symbol] + bits(s, lext[symbol]); - - /* get and check distance */ - symbol = decode(s, distcode); - if (symbol < 0) return symbol; /* invalid symbol */ - dist = dists[symbol] + bits(s, dext[symbol]); - if (dist > s->outcnt) - return -10; /* distance too far back */ - - /* copy length bytes from distance bytes back */ - if (s->out != NIL) { - if (s->outcnt + len > s->outlen) return 1; - while (len--) { - s->out[s->outcnt] = s->out[s->outcnt - dist]; - s->outcnt++; - } - } - else - s->outcnt += len; - } - } while (symbol != 256); /* end of block symbol */ - - /* done with a valid fixed or dynamic block */ - return 0; -} - - -local int fixed(struct state *s) -{ - static int virgin = 1; - static short lencnt[MAXBITS+1], lensym[FIXLCODES]; - static short distcnt[MAXBITS+1], distsym[MAXDCODES]; - static struct huffman lencode = {lencnt, lensym}; - static struct huffman distcode = {distcnt, distsym}; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - int symbol; - short lengths[FIXLCODES]; - - /* literal/length table */ - for (symbol = 0; symbol < 144; symbol++) - lengths[symbol] = 8; - for (; symbol < 256; symbol++) - lengths[symbol] = 9; - for (; symbol < 280; symbol++) - lengths[symbol] = 7; - for (; symbol < FIXLCODES; symbol++) - lengths[symbol] = 8; - construct(&lencode, lengths, FIXLCODES); - - /* distance table */ - for (symbol = 0; symbol < MAXDCODES; symbol++) - lengths[symbol] = 5; - construct(&distcode, lengths, MAXDCODES); - - /* do this just once */ - virgin = 0; - } - - /* decode data until end-of-block code */ - return codes(s, &lencode, &distcode); -} - - -local int dynamic(struct state *s) -{ - int nlen, ndist, ncode; /* number of lengths in descriptor */ - int index; /* index of lengths[] */ - int err; /* construct() return value */ - short lengths[MAXCODES]; /* descriptor code lengths */ - short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ - short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ - struct huffman lencode = {lencnt, lensym}; /* length code */ - struct huffman distcode = {distcnt, distsym}; /* distance code */ - static const short order[19] = /* permutation of code length codes */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* get number of lengths in each table, check lengths */ - nlen = bits(s, 5) + 257; - ndist = bits(s, 5) + 1; - ncode = bits(s, 4) + 4; - if (nlen > MAXLCODES || ndist > MAXDCODES) - return -3; /* bad counts */ - - /* read code length code lengths (really), missing lengths are zero */ - for (index = 0; index < ncode; index++) - lengths[order[index]] = bits(s, 3); - for (; index < 19; index++) - lengths[order[index]] = 0; - - /* build huffman table for code lengths codes (use lencode temporarily) */ - err = construct(&lencode, lengths, 19); - if (err != 0) return -4; /* require complete code set here */ - - /* read length/literal and distance code length tables */ - index = 0; - while (index < nlen + ndist) { - int symbol; /* decoded value */ - int len; /* last length to repeat */ - - symbol = decode(s, &lencode); - if (symbol < 16) /* length in 0..15 */ - lengths[index++] = symbol; - else { /* repeat instruction */ - len = 0; /* assume repeating zeros */ - if (symbol == 16) { /* repeat last length 3..6 times */ - if (index == 0) return -5; /* no last length! */ - len = lengths[index - 1]; /* last length */ - symbol = 3 + bits(s, 2); - } - else if (symbol == 17) /* repeat zero 3..10 times */ - symbol = 3 + bits(s, 3); - else /* == 18, repeat zero 11..138 times */ - symbol = 11 + bits(s, 7); - if (index + symbol > nlen + ndist) - return -6; /* too many lengths! */ - while (symbol--) /* repeat last or zero symbol times */ - lengths[index++] = len; - } - } - - /* build huffman table for literal/length codes */ - err = construct(&lencode, lengths, nlen); - if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) - return -7; /* only allow incomplete codes if just one code */ - - /* build huffman table for distance codes */ - err = construct(&distcode, lengths + nlen, ndist); - if (err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) - return -8; /* only allow incomplete codes if just one code */ - - /* decode data until end-of-block code */ - return codes(s, &lencode, &distcode); -} - - -void _acrtused () { } - -// Decompress deflated data -int far main ( - unsigned char *dest, /* pointer to destination pointer */ - unsigned int destlen, /* amount of output space */ - unsigned char *source) /* pointer to source data pointer */ -{ - struct state s; /* input/output state */ - int last, type; /* block information */ - int err; /* return value */ - - /* initialize output state */ - s.out = dest; - s.outlen = destlen; /* ignored if dest is NIL */ - s.outcnt = 0; - - /* initialize input state */ - s.in = source; - s.incnt = 0; - s.bitbuf = 0; - s.bitcnt = 0; - - /* process blocks until last block or error */ - do { - last = bits(&s, 1); /* one if last block */ - type = bits(&s, 2); /* block type 0..3 */ - err = type == 0 ? stored(&s) : - (type == 1 ? fixed(&s) : - (type == 2 ? dynamic(&s) : - -1)); /* type == 3, invalid */ - if (err != 0) break; /* return with error */ - } while (!last); - - return err; -} +/* + puff.c + Copyright (C) 2002-2004 Mark Adler, all rights reserved + version 1.8, 9 Jan 2004 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu +*/ + +/* Adapted by TrueCrypt Foundation */ + + +#define local static /* for local function definitions */ +#define NIL ((unsigned char *)0) /* for no output option */ + +/* + * Maximums for allocations and loops. It is not useful to change these -- + * they are fixed by the deflate format. + */ +#define MAXBITS 15 /* maximum bits in a code */ +#define MAXLCODES 286 /* maximum number of literal/length codes */ +#define MAXDCODES 30 /* maximum number of distance codes */ +#define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ +#define FIXLCODES 288 /* number of fixed literal/length codes */ + +/* input and output state */ +struct state { + /* output state */ + unsigned char *out; /* output buffer */ + unsigned int outlen; /* available space at out */ + unsigned int outcnt; /* bytes written to out so far */ + + /* input state */ + unsigned char *in; /* input buffer */ + unsigned int incnt; /* bytes read so far */ + int bitbuf; /* bit buffer */ + int bitcnt; /* number of bits in bit buffer */ +}; + + +local int bits(struct state *s, int need) +{ + long val; /* bit accumulator (can use up to 20 bits) */ + + /* load at least need bits into val */ + val = s->bitbuf; + while (s->bitcnt < need) { + val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ + s->bitcnt += 8; + } + + /* drop need bits and update buffer, always zero to seven bits left */ + s->bitbuf = (int)(val >> need); + s->bitcnt -= need; + + /* return need bits, zeroing the bits above that */ + return (int)(val & ((1L << need) - 1)); +} + + +local int stored(struct state *s) +{ + unsigned len; /* length of stored block */ + + /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ + s->bitbuf = 0; + s->bitcnt = 0; + + /* get length and check against its one's complement */ + len = s->in[s->incnt++]; + len |= s->in[s->incnt++] << 8; + if (s->in[s->incnt++] != (~len & 0xff) || + s->in[s->incnt++] != ((~len >> 8) & 0xff)) + return -2; /* didn't match complement! */ + + /* copy len bytes from in to out */ + if (s->out != NIL) { + if (s->outcnt + len > s->outlen) + return 1; /* not enough output space */ + while (len--) + s->out[s->outcnt++] = s->in[s->incnt++]; + } + else { /* just scanning */ + s->outcnt += len; + s->incnt += len; + } + + /* done with a valid stored block */ + return 0; +} + + +struct huffman { + short *count; /* number of symbols of each length */ + short *symbol; /* canonically ordered symbols */ +}; + + +#ifdef SLOW +local int decode(struct state *s, struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + + code = first = index = 0; + for (len = 1; len <= MAXBITS; len++) { + code |= bits(s, 1); /* get next bit */ + count = h->count[len]; + if (code < first + count) /* if length len, return symbol */ + return h->symbol[index + (code - first)]; + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + } + return -9; /* ran out of codes */ +} + +/* + * A faster version of decode() for real applications of this code. It's not + * as readable, but it makes puff() twice as fast. And it only makes the code + * a few percent larger. + */ +#else /* !SLOW */ +local int decode(struct state *s, struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + int bitbuf; /* bits from stream */ + int left; /* bits left in next or left to process */ + short *next; /* next number of codes */ + + bitbuf = s->bitbuf; + left = s->bitcnt; + code = first = index = 0; + len = 1; + next = h->count + 1; + while (1) { + while (left--) { + code |= bitbuf & 1; + bitbuf >>= 1; + count = *next++; + if (code < first + count) { /* if length len, return symbol */ + s->bitbuf = bitbuf; + s->bitcnt = (s->bitcnt - len) & 7; + return h->symbol[index + (code - first)]; + } + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + len++; + } + left = (MAXBITS+1) - len; + if (left == 0) break; + bitbuf = s->in[s->incnt++]; + if (left > 8) left = 8; + } + return -9; /* ran out of codes */ +} +#endif /* SLOW */ + + +local int construct(struct huffman *h, short *length, int n) +{ + int symbol; /* current symbol when stepping through length[] */ + int len; /* current length when stepping through h->count[] */ + int left; /* number of possible codes left of current length */ + short offs[MAXBITS+1]; /* offsets in symbol table for each length */ + + /* count number of codes of each length */ + for (len = 0; len <= MAXBITS; len++) + h->count[len] = 0; + for (symbol = 0; symbol < n; symbol++) + (h->count[length[symbol]])++; /* assumes lengths are within bounds */ + if (h->count[0] == n) /* no codes! */ + return 0; /* complete, but decode() will fail */ + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; /* one possible code of zero length */ + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; /* one more bit, double codes left */ + left -= h->count[len]; /* deduct count from possible codes */ + if (left < 0) return left; /* over-subscribed--return negative */ + } /* left > 0 means incomplete */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + h->count[len]; + + /* + * put symbols in table sorted by length, by symbol order within each + * length + */ + for (symbol = 0; symbol < n; symbol++) + if (length[symbol] != 0) + h->symbol[offs[length[symbol]]++] = symbol; + + /* return zero for complete set, positive for incomplete set */ + return left; +} + + +local int codes(struct state *s, + struct huffman *lencode, + struct huffman *distcode) +{ + int symbol; /* decoded symbol */ + int len; /* length for copy */ + unsigned dist; /* distance for copy */ + static const short lens[29] = { /* Size base for length codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; + static const short lext[29] = { /* Extra bits for length codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; + static const short dists[30] = { /* Offset base for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; + static const short dext[30] = { /* Extra bits for distance codes 0..29 */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + /* decode literals and length/distance pairs */ + do { + symbol = decode(s, lencode); + if (symbol < 0) return symbol; /* invalid symbol */ + if (symbol < 256) { /* literal: symbol is the byte */ + /* write out the literal */ + if (s->out != NIL) { + if (s->outcnt == s->outlen) return 1; + s->out[s->outcnt] = symbol; + } + s->outcnt++; + } + else if (symbol > 256) { /* length */ + /* get and compute length */ + symbol -= 257; + if (symbol >= 29) return -9; /* invalid fixed code */ + len = lens[symbol] + bits(s, lext[symbol]); + + /* get and check distance */ + symbol = decode(s, distcode); + if (symbol < 0) return symbol; /* invalid symbol */ + dist = dists[symbol] + bits(s, dext[symbol]); + if (dist > s->outcnt) + return -10; /* distance too far back */ + + /* copy length bytes from distance bytes back */ + if (s->out != NIL) { + if (s->outcnt + len > s->outlen) return 1; + while (len--) { + s->out[s->outcnt] = s->out[s->outcnt - dist]; + s->outcnt++; + } + } + else + s->outcnt += len; + } + } while (symbol != 256); /* end of block symbol */ + + /* done with a valid fixed or dynamic block */ + return 0; +} + + +local int fixed(struct state *s) +{ + static int virgin = 1; + static short lencnt[MAXBITS+1], lensym[FIXLCODES]; + static short distcnt[MAXBITS+1], distsym[MAXDCODES]; + static struct huffman lencode = {lencnt, lensym}; + static struct huffman distcode = {distcnt, distsym}; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + int symbol; + short lengths[FIXLCODES]; + + /* literal/length table */ + for (symbol = 0; symbol < 144; symbol++) + lengths[symbol] = 8; + for (; symbol < 256; symbol++) + lengths[symbol] = 9; + for (; symbol < 280; symbol++) + lengths[symbol] = 7; + for (; symbol < FIXLCODES; symbol++) + lengths[symbol] = 8; + construct(&lencode, lengths, FIXLCODES); + + /* distance table */ + for (symbol = 0; symbol < MAXDCODES; symbol++) + lengths[symbol] = 5; + construct(&distcode, lengths, MAXDCODES); + + /* do this just once */ + virgin = 0; + } + + /* decode data until end-of-block code */ + return codes(s, &lencode, &distcode); +} + + +local int dynamic(struct state *s) +{ + int nlen, ndist, ncode; /* number of lengths in descriptor */ + int index; /* index of lengths[] */ + int err; /* construct() return value */ + short lengths[MAXCODES]; /* descriptor code lengths */ + short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ + short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ + struct huffman lencode = {lencnt, lensym}; /* length code */ + struct huffman distcode = {distcnt, distsym}; /* distance code */ + static const short order[19] = /* permutation of code length codes */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* get number of lengths in each table, check lengths */ + nlen = bits(s, 5) + 257; + ndist = bits(s, 5) + 1; + ncode = bits(s, 4) + 4; + if (nlen > MAXLCODES || ndist > MAXDCODES) + return -3; /* bad counts */ + + /* read code length code lengths (really), missing lengths are zero */ + for (index = 0; index < ncode; index++) + lengths[order[index]] = bits(s, 3); + for (; index < 19; index++) + lengths[order[index]] = 0; + + /* build huffman table for code lengths codes (use lencode temporarily) */ + err = construct(&lencode, lengths, 19); + if (err != 0) return -4; /* require complete code set here */ + + /* read length/literal and distance code length tables */ + index = 0; + while (index < nlen + ndist) { + int symbol; /* decoded value */ + int len; /* last length to repeat */ + + symbol = decode(s, &lencode); + if (symbol < 16) /* length in 0..15 */ + lengths[index++] = symbol; + else { /* repeat instruction */ + len = 0; /* assume repeating zeros */ + if (symbol == 16) { /* repeat last length 3..6 times */ + if (index == 0) return -5; /* no last length! */ + len = lengths[index - 1]; /* last length */ + symbol = 3 + bits(s, 2); + } + else if (symbol == 17) /* repeat zero 3..10 times */ + symbol = 3 + bits(s, 3); + else /* == 18, repeat zero 11..138 times */ + symbol = 11 + bits(s, 7); + if (index + symbol > nlen + ndist) + return -6; /* too many lengths! */ + while (symbol--) /* repeat last or zero symbol times */ + lengths[index++] = len; + } + } + + /* build huffman table for literal/length codes */ + err = construct(&lencode, lengths, nlen); + if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) + return -7; /* only allow incomplete codes if just one code */ + + /* build huffman table for distance codes */ + err = construct(&distcode, lengths + nlen, ndist); + if (err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) + return -8; /* only allow incomplete codes if just one code */ + + /* decode data until end-of-block code */ + return codes(s, &lencode, &distcode); +} + + +void _acrtused () { } + +// Decompress deflated data +int far main ( + unsigned char *dest, /* pointer to destination pointer */ + unsigned int destlen, /* amount of output space */ + unsigned char *source) /* pointer to source data pointer */ +{ + struct state s; /* input/output state */ + int last, type; /* block information */ + int err; /* return value */ + + /* initialize output state */ + s.out = dest; + s.outlen = destlen; /* ignored if dest is NIL */ + s.outcnt = 0; + + /* initialize input state */ + s.in = source; + s.incnt = 0; + s.bitbuf = 0; + s.bitcnt = 0; + + /* process blocks until last block or error */ + do { + last = bits(&s, 1); /* one if last block */ + type = bits(&s, 2); /* block type 0..3 */ + err = type == 0 ? stored(&s) : + (type == 1 ? fixed(&s) : + (type == 2 ? dynamic(&s) : + -1)); /* type == 3, invalid */ + if (err != 0) break; /* return with error */ + } while (!last); + + return err; +} diff --git a/Boot/Windows/IntFilter.cpp b/Boot/Windows/IntFilter.cpp index c9ebe9b..bdf4a4f 100644 --- a/Boot/Windows/IntFilter.cpp +++ b/Boot/Windows/IntFilter.cpp @@ -1,651 +1,641 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform.h" -#include "BootMemory.h" -#include "BootConfig.h" -#include "BootConsoleIo.h" -#include "BootDebug.h" -#include "BootDefs.h" -#include "BootDiskIo.h" -#include "BootEncryptedIo.h" -#include "BootStrings.h" -#include "IntFilter.h" - -static uint32 OriginalInt13Handler; -static uint32 OriginalInt15Handler; - -static Registers IntRegisters; - - -bool Int13Filter () -{ - CheckStack(); - - Registers regs; - memcpy (®s, &IntRegisters, sizeof (regs)); - __asm sti - - static int ReEntryCount = -1; - ++ReEntryCount; - - byte function = (byte) (regs.AX >> 8); - -#ifdef TC_TRACE_INT13 - DisableScreenOutput(); - - PrintHex (function); - - Print (" EN:"); Print (ReEntryCount); - Print (" SS:"); PrintHex (regs.SS); - - uint16 spdbg; - __asm mov spdbg, sp - PrintChar (' '); - PrintHex (spdbg); - PrintChar ('<'); PrintHex (TC_BOOT_LOADER_STACK_TOP); - -#endif - - bool passOriginalRequest = true; - - switch (function) - { - case 0x2: // Read sectors - case 0x3: // Write sectors - { - byte drive = (byte) regs.DX; - - ChsAddress chs; - chs.Cylinder = ((regs.CX << 2) & 0x300) | (regs.CX >> 8); - chs.Head = regs.DX >> 8; - chs.Sector = regs.CX & 0x3f; - - byte sectorCount = (byte) regs.AX; - -#ifdef TC_TRACE_INT13 - PrintVal (": Drive", drive - TC_FIRST_BIOS_DRIVE, false); - Print (" Chs: "); Print (chs); -#endif - - uint64 sector; - if (drive == BootDrive) - { - ChsToLba (BootDriveGeometry, chs, sector); -#ifdef TC_TRACE_INT13 - PrintVal (" Sec", sector.LowPart, false); -#endif - } - -#ifdef TC_TRACE_INT13 - PrintVal (" Count", sectorCount, false); - Print (" Buf: "); PrintHex (regs.ES); PrintChar (':'); PrintHex (regs.BX); - PrintEndl(); -#endif - - if (ReEntryCount == 0 && drive == EncryptedVirtualPartition.Drive) - { - BiosResult result; - - if (function == 0x3) - result = WriteEncryptedSectors (regs.ES, regs.BX, drive, sector, sectorCount); - else - result = ReadEncryptedSectors (regs.ES, regs.BX, drive, sector, sectorCount); - - __asm cli - - memcpy (&IntRegisters, ®s, sizeof (regs)); - IntRegisters.AX = (uint16) result << 8; - - if (result == BiosResultSuccess) - { - IntRegisters.AX |= sectorCount; - IntRegisters.Flags &= ~TC_X86_CARRY_FLAG; - } - else - IntRegisters.Flags |= TC_X86_CARRY_FLAG; - - passOriginalRequest = false; - } - } - break; - - case 0x42: // Read sectors LBA - case 0x43: // Write sectors LBA - { - byte drive = (byte) regs.DX; - - BiosLbaPacket lba; - CopyMemory (regs.DS, regs.SI, (byte *) &lba, sizeof (lba)); - -#ifdef TC_TRACE_INT13 - PrintVal (": Drive", drive - TC_FIRST_BIOS_DRIVE, false); - PrintVal (" Sec", lba.Sector.LowPart, false); -#endif - - if (drive == BootDrive) - { - ChsAddress chs; - LbaToChs (BootDriveGeometry, lba.Sector, chs); -#ifdef TC_TRACE_INT13 - Print (" Chs: "); - Print (chs); -#endif - } - -#ifdef TC_TRACE_INT13 - PrintVal (" Count", lba.SectorCount, false); - PrintVal (" Buf", lba.Buffer, false, true); - PrintEndl(); -#endif - - if (ReEntryCount == 0 && drive == EncryptedVirtualPartition.Drive) - { - BiosResult result; - - uint16 segment = (uint16) (lba.Buffer >> 16); - uint16 offset = (uint16) lba.Buffer; - - if (function == 0x43) - result = WriteEncryptedSectors (segment, offset, drive, lba.Sector, lba.SectorCount); - else - result = ReadEncryptedSectors (segment, offset, drive, lba.Sector, lba.SectorCount); - - __asm cli - - memcpy (&IntRegisters, ®s, sizeof (regs)); - IntRegisters.AX = (IntRegisters.AX & 0xff) | ((uint16) result << 8); - - if (result == BiosResultSuccess) - IntRegisters.Flags &= ~TC_X86_CARRY_FLAG; - else - IntRegisters.Flags |= TC_X86_CARRY_FLAG; - - passOriginalRequest = false; - } - } - break; - - default: -#ifdef TC_TRACE_INT13 - PrintEndl(); -#endif - break; - } - -#ifdef TC_TRACE_INT13 - EnableScreenOutput(); -#endif - --ReEntryCount; - - return passOriginalRequest; -} - - -#define TC_MAX_MEMORY_MAP_SIZE 36 - -BiosMemoryMapEntry BiosMemoryMap[TC_MAX_MEMORY_MAP_SIZE]; -static size_t BiosMemoryMapSize; - - -static void CreateBootLoaderMemoryMapEntry (BiosMemoryMapEntry *newMapEntry, uint32 bootLoaderStart) -{ - newMapEntry->Type = 0x2; - newMapEntry->BaseAddress.HighPart = 0; - newMapEntry->BaseAddress.LowPart = bootLoaderStart; - newMapEntry->Length.HighPart = 0; - newMapEntry->Length.LowPart = TC_BOOT_MEMORY_REQUIRED * 1024UL; -} - - -static bool CreateNewBiosMemoryMap () -{ - // Create a new BIOS memory map presenting the memory area of the loader as reserved - - BiosMemoryMapSize = 0; - BiosMemoryMapEntry entry; - BiosMemoryMapEntry *newMapEntry = BiosMemoryMap; - - const BiosMemoryMapEntry *mapEnd = BiosMemoryMap + TC_MAX_MEMORY_MAP_SIZE; - - uint64 bootLoaderStart; - bootLoaderStart.HighPart = 0; - - uint16 codeSeg; - __asm mov codeSeg, cs - bootLoaderStart.LowPart = GetLinearAddress (codeSeg, 0); - - uint64 bootLoaderEnd; - bootLoaderEnd.HighPart = 0; - bootLoaderEnd.LowPart = bootLoaderStart.LowPart + TC_BOOT_MEMORY_REQUIRED * 1024UL; - - bool loaderEntryInserted = false; - - if (GetFirstBiosMemoryMapEntry (entry)) - { - do - { - uint64 entryEnd = entry.BaseAddress + entry.Length; - - if (entry.Type == 0x1 && RegionsIntersect (bootLoaderStart, TC_BOOT_MEMORY_REQUIRED * 1024UL, entry.BaseAddress, entryEnd - 1)) - { - // Free map entry covers the boot loader area - - if (entry.BaseAddress < bootLoaderStart) - { - // Create free entry below the boot loader area - if (newMapEntry >= mapEnd) - goto mapOverflow; - - *newMapEntry = entry; - newMapEntry->Length = bootLoaderStart - entry.BaseAddress; - ++newMapEntry; - } - - if (!loaderEntryInserted) - { - // Create reserved entry for the boot loader if it has not been done yet - if (newMapEntry >= mapEnd) - goto mapOverflow; - - CreateBootLoaderMemoryMapEntry (newMapEntry, bootLoaderStart.LowPart); - ++newMapEntry; - loaderEntryInserted = true; - } - - if (bootLoaderEnd < entryEnd) - { - // Create free entry above the boot loader area - if (newMapEntry >= mapEnd) - goto mapOverflow; - - newMapEntry->Type = 0x1; - newMapEntry->BaseAddress = bootLoaderEnd; - newMapEntry->Length = entryEnd - bootLoaderEnd; - ++newMapEntry; - } - } - else - { - if (newMapEntry >= mapEnd) - goto mapOverflow; - - if (!loaderEntryInserted && entry.BaseAddress > bootLoaderStart) - { - // Create reserved entry for the boot loader if it has not been done yet - CreateBootLoaderMemoryMapEntry (newMapEntry, bootLoaderStart.LowPart); - ++newMapEntry; - loaderEntryInserted = true; - } - - // Copy map entry - *newMapEntry++ = entry; - } - - } while (GetNextBiosMemoryMapEntry (entry)); - } - - BiosMemoryMapSize = newMapEntry - BiosMemoryMap; - return true; - -mapOverflow: - size_t overSize = 0; - while (GetNextBiosMemoryMapEntry (entry)) - { - ++overSize; - } - - PrintError ("MMAP: ", true, false); - Print (overSize); - PrintEndl(); - - return false; -} - - -bool Int15Filter () -{ - CheckStack(); - -#ifdef TC_TRACE_INT15 - DisableScreenOutput(); - - Print ("15-"); - PrintHex (IntRegisters.AX); - - Print (" SS:"); PrintHex (IntRegisters.SS); - - uint16 spdbg; - __asm mov spdbg, sp - PrintChar (' '); - PrintHex (spdbg); - PrintChar ('<'); PrintHex (TC_BOOT_LOADER_STACK_TOP); - - Print (" EAX:"); PrintHex (IntRegisters.EAX); - Print (" EBX:"); PrintHex (IntRegisters.EBX); - Print (" ECX:"); PrintHex (IntRegisters.ECX); - Print (" EDX:"); PrintHex (IntRegisters.EDX); - Print (" DI:"); PrintHex (IntRegisters.DI); - PrintEndl(); - -#endif - - if (IntRegisters.EBX >= BiosMemoryMapSize) - { - IntRegisters.Flags |= TC_X86_CARRY_FLAG; - IntRegisters.EBX = 0; - IntRegisters.AX = -1; - } - else - { - CopyMemory ((byte *) &BiosMemoryMap[IntRegisters.EBX], IntRegisters.ES, IntRegisters.DI, sizeof (BiosMemoryMap[0])); - - IntRegisters.Flags &= ~TC_X86_CARRY_FLAG; - IntRegisters.EAX = 0x534D4150UL; - - ++IntRegisters.EBX; - if (IntRegisters.EBX >= BiosMemoryMapSize) - IntRegisters.EBX = 0; - - IntRegisters.ECX = sizeof (BiosMemoryMap[0]); - } - - if (IntRegisters.EBX == 0 && !(BootSectorFlags & TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER)) - { - // Uninstall filter when the modified map has been issued three times to prevent - // problems with hardware drivers on some notebooks running Windows XP. - - static CompleteMapIssueCount = 0; - if (++CompleteMapIssueCount >= 3) - { - __asm - { - cli - push es - - lea si, OriginalInt15Handler - xor ax, ax - mov es, ax - mov di, 0x15 * 4 - - mov ax, [si] - mov es:[di], ax - mov ax, [si + 2] - mov es:[di + 2], ax - - pop es - sti - } - } - } - -#ifdef TC_TRACE_INT15 - BiosMemoryMapEntry entry; - CopyMemory (IntRegisters.ES, IntRegisters.DI, (byte *) &entry, sizeof (entry)); - PrintHex (entry.Type); PrintChar (' '); - PrintHex (entry.BaseAddress); PrintChar (' '); - PrintHex (entry.Length); PrintChar (' '); - PrintHex (entry.BaseAddress + entry.Length); PrintEndl(); - - Print ("EAX:"); PrintHex (IntRegisters.EAX); - Print (" EBX:"); PrintHex (IntRegisters.EBX); - Print (" ECX:"); PrintHex (IntRegisters.ECX); - Print (" EDX:"); PrintHex (IntRegisters.EDX); - Print (" DI:"); PrintHex (IntRegisters.DI); - Print (" FL:"); PrintHex (IntRegisters.Flags); - PrintEndl (2); -#endif - -#ifdef TC_TRACE_INT15 - EnableScreenOutput(); -#endif - return false; -} - - -void IntFilterEntry () -{ - // No automatic variables should be used in this scope as SS may change - static uint16 OrigStackPointer; - static uint16 OrigStackSegment; - - __asm - { - pushf - pushad - - cli - mov cs:IntRegisters.DI, di - - lea di, cs:IntRegisters.EAX - TC_ASM_EMIT4 (66,2E,89,05) // mov [cs:di], eax - lea di, cs:IntRegisters.EBX - TC_ASM_EMIT4 (66,2E,89,1D) // mov [cs:di], ebx - lea di, cs:IntRegisters.ECX - TC_ASM_EMIT4 (66,2E,89,0D) // mov [cs:di], ecx - lea di, cs:IntRegisters.EDX - TC_ASM_EMIT4 (66,2E,89,15) // mov [cs:di], edx - - mov ax, [bp + 8] - mov cs:IntRegisters.Flags, ax - - mov cs:IntRegisters.SI, si - mov si, [bp + 2] // Int number - - mov cs:IntRegisters.DS, ds - mov cs:IntRegisters.ES, es - mov cs:IntRegisters.SS, ss - - // Compiler assumes SS == DS - use our stack if this condition is not met - mov ax, ss - mov bx, cs - cmp ax, bx - jz stack_ok - - mov cs:OrigStackPointer, sp - mov cs:OrigStackSegment, ss - mov ax, cs - mov ss, ax - mov sp, TC_BOOT_LOADER_STACK_TOP - - stack_ok: - // DS = CS - push ds - push es - mov ax, cs - mov ds, ax - mov es, ax - - push si // Int number - - // Filter request - cmp si, 0x15 - je filter15 - cmp si, 0x13 - jne $ - - call Int13Filter - jmp s0 - - filter15: - call Int15Filter - - s0: - pop si // Int number - pop es - pop ds - - // Restore original SS:SP if our stack is empty - cli - mov bx, TC_BOOT_LOADER_STACK_TOP - cmp bx, sp - jnz stack_in_use - - mov ss, cs:OrigStackSegment - mov sp, cs:OrigStackPointer - stack_in_use: - - test ax, ax // passOriginalRequest - jnz pass_request - - // Return results of filtered request - popad - popf - mov ax, cs:IntRegisters.Flags - mov [bp + 8], ax - leave - - lea di, cs:IntRegisters.EAX - TC_ASM_EMIT4 (66,2E,8B,05) // mov eax, [cs:di] - lea di, cs:IntRegisters.EBX - TC_ASM_EMIT4 (66,2E,8B,1D) // mov ebx, [cs:di] - lea di, cs:IntRegisters.ECX - TC_ASM_EMIT4 (66,2E,8B,0D) // mov ecx, [cs:di] - lea di, cs:IntRegisters.EDX - TC_ASM_EMIT4 (66,2E,8B,15) // mov edx, [cs:di] - - mov di, cs:IntRegisters.DI - mov si, cs:IntRegisters.SI - mov es, cs:IntRegisters.ES - mov ds, cs:IntRegisters.DS - - sti - add sp, 2 - iret - - // Pass original request - pass_request: - sti - cmp si, 0x15 - je pass15 - cmp si, 0x13 - jne $ - - popad - popf - leave - add sp, 2 - jmp cs:OriginalInt13Handler - - pass15: - popad - popf - leave - add sp, 2 - jmp cs:OriginalInt15Handler - } -} - - -void Int13FilterEntry () -{ - __asm - { - leave - push 0x13 - jmp IntFilterEntry - } -} - - -static void Int15FilterEntry () -{ - __asm - { - pushf - cmp ax, 0xe820 // Get system memory map - je filter - - popf - leave - jmp cs:OriginalInt15Handler - - filter: - leave - push 0x15 - jmp IntFilterEntry - } -} - - -bool InstallInterruptFilters () -{ - -#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE - - // If the filters have already been installed, it usually indicates stack corruption - // and a consequent reentry of this routine without a system reset. - - uint32 currentInt13Handler; - CopyMemory (0, 0x13 * 4, ¤tInt13Handler, sizeof (currentInt13Handler)); - - if (currentInt13Handler == (uint32) Int13FilterEntry) - { - PrintError ("Memory corrupted"); - Print (TC_BOOT_STR_UPGRADE_BIOS); - - GetKeyboardChar(); - return true; - } - -#endif - - if (!CreateNewBiosMemoryMap()) - return false; - - __asm - { - cli - push es - - // Save original INT 13 handler - xor ax, ax - mov es, ax - - mov si, 0x13 * 4 - lea di, OriginalInt13Handler - - mov ax, es:[si] - mov [di], ax - mov ax, es:[si + 2] - mov [di + 2], ax - - // Install INT 13 filter - lea ax, Int13FilterEntry - mov es:[si], ax - mov es:[si + 2], cs - - // Save original INT 15 handler - mov si, 0x15 * 4 - lea di, OriginalInt15Handler - - mov ax, es:[si] - mov [di], ax - mov ax, es:[si + 2] - mov [di + 2], ax - - // Install INT 15 filter - lea ax, Int15FilterEntry - mov es:[si], ax - mov es:[si + 2], cs - - // If the BIOS does not support system memory map (INT15 0xe820), - // set amount of available memory to CS:0000 - 0:0000 - cmp BiosMemoryMapSize, 1 - jg mem_map_ok - mov ax, cs - shr ax, 10 - 4 // CS * 16 / 1024 - mov es:[0x413], ax // = KBytes available - mem_map_ok: - - pop es - sti - } - - return true; -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform.h" +#include "BootMemory.h" +#include "BootConfig.h" +#include "BootConsoleIo.h" +#include "BootDebug.h" +#include "BootDefs.h" +#include "BootDiskIo.h" +#include "BootEncryptedIo.h" +#include "BootStrings.h" +#include "IntFilter.h" + +static uint32 OriginalInt13Handler; +static uint32 OriginalInt15Handler; + +static Registers IntRegisters; + + +bool Int13Filter () +{ + CheckStack(); + + Registers regs; + memcpy (®s, &IntRegisters, sizeof (regs)); + __asm sti + + static int ReEntryCount = -1; + ++ReEntryCount; + + byte function = (byte) (regs.AX >> 8); + +#ifdef TC_TRACE_INT13 + DisableScreenOutput(); + + PrintHex (function); + + Print (" EN:"); Print (ReEntryCount); + Print (" SS:"); PrintHex (regs.SS); + + uint16 spdbg; + __asm mov spdbg, sp + PrintChar (' '); + PrintHex (spdbg); + PrintChar ('<'); PrintHex (TC_BOOT_LOADER_STACK_TOP); + +#endif + + bool passOriginalRequest = true; + + switch (function) + { + case 0x2: // Read sectors + case 0x3: // Write sectors + { + byte drive = (byte) regs.DX; + + ChsAddress chs; + chs.Cylinder = ((regs.CX << 2) & 0x300) | (regs.CX >> 8); + chs.Head = regs.DX >> 8; + chs.Sector = regs.CX & 0x3f; + + byte sectorCount = (byte) regs.AX; + +#ifdef TC_TRACE_INT13 + PrintVal (": Drive", drive - TC_FIRST_BIOS_DRIVE, false); + Print (" Chs: "); Print (chs); +#endif + + uint64 sector; + if (drive == BootDrive) + { + if (!BootDriveGeometryValid) + TC_THROW_FATAL_EXCEPTION; + + ChsToLba (BootDriveGeometry, chs, sector); +#ifdef TC_TRACE_INT13 + PrintVal (" Sec", sector.LowPart, false); +#endif + } + +#ifdef TC_TRACE_INT13 + PrintVal (" Count", sectorCount, false); + Print (" Buf: "); PrintHex (regs.ES); PrintChar (':'); PrintHex (regs.BX); + PrintEndl(); +#endif + + if (ReEntryCount == 0 && drive == EncryptedVirtualPartition.Drive) + { + BiosResult result; + + if (function == 0x3) + result = WriteEncryptedSectors (regs.ES, regs.BX, drive, sector, sectorCount); + else + result = ReadEncryptedSectors (regs.ES, regs.BX, drive, sector, sectorCount); + + __asm cli + + memcpy (&IntRegisters, ®s, sizeof (regs)); + IntRegisters.AX = (uint16) result << 8; + + if (result == BiosResultSuccess) + { + IntRegisters.AX |= sectorCount; + IntRegisters.Flags &= ~TC_X86_CARRY_FLAG; + } + else + IntRegisters.Flags |= TC_X86_CARRY_FLAG; + + passOriginalRequest = false; + } + } + break; + + case 0x42: // Read sectors LBA + case 0x43: // Write sectors LBA + { + byte drive = (byte) regs.DX; + + BiosLbaPacket lba; + CopyMemory (regs.DS, regs.SI, (byte *) &lba, sizeof (lba)); + +#ifdef TC_TRACE_INT13 + PrintVal (": Drive", drive - TC_FIRST_BIOS_DRIVE, false); + PrintVal (" Sec", lba.Sector.LowPart, false); + PrintVal (" Count", lba.SectorCount, false); + PrintVal (" Buf", lba.Buffer, false, true); + PrintEndl(); +#endif + + if (ReEntryCount == 0 && drive == EncryptedVirtualPartition.Drive) + { + BiosResult result; + + uint16 segment = (uint16) (lba.Buffer >> 16); + uint16 offset = (uint16) lba.Buffer; + + if (function == 0x43) + result = WriteEncryptedSectors (segment, offset, drive, lba.Sector, lba.SectorCount); + else + result = ReadEncryptedSectors (segment, offset, drive, lba.Sector, lba.SectorCount); + + __asm cli + + memcpy (&IntRegisters, ®s, sizeof (regs)); + IntRegisters.AX = (IntRegisters.AX & 0xff) | ((uint16) result << 8); + + if (result == BiosResultSuccess) + IntRegisters.Flags &= ~TC_X86_CARRY_FLAG; + else + IntRegisters.Flags |= TC_X86_CARRY_FLAG; + + passOriginalRequest = false; + } + } + break; + + default: +#ifdef TC_TRACE_INT13 + PrintEndl(); +#endif + break; + } + +#ifdef TC_TRACE_INT13 + EnableScreenOutput(); +#endif + --ReEntryCount; + + return passOriginalRequest; +} + + +#define TC_MAX_MEMORY_MAP_SIZE 36 + +BiosMemoryMapEntry BiosMemoryMap[TC_MAX_MEMORY_MAP_SIZE]; +static size_t BiosMemoryMapSize; + + +static void CreateBootLoaderMemoryMapEntry (BiosMemoryMapEntry *newMapEntry, uint32 bootLoaderStart) +{ + newMapEntry->Type = 0x2; + newMapEntry->BaseAddress.HighPart = 0; + newMapEntry->BaseAddress.LowPart = bootLoaderStart; + newMapEntry->Length.HighPart = 0; + newMapEntry->Length.LowPart = TC_BOOT_MEMORY_REQUIRED * 1024UL; +} + + +static bool CreateNewBiosMemoryMap () +{ + // Create a new BIOS memory map presenting the memory area of the loader as reserved + + BiosMemoryMapSize = 0; + BiosMemoryMapEntry entry; + BiosMemoryMapEntry *newMapEntry = BiosMemoryMap; + + const BiosMemoryMapEntry *mapEnd = BiosMemoryMap + TC_MAX_MEMORY_MAP_SIZE; + + uint64 bootLoaderStart; + bootLoaderStart.HighPart = 0; + + uint16 codeSeg; + __asm mov codeSeg, cs + bootLoaderStart.LowPart = GetLinearAddress (codeSeg, 0); + + uint64 bootLoaderEnd; + bootLoaderEnd.HighPart = 0; + bootLoaderEnd.LowPart = bootLoaderStart.LowPart + TC_BOOT_MEMORY_REQUIRED * 1024UL; + + bool loaderEntryInserted = false; + + if (GetFirstBiosMemoryMapEntry (entry)) + { + do + { + uint64 entryEnd = entry.BaseAddress + entry.Length; + + if (entry.Type == 0x1 && RegionsIntersect (bootLoaderStart, TC_BOOT_MEMORY_REQUIRED * 1024UL, entry.BaseAddress, entryEnd - 1)) + { + // Free map entry covers the boot loader area + + if (entry.BaseAddress < bootLoaderStart) + { + // Create free entry below the boot loader area + if (newMapEntry >= mapEnd) + goto mapOverflow; + + *newMapEntry = entry; + newMapEntry->Length = bootLoaderStart - entry.BaseAddress; + ++newMapEntry; + } + + if (!loaderEntryInserted) + { + // Create reserved entry for the boot loader if it has not been done yet + if (newMapEntry >= mapEnd) + goto mapOverflow; + + CreateBootLoaderMemoryMapEntry (newMapEntry, bootLoaderStart.LowPart); + ++newMapEntry; + loaderEntryInserted = true; + } + + if (bootLoaderEnd < entryEnd) + { + // Create free entry above the boot loader area + if (newMapEntry >= mapEnd) + goto mapOverflow; + + newMapEntry->Type = 0x1; + newMapEntry->BaseAddress = bootLoaderEnd; + newMapEntry->Length = entryEnd - bootLoaderEnd; + ++newMapEntry; + } + } + else + { + if (newMapEntry >= mapEnd) + goto mapOverflow; + + if (!loaderEntryInserted && entry.BaseAddress > bootLoaderStart) + { + // Create reserved entry for the boot loader if it has not been done yet + CreateBootLoaderMemoryMapEntry (newMapEntry, bootLoaderStart.LowPart); + ++newMapEntry; + loaderEntryInserted = true; + } + + // Copy map entry + *newMapEntry++ = entry; + } + + } while (GetNextBiosMemoryMapEntry (entry)); + } + + BiosMemoryMapSize = newMapEntry - BiosMemoryMap; + return true; + +mapOverflow: + size_t overSize = 0; + while (GetNextBiosMemoryMapEntry (entry)) + { + ++overSize; + } + + PrintErrorNoEndl ("MMAP: "); + Print (overSize); + PrintEndl(); + + return false; +} + + +bool Int15Filter () +{ + CheckStack(); + +#ifdef TC_TRACE_INT15 + DisableScreenOutput(); + + Print ("15-"); + PrintHex (IntRegisters.AX); + + Print (" SS:"); PrintHex (IntRegisters.SS); + + uint16 spdbg; + __asm mov spdbg, sp + PrintChar (' '); + PrintHex (spdbg); + PrintChar ('<'); PrintHex (TC_BOOT_LOADER_STACK_TOP); + + Print (" EAX:"); PrintHex (IntRegisters.EAX); + Print (" EBX:"); PrintHex (IntRegisters.EBX); + Print (" ECX:"); PrintHex (IntRegisters.ECX); + Print (" EDX:"); PrintHex (IntRegisters.EDX); + Print (" DI:"); PrintHex (IntRegisters.DI); + PrintEndl(); + +#endif + + if (IntRegisters.EBX >= BiosMemoryMapSize) + { + IntRegisters.Flags |= TC_X86_CARRY_FLAG; + IntRegisters.EBX = 0; + IntRegisters.AX = -1; + } + else + { + CopyMemory ((byte *) &BiosMemoryMap[IntRegisters.EBX], IntRegisters.ES, IntRegisters.DI, sizeof (BiosMemoryMap[0])); + + IntRegisters.Flags &= ~TC_X86_CARRY_FLAG; + IntRegisters.EAX = 0x534D4150UL; + + ++IntRegisters.EBX; + if (IntRegisters.EBX >= BiosMemoryMapSize) + IntRegisters.EBX = 0; + + IntRegisters.ECX = sizeof (BiosMemoryMap[0]); + } + + if (IntRegisters.EBX == 0 && !(BootSectorFlags & TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER)) + { + // Uninstall filter when the modified map has been issued three times to prevent + // problems with hardware drivers on some notebooks running Windows XP. + + static int CompleteMapIssueCount = 0; + if (++CompleteMapIssueCount >= 3) + { + __asm + { + cli + push es + + lea si, OriginalInt15Handler + xor ax, ax + mov es, ax + mov di, 0x15 * 4 + + mov ax, [si] + mov es:[di], ax + mov ax, [si + 2] + mov es:[di + 2], ax + + pop es + sti + } + } + } + +#ifdef TC_TRACE_INT15 + BiosMemoryMapEntry entry; + CopyMemory (IntRegisters.ES, IntRegisters.DI, (byte *) &entry, sizeof (entry)); + PrintHex (entry.Type); PrintChar (' '); + PrintHex (entry.BaseAddress); PrintChar (' '); + PrintHex (entry.Length); PrintChar (' '); + PrintHex (entry.BaseAddress + entry.Length); PrintEndl(); + + Print ("EAX:"); PrintHex (IntRegisters.EAX); + Print (" EBX:"); PrintHex (IntRegisters.EBX); + Print (" ECX:"); PrintHex (IntRegisters.ECX); + Print (" EDX:"); PrintHex (IntRegisters.EDX); + Print (" DI:"); PrintHex (IntRegisters.DI); + Print (" FL:"); PrintHex (IntRegisters.Flags); + PrintEndl (2); +#endif + +#ifdef TC_TRACE_INT15 + EnableScreenOutput(); +#endif + return false; +} + + +void IntFilterEntry () +{ + // No automatic variables should be used in this scope as SS may change + static uint16 OrigStackPointer; + static uint16 OrigStackSegment; + + __asm + { + pushf + pushad + + cli + mov cs:IntRegisters.DI, di + + lea di, cs:IntRegisters.EAX + TC_ASM_EMIT4 (66,2E,89,05) // mov [cs:di], eax + lea di, cs:IntRegisters.EBX + TC_ASM_EMIT4 (66,2E,89,1D) // mov [cs:di], ebx + lea di, cs:IntRegisters.ECX + TC_ASM_EMIT4 (66,2E,89,0D) // mov [cs:di], ecx + lea di, cs:IntRegisters.EDX + TC_ASM_EMIT4 (66,2E,89,15) // mov [cs:di], edx + + mov ax, [bp + 8] + mov cs:IntRegisters.Flags, ax + + mov cs:IntRegisters.SI, si + mov si, [bp + 2] // Int number + + mov cs:IntRegisters.DS, ds + mov cs:IntRegisters.ES, es + mov cs:IntRegisters.SS, ss + + // Compiler assumes SS == DS - use our stack if this condition is not met + mov ax, ss + mov bx, cs + cmp ax, bx + jz stack_ok + + mov cs:OrigStackPointer, sp + mov cs:OrigStackSegment, ss + mov ax, cs + mov ss, ax + mov sp, TC_BOOT_LOADER_STACK_TOP + + stack_ok: + // DS = CS + push ds + push es + mov ax, cs + mov ds, ax + mov es, ax + + push si // Int number + + // Filter request + cmp si, 0x15 + je filter15 + cmp si, 0x13 + jne $ + + call Int13Filter + jmp s0 + + filter15: + call Int15Filter + + s0: + pop si // Int number + pop es + pop ds + + // Restore original SS:SP if our stack is empty + cli + mov bx, TC_BOOT_LOADER_STACK_TOP + cmp bx, sp + jnz stack_in_use + + mov ss, cs:OrigStackSegment + mov sp, cs:OrigStackPointer + stack_in_use: + + test ax, ax // passOriginalRequest + jnz pass_request + + // Return results of filtered request + popad + popf + mov ax, cs:IntRegisters.Flags + mov [bp + 8], ax + leave + + lea di, cs:IntRegisters.EAX + TC_ASM_EMIT4 (66,2E,8B,05) // mov eax, [cs:di] + lea di, cs:IntRegisters.EBX + TC_ASM_EMIT4 (66,2E,8B,1D) // mov ebx, [cs:di] + lea di, cs:IntRegisters.ECX + TC_ASM_EMIT4 (66,2E,8B,0D) // mov ecx, [cs:di] + lea di, cs:IntRegisters.EDX + TC_ASM_EMIT4 (66,2E,8B,15) // mov edx, [cs:di] + + mov di, cs:IntRegisters.DI + mov si, cs:IntRegisters.SI + mov es, cs:IntRegisters.ES + mov ds, cs:IntRegisters.DS + + sti + add sp, 2 + iret + + // Pass original request + pass_request: + sti + cmp si, 0x15 + je pass15 + cmp si, 0x13 + jne $ + + popad + popf + leave + add sp, 2 + jmp cs:OriginalInt13Handler + + pass15: + popad + popf + leave + add sp, 2 + jmp cs:OriginalInt15Handler + } +} + + +void Int13FilterEntry () +{ + __asm + { + leave + push 0x13 + jmp IntFilterEntry + } +} + + +static void Int15FilterEntry () +{ + __asm + { + pushf + cmp ax, 0xe820 // Get system memory map + je filter + + popf + leave + jmp cs:OriginalInt15Handler + + filter: + leave + push 0x15 + jmp IntFilterEntry + } +} + + +bool InstallInterruptFilters () +{ + +#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE + + // If the filters have already been installed, it usually indicates stack corruption + // and a consequent reentry of this routine without a system reset. + + uint32 currentInt13Handler; + CopyMemory (0, 0x13 * 4, ¤tInt13Handler, sizeof (currentInt13Handler)); + + if (currentInt13Handler == (uint32) Int13FilterEntry) + { + PrintError ("Memory corrupted"); + Print (TC_BOOT_STR_UPGRADE_BIOS); + + GetKeyboardChar(); + return true; + } + +#endif + + if (!CreateNewBiosMemoryMap()) + return false; + + __asm + { + cli + push es + + // Save original INT 13 handler + xor ax, ax + mov es, ax + + mov si, 0x13 * 4 + lea di, OriginalInt13Handler + + mov ax, es:[si] + mov [di], ax + mov ax, es:[si + 2] + mov [di + 2], ax + + // Install INT 13 filter + lea ax, Int13FilterEntry + mov es:[si], ax + mov es:[si + 2], cs + + // Save original INT 15 handler + mov si, 0x15 * 4 + lea di, OriginalInt15Handler + + mov ax, es:[si] + mov [di], ax + mov ax, es:[si + 2] + mov [di + 2], ax + + // Install INT 15 filter + lea ax, Int15FilterEntry + mov es:[si], ax + mov es:[si + 2], cs + + // If the BIOS does not support system memory map (INT15 0xe820), + // set amount of available memory to CS:0000 - 0:0000 + cmp BiosMemoryMapSize, 1 + jg mem_map_ok + mov ax, cs + shr ax, 10 - 4 // CS * 16 / 1024 + mov es:[0x413], ax // = KBytes available + mem_map_ok: + + pop es + sti + } + + return true; +} diff --git a/Boot/Windows/IntFilter.h b/Boot/Windows/IntFilter.h index 32150f2..d33531b 100644 --- a/Boot/Windows/IntFilter.h +++ b/Boot/Windows/IntFilter.h @@ -1,16 +1,16 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_IntFilter -#define TC_HEADER_Boot_IntFilter - -#include "Platform.h" - -bool InstallInterruptFilters (); - -#endif TC_HEADER_Boot_IntFilter +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_IntFilter +#define TC_HEADER_Boot_IntFilter + +#include "Platform.h" + +bool InstallInterruptFilters (); + +#endif TC_HEADER_Boot_IntFilter diff --git a/Boot/Windows/Makefile b/Boot/Windows/Makefile index e50ad00..62be1b8 100644 --- a/Boot/Windows/Makefile +++ b/Boot/Windows/Makefile @@ -1,183 +1,183 @@ -# -# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -PROJ = BootLoader -.SILENT: - -!ifndef MSVC16_ROOT -!error Environment variable MSVC16_ROOT must point to the installation directory of MS Visual C++ 1.5 -!endif - -ENVPATH = $(PATH) - -CPP = $(MSVC16_ROOT)\bin\cl.exe -LD = $(MSVC16_ROOT)\bin\link.exe - -AFLAGS = /nologo /AT /omf - -CPPFLAGS = /nologo /W2 /Fc /I "$(MSVC16_ROOT)\Include" /I"..\..\.." /I"..\..\..\Common" /I"..\..\..\Crypto" -CPPFLAGS = $(CPPFLAGS) /D __int8=char /D __int16=int /D __int32=long /D BOOL=__int32 /D FALSE=0 /D TRUE=1 -CPPFLAGS = $(CPPFLAGS) /D LITTLE_ENDIAN=1234 /D BYTE_ORDER=1234 /D TC_WINDOWS_BOOT /D TC_MINIMIZE_CODE_SIZE /D TC_NO_COMPILER_INT64 -CPPFLAGS = $(CPPFLAGS) /D malloc=malloc_NA - -LFLAGS = /NOLOGO /ONERROR:NOEXE /NOI /BATCH - -OBJDIR = Release - -!ifdef RESCUE_DISK -OBJDIR = Rescue -CPPFLAGS = $(CPPFLAGS) /D TC_WINDOWS_BOOT_RESCUE_DISK_MODE -!endif - -!ifdef SINGLE_CIPHER -OBJDIR = $(OBJDIR)_$(SINGLE_CIPHER) -CPPFLAGS = $(CPPFLAGS) /D TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE /D TC_WINDOWS_BOOT_$(SINGLE_CIPHER) -!endif - -OUTDIR = $(OBJDIR) -TARGETEXT = com -TARGETS = $(OUTDIR)\BootDefs.i $(OUTDIR)\BootSector.bin $(OUTDIR)\Decompressor.com -CPPFLAGS = $(CPPFLAGS) /AT /Zl /f- /G3 /Oe /Os /Ob1 /OV0 /Gs /Gf /Gy /D NDEBUG -LFLAGS = $(LFLAGS) /NOD /NOE /TINY -OBJS = $(OUTDIR)\BootCrt.obj -LIBS = slibce - -!if 1 -SRCDIR = .. -!else -SRCDIR = $(MAKEDIR) -!endif - -TARGETS = $(TARGETS) $(OUTDIR)\$(PROJ).$(TARGETEXT) - -OBJS = $(OBJS) $(OUTDIR)\BootConfig.obj -OBJS = $(OBJS) $(OUTDIR)\BootConsoleIo.obj -OBJS = $(OBJS) $(OUTDIR)\BootDebug.obj -OBJS = $(OBJS) $(OUTDIR)\BootDiskIo.obj -OBJS = $(OBJS) $(OUTDIR)\BootEncryptedIo.obj -OBJS = $(OBJS) $(OUTDIR)\BootMain.obj -OBJS = $(OBJS) $(OUTDIR)\BootMemory.obj -OBJS = $(OBJS) $(OUTDIR)\IntFilter.obj -OBJS = $(OBJS) $(OUTDIR)\Platform.obj - -OBJS = $(OBJS) $(OUTDIR)\Crc.obj -OBJS = $(OBJS) $(OUTDIR)\Crypto.obj -OBJS = $(OBJS) $(OUTDIR)\Endian.obj -OBJS = $(OBJS) $(OUTDIR)\Pkcs5.obj -OBJS = $(OBJS) $(OUTDIR)\Volumes.obj -OBJS = $(OBJS) $(OUTDIR)\Xts.obj - -OBJS = $(OBJS) $(OUTDIR)\Rmd160.obj - -!if !DEFINED (SINGLE_CIPHER) -OBJS = $(OBJS) $(OUTDIR)\AesSmall.obj -!else if "$(SINGLE_CIPHER)" == "AES" -OBJS = $(OBJS) $(OUTDIR)\AesSmall_x86.obj -OBJS = $(OBJS) $(OUTDIR)\Aestab.obj -!endif - -!if !DEFINED (SINGLE_CIPHER) || "$(SINGLE_CIPHER)" == "SERPENT" -OBJS = $(OBJS) $(OUTDIR)\Serpent.obj -!endif - -!if !DEFINED (SINGLE_CIPHER) || "$(SINGLE_CIPHER)" == "TWOFISH" -OBJS = $(OBJS) $(OUTDIR)\Twofish.obj -!endif - - -all: env $(TARGETS) - -env: - set INCLUDE=. - set LIB=. - set LIBPATH=. - -clean: - -del /q /s $(OBJDIR) >NUL: - - -.asm{$(OUTDIR)}.obj: - cd $(OBJDIR) - $(AS) $(AFLAGS) /c "$(SRCDIR)\$<" - cd .. - -{..\..\Crypto}.asm{$(OUTDIR)}.obj: - cd $(OBJDIR) - echo $(NUL: - -dd.exe conv=notrunc bs=512 conv=notrunc if=BootSector.bin of=$(PROJ).flp 2>NUL: - cd .. - -$(OUTDIR)\Decompressor.com: $(OUTDIR)\BootCrt.obj $(OUTDIR)\Decompressor.obj - cd $(OBJDIR) - $(LD) $(LFLAGS) BootCrt.obj Decompressor.obj,Decompressor.com,Decompressor.map,$(MSVC16_ROOT)\lib\+slibce,, - -dd.exe conv=notrunc,sync bs=512 seek=1 if=Decompressor.com of=$(PROJ).flp 2>NUL: - cd .. - -$(OUTDIR)\$(PROJ).$(TARGETEXT): $(OBJS) - @echo Linking... - cd $(OBJDIR) - - echo >NUL: @<<$(PROJ).crf2 - -$(PROJ).$(TARGETEXT) -$(PROJ).map -$(MSVC16_ROOT)\lib\+ -$(LIBS) -; -<< - del $(PROJ).crf >NUL: 2>NUL: - for %F in ($(**F)) do @echo %F + >>$(PROJ).crf - type $(PROJ).crf2 >>$(PROJ).crf - - $(LD) $(LFLAGS) @$(PROJ).crf - del $(PROJ).crf $(PROJ).crf2 - - gzip.exe -c -n --best $(PROJ).$(TARGETEXT) >$(PROJ).$(TARGETEXT).gz - -dd.exe conv=notrunc,sync bs=512 seek=5 if=$(PROJ).$(TARGETEXT).gz of=$(PROJ).flp 2>NUL: - cd .. +# +# Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +PROJ = BootLoader +.SILENT: + +!ifndef MSVC16_ROOT +!error Environment variable MSVC16_ROOT must point to the installation directory of MS Visual C++ 1.5 +!endif + +ENVPATH = $(PATH) + +CC = $(MSVC16_ROOT)\bin\cl.exe +LD = $(MSVC16_ROOT)\bin\link.exe + +AFLAGS = /nologo /omf + +CFLAGS = /nologo /W3 /Fc /I "$(MSVC16_ROOT)\Include" /I"..\..\.." /I"..\..\..\Common" /I"..\..\..\Crypto" +CFLAGS = $(CFLAGS) /D __int8=char /D __int16=int /D __int32=long /D BOOL=char /D FALSE=0 /D TRUE=1 +CFLAGS = $(CFLAGS) /D LITTLE_ENDIAN=1234 /D BYTE_ORDER=1234 /D TC_WINDOWS_BOOT /D TC_MINIMIZE_CODE_SIZE /D TC_NO_COMPILER_INT64 +CFLAGS = $(CFLAGS) /D malloc=malloc_NA + +LFLAGS = /NOLOGO /ONERROR:NOEXE /NOI /BATCH + +OBJDIR = Release + +!ifdef RESCUE_DISK +OBJDIR = Rescue +CFLAGS = $(CFLAGS) /D TC_WINDOWS_BOOT_RESCUE_DISK_MODE +!endif + +!ifdef SINGLE_CIPHER +OBJDIR = $(OBJDIR)_$(SINGLE_CIPHER) +CFLAGS = $(CFLAGS) /D TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE /D TC_WINDOWS_BOOT_$(SINGLE_CIPHER) +!endif + +OUTDIR = $(OBJDIR) +TARGETEXT = com +TARGETS = $(OUTDIR)\BootDefs.i $(OUTDIR)\BootSector.bin $(OUTDIR)\Decompressor.com +CFLAGS = $(CFLAGS) /AT /Zl /f- /G3 /Oe /Os /Ob1 /OV0 /Gs /Gf /Gy /D NDEBUG +LFLAGS = $(LFLAGS) /NOD /NOE /TINY +OBJS = $(OUTDIR)\BootCrt.obj +LIBS = slibce + +!if 1 +SRCDIR = .. +!else +SRCDIR = $(MAKEDIR) +!endif + +TARGETS = $(TARGETS) $(OUTDIR)\$(PROJ).$(TARGETEXT) + +OBJS = $(OBJS) $(OUTDIR)\BootConfig.obj +OBJS = $(OBJS) $(OUTDIR)\BootConsoleIo.obj +OBJS = $(OBJS) $(OUTDIR)\BootDebug.obj +OBJS = $(OBJS) $(OUTDIR)\BootDiskIo.obj +OBJS = $(OBJS) $(OUTDIR)\BootEncryptedIo.obj +OBJS = $(OBJS) $(OUTDIR)\BootMain.obj +OBJS = $(OBJS) $(OUTDIR)\BootMemory.obj +OBJS = $(OBJS) $(OUTDIR)\IntFilter.obj +OBJS = $(OBJS) $(OUTDIR)\Platform.obj + +OBJS = $(OBJS) $(OUTDIR)\Crc.obj +OBJS = $(OBJS) $(OUTDIR)\Crypto.obj +OBJS = $(OBJS) $(OUTDIR)\Endian.obj +OBJS = $(OBJS) $(OUTDIR)\Pkcs5.obj +OBJS = $(OBJS) $(OUTDIR)\Volumes.obj +OBJS = $(OBJS) $(OUTDIR)\Xts.obj + +OBJS = $(OBJS) $(OUTDIR)\Rmd160.obj + +!if !DEFINED (SINGLE_CIPHER) +OBJS = $(OBJS) $(OUTDIR)\AesSmall.obj +!else if "$(SINGLE_CIPHER)" == "AES" +OBJS = $(OBJS) $(OUTDIR)\AesSmall_x86.obj +OBJS = $(OBJS) $(OUTDIR)\Aestab.obj +!endif + +!if !DEFINED (SINGLE_CIPHER) || "$(SINGLE_CIPHER)" == "SERPENT" +OBJS = $(OBJS) $(OUTDIR)\Serpent.obj +!endif + +!if !DEFINED (SINGLE_CIPHER) || "$(SINGLE_CIPHER)" == "TWOFISH" +OBJS = $(OBJS) $(OUTDIR)\Twofish.obj +!endif + + +all: env $(TARGETS) + +env: + set INCLUDE=. + set LIB=. + set LIBPATH=. + +clean: + -del /q /s $(OBJDIR) >NUL: + + +.asm{$(OUTDIR)}.obj: + cd $(OBJDIR) + $(AS) $(AFLAGS) /c "$(SRCDIR)\$<" + cd .. + +{..\..\Crypto}.asm{$(OUTDIR)}.obj: + cd $(OBJDIR) + echo $(NUL: + -dd.exe conv=notrunc bs=512 if=BootSector.bin of=$(PROJ).flp 2>NUL: + cd .. + +$(OUTDIR)\Decompressor.com: $(OUTDIR)\BootCrt.obj $(OUTDIR)\Decompressor.obj + cd $(OBJDIR) + $(LD) $(LFLAGS) BootCrt.obj Decompressor.obj,Decompressor.com,Decompressor.map,$(MSVC16_ROOT)\lib\+slibce,, + -dd.exe conv=notrunc,sync bs=512 seek=1 if=Decompressor.com of=$(PROJ).flp 2>NUL: + cd .. + +$(OUTDIR)\$(PROJ).$(TARGETEXT): $(OBJS) + @echo Linking... + cd $(OBJDIR) + + echo >NUL: @<<$(PROJ).crf2 + +$(PROJ).$(TARGETEXT) +$(PROJ).map +$(MSVC16_ROOT)\lib\+ +$(LIBS) +; +<< + del $(PROJ).crf >NUL: 2>NUL: + for %F in ($(**F)) do @echo %F + >>$(PROJ).crf + type $(PROJ).crf2 >>$(PROJ).crf + + $(LD) $(LFLAGS) @$(PROJ).crf + del $(PROJ).crf $(PROJ).crf2 + + gzip.exe -c -n --best $(PROJ).$(TARGETEXT) >$(PROJ).$(TARGETEXT).gz + -dd.exe conv=notrunc,sync bs=512 seek=5 if=$(PROJ).$(TARGETEXT).gz of=$(PROJ).flp 2>NUL: + cd .. diff --git a/Boot/Windows/Platform.cpp b/Boot/Windows/Platform.cpp index 11fc88e..7db0ebe 100644 --- a/Boot/Windows/Platform.cpp +++ b/Boot/Windows/Platform.cpp @@ -1,226 +1,226 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform.h" -#include "BootConsoleIo.h" - - -uint64 operator+ (const uint64 &a, const uint64 &b) -{ - int carry = 0; - uint64 r; - - r.LowPart = a.LowPart + b.LowPart; - __asm - { - jnc nocarry - mov carry, 1 - nocarry: - } - - r.HighPart = a.HighPart + b.HighPart + carry; - - return r; -} - -uint64 operator+ (const uint64 &a, uint32 b) -{ - uint64 b64; - b64.HighPart = 0; - b64.LowPart = b; - return a + b64; -} - -uint64 &operator+= (uint64 &a, const uint64 &b) -{ - return a = a + b; -} - -uint64 operator- (const uint64 &a, const uint64 &b) -{ - int carry = 0; - uint64 r; - - r.LowPart = a.LowPart - b.LowPart; - __asm - { - jnc nocarry - mov carry, 1 - nocarry: - } - - r.HighPart = a.HighPart - b.HighPart - carry; - - return r; -} - -uint64 operator- (const uint64 &a, uint32 b) -{ - uint64 b64; - b64.HighPart = 0; - b64.LowPart = b; - return a - b64; -} - -uint64 &operator-= (uint64 &a, const uint64 &b) -{ - return a = a - b; -} - -uint64 operator>> (const uint64 &a, int shiftCount) -{ - uint64 r = a; - - while (shiftCount--) - { - r.LowPart >>= 1; - - if ((byte) r.HighPart & 1) - r.LowPart |= 0x80000000UL; - - r.HighPart >>= 1; - } - - return r; -} - -uint64 operator<< (const uint64 &a, int shiftCount) -{ - uint64 r = a; - - while (shiftCount--) - r += r; - - return r; -} - -uint64 &operator++ (uint64 &a) -{ - uint64 b; - b.HighPart = 0; - b.LowPart = 1; - - return a += b; -} - -bool operator== (const uint64 &a, const uint64 &b) -{ - return a.HighPart == b.HighPart && a.LowPart == b.LowPart; -} - -bool operator> (const uint64 &a, const uint64 &b) -{ - return (a.HighPart > b.HighPart) || (a.HighPart == b.HighPart && a.LowPart > b.LowPart); -} - -bool operator< (const uint64 &a, const uint64 &b) -{ - return (a.HighPart < b.HighPart) || (a.HighPart == b.HighPart && a.LowPart < b.LowPart); -} - -bool operator>= (const uint64 &a, const uint64 &b) -{ - return a > b || a == b; -} - -bool operator<= (const uint64 &a, const uint64 &b) -{ - return a < b || a == b; -} - -bool TestInt64 () -{ - uint64 a, b, c; - a.HighPart = 0x00112233UL; - a.LowPart = 0xabcd1234UL; - - b.HighPart = 0x00ffeeddUL; - b.LowPart = 0xffffFFFFUL; - - a += b; - a -= b; - - ++a; - - b = b + (uint32) 1UL; - - c = (a - ((a + b) >> 32) - (uint32) 1UL); - if (c.HighPart != 0x112233UL || c.LowPart != 0xAABC0123UL) - return false; - - c = c << 9; - return c.HighPart == 0x22446755UL && c.LowPart == 0x78024600UL; -} - - -void CopyMemory (void *source, uint16 destSegment, uint16 destOffset, uint16 blockSize) -{ - __asm - { - push es - mov si, ss:source - mov es, ss:destSegment - mov di, ss:destOffset - mov cx, ss:blockSize - cld - rep movsb - pop es - } -} - - -void CopyMemory (uint16 sourceSegment, uint16 sourceOffset, void *destination, uint16 blockSize) -{ - __asm - { - push ds - push es - mov ax, ds - mov es, ax - mov di, ss:destination - mov si, ss:sourceOffset - mov cx, ss:blockSize - mov ds, ss:sourceSegment - cld - rep movsb - pop es - pop ds - } -} - - -void EraseMemory (void *memory, int size) -{ - memset (memory, 0, size); -} - - -uint32 GetLinearAddress (uint16 segment, uint16 offset) -{ - return (uint32 (segment) << 4) + offset; -} - - -bool RegionsIntersect (const uint64 &start1, uint32 length1, const uint64 &start2, const uint64 &end2) -{ - uint64 end1 = start1 + length1 - 1UL; - uint64 intersectEnd = (end1 <= end2) ? end1 : end2; - - uint64 intersectStart = (start1 >= start2) ? start1 : start2; - if (intersectStart > intersectEnd) - return false; - - return (intersectEnd + 1UL - intersectStart).LowPart != 0; -} - - -void ThrowFatalException (int line) -{ - PrintChar ('#'); Print (line); - while (1); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform.h" +#include "BootConsoleIo.h" + + +uint64 operator+ (const uint64 &a, const uint64 &b) +{ + int carry = 0; + uint64 r; + + r.LowPart = a.LowPart + b.LowPart; + __asm + { + jnc nocarry + mov carry, 1 + nocarry: + } + + r.HighPart = a.HighPart + b.HighPart + carry; + + return r; +} + +uint64 operator+ (const uint64 &a, uint32 b) +{ + uint64 b64; + b64.HighPart = 0; + b64.LowPart = b; + return a + b64; +} + +uint64 &operator+= (uint64 &a, const uint64 &b) +{ + return a = a + b; +} + +uint64 operator- (const uint64 &a, const uint64 &b) +{ + int carry = 0; + uint64 r; + + r.LowPart = a.LowPart - b.LowPart; + __asm + { + jnc nocarry + mov carry, 1 + nocarry: + } + + r.HighPart = a.HighPart - b.HighPart - carry; + + return r; +} + +uint64 operator- (const uint64 &a, uint32 b) +{ + uint64 b64; + b64.HighPart = 0; + b64.LowPart = b; + return a - b64; +} + +uint64 &operator-= (uint64 &a, const uint64 &b) +{ + return a = a - b; +} + +uint64 operator>> (const uint64 &a, int shiftCount) +{ + uint64 r = a; + + while (shiftCount--) + { + r.LowPart >>= 1; + + if ((byte) r.HighPart & 1) + r.LowPart |= 0x80000000UL; + + r.HighPart >>= 1; + } + + return r; +} + +uint64 operator<< (const uint64 &a, int shiftCount) +{ + uint64 r = a; + + while (shiftCount--) + r += r; + + return r; +} + +uint64 &operator++ (uint64 &a) +{ + uint64 b; + b.HighPart = 0; + b.LowPart = 1; + + return a += b; +} + +bool operator== (const uint64 &a, const uint64 &b) +{ + return a.HighPart == b.HighPart && a.LowPart == b.LowPart; +} + +bool operator> (const uint64 &a, const uint64 &b) +{ + return (a.HighPart > b.HighPart) || (a.HighPart == b.HighPart && a.LowPart > b.LowPart); +} + +bool operator< (const uint64 &a, const uint64 &b) +{ + return (a.HighPart < b.HighPart) || (a.HighPart == b.HighPart && a.LowPart < b.LowPart); +} + +bool operator>= (const uint64 &a, const uint64 &b) +{ + return a > b || a == b; +} + +bool operator<= (const uint64 &a, const uint64 &b) +{ + return a < b || a == b; +} + +bool TestInt64 () +{ + uint64 a, b, c; + a.HighPart = 0x00112233UL; + a.LowPart = 0xabcd1234UL; + + b.HighPart = 0x00ffeeddUL; + b.LowPart = 0xffffFFFFUL; + + a += b; + a -= b; + + ++a; + + b = b + (uint32) 1UL; + + c = (a - ((a + b) >> 32) - (uint32) 1UL); + if (c.HighPart != 0x112233UL || c.LowPart != 0xAABC0123UL) + return false; + + c = c << 9; + return c.HighPart == 0x22446755UL && c.LowPart == 0x78024600UL; +} + + +void CopyMemory (void *source, uint16 destSegment, uint16 destOffset, uint16 blockSize) +{ + __asm + { + push es + mov si, ss:source + mov es, ss:destSegment + mov di, ss:destOffset + mov cx, ss:blockSize + cld + rep movsb + pop es + } +} + + +void CopyMemory (uint16 sourceSegment, uint16 sourceOffset, void *destination, uint16 blockSize) +{ + __asm + { + push ds + push es + mov ax, ds + mov es, ax + mov di, ss:destination + mov si, ss:sourceOffset + mov cx, ss:blockSize + mov ds, ss:sourceSegment + cld + rep movsb + pop es + pop ds + } +} + + +void EraseMemory (void *memory, int size) +{ + memset (memory, 0, size); +} + + +uint32 GetLinearAddress (uint16 segment, uint16 offset) +{ + return (uint32 (segment) << 4) + offset; +} + + +bool RegionsIntersect (const uint64 &start1, uint32 length1, const uint64 &start2, const uint64 &end2) +{ + uint64 end1 = start1 + length1 - 1UL; + uint64 intersectEnd = (end1 <= end2) ? end1 : end2; + + uint64 intersectStart = (start1 >= start2) ? start1 : start2; + if (intersectStart > intersectEnd) + return false; + + return (intersectEnd + 1UL - intersectStart).LowPart != 0; +} + + +void ThrowFatalException (int line) +{ + PrintChar ('#'); Print (line); + while (1); +} diff --git a/Boot/Windows/Platform.h b/Boot/Windows/Platform.h index 87c316f..8d94eb1 100644 --- a/Boot/Windows/Platform.h +++ b/Boot/Windows/Platform.h @@ -1,112 +1,112 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Boot_Platform -#define TC_HEADER_Boot_Platform - -#pragma warning ( disable : 4769 ) - -#include "TCdefs.h" -#include - -typedef int bool; -#define false 0 -#define true 1 - -#define nullptr 0 -#define NULL 0 - -typedef UINT64_STRUCT uint64; - -#define array_capacity(arr) (sizeof (arr) / sizeof ((arr)[0])) - -#define TC_TO_STRING2(n) #n -#define TC_TO_STRING(n) TC_TO_STRING2(n) - - -#define TC_X86_CARRY_FLAG 0x1 - -#define TC_ASM_EMIT(A,B) __asm _emit 0x##A __asm _emit 0x##B -#define TC_ASM_EMIT3(A,B,C) __asm _emit 0x##A __asm _emit 0x##B __asm _emit 0x##C -#define TC_ASM_EMIT4(A,B,C,D) __asm _emit 0x##A __asm _emit 0x##B __asm _emit 0x##C __asm _emit 0x##D - -#define TC_ASM_MOV_EAX_DI TC_ASM_EMIT3 (66, 8B, 05) -#define TC_ASM_MOV_EBX_DI TC_ASM_EMIT3 (66, 8B, 1D) -#define TC_ASM_MOV_ECX_DI TC_ASM_EMIT3 (66, 8B, 0D) -#define TC_ASM_MOV_EDX_DI TC_ASM_EMIT3 (66, 8B, 15) - -#define TC_ASM_MOV_DI_EAX TC_ASM_EMIT3 (66, 89, 05) -#define TC_ASM_MOV_DI_EBX TC_ASM_EMIT3 (66, 89, 1D) -#define TC_ASM_MOV_DI_ECX TC_ASM_EMIT3 (66, 89, 0D) -#define TC_ASM_MOV_DI_EDX TC_ASM_EMIT3 (66, 89, 15) - - -#pragma pack(1) - -struct Registers -{ - uint16 Flags; - - union - { - uint32 EAX; - struct { uint16 AX; uint16 EAXH; }; - }; - - union - { - uint32 EBX; - struct { uint16 BX; uint16 EBXH; }; - }; - - union - { - uint32 ECX; - struct { uint16 CX; uint16 ECXH; }; - }; - - union - { - uint32 EDX; - struct { uint16 DX; uint16 EDXH; }; - }; - - uint16 DI; - uint16 SI; - uint16 DS; - uint16 ES; - uint16 SS; -}; - -#pragma pack() - - -uint64 operator+ (const uint64 &a, const uint64 &b); -uint64 operator+ (const uint64 &a, uint32 b); -uint64 &operator+= (uint64 &a, const uint64 &b); -uint64 operator- (const uint64 &a, const uint64 &b); -uint64 operator- (const uint64 &a, uint32 b); -uint64 &operator-= (uint64 &a, const uint64 &b); -uint64 operator>> (const uint64 &a, int shiftCount); -uint64 operator<< (const uint64 &a, int shiftCount); -uint64 &operator++ (uint64 &a); -bool operator== (const uint64 &a, const uint64 &b); -bool operator> (const uint64 &a, const uint64 &b); -bool operator< (const uint64 &a, const uint64 &b); -bool operator>= (const uint64 &a, const uint64 &b); -bool operator<= (const uint64 &a, const uint64 &b); - -void CopyMemory (void *source, uint16 destSegment, uint16 destOffset, uint16 blockSize); -void CopyMemory (uint16 sourceSegment, uint16 sourceOffset, void *destination, uint16 blockSize); -extern "C" void EraseMemory (void *memory, int size); -uint32 GetLinearAddress (uint16 segment, uint16 offset); -bool RegionsIntersect (const uint64 &start1, uint32 length1, const uint64 &start2, const uint64 &end2); -bool TestInt64 (); -extern "C" void ThrowFatalException (int line); - -#endif // TC_HEADER_Boot_Platform +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Boot_Platform +#define TC_HEADER_Boot_Platform + +#pragma warning (disable: 4018 4102 4704 4769) + +#include "TCdefs.h" +#include + +typedef char bool; +#define false 0 +#define true 1 + +#define nullptr 0 +#define NULL 0 + +typedef UINT64_STRUCT uint64; + +#define array_capacity(arr) (sizeof (arr) / sizeof ((arr)[0])) + +#define TC_TO_STRING2(n) #n +#define TC_TO_STRING(n) TC_TO_STRING2(n) + + +#define TC_X86_CARRY_FLAG 0x1 + +#define TC_ASM_EMIT(A,B) __asm _emit 0x##A __asm _emit 0x##B +#define TC_ASM_EMIT3(A,B,C) __asm _emit 0x##A __asm _emit 0x##B __asm _emit 0x##C +#define TC_ASM_EMIT4(A,B,C,D) __asm _emit 0x##A __asm _emit 0x##B __asm _emit 0x##C __asm _emit 0x##D + +#define TC_ASM_MOV_EAX_DI TC_ASM_EMIT3 (66, 8B, 05) +#define TC_ASM_MOV_EBX_DI TC_ASM_EMIT3 (66, 8B, 1D) +#define TC_ASM_MOV_ECX_DI TC_ASM_EMIT3 (66, 8B, 0D) +#define TC_ASM_MOV_EDX_DI TC_ASM_EMIT3 (66, 8B, 15) + +#define TC_ASM_MOV_DI_EAX TC_ASM_EMIT3 (66, 89, 05) +#define TC_ASM_MOV_DI_EBX TC_ASM_EMIT3 (66, 89, 1D) +#define TC_ASM_MOV_DI_ECX TC_ASM_EMIT3 (66, 89, 0D) +#define TC_ASM_MOV_DI_EDX TC_ASM_EMIT3 (66, 89, 15) + + +#pragma pack(1) + +struct Registers +{ + uint16 Flags; + + union + { + uint32 EAX; + struct { uint16 AX; uint16 EAXH; }; + }; + + union + { + uint32 EBX; + struct { uint16 BX; uint16 EBXH; }; + }; + + union + { + uint32 ECX; + struct { uint16 CX; uint16 ECXH; }; + }; + + union + { + uint32 EDX; + struct { uint16 DX; uint16 EDXH; }; + }; + + uint16 DI; + uint16 SI; + uint16 DS; + uint16 ES; + uint16 SS; +}; + +#pragma pack() + + +uint64 operator+ (const uint64 &a, const uint64 &b); +uint64 operator+ (const uint64 &a, uint32 b); +uint64 &operator+= (uint64 &a, const uint64 &b); +uint64 operator- (const uint64 &a, const uint64 &b); +uint64 operator- (const uint64 &a, uint32 b); +uint64 &operator-= (uint64 &a, const uint64 &b); +uint64 operator>> (const uint64 &a, int shiftCount); +uint64 operator<< (const uint64 &a, int shiftCount); +uint64 &operator++ (uint64 &a); +bool operator== (const uint64 &a, const uint64 &b); +bool operator> (const uint64 &a, const uint64 &b); +bool operator< (const uint64 &a, const uint64 &b); +bool operator>= (const uint64 &a, const uint64 &b); +bool operator<= (const uint64 &a, const uint64 &b); + +void CopyMemory (void *source, uint16 destSegment, uint16 destOffset, uint16 blockSize); +void CopyMemory (uint16 sourceSegment, uint16 sourceOffset, void *destination, uint16 blockSize); +extern "C" void EraseMemory (void *memory, int size); +uint32 GetLinearAddress (uint16 segment, uint16 offset); +bool RegionsIntersect (const uint64 &start1, uint32 length1, const uint64 &start2, const uint64 &end2); +bool TestInt64 (); +extern "C" void ThrowFatalException (int line); + +#endif // TC_HEADER_Boot_Platform diff --git a/Build/Include/Makefile.inc b/Build/Include/Makefile.inc index a2322c0..13e7109 100644 --- a/Build/Include/Makefile.inc +++ b/Build/Include/Makefile.inc @@ -1,54 +1,54 @@ -# -# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -$(NAME): $(NAME).a - -clean: - @echo Cleaning $(NAME) - rm -f $(APPNAME) $(NAME).a $(OBJS) $(OBJS:.o=.d) *.gch - -%.o: %.c - @echo Compiling $($@ - -%.txt.h: %.txt - echo Converting $($@ - -%.bmp.h: %.bmp - echo Converting $($@ - - -# Dependencies --include $(OBJS:.o=.d) - - -$(NAME).a: $(OBJS) - @echo Updating library $@ - $(AR) $(AFLAGS) -rcu $@ $(OBJS) - $(RANLIB) $@ +# +# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +$(NAME): $(NAME).a + +clean: + @echo Cleaning $(NAME) + rm -f $(APPNAME) $(NAME).a $(OBJS) $(OBJS:.o=.d) *.gch + +%.o: %.c + @echo Compiling $($@ + +%.txt.h: %.txt + echo Converting $($@ + +%.bmp.h: %.bmp + echo Converting $($@ + + +# Dependencies +-include $(OBJS:.o=.d) + + +$(NAME).a: $(OBJS) + @echo Updating library $@ + $(AR) $(AFLAGS) -rcu $@ $(OBJS) + $(RANLIB) $@ diff --git a/Build/Resources/MacOSX/Info.plist.xml b/Build/Resources/MacOSX/Info.plist.xml index 29e114f..8f7bc37 100644 --- a/Build/Resources/MacOSX/Info.plist.xml +++ b/Build/Resources/MacOSX/Info.plist.xml @@ -1,44 +1,44 @@ - - - - - CFBundleInfoDictionaryVersion - 6.0 - - CFBundleIdentifier - org.TrueCryptFoundation.TrueCrypt - - CFBundleDevelopmentRegion - English - - CFBundleExecutable - TrueCrypt - - CFBundleIconFile - TrueCrypt.icns - - CFBundleName - TrueCrypt - - CFBundlePackageType - APPL - - CFBundleSignature - TRUE - - CFBundleVersion - 0 - - CFBundleShortVersionString - _VERSION_ - - CFBundleLongVersionString - TrueCrypt _VERSION_ - - LSRequiresCarbon - - - CSResourcesFileMapped - - - + + + + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundleIdentifier + org.TrueCryptFoundation.TrueCrypt + + CFBundleDevelopmentRegion + English + + CFBundleExecutable + TrueCrypt + + CFBundleIconFile + TrueCrypt.icns + + CFBundleName + TrueCrypt + + CFBundlePackageType + APPL + + CFBundleSignature + TRUE + + CFBundleVersion + 0 + + CFBundleShortVersionString + _VERSION_ + + CFBundleLongVersionString + TrueCrypt _VERSION_ + + LSRequiresCarbon + + + CSResourcesFileMapped + + + diff --git a/Common/APIDRVR.H b/Common/APIDRVR.H index 5a4b0c0..3e490bc 100644 --- a/Common/APIDRVR.H +++ b/Common/APIDRVR.H @@ -1,295 +1,301 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#pragma once - -#include "Tcdefs.h" -#include "Boot/Windows/BootDefs.h" -#include "Common.h" -#include "Crypto.h" -#include "Wipe.h" - -#ifdef _WIN32 - -/* WARNING: Modifying the following values or their meanings can introduce incompatibility with previous versions. */ - -#define TC_IOCTL(CODE) (CTL_CODE (FILE_DEVICE_UNKNOWN, 0x800 + (CODE), METHOD_BUFFERED, FILE_ANY_ACCESS)) - -#define TC_IOCTL_GET_DRIVER_VERSION TC_IOCTL (1) -#define TC_IOCTL_GET_BOOT_LOADER_VERSION TC_IOCTL (2) -#define TC_IOCTL_MOUNT_VOLUME TC_IOCTL (3) -#define TC_IOCTL_DISMOUNT_VOLUME TC_IOCTL (4) -#define TC_IOCTL_DISMOUNT_ALL_VOLUMES TC_IOCTL (5) -#define TC_IOCTL_GET_MOUNTED_VOLUMES TC_IOCTL (6) -#define TC_IOCTL_GET_VOLUME_PROPERTIES TC_IOCTL (7) -#define TC_IOCTL_GET_DEVICE_REFCOUNT TC_IOCTL (8) -#define TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED TC_IOCTL (9) -#define TC_IOCTL_IS_ANY_VOLUME_MOUNTED TC_IOCTL (10) -#define TC_IOCTL_GET_PASSWORD_CACHE_STATUS TC_IOCTL (11) -#define TC_IOCTL_WIPE_PASSWORD_CACHE TC_IOCTL (12) -#define TC_IOCTL_OPEN_TEST TC_IOCTL (13) -#define TC_IOCTL_GET_DRIVE_PARTITION_INFO TC_IOCTL (14) -#define TC_IOCTL_GET_DRIVE_GEOMETRY TC_IOCTL (15) -#define TC_IOCTL_PROBE_REAL_DRIVE_SIZE TC_IOCTL (16) -#define TC_IOCTL_GET_RESOLVED_SYMLINK TC_IOCTL (17) -#define TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS TC_IOCTL (18) -#define TC_IOCTL_BOOT_ENCRYPTION_SETUP TC_IOCTL (19) -#define TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP TC_IOCTL (20) -#define TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT TC_IOCTL (21) -#define TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES TC_IOCTL (22) -#define TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER TC_IOCTL (23) -#define TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME TC_IOCTL (24) -#define TC_IOCTL_GET_TRAVELER_MODE_STATUS TC_IOCTL (25) -#define TC_IOCTL_SET_TRAVELER_MODE_STATUS TC_IOCTL (26) -#define TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING TC_IOCTL (27) -#define TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG TC_IOCTL (28) -#define TC_IOCTL_DISK_IS_WRITABLE TC_IOCTL (29) -#define TC_IOCTL_START_DECOY_SYSTEM_WIPE TC_IOCTL (30) -#define TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE TC_IOCTL (31) -#define TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS TC_IOCTL (32) -#define TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT TC_IOCTL (33) -#define TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR TC_IOCTL (34) - -// Legacy IOCTLs used before version 5.0 -#define TC_IOCTL_LEGACY_GET_DRIVER_VERSION 466968 -#define TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES 466948 - - -/* Start of driver interface structures, the size of these structures may - change between versions; so make sure you first send DRIVER_VERSION to - check that it's the correct device driver */ - -#pragma pack (push) -#pragma pack(1) - -typedef struct -{ - int nReturnCode; /* Return code back from driver */ - BOOL FilesystemDirty; - BOOL VolumeMountedReadOnlyAfterAccessDenied; - BOOL VolumeMountedReadOnlyAfterDeviceWriteProtected; - - short wszVolume[TC_MAX_PATH]; /* Volume to be mounted */ - Password VolumePassword; /* User password */ - BOOL bCache; /* Cache passwords in driver */ - int nDosDriveNo; /* Drive number to mount */ - int BytesPerSector; - BOOL bMountReadOnly; /* Mount volume in read-only mode */ - BOOL bMountRemovable; /* Mount volume as removable media */ - BOOL bExclusiveAccess; /* Open host file/device in exclusive access mode */ - BOOL bMountManager; /* Announce volume to mount manager */ - BOOL bPreserveTimestamp; /* Preserve file container timestamp */ - BOOL bPartitionInInactiveSysEncScope; /* If TRUE, we are to attempt to mount a partition located on an encrypted system drive without pre-boot authentication. */ - int nPartitionInInactiveSysEncScopeDriveNo; /* If bPartitionInInactiveSysEncScope is TRUE, this contains the drive number of the system drive on which the partition is located. */ - // Hidden volume protection - BOOL bProtectHiddenVolume; /* TRUE if the user wants the hidden volume within this volume to be protected against being overwritten (damaged) */ - Password ProtectedHidVolPassword; /* Password to the hidden volume to be protected against overwriting */ - BOOL UseBackupHeader; - BOOL RecoveryMode; -} MOUNT_STRUCT; - -typedef struct -{ - int nDosDriveNo; /* Drive letter to unmount */ - BOOL ignoreOpenFiles; - BOOL HiddenVolumeProtectionTriggered; - int nReturnCode; /* Return code back from driver */ -} UNMOUNT_STRUCT; - -typedef struct -{ - unsigned __int32 ulMountedDrives; /* Bitfield of all mounted drive letters */ - short wszVolume[26][TC_MAX_PATH]; /* Volume names of mounted volumes */ - unsigned __int64 diskLength[26]; - int ea[26]; - int volumeType[26]; /* Volume type (e.g. PROP_VOL_TYPE_OUTER, PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, etc.) */ -} MOUNT_LIST_STRUCT; - -typedef struct -{ - int driveNo; - int uniqueId; - short wszVolume[TC_MAX_PATH]; - unsigned __int64 diskLength; - int ea; - int mode; - int pkcs5; - int pkcs5Iterations; - BOOL hiddenVolume; - BOOL readOnly; - BOOL removable; -#if 0 - unsigned __int64 volumeCreationTime; // Deprecated in v6.0 - unsigned __int64 headerCreationTime; // Deprecated in v6.0 -#endif - uint32 volumeHeaderFlags; - unsigned __int64 totalBytesRead; - unsigned __int64 totalBytesWritten; - int hiddenVolProtection; /* Hidden volume protection status (e.g. HIDVOL_PROT_STATUS_NONE, HIDVOL_PROT_STATUS_ACTIVE, etc.) */ - int volFormatVersion; -} VOLUME_PROPERTIES_STRUCT; - -typedef struct -{ - WCHAR symLinkName[TC_MAX_PATH]; - WCHAR targetName[TC_MAX_PATH]; -} RESOLVE_SYMLINK_STRUCT; - -typedef struct -{ - WCHAR deviceName[TC_MAX_PATH]; - PARTITION_INFORMATION partInfo; - BOOL IsGPT; - BOOL IsDynamic; -} -DISK_PARTITION_INFO_STRUCT; - -typedef struct -{ - WCHAR deviceName[TC_MAX_PATH]; - DISK_GEOMETRY diskGeometry; -} -DISK_GEOMETRY_STRUCT; - -typedef struct -{ - WCHAR DeviceName[TC_MAX_PATH]; - LARGE_INTEGER RealDriveSize; - BOOL TimeOut; -} ProbeRealDriveSizeRequest; - -typedef struct -{ - short wszFileName[TC_MAX_PATH]; // Volume to be "open tested" - BOOL bDetectTCBootLoader; // Whether the driver is to determine if the first sector contains a portion of the TrueCrypt Boot Loader - BOOL TCBootLoaderDetected; - BOOL DetectFilesystem; - BOOL FilesystemDetected; -} OPEN_TEST_STRUCT; - - -typedef enum -{ - SetupNone = 0, - SetupEncryption, - SetupDecryption -} BootEncryptionSetupMode; - - -typedef struct -{ - // New fields must be added at the end of the structure to maintain compatibility with previous versions - BOOL DeviceFilterActive; - - uint16 BootLoaderVersion; - - BOOL DriveMounted; - BOOL VolumeHeaderPresent; - BOOL DriveEncrypted; - - LARGE_INTEGER BootDriveLength; - - int64 ConfiguredEncryptedAreaStart; - int64 ConfiguredEncryptedAreaEnd; - int64 EncryptedAreaStart; - int64 EncryptedAreaEnd; - - uint32 VolumeHeaderSaltCrc32; - - BOOL SetupInProgress; - BootEncryptionSetupMode SetupMode; - BOOL TransformWaitingForIdle; - - uint32 HibernationPreventionCount; - - BOOL HiddenSystem; - int64 HiddenSystemPartitionStart; - - // Number of times the filter driver answered that an unencrypted volume - // is read-only (or mounted an outer/normal TrueCrypt volume as read only) - uint32 HiddenSysLeakProtectionCount; - -} BootEncryptionStatus; - - -typedef struct -{ - BootEncryptionSetupMode SetupMode; - WipeAlgorithmId WipeAlgorithm; - BOOL ZeroUnreadableSectors; - BOOL DiscardUnreadableEncryptedSectors; -} BootEncryptionSetupRequest; - - -typedef struct -{ - Password VolumePassword; -} ReopenBootVolumeHeaderRequest; - - -typedef struct -{ - char BootEncryptionAlgorithmName[256]; -} GetBootEncryptionAlgorithmNameRequest; - -typedef struct -{ - wchar_t DevicePath[TC_MAX_PATH]; - byte Configuration; - BOOL DriveIsDynamic; - uint16 BootLoaderVersion; - byte UserConfiguration; - char CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; -} GetSystemDriveConfigurationRequest; - -typedef struct -{ - WipeAlgorithmId WipeAlgorithm; - byte WipeKey[MASTER_KEYDATA_SIZE]; -} WipeDecoySystemRequest; - -typedef struct -{ - BOOL WipeInProgress; - WipeAlgorithmId WipeAlgorithm; - int64 WipedAreaEnd; -} DecoySystemWipeStatus; - -typedef struct -{ - LARGE_INTEGER Offset; - byte Data[SECTOR_SIZE]; -} WriteBootDriveSectorRequest; - -#pragma pack (pop) - -#ifdef NT4_DRIVER -#define DRIVER_STR WIDE -#else -#define DRIVER_STR -#endif - -/* NT only */ - -#define TC_UNIQUE_ID_PREFIX "TrueCryptVolume" -#define TC_MOUNT_PREFIX L"\\Device\\TrueCryptVolume" - -#define NT_MOUNT_PREFIX DRIVER_STR("\\Device\\TrueCryptVolume") -#define NT_ROOT_PREFIX DRIVER_STR("\\Device\\TrueCrypt") -#define DOS_MOUNT_PREFIX DRIVER_STR("\\DosDevices\\") -#define DOS_ROOT_PREFIX DRIVER_STR("\\DosDevices\\TrueCrypt") -#define WIN32_ROOT_PREFIX DRIVER_STR("\\\\.\\TrueCrypt") - -#define TC_DRIVER_CONFIG_REG_VALUE_NAME DRIVER_STR("TrueCryptConfig") - -#define TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD 0x1 - -#endif /* _WIN32 */ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#pragma once + +#include "Tcdefs.h" +#include "Boot/Windows/BootDefs.h" +#include "Common.h" +#include "Crypto.h" +#include "Wipe.h" + +#ifdef _WIN32 + +/* WARNING: Modifying the following values or their meanings can introduce incompatibility with previous versions. */ + +#define TC_IOCTL(CODE) (CTL_CODE (FILE_DEVICE_UNKNOWN, 0x800 + (CODE), METHOD_BUFFERED, FILE_ANY_ACCESS)) + +#define TC_IOCTL_GET_DRIVER_VERSION TC_IOCTL (1) +#define TC_IOCTL_GET_BOOT_LOADER_VERSION TC_IOCTL (2) +#define TC_IOCTL_MOUNT_VOLUME TC_IOCTL (3) +#define TC_IOCTL_DISMOUNT_VOLUME TC_IOCTL (4) +#define TC_IOCTL_DISMOUNT_ALL_VOLUMES TC_IOCTL (5) +#define TC_IOCTL_GET_MOUNTED_VOLUMES TC_IOCTL (6) +#define TC_IOCTL_GET_VOLUME_PROPERTIES TC_IOCTL (7) +#define TC_IOCTL_GET_DEVICE_REFCOUNT TC_IOCTL (8) +#define TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED TC_IOCTL (9) +#define TC_IOCTL_IS_ANY_VOLUME_MOUNTED TC_IOCTL (10) +#define TC_IOCTL_GET_PASSWORD_CACHE_STATUS TC_IOCTL (11) +#define TC_IOCTL_WIPE_PASSWORD_CACHE TC_IOCTL (12) +#define TC_IOCTL_OPEN_TEST TC_IOCTL (13) +#define TC_IOCTL_GET_DRIVE_PARTITION_INFO TC_IOCTL (14) +#define TC_IOCTL_GET_DRIVE_GEOMETRY TC_IOCTL (15) +#define TC_IOCTL_PROBE_REAL_DRIVE_SIZE TC_IOCTL (16) +#define TC_IOCTL_GET_RESOLVED_SYMLINK TC_IOCTL (17) +#define TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS TC_IOCTL (18) +#define TC_IOCTL_BOOT_ENCRYPTION_SETUP TC_IOCTL (19) +#define TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP TC_IOCTL (20) +#define TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT TC_IOCTL (21) +#define TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES TC_IOCTL (22) +#define TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER TC_IOCTL (23) +#define TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME TC_IOCTL (24) +#define TC_IOCTL_GET_PORTABLE_MODE_STATUS TC_IOCTL (25) +#define TC_IOCTL_SET_PORTABLE_MODE_STATUS TC_IOCTL (26) +#define TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING TC_IOCTL (27) +#define TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG TC_IOCTL (28) +#define TC_IOCTL_DISK_IS_WRITABLE TC_IOCTL (29) +#define TC_IOCTL_START_DECOY_SYSTEM_WIPE TC_IOCTL (30) +#define TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE TC_IOCTL (31) +#define TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS TC_IOCTL (32) +#define TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT TC_IOCTL (33) +#define TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR TC_IOCTL (34) +#define TC_IOCTL_IS_SYSTEM_FAVORITE_VOLUME_DIRTY TC_IOCTL (35) +#define TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY TC_IOCTL (36) + +// Legacy IOCTLs used before version 5.0 +#define TC_IOCTL_LEGACY_GET_DRIVER_VERSION 466968 +#define TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES 466948 + + +/* Start of driver interface structures, the size of these structures may + change between versions; so make sure you first send DRIVER_VERSION to + check that it's the correct device driver */ + +#pragma pack (push) +#pragma pack(1) + +typedef struct +{ + int nReturnCode; /* Return code back from driver */ + BOOL FilesystemDirty; + BOOL VolumeMountedReadOnlyAfterAccessDenied; + BOOL VolumeMountedReadOnlyAfterDeviceWriteProtected; + + short wszVolume[TC_MAX_PATH]; /* Volume to be mounted */ + Password VolumePassword; /* User password */ + BOOL bCache; /* Cache passwords in driver */ + int nDosDriveNo; /* Drive number to mount */ + int BytesPerSector; + BOOL bMountReadOnly; /* Mount volume in read-only mode */ + BOOL bMountRemovable; /* Mount volume as removable media */ + BOOL bExclusiveAccess; /* Open host file/device in exclusive access mode */ + BOOL bMountManager; /* Announce volume to mount manager */ + BOOL bPreserveTimestamp; /* Preserve file container timestamp */ + BOOL bPartitionInInactiveSysEncScope; /* If TRUE, we are to attempt to mount a partition located on an encrypted system drive without pre-boot authentication. */ + int nPartitionInInactiveSysEncScopeDriveNo; /* If bPartitionInInactiveSysEncScope is TRUE, this contains the drive number of the system drive on which the partition is located. */ + BOOL SystemFavorite; + // Hidden volume protection + BOOL bProtectHiddenVolume; /* TRUE if the user wants the hidden volume within this volume to be protected against being overwritten (damaged) */ + Password ProtectedHidVolPassword; /* Password to the hidden volume to be protected against overwriting */ + BOOL UseBackupHeader; + BOOL RecoveryMode; +} MOUNT_STRUCT; + +typedef struct +{ + int nDosDriveNo; /* Drive letter to unmount */ + BOOL ignoreOpenFiles; + BOOL HiddenVolumeProtectionTriggered; + int nReturnCode; /* Return code back from driver */ +} UNMOUNT_STRUCT; + +typedef struct +{ + unsigned __int32 ulMountedDrives; /* Bitfield of all mounted drive letters */ + short wszVolume[26][TC_MAX_PATH]; /* Volume names of mounted volumes */ + unsigned __int64 diskLength[26]; + int ea[26]; + int volumeType[26]; /* Volume type (e.g. PROP_VOL_TYPE_OUTER, PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, etc.) */ +} MOUNT_LIST_STRUCT; + +typedef struct +{ + int driveNo; + int uniqueId; + short wszVolume[TC_MAX_PATH]; + unsigned __int64 diskLength; + int ea; + int mode; + int pkcs5; + int pkcs5Iterations; + BOOL hiddenVolume; + BOOL readOnly; + BOOL removable; + BOOL partitionInInactiveSysEncScope; +#if 0 + unsigned __int64 volumeCreationTime; // Deprecated in v6.0 + unsigned __int64 headerCreationTime; // Deprecated in v6.0 +#endif + uint32 volumeHeaderFlags; + unsigned __int64 totalBytesRead; + unsigned __int64 totalBytesWritten; + int hiddenVolProtection; /* Hidden volume protection status (e.g. HIDVOL_PROT_STATUS_NONE, HIDVOL_PROT_STATUS_ACTIVE, etc.) */ + int volFormatVersion; +} VOLUME_PROPERTIES_STRUCT; + +typedef struct +{ + WCHAR symLinkName[TC_MAX_PATH]; + WCHAR targetName[TC_MAX_PATH]; +} RESOLVE_SYMLINK_STRUCT; + +typedef struct +{ + WCHAR deviceName[TC_MAX_PATH]; + PARTITION_INFORMATION partInfo; + BOOL IsGPT; + BOOL IsDynamic; +} +DISK_PARTITION_INFO_STRUCT; + +typedef struct +{ + WCHAR deviceName[TC_MAX_PATH]; + DISK_GEOMETRY diskGeometry; +} +DISK_GEOMETRY_STRUCT; + +typedef struct +{ + WCHAR DeviceName[TC_MAX_PATH]; + LARGE_INTEGER RealDriveSize; + BOOL TimeOut; +} ProbeRealDriveSizeRequest; + +typedef struct +{ + short wszFileName[TC_MAX_PATH]; // Volume to be "open tested" + BOOL bDetectTCBootLoader; // Whether the driver is to determine if the first sector contains a portion of the TrueCrypt Boot Loader + BOOL TCBootLoaderDetected; + BOOL DetectFilesystem; + BOOL FilesystemDetected; +} OPEN_TEST_STRUCT; + + +typedef enum +{ + SetupNone = 0, + SetupEncryption, + SetupDecryption +} BootEncryptionSetupMode; + + +typedef struct +{ + // New fields must be added at the end of the structure to maintain compatibility with previous versions + BOOL DeviceFilterActive; + + uint16 BootLoaderVersion; + + BOOL DriveMounted; + BOOL VolumeHeaderPresent; + BOOL DriveEncrypted; + + LARGE_INTEGER BootDriveLength; + + int64 ConfiguredEncryptedAreaStart; + int64 ConfiguredEncryptedAreaEnd; + int64 EncryptedAreaStart; + int64 EncryptedAreaEnd; + + uint32 VolumeHeaderSaltCrc32; + + BOOL SetupInProgress; + BootEncryptionSetupMode SetupMode; + BOOL TransformWaitingForIdle; + + uint32 HibernationPreventionCount; + + BOOL HiddenSystem; + int64 HiddenSystemPartitionStart; + + // Number of times the filter driver answered that an unencrypted volume + // is read-only (or mounted an outer/normal TrueCrypt volume as read only) + uint32 HiddenSysLeakProtectionCount; + +} BootEncryptionStatus; + + +typedef struct +{ + BootEncryptionSetupMode SetupMode; + WipeAlgorithmId WipeAlgorithm; + BOOL ZeroUnreadableSectors; + BOOL DiscardUnreadableEncryptedSectors; +} BootEncryptionSetupRequest; + + +typedef struct +{ + Password VolumePassword; +} ReopenBootVolumeHeaderRequest; + + +typedef struct +{ + char BootEncryptionAlgorithmName[256]; +} GetBootEncryptionAlgorithmNameRequest; + +typedef struct +{ + wchar_t DevicePath[TC_MAX_PATH]; + byte Configuration; + BOOL DriveIsDynamic; + uint16 BootLoaderVersion; + byte UserConfiguration; + char CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; +} GetSystemDriveConfigurationRequest; + +typedef struct +{ + WipeAlgorithmId WipeAlgorithm; + byte WipeKey[MASTER_KEYDATA_SIZE]; +} WipeDecoySystemRequest; + +typedef struct +{ + BOOL WipeInProgress; + WipeAlgorithmId WipeAlgorithm; + int64 WipedAreaEnd; +} DecoySystemWipeStatus; + +typedef struct +{ + LARGE_INTEGER Offset; + byte Data[SECTOR_SIZE]; +} WriteBootDriveSectorRequest; + +#pragma pack (pop) + +#ifdef NT4_DRIVER +#define DRIVER_STR WIDE +#else +#define DRIVER_STR +#endif + +/* NT only */ + +#define TC_UNIQUE_ID_PREFIX "TrueCryptVolume" +#define TC_MOUNT_PREFIX L"\\Device\\TrueCryptVolume" + +#define NT_MOUNT_PREFIX DRIVER_STR("\\Device\\TrueCryptVolume") +#define NT_ROOT_PREFIX DRIVER_STR("\\Device\\TrueCrypt") +#define DOS_MOUNT_PREFIX DRIVER_STR("\\DosDevices\\") +#define DOS_ROOT_PREFIX DRIVER_STR("\\DosDevices\\TrueCrypt") +#define WIN32_ROOT_PREFIX DRIVER_STR("\\\\.\\TrueCrypt") + +#define TC_DRIVER_CONFIG_REG_VALUE_NAME DRIVER_STR("TrueCryptConfig") + +#define TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD 0x1 +#define TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES 0x2 +#define TC_DRIVER_CONFIG_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS 0x4 + +#endif /* _WIN32 */ diff --git a/Common/BaseCom.cpp b/Common/BaseCom.cpp index 930d71b..6d8a0ea 100644 --- a/Common/BaseCom.cpp +++ b/Common/BaseCom.cpp @@ -1,189 +1,236 @@ -/* - Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include "BaseCom.h" -#include "BootEncryption.h" -#include "Dlgcode.h" -#include "Registry.h" - -using namespace TrueCrypt; - -HRESULT CreateElevatedComObject (HWND hwnd, REFGUID guid, REFIID iid, void **ppv) -{ - WCHAR monikerName[1024]; - WCHAR clsid[1024]; - BIND_OPTS3 bo; - - StringFromGUID2 (guid, clsid, sizeof (clsid) / 2); - swprintf_s (monikerName, sizeof (monikerName) / 2, L"Elevation:Administrator!new:%s", clsid); - - memset (&bo, 0, sizeof (bo)); - bo.cbStruct = sizeof (bo); - bo.hwnd = hwnd; - bo.dwClassContext = CLSCTX_LOCAL_SERVER; - - // Prevent the GUI from being half-rendered when the UAC prompt "freezes" it - MSG paintMsg; - int MsgCounter = 5000; // Avoid endless processing of paint messages - while (PeekMessage (&paintMsg, hwnd, 0, 0, PM_REMOVE | PM_QS_PAINT) != 0 && --MsgCounter > 0) - { - DispatchMessage (&paintMsg); - } - - return CoGetObject (monikerName, &bo, iid, ppv); -} - - -BOOL ComGetInstanceBase (HWND hWnd, REFCLSID clsid, REFIID iid, void **tcServer) -{ - BOOL r; - - if (IsUacSupported ()) - r = CreateElevatedComObject (hWnd, clsid, iid, tcServer) == S_OK; - else - r = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER, iid, tcServer) == S_OK; - - if (!r) - Error ("UAC_INIT_ERROR"); - - return r; -} - - -DWORD BaseCom::CallDriver (DWORD ioctl, BSTR input, BSTR *output) -{ - try - { - BootEncryption bootEnc (NULL); - bootEnc.CallDriver (ioctl, - (BYTE *) input, !(BYTE *) input ? 0 : ((DWORD *) ((BYTE *) input))[-1], - (BYTE *) *output, !(BYTE *) *output ? 0 : ((DWORD *) ((BYTE *) *output))[-1]); - } - catch (SystemException &) - { - return GetLastError(); - } - catch (Exception &e) - { - e.Show (NULL); - return ERROR_EXCEPTION_IN_SERVICE; - } - catch (...) - { - return ERROR_EXCEPTION_IN_SERVICE; - } - - return ERROR_SUCCESS; -} - - -BOOL BaseCom::IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) -{ - return ::IsPagingFileActive (checkNonWindowsPartitionsOnly); -} - - -DWORD BaseCom::ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone) -{ - USES_CONVERSION; - - try - { - auto_ptr file (device ? new Device (string (CW2A (filePath)), !write) : new File (string (CW2A (filePath)), !write)); - file->SeekAt (offset); - - if (write) - { - file->Write ((BYTE *) *bufferBstr, size); - *sizeDone = size; - } - else - { - *sizeDone = file->Read ((BYTE *) *bufferBstr, size); - } - } - catch (SystemException &) - { - return GetLastError(); - } - catch (Exception &e) - { - e.Show (NULL); - return ERROR_EXCEPTION_IN_SERVICE; - } - catch (...) - { - return ERROR_EXCEPTION_IN_SERVICE; - } - - return ERROR_SUCCESS; -} - - -DWORD BaseCom::RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass) -{ - try - { - BootEncryption bootEnc (NULL); - bootEnc.RegisterFilterDriver (registerDriver ? true : false, volumeClass ? true : false); - } - catch (SystemException &) - { - return GetLastError(); - } - catch (Exception &e) - { - e.Show (NULL); - return ERROR_EXCEPTION_IN_SERVICE; - } - catch (...) - { - return ERROR_EXCEPTION_IN_SERVICE; - } - - return ERROR_SUCCESS; -} - - -DWORD BaseCom::SetDriverServiceStartType (DWORD startType) -{ - try - { - BootEncryption bootEnc (NULL); - bootEnc.SetDriverServiceStartType (startType); - } - catch (SystemException &) - { - return GetLastError(); - } - catch (Exception &e) - { - e.Show (NULL); - return ERROR_EXCEPTION_IN_SERVICE; - } - catch (...) - { - return ERROR_EXCEPTION_IN_SERVICE; - } - - return ERROR_SUCCESS; -} - - -DWORD BaseCom::WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value) -{ - USES_CONVERSION; - if (!::WriteLocalMachineRegistryDword (CW2A (keyPath), CW2A (valueName), value)) - return GetLastError(); - - return ERROR_SUCCESS; -} +/* + Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include "BaseCom.h" +#include "BootEncryption.h" +#include "Dlgcode.h" +#include "Registry.h" + +using namespace TrueCrypt; + +HRESULT CreateElevatedComObject (HWND hwnd, REFGUID guid, REFIID iid, void **ppv) +{ + WCHAR monikerName[1024]; + WCHAR clsid[1024]; + BIND_OPTS3 bo; + + StringFromGUID2 (guid, clsid, sizeof (clsid) / 2); + swprintf_s (monikerName, sizeof (monikerName) / 2, L"Elevation:Administrator!new:%s", clsid); + + memset (&bo, 0, sizeof (bo)); + bo.cbStruct = sizeof (bo); + bo.hwnd = hwnd; + bo.dwClassContext = CLSCTX_LOCAL_SERVER; + + // Prevent the GUI from being half-rendered when the UAC prompt "freezes" it + MSG paintMsg; + int MsgCounter = 5000; // Avoid endless processing of paint messages + while (PeekMessage (&paintMsg, hwnd, 0, 0, PM_REMOVE | PM_QS_PAINT) != 0 && --MsgCounter > 0) + { + DispatchMessage (&paintMsg); + } + + return CoGetObject (monikerName, &bo, iid, ppv); +} + + +BOOL ComGetInstanceBase (HWND hWnd, REFCLSID clsid, REFIID iid, void **tcServer) +{ + BOOL r; + + if (IsUacSupported ()) + r = CreateElevatedComObject (hWnd, clsid, iid, tcServer) == S_OK; + else + r = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER, iid, tcServer) == S_OK; + + if (!r) + Error ("UAC_INIT_ERROR"); + + return r; +} + + +DWORD BaseCom::CallDriver (DWORD ioctl, BSTR input, BSTR *output) +{ + try + { + BootEncryption bootEnc (NULL); + bootEnc.CallDriver (ioctl, + (BYTE *) input, !(BYTE *) input ? 0 : ((DWORD *) ((BYTE *) input))[-1], + (BYTE *) *output, !(BYTE *) *output ? 0 : ((DWORD *) ((BYTE *) *output))[-1]); + } + catch (SystemException &) + { + return GetLastError(); + } + catch (Exception &e) + { + e.Show (NULL); + return ERROR_EXCEPTION_IN_SERVICE; + } + catch (...) + { + return ERROR_EXCEPTION_IN_SERVICE; + } + + return ERROR_SUCCESS; +} + + +DWORD BaseCom::CopyFile (BSTR sourceFile, BSTR destinationFile) +{ + USES_CONVERSION; + + if (!::CopyFile (CW2A (sourceFile), CW2A (destinationFile), FALSE)) + return GetLastError(); + + return ERROR_SUCCESS; +} + + +DWORD BaseCom::DeleteFile (BSTR file) +{ + USES_CONVERSION; + + if (!::DeleteFile (CW2A (file))) + return GetLastError(); + + return ERROR_SUCCESS; +} + + +BOOL BaseCom::IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) +{ + return ::IsPagingFileActive (checkNonWindowsPartitionsOnly); +} + + +DWORD BaseCom::ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone) +{ + USES_CONVERSION; + + try + { + auto_ptr file (device ? new Device (string (CW2A (filePath)), !write) : new File (string (CW2A (filePath)), !write)); + file->SeekAt (offset); + + if (write) + { + file->Write ((BYTE *) *bufferBstr, size); + *sizeDone = size; + } + else + { + *sizeDone = file->Read ((BYTE *) *bufferBstr, size); + } + } + catch (SystemException &) + { + return GetLastError(); + } + catch (Exception &e) + { + e.Show (NULL); + return ERROR_EXCEPTION_IN_SERVICE; + } + catch (...) + { + return ERROR_EXCEPTION_IN_SERVICE; + } + + return ERROR_SUCCESS; +} + + +DWORD BaseCom::RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass) +{ + try + { + BootEncryption bootEnc (NULL); + bootEnc.RegisterFilterDriver (registerDriver ? true : false, volumeClass ? true : false); + } + catch (SystemException &) + { + return GetLastError(); + } + catch (Exception &e) + { + e.Show (NULL); + return ERROR_EXCEPTION_IN_SERVICE; + } + catch (...) + { + return ERROR_EXCEPTION_IN_SERVICE; + } + + return ERROR_SUCCESS; +} + + +DWORD BaseCom::RegisterSystemFavoritesService (BOOL registerService) +{ + try + { + BootEncryption bootEnc (NULL); + bootEnc.RegisterSystemFavoritesService (registerService); + } + catch (SystemException &) + { + return GetLastError(); + } + catch (Exception &e) + { + e.Show (NULL); + return ERROR_EXCEPTION_IN_SERVICE; + } + catch (...) + { + return ERROR_EXCEPTION_IN_SERVICE; + } + + return ERROR_SUCCESS; +} + + +DWORD BaseCom::SetDriverServiceStartType (DWORD startType) +{ + try + { + BootEncryption bootEnc (NULL); + bootEnc.SetDriverServiceStartType (startType); + } + catch (SystemException &) + { + return GetLastError(); + } + catch (Exception &e) + { + e.Show (NULL); + return ERROR_EXCEPTION_IN_SERVICE; + } + catch (...) + { + return ERROR_EXCEPTION_IN_SERVICE; + } + + return ERROR_SUCCESS; +} + + +DWORD BaseCom::WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value) +{ + USES_CONVERSION; + if (!::WriteLocalMachineRegistryDword (CW2A (keyPath), CW2A (valueName), value)) + return GetLastError(); + + return ERROR_SUCCESS; +} diff --git a/Common/BaseCom.h b/Common/BaseCom.h index 6518863..161f2f5 100644 --- a/Common/BaseCom.h +++ b/Common/BaseCom.h @@ -1,112 +1,115 @@ -/* - Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_BASE_COM -#define TC_HEADER_BASE_COM - -#include - -template -class TrueCryptFactory : public IClassFactory -{ - -public: - TrueCryptFactory (DWORD messageThreadId) : - RefCount (1), ServerLockCount (0), MessageThreadId (messageThreadId) { } - - ~TrueCryptFactory () { } - - virtual ULONG STDMETHODCALLTYPE AddRef () - { - return InterlockedIncrement (&RefCount) - 1; - } - - virtual ULONG STDMETHODCALLTYPE Release () - { - ULONG r = InterlockedDecrement (&RefCount) + 1; - - if (r == 0) - delete this; - - return r; - } - - virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) - { - if (riid == IID_IUnknown || riid == IID_IClassFactory) - *ppvObject = this; - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - AddRef (); - return S_OK; - } - - virtual HRESULT STDMETHODCALLTYPE CreateInstance (IUnknown *pUnkOuter, REFIID riid, void **ppvObject) - { - if (pUnkOuter != NULL) - return CLASS_E_NOAGGREGATION; - - TClass *tc = new TClass (MessageThreadId); - if (tc == NULL) - return E_OUTOFMEMORY; - - HRESULT hr = tc->QueryInterface (riid, ppvObject); - - if (hr) - delete tc; - - return hr; - } - - virtual HRESULT STDMETHODCALLTYPE LockServer (BOOL fLock) - { - if (fLock) - { - InterlockedIncrement (&ServerLockCount); - } - else - { - if (!InterlockedDecrement (&ServerLockCount)) - PostThreadMessage (MessageThreadId, WM_APP, 0, 0); - } - - return S_OK; - } - - virtual bool IsServerLocked () - { - return ServerLockCount > 0; - } - -protected: - DWORD MessageThreadId; - LONG RefCount; - LONG ServerLockCount; -}; - - -class BaseCom -{ -public: - static DWORD CallDriver (DWORD ioctl, BSTR input, BSTR *output); - static BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); - static DWORD ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone); - static DWORD RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass); - static DWORD SetDriverServiceStartType (DWORD startType); - static DWORD WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value); -}; - - -BOOL ComGetInstanceBase (HWND hWnd, REFCLSID clsid, REFIID iid, void **tcServer); -HRESULT CreateElevatedComObject (HWND hwnd, REFGUID guid, REFIID iid, void **ppv); - -#endif // TC_HEADER_BASE_COM +/* + Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_BASE_COM +#define TC_HEADER_BASE_COM + +#include + +template +class TrueCryptFactory : public IClassFactory +{ + +public: + TrueCryptFactory (DWORD messageThreadId) : + RefCount (1), ServerLockCount (0), MessageThreadId (messageThreadId) { } + + ~TrueCryptFactory () { } + + virtual ULONG STDMETHODCALLTYPE AddRef () + { + return InterlockedIncrement (&RefCount) - 1; + } + + virtual ULONG STDMETHODCALLTYPE Release () + { + ULONG r = InterlockedDecrement (&RefCount) + 1; + + if (r == 0) + delete this; + + return r; + } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) + { + if (riid == IID_IUnknown || riid == IID_IClassFactory) + *ppvObject = this; + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + AddRef (); + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE CreateInstance (IUnknown *pUnkOuter, REFIID riid, void **ppvObject) + { + if (pUnkOuter != NULL) + return CLASS_E_NOAGGREGATION; + + TClass *tc = new TClass (MessageThreadId); + if (tc == NULL) + return E_OUTOFMEMORY; + + HRESULT hr = tc->QueryInterface (riid, ppvObject); + + if (hr) + delete tc; + + return hr; + } + + virtual HRESULT STDMETHODCALLTYPE LockServer (BOOL fLock) + { + if (fLock) + { + InterlockedIncrement (&ServerLockCount); + } + else + { + if (!InterlockedDecrement (&ServerLockCount)) + PostThreadMessage (MessageThreadId, WM_APP, 0, 0); + } + + return S_OK; + } + + virtual bool IsServerLocked () + { + return ServerLockCount > 0; + } + +protected: + DWORD MessageThreadId; + LONG RefCount; + LONG ServerLockCount; +}; + + +class BaseCom +{ +public: + static DWORD CallDriver (DWORD ioctl, BSTR input, BSTR *output); + static DWORD CopyFile (BSTR sourceFile, BSTR destinationFile); + static DWORD DeleteFile (BSTR file); + static BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); + static DWORD ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone); + static DWORD RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass); + static DWORD RegisterSystemFavoritesService (BOOL registerService); + static DWORD SetDriverServiceStartType (DWORD startType); + static DWORD WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value); +}; + + +BOOL ComGetInstanceBase (HWND hWnd, REFCLSID clsid, REFIID iid, void **tcServer); +HRESULT CreateElevatedComObject (HWND hwnd, REFGUID guid, REFIID iid, void **ppv); + +#endif // TC_HEADER_BASE_COM diff --git a/Common/BootEncryption.cpp b/Common/BootEncryption.cpp index 504ac10..477e80f 100644 --- a/Common/BootEncryption.cpp +++ b/Common/BootEncryption.cpp @@ -1,2127 +1,2327 @@ -/* -Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - -Governed by the TrueCrypt License 2.7 the full text of which is contained -in the file License.txt included in TrueCrypt binary and source code -distribution packages. -*/ - -#include "Tcdefs.h" -#include "Platform/Finally.h" -#include "Platform/ForEach.h" -#include -#include -#include -#include -#include -#include "BootEncryption.h" -#include "Boot/Windows/BootCommon.h" -#include "Common/Resource.h" -#include "Crc.h" -#include "Crypto.h" -#include "Dlgcode.h" -#include "Endian.h" -#include "Language.h" -#include "Random.h" -#include "Registry.h" -#include "Volumes.h" - -#ifdef VOLFORMAT -#include "Format/FormatCom.h" -#elif defined (TCMOUNT) -#include "Mount/MainCom.h" -#endif - -namespace TrueCrypt -{ -#if !defined (SETUP) - - class Elevator - { - public: - - static void AddReference () - { - ++ReferenceCount; - } - - - static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) - { - Elevate(); - - CComBSTR inputBstr; - if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK) - throw ParameterIncorrect (SRC_POS); - - CComBSTR outputBstr; - if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK) - throw ParameterIncorrect (SRC_POS); - - DWORD result = ElevatedComInstance->CallDriver (ioctl, inputBstr, &outputBstr); - - if (output) - memcpy (output, *(void **) &outputBstr, outputSize); - - if (result != ERROR_SUCCESS) - { - SetLastError (result); - throw SystemException(); - } - } - - static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) - { - Elevate(); - - CComBSTR bufferBstr; - if (bufferBstr.AppendBytes ((const char *) buffer, size) != S_OK) - throw ParameterIncorrect (SRC_POS); - DWORD result = ElevatedComInstance->ReadWriteFile (write, device, CComBSTR (filePath.c_str()), &bufferBstr, offset, size, sizeDone); - - if (result != ERROR_SUCCESS) - { - SetLastError (result); - throw SystemException(); - } - - if (!write) - memcpy (buffer, (BYTE *) bufferBstr.m_str, size); - } - - static BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) - { - Elevate(); - - return ElevatedComInstance->IsPagingFileActive (checkNonWindowsPartitionsOnly); - } - - static void WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value) - { - Elevate(); - - DWORD result = ElevatedComInstance->WriteLocalMachineRegistryDwordValue (CComBSTR (keyPath), CComBSTR (valueName), value); - - if (result != ERROR_SUCCESS) - { - SetLastError (result); - throw SystemException(); - } - } - - static void RegisterFilterDriver (bool registerDriver, bool volumeClass) - { - Elevate(); - - DWORD result = ElevatedComInstance->RegisterFilterDriver (registerDriver ? TRUE : FALSE, volumeClass ? TRUE : FALSE); - if (result != ERROR_SUCCESS) - { - SetLastError (result); - throw SystemException(); - } - } - - - static void Release () - { - if (--ReferenceCount == 0 && ElevatedComInstance) - { - ElevatedComInstance->Release(); - ElevatedComInstance = nullptr; - CoUninitialize (); - } - } - - static void SetDriverServiceStartType (DWORD startType) - { - Elevate(); - - DWORD result = ElevatedComInstance->SetDriverServiceStartType (startType); - if (result != ERROR_SUCCESS) - { - SetLastError (result); - throw SystemException(); - } - } - - protected: - static void Elevate () - { - if (IsAdmin()) - { - SetLastError (ERROR_ACCESS_DENIED); - throw SystemException(); - } - - if (!ElevatedComInstance || ElevatedComInstanceThreadId != GetCurrentThreadId()) - { - CoInitialize (NULL); - ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg); - ElevatedComInstanceThreadId = GetCurrentThreadId(); - } - } - -#if defined (TCMOUNT) - static ITrueCryptMainCom *ElevatedComInstance; -#elif defined (VOLFORMAT) - static ITrueCryptFormatCom *ElevatedComInstance; -#endif - static DWORD ElevatedComInstanceThreadId; - static int ReferenceCount; - }; - -#if defined (TCMOUNT) - ITrueCryptMainCom *Elevator::ElevatedComInstance; -#elif defined (VOLFORMAT) - ITrueCryptFormatCom *Elevator::ElevatedComInstance; -#endif - DWORD Elevator::ElevatedComInstanceThreadId; - int Elevator::ReferenceCount = 0; - -#else // SETUP - - class Elevator - { - public: - static void AddReference () { } - static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); } - static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) { throw ParameterIncorrect (SRC_POS); } - static void RegisterFilterDriver (bool registerDriver, bool volumeClass) { throw ParameterIncorrect (SRC_POS); } - static void Release () { } - static void SetDriverServiceStartType (DWORD startType) { throw ParameterIncorrect (SRC_POS); } - }; - -#endif // SETUP - - - File::File (string path, bool readOnly, bool create) : Elevated (false), FileOpen (false) - { - Handle = CreateFile (path.c_str(), - readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING, - FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL); - - try - { - throw_sys_if (Handle == INVALID_HANDLE_VALUE); - } - catch (SystemException &) - { - if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) - Elevated = true; - else - throw; - } - - FileOpen = true; - FilePointerPosition = 0; - IsDevice = false; - Path = path; - } - - void File::Close () - { - if (FileOpen) - { - if (!Elevated) - CloseHandle (Handle); - - FileOpen = false; - } - } - - DWORD File::Read (byte *buffer, DWORD size) - { - DWORD bytesRead; - - if (Elevated) - { - DWORD bytesRead; - - Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead); - FilePointerPosition += bytesRead; - return bytesRead; - } - - throw_sys_if (!ReadFile (Handle, buffer, size, &bytesRead, NULL)); - return bytesRead; - } - - void File::SeekAt (int64 position) - { - FilePointerPosition = position; - - if (!Elevated) - { - LARGE_INTEGER pos; - pos.QuadPart = position; - throw_sys_if (!SetFilePointerEx (Handle, pos, NULL, FILE_BEGIN)); - } - } - - void File::Write (byte *buffer, DWORD size) - { - DWORD bytesWritten; - - try - { - if (Elevated) - { - Elevator::ReadWriteFile (true, IsDevice, Path, buffer, FilePointerPosition, size, &bytesWritten); - FilePointerPosition += bytesWritten; - throw_sys_if (bytesWritten != size); - } - else - { - throw_sys_if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL) || bytesWritten != size); - } - } - catch (SystemException &e) - { - if (!IsDevice || e.ErrorCode != ERROR_WRITE_PROTECT || !IsHiddenOSRunning()) - throw; - - BootEncryption bootEnc (NULL); - - while (size >= SECTOR_SIZE) - { - bootEnc.WriteBootDriveSector (FilePointerPosition, buffer); - - FilePointerPosition += SECTOR_SIZE; - buffer += SECTOR_SIZE; - size -= SECTOR_SIZE; - } - } - } - - void Show (HWND parent, const string &str) - { - MessageBox (parent, str.c_str(), NULL, 0); - } - - - Device::Device (string path, bool readOnly) - { - FileOpen = false; - Elevated = false; - - Handle = CreateFile ((string ("\\\\.\\") + path).c_str(), - readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL); - - try - { - throw_sys_if (Handle == INVALID_HANDLE_VALUE); - } - catch (SystemException &) - { - if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) - Elevated = true; - else - throw; - } - - FileOpen = true; - FilePointerPosition = 0; - IsDevice = true; - Path = path; - } - - - BootEncryption::BootEncryption (HWND parent) - : DriveConfigValid (false), - ParentWindow (parent), - RealSystemDriveSizeValid (false), - RescueIsoImage (nullptr), - RescueVolumeHeaderValid (false), - SelectedEncryptionAlgorithmId (0), - VolumeHeaderValid (false) - { - Elevator::AddReference(); - } - - - BootEncryption::~BootEncryption () - { - if (RescueIsoImage) - delete RescueIsoImage; - - Elevator::Release(); - } - - - void BootEncryption::CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) - { - try - { - DWORD bytesReturned; - throw_sys_if (!DeviceIoControl (hDriver, ioctl, input, inputSize, output, outputSize, &bytesReturned, NULL)); - } - catch (SystemException &) - { - if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) - Elevator::CallDriver (ioctl, input, inputSize, output, outputSize); - else - throw; - } - } - - - // Finds the first partition physically located behind the active one and returns its properties - Partition BootEncryption::GetPartitionForHiddenOS () - { - Partition candidatePartition; - - memset (&candidatePartition, 0, sizeof(candidatePartition)); - - // The user may have modified/added/deleted partitions since the time the partition table was last scanned - InvalidateCachedSysDriveProperties(); - - SystemDriveConfiguration config = GetSystemDriveConfiguration (); - bool activePartitionFound = false; - bool candidateForHiddenOSFound = false; - - if (config.SystemPartition.IsGPT) - throw ParameterIncorrect (SRC_POS); // It is assumed that CheckRequirements() had been called - - // Find the first active partition on the system drive - foreach (const Partition &partition, config.Partitions) - { - if (partition.Info.BootIndicator) - { - if (partition.Info.PartitionNumber != config.SystemPartition.Number) - { - throw ErrorException (wstring (GetString ("SYSTEM_PARTITION_NOT_ACTIVE")) - + GetRemarksOnHiddenOS()); - } - - activePartitionFound = true; - break; - } - } - - /* WARNING: Note that the partition number at the end of a device path (\Device\HarddiskY\PartitionX) must - NOT be used to find the first partition physically located behind the active one. The reason is that the - user may have deleted and created partitions during this session and e.g. the second partition could have - a higer number than the third one. */ - - - // Find the first partition physically located behind the active partition - if (activePartitionFound) - { - int64 minOffsetFound = config.DrivePartition.Info.PartitionLength.QuadPart; - - foreach (const Partition &partition, config.Partitions) - { - if (partition.Info.StartingOffset.QuadPart > config.SystemPartition.Info.StartingOffset.QuadPart - && partition.Info.StartingOffset.QuadPart < minOffsetFound) - { - minOffsetFound = partition.Info.StartingOffset.QuadPart; - - candidatePartition = partition; - - candidateForHiddenOSFound = true; - } - } - - if (!candidateForHiddenOSFound) - { - throw ErrorException (wstring (GetString ("NO_PARTITION_FOLLOWS_BOOT_PARTITION")) - + GetRemarksOnHiddenOS()); - } - - if (config.SystemPartition.Info.PartitionLength.QuadPart > TC_MAX_FAT_FS_SIZE) - { - if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS) - { - throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS_NTFS")) - + GetRemarksOnHiddenOS()); - } - } - else if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_FAT) - { - throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS")) - + GetRemarksOnHiddenOS()); - } - } - else - { - // No active partition on the system drive - throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR"); - } - - HiddenOSCandidatePartition = candidatePartition; - return candidatePartition; - } - - - DWORD BootEncryption::GetDriverServiceStartType () - { - DWORD startType; - throw_sys_if (!ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", &startType)); - return startType; - } - - - wstring BootEncryption::GetRemarksOnHiddenOS () - { - return (wstring (L"\n\n") - + GetString ("TWO_SYSTEMS_IN_ONE_PARTITION_REMARK") - + L"\n\n" - + GetString ("FOR_MORE_INFO_ON_PARTITIONS")); - } - - - void BootEncryption::SetDriverServiceStartType (DWORD startType) - { - if (!IsAdmin() && IsUacSupported()) - { - Elevator::SetDriverServiceStartType (startType); - return; - } - - BOOL startOnBoot = (startType == SERVICE_BOOT_START); - - SC_HANDLE serviceManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - throw_sys_if (!serviceManager); - - finally_do_arg (SC_HANDLE, serviceManager, { CloseServiceHandle (finally_arg); }); - - SC_HANDLE service = OpenService (serviceManager, "truecrypt", SERVICE_CHANGE_CONFIG); - throw_sys_if (!service); - - finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); }); - - // Windows versions preceding Vista can be installed on FAT filesystem which does not - // support long filenames during boot. Convert the driver path to short form if required. - string driverPath; - if (startOnBoot && !IsOSAtLeast (WIN_VISTA)) - { - char pathBuf[MAX_PATH]; - char filesystem[128]; - - string path (GetWindowsDirectory()); - path += "\\drivers\\truecrypt.sys"; - - if (GetVolumePathName (path.c_str(), pathBuf, sizeof (pathBuf)) - && GetVolumeInformation (pathBuf, NULL, 0, NULL, NULL, NULL, filesystem, sizeof(filesystem)) - && memcmp (filesystem, "FAT", 3) == 0) - { - throw_sys_if (GetShortPathName (path.c_str(), pathBuf, sizeof (pathBuf)) == 0); - - // Convert absolute path to relative to the Windows directory - driverPath = pathBuf; - driverPath = driverPath.substr (driverPath.rfind ("\\", driverPath.rfind ("\\", driverPath.rfind ("\\") - 1) - 1) + 1); - - if (Is64BitOs()) - driverPath = "SysWOW64" + driverPath.substr (driverPath.find ("\\")); - } - } - - throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, - startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL, - driverPath.empty() ? NULL : driverPath.c_str(), - startOnBoot ? "Filter" : NULL, - NULL, NULL, NULL, NULL, NULL)); - - // ChangeServiceConfig() rejects SERVICE_BOOT_START with ERROR_INVALID_PARAMETER - throw_sys_if (!WriteLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", startType)); - } - - - void BootEncryption::ProbeRealSystemDriveSize () - { - if (RealSystemDriveSizeValid) - return; - - GetSystemDriveConfiguration(); - - ProbeRealDriveSizeRequest request; - _snwprintf (request.DeviceName, array_capacity (request.DeviceName), L"%hs", DriveConfig.DrivePartition.DevicePath.c_str()); - - CallDriver (TC_IOCTL_PROBE_REAL_DRIVE_SIZE, &request, sizeof (request), &request, sizeof (request)); - DriveConfig.DrivePartition.Info.PartitionLength = request.RealDriveSize; - - RealSystemDriveSizeValid = true; - - if (request.TimeOut) - throw TimeOut (SRC_POS); - } - - - void BootEncryption::InvalidateCachedSysDriveProperties () - { - DriveConfigValid = false; - RealSystemDriveSizeValid = false; - } - - - PartitionList BootEncryption::GetDrivePartitions (int driveNumber) - { - PartitionList partList; - - for (int partNumber = 0; partNumber < 64; ++partNumber) - { - stringstream partPath; - partPath << "\\Device\\Harddisk" << driveNumber << "\\Partition" << partNumber; - - DISK_PARTITION_INFO_STRUCT diskPartInfo; - _snwprintf (diskPartInfo.deviceName, array_capacity (diskPartInfo.deviceName), L"%hs", partPath.str().c_str()); - - try - { - CallDriver (TC_IOCTL_GET_DRIVE_PARTITION_INFO, &diskPartInfo, sizeof (diskPartInfo), &diskPartInfo, sizeof (diskPartInfo)); - } - catch (...) - { - continue; - } - - Partition part; - part.DevicePath = partPath.str(); - part.Number = partNumber; - part.Info = diskPartInfo.partInfo; - part.IsGPT = diskPartInfo.IsGPT; - - // Mount point - wstringstream ws; - ws << partPath.str().c_str(); - int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str()); - - if (driveNumber >= 0) - { - part.MountPoint += (char) (driveNumber + 'A'); - part.MountPoint += ":"; - } - - // Volume ID - wchar_t volumePath[TC_MAX_PATH]; - if (ResolveSymbolicLink ((wchar_t *) ws.str().c_str(), volumePath)) - { - wchar_t volumeName[TC_MAX_PATH]; - HANDLE fh = FindFirstVolumeW (volumeName, array_capacity (volumeName)); - if (fh != INVALID_HANDLE_VALUE) - { - do - { - wstring volumeNameStr = volumeName; - wchar_t devicePath[TC_MAX_PATH]; - - if (QueryDosDeviceW (volumeNameStr.substr (4, volumeNameStr.size() - 1 - 4).c_str(), devicePath, array_capacity (devicePath)) != 0 - && wcscmp (volumePath, devicePath) == 0) - { - part.VolumeNameId = volumeName; - break; - } - - } while (FindNextVolumeW (fh, volumeName, array_capacity (volumeName))); - - FindVolumeClose (fh); - } - } - - partList.push_back (part); - } - - return partList; - } - - - DISK_GEOMETRY BootEncryption::GetDriveGeometry (int driveNumber) - { - stringstream devName; - devName << "\\Device\\Harddisk" << driveNumber << "\\Partition0"; - - DISK_GEOMETRY geometry; - throw_sys_if (!::GetDriveGeometry ((char *) devName.str().c_str(), &geometry)); - return geometry; - } - - - string BootEncryption::GetWindowsDirectory () - { - char buf[MAX_PATH]; - throw_sys_if (GetSystemDirectory (buf, sizeof (buf)) == 0); - - return string (buf); - } - - - string BootEncryption::GetTempPath () - { - char tempPath[MAX_PATH]; - DWORD tempLen = ::GetTempPath (sizeof (tempPath), tempPath); - if (tempLen == 0 || tempLen > sizeof (tempPath)) - throw ParameterIncorrect (SRC_POS); - - return string (tempPath); - } - - - uint16 BootEncryption::GetInstalledBootLoaderVersion () - { - uint16 version; - CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version)); - return version; - } - - - // Note that this does not require admin rights (it just requires the driver to be running) - bool BootEncryption::IsBootLoaderOnDrive (char *devicePath) - { - try - { - OPEN_TEST_STRUCT openTestStruct; - memset (&openTestStruct, 0, sizeof (openTestStruct)); - DWORD dwResult; - - strcpy ((char *) &openTestStruct.wszFileName[0], devicePath); - ToUNICODE ((char *) &openTestStruct.wszFileName[0]); - - openTestStruct.bDetectTCBootLoader = TRUE; - - return (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, - &openTestStruct, sizeof (OPEN_TEST_STRUCT), - &openTestStruct, sizeof (OPEN_TEST_STRUCT), - &dwResult, NULL) && openTestStruct.TCBootLoaderDetected); - } - catch (...) - { - return false; - } - } - - - BootEncryptionStatus BootEncryption::GetStatus () - { - /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */ - - BootEncryptionStatus status; - CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status)); - return status; - } - - - void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties) - { - if (properties == NULL) - throw ParameterIncorrect (SRC_POS); - - CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties)); - } - - - bool BootEncryption::IsHiddenSystemRunning () - { - int hiddenSystemStatus; - - CallDriver (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING, nullptr, 0, &hiddenSystemStatus, sizeof (hiddenSystemStatus)); - return hiddenSystemStatus != 0; - } - - - bool BootEncryption::SystemDriveContainsPartitionType (byte type) - { - Device device (GetSystemDriveConfiguration().DevicePath, true); - - byte mbrBuf[SECTOR_SIZE]; - device.SeekAt (0); - device.Read (mbrBuf, sizeof (mbrBuf)); - - MBR *mbr = reinterpret_cast (mbrBuf); - if (mbr->Signature != 0xaa55) - throw ParameterIncorrect (SRC_POS); - - for (size_t i = 0; i < array_capacity (mbr->Partitions); ++i) - { - if (mbr->Partitions[i].Type == type) - return true; - } - - return false; - } - - - bool BootEncryption::SystemDriveContainsExtendedPartition () - { - return SystemDriveContainsPartitionType (PARTITION_EXTENDED) || SystemDriveContainsPartitionType (PARTITION_XINT13_EXTENDED); - } - - - bool BootEncryption::SystemDriveIsDynamic () - { - GetSystemDriveConfigurationRequest request; - _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str()); - - CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request)); - return request.DriveIsDynamic ? true : false; - } - - - SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration () - { - if (DriveConfigValid) - return DriveConfig; - - SystemDriveConfiguration config; - - string winDir = GetWindowsDirectory(); - - // Scan all drives - for (int driveNumber = 0; driveNumber < 32; ++driveNumber) - { - bool windowsFound = false; - config.SystemLoaderPresent = false; - - PartitionList partitions = GetDrivePartitions (driveNumber); - foreach (const Partition &part, partitions) - { - if (!part.MountPoint.empty() - && (_access ((part.MountPoint + "\\bootmgr").c_str(), 0) == 0 || _access ((part.MountPoint + "\\ntldr").c_str(), 0) == 0)) - { - config.SystemLoaderPresent = true; - } - else if (!part.VolumeNameId.empty() - && (_waccess ((part.VolumeNameId + L"\\bootmgr").c_str(), 0) == 0 || _waccess ((part.VolumeNameId + L"\\ntldr").c_str(), 0) == 0)) - { - config.SystemLoaderPresent = true; - } - - if (!windowsFound && !part.MountPoint.empty() && ToUpperCase (winDir).find (ToUpperCase (part.MountPoint)) == 0) - { - config.SystemPartition = part; - windowsFound = true; - } - } - - if (windowsFound) - { - config.DriveNumber = driveNumber; - - stringstream ss; - ss << "PhysicalDrive" << driveNumber; - config.DevicePath = ss.str(); - - stringstream kernelPath; - kernelPath << "\\Device\\Harddisk" << driveNumber << "\\Partition0"; - config.DeviceKernelPath = kernelPath.str(); - - config.DrivePartition = partitions.front(); - partitions.pop_front(); - config.Partitions = partitions; - - config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull; - config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart; - - foreach (const Partition &part, config.Partitions) - { - if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace) - config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart; - - config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart; - } - - DriveConfig = config; - DriveConfigValid = true; - return DriveConfig; - } - } - - throw ParameterIncorrect (SRC_POS); - } - - - bool BootEncryption::SystemPartitionCoversWholeDrive () - { - SystemDriveConfiguration config = GetSystemDriveConfiguration(); - - return config.Partitions.size() == 1 - && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 64 * BYTES_PER_MB; - } - - - uint32 BootEncryption::GetChecksum (byte *data, size_t size) - { - uint32 sum = 0; - - while (size-- > 0) - { - sum += *data++; - sum = _rotl (sum, 1); - } - - return sum; - } - - - void BootEncryption::CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation) - { - if (bufferSize < TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE) - throw ParameterIncorrect (SRC_POS); - - ZeroMemory (buffer, bufferSize); - - int ea = 0; - if (GetStatus().DriveMounted) - { - try - { - GetBootEncryptionAlgorithmNameRequest request; - CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME, NULL, 0, &request, sizeof (request)); - - if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0) - ea = AES; - else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0) - ea = SERPENT; - else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0) - ea = TWOFISH; - } - catch (...) - { - try - { - VOLUME_PROPERTIES_STRUCT properties; - GetVolumeProperties (&properties); - ea = properties.ea; - } - catch (...) { } - } - } - else - { - if (SelectedEncryptionAlgorithmId == 0) - throw ParameterIncorrect (SRC_POS); - - ea = SelectedEncryptionAlgorithmId; - } - - int bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR : IDR_BOOT_SECTOR; - int bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER : IDR_BOOT_LOADER; - - switch (ea) - { - case AES: - bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_AES : IDR_BOOT_SECTOR_AES; - bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_AES : IDR_BOOT_LOADER_AES; - break; - - case SERPENT: - bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SERPENT : IDR_BOOT_SECTOR_SERPENT; - bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SERPENT : IDR_BOOT_LOADER_SERPENT; - break; - - case TWOFISH: - bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_TWOFISH : IDR_BOOT_SECTOR_TWOFISH; - bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_TWOFISH : IDR_BOOT_LOADER_TWOFISH; - break; - } - - // Boot sector - DWORD size; - byte *bootSecResourceImg = MapResource ("BIN", bootSectorId, &size); - if (!bootSecResourceImg || size != SECTOR_SIZE) - throw ParameterIncorrect (SRC_POS); - - memcpy (buffer, bootSecResourceImg, size); - - *(uint16 *) (buffer + TC_BOOT_SECTOR_VERSION_OFFSET) = BE16 (VERSION_NUM); - - if (IsOSAtLeast (WIN_VISTA)) - buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER; - - // Checksum of the backup header of the outer volume for the hidden system - if (hiddenOSCreation) - { - Device device (GetSystemDriveConfiguration().DevicePath); - byte headerSector[SECTOR_SIZE]; - - device.SeekAt (HiddenOSCandidatePartition.Info.StartingOffset.QuadPart + HiddenOSCandidatePartition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE + TC_VOLUME_HEADER_EFFECTIVE_SIZE); - device.Read (headerSector, sizeof (headerSector)); - - *(uint32 *) (buffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET) = GetCrc32 (headerSector, sizeof (headerSector)); - } - - // Decompressor - byte *decompressor = MapResource ("BIN", IDR_BOOT_LOADER_DECOMPRESSOR, &size); - if (!decompressor || size > TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE) - throw ParameterIncorrect (SRC_POS); - - memcpy (buffer + SECTOR_SIZE, decompressor, size); - - // Compressed boot loader - byte *bootLoader = MapResource ("BIN", bootLoaderId, &size); - if (!bootLoader || size > TC_MAX_BOOT_LOADER_SECTOR_COUNT * SECTOR_SIZE) - throw ParameterIncorrect (SRC_POS); - - memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE, bootLoader, size); - - // Boot loader and decompressor checksum - *(uint16 *) (buffer + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET) = static_cast (size); - *(uint32 *) (buffer + TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET) = GetChecksum (buffer + SECTOR_SIZE, - TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE + size); - - // Backup of decompressor and boot loader - if (size + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE <= TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE) - { - memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE, - buffer + SECTOR_SIZE, TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE); - - buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE; - } - else if (!rescueDisk && bootLoaderId != IDR_BOOT_LOADER) - { - throw ParameterIncorrect (SRC_POS); - } - } - - - void BootEncryption::ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig, string *customUserMessage, uint16 *bootLoaderVersion) - { - if (config && bufLength < TC_BOOT_CFG_FLAG_AREA_SIZE) - throw ParameterIncorrect (SRC_POS); - - GetSystemDriveConfigurationRequest request; - _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str()); - - try - { - CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request)); - if (config) - *config = request.Configuration; - - if (userConfig) - *userConfig = request.UserConfiguration; - - if (customUserMessage) - { - request.CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0; - *customUserMessage = request.CustomUserMessage; - } - - if (bootLoaderVersion) - *bootLoaderVersion = request.BootLoaderVersion; - } - catch (...) - { - if (config) - *config = 0; - - if (userConfig) - *userConfig = 0; - - if (customUserMessage) - customUserMessage->clear(); - - if (bootLoaderVersion) - *bootLoaderVersion = 0; - } - } - - - void BootEncryption::WriteBootSectorConfig (const byte newConfig[]) - { - Device device (GetSystemDriveConfiguration().DevicePath); - byte mbr[SECTOR_SIZE]; - - device.SeekAt (0); - device.Read (mbr, sizeof (mbr)); - - memcpy (mbr + TC_BOOT_SECTOR_CONFIG_OFFSET, newConfig, TC_BOOT_CFG_FLAG_AREA_SIZE); - - device.SeekAt (0); - device.Write (mbr, sizeof (mbr)); - - byte mbrVerificationBuf[SECTOR_SIZE]; - device.SeekAt (0); - device.Read (mbrVerificationBuf, sizeof (mbr)); - - if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) - throw ErrorException ("ERROR_MBR_PROTECTED"); - } - - - void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage) - { - Device device (GetSystemDriveConfiguration().DevicePath); - byte mbr[SECTOR_SIZE]; - - device.SeekAt (0); - device.Read (mbr, sizeof (mbr)); - - if (!BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME) - || BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET)) > VERSION_NUM) - { - return; - } - - mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = userConfig; - - memset (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, 0, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); - - if (!customUserMessage.empty()) - { - if (customUserMessage.size() > TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH) - throw ParameterIncorrect (SRC_POS); - - memcpy (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, customUserMessage.c_str(), customUserMessage.size()); - } - - device.SeekAt (0); - device.Write (mbr, sizeof (mbr)); - - byte mbrVerificationBuf[SECTOR_SIZE]; - device.SeekAt (0); - device.Read (mbrVerificationBuf, sizeof (mbr)); - - if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) - throw ErrorException ("ERROR_MBR_PROTECTED"); - } - - - unsigned int BootEncryption::GetHiddenOSCreationPhase () - { - byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE]; - - ReadBootSectorConfig (configFlags, sizeof(configFlags)); - - return (configFlags[0] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE); - } - - - void BootEncryption::SetHiddenOSCreationPhase (unsigned int newPhase) - { -#if TC_BOOT_CFG_FLAG_AREA_SIZE != 1 -# error TC_BOOT_CFG_FLAG_AREA_SIZE != 1; revise GetHiddenOSCreationPhase() and SetHiddenOSCreationPhase() -#endif - byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE]; - - ReadBootSectorConfig (configFlags, sizeof(configFlags)); - - configFlags[0] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; - - configFlags[0] |= newPhase; - - WriteBootSectorConfig (configFlags); - } - - -#ifndef SETUP - - void BootEncryption::StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm) - { - if (!IsHiddenOSRunning()) - throw ParameterIncorrect (SRC_POS); - - WipeDecoySystemRequest request; - ZeroMemory (&request, sizeof (request)); - - request.WipeAlgorithm = wipeAlgorithm; - - if (Randinit() != ERR_SUCCESS) - throw ParameterIncorrect (SRC_POS); - - UserEnrichRandomPool (ParentWindow); - - if (!RandgetBytes (request.WipeKey, sizeof (request.WipeKey), TRUE)) - throw ParameterIncorrect (SRC_POS); - - CallDriver (TC_IOCTL_START_DECOY_SYSTEM_WIPE, &request, sizeof (request), NULL, 0); - - burn (&request, sizeof (request)); - } - - - void BootEncryption::AbortDecoyOSWipe () - { - CallDriver (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE); - } - - - DecoySystemWipeStatus BootEncryption::GetDecoyOSWipeStatus () - { - DecoySystemWipeStatus status; - CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS, NULL, 0, &status, sizeof (status)); - return status; - } - - - void BootEncryption::CheckDecoyOSWipeResult () - { - CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT); - } - - - void BootEncryption::WipeHiddenOSCreationConfig () - { - if (IsHiddenOSRunning() || Randinit() != ERR_SUCCESS) - throw ParameterIncorrect (SRC_POS); - - Device device (GetSystemDriveConfiguration().DevicePath); - byte mbr[SECTOR_SIZE]; - - device.SeekAt (0); - device.Read (mbr, sizeof (mbr)); - - finally_do_arg (BootEncryption *, this, - { - try - { - finally_arg->SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); - } catch (...) { } - }); - -#if PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE -# error PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE -#endif - - byte randData[PRAND_DISK_WIPE_PASSES]; - if (!RandgetBytes (randData, sizeof (randData), FALSE)) - throw ParameterIncorrect (SRC_POS); - - for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) - { - for (int i = 0; i < TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE; ++i) - { - mbr[TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + i] = randData[wipePass]; - } - - mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; - mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] |= randData[wipePass] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; - - if (wipePass == PRAND_DISK_WIPE_PASSES - 1) - memset (mbr + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET, 0, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE); - - device.SeekAt (0); - device.Write (mbr, sizeof (mbr)); - } - - for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES/4 + 1; wipePass++) - { - SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); - SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING); - SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPING); - SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED); - } - SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); - } - -#endif // !SETUP - - - void BootEncryption::InstallBootLoader (bool preserveUserConfig, bool hiddenOSCreation) - { - byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; - CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation); - - // Write MBR - Device device (GetSystemDriveConfiguration().DevicePath); - byte mbr[SECTOR_SIZE]; - - device.SeekAt (0); - device.Read (mbr, sizeof (mbr)); - - if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME)) - { - uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET)); - if (version != 0) - { - bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; - memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); - } - } - - memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE); - - device.SeekAt (0); - device.Write (mbr, sizeof (mbr)); - - byte mbrVerificationBuf[SECTOR_SIZE]; - device.SeekAt (0); - device.Read (mbrVerificationBuf, sizeof (mbr)); - - if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) - throw ErrorException ("ERROR_MBR_PROTECTED"); - - // Write boot loader - device.SeekAt (SECTOR_SIZE); - device.Write (bootLoaderBuf + SECTOR_SIZE, sizeof (bootLoaderBuf) - SECTOR_SIZE); - } - - - string BootEncryption::GetSystemLoaderBackupPath () - { - char pathBuf[MAX_PATH]; - - throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf))); - - string path = string (pathBuf) + "\\" TC_APP_NAME; - CreateDirectory (path.c_str(), NULL); - - return path + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME; - } - - - void BootEncryption::RenameDeprecatedSystemLoaderBackup () - { - char pathBuf[MAX_PATH]; - - if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA, NULL, 0, pathBuf))) - { - string path = string (pathBuf) + "\\" TC_APP_NAME + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY; - - if (FileExists (path.c_str()) && !FileExists (GetSystemLoaderBackupPath().c_str())) - throw_sys_if (rename (path.c_str(), GetSystemLoaderBackupPath().c_str()) != 0); - } - } - - -#ifndef SETUP - void BootEncryption::CreateRescueIsoImage (bool initialSetup, const string &isoImagePath) - { - BootEncryptionStatus encStatus = GetStatus(); - if (encStatus.SetupInProgress) - throw ParameterIncorrect (SRC_POS); - - Buffer imageBuf (RescueIsoImageSize); - - byte *image = imageBuf.Ptr(); - memset (image, 0, RescueIsoImageSize); - - // Primary volume descriptor - strcpy ((char *)image + 0x8000, "\001CD001\001"); - strcpy ((char *)image + 0x7fff + 41, "TrueCrypt Rescue Disk "); - *(uint32 *) (image + 0x7fff + 81) = RescueIsoImageSize / 2048; - *(uint32 *) (image + 0x7fff + 85) = BE32 (RescueIsoImageSize / 2048); - image[0x7fff + 121] = 1; - image[0x7fff + 124] = 1; - image[0x7fff + 125] = 1; - image[0x7fff + 128] = 1; - image[0x7fff + 130] = 8; - image[0x7fff + 131] = 8; - - image[0x7fff + 133] = 10; - image[0x7fff + 140] = 10; - image[0x7fff + 141] = 0x14; - image[0x7fff + 157] = 0x22; - image[0x7fff + 159] = 0x18; - - // Boot record volume descriptor - strcpy ((char *)image + 0x8801, "CD001\001EL TORITO SPECIFICATION"); - image[0x8800 + 0x47] = 0x19; - - // Volume descriptor set terminator - strcpy ((char *)image + 0x9000, "\377CD001\001"); - - // Path table - image[0xA000 + 0] = 1; - image[0xA000 + 2] = 0x18; - image[0xA000 + 6] = 1; - - // Root directory - image[0xc000 + 0] = 0x22; - image[0xc000 + 2] = 0x18; - image[0xc000 + 9] = 0x18; - image[0xc000 + 11] = 0x08; - image[0xc000 + 16] = 0x08; - image[0xc000 + 25] = 0x02; - image[0xc000 + 28] = 0x01; - image[0xc000 + 31] = 0x01; - image[0xc000 + 32] = 0x01; - image[0xc000 + 34] = 0x22; - image[0xc000 + 36] = 0x18; - image[0xc000 + 43] = 0x18; - image[0xc000 + 45] = 0x08; - image[0xc000 + 50] = 0x08; - image[0xc000 + 59] = 0x02; - image[0xc000 + 62] = 0x01; - *(uint32 *) (image + 0xc000 + 65) = 0x010101; - - // Validation entry - image[0xc800] = 1; - int offset = 0xc800 + 0x1c; - image[offset++] = 0xaa; - image[offset++] = 0x55; - image[offset++] = 0x55; - image[offset] = 0xaa; - - // Initial entry - offset = 0xc820; - image[offset++] = 0x88; - image[offset++] = 2; - image[0xc820 + 6] = 1; - image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR; - - // TrueCrypt Boot Loader - CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, true); - - // Volume header - if (initialSetup) - { - if (!RescueVolumeHeaderValid) - throw ParameterIncorrect (SRC_POS); - - memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - } - else - { - Device bootDevice (GetSystemDriveConfiguration().DevicePath, true); - bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); - bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - } - - // Original system loader - try - { - File sysBakFile (GetSystemLoaderBackupPath(), true); - sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE); - - image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER; - } - catch (Exception &e) - { - e.Show (ParentWindow); - Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK"); - } - - // Boot loader backup - CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, false); - - RescueIsoImage = new byte[RescueIsoImageSize]; - if (!RescueIsoImage) - throw bad_alloc(); - memcpy (RescueIsoImage, image, RescueIsoImageSize); - - if (!isoImagePath.empty()) - { - File isoFile (isoImagePath, false, true); - isoFile.Write (image, RescueIsoImageSize); - } - } -#endif - - bool BootEncryption::VerifyRescueDisk () - { - if (!RescueIsoImage) - throw ParameterIncorrect (SRC_POS); - - for (char drive = 'Z'; drive >= 'D'; --drive) - { - try - { - string path = "X:"; - path[0] = drive; - - Device driveDevice (path, true); - size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048; - Buffer buffer ((verifiedSectorCount + 1) * 2048); - - DWORD bytesRead = driveDevice.Read (buffer.Ptr(), buffer.Size()); - if (bytesRead != buffer.Size()) - continue; - - if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0) - return true; - } - catch (...) { } - } - - return false; - } - - -#ifndef SETUP - - void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5) - { - PCRYPTO_INFO cryptoInfo = NULL; - - if (!IsRandomNumberGeneratorStarted()) - throw ParameterIncorrect (SRC_POS); - - throw_sys_if (CreateVolumeHeaderInMemory (TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, NULL, &cryptoInfo, - volumeSize, 0, encryptedAreaStart, 0, TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION, TC_HEADER_FLAG_ENCRYPTED_SYSTEM, FALSE) != 0); - - finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); }); - - // Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize) - memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader)); - ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, NULL, cryptoInfo); - - DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); - - if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x54525545) - throw ParameterIncorrect (SRC_POS); - - byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH; - mputInt64 (fieldPos, volumeSize); - - // CRC of the header fields - uint32 crc = GetCrc32 (RescueVolumeHeader + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); - fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_HEADER_CRC; - mputLong (fieldPos, crc); - - EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); - - VolumeHeaderValid = true; - RescueVolumeHeaderValid = true; - } - - - void BootEncryption::InstallVolumeHeader () - { - if (!VolumeHeaderValid) - throw ParameterIncorrect (SRC_POS); - - Device device (GetSystemDriveConfiguration().DevicePath); - - device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); - device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader)); - } - - - // For synchronous operations use AbortSetupWait() - void BootEncryption::AbortSetup () - { - CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); - } - - - // For asynchronous operations use AbortSetup() - void BootEncryption::AbortSetupWait () - { - CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); - - BootEncryptionStatus encStatus = GetStatus(); - - while (encStatus.SetupInProgress) - { - Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL); - encStatus = GetStatus(); - } - } - - - void BootEncryption::BackupSystemLoader () - { - Device device (GetSystemDriveConfiguration().DevicePath, true); - - byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE]; - - device.SeekAt (0); - device.Read (bootLoaderBuf, sizeof (bootLoaderBuf)); - - // Prevent TrueCrypt loader from being backed up - for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i) - { - if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0) - { - if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED") == IDNO) - throw UserAbort (SRC_POS); - return; - } - } - - File backupFile (GetSystemLoaderBackupPath(), false, true); - backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf)); - } - - - void BootEncryption::RestoreSystemLoader () - { - byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE]; - - File backupFile (GetSystemLoaderBackupPath(), true); - - if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf)) - throw ParameterIncorrect (SRC_POS); - - Device device (GetSystemDriveConfiguration().DevicePath); - - // Preserve current partition table - byte mbr[SECTOR_SIZE]; - device.SeekAt (0); - device.Read (mbr, sizeof (mbr)); - memcpy (bootLoaderBuf + TC_MAX_MBR_BOOT_CODE_SIZE, mbr + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbr) - TC_MAX_MBR_BOOT_CODE_SIZE); - - device.SeekAt (0); - device.Write (bootLoaderBuf, sizeof (bootLoaderBuf)); - } - -#endif // SETUP - - void BootEncryption::RegisterDeviceClassFilter (bool registerFilter, const GUID *deviceClassGuid) - { - HKEY classRegKey = SetupDiOpenClassRegKey (deviceClassGuid, KEY_READ | KEY_WRITE); - throw_sys_if (classRegKey == INVALID_HANDLE_VALUE); - finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); }); - - if (registerFilter) - { - // Register class filter below all other filters in the stack - - size_t strSize = strlen ("truecrypt") + 1; - byte regKeyBuf[65536]; - DWORD size = sizeof (regKeyBuf) - strSize; - - // SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly - strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf)); - - if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS) - size = 1; - - throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS); - } - else - { - // Unregister a class filter - string infFileName = GetTempPath() + "\\truecrypt_device_filter.inf"; - - File infFile (infFileName, false, true); - finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); }); - - string infTxt = "[truecrypt]\r\n" - "DelReg=truecrypt_reg\r\n\r\n" - "[truecrypt_reg]\r\n" - "HKR,,\"UpperFilters\",0x00018002,\"truecrypt\"\r\n"; - - infFile.Write ((byte *) infTxt.c_str(), infTxt.size()); - infFile.Close(); - - HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); - throw_sys_if (hInf == INVALID_HANDLE_VALUE); - finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); }); - - throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL)); - } - } - - void BootEncryption::RegisterFilterDriver (bool registerDriver, bool volumeClass) - { - if (!IsAdmin() && IsUacSupported()) - { - Elevator::RegisterFilterDriver (registerDriver, volumeClass); - return; - } - - if (volumeClass) - { - RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_VOLUME); - RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_FLOPPYDISK); - } - else - { - RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_DISKDRIVE); - } - } - -#ifndef SETUP - - void BootEncryption::CheckRequirements () - { - if (nCurrentOS == WIN_2000) - throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS"); - - if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1) - throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_VISTA_SP0"); - - if (IsNonInstallMode()) - throw ErrorException ("FEATURE_REQUIRES_INSTALLATION"); - - SystemDriveConfiguration config = GetSystemDriveConfiguration (); - - if (config.SystemPartition.IsGPT) - throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED"); - - if (SystemDriveIsDynamic()) - throw ErrorException ("SYSENC_UNSUPPORTED_FOR_DYNAMIC_DISK"); - - if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE) - throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER"); - - DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber); - - if (geometry.BytesPerSector != SECTOR_SIZE) - throw ErrorException ("LARGE_SECTOR_UNSUPPORTED"); - - if (!config.SystemLoaderPresent) - throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR"); - - if (!config.SystemPartition.IsGPT) - { - // Determine whether there is an Active partition on the system drive - bool activePartitionFound = false; - foreach (const Partition &partition, config.Partitions) - { - if (partition.Info.BootIndicator) - { - activePartitionFound = true; - break; - } - } - - if (!activePartitionFound) - throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR"); - } - } - - - void BootEncryption::CheckRequirementsHiddenOS () - { - // It is assumed that CheckRequirements() had been called (so we don't check e.g. whether it's GPT). - - // The user may have modified/added/deleted partitions since the partition table was last scanned. - InvalidateCachedSysDriveProperties (); - - GetPartitionForHiddenOS (); - } - - - void BootEncryption::InitialSecurityChecksForHiddenOS () - { - char windowsDrive = toupper (GetWindowsDirectory()[0]); - - // Paging files - bool pagingFilesOk = !IsPagingFileActive (TRUE); - - char pagingFileRegData[65536]; - DWORD pagingFileRegDataSize = sizeof (pagingFileRegData); - - if (ReadLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", pagingFileRegData, &pagingFileRegDataSize) - && pagingFileRegDataSize > 4) - { - for (size_t i = 1; i < pagingFileRegDataSize - 2; ++i) - { - if (memcmp (pagingFileRegData + i, ":\\", 2) == 0 && toupper (pagingFileRegData[i - 1]) != windowsDrive) - { - pagingFilesOk = false; - break; - } - } - } - - if (!pagingFilesOk) - { - if (AskWarnYesNoString ((wchar_t *) (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION")) - + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION") - + L"\n\n\n" - + GetString ("RESTRICT_PAGING_FILES_TO_SYS_PARTITION") - ).c_str()) == IDYES) - { - RestrictPagingFilesToSystemPartition(); - RestartComputer(); - AbortProcessSilent(); - } - - throw ErrorException (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION")) - + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); - } - - // User profile - char *configPath = GetConfigPath ("dummy"); - if (configPath && toupper (configPath[0]) != windowsDrive) - { - throw ErrorException (wstring (GetString ("USER_PROFILE_NOT_ON_SYS_PARTITION")) - + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); - } - - // Temporary files - if (toupper (GetTempPath()[0]) != windowsDrive) - { - throw ErrorException (wstring (GetString ("TEMP_NOT_ON_SYS_PARTITION")) - + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); - } - } - - - void BootEncryption::Deinstall () - { - BootEncryptionStatus encStatus = GetStatus(); - - if (encStatus.DriveEncrypted || encStatus.DriveMounted) - throw ParameterIncorrect (SRC_POS); - - SystemDriveConfiguration config = GetSystemDriveConfiguration (); - - if (encStatus.VolumeHeaderPresent) - { - // Verify CRC of header salt - Device device (config.DevicePath, true); - byte header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; - - device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); - device.Read (header, sizeof (header)); - - if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE)) - throw ParameterIncorrect (SRC_POS); - } - - RegisterFilterDriver (false, false); - RegisterFilterDriver (false, true); - SetDriverServiceStartType (SERVICE_SYSTEM_START); - - SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); // In case RestoreSystemLoader() fails - - try - { - RestoreSystemLoader (); - } - catch (Exception &e) - { - e.Show (ParentWindow); - throw ErrorException ("SYS_LOADER_RESTORE_FAILED"); - } - } - - - int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5) - { - BootEncryptionStatus encStatus = GetStatus(); - - if (encStatus.SetupInProgress) - throw ParameterIncorrect (SRC_POS); - - SystemDriveConfiguration config = GetSystemDriveConfiguration (); - - char header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; - Device device (config.DevicePath); - - // Only one algorithm is currently supported - if (pkcs5 != 0) - throw ParameterIncorrect (SRC_POS); - - int64 headerOffset = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; - int64 backupHeaderOffset = -1; - - if (encStatus.HiddenSystem) - { - headerOffset = encStatus.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; - - // Find hidden system partition - foreach (const Partition &partition, config.Partitions) - { - if (partition.Info.StartingOffset.QuadPart == encStatus.HiddenSystemPartitionStart) - { - backupHeaderOffset = partition.Info.StartingOffset.QuadPart + partition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_SIZE; - break; - } - } - - if (backupHeaderOffset == -1) - throw ParameterIncorrect (SRC_POS); - } - - device.SeekAt (headerOffset); - device.Read ((byte *) header, sizeof (header)); - - PCRYPTO_INFO cryptoInfo = NULL; - - int status = ReadVolumeHeader (!encStatus.HiddenSystem, header, oldPassword, &cryptoInfo, NULL); - finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); }); - - if (status != 0) - { - handleError (ParentWindow, status); - return status; - } - - // Change the PKCS-5 PRF if requested by user - if (pkcs5 != 0) - { - cryptoInfo->pkcs5 = pkcs5; - RandSetHashFunction (pkcs5); - } - - throw_sys_if (Randinit () != 0); - finally_do ({ RandStop (FALSE); }); - - NormalCursor(); - UserEnrichRandomPool (ParentWindow); - WaitCursor(); - - /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using - techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy - to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22 - times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might - impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the - valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman - recommends. During each pass we will write a valid working header. Each pass will use the same master - key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only - item that will be different for each pass will be the salt. This is sufficient to cause each "version" - of the header to differ substantially and in a random manner from the versions written during the - other passes. */ - - bool headerUpdated = false; - int result = ERR_SUCCESS; - - try - { - BOOL backupHeader = FALSE; - while (TRUE) - { - for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) - { - PCRYPTO_INFO tmpCryptoInfo = NULL; - - status = CreateVolumeHeaderInMemory (!encStatus.HiddenSystem, - header, - cryptoInfo->ea, - cryptoInfo->mode, - newPassword, - cryptoInfo->pkcs5, - (char *) cryptoInfo->master_keydata, - &tmpCryptoInfo, - cryptoInfo->VolumeSize.Value, - cryptoInfo->hiddenVolumeSize, - cryptoInfo->EncryptedAreaStart.Value, - cryptoInfo->EncryptedAreaLength.Value, - cryptoInfo->RequiredProgramVersion, - cryptoInfo->HeaderFlags | TC_HEADER_FLAG_ENCRYPTED_SYSTEM, - wipePass < PRAND_DISK_WIPE_PASSES - 1); - - if (tmpCryptoInfo) - crypto_close (tmpCryptoInfo); - - if (status != 0) - { - handleError (ParentWindow, status); - return status; - } - - device.SeekAt (headerOffset); - device.Write ((byte *) header, sizeof (header)); - headerUpdated = true; - } - - if (!encStatus.HiddenSystem || backupHeader) - break; - - backupHeader = TRUE; - headerOffset = backupHeaderOffset; - } - } - catch (Exception &e) - { - e.Show (ParentWindow); - result = ERR_OS_ERROR; - } - - if (headerUpdated) - { - ReopenBootVolumeHeaderRequest reopenRequest; - reopenRequest.VolumePassword = *newPassword; - finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); }); - - CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest)); - } - - return result; - } - - - void BootEncryption::CheckEncryptionSetupResult () - { - CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT); - } - - - void BootEncryption::Install (bool hiddenSystem) - { - BootEncryptionStatus encStatus = GetStatus(); - if (encStatus.DriveMounted) - throw ParameterIncorrect (SRC_POS); - - try - { - InstallBootLoader (false, hiddenSystem); - - if (!hiddenSystem) - InstallVolumeHeader (); - - RegisterBootDriver (hiddenSystem); - } - catch (Exception &) - { - try - { - RestoreSystemLoader (); - } - catch (Exception &e) - { - e.Show (ParentWindow); - } - - throw; - } - } - - - void BootEncryption::PrepareHiddenOSCreation (int ea, int mode, int pkcs5) - { - BootEncryptionStatus encStatus = GetStatus(); - if (encStatus.DriveMounted) - throw ParameterIncorrect (SRC_POS); - - CheckRequirements(); - BackupSystemLoader(); - - SelectedEncryptionAlgorithmId = ea; - } - - - void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath) - { - BootEncryptionStatus encStatus = GetStatus(); - if (encStatus.DriveMounted) - throw ParameterIncorrect (SRC_POS); - - CheckRequirements (); - - SystemDriveConfiguration config = GetSystemDriveConfiguration(); - - // Some chipset drivers may prevent access to the last sector of the drive - if (!systemPartitionOnly) - { - DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber); - Buffer sector (geometry.BytesPerSector); - - Device device (config.DevicePath); - - try - { - device.SeekAt (config.DrivePartition.Info.PartitionLength.QuadPart - geometry.BytesPerSector); - device.Read (sector.Ptr(), sector.Size()); - } - catch (SystemException &e) - { - if (e.ErrorCode != ERROR_CRC) - { - e.Show (ParentWindow); - Error ("WHOLE_DRIVE_ENCRYPTION_PREVENTED_BY_DRIVERS"); - throw UserAbort (SRC_POS); - } - } - } - - BackupSystemLoader (); - - uint64 volumeSize; - uint64 encryptedAreaStart; - - if (systemPartitionOnly) - { - volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart; - encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart; - } - else - { - volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE; - encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE; - } - - SelectedEncryptionAlgorithmId = ea; - CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5); - - if (!rescueIsoImagePath.empty()) - CreateRescueIsoImage (true, rescueIsoImagePath); - } - - bool BootEncryption::IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) - { - if (!IsAdmin() && IsUacSupported()) - return Elevator::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false; - - return ::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false; - } - - void BootEncryption::RestrictPagingFilesToSystemPartition () - { - char pagingFiles[128]; - strncpy (pagingFiles, "X:\\pagefile.sys 0 0", sizeof (pagingFiles)); - pagingFiles[0] = GetWindowsDirectory()[0]; - - throw_sys_if (!WriteLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", pagingFiles, strlen (pagingFiles) + 2)); - } - - void BootEncryption::WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value) - { - if (!IsAdmin() && IsUacSupported()) - { - Elevator::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value); - return; - } - - throw_sys_if (!WriteLocalMachineRegistryDword (keyPath, valueName, value)); - } - - - void BootEncryption::StartDecryption (BOOL discardUnreadableEncryptedSectors) - { - BootEncryptionStatus encStatus = GetStatus(); - - if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress) - throw ParameterIncorrect (SRC_POS); - - BootEncryptionSetupRequest request; - ZeroMemory (&request, sizeof (request)); - - request.SetupMode = SetupDecryption; - request.DiscardUnreadableEncryptedSectors = discardUnreadableEncryptedSectors; - - CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0); - } - - - void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm, bool zeroUnreadableSectors) - { - BootEncryptionStatus encStatus = GetStatus(); - - if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress) - throw ParameterIncorrect (SRC_POS); - - BootEncryptionSetupRequest request; - ZeroMemory (&request, sizeof (request)); - - request.SetupMode = SetupEncryption; - request.WipeAlgorithm = wipeAlgorithm; - request.ZeroUnreadableSectors = zeroUnreadableSectors; - - CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0); - } - -#endif // !SETUP - - - void BootEncryption::WriteBootDriveSector (uint64 offset, byte *data) - { - WriteBootDriveSectorRequest request; - request.Offset.QuadPart = offset; - memcpy (request.Data, data, sizeof (request.Data)); - - CallDriver (TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR, &request, sizeof (request), NULL, 0); - } - - - void BootEncryption::RegisterBootDriver (bool hiddenSystem) - { - SetDriverServiceStartType (SERVICE_BOOT_START); - - try - { - RegisterFilterDriver (false, false); - RegisterFilterDriver (false, true); - } - catch (...) { } - - RegisterFilterDriver (true, false); - - if (hiddenSystem) - RegisterFilterDriver (true, true); - } - - - bool BootEncryption::RestartComputer (void) - { - return (::RestartComputer() != FALSE); - } -} +/* +Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + +Governed by the TrueCrypt License 2.8 the full text of which is contained +in the file License.txt included in TrueCrypt binary and source code +distribution packages. +*/ + +#include "Tcdefs.h" +#include "Platform/Finally.h" +#include "Platform/ForEach.h" +#include +#include +#include +#include +#include +#include "BootEncryption.h" +#include "Boot/Windows/BootCommon.h" +#include "Common/Resource.h" +#include "Crc.h" +#include "Crypto.h" +#include "Dlgcode.h" +#include "Endian.h" +#include "Language.h" +#include "Random.h" +#include "Registry.h" +#include "Volumes.h" + +#ifdef VOLFORMAT +#include "Format/FormatCom.h" +#elif defined (TCMOUNT) +#include "Mount/MainCom.h" +#endif + +namespace TrueCrypt +{ +#if !defined (SETUP) + + class Elevator + { + public: + + static void AddReference () + { + ++ReferenceCount; + } + + + static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) + { + Elevate(); + + CComBSTR inputBstr; + if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK) + throw ParameterIncorrect (SRC_POS); + + CComBSTR outputBstr; + if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK) + throw ParameterIncorrect (SRC_POS); + + DWORD result = ElevatedComInstance->CallDriver (ioctl, inputBstr, &outputBstr); + + if (output) + memcpy (output, *(void **) &outputBstr, outputSize); + + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + } + + static void CopyFile (const string &sourceFile, const string &destinationFile) + { + Elevate(); + + DWORD result = ElevatedComInstance->CopyFile (CComBSTR (sourceFile.c_str()), CComBSTR (destinationFile.c_str())); + + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + } + + static void DeleteFile (const string &file) + { + Elevate(); + + DWORD result = ElevatedComInstance->DeleteFile (CComBSTR (file.c_str())); + + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + } + + static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) + { + Elevate(); + + CComBSTR bufferBstr; + if (bufferBstr.AppendBytes ((const char *) buffer, size) != S_OK) + throw ParameterIncorrect (SRC_POS); + DWORD result = ElevatedComInstance->ReadWriteFile (write, device, CComBSTR (filePath.c_str()), &bufferBstr, offset, size, sizeDone); + + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + + if (!write) + memcpy (buffer, (BYTE *) bufferBstr.m_str, size); + } + + static BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) + { + Elevate(); + + return ElevatedComInstance->IsPagingFileActive (checkNonWindowsPartitionsOnly); + } + + static void WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value) + { + Elevate(); + + DWORD result = ElevatedComInstance->WriteLocalMachineRegistryDwordValue (CComBSTR (keyPath), CComBSTR (valueName), value); + + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + } + + static void RegisterFilterDriver (bool registerDriver, bool volumeClass) + { + Elevate(); + + DWORD result = ElevatedComInstance->RegisterFilterDriver (registerDriver ? TRUE : FALSE, volumeClass ? TRUE : FALSE); + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + } + + static void RegisterSystemFavoritesService (BOOL registerService) + { + Elevate(); + + DWORD result = ElevatedComInstance->RegisterSystemFavoritesService (registerService); + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + } + + static void Release () + { + if (--ReferenceCount == 0 && ElevatedComInstance) + { + ElevatedComInstance->Release(); + ElevatedComInstance = nullptr; + CoUninitialize (); + } + } + + static void SetDriverServiceStartType (DWORD startType) + { + Elevate(); + + DWORD result = ElevatedComInstance->SetDriverServiceStartType (startType); + if (result != ERROR_SUCCESS) + { + SetLastError (result); + throw SystemException(); + } + } + + protected: + static void Elevate () + { + if (IsAdmin()) + { + SetLastError (ERROR_ACCESS_DENIED); + throw SystemException(); + } + + if (!ElevatedComInstance || ElevatedComInstanceThreadId != GetCurrentThreadId()) + { + CoInitialize (NULL); + ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg); + ElevatedComInstanceThreadId = GetCurrentThreadId(); + } + } + +#if defined (TCMOUNT) + static ITrueCryptMainCom *ElevatedComInstance; +#elif defined (VOLFORMAT) + static ITrueCryptFormatCom *ElevatedComInstance; +#endif + static DWORD ElevatedComInstanceThreadId; + static int ReferenceCount; + }; + +#if defined (TCMOUNT) + ITrueCryptMainCom *Elevator::ElevatedComInstance; +#elif defined (VOLFORMAT) + ITrueCryptFormatCom *Elevator::ElevatedComInstance; +#endif + DWORD Elevator::ElevatedComInstanceThreadId; + int Elevator::ReferenceCount = 0; + +#else // SETUP + + class Elevator + { + public: + static void AddReference () { } + static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); } + static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) { throw ParameterIncorrect (SRC_POS); } + static void RegisterFilterDriver (bool registerDriver, bool volumeClass) { throw ParameterIncorrect (SRC_POS); } + static void Release () { } + static void SetDriverServiceStartType (DWORD startType) { throw ParameterIncorrect (SRC_POS); } + }; + +#endif // SETUP + + + File::File (string path, bool readOnly, bool create) : Elevated (false), FileOpen (false) + { + Handle = CreateFile (path.c_str(), + readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL); + + try + { + throw_sys_if (Handle == INVALID_HANDLE_VALUE); + } + catch (SystemException &) + { + if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) + Elevated = true; + else + throw; + } + + FileOpen = true; + FilePointerPosition = 0; + IsDevice = false; + Path = path; + } + + void File::Close () + { + if (FileOpen) + { + if (!Elevated) + CloseHandle (Handle); + + FileOpen = false; + } + } + + DWORD File::Read (byte *buffer, DWORD size) + { + DWORD bytesRead; + + if (Elevated) + { + DWORD bytesRead; + + Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead); + FilePointerPosition += bytesRead; + return bytesRead; + } + + throw_sys_if (!ReadFile (Handle, buffer, size, &bytesRead, NULL)); + return bytesRead; + } + + void File::SeekAt (int64 position) + { + FilePointerPosition = position; + + if (!Elevated) + { + LARGE_INTEGER pos; + pos.QuadPart = position; + throw_sys_if (!SetFilePointerEx (Handle, pos, NULL, FILE_BEGIN)); + } + } + + void File::Write (byte *buffer, DWORD size) + { + DWORD bytesWritten; + + try + { + if (Elevated) + { + Elevator::ReadWriteFile (true, IsDevice, Path, buffer, FilePointerPosition, size, &bytesWritten); + FilePointerPosition += bytesWritten; + throw_sys_if (bytesWritten != size); + } + else + { + throw_sys_if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL) || bytesWritten != size); + } + } + catch (SystemException &e) + { + if (!IsDevice || e.ErrorCode != ERROR_WRITE_PROTECT) + throw; + + BootEncryption bootEnc (NULL); + + while (size >= SECTOR_SIZE) + { + bootEnc.WriteBootDriveSector (FilePointerPosition, buffer); + + FilePointerPosition += SECTOR_SIZE; + buffer += SECTOR_SIZE; + size -= SECTOR_SIZE; + } + } + } + + void Show (HWND parent, const string &str) + { + MessageBox (parent, str.c_str(), NULL, 0); + } + + + Device::Device (string path, bool readOnly) + { + FileOpen = false; + Elevated = false; + + Handle = CreateFile ((string ("\\\\.\\") + path).c_str(), + readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL); + + try + { + throw_sys_if (Handle == INVALID_HANDLE_VALUE); + } + catch (SystemException &) + { + if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) + Elevated = true; + else + throw; + } + + FileOpen = true; + FilePointerPosition = 0; + IsDevice = true; + Path = path; + } + + + BootEncryption::BootEncryption (HWND parent) + : DriveConfigValid (false), + ParentWindow (parent), + RealSystemDriveSizeValid (false), + RescueIsoImage (nullptr), + RescueVolumeHeaderValid (false), + SelectedEncryptionAlgorithmId (0), + VolumeHeaderValid (false) + { + Elevator::AddReference(); + } + + + BootEncryption::~BootEncryption () + { + if (RescueIsoImage) + delete RescueIsoImage; + + Elevator::Release(); + } + + + void BootEncryption::CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) + { + try + { + DWORD bytesReturned; + throw_sys_if (!DeviceIoControl (hDriver, ioctl, input, inputSize, output, outputSize, &bytesReturned, NULL)); + } + catch (SystemException &) + { + if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported()) + Elevator::CallDriver (ioctl, input, inputSize, output, outputSize); + else + throw; + } + } + + + // Finds the first partition physically located behind the active one and returns its properties + Partition BootEncryption::GetPartitionForHiddenOS () + { + Partition candidatePartition; + + memset (&candidatePartition, 0, sizeof(candidatePartition)); + + // The user may have modified/added/deleted partitions since the time the partition table was last scanned + InvalidateCachedSysDriveProperties(); + + SystemDriveConfiguration config = GetSystemDriveConfiguration (); + bool activePartitionFound = false; + bool candidateForHiddenOSFound = false; + + if (config.SystemPartition.IsGPT) + throw ParameterIncorrect (SRC_POS); // It is assumed that CheckRequirements() had been called + + // Find the first active partition on the system drive + foreach (const Partition &partition, config.Partitions) + { + if (partition.Info.BootIndicator) + { + if (partition.Info.PartitionNumber != config.SystemPartition.Number) + { + // If there is an extra boot partition, the system partition must be located right behind it + if (IsOSAtLeast (WIN_7) && config.ExtraBootPartitionPresent) + { + int64 minOffsetFound = config.DrivePartition.Info.PartitionLength.QuadPart; + Partition bootPartition = partition; + Partition partitionBehindBoot; + + foreach (const Partition &partition, config.Partitions) + { + if (partition.Info.StartingOffset.QuadPart > bootPartition.Info.StartingOffset.QuadPart + && partition.Info.StartingOffset.QuadPart < minOffsetFound) + { + minOffsetFound = partition.Info.StartingOffset.QuadPart; + partitionBehindBoot = partition; + } + } + + if (minOffsetFound != config.DrivePartition.Info.PartitionLength.QuadPart + && partitionBehindBoot.Number == config.SystemPartition.Number) + { + activePartitionFound = true; + break; + } + } + + throw ErrorException (wstring (GetString ("SYSTEM_PARTITION_NOT_ACTIVE")) + + GetRemarksOnHiddenOS()); + } + + activePartitionFound = true; + break; + } + } + + /* WARNING: Note that the partition number at the end of a device path (\Device\HarddiskY\PartitionX) must + NOT be used to find the first partition physically located behind the active one. The reason is that the + user may have deleted and created partitions during this session and e.g. the second partition could have + a higer number than the third one. */ + + + // Find the first partition physically located behind the active partition + if (activePartitionFound) + { + int64 minOffsetFound = config.DrivePartition.Info.PartitionLength.QuadPart; + + foreach (const Partition &partition, config.Partitions) + { + if (partition.Info.StartingOffset.QuadPart > config.SystemPartition.Info.StartingOffset.QuadPart + && partition.Info.StartingOffset.QuadPart < minOffsetFound) + { + minOffsetFound = partition.Info.StartingOffset.QuadPart; + + candidatePartition = partition; + + candidateForHiddenOSFound = true; + } + } + + if (!candidateForHiddenOSFound) + { + throw ErrorException (wstring (GetString ("NO_PARTITION_FOLLOWS_BOOT_PARTITION")) + + GetRemarksOnHiddenOS()); + } + + if (config.SystemPartition.Info.PartitionLength.QuadPart > TC_MAX_FAT_FS_SIZE) + { + if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS) + { + throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS_NTFS")) + + GetRemarksOnHiddenOS()); + } + } + else if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_FAT) + { + throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS")) + + GetRemarksOnHiddenOS()); + } + } + else + { + // No active partition on the system drive + throw ErrorException ("SYSTEM_PARTITION_NOT_ACTIVE"); + } + + HiddenOSCandidatePartition = candidatePartition; + return candidatePartition; + } + + + DWORD BootEncryption::GetDriverServiceStartType () + { + DWORD startType; + throw_sys_if (!ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", &startType)); + return startType; + } + + + wstring BootEncryption::GetRemarksOnHiddenOS () + { + return (wstring (L"\n\n") + + GetString ("TWO_SYSTEMS_IN_ONE_PARTITION_REMARK") + + L"\n\n" + + GetString ("FOR_MORE_INFO_ON_PARTITIONS")); + } + + + void BootEncryption::SetDriverServiceStartType (DWORD startType) + { + if (!IsAdmin() && IsUacSupported()) + { + Elevator::SetDriverServiceStartType (startType); + return; + } + + BOOL startOnBoot = (startType == SERVICE_BOOT_START); + + SC_HANDLE serviceManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + throw_sys_if (!serviceManager); + + finally_do_arg (SC_HANDLE, serviceManager, { CloseServiceHandle (finally_arg); }); + + SC_HANDLE service = OpenService (serviceManager, "truecrypt", SERVICE_CHANGE_CONFIG); + throw_sys_if (!service); + + finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); }); + + // Windows versions preceding Vista can be installed on FAT filesystem which does not + // support long filenames during boot. Convert the driver path to short form if required. + string driverPath; + if (startOnBoot && !IsOSAtLeast (WIN_VISTA)) + { + char pathBuf[MAX_PATH]; + char filesystem[128]; + + string path (GetWindowsDirectory()); + path += "\\drivers\\truecrypt.sys"; + + if (GetVolumePathName (path.c_str(), pathBuf, sizeof (pathBuf)) + && GetVolumeInformation (pathBuf, NULL, 0, NULL, NULL, NULL, filesystem, sizeof(filesystem)) + && memcmp (filesystem, "FAT", 3) == 0) + { + throw_sys_if (GetShortPathName (path.c_str(), pathBuf, sizeof (pathBuf)) == 0); + + // Convert absolute path to relative to the Windows directory + driverPath = pathBuf; + driverPath = driverPath.substr (driverPath.rfind ("\\", driverPath.rfind ("\\", driverPath.rfind ("\\") - 1) - 1) + 1); + + if (Is64BitOs()) + driverPath = "SysWOW64" + driverPath.substr (driverPath.find ("\\")); + } + } + + throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, + startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL, + driverPath.empty() ? NULL : driverPath.c_str(), + startOnBoot ? "Filter" : NULL, + NULL, NULL, NULL, NULL, NULL)); + + // ChangeServiceConfig() rejects SERVICE_BOOT_START with ERROR_INVALID_PARAMETER + throw_sys_if (!WriteLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", startType)); + } + + + void BootEncryption::ProbeRealSystemDriveSize () + { + if (RealSystemDriveSizeValid) + return; + + GetSystemDriveConfiguration(); + + ProbeRealDriveSizeRequest request; + _snwprintf (request.DeviceName, array_capacity (request.DeviceName), L"%hs", DriveConfig.DrivePartition.DevicePath.c_str()); + + CallDriver (TC_IOCTL_PROBE_REAL_DRIVE_SIZE, &request, sizeof (request), &request, sizeof (request)); + DriveConfig.DrivePartition.Info.PartitionLength = request.RealDriveSize; + + RealSystemDriveSizeValid = true; + + if (request.TimeOut) + throw TimeOut (SRC_POS); + } + + + void BootEncryption::InvalidateCachedSysDriveProperties () + { + DriveConfigValid = false; + RealSystemDriveSizeValid = false; + } + + + PartitionList BootEncryption::GetDrivePartitions (int driveNumber) + { + PartitionList partList; + + for (int partNumber = 0; partNumber < 64; ++partNumber) + { + stringstream partPath; + partPath << "\\Device\\Harddisk" << driveNumber << "\\Partition" << partNumber; + + DISK_PARTITION_INFO_STRUCT diskPartInfo; + _snwprintf (diskPartInfo.deviceName, array_capacity (diskPartInfo.deviceName), L"%hs", partPath.str().c_str()); + + try + { + CallDriver (TC_IOCTL_GET_DRIVE_PARTITION_INFO, &diskPartInfo, sizeof (diskPartInfo), &diskPartInfo, sizeof (diskPartInfo)); + } + catch (...) + { + continue; + } + + Partition part; + part.DevicePath = partPath.str(); + part.Number = partNumber; + part.Info = diskPartInfo.partInfo; + part.IsGPT = diskPartInfo.IsGPT; + + // Mount point + wstringstream ws; + ws << partPath.str().c_str(); + int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str()); + + if (driveNumber >= 0) + { + part.MountPoint += (char) (driveNumber + 'A'); + part.MountPoint += ":"; + } + + // Volume ID + wchar_t volumePath[TC_MAX_PATH]; + if (ResolveSymbolicLink ((wchar_t *) ws.str().c_str(), volumePath)) + { + wchar_t volumeName[TC_MAX_PATH]; + HANDLE fh = FindFirstVolumeW (volumeName, array_capacity (volumeName)); + if (fh != INVALID_HANDLE_VALUE) + { + do + { + wstring volumeNameStr = volumeName; + wchar_t devicePath[TC_MAX_PATH]; + + if (QueryDosDeviceW (volumeNameStr.substr (4, volumeNameStr.size() - 1 - 4).c_str(), devicePath, array_capacity (devicePath)) != 0 + && wcscmp (volumePath, devicePath) == 0) + { + part.VolumeNameId = volumeName; + break; + } + + } while (FindNextVolumeW (fh, volumeName, array_capacity (volumeName))); + + FindVolumeClose (fh); + } + } + + partList.push_back (part); + } + + return partList; + } + + + DISK_GEOMETRY BootEncryption::GetDriveGeometry (int driveNumber) + { + stringstream devName; + devName << "\\Device\\Harddisk" << driveNumber << "\\Partition0"; + + DISK_GEOMETRY geometry; + throw_sys_if (!::GetDriveGeometry ((char *) devName.str().c_str(), &geometry)); + return geometry; + } + + + string BootEncryption::GetWindowsDirectory () + { + char buf[MAX_PATH]; + throw_sys_if (GetSystemDirectory (buf, sizeof (buf)) == 0); + + return string (buf); + } + + + string BootEncryption::GetTempPath () + { + char tempPath[MAX_PATH]; + DWORD tempLen = ::GetTempPath (sizeof (tempPath), tempPath); + if (tempLen == 0 || tempLen > sizeof (tempPath)) + throw ParameterIncorrect (SRC_POS); + + return string (tempPath); + } + + + uint16 BootEncryption::GetInstalledBootLoaderVersion () + { + uint16 version; + CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version)); + return version; + } + + + // Note that this does not require admin rights (it just requires the driver to be running) + bool BootEncryption::IsBootLoaderOnDrive (char *devicePath) + { + try + { + OPEN_TEST_STRUCT openTestStruct; + memset (&openTestStruct, 0, sizeof (openTestStruct)); + DWORD dwResult; + + strcpy ((char *) &openTestStruct.wszFileName[0], devicePath); + ToUNICODE ((char *) &openTestStruct.wszFileName[0]); + + openTestStruct.bDetectTCBootLoader = TRUE; + + return (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, + &openTestStruct, sizeof (OPEN_TEST_STRUCT), + &openTestStruct, sizeof (OPEN_TEST_STRUCT), + &dwResult, NULL) && openTestStruct.TCBootLoaderDetected); + } + catch (...) + { + return false; + } + } + + + BootEncryptionStatus BootEncryption::GetStatus () + { + /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */ + + BootEncryptionStatus status; + CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status)); + return status; + } + + + void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties) + { + if (properties == NULL) + throw ParameterIncorrect (SRC_POS); + + CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties)); + } + + + bool BootEncryption::IsHiddenSystemRunning () + { + int hiddenSystemStatus; + + CallDriver (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING, nullptr, 0, &hiddenSystemStatus, sizeof (hiddenSystemStatus)); + return hiddenSystemStatus != 0; + } + + + bool BootEncryption::SystemDriveContainsPartitionType (byte type) + { + Device device (GetSystemDriveConfiguration().DevicePath, true); + + byte mbrBuf[SECTOR_SIZE]; + device.SeekAt (0); + device.Read (mbrBuf, sizeof (mbrBuf)); + + MBR *mbr = reinterpret_cast (mbrBuf); + if (mbr->Signature != 0xaa55) + throw ParameterIncorrect (SRC_POS); + + for (size_t i = 0; i < array_capacity (mbr->Partitions); ++i) + { + if (mbr->Partitions[i].Type == type) + return true; + } + + return false; + } + + + bool BootEncryption::SystemDriveContainsExtendedPartition () + { + return SystemDriveContainsPartitionType (PARTITION_EXTENDED) || SystemDriveContainsPartitionType (PARTITION_XINT13_EXTENDED); + } + + + bool BootEncryption::SystemDriveIsDynamic () + { + GetSystemDriveConfigurationRequest request; + _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str()); + + CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request)); + return request.DriveIsDynamic ? true : false; + } + + + SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration () + { + if (DriveConfigValid) + return DriveConfig; + + SystemDriveConfiguration config; + + string winDir = GetWindowsDirectory(); + + // Scan all drives + for (int driveNumber = 0; driveNumber < 32; ++driveNumber) + { + bool windowsFound = false; + bool activePartitionFound = false; + config.ExtraBootPartitionPresent = false; + config.SystemLoaderPresent = false; + + PartitionList partitions = GetDrivePartitions (driveNumber); + foreach (const Partition &part, partitions) + { + if (!part.MountPoint.empty() + && (_access ((part.MountPoint + "\\bootmgr").c_str(), 0) == 0 || _access ((part.MountPoint + "\\ntldr").c_str(), 0) == 0)) + { + config.SystemLoaderPresent = true; + } + else if (!part.VolumeNameId.empty() + && (_waccess ((part.VolumeNameId + L"\\bootmgr").c_str(), 0) == 0 || _waccess ((part.VolumeNameId + L"\\ntldr").c_str(), 0) == 0)) + { + config.SystemLoaderPresent = true; + } + + if (!windowsFound && !part.MountPoint.empty() && ToUpperCase (winDir).find (ToUpperCase (part.MountPoint)) == 0) + { + config.SystemPartition = part; + windowsFound = true; + } + + if (!activePartitionFound && part.Info.BootIndicator) + { + activePartitionFound = true; + + if (part.Info.PartitionLength.QuadPart > 0 && part.Info.PartitionLength.QuadPart <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE) + config.ExtraBootPartitionPresent = true; + } + } + + if (windowsFound) + { + config.DriveNumber = driveNumber; + + stringstream ss; + ss << "PhysicalDrive" << driveNumber; + config.DevicePath = ss.str(); + + stringstream kernelPath; + kernelPath << "\\Device\\Harddisk" << driveNumber << "\\Partition0"; + config.DeviceKernelPath = kernelPath.str(); + + config.DrivePartition = partitions.front(); + partitions.pop_front(); + config.Partitions = partitions; + + config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull; + config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart; + + foreach (const Partition &part, config.Partitions) + { + if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace) + config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart; + + config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart; + } + + DriveConfig = config; + DriveConfigValid = true; + return DriveConfig; + } + } + + throw ParameterIncorrect (SRC_POS); + } + + + bool BootEncryption::SystemPartitionCoversWholeDrive () + { + SystemDriveConfiguration config = GetSystemDriveConfiguration(); + + if (IsOSAtLeast (WIN_7) + && config.Partitions.size() == 2 + && config.ExtraBootPartitionPresent + && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 164 * BYTES_PER_MB) + { + return true; + } + + return config.Partitions.size() == 1 + && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 64 * BYTES_PER_MB; + } + + + uint32 BootEncryption::GetChecksum (byte *data, size_t size) + { + uint32 sum = 0; + + while (size-- > 0) + { + sum += *data++; + sum = _rotl (sum, 1); + } + + return sum; + } + + + void BootEncryption::CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation) + { + if (bufferSize < TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE) + throw ParameterIncorrect (SRC_POS); + + ZeroMemory (buffer, bufferSize); + + int ea = 0; + if (GetStatus().DriveMounted) + { + try + { + GetBootEncryptionAlgorithmNameRequest request; + CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME, NULL, 0, &request, sizeof (request)); + + if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0) + ea = AES; + else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0) + ea = SERPENT; + else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0) + ea = TWOFISH; + } + catch (...) + { + try + { + VOLUME_PROPERTIES_STRUCT properties; + GetVolumeProperties (&properties); + ea = properties.ea; + } + catch (...) { } + } + } + else + { + if (SelectedEncryptionAlgorithmId == 0) + throw ParameterIncorrect (SRC_POS); + + ea = SelectedEncryptionAlgorithmId; + } + + int bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR : IDR_BOOT_SECTOR; + int bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER : IDR_BOOT_LOADER; + + switch (ea) + { + case AES: + bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_AES : IDR_BOOT_SECTOR_AES; + bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_AES : IDR_BOOT_LOADER_AES; + break; + + case SERPENT: + bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SERPENT : IDR_BOOT_SECTOR_SERPENT; + bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SERPENT : IDR_BOOT_LOADER_SERPENT; + break; + + case TWOFISH: + bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_TWOFISH : IDR_BOOT_SECTOR_TWOFISH; + bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_TWOFISH : IDR_BOOT_LOADER_TWOFISH; + break; + } + + // Boot sector + DWORD size; + byte *bootSecResourceImg = MapResource ("BIN", bootSectorId, &size); + if (!bootSecResourceImg || size != SECTOR_SIZE) + throw ParameterIncorrect (SRC_POS); + + memcpy (buffer, bootSecResourceImg, size); + + *(uint16 *) (buffer + TC_BOOT_SECTOR_VERSION_OFFSET) = BE16 (VERSION_NUM); + + if (IsOSAtLeast (WIN_VISTA)) + buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER; + + // Checksum of the backup header of the outer volume for the hidden system + if (hiddenOSCreation) + { + Device device (GetSystemDriveConfiguration().DevicePath); + byte headerSector[SECTOR_SIZE]; + + device.SeekAt (HiddenOSCandidatePartition.Info.StartingOffset.QuadPart + HiddenOSCandidatePartition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE + TC_VOLUME_HEADER_EFFECTIVE_SIZE); + device.Read (headerSector, sizeof (headerSector)); + + *(uint32 *) (buffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET) = GetCrc32 (headerSector, sizeof (headerSector)); + } + + // Decompressor + byte *decompressor = MapResource ("BIN", IDR_BOOT_LOADER_DECOMPRESSOR, &size); + if (!decompressor || size > TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE) + throw ParameterIncorrect (SRC_POS); + + memcpy (buffer + SECTOR_SIZE, decompressor, size); + + // Compressed boot loader + byte *bootLoader = MapResource ("BIN", bootLoaderId, &size); + if (!bootLoader || size > TC_MAX_BOOT_LOADER_SECTOR_COUNT * SECTOR_SIZE) + throw ParameterIncorrect (SRC_POS); + + memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE, bootLoader, size); + + // Boot loader and decompressor checksum + *(uint16 *) (buffer + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET) = static_cast (size); + *(uint32 *) (buffer + TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET) = GetChecksum (buffer + SECTOR_SIZE, + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE + size); + + // Backup of decompressor and boot loader + if (size + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * SECTOR_SIZE <= TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE) + { + memcpy (buffer + SECTOR_SIZE + TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE, + buffer + SECTOR_SIZE, TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * SECTOR_SIZE); + + buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE; + } + else if (!rescueDisk && bootLoaderId != IDR_BOOT_LOADER) + { + throw ParameterIncorrect (SRC_POS); + } + } + + + void BootEncryption::ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig, string *customUserMessage, uint16 *bootLoaderVersion) + { + if (config && bufLength < TC_BOOT_CFG_FLAG_AREA_SIZE) + throw ParameterIncorrect (SRC_POS); + + GetSystemDriveConfigurationRequest request; + _snwprintf (request.DevicePath, array_capacity (request.DevicePath), L"%hs", GetSystemDriveConfiguration().DeviceKernelPath.c_str()); + + try + { + CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request)); + if (config) + *config = request.Configuration; + + if (userConfig) + *userConfig = request.UserConfiguration; + + if (customUserMessage) + { + request.CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0; + *customUserMessage = request.CustomUserMessage; + } + + if (bootLoaderVersion) + *bootLoaderVersion = request.BootLoaderVersion; + } + catch (...) + { + if (config) + *config = 0; + + if (userConfig) + *userConfig = 0; + + if (customUserMessage) + customUserMessage->clear(); + + if (bootLoaderVersion) + *bootLoaderVersion = 0; + } + } + + + void BootEncryption::WriteBootSectorConfig (const byte newConfig[]) + { + Device device (GetSystemDriveConfiguration().DevicePath); + byte mbr[SECTOR_SIZE]; + + device.SeekAt (0); + device.Read (mbr, sizeof (mbr)); + + memcpy (mbr + TC_BOOT_SECTOR_CONFIG_OFFSET, newConfig, TC_BOOT_CFG_FLAG_AREA_SIZE); + + device.SeekAt (0); + device.Write (mbr, sizeof (mbr)); + + byte mbrVerificationBuf[SECTOR_SIZE]; + device.SeekAt (0); + device.Read (mbrVerificationBuf, sizeof (mbr)); + + if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) + throw ErrorException ("ERROR_MBR_PROTECTED"); + } + + + void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage) + { + Device device (GetSystemDriveConfiguration().DevicePath); + byte mbr[SECTOR_SIZE]; + + device.SeekAt (0); + device.Read (mbr, sizeof (mbr)); + + if (!BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME) + || BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET)) > VERSION_NUM) + { + return; + } + + mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = userConfig; + + memset (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, 0, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); + + if (!customUserMessage.empty()) + { + if (customUserMessage.size() > TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH) + throw ParameterIncorrect (SRC_POS); + + memcpy (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, customUserMessage.c_str(), customUserMessage.size()); + } + + device.SeekAt (0); + device.Write (mbr, sizeof (mbr)); + + byte mbrVerificationBuf[SECTOR_SIZE]; + device.SeekAt (0); + device.Read (mbrVerificationBuf, sizeof (mbr)); + + if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) + throw ErrorException ("ERROR_MBR_PROTECTED"); + } + + + unsigned int BootEncryption::GetHiddenOSCreationPhase () + { + byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE]; + + ReadBootSectorConfig (configFlags, sizeof(configFlags)); + + return (configFlags[0] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE); + } + + + void BootEncryption::SetHiddenOSCreationPhase (unsigned int newPhase) + { +#if TC_BOOT_CFG_FLAG_AREA_SIZE != 1 +# error TC_BOOT_CFG_FLAG_AREA_SIZE != 1; revise GetHiddenOSCreationPhase() and SetHiddenOSCreationPhase() +#endif + byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE]; + + ReadBootSectorConfig (configFlags, sizeof(configFlags)); + + configFlags[0] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; + + configFlags[0] |= newPhase; + + WriteBootSectorConfig (configFlags); + } + + +#ifndef SETUP + + void BootEncryption::StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm) + { + if (!IsHiddenOSRunning()) + throw ParameterIncorrect (SRC_POS); + + WipeDecoySystemRequest request; + ZeroMemory (&request, sizeof (request)); + + request.WipeAlgorithm = wipeAlgorithm; + + if (Randinit() != ERR_SUCCESS) + throw ParameterIncorrect (SRC_POS); + + UserEnrichRandomPool (ParentWindow); + + if (!RandgetBytes (request.WipeKey, sizeof (request.WipeKey), TRUE)) + throw ParameterIncorrect (SRC_POS); + + CallDriver (TC_IOCTL_START_DECOY_SYSTEM_WIPE, &request, sizeof (request), NULL, 0); + + burn (&request, sizeof (request)); + } + + + void BootEncryption::AbortDecoyOSWipe () + { + CallDriver (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE); + } + + + DecoySystemWipeStatus BootEncryption::GetDecoyOSWipeStatus () + { + DecoySystemWipeStatus status; + CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS, NULL, 0, &status, sizeof (status)); + return status; + } + + + void BootEncryption::CheckDecoyOSWipeResult () + { + CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT); + } + + + void BootEncryption::WipeHiddenOSCreationConfig () + { + if (IsHiddenOSRunning() || Randinit() != ERR_SUCCESS) + throw ParameterIncorrect (SRC_POS); + + Device device (GetSystemDriveConfiguration().DevicePath); + byte mbr[SECTOR_SIZE]; + + device.SeekAt (0); + device.Read (mbr, sizeof (mbr)); + + finally_do_arg (BootEncryption *, this, + { + try + { + finally_arg->SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); + } catch (...) { } + }); + +#if PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE +# error PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE +#endif + + byte randData[PRAND_DISK_WIPE_PASSES]; + if (!RandgetBytes (randData, sizeof (randData), FALSE)) + throw ParameterIncorrect (SRC_POS); + + for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) + { + for (int i = 0; i < TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE; ++i) + { + mbr[TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + i] = randData[wipePass]; + } + + mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; + mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] |= randData[wipePass] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE; + + if (wipePass == PRAND_DISK_WIPE_PASSES - 1) + memset (mbr + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET, 0, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE); + + device.SeekAt (0); + device.Write (mbr, sizeof (mbr)); + } + + for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES/4 + 1; wipePass++) + { + SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); + SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING); + SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPING); + SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED); + } + SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); + } + +#endif // !SETUP + + + void BootEncryption::InstallBootLoader (bool preserveUserConfig, bool hiddenOSCreation) + { + byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; + CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation); + + // Write MBR + Device device (GetSystemDriveConfiguration().DevicePath); + byte mbr[SECTOR_SIZE]; + + device.SeekAt (0); + device.Read (mbr, sizeof (mbr)); + + if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME)) + { + uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET)); + if (version != 0) + { + bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; + memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); + } + } + + memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE); + + device.SeekAt (0); + device.Write (mbr, sizeof (mbr)); + + byte mbrVerificationBuf[SECTOR_SIZE]; + device.SeekAt (0); + device.Read (mbrVerificationBuf, sizeof (mbr)); + + if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0) + throw ErrorException ("ERROR_MBR_PROTECTED"); + + // Write boot loader + device.SeekAt (SECTOR_SIZE); + device.Write (bootLoaderBuf + SECTOR_SIZE, sizeof (bootLoaderBuf) - SECTOR_SIZE); + } + + + string BootEncryption::GetSystemLoaderBackupPath () + { + char pathBuf[MAX_PATH]; + + throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf))); + + string path = string (pathBuf) + "\\" TC_APP_NAME; + CreateDirectory (path.c_str(), NULL); + + return path + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME; + } + + + void BootEncryption::RenameDeprecatedSystemLoaderBackup () + { + char pathBuf[MAX_PATH]; + + if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA, NULL, 0, pathBuf))) + { + string path = string (pathBuf) + "\\" TC_APP_NAME + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY; + + if (FileExists (path.c_str()) && !FileExists (GetSystemLoaderBackupPath().c_str())) + throw_sys_if (rename (path.c_str(), GetSystemLoaderBackupPath().c_str()) != 0); + } + } + + +#ifndef SETUP + void BootEncryption::CreateRescueIsoImage (bool initialSetup, const string &isoImagePath) + { + BootEncryptionStatus encStatus = GetStatus(); + if (encStatus.SetupInProgress) + throw ParameterIncorrect (SRC_POS); + + Buffer imageBuf (RescueIsoImageSize); + + byte *image = imageBuf.Ptr(); + memset (image, 0, RescueIsoImageSize); + + // Primary volume descriptor + strcpy ((char *)image + 0x8000, "\001CD001\001"); + strcpy ((char *)image + 0x7fff + 41, "TrueCrypt Rescue Disk "); + *(uint32 *) (image + 0x7fff + 81) = RescueIsoImageSize / 2048; + *(uint32 *) (image + 0x7fff + 85) = BE32 (RescueIsoImageSize / 2048); + image[0x7fff + 121] = 1; + image[0x7fff + 124] = 1; + image[0x7fff + 125] = 1; + image[0x7fff + 128] = 1; + image[0x7fff + 130] = 8; + image[0x7fff + 131] = 8; + + image[0x7fff + 133] = 10; + image[0x7fff + 140] = 10; + image[0x7fff + 141] = 0x14; + image[0x7fff + 157] = 0x22; + image[0x7fff + 159] = 0x18; + + // Boot record volume descriptor + strcpy ((char *)image + 0x8801, "CD001\001EL TORITO SPECIFICATION"); + image[0x8800 + 0x47] = 0x19; + + // Volume descriptor set terminator + strcpy ((char *)image + 0x9000, "\377CD001\001"); + + // Path table + image[0xA000 + 0] = 1; + image[0xA000 + 2] = 0x18; + image[0xA000 + 6] = 1; + + // Root directory + image[0xc000 + 0] = 0x22; + image[0xc000 + 2] = 0x18; + image[0xc000 + 9] = 0x18; + image[0xc000 + 11] = 0x08; + image[0xc000 + 16] = 0x08; + image[0xc000 + 25] = 0x02; + image[0xc000 + 28] = 0x01; + image[0xc000 + 31] = 0x01; + image[0xc000 + 32] = 0x01; + image[0xc000 + 34] = 0x22; + image[0xc000 + 36] = 0x18; + image[0xc000 + 43] = 0x18; + image[0xc000 + 45] = 0x08; + image[0xc000 + 50] = 0x08; + image[0xc000 + 59] = 0x02; + image[0xc000 + 62] = 0x01; + *(uint32 *) (image + 0xc000 + 65) = 0x010101; + + // Validation entry + image[0xc800] = 1; + int offset = 0xc800 + 0x1c; + image[offset++] = 0xaa; + image[offset++] = 0x55; + image[offset++] = 0x55; + image[offset] = 0xaa; + + // Initial entry + offset = 0xc820; + image[offset++] = 0x88; + image[offset++] = 2; + image[0xc820 + 6] = 1; + image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR; + + // TrueCrypt Boot Loader + CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, true); + + // Volume header + if (initialSetup) + { + if (!RescueVolumeHeaderValid) + throw ParameterIncorrect (SRC_POS); + + memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + } + else + { + Device bootDevice (GetSystemDriveConfiguration().DevicePath, true); + bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); + bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + } + + // Original system loader + try + { + File sysBakFile (GetSystemLoaderBackupPath(), true); + sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE); + + image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER; + } + catch (Exception &e) + { + e.Show (ParentWindow); + Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK"); + } + + // Boot loader backup + CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, false); + + RescueIsoImage = new byte[RescueIsoImageSize]; + if (!RescueIsoImage) + throw bad_alloc(); + memcpy (RescueIsoImage, image, RescueIsoImageSize); + + if (!isoImagePath.empty()) + { + File isoFile (isoImagePath, false, true); + isoFile.Write (image, RescueIsoImageSize); + } + } +#endif + + bool BootEncryption::VerifyRescueDisk () + { + if (!RescueIsoImage) + throw ParameterIncorrect (SRC_POS); + + for (char drive = 'Z'; drive >= 'D'; --drive) + { + try + { + string path = "X:"; + path[0] = drive; + + Device driveDevice (path, true); + size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048; + Buffer buffer ((verifiedSectorCount + 1) * 2048); + + DWORD bytesRead = driveDevice.Read (buffer.Ptr(), buffer.Size()); + if (bytesRead != buffer.Size()) + continue; + + if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0) + return true; + } + catch (...) { } + } + + return false; + } + + +#ifndef SETUP + + void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5) + { + PCRYPTO_INFO cryptoInfo = NULL; + + if (!IsRandomNumberGeneratorStarted()) + throw ParameterIncorrect (SRC_POS); + + throw_sys_if (CreateVolumeHeaderInMemory (TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, NULL, &cryptoInfo, + volumeSize, 0, encryptedAreaStart, 0, TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION, TC_HEADER_FLAG_ENCRYPTED_SYSTEM, FALSE) != 0); + + finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); }); + + // Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize) + memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader)); + ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, NULL, cryptoInfo); + + DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); + + if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x54525545) + throw ParameterIncorrect (SRC_POS); + + byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH; + mputInt64 (fieldPos, volumeSize); + + // CRC of the header fields + uint32 crc = GetCrc32 (RescueVolumeHeader + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); + fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_HEADER_CRC; + mputLong (fieldPos, crc); + + EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); + + VolumeHeaderValid = true; + RescueVolumeHeaderValid = true; + } + + + void BootEncryption::InstallVolumeHeader () + { + if (!VolumeHeaderValid) + throw ParameterIncorrect (SRC_POS); + + Device device (GetSystemDriveConfiguration().DevicePath); + + device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); + device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader)); + } + + + // For synchronous operations use AbortSetupWait() + void BootEncryption::AbortSetup () + { + CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); + } + + + // For asynchronous operations use AbortSetup() + void BootEncryption::AbortSetupWait () + { + CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); + + BootEncryptionStatus encStatus = GetStatus(); + + while (encStatus.SetupInProgress) + { + Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL); + encStatus = GetStatus(); + } + } + + + void BootEncryption::BackupSystemLoader () + { + Device device (GetSystemDriveConfiguration().DevicePath, true); + + byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE]; + + device.SeekAt (0); + device.Read (bootLoaderBuf, sizeof (bootLoaderBuf)); + + // Prevent TrueCrypt loader from being backed up + for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i) + { + if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0) + { + if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED") == IDNO) + throw UserAbort (SRC_POS); + return; + } + } + + File backupFile (GetSystemLoaderBackupPath(), false, true); + backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf)); + } + + + void BootEncryption::RestoreSystemLoader () + { + byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE]; + + File backupFile (GetSystemLoaderBackupPath(), true); + + if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf)) + throw ParameterIncorrect (SRC_POS); + + Device device (GetSystemDriveConfiguration().DevicePath); + + // Preserve current partition table + byte mbr[SECTOR_SIZE]; + device.SeekAt (0); + device.Read (mbr, sizeof (mbr)); + memcpy (bootLoaderBuf + TC_MAX_MBR_BOOT_CODE_SIZE, mbr + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbr) - TC_MAX_MBR_BOOT_CODE_SIZE); + + device.SeekAt (0); + device.Write (bootLoaderBuf, sizeof (bootLoaderBuf)); + } + +#endif // SETUP + + void BootEncryption::RegisterDeviceClassFilter (bool registerFilter, const GUID *deviceClassGuid) + { + HKEY classRegKey = SetupDiOpenClassRegKey (deviceClassGuid, KEY_READ | KEY_WRITE); + throw_sys_if (classRegKey == INVALID_HANDLE_VALUE); + finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); }); + + if (registerFilter) + { + // Register class filter below all other filters in the stack + + size_t strSize = strlen ("truecrypt") + 1; + byte regKeyBuf[65536]; + DWORD size = sizeof (regKeyBuf) - strSize; + + // SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly + strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf)); + + if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS) + size = 1; + + throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS); + } + else + { + // Unregister a class filter + string infFileName = GetTempPath() + "\\truecrypt_device_filter.inf"; + + File infFile (infFileName, false, true); + finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); }); + + string infTxt = "[truecrypt]\r\n" + "DelReg=truecrypt_reg\r\n\r\n" + "[truecrypt_reg]\r\n" + "HKR,,\"UpperFilters\",0x00018002,\"truecrypt\"\r\n"; + + infFile.Write ((byte *) infTxt.c_str(), infTxt.size()); + infFile.Close(); + + HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); + throw_sys_if (hInf == INVALID_HANDLE_VALUE); + finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); }); + + throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL)); + } + } + + void BootEncryption::RegisterFilterDriver (bool registerDriver, bool volumeClass) + { + if (!IsAdmin() && IsUacSupported()) + { + Elevator::RegisterFilterDriver (registerDriver, volumeClass); + return; + } + + if (volumeClass) + { + RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_VOLUME); + RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_FLOPPYDISK); + } + else + { + RegisterDeviceClassFilter (registerDriver, &GUID_DEVCLASS_DISKDRIVE); + } + } + +#ifndef SETUP + + void BootEncryption::RegisterSystemFavoritesService (BOOL registerService) + { + if (!IsAdmin() && IsUacSupported()) + { + Elevator::RegisterSystemFavoritesService (registerService); + return; + } + + SC_HANDLE scm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + throw_sys_if (!scm); + + if (registerService) + { + char appPath[TC_MAX_PATH]; + throw_sys_if (!GetModuleFileName (NULL, appPath, sizeof (appPath))); + + SC_HANDLE service = CreateService (scm, + TC_SYSTEM_FAVORITES_SERVICE_NAME, + TC_APP_NAME " System Favorites", + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, + (string ("\"") + appPath + "\" " TC_SYSTEM_FAVORITES_SERVICE_CMDLINE_OPTION).c_str(), + TC_SYSTEM_FAVORITES_SERVICE_LOAD_ORDER_GROUP, + NULL, + NULL, + NULL, + NULL); + + throw_sys_if (!service); + + SERVICE_DESCRIPTION description; + description.lpDescription = "Mounts TrueCrypt system favorite volumes."; + ChangeServiceConfig2 (service, SERVICE_CONFIG_DESCRIPTION, &description); + + CloseServiceHandle (service); + + try + { + SetDriverConfigurationFlag (TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES, true); + } + catch (...) + { + try + { + RegisterSystemFavoritesService (false); + } + catch (...) { } + + throw; + } + } + else + { + SetDriverConfigurationFlag (TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES, false); + + SC_HANDLE service = OpenService (scm, TC_SYSTEM_FAVORITES_SERVICE_NAME, SERVICE_ALL_ACCESS); + throw_sys_if (!service); + + throw_sys_if (!DeleteService (service)); + CloseServiceHandle (service); + } + } + + void BootEncryption::CheckRequirements () + { + if (nCurrentOS == WIN_2000) + throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS"); + + if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1) + throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_VISTA_SP0"); + + if (IsNonInstallMode()) + throw ErrorException ("FEATURE_REQUIRES_INSTALLATION"); + + SystemDriveConfiguration config = GetSystemDriveConfiguration (); + + if (config.SystemPartition.IsGPT) + throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED"); + + if (SystemDriveIsDynamic()) + throw ErrorException ("SYSENC_UNSUPPORTED_FOR_DYNAMIC_DISK"); + + if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE) + throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER"); + + DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber); + + if (geometry.BytesPerSector != SECTOR_SIZE) + throw ErrorException ("LARGE_SECTOR_UNSUPPORTED"); + + bool activePartitionFound = false; + if (!config.SystemPartition.IsGPT) + { + // Determine whether there is an Active partition on the system drive + foreach (const Partition &partition, config.Partitions) + { + if (partition.Info.BootIndicator) + { + activePartitionFound = true; + break; + } + } + } + + if (!config.SystemLoaderPresent || !activePartitionFound) + { + static bool confirmed = false; + + if (!confirmed && AskWarnNoYes ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR") == IDNO) + throw UserAbort (SRC_POS); + + confirmed = true; + } + } + + + void BootEncryption::CheckRequirementsHiddenOS () + { + // It is assumed that CheckRequirements() had been called (so we don't check e.g. whether it's GPT). + + // The user may have modified/added/deleted partitions since the partition table was last scanned. + InvalidateCachedSysDriveProperties (); + + GetPartitionForHiddenOS (); + } + + + void BootEncryption::InitialSecurityChecksForHiddenOS () + { + char windowsDrive = (char) toupper (GetWindowsDirectory()[0]); + + // Paging files + bool pagingFilesOk = !IsPagingFileActive (TRUE); + + char pagingFileRegData[65536]; + DWORD pagingFileRegDataSize = sizeof (pagingFileRegData); + + if (ReadLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", pagingFileRegData, &pagingFileRegDataSize) + && pagingFileRegDataSize > 4) + { + for (size_t i = 1; i < pagingFileRegDataSize - 2; ++i) + { + if (memcmp (pagingFileRegData + i, ":\\", 2) == 0 && toupper (pagingFileRegData[i - 1]) != windowsDrive) + { + pagingFilesOk = false; + break; + } + } + } + + if (!pagingFilesOk) + { + if (AskWarnYesNoString ((wchar_t *) (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION")) + + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION") + + L"\n\n\n" + + GetString ("RESTRICT_PAGING_FILES_TO_SYS_PARTITION") + ).c_str()) == IDYES) + { + RestrictPagingFilesToSystemPartition(); + RestartComputer(); + AbortProcessSilent(); + } + + throw ErrorException (wstring (GetString ("PAGING_FILE_NOT_ON_SYS_PARTITION")) + + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); + } + + // User profile + char *configPath = GetConfigPath ("dummy"); + if (configPath && toupper (configPath[0]) != windowsDrive) + { + throw ErrorException (wstring (GetString ("USER_PROFILE_NOT_ON_SYS_PARTITION")) + + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); + } + + // Temporary files + if (toupper (GetTempPath()[0]) != windowsDrive) + { + throw ErrorException (wstring (GetString ("TEMP_NOT_ON_SYS_PARTITION")) + + GetString ("LEAKS_OUTSIDE_SYSPART_UNIVERSAL_EXPLANATION")); + } + } + + + void BootEncryption::Deinstall () + { + BootEncryptionStatus encStatus = GetStatus(); + + if (encStatus.DriveEncrypted || encStatus.DriveMounted) + throw ParameterIncorrect (SRC_POS); + + SystemDriveConfiguration config = GetSystemDriveConfiguration (); + + if (encStatus.VolumeHeaderPresent) + { + // Verify CRC of header salt + Device device (config.DevicePath, true); + byte header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; + + device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET); + device.Read (header, sizeof (header)); + + if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE)) + throw ParameterIncorrect (SRC_POS); + } + + RegisterFilterDriver (false, false); + RegisterFilterDriver (false, true); + SetDriverServiceStartType (SERVICE_SYSTEM_START); + + SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE); // In case RestoreSystemLoader() fails + + try + { + RegisterSystemFavoritesService (false); + } + catch (...) { } + + try + { + RestoreSystemLoader (); + } + catch (Exception &e) + { + e.Show (ParentWindow); + throw ErrorException ("SYS_LOADER_RESTORE_FAILED"); + } + + } + + + int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5) + { + BootEncryptionStatus encStatus = GetStatus(); + + if (encStatus.SetupInProgress) + throw ParameterIncorrect (SRC_POS); + + SystemDriveConfiguration config = GetSystemDriveConfiguration (); + + char header[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; + Device device (config.DevicePath); + + // Only one algorithm is currently supported + if (pkcs5 != 0) + throw ParameterIncorrect (SRC_POS); + + int64 headerOffset = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + int64 backupHeaderOffset = -1; + + if (encStatus.HiddenSystem) + { + headerOffset = encStatus.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; + + // Find hidden system partition + foreach (const Partition &partition, config.Partitions) + { + if (partition.Info.StartingOffset.QuadPart == encStatus.HiddenSystemPartitionStart) + { + backupHeaderOffset = partition.Info.StartingOffset.QuadPart + partition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_SIZE; + break; + } + } + + if (backupHeaderOffset == -1) + throw ParameterIncorrect (SRC_POS); + } + + device.SeekAt (headerOffset); + device.Read ((byte *) header, sizeof (header)); + + PCRYPTO_INFO cryptoInfo = NULL; + + int status = ReadVolumeHeader (!encStatus.HiddenSystem, header, oldPassword, &cryptoInfo, NULL); + finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); }); + + if (status != 0) + { + handleError (ParentWindow, status); + return status; + } + + // Change the PKCS-5 PRF if requested by user + if (pkcs5 != 0) + { + cryptoInfo->pkcs5 = pkcs5; + RandSetHashFunction (pkcs5); + } + + throw_sys_if (Randinit () != 0); + finally_do ({ RandStop (FALSE); }); + + NormalCursor(); + UserEnrichRandomPool (ParentWindow); + WaitCursor(); + + /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using + techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy + to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22 + times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might + impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the + valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman + recommends. During each pass we will write a valid working header. Each pass will use the same master + key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only + item that will be different for each pass will be the salt. This is sufficient to cause each "version" + of the header to differ substantially and in a random manner from the versions written during the + other passes. */ + + bool headerUpdated = false; + int result = ERR_SUCCESS; + + try + { + BOOL backupHeader = FALSE; + while (TRUE) + { + for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) + { + PCRYPTO_INFO tmpCryptoInfo = NULL; + + status = CreateVolumeHeaderInMemory (!encStatus.HiddenSystem, + header, + cryptoInfo->ea, + cryptoInfo->mode, + newPassword, + cryptoInfo->pkcs5, + (char *) cryptoInfo->master_keydata, + &tmpCryptoInfo, + cryptoInfo->VolumeSize.Value, + cryptoInfo->hiddenVolumeSize, + cryptoInfo->EncryptedAreaStart.Value, + cryptoInfo->EncryptedAreaLength.Value, + cryptoInfo->RequiredProgramVersion, + cryptoInfo->HeaderFlags | TC_HEADER_FLAG_ENCRYPTED_SYSTEM, + wipePass < PRAND_DISK_WIPE_PASSES - 1); + + if (tmpCryptoInfo) + crypto_close (tmpCryptoInfo); + + if (status != 0) + { + handleError (ParentWindow, status); + return status; + } + + device.SeekAt (headerOffset); + device.Write ((byte *) header, sizeof (header)); + headerUpdated = true; + } + + if (!encStatus.HiddenSystem || backupHeader) + break; + + backupHeader = TRUE; + headerOffset = backupHeaderOffset; + } + } + catch (Exception &e) + { + e.Show (ParentWindow); + result = ERR_OS_ERROR; + } + + if (headerUpdated) + { + ReopenBootVolumeHeaderRequest reopenRequest; + reopenRequest.VolumePassword = *newPassword; + finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); }); + + CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest)); + } + + return result; + } + + + void BootEncryption::CheckEncryptionSetupResult () + { + CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT); + } + + + void BootEncryption::Install (bool hiddenSystem) + { + BootEncryptionStatus encStatus = GetStatus(); + if (encStatus.DriveMounted) + throw ParameterIncorrect (SRC_POS); + + try + { + InstallBootLoader (false, hiddenSystem); + + if (!hiddenSystem) + InstallVolumeHeader (); + + RegisterBootDriver (hiddenSystem); + } + catch (Exception &) + { + try + { + RestoreSystemLoader (); + } + catch (Exception &e) + { + e.Show (ParentWindow); + } + + throw; + } + } + + + void BootEncryption::PrepareHiddenOSCreation (int ea, int mode, int pkcs5) + { + BootEncryptionStatus encStatus = GetStatus(); + if (encStatus.DriveMounted) + throw ParameterIncorrect (SRC_POS); + + CheckRequirements(); + BackupSystemLoader(); + + SelectedEncryptionAlgorithmId = ea; + } + + + void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath) + { + BootEncryptionStatus encStatus = GetStatus(); + if (encStatus.DriveMounted) + throw ParameterIncorrect (SRC_POS); + + CheckRequirements (); + + SystemDriveConfiguration config = GetSystemDriveConfiguration(); + + // Some chipset drivers may prevent access to the last sector of the drive + if (!systemPartitionOnly) + { + DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber); + Buffer sector (geometry.BytesPerSector); + + Device device (config.DevicePath); + + try + { + device.SeekAt (config.DrivePartition.Info.PartitionLength.QuadPart - geometry.BytesPerSector); + device.Read (sector.Ptr(), sector.Size()); + } + catch (SystemException &e) + { + if (e.ErrorCode != ERROR_CRC) + { + e.Show (ParentWindow); + Error ("WHOLE_DRIVE_ENCRYPTION_PREVENTED_BY_DRIVERS"); + throw UserAbort (SRC_POS); + } + } + } + + BackupSystemLoader (); + + uint64 volumeSize; + uint64 encryptedAreaStart; + + if (systemPartitionOnly) + { + volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart; + encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart; + } + else + { + volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE; + encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE; + } + + SelectedEncryptionAlgorithmId = ea; + CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5); + + if (!rescueIsoImagePath.empty()) + CreateRescueIsoImage (true, rescueIsoImagePath); + } + + bool BootEncryption::IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) + { + if (!IsAdmin() && IsUacSupported()) + return Elevator::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false; + + return ::IsPagingFileActive (checkNonWindowsPartitionsOnly) ? true : false; + } + + void BootEncryption::RestrictPagingFilesToSystemPartition () + { + char pagingFiles[128]; + strncpy (pagingFiles, "X:\\pagefile.sys 0 0", sizeof (pagingFiles)); + pagingFiles[0] = GetWindowsDirectory()[0]; + + throw_sys_if (!WriteLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", pagingFiles, strlen (pagingFiles) + 2)); + } + + void BootEncryption::WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value) + { + if (!IsAdmin() && IsUacSupported()) + { + Elevator::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value); + return; + } + + throw_sys_if (!WriteLocalMachineRegistryDword (keyPath, valueName, value)); + } + + uint32 BootEncryption::ReadDriverConfigurationFlags () + { + DWORD configMap; + + if (!ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, &configMap)) + configMap = 0; + + return configMap; + } + + void BootEncryption::SetDriverConfigurationFlag (uint32 flag, bool state) + { + DWORD configMap = ReadDriverConfigurationFlags(); + + if (state) + configMap |= flag; + else + configMap &= ~flag; + + WriteLocalMachineRegistryDwordValue ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, configMap); + } + + void BootEncryption::StartDecryption (BOOL discardUnreadableEncryptedSectors) + { + BootEncryptionStatus encStatus = GetStatus(); + + if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress) + throw ParameterIncorrect (SRC_POS); + + BootEncryptionSetupRequest request; + ZeroMemory (&request, sizeof (request)); + + request.SetupMode = SetupDecryption; + request.DiscardUnreadableEncryptedSectors = discardUnreadableEncryptedSectors; + + CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0); + } + + void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm, bool zeroUnreadableSectors) + { + BootEncryptionStatus encStatus = GetStatus(); + + if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress) + throw ParameterIncorrect (SRC_POS); + + BootEncryptionSetupRequest request; + ZeroMemory (&request, sizeof (request)); + + request.SetupMode = SetupEncryption; + request.WipeAlgorithm = wipeAlgorithm; + request.ZeroUnreadableSectors = zeroUnreadableSectors; + + CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0); + } + + void BootEncryption::CopyFileAdmin (const string &sourceFile, const string &destinationFile) + { + if (!IsAdmin()) + { + if (!IsUacSupported()) + { + SetLastError (ERROR_ACCESS_DENIED); + throw SystemException(); + } + else + Elevator::CopyFile (sourceFile, destinationFile); + } + else + throw_sys_if (!::CopyFile (sourceFile.c_str(), destinationFile.c_str(), FALSE)); + } + + void BootEncryption::DeleteFileAdmin (const string &file) + { + if (!IsAdmin() && IsUacSupported()) + Elevator::DeleteFile (file); + else + throw_sys_if (!::DeleteFile (file.c_str())); + } + +#endif // !SETUP + + + void BootEncryption::WriteBootDriveSector (uint64 offset, byte *data) + { + WriteBootDriveSectorRequest request; + request.Offset.QuadPart = offset; + memcpy (request.Data, data, sizeof (request.Data)); + + CallDriver (TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR, &request, sizeof (request), NULL, 0); + } + + + void BootEncryption::RegisterBootDriver (bool hiddenSystem) + { + SetDriverServiceStartType (SERVICE_BOOT_START); + + try + { + RegisterFilterDriver (false, false); + RegisterFilterDriver (false, true); + } + catch (...) { } + + RegisterFilterDriver (true, false); + + if (hiddenSystem) + RegisterFilterDriver (true, true); + } + + + bool BootEncryption::RestartComputer (void) + { + return (::RestartComputer() != FALSE); + } +} diff --git a/Common/BootEncryption.h b/Common/BootEncryption.h index 4f49a07..46d90a5 100644 --- a/Common/BootEncryption.h +++ b/Common/BootEncryption.h @@ -1,222 +1,232 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Common_BootEncryption -#define TC_HEADER_Common_BootEncryption - -#include "Tcdefs.h" -#include "Dlgcode.h" -#include "Exception.h" -#include "Platform/PlatformBase.h" -#include "Volumes.h" - -using namespace std; - -namespace TrueCrypt -{ - class File - { - public: - File () : FileOpen (false) { } - File (string path, bool readOnly = false, bool create = false); - ~File () { Close(); } - - void Close (); - DWORD Read (byte *buffer, DWORD size); - void Write (byte *buffer, DWORD size); - void SeekAt (int64 position); - - protected: - bool Elevated; - bool FileOpen; - uint64 FilePointerPosition; - HANDLE Handle; - bool IsDevice; - string Path; - }; - - - class Device : public File - { - public: - Device (string path, bool readOnly = false); - }; - - - class Buffer - { - public: - Buffer (size_t size) : DataSize (size) - { - DataPtr = new byte[size]; - if (!DataPtr) - throw bad_alloc(); - } - - ~Buffer () { delete DataPtr; } - byte *Ptr () const { return DataPtr; } - size_t Size () const { return DataSize; } - - protected: - byte *DataPtr; - size_t DataSize; - }; - - - struct Partition - { - string DevicePath; - PARTITION_INFORMATION Info; - string MountPoint; - int Number; - BOOL IsGPT; - wstring VolumeNameId; - }; - - typedef list PartitionList; - -#pragma pack (push) -#pragma pack(1) - - struct PartitionEntryMBR - { - byte BootIndicator; - - byte StartHead; - byte StartCylSector; - byte StartCylinder; - - byte Type; - - byte EndHead; - byte EndSector; - byte EndCylinder; - - uint32 StartLBA; - uint32 SectorCountLBA; - }; - - struct MBR - { - byte Code[446]; - PartitionEntryMBR Partitions[4]; - uint16 Signature; - }; - -#pragma pack (pop) - - struct SystemDriveConfiguration - { - string DeviceKernelPath; - string DevicePath; - int DriveNumber; - Partition DrivePartition; - int64 InitialUnallocatedSpace; - PartitionList Partitions; - Partition SystemPartition; - int64 TotalUnallocatedSpace; - bool SystemLoaderPresent; - }; - - class BootEncryption - { - public: - BootEncryption (HWND parent); - ~BootEncryption (); - - void AbortDecoyOSWipe (); - void AbortSetup (); - void AbortSetupWait (); - void CallDriver (DWORD ioctl, void *input = nullptr, DWORD inputSize = 0, void *output = nullptr, DWORD outputSize = 0); - int ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5); - void CheckDecoyOSWipeResult (); - void CheckEncryptionSetupResult (); - void CheckRequirements (); - void CheckRequirementsHiddenOS (); - void CreateRescueIsoImage (bool initialSetup, const string &isoImagePath); - void Deinstall (); - DecoySystemWipeStatus GetDecoyOSWipeStatus (); - DWORD GetDriverServiceStartType (); - unsigned int GetHiddenOSCreationPhase (); - uint16 GetInstalledBootLoaderVersion (); - Partition GetPartitionForHiddenOS (); - bool IsBootLoaderOnDrive (char *devicePath); - BootEncryptionStatus GetStatus (); - string GetTempPath (); - void GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties); - SystemDriveConfiguration GetSystemDriveConfiguration (); - void Install (bool hiddenSystem); - void InstallBootLoader (bool preserveUserConfig = false, bool hiddenOSCreation = false); - void InvalidateCachedSysDriveProperties (); - bool IsHiddenSystemRunning (); - bool IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); - void PrepareHiddenOSCreation (int ea, int mode, int pkcs5); - void PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath); - void ProbeRealSystemDriveSize (); - void ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig = nullptr, string *customUserMessage = nullptr, uint16 *bootLoaderVersion = nullptr); - void RegisterBootDriver (bool hiddenSystem); - void RegisterFilterDriver (bool registerDriver, bool volumeClass); - void RenameDeprecatedSystemLoaderBackup (); - bool RestartComputer (void); - void InitialSecurityChecksForHiddenOS (); - void RestrictPagingFilesToSystemPartition (); - void SetDriverServiceStartType (DWORD startType); - void SetHiddenOSCreationPhase (unsigned int newPhase); - void StartDecryption (BOOL discardUnreadableEncryptedSectors); - void StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm); - void StartEncryption (WipeAlgorithmId wipeAlgorithm, bool zeroUnreadableSectors); - bool SystemDriveContainsPartitionType (byte type); - bool SystemDriveContainsExtendedPartition (); - bool SystemPartitionCoversWholeDrive (); - bool SystemDriveIsDynamic (); - bool VerifyRescueDisk (); - void WipeHiddenOSCreationConfig (); - void WriteBootDriveSector (uint64 offset, byte *data); - void WriteBootSectorConfig (const byte newConfig[]); - void WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage); - void WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value); - - protected: - static const uint32 RescueIsoImageSize = 1835008; // Size of ISO9660 image with bootable emulated 1.44MB floppy disk image - - void BackupSystemLoader (); - void CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation = false); - void CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5); - string GetSystemLoaderBackupPath (); - uint32 GetChecksum (byte *data, size_t size); - DISK_GEOMETRY GetDriveGeometry (int driveNumber); - PartitionList GetDrivePartitions (int driveNumber); - wstring GetRemarksOnHiddenOS (); - string GetWindowsDirectory (); - void RegisterDeviceClassFilter (bool registerFilter, const GUID *deviceClassGuid); - void RestoreSystemLoader (); - void InstallVolumeHeader (); - - HWND ParentWindow; - SystemDriveConfiguration DriveConfig; - int SelectedEncryptionAlgorithmId; - Partition HiddenOSCandidatePartition; - byte *RescueIsoImage; - byte RescueVolumeHeader[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; - byte VolumeHeader[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; - bool DriveConfigValid; - bool RealSystemDriveSizeValid; - bool RescueVolumeHeaderValid; - bool VolumeHeaderValid; - }; -} - -#define TC_ABORT_TRANSFORM_WAIT_INTERVAL 10 - -#define MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS 2.1 -#define MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_FAT 1.05 - -#define TC_SYS_BOOT_LOADER_BACKUP_NAME "Original System Loader" -#define TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY "Original System Loader.bak" // Deprecated to prevent removal by some "cleaners" - -#endif // TC_HEADER_Common_BootEncryption +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Common_BootEncryption +#define TC_HEADER_Common_BootEncryption + +#include "Tcdefs.h" +#include "Dlgcode.h" +#include "Exception.h" +#include "Platform/PlatformBase.h" +#include "Volumes.h" + +using namespace std; + +namespace TrueCrypt +{ + class File + { + public: + File () : FileOpen (false) { } + File (string path, bool readOnly = false, bool create = false); + ~File () { Close(); } + + void Close (); + DWORD Read (byte *buffer, DWORD size); + void Write (byte *buffer, DWORD size); + void SeekAt (int64 position); + + protected: + bool Elevated; + bool FileOpen; + uint64 FilePointerPosition; + HANDLE Handle; + bool IsDevice; + string Path; + }; + + + class Device : public File + { + public: + Device (string path, bool readOnly = false); + }; + + + class Buffer + { + public: + Buffer (size_t size) : DataSize (size) + { + DataPtr = new byte[size]; + if (!DataPtr) + throw bad_alloc(); + } + + ~Buffer () { delete DataPtr; } + byte *Ptr () const { return DataPtr; } + size_t Size () const { return DataSize; } + + protected: + byte *DataPtr; + size_t DataSize; + }; + + + struct Partition + { + string DevicePath; + PARTITION_INFORMATION Info; + string MountPoint; + size_t Number; + BOOL IsGPT; + wstring VolumeNameId; + }; + + typedef list PartitionList; + +#pragma pack (push) +#pragma pack(1) + + struct PartitionEntryMBR + { + byte BootIndicator; + + byte StartHead; + byte StartCylSector; + byte StartCylinder; + + byte Type; + + byte EndHead; + byte EndSector; + byte EndCylinder; + + uint32 StartLBA; + uint32 SectorCountLBA; + }; + + struct MBR + { + byte Code[446]; + PartitionEntryMBR Partitions[4]; + uint16 Signature; + }; + +#pragma pack (pop) + + struct SystemDriveConfiguration + { + string DeviceKernelPath; + string DevicePath; + int DriveNumber; + Partition DrivePartition; + bool ExtraBootPartitionPresent; + int64 InitialUnallocatedSpace; + PartitionList Partitions; + Partition SystemPartition; + int64 TotalUnallocatedSpace; + bool SystemLoaderPresent; + }; + + class BootEncryption + { + public: + BootEncryption (HWND parent); + ~BootEncryption (); + + void AbortDecoyOSWipe (); + void AbortSetup (); + void AbortSetupWait (); + void CallDriver (DWORD ioctl, void *input = nullptr, DWORD inputSize = 0, void *output = nullptr, DWORD outputSize = 0); + int ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5); + void CheckDecoyOSWipeResult (); + void CheckEncryptionSetupResult (); + void CheckRequirements (); + void CheckRequirementsHiddenOS (); + void CopyFileAdmin (const string &sourceFile, const string &destinationFile); + void CreateRescueIsoImage (bool initialSetup, const string &isoImagePath); + void Deinstall (); + void DeleteFileAdmin (const string &file); + DecoySystemWipeStatus GetDecoyOSWipeStatus (); + DWORD GetDriverServiceStartType (); + unsigned int GetHiddenOSCreationPhase (); + uint16 GetInstalledBootLoaderVersion (); + Partition GetPartitionForHiddenOS (); + bool IsBootLoaderOnDrive (char *devicePath); + BootEncryptionStatus GetStatus (); + string GetTempPath (); + void GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties); + SystemDriveConfiguration GetSystemDriveConfiguration (); + void Install (bool hiddenSystem); + void InstallBootLoader (bool preserveUserConfig = false, bool hiddenOSCreation = false); + void InvalidateCachedSysDriveProperties (); + bool IsHiddenSystemRunning (); + bool IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); + void PrepareHiddenOSCreation (int ea, int mode, int pkcs5); + void PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath); + void ProbeRealSystemDriveSize (); + void ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig = nullptr, string *customUserMessage = nullptr, uint16 *bootLoaderVersion = nullptr); + uint32 ReadDriverConfigurationFlags (); + void RegisterBootDriver (bool hiddenSystem); + void RegisterFilterDriver (bool registerDriver, bool volumeClass); + void RegisterSystemFavoritesService (BOOL registerService); + void RenameDeprecatedSystemLoaderBackup (); + bool RestartComputer (void); + void InitialSecurityChecksForHiddenOS (); + void RestrictPagingFilesToSystemPartition (); + void SetDriverConfigurationFlag (uint32 flag, bool state); + void SetDriverServiceStartType (DWORD startType); + void SetHiddenOSCreationPhase (unsigned int newPhase); + void StartDecryption (BOOL discardUnreadableEncryptedSectors); + void StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm); + void StartEncryption (WipeAlgorithmId wipeAlgorithm, bool zeroUnreadableSectors); + bool SystemDriveContainsPartitionType (byte type); + bool SystemDriveContainsExtendedPartition (); + bool SystemPartitionCoversWholeDrive (); + bool SystemDriveIsDynamic (); + bool VerifyRescueDisk (); + void WipeHiddenOSCreationConfig (); + void WriteBootDriveSector (uint64 offset, byte *data); + void WriteBootSectorConfig (const byte newConfig[]); + void WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage); + void WriteLocalMachineRegistryDwordValue (char *keyPath, char *valueName, DWORD value); + + protected: + static const uint32 RescueIsoImageSize = 1835008; // Size of ISO9660 image with bootable emulated 1.44MB floppy disk image + + void BackupSystemLoader (); + void CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation = false); + void CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5); + string GetSystemLoaderBackupPath (); + uint32 GetChecksum (byte *data, size_t size); + DISK_GEOMETRY GetDriveGeometry (int driveNumber); + PartitionList GetDrivePartitions (int driveNumber); + wstring GetRemarksOnHiddenOS (); + string GetWindowsDirectory (); + void RegisterDeviceClassFilter (bool registerFilter, const GUID *deviceClassGuid); + void RestoreSystemLoader (); + void InstallVolumeHeader (); + + HWND ParentWindow; + SystemDriveConfiguration DriveConfig; + int SelectedEncryptionAlgorithmId; + Partition HiddenOSCandidatePartition; + byte *RescueIsoImage; + byte RescueVolumeHeader[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; + byte VolumeHeader[TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE]; + bool DriveConfigValid; + bool RealSystemDriveSizeValid; + bool RescueVolumeHeaderValid; + bool VolumeHeaderValid; + }; +} + +#define TC_ABORT_TRANSFORM_WAIT_INTERVAL 10 + +#define MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS 2.1 +#define MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_FAT 1.05 + +#define TC_SYS_BOOT_LOADER_BACKUP_NAME "Original System Loader" +#define TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY "Original System Loader.bak" // Deprecated to prevent removal by some "cleaners" + +#define TC_SYSTEM_FAVORITES_SERVICE_NAME TC_APP_NAME "SystemFavorites" +#define TC_SYSTEM_FAVORITES_SERVICE_LOAD_ORDER_GROUP "Event Log" +#define TC_SYSTEM_FAVORITES_SERVICE_CMDLINE_OPTION "/systemFavoritesService" + +#endif // TC_HEADER_Common_BootEncryption diff --git a/Common/CACHE.C b/Common/CACHE.C index 9d83da9..d4bd6f9 100644 --- a/Common/CACHE.C +++ b/Common/CACHE.C @@ -1,100 +1,100 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#ifndef NT4_DRIVER -#pragma VxD_LOCKED_CODE_SEG -#pragma VxD_LOCKED_DATA_SEG -#endif - -#include "Crypto.h" -#include "Fat.h" -#include "Volumes.h" -#include "Apidrvr.h" -#include "Common.h" -#include "Cache.h" - -Password CachedPasswords[CACHE_SIZE]; -int cacheEmpty = 1; -static int nPasswordIdx = 0; - -int ReadVolumeHeaderWCache (BOOL bBoot, BOOL bCache, char *header, Password *password, PCRYPTO_INFO *retInfo) -{ - int nReturnCode = ERR_PASSWORD_WRONG; - int i; - - /* Attempt to recognize volume using mount password */ - if (password->Length > 0) - { - nReturnCode = ReadVolumeHeader (bBoot, header, password, retInfo, NULL); - - /* Save mount passwords back into cache if asked to do so */ - if (bCache && (nReturnCode == 0 || nReturnCode == ERR_CIPHER_INIT_WEAK_KEY)) - { - for (i = 0; i < CACHE_SIZE; i++) - { - if (memcmp (&CachedPasswords[i], password, sizeof (Password)) == 0) - break; - } - - if (i == CACHE_SIZE) - { - /* Store the password */ - CachedPasswords[nPasswordIdx] = *password; - - /* Try another slot */ - nPasswordIdx = (nPasswordIdx + 1) % CACHE_SIZE; - - cacheEmpty = 0; - } - } - } - else if (!cacheEmpty) - { - /* Attempt to recognize volume using cached passwords */ - for (i = 0; i < CACHE_SIZE; i++) - { - if (CachedPasswords[i].Length > 0) - { - nReturnCode = ReadVolumeHeader (bBoot, header, &CachedPasswords[i], retInfo, NULL); - - if (nReturnCode != ERR_PASSWORD_WRONG) - break; - } - } - } - - return nReturnCode; -} - - -void AddPasswordToCache (Password *password) -{ - int i; - for (i = 0; i < CACHE_SIZE; i++) - { - if (memcmp (&CachedPasswords[i], password, sizeof (Password)) == 0) - return; - } - - CachedPasswords[nPasswordIdx] = *password; - nPasswordIdx = (nPasswordIdx + 1) % CACHE_SIZE; - cacheEmpty = 0; -} - - -void WipeCache () -{ - burn (CachedPasswords, sizeof (CachedPasswords)); - nPasswordIdx = 0; - cacheEmpty = 1; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#ifndef NT4_DRIVER +#pragma VxD_LOCKED_CODE_SEG +#pragma VxD_LOCKED_DATA_SEG +#endif + +#include "Crypto.h" +#include "Fat.h" +#include "Volumes.h" +#include "Apidrvr.h" +#include "Common.h" +#include "Cache.h" + +Password CachedPasswords[CACHE_SIZE]; +int cacheEmpty = 1; +static int nPasswordIdx = 0; + +int ReadVolumeHeaderWCache (BOOL bBoot, BOOL bCache, char *header, Password *password, PCRYPTO_INFO *retInfo) +{ + int nReturnCode = ERR_PASSWORD_WRONG; + int i; + + /* Attempt to recognize volume using mount password */ + if (password->Length > 0) + { + nReturnCode = ReadVolumeHeader (bBoot, header, password, retInfo, NULL); + + /* Save mount passwords back into cache if asked to do so */ + if (bCache && (nReturnCode == 0 || nReturnCode == ERR_CIPHER_INIT_WEAK_KEY)) + { + for (i = 0; i < CACHE_SIZE; i++) + { + if (memcmp (&CachedPasswords[i], password, sizeof (Password)) == 0) + break; + } + + if (i == CACHE_SIZE) + { + /* Store the password */ + CachedPasswords[nPasswordIdx] = *password; + + /* Try another slot */ + nPasswordIdx = (nPasswordIdx + 1) % CACHE_SIZE; + + cacheEmpty = 0; + } + } + } + else if (!cacheEmpty) + { + /* Attempt to recognize volume using cached passwords */ + for (i = 0; i < CACHE_SIZE; i++) + { + if (CachedPasswords[i].Length > 0) + { + nReturnCode = ReadVolumeHeader (bBoot, header, &CachedPasswords[i], retInfo, NULL); + + if (nReturnCode != ERR_PASSWORD_WRONG) + break; + } + } + } + + return nReturnCode; +} + + +void AddPasswordToCache (Password *password) +{ + int i; + for (i = 0; i < CACHE_SIZE; i++) + { + if (memcmp (&CachedPasswords[i], password, sizeof (Password)) == 0) + return; + } + + CachedPasswords[nPasswordIdx] = *password; + nPasswordIdx = (nPasswordIdx + 1) % CACHE_SIZE; + cacheEmpty = 0; +} + + +void WipeCache () +{ + burn (CachedPasswords, sizeof (CachedPasswords)); + nPasswordIdx = 0; + cacheEmpty = 1; +} diff --git a/Common/CACHE.H b/Common/CACHE.H index 47b785a..9171574 100644 --- a/Common/CACHE.H +++ b/Common/CACHE.H @@ -1,23 +1,23 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Common.h" - -#ifndef CACHE_SIZE -/* WARNING: Changing this value might not be safe (some items may be hard coded for 4)! Inspection necessary. */ -#define CACHE_SIZE 4 -#endif - -extern int cacheEmpty; - -void AddPasswordToCache (Password *password); -int ReadVolumeHeaderWCache (BOOL bBoot, BOOL bCache, char *header, Password *password, PCRYPTO_INFO *retInfo); -void WipeCache (void); +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Common.h" + +#ifndef CACHE_SIZE +/* WARNING: Changing this value might not be safe (some items may be hard coded for 4)! Inspection necessary. */ +#define CACHE_SIZE 4 +#endif + +extern int cacheEmpty; + +void AddPasswordToCache (Password *password); +int ReadVolumeHeaderWCache (BOOL bBoot, BOOL bCache, char *header, Password *password, PCRYPTO_INFO *retInfo); +void WipeCache (void); diff --git a/Common/CMDLINE.C b/Common/CMDLINE.C index 4ed975d..40d0a43 100644 --- a/Common/CMDLINE.C +++ b/Common/CMDLINE.C @@ -1,290 +1,244 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#include -#include -#include "Cmdline.h" - -#include "Resource.h" -#include "Crypto.h" -#include "Apidrvr.h" -#include "Dlgcode.h" -#include "Language.h" - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK CommandHelpDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (lParam); /* remove warning */ - if (wParam); /* remove warning */ - - switch (msg) - { - case WM_INITDIALOG: - { - char * tmp = err_malloc(8192); - char tmp2[MAX_PATH * 2]; - argumentspec *as; - int i; - - LocalizeDialog (hwndDlg, "IDD_COMMANDHELP_DLG"); - - as = (argumentspec*) lParam; - - *tmp = 0; - - strcpy (tmp, "Command line options:\n\n"); - for (i = 0; i < as->arg_cnt; i ++) - { - if (!as->args[i].Internal) - { - sprintf(tmp2, "%s\t%s\n", as->args[i].short_name, as->args[i].long_name); - strcat(tmp,tmp2); - } - } - - SetWindowText (GetDlgItem (hwndDlg, IDC_COMMANDHELP_TEXT), (char*) tmp); - return 1; - } - - case WM_COMMAND: - EndDialog (hwndDlg, IDOK); - return 1; - case WM_CLOSE: - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - -int Win32CommandLine (char *lpszCommandLine, char ***lpszArgs) -{ - int i = 0, k = 0, x = 0, nValid = TRUE; - int nLen = strlen (lpszCommandLine); - int nArrSize = 1024; - char szTmp[MAX_PATH * 2]; - - *lpszArgs = malloc (sizeof (char *)* nArrSize); - - if (*lpszArgs == NULL) - return 0; - - while (i < nLen) - { - if (lpszCommandLine[i] == ' ') - { - if (k > 0) - { - szTmp[k] = 0; - (*lpszArgs)[x] = _strdup (szTmp); - if ((*lpszArgs)[x] == NULL) - { - free (*lpszArgs); - return 0; - } - x++; - k = 0; - if (x == nArrSize) - { - break; - } - } - i++; - continue; - } - if (lpszCommandLine[i] == '"') - { - i++; - while (i < nLen) - { - if (lpszCommandLine[i] == '"') - break; - if (k < sizeof (szTmp)) - szTmp[k++] = lpszCommandLine[i++]; - else - { - free (*lpszArgs); - return 0; - } - } - - if (lpszCommandLine[i] != '"') - { - nValid = FALSE; - break; - } - } - else - { - if (k < sizeof (szTmp)) - szTmp[k++] = lpszCommandLine[i]; - else - { - free (*lpszArgs); - return 0; - } - } - - i++; - } - - if (nValid == FALSE) - { - free (*lpszArgs); - return 0; - } - else if (k > 0) - { - szTmp[k] = 0; - (*lpszArgs)[x] = _strdup (szTmp); - if ((*lpszArgs)[x] == NULL) - { - free (*lpszArgs); - return 0; - } - x++; - k = 0; - } - if (!x) - { - free (*lpszArgs); - return 0; - } - return x; -} - -int GetArgSepPosOffset (char *lpszArgument) -{ - if (lpszArgument[0] == '/') - return 1; - else if (lpszArgument[0] == '-' && lpszArgument[1] == '-') - return 2; - else if (lpszArgument[0] == '-') - return 1; - else - return 0; -} - -int GetArgumentID (argumentspec *as, char *lpszArgument, int *nArgPos) -{ - char szTmp[MAX_PATH * 2]; - int i; - - i = strlen (lpszArgument); - szTmp[i] = 0; - while (--i >= 0) - { - szTmp[i] = (char) tolower (lpszArgument[i]); - } - - for (i = 0; i < as->arg_cnt; i++) - { - size_t k; - - k = strlen (as->args[i].long_name); - if (memcmp (as->args[i].long_name, szTmp, k * sizeof (char)) == 0) - { - int x; - for (x = i + 1; x < as->arg_cnt; x++) - { - size_t m; - - m = strlen (as->args[x].long_name); - if (memcmp (as->args[x].long_name, szTmp, m * sizeof (char)) == 0) - { - break; - } - } - - if (x == as->arg_cnt) - { - if (strlen (lpszArgument) != k) - *nArgPos = k; - else - *nArgPos = 0; - return as->args[i].Id; - } - } - } - - for (i = 0; i < as->arg_cnt; i++) - { - size_t k; - - if (as->args[i].short_name[0] == 0) - continue; - - k = strlen (as->args[i].short_name); - if (memcmp (as->args[i].short_name, szTmp, k * sizeof (char)) == 0) - { - int x; - for (x = i + 1; x < as->arg_cnt; x++) - { - size_t m; - - if (as->args[x].short_name[0] == 0) - continue; - - m = strlen (as->args[x].short_name); - if (memcmp (as->args[x].short_name, szTmp, m * sizeof (char)) == 0) - { - break; - } - } - - if (x == as->arg_cnt) - { - if (strlen (lpszArgument) != k) - *nArgPos = k; - else - *nArgPos = 0; - return as->args[i].Id; - } - } - } - - - return -1; -} - -int GetArgumentValue (char **lpszCommandLineArgs, int nArgPos, int *nArgIdx, - int nNoCommandLineArgs, char *lpszValue, int nValueSize) -{ - *lpszValue = 0; - - if (nArgPos) - { - /* Handles the case of no space between parameter code and - value */ - strncpy (lpszValue, &lpszCommandLineArgs[*nArgIdx][nArgPos], nValueSize); - lpszValue[nValueSize - 1] = 0; - return HAS_ARGUMENT; - } - else if (*nArgIdx + 1 < nNoCommandLineArgs) - { - int x = GetArgSepPosOffset (lpszCommandLineArgs[*nArgIdx + 1]); - if (x == 0) - { - /* Handles the case of space between parameter code - and value */ - strncpy (lpszValue, &lpszCommandLineArgs[*nArgIdx + 1][x], nValueSize); - lpszValue[nValueSize - 1] = 0; - (*nArgIdx)++; - return HAS_ARGUMENT; - } - } - - return HAS_NO_ARGUMENT; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#include +#include +#include "Cmdline.h" + +#include "Resource.h" +#include "Crypto.h" +#include "Apidrvr.h" +#include "Dlgcode.h" +#include "Language.h" + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK CommandHelpDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (lParam); /* remove warning */ + if (wParam); /* remove warning */ + + switch (msg) + { + case WM_INITDIALOG: + { + char * tmp = err_malloc(8192); + char tmp2[MAX_PATH * 2]; + argumentspec *as; + int i; + + LocalizeDialog (hwndDlg, "IDD_COMMANDHELP_DLG"); + + as = (argumentspec*) lParam; + + *tmp = 0; + + strcpy (tmp, "Command line options:\n\n"); + for (i = 0; i < as->arg_cnt; i ++) + { + if (!as->args[i].Internal) + { + sprintf(tmp2, "%s\t%s\n", as->args[i].short_name, as->args[i].long_name); + strcat(tmp,tmp2); + } + } + + SetWindowText (GetDlgItem (hwndDlg, IDC_COMMANDHELP_TEXT), (char*) tmp); + return 1; + } + + case WM_COMMAND: + EndDialog (hwndDlg, IDOK); + return 1; + case WM_CLOSE: + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + +int Win32CommandLine (char *lpszCommandLine, char ***lpszArgs) +{ + int argumentCount; + int i; + + LPWSTR *arguments = CommandLineToArgvW (GetCommandLineW(), &argumentCount); + if (!arguments) + { + handleWin32Error (NULL); + return 0; + } + + --argumentCount; + if (argumentCount < 1) + { + LocalFree (arguments); + return 0; + } + + *lpszArgs = malloc (sizeof (char *) * argumentCount); + if (!*lpszArgs) + AbortProcess ("OUTOFMEMORY"); + + for (i = 0; i < argumentCount; ++i) + { + size_t argLen = wcslen (arguments[i + 1]); + + char *arg = malloc (argLen + 1); + if (!arg) + AbortProcess ("OUTOFMEMORY"); + + if (argLen > 0) + { + int len = WideCharToMultiByte (CP_ACP, 0, arguments[i + 1], -1, arg, argLen + 1, NULL, NULL); + if (len == 0) + { + handleWin32Error (NULL); + AbortProcessSilent(); + } + } + else + arg[0] = 0; + + (*lpszArgs)[i] = arg; + } + + LocalFree (arguments); + return argumentCount; +} + +int GetArgSepPosOffset (char *lpszArgument) +{ + if (lpszArgument[0] == '/') + return 1; + else if (lpszArgument[0] == '-' && lpszArgument[1] == '-') + return 2; + else if (lpszArgument[0] == '-') + return 1; + else + return 0; +} + +int GetArgumentID (argumentspec *as, char *lpszArgument, int *nArgPos) +{ + char szTmp[MAX_PATH * 2]; + int i; + + i = strlen (lpszArgument); + szTmp[i] = 0; + while (--i >= 0) + { + szTmp[i] = (char) tolower (lpszArgument[i]); + } + + for (i = 0; i < as->arg_cnt; i++) + { + size_t k; + + k = strlen (as->args[i].long_name); + if (memcmp (as->args[i].long_name, szTmp, k * sizeof (char)) == 0) + { + int x; + for (x = i + 1; x < as->arg_cnt; x++) + { + size_t m; + + m = strlen (as->args[x].long_name); + if (memcmp (as->args[x].long_name, szTmp, m * sizeof (char)) == 0) + { + break; + } + } + + if (x == as->arg_cnt) + { + if (strlen (lpszArgument) != k) + *nArgPos = k; + else + *nArgPos = 0; + return as->args[i].Id; + } + } + } + + for (i = 0; i < as->arg_cnt; i++) + { + size_t k; + + if (as->args[i].short_name[0] == 0) + continue; + + k = strlen (as->args[i].short_name); + if (memcmp (as->args[i].short_name, szTmp, k * sizeof (char)) == 0) + { + int x; + for (x = i + 1; x < as->arg_cnt; x++) + { + size_t m; + + if (as->args[x].short_name[0] == 0) + continue; + + m = strlen (as->args[x].short_name); + if (memcmp (as->args[x].short_name, szTmp, m * sizeof (char)) == 0) + { + break; + } + } + + if (x == as->arg_cnt) + { + if (strlen (lpszArgument) != k) + *nArgPos = k; + else + *nArgPos = 0; + return as->args[i].Id; + } + } + } + + + return -1; +} + +int GetArgumentValue (char **lpszCommandLineArgs, int nArgPos, int *nArgIdx, + int nNoCommandLineArgs, char *lpszValue, int nValueSize) +{ + *lpszValue = 0; + + if (nArgPos) + { + /* Handles the case of no space between parameter code and + value */ + strncpy (lpszValue, &lpszCommandLineArgs[*nArgIdx][nArgPos], nValueSize); + lpszValue[nValueSize - 1] = 0; + return HAS_ARGUMENT; + } + else if (*nArgIdx + 1 < nNoCommandLineArgs) + { + int x = GetArgSepPosOffset (lpszCommandLineArgs[*nArgIdx + 1]); + if (x == 0) + { + /* Handles the case of space between parameter code + and value */ + strncpy (lpszValue, &lpszCommandLineArgs[*nArgIdx + 1][x], nValueSize); + lpszValue[nValueSize - 1] = 0; + (*nArgIdx)++; + return HAS_ARGUMENT; + } + } + + return HAS_NO_ARGUMENT; +} diff --git a/Common/CMDLINE.H b/Common/CMDLINE.H index e35ead9..487b11f 100644 --- a/Common/CMDLINE.H +++ b/Common/CMDLINE.H @@ -1,41 +1,41 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define HAS_ARGUMENT 1 -#define HAS_NO_ARGUMENT !HAS_ARGUMENT - -typedef struct argument_t -{ - int Id; - char long_name[32]; - char short_name[8]; - BOOL Internal; -} argument; - -typedef struct argumentspec_t -{ - argument *args; - int arg_cnt; -} argumentspec; - -BOOL CALLBACK CommandHelpDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); -int Win32CommandLine ( char *lpszCommandLine , char ***lpszArgs ); -int GetArgSepPosOffset ( char *lpszArgument ); -int GetArgumentID ( argumentspec *as , char *lpszArgument , int *nArgPos ); -int GetArgumentValue ( char **lpszCommandLineArgs , int nArgPos , int *nArgIdx , int nNoCommandLineArgs , char *lpszValue , int nValueSize ); - -#ifdef __cplusplus -} -#endif +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define HAS_ARGUMENT 1 +#define HAS_NO_ARGUMENT !HAS_ARGUMENT + +typedef struct argument_t +{ + int Id; + char long_name[32]; + char short_name[8]; + BOOL Internal; +} argument; + +typedef struct argumentspec_t +{ + argument *args; + int arg_cnt; +} argumentspec; + +BOOL CALLBACK CommandHelpDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); +int Win32CommandLine ( char *lpszCommandLine , char ***lpszArgs ); +int GetArgSepPosOffset ( char *lpszArgument ); +int GetArgumentID ( argumentspec *as , char *lpszArgument , int *nArgPos ); +int GetArgumentValue ( char **lpszCommandLineArgs , int nArgPos , int *nArgIdx , int nNoCommandLineArgs , char *lpszValue , int nValueSize ); + +#ifdef __cplusplus +} +#endif diff --git a/Common/COMBO.C b/Common/COMBO.C index d821972..031a597 100644 --- a/Common/COMBO.C +++ b/Common/COMBO.C @@ -1,212 +1,212 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" -#include "Combo.h" -#include "Dlgcode.h" -#include "Xml.h" - -#include - -#define SIZEOF_MRU_LIST 20 - -void AddComboItem (HWND hComboBox, char *lpszFileName, BOOL saveHistory) -{ - LPARAM nIndex; - - if (!saveHistory) - { - SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); - SetWindowText (hComboBox, lpszFileName); - return; - } - - nIndex = SendMessage (hComboBox, CB_FINDSTRINGEXACT, (WPARAM) - 1, (LPARAM) & lpszFileName[0]); - - if (nIndex == CB_ERR && *lpszFileName) - { - time_t lTime = time (NULL); - nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) & lpszFileName[0]); - if (nIndex != CB_ERR) - SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) lTime); - } - - if (nIndex != CB_ERR && *lpszFileName) - nIndex = SendMessage (hComboBox, CB_SETCURSEL, nIndex, 0); - - if (*lpszFileName == 0) - { - SendMessage (hComboBox, CB_SETCURSEL, (WPARAM) - 1, 0); - } -} - - -LPARAM MoveEditToCombo (HWND hComboBox, BOOL saveHistory) -{ - char szTmp[TC_MAX_PATH] = {0}; - - if (!saveHistory) - { - GetWindowText (hComboBox, szTmp, sizeof (szTmp)); - SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); - SetWindowText (hComboBox, szTmp); - return 0; - } - - GetWindowText (hComboBox, szTmp, sizeof (szTmp)); - - if (strlen (szTmp) > 0) - { - LPARAM nIndex = SendMessage (hComboBox, CB_FINDSTRINGEXACT, (WPARAM) - 1, - (LPARAM) & szTmp[0]); - if (nIndex == CB_ERR) - { - time_t lTime = time (NULL); - nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) & szTmp[0]); - if (nIndex != CB_ERR) - SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (DWORD) lTime); - } - else - { - time_t lTime = time (NULL); - SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (DWORD) lTime); - } - - return nIndex; - } - - return SendMessage (hComboBox, CB_GETCURSEL, 0, 0); -} - -int GetOrderComboIdx (HWND hComboBox, int *nIdxList, int nElems) -{ - int x = (int) SendMessage (hComboBox, CB_GETCOUNT, 0, 0); - if (x != CB_ERR) - { - int i, nHighIdx = CB_ERR; - time_t lHighTime = -1; - - for (i = 0; i < x; i++) - { - time_t lTime = SendMessage (hComboBox, CB_GETITEMDATA, (WPARAM) i, 0); - if (lTime > lHighTime) - { - int n; - for (n = 0; n < nElems; n++) - if (nIdxList[n] == i) - break; - if (n == nElems) - { - lHighTime = lTime; - nHighIdx = i; - } - } - } - - return nHighIdx; - } - - return CB_ERR; -} - -LPARAM UpdateComboOrder (HWND hComboBox) -{ - LPARAM nIndex; - - nIndex = SendMessage (hComboBox, CB_GETCURSEL, 0, 0); - - if (nIndex != CB_ERR) - { - time_t lTime = time (NULL); - nIndex = SendMessage (hComboBox, CB_SETITEMDATA, (WPARAM) nIndex, - (LPARAM) lTime); - } - - return nIndex; -} - -void LoadCombo (HWND hComboBox) -{ - DWORD size; - char *history = LoadFile (GetConfigPath (TC_APPD_FILENAME_HISTORY), &size); - char *xml = history; - char volume[MAX_PATH]; - - if (xml == NULL) return; - - while (xml = XmlFindElement (xml, "volume")) - { - XmlGetNodeText (xml, volume, sizeof (volume)); - AddComboItem (hComboBox, volume, TRUE); - xml++; - } - - SendMessage (hComboBox, CB_SETCURSEL, 0, 0); - - free (history); -} - -void DumpCombo (HWND hComboBox, int bClear) -{ - FILE *f; - int i, nComboIdx[SIZEOF_MRU_LIST]; - - if (bClear) - { - DeleteFile (GetConfigPath (TC_APPD_FILENAME_HISTORY)); - return; - } - - f = fopen (GetConfigPath (TC_APPD_FILENAME_HISTORY), "w"); - if (f == NULL) return; - - XmlWriteHeader (f); - fputs ("\n\t", f); - - /* combo list part:- get mru items */ - for (i = 0; i < SIZEOF_MRU_LIST; i++) - nComboIdx[i] = GetOrderComboIdx (hComboBox, &nComboIdx[0], i); - - /* combo list part:- write out mru items */ - for (i = 0; i < SIZEOF_MRU_LIST; i++) - { - char szTmp[MAX_PATH] = { 0 }; - - if (SendMessage (hComboBox, CB_GETLBTEXTLEN, nComboIdx[i], 0) < sizeof (szTmp)) - SendMessage (hComboBox, CB_GETLBTEXT, nComboIdx[i], (LPARAM) & szTmp[0]); - - if (szTmp[0] != 0) - { - char q[MAX_PATH * 2] = { 0 }; - XmlQuoteText (szTmp, q, sizeof (q)); - - fprintf (f, "\n\t\t%s", q); - } - } - - fputs ("\n\t", f); - XmlWriteFooter (f); - fclose (f); -} - -void ClearCombo (HWND hComboBox) -{ - int i; - for (i = 0; i < SIZEOF_MRU_LIST; i++) - { - SendMessage (hComboBox, CB_DELETESTRING, 0, 0); - } -} - -int IsComboEmpty (HWND hComboBox) -{ - return SendMessage (hComboBox, CB_GETCOUNT, 0, 0) < 1; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" +#include "Combo.h" +#include "Dlgcode.h" +#include "Xml.h" + +#include + +#define SIZEOF_MRU_LIST 20 + +void AddComboItem (HWND hComboBox, char *lpszFileName, BOOL saveHistory) +{ + LPARAM nIndex; + + if (!saveHistory) + { + SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); + SetWindowText (hComboBox, lpszFileName); + return; + } + + nIndex = SendMessage (hComboBox, CB_FINDSTRINGEXACT, (WPARAM) - 1, (LPARAM) & lpszFileName[0]); + + if (nIndex == CB_ERR && *lpszFileName) + { + time_t lTime = time (NULL); + nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) & lpszFileName[0]); + if (nIndex != CB_ERR) + SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) lTime); + } + + if (nIndex != CB_ERR && *lpszFileName) + nIndex = SendMessage (hComboBox, CB_SETCURSEL, nIndex, 0); + + if (*lpszFileName == 0) + { + SendMessage (hComboBox, CB_SETCURSEL, (WPARAM) - 1, 0); + } +} + + +LPARAM MoveEditToCombo (HWND hComboBox, BOOL saveHistory) +{ + char szTmp[TC_MAX_PATH] = {0}; + + if (!saveHistory) + { + GetWindowText (hComboBox, szTmp, sizeof (szTmp)); + SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); + SetWindowText (hComboBox, szTmp); + return 0; + } + + GetWindowText (hComboBox, szTmp, sizeof (szTmp)); + + if (strlen (szTmp) > 0) + { + LPARAM nIndex = SendMessage (hComboBox, CB_FINDSTRINGEXACT, (WPARAM) - 1, + (LPARAM) & szTmp[0]); + if (nIndex == CB_ERR) + { + time_t lTime = time (NULL); + nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) & szTmp[0]); + if (nIndex != CB_ERR) + SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (DWORD) lTime); + } + else + { + time_t lTime = time (NULL); + SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (DWORD) lTime); + } + + return nIndex; + } + + return SendMessage (hComboBox, CB_GETCURSEL, 0, 0); +} + +int GetOrderComboIdx (HWND hComboBox, int *nIdxList, int nElems) +{ + int x = (int) SendMessage (hComboBox, CB_GETCOUNT, 0, 0); + if (x != CB_ERR) + { + int i, nHighIdx = CB_ERR; + time_t lHighTime = -1; + + for (i = 0; i < x; i++) + { + time_t lTime = SendMessage (hComboBox, CB_GETITEMDATA, (WPARAM) i, 0); + if (lTime > lHighTime) + { + int n; + for (n = 0; n < nElems; n++) + if (nIdxList[n] == i) + break; + if (n == nElems) + { + lHighTime = lTime; + nHighIdx = i; + } + } + } + + return nHighIdx; + } + + return CB_ERR; +} + +LPARAM UpdateComboOrder (HWND hComboBox) +{ + LPARAM nIndex; + + nIndex = SendMessage (hComboBox, CB_GETCURSEL, 0, 0); + + if (nIndex != CB_ERR) + { + time_t lTime = time (NULL); + nIndex = SendMessage (hComboBox, CB_SETITEMDATA, (WPARAM) nIndex, + (LPARAM) lTime); + } + + return nIndex; +} + +void LoadCombo (HWND hComboBox) +{ + DWORD size; + char *history = LoadFile (GetConfigPath (TC_APPD_FILENAME_HISTORY), &size); + char *xml = history; + char volume[MAX_PATH]; + + if (xml == NULL) return; + + while (xml = XmlFindElement (xml, "volume")) + { + XmlGetNodeText (xml, volume, sizeof (volume)); + AddComboItem (hComboBox, volume, TRUE); + xml++; + } + + SendMessage (hComboBox, CB_SETCURSEL, 0, 0); + + free (history); +} + +void DumpCombo (HWND hComboBox, int bClear) +{ + FILE *f; + int i, nComboIdx[SIZEOF_MRU_LIST]; + + if (bClear) + { + DeleteFile (GetConfigPath (TC_APPD_FILENAME_HISTORY)); + return; + } + + f = fopen (GetConfigPath (TC_APPD_FILENAME_HISTORY), "w"); + if (f == NULL) return; + + XmlWriteHeader (f); + fputs ("\n\t", f); + + /* combo list part:- get mru items */ + for (i = 0; i < SIZEOF_MRU_LIST; i++) + nComboIdx[i] = GetOrderComboIdx (hComboBox, &nComboIdx[0], i); + + /* combo list part:- write out mru items */ + for (i = 0; i < SIZEOF_MRU_LIST; i++) + { + char szTmp[MAX_PATH] = { 0 }; + + if (SendMessage (hComboBox, CB_GETLBTEXTLEN, nComboIdx[i], 0) < sizeof (szTmp)) + SendMessage (hComboBox, CB_GETLBTEXT, nComboIdx[i], (LPARAM) & szTmp[0]); + + if (szTmp[0] != 0) + { + char q[MAX_PATH * 2] = { 0 }; + XmlQuoteText (szTmp, q, sizeof (q)); + + fprintf (f, "\n\t\t%s", q); + } + } + + fputs ("\n\t", f); + XmlWriteFooter (f); + fclose (f); +} + +void ClearCombo (HWND hComboBox) +{ + int i; + for (i = 0; i < SIZEOF_MRU_LIST; i++) + { + SendMessage (hComboBox, CB_DELETESTRING, 0, 0); + } +} + +int IsComboEmpty (HWND hComboBox) +{ + return SendMessage (hComboBox, CB_GETCOUNT, 0, 0) < 1; +} diff --git a/Common/COMBO.H b/Common/COMBO.H index ff14547..d434c14 100644 --- a/Common/COMBO.H +++ b/Common/COMBO.H @@ -1,27 +1,27 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifdef __cplusplus -extern "C" { -#endif - -void AddComboItem (HWND hComboBox, char *lpszFileName, BOOL saveHistory); -LPARAM MoveEditToCombo (HWND hComboBox, BOOL saveHistory); -int GetOrderComboIdx ( HWND hComboBox , int *nIdxList , int nElems ); -LPARAM UpdateComboOrder ( HWND hComboBox ); -void LoadCombo ( HWND hComboBox ); -void DumpCombo ( HWND hComboBox , int bClear ); -void ClearCombo (HWND hComboBox); -int IsComboEmpty (HWND hComboBox); - -#ifdef __cplusplus -} -#endif +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifdef __cplusplus +extern "C" { +#endif + +void AddComboItem (HWND hComboBox, char *lpszFileName, BOOL saveHistory); +LPARAM MoveEditToCombo (HWND hComboBox, BOOL saveHistory); +int GetOrderComboIdx ( HWND hComboBox , int *nIdxList , int nElems ); +LPARAM UpdateComboOrder ( HWND hComboBox ); +void LoadCombo ( HWND hComboBox ); +void DumpCombo ( HWND hComboBox , int bClear ); +void ClearCombo (HWND hComboBox); +int IsComboEmpty (HWND hComboBox); + +#ifdef __cplusplus +} +#endif diff --git a/Common/CRC.C b/Common/CRC.C index 6a3ff5b..f1cb15e 100644 --- a/Common/CRC.C +++ b/Common/CRC.C @@ -1,133 +1,133 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" -#include "Crc.h" -#include "Common/Endian.h" - -#ifndef TC_MINIMIZE_CODE_SIZE - -/* CRC polynomial 0x04c11db7 */ -unsigned __int32 crc_32_tab[]= -{ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -unsigned __int32 GetCrc32 (unsigned char *data, int length) -{ - unsigned __int32 CRC = 0xffffffff; - - while (length--) - { - CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *data++) & 0xFF ]; - } - - return CRC ^ 0xffffffff; -} - -unsigned __int32 crc32int (unsigned __int32 *data) -{ - unsigned char *d = (unsigned char *) data; - unsigned __int32 CRC = 0xffffffff; - - CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; - CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; - CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; - return (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d) & 0xFF ] ^ 0xffffffff; -} - -#if BYTE_ORDER == LITTLE_ENDIAN -# define CRC_SELFTEST 0x6fcf9e13 -#else -# define CRC_SELFTEST 0xca87914d -#endif - -BOOL crc32_selftests (void) -{ - int i; - unsigned __int32 crc = 0xffffffff; - BOOL bSuccess = FALSE; - - for (i = 0; i < (int)sizeof(crc_32_tab); i++) - crc = UPDC32 (((unsigned char *) crc_32_tab)[i], crc); - - bSuccess = CRC_SELFTEST == (crc ^ 0xffffffff); - - bSuccess &= GetCrc32 ((unsigned char *)crc_32_tab, sizeof crc_32_tab) == CRC_SELFTEST; - - return bSuccess; -} - -#else // TC_MINIMIZE_CODE_SIZE - -unsigned __int32 GetCrc32 (unsigned char *data, int length) -{ - unsigned __int32 r = 0xFFFFFFFFUL; - int i, b; - - for (i = 0; i < length; ++i) - { - r ^= data[i]; - for (b = 0; b < 8; ++b) - { - if ((unsigned __int8) r & 1) - r = (r >> 1) ^ 0xEDB88320UL; - else - r >>= 1; - } - } - - return r ^ 0xFFFFFFFFUL; -} - -BOOL crc32_selftests () -{ - unsigned __int8 testData[32]; - unsigned __int8 i; - - for (i = 0; i < sizeof (testData); ++i) - testData[i] = i; - - return GetCrc32 (testData, sizeof (testData)) == 0x91267E8AUL; -} - -#endif // TC_MINIMIZE_CODE_SIZE +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" +#include "Crc.h" +#include "Common/Endian.h" + +#ifndef TC_MINIMIZE_CODE_SIZE + +/* CRC polynomial 0x04c11db7 */ +unsigned __int32 crc_32_tab[]= +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +unsigned __int32 GetCrc32 (unsigned char *data, int length) +{ + unsigned __int32 CRC = 0xffffffff; + + while (length--) + { + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *data++) & 0xFF ]; + } + + return CRC ^ 0xffffffff; +} + +unsigned __int32 crc32int (unsigned __int32 *data) +{ + unsigned char *d = (unsigned char *) data; + unsigned __int32 CRC = 0xffffffff; + + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; + return (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d) & 0xFF ] ^ 0xffffffff; +} + +#if BYTE_ORDER == LITTLE_ENDIAN +# define CRC_SELFTEST 0x6fcf9e13 +#else +# define CRC_SELFTEST 0xca87914d +#endif + +BOOL crc32_selftests (void) +{ + int i; + unsigned __int32 crc = 0xffffffff; + BOOL bSuccess = FALSE; + + for (i = 0; i < (int)sizeof(crc_32_tab); i++) + crc = UPDC32 (((unsigned char *) crc_32_tab)[i], crc); + + bSuccess = CRC_SELFTEST == (crc ^ 0xffffffff); + + bSuccess &= GetCrc32 ((unsigned char *)crc_32_tab, sizeof crc_32_tab) == CRC_SELFTEST; + + return bSuccess; +} + +#else // TC_MINIMIZE_CODE_SIZE + +unsigned __int32 GetCrc32 (unsigned char *data, int length) +{ + unsigned __int32 r = 0xFFFFFFFFUL; + int i, b; + + for (i = 0; i < length; ++i) + { + r ^= data[i]; + for (b = 0; b < 8; ++b) + { + if ((unsigned __int8) r & 1) + r = (r >> 1) ^ 0xEDB88320UL; + else + r >>= 1; + } + } + + return r ^ 0xFFFFFFFFUL; +} + +BOOL crc32_selftests () +{ + unsigned __int8 testData[32]; + unsigned __int8 i; + + for (i = 0; i < sizeof (testData); ++i) + testData[i] = i; + + return GetCrc32 (testData, sizeof (testData)) == 0x91267E8AUL; +} + +#endif // TC_MINIMIZE_CODE_SIZE diff --git a/Common/CRC.H b/Common/CRC.H index cfe91ad..d4dd168 100644 --- a/Common/CRC.H +++ b/Common/CRC.H @@ -1,35 +1,35 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TC_HEADER_CRC -#define TC_HEADER_CRC - -#include "Tcdefs.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define UPDC32(octet, crc)\ - (unsigned __int32)((crc_32_tab[(((unsigned __int32)(crc)) ^ ((unsigned char)(octet))) & 0xff] ^ (((unsigned __int32)(crc)) >> 8))) - -unsigned __int32 GetCrc32 (unsigned char *data, int length); -unsigned __int32 crc32int (unsigned __int32 *data); -BOOL crc32_selftests (void); - -extern unsigned __int32 crc_32_tab[]; - -#if defined(__cplusplus) -} -#endif - -#endif // TC_HEADER_CRC +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_CRC +#define TC_HEADER_CRC + +#include "Tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define UPDC32(octet, crc)\ + (unsigned __int32)((crc_32_tab[(((unsigned __int32)(crc)) ^ ((unsigned char)(octet))) & 0xff] ^ (((unsigned __int32)(crc)) >> 8))) + +unsigned __int32 GetCrc32 (unsigned char *data, int length); +unsigned __int32 crc32int (unsigned __int32 *data); +BOOL crc32_selftests (void); + +extern unsigned __int32 crc_32_tab[]; + +#if defined(__cplusplus) +} +#endif + +#endif // TC_HEADER_CRC diff --git a/Common/CRYPTO.C b/Common/CRYPTO.C index 122a187..a84dcb5 100644 --- a/Common/CRYPTO.C +++ b/Common/CRYPTO.C @@ -1,1717 +1,1717 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" -#include "Crypto.h" -#include "Xts.h" -#include "Crc.h" -#include "Common/Endian.h" -#include -#ifndef TC_WINDOWS_BOOT -#include "EncryptionThreadPool.h" -#endif -#include "Volumes.h" - -/* Update the following when adding a new cipher or EA: - - Crypto.h: - ID #define - MAX_EXPANDED_KEY #define - - Crypto.c: - Ciphers[] - EncryptionAlgorithms[] - CipherInit() - EncipherBlock() - DecipherBlock() - -*/ - -#ifndef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE - -// Cipher configuration -static Cipher Ciphers[] = -{ -// Block Size Key Size Key Schedule Size -// ID Name (Bytes) (Bytes) (Bytes) - { AES, "AES", 16, 32, AES_KS }, - { SERPENT, "Serpent", 16, 32, 140*4 }, - { TWOFISH, "Twofish", 16, 32, TWOFISH_KS }, -#ifndef TC_WINDOWS_BOOT - { BLOWFISH, "Blowfish", 8, 56, sizeof (BF_KEY) }, // Deprecated/legacy - { CAST, "CAST5", 8, 16, sizeof (CAST_KEY) }, // Deprecated/legacy - { TRIPLEDES,"Triple DES", 8, 8*3, sizeof (TDES_KEY) }, // Deprecated/legacy -#endif - { 0, 0, 0, 0, 0 } -}; - - -// Encryption algorithm configuration -// The following modes have been deprecated (legacy): LRW, CBC, INNER_CBC, OUTER_CBC -static EncryptionAlgorithm EncryptionAlgorithms[] = -{ - // Cipher(s) Modes FormatEnabled - -#ifndef TC_WINDOWS_BOOT - - { { 0, 0 }, { 0, 0, 0, 0 }, 0 }, // Must be all-zero - { { AES, 0 }, { XTS, LRW, CBC, 0 }, 1 }, - { { SERPENT, 0 }, { XTS, LRW, CBC, 0 }, 1 }, - { { TWOFISH, 0 }, { XTS, LRW, CBC, 0 }, 1 }, - { { TWOFISH, AES, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, - { { SERPENT, TWOFISH, AES, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, - { { AES, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, - { { AES, TWOFISH, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, - { { SERPENT, TWOFISH, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, - { { BLOWFISH, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy - { { CAST, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy - { { TRIPLEDES, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy - { { BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy - { { SERPENT, BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy - { { 0, 0 }, { 0, 0, 0, 0 }, 0 } // Must be all-zero - -#else // TC_WINDOWS_BOOT - - // Encryption algorithms available for boot drive encryption - { { 0, 0 }, { 0, 0 }, 0 }, // Must be all-zero - { { AES, 0 }, { XTS, 0 }, 1 }, - { { SERPENT, 0 }, { XTS, 0 }, 1 }, - { { TWOFISH, 0 }, { XTS, 0 }, 1 }, - { { TWOFISH, AES, 0 }, { XTS, 0 }, 1 }, - { { SERPENT, TWOFISH, AES, 0 }, { XTS, 0 }, 1 }, - { { AES, SERPENT, 0 }, { XTS, 0 }, 1 }, - { { AES, TWOFISH, SERPENT, 0 }, { XTS, 0 }, 1 }, - { { SERPENT, TWOFISH, 0 }, { XTS, 0 }, 1 }, - { { 0, 0 }, { 0, 0 }, 0 }, // Must be all-zero - -#endif - -}; - - - -// Hash algorithms -static Hash Hashes[] = -{ // ID Name Deprecated System Encryption - { RIPEMD160, "RIPEMD-160", FALSE, TRUE }, -#ifndef TC_WINDOWS_BOOT - { SHA512, "SHA-512", FALSE, FALSE }, - { WHIRLPOOL, "Whirlpool", FALSE, FALSE }, - { SHA1, "SHA-1", TRUE, FALSE }, // Deprecated/legacy -#endif - { 0, 0, 0 } -}; - -/* Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) */ -int CipherInit (int cipher, unsigned char *key, unsigned __int8 *ks) -{ - int retVal = ERR_SUCCESS; - - switch (cipher) - { - case AES: -#ifndef TC_WINDOWS_BOOT - if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) - return ERR_CIPHER_INIT_FAILURE; - - if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != EXIT_SUCCESS) - return ERR_CIPHER_INIT_FAILURE; -#else - if (aes_set_key (key, (length_type) CipherGetKeySize(AES), (aes_context *) ks) != 0) - return ERR_CIPHER_INIT_FAILURE; -#endif - break; - - case SERPENT: - serpent_set_key (key, CipherGetKeySize(SERPENT) * 8, ks); - break; - - case TWOFISH: - twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, CipherGetKeySize(TWOFISH) * 8); - break; - -#ifndef TC_WINDOWS_BOOT - - case BLOWFISH: - /* Deprecated/legacy */ - BlowfishSetKey ((BF_KEY *)ks, CipherGetKeySize(BLOWFISH), key); - break; - - case CAST: - /* Deprecated/legacy */ - Cast5SetKey ((CAST_KEY *) ks, CipherGetKeySize(CAST), key); - break; - - case TRIPLEDES: - /* Deprecated/legacy */ - TripleDesSetKey (key, CipherGetKeySize (TRIPLEDES), (TDES_KEY *) ks); - - // Verify whether all three DES keys are mutually different - if (((*((__int64 *) key) ^ *((__int64 *) key+1)) & 0xFEFEFEFEFEFEFEFEULL) == 0 - || ((*((__int64 *) key+1) ^ *((__int64 *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0 - || ((*((__int64 *) key) ^ *((__int64 *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0) - retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error - - break; - -#endif // TC_WINDOWS_BOOT - - default: - // Unknown/wrong cipher ID - return ERR_CIPHER_INIT_FAILURE; - } - - return retVal; -} - -void EncipherBlock(int cipher, void *data, void *ks) -{ - switch (cipher) - { - case AES: aes_encrypt (data, data, ks); break; - case TWOFISH: twofish_encrypt (ks, data, data); break; - case SERPENT: serpent_encrypt (data, data, ks); break; -#ifndef TC_WINDOWS_BOOT - case BLOWFISH: BlowfishEncryptLE (data, data, ks, 1); break; // Deprecated/legacy - case CAST: Cast5Encrypt (data, data, ks); break; // Deprecated/legacy - case TRIPLEDES: TripleDesEncrypt (data, data, ks, 1); break; // Deprecated/legacy -#endif - default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID - } -} - -void DecipherBlock(int cipher, void *data, void *ks) -{ - switch (cipher) - { - case SERPENT: serpent_decrypt (data, data, ks); break; - case TWOFISH: twofish_decrypt (ks, data, data); break; -#ifndef TC_WINDOWS_BOOT - case AES: aes_decrypt (data, data, (void *) ((char *) ks + sizeof(aes_encrypt_ctx))); break; - case BLOWFISH: BlowfishEncryptLE (data, data, ks, 0); break; // Deprecated/legacy - case CAST: Cast5Decrypt (data, data, ks); break; // Deprecated/legacy - case TRIPLEDES: TripleDesEncrypt (data, data, ks, 0); break; // Deprecated/legacy -#else - case AES: aes_decrypt (data, data, ks); break; -#endif - default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID - } -} - -// Ciphers support - -Cipher *CipherGet (int id) -{ - int i; - for (i = 0; Ciphers[i].Id != 0; i++) - if (Ciphers[i].Id == id) - return &Ciphers[i]; - - return NULL; -} - -char *CipherGetName (int cipherId) -{ - return CipherGet (cipherId) -> Name; -} - -int CipherGetBlockSize (int cipherId) -{ - return CipherGet (cipherId) -> BlockSize; -} - -int CipherGetKeySize (int cipherId) -{ - return CipherGet (cipherId) -> KeySize; -} - -int CipherGetKeyScheduleSize (int cipherId) -{ - return CipherGet (cipherId) -> KeyScheduleSize; -} - - -// Encryption algorithms support - -int EAGetFirst () -{ - return 1; -} - -// Returns number of EAs -int EAGetCount (void) -{ - int ea, count = 0; - - for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) - { - count++; - } - return count; -} - -int EAGetNext (int previousEA) -{ - int id = previousEA + 1; - if (EncryptionAlgorithms[id].Ciphers[0] != 0) return id; - return 0; -} - - -// Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) -int EAInit (int ea, unsigned char *key, unsigned __int8 *ks) -{ - int c, retVal = ERR_SUCCESS; - - if (ea == 0) - return ERR_CIPHER_INIT_FAILURE; - - for (c = EAGetFirstCipher (ea); c != 0; c = EAGetNextCipher (ea, c)) - { - switch (CipherInit (c, key, ks)) - { - case ERR_CIPHER_INIT_FAILURE: - return ERR_CIPHER_INIT_FAILURE; - - case ERR_CIPHER_INIT_WEAK_KEY: - retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error - break; - } - - key += CipherGetKeySize (c); - ks += CipherGetKeyScheduleSize (c); - } - return retVal; -} - - -#ifndef TC_WINDOWS_BOOT - -BOOL EAInitMode (PCRYPTO_INFO ci) -{ - switch (ci->mode) - { - case XTS: - // Secondary key schedule - if (EAInit (ci->ea, ci->k2, ci->ks2) != ERR_SUCCESS) - return FALSE; - - /* Note: XTS mode could potentially be initialized with a weak key causing all blocks in one data unit - on the volume to be tweaked with zero tweaks (i.e. 512 bytes of the volume would be encrypted in ECB - mode). However, to create a TrueCrypt volume with such a weak key, each human being on Earth would have - to create approximately 11,378,125,361,078,862 (about eleven quadrillion) TrueCrypt volumes (provided - that the size of each of the volumes is 1024 terabytes). */ - break; - - case LRW: - switch (CipherGetBlockSize (EAGetFirstCipher (ci->ea))) - { - case 8: - /* Deprecated/legacy */ - return Gf64TabInit (ci->k2, &ci->gf_ctx); - - case 16: - return Gf128Tab64Init (ci->k2, &ci->gf_ctx); - - default: - TC_THROW_FATAL_EXCEPTION; - } - - break; - - case CBC: - case INNER_CBC: - case OUTER_CBC: - // The mode does not need to be initialized or is initialized elsewhere - return TRUE; - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } - return TRUE; -} - - -// Returns name of EA, cascaded cipher names are separated by hyphens -char *EAGetName (char *buf, int ea) -{ - int i = EAGetLastCipher(ea); - strcpy (buf, (i != 0) ? CipherGetName (i) : "?"); - - while (i = EAGetPreviousCipher(ea, i)) - { - strcat (buf, "-"); - strcat (buf, CipherGetName (i)); - } - - return buf; -} - - -int EAGetByName (char *name) -{ - int ea = EAGetFirst (); - char n[128]; - - do - { - EAGetName (n, ea); - if (strcmp (n, name) == 0) - return ea; - } - while (ea = EAGetNext (ea)); - - return 0; -} - -#endif // TC_WINDOWS_BOOT - -// Returns sum of key sizes of all ciphers of the EA (in bytes) -int EAGetKeySize (int ea) -{ - int i = EAGetFirstCipher (ea); - int size = CipherGetKeySize (i); - - while (i = EAGetNextCipher (ea, i)) - { - size += CipherGetKeySize (i); - } - - return size; -} - - -// Returns the first mode of operation of EA -int EAGetFirstMode (int ea) -{ - return (EncryptionAlgorithms[ea].Modes[0]); -} - - -int EAGetNextMode (int ea, int previousModeId) -{ - int c, i = 0; - while (c = EncryptionAlgorithms[ea].Modes[i++]) - { - if (c == previousModeId) - return EncryptionAlgorithms[ea].Modes[i]; - } - - return 0; -} - - -#ifndef TC_WINDOWS_BOOT - -// Returns the name of the mode of operation of the whole EA -char *EAGetModeName (int ea, int mode, BOOL capitalLetters) -{ - switch (mode) - { - case XTS: - - return "XTS"; - - case LRW: - - /* Deprecated/legacy */ - - return "LRW"; - - case CBC: - { - /* Deprecated/legacy */ - - char eaName[100]; - EAGetName (eaName, ea); - - if (strcmp (eaName, "Triple DES") == 0) - return capitalLetters ? "Outer-CBC" : "outer-CBC"; - - return "CBC"; - } - - case OUTER_CBC: - - /* Deprecated/legacy */ - - return capitalLetters ? "Outer-CBC" : "outer-CBC"; - - case INNER_CBC: - - /* Deprecated/legacy */ - - return capitalLetters ? "Inner-CBC" : "inner-CBC"; - - } - return "[unknown]"; -} - -#endif // TC_WINDOWS_BOOT - - -// Returns sum of key schedule sizes of all ciphers of the EA -int EAGetKeyScheduleSize (int ea) -{ - int i = EAGetFirstCipher(ea); - int size = CipherGetKeyScheduleSize (i); - - while (i = EAGetNextCipher(ea, i)) - { - size += CipherGetKeyScheduleSize (i); - } - - return size; -} - - -// Returns the largest key size needed by an EA for the specified mode of operation -int EAGetLargestKeyForMode (int mode) -{ - int ea, key = 0; - - for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) - { - if (!EAIsModeSupported (ea, mode)) - continue; - - if (EAGetKeySize (ea) >= key) - key = EAGetKeySize (ea); - } - return key; -} - - -// Returns the largest key needed by any EA for any mode -int EAGetLargestKey () -{ - int ea, key = 0; - - for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) - { - if (EAGetKeySize (ea) >= key) - key = EAGetKeySize (ea); - } - - return key; -} - - -// Returns number of ciphers in EA -int EAGetCipherCount (int ea) -{ - int i = 0; - while (EncryptionAlgorithms[ea].Ciphers[i++]); - - return i - 1; -} - - -int EAGetFirstCipher (int ea) -{ - return EncryptionAlgorithms[ea].Ciphers[0]; -} - - -int EAGetLastCipher (int ea) -{ - int c, i = 0; - while (c = EncryptionAlgorithms[ea].Ciphers[i++]); - - return EncryptionAlgorithms[ea].Ciphers[i - 2]; -} - - -int EAGetNextCipher (int ea, int previousCipherId) -{ - int c, i = 0; - while (c = EncryptionAlgorithms[ea].Ciphers[i++]) - { - if (c == previousCipherId) - return EncryptionAlgorithms[ea].Ciphers[i]; - } - - return 0; -} - - -int EAGetPreviousCipher (int ea, int previousCipherId) -{ - int c, i = 0; - - if (EncryptionAlgorithms[ea].Ciphers[i++] == previousCipherId) - return 0; - - while (c = EncryptionAlgorithms[ea].Ciphers[i++]) - { - if (c == previousCipherId) - return EncryptionAlgorithms[ea].Ciphers[i - 2]; - } - - return 0; -} - - -int EAIsFormatEnabled (int ea) -{ - return EncryptionAlgorithms[ea].FormatEnabled; -} - - -// Returns TRUE if the mode of operation is supported for the encryption algorithm -BOOL EAIsModeSupported (int ea, int testedMode) -{ - int mode; - - for (mode = EAGetFirstMode (ea); mode != 0; mode = EAGetNextMode (ea, mode)) - { - if (mode == testedMode) - return TRUE; - } - return FALSE; -} - - -Hash *HashGet (int id) -{ - int i; - for (i = 0; Hashes[i].Id != 0; i++) - if (Hashes[i].Id == id) - return &Hashes[i]; - - return 0; -} - - -int HashGetIdByName (char *name) -{ - int i; - for (i = 0; Hashes[i].Id != 0; i++) - if (strcmp (Hashes[i].Name, name) == 0) - return Hashes[i].Id; - - return 0; -} - - -char *HashGetName (int hashId) -{ - return HashGet (hashId) -> Name; -} - - -BOOL HashIsDeprecated (int hashId) -{ - return HashGet (hashId) -> Deprecated; -} - - -#endif // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE - - -#ifdef TC_WINDOWS_BOOT - -static byte CryptoInfoBufferInUse = 0; -CRYPTO_INFO CryptoInfoBuffer; - -#endif - -PCRYPTO_INFO crypto_open () -{ -#ifndef TC_WINDOWS_BOOT - - /* Do the crt allocation */ - PCRYPTO_INFO cryptoInfo = (PCRYPTO_INFO) TCalloc (sizeof (CRYPTO_INFO)); - memset (cryptoInfo, 0, sizeof (CRYPTO_INFO)); - -#ifndef DEVICE_DRIVER - VirtualLock (cryptoInfo, sizeof (CRYPTO_INFO)); -#endif - - if (cryptoInfo == NULL) - return NULL; - - cryptoInfo->ea = -1; - return cryptoInfo; - -#else // TC_WINDOWS_BOOT - -#if 0 - if (CryptoInfoBufferInUse) - TC_THROW_FATAL_EXCEPTION; -#endif - CryptoInfoBufferInUse = 1; - return &CryptoInfoBuffer; - -#endif // TC_WINDOWS_BOOT -} - -void crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen) -{ - keyInfo->keyLength = nUserKeyLen; - burn (keyInfo->userKey, sizeof (keyInfo->userKey)); - memcpy (keyInfo->userKey, lpszUserKey, nUserKeyLen); -} - -void crypto_close (PCRYPTO_INFO cryptoInfo) -{ -#ifndef TC_WINDOWS_BOOT - - if (cryptoInfo != NULL) - { - burn (cryptoInfo, sizeof (CRYPTO_INFO)); -#ifndef DEVICE_DRIVER - VirtualUnlock (cryptoInfo, sizeof (CRYPTO_INFO)); -#endif - TCfree (cryptoInfo); - } - -#else // TC_WINDOWS_BOOT - - burn (&CryptoInfoBuffer, sizeof (CryptoInfoBuffer)); - CryptoInfoBufferInUse = FALSE; - -#endif // TC_WINDOWS_BOOT -} - - -#ifndef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE - - -#ifndef TC_NO_COMPILER_INT64 -void Xor128 (unsigned __int64 *a, unsigned __int64 *b) -{ - *a++ ^= *b++; - *a ^= *b; -} - - -void Xor64 (unsigned __int64 *a, unsigned __int64 *b) -{ - *a ^= *b; -} - - -void EncryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) -{ - /* Deprecated/legacy */ - - int cipher = EAGetFirstCipher (cryptoInfo->ea); - int cipherCount = EAGetCipherCount (cryptoInfo->ea); - unsigned __int8 *p = buffer; - unsigned __int8 *ks = cryptoInfo->ks; - unsigned __int8 i[8]; - unsigned __int8 t[16]; - unsigned __int64 b; - - *(unsigned __int64 *)i = BE64(blockIndex); - - if (length % 16) - TC_THROW_FATAL_EXCEPTION; - - // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). - - for (b = 0; b < length >> 4; b++) - { - Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); - Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - if (cipherCount > 1) - { - // Cipher cascade - for (cipher = EAGetFirstCipher (cryptoInfo->ea); - cipher != 0; - cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) - { - EncipherBlock (cipher, p, ks); - ks += CipherGetKeyScheduleSize (cipher); - } - ks = cryptoInfo->ks; - } - else - { - EncipherBlock (cipher, p, ks); - } - - Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - p += 16; - - if (i[7] != 0xff) - i[7]++; - else - *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); - } - - FAST_ERASE64 (t, sizeof(t)); -} - - -void EncryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) -{ - /* Deprecated/legacy */ - - int cipher = EAGetFirstCipher (cryptoInfo->ea); - unsigned __int8 *p = buffer; - unsigned __int8 *ks = cryptoInfo->ks; - unsigned __int8 i[8]; - unsigned __int8 t[8]; - unsigned __int64 b; - - *(unsigned __int64 *)i = BE64(blockIndex); - - if (length % 8) - TC_THROW_FATAL_EXCEPTION; - - for (b = 0; b < length >> 3; b++) - { - Gf64MulTab (i, t, &cryptoInfo->gf_ctx); - Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - EncipherBlock (cipher, p, ks); - - Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - p += 8; - - if (i[7] != 0xff) - i[7]++; - else - *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); - } - - FAST_ERASE64 (t, sizeof(t)); -} - - -void DecryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) -{ - /* Deprecated/legacy */ - - int cipher = EAGetFirstCipher (cryptoInfo->ea); - int cipherCount = EAGetCipherCount (cryptoInfo->ea); - unsigned __int8 *p = buffer; - unsigned __int8 *ks = cryptoInfo->ks; - unsigned __int8 i[8]; - unsigned __int8 t[16]; - unsigned __int64 b; - - *(unsigned __int64 *)i = BE64(blockIndex); - - if (length % 16) - TC_THROW_FATAL_EXCEPTION; - - // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). - - for (b = 0; b < length >> 4; b++) - { - Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); - Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - if (cipherCount > 1) - { - // Cipher cascade - ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); - - for (cipher = EAGetLastCipher (cryptoInfo->ea); - cipher != 0; - cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) - { - ks -= CipherGetKeyScheduleSize (cipher); - DecipherBlock (cipher, p, ks); - } - } - else - { - DecipherBlock (cipher, p, ks); - } - - Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - p += 16; - - if (i[7] != 0xff) - i[7]++; - else - *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); - } - - FAST_ERASE64 (t, sizeof(t)); -} - - - -void DecryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) -{ - /* Deprecated/legacy */ - - int cipher = EAGetFirstCipher (cryptoInfo->ea); - unsigned __int8 *p = buffer; - unsigned __int8 *ks = cryptoInfo->ks; - unsigned __int8 i[8]; - unsigned __int8 t[8]; - unsigned __int64 b; - - *(unsigned __int64 *)i = BE64(blockIndex); - - if (length % 8) - TC_THROW_FATAL_EXCEPTION; - - for (b = 0; b < length >> 3; b++) - { - Gf64MulTab (i, t, &cryptoInfo->gf_ctx); - Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - DecipherBlock (cipher, p, ks); - - Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); - - p += 8; - - if (i[7] != 0xff) - i[7]++; - else - *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); - } - - FAST_ERASE64 (t, sizeof(t)); -} - - -// Initializes IV and whitening values for sector encryption/decryption in CBC mode. -// IMPORTANT: This function has been deprecated (legacy). -static void -InitSectorIVAndWhitening (unsigned __int64 unitNo, - int blockSize, - unsigned __int32 *iv, - unsigned __int64 *ivSeed, - unsigned __int32 *whitening) -{ - - /* IMPORTANT: This function has been deprecated (legacy) */ - - unsigned __int64 iv64[4]; - unsigned __int32 *iv32 = (unsigned __int32 *) iv64; - - iv64[0] = ivSeed[0] ^ LE64(unitNo); - iv64[1] = ivSeed[1] ^ LE64(unitNo); - iv64[2] = ivSeed[2] ^ LE64(unitNo); - if (blockSize == 16) - { - iv64[3] = ivSeed[3] ^ LE64(unitNo); - } - - iv[0] = iv32[0]; - iv[1] = iv32[1]; - - switch (blockSize) - { - case 16: - - // 128-bit block - - iv[2] = iv32[2]; - iv[3] = iv32[3]; - - whitening[0] = LE32( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) ); - whitening[1] = LE32( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) ); - break; - - case 8: - - // 64-bit block - - whitening[0] = LE32( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) ); - whitening[1] = LE32( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) ); - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } -} - - -// EncryptBufferCBC (deprecated/legacy) -// -// data: data to be encrypted -// len: number of bytes to encrypt (must be divisible by the largest cipher block size) -// ks: scheduled key -// iv: IV -// whitening: whitening constants -// ea: outer-CBC cascade ID (0 = CBC/inner-CBC) -// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC) - -static void -EncryptBufferCBC (unsigned __int32 *data, - unsigned int len, - unsigned __int8 *ks, - unsigned __int32 *iv, - unsigned __int32 *whitening, - int ea, - int cipher) -{ - /* IMPORTANT: This function has been deprecated (legacy) */ - - unsigned __int32 bufIV[4]; - unsigned __int64 i; - int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); - - if (len % blockSize) - TC_THROW_FATAL_EXCEPTION; - - // IV - bufIV[0] = iv[0]; - bufIV[1] = iv[1]; - if (blockSize == 16) - { - bufIV[2] = iv[2]; - bufIV[3] = iv[3]; - } - - // Encrypt each block - for (i = 0; i < len/blockSize; i++) - { - // CBC - data[0] ^= bufIV[0]; - data[1] ^= bufIV[1]; - if (blockSize == 16) - { - data[2] ^= bufIV[2]; - data[3] ^= bufIV[3]; - } - - if (ea != 0) - { - // Outer-CBC - for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) - { - EncipherBlock (cipher, data, ks); - ks += CipherGetKeyScheduleSize (cipher); - } - ks -= EAGetKeyScheduleSize (ea); - } - else - { - // CBC/inner-CBC - EncipherBlock (cipher, data, ks); - } - - // CBC - bufIV[0] = data[0]; - bufIV[1] = data[1]; - if (blockSize == 16) - { - bufIV[2] = data[2]; - bufIV[3] = data[3]; - } - - // Whitening - data[0] ^= whitening[0]; - data[1] ^= whitening[1]; - if (blockSize == 16) - { - data[2] ^= whitening[0]; - data[3] ^= whitening[1]; - } - - data += blockSize / sizeof(*data); - } -} - - -// DecryptBufferCBC (deprecated/legacy) -// -// data: data to be decrypted -// len: number of bytes to decrypt (must be divisible by the largest cipher block size) -// ks: scheduled key -// iv: IV -// whitening: whitening constants -// ea: outer-CBC cascade ID (0 = CBC/inner-CBC) -// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC) - -static void -DecryptBufferCBC (unsigned __int32 *data, - unsigned int len, - unsigned __int8 *ks, - unsigned __int32 *iv, - unsigned __int32 *whitening, - int ea, - int cipher) -{ - - /* IMPORTANT: This function has been deprecated (legacy) */ - - unsigned __int32 bufIV[4]; - unsigned __int64 i; - unsigned __int32 ct[4]; - int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); - - if (len % blockSize) - TC_THROW_FATAL_EXCEPTION; - - // IV - bufIV[0] = iv[0]; - bufIV[1] = iv[1]; - if (blockSize == 16) - { - bufIV[2] = iv[2]; - bufIV[3] = iv[3]; - } - - // Decrypt each block - for (i = 0; i < len/blockSize; i++) - { - // Dewhitening - data[0] ^= whitening[0]; - data[1] ^= whitening[1]; - if (blockSize == 16) - { - data[2] ^= whitening[0]; - data[3] ^= whitening[1]; - } - - // CBC - ct[0] = data[0]; - ct[1] = data[1]; - if (blockSize == 16) - { - ct[2] = data[2]; - ct[3] = data[3]; - } - - if (ea != 0) - { - // Outer-CBC - ks += EAGetKeyScheduleSize (ea); - for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) - { - ks -= CipherGetKeyScheduleSize (cipher); - DecipherBlock (cipher, data, ks); - } - } - else - { - // CBC/inner-CBC - DecipherBlock (cipher, data, ks); - } - - // CBC - data[0] ^= bufIV[0]; - data[1] ^= bufIV[1]; - bufIV[0] = ct[0]; - bufIV[1] = ct[1]; - if (blockSize == 16) - { - data[2] ^= bufIV[2]; - data[3] ^= bufIV[3]; - bufIV[2] = ct[2]; - bufIV[3] = ct[3]; - } - - data += blockSize / sizeof(*data); - } -} -#endif // #ifndef TC_NO_COMPILER_INT64 - - -// EncryptBuffer -// -// buf: data to be encrypted; the start of the buffer is assumed to be aligned with the start of a data unit. -// len: number of bytes to encrypt; must be divisible by the block size (for cascaded ciphers, divisible -// by the largest block size used within the cascade) -void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) -{ - switch (cryptoInfo->mode) - { - case XTS: - { - unsigned __int8 *ks = cryptoInfo->ks; - unsigned __int8 *ks2 = cryptoInfo->ks2; - UINT64_STRUCT dataUnitNo; - int cipher; - - // When encrypting/decrypting a buffer (typically a volume header) the sequential number - // of the first XTS data unit in the buffer is always 0 and the start of the buffer is - // always assumed to be aligned with the start of a data unit. - dataUnitNo.LowPart = 0; - dataUnitNo.HighPart = 0; - - for (cipher = EAGetFirstCipher (cryptoInfo->ea); - cipher != 0; - cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) - { - EncryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); - - ks += CipherGetKeyScheduleSize (cipher); - ks2 += CipherGetKeyScheduleSize (cipher); - } - } - break; - -#ifndef TC_NO_COMPILER_INT64 - case LRW: - - /* Deprecated/legacy */ - - switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) - { - case 8: - EncryptBufferLRW64 ((unsigned __int8 *)buf, (unsigned __int64) len, 1, cryptoInfo); - break; - - case 16: - EncryptBufferLRW128 ((unsigned __int8 *)buf, (unsigned __int64) len, 1, cryptoInfo); - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } - break; - - case CBC: - case INNER_CBC: - { - /* Deprecated/legacy */ - - unsigned __int8 *ks = cryptoInfo->ks; - int cipher; - - for (cipher = EAGetFirstCipher (cryptoInfo->ea); - cipher != 0; - cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) - { - EncryptBufferCBC ((unsigned __int32 *) buf, - (unsigned int) len, - ks, - (unsigned __int32 *) cryptoInfo->k2, - (unsigned __int32 *) &cryptoInfo->k2[8], - 0, - cipher); - - ks += CipherGetKeyScheduleSize (cipher); - } - } - break; - - case OUTER_CBC: - - /* Deprecated/legacy */ - - EncryptBufferCBC ((unsigned __int32 *) buf, - (unsigned int) len, - cryptoInfo->ks, - (unsigned __int32 *) cryptoInfo->k2, - (unsigned __int32 *) &cryptoInfo->k2[8], - cryptoInfo->ea, - 0); - - break; -#endif // #ifndef TC_NO_COMPILER_INT64 - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } -} - -#ifndef TC_NO_COMPILER_INT64 -// Converts a data unit number to the index of the first LRW block in the data unit. -// Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). -uint64 DataUnit2LRWIndex (uint64 dataUnit, int blockSize, PCRYPTO_INFO ci) -{ - /* Deprecated/legacy */ - - if (ci->hiddenVolume) - dataUnit -= ci->hiddenVolumeOffset / ENCRYPTION_DATA_UNIT_SIZE; - else - dataUnit -= TC_VOLUME_HEADER_SIZE_LEGACY / ENCRYPTION_DATA_UNIT_SIZE; // Compensate for the volume header size - - switch (blockSize) - { - case 8: - return (dataUnit << 6) | 1; - - case 16: - return (dataUnit << 5) | 1; - - default: - TC_THROW_FATAL_EXCEPTION; - } - - return 0; -} -#endif // #ifndef TC_NO_COMPILER_INT64 - - -// buf: data to be encrypted -// unitNo: sequential number of the data unit with which the buffer starts -// nbrUnits: number of data units in the buffer -void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) -#ifndef TC_WINDOWS_BOOT -{ - EncryptionThreadPoolDoWork (EncryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci); -} - -void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) -#endif // !TC_WINDOWS_BOOT -{ - int ea = ci->ea; - unsigned __int8 *ks = ci->ks; - unsigned __int8 *ks2 = ci->ks2; - int cipher; - -#ifndef TC_NO_COMPILER_INT64 - void *iv = ci->k2; // Deprecated/legacy - unsigned __int64 unitNo = structUnitNo->Value; - unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy - unsigned __int32 sectorIV[4]; // Deprecated/legacy - unsigned __int32 secWhitening[2]; // Deprecated/legacy -#endif - - switch (ci->mode) - { - case XTS: - for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) - { - EncryptBufferXTS (buf, - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, - structUnitNo, - 0, - ks, - ks2, - cipher); - - ks += CipherGetKeyScheduleSize (cipher); - ks2 += CipherGetKeyScheduleSize (cipher); - } - break; - -#ifndef TC_NO_COMPILER_INT64 - case LRW: - - /* Deprecated/legacy */ - - switch (CipherGetBlockSize (EAGetFirstCipher (ea))) - { - case 8: - EncryptBufferLRW64 (buf, - (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, - DataUnit2LRWIndex (unitNo, 8, ci), - ci); - break; - - case 16: - EncryptBufferLRW128 (buf, - (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, - DataUnit2LRWIndex (unitNo, 16, ci), - ci); - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } - break; - - case CBC: - case INNER_CBC: - - /* Deprecated/legacy */ - - while (nbrUnits--) - { - for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) - { - InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); - - EncryptBufferCBC ((unsigned __int32 *) buf, - ENCRYPTION_DATA_UNIT_SIZE, - ks, - sectorIV, - secWhitening, - 0, - cipher); - - ks += CipherGetKeyScheduleSize (cipher); - } - ks -= EAGetKeyScheduleSize (ea); - buf += ENCRYPTION_DATA_UNIT_SIZE; - unitNo++; - } - break; - - case OUTER_CBC: - - /* Deprecated/legacy */ - - while (nbrUnits--) - { - InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); - - EncryptBufferCBC ((unsigned __int32 *) buf, - ENCRYPTION_DATA_UNIT_SIZE, - ks, - sectorIV, - secWhitening, - ea, - 0); - - buf += ENCRYPTION_DATA_UNIT_SIZE; - unitNo++; - } - break; -#endif // #ifndef TC_NO_COMPILER_INT64 - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } -} - -// DecryptBuffer -// -// buf: data to be decrypted; the start of the buffer is assumed to be aligned with the start of a data unit. -// len: number of bytes to decrypt; must be divisible by the block size (for cascaded ciphers, divisible -// by the largest block size used within the cascade) -void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) -{ - switch (cryptoInfo->mode) - { - case XTS: - { - unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); - unsigned __int8 *ks2 = cryptoInfo->ks2 + EAGetKeyScheduleSize (cryptoInfo->ea); - UINT64_STRUCT dataUnitNo; - int cipher; - - // When encrypting/decrypting a buffer (typically a volume header) the sequential number - // of the first XTS data unit in the buffer is always 0 and the start of the buffer is - // always assumed to be aligned with the start of the data unit 0. - dataUnitNo.LowPart = 0; - dataUnitNo.HighPart = 0; - - for (cipher = EAGetLastCipher (cryptoInfo->ea); - cipher != 0; - cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) - { - ks -= CipherGetKeyScheduleSize (cipher); - ks2 -= CipherGetKeyScheduleSize (cipher); - - DecryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); - } - } - break; - -#ifndef TC_NO_COMPILER_INT64 - case LRW: - - /* Deprecated/legacy */ - - switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) - { - case 8: - DecryptBufferLRW64 (buf, (unsigned __int64) len, 1, cryptoInfo); - break; - - case 16: - DecryptBufferLRW128 (buf, (unsigned __int64) len, 1, cryptoInfo); - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } - break; - - case CBC: - case INNER_CBC: - { - /* Deprecated/legacy */ - - unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); - int cipher; - for (cipher = EAGetLastCipher (cryptoInfo->ea); - cipher != 0; - cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) - { - ks -= CipherGetKeyScheduleSize (cipher); - - DecryptBufferCBC ((unsigned __int32 *) buf, - (unsigned int) len, - ks, - (unsigned __int32 *) cryptoInfo->k2, - (unsigned __int32 *) &cryptoInfo->k2[8], - 0, - cipher); - } - } - break; - - case OUTER_CBC: - - /* Deprecated/legacy */ - - DecryptBufferCBC ((unsigned __int32 *) buf, - (unsigned int) len, - cryptoInfo->ks, - (unsigned __int32 *) cryptoInfo->k2, - (unsigned __int32 *) &cryptoInfo->k2[8], - cryptoInfo->ea, - 0); - - break; -#endif // #ifndef TC_NO_COMPILER_INT64 - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } -} - -// buf: data to be decrypted -// unitNo: sequential number of the data unit with which the buffer starts -// nbrUnits: number of data units in the buffer -void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) -#ifndef TC_WINDOWS_BOOT -{ - EncryptionThreadPoolDoWork (DecryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci); -} - -void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) -#endif // !TC_WINDOWS_BOOT -{ - int ea = ci->ea; - unsigned __int8 *ks = ci->ks; - unsigned __int8 *ks2 = ci->ks2; - int cipher; - -#ifndef TC_NO_COMPILER_INT64 - void *iv = ci->k2; // Deprecated/legacy - unsigned __int64 unitNo = structUnitNo->Value; - unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy - unsigned __int32 sectorIV[4]; // Deprecated/legacy - unsigned __int32 secWhitening[2]; // Deprecated/legacy -#endif // #ifndef TC_NO_COMPILER_INT64 - - - switch (ci->mode) - { - case XTS: - ks += EAGetKeyScheduleSize (ea); - ks2 += EAGetKeyScheduleSize (ea); - - for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) - { - ks -= CipherGetKeyScheduleSize (cipher); - ks2 -= CipherGetKeyScheduleSize (cipher); - - DecryptBufferXTS (buf, - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, - structUnitNo, - 0, - ks, - ks2, - cipher); - } - break; - -#ifndef TC_NO_COMPILER_INT64 - case LRW: - - /* Deprecated/legacy */ - - switch (CipherGetBlockSize (EAGetFirstCipher (ea))) - { - case 8: - DecryptBufferLRW64 (buf, - (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, - DataUnit2LRWIndex (unitNo, 8, ci), - ci); - break; - - case 16: - DecryptBufferLRW128 (buf, - (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, - DataUnit2LRWIndex (unitNo, 16, ci), - ci); - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } - break; - - case CBC: - case INNER_CBC: - - /* Deprecated/legacy */ - - while (nbrUnits--) - { - ks += EAGetKeyScheduleSize (ea); - for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) - { - InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); - - ks -= CipherGetKeyScheduleSize (cipher); - - DecryptBufferCBC ((unsigned __int32 *) buf, - ENCRYPTION_DATA_UNIT_SIZE, - ks, - sectorIV, - secWhitening, - 0, - cipher); - } - buf += ENCRYPTION_DATA_UNIT_SIZE; - unitNo++; - } - break; - - case OUTER_CBC: - - /* Deprecated/legacy */ - - while (nbrUnits--) - { - InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); - - DecryptBufferCBC ((unsigned __int32 *) buf, - ENCRYPTION_DATA_UNIT_SIZE, - ks, - sectorIV, - secWhitening, - ea, - 0); - - buf += ENCRYPTION_DATA_UNIT_SIZE; - unitNo++; - } - break; -#endif // #ifndef TC_NO_COMPILER_INT64 - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } -} - - -// Returns the maximum number of bytes necessary to be generated by the PBKDF2 (PKCS #5) -int GetMaxPkcs5OutSize (void) -{ - int size = 32; - - size = max (size, EAGetLargestKeyForMode (XTS) * 2); // Sizes of primary + secondary keys - -#ifndef TC_WINDOWS_BOOT - size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (LRW)); // Deprecated/legacy - size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (CBC)); // Deprecated/legacy - size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (OUTER_CBC)); // Deprecated/legacy - size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (INNER_CBC)); // Deprecated/legacy -#endif - - return size; -} - - -#else // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE - - -#if !defined (TC_WINDOWS_BOOT_AES) && !defined (TC_WINDOWS_BOOT_SERPENT) && !defined (TC_WINDOWS_BOOT_TWOFISH) -#error No cipher defined -#endif - -void EncipherBlock(int cipher, void *data, void *ks) -{ -#ifdef TC_WINDOWS_BOOT_AES - aes_encrypt (data, data, ks); -#elif defined (TC_WINDOWS_BOOT_SERPENT) - serpent_encrypt (data, data, ks); -#elif defined (TC_WINDOWS_BOOT_TWOFISH) - twofish_encrypt (ks, data, data); -#endif -} - -void DecipherBlock(int cipher, void *data, void *ks) -{ -#ifdef TC_WINDOWS_BOOT_AES - aes_decrypt (data, data, (aes_decrypt_ctx *) ((byte *) ks + sizeof(aes_encrypt_ctx))); -#elif defined (TC_WINDOWS_BOOT_SERPENT) - serpent_decrypt (data, data, ks); -#elif defined (TC_WINDOWS_BOOT_TWOFISH) - twofish_decrypt (ks, data, data); -#endif -} - -int EAGetFirst () -{ - return 1; -} - -int EAGetNext (int previousEA) -{ - return 0; -} - -int EAInit (int ea, unsigned char *key, unsigned __int8 *ks) -{ -#ifdef TC_WINDOWS_BOOT_AES - - aes_init(); - - if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) - return ERR_CIPHER_INIT_FAILURE; - if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ks + sizeof (aes_encrypt_ctx))) != EXIT_SUCCESS) - return ERR_CIPHER_INIT_FAILURE; - -#elif defined (TC_WINDOWS_BOOT_SERPENT) - serpent_set_key (key, 32 * 8, ks); -#elif defined (TC_WINDOWS_BOOT_TWOFISH) - twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, 32 * 8); -#endif - return ERR_SUCCESS; -} - -int EAGetKeySize (int ea) -{ - return 32; -} - -int EAGetFirstCipher (int ea) -{ - return 1; -} - -void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) -{ - UINT64_STRUCT dataUnitNo; - dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; - EncryptBufferXTS (buf, len, &dataUnitNo, 0, cryptoInfo->ks, cryptoInfo->ks2, 1); -} - -void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) -{ - EncryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ci->ks, ci->ks2, 1); -} - -void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) -{ - UINT64_STRUCT dataUnitNo; - dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; - DecryptBufferXTS (buf, len, &dataUnitNo, 0, cryptoInfo->ks, cryptoInfo->ks2, 1); -} - -void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) -{ - DecryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ci->ks, ci->ks2, 1); -} - -#endif // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" +#include "Crypto.h" +#include "Xts.h" +#include "Crc.h" +#include "Common/Endian.h" +#include +#ifndef TC_WINDOWS_BOOT +#include "EncryptionThreadPool.h" +#endif +#include "Volumes.h" + +/* Update the following when adding a new cipher or EA: + + Crypto.h: + ID #define + MAX_EXPANDED_KEY #define + + Crypto.c: + Ciphers[] + EncryptionAlgorithms[] + CipherInit() + EncipherBlock() + DecipherBlock() + +*/ + +#ifndef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + +// Cipher configuration +static Cipher Ciphers[] = +{ +// Block Size Key Size Key Schedule Size +// ID Name (Bytes) (Bytes) (Bytes) + { AES, "AES", 16, 32, AES_KS }, + { SERPENT, "Serpent", 16, 32, 140*4 }, + { TWOFISH, "Twofish", 16, 32, TWOFISH_KS }, +#ifndef TC_WINDOWS_BOOT + { BLOWFISH, "Blowfish", 8, 56, sizeof (BF_KEY) }, // Deprecated/legacy + { CAST, "CAST5", 8, 16, sizeof (CAST_KEY) }, // Deprecated/legacy + { TRIPLEDES,"Triple DES", 8, 8*3, sizeof (TDES_KEY) }, // Deprecated/legacy +#endif + { 0, 0, 0, 0, 0 } +}; + + +// Encryption algorithm configuration +// The following modes have been deprecated (legacy): LRW, CBC, INNER_CBC, OUTER_CBC +static EncryptionAlgorithm EncryptionAlgorithms[] = +{ + // Cipher(s) Modes FormatEnabled + +#ifndef TC_WINDOWS_BOOT + + { { 0, 0 }, { 0, 0, 0, 0 }, 0 }, // Must be all-zero + { { AES, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { SERPENT, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { TWOFISH, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { TWOFISH, AES, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, AES, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { AES, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { AES, TWOFISH, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { BLOWFISH, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { CAST, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { TRIPLEDES, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy + { { SERPENT, BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy + { { 0, 0 }, { 0, 0, 0, 0 }, 0 } // Must be all-zero + +#else // TC_WINDOWS_BOOT + + // Encryption algorithms available for boot drive encryption + { { 0, 0 }, { 0, 0 }, 0 }, // Must be all-zero + { { AES, 0 }, { XTS, 0 }, 1 }, + { { SERPENT, 0 }, { XTS, 0 }, 1 }, + { { TWOFISH, 0 }, { XTS, 0 }, 1 }, + { { TWOFISH, AES, 0 }, { XTS, 0 }, 1 }, + { { SERPENT, TWOFISH, AES, 0 }, { XTS, 0 }, 1 }, + { { AES, SERPENT, 0 }, { XTS, 0 }, 1 }, + { { AES, TWOFISH, SERPENT, 0 }, { XTS, 0 }, 1 }, + { { SERPENT, TWOFISH, 0 }, { XTS, 0 }, 1 }, + { { 0, 0 }, { 0, 0 }, 0 }, // Must be all-zero + +#endif + +}; + + + +// Hash algorithms +static Hash Hashes[] = +{ // ID Name Deprecated System Encryption + { RIPEMD160, "RIPEMD-160", FALSE, TRUE }, +#ifndef TC_WINDOWS_BOOT + { SHA512, "SHA-512", FALSE, FALSE }, + { WHIRLPOOL, "Whirlpool", FALSE, FALSE }, + { SHA1, "SHA-1", TRUE, FALSE }, // Deprecated/legacy +#endif + { 0, 0, 0 } +}; + +/* Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) */ +int CipherInit (int cipher, unsigned char *key, unsigned __int8 *ks) +{ + int retVal = ERR_SUCCESS; + + switch (cipher) + { + case AES: +#ifndef TC_WINDOWS_BOOT + if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + + if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; +#else + if (aes_set_key (key, (length_type) CipherGetKeySize(AES), (aes_context *) ks) != 0) + return ERR_CIPHER_INIT_FAILURE; +#endif + break; + + case SERPENT: + serpent_set_key (key, CipherGetKeySize(SERPENT) * 8, ks); + break; + + case TWOFISH: + twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, CipherGetKeySize(TWOFISH) * 8); + break; + +#ifndef TC_WINDOWS_BOOT + + case BLOWFISH: + /* Deprecated/legacy */ + BlowfishSetKey ((BF_KEY *)ks, CipherGetKeySize(BLOWFISH), key); + break; + + case CAST: + /* Deprecated/legacy */ + Cast5SetKey ((CAST_KEY *) ks, CipherGetKeySize(CAST), key); + break; + + case TRIPLEDES: + /* Deprecated/legacy */ + TripleDesSetKey (key, CipherGetKeySize (TRIPLEDES), (TDES_KEY *) ks); + + // Verify whether all three DES keys are mutually different + if (((*((__int64 *) key) ^ *((__int64 *) key+1)) & 0xFEFEFEFEFEFEFEFEULL) == 0 + || ((*((__int64 *) key+1) ^ *((__int64 *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0 + || ((*((__int64 *) key) ^ *((__int64 *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0) + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + + break; + +#endif // TC_WINDOWS_BOOT + + default: + // Unknown/wrong cipher ID + return ERR_CIPHER_INIT_FAILURE; + } + + return retVal; +} + +void EncipherBlock(int cipher, void *data, void *ks) +{ + switch (cipher) + { + case AES: aes_encrypt (data, data, ks); break; + case TWOFISH: twofish_encrypt (ks, data, data); break; + case SERPENT: serpent_encrypt (data, data, ks); break; +#ifndef TC_WINDOWS_BOOT + case BLOWFISH: BlowfishEncryptLE (data, data, ks, 1); break; // Deprecated/legacy + case CAST: Cast5Encrypt (data, data, ks); break; // Deprecated/legacy + case TRIPLEDES: TripleDesEncrypt (data, data, ks, 1); break; // Deprecated/legacy +#endif + default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID + } +} + +void DecipherBlock(int cipher, void *data, void *ks) +{ + switch (cipher) + { + case SERPENT: serpent_decrypt (data, data, ks); break; + case TWOFISH: twofish_decrypt (ks, data, data); break; +#ifndef TC_WINDOWS_BOOT + case AES: aes_decrypt (data, data, (void *) ((char *) ks + sizeof(aes_encrypt_ctx))); break; + case BLOWFISH: BlowfishEncryptLE (data, data, ks, 0); break; // Deprecated/legacy + case CAST: Cast5Decrypt (data, data, ks); break; // Deprecated/legacy + case TRIPLEDES: TripleDesEncrypt (data, data, ks, 0); break; // Deprecated/legacy +#else + case AES: aes_decrypt (data, data, ks); break; +#endif + default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID + } +} + +// Ciphers support + +Cipher *CipherGet (int id) +{ + int i; + for (i = 0; Ciphers[i].Id != 0; i++) + if (Ciphers[i].Id == id) + return &Ciphers[i]; + + return NULL; +} + +char *CipherGetName (int cipherId) +{ + return CipherGet (cipherId) -> Name; +} + +int CipherGetBlockSize (int cipherId) +{ + return CipherGet (cipherId) -> BlockSize; +} + +int CipherGetKeySize (int cipherId) +{ + return CipherGet (cipherId) -> KeySize; +} + +int CipherGetKeyScheduleSize (int cipherId) +{ + return CipherGet (cipherId) -> KeyScheduleSize; +} + + +// Encryption algorithms support + +int EAGetFirst () +{ + return 1; +} + +// Returns number of EAs +int EAGetCount (void) +{ + int ea, count = 0; + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + count++; + } + return count; +} + +int EAGetNext (int previousEA) +{ + int id = previousEA + 1; + if (EncryptionAlgorithms[id].Ciphers[0] != 0) return id; + return 0; +} + + +// Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) +int EAInit (int ea, unsigned char *key, unsigned __int8 *ks) +{ + int c, retVal = ERR_SUCCESS; + + if (ea == 0) + return ERR_CIPHER_INIT_FAILURE; + + for (c = EAGetFirstCipher (ea); c != 0; c = EAGetNextCipher (ea, c)) + { + switch (CipherInit (c, key, ks)) + { + case ERR_CIPHER_INIT_FAILURE: + return ERR_CIPHER_INIT_FAILURE; + + case ERR_CIPHER_INIT_WEAK_KEY: + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + break; + } + + key += CipherGetKeySize (c); + ks += CipherGetKeyScheduleSize (c); + } + return retVal; +} + + +#ifndef TC_WINDOWS_BOOT + +BOOL EAInitMode (PCRYPTO_INFO ci) +{ + switch (ci->mode) + { + case XTS: + // Secondary key schedule + if (EAInit (ci->ea, ci->k2, ci->ks2) != ERR_SUCCESS) + return FALSE; + + /* Note: XTS mode could potentially be initialized with a weak key causing all blocks in one data unit + on the volume to be tweaked with zero tweaks (i.e. 512 bytes of the volume would be encrypted in ECB + mode). However, to create a TrueCrypt volume with such a weak key, each human being on Earth would have + to create approximately 11,378,125,361,078,862 (about eleven quadrillion) TrueCrypt volumes (provided + that the size of each of the volumes is 1024 terabytes). */ + break; + + case LRW: + switch (CipherGetBlockSize (EAGetFirstCipher (ci->ea))) + { + case 8: + /* Deprecated/legacy */ + return Gf64TabInit (ci->k2, &ci->gf_ctx); + + case 16: + return Gf128Tab64Init (ci->k2, &ci->gf_ctx); + + default: + TC_THROW_FATAL_EXCEPTION; + } + + break; + + case CBC: + case INNER_CBC: + case OUTER_CBC: + // The mode does not need to be initialized or is initialized elsewhere + return TRUE; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + return TRUE; +} + + +// Returns name of EA, cascaded cipher names are separated by hyphens +char *EAGetName (char *buf, int ea) +{ + int i = EAGetLastCipher(ea); + strcpy (buf, (i != 0) ? CipherGetName (i) : "?"); + + while (i = EAGetPreviousCipher(ea, i)) + { + strcat (buf, "-"); + strcat (buf, CipherGetName (i)); + } + + return buf; +} + + +int EAGetByName (char *name) +{ + int ea = EAGetFirst (); + char n[128]; + + do + { + EAGetName (n, ea); + if (strcmp (n, name) == 0) + return ea; + } + while (ea = EAGetNext (ea)); + + return 0; +} + +#endif // TC_WINDOWS_BOOT + +// Returns sum of key sizes of all ciphers of the EA (in bytes) +int EAGetKeySize (int ea) +{ + int i = EAGetFirstCipher (ea); + int size = CipherGetKeySize (i); + + while (i = EAGetNextCipher (ea, i)) + { + size += CipherGetKeySize (i); + } + + return size; +} + + +// Returns the first mode of operation of EA +int EAGetFirstMode (int ea) +{ + return (EncryptionAlgorithms[ea].Modes[0]); +} + + +int EAGetNextMode (int ea, int previousModeId) +{ + int c, i = 0; + while (c = EncryptionAlgorithms[ea].Modes[i++]) + { + if (c == previousModeId) + return EncryptionAlgorithms[ea].Modes[i]; + } + + return 0; +} + + +#ifndef TC_WINDOWS_BOOT + +// Returns the name of the mode of operation of the whole EA +char *EAGetModeName (int ea, int mode, BOOL capitalLetters) +{ + switch (mode) + { + case XTS: + + return "XTS"; + + case LRW: + + /* Deprecated/legacy */ + + return "LRW"; + + case CBC: + { + /* Deprecated/legacy */ + + char eaName[100]; + EAGetName (eaName, ea); + + if (strcmp (eaName, "Triple DES") == 0) + return capitalLetters ? "Outer-CBC" : "outer-CBC"; + + return "CBC"; + } + + case OUTER_CBC: + + /* Deprecated/legacy */ + + return capitalLetters ? "Outer-CBC" : "outer-CBC"; + + case INNER_CBC: + + /* Deprecated/legacy */ + + return capitalLetters ? "Inner-CBC" : "inner-CBC"; + + } + return "[unknown]"; +} + +#endif // TC_WINDOWS_BOOT + + +// Returns sum of key schedule sizes of all ciphers of the EA +int EAGetKeyScheduleSize (int ea) +{ + int i = EAGetFirstCipher(ea); + int size = CipherGetKeyScheduleSize (i); + + while (i = EAGetNextCipher(ea, i)) + { + size += CipherGetKeyScheduleSize (i); + } + + return size; +} + + +// Returns the largest key size needed by an EA for the specified mode of operation +int EAGetLargestKeyForMode (int mode) +{ + int ea, key = 0; + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (!EAIsModeSupported (ea, mode)) + continue; + + if (EAGetKeySize (ea) >= key) + key = EAGetKeySize (ea); + } + return key; +} + + +// Returns the largest key needed by any EA for any mode +int EAGetLargestKey () +{ + int ea, key = 0; + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (EAGetKeySize (ea) >= key) + key = EAGetKeySize (ea); + } + + return key; +} + + +// Returns number of ciphers in EA +int EAGetCipherCount (int ea) +{ + int i = 0; + while (EncryptionAlgorithms[ea].Ciphers[i++]); + + return i - 1; +} + + +int EAGetFirstCipher (int ea) +{ + return EncryptionAlgorithms[ea].Ciphers[0]; +} + + +int EAGetLastCipher (int ea) +{ + int c, i = 0; + while (c = EncryptionAlgorithms[ea].Ciphers[i++]); + + return EncryptionAlgorithms[ea].Ciphers[i - 2]; +} + + +int EAGetNextCipher (int ea, int previousCipherId) +{ + int c, i = 0; + while (c = EncryptionAlgorithms[ea].Ciphers[i++]) + { + if (c == previousCipherId) + return EncryptionAlgorithms[ea].Ciphers[i]; + } + + return 0; +} + + +int EAGetPreviousCipher (int ea, int previousCipherId) +{ + int c, i = 0; + + if (EncryptionAlgorithms[ea].Ciphers[i++] == previousCipherId) + return 0; + + while (c = EncryptionAlgorithms[ea].Ciphers[i++]) + { + if (c == previousCipherId) + return EncryptionAlgorithms[ea].Ciphers[i - 2]; + } + + return 0; +} + + +int EAIsFormatEnabled (int ea) +{ + return EncryptionAlgorithms[ea].FormatEnabled; +} + + +// Returns TRUE if the mode of operation is supported for the encryption algorithm +BOOL EAIsModeSupported (int ea, int testedMode) +{ + int mode; + + for (mode = EAGetFirstMode (ea); mode != 0; mode = EAGetNextMode (ea, mode)) + { + if (mode == testedMode) + return TRUE; + } + return FALSE; +} + + +Hash *HashGet (int id) +{ + int i; + for (i = 0; Hashes[i].Id != 0; i++) + if (Hashes[i].Id == id) + return &Hashes[i]; + + return 0; +} + + +int HashGetIdByName (char *name) +{ + int i; + for (i = 0; Hashes[i].Id != 0; i++) + if (strcmp (Hashes[i].Name, name) == 0) + return Hashes[i].Id; + + return 0; +} + + +char *HashGetName (int hashId) +{ + return HashGet (hashId) -> Name; +} + + +BOOL HashIsDeprecated (int hashId) +{ + return HashGet (hashId) -> Deprecated; +} + + +#endif // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + + +#ifdef TC_WINDOWS_BOOT + +static byte CryptoInfoBufferInUse = 0; +CRYPTO_INFO CryptoInfoBuffer; + +#endif + +PCRYPTO_INFO crypto_open () +{ +#ifndef TC_WINDOWS_BOOT + + /* Do the crt allocation */ + PCRYPTO_INFO cryptoInfo = (PCRYPTO_INFO) TCalloc (sizeof (CRYPTO_INFO)); + memset (cryptoInfo, 0, sizeof (CRYPTO_INFO)); + +#ifndef DEVICE_DRIVER + VirtualLock (cryptoInfo, sizeof (CRYPTO_INFO)); +#endif + + if (cryptoInfo == NULL) + return NULL; + + cryptoInfo->ea = -1; + return cryptoInfo; + +#else // TC_WINDOWS_BOOT + +#if 0 + if (CryptoInfoBufferInUse) + TC_THROW_FATAL_EXCEPTION; +#endif + CryptoInfoBufferInUse = 1; + return &CryptoInfoBuffer; + +#endif // TC_WINDOWS_BOOT +} + +void crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen) +{ + keyInfo->keyLength = nUserKeyLen; + burn (keyInfo->userKey, sizeof (keyInfo->userKey)); + memcpy (keyInfo->userKey, lpszUserKey, nUserKeyLen); +} + +void crypto_close (PCRYPTO_INFO cryptoInfo) +{ +#ifndef TC_WINDOWS_BOOT + + if (cryptoInfo != NULL) + { + burn (cryptoInfo, sizeof (CRYPTO_INFO)); +#ifndef DEVICE_DRIVER + VirtualUnlock (cryptoInfo, sizeof (CRYPTO_INFO)); +#endif + TCfree (cryptoInfo); + } + +#else // TC_WINDOWS_BOOT + + burn (&CryptoInfoBuffer, sizeof (CryptoInfoBuffer)); + CryptoInfoBufferInUse = FALSE; + +#endif // TC_WINDOWS_BOOT +} + + +#ifndef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + + +#ifndef TC_NO_COMPILER_INT64 +void Xor128 (unsigned __int64 *a, unsigned __int64 *b) +{ + *a++ ^= *b++; + *a ^= *b; +} + + +void Xor64 (unsigned __int64 *a, unsigned __int64 *b) +{ + *a ^= *b; +} + + +void EncryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[16]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 16) + TC_THROW_FATAL_EXCEPTION; + + // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). + + for (b = 0; b < length >> 4; b++) + { + Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + if (cipherCount > 1) + { + // Cipher cascade + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncipherBlock (cipher, p, ks); + ks += CipherGetKeyScheduleSize (cipher); + } + ks = cryptoInfo->ks; + } + else + { + EncipherBlock (cipher, p, ks); + } + + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 16; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +void EncryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[8]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 8) + TC_THROW_FATAL_EXCEPTION; + + for (b = 0; b < length >> 3; b++) + { + Gf64MulTab (i, t, &cryptoInfo->gf_ctx); + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + EncipherBlock (cipher, p, ks); + + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 8; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +void DecryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[16]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 16) + TC_THROW_FATAL_EXCEPTION; + + // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). + + for (b = 0; b < length >> 4; b++) + { + Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + if (cipherCount > 1) + { + // Cipher cascade + ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + DecipherBlock (cipher, p, ks); + } + } + else + { + DecipherBlock (cipher, p, ks); + } + + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 16; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + + +void DecryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[8]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 8) + TC_THROW_FATAL_EXCEPTION; + + for (b = 0; b < length >> 3; b++) + { + Gf64MulTab (i, t, &cryptoInfo->gf_ctx); + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + DecipherBlock (cipher, p, ks); + + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 8; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +// Initializes IV and whitening values for sector encryption/decryption in CBC mode. +// IMPORTANT: This function has been deprecated (legacy). +static void +InitSectorIVAndWhitening (unsigned __int64 unitNo, + int blockSize, + unsigned __int32 *iv, + unsigned __int64 *ivSeed, + unsigned __int32 *whitening) +{ + + /* IMPORTANT: This function has been deprecated (legacy) */ + + unsigned __int64 iv64[4]; + unsigned __int32 *iv32 = (unsigned __int32 *) iv64; + + iv64[0] = ivSeed[0] ^ LE64(unitNo); + iv64[1] = ivSeed[1] ^ LE64(unitNo); + iv64[2] = ivSeed[2] ^ LE64(unitNo); + if (blockSize == 16) + { + iv64[3] = ivSeed[3] ^ LE64(unitNo); + } + + iv[0] = iv32[0]; + iv[1] = iv32[1]; + + switch (blockSize) + { + case 16: + + // 128-bit block + + iv[2] = iv32[2]; + iv[3] = iv32[3]; + + whitening[0] = LE32( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) ); + whitening[1] = LE32( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) ); + break; + + case 8: + + // 64-bit block + + whitening[0] = LE32( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) ); + whitening[1] = LE32( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) ); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } +} + + +// EncryptBufferCBC (deprecated/legacy) +// +// data: data to be encrypted +// len: number of bytes to encrypt (must be divisible by the largest cipher block size) +// ks: scheduled key +// iv: IV +// whitening: whitening constants +// ea: outer-CBC cascade ID (0 = CBC/inner-CBC) +// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC) + +static void +EncryptBufferCBC (unsigned __int32 *data, + unsigned int len, + unsigned __int8 *ks, + unsigned __int32 *iv, + unsigned __int32 *whitening, + int ea, + int cipher) +{ + /* IMPORTANT: This function has been deprecated (legacy) */ + + unsigned __int32 bufIV[4]; + unsigned __int64 i; + int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); + + if (len % blockSize) + TC_THROW_FATAL_EXCEPTION; + + // IV + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + // Encrypt each block + for (i = 0; i < len/blockSize; i++) + { + // CBC + data[0] ^= bufIV[0]; + data[1] ^= bufIV[1]; + if (blockSize == 16) + { + data[2] ^= bufIV[2]; + data[3] ^= bufIV[3]; + } + + if (ea != 0) + { + // Outer-CBC + for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) + { + EncipherBlock (cipher, data, ks); + ks += CipherGetKeyScheduleSize (cipher); + } + ks -= EAGetKeyScheduleSize (ea); + } + else + { + // CBC/inner-CBC + EncipherBlock (cipher, data, ks); + } + + // CBC + bufIV[0] = data[0]; + bufIV[1] = data[1]; + if (blockSize == 16) + { + bufIV[2] = data[2]; + bufIV[3] = data[3]; + } + + // Whitening + data[0] ^= whitening[0]; + data[1] ^= whitening[1]; + if (blockSize == 16) + { + data[2] ^= whitening[0]; + data[3] ^= whitening[1]; + } + + data += blockSize / sizeof(*data); + } +} + + +// DecryptBufferCBC (deprecated/legacy) +// +// data: data to be decrypted +// len: number of bytes to decrypt (must be divisible by the largest cipher block size) +// ks: scheduled key +// iv: IV +// whitening: whitening constants +// ea: outer-CBC cascade ID (0 = CBC/inner-CBC) +// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC) + +static void +DecryptBufferCBC (unsigned __int32 *data, + unsigned int len, + unsigned __int8 *ks, + unsigned __int32 *iv, + unsigned __int32 *whitening, + int ea, + int cipher) +{ + + /* IMPORTANT: This function has been deprecated (legacy) */ + + unsigned __int32 bufIV[4]; + unsigned __int64 i; + unsigned __int32 ct[4]; + int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); + + if (len % blockSize) + TC_THROW_FATAL_EXCEPTION; + + // IV + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + // Decrypt each block + for (i = 0; i < len/blockSize; i++) + { + // Dewhitening + data[0] ^= whitening[0]; + data[1] ^= whitening[1]; + if (blockSize == 16) + { + data[2] ^= whitening[0]; + data[3] ^= whitening[1]; + } + + // CBC + ct[0] = data[0]; + ct[1] = data[1]; + if (blockSize == 16) + { + ct[2] = data[2]; + ct[3] = data[3]; + } + + if (ea != 0) + { + // Outer-CBC + ks += EAGetKeyScheduleSize (ea); + for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + DecipherBlock (cipher, data, ks); + } + } + else + { + // CBC/inner-CBC + DecipherBlock (cipher, data, ks); + } + + // CBC + data[0] ^= bufIV[0]; + data[1] ^= bufIV[1]; + bufIV[0] = ct[0]; + bufIV[1] = ct[1]; + if (blockSize == 16) + { + data[2] ^= bufIV[2]; + data[3] ^= bufIV[3]; + bufIV[2] = ct[2]; + bufIV[3] = ct[3]; + } + + data += blockSize / sizeof(*data); + } +} +#endif // #ifndef TC_NO_COMPILER_INT64 + + +// EncryptBuffer +// +// buf: data to be encrypted; the start of the buffer is assumed to be aligned with the start of a data unit. +// len: number of bytes to encrypt; must be divisible by the block size (for cascaded ciphers, divisible +// by the largest block size used within the cascade) +void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) +{ + switch (cryptoInfo->mode) + { + case XTS: + { + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 *ks2 = cryptoInfo->ks2; + UINT64_STRUCT dataUnitNo; + int cipher; + + // When encrypting/decrypting a buffer (typically a volume header) the sequential number + // of the first XTS data unit in the buffer is always 0 and the start of the buffer is + // always assumed to be aligned with the start of a data unit. + dataUnitNo.LowPart = 0; + dataUnitNo.HighPart = 0; + + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); + + ks += CipherGetKeyScheduleSize (cipher); + ks2 += CipherGetKeyScheduleSize (cipher); + } + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) + { + case 8: + EncryptBufferLRW64 ((unsigned __int8 *)buf, (unsigned __int64) len, 1, cryptoInfo); + break; + + case 16: + EncryptBufferLRW128 ((unsigned __int8 *)buf, (unsigned __int64) len, 1, cryptoInfo); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + + case CBC: + case INNER_CBC: + { + /* Deprecated/legacy */ + + unsigned __int8 *ks = cryptoInfo->ks; + int cipher; + + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncryptBufferCBC ((unsigned __int32 *) buf, + (unsigned int) len, + ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + 0, + cipher); + + ks += CipherGetKeyScheduleSize (cipher); + } + } + break; + + case OUTER_CBC: + + /* Deprecated/legacy */ + + EncryptBufferCBC ((unsigned __int32 *) buf, + (unsigned int) len, + cryptoInfo->ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + cryptoInfo->ea, + 0); + + break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } +} + +#ifndef TC_NO_COMPILER_INT64 +// Converts a data unit number to the index of the first LRW block in the data unit. +// Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). +uint64 DataUnit2LRWIndex (uint64 dataUnit, int blockSize, PCRYPTO_INFO ci) +{ + /* Deprecated/legacy */ + + if (ci->hiddenVolume) + dataUnit -= ci->hiddenVolumeOffset / ENCRYPTION_DATA_UNIT_SIZE; + else + dataUnit -= TC_VOLUME_HEADER_SIZE_LEGACY / ENCRYPTION_DATA_UNIT_SIZE; // Compensate for the volume header size + + switch (blockSize) + { + case 8: + return (dataUnit << 6) | 1; + + case 16: + return (dataUnit << 5) | 1; + + default: + TC_THROW_FATAL_EXCEPTION; + } + + return 0; +} +#endif // #ifndef TC_NO_COMPILER_INT64 + + +// buf: data to be encrypted +// unitNo: sequential number of the data unit with which the buffer starts +// nbrUnits: number of data units in the buffer +void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, uint32 nbrUnits, PCRYPTO_INFO ci) +#ifndef TC_WINDOWS_BOOT +{ + EncryptionThreadPoolDoWork (EncryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci); +} + +void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +#endif // !TC_WINDOWS_BOOT +{ + int ea = ci->ea; + unsigned __int8 *ks = ci->ks; + unsigned __int8 *ks2 = ci->ks2; + int cipher; + +#ifndef TC_NO_COMPILER_INT64 + void *iv = ci->k2; // Deprecated/legacy + unsigned __int64 unitNo = structUnitNo->Value; + unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy + unsigned __int32 sectorIV[4]; // Deprecated/legacy + unsigned __int32 secWhitening[2]; // Deprecated/legacy +#endif + + switch (ci->mode) + { + case XTS: + for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) + { + EncryptBufferXTS (buf, + nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + structUnitNo, + 0, + ks, + ks2, + cipher); + + ks += CipherGetKeyScheduleSize (cipher); + ks2 += CipherGetKeyScheduleSize (cipher); + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (ea))) + { + case 8: + EncryptBufferLRW64 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 8, ci), + ci); + break; + + case 16: + EncryptBufferLRW128 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 16, ci), + ci); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + + case CBC: + case INNER_CBC: + + /* Deprecated/legacy */ + + while (nbrUnits--) + { + for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) + { + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); + + EncryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, + ks, + sectorIV, + secWhitening, + 0, + cipher); + + ks += CipherGetKeyScheduleSize (cipher); + } + ks -= EAGetKeyScheduleSize (ea); + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; + } + break; + + case OUTER_CBC: + + /* Deprecated/legacy */ + + while (nbrUnits--) + { + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); + + EncryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, + ks, + sectorIV, + secWhitening, + ea, + 0); + + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; + } + break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } +} + +// DecryptBuffer +// +// buf: data to be decrypted; the start of the buffer is assumed to be aligned with the start of a data unit. +// len: number of bytes to decrypt; must be divisible by the block size (for cascaded ciphers, divisible +// by the largest block size used within the cascade) +void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) +{ + switch (cryptoInfo->mode) + { + case XTS: + { + unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + unsigned __int8 *ks2 = cryptoInfo->ks2 + EAGetKeyScheduleSize (cryptoInfo->ea); + UINT64_STRUCT dataUnitNo; + int cipher; + + // When encrypting/decrypting a buffer (typically a volume header) the sequential number + // of the first XTS data unit in the buffer is always 0 and the start of the buffer is + // always assumed to be aligned with the start of the data unit 0. + dataUnitNo.LowPart = 0; + dataUnitNo.HighPart = 0; + + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + ks2 -= CipherGetKeyScheduleSize (cipher); + + DecryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); + } + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) + { + case 8: + DecryptBufferLRW64 (buf, (unsigned __int64) len, 1, cryptoInfo); + break; + + case 16: + DecryptBufferLRW128 (buf, (unsigned __int64) len, 1, cryptoInfo); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + + case CBC: + case INNER_CBC: + { + /* Deprecated/legacy */ + + unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + int cipher; + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + + DecryptBufferCBC ((unsigned __int32 *) buf, + (unsigned int) len, + ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + 0, + cipher); + } + } + break; + + case OUTER_CBC: + + /* Deprecated/legacy */ + + DecryptBufferCBC ((unsigned __int32 *) buf, + (unsigned int) len, + cryptoInfo->ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + cryptoInfo->ea, + 0); + + break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } +} + +// buf: data to be decrypted +// unitNo: sequential number of the data unit with which the buffer starts +// nbrUnits: number of data units in the buffer +void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, uint32 nbrUnits, PCRYPTO_INFO ci) +#ifndef TC_WINDOWS_BOOT +{ + EncryptionThreadPoolDoWork (DecryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci); +} + +void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +#endif // !TC_WINDOWS_BOOT +{ + int ea = ci->ea; + unsigned __int8 *ks = ci->ks; + unsigned __int8 *ks2 = ci->ks2; + int cipher; + +#ifndef TC_NO_COMPILER_INT64 + void *iv = ci->k2; // Deprecated/legacy + unsigned __int64 unitNo = structUnitNo->Value; + unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy + unsigned __int32 sectorIV[4]; // Deprecated/legacy + unsigned __int32 secWhitening[2]; // Deprecated/legacy +#endif // #ifndef TC_NO_COMPILER_INT64 + + + switch (ci->mode) + { + case XTS: + ks += EAGetKeyScheduleSize (ea); + ks2 += EAGetKeyScheduleSize (ea); + + for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + ks2 -= CipherGetKeyScheduleSize (cipher); + + DecryptBufferXTS (buf, + nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + structUnitNo, + 0, + ks, + ks2, + cipher); + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (ea))) + { + case 8: + DecryptBufferLRW64 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 8, ci), + ci); + break; + + case 16: + DecryptBufferLRW128 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 16, ci), + ci); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + + case CBC: + case INNER_CBC: + + /* Deprecated/legacy */ + + while (nbrUnits--) + { + ks += EAGetKeyScheduleSize (ea); + for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) + { + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); + + ks -= CipherGetKeyScheduleSize (cipher); + + DecryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, + ks, + sectorIV, + secWhitening, + 0, + cipher); + } + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; + } + break; + + case OUTER_CBC: + + /* Deprecated/legacy */ + + while (nbrUnits--) + { + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); + + DecryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, + ks, + sectorIV, + secWhitening, + ea, + 0); + + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; + } + break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } +} + + +// Returns the maximum number of bytes necessary to be generated by the PBKDF2 (PKCS #5) +int GetMaxPkcs5OutSize (void) +{ + int size = 32; + + size = max (size, EAGetLargestKeyForMode (XTS) * 2); // Sizes of primary + secondary keys + +#ifndef TC_WINDOWS_BOOT + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (LRW)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (CBC)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (OUTER_CBC)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (INNER_CBC)); // Deprecated/legacy +#endif + + return size; +} + + +#else // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + + +#if !defined (TC_WINDOWS_BOOT_AES) && !defined (TC_WINDOWS_BOOT_SERPENT) && !defined (TC_WINDOWS_BOOT_TWOFISH) +#error No cipher defined +#endif + +void EncipherBlock(int cipher, void *data, void *ks) +{ +#ifdef TC_WINDOWS_BOOT_AES + aes_encrypt (data, data, ks); +#elif defined (TC_WINDOWS_BOOT_SERPENT) + serpent_encrypt (data, data, ks); +#elif defined (TC_WINDOWS_BOOT_TWOFISH) + twofish_encrypt (ks, data, data); +#endif +} + +void DecipherBlock(int cipher, void *data, void *ks) +{ +#ifdef TC_WINDOWS_BOOT_AES + aes_decrypt (data, data, (aes_decrypt_ctx *) ((byte *) ks + sizeof(aes_encrypt_ctx))); +#elif defined (TC_WINDOWS_BOOT_SERPENT) + serpent_decrypt (data, data, ks); +#elif defined (TC_WINDOWS_BOOT_TWOFISH) + twofish_decrypt (ks, data, data); +#endif +} + +int EAGetFirst () +{ + return 1; +} + +int EAGetNext (int previousEA) +{ + return 0; +} + +int EAInit (int ea, unsigned char *key, unsigned __int8 *ks) +{ +#ifdef TC_WINDOWS_BOOT_AES + + aes_init(); + + if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ks + sizeof (aes_encrypt_ctx))) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + +#elif defined (TC_WINDOWS_BOOT_SERPENT) + serpent_set_key (key, 32 * 8, ks); +#elif defined (TC_WINDOWS_BOOT_TWOFISH) + twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, 32 * 8); +#endif + return ERR_SUCCESS; +} + +int EAGetKeySize (int ea) +{ + return 32; +} + +int EAGetFirstCipher (int ea) +{ + return 1; +} + +void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) +{ + UINT64_STRUCT dataUnitNo; + dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; + EncryptBufferXTS (buf, len, &dataUnitNo, 0, cryptoInfo->ks, cryptoInfo->ks2, 1); +} + +void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +{ + EncryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ci->ks, ci->ks2, 1); +} + +void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) +{ + UINT64_STRUCT dataUnitNo; + dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; + DecryptBufferXTS (buf, len, &dataUnitNo, 0, cryptoInfo->ks, cryptoInfo->ks2, 1); +} + +void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +{ + DecryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ci->ks, ci->ks2, 1); +} + +#endif // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE diff --git a/Common/CRYPTO.H b/Common/CRYPTO.H index c553da6..9e4db21 100644 --- a/Common/CRYPTO.H +++ b/Common/CRYPTO.H @@ -1,320 +1,320 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -/* Update the following when adding a new cipher or EA: - - Crypto.h: - ID #define - MAX_EXPANDED_KEY #define - - Crypto.c: - Ciphers[] - EncryptionAlgorithms[] - CipherInit() - EncipherBlock() - DecipherBlock() - -*/ - -#ifndef CRYPTO_H -#define CRYPTO_H - -#include "Tcdefs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Encryption data unit size, which may differ from the sector size and must always be 512 -#define ENCRYPTION_DATA_UNIT_SIZE 512 - -// Size of the salt (in bytes) -#define PKCS5_SALT_SIZE 64 - -// Size of the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode) -#define MASTER_KEYDATA_SIZE 256 - -// Size of the deprecated volume header item containing either an IV seed (CBC mode) or tweak key (LRW mode) -#define LEGACY_VOL_IV_SIZE 32 - -// The first PRF to try when mounting -#define FIRST_PRF_ID 1 - -// Hash algorithms (pseudorandom functions). -enum -{ - RIPEMD160 = FIRST_PRF_ID, -#ifndef TC_WINDOWS_BOOT - SHA512, - WHIRLPOOL, - SHA1, // Deprecated/legacy -#endif - HASH_ENUM_END_ID -}; - -// The last PRF to try when mounting and also the number of implemented PRFs -#define LAST_PRF_ID (HASH_ENUM_END_ID - 1) - -#define RIPEMD160_BLOCKSIZE 64 -#define RIPEMD160_DIGESTSIZE 20 - -#define SHA1_BLOCKSIZE 64 -#define SHA1_DIGESTSIZE 20 - -#define SHA512_BLOCKSIZE 128 -#define SHA512_DIGESTSIZE 64 - -#define WHIRLPOOL_BLOCKSIZE 64 -#define WHIRLPOOL_DIGESTSIZE 64 - -#define MAX_DIGESTSIZE WHIRLPOOL_DIGESTSIZE - -#define DEFAULT_HASH_ALGORITHM FIRST_PRF_ID -#define DEFAULT_HASH_ALGORITHM_BOOT RIPEMD160 - -// The mode of operation used for newly created volumes and first to try when mounting -#define FIRST_MODE_OF_OPERATION_ID 1 - -// Modes of operation -enum -{ - /* If you add/remove a mode, update the following: GetMaxPkcs5OutSize(), EAInitMode() */ - - XTS = FIRST_MODE_OF_OPERATION_ID, -#ifndef TC_WINDOWS_BOOT - LRW, // Deprecated/legacy - CBC, // Deprecated/legacy - OUTER_CBC, // Deprecated/legacy - INNER_CBC, // Deprecated/legacy -#endif - MODE_ENUM_END_ID -}; - - -// The last mode of operation to try when mounting and also the number of implemented modes -#define LAST_MODE_OF_OPERATION (MODE_ENUM_END_ID - 1) - -// Ciphertext/plaintext block size for XTS mode (in bytes) -#define BYTES_PER_XTS_BLOCK 16 - -// Number of ciphertext/plaintext blocks per XTS data unit -#define BLOCKS_PER_XTS_DATA_UNIT (ENCRYPTION_DATA_UNIT_SIZE / BYTES_PER_XTS_BLOCK) - - -// Cipher IDs -enum -{ - NONE = 0, - AES, - SERPENT, - TWOFISH, -#ifndef TC_WINDOWS_BOOT - BLOWFISH, // Deprecated/legacy - CAST, // Deprecated/legacy - TRIPLEDES // Deprecated/legacy -#endif -}; - -typedef struct -{ - int Id; // Cipher ID - char *Name; // Name - int BlockSize; // Block size (bytes) - int KeySize; // Key size (bytes) - int KeyScheduleSize; // Scheduled key size (bytes) -} Cipher; - -typedef struct -{ - int Ciphers[4]; // Null terminated array of ciphers used by encryption algorithm - int Modes[LAST_MODE_OF_OPERATION + 1]; // Null terminated array of modes of operation - int FormatEnabled; -} EncryptionAlgorithm; - -typedef struct -{ - int Id; // Hash ID - char *Name; // Name - BOOL Deprecated; - BOOL SystemEncryption; // Available for system encryption -} Hash; - -// Maxium length of scheduled key -#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_AES) -# define AES_KS (sizeof(aes_encrypt_ctx) + sizeof(aes_decrypt_ctx)) -#else -# define AES_KS (sizeof(aes_context)) -#endif -#define SERPENT_KS (140 * 4) - -#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE - -# ifdef TC_WINDOWS_BOOT_AES -# define MAX_EXPANDED_KEY AES_KS -# elif defined (TC_WINDOWS_BOOT_SERPENT) -# define MAX_EXPANDED_KEY SERPENT_KS -# elif defined (TC_WINDOWS_BOOT_TWOFISH) -# define MAX_EXPANDED_KEY TWOFISH_KS -# endif - -#else - -#define MAX_EXPANDED_KEY (AES_KS + SERPENT_KS + TWOFISH_KS) - -#endif - -#ifdef DEBUG -# define PRAND_DISK_WIPE_PASSES 3 -#else -# define PRAND_DISK_WIPE_PASSES 256 -#endif - -#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_AES) -# include "Aes.h" -#else -# include "AesSmall.h" -#endif - -#include "Blowfish.h" -#include "Cast.h" -#include "Des.h" -#include "Serpent.h" -#include "Twofish.h" - -#include "Rmd160.h" -#ifndef TC_WINDOWS_BOOT -# include "Sha1.h" -# include "Sha2.h" -# include "Whirlpool.h" -#endif - -#include "GfMul.h" -#include "Password.h" - -typedef struct keyInfo_t -{ - int noIterations; /* Number of times to iterate (PKCS-5) */ - int keyLength; /* Length of the key */ - __int8 userKey[MAX_PASSWORD]; /* Password (to which keyfiles may have been applied). WITHOUT +1 for the null terminator. */ - __int8 salt[PKCS5_SALT_SIZE]; /* PKCS-5 salt */ - __int8 master_keydata[MASTER_KEYDATA_SIZE]; /* Concatenated master primary and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */ -} KEY_INFO, *PKEY_INFO; - -typedef struct CRYPTO_INFO_t -{ - int ea; /* Encryption algorithm ID */ - int mode; /* Mode of operation (e.g., XTS) */ - unsigned __int8 ks[MAX_EXPANDED_KEY]; /* Primary key schedule (if it is a cascade, it conatins multiple concatenated keys) */ - unsigned __int8 ks2[MAX_EXPANDED_KEY]; /* Secondary key schedule (if cascade, multiple concatenated) for XTS mode. */ - - BOOL hiddenVolume; // Indicates whether the volume is mounted/mountable as hidden volume - -#ifndef TC_WINDOWS_BOOT - uint16 HeaderVersion; - - GfCtx gf_ctx; - - unsigned __int8 master_keydata[MASTER_KEYDATA_SIZE]; /* This holds the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */ - unsigned __int8 k2[MASTER_KEYDATA_SIZE]; /* For XTS, this contains the secondary key (if cascade, multiple concatenated). For LRW (deprecated/legacy), it contains the tweak key. For CBC (deprecated/legacy), it contains the IV seed. */ - unsigned __int8 salt[PKCS5_SALT_SIZE]; - int noIterations; - int pkcs5; - - uint64 volume_creation_time; // Legacy - uint64 header_creation_time; // Legacy - - BOOL bProtectHiddenVolume; // Indicates whether the volume contains a hidden volume to be protected against overwriting - BOOL bHiddenVolProtectionAction; // TRUE if a write operation has been denied by the driver in order to prevent the hidden volume from being overwritten (set to FALSE upon volume mount). - - uint64 volDataAreaOffset; // Absolute position, in bytes, of the first data sector of the volume. - - uint64 hiddenVolumeSize; // Size of the hidden volume excluding the header (in bytes). Set to 0 for standard volumes. - uint64 hiddenVolumeOffset; // Absolute position, in bytes, of the first hidden volume data sector within the host volume (provided that there is a hidden volume within). This must be set for all hidden volumes; in case of a normal volume, this variable is only used when protecting a hidden volume within it. - uint64 hiddenVolumeProtectedSize; - - BOOL bPartitionInInactiveSysEncScope; // If TRUE, the volume is a partition located on an encrypted system drive and mounted without pre-boot authentication. - - UINT64_STRUCT FirstDataUnitNo; // First data unit number of the volume. This is 0 for file-hosted and non-system partition-hosted volumes. For partitions within key scope of system encryption this reflects real physical offset within the device (this is used e.g. when such a partition is mounted as a regular volume without pre-boot authentication). - - uint16 RequiredProgramVersion; - BOOL LegacyVolume; - -#endif // TC_WINDOWS_BOOT - - UINT64_STRUCT VolumeSize; - - UINT64_STRUCT EncryptedAreaStart; - UINT64_STRUCT EncryptedAreaLength; - - uint32 HeaderFlags; - -} CRYPTO_INFO, *PCRYPTO_INFO; - -PCRYPTO_INFO crypto_open (void); -void crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen); -void crypto_close (PCRYPTO_INFO cryptoInfo); - -int CipherGetBlockSize (int cipher); -int CipherGetKeySize (int cipher); -int CipherGetKeyScheduleSize (int cipher); -char * CipherGetName (int cipher); - -int CipherInit (int cipher, unsigned char *key, unsigned char *ks); -int EAInit (int ea, unsigned char *key, unsigned char *ks); -BOOL EAInitMode (PCRYPTO_INFO ci); -void EncipherBlock(int cipher, void *data, void *ks); -void DecipherBlock(int cipher, void *data, void *ks); - -int EAGetFirst (); -int EAGetCount (void); -int EAGetNext (int previousEA); -char * EAGetName (char *buf, int ea); -int EAGetByName (char *name); -int EAGetKeySize (int ea); -int EAGetFirstMode (int ea); -int EAGetNextMode (int ea, int previousModeId); -char * EAGetModeName (int ea, int mode, BOOL capitalLetters); -int EAGetKeyScheduleSize (int ea); -int EAGetLargestKey (); -int EAGetLargestKeyForMode (int mode); - -int EAGetCipherCount (int ea); -int EAGetFirstCipher (int ea); -int EAGetLastCipher (int ea); -int EAGetNextCipher (int ea, int previousCipherId); -int EAGetPreviousCipher (int ea, int previousCipherId); -int EAIsFormatEnabled (int ea); -BOOL EAIsModeSupported (int ea, int testedMode); - -char *HashGetName (int hash_algo_id); -BOOL HashIsDeprecated (int hashId); - -int GetMaxPkcs5OutSize (void); - -void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); -void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); -void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); -void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); -void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo); -void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo); -#ifndef TC_NO_COMPILER_INT64 -void EncryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); -void DecryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); -void EncryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); -void DecryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); -uint64 DataUnit2LRWIndex (uint64 dataUnit, int blockSize, PCRYPTO_INFO ci); -#endif // #ifndef TC_NO_COMPILER_INT64 - -#ifdef __cplusplus -} -#endif - -#endif /* CRYPTO_H */ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +/* Update the following when adding a new cipher or EA: + + Crypto.h: + ID #define + MAX_EXPANDED_KEY #define + + Crypto.c: + Ciphers[] + EncryptionAlgorithms[] + CipherInit() + EncipherBlock() + DecipherBlock() + +*/ + +#ifndef CRYPTO_H +#define CRYPTO_H + +#include "Tcdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Encryption data unit size, which may differ from the sector size and must always be 512 +#define ENCRYPTION_DATA_UNIT_SIZE 512 + +// Size of the salt (in bytes) +#define PKCS5_SALT_SIZE 64 + +// Size of the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode) +#define MASTER_KEYDATA_SIZE 256 + +// Size of the deprecated volume header item containing either an IV seed (CBC mode) or tweak key (LRW mode) +#define LEGACY_VOL_IV_SIZE 32 + +// The first PRF to try when mounting +#define FIRST_PRF_ID 1 + +// Hash algorithms (pseudorandom functions). +enum +{ + RIPEMD160 = FIRST_PRF_ID, +#ifndef TC_WINDOWS_BOOT + SHA512, + WHIRLPOOL, + SHA1, // Deprecated/legacy +#endif + HASH_ENUM_END_ID +}; + +// The last PRF to try when mounting and also the number of implemented PRFs +#define LAST_PRF_ID (HASH_ENUM_END_ID - 1) + +#define RIPEMD160_BLOCKSIZE 64 +#define RIPEMD160_DIGESTSIZE 20 + +#define SHA1_BLOCKSIZE 64 +#define SHA1_DIGESTSIZE 20 + +#define SHA512_BLOCKSIZE 128 +#define SHA512_DIGESTSIZE 64 + +#define WHIRLPOOL_BLOCKSIZE 64 +#define WHIRLPOOL_DIGESTSIZE 64 + +#define MAX_DIGESTSIZE WHIRLPOOL_DIGESTSIZE + +#define DEFAULT_HASH_ALGORITHM FIRST_PRF_ID +#define DEFAULT_HASH_ALGORITHM_BOOT RIPEMD160 + +// The mode of operation used for newly created volumes and first to try when mounting +#define FIRST_MODE_OF_OPERATION_ID 1 + +// Modes of operation +enum +{ + /* If you add/remove a mode, update the following: GetMaxPkcs5OutSize(), EAInitMode() */ + + XTS = FIRST_MODE_OF_OPERATION_ID, +#ifndef TC_WINDOWS_BOOT + LRW, // Deprecated/legacy + CBC, // Deprecated/legacy + OUTER_CBC, // Deprecated/legacy + INNER_CBC, // Deprecated/legacy +#endif + MODE_ENUM_END_ID +}; + + +// The last mode of operation to try when mounting and also the number of implemented modes +#define LAST_MODE_OF_OPERATION (MODE_ENUM_END_ID - 1) + +// Ciphertext/plaintext block size for XTS mode (in bytes) +#define BYTES_PER_XTS_BLOCK 16 + +// Number of ciphertext/plaintext blocks per XTS data unit +#define BLOCKS_PER_XTS_DATA_UNIT (ENCRYPTION_DATA_UNIT_SIZE / BYTES_PER_XTS_BLOCK) + + +// Cipher IDs +enum +{ + NONE = 0, + AES, + SERPENT, + TWOFISH, +#ifndef TC_WINDOWS_BOOT + BLOWFISH, // Deprecated/legacy + CAST, // Deprecated/legacy + TRIPLEDES // Deprecated/legacy +#endif +}; + +typedef struct +{ + int Id; // Cipher ID + char *Name; // Name + int BlockSize; // Block size (bytes) + int KeySize; // Key size (bytes) + int KeyScheduleSize; // Scheduled key size (bytes) +} Cipher; + +typedef struct +{ + int Ciphers[4]; // Null terminated array of ciphers used by encryption algorithm + int Modes[LAST_MODE_OF_OPERATION + 1]; // Null terminated array of modes of operation + int FormatEnabled; +} EncryptionAlgorithm; + +typedef struct +{ + int Id; // Hash ID + char *Name; // Name + BOOL Deprecated; + BOOL SystemEncryption; // Available for system encryption +} Hash; + +// Maxium length of scheduled key +#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_AES) +# define AES_KS (sizeof(aes_encrypt_ctx) + sizeof(aes_decrypt_ctx)) +#else +# define AES_KS (sizeof(aes_context)) +#endif +#define SERPENT_KS (140 * 4) + +#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + +# ifdef TC_WINDOWS_BOOT_AES +# define MAX_EXPANDED_KEY AES_KS +# elif defined (TC_WINDOWS_BOOT_SERPENT) +# define MAX_EXPANDED_KEY SERPENT_KS +# elif defined (TC_WINDOWS_BOOT_TWOFISH) +# define MAX_EXPANDED_KEY TWOFISH_KS +# endif + +#else + +#define MAX_EXPANDED_KEY (AES_KS + SERPENT_KS + TWOFISH_KS) + +#endif + +#ifdef DEBUG +# define PRAND_DISK_WIPE_PASSES 3 +#else +# define PRAND_DISK_WIPE_PASSES 256 +#endif + +#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_AES) +# include "Aes.h" +#else +# include "AesSmall.h" +#endif + +#include "Blowfish.h" +#include "Cast.h" +#include "Des.h" +#include "Serpent.h" +#include "Twofish.h" + +#include "Rmd160.h" +#ifndef TC_WINDOWS_BOOT +# include "Sha1.h" +# include "Sha2.h" +# include "Whirlpool.h" +#endif + +#include "GfMul.h" +#include "Password.h" + +typedef struct keyInfo_t +{ + int noIterations; /* Number of times to iterate (PKCS-5) */ + int keyLength; /* Length of the key */ + __int8 userKey[MAX_PASSWORD]; /* Password (to which keyfiles may have been applied). WITHOUT +1 for the null terminator. */ + __int8 salt[PKCS5_SALT_SIZE]; /* PKCS-5 salt */ + __int8 master_keydata[MASTER_KEYDATA_SIZE]; /* Concatenated master primary and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */ +} KEY_INFO, *PKEY_INFO; + +typedef struct CRYPTO_INFO_t +{ + int ea; /* Encryption algorithm ID */ + int mode; /* Mode of operation (e.g., XTS) */ + unsigned __int8 ks[MAX_EXPANDED_KEY]; /* Primary key schedule (if it is a cascade, it conatins multiple concatenated keys) */ + unsigned __int8 ks2[MAX_EXPANDED_KEY]; /* Secondary key schedule (if cascade, multiple concatenated) for XTS mode. */ + + BOOL hiddenVolume; // Indicates whether the volume is mounted/mountable as hidden volume + +#ifndef TC_WINDOWS_BOOT + uint16 HeaderVersion; + + GfCtx gf_ctx; + + unsigned __int8 master_keydata[MASTER_KEYDATA_SIZE]; /* This holds the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */ + unsigned __int8 k2[MASTER_KEYDATA_SIZE]; /* For XTS, this contains the secondary key (if cascade, multiple concatenated). For LRW (deprecated/legacy), it contains the tweak key. For CBC (deprecated/legacy), it contains the IV seed. */ + unsigned __int8 salt[PKCS5_SALT_SIZE]; + int noIterations; + int pkcs5; + + uint64 volume_creation_time; // Legacy + uint64 header_creation_time; // Legacy + + BOOL bProtectHiddenVolume; // Indicates whether the volume contains a hidden volume to be protected against overwriting + BOOL bHiddenVolProtectionAction; // TRUE if a write operation has been denied by the driver in order to prevent the hidden volume from being overwritten (set to FALSE upon volume mount). + + uint64 volDataAreaOffset; // Absolute position, in bytes, of the first data sector of the volume. + + uint64 hiddenVolumeSize; // Size of the hidden volume excluding the header (in bytes). Set to 0 for standard volumes. + uint64 hiddenVolumeOffset; // Absolute position, in bytes, of the first hidden volume data sector within the host volume (provided that there is a hidden volume within). This must be set for all hidden volumes; in case of a normal volume, this variable is only used when protecting a hidden volume within it. + uint64 hiddenVolumeProtectedSize; + + BOOL bPartitionInInactiveSysEncScope; // If TRUE, the volume is a partition located on an encrypted system drive and mounted without pre-boot authentication. + + UINT64_STRUCT FirstDataUnitNo; // First data unit number of the volume. This is 0 for file-hosted and non-system partition-hosted volumes. For partitions within key scope of system encryption this reflects real physical offset within the device (this is used e.g. when such a partition is mounted as a regular volume without pre-boot authentication). + + uint16 RequiredProgramVersion; + BOOL LegacyVolume; + +#endif // TC_WINDOWS_BOOT + + UINT64_STRUCT VolumeSize; + + UINT64_STRUCT EncryptedAreaStart; + UINT64_STRUCT EncryptedAreaLength; + + uint32 HeaderFlags; + +} CRYPTO_INFO, *PCRYPTO_INFO; + +PCRYPTO_INFO crypto_open (void); +void crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen); +void crypto_close (PCRYPTO_INFO cryptoInfo); + +int CipherGetBlockSize (int cipher); +int CipherGetKeySize (int cipher); +int CipherGetKeyScheduleSize (int cipher); +char * CipherGetName (int cipher); + +int CipherInit (int cipher, unsigned char *key, unsigned char *ks); +int EAInit (int ea, unsigned char *key, unsigned char *ks); +BOOL EAInitMode (PCRYPTO_INFO ci); +void EncipherBlock(int cipher, void *data, void *ks); +void DecipherBlock(int cipher, void *data, void *ks); + +int EAGetFirst (); +int EAGetCount (void); +int EAGetNext (int previousEA); +char * EAGetName (char *buf, int ea); +int EAGetByName (char *name); +int EAGetKeySize (int ea); +int EAGetFirstMode (int ea); +int EAGetNextMode (int ea, int previousModeId); +char * EAGetModeName (int ea, int mode, BOOL capitalLetters); +int EAGetKeyScheduleSize (int ea); +int EAGetLargestKey (); +int EAGetLargestKeyForMode (int mode); + +int EAGetCipherCount (int ea); +int EAGetFirstCipher (int ea); +int EAGetLastCipher (int ea); +int EAGetNextCipher (int ea, int previousCipherId); +int EAGetPreviousCipher (int ea, int previousCipherId); +int EAIsFormatEnabled (int ea); +BOOL EAIsModeSupported (int ea, int testedMode); + +char *HashGetName (int hash_algo_id); +BOOL HashIsDeprecated (int hashId); + +int GetMaxPkcs5OutSize (void); + +void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, uint32 nbrUnits, PCRYPTO_INFO ci); +void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); +void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, uint32 nbrUnits, PCRYPTO_INFO ci); +void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); +void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo); +void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo); +#ifndef TC_NO_COMPILER_INT64 +void EncryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); +void DecryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); +void EncryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); +void DecryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo); +uint64 DataUnit2LRWIndex (uint64 dataUnit, int blockSize, PCRYPTO_INFO ci); +#endif // #ifndef TC_NO_COMPILER_INT64 + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTO_H */ diff --git a/Common/Common.h b/Common/Common.h index 95c6138..291e624 100644 --- a/Common/Common.h +++ b/Common/Common.h @@ -1,54 +1,75 @@ -/* - Copyright (c) 2005-2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef COMMON_H -#define COMMON_H - -#include "Crypto.h" - -/* Volume types */ -enum -{ - TC_VOLUME_TYPE_NORMAL = 0, - TC_VOLUME_TYPE_HIDDEN, - TC_VOLUME_TYPE_HIDDEN_LEGACY, - TC_VOLUME_TYPE_COUNT -}; - -/* Prop volume types */ -enum -{ - PROP_VOL_TYPE_NORMAL = 0, - PROP_VOL_TYPE_HIDDEN, - PROP_VOL_TYPE_OUTER, /* Outer/normal (hidden volume protected) */ - PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, /* Outer/normal (hidden volume protected AND write already prevented) */ - PROP_VOL_TYPE_SYSTEM, - PROP_NBR_VOLUME_TYPES -}; - -/* Hidden volume protection status */ -enum -{ - HIDVOL_PROT_STATUS_NONE = 0, - HIDVOL_PROT_STATUS_ACTIVE, - HIDVOL_PROT_STATUS_ACTION_TAKEN /* Active + action taken (write operation has already been denied) */ -}; - -typedef struct -{ - BOOL ReadOnly; - BOOL Removable; - BOOL ProtectHiddenVolume; - BOOL PreserveTimestamp; - BOOL PartitionInInactiveSysEncScope; /* If TRUE, we are to attempt to mount a partition located on an encrypted system drive without pre-boot authentication. */ - Password ProtectedHidVolPassword; /* Password of hidden volume to protect against overwriting */ - BOOL UseBackupHeader; - BOOL RecoveryMode; -} MountOptions; - -#endif +/* + Copyright (c) 2005-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef COMMON_H +#define COMMON_H + +#include "Crypto.h" + +typedef enum +{ + // IMPORTANT: If you add a new item here, update IsOSVersionAtLeast(). + + WIN_UNKNOWN = 0, + WIN_31, + WIN_95, + WIN_98, + WIN_ME, + WIN_NT3, + WIN_NT4, + WIN_2000, + WIN_XP, + WIN_XP64, + WIN_SERVER_2003, + WIN_VISTA, + WIN_SERVER_2008, + WIN_7, + WIN_SERVER_2008_R2, +} OSVersionEnum; + +/* Volume types */ +enum +{ + TC_VOLUME_TYPE_NORMAL = 0, + TC_VOLUME_TYPE_HIDDEN, + TC_VOLUME_TYPE_HIDDEN_LEGACY, + TC_VOLUME_TYPE_COUNT +}; + +/* Prop volume types */ +enum +{ + PROP_VOL_TYPE_NORMAL = 0, + PROP_VOL_TYPE_HIDDEN, + PROP_VOL_TYPE_OUTER, /* Outer/normal (hidden volume protected) */ + PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, /* Outer/normal (hidden volume protected AND write already prevented) */ + PROP_VOL_TYPE_SYSTEM, + PROP_NBR_VOLUME_TYPES +}; + +/* Hidden volume protection status */ +enum +{ + HIDVOL_PROT_STATUS_NONE = 0, + HIDVOL_PROT_STATUS_ACTIVE, + HIDVOL_PROT_STATUS_ACTION_TAKEN /* Active + action taken (write operation has already been denied) */ +}; + +typedef struct +{ + BOOL ReadOnly; + BOOL Removable; + BOOL ProtectHiddenVolume; + BOOL PreserveTimestamp; + BOOL PartitionInInactiveSysEncScope; /* If TRUE, we are to attempt to mount a partition located on an encrypted system drive without pre-boot authentication. */ + Password ProtectedHidVolPassword; /* Password of hidden volume to protect against overwriting */ + BOOL UseBackupHeader; + BOOL RecoveryMode; +} MountOptions; + +#endif diff --git a/Common/Common.rc b/Common/Common.rc index 1966262..5d3007e 100644 --- a/Common/Common.rc +++ b/Common/Common.rc @@ -35,7 +35,7 @@ BEGIN EDITTEXT IDC_ABOUT_CREDITS,7,111,277,45,ES_MULTILINE | WS_VSCROLL | NOT WS_TABSTOP DEFPUSHBUTTON "OK",IDOK,233,178,50,14 LTEXT "",IDC_HOMEPAGE,18,87,117,9,SS_NOTIFY - LTEXT "Copyright © 2003-2009 TrueCrypt Foundation",IDC_STATIC,18,71,207,8 + LTEXT "",IDT_ABOUT_RELEASE,18,71,235,8 CONTROL 517,IDC_ABOUT_BKG,"Static",SS_BITMAP,0,0,12,11,WS_EX_STATICEDGE LTEXT "",IDT_ABOUT_VERSION,18,61,161,8 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,1,167,291,1,WS_EX_STATICEDGE diff --git a/Common/DLGCODE.C b/Common/DLGCODE.C index 7a8ebc0..600cc53 100644 --- a/Common/DLGCODE.C +++ b/Common/DLGCODE.C @@ -1,8995 +1,9319 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Resource.h" - -#include "Platform/Finally.h" -#include "Platform/ForEach.h" -#include "Apidrvr.h" -#include "BootEncryption.h" -#include "Combo.h" -#include "Crc.h" -#include "Crypto.h" -#include "Dictionary.h" -#include "Dlgcode.h" -#include "EncryptionThreadPool.h" -#include "Endian.h" -#include "Format/Inplace.h" -#include "Language.h" -#include "Keyfiles.h" -#include "Mount/Mount.h" -#include "Pkcs5.h" -#include "Random.h" -#include "Registry.h" -#include "SecurityToken.h" -#include "Tests.h" -#include "Volumes.h" -#include "Wipe.h" -#include "Xml.h" -#include "Xts.h" -#include "Boot/Windows/BootCommon.h" - -using namespace TrueCrypt; - -#ifdef VOLFORMAT -#include "Format/Tcformat.h" -#endif - -#ifdef SETUP -#include "Setup/Setup.h" -#endif - -LONG DriverVersion; - -char *LastDialogId; -char szHelpFile[TC_MAX_PATH]; -char szHelpFile2[TC_MAX_PATH]; -char SecurityTokenLibraryPath[TC_MAX_PATH]; - -HFONT hFixedDigitFont = NULL; -HFONT hBoldFont = NULL; -HFONT hTitleFont = NULL; -HFONT hFixedFont = NULL; - -HFONT hUserFont = NULL; -HFONT hUserUnderlineFont = NULL; -HFONT hUserBoldFont = NULL; -HFONT hUserUnderlineBoldFont = NULL; - -int ScreenDPI = USER_DEFAULT_SCREEN_DPI; -double DPIScaleFactorX = 1; -double DPIScaleFactorY = 1; -double DlgAspectRatio = 1; - -HWND MainDlg = NULL; -wchar_t *lpszTitle = NULL; - -BOOL Silent = FALSE; -BOOL bPreserveTimestamp = TRUE; -BOOL bStartOnLogon = FALSE; -BOOL bMountDevicesOnLogon = FALSE; -BOOL bMountFavoritesOnLogon = FALSE; - -BOOL bHistory = FALSE; - -// Status of detection of hidden sectors (whole-system-drive encryption). -// 0 - Unknown/undetermined/success, 1: Detection is or was in progress (but did not complete e.g. due to system crash). -int HiddenSectorDetectionStatus = 0; - -OSVersionEnum nCurrentOS = WIN_UNKNOWN; -int CurrentOSMajor = 0; -int CurrentOSMinor = 0; -int CurrentOSServicePack = 0; -BOOL RemoteSession = FALSE; -BOOL UacElevated = FALSE; - -BOOL bTravelerModeConfirmed = FALSE; // TRUE if it is certain that the instance is running in traveler mode - -BOOL bInPlaceEncNonSysPending = FALSE; // TRUE if the non-system in-place encryption config file indicates that one or more partitions are scheduled to be encrypted. This flag is set only when config files are loaded during app startup. - -/* Globals used by Mount and Format (separately per instance) */ -BOOL KeyFilesEnable = FALSE; -KeyFile *FirstKeyFile = NULL; -KeyFilesDlgParam defaultKeyFilesParam; - -BOOL IgnoreWmDeviceChange = FALSE; - -/* Handle to the device driver */ -HANDLE hDriver = INVALID_HANDLE_VALUE; - -/* This mutex is used to prevent multiple instances of the wizard or main app from dealing with system encryption */ -volatile HANDLE hSysEncMutex = NULL; - -/* This mutex is used for non-system in-place encryption but only for informative (non-blocking) purposes, -such as whether an app should prompt the user whether to resume scheduled process. */ -volatile HANDLE hNonSysInplaceEncMutex = NULL; - -/* This mutex is used to prevent multiple instances of the wizard or main app from trying to install or -register the driver or from trying to launch it in traveler mode at the same time. */ -volatile HANDLE hDriverSetupMutex = NULL; - -/* This mutex is used to prevent users from running the main TrueCrypt app or the wizard while an instance -of the TrueCrypt installer is running (which is also useful for enforcing restart before the apps can be used). */ -volatile HANDLE hAppSetupMutex = NULL; - -HINSTANCE hInst = NULL; -HCURSOR hCursor = NULL; - -ATOM hDlgClass, hSplashClass; - -/* This value may changed only by calling ChangeSystemEncryptionStatus(). Only the wizard can change it -(others may still read it though). */ -int SystemEncryptionStatus = SYSENC_STATUS_NONE; - -/* Only the wizard can change this value (others may only read it). */ -WipeAlgorithmId nWipeMode = TC_WIPE_NONE; - -BOOL bSysPartitionSelected = FALSE; /* TRUE if the user selected the system partition via the Select Device dialog */ -BOOL bSysDriveSelected = FALSE; /* TRUE if the user selected the system drive via the Select Device dialog */ - -/* To populate these arrays, call GetSysDevicePaths(). If they contain valid paths, bCachedSysDevicePathsValid is TRUE. */ -char SysPartitionDevicePath [TC_MAX_PATH]; -char SysDriveDevicePath [TC_MAX_PATH]; -char bCachedSysDevicePathsValid = FALSE; - -BOOL bHyperLinkBeingTracked = FALSE; - -int WrongPwdRetryCounter = 0; - -static FILE *ConfigFileHandle; -char *ConfigBuffer; - -#define RANDPOOL_DISPLAY_REFRESH_INTERVAL 30 -#define RANDPOOL_DISPLAY_ROWS 20 -#define RANDPOOL_DISPLAY_COLUMNS 32 - -/* Windows dialog class */ -#define WINDOWS_DIALOG_CLASS "#32770" - -/* Custom class names */ -#define TC_DLG_CLASS "CustomDlg" -#define TC_SPLASH_CLASS "SplashDlg" - -/* Benchmarks */ - -#ifndef SETUP - -#define BENCHMARK_MAX_ITEMS 100 -#define BENCHMARK_DEFAULT_BUF_SIZE BYTES_PER_MB -#define HASH_FNC_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. -#define PKCS5_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. -#if PKCS5_BENCHMARKS && HASH_FNC_BENCHMARKS -#error PKCS5_BENCHMARKS and HASH_FNC_BENCHMARKS are both TRUE (at least one of them should be FALSE). -#endif - -enum -{ - BENCHMARK_SORT_BY_NAME = 0, - BENCHMARK_SORT_BY_SPEED -}; - -typedef struct -{ - int id; - char name[100]; - unsigned __int64 encSpeed; - unsigned __int64 decSpeed; - unsigned __int64 meanBytesPerSec; -} BENCHMARK_REC; - -BENCHMARK_REC benchmarkTable [BENCHMARK_MAX_ITEMS]; -int benchmarkTotalItems = 0; -int benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; -int benchmarkLastBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; -int benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; -LARGE_INTEGER benchmarkPerformanceFrequency; - -#endif // #ifndef SETUP - - -typedef struct -{ - void *strings; - BOOL bold; - -} MULTI_CHOICE_DLGPROC_PARAMS; - - -void cleanup () -{ - /* Cleanup the GDI fonts */ - if (hFixedFont != NULL) - DeleteObject (hFixedFont); - if (hFixedDigitFont != NULL) - DeleteObject (hFixedDigitFont); - if (hBoldFont != NULL) - DeleteObject (hBoldFont); - if (hTitleFont != NULL) - DeleteObject (hTitleFont); - if (hUserFont != NULL) - DeleteObject (hUserFont); - if (hUserUnderlineFont != NULL) - DeleteObject (hUserUnderlineFont); - if (hUserBoldFont != NULL) - DeleteObject (hUserBoldFont); - if (hUserUnderlineBoldFont != NULL) - DeleteObject (hUserUnderlineBoldFont); - - /* Cleanup our dialog class */ - if (hDlgClass) - UnregisterClass (TC_DLG_CLASS, hInst); - if (hSplashClass) - UnregisterClass (TC_SPLASH_CLASS, hInst); - - /* Close the device driver handle */ - if (hDriver != INVALID_HANDLE_VALUE) - { - // Unload driver mode if possible (non-install mode) - if (IsNonInstallMode ()) - { - // If a dismount was forced in the lifetime of the driver, Windows may later prevent it to be loaded again from - // the same path. Therefore, the driver will not be unloaded even though it was loaded in non-install mode. - int refDevDeleted; - DWORD dwResult; - - if (!DeviceIoControl (hDriver, TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED, NULL, 0, &refDevDeleted, sizeof (refDevDeleted), &dwResult, NULL)) - refDevDeleted = 0; - - if (!refDevDeleted) - DriverUnload (); - else - { - CloseHandle (hDriver); - hDriver = INVALID_HANDLE_VALUE; - } - } - else - { - CloseHandle (hDriver); - hDriver = INVALID_HANDLE_VALUE; - } - } - - if (ConfigBuffer != NULL) - { - free (ConfigBuffer); - ConfigBuffer = NULL; - } - - CoUninitialize (); - - CloseSysEncMutex (); - -#ifndef SETUP - try - { - if (SecurityToken::IsInitialized()) - SecurityToken::CloseLibrary(); - } - catch (...) { } - - EncryptionThreadPoolStop(); -#endif -} - - -void LowerCaseCopy (char *lpszDest, const char *lpszSource) -{ - int i = strlen (lpszSource); - - lpszDest[i] = 0; - while (--i >= 0) - { - lpszDest[i] = (char) tolower (lpszSource[i]); - } - -} - -void UpperCaseCopy (char *lpszDest, const char *lpszSource) -{ - int i = strlen (lpszSource); - - lpszDest[i] = 0; - while (--i >= 0) - { - lpszDest[i] = (char) toupper (lpszSource[i]); - } -} - - -std::string ToUpperCase (const std::string &str) -{ - string u; - foreach (char c, str) - { - u += (char) toupper (c); - } - - return u; -} - - -BOOL IsVolumeDeviceHosted (char *lpszDiskFile) -{ - return strstr (lpszDiskFile, "\\Device\\") == lpszDiskFile - || strstr (lpszDiskFile, "\\DEVICE\\") == lpszDiskFile; -} - - -void CreateFullVolumePath (char *lpszDiskFile, const char *lpszFileName, BOOL * bDevice) -{ - UpperCaseCopy (lpszDiskFile, lpszFileName); - - *bDevice = FALSE; - - if (memcmp (lpszDiskFile, "\\DEVICE", sizeof (char) * 7) == 0) - { - *bDevice = TRUE; - } - - strcpy (lpszDiskFile, lpszFileName); - -#if _DEBUG - OutputDebugString ("CreateFullVolumePath: "); - OutputDebugString (lpszDiskFile); - OutputDebugString ("\n"); -#endif - -} - -int FakeDosNameForDevice (const char *lpszDiskFile, char *lpszDosDevice, char *lpszCFDevice, BOOL bNameOnly) -{ - BOOL bDosLinkCreated = TRUE; - sprintf (lpszDosDevice, "truecrypt%lu", GetCurrentProcessId ()); - - if (bNameOnly == FALSE) - bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); - - if (bDosLinkCreated == FALSE) - return ERR_OS_ERROR; - else - sprintf (lpszCFDevice, "\\\\.\\%s", lpszDosDevice); - - return 0; -} - -int RemoveFakeDosName (char *lpszDiskFile, char *lpszDosDevice) -{ - BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | - DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); - if (bDosLinkRemoved == FALSE) - { - return ERR_OS_ERROR; - } - - return 0; -} - - -void AbortProcess (char *stringId) -{ - // Note that this function also causes localcleanup() to be called (see atexit()) - MessageBeep (MB_ICONEXCLAMATION); - MessageBoxW (NULL, GetString (stringId), lpszTitle, ICON_HAND); - exit (1); -} - -void AbortProcessSilent (void) -{ - // Note that this function also causes localcleanup() to be called (see atexit()) - exit (1); -} - -void *err_malloc (size_t size) -{ - void *z = (void *) TCalloc (size); - if (z) - return z; - AbortProcess ("OUTOFMEMORY"); - return 0; -} - -char *err_strdup (char *lpszText) -{ - int j = (strlen (lpszText) + 1) * sizeof (char); - char *z = (char *) err_malloc (j); - memmove (z, lpszText, j); - return z; -} - - -BOOL IsDiskReadError (DWORD error) -{ - return (error == ERROR_CRC - || error == ERROR_IO_DEVICE - || error == ERROR_BAD_CLUSTERS - || error == ERROR_SECTOR_NOT_FOUND - || error == ERROR_READ_FAULT - || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT -} - - -BOOL IsDiskWriteError (DWORD error) -{ - return (error == ERROR_IO_DEVICE - || error == ERROR_BAD_CLUSTERS - || error == ERROR_SECTOR_NOT_FOUND - || error == ERROR_WRITE_FAULT - || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT -} - - -BOOL IsDiskError (DWORD error) -{ - return IsDiskReadError (error) || IsDiskWriteError (error); -} - - -DWORD handleWin32Error (HWND hwndDlg) -{ - PWSTR lpMsgBuf; - DWORD dwError = GetLastError (); - - if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) - return dwError; - - // Access denied - if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) - { - Error ("ERR_ACCESS_DENIED"); - SetLastError (dwError); // Preserve the original error code - return dwError; - } - - FormatMessageW ( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dwError, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - (PWSTR) &lpMsgBuf, - 0, - NULL - ); - - MessageBoxW (hwndDlg, lpMsgBuf, lpszTitle, ICON_HAND); - LocalFree (lpMsgBuf); - - // User-friendly hardware error explanation - if (IsDiskError (dwError)) - Error ("ERR_HARDWARE_ERROR"); - - // Device not ready - if (dwError == ERROR_NOT_READY) - HandleDriveNotReadyError(); - - SetLastError (dwError); // Preserve the original error code - - return dwError; -} - -BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf) -{ - DWORD dwError = GetLastError (); - - if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - lpszMsgBuf, nWSizeOfBuf, NULL)) - { - SetLastError (dwError); // Preserve the original error code - return TRUE; - } - - SetLastError (dwError); // Preserve the original error code - return FALSE; -} - - -// If the user has a non-default screen DPI, all absolute font sizes must be -// converted using this function. -int CompensateDPIFont (int val) -{ - if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) - return val; - else - { - double tmpVal = (double) val * DPIScaleFactorY * DlgAspectRatio * 0.999; - - if (tmpVal > 0) - return (int) floor(tmpVal); - else - return (int) ceil(tmpVal); - } -} - - -// If the user has a non-default screen DPI, some screen coordinates and sizes must -// be converted using this function -int CompensateXDPI (int val) -{ - if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) - return val; - else - { - double tmpVal = (double) val * DPIScaleFactorX; - - if (tmpVal > 0) - return (int) floor(tmpVal); - else - return (int) ceil(tmpVal); - } -} - - -// If the user has a non-default screen DPI, some screen coordinates and sizes must -// be converted using this function -int CompensateYDPI (int val) -{ - if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) - return val; - else - { - double tmpVal = (double) val * DPIScaleFactorY; - - if (tmpVal > 0) - return (int) floor(tmpVal); - else - return (int) ceil(tmpVal); - } -} - - -int GetTextGfxWidth (HWND hwndDlgItem, wchar_t *text, HFONT hFont) -{ - SIZE sizes; - TEXTMETRIC textMetrics; - HDC hdc = GetDC (hwndDlgItem); - - SelectObject(hdc, (HGDIOBJ) hFont); - - GetTextExtentPoint32W (hdc, text, wcslen (text), &sizes); - - GetTextMetrics(hdc, &textMetrics); // Necessary for non-TrueType raster fonts (tmOverhang) - - ReleaseDC (hwndDlgItem, hdc); - - return ((int) sizes.cx - (int) textMetrics.tmOverhang); -} - - -int GetTextGfxHeight (HWND hwndDlgItem, wchar_t *text, HFONT hFont) -{ - SIZE sizes; - HDC hdc = GetDC (hwndDlgItem); - - SelectObject(hdc, (HGDIOBJ) hFont); - - GetTextExtentPoint32W (hdc, text, wcslen (text), &sizes); - - ReleaseDC (hwndDlgItem, hdc); - - return ((int) sizes.cy); -} - - -static LRESULT CALLBACK HyperlinkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - WNDPROC wp = (WNDPROC) GetWindowLongPtr (hwnd, GWL_USERDATA); - - switch (message) - { - case WM_SETCURSOR: - if (!bHyperLinkBeingTracked) - { - TRACKMOUSEEVENT trackMouseEvent; - - trackMouseEvent.cbSize = sizeof(trackMouseEvent); - trackMouseEvent.dwFlags = TME_LEAVE; - trackMouseEvent.hwndTrack = hwnd; - - bHyperLinkBeingTracked = TrackMouseEvent(&trackMouseEvent); - - HandCursor(); - } - return 0; - - case WM_MOUSELEAVE: - bHyperLinkBeingTracked = FALSE; - NormalCursor(); - return 0; - } - - return CallWindowProc (wp, hwnd, message, wParam, lParam); -} - - -BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId) -{ - HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); - - SendMessage (hwndCtrl, WM_SETFONT, (WPARAM) hUserUnderlineFont, 0); - - SetWindowLongPtr (hwndCtrl, GWL_USERDATA, (LONG_PTR) GetWindowLongPtr (hwndCtrl, GWL_WNDPROC)); - SetWindowLongPtr (hwndCtrl, GWL_WNDPROC, (LONG_PTR) HyperlinkProc); - - // Resize the field according to its actual length in pixels and move it if centered or right-aligned. - // This should be done again if the link text changes. - AccommodateTextField (hwndDlg, ctrlId, TRUE); - - return TRUE; -} - - -// Resizes a text field according to its actual width in pixels (font size is taken into account) and moves -// it accordingly if the field is centered or right-aligned. Should be used on all hyperlinks upon dialog init -// after localization (bFirstUpdate should be TRUE) and later whenever a hyperlink text changes (bFirstUpdate -// must be FALSE). -void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate) -{ - RECT rec, wrec, trec; - HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); - int width, origWidth, origHeight; - int horizSubOffset, vertOffset, alignPosDiff = 0; - wchar_t text [MAX_URL_LENGTH]; - WINDOWINFO windowInfo; - BOOL bBorderlessWindow = !(GetWindowLongPtr (hwndDlg, GWL_STYLE) & (WS_BORDER | WS_DLGFRAME)); - - // Resize the field according to its length and font size and move if centered or right-aligned - - GetWindowTextW (hwndCtrl, text, sizeof (text) / sizeof (wchar_t)); - - width = GetTextGfxWidth (hwndCtrl, text, hUserUnderlineFont); - - GetClientRect (hwndCtrl, &rec); - origWidth = rec.right; - origHeight = rec.bottom; - - if (width >= 0 - && (!bFirstUpdate || origWidth > width)) // The original width of the field is the maximum allowed size - { - horizSubOffset = origWidth - width; - - // Window coords - GetWindowRect(hwndDlg, &wrec); - GetClientRect(hwndDlg, &trec); - - // Vertical "title bar" offset - vertOffset = wrec.bottom - wrec.top - trec.bottom - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CYFIXEDFRAME)); - - // Text field coords - GetWindowRect(hwndCtrl, &rec); - - // Alignment offset - windowInfo.cbSize = sizeof(windowInfo); - GetWindowInfo (hwndCtrl, &windowInfo); - - if (windowInfo.dwStyle & SS_CENTER) - alignPosDiff = horizSubOffset / 2; - else if (windowInfo.dwStyle & SS_RIGHT) - alignPosDiff = horizSubOffset; - - // Resize/move - if (alignPosDiff > 0) - { - // Resize and move the text field - MoveWindow (hwndCtrl, - rec.left - wrec.left - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CXFIXEDFRAME)) + alignPosDiff, - rec.top - wrec.top - vertOffset, - origWidth - horizSubOffset, - origHeight, - TRUE); - } - else - { - // Resize the text field - SetWindowPos (hwndCtrl, 0, 0, 0, - origWidth - horizSubOffset, - origHeight, - SWP_NOMOVE | SWP_NOZORDER); - } - - SetWindowPos (hwndCtrl, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - - InvalidateRect (hwndCtrl, NULL, TRUE); - } -} - - -// Protects an input field from having its content updated by a Paste action (call ToBootPwdField() to use this). -static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - WNDPROC wp = (WNDPROC) GetWindowLongPtr (hwnd, GWL_USERDATA); - - switch (message) - { - case WM_PASTE: - return 1; - } - - return CallWindowProc (wp, hwnd, message, wParam, lParam); -} - - -// Protects an input field from having its content updated by a Paste action. Used for pre-boot password -// input fields (only the US keyboard layout is supported in pre-boot environment so we must prevent the -// user from pasting a password typed using a non-US keyboard layout). -void ToBootPwdField (HWND hwndDlg, UINT ctrlId) -{ - HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); - - SetWindowLongPtr (hwndCtrl, GWL_USERDATA, (LONG_PTR) GetWindowLongPtr (hwndCtrl, GWL_WNDPROC)); - SetWindowLongPtr (hwndCtrl, GWL_WNDPROC, (LONG_PTR) BootPwdFieldProc); -} - - - -// This function currently serves the following purposes: -// - Determines scaling factors for current screen DPI and GUI aspect ratio. -// - Determines how Windows skews the GUI aspect ratio (which happens when the user has a non-default DPI). -// The determined values must be used when performing some GUI operations and calculations. -BOOL CALLBACK AuxiliaryDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - { - HDC hDC = GetDC (hwndDlg); - - ScreenDPI = GetDeviceCaps (hDC, LOGPIXELSY); - ReleaseDC (hwndDlg, hDC); - - DPIScaleFactorX = 1; - DPIScaleFactorY = 1; - DlgAspectRatio = 1; - - if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) - { - // Windows skews the GUI aspect ratio if the user has a non-default DPI. Hence, working with - // actual screen DPI is redundant and leads to incorrect results. What really matters here is - // how Windows actually renders our GUI. This is determined by comparing the expected and current - // sizes of a hidden calibration text field. - - RECT trec; - - trec.right = 0; - trec.bottom = 0; - - GetClientRect (GetDlgItem (hwndDlg, IDC_ASPECT_RATIO_CALIBRATION_BOX), &trec); - - if (trec.right != 0 && trec.bottom != 0) - { - // The size of the 282x282 IDC_ASPECT_RATIO_CALIBRATION_BOX rendered at the default DPI (96) is 423x458 - DPIScaleFactorX = (double) trec.right / 423; - DPIScaleFactorY = (double) trec.bottom / 458; - DlgAspectRatio = DPIScaleFactorX / DPIScaleFactorY; - } - } - - EndDialog (hwndDlg, 0); - return 1; - } - - case WM_CLOSE: - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - static HBITMAP hbmTextualLogoBitmapRescaled = NULL; - - switch (msg) - { - case WM_INITDIALOG: - { - char szTmp[100]; - RECT rec; - - LocalizeDialog (hwndDlg, "IDD_ABOUT_DLG"); - - // Hyperlink - SetWindowText (GetDlgItem (hwndDlg, IDC_HOMEPAGE), "www.truecrypt.org"); - ToHyperlink (hwndDlg, IDC_HOMEPAGE); - - // Logo area background (must not keep aspect ratio; must retain Windows-imposed distortion) - GetClientRect (GetDlgItem (hwndDlg, IDC_ABOUT_LOGO_AREA), &rec); - SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, rec.right, rec.bottom, SWP_NOMOVE); - - // Resize the logo bitmap if the user has a non-default DPI - if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) - { - // Logo (must recreate and keep the original aspect ratio as Windows distorts it) - hbmTextualLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_TEXTUAL_LOGO_288DPI), - GetDlgItem (hwndDlg, IDC_TEXTUAL_LOGO_IMG), - 0, 0, 0, 0, FALSE, TRUE); - - SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - } - - // Version - SendMessage (GetDlgItem (hwndDlg, IDT_ABOUT_VERSION), WM_SETFONT, (WPARAM) hUserBoldFont, 0); - sprintf (szTmp, "TrueCrypt %s", VERSION_STRING); -#if (defined(_DEBUG) || defined(DEBUG)) - strcat (szTmp, " (debug)"); -#endif - SetDlgItemText (hwndDlg, IDT_ABOUT_VERSION, szTmp); - - // Credits - SendMessage (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), WM_SETFONT, (WPARAM) hUserFont, (LPARAM) 0); - SendMessage (hwndDlg, WM_APP, 0, 0); - return 1; - } - - case WM_APP: - SetWindowText (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), - "Portions of this software are based in part on the works of the following people: " - "Paul Le Roux, " - "Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, Niels Ferguson, " - "Lars Knudsen, Ross Anderson, Eli Biham, " - "Joan Daemen, Vincent Rijmen, " - "Phillip Rogaway, " - "Hans Dobbertin, Antoon Bosselaers, Bart Preneel, " - "Paulo Barreto, Brian Gladman, Wei Dai, Peter Gutmann, and many others.\r\n\r\n" - - "Portions of this software:\r\n" - "Copyright \xA9 2003-2009 TrueCrypt Foundation. All Rights Reserved.\r\n" - "Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\r\n" - "Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\r\n" - "Copyright \xA9 2002-2004 Mark Adler. All Rights Reserved.\r\n\r\n" - - "This software as a whole:\r\n" - "Copyright \xA9 2009 TrueCrypt Foundation. All rights reserved.\r\n\r\n" - - "A TrueCrypt Foundation Release"); - - return 1; - - case WM_COMMAND: - if (lw == IDOK || lw == IDCANCEL) - { - PostMessage (hwndDlg, WM_CLOSE, 0, 0); - return 1; - } - - if (lw == IDC_HOMEPAGE) - { - Applink ("main", TRUE, ""); - return 1; - } - - if (lw == IDC_DONATIONS) - { - Applink ("donate", FALSE, ""); - return 1; - } - - // Disallow modification of credits - if (HIWORD (wParam) == EN_UPDATE) - { - SendMessage (hwndDlg, WM_APP, 0, 0); - return 1; - } - - return 0; - - case WM_CLOSE: - /* Delete buffered bitmaps (if any) */ - if (hbmTextualLogoBitmapRescaled != NULL) - { - DeleteObject ((HGDIOBJ) hbmTextualLogoBitmapRescaled); - hbmTextualLogoBitmapRescaled = NULL; - } - - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - - -BOOL -IsButtonChecked (HWND hButton) -{ - if (SendMessage (hButton, BM_GETCHECK, 0, 0) == BST_CHECKED) - return TRUE; - else - return FALSE; -} - -void -CheckButton (HWND hButton) -{ - SendMessage (hButton, BM_SETCHECK, BST_CHECKED, 0); -} - - -void LeftPadString (char *szTmp, int len, int targetLen, char filler) -{ - int i; - - if (targetLen <= len) - return; - - for (i = targetLen-1; i >= (targetLen-len); i--) - szTmp [i] = szTmp [i-(targetLen-len)]; - - memset (szTmp, filler, targetLen-len); - szTmp [targetLen] = 0; -} - - -/***************************************************************************** - ToSBCS: converts a unicode string to Single Byte Character String (SBCS). - ***************************************************************************/ - -void -ToSBCS (LPWSTR lpszText) -{ - int j = wcslen (lpszText); - if (j == 0) - { - strcpy ((char *) lpszText, ""); - return; - } - else - { - char *lpszNewText = (char *) err_malloc (j + 1); - j = WideCharToMultiByte (CP_ACP, 0L, lpszText, -1, lpszNewText, j + 1, NULL, NULL); - if (j > 0) - strcpy ((char *) lpszText, lpszNewText); - else - strcpy ((char *) lpszText, ""); - free (lpszNewText); - } -} - -/***************************************************************************** - ToUNICODE: converts a SBCS string to a UNICODE string. - ***************************************************************************/ - -void -ToUNICODE (char *lpszText) -{ - int j = strlen (lpszText); - if (j == 0) - { - wcscpy ((LPWSTR) lpszText, (LPWSTR) WIDE ("")); - return; - } - else - { - LPWSTR lpszNewText = (LPWSTR) err_malloc ((j + 1) * 2); - j = MultiByteToWideChar (CP_ACP, 0L, lpszText, -1, lpszNewText, j + 1); - if (j > 0) - wcscpy ((LPWSTR) lpszText, lpszNewText); - else - wcscpy ((LPWSTR) lpszText, (LPWSTR) WIDE ("")); - free (lpszNewText); - } -} - -/* InitDialog - initialize the applications main dialog, this function should - be called only once in the dialogs WM_INITDIALOG message handler */ -void -InitDialog (HWND hwndDlg) -{ - NONCLIENTMETRICSW metric; - static BOOL aboutMenuAppended = FALSE; - - int nHeight; - LOGFONTW lf; - HMENU hMenu; - Font *font; - - /* Fonts */ - - // Normal - font = GetFont ("font_normal"); - - metric.cbSize = sizeof (metric); - SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(metric), &metric, 0); - - metric.lfMessageFont.lfHeight = CompensateDPIFont (!font ? -11 : -font->Size); - metric.lfMessageFont.lfWidth = 0; - - if (font && wcscmp (font->FaceName, L"default") != 0) - { - wcsncpy ((WCHAR *)metric.lfMessageFont.lfFaceName, font->FaceName, sizeof (metric.lfMessageFont.lfFaceName)/2); - } - else if (IsOSAtLeast (WIN_VISTA)) - { - // Vista's new default font (size and spacing) breaks compatibility with Windows 2k/XP applications. - // Force use of Tahoma (as Microsoft does in many dialogs) until a native Vista look is implemented. - wcsncpy ((WCHAR *)metric.lfMessageFont.lfFaceName, L"Tahoma", sizeof (metric.lfMessageFont.lfFaceName)/2); - } - - hUserFont = CreateFontIndirectW (&metric.lfMessageFont); - - metric.lfMessageFont.lfUnderline = TRUE; - hUserUnderlineFont = CreateFontIndirectW (&metric.lfMessageFont); - - metric.lfMessageFont.lfUnderline = FALSE; - metric.lfMessageFont.lfWeight = FW_BOLD; - hUserBoldFont = CreateFontIndirectW (&metric.lfMessageFont); - - metric.lfMessageFont.lfUnderline = TRUE; - metric.lfMessageFont.lfWeight = FW_BOLD; - hUserUnderlineBoldFont = CreateFontIndirectW (&metric.lfMessageFont); - - // Fixed-size (hexadecimal digits) - nHeight = CompensateDPIFont (-12); - lf.lfHeight = nHeight; - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - lf.lfWeight = FW_NORMAL; - lf.lfItalic = FALSE; - lf.lfUnderline = FALSE; - lf.lfStrikeOut = FALSE; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfOutPrecision = OUT_DEFAULT_PRECIS; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfQuality = PROOF_QUALITY; - lf.lfPitchAndFamily = FF_DONTCARE; - wcscpy (lf.lfFaceName, L"Courier New"); - hFixedDigitFont = CreateFontIndirectW (&lf); - if (hFixedDigitFont == NULL) - { - handleWin32Error (hwndDlg); - AbortProcess ("NOFONT"); - } - - // Bold - font = GetFont ("font_bold"); - - nHeight = CompensateDPIFont (!font ? -13 : -font->Size); - lf.lfHeight = nHeight; - lf.lfWeight = FW_BLACK; - wcsncpy (lf.lfFaceName, !font ? L"Arial" : font->FaceName, sizeof (lf.lfFaceName)/2); - hBoldFont = CreateFontIndirectW (&lf); - if (hBoldFont == NULL) - { - handleWin32Error (hwndDlg); - AbortProcess ("NOFONT"); - } - - // Title - font = GetFont ("font_title"); - - nHeight = CompensateDPIFont (!font ? -21 : -font->Size); - lf.lfHeight = nHeight; - lf.lfWeight = FW_REGULAR; - wcsncpy (lf.lfFaceName, !font ? L"Times New Roman" : font->FaceName, sizeof (lf.lfFaceName)/2); - hTitleFont = CreateFontIndirectW (&lf); - if (hTitleFont == NULL) - { - handleWin32Error (hwndDlg); - AbortProcess ("NOFONT"); - } - - // Fixed-size - font = GetFont ("font_fixed"); - - nHeight = CompensateDPIFont (!font ? -12 : -font->Size); - lf.lfHeight = nHeight; - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - lf.lfWeight = FW_NORMAL; - lf.lfItalic = FALSE; - lf.lfUnderline = FALSE; - lf.lfStrikeOut = FALSE; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfOutPrecision = OUT_DEFAULT_PRECIS; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfQuality = PROOF_QUALITY; - lf.lfPitchAndFamily = FF_DONTCARE; - wcsncpy (lf.lfFaceName, !font ? L"Lucida Console" : font->FaceName, sizeof (lf.lfFaceName)/2); - hFixedFont = CreateFontIndirectW (&lf); - if (hFixedFont == NULL) - { - handleWin32Error (hwndDlg); - AbortProcess ("NOFONT"); - } - - if (!aboutMenuAppended) - { - hMenu = GetSystemMenu (hwndDlg, FALSE); - AppendMenu (hMenu, MF_SEPARATOR, 0, NULL); - AppendMenuW (hMenu, MF_ENABLED | MF_STRING, IDC_ABOUT, GetString ("ABOUTBOX")); - - aboutMenuAppended = TRUE; - } -} - -HDC CreateMemBitmap (HINSTANCE hInstance, HWND hwnd, char *resource) -{ - HBITMAP picture = LoadBitmap (hInstance, resource); - HDC viewDC = GetDC (hwnd), dcMem; - - dcMem = CreateCompatibleDC (viewDC); - - SetMapMode (dcMem, MM_TEXT); - - SelectObject (dcMem, picture); - - DeleteObject (picture); - - ReleaseDC (hwnd, viewDC); - - return dcMem; -} - - -/* Renders the specified bitmap at the specified location and stretches it to fit (anti-aliasing is applied). -If bDirectRender is FALSE and both nWidth and nHeight are zero, the width and height of hwndDest are -retrieved and adjusted according to screen DPI (the width and height of the resultant image are adjusted the -same way); furthermore, if bKeepAspectRatio is TRUE, the smaller DPI factor of the two (i.e. horiz. or vert.) -is used both for horiz. and vert. scaling (note that the overall GUI aspect ratio changes irregularly in -both directions depending on the DPI). If bDirectRender is TRUE, bKeepAspectRatio is ignored. -This function returns a handle to the scaled bitmap. When the bitmap is no longer needed, it should be -deleted by calling DeleteObject() with the handle passed as the parameter. -Known Windows issues: -- For some reason, anti-aliasing is not applied if the source bitmap contains less than 16K pixels. -- Windows 2000 may produce slightly inaccurate colors even when source, buffer, and target are 24-bit true color. */ -HBITMAP RenderBitmap (char *resource, HWND hwndDest, int x, int y, int nWidth, int nHeight, BOOL bDirectRender, BOOL bKeepAspectRatio) -{ - LRESULT lResult = 0; - - HDC hdcSrc = CreateMemBitmap (hInst, hwndDest, resource); - - HGDIOBJ picture = GetCurrentObject (hdcSrc, OBJ_BITMAP); - - HBITMAP hbmpRescaled; - BITMAP bitmap; - - HDC hdcRescaled; - - if (!bDirectRender && nWidth == 0 && nHeight == 0) - { - RECT rec; - - GetClientRect (hwndDest, &rec); - - if (bKeepAspectRatio) - { - if (DlgAspectRatio > 1) - { - // Do not fix this, it's correct. We use the Y scale factor intentionally for both - // directions to maintain aspect ratio (see above for more info). - nWidth = CompensateYDPI (rec.right); - nHeight = CompensateYDPI (rec.bottom); - } - else - { - // Do not fix this, it's correct. We use the X scale factor intentionally for both - // directions to maintain aspect ratio (see above for more info). - nWidth = CompensateXDPI (rec.right); - nHeight = CompensateXDPI (rec.bottom); - } - } - else - { - nWidth = CompensateXDPI (rec.right); - nHeight = CompensateYDPI (rec.bottom); - } - } - - GetObject (picture, sizeof (BITMAP), &bitmap); - - hdcRescaled = CreateCompatibleDC (hdcSrc); - - hbmpRescaled = CreateCompatibleBitmap (hdcSrc, nWidth, nHeight); - - SelectObject (hdcRescaled, hbmpRescaled); - - /* Anti-aliasing mode (HALFTONE is the only anti-aliasing algorithm natively supported by Windows 2000. - TODO: GDI+ offers higher quality -- InterpolationModeHighQualityBicubic) */ - SetStretchBltMode (hdcRescaled, HALFTONE); - - StretchBlt (hdcRescaled, - 0, - 0, - nWidth, - nHeight, - hdcSrc, - 0, - 0, - bitmap.bmWidth, - bitmap.bmHeight, - SRCCOPY); - - DeleteDC (hdcSrc); - - if (bDirectRender) - { - HDC hdcDest = GetDC (hwndDest); - - BitBlt (hdcDest, x, y, nWidth, nHeight, hdcRescaled, 0, 0, SRCCOPY); - DeleteDC (hdcDest); - } - else - { - lResult = SendMessage (hwndDest, (UINT) STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) (HANDLE) hbmpRescaled); - } - - if ((HGDIOBJ) lResult != NULL && (HGDIOBJ) lResult != (HGDIOBJ) hbmpRescaled) - DeleteObject ((HGDIOBJ) lResult); - - DeleteDC (hdcRescaled); - - return hbmpRescaled; -} - - -LRESULT CALLBACK -RedTick (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_CREATE) - { - } - else if (uMsg == WM_DESTROY) - { - } - else if (uMsg == WM_TIMER) - { - } - else if (uMsg == WM_PAINT) - { - PAINTSTRUCT tmp; - HPEN hPen; - HDC hDC; - BOOL bEndPaint; - RECT Rect; - - if (GetUpdateRect (hwnd, NULL, FALSE)) - { - hDC = BeginPaint (hwnd, &tmp); - bEndPaint = TRUE; - if (hDC == NULL) - return DefWindowProc (hwnd, uMsg, wParam, lParam); - } - else - { - hDC = GetDC (hwnd); - bEndPaint = FALSE; - } - - GetClientRect (hwnd, &Rect); - - hPen = CreatePen (PS_SOLID, 2, RGB (0, 255, 0)); - if (hPen != NULL) - { - HGDIOBJ hObj = SelectObject (hDC, hPen); - WORD bx = LOWORD (GetDialogBaseUnits ()); - WORD by = HIWORD (GetDialogBaseUnits ()); - - MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); - LineTo (hDC, Rect.right, Rect.top); - MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); - - LineTo (hDC, (3 * bx) / 4, (2 * by) / 8); - - SelectObject (hDC, hObj); - DeleteObject (hPen); - } - - if (bEndPaint) - EndPaint (hwnd, &tmp); - else - ReleaseDC (hwnd, hDC); - - return TRUE; - } - - return DefWindowProc (hwnd, uMsg, wParam, lParam); -} - -BOOL -RegisterRedTick (HINSTANCE hInstance) -{ - WNDCLASS wc; - ULONG rc; - - memset(&wc, 0 , sizeof wc); - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.cbClsExtra = 0; - wc.cbWndExtra = 4; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); - wc.hCursor = NULL; - wc.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH); - wc.lpszClassName = "REDTICK"; - wc.lpfnWndProc = &RedTick; - - rc = (ULONG) RegisterClass (&wc); - - return rc == 0 ? FALSE : TRUE; -} - -BOOL -UnregisterRedTick (HINSTANCE hInstance) -{ - return UnregisterClass ("REDTICK", hInstance); -} - -LRESULT CALLBACK -SplashDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return DefDlgProc (hwnd, uMsg, wParam, lParam); -} - -void -WaitCursor () -{ - static HCURSOR hcWait; - if (hcWait == NULL) - hcWait = LoadCursor (NULL, IDC_WAIT); - SetCursor (hcWait); - hCursor = hcWait; -} - -void -NormalCursor () -{ - static HCURSOR hcArrow; - if (hcArrow == NULL) - hcArrow = LoadCursor (NULL, IDC_ARROW); - SetCursor (hcArrow); - hCursor = NULL; -} - -void -ArrowWaitCursor () -{ - static HCURSOR hcArrowWait; - if (hcArrowWait == NULL) - hcArrowWait = LoadCursor (NULL, IDC_APPSTARTING); - SetCursor (hcArrowWait); - hCursor = hcArrowWait; -} - -void HandCursor () -{ - static HCURSOR hcHand; - if (hcHand == NULL) - hcHand = LoadCursor (NULL, IDC_HAND); - SetCursor (hcHand); - hCursor = hcHand; -} - -void -AddComboPair (HWND hComboBox, const char *lpszItem, int value) -{ - LPARAM nIndex; - - nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem); - nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value); -} - -void -AddComboPairW (HWND hComboBox, const wchar_t *lpszItem, int value) -{ - LPARAM nIndex; - - nIndex = SendMessageW (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem); - nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value); -} - -void -SelectAlgo (HWND hComboBox, int *algo_id) -{ - LPARAM nCount = SendMessage (hComboBox, CB_GETCOUNT, 0, 0); - LPARAM x, i; - - for (i = 0; i < nCount; i++) - { - x = SendMessage (hComboBox, CB_GETITEMDATA, i, 0); - if (x == (LPARAM) *algo_id) - { - SendMessage (hComboBox, CB_SETCURSEL, i, 0); - return; - } - } - - /* Something went wrong ; couldn't find the requested algo id so we drop - back to a default */ - - *algo_id = SendMessage (hComboBox, CB_GETITEMDATA, 0, 0); - - SendMessage (hComboBox, CB_SETCURSEL, 0, 0); - -} - -void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption) -{ - if (bNA) - { - AddComboPairW (hComboBox, GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"), TC_WIPE_NONE); - } - else - { - if (bInPlaceEncryption) - AddComboPairW (hComboBox, GetString ("WIPE_MODE_NONE"), TC_WIPE_NONE); - else - AddComboPairW (hComboBox, GetString ("WIPE_MODE_1_RAND"), TC_WIPE_1_RAND); - - AddComboPairW (hComboBox, GetString ("WIPE_MODE_3_DOD_5220"), TC_WIPE_3_DOD_5220); - AddComboPairW (hComboBox, GetString ("WIPE_MODE_7_DOD_5220"), TC_WIPE_7_DOD_5220); - AddComboPairW (hComboBox, GetString ("WIPE_MODE_35_GUTMANN"), TC_WIPE_35_GUTMANN); - } -} - -wchar_t *GetWipeModeName (WipeAlgorithmId modeId) -{ - switch (modeId) - { - case TC_WIPE_NONE: - return GetString ("WIPE_MODE_NONE"); - - case TC_WIPE_1_RAND: - return GetString ("WIPE_MODE_1_RAND"); - - case TC_WIPE_3_DOD_5220: - return GetString ("WIPE_MODE_3_DOD_5220"); - - case TC_WIPE_7_DOD_5220: - return GetString ("WIPE_MODE_7_DOD_5220"); - - case TC_WIPE_35_GUTMANN: - return GetString ("WIPE_MODE_35_GUTMANN"); - - default: - return GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"); - } -} - -wchar_t *GetPathType (const char *path, BOOL bUpperCase, BOOL *bIsPartition) -{ - if (strstr (path, "Partition") - && strstr (path, "Partition0") == NULL) - { - *bIsPartition = TRUE; - return GetString (bUpperCase ? "PARTITION_UPPER_CASE" : "PARTITION_LOWER_CASE"); - } - else if (strstr (path, "HarddiskVolume")) - { - *bIsPartition = TRUE; - return GetString (bUpperCase ? "VOLUME_UPPER_CASE" : "VOLUME_LOWER_CASE"); - } - - *bIsPartition = FALSE; - return GetString (bUpperCase ? "DEVICE_UPPER_CASE" : "DEVICE_LOWER_CASE"); -} - -LRESULT CALLBACK CustomDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_SETCURSOR && hCursor != NULL) - { - SetCursor (hCursor); - return TRUE; - } - - return DefDlgProc (hwnd, uMsg, wParam, lParam); -} - - -static BOOL IsReturnAddress (DWORD64 address) -{ - static size_t codeEnd = 0; - byte *sp = (byte *) address; - - if (codeEnd == 0) - { - MEMORY_BASIC_INFORMATION mi; - if (VirtualQuery ((LPCVOID) 0x401000, &mi, sizeof (mi)) >= sizeof (mi)) - codeEnd = (size_t) mi.BaseAddress + mi.RegionSize; - } - - if (address < 0x401000 + 8 || address > codeEnd) - return FALSE; - - return sp[-5] == 0xe8 // call ADDR - || (sp[-6] == 0xff && sp[-5] == 0x15) // call [ADDR] - || (sp[-2] == 0xff && (sp[-1] & 0xf0) == 0xd0); // call REG -} - - -typedef struct -{ - EXCEPTION_POINTERS *ExceptionPointers; - HANDLE ExceptionThread; - -} ExceptionHandlerThreadArgs; - - -void ExceptionHandlerThread (void *threadArg) -{ - ExceptionHandlerThreadArgs *args = (ExceptionHandlerThreadArgs *) threadArg; - - EXCEPTION_POINTERS *ep = args->ExceptionPointers; - DWORD addr; - DWORD exCode = ep->ExceptionRecord->ExceptionCode; - SYSTEM_INFO si; - wchar_t msg[8192]; - char modPath[MAX_PATH]; - int crc = 0; - char url[MAX_URL_LENGTH]; - char lpack[128]; - stringstream callStack; - addr = (DWORD) ep->ExceptionRecord->ExceptionAddress; - PDWORD sp = (PDWORD) ep->ContextRecord->Esp; - int frameNumber = 0; - - switch (exCode) - { - case STATUS_IN_PAGE_ERROR: - case 0xeedfade: - // Exception not caused by TrueCrypt - MessageBoxW (0, GetString ("EXCEPTION_REPORT_EXT"), - GetString ("EXCEPTION_REPORT_TITLE"), - MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); - return; - } - - // Call stack - HMODULE dbgDll = LoadLibrary ("dbghelp.dll"); - if (dbgDll) - { - typedef DWORD (__stdcall *SymGetOptions_t) (); - typedef DWORD (__stdcall *SymSetOptions_t) (DWORD SymOptions); - typedef BOOL (__stdcall *SymInitialize_t) (HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess); - typedef BOOL (__stdcall *StackWalk64_t) (DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); - typedef BOOL (__stdcall * SymFromAddr_t) (HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol); - - SymGetOptions_t DbgHelpSymGetOptions = (SymGetOptions_t) GetProcAddress (dbgDll, "SymGetOptions"); - SymSetOptions_t DbgHelpSymSetOptions = (SymSetOptions_t) GetProcAddress (dbgDll, "SymSetOptions"); - SymInitialize_t DbgHelpSymInitialize = (SymInitialize_t) GetProcAddress (dbgDll, "SymInitialize"); - PFUNCTION_TABLE_ACCESS_ROUTINE64 DbgHelpSymFunctionTableAccess64 = (PFUNCTION_TABLE_ACCESS_ROUTINE64) GetProcAddress (dbgDll, "SymFunctionTableAccess64"); - PGET_MODULE_BASE_ROUTINE64 DbgHelpSymGetModuleBase64 = (PGET_MODULE_BASE_ROUTINE64) GetProcAddress (dbgDll, "SymGetModuleBase64"); - StackWalk64_t DbgHelpStackWalk64 = (StackWalk64_t) GetProcAddress (dbgDll, "StackWalk64"); - SymFromAddr_t DbgHelpSymFromAddr = (SymFromAddr_t) GetProcAddress (dbgDll, "SymFromAddr"); - - if (DbgHelpSymGetOptions && DbgHelpSymSetOptions && DbgHelpSymInitialize && DbgHelpSymFunctionTableAccess64 && DbgHelpSymGetModuleBase64 && DbgHelpStackWalk64 && DbgHelpSymFromAddr) - { - DbgHelpSymSetOptions (DbgHelpSymGetOptions() | SYMOPT_DEFERRED_LOADS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_NO_CPP); - - if (DbgHelpSymInitialize (GetCurrentProcess(), NULL, TRUE)) - { - STACKFRAME64 frame; - memset (&frame, 0, sizeof (frame)); - - frame.AddrPC.Offset = ep->ContextRecord->Eip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrStack.Offset = ep->ContextRecord->Esp; - frame.AddrStack.Mode = AddrModeFlat; - frame.AddrFrame.Offset = ep->ContextRecord->Ebp; - frame.AddrFrame.Mode = AddrModeFlat; - - string lastSymbol; - - while (frameNumber < 32 && DbgHelpStackWalk64 (IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), args->ExceptionThread, &frame, ep->ContextRecord, NULL, DbgHelpSymFunctionTableAccess64, DbgHelpSymGetModuleBase64, NULL)) - { - if (!frame.AddrPC.Offset) - continue; - - ULONG64 symbolBuffer[(sizeof (SYMBOL_INFO) + MAX_SYM_NAME * sizeof (TCHAR) + sizeof (ULONG64) - 1) / sizeof (ULONG64)]; - memset (symbolBuffer, 0, sizeof (symbolBuffer)); - - PSYMBOL_INFO symbol = (PSYMBOL_INFO) symbolBuffer; - symbol->SizeOfStruct = sizeof (SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; - - if (DbgHelpSymFromAddr (GetCurrentProcess(), frame.AddrPC.Offset, NULL, symbol) && symbol->NameLen > 0) - { - for (size_t i = 0; i < symbol->NameLen; ++i) - { - if (!isalnum (symbol->Name[i])) - symbol->Name[i] = '_'; - } - - if (symbol->Name != lastSymbol) - callStack << "&st" << frameNumber++ << "=" << symbol->Name; - - lastSymbol = symbol->Name; - } - else if (frameNumber == 0 || IsReturnAddress (frame.AddrPC.Offset)) - { - callStack << "&st" << frameNumber++ << "=0x" << hex << frame.AddrPC.Offset << dec; - } - } - } - } - } - - // StackWalk64() may fail due to missing frame pointers - list retAddrs; - if (frameNumber == 0) - retAddrs.push_back (ep->ContextRecord->Eip); - - retAddrs.push_back (0); - - MEMORY_BASIC_INFORMATION mi; - VirtualQuery (sp, &mi, sizeof (mi)); - PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize); - int i = 0; - - while (retAddrs.size() < 16 && &sp[i] < stackTop) - { - if (IsReturnAddress (sp[i])) - { - bool duplicate = false; - foreach (DWORD prevAddr, retAddrs) - { - if (sp[i] == prevAddr) - { - duplicate = true; - break; - } - } - - if (!duplicate) - retAddrs.push_back (sp[i]); - } - i++; - } - - if (retAddrs.size() > 1) - { - foreach (DWORD addr, retAddrs) - { - callStack << "&st" << frameNumber++ << "=0x" << hex << addr << dec; - } - } - - // Checksum of the module - if (GetModuleFileName (NULL, modPath, sizeof (modPath))) - { - HANDLE h = CreateFile (modPath, FILE_READ_DATA | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h != INVALID_HANDLE_VALUE) - { - BY_HANDLE_FILE_INFORMATION fi; - if (GetFileInformationByHandle (h, &fi)) - { - char *buf = (char *) malloc (fi.nFileSizeLow); - if (buf) - { - DWORD bytesRead; - if (ReadFile (h, buf, fi.nFileSizeLow, &bytesRead, NULL) && bytesRead == fi.nFileSizeLow) - crc = GetCrc32 ((unsigned char *) buf, fi.nFileSizeLow); - free (buf); - } - } - CloseHandle (h); - } - } - - GetSystemInfo (&si); - - if (LocalizationActive) - sprintf_s (lpack, sizeof (lpack), "&langpack=%s_%s", GetPreferredLangId (), GetActiveLangPackVersion ()); - else - lpack[0] = 0; - - sprintf (url, TC_APPLINK_SECURE "&dest=err-report%s&os=%s&osver=%d.%d.%d&arch=%s&cpus=%d&app=%s&cksum=%x&dlg=%s&err=%x&addr=%x" - , lpack - , GetWindowsEdition().c_str() - , CurrentOSMajor - , CurrentOSMinor - , CurrentOSServicePack - , Is64BitOs () ? "x64" : "x86" - , si.dwNumberOfProcessors -#ifdef TCMOUNT - ,"main" -#endif -#ifdef VOLFORMAT - ,"format" -#endif -#ifdef SETUP - ,"setup" -#endif - , crc - , LastDialogId ? LastDialogId : "-" - , exCode - , addr); - - string urlStr = url + callStack.str(); - - _snwprintf (msg, array_capacity (msg), GetString ("EXCEPTION_REPORT"), urlStr.c_str()); - - if (IDYES == MessageBoxW (0, msg, GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1)) - ShellExecute (NULL, "open", urlStr.c_str(), NULL, NULL, SW_SHOWNORMAL); - else - UnhandledExceptionFilter (ep); -} - - -LONG __stdcall ExceptionHandler (EXCEPTION_POINTERS *ep) -{ - SetUnhandledExceptionFilter (NULL); - - ExceptionHandlerThreadArgs args; - args.ExceptionPointers = ep; - args.ExceptionThread = GetCurrentThread(); - - WaitForSingleObject ((HANDLE) _beginthread (ExceptionHandlerThread, 0, &args), INFINITE); - - return EXCEPTION_EXECUTE_HANDLER; -} - - -static LRESULT CALLBACK NonInstallUacWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProc (hWnd, message, wParam, lParam); -} - - -// Mutex handling to prevent multiple instances of the wizard or main app from dealing with system encryption. -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL CreateSysEncMutex (void) -{ - return TCCreateMutex (&hSysEncMutex, TC_MUTEX_NAME_SYSENC); -} - - -BOOL InstanceHasSysEncMutex (void) -{ - return (hSysEncMutex != NULL); -} - - -// Mutex handling to prevent multiple instances of the wizard from dealing with system encryption -void CloseSysEncMutex (void) -{ - TCCloseMutex (&hSysEncMutex); -} - - -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL CreateNonSysInplaceEncMutex (void) -{ - return TCCreateMutex (&hNonSysInplaceEncMutex, TC_MUTEX_NAME_NONSYS_INPLACE_ENC); -} - - -BOOL InstanceHasNonSysInplaceEncMutex (void) -{ - return (hNonSysInplaceEncMutex != NULL); -} - - -void CloseNonSysInplaceEncMutex (void) -{ - TCCloseMutex (&hNonSysInplaceEncMutex); -} - - -// Returns TRUE if another instance of the wizard is preparing, resuming or performing non-system in-place encryption -BOOL NonSysInplaceEncInProgressElsewhere (void) -{ - return (!InstanceHasNonSysInplaceEncMutex () - && MutexExistsOnSystem (TC_MUTEX_NAME_NONSYS_INPLACE_ENC)); -} - - -// Mutex handling to prevent multiple instances of the wizard or main app from trying to install -// or register the driver or from trying to launch it in traveler mode at the same time. -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL CreateDriverSetupMutex (void) -{ - return TCCreateMutex (&hDriverSetupMutex, TC_MUTEX_NAME_DRIVER_SETUP); -} - - -void CloseDriverSetupMutex (void) -{ - TCCloseMutex (&hDriverSetupMutex); -} - - -BOOL CreateAppSetupMutex (void) -{ - return TCCreateMutex (&hAppSetupMutex, TC_MUTEX_NAME_APP_SETUP); -} - - -void CloseAppSetupMutex (void) -{ - TCCloseMutex (&hAppSetupMutex); -} - - -BOOL IsTrueCryptInstallerRunning (void) -{ - return (MutexExistsOnSystem (TC_MUTEX_NAME_APP_SETUP)); -} - - -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL TCCreateMutex (volatile HANDLE *hMutex, char *name) -{ - if (*hMutex != NULL) - return TRUE; // This instance already has the mutex - - *hMutex = CreateMutex (NULL, TRUE, name); - if (*hMutex == NULL) - { - // In multi-user configurations, the OS returns "Access is denied" here when a user attempts - // to acquire the mutex if another user already has. However, on Vista, "Access is denied" is - // returned also if the mutex is owned by a process with admin rights while we have none. - - return FALSE; - } - - if (GetLastError () == ERROR_ALREADY_EXISTS) - { - ReleaseMutex (*hMutex); - CloseHandle (*hMutex); - - *hMutex = NULL; - return FALSE; - } - - return TRUE; -} - - -void TCCloseMutex (volatile HANDLE *hMutex) -{ - if (*hMutex != NULL) - { - if (ReleaseMutex (*hMutex) - && CloseHandle (*hMutex)) - *hMutex = NULL; - } -} - - -// Returns TRUE if a process running on the system has the specified mutex (otherwise FALSE). -BOOL MutexExistsOnSystem (char *name) -{ - if (name[0] == 0) - return FALSE; - - HANDLE hMutex = OpenMutex (MUTEX_ALL_ACCESS, FALSE, name); - - if (hMutex == NULL) - { - if (GetLastError () == ERROR_FILE_NOT_FOUND) - return FALSE; - - if (GetLastError () == ERROR_ACCESS_DENIED) // On Vista, this is returned if the owner of the mutex is elevated while we are not - return TRUE; - - // The call failed and it is not certain whether the mutex exists or not - return FALSE; - } - - CloseHandle (hMutex); - return TRUE; -} - - -BOOL LoadSysEncSettings (HWND hwndDlg) -{ - BOOL status = TRUE; - DWORD size = 0; - char *sysEncCfgFileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), &size); - char *xml = sysEncCfgFileBuf; - char paramName[100], paramVal[MAX_PATH]; - - // Defaults - int newSystemEncryptionStatus = SYSENC_STATUS_NONE; - WipeAlgorithmId newnWipeMode = TC_WIPE_NONE; - - if (!FileExists (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION))) - { - SystemEncryptionStatus = newSystemEncryptionStatus; - nWipeMode = newnWipeMode; - } - - if (xml == NULL) - { - return FALSE; - } - - while (xml = XmlFindElement (xml, "config")) - { - XmlGetAttributeText (xml, "key", paramName, sizeof (paramName)); - XmlGetNodeText (xml, paramVal, sizeof (paramVal)); - - if (strcmp (paramName, "SystemEncryptionStatus") == 0) - { - newSystemEncryptionStatus = atoi (paramVal); - } - else if (strcmp (paramName, "WipeMode") == 0) - { - newnWipeMode = (WipeAlgorithmId) atoi (paramVal); - } - - xml++; - } - - SystemEncryptionStatus = newSystemEncryptionStatus; - nWipeMode = newnWipeMode; - - free (sysEncCfgFileBuf); - return status; -} - - -// Returns the number of partitions where non-system in-place encryption is progress or had been in progress -// but was interrupted. In addition, via the passed pointer, returns the last selected wipe algorithm ID. -int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm) -{ - char *fileBuf = NULL; - char *fileBuf2 = NULL; - DWORD size, size2; - int count; - - *wipeAlgorithm = TC_WIPE_NONE; - - if (!FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) - return 0; - - if ((fileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), &size)) == NULL) - return 0; - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) - { - if ((fileBuf2 = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), &size2)) != NULL) - *wipeAlgorithm = (WipeAlgorithmId) atoi (fileBuf2); - } - - count = atoi (fileBuf); - - if (fileBuf != NULL) - TCfree (fileBuf); - - if (fileBuf2 != NULL) - TCfree (fileBuf2); - - return (count); -} - - -void RemoveNonSysInPlaceEncNotifications (void) -{ - if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) - remove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC)); - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) - remove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)); - - if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE) - ManageStartupSeqWiz (TRUE, ""); -} - - -void SavePostInstallTasksSettings (int command) -{ - FILE *f = NULL; - - switch (command) - { - case TC_POST_INSTALL_CFG_REMOVE_ALL: - remove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)); - remove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES)); - break; - - case TC_POST_INSTALL_CFG_TUTORIAL: - f = fopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL), "w"); - break; - - case TC_POST_INSTALL_CFG_RELEASE_NOTES: - f = fopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES), "w"); - break; - - default: - return; - } - - if (f == NULL) - return; - - if (fputs ("1", f) < 0) - { - // Error - fclose (f); - return; - } - - TCFlushFile (f); - - fclose (f); -} - - -void DoPostInstallTasks (void) -{ - BOOL bDone = FALSE; - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL))) - { - if (AskYesNo ("AFTER_INSTALL_TUTORIAL") == IDYES) - Applink ("beginnerstutorial", TRUE, ""); - - bDone = TRUE; - } - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES))) - { - if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES") == IDYES) - Applink ("releasenotes", TRUE, ""); - - bDone = TRUE; - } - - if (bDone) - SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL); -} - - -/* InitApp - initialize the application, this function is called once in the - applications WinMain function, but before the main dialog has been created */ -void InitApp (HINSTANCE hInstance, char *lpszCommandLine) -{ - WNDCLASS wc; - OSVERSIONINFO os; - char langId[6]; - - /* Save the instance handle for later */ - hInst = hInstance; - - /* Pull down the windows version */ - os.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - - if (GetVersionEx (&os) == FALSE) - AbortProcess ("NO_OS_VER"); - - CurrentOSMajor = os.dwMajorVersion; - CurrentOSMinor = os.dwMinorVersion; - - if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0) - nCurrentOS = WIN_2000; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1) - nCurrentOS = WIN_XP; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2) - { - OSVERSIONINFOEX osEx; - - osEx.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); - GetVersionEx ((LPOSVERSIONINFOA) &osEx); - - if (osEx.wProductType == VER_NT_SERVER || osEx.wProductType == VER_NT_DOMAIN_CONTROLLER) - nCurrentOS = WIN_SERVER_2003; - else - nCurrentOS = WIN_XP64; - } - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0) - { - OSVERSIONINFOEX osEx; - - osEx.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); - GetVersionEx ((LPOSVERSIONINFOA) &osEx); - - if (osEx.wProductType == VER_NT_SERVER || osEx.wProductType == VER_NT_DOMAIN_CONTROLLER) - nCurrentOS = WIN_SERVER_2008; - else - nCurrentOS = WIN_VISTA; - } - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1) - nCurrentOS = WIN_7; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4) - nCurrentOS = WIN_NT4; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0) - nCurrentOS = WIN_95; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10) - nCurrentOS = WIN_98; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90) - nCurrentOS = WIN_ME; - else if (os.dwPlatformId == VER_PLATFORM_WIN32s) - nCurrentOS = WIN_31; - else - nCurrentOS = WIN_UNKNOWN; - - CoInitialize (NULL); - - langId[0] = 0; - SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId))); - - if (langId[0] == 0) - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), NULL, - (DLGPROC) LanguageDlgProc, (LPARAM) 1); - - LoadLanguageFile (); - -#ifndef SETUP - // UAC elevation moniker cannot be used in traveler mode. - // A new instance of the application must be created with elevated privileges. - if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ()) - { - char modPath[MAX_PATH], newCmdLine[4096]; - WNDCLASSEX wcex; - HWND hWnd; - - if (strstr (lpszCommandLine, "/q UAC ") == lpszCommandLine) - { - Error ("UAC_INIT_ERROR"); - exit (1); - } - - memset (&wcex, 0, sizeof (wcex)); - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.lpfnWndProc = (WNDPROC) NonInstallUacWndProc; - wcex.hInstance = hInstance; - wcex.lpszClassName = "TrueCrypt"; - RegisterClassEx (&wcex); - - // A small transparent window is necessary to bring the new instance to foreground - hWnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_LAYERED, - "TrueCrypt", "TrueCrypt", 0, - GetSystemMetrics (SM_CXSCREEN)/2, - GetSystemMetrics (SM_CYSCREEN)/2, - 1, 1, NULL, NULL, hInstance, NULL); - - SetLayeredWindowAttributes (hWnd, 0, 0, LWA_ALPHA); - ShowWindow (hWnd, SW_SHOWNORMAL); - - GetModuleFileName (NULL, modPath, sizeof (modPath)); - - strcpy (newCmdLine, "/q UAC "); - strcat_s (newCmdLine, sizeof (newCmdLine), lpszCommandLine); - - if ((int)ShellExecute (hWnd, "runas", modPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32) - exit (1); - - Sleep (2000); - exit (0); - } -#endif - - SetUnhandledExceptionFilter (ExceptionHandler); - - RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0; - - // OS version check - if (CurrentOSMajor < 5) - { - MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP); - exit (1); - } - else - { - OSVERSIONINFOEX osEx; - - // Service pack check & warnings about critical MS issues - osEx.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); - if (GetVersionEx ((LPOSVERSIONINFOA) &osEx) != 0) - { - CurrentOSServicePack = osEx.wServicePackMajor; - switch (nCurrentOS) - { - case WIN_2000: - if (osEx.wServicePackMajor < 3) - Warning ("LARGE_IDE_WARNING_2K"); - else - { - DWORD val = 0, size = sizeof(val); - HKEY hkey; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Atapi\\Parameters", 0, KEY_READ, &hkey) == ERROR_SUCCESS - && (RegQueryValueEx (hkey, "EnableBigLba", 0, 0, (LPBYTE) &val, &size) != ERROR_SUCCESS - || val != 1)) - - { - Warning ("LARGE_IDE_WARNING_2K_REGISTRY"); - } - RegCloseKey (hkey); - } - break; - - case WIN_XP: - if (osEx.wServicePackMajor < 1) - { - HKEY k; - // PE environment does not report version of SP - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\minint", 0, KEY_READ, &k) != ERROR_SUCCESS) - Warning ("LARGE_IDE_WARNING_XP"); - else - RegCloseKey (k); - } - break; - } - } - } - - /* Get the attributes for the standard dialog class */ - if ((GetClassInfo (hInst, WINDOWS_DIALOG_CLASS, &wc)) == 0) - { - handleWin32Error (NULL); - AbortProcess ("INIT_REGISTER"); - } - -#ifndef SETUP - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_TRUECRYPT_ICON)); -#else -#include "../setup/resource.h" - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_SETUP)); -#endif - wc.lpszClassName = TC_DLG_CLASS; - wc.lpfnWndProc = &CustomDlgProc; - wc.hCursor = LoadCursor (NULL, IDC_ARROW); - wc.cbWndExtra = DLGWINDOWEXTRA; - - hDlgClass = RegisterClass (&wc); - if (hDlgClass == 0) - { - handleWin32Error (NULL); - AbortProcess ("INIT_REGISTER"); - } - - wc.lpszClassName = TC_SPLASH_CLASS; - wc.lpfnWndProc = &SplashDlgProc; - wc.hCursor = LoadCursor (NULL, IDC_ARROW); - wc.cbWndExtra = DLGWINDOWEXTRA; - - hSplashClass = RegisterClass (&wc); - if (hSplashClass == 0) - { - handleWin32Error (NULL); - AbortProcess ("INIT_REGISTER"); - } - - // Required for RichEdit text fields to work - if (LoadLibrary("Riched20.dll") == NULL) - { - // This error is fatal e.g. because legal notices could not be displayed - handleWin32Error (NULL); - AbortProcess ("INIT_RICHEDIT"); - } - - // DPI and GUI aspect ratio - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_AUXILIARY_DLG), NULL, - (DLGPROC) AuxiliaryDlgProc, (LPARAM) 1); - - InitHelpFileName (); - -#ifndef SETUP - if (!EncryptionThreadPoolStart()) - { - handleWin32Error (NULL); - exit (1); - } -#endif -} - -void InitHelpFileName (void) -{ - char *lpszTmp; - - GetModuleFileName (NULL, szHelpFile, sizeof (szHelpFile)); - lpszTmp = strrchr (szHelpFile, '\\'); - if (lpszTmp) - { - char szTemp[TC_MAX_PATH]; - - // Primary file name - if (strcmp (GetPreferredLangId(), "en") == 0 - || GetPreferredLangId() == NULL) - { - strcpy (++lpszTmp, "TrueCrypt User Guide.pdf"); - } - else - { - sprintf (szTemp, "TrueCrypt User Guide.%s.pdf", GetPreferredLangId()); - strcpy (++lpszTmp, szTemp); - } - - // Secondary file name (used when localized documentation is not found). - GetModuleFileName (NULL, szHelpFile2, sizeof (szHelpFile2)); - lpszTmp = strrchr (szHelpFile2, '\\'); - if (lpszTmp) - { - strcpy (++lpszTmp, "TrueCrypt User Guide.pdf"); - } - } -} - -BOOL OpenDevice (const char *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem) -{ - DWORD dwResult; - BOOL bResult; - - strcpy ((char *) &driver->wszFileName[0], lpszPath); - ToUNICODE ((char *) &driver->wszFileName[0]); - - driver->bDetectTCBootLoader = FALSE; - driver->DetectFilesystem = detectFilesystem; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, - driver, sizeof (OPEN_TEST_STRUCT), - driver, sizeof (OPEN_TEST_STRUCT), - &dwResult, NULL); - - if (bResult == FALSE) - { - dwResult = GetLastError (); - - if (dwResult == ERROR_SHARING_VIOLATION || dwResult == ERROR_NOT_READY) - { - driver->TCBootLoaderDetected = FALSE; - driver->FilesystemDetected = FALSE; - return TRUE; - } - else - return FALSE; - } - - return TRUE; -} - - -// Tells the driver that it's running in traveler mode -void NotifyDriverOfTravelerMode (void) -{ - if (hDriver != INVALID_HANDLE_VALUE) - { - DWORD dwResult; - - DeviceIoControl (hDriver, TC_IOCTL_SET_TRAVELER_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL); - } -} - - -BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize) -{ - DWORD fileSystemFlags; - wchar_t root[] = { L'A' + driveNo, L':', L'\\', 0 }; - - return GetVolumeInformationW (root, label, labelSize / 2, NULL, NULL, &fileSystemFlags, NULL, 0); -} - - -/* Stores the device path of the system partition in SysPartitionDevicePath and the device path of the system drive -in SysDriveDevicePath. -IMPORTANT: As this may take a very long time if called for the first time, it should be called only before performing - a dangerous operation (such as header backup restore or formatting a supposedly non-system device) never - at WM_INITDIALOG or any other GUI events -- instead call IsSystemDevicePath (path, hwndDlg, FALSE) for - very fast preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK - return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the user - selected the system partition/device. -After this function completes successfully, the results are cached for the rest of the session and repeated -executions complete very fast. Returns TRUE if successful (otherwise FALSE). */ -BOOL GetSysDevicePaths (HWND hwndDlg) -{ - if (!bCachedSysDevicePathsValid - || strlen (SysPartitionDevicePath) <= 1 - || strlen (SysDriveDevicePath) <= 1) - { - foreach (const HostDevice &device, GetAvailableHostDevices (false, true)) - { - if (device.ContainsSystem) - strcpy_s (device.IsPartition ? SysPartitionDevicePath : SysDriveDevicePath, TC_MAX_PATH, device.Path.c_str()); - } - - bCachedSysDevicePathsValid = 1; - } - - return (bCachedSysDevicePathsValid - && strlen (SysPartitionDevicePath) > 1 - && strlen (SysDriveDevicePath) > 1); -} - -/* Determines whether the device path is the path of the system partition or of the system drive (or neither). -If bReliableRequired is TRUE, very fast execution is guaranteed, but the results cannot be relied upon. -If it's FALSE and the function is called for the first time, execution may take up to one minute but the -results are reliable. -IMPORTANT: As the execution may take a very long time if called for the first time with bReliableRequired set - to TRUE, it should be called with bReliableRequired set to TRUE only before performing a dangerous - operation (such as header backup restore or formatting a supposedly non-system device) never at - WM_INITDIALOG or any other GUI events (use IsSystemDevicePath(path, hwndDlg, FALSE) for fast - preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK - return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the - user selected the system partition/device). -After this function completes successfully, the results are cached for the rest of the session, bReliableRequired -is ignored (TRUE implied), repeated executions complete very fast, and the results are always reliable. -Return codes: -1 - it is the system partition path (e.g. \Device\Harddisk0\Partition1) -2 - it is the system drive path (e.g. \Device\Harddisk0\Partition0) -0 - it's not the system partition/drive path --1 - the result can't be determined, isn't reliable, or there was an error. */ -int IsSystemDevicePath (char *path, HWND hwndDlg, BOOL bReliableRequired) -{ - if (!bCachedSysDevicePathsValid - && bReliableRequired) - { - if (!GetSysDevicePaths (hwndDlg)) - return -1; - } - - if (strlen (SysPartitionDevicePath) <= 1 || strlen (SysDriveDevicePath) <= 1) - return -1; - - if (strncmp (path, SysPartitionDevicePath, max (strlen(path), strlen(SysPartitionDevicePath))) == 0) - return 1; - else if (strncmp (path, SysDriveDevicePath, max (strlen(path), strlen(SysDriveDevicePath))) == 0) - return 2; - - return 0; -} - -BOOL TextInfoDialogBox (int nID) -{ - return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_INFO_DIALOG_BOX_DLG), MainDlg, (DLGPROC) TextInfoDialogBoxDlgProc, (LPARAM) nID); -} - -BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - static int nID = 0; - - switch (msg) - { - case WM_INITDIALOG: - { - nID = (int) lParam; - - // Left margin for rich edit text field - SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); - - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_HIDE); - - switch (nID) - { - case TC_TBXID_LEGAL_NOTICES: - LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); - break; - - case TC_TBXID_SYS_ENCRYPTION_PRETEST: - LocalizeDialog (hwndDlg, NULL); - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); - break; - - case TC_TBXID_SYS_ENC_RESCUE_DISK: - LocalizeDialog (hwndDlg, NULL); - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); - break; - - case TC_TBXID_DECOY_OS_INSTRUCTIONS: - LocalizeDialog (hwndDlg, NULL); - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); - break; - } - - SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); - } - return 0; - - case WM_COMMAND: - if (lw == IDOK || lw == IDCANCEL) - { - NormalCursor (); - EndDialog (hwndDlg, 0); - return 1; - } - - if (lw == IDC_PRINT) - { - switch (nID) - { - case TC_TBXID_SYS_ENCRYPTION_PRETEST: - PrintHardCopyTextUTF16 (GetString ("SYS_ENCRYPTION_PRETEST_INFO2"), "Pre-Boot Troubleshooting", wcslen (GetString ("SYS_ENCRYPTION_PRETEST_INFO2")) * 2); - break; - - case TC_TBXID_SYS_ENC_RESCUE_DISK: - PrintHardCopyTextUTF16 (GetString ("RESCUE_DISK_HELP"), "TrueCrypt Rescue Disk Help", wcslen (GetString ("RESCUE_DISK_HELP")) * 2); - break; - - case TC_TBXID_DECOY_OS_INSTRUCTIONS: - PrintHardCopyTextUTF16 (GetString ("DECOY_OS_INSTRUCTIONS"), "How to Create Decoy OS", wcslen (GetString ("DECOY_OS_INSTRUCTIONS")) * 2); - break; - } - return 1; - } - - return 0; - - case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: - { - char *r = NULL; - - switch (nID) - { - case TC_TBXID_LEGAL_NOTICES: - LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); - r = GetLegalNotices (); - if (r != NULL) - { - SetWindowText (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), r); - free (r); - } - break; - - case TC_TBXID_SYS_ENCRYPTION_PRETEST: - LocalizeDialog (hwndDlg, NULL); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("SYS_ENCRYPTION_PRETEST_INFO2")); - break; - - case TC_TBXID_SYS_ENC_RESCUE_DISK: - LocalizeDialog (hwndDlg, NULL); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("RESCUE_DISK_HELP")); - break; - - case TC_TBXID_DECOY_OS_INSTRUCTIONS: - LocalizeDialog (hwndDlg, NULL); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("DECOY_OS_INSTRUCTIONS")); - break; - } - } - return 1; - - case WM_CLOSE: - NormalCursor (); - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - - -char * GetLegalNotices () -{ - static char *resource; - static DWORD size; - char *buf = NULL; - - if (resource == NULL) - resource = (char *) MapResource ("Text", IDR_LICENSE, &size); - - if (resource != NULL) - { - buf = (char *) malloc (size + 1); - if (buf != NULL) - { - memcpy (buf, resource, size); - buf[size] = 0; - } - } - - return buf; -} - - -BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static char *lpszFileName; // This is actually a pointer to a GLOBAL array - static vector devices; - static map itemToDeviceMap; - - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - LVCOLUMNW LvCol; - HWND hList = GetDlgItem (hwndDlg, IDC_DEVICELIST); - - LocalizeDialog (hwndDlg, "IDD_RAWDEVICES_DLG"); - - SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP - ); - - memset (&LvCol,0,sizeof(LvCol)); - LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - LvCol.pszText = GetString ("DEVICE"); - LvCol.cx = CompensateXDPI (186); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("DRIVE"); - LvCol.cx = CompensateXDPI (38); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("SIZE"); - LvCol.cx = CompensateXDPI (64); - LvCol.fmt = LVCFMT_RIGHT; - SendMessage (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("VOLUME_LABEL"); - LvCol.cx = CompensateXDPI (128); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); - - devices.clear(); - itemToDeviceMap.clear(); - - WaitCursor(); - devices = GetAvailableHostDevices (false, true, false); - NormalCursor(); - - if (devices.empty()) - { - MessageBoxW (hwndDlg, GetString ("RAWDEVICES"), lpszTitle, ICON_HAND); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - int line = 1; - LVITEM item; - memset (&item, 0, sizeof (item)); - item.mask = LVIF_TEXT; - - foreach (const HostDevice &device, devices) - { - item.iSubItem = 1; - - if (device.ContainsSystem) - { - if (device.IsPartition) - strcpy_s (SysPartitionDevicePath, sizeof (SysPartitionDevicePath), device.Path.c_str()); - else - strcpy_s (SysDriveDevicePath, sizeof (SysDriveDevicePath), device.Path.c_str()); - } - - // Path - if (!device.IsPartition || device.DynamicVolume) - { - if (!device.Floppy && device.Size == 0) - continue; - - if (line > 1) - { - ListItemAdd (hList, item.iItem, ""); - item.iItem = line++; - } - - if (device.Floppy || device.DynamicVolume) - { - ListItemAdd (hList, item.iItem, (char *) device.Path.c_str()); - } - else - { - wchar_t s[1024]; - if (device.Removable) - wsprintfW (s, L"%s %d", GetString ("REMOVABLE_DISK"), device.SystemNumber); - else - wsprintfW (s, L"%s %d", GetString ("HARDDISK"), device.SystemNumber); - - if (!device.Partitions.empty()) - wcscat (s, L":"); - - ListItemAddW (hList, item.iItem, s); - } - } - else - { - ListItemAdd (hList, item.iItem, (char *) device.Path.c_str()); - } - - itemToDeviceMap[item.iItem] = device; - - // Size - if (device.Size != 0) - { - wchar_t size[100] = { 0 }; - GetSizeString (device.Size, size); - ListSubItemSetW (hList, item.iItem, 2, size); - } - - // Mount point - if (!device.MountPoint.empty()) - ListSubItemSet (hList, item.iItem, 1, (char *) device.MountPoint.c_str()); - - // Label - if (!device.Name.empty()) - ListSubItemSetW (hList, item.iItem, 3, (wchar_t *) device.Name.c_str()); - - item.iItem = line++; - } - - lpszFileName = (char *) lParam; - -#ifdef VOLFORMAT - EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); -#endif - return 1; - } - - case WM_COMMAND: - case WM_NOTIFY: - // catch non-device line selected - if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED )) - { - LVITEM LvItem; - memset(&LvItem,0,sizeof(LvItem)); - LvItem.mask = LVIF_TEXT | LVIF_PARAM; - LvItem.iItem = ((LPNMLISTVIEW) lParam)->iItem; - LvItem.pszText = lpszFileName; - LvItem.cchTextMax = TC_MAX_PATH; - - SendMessage (GetDlgItem (hwndDlg, IDC_DEVICELIST), LVM_GETITEM, LvItem.iItem, (LPARAM) &LvItem); - EnableWindow (GetDlgItem ((HWND) hwndDlg, IDOK), lpszFileName[0] != 0 && lpszFileName[0] != ' '); - - return 1; - } - - if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) - { - int selectedItem = ListView_GetSelectionMark (GetDlgItem (hwndDlg, IDC_DEVICELIST)); - - if (selectedItem == -1 || itemToDeviceMap.find (selectedItem) == itemToDeviceMap.end()) - return 1; // non-device line selected - - const HostDevice selectedDevice = itemToDeviceMap[selectedItem]; - strcpy_s (lpszFileName, TC_MAX_PATH, selectedDevice.Path.c_str()); - -#ifdef VOLFORMAT - if (selectedDevice.ContainsSystem && selectedDevice.IsPartition) - { - if (WizardMode != WIZARD_MODE_SYS_DEVICE) - { - if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE") == IDNO) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - bSysPartitionSelected = TRUE; - bSysDriveSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - - NormalCursor (); - EndDialog (hwndDlg, IDOK); - return 1; - } - else - { - // This should never be the case because the Select Device dialog is not available in this wizard mode - bSysPartitionSelected = TRUE; - bSysDriveSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - } - - if (!(selectedDevice.ContainsSystem && !selectedDevice.IsPartition)) - { - if (bWarnDeviceFormatAdvanced - && !bHiddenVolDirect - && AskWarnNoYes("FORMAT_DEVICE_FOR_ADVANCED_ONLY") == IDNO) - { - if (AskNoYes("CONFIRM_CHANGE_WIZARD_MODE_TO_FILE_CONTAINER") == IDYES) - { - SwitchWizardToFileContainerMode (); - } - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - if (!bHiddenVolDirect) - bWarnDeviceFormatAdvanced = FALSE; - } - -#else // #ifdef VOLFORMAT - - bSysPartitionSelected = (selectedDevice.ContainsSystem && selectedDevice.IsPartition); - bSysDriveSelected = FALSE; - -#endif // #ifdef VOLFORMAT - - if (!selectedDevice.IsPartition && !selectedDevice.Floppy) - { - // Whole device selected - -#ifdef VOLFORMAT - if (selectedDevice.ContainsSystem && !selectedDevice.IsPartition) - { - if (WizardMode != WIZARD_MODE_SYS_DEVICE) - { - if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE") == IDNO) - { - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - bSysDriveSelected = TRUE; - bSysPartitionSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - - NormalCursor (); - EndDialog (hwndDlg, IDOK); - return 1; - } - else - { - // This should never be the case because the Select Device dialog is not available in this wizard mode - bSysDriveSelected = TRUE; - bSysPartitionSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - } - - // Disallow format if the device contains partitions, but not if the partition is virtual or system - if (!selectedDevice.IsVirtualPartition - && !bHiddenVolDirect) - { - if (!selectedDevice.Partitions.empty()) - { - EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); - Error ("DEVICE_PARTITIONS_ERR_W_INPLACE_ENC_NOTE"); - return 1; - } - - if (AskWarnNoYes ("WHOLE_NONSYS_DEVICE_ENC_CONFIRM") == IDNO) - return 1; - } -#else // #ifdef VOLFORMAT - - bSysDriveSelected = (selectedDevice.ContainsSystem && !selectedDevice.IsPartition); - bSysPartitionSelected = FALSE; - -#endif // #ifdef VOLFORMAT - } - else - bSysDriveSelected = FALSE; - -#ifdef VOLFORMAT - bRemovableHostDevice = selectedDevice.Removable; -#endif - NormalCursor (); - EndDialog (hwndDlg, IDOK); - return 1; - } - - if (lw == IDCANCEL) - { - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - return 0; - } - return 0; -} - - -BOOL DoDriverInstall (HWND hwndDlg) -{ -#ifdef SETUP - if (SystemEncryptionUpgrade) - return TRUE; -#endif - - SC_HANDLE hManager, hService = NULL; - BOOL bOK = FALSE, bRet; - - hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hManager == NULL) - goto error; - -#ifdef SETUP - StatusMessage (hwndDlg, "INSTALLING_DRIVER"); -#endif - - hService = CreateService (hManager, "truecrypt", "truecrypt", - SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL, - !Is64BitOs () ? "System32\\drivers\\truecrypt.sys" : "SysWOW64\\drivers\\truecrypt.sys", - NULL, NULL, NULL, NULL, NULL); - - if (hService == NULL) - goto error; - else - CloseServiceHandle (hService); - - hService = OpenService (hManager, "truecrypt", SERVICE_ALL_ACCESS); - if (hService == NULL) - goto error; - -#ifdef SETUP - StatusMessage (hwndDlg, "STARTING_DRIVER"); -#endif - - bRet = StartService (hService, 0, NULL); - if (bRet == FALSE) - goto error; - - bOK = TRUE; - -error: - if (bOK == FALSE && GetLastError () != ERROR_SERVICE_ALREADY_RUNNING) - { - handleWin32Error (hwndDlg); - MessageBoxW (hwndDlg, GetString ("DRIVER_INSTALL_FAILED"), lpszTitle, MB_ICONHAND); - } - else - bOK = TRUE; - - if (hService != NULL) - CloseServiceHandle (hService); - - if (hManager != NULL) - CloseServiceHandle (hManager); - - return bOK; -} - - -// Install and start driver service and mark it for removal (non-install mode) -static int DriverLoad () -{ - HANDLE file; - WIN32_FIND_DATA find; - SC_HANDLE hManager, hService = NULL; - char driverPath[TC_MAX_PATH*2]; - BOOL res; - char *tmp; - - GetModuleFileName (NULL, driverPath, sizeof (driverPath)); - tmp = strrchr (driverPath, '\\'); - if (!tmp) - { - strcpy (driverPath, "."); - tmp = driverPath + 1; - } - - strcpy (tmp, !Is64BitOs () ? "\\truecrypt.sys" : "\\truecrypt-x64.sys"); - - file = FindFirstFile (driverPath, &find); - - if (file == INVALID_HANDLE_VALUE) - { - MessageBoxW (0, GetString ("DRIVER_NOT_FOUND"), lpszTitle, ICON_HAND); - return ERR_DONT_REPORT; - } - - FindClose (file); - - hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hManager == NULL) - { - if (GetLastError () == ERROR_ACCESS_DENIED) - { - MessageBoxW (0, GetString ("ADMIN_PRIVILEGES_DRIVER"), lpszTitle, ICON_HAND); - return ERR_DONT_REPORT; - } - - return ERR_OS_ERROR; - } - - hService = OpenService (hManager, "truecrypt", SERVICE_ALL_ACCESS); - if (hService != NULL) - { - // Remove stale service (driver is not loaded but service exists) - DeleteService (hService); - CloseServiceHandle (hService); - Sleep (500); - } - - hService = CreateService (hManager, "truecrypt", "truecrypt", - SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, - driverPath, NULL, NULL, NULL, NULL, NULL); - - if (hService == NULL) - { - CloseServiceHandle (hManager); - return ERR_OS_ERROR; - } - - res = StartService (hService, 0, NULL); - DeleteService (hService); - - CloseServiceHandle (hManager); - CloseServiceHandle (hService); - - return !res ? ERR_OS_ERROR : ERROR_SUCCESS; -} - - -BOOL DriverUnload () -{ - MOUNT_LIST_STRUCT driver; - int refCount; - int volumesMounted; - DWORD dwResult; - BOOL bResult; - - SC_HANDLE hManager, hService = NULL; - BOOL bRet; - SERVICE_STATUS status; - int x; - - if (hDriver == INVALID_HANDLE_VALUE) - return TRUE; - - try - { - if (BootEncryption (NULL).GetStatus().DeviceFilterActive) - return FALSE; - } - catch (...) { } - - // Test for mounted volumes - bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL); - - if (!bResult) - { - bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL); - if (bResult) - volumesMounted = driver.ulMountedDrives; - } - - if (bResult) - { - if (volumesMounted != 0) - return FALSE; - } - else - return TRUE; - - // Test for any applications attached to driver - refCount = GetDriverRefCount (); - - if (refCount > 1) - return FALSE; - - CloseHandle (hDriver); - hDriver = INVALID_HANDLE_VALUE; - - // Stop driver service - - hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hManager == NULL) - goto error; - - hService = OpenService (hManager, "truecrypt", SERVICE_ALL_ACCESS); - if (hService == NULL) - goto error; - - bRet = QueryServiceStatus (hService, &status); - if (bRet != TRUE) - goto error; - - if (status.dwCurrentState != SERVICE_STOPPED) - { - ControlService (hService, SERVICE_CONTROL_STOP, &status); - - for (x = 0; x < 5; x++) - { - bRet = QueryServiceStatus (hService, &status); - if (bRet != TRUE) - goto error; - - if (status.dwCurrentState == SERVICE_STOPPED) - break; - - Sleep (200); - } - } - -error: - if (hService != NULL) - CloseServiceHandle (hService); - - if (hManager != NULL) - CloseServiceHandle (hManager); - - if (status.dwCurrentState == SERVICE_STOPPED) - { - hDriver = INVALID_HANDLE_VALUE; - return TRUE; - } - - return FALSE; -} - - -int DriverAttach (void) -{ - /* Try to open a handle to the device driver. It will be closed later. */ - -#ifndef SETUP - - int nLoadRetryCount = 0; -start: - -#endif - - hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - - if (hDriver == INVALID_HANDLE_VALUE) - { -#ifndef SETUP - - LoadSysEncSettings (NULL); - - if (!CreateDriverSetupMutex ()) - { - // Another instance is already attempting to install, register or start the driver - - while (!CreateDriverSetupMutex ()) - { - Sleep (100); // Wait until the other instance finishes - } - - // Try to open a handle to the driver again (keep the mutex in case the other instance failed) - goto start; - } - else - { - // No other instance is currently attempting to install, register or start the driver - - if (SystemEncryptionStatus != SYSENC_STATUS_NONE) - { - // This is an inconsistent state. The config file indicates system encryption should be - // active, but the driver is not running. This may happen e.g. when the pretest fails and - // the user selects "Last Known Good Configuration" from the Windows boot menu. - // To fix this, we're going to reinstall the driver, start it, and register it for boot. - - if (DoDriverInstall (NULL)) - { - Sleep (1000); - hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - - try - { - BootEncryption bootEnc (NULL); - bootEnc.RegisterBootDriver (bootEnc.GetHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE ? true : false); - } - catch (Exception &e) - { - e.Show (NULL); - } - } - - CloseDriverSetupMutex (); - } - else - { - // Attempt to load the driver (non-install/traveler mode) -load: - BOOL res = DriverLoad (); - - CloseDriverSetupMutex (); - - if (res != ERROR_SUCCESS) - return res; - - bTravelerModeConfirmed = TRUE; - - hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - } - - if (bTravelerModeConfirmed) - NotifyDriverOfTravelerMode (); - } - -#endif // #ifndef SETUP - - if (hDriver == INVALID_HANDLE_VALUE) - return ERR_OS_ERROR; - } - - CloseDriverSetupMutex (); - - if (hDriver != INVALID_HANDLE_VALUE) - { - DWORD dwResult; - - BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); - - if (!bResult) - bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); - -#ifndef SETUP // Don't check version during setup to allow removal of another version - if (bResult == FALSE) - { - return ERR_OS_ERROR; - } - else if (DriverVersion != VERSION_NUM) - { - // Unload an incompatbile version of the driver loaded in non-install mode and load the required version - if (IsNonInstallMode () && CreateDriverSetupMutex () && DriverUnload () && nLoadRetryCount++ < 3) - goto load; - - CloseDriverSetupMutex (); - CloseHandle (hDriver); - hDriver = INVALID_HANDLE_VALUE; - return ERR_DRIVER_VERSION; - } -#else - if (!bResult) - DriverVersion = 0; -#endif - } - - return 0; -} - - -void ResetCurrentDirectory () -{ - char p[MAX_PATH]; - if (!IsNonInstallMode () && SHGetFolderPath (NULL, CSIDL_PROFILE, NULL, 0, p) == ERROR_SUCCESS) - { - SetCurrentDirectory (p); - } - else - { - GetModPath (p, sizeof (p)); - SetCurrentDirectory (p); - } -} - - -BOOL BrowseFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter) -{ - return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter); -} - - -BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, char *initialDir, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter) -{ - OPENFILENAMEW ofn; - wchar_t file[TC_MAX_PATH] = { 0 }; - wchar_t wInitialDir[TC_MAX_PATH] = { 0 }; - wchar_t filter[1024]; - BOOL status = FALSE; - - CoInitialize (NULL); - - ZeroMemory (&ofn, sizeof (ofn)); - *lpszFileName = 0; - - if (initialDir) - { - swprintf_s (wInitialDir, sizeof (wInitialDir) / 2, L"%hs", initialDir); - ofn.lpstrInitialDir = wInitialDir; - } - - ofn.lStructSize = sizeof (ofn); - ofn.hwndOwner = hwndDlg; - - wsprintfW (filter, L"%ls (*.*)%c*.*%c%ls (*.tc)%c*.tc%c%c", - GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); - ofn.lpstrFilter = browseFilter ? browseFilter : filter; - ofn.nFilterIndex = 1; - ofn.lpstrFile = file; - ofn.nMaxFile = sizeof (file) / sizeof (file[0]); - ofn.lpstrTitle = GetString (stringId); - ofn.Flags = OFN_HIDEREADONLY - | OFN_PATHMUSTEXIST - | (keepHistory ? 0 : OFN_DONTADDTORECENT) - | (saveMode ? OFN_OVERWRITEPROMPT : 0); - - if (!keepHistory) - CleanLastVisitedMRU (); - - if (!saveMode) - { - if (!GetOpenFileNameW (&ofn)) - goto ret; - } - else - { - if (!GetSaveFileNameW (&ofn)) - goto ret; - } - - WideCharToMultiByte (CP_ACP, 0, file, -1, lpszFileName, MAX_PATH, NULL, NULL); - - if (!keepHistory) - CleanLastVisitedMRU (); - - ResetCurrentDirectory (); - status = TRUE; - -ret: - CoUninitialize(); - return status; -} - - -static char SelectMultipleFilesPath[131072]; -static int SelectMultipleFilesOffset; - -BOOL SelectMultipleFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory) -{ - OPENFILENAMEW ofn; - wchar_t file[0xffff * 2] = { 0 }; // The size must not exceed 0xffff*2 due to a bug in Windows 2000 and XP SP1 - wchar_t filter[1024]; - BOOL status = FALSE; - - CoInitialize (NULL); - - ZeroMemory (&ofn, sizeof (ofn)); - - *lpszFileName = 0; - ofn.lStructSize = sizeof (ofn); - ofn.hwndOwner = hwndDlg; - wsprintfW (filter, L"%ls (*.*)%c*.*%c%ls (*.tc)%c*.tc%c%c", - GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); - ofn.lpstrFilter = filter; - ofn.nFilterIndex = 1; - ofn.lpstrFile = file; - ofn.nMaxFile = sizeof (file) / sizeof (file[0]); - ofn.lpstrTitle = GetString (stringId); - ofn.Flags = OFN_HIDEREADONLY - | OFN_EXPLORER - | OFN_PATHMUSTEXIST - | OFN_ALLOWMULTISELECT - | (keepHistory ? 0 : OFN_DONTADDTORECENT); - - if (!keepHistory) - CleanLastVisitedMRU (); - - if (!GetOpenFileNameW (&ofn)) - goto ret; - - if (file[ofn.nFileOffset - 1] != 0) - { - // Single file selected - WideCharToMultiByte (CP_ACP, 0, file, -1, lpszFileName, MAX_PATH, NULL, NULL); - SelectMultipleFilesOffset = 0; - } - else - { - // Multiple files selected - int n; - wchar_t *f = file; - char *s = SelectMultipleFilesPath; - while ((n = WideCharToMultiByte (CP_ACP, 0, f, -1, s, MAX_PATH, NULL, NULL)) > 1) - { - f += n; - s += n; - } - - SelectMultipleFilesOffset = ofn.nFileOffset; - SelectMultipleFilesNext (lpszFileName); - } - - if (!keepHistory) - CleanLastVisitedMRU (); - - ResetCurrentDirectory (); - status = TRUE; - -ret: - CoUninitialize(); - return status; -} - - -BOOL SelectMultipleFilesNext (char *lpszFileName) -{ - if (SelectMultipleFilesOffset == 0) - return FALSE; - - strncpy (lpszFileName, SelectMultipleFilesPath, TC_MAX_PATH); - lpszFileName[TC_MAX_PATH - 1] = 0; - - if (lpszFileName[strlen (lpszFileName) - 1] != '\\') - strcat (lpszFileName, "\\"); - - strcat (lpszFileName, SelectMultipleFilesPath + SelectMultipleFilesOffset); - - SelectMultipleFilesOffset += strlen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1; - if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0) - SelectMultipleFilesOffset = 0; - - return TRUE; -} - - -static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) -{ - switch(uMsg) { - case BFFM_INITIALIZED: - { - /* WParam is TRUE since we are passing a path. - It would be FALSE if we were passing a pidl. */ - SendMessage (hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData); - break; - } - - case BFFM_SELCHANGED: - { - char szDir[TC_MAX_PATH]; - - /* Set the status window to the currently selected path. */ - if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) - { - SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir); - } - break; - } - - default: - break; - } - - return 0; -} - - -BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, char *dirName) -{ - BROWSEINFOW bi; - LPITEMIDLIST pidl; - LPMALLOC pMalloc; - BOOL bOK = FALSE; - - CoInitialize (NULL); - - if (SUCCEEDED (SHGetMalloc (&pMalloc))) - { - ZeroMemory (&bi, sizeof(bi)); - bi.hwndOwner = hwndDlg; - bi.pszDisplayName = 0; - bi.lpszTitle = GetString (lpszTitle); - bi.pidlRoot = 0; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM)dirName; - - pidl = SHBrowseForFolderW (&bi); - if (pidl != NULL) - { - if (SHGetPathFromIDList(pidl, dirName)) - { - bOK = TRUE; - } - - pMalloc->Free (pidl); - pMalloc->Release(); - } - } - - CoUninitialize(); - - return bOK; -} - - -std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) -{ - WCHAR szTmp[8192]; - - swprintf (szTmp, GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG")); - if (CheckCapsLock (hwndDlg, TRUE)) - wcscat (szTmp, GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); - -#ifdef TCMOUNT - if (TCBootLoaderOnInactiveSysEncDrive ()) - { - swprintf (szTmp, GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_OR_MODE_WRONG" : "PASSWORD_OR_MODE_WRONG")); - - if (CheckCapsLock (hwndDlg, TRUE)) - wcscat (szTmp, GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); - - wcscat (szTmp, GetString ("SYSENC_MOUNT_WITHOUT_PBA_NOTE")); - } -#endif - - return szTmp; -} - - -void handleError (HWND hwndDlg, int code) -{ - WCHAR szTmp[4096]; - - if (Silent) return; - - switch (code) - { - case ERR_OS_ERROR: - handleWin32Error (hwndDlg); - break; - case ERR_OUTOFMEMORY: - MessageBoxW (hwndDlg, GetString ("OUTOFMEMORY"), lpszTitle, ICON_HAND); - break; - - case ERR_PASSWORD_WRONG: - MessageBoxW (hwndDlg, GetWrongPasswordErrorMessage (hwndDlg).c_str(), lpszTitle, MB_ICONWARNING); - break; - - case ERR_DRIVE_NOT_FOUND: - MessageBoxW (hwndDlg, GetString ("NOT_FOUND"), lpszTitle, ICON_HAND); - break; - case ERR_FILES_OPEN: - MessageBoxW (hwndDlg, GetString ("OPENFILES_DRIVER"), lpszTitle, ICON_HAND); - break; - case ERR_FILES_OPEN_LOCK: - MessageBoxW (hwndDlg, GetString ("OPENFILES_LOCK"), lpszTitle, ICON_HAND); - break; - case ERR_VOL_SIZE_WRONG: - MessageBoxW (hwndDlg, GetString ("VOL_SIZE_WRONG"), lpszTitle, ICON_HAND); - break; - case ERR_COMPRESSION_NOT_SUPPORTED: - MessageBoxW (hwndDlg, GetString ("COMPRESSION_NOT_SUPPORTED"), lpszTitle, ICON_HAND); - break; - case ERR_PASSWORD_CHANGE_VOL_TYPE: - MessageBoxW (hwndDlg, GetString ("WRONG_VOL_TYPE"), lpszTitle, ICON_HAND); - break; - case ERR_VOL_SEEKING: - MessageBoxW (hwndDlg, GetString ("VOL_SEEKING"), lpszTitle, ICON_HAND); - break; - case ERR_CIPHER_INIT_FAILURE: - MessageBoxW (hwndDlg, GetString ("ERR_CIPHER_INIT_FAILURE"), lpszTitle, ICON_HAND); - break; - case ERR_CIPHER_INIT_WEAK_KEY: - MessageBoxW (hwndDlg, GetString ("ERR_CIPHER_INIT_WEAK_KEY"), lpszTitle, ICON_HAND); - break; - case ERR_VOL_ALREADY_MOUNTED: - MessageBoxW (hwndDlg, GetString ("VOL_ALREADY_MOUNTED"), lpszTitle, ICON_HAND); - break; - case ERR_FILE_OPEN_FAILED: - MessageBoxW (hwndDlg, GetString ("FILE_OPEN_FAILED"), lpszTitle, ICON_HAND); - break; - case ERR_VOL_MOUNT_FAILED: - MessageBoxW (hwndDlg, GetString ("VOL_MOUNT_FAILED"), lpszTitle, ICON_HAND); - break; - case ERR_NO_FREE_DRIVES: - MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND); - break; - case ERR_ACCESS_DENIED: - MessageBoxW (hwndDlg, GetString ("ACCESS_DENIED"), lpszTitle, ICON_HAND); - break; - - case ERR_DRIVER_VERSION: - wsprintfW (szTmp, GetString ("DRIVER_VERSION"), VERSION_STRING); - MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND); - break; - - case ERR_NEW_VERSION_REQUIRED: - MessageBoxW (hwndDlg, GetString ("NEW_VERSION_REQUIRED"), lpszTitle, ICON_HAND); - break; - - case ERR_SELF_TESTS_FAILED: - Error ("ERR_SELF_TESTS_FAILED"); - break; - - case ERR_VOL_FORMAT_BAD: - Error ("ERR_VOL_FORMAT_BAD"); - break; - - case ERR_ENCRYPTION_NOT_COMPLETED: - Error ("ERR_ENCRYPTION_NOT_COMPLETED"); - break; - - case ERR_NONSYS_INPLACE_ENC_INCOMPLETE: - Error ("ERR_NONSYS_INPLACE_ENC_INCOMPLETE"); - break; - - case ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG: - Error ("ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG"); - break; - - case ERR_PARAMETER_INCORRECT: - Error ("ERR_PARAMETER_INCORRECT"); - break; - - case ERR_USER_ABORT: - case ERR_DONT_REPORT: - // A non-error - break; - - default: - wsprintfW (szTmp, GetString ("ERR_UNKNOWN"), code); - MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND); - } -} - -static BOOL CALLBACK LocalizeDialogEnum( HWND hwnd, LPARAM font) -{ - // Localization of controls - - if (LocalizationActive) - { - int ctrlId = GetDlgCtrlID (hwnd); - if (ctrlId != 0) - { - char name[10] = { 0 }; - GetClassName (hwnd, name, sizeof (name)); - - if (_stricmp (name, "Button") == 0 || _stricmp (name, "Static") == 0) - { - wchar_t *str = (wchar_t *) GetDictionaryValueByInt (ctrlId); - if (str != NULL) - SetWindowTextW (hwnd, str); - } - } - } - - // Font - SendMessage (hwnd, WM_SETFONT, (WPARAM) font, 0); - - return TRUE; -} - -void LocalizeDialog (HWND hwnd, char *stringId) -{ - LastDialogId = stringId; - SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) 'TRUE'); - SendMessage (hwnd, WM_SETFONT, (WPARAM) hUserFont, 0); - - if (stringId == NULL) - SetWindowText (hwnd, "TrueCrypt"); - else - SetWindowTextW (hwnd, GetString (stringId)); - - if (hUserFont != 0) - EnumChildWindows (hwnd, LocalizeDialogEnum, (LPARAM) hUserFont); -} - -void OpenVolumeExplorerWindow (int driveNo) -{ - char dosName[5]; - SHFILEINFO fInfo; - - sprintf (dosName, "%c:\\", (char) driveNo + 'A'); - - // Force explorer to discover the drive - SHGetFileInfo (dosName, 0, &fInfo, sizeof (fInfo), 0); - - ShellExecute (NULL, "open", dosName, NULL, NULL, SW_SHOWNORMAL); -} - -static BOOL explorerCloseSent; -static HWND explorerTopLevelWindow; - -static BOOL CALLBACK CloseVolumeExplorerWindowsChildEnum (HWND hwnd, LPARAM driveStr) -{ - char s[MAX_PATH]; - SendMessage (hwnd, WM_GETTEXT, sizeof (s), (LPARAM) s); - - if (strstr (s, (char *) driveStr) != NULL) - { - PostMessage (explorerTopLevelWindow, WM_CLOSE, 0, 0); - explorerCloseSent = TRUE; - return FALSE; - } - - return TRUE; -} - -static BOOL CALLBACK CloseVolumeExplorerWindowsEnum (HWND hwnd, LPARAM driveNo) -{ - char driveStr[10]; - char s[MAX_PATH]; - - sprintf (driveStr, "%c:\\", driveNo + 'A'); - - GetClassName (hwnd, s, sizeof s); - if (strcmp (s, "CabinetWClass") == 0) - { - GetWindowText (hwnd, s, sizeof s); - if (strstr (s, driveStr) != NULL) - { - PostMessage (hwnd, WM_CLOSE, 0, 0); - explorerCloseSent = TRUE; - return TRUE; - } - - explorerTopLevelWindow = hwnd; - EnumChildWindows (hwnd, CloseVolumeExplorerWindowsChildEnum, (LPARAM) driveStr); - } - - return TRUE; -} - -BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo) -{ - if (driveNo >= 0) - { - explorerCloseSent = FALSE; - EnumWindows (CloseVolumeExplorerWindowsEnum, (LPARAM) driveNo); - } - - return explorerCloseSent; -} - -void GetSizeString (unsigned __int64 size, wchar_t *str) -{ - static wchar_t *b, *kb, *mb, *gb, *tb, *pb; - static int serNo; - - if (b == NULL || serNo != LocalizationSerialNo) - { - serNo = LocalizationSerialNo; - kb = GetString ("KB"); - mb = GetString ("MB"); - gb = GetString ("GB"); - tb = GetString ("TB"); - pb = GetString ("PB"); - b = GetString ("BYTE"); - } - - if (size > 1024I64*1024*1024*1024*1024*99) - swprintf (str, L"%I64d %s", size/1024/1024/1024/1024/1024, pb); - else if (size > 1024I64*1024*1024*1024*1024) - swprintf (str, L"%.1f %s",(double)(size/1024.0/1024/1024/1024/1024), pb); - else if (size > 1024I64*1024*1024*1024*99) - swprintf (str, L"%I64d %s",size/1024/1024/1024/1024, tb); - else if (size > 1024I64*1024*1024*1024) - swprintf (str, L"%.1f %s",(double)(size/1024.0/1024/1024/1024), tb); - else if (size > 1024I64*1024*1024*99) - swprintf (str, L"%I64d %s",size/1024/1024/1024, gb); - else if (size > 1024I64*1024*1024) - swprintf (str, L"%.1f %s",(double)(size/1024.0/1024/1024), gb); - else if (size > 1024I64*1024*99) - swprintf (str, L"%I64d %s", size/1024/1024, mb); - else if (size > 1024I64*1024) - swprintf (str, L"%.1f %s",(double)(size/1024.0/1024), mb); - else if (size >= 1024I64) - swprintf (str, L"%I64d %s", size/1024, kb); - else - swprintf (str, L"%I64d %s", size, b); -} - -#ifndef SETUP -void GetSpeedString (unsigned __int64 speed, wchar_t *str) -{ - static wchar_t *b, *kb, *mb, *gb, *tb, *pb; - static int serNo; - - if (b == NULL || serNo != LocalizationSerialNo) - { - serNo = LocalizationSerialNo; - kb = GetString ("KB_PER_SEC"); - mb = GetString ("MB_PER_SEC"); - gb = GetString ("GB_PER_SEC"); - tb = GetString ("TB_PER_SEC"); - pb = GetString ("PB_PER_SEC"); - b = GetString ("B_PER_SEC"); - } - - if (speed > 1024I64*1024*1024*1024*1024*99) - swprintf (str, L"%I64d %s", speed/1024/1024/1024/1024/1024, pb); - else if (speed > 1024I64*1024*1024*1024*1024) - swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024/1024), pb); - else if (speed > 1024I64*1024*1024*1024*99) - swprintf (str, L"%I64d %s",speed/1024/1024/1024/1024, tb); - else if (speed > 1024I64*1024*1024*1024) - swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024), tb); - else if (speed > 1024I64*1024*1024*99) - swprintf (str, L"%I64d %s",speed/1024/1024/1024, gb); - else if (speed > 1024I64*1024*1024) - swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024/1024), gb); - else if (speed > 1024I64*1024*99) - swprintf (str, L"%I64d %s", speed/1024/1024, mb); - else if (speed > 1024I64*1024) - swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024), mb); - else if (speed > 1024I64) - swprintf (str, L"%I64d %s", speed/1024, kb); - else - swprintf (str, L"%I64d %s", speed, b); -} - -static void DisplayBenchmarkResults (HWND hwndDlg) -{ - wchar_t item1[100]={0}; - LVITEMW LvItem; - HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); - int ea, i; - BOOL unsorted = TRUE; - BENCHMARK_REC tmp_line; - - /* Sort the list */ - - switch (benchmarkSortMethod) - { - case BENCHMARK_SORT_BY_SPEED: - - while (unsorted) - { - unsorted = FALSE; - for (i = 0; i < benchmarkTotalItems - 1; i++) - { - if (benchmarkTable[i].meanBytesPerSec < benchmarkTable[i+1].meanBytesPerSec) - { - unsorted = TRUE; - memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); - } - } - } - break; - - case BENCHMARK_SORT_BY_NAME: - - while (unsorted) - { - unsorted = FALSE; - for (i = 0; i < benchmarkTotalItems - 1; i++) - { - if (benchmarkTable[i].id > benchmarkTable[i+1].id) - { - unsorted = TRUE; - memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); - } - } - } - break; - } - - /* Render the results */ - - SendMessage (hList,LVM_DELETEALLITEMS,0,(LPARAM)&LvItem); - - for (i = 0; i < benchmarkTotalItems; i++) - { - ea = benchmarkTable[i].id; - - memset (&LvItem,0,sizeof(LvItem)); - LvItem.mask = LVIF_TEXT; - LvItem.iItem = i; - LvItem.iSubItem = 0; - LvItem.pszText = (LPWSTR) benchmarkTable[i].name; - SendMessageW (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); - -#if PKCS5_BENCHMARKS - wcscpy (item1, L"-"); -#else - GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].encSpeed / benchmarkPerformanceFrequency.QuadPart)), item1); -#endif - LvItem.iSubItem = 1; - LvItem.pszText = item1; - - SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); - -#if PKCS5_BENCHMARKS - wcscpy (item1, L"-"); -#else - GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].decSpeed / benchmarkPerformanceFrequency.QuadPart)), item1); -#endif - LvItem.iSubItem = 2; - LvItem.pszText = item1; - - SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); - -#if PKCS5_BENCHMARKS - swprintf (item1, L"%d t", benchmarkTable[i].encSpeed); -#else - GetSpeedString (benchmarkTable[i].meanBytesPerSec, item1); -#endif - LvItem.iSubItem = 3; - LvItem.pszText = item1; - - SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); - } -} - -static BOOL PerformBenchmark(HWND hwndDlg) -{ - LARGE_INTEGER performanceCountStart, performanceCountEnd; - BYTE *lpTestBuffer; - PCRYPTO_INFO ci = NULL; - UINT64_STRUCT startDataUnitNo; - - startDataUnitNo.Value = 0; - -#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) - ci = crypto_open (); - if (!ci) - return FALSE; -#endif - - if (QueryPerformanceFrequency (&benchmarkPerformanceFrequency) == 0) - { - MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); - return FALSE; - } - - lpTestBuffer = (BYTE *) malloc(benchmarkBufferSize - (benchmarkBufferSize % 16)); - if (lpTestBuffer == NULL) - { - MessageBoxW (hwndDlg, GetString ("ERR_MEM_ALLOC"), lpszTitle, ICON_HAND); - return FALSE; - } - VirtualLock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); - - WaitCursor (); - benchmarkTotalItems = 0; - -#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) - // CPU "warm up" (an attempt to prevent skewed results on systems where CPU frequency - // gradually changes depending on CPU load). - ci->ea = EAGetFirst(); - if (!EAInit (ci->ea, ci->master_keydata, ci->ks)) - { - ci->mode = FIRST_MODE_OF_OPERATION_ID; - if (EAInitMode (ci)) - { - int i; - - for (i = 0; i < 2; i++) - { - EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - } - } - } -#endif - -#if HASH_FNC_BENCHMARKS - - /* Measures the speed at which each of the hash algorithms processes the message to produce - a single digest. - - The hash algorithm benchmarks are included here for development purposes only. Do not enable - them when building a public release (the benchmark GUI strings wouldn't make sense). */ - - { - BYTE *digest [MAX_DIGESTSIZE]; - WHIRLPOOL_CTX wctx; - RMD160_CTX rctx; - sha1_ctx sctx; - sha512_ctx s2ctx; - int hid; - - for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) - { - if (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - switch (hid) - { - case SHA1: - sha1_begin (&sctx); - sha1_hash (lpTestBuffer, benchmarkBufferSize, &sctx); - sha1_end ((unsigned char *) digest, &sctx); - break; - - case SHA512: - sha512_begin (&s2ctx); - sha512_hash (lpTestBuffer, benchmarkBufferSize, &s2ctx); - sha512_end ((unsigned char *) digest, &s2ctx); - break; - - case RIPEMD160: - RMD160Init(&rctx); - RMD160Update(&rctx, lpTestBuffer, benchmarkBufferSize); - RMD160Final((unsigned char *) digest, &rctx); - break; - - case WHIRLPOOL: - WHIRLPOOL_init (&wctx); - WHIRLPOOL_add (lpTestBuffer, benchmarkBufferSize * 8, &wctx); - WHIRLPOOL_finalize (&wctx, (unsigned char *) digest); - break; - } - - if (QueryPerformanceCounter (&performanceCountEnd) == 0) - goto counter_error; - - benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; - - benchmarkTable[benchmarkTotalItems].decSpeed = benchmarkTable[benchmarkTotalItems].encSpeed; - benchmarkTable[benchmarkTotalItems].id = hid; - benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; - sprintf (benchmarkTable[benchmarkTotalItems].name, "%s", HashGetName(hid)); - - benchmarkTotalItems++; - } - } - -#elif PKCS5_BENCHMARKS // #if HASH_FNC_BENCHMARKS - - /* Measures the time that it takes for the PKCS-5 routine to derive a header key using - each of the implemented PRF algorithms. - - The PKCS-5 benchmarks are included here for development purposes only. Do not enable - them when building a public release (the benchmark GUI strings wouldn't make sense). */ - { - int thid, i; - char dk[MASTER_KEYDATA_SIZE]; - char *tmp_salt = {"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"}; - - for (thid = FIRST_PRF_ID; thid <= LAST_PRF_ID; thid++) - { - if (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - for (i = 1; i <= 5; i++) - { - switch (thid) - { - case SHA1: - /* PKCS-5 test with HMAC-SHA-1 used as the PRF */ - derive_key_sha1 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); - break; - - case SHA512: - /* PKCS-5 test with HMAC-SHA-512 used as the PRF */ - derive_key_sha512 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); - break; - - case RIPEMD160: - /* PKCS-5 test with HMAC-RIPEMD-160 used as the PRF */ - derive_key_ripemd160 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); - break; - - case WHIRLPOOL: - /* PKCS-5 test with HMAC-Whirlpool used as the PRF */ - derive_key_whirlpool ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); - break; - } - } - - if (QueryPerformanceCounter (&performanceCountEnd) == 0) - goto counter_error; - - benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; - benchmarkTable[benchmarkTotalItems].id = thid; - sprintf (benchmarkTable[benchmarkTotalItems].name, "%s", get_pkcs5_prf_name (thid)); - - benchmarkTotalItems++; - } - } - -#else // #elif PKCS5_BENCHMARKS - - /* Encryption algorithm benchmarks */ - - for (ci->ea = EAGetFirst(); ci->ea != 0; ci->ea = EAGetNext(ci->ea)) - { - if (!EAIsFormatEnabled (ci->ea)) - continue; - - EAInit (ci->ea, ci->master_keydata, ci->ks); - - ci->mode = FIRST_MODE_OF_OPERATION_ID; - EAInitMode (ci); - - if (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - - if (QueryPerformanceCounter (&performanceCountEnd) == 0) - goto counter_error; - - benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; - - if (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - - if (QueryPerformanceCounter (&performanceCountEnd) == 0) - goto counter_error; - - benchmarkTable[benchmarkTotalItems].decSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; - benchmarkTable[benchmarkTotalItems].id = ci->ea; - benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; - EAGetName (benchmarkTable[benchmarkTotalItems].name, ci->ea); - - benchmarkTotalItems++; - } - -#endif // #elif PKCS5_BENCHMARKS (#else) - - if (ci) - crypto_close (ci); - - VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); - - free(lpTestBuffer); - - benchmarkLastBufferSize = benchmarkBufferSize; - - DisplayBenchmarkResults(hwndDlg); - - EnableWindow (GetDlgItem (hwndDlg, IDC_PERFORM_BENCHMARK), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDCLOSE), TRUE); - - NormalCursor (); - return TRUE; - -counter_error: - - if (ci) - crypto_close (ci); - - VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); - - free(lpTestBuffer); - - NormalCursor (); - - EnableWindow (GetDlgItem (hwndDlg, IDC_PERFORM_BENCHMARK), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDCLOSE), TRUE); - - MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); - return FALSE; -} - - -BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - LPARAM nIndex; - HWND hCboxSortMethod = GetDlgItem (hwndDlg, IDC_BENCHMARK_SORT_METHOD); - HWND hCboxBufferSize = GetDlgItem (hwndDlg, IDC_BENCHMARK_BUFFER_SIZE); - - switch (msg) - { - case WM_INITDIALOG: - { - LVCOLUMNW LvCol; - wchar_t s[128]; - HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); - - LocalizeDialog (hwndDlg, "IDD_BENCHMARK_DLG"); - - benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; - benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; - - SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP - ); - - memset (&LvCol,0,sizeof(LvCol)); - LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - LvCol.pszText = GetString ("ALGORITHM"); - LvCol.cx = CompensateXDPI (114); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("ENCRYPTION"); - LvCol.cx = CompensateXDPI (80); - LvCol.fmt = LVCFMT_RIGHT; - SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("DECRYPTION"); - LvCol.cx = CompensateXDPI (80); - LvCol.fmt = LVCFMT_RIGHT; - SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("MEAN"); - LvCol.cx = CompensateXDPI (80); - LvCol.fmt = LVCFMT_RIGHT; - SendMessageW (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); - - /* Combo boxes */ - - // Sort method - - SendMessage (hCboxSortMethod, CB_RESETCONTENT, 0, 0); - - nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("ALPHABETICAL_CATEGORIZED")); - SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); - - nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("MEAN_SPEED")); - SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); - - SendMessage (hCboxSortMethod, CB_SETCURSEL, 1, 0); // Default sort method - - // Buffer size - - SendMessage (hCboxBufferSize, CB_RESETCONTENT, 0, 0); - - swprintf (s, L"100 %s", GetString ("KB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_KB); - - swprintf (s, L"500 %s", GetString ("KB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_KB); - - swprintf (s, L"1 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_MB); - - swprintf (s, L"5 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 5 * BYTES_PER_MB); - - swprintf (s, L"10 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 10 * BYTES_PER_MB); - - swprintf (s, L"50 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 50 * BYTES_PER_MB); - - swprintf (s, L"100 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_MB); - - swprintf (s, L"200 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 200 * BYTES_PER_MB); - - swprintf (s, L"500 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_MB); - - swprintf (s, L"1 %s", GetString ("GB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_GB); - - SendMessage (hCboxBufferSize, CB_SETCURSEL, 3, 0); // Default buffer size - - return 1; - } - break; - - case WM_COMMAND: - case WM_NOTIFY: - - if (lw == IDC_BENCHMARK_SORT_METHOD) - { - nIndex = SendMessage (hCboxSortMethod, CB_GETCURSEL, 0, 0); - if (nIndex != benchmarkSortMethod) - { - benchmarkSortMethod = nIndex; - DisplayBenchmarkResults (hwndDlg); - } - return 1; - } - - if (lw == IDC_PERFORM_BENCHMARK) - { - nIndex = SendMessage (hCboxBufferSize, CB_GETCURSEL, 0, 0); - benchmarkBufferSize = SendMessage (hCboxBufferSize, CB_GETITEMDATA, nIndex, 0); - - if (PerformBenchmark (hwndDlg) == FALSE) - { - EndDialog (hwndDlg, IDCLOSE); - } - return 1; - } - if (lw == IDCLOSE || lw == IDCANCEL) - { - EndDialog (hwndDlg, IDCLOSE); - return 1; - } - return 0; - - break; - - case WM_CLOSE: - EndDialog (hwndDlg, IDCLOSE); - return 1; - - break; - - } - return 0; -} - - -static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - static unsigned char randPool [RNG_POOL_SIZE]; - static unsigned char lastRandPool [RNG_POOL_SIZE]; - static char outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; - static BOOL bDisplayPoolContents = TRUE; - static BOOL bRandPoolDispAscii = FALSE; - int hash_algo = RandGetHashFunction(); - int hid; - - switch (msg) - { - case WM_INITDIALOG: - { - HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); - - VirtualLock (randPool, sizeof(randPool)); - VirtualLock (lastRandPool, sizeof(lastRandPool)); - VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); - - LocalizeDialog (hwndDlg, "IDD_RANDOM_POOL_ENRICHMENT"); - - SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); - for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) - { - if (!HashIsDeprecated (hid)) - AddComboPair (hComboBox, HashGetName(hid), hid); - } - SelectAlgo (hComboBox, &hash_algo); - - SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); - - SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); - SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - return 1; - } - - case WM_TIMER: - { - char tmp[4]; - unsigned char tmpByte; - int col, row; - - if (bDisplayPoolContents) - { - RandpeekBytes (randPool, sizeof (randPool)); - - if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) - { - outputDispBuffer[0] = 0; - - for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) - { - for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) - { - tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; - - sprintf (tmp, bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != '&') ? " %c " : " . ") : "%02X ", tmpByte); - strcat (outputDispBuffer, tmp); - } - strcat (outputDispBuffer, "\n"); - } - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); - - memcpy (lastRandPool, randPool, sizeof(lastRandPool)); - } - } - return 1; - } - - case WM_COMMAND: - if (lw == IDC_CONTINUE) - lw = IDOK; - - if (lw == IDOK || lw == IDCLOSE || lw == IDCANCEL) - { - goto exit; - } - - if (lw == IDC_PRF_ID && hw == CBN_SELCHANGE) - { - hid = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETCURSEL, 0, 0); - hash_algo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETITEMDATA, hid, 0); - RandSetHashFunction (hash_algo); - return 1; - } - - if (lw == IDC_DISPLAY_POOL_CONTENTS) - { - if (!(bDisplayPoolContents = GetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS))) - { - char tmp[RNG_POOL_SIZE+1]; - - memset (tmp, ' ', sizeof(tmp)); - tmp [RNG_POOL_SIZE] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); - } - - return 1; - } - - return 0; - - case WM_CLOSE: - { - char tmp[RNG_POOL_SIZE+1]; -exit: - KillTimer (hwndDlg, 0xfd); - - burn (randPool, sizeof(randPool)); - burn (lastRandPool, sizeof(lastRandPool)); - burn (outputDispBuffer, sizeof(outputDispBuffer)); - - // Attempt to wipe the pool contents in the GUI text area - memset (tmp, 'X', RNG_POOL_SIZE); - tmp [RNG_POOL_SIZE] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); - - if (msg == WM_COMMAND && lw == IDOK) - EndDialog (hwndDlg, IDOK); - else - EndDialog (hwndDlg, IDCLOSE); - - return 1; - } - } - return 0; -} - - -void UserEnrichRandomPool (HWND hwndDlg) -{ - Randinit(); - - if (!IsRandomPoolEnrichedByUser()) - { - INT_PTR result = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RANDOM_POOL_ENRICHMENT), hwndDlg ? hwndDlg : MainDlg, (DLGPROC) RandomPoolEnrichementDlgProc, (LPARAM) 0); - SetRandomPoolEnrichedByUserStatus (result == IDOK); - } -} - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK -KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - static unsigned char randPool [RNG_POOL_SIZE]; - static unsigned char lastRandPool [RNG_POOL_SIZE]; - static char outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; - static BOOL bDisplayPoolContents = TRUE; - static BOOL bRandPoolDispAscii = FALSE; - int hash_algo = RandGetHashFunction(); - int hid; - - switch (msg) - { - case WM_INITDIALOG: - { - HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); - - VirtualLock (randPool, sizeof(randPool)); - VirtualLock (lastRandPool, sizeof(lastRandPool)); - VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); - - LocalizeDialog (hwndDlg, "IDD_KEYFILE_GENERATOR_DLG"); - - SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); - for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) - { - if (!HashIsDeprecated (hid)) - AddComboPair (hComboBox, HashGetName(hid), hid); - } - SelectAlgo (hComboBox, &hash_algo); - - SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); - -#ifndef VOLFORMAT - if (Randinit ()) - { - Error ("INIT_RAND"); - EndDialog (hwndDlg, IDCLOSE); - } -#endif - SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); - SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - return 1; - } - - case WM_TIMER: - { - char tmp[4]; - unsigned char tmpByte; - int col, row; - - if (bDisplayPoolContents) - { - RandpeekBytes (randPool, sizeof (randPool)); - - if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) - { - outputDispBuffer[0] = 0; - - for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) - { - for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) - { - tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; - - sprintf (tmp, bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != '&') ? " %c " : " . ") : "%02X ", tmpByte); - strcat (outputDispBuffer, tmp); - } - strcat (outputDispBuffer, "\n"); - } - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); - - memcpy (lastRandPool, randPool, sizeof(lastRandPool)); - } - } - return 1; - } - - case WM_COMMAND: - - if (lw == IDCLOSE || lw == IDCANCEL) - { - goto exit; - } - - if (lw == IDC_PRF_ID && hw == CBN_SELCHANGE) - { - hid = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETCURSEL, 0, 0); - hash_algo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETITEMDATA, hid, 0); - RandSetHashFunction (hash_algo); - return 1; - } - - if (lw == IDC_DISPLAY_POOL_CONTENTS) - { - if (!(bDisplayPoolContents = GetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS))) - { - char tmp[RNG_POOL_SIZE+1]; - - memset (tmp, ' ', sizeof(tmp)); - tmp [RNG_POOL_SIZE] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); - } - return 1; - } - - if (lw == IDC_GENERATE_AND_SAVE_KEYFILE) - { - char szFileName [TC_MAX_PATH]; - unsigned char keyfile [MAX_PASSWORD]; - int fhKeyfile = -1; - - /* Select filename */ - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, TRUE, NULL)) - return 1; - - /* Conceive the file */ - if ((fhKeyfile = _open(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) - { - handleWin32Error (hwndDlg); - return 1; - } - - /* Generate the keyfile */ - WaitCursor(); - if (!RandgetBytes (keyfile, sizeof(keyfile), TRUE)) - { - _close (fhKeyfile); - DeleteFile (szFileName); - NormalCursor(); - return 1; - } - NormalCursor(); - - /* Write the keyfile */ - if (_write (fhKeyfile, keyfile, sizeof(keyfile)) == -1) - handleWin32Error (hwndDlg); - else - Info("KEYFILE_CREATED"); - - burn (keyfile, sizeof(keyfile)); - _close (fhKeyfile); - return 1; - } - return 0; - - case WM_CLOSE: - { - char tmp[RNG_POOL_SIZE+1]; -exit: - WaitCursor(); - KillTimer (hwndDlg, 0xfd); - -#ifndef VOLFORMAT - RandStop (FALSE); -#endif - /* Cleanup */ - - burn (randPool, sizeof(randPool)); - burn (lastRandPool, sizeof(lastRandPool)); - burn (outputDispBuffer, sizeof(outputDispBuffer)); - - // Attempt to wipe the pool contents in the GUI text area - memset (tmp, 'X', RNG_POOL_SIZE); - tmp [RNG_POOL_SIZE] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); - - EndDialog (hwndDlg, IDCLOSE); - NormalCursor (); - return 1; - } - } - return 0; -} - - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure -should return nonzero if it processes the message, and zero if it does -not. - see DialogProc */ -BOOL CALLBACK -CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static int idTestCipher = -1; /* Currently selected cipher for the test vector facility (none = -1). */ - static BOOL bXTSTestEnabled = FALSE; - - PCRYPTO_INFO ci; - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - - switch (uMsg) - { - case WM_INITDIALOG: - { - int ea; - char buf[100]; - - LocalizeDialog (hwndDlg, "IDD_CIPHER_TEST_DLG"); - - SendMessage(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), WM_SETFONT, (WPARAM)hBoldFont, MAKELPARAM(TRUE,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY), EM_LIMITTEXT, 128,0); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), EM_LIMITTEXT,64,0); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), EM_LIMITTEXT,64,0); - SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), EM_LIMITTEXT, 128,0); - SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), EM_LIMITTEXT,32,0); - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED, bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - - if (idTestCipher == -1) - idTestCipher = (int) lParam; - - SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_RESETCONTENT, 0, 0); - for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) - { - if (EAGetCipherCount (ea) == 1 && EAIsFormatEnabled (ea)) - AddComboPair (GetDlgItem (hwndDlg, IDC_CIPHER), EAGetName (buf, ea), EAGetFirstCipher (ea)); - } - - ResetCipherTest(hwndDlg, idTestCipher); - - SelectAlgo (GetDlgItem (hwndDlg, IDC_CIPHER), &idTestCipher); - - return 1; - } - - case WM_COMMAND: - - if (hw == CBN_SELCHANGE && lw == IDC_CIPHER) - { - idTestCipher = (int) SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETCURSEL, 0, 0), 0); - ResetCipherTest(hwndDlg, idTestCipher); - SendMessage (hwndDlg, WM_INITDIALOG, 0, 0); - return 1; - } - - if (hw == CBN_SELCHANGE && lw == IDC_KEY_SIZE) - { - // NOP - return 1; - } - - if (lw == IDC_RESET) - { - ResetCipherTest(hwndDlg, idTestCipher); - - return 1; - } - - if (lw == IDC_AUTO) - { - WaitCursor (); - if (!AutoTestAlgorithms()) - { - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); - SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_FAILED")); - } - else - { - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); - SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_PASSED")); - ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_SHOWNORMAL); - } - NormalCursor (); - - return 1; - - } - - if (lw == IDC_XTS_MODE_ENABLED) - { - bXTSTestEnabled = GetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED); - EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - if (bXTSTestEnabled) - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, 0,0); - } - - if (lw == IDOK || lw == IDC_ENCRYPT || lw == IDC_DECRYPT) - { - char key[128+1], inputtext[128+1], secondaryKey[64+1], dataUnitNo[16+1], szTmp[128+1]; - int ks, pt, n, tlen, blockNo = 0; - BOOL bEncrypt; - - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); - - ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETCURSEL, 0,0); - ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETITEMDATA, ks,0); - pt = (int) SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_GETITEMDATA, 0,0); - - bEncrypt = lw == IDC_ENCRYPT; - - memset(key,0,sizeof(key)); - memset(szTmp,0,sizeof(szTmp)); - n = GetWindowText(GetDlgItem(hwndDlg, IDC_KEY), szTmp, sizeof(szTmp)); - if (n != ks * 2) - { - Warning ("TEST_KEY_SIZE"); - return 1; - } - - for (n = 0; n < ks; n ++) - { - char szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = strtol(szTmp2, &ptr, 16); - - key[n] = (char) x; - } - - memset(inputtext, 0, sizeof(inputtext)); - memset(secondaryKey, 0, sizeof(secondaryKey)); - memset(dataUnitNo, 0, sizeof(dataUnitNo)); - memset(szTmp, 0, sizeof(szTmp)); - - if (bEncrypt) - { - n = GetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), szTmp, sizeof(szTmp)); - } - else - { - n = GetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), szTmp, sizeof(szTmp)); - } - - if (n != pt * 2) - { - if (bEncrypt) - { - Warning ("TEST_PLAINTEXT_SIZE"); - return 1; - } - else - { - Warning ("TEST_CIPHERTEXT_SIZE"); - return 1; - } - } - - for (n = 0; n < pt; n ++) - { - char szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = strtol(szTmp2, &ptr, 16); - - inputtext[n] = (char) x; - } - - // XTS - if (bXTSTestEnabled) - { - // Secondary key - - if (GetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), szTmp, sizeof(szTmp)) != 64) - { - Warning ("TEST_INCORRECT_SECONDARY_KEY_SIZE"); - return 1; - } - - for (n = 0; n < 64; n ++) - { - char szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = strtol(szTmp2, &ptr, 16); - - secondaryKey[n] = (char) x; - } - - // Data unit number - - tlen = GetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), szTmp, sizeof(szTmp)); - - if (tlen > 16 || tlen < 1) - { - Warning ("TEST_INCORRECT_TEST_DATA_UNIT_SIZE"); - return 1; - } - - LeftPadString (szTmp, tlen, 16, '0'); - - for (n = 0; n < 16; n ++) - { - char szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = strtol(szTmp2, &ptr, 16); - - dataUnitNo[n] = (char) x; - } - - // Block number - - blockNo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETCURSEL, 0, 0), 0); - } // if (bXTSTestEnabled) - - - /* Perform the actual tests */ - - if (ks != CB_ERR && pt != CB_ERR) - { - char tmp[128]; - int tmpRetVal; - - /* Copy the plain/ciphertext */ - memcpy(tmp,inputtext, pt); - - if (bXTSTestEnabled) - { - UINT64_STRUCT structDataUnitNo; - - /* XTS mode */ - - ci = crypto_open (); - if (!ci) - return 1; - - ci->mode = XTS; - - for (ci->ea = EAGetFirst (); ci->ea != 0 ; ci->ea = EAGetNext (ci->ea)) - if (EAGetCipherCount (ci->ea) == 1 && EAGetFirstCipher (ci->ea) == idTestCipher) - break; - - if ((tmpRetVal = EAInit (ci->ea, (unsigned char *) key, ci->ks)) != ERR_SUCCESS) - { - handleError (hwndDlg, tmpRetVal); - return 1; - } - - memcpy (&ci->k2, secondaryKey, sizeof (secondaryKey)); - if (!EAInitMode (ci)) - return 1; - - structDataUnitNo.Value = BE64(((unsigned __int64 *)dataUnitNo)[0]); - - if (bEncrypt) - EncryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); - else - DecryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); - - crypto_close (ci); - } - else - { - if (idTestCipher == BLOWFISH) - { - /* Deprecated/legacy */ - - /* Convert to little-endian, this is needed here and not in - above auto-tests because BF_ecb_encrypt above correctly converts - from big to little endian, and EncipherBlock does not! */ - LongReverse((unsigned int *) tmp, pt); - } - - CipherInit2(idTestCipher, key, ks_tmp, ks); - - if (bEncrypt) - { - EncipherBlock(idTestCipher, tmp, ks_tmp); - } - else - { - DecipherBlock(idTestCipher, tmp, ks_tmp); - } - - if (idTestCipher == BLOWFISH) - { - /* Deprecated/legacy */ - - /* Convert back to big-endian */ - LongReverse((unsigned int *) tmp, pt); - } - } - *szTmp = 0; - - for (n = 0; n < pt; n ++) - { - char szTmp2[3]; - sprintf(szTmp2, "%02x", (int)((unsigned char)tmp[n])); - strcat(szTmp, szTmp2); - } - - if (bEncrypt) - SetWindowText(GetDlgItem(hwndDlg,IDC_CIPHERTEXT), szTmp); - else - SetWindowText(GetDlgItem(hwndDlg,IDC_PLAINTEXT), szTmp); - } - - return 1; - } - - if (lw == IDCLOSE || lw == IDCANCEL) - { - idTestCipher = -1; - EndDialog (hwndDlg, 0); - return 1; - } - break; - - case WM_CLOSE: - idTestCipher = -1; - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - -void -ResetCipherTest(HWND hwndDlg, int idTestCipher) -{ - int ndx; - - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); - - EnableWindow(GetDlgItem(hwndDlg,IDC_KEY_SIZE), FALSE); - - /* Setup the keysize and plaintext sizes for the selected cipher */ - - SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); - SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_RESETCONTENT, 0,0); - SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_RESETCONTENT, 0,0); - - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) "64"); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 8); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); - - for (ndx = 0; ndx < BLOCKS_PER_XTS_DATA_UNIT; ndx++) - { - char tmpStr [16]; - - sprintf (tmpStr, "%d", ndx); - - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_ADDSTRING, 0,(LPARAM) tmpStr); - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETITEMDATA, ndx,(LPARAM) ndx); - } - - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETCURSEL, 0, 0); - - SetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), "0000000000000000000000000000000000000000000000000000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), "0"); - - if (idTestCipher == BLOWFISH) - { - /* Deprecated/legacy */ - - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "448"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 56); - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "256"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32); - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "128"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "64"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 8); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, 0,0); - SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - } - - - if (idTestCipher == CAST) - { - /* Deprecated/legacy */ - - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "128"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); - SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "00000000000000000000000000000000"); - } - - if (idTestCipher == TRIPLEDES) - { - /* Deprecated/legacy */ - - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "168"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 24); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); - SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "000000000000000000000000000000000000000000000000"); - } - - SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), "0000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), "0000000000000000"); - - if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH) - { - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "256"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); - - SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); - ndx = SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) "128"); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); - - SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "0000000000000000000000000000000000000000000000000000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), "00000000000000000000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), "00000000000000000000000000000000"); - } -} - -#endif // #ifndef SETUP - - -BOOL CALLBACK MultiChoiceDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - int nChoiceIDs [MAX_MULTI_CHOICES+1] = { IDC_MULTI_CHOICE_MSG, IDC_CHOICE1, IDC_CHOICE2, IDC_CHOICE3, - IDC_CHOICE4, IDC_CHOICE5, IDC_CHOICE6, IDC_CHOICE7, IDC_CHOICE8, IDC_CHOICE9, IDC_CHOICE10 }; - int nBaseButtonWidth = 0; - int nBaseButtonHeight = 0; - int nActiveChoices = -1; - int nStr = 0; - int vertSubOffset, horizSubOffset, vertMsgHeightOffset; - int vertOffset = 0; - int nLongestButtonCaptionWidth = 6; - int nLongestButtonCaptionCharLen = 1; - int nTextGfxLineHeight = 0; - int nMainTextLenInChars = 0; - int newLineSeqCount = 0; - RECT rec, wrec, wtrec, trec; - BOOL bResolve; - - WORD lw = LOWORD (wParam); - - switch (uMsg) - { - case WM_INITDIALOG: - { - char **pStr = (char **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; - char **pStrOrig = pStr; - wchar_t **pwStr = (wchar_t **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; - wchar_t **pwStrOrig = pwStr; - - LocalizeDialog (hwndDlg, NULL); - - SetWindowPos (hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - SetWindowPos (hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - - bResolve = (*pStr == NULL); - - // Style - if (((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->bold) - { - SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_CHOICE_MSG), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - } - - // Process the strings - pStr++; - pwStr++; - - do - { - if (*pStr != 0) - { - SetWindowTextW (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), bResolve ? GetString(*pStr) : *pwStr); - - if (nStr > 0) - { - nLongestButtonCaptionWidth = max ( - GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_CHOICE1), - bResolve ? GetString(*pStr) : *pwStr, - hUserFont), - nLongestButtonCaptionWidth); - - nLongestButtonCaptionCharLen = max (nLongestButtonCaptionCharLen, - (int) wcslen ((const wchar_t *) (bResolve ? GetString(*pStr) : *pwStr))); - } - - nActiveChoices++; - pStr++; - pwStr++; - } - else - { - ShowWindow(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), SW_HIDE); - } - nStr++; - - } while (nStr < MAX_MULTI_CHOICES+1); - - // Length of main message in characters (not bytes) - nMainTextLenInChars = wcslen ((const wchar_t *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1))); - - if (nMainTextLenInChars > 200 - && nMainTextLenInChars / nLongestButtonCaptionCharLen >= 10) - { - // As the main text is longer than 200 characters, we will "pad" the widest button caption with - // spaces (if it is not wide enough) so as to increase the width of the whole dialog window. - // Otherwise, it would look too tall (dialog boxes look better when they are more wide than tall). - nLongestButtonCaptionWidth = CompensateXDPI (max ( - nLongestButtonCaptionWidth, - min (350, nMainTextLenInChars))); - } - - // Get the window coords - GetWindowRect(hwndDlg, &wrec); - - // Get the base button size - GetClientRect(GetDlgItem(hwndDlg, IDC_CHOICE1), &rec); - nBaseButtonWidth = rec.right + 2; - nBaseButtonHeight = rec.bottom + 2; - - // Increase in width based on the gfx length of the widest button caption - horizSubOffset = min (CompensateXDPI (500), max (0, nLongestButtonCaptionWidth + CompensateXDPI (50) - nBaseButtonWidth)); - - // Vertical "title bar" offset - GetClientRect(hwndDlg, &wtrec); - vertOffset = wrec.bottom - wrec.top - wtrec.bottom - GetSystemMetrics(SM_CYFIXEDFRAME); - - // Height/width of the message text - GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); - - // Determine the number of newlines contained in the message text - { - int64 offset = -1; - - do - { - offset = FindString ((char *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1)), - (char *) L"\n", - nMainTextLenInChars * 2, - wcslen (L"\n") * 2, - offset + 1); - - newLineSeqCount++; - - } while (offset != -1); - } - - nTextGfxLineHeight = GetTextGfxHeight (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), - bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), - hUserFont); - - vertMsgHeightOffset = ((GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), - bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), - hUserFont) / (trec.right + horizSubOffset) + 1) * nTextGfxLineHeight) - trec.bottom; - - vertMsgHeightOffset = min (CompensateYDPI (350), vertMsgHeightOffset + newLineSeqCount * nTextGfxLineHeight + (trec.bottom + vertMsgHeightOffset) / 10); // As reserve, we are adding 10% and the number of lines equal to the number of newlines in the message - - // Reduction in height according to the number of shown buttons - vertSubOffset = ((MAX_MULTI_CHOICES - nActiveChoices) * nBaseButtonHeight); - - if (horizSubOffset > 0 - || vertMsgHeightOffset > 0 - || vertOffset > 0) - { - // Resize/move each button if necessary - for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) - { - GetWindowRect(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), &rec); - - MoveWindow (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset + vertMsgHeightOffset, - nBaseButtonWidth + horizSubOffset, - nBaseButtonHeight, - TRUE); - } - - // Resize/move the remaining GUI elements - GetWindowRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &rec); - GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); - MoveWindow (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset, - trec.right + 2 + horizSubOffset, - trec.bottom + 2 + vertMsgHeightOffset, - TRUE); - - GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &rec); - GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &trec); - MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset, - trec.right + 2 + horizSubOffset, - trec.bottom + 2, - TRUE); - - GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &rec); - GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &trec); - MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset + vertMsgHeightOffset, - trec.right + 2 + horizSubOffset, - trec.bottom + 2, - TRUE); - } - - // Resize the window according to number of shown buttons and the longest button caption - MoveWindow (hwndDlg, - wrec.left - horizSubOffset / 2, - wrec.top + vertSubOffset / 2 - vertMsgHeightOffset / 2, - wrec.right - wrec.left + horizSubOffset, - wrec.bottom - wrec.top - vertSubOffset + 1 + vertMsgHeightOffset, - TRUE); - - return 1; - } - - case WM_COMMAND: - - if (lw == IDCLOSE || lw == IDCANCEL) - { - EndDialog (hwndDlg, 0); - return 1; - } - - for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) - { - if (lw == nChoiceIDs[nStr]) - { - EndDialog (hwndDlg, nStr); - return 1; - } - } - break; - - case WM_CLOSE: - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - - -BOOL CheckCapsLock (HWND hwnd, BOOL quiet) -{ - if ((GetKeyState(VK_CAPITAL) & 1) != 0) - { - if (!quiet) - { - MessageBoxW (hwnd, GetString ("CAPSLOCK_ON"), lpszTitle, MB_ICONEXCLAMATION); - } - return TRUE; - } - return FALSE; -} - - -// Checks whether the file extension is not used for executable files or similarly problematic, which often -// causes Windows and antivirus software to interfere with the container -BOOL CheckFileExtension (char *fileName) -{ - int i = 0; - char *ext = strrchr (fileName, '.'); - static char *problemFileExt[] = { - // These are protected by the Windows Resource Protection - ".asa", ".asp", ".aspx", ".ax", ".bas", ".bat", ".bin", ".cer", ".chm", ".clb", ".cmd", ".cnt", ".cnv", - ".com", ".cpl", ".cpx", ".crt", ".csh", ".dll", ".drv", ".dtd", ".exe", ".fxp", ".grp", ".h1s", ".hlp", - ".hta", ".ime", ".inf", ".ins", ".isp", ".its", ".js", ".jse", ".ksh", ".lnk", ".mad", ".maf", ".mag", - ".mam", ".man", ".maq", ".mar", ".mas", ".mat", ".mau", ".mav", ".maw", ".mda", ".mdb", ".mde", ".mdt", - ".mdw", ".mdz", ".msc", ".msi", ".msp", ".mst", ".mui", ".nls", ".ocx", ".ops", ".pal", ".pcd", ".pif", - ".prf", ".prg", ".pst", ".reg", ".scf", ".scr", ".sct", ".shb", ".shs", ".sys", ".tlb", ".tsp", ".url", - ".vb", ".vbe", ".vbs", ".vsmacros", ".vss", ".vst", ".vsw", ".ws", ".wsc", ".wsf", ".wsh", ".xsd", ".xsl", - // These additional file extensions are usually watched by antivirus programs - ".386", ".acm", ".ade", ".adp", ".ani", ".app", ".asd", ".asf", ".asx", ".awx", ".ax", ".boo", ".bz2", ".cdf", - ".class", ".dhtm", ".dhtml",".dlo", ".emf", ".eml", ".flt", ".fot", ".gz", ".hlp", ".htm", ".html", ".ini", - ".j2k", ".jar", ".jff", ".jif", ".jmh", ".jng", ".jp2", ".jpe", ".jpeg", ".jpg", ".lsp", ".mod", ".nws", - ".obj", ".olb", ".osd", ".ov1", ".ov2", ".ov3", ".ovl", ".ovl", ".ovr", ".pdr", ".pgm", ".php", ".pkg", - ".pl", ".png", ".pot", ".pps", ".ppt", ".rar", ".rpl", ".rtf", ".sbf", ".script", ".sh", ".sha", ".shtm", - ".shtml", ".spl", ".swf", ".tar", ".tgz", ".tmp", ".ttf", ".vcs", ".vlm", ".vxd", ".vxo", ".wiz", ".wll", ".wmd", - ".wmf", ".wms", ".wmz", ".wpc", ".wsc", ".wsh", ".wwk", ".xhtm", ".xhtml", ".xl", ".xml", ".zip", ".7z", 0}; - - if (!ext) - return FALSE; - - while (problemFileExt[i]) - { - if (!_stricmp (ext, problemFileExt[i++])) - return TRUE; - } - - return FALSE; -} - - -void IncreaseWrongPwdRetryCount (int count) -{ - WrongPwdRetryCounter += count; -} - - -void ResetWrongPwdRetryCount (void) -{ - WrongPwdRetryCounter = 0; -} - - -BOOL WrongPwdRetryCountOverLimit (void) -{ - return (WrongPwdRetryCounter > TC_TRY_HEADER_BAK_AFTER_NBR_WRONG_PWD_TRIES); -} - - -int GetFirstAvailableDrive () -{ - DWORD dwUsedDrives = GetLogicalDrives(); - int i; - - for (i = 3; i < 26; i++) - { - if (!(dwUsedDrives & 1 << i)) - return i; - } - - return -1; -} - - -int GetLastAvailableDrive () -{ - DWORD dwUsedDrives = GetLogicalDrives(); - int i; - - for (i = 25; i > 2; i--) - { - if (!(dwUsedDrives & 1 << i)) - return i; - } - - return -1; -} - - -BOOL IsDriveAvailable (int driveNo) -{ - return (GetLogicalDrives() & (1 << driveNo)) == 0; -} - - -BOOL IsDeviceMounted (char *deviceName) -{ - BOOL bResult = FALSE; - DWORD dwResult; - HANDLE dev = INVALID_HANDLE_VALUE; - - if ((dev = CreateFile (deviceName, - GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL)) != INVALID_HANDLE_VALUE) - { - bResult = DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL); - CloseHandle (dev); - } - - return bResult; -} - - -int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) -{ - UNMOUNT_STRUCT unmount; - DWORD dwResult; - - BOOL bResult; - - unmount.nDosDriveNo = nDosDriveNo; - unmount.ignoreOpenFiles = forced; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_VOLUME, &unmount, - sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); - - if (bResult == FALSE) - { - handleWin32Error (hwndDlg); - return 1; - } - -#ifdef TCMOUNT - - if (unmount.nReturnCode == ERR_SUCCESS - && unmount.HiddenVolumeProtectionTriggered - && !VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo]) - { - wchar_t msg[4096]; - - VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] = TRUE; - swprintf (msg, GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), nDosDriveNo + 'A'); - SetForegroundWindow (hwndDlg); - MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - } - -#endif // #ifdef TCMOUNT - - return unmount.nReturnCode; -} - - -void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap) -{ - DEV_BROADCAST_VOLUME dbv; - DWORD dwResult; - LONG eventId = 0; - int i; - - if (message == DBT_DEVICEARRIVAL) - eventId = SHCNE_DRIVEADD; - else if (message == DBT_DEVICEREMOVECOMPLETE) - eventId = SHCNE_DRIVEREMOVED; - - if (driveMap == 0) - driveMap = (1 << nDosDriveNo); - - if (eventId != 0) - { - for (i = 0; i < 26; i++) - { - if (driveMap & (1 << i)) - { - char root[] = {i + 'A', ':', '\\', 0 }; - SHChangeNotify (eventId, SHCNF_PATH, root, NULL); - - if (nCurrentOS == WIN_2000 && RemoteSession) - { - char target[32]; - wsprintf (target, "%ls%c", TC_MOUNT_PREFIX, i + 'A'); - root[2] = 0; - - if (message == DBT_DEVICEARRIVAL) - DefineDosDevice (DDD_RAW_TARGET_PATH, root, target); - else if (message == DBT_DEVICEREMOVECOMPLETE) - DefineDosDevice (DDD_RAW_TARGET_PATH| DDD_REMOVE_DEFINITION - | DDD_EXACT_MATCH_ON_REMOVE, root, target); - } - } - } - } - - dbv.dbcv_size = sizeof (dbv); - dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME; - dbv.dbcv_reserved = 0; - dbv.dbcv_unitmask = driveMap; - dbv.dbcv_flags = 0; - - UINT timeOut = 1000; - - // SHChangeNotify() works on Vista, so the Explorer does not require WM_DEVICECHANGE - if (CurrentOSMajor >= 6) - timeOut = 100; - - IgnoreWmDeviceChange = TRUE; - SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), 0, timeOut, &dwResult); - - // Explorer prior Vista sometimes fails to register a new drive - if (CurrentOSMajor < 6 && message == DBT_DEVICEARRIVAL) - SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), 0, 200, &dwResult); - - IgnoreWmDeviceChange = FALSE; -} - - -// Use only cached passwords if password = NULL -// -// Returns: -// -1 = user aborted mount / error -// 0 = mount failed -// 1 = mount OK -// 2 = mount OK in shared mode - -int MountVolume (HWND hwndDlg, - int driveNo, - char *volumePath, - Password *password, - BOOL cachePassword, - BOOL sharedAccess, - MountOptions *mountOptions, - BOOL quiet, - BOOL bReportWrongPassword) -{ - MOUNT_STRUCT mount; - DWORD dwResult; - BOOL bResult, bDevice; - char root[MAX_PATH]; - -#ifdef TCMOUNT - if (mountOptions->PartitionInInactiveSysEncScope) - { - if (!CheckSysEncMountWithoutPBA (volumePath, quiet)) - return -1; - } -#endif - - if (IsMountedVolume (volumePath)) - { - if (!quiet) - Error ("VOL_ALREADY_MOUNTED"); - return -1; - } - - if (!IsDriveAvailable (driveNo)) - { - if (!quiet) - Error ("DRIVE_LETTER_UNAVAILABLE"); - - return -1; - } - - // If using cached passwords, check cache status first - if (password == NULL && IsPasswordCacheEmpty ()) - return 0; - - ZeroMemory (&mount, sizeof (mount)); - mount.bExclusiveAccess = sharedAccess ? FALSE : TRUE; - mount.UseBackupHeader = mountOptions->UseBackupHeader; - mount.RecoveryMode = mountOptions->RecoveryMode; - -retry: - mount.nDosDriveNo = driveNo; - mount.bCache = cachePassword; - - mount.bPartitionInInactiveSysEncScope = FALSE; - - if (password != NULL) - mount.VolumePassword = *password; - else - mount.VolumePassword.Length = 0; - - if (!mountOptions->ReadOnly && mountOptions->ProtectHiddenVolume) - { - mount.ProtectedHidVolPassword = mountOptions->ProtectedHidVolPassword; - mount.bProtectHiddenVolume = TRUE; - } - else - mount.bProtectHiddenVolume = FALSE; - - mount.bMountReadOnly = mountOptions->ReadOnly; - mount.bMountRemovable = mountOptions->Removable; - mount.bPreserveTimestamp = mountOptions->PreserveTimestamp; - - mount.bMountManager = TRUE; - - // Windows 2000 mount manager causes problems with remounted volumes - if (CurrentOSMajor == 5 && CurrentOSMinor == 0) - mount.bMountManager = FALSE; - - string path = volumePath; - if (path.find ("\\\\?\\") == 0) - { - // Remove \\?\ prefix - path = path.substr (4); - strcpy_s (volumePath, TC_MAX_PATH, path.c_str()); - } - - if (path.find ("Volume{") == 0 && path.rfind ("}\\") == path.size() - 2) - { - // Resolve volume name - if (QueryDosDevice (path.substr (0, path.size() - 1).c_str(), volumePath, TC_MAX_PATH) == 0) - strcpy_s (volumePath, TC_MAX_PATH, path.c_str()); - } - - CreateFullVolumePath ((char *) mount.wszVolume, volumePath, &bDevice); - - if (!bDevice) - { - // UNC path - if (path.find ("\\\\") == 0) - { - _snprintf ((char *)mount.wszVolume, MAX_PATH, "UNC%s", volumePath + 1); - } - - if (GetVolumePathName (volumePath, root, sizeof (root) - 1)) - { - DWORD bps, flags, d; - if (GetDiskFreeSpace (root, &d, &bps, &d, &d)) - mount.BytesPerSector = bps; - - // Read-only host filesystem - if (!mount.bMountReadOnly && GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) - mount.bMountReadOnly = (flags & FILE_READ_ONLY_VOLUME) != 0; - } - } - - ToUNICODE ((char *) mount.wszVolume); - - if (mountOptions->PartitionInInactiveSysEncScope) - { - if (mount.wszVolume == NULL || swscanf_s ((const wchar_t *) mount.wszVolume, - WIDE("\\Device\\Harddisk%d\\Partition"), - &mount.nPartitionInInactiveSysEncScopeDriveNo, - sizeof(mount.nPartitionInInactiveSysEncScopeDriveNo)) != 1) - { - return -1; - } - - mount.bPartitionInInactiveSysEncScope = TRUE; - } - - bResult = DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, &mount, - sizeof (mount), &mount, sizeof (mount), &dwResult, NULL); - - burn (&mount.VolumePassword, sizeof (mount.VolumePassword)); - burn (&mount.ProtectedHidVolPassword, sizeof (mount.ProtectedHidVolPassword)); - - if (bResult == FALSE) - { - // Volume already open by another process - if (GetLastError () == ERROR_SHARING_VIOLATION) - { - if (mount.bExclusiveAccess == FALSE) - { - if (!quiet) - MessageBoxW (hwndDlg, GetString ("FILE_IN_USE_FAILED"), - lpszTitle, MB_ICONSTOP); - - return -1; - } - else - { - if (quiet) - { - mount.bExclusiveAccess = FALSE; - goto retry; - } - - // Ask user - if (IDYES == MessageBoxW (hwndDlg, GetString ("FILE_IN_USE"), - lpszTitle, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION)) - { - mount.bExclusiveAccess = FALSE; - goto retry; - } - } - - return -1; - } - - if (!quiet) - handleWin32Error (hwndDlg); - - return -1; - } - - if (mount.nReturnCode != 0) - { - if (mount.nReturnCode == ERR_PASSWORD_WRONG) - { - // Do not report wrong password, if not instructed to - if (bReportWrongPassword) - { - IncreaseWrongPwdRetryCount (1); // We increase the count here only if bReportWrongPassword is TRUE, because "Auto-Mount All Devices" and other callers do it separately - - if (WrongPwdRetryCountOverLimit () - && !mount.UseBackupHeader) - { - // Retry using embedded header backup (if any) - mount.UseBackupHeader = TRUE; - goto retry; - } - - if (bDevice && mount.bProtectHiddenVolume) - { - int driveNo; - - if (sscanf (volumePath, "\\Device\\Harddisk%d\\Partition", &driveNo) == 1) - { - OPEN_TEST_STRUCT openTestStruct; - memset (&openTestStruct, 0, sizeof (openTestStruct)); - - openTestStruct.bDetectTCBootLoader = TRUE; - _snwprintf ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", driveNo); - - DWORD dwResult; - if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &dwResult, NULL) && openTestStruct.TCBootLoaderDetected) - WarningDirect ((GetWrongPasswordErrorMessage (hwndDlg) + L"\n\n" + GetString ("HIDDEN_VOL_PROT_PASSWORD_US_KEYB_LAYOUT")).c_str()); - else - handleError (hwndDlg, mount.nReturnCode); - } - } - else - handleError (hwndDlg, mount.nReturnCode); - } - - return 0; - } - - if (!quiet) - handleError (hwndDlg, mount.nReturnCode); - - return 0; - } - - // Mount successful - - if (mount.UseBackupHeader != mountOptions->UseBackupHeader - && mount.UseBackupHeader) - { - if (bReportWrongPassword && !Silent) - Warning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); - } - - if (mount.FilesystemDirty) - { - wchar_t msg[1024]; - wchar_t mountPoint[] = { L'A' + driveNo, L':', 0 }; - wsprintfW (msg, GetString ("MOUNTED_VOLUME_DIRTY"), mountPoint); - - if (AskWarnYesNoString (msg) == IDYES) - CheckFilesystem (driveNo, TRUE); - } - - if (mount.VolumeMountedReadOnlyAfterAccessDenied - && !Silent - && !bDevice - && !FileHasReadOnlyAttribute (volumePath) - && !IsFileOnReadOnlyFilesystem (volumePath)) - { - wchar_t msg[1024]; - wchar_t mountPoint[] = { L'A' + driveNo, L':', 0 }; - wsprintfW (msg, GetString ("MOUNTED_CONTAINER_FORCED_READ_ONLY"), mountPoint); - - WarningDirect (msg); - } - - if (mount.VolumeMountedReadOnlyAfterAccessDenied - && !Silent - && bDevice) - { - wchar_t msg[1024]; - wchar_t mountPoint[] = { L'A' + driveNo, L':', 0 }; - wsprintfW (msg, GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY"), mountPoint); - - WarningDirect (msg); - } - - if (mount.VolumeMountedReadOnlyAfterDeviceWriteProtected - && !Silent - && strstr (volumePath, "\\Device\\Harddisk") == volumePath) - { - wchar_t msg[1024]; - wchar_t mountPoint[] = { L'A' + driveNo, L':', 0 }; - wsprintfW (msg, GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY_WRITE_PROTECTION"), mountPoint); - - WarningDirect (msg); - - if (CurrentOSMajor >= 6 - && strstr (volumePath, "\\Device\\HarddiskVolume") != volumePath - && AskNoYes ("ASK_REMOVE_DEVICE_WRITE_PROTECTION") == IDYES) - { - RemoveDeviceWriteProtection (hwndDlg, volumePath); - } - } - - ResetWrongPwdRetryCount (); - - BroadcastDeviceChange (DBT_DEVICEARRIVAL, driveNo, 0); - - if (mount.bExclusiveAccess == FALSE) - return 2; - - return 1; -} - - -BOOL UnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount) -{ - int result; - BOOL forced = forceUnmount; - int dismountMaxRetries = UNMOUNT_MAX_AUTO_RETRIES; - -retry: - BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, nDosDriveNo, 0); - - do - { - result = DriverUnmountVolume (hwndDlg, nDosDriveNo, forced); - - if (result == ERR_FILES_OPEN) - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - else - break; - - } while (--dismountMaxRetries > 0); - - if (result != 0) - { - if (result == ERR_FILES_OPEN && !Silent) - { - if (IDYES == AskWarnNoYes ("UNMOUNT_LOCK_FAILED")) - { - forced = TRUE; - goto retry; - } - - return FALSE; - } - - Error ("UNMOUNT_FAILED"); - - return FALSE; - } - - BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, nDosDriveNo, 0); - - return TRUE; -} - - -BOOL IsPasswordCacheEmpty (void) -{ - DWORD dw; - return !DeviceIoControl (hDriver, TC_IOCTL_GET_PASSWORD_CACHE_STATUS, 0, 0, 0, 0, &dw, 0); -} - - -BOOL IsMountedVolume (const char *volname) -{ - MOUNT_LIST_STRUCT mlist; - DWORD dwResult; - int i; - char volume[TC_MAX_PATH*2+16]; - - strcpy (volume, volname); - - if (strstr (volname, "\\Device\\") != volname) - sprintf(volume, "\\??\\%s", volname); - ToUNICODE (volume); - - memset (&mlist, 0, sizeof (mlist)); - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, - sizeof (mlist), &mlist, sizeof (mlist), &dwResult, - NULL); - - for (i=0 ; i<26; i++) - if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume)) - return TRUE; - - return FALSE; -} - - -int GetMountedVolumeDriveNo (char *volname) -{ - MOUNT_LIST_STRUCT mlist; - DWORD dwResult; - int i; - char volume[TC_MAX_PATH*2+16]; - - if (volname == NULL) - return -1; - - strcpy (volume, volname); - - if (strstr (volname, "\\Device\\") != volname) - sprintf(volume, "\\??\\%s", volname); - ToUNICODE (volume); - - memset (&mlist, 0, sizeof (mlist)); - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, - sizeof (mlist), &mlist, sizeof (mlist), &dwResult, - NULL); - - for (i=0 ; i<26; i++) - if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume)) - return i; - - return -1; -} - - -BOOL IsAdmin (void) -{ - return IsUserAnAdmin (); -} - - -BOOL IsUacSupported () -{ - HKEY hkey; - DWORD value = 1, size = sizeof (DWORD); - - if (!IsOSAtLeast (WIN_VISTA)) - return FALSE; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_READ, &hkey) == ERROR_SUCCESS) - { - if (RegQueryValueEx (hkey, "EnableLUA", 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS) - value = 1; - - RegCloseKey (hkey); - } - - return value != 0; -} - - -BOOL ResolveSymbolicLink (PWSTR symLinkName, PWSTR targetName) -{ - BOOL bResult; - DWORD dwResult; - RESOLVE_SYMLINK_STRUCT resolve; - - memset (&resolve, 0, sizeof(resolve)); - wcscpy ((PWSTR) &resolve.symLinkName, symLinkName); - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_RESOLVED_SYMLINK, &resolve, - sizeof (resolve), &resolve, sizeof (resolve), &dwResult, - NULL); - - wcscpy (targetName, (PWSTR) &resolve.targetName); - - return bResult; -} - - -BOOL GetPartitionInfo (const char *deviceName, PPARTITION_INFORMATION rpartInfo) -{ - BOOL bResult; - DWORD dwResult; - DISK_PARTITION_INFO_STRUCT dpi; - - memset (&dpi, 0, sizeof(dpi)); - wsprintfW ((PWSTR) &dpi.deviceName, L"%hs", deviceName); - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, &dpi, - sizeof (dpi), &dpi, sizeof (dpi), &dwResult, NULL); - - memcpy (rpartInfo, &dpi.partInfo, sizeof (PARTITION_INFORMATION)); - return bResult; -} - - -BOOL GetDeviceInfo (const char *deviceName, DISK_PARTITION_INFO_STRUCT *info) -{ - DWORD dwResult; - - memset (info, 0, sizeof(*info)); - wsprintfW ((PWSTR) &info->deviceName, L"%hs", deviceName); - - return DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, info, sizeof (*info), info, sizeof (*info), &dwResult, NULL); -} - - -BOOL GetDriveGeometry (const char *deviceName, PDISK_GEOMETRY diskGeometry) -{ - BOOL bResult; - DWORD dwResult; - DISK_GEOMETRY_STRUCT dg; - - memset (&dg, 0, sizeof(dg)); - wsprintfW ((PWSTR) &dg.deviceName, L"%hs", deviceName); - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_GEOMETRY, &dg, - sizeof (dg), &dg, sizeof (dg), &dwResult, NULL); - - memcpy (diskGeometry, &dg.diskGeometry, sizeof (DISK_GEOMETRY)); - return bResult; -} - - -// Returns drive letter number assigned to device (-1 if none) -int GetDiskDeviceDriveLetter (PWSTR deviceName) -{ - int i; - WCHAR link[MAX_PATH]; - WCHAR target[MAX_PATH]; - WCHAR device[MAX_PATH]; - - if (!ResolveSymbolicLink (deviceName, device)) - wcscpy (device, deviceName); - - for (i = 0; i < 26; i++) - { - WCHAR drive[] = { i + 'A', ':', 0 }; - - wcscpy (link, L"\\DosDevices\\"); - wcscat (link, drive); - - ResolveSymbolicLink (link, target); - - if (wcscmp (device, target) == 0) - return i; - } - - return -1; -} - - -// WARNING: This function does NOT provide 100% reliable results -- do NOT use it for critical/dangerous operations! -// Return values: 0 - filesystem does not appear empty, 1 - filesystem appears empty, -1 - an error occurred -int FileSystemAppearsEmpty (const char *devicePath) -{ - float percentFreeSpace = 0.0; - __int64 occupiedBytes = 0; - - if (GetStatsFreeSpaceOnPartition (devicePath, &percentFreeSpace, &occupiedBytes, TRUE) != -1) - { - if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. - || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. - { - return 0; - } - else - return 1; - } - else - return -1; -} - - -// Returns the free space on the specified partition (volume) in bytes. If the 'occupiedBytes' pointer -// is not NULL, size of occupied space (in bytes) is written to the pointed location. In addition, if the -// 'percent' pointer is not NULL, % of free space is stored in the pointed location. If there's an error, -// returns -1. -__int64 GetStatsFreeSpaceOnPartition (const char *devicePath, float *percentFree, __int64 *occupiedBytes, BOOL silent) -{ - WCHAR devPath [MAX_PATH]; - int driveLetterNo = -1; - char szRootPath[4] = {0, ':', '\\', 0}; - ULARGE_INTEGER freeSpaceSize; - ULARGE_INTEGER totalNumberOfBytes; - ULARGE_INTEGER totalNumberOfFreeBytes; - - strcpy ((char *) devPath, devicePath); - ToUNICODE ((char *) devPath); - - driveLetterNo = GetDiskDeviceDriveLetter (devPath); - szRootPath[0] = driveLetterNo + 'A'; - - - if (!GetDiskFreeSpaceEx (szRootPath, &freeSpaceSize, &totalNumberOfBytes, &totalNumberOfFreeBytes)) - { - if (!silent) - { - handleWin32Error (MainDlg); - Error ("CANNOT_CALC_SPACE"); - } - - return -1; - } - - - if (percentFree != NULL || occupiedBytes != NULL) - { - // Determine occupied space and % of free space - - PARTITION_INFORMATION partitionInfo; - - if (!GetPartitionInfo (devicePath, &partitionInfo)) - { - if (!silent) - { - handleWin32Error (MainDlg); - Error ("CANT_GET_VOLSIZE"); - } - return -1; - } - - if (occupiedBytes != NULL) - *occupiedBytes = partitionInfo.PartitionLength.QuadPart - freeSpaceSize.QuadPart; - - if (percentFree != NULL) - *percentFree = (float) ((double) freeSpaceSize.QuadPart / (double) partitionInfo.PartitionLength.QuadPart * 100.0); - } - - return freeSpaceSize.QuadPart; -} - - -// Returns -1 if there's an error. -__int64 GetDeviceSize (const char *devicePath) -{ - PARTITION_INFORMATION partitionInfo; - - if (!GetPartitionInfo (devicePath, &partitionInfo)) - return -1; - - return partitionInfo.PartitionLength.QuadPart; -} - - -HANDLE DismountDrive (char *devName, char *devicePath) -{ - DWORD dwResult; - HANDLE hVolume; - BOOL bResult = FALSE; - int attempt = UNMOUNT_MAX_AUTO_RETRIES; - int driveLetterNo = -1; - WCHAR devPath [MAX_PATH]; - - strcpy ((char *) devPath, devicePath); - ToUNICODE ((char *) devPath); - driveLetterNo = GetDiskDeviceDriveLetter (devPath); - - - hVolume = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hVolume == INVALID_HANDLE_VALUE) - return INVALID_HANDLE_VALUE; - - - // Try to lock the volume first so that dismount is not forced. - // If we fail, we will dismount anyway even if it needs to be forced. - - CloseVolumeExplorerWindows (MainDlg, driveLetterNo); - - while (!(bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - - // Try to dismount the volume - - attempt = UNMOUNT_MAX_AUTO_RETRIES; - - while (!(bResult = DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - if (!bResult) - CloseHandle (hVolume); - - return (bResult ? hVolume : INVALID_HANDLE_VALUE); -} - -// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the -// offset of the first occurrence of the string. The string and the buffer may contain zeroes, -// which do NOT terminate them. -int64 FindString (const char *buf, const char *str, int64 bufLen, size_t strLen, int64 startOffset) -{ - if (buf == NULL - || str == NULL - || strLen > bufLen - || bufLen < 1 - || strLen < 1 - || startOffset > bufLen - strLen) - { - return -1; - } - - for (int64 i = startOffset; i < bufLen - strLen; i++) - { - if (memcmp (buf + i, str, strLen) == 0) - return i; - } - - return -1; -} - -// Returns TRUE if the file exists (otherwise FALSE). -BOOL FileExists (const char *filePathPtr) -{ - char filePath [TC_MAX_PATH]; - - // Strip quotation marks (if any) - if (filePathPtr [0] == '"') - { - strcpy (filePath, filePathPtr + 1); - } - else - { - strcpy (filePath, filePathPtr); - } - - // Strip quotation marks (if any) - if (filePath [strlen (filePath) - 1] == '"') - filePath [strlen (filePath) - 1] = 0; - - return (_access (filePath, 0) != -1); -} - -// Searches the file from its end for the LAST occurrence of the string str. -// The string may contain zeroes, which do NOT terminate the string. -// If the string is found, its offset from the start of the file is returned. -// If the string isn't found or if any error occurs, -1 is returned. -__int64 FindStringInFile (const char *filePath, const char* str, int strLen) -{ - int bufSize = 64 * BYTES_PER_KB; - char *buffer = (char *) malloc (bufSize); - HANDLE src = NULL; - DWORD bytesRead; - BOOL readRetVal; - __int64 filePos = GetFileSize64 (filePath); - int bufPos = 0; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL bExit = FALSE; - int filePosStep; - __int64 retVal = -1; - - if (filePos <= 0 - || buffer == NULL - || strLen > bufSize - || strLen < 1) - return -1; - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return -1; - } - - filePosStep = bufSize - strLen + 1; - - do - { - filePos -= filePosStep; - - if (filePos < 0) - { - filePos = 0; - bExit = TRUE; - } - - seekOffset.QuadPart = filePos; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0 - || bytesRead == 0) - goto fsif_end; - - bufPos = bytesRead - strLen; - - while (bufPos > 0) - { - if (memcmp (buffer + bufPos, str, strLen) == 0) - { - // String found - retVal = filePos + bufPos; - goto fsif_end; - } - bufPos--; - } - - } while (!bExit); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED) -// so we need to use our own copy function -BOOL TCCopyFile (char *sourceFileName, char *destinationFile) -{ - __int8 *buffer; - HANDLE src, dst; - FILETIME fileTime; - DWORD bytesRead, bytesWritten; - BOOL res; - - src = CreateFile (sourceFileName, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - return FALSE; - - dst = CreateFile (destinationFile, - GENERIC_WRITE, - 0, NULL, CREATE_ALWAYS, 0, NULL); - - if (dst == INVALID_HANDLE_VALUE) - { - CloseHandle (src); - return FALSE; - } - - buffer = (char *) malloc (64 * 1024); - if (!buffer) - { - CloseHandle (src); - CloseHandle (dst); - return FALSE; - } - - while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL)) - { - if (bytesRead == 0) - { - res = 1; - break; - } - - if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL) - || bytesRead != bytesWritten) - { - res = 0; - break; - } - } - - GetFileTime (src, NULL, NULL, &fileTime); - SetFileTime (dst, NULL, NULL, &fileTime); - - CloseHandle (src); - CloseHandle (dst); - - free (buffer); - return res != 0; -} - -// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file -// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE). -BOOL SaveBufferToFile (char *inputBuffer, char *destinationFile, DWORD inputLength, BOOL bAppend) -{ - HANDLE dst; - DWORD bytesWritten; - BOOL res = TRUE; - - dst = CreateFile (destinationFile, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); - - if (dst == INVALID_HANDLE_VALUE) - { - handleWin32Error (MainDlg); - return FALSE; - } - - if (bAppend) - SetFilePointer (dst, 0, NULL, FILE_END); - - if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL) - || inputLength != bytesWritten) - { - res = FALSE; - } - - if (!res) - { - // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite - // of an existing file (it's not an error) - if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) ) - handleWin32Error (MainDlg); - } - - CloseHandle (dst); - FlushFileBuffers (dst); - - if (!res && !bAppend) - remove (destinationFile); - - return res; -} - - -// Proper flush for Windows systems. Returns TRUE if successful. -BOOL TCFlushFile (FILE *f) -{ - HANDLE hf = (HANDLE) _get_osfhandle (_fileno (f)); - - fflush (f); - - if (hf == INVALID_HANDLE_VALUE) - return FALSE; - - return FlushFileBuffers (hf) != 0; -} - - -// Prints a UTF-16 text (note that this involves a real printer, not a screen). -// textByteLen - length of the text in bytes -// title - printed as part of the page header and used as the filename for a temporary file -BOOL PrintHardCopyTextUTF16 (wchar_t *text, char *title, int textByteLen) -{ - char cl [MAX_PATH*3] = {"/p \""}; - char path [MAX_PATH * 2] = { 0 }; - char filename [MAX_PATH + 1] = { 0 }; - - strcpy (filename, title); - //strcat (filename, ".txt"); - - GetTempPath (sizeof (path), path); - - if (!FileExists (path)) - { - strcpy (path, GetConfigPath (filename)); - - if (strlen(path) < 2) - return FALSE; - } - else - { - strcat (path, filename); - } - - // Write the Unicode signature - if (!SaveBufferToFile ("\xFF\xFE", path, 2, FALSE)) - { - remove (path); - return FALSE; - } - - // Write the actual text - if (!SaveBufferToFile ((char *) text, path, textByteLen, TRUE)) - { - remove (path); - return FALSE; - } - - strcat (cl, path); - strcat (cl, "\""); - - WaitCursor (); - ShellExecute (NULL, "open", PRINT_TOOL, cl, NULL, SW_HIDE); - Sleep (6000); - NormalCursor(); - - remove (path); - - return TRUE; -} - - -BOOL IsNonInstallMode () -{ - HKEY hkey; - DWORD dw; - - if (bTravelerModeConfirmed) - return TRUE; - - if (hDriver != INVALID_HANDLE_VALUE) - { - // The driver is running - if (DeviceIoControl (hDriver, TC_IOCTL_GET_TRAVELER_MODE_STATUS, NULL, 0, NULL, 0, &dw, 0)) - { - bTravelerModeConfirmed = TRUE; - return TRUE; - } - else - { - // This is also returned if we fail to determine the status (it does not mean that traveler mode is disproved). - return FALSE; - } - } - else - { - // The tests in this block are necessary because this function is in some cases called before DriverAttach(). - - HANDLE hDriverTmp = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - - if (hDriverTmp == INVALID_HANDLE_VALUE) - { - // The driver was not found in the system path - - char path[MAX_PATH * 2] = { 0 }; - - // We can't use GetConfigPath() here because it would call us back (indirect recursion) - if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path))) - { - strcat (path, "\\TrueCrypt\\"); - strcat (path, TC_APPD_FILENAME_SYSTEM_ENCRYPTION); - - if (FileExists (path)) - { - // To maintain consistency and safety, if the system encryption config file exits, we cannot - // allow traveler mode. (This happens e.g. when the pretest fails and the user selects - // "Last Known Good Configuration" from the Windows boot menu.) - - // However, if UAC elevation is needed, we have to confirm traveler mode first (after we are elevated, we won't). - if (!IsAdmin () && IsUacSupported ()) - return TRUE; - - return FALSE; - } - } - - // As the driver was not found in the system path, we can predict that we will run in traveler mode - return TRUE; - } - else - CloseHandle (hDriverTmp); - } - - // The following test may be unreliable in some cases (e.g. after the user selects restore "Last Known Good - // Configuration" from the Windows boot menu). - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt", 0, KEY_READ, &hkey) == ERROR_SUCCESS) - { - RegCloseKey (hkey); - return FALSE; - } - else - return TRUE; -} - - -LRESULT SetCheckBox (HWND hwndDlg, int dlgItem, BOOL state) -{ - return SendDlgItemMessage (hwndDlg, dlgItem, BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0); -} - - -BOOL GetCheckBox (HWND hwndDlg, int dlgItem) -{ - return IsButtonChecked (GetDlgItem (hwndDlg, dlgItem)); -} - - -// Adds or removes TrueCrypt.exe to/from the system startup sequence (with appropriate command line arguments) -void ManageStartupSeq (void) -{ - if (!IsNonInstallMode ()) - { - char regk [64]; - - // Split the string in order to prevent some antivirus packages from falsely reporting - // TrueCrypt.exe to contain a possible Trojan horse because of this string (heuristic scan). - sprintf (regk, "%s%s", "Software\\Microsoft\\Windows\\Curren", "tVersion\\Run"); - - if (bStartOnLogon || bMountDevicesOnLogon || bMountFavoritesOnLogon) - { - char exe[MAX_PATH * 2] = { '"' }; - - GetModuleFileName (NULL, exe + 1, sizeof (exe) - 1); - -#ifdef VOLFORMAT - { - char *tmp = NULL; - - if (tmp = strrchr (exe, '\\')) - strcpy (++tmp, "TrueCrypt.exe"); - } -#endif - strcat (exe, "\" /q preferences"); - - if (bMountDevicesOnLogon) strcat (exe, " /a devices"); - if (bMountFavoritesOnLogon) strcat (exe, " /a favorites"); - - WriteRegistryString (regk, "TrueCrypt", exe); - } - else - DeleteRegistryValue (regk, "TrueCrypt"); - } -} - - -// Adds or removes the TrueCrypt Volume Creation Wizard to/from the system startup sequence -void ManageStartupSeqWiz (BOOL bRemove, const char *arg) -{ - char regk [64]; - - // Split this string in order to prevent some low-quality antivirus software from falsely reporting - // our .exe files to contain a possible Trojan horse because of this string (heuristic scan). - sprintf (regk, "%s%s", "Software\\Microsoft\\Windows\\Curren", "tVersion\\Run"); - - if (!bRemove) - { - char exe[MAX_PATH * 2] = { '"' }; - GetModuleFileName (NULL, exe + 1, sizeof (exe) - 1); - -#ifndef VOLFORMAT - { - char *tmp = NULL; - - if (tmp = strrchr (exe, '\\')) - strcpy (++tmp, "TrueCrypt Format.exe"); - } -#endif - - if (strlen (arg) > 0) - { - strcat (exe, "\" "); - strcat (exe, arg); - } - - WriteRegistryString (regk, "TrueCrypt Format", exe); - } - else - DeleteRegistryValue (regk, "TrueCrypt Format"); -} - - -// Delete the last used Windows file selector path for TrueCrypt from the registry -void CleanLastVisitedMRU (void) -{ - WCHAR exeFilename[MAX_PATH]; - WCHAR *strToMatch; - - WCHAR strTmp[4096]; - char regPath[128]; - char key[64]; - int id, len; - - GetModuleFileNameW (NULL, exeFilename, sizeof (exeFilename) / sizeof(exeFilename[0])); - strToMatch = wcsrchr (exeFilename, '\\') + 1; - - sprintf (regPath, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisited%sMRU", IsOSAtLeast (WIN_VISTA) ? "Pidl" : ""); - - for (id = (IsOSAtLeast (WIN_VISTA) ? 0 : 'a'); id <= (IsOSAtLeast (WIN_VISTA) ? 1000 : 'z'); id++) - { - *strTmp = 0; - sprintf (key, (IsOSAtLeast (WIN_VISTA) ? "%d" : "%c"), id); - - if ((len = ReadRegistryBytes (regPath, key, (char *) strTmp, sizeof (strTmp))) > 0) - { - if (_wcsicmp (strTmp, strToMatch) == 0) - { - char buf[65536], bufout[sizeof (buf)]; - - // Overwrite the entry with zeroes while keeping its original size - memset (strTmp, 0, len); - if (!WriteRegistryBytes (regPath, key, (char *) strTmp, len)) - MessageBoxW (NULL, GetString ("CLEAN_WINMRU_FAILED"), lpszTitle, ICON_HAND); - - DeleteRegistryValue (regPath, key); - - // Remove ID from MRUList - if (IsOSAtLeast (WIN_VISTA)) - { - int *p = (int *)buf; - int *pout = (int *)bufout; - int l; - - l = len = ReadRegistryBytes ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", "MRUListEx", buf, sizeof (buf)); - while (l > 0) - { - l -= sizeof (int); - - if (*p == id) - { - p++; - len -= sizeof (int); - continue; - } - *pout++ = *p++; - } - - WriteRegistryBytes ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", "MRUListEx", bufout, len); - } - else - { - char *p = buf; - char *pout = bufout; - - ReadRegistryString ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", "MRUList", "", buf, sizeof (buf)); - while (*p) - { - if (*p == id) - { - p++; - continue; - } - *pout++ = *p++; - } - *pout++ = 0; - - WriteRegistryString ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", "MRUList", bufout); - } - - break; - } - } - } -} - - -#ifndef SETUP -void ClearHistory (HWND hwndDlgItem) -{ - ArrowWaitCursor (); - - ClearCombo (hwndDlgItem); - DumpCombo (hwndDlgItem, TRUE); - - CleanLastVisitedMRU (); - - NormalCursor (); -} -#endif // #ifndef SETUP - - -LRESULT ListItemAdd (HWND list, int index, char *string) -{ - LVITEM li; - memset (&li, 0, sizeof(li)); - - li.mask = LVIF_TEXT; - li.pszText = string; - li.iItem = index; - li.iSubItem = 0; - return ListView_InsertItem (list, &li); -} - - -LRESULT ListItemAddW (HWND list, int index, wchar_t *string) -{ - LVITEMW li; - memset (&li, 0, sizeof(li)); - - li.mask = LVIF_TEXT; - li.pszText = string; - li.iItem = index; - li.iSubItem = 0; - return SendMessageW (list, LVM_INSERTITEMW, 0, (LPARAM)(&li)); -} - - -LRESULT ListSubItemSet (HWND list, int index, int subIndex, char *string) -{ - LVITEM li; - memset (&li, 0, sizeof(li)); - - li.mask = LVIF_TEXT; - li.pszText = string; - li.iItem = index; - li.iSubItem = subIndex; - return ListView_SetItem (list, &li); -} - - -LRESULT ListSubItemSetW (HWND list, int index, int subIndex, wchar_t *string) -{ - LVITEMW li; - memset (&li, 0, sizeof(li)); - - li.mask = LVIF_TEXT; - li.pszText = string; - li.iItem = index; - li.iSubItem = subIndex; - return SendMessageW (list, LVM_SETITEMW, 0, (LPARAM)(&li)); -} - - -BOOL GetMountList (MOUNT_LIST_STRUCT *list) -{ - DWORD dwResult; - - memset (list, 0, sizeof (*list)); - return DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, list, - sizeof (*list), list, sizeof (*list), &dwResult, - NULL); -} - - -int GetDriverRefCount () -{ - DWORD dwResult; - BOOL bResult; - int refCount; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, - sizeof (refCount), &dwResult, NULL); - - if (bResult) - return refCount; - else - return -1; -} - -// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been -// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). -BOOL LoadInt32 (char *filePath, unsigned __int32 *result, __int64 fileOffset) -{ - int bufSize = sizeof(__int32); - unsigned char *buffer = (unsigned char *) malloc (bufSize); - unsigned char *bufferPtr = buffer; - HANDLE src = NULL; - DWORD bytesRead; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL retVal = FALSE; - - if (buffer == NULL) - return -1; - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return FALSE; - } - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 - || bytesRead != bufSize) - goto fsif_end; - - - retVal = TRUE; - - *result = mgetLong(bufferPtr); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been -// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). -BOOL LoadInt16 (char *filePath, int *result, __int64 fileOffset) -{ - int bufSize = sizeof(__int16); - unsigned char *buffer = (unsigned char *) malloc (bufSize); - unsigned char *bufferPtr = buffer; - HANDLE src = NULL; - DWORD bytesRead; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL retVal = FALSE; - - if (buffer == NULL) - return -1; - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return FALSE; - } - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 - || bytesRead != bufSize) - goto fsif_end; - - - retVal = TRUE; - - *result = mgetWord(bufferPtr); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated. -char *LoadFile (const char *fileName, DWORD *size) -{ - char *buf; - HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) - return NULL; - - *size = GetFileSize (h, NULL); - buf = (char *) malloc (*size + 1); - - if (buf == NULL) - { - CloseHandle (h); - return NULL; - } - - ZeroMemory (buf, *size + 1); - - if (!ReadFile (h, buf, *size, size, NULL)) - { - free (buf); - buf = NULL; - } - - CloseHandle (h); - return buf; -} - - -// Returns NULL if there's any error. -char *LoadFileBlock (char *fileName, __int64 fileOffset, int count) -{ - char *buf; - DWORD bytesRead = 0; - LARGE_INTEGER seekOffset, seekOffsetNew; - - HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) - return NULL; - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - { - CloseHandle (h); - return NULL; - } - - buf = (char *) malloc (count); - - if (buf == NULL) - { - CloseHandle (h); - return NULL; - } - - ZeroMemory (buf, count); - - if (buf != NULL) - ReadFile (h, buf, count, &bytesRead, NULL); - - CloseHandle (h); - - if (bytesRead != count) - { - free (buf); - return NULL; - } - - return buf; -} - - -// Returns -1 if there is an error, or the size of the file. -__int64 GetFileSize64 (const char *path) -{ - HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - LARGE_INTEGER size; - - if (h == INVALID_HANDLE_VALUE) - return -1; - - if (GetFileSizeEx (h, &size) == 0) - return -1; - - CloseHandle (h); - - return size.QuadPart; -} - - -char *GetModPath (char *path, int maxSize) -{ - GetModuleFileName (NULL, path, maxSize); - strrchr (path, '\\')[1] = 0; - return path; -} - - -char *GetConfigPath (char *fileName) -{ - static char path[MAX_PATH * 2] = { 0 }; - - if (IsNonInstallMode ()) - { - GetModPath (path, sizeof (path)); - strcat (path, fileName); - - return path; - } - - if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) - { - strcat (path, "\\TrueCrypt\\"); - CreateDirectory (path, NULL); - strcat (path, fileName); - } - else - path[0] = 0; - - return path; -} - -// Returns 0 if an error occurs or the drive letter (as an upper-case char) of the system partition (e.g. 'C'); -char GetSystemDriveLetter (void) -{ - char systemDir [MAX_PATH]; - - if (GetSystemDirectory (systemDir, sizeof (systemDir))) - return (toupper (systemDir [0])); - else - return 0; -} - -int Info (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONINFORMATION); -} - - -int InfoTopMost (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int InfoDirect (const wchar_t *msg) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, msg, lpszTitle, MB_ICONINFORMATION); -} - - -int Warning (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING); -} - - -int WarningTopMost (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int WarningDirect (const wchar_t *warnMsg) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, warnMsg, lpszTitle, MB_ICONWARNING); -} - - -int Error (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR); -} - - -int ErrorTopMost (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int ErrorDirect (const wchar_t *errMsg) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, errMsg, lpszTitle, MB_ICONERROR); -} - - -int AskYesNo (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskNoYes (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); -} - - -int AskOkCancel (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_OKCANCEL | MB_DEFBUTTON1); -} - - -int AskWarnYesNo (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskWarnNoYes (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); -} - - -int AskWarnNoYesString (wchar_t *string) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); -} - - -int AskWarnYesNoString (wchar_t *string) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskWarnOkCancel (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1); -} - - -int AskWarnCancelOk (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2); -} - - -int AskErrYesNo (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskErrNoYes (char *stringId) -{ - if (Silent) return 0; - return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON2); -} - - -// The function accepts two input formats: -// Input format 1: {0, "MESSAGE_STRING_ID", "BUTTON_1_STRING_ID", ... "LAST_BUTTON_STRING_ID", 0}; -// Input format 2: {L"", L"Message text", L"Button caption 1", ... L"Last button caption", 0}; -// The second format is to be used if any of the strings contains format specification (e.g. %s, %d) or -// in any other cases where a string needs to be resolved before calling this function. -// If the returned value is 0, the user closed the dialog window without making a choice. -// If the user made a choice, the returned value is the ordinal number of the choice (1..MAX_MULTI_CHOICES) -int AskMultiChoice (void *strings[], BOOL bBold) -{ - MULTI_CHOICE_DLGPROC_PARAMS params; - - params.strings = &strings[0]; - params.bold = bBold; - - return DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_MULTI_CHOICE_DLG), MainDlg, - (DLGPROC) MultiChoiceDialogProc, (LPARAM) ¶ms); -} - - -BOOL ConfigWriteBegin () -{ - DWORD size; - if (ConfigFileHandle != NULL) - return FALSE; - - if (ConfigBuffer == NULL) - ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); - - ConfigFileHandle = fopen (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), "w"); - if (ConfigFileHandle == NULL) - { - free (ConfigBuffer); - ConfigBuffer = NULL; - return FALSE; - } - XmlWriteHeader (ConfigFileHandle); - fputs ("\n\t", ConfigFileHandle); - - return TRUE; -} - - -BOOL ConfigWriteEnd () -{ - char *xml = ConfigBuffer; - char key[128], value[2048]; - - if (ConfigFileHandle == NULL) return FALSE; - - // Write unmodified values - while (xml && (xml = XmlFindElement (xml, "config"))) - { - XmlGetAttributeText (xml, "key", key, sizeof (key)); - XmlGetNodeText (xml, value, sizeof (value)); - - fprintf (ConfigFileHandle, "\n\t\t%s", key, value); - xml++; - } - - fputs ("\n\t", ConfigFileHandle); - XmlWriteFooter (ConfigFileHandle); - - TCFlushFile (ConfigFileHandle); - - fclose (ConfigFileHandle); - ConfigFileHandle = NULL; - - if (ConfigBuffer != NULL) - { - DWORD size; - free (ConfigBuffer); - ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); - } - - return TRUE; -} - - -BOOL ConfigWriteString (char *configKey, char *configValue) -{ - char *c; - if (ConfigFileHandle == NULL) - return FALSE; - - // Mark previous config value as updated - if (ConfigBuffer != NULL) - { - c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); - if (c != NULL) - c[1] = '!'; - } - - return 0 != fprintf ( - ConfigFileHandle, "\n\t\t%s", - configKey, configValue); -} - - -BOOL ConfigWriteInt (char *configKey, int configValue) -{ - char val[32]; - sprintf (val, "%d", configValue); - return ConfigWriteString (configKey, val); -} - - -static BOOL ConfigRead (char *configKey, char *configValue, int maxValueSize) -{ - DWORD size; - char *xml; - - if (ConfigBuffer == NULL) - ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); - - xml = ConfigBuffer; - if (xml != NULL) - { - xml = XmlFindElementByAttributeValue (xml, "config", "key", configKey); - if (xml != NULL) - { - XmlGetNodeText (xml, configValue, maxValueSize); - return TRUE; - } - } - - return FALSE; -} - - -int ConfigReadInt (char *configKey, int defaultValue) -{ - char s[32]; - - if (ConfigRead (configKey, s, sizeof (s))) - return atoi (s); - else - return defaultValue; -} - - -char *ConfigReadString (char *configKey, char *defaultValue, char *str, int maxLen) -{ - if (ConfigRead (configKey, str, maxLen)) - return str; - else - return defaultValue; -} - - -void OpenPageHelp (HWND hwndDlg, int nPage) -{ - int r = (int)ShellExecute (NULL, "open", szHelpFile, NULL, NULL, SW_SHOWNORMAL); - - if (r == ERROR_FILE_NOT_FOUND) - { - // Try the secondary help file - r = (int)ShellExecute (NULL, "open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL); - - if (r == ERROR_FILE_NOT_FOUND) - { - OpenOnlineHelp (); - return; - } - } - - if (r == SE_ERR_NOASSOC) - { - if (AskYesNo ("HELP_READER_ERROR") == IDYES) - OpenOnlineHelp (); - } -} - - -void OpenOnlineHelp () -{ - Applink ("help", TRUE, ""); -} - - -#ifndef SETUP - -void RestoreDefaultKeyFilesParam (void) -{ - KeyFileRemoveAll (&FirstKeyFile); - if (defaultKeyFilesParam.FirstKeyFile != NULL) - { - FirstKeyFile = KeyFileCloneAll (defaultKeyFilesParam.FirstKeyFile); - KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; - } - else - KeyFilesEnable = FALSE; -} - - -BOOL LoadDefaultKeyFilesParam (void) -{ - BOOL status = TRUE; - DWORD size; - char *defaultKeyfilesFile = LoadFile (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES), &size); - char *xml = defaultKeyfilesFile; - KeyFile *kf; - - if (xml == NULL) - return FALSE; - - KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); - - while (xml = XmlFindElement (xml, "keyfile")) - { - kf = (KeyFile *) malloc (sizeof (KeyFile)); - - if (XmlGetNodeText (xml, kf->FileName, sizeof (kf->FileName)) != NULL) - defaultKeyFilesParam.FirstKeyFile = KeyFileAdd (defaultKeyFilesParam.FirstKeyFile, kf); - else - free (kf); - - xml++; - } - - free (defaultKeyfilesFile); - KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; - - return status; -} - -#endif /* #ifndef SETUP */ - - -void Debug (char *format, ...) -{ - char buf[1024]; - va_list val; - - va_start(val, format); - _vsnprintf (buf, sizeof (buf), format, val); - va_end(val); - - OutputDebugString (buf); -} - - -void DebugMsgBox (char *format, ...) -{ - char buf[1024]; - va_list val; - - va_start(val, format); - _vsnprintf (buf, sizeof (buf), format, val); - va_end(val); - - MessageBox (MainDlg, buf, "TrueCrypt debug", 0); -} - - -BOOL IsOSAtLeast (OSVersionEnum reqMinOS) -{ - return IsOSVersionAtLeast (reqMinOS, 0); -} - - -// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack. -// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE. -// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE. -// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE. -BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack) -{ - int major, minor; - - switch (reqMinOS) - { - case WIN_2000: major = 5; minor = 0; break; - case WIN_XP: major = 5; minor = 1; break; - case WIN_SERVER_2003: major = 5; minor = 2; break; - case WIN_VISTA: major = 6; minor = 0; break; - case WIN_7: major = 6; minor = 1; break; - - default: - TC_THROW_FATAL_EXCEPTION; - break; - } - - return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack) - >= (major << 16 | minor << 8 | reqMinServicePack)); -} - - -BOOL Is64BitOs () -{ - static BOOL isWow64 = FALSE; - static BOOL valid = FALSE; - typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process); - LPFN_ISWOW64PROCESS fnIsWow64Process; - - if (valid) - return isWow64; - - fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle("kernel32"), "IsWow64Process"); - - if (fnIsWow64Process != NULL) - if (!fnIsWow64Process (GetCurrentProcess(), &isWow64)) - isWow64 = FALSE; - - valid = TRUE; - return isWow64; -} - - -// Returns TRUE, if the currently running operating system is installed in a hidden volume. If it's not, or if -// there's an error, returns FALSE. -BOOL IsHiddenOSRunning (void) -{ - static BOOL statusCached = FALSE; - static BOOL hiddenOSRunning; - - if (!statusCached) - { - try - { - hiddenOSRunning = BootEncryption (MainDlg).IsHiddenSystemRunning(); - } - catch (...) - { - hiddenOSRunning = FALSE; - } - - statusCached = TRUE; - } - - return hiddenOSRunning; -} - - -BOOL RestartComputer (void) -{ - TOKEN_PRIVILEGES tokenPrivil; - HANDLE hTkn; - - if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn)) - { - return false; - } - - LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid); - tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - tokenPrivil.PrivilegeCount = 1; - - AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0); - if (GetLastError() != ERROR_SUCCESS) - return false; - - if (!ExitWindowsEx (EWX_REBOOT | EWX_FORCE, - SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) - return false; - - return true; -} - - -std::string GetWindowsEdition () -{ - string osname = "win"; - - OSVERSIONINFOEXA osVer; - osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXA); - GetVersionExA ((LPOSVERSIONINFOA) &osVer); - - BOOL home = (osVer.wSuiteMask & VER_SUITE_PERSONAL); - BOOL server = (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); - - HKEY hkey; - char productName[300] = {0}; - DWORD productNameSize = sizeof (productName); - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) - { - if (RegQueryValueEx (hkey, "ProductName", 0, 0, (LPBYTE) &productName, &productNameSize) != ERROR_SUCCESS || productNameSize < 1) - productName[0] = 0; - - RegCloseKey (hkey); - } - - switch (nCurrentOS) - { - case WIN_2000: - osname += "2000"; - break; - - case WIN_XP: - case WIN_XP64: - osname += "xp"; - osname += home ? "-home" : "-pro"; - break; - - case WIN_SERVER_2003: - osname += "2003"; - break; - - case WIN_VISTA: - osname += "vista"; - break; - - case WIN_SERVER_2008: - osname += "2008"; - break; - - case WIN_7: - osname += "7"; - break; - - default: - stringstream s; - s << CurrentOSMajor << "." << CurrentOSMinor; - osname += s.str(); - break; - } - - if (server) - osname += "-server"; - - if (IsOSAtLeast (WIN_VISTA)) - { - if (home) - osname += "-home"; - else if (strstr (productName, "Standard") != 0) - osname += "-standard"; - else if (strstr (productName, "Professional") != 0) - osname += "-pro"; - else if (strstr (productName, "Business") != 0) - osname += "-business"; - else if (strstr (productName, "Enterprise") != 0) - osname += "-enterprise"; - else if (strstr (productName, "Datacenter") != 0) - osname += "-datacenter"; - else if (strstr (productName, "Ultimate") != 0) - osname += "-ultimate"; - } - - if (GetSystemMetrics (SM_STARTER)) - osname += "-starter"; - else if (strstr (productName, "Basic") != 0) - osname += "-basic"; - - if (Is64BitOs()) - osname += "-x64"; - - if (CurrentOSServicePack > 0) - { - stringstream s; - s << "-sp" << CurrentOSServicePack; - osname += s.str(); - } - - return osname; -} - - -void Applink (char *dest, BOOL bSendOS, char *extraOutput) -{ - char url [MAX_URL_LENGTH]; - - ArrowWaitCursor (); - - sprintf_s (url, sizeof (url), TC_APPLINK "%s%s&dest=%s", bSendOS ? ("&os=" + GetWindowsEdition()).c_str() : "", extraOutput, dest); - ShellExecute (NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); - - Sleep (200); - NormalCursor (); -} - - -char *RelativePath2Absolute (char *szFileName) -{ - if (szFileName[0] != '\\' - && strchr (szFileName, ':') == 0 - && strstr (szFileName, "Volume{") != szFileName) - { - char path[MAX_PATH*2]; - GetCurrentDirectory (MAX_PATH, path); - - if (path[strlen (path) - 1] != '\\') - strcat (path, "\\"); - - strcat (path, szFileName); - strncpy (szFileName, path, MAX_PATH-1); - } - - return szFileName; -} - - -void HandleDriveNotReadyError () -{ - HKEY hkey = 0; - DWORD value = 0, size = sizeof (DWORD); - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\MountMgr", - 0, KEY_READ, &hkey) != ERROR_SUCCESS) - return; - - if (RegQueryValueEx (hkey, "NoAutoMount", 0, 0, (LPBYTE) &value, &size) == ERROR_SUCCESS - && value != 0) - Warning ("SYS_AUTOMOUNT_DISABLED"); - else if (nCurrentOS == WIN_VISTA && CurrentOSServicePack < 1) - Warning ("SYS_ASSIGN_DRIVE_LETTER"); - else - Error ("ERR_HARDWARE_ERROR"); - - RegCloseKey (hkey); -} - - -BOOL CALLBACK CloseTCWindowsEnum (HWND hwnd, LPARAM lParam) -{ - if (GetWindowLongPtr (hwnd, GWLP_USERDATA) == (LONG_PTR) 'TRUE') - { - char name[1024] = { 0 }; - GetWindowText (hwnd, name, sizeof (name) - 1); - if (hwnd != MainDlg && strstr (name, "TrueCrypt")) - { - PostMessage (hwnd, TC_APPMSG_CLOSE_BKG_TASK, 0, 0); - - if (DriverVersion < 0x0430) - PostMessage (hwnd, WM_ENDSESSION, 0, 0); - - PostMessage (hwnd, WM_CLOSE, 0, 0); - - if (lParam != 0) - *((BOOL *)lParam) = TRUE; - } - } - return TRUE; -} - -BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam) -{ - if (*(HWND *)lParam == hwnd) - return TRUE; - - if (GetWindowLongPtr (hwnd, GWLP_USERDATA) == (LONG_PTR) 'TRUE') - { - char name[32] = { 0 }; - GetWindowText (hwnd, name, sizeof (name) - 1); - if (hwnd != MainDlg && strcmp (name, "TrueCrypt") == 0) - { - if (lParam != 0) - *((HWND *)lParam) = hwnd; - } - } - return TRUE; -} - - -BYTE *MapResource (char *resourceType, int resourceId, PDWORD size) -{ - HGLOBAL hResL; - HRSRC hRes; - - hRes = FindResource (NULL, MAKEINTRESOURCE(resourceId), resourceType); - hResL = LoadResource (NULL, hRes); - - if (size != NULL) - *size = SizeofResource (NULL, hRes); - - return (BYTE *) LockResource (hResL); -} - - -void InconsistencyResolved (char *techInfo) -{ - wchar_t finalMsg[8024]; - - wsprintfW (finalMsg, GetString ("INCONSISTENCY_RESOLVED"), techInfo); - MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); -} - - -void ReportUnexpectedState (char *techInfo) -{ - wchar_t finalMsg[8024]; - - wsprintfW (finalMsg, GetString ("UNEXPECTED_STATE"), techInfo); - MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); -} - - -#ifndef SETUP - -int OpenVolume (OpenVolumeContext *context, const char *volumePath, Password *password, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader) -{ - int status = ERR_PARAMETER_INCORRECT; - int volumeType; - char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; - char szDosDevice[TC_MAX_PATH]; - char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - LARGE_INTEGER headerOffset; - DWORD dwResult; - - context->VolumeIsOpen = FALSE; - context->CryptoInfo = NULL; - context->HostFileHandle = INVALID_HANDLE_VALUE; - context->TimestampsValid = FALSE; - - CreateFullVolumePath (szDiskFile, volumePath, &context->IsDevice); - - if (context->IsDevice) - { - status = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE); - if (status != 0) - return status; - - preserveTimestamps = FALSE; - } - else - strcpy (szCFDevice, szDiskFile); - - if (preserveTimestamps) - write = TRUE; - - context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (context->HostFileHandle == INVALID_HANDLE_VALUE) - { - status = ERR_OS_ERROR; - goto error; - } - - if (context->IsDevice) - { - // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, - // the NTFS driver guards hidden sectors and prevents e.g. header backup restore after the user - // accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS, etc.) - - DeviceIoControl (context->HostFileHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwResult, NULL); - } - - context->VolumeIsOpen = TRUE; - - // Remember the container modification/creation date and time - if (!context->IsDevice && preserveTimestamps) - { - if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0) - { - context->TimestampsValid = FALSE; - Warning ("GETFILETIME_FAILED_GENERIC"); - } - else - context->TimestampsValid = TRUE; - } - - // Determine host size - if (context->IsDevice) - { - PARTITION_INFORMATION diskInfo; - - if (GetPartitionInfo (volumePath, &diskInfo)) - { - context->HostSize = diskInfo.PartitionLength.QuadPart; - } - else - { - DISK_GEOMETRY driveInfo; - - if (!DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) - { - status = ERR_OS_ERROR; - goto error; - } - - context->HostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; - } - - if (context->HostSize == 0) - { - status = ERR_VOL_SIZE_WRONG; - goto error; - } - } - else - { - LARGE_INTEGER fileSize; - if (!GetFileSizeEx (context->HostFileHandle, &fileSize)) - { - status = ERR_OS_ERROR; - goto error; - } - - context->HostSize = fileSize.QuadPart; - } - - for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++) - { - // Seek the volume header - switch (volumeType) - { - case TC_VOLUME_TYPE_NORMAL: - headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; - break; - - case TC_VOLUME_TYPE_HIDDEN: - if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > context->HostSize) - continue; - - headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_SIZE : TC_HIDDEN_VOLUME_HEADER_OFFSET; - break; - - case TC_VOLUME_TYPE_HIDDEN_LEGACY: - if (useBackupHeader) - { - status = ERR_PASSWORD_WRONG; - goto error; - } - - headerOffset.QuadPart = context->HostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; - break; - } - - if (!SetFilePointerEx ((HANDLE) context->HostFileHandle, headerOffset, NULL, FILE_BEGIN)) - { - status = ERR_OS_ERROR; - goto error; - } - - // Read volume header - DWORD bytesRead; - if (!ReadFile (context->HostFileHandle, buffer, sizeof (buffer), &bytesRead, NULL)) - { - status = ERR_OS_ERROR; - goto error; - } - - if (bytesRead != sizeof (buffer) - && context->IsDevice) - { - // If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the - // filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is - // shorter than the partition). This can happen for example after the user quick-formats a dismounted - // partition-hosted TrueCrypt volume and then tries to read the embedded backup header. - - memset (buffer, 0, sizeof (buffer)); - } - - // Decrypt volume header - status = ReadVolumeHeader (FALSE, buffer, password, &context->CryptoInfo, NULL); - - if (status == ERR_PASSWORD_WRONG) - continue; // Try next volume type - - break; - } - - if (status == ERR_SUCCESS) - return status; - -error: - DWORD sysError = GetLastError (); - - CloseVolume (context); - - SetLastError (sysError); - return status; -} - - -void CloseVolume (OpenVolumeContext *context) -{ - if (!context->VolumeIsOpen) - return; - - if (context->HostFileHandle != INVALID_HANDLE_VALUE) - { - // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). - if (context->TimestampsValid) - { - if (!SetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime)) - { - handleWin32Error (NULL); - Warning ("SETFILETIME_FAILED_PW"); - } - } - - CloseHandle (context->HostFileHandle); - context->HostFileHandle = INVALID_HANDLE_VALUE; - } - - if (context->CryptoInfo) - { - crypto_close (context->CryptoInfo); - context->CryptoInfo = NULL; - } - - context->VolumeIsOpen = FALSE; -} - - -int ReEncryptVolumeHeader (char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, BOOL wipeMode) -{ - CRYPTO_INFO *newCryptoInfo = NULL; - - RandSetHashFunction (cryptoInfo->pkcs5); - - if (Randinit() != ERR_SUCCESS) - return ERR_PARAMETER_INCORRECT; - - UserEnrichRandomPool (NULL); - - int status = CreateVolumeHeaderInMemory (bBoot, - buffer, - cryptoInfo->ea, - cryptoInfo->mode, - password, - cryptoInfo->pkcs5, - (char *) cryptoInfo->master_keydata, - &newCryptoInfo, - cryptoInfo->VolumeSize.Value, - cryptoInfo->hiddenVolume ? cryptoInfo->hiddenVolumeSize : 0, - cryptoInfo->EncryptedAreaStart.Value, - cryptoInfo->EncryptedAreaLength.Value, - cryptoInfo->RequiredProgramVersion, - cryptoInfo->HeaderFlags, - wipeMode); - - if (newCryptoInfo != NULL) - crypto_close (newCryptoInfo); - - return status; -} - -#endif // !SETUP - - -BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) -{ - // GlobalMemoryStatusEx() cannot be used to determine if a paging file is active - - char data[65536]; - DWORD size = sizeof (data); - - if (IsPagingFileWildcardActive()) - return TRUE; - - if (ReadLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", data, &size) - && size > 12 && !checkNonWindowsPartitionsOnly) - return TRUE; - - if (!IsAdmin()) - AbortProcess ("UAC_INIT_ERROR"); - - for (char drive = 'C'; drive <= 'Z'; ++drive) - { - // Query geometry of the drive first to prevent "no medium" pop-ups - string drivePath = "\\\\.\\X:"; - drivePath[4] = drive; - - if (checkNonWindowsPartitionsOnly) - { - char sysDir[MAX_PATH]; - if (GetSystemDirectory (sysDir, sizeof (sysDir)) != 0 && toupper (sysDir[0]) == drive) - continue; - } - - HANDLE handle = CreateFile (drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (handle == INVALID_HANDLE_VALUE) - continue; - - DISK_GEOMETRY driveInfo; - DWORD dwResult; - - if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) - { - CloseHandle (handle); - continue; - } - - CloseHandle (handle); - - // Test if a paging file exists and is locked by another process - string path = "X:\\pagefile.sys"; - path[0] = drive; - - handle = CreateFile (path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - - if (handle != INVALID_HANDLE_VALUE) - CloseHandle (handle); - else if (GetLastError() == ERROR_SHARING_VIOLATION) - return TRUE; - } - - return FALSE; -} - - -BOOL IsPagingFileWildcardActive () -{ - char pagingFiles[65536]; - DWORD size = sizeof (pagingFiles); - char *mmKey = "System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"; - - if (!ReadLocalMachineRegistryString (mmKey, "PagingFiles", pagingFiles, &size)) - { - size = sizeof (pagingFiles); - if (!ReadLocalMachineRegistryMultiString (mmKey, "PagingFiles", pagingFiles, &size)) - size = 0; - } - - return size > 0 && strstr (pagingFiles, "?:\\") == pagingFiles; -} - - -BOOL DisablePagingFile () -{ - char empty[] = { 0, 0 }; - return WriteLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", empty, sizeof (empty)); -} - - -std::wstring SingleStringToWide (const std::string &singleString) -{ - if (singleString.empty()) - return std::wstring(); - - WCHAR wbuf[65536]; - int wideLen = MultiByteToWideChar (CP_ACP, 0, singleString.c_str(), -1, wbuf, array_capacity (wbuf) - 1); - throw_sys_if (wideLen == 0); - - wbuf[wideLen] = 0; - return wbuf; -} - - -std::wstring Utf8StringToWide (const std::string &utf8String) -{ - if (utf8String.empty()) - return std::wstring(); - - WCHAR wbuf[65536]; - int wideLen = MultiByteToWideChar (CP_UTF8, 0, utf8String.c_str(), -1, wbuf, array_capacity (wbuf) - 1); - throw_sys_if (wideLen == 0); - - wbuf[wideLen] = 0; - return wbuf; -} - - -std::string WideToUtf8String (const std::wstring &wideString) -{ - if (wideString.empty()) - return std::string(); - - char buf[65536]; - int len = WideCharToMultiByte (CP_UTF8, 0, wideString.c_str(), -1, buf, array_capacity (buf) - 1, NULL, NULL); - throw_sys_if (len == 0); - - buf[len] = 0; - return buf; -} - - -std::string WideToSingleString (const std::wstring &wideString) -{ - if (wideString.empty()) - return std::string(); - - char buf[65536]; - int len = WideCharToMultiByte (CP_ACP, 0, wideString.c_str(), -1, buf, array_capacity (buf) - 1, NULL, NULL); - throw_sys_if (len == 0); - - buf[len] = 0; - return buf; -} - - -#ifndef SETUP - -BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - static string *password; - - switch (msg) - { - case WM_INITDIALOG: - { - password = (string *) lParam; - LocalizeDialog (hwndDlg, "IDD_TOKEN_PASSWORD"); - - wchar_t s[1024]; - wsprintfW (s, GetString ("ENTER_TOKEN_PASSWORD"), Utf8StringToWide (password->c_str()).c_str()); - SetWindowTextW (GetDlgItem (hwndDlg, IDT_TOKEN_PASSWORD_INFO), s); - - SendMessage (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), EM_LIMITTEXT, SecurityToken::MaxPasswordLength, 0); - - SetForegroundWindow (hwndDlg); - SetFocus (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD)); - } - return 0; - - case WM_COMMAND: - if (lw == IDCANCEL || lw == IDOK) - { - if (lw == IDOK) - { - wchar_t passwordWide[SecurityToken::MaxPasswordLength + 1]; - - if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), passwordWide, SecurityToken::MaxPasswordLength + 1) == 0) - { - handleWin32Error (hwndDlg); - break; - } - - char passwordUtf8[SecurityToken::MaxPasswordLength + 1]; - - int len = WideCharToMultiByte (CP_UTF8, 0, passwordWide, -1, passwordUtf8, array_capacity (passwordUtf8) - 1, nullptr, nullptr); - passwordUtf8[len] = 0; - *password = passwordUtf8; - - burn (passwordWide, sizeof (passwordWide)); - burn (passwordUtf8, sizeof (passwordUtf8)); - } - - // Attempt to wipe password stored in the input field buffer - char tmp[SecurityToken::MaxPasswordLength+1]; - memset (tmp, 'X', SecurityToken::MaxPasswordLength); - tmp[SecurityToken::MaxPasswordLength] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), tmp); - - EndDialog (hwndDlg, lw); - } - return 1; - } - - return 0; -} - - -struct NewSecurityTokenKeyfileDlgProcParams -{ - CK_SLOT_ID SlotId; - string Name; -}; - -static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static NewSecurityTokenKeyfileDlgProcParams *newParams; - - WORD lw = LOWORD (wParam); - switch (msg) - { - case WM_INITDIALOG: - { - newParams = (NewSecurityTokenKeyfileDlgProcParams *) lParam; - - WaitCursor(); - finally_do ({ NormalCursor(); }); - - list tokens; - - try - { - tokens = SecurityToken::GetAvailableTokens(); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - if (tokens.empty()) - { - Error ("NO_TOKENS_FOUND"); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - foreach (const SecurityTokenInfo &token, tokens) - { - wstringstream tokenLabel; - tokenLabel << L"[" << token.SlotId << L"] " << token.Label; - - AddComboPairW (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token.SlotId); - } - - ComboBox_SetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), 0); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), Utf8StringToWide (newParams->Name).c_str()); - return 1; - } - - case WM_COMMAND: - switch (lw) - { - case IDOK: - { - int selectedToken = ComboBox_GetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN)); - if (selectedToken == CB_ERR) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - newParams->SlotId = ComboBox_GetItemData (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), selectedToken); - - wchar_t name[1024]; - if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0) - { - try - { - newParams->Name = WideToUtf8String (name); - } - catch (...) { } - } - - EndDialog (hwndDlg, IDOK); - return 1; - } - - case IDCANCEL: - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - if (HIWORD (wParam) == EN_CHANGE) - { - wchar_t name[2]; - EnableWindow (GetDlgItem (hwndDlg, IDOK), (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0)); - return 1; - } - } - - return 0; -} - - -static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector &keyfiles) -{ - HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); - LVITEMW lvItem; - int line = 0; - - ListView_DeleteAllItems (tokenListControl); - - foreach (const SecurityTokenKeyfile &keyfile, keyfiles) - { - memset (&lvItem, 0, sizeof(lvItem)); - lvItem.mask = LVIF_TEXT; - lvItem.iItem = line++; - - stringstream s; - s << keyfile.SlotId; - - ListItemAdd (tokenListControl, lvItem.iItem, (char *) s.str().c_str()); - ListSubItemSetW (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile.Token.Label.c_str()); - ListSubItemSetW (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile.Id.c_str()); - } - - BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); - EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); - EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); -} - - -static list SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector &keyfiles) -{ - HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); - list selectedKeyfiles; - - int itemId = -1; - while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1) - { - selectedKeyfiles.push_back (keyfiles[itemId]); - } - - return selectedKeyfiles; -} - - -BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static list *selectedTokenKeyfiles; - static vector keyfiles; - - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - selectedTokenKeyfiles = (list *) lParam; - - LVCOLUMNW LvCol; - HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); - - LocalizeDialog (hwndDlg, selectedTokenKeyfiles ? "SELECT_TOKEN_KEYFILES" : "IDD_TOKEN_KEYFILES"); - - SendMessage (tokenListControl,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP - ); - - memset (&LvCol, 0, sizeof(LvCol)); - LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - LvCol.pszText = GetString ("TOKEN_SLOT_ID"); - LvCol.cx = CompensateXDPI (40); - LvCol.fmt = LVCFMT_CENTER; - SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 1, (LPARAM)&LvCol); - - LvCol.pszText = GetString ("TOKEN_NAME"); - LvCol.cx = CompensateXDPI (128); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 2, (LPARAM)&LvCol); - - LvCol.pszText = GetString ("TOKEN_DATA_OBJECT_LABEL"); - LvCol.cx = CompensateXDPI (180); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 3, (LPARAM)&LvCol); - - keyfiles.clear(); - - try - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - keyfiles = SecurityToken::GetAvailableKeyfiles(); - } - catch (UserAbort&) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - catch (Exception &e) - { - e.Show (hwndDlg); - - if (keyfiles.empty()) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - } - - SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); - return 1; - } - - case WM_COMMAND: - case WM_NOTIFY: - if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) - { - if (selectedTokenKeyfiles) - { - foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) - { - selectedTokenKeyfiles->push_back (SecurityTokenKeyfilePath (keyfile)); - } - } - - EndDialog (hwndDlg, IDOK); - return 1; - } - - if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) - { - BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); - EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); - EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); - return 1; - } - - switch (lw) - { - case IDCANCEL: - EndDialog (hwndDlg, IDCANCEL); - return 1; - - case IDC_IMPORT_KEYFILE: - { - char keyfilePath[TC_MAX_PATH]; - - if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE, NULL)) - { - DWORD keyfileSize; - byte *keyfileData = (byte *) LoadFile (keyfilePath, &keyfileSize); - if (!keyfileData) - { - handleWin32Error (hwndDlg); - return 1; - } - - if (keyfileSize != 0) - { - NewSecurityTokenKeyfileDlgProcParams newParams; - newParams.Name = WideToUtf8String (SingleStringToWide (keyfilePath)); - - size_t lastBackSlash = newParams.Name.find_last_of ('\\'); - if (lastBackSlash != string::npos) - newParams.Name = newParams.Name.substr (lastBackSlash + 1); - - if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_NEW_TOKEN_KEYFILE), hwndDlg, (DLGPROC) NewSecurityTokenKeyfileDlgProc, (LPARAM) &newParams) == IDOK) - { - vector keyfileDataVector (keyfileSize); - memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize); - - try - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); - - keyfiles = SecurityToken::GetAvailableKeyfiles(); - SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - burn (&keyfileDataVector.front(), keyfileSize); - } - } - else - { - SetLastError (ERROR_HANDLE_EOF); - handleWin32Error (hwndDlg); - } - - burn (keyfileData, keyfileSize); - TCfree (keyfileData); - } - - return 1; - } - - case IDC_EXPORT: - { - try - { - foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) - { - char keyfilePath[TC_MAX_PATH]; - - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL)) - break; - - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - vector keyfileData; - - SecurityToken::GetKeyfileData (keyfile, keyfileData); - - if (keyfileData.empty()) - { - SetLastError (ERROR_HANDLE_EOF); - handleWin32Error (hwndDlg); - return 1; - } - - finally_do_arg (vector *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); }); - - if (!SaveBufferToFile ((char *) &keyfileData.front(), keyfilePath, keyfileData.size(), FALSE)) - throw SystemException (); - } - - Info ("KEYFILE_EXPORTED"); - } - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - return 1; - } - - case IDC_DELETE: - { - if (AskNoYes ("CONFIRM_SEL_FILES_DELETE") == IDNO) - return 1; - - try - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) - { - SecurityToken::DeleteKeyfile (keyfile); - } - - keyfiles = SecurityToken::GetAvailableKeyfiles(); - SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - return 1; - } - } - - return 0; - } - return 0; -} - - -BOOL InitSecurityTokenLibrary () -{ - if (SecurityTokenLibraryPath[0] == 0) - { - Error ("NO_PKCS11_MODULE_SPECIFIED"); - return FALSE; - } - - struct PinRequestHandler : public GetPinFunctor - { - virtual void operator() (string &str) - { - if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PASSWORD), MainDlg, (DLGPROC) SecurityTokenPasswordDlgProc, (LPARAM) &str) == IDCANCEL) - throw UserAbort (SRC_POS); - - if (hCursor != NULL) - SetCursor (hCursor); - } - }; - - struct WarningHandler : public SendExceptionFunctor - { - virtual void operator() (const Exception &e) - { - e.Show (NULL); - } - }; - - try - { - SecurityToken::InitLibrary (SecurityTokenLibraryPath, auto_ptr (new PinRequestHandler), auto_ptr (new WarningHandler)); - } - catch (Exception &e) - { - e.Show (NULL); - Error ("PKCS11_MODULE_INIT_FAILED"); - return FALSE; - } - - return TRUE; -} - -#endif // !SETUP - -std::vector GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems) -{ - vector devices; - - for (int devNumber = 0; devNumber < 64; devNumber++) - { - for (int partNumber = 0; partNumber < 32; partNumber++) - { - stringstream strm; - strm << "\\Device\\Harddisk" << devNumber << "\\Partition" << partNumber; - string devPathStr (strm.str()); - const char *devPath = devPathStr.c_str(); - - OPEN_TEST_STRUCT openTest; - if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0)) - { - if (partNumber == 0) - break; - - continue; - } - - HostDevice device; - device.SystemNumber = devNumber; - device.Path = devPath; - - PARTITION_INFORMATION partInfo; - - if (GetPartitionInfo (devPath, &partInfo)) - device.Size = partInfo.PartitionLength.QuadPart; - - device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; - - if (!noDeviceProperties) - { - DISK_GEOMETRY geometry; - - wstringstream ws; - ws << devPathStr.c_str(); - int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str()); - - if (driveNumber >= 0) - { - device.MountPoint += (char) (driveNumber + 'A'); - device.MountPoint += ":"; - - wchar_t name[64]; - if (GetDriveLabel (driveNumber, name, sizeof (name))) - device.Name = name; - - if (GetSystemDriveLetter() == 'A' + driveNumber) - device.ContainsSystem = true; - } - - if (partNumber == 0 && GetDriveGeometry (devPath, &geometry)) - device.Removable = (geometry.MediaType == RemovableMedia); - } - - if (partNumber == 0) - { - devices.push_back (device); - } - else - { - HostDevice &dev0 = *--devices.end(); - - // System creates a virtual partition1 for some storage devices without - // partition table. We try to detect this case by comparing sizes of - // partition0 and partition1. If they match, no partition of the device - // is displayed to the user to avoid confusion. Drive letter assigned by - // system to partition1 is assigned partition0 - if (partNumber == 1 && dev0.Size == device.Size) - { - dev0.IsVirtualPartition = true; - dev0.MountPoint = device.MountPoint; - dev0.Name = device.Name; - dev0.Path = device.Path; - dev0.HasUnencryptedFilesystem = device.HasUnencryptedFilesystem; - break; - } - - device.IsPartition = true; - device.SystemNumber = partNumber; - device.Removable = dev0.Removable; - - if (device.ContainsSystem) - dev0.ContainsSystem = true; - - dev0.Partitions.push_back (device); - - if (singleList) - devices.push_back (device); - } - } - } - - // Vista does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices - if (CurrentOSMajor >= 6) - { - for (int devNumber = 0; devNumber < 256; devNumber++) - { - stringstream strm; - strm << "\\Device\\HarddiskVolume" << devNumber; - string devPathStr (strm.str()); - const char *devPath = devPathStr.c_str(); - - OPEN_TEST_STRUCT openTest; - if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems)) - continue; - - DISK_PARTITION_INFO_STRUCT info; - if (GetDeviceInfo (devPath, &info) && info.IsDynamic) - { - HostDevice device; - device.DynamicVolume = true; - device.IsPartition = true; - device.SystemNumber = devNumber; - device.Path = devPath; - device.Size = info.partInfo.PartitionLength.QuadPart; - device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; - - if (!noDeviceProperties) - { - wstringstream ws; - ws << devPathStr.c_str(); - int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str()); - - if (driveNumber >= 0) - { - device.MountPoint += (char) (driveNumber + 'A'); - device.MountPoint += ":"; - - wchar_t name[64]; - if (GetDriveLabel (driveNumber, name, sizeof (name))) - device.Name = name; - - if (GetSystemDriveLetter() == 'A' + driveNumber) - device.ContainsSystem = true; - } - } - - devices.push_back (device); - } - } - } - - // Floppy drives - if (!noFloppy) - { - HostDevice floppy; - floppy.Floppy = true; - - char path[TC_MAX_PATH]; - - if (QueryDosDevice ("A:", path, sizeof (path)) != 0 && GetDriveType ("A:\\") == DRIVE_REMOVABLE) - { - floppy.MountPoint = "A:"; - floppy.Path = "\\Device\\Floppy0"; - devices.push_back (floppy); - } - - if (QueryDosDevice ("B:", path, sizeof (path)) != 0 && GetDriveType ("B:\\") == DRIVE_REMOVABLE) - { - floppy.MountPoint = "B:"; - floppy.Path = "\\Device\\Floppy1"; - devices.push_back (floppy); - } - } - - return devices; -} - - -BOOL FileHasReadOnlyAttribute (const char *path) -{ - DWORD attributes = GetFileAttributes (path); - return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY) != 0; -} - - -BOOL IsFileOnReadOnlyFilesystem (const char *path) -{ - char root[MAX_PATH]; - if (!GetVolumePathName (path, root, sizeof (root))) - return FALSE; - - DWORD flags, d; - if (!GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) - return FALSE; - - return (flags & FILE_READ_ONLY_VOLUME) ? TRUE : FALSE; -} - - -void CheckFilesystem (int driveNo, BOOL fixErrors) -{ - wchar_t msg[1024], param[1024]; - char driveRoot[] = { 'A' + driveNo, ':', 0}; - - if (fixErrors && AskWarnYesNo ("FILESYS_REPAIR_CONFIRM_BACKUP") == IDNO) - return; - - wsprintfW (msg, GetString (fixErrors ? "REPAIRING_FS" : "CHECKING_FS"), driveRoot); - wsprintfW (param, fixErrors ? L"/C echo %s & chkdsk %hs /F /X & pause" : L"/C echo %s & chkdsk %hs & pause", msg, driveRoot); - - ShellExecuteW (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", L"cmd.exe", param, NULL, SW_SHOW); -} - - -BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str) -{ - size_t strLen = strlen (str); - - if (bufferSize < strLen) - return FALSE; - - bufferSize -= strLen; - - for (size_t i = 0; i < bufferSize; ++i) - { - if (memcmp (buffer + i, str, strLen) == 0) - return TRUE; - } - - return FALSE; -} - - -#ifndef SETUP - -int AskNonSysInPlaceEncryptionResume () -{ - if (AskWarnYesNo ("NONSYS_INPLACE_ENC_RESUME_PROMPT") == IDYES) - return IDYES; - - char *multiChoiceStr[] = { 0, "ASK_NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL", "DO_NOT_PROMPT_ME", "KEEP_PROMPTING_ME", 0 }; - - switch (AskMultiChoice ((void **) multiChoiceStr, FALSE)) - { - case 1: - RemoveNonSysInPlaceEncNotifications(); - Warning ("NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL_NOTE"); - break; - - default: - // NOP - break; - } - - return IDNO; -} - -#endif // !SETUP - - -BOOL RemoveDeviceWriteProtection (HWND hwndDlg, char *devicePath) -{ - int driveNumber; - int partitionNumber; - - char temp[MAX_PATH*2]; - char cmdBatch[MAX_PATH*2]; - char diskpartScript[MAX_PATH*2]; - - if (sscanf (devicePath, "\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2) - return FALSE; - - if (GetTempPath (sizeof (temp), temp) == 0) - return FALSE; - - _snprintf (cmdBatch, sizeof (cmdBatch), "%s\\TrueCrypt_Write_Protection_Removal.cmd", temp); - _snprintf (diskpartScript, sizeof (diskpartScript), "%s\\TrueCrypt_Write_Protection_Removal.diskpart", temp); - - FILE *f = fopen (cmdBatch, "w"); - if (!f) - { - handleWin32Error (hwndDlg); - return FALSE; - } - - fprintf (f, "@diskpart /s \"%s\"\n@pause\n@del \"%s\" \"%s\"", diskpartScript, diskpartScript, cmdBatch); - fclose (f); - - f = fopen (diskpartScript, "w"); - if (!f) - { - handleWin32Error (hwndDlg); - DeleteFile (cmdBatch); - return FALSE; - } - - fprintf (f, "select disk %d\nattributes disk clear readonly\n", driveNumber); - - if (partitionNumber != 0) - fprintf (f, "select partition %d\nattributes volume clear readonly\n", partitionNumber); - - fprintf (f, "exit\n"); - fclose (f); - - ShellExecute (NULL, (!IsAdmin() && IsUacSupported()) ? "runas" : "open", cmdBatch, NULL, NULL, SW_SHOW); - - return TRUE; -} - - -static LRESULT CALLBACK EnableElevatedCursorChangeWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProc (hWnd, message, wParam, lParam); -} - - -void EnableElevatedCursorChange (HWND parent) -{ - // Create a transparent window to work around a UAC issue preventing change of the cursor - if (UacElevated) - { - const char *className = "TrueCryptEnableElevatedCursorChange"; - WNDCLASSEX winClass; - HWND hWnd; - - memset (&winClass, 0, sizeof (winClass)); - winClass.cbSize = sizeof (WNDCLASSEX); - winClass.lpfnWndProc = (WNDPROC) EnableElevatedCursorChangeWndProc; - winClass.hInstance = hInst; - winClass.lpszClassName = className; - RegisterClassEx (&winClass); - - hWnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_LAYERED, className, "TrueCrypt UAC", 0, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), parent, NULL, hInst, NULL); - SetLayeredWindowAttributes (hWnd, 0, 1, LWA_ALPHA); - ShowWindow (hWnd, SW_SHOWNORMAL); - - DestroyWindow (hWnd); - UnregisterClass (className, hInst); - } -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Resource.h" + +#include "Platform/Finally.h" +#include "Platform/ForEach.h" +#include "Apidrvr.h" +#include "BootEncryption.h" +#include "Combo.h" +#include "Crc.h" +#include "Crypto.h" +#include "Dictionary.h" +#include "Dlgcode.h" +#include "EncryptionThreadPool.h" +#include "Endian.h" +#include "Format/Inplace.h" +#include "Language.h" +#include "Keyfiles.h" +#include "Pkcs5.h" +#include "Random.h" +#include "Registry.h" +#include "SecurityToken.h" +#include "Tests.h" +#include "Volumes.h" +#include "Wipe.h" +#include "Xml.h" +#include "Xts.h" +#include "Boot/Windows/BootCommon.h" + +#ifdef TCMOUNT +#include "Mount/Mount.h" +#endif + +#ifdef VOLFORMAT +#include "Format/Tcformat.h" +#endif + +#ifdef SETUP +#include "Setup/Setup.h" +#endif + +using namespace TrueCrypt; + +LONG DriverVersion; + +char *LastDialogId; +char szHelpFile[TC_MAX_PATH]; +char szHelpFile2[TC_MAX_PATH]; +char SecurityTokenLibraryPath[TC_MAX_PATH]; + +HFONT hFixedDigitFont = NULL; +HFONT hBoldFont = NULL; +HFONT hTitleFont = NULL; +HFONT hFixedFont = NULL; + +HFONT hUserFont = NULL; +HFONT hUserUnderlineFont = NULL; +HFONT hUserBoldFont = NULL; +HFONT hUserUnderlineBoldFont = NULL; + +HFONT WindowTitleBarFont; + +int ScreenDPI = USER_DEFAULT_SCREEN_DPI; +double DPIScaleFactorX = 1; +double DPIScaleFactorY = 1; +double DlgAspectRatio = 1; + +HWND MainDlg = NULL; +wchar_t *lpszTitle = NULL; + +BOOL Silent = FALSE; +BOOL bPreserveTimestamp = TRUE; +BOOL bStartOnLogon = FALSE; +BOOL bMountDevicesOnLogon = FALSE; +BOOL bMountFavoritesOnLogon = FALSE; + +BOOL bHistory = FALSE; + +// Status of detection of hidden sectors (whole-system-drive encryption). +// 0 - Unknown/undetermined/completed, 1: Detection is or was in progress (but did not complete e.g. due to system crash). +int HiddenSectorDetectionStatus = 0; + +OSVersionEnum nCurrentOS = WIN_UNKNOWN; +int CurrentOSMajor = 0; +int CurrentOSMinor = 0; +int CurrentOSServicePack = 0; +BOOL RemoteSession = FALSE; +BOOL UacElevated = FALSE; + +BOOL bPortableModeConfirmed = FALSE; // TRUE if it is certain that the instance is running in portable mode + +BOOL bInPlaceEncNonSysPending = FALSE; // TRUE if the non-system in-place encryption config file indicates that one or more partitions are scheduled to be encrypted. This flag is set only when config files are loaded during app startup. + +/* Globals used by Mount and Format (separately per instance) */ +BOOL KeyFilesEnable = FALSE; +KeyFile *FirstKeyFile = NULL; +KeyFilesDlgParam defaultKeyFilesParam; + +BOOL IgnoreWmDeviceChange = FALSE; +BOOL DeviceChangeBroadcastDisabled = FALSE; +BOOL LastMountedVolumeDirty; +BOOL MountVolumesAsSystemFavorite = FALSE; + +/* Handle to the device driver */ +HANDLE hDriver = INVALID_HANDLE_VALUE; + +/* This mutex is used to prevent multiple instances of the wizard or main app from dealing with system encryption */ +volatile HANDLE hSysEncMutex = NULL; + +/* This mutex is used for non-system in-place encryption but only for informative (non-blocking) purposes, +such as whether an app should prompt the user whether to resume scheduled process. */ +volatile HANDLE hNonSysInplaceEncMutex = NULL; + +/* This mutex is used to prevent multiple instances of the wizard or main app from trying to install or +register the driver or from trying to launch it in portable mode at the same time. */ +volatile HANDLE hDriverSetupMutex = NULL; + +/* This mutex is used to prevent users from running the main TrueCrypt app or the wizard while an instance +of the TrueCrypt installer is running (which is also useful for enforcing restart before the apps can be used). */ +volatile HANDLE hAppSetupMutex = NULL; + +HINSTANCE hInst = NULL; +HCURSOR hCursor = NULL; + +ATOM hDlgClass, hSplashClass; + +/* This value may changed only by calling ChangeSystemEncryptionStatus(). Only the wizard can change it +(others may still read it though). */ +int SystemEncryptionStatus = SYSENC_STATUS_NONE; + +/* Only the wizard can change this value (others may only read it). */ +WipeAlgorithmId nWipeMode = TC_WIPE_NONE; + +BOOL bSysPartitionSelected = FALSE; /* TRUE if the user selected the system partition via the Select Device dialog */ +BOOL bSysDriveSelected = FALSE; /* TRUE if the user selected the system drive via the Select Device dialog */ + +/* To populate these arrays, call GetSysDevicePaths(). If they contain valid paths, bCachedSysDevicePathsValid is TRUE. */ +char SysPartitionDevicePath [TC_MAX_PATH]; +char SysDriveDevicePath [TC_MAX_PATH]; +char bCachedSysDevicePathsValid = FALSE; + +BOOL bHyperLinkBeingTracked = FALSE; + +int WrongPwdRetryCounter = 0; + +static FILE *ConfigFileHandle; +char *ConfigBuffer; + +#define RANDPOOL_DISPLAY_REFRESH_INTERVAL 30 +#define RANDPOOL_DISPLAY_ROWS 20 +#define RANDPOOL_DISPLAY_COLUMNS 32 + +/* Windows dialog class */ +#define WINDOWS_DIALOG_CLASS "#32770" + +/* Custom class names */ +#define TC_DLG_CLASS "CustomDlg" +#define TC_SPLASH_CLASS "SplashDlg" + +/* Benchmarks */ + +#ifndef SETUP + +#define BENCHMARK_MAX_ITEMS 100 +#define BENCHMARK_DEFAULT_BUF_SIZE BYTES_PER_MB +#define HASH_FNC_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. +#define PKCS5_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. +#if PKCS5_BENCHMARKS && HASH_FNC_BENCHMARKS +#error PKCS5_BENCHMARKS and HASH_FNC_BENCHMARKS are both TRUE (at least one of them should be FALSE). +#endif + +enum +{ + BENCHMARK_SORT_BY_NAME = 0, + BENCHMARK_SORT_BY_SPEED +}; + +typedef struct +{ + int id; + char name[100]; + unsigned __int64 encSpeed; + unsigned __int64 decSpeed; + unsigned __int64 meanBytesPerSec; +} BENCHMARK_REC; + +BENCHMARK_REC benchmarkTable [BENCHMARK_MAX_ITEMS]; +int benchmarkTotalItems = 0; +int benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; +int benchmarkLastBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; +int benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; +LARGE_INTEGER benchmarkPerformanceFrequency; + +#endif // #ifndef SETUP + + +typedef struct +{ + void *strings; + BOOL bold; + +} MULTI_CHOICE_DLGPROC_PARAMS; + + +void cleanup () +{ + /* Cleanup the GDI fonts */ + if (hFixedFont != NULL) + DeleteObject (hFixedFont); + if (hFixedDigitFont != NULL) + DeleteObject (hFixedDigitFont); + if (hBoldFont != NULL) + DeleteObject (hBoldFont); + if (hTitleFont != NULL) + DeleteObject (hTitleFont); + if (hUserFont != NULL) + DeleteObject (hUserFont); + if (hUserUnderlineFont != NULL) + DeleteObject (hUserUnderlineFont); + if (hUserBoldFont != NULL) + DeleteObject (hUserBoldFont); + if (hUserUnderlineBoldFont != NULL) + DeleteObject (hUserUnderlineBoldFont); + + /* Cleanup our dialog class */ + if (hDlgClass) + UnregisterClass (TC_DLG_CLASS, hInst); + if (hSplashClass) + UnregisterClass (TC_SPLASH_CLASS, hInst); + + /* Close the device driver handle */ + if (hDriver != INVALID_HANDLE_VALUE) + { + // Unload driver mode if possible (non-install mode) + if (IsNonInstallMode ()) + { + // If a dismount was forced in the lifetime of the driver, Windows may later prevent it to be loaded again from + // the same path. Therefore, the driver will not be unloaded even though it was loaded in non-install mode. + int refDevDeleted; + DWORD dwResult; + + if (!DeviceIoControl (hDriver, TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED, NULL, 0, &refDevDeleted, sizeof (refDevDeleted), &dwResult, NULL)) + refDevDeleted = 0; + + if (!refDevDeleted) + DriverUnload (); + else + { + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + } + } + else + { + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + } + } + + if (ConfigBuffer != NULL) + { + free (ConfigBuffer); + ConfigBuffer = NULL; + } + + CoUninitialize (); + + CloseSysEncMutex (); + +#ifndef SETUP + try + { + if (SecurityToken::IsInitialized()) + SecurityToken::CloseLibrary(); + } + catch (...) { } + + EncryptionThreadPoolStop(); +#endif +} + + +void LowerCaseCopy (char *lpszDest, const char *lpszSource) +{ + int i = strlen (lpszSource); + + lpszDest[i] = 0; + while (--i >= 0) + { + lpszDest[i] = (char) tolower (lpszSource[i]); + } + +} + +void UpperCaseCopy (char *lpszDest, const char *lpszSource) +{ + int i = strlen (lpszSource); + + lpszDest[i] = 0; + while (--i >= 0) + { + lpszDest[i] = (char) toupper (lpszSource[i]); + } +} + + +std::string ToUpperCase (const std::string &str) +{ + string u; + foreach (char c, str) + { + u += (char) toupper (c); + } + + return u; +} + + +BOOL IsVolumeDeviceHosted (char *lpszDiskFile) +{ + return strstr (lpszDiskFile, "\\Device\\") == lpszDiskFile + || strstr (lpszDiskFile, "\\DEVICE\\") == lpszDiskFile; +} + + +void CreateFullVolumePath (char *lpszDiskFile, const char *lpszFileName, BOOL * bDevice) +{ + UpperCaseCopy (lpszDiskFile, lpszFileName); + + *bDevice = FALSE; + + if (memcmp (lpszDiskFile, "\\DEVICE", sizeof (char) * 7) == 0) + { + *bDevice = TRUE; + } + + strcpy (lpszDiskFile, lpszFileName); + +#if _DEBUG + OutputDebugString ("CreateFullVolumePath: "); + OutputDebugString (lpszDiskFile); + OutputDebugString ("\n"); +#endif + +} + +int FakeDosNameForDevice (const char *lpszDiskFile, char *lpszDosDevice, char *lpszCFDevice, BOOL bNameOnly) +{ + BOOL bDosLinkCreated = TRUE; + sprintf (lpszDosDevice, "truecrypt%lu", GetCurrentProcessId ()); + + if (bNameOnly == FALSE) + bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); + + if (bDosLinkCreated == FALSE) + return ERR_OS_ERROR; + else + sprintf (lpszCFDevice, "\\\\.\\%s", lpszDosDevice); + + return 0; +} + +int RemoveFakeDosName (char *lpszDiskFile, char *lpszDosDevice) +{ + BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | + DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); + if (bDosLinkRemoved == FALSE) + { + return ERR_OS_ERROR; + } + + return 0; +} + + +void AbortProcess (char *stringId) +{ + // Note that this function also causes localcleanup() to be called (see atexit()) + MessageBeep (MB_ICONEXCLAMATION); + MessageBoxW (NULL, GetString (stringId), lpszTitle, ICON_HAND); + exit (1); +} + +void AbortProcessSilent (void) +{ + // Note that this function also causes localcleanup() to be called (see atexit()) + exit (1); +} + + +#pragma warning(push) +#pragma warning(disable:4702) + +void *err_malloc (size_t size) +{ + void *z = (void *) TCalloc (size); + if (z) + return z; + AbortProcess ("OUTOFMEMORY"); + return 0; +} + +#pragma warning(pop) + + +char *err_strdup (char *lpszText) +{ + int j = (strlen (lpszText) + 1) * sizeof (char); + char *z = (char *) err_malloc (j); + memmove (z, lpszText, j); + return z; +} + + +BOOL IsDiskReadError (DWORD error) +{ + return (error == ERROR_CRC + || error == ERROR_IO_DEVICE + || error == ERROR_BAD_CLUSTERS + || error == ERROR_SECTOR_NOT_FOUND + || error == ERROR_READ_FAULT + || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers + || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT +} + + +BOOL IsDiskWriteError (DWORD error) +{ + return (error == ERROR_IO_DEVICE + || error == ERROR_BAD_CLUSTERS + || error == ERROR_SECTOR_NOT_FOUND + || error == ERROR_WRITE_FAULT + || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers + || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT +} + + +BOOL IsDiskError (DWORD error) +{ + return IsDiskReadError (error) || IsDiskWriteError (error); +} + + +DWORD handleWin32Error (HWND hwndDlg) +{ + PWSTR lpMsgBuf; + DWORD dwError = GetLastError (); + + if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) + return dwError; + + // Access denied + if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) + { + Error ("ERR_ACCESS_DENIED"); + SetLastError (dwError); // Preserve the original error code + return dwError; + } + + FormatMessageW ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (PWSTR) &lpMsgBuf, + 0, + NULL + ); + + MessageBoxW (hwndDlg, lpMsgBuf, lpszTitle, ICON_HAND); + LocalFree (lpMsgBuf); + + // User-friendly hardware error explanation + if (IsDiskError (dwError)) + Error ("ERR_HARDWARE_ERROR"); + + // Device not ready + if (dwError == ERROR_NOT_READY) + HandleDriveNotReadyError(); + + SetLastError (dwError); // Preserve the original error code + + return dwError; +} + +BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf) +{ + DWORD dwError = GetLastError (); + + if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + lpszMsgBuf, nWSizeOfBuf, NULL)) + { + SetLastError (dwError); // Preserve the original error code + return TRUE; + } + + SetLastError (dwError); // Preserve the original error code + return FALSE; +} + + +// If the user has a non-default screen DPI, all absolute font sizes must be +// converted using this function. +int CompensateDPIFont (int val) +{ + if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) + return val; + else + { + double tmpVal = (double) val * DPIScaleFactorY * DlgAspectRatio * 0.999; + + if (tmpVal > 0) + return (int) floor(tmpVal); + else + return (int) ceil(tmpVal); + } +} + + +// If the user has a non-default screen DPI, some screen coordinates and sizes must +// be converted using this function +int CompensateXDPI (int val) +{ + if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) + return val; + else + { + double tmpVal = (double) val * DPIScaleFactorX; + + if (tmpVal > 0) + return (int) floor(tmpVal); + else + return (int) ceil(tmpVal); + } +} + + +// If the user has a non-default screen DPI, some screen coordinates and sizes must +// be converted using this function +int CompensateYDPI (int val) +{ + if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) + return val; + else + { + double tmpVal = (double) val * DPIScaleFactorY; + + if (tmpVal > 0) + return (int) floor(tmpVal); + else + return (int) ceil(tmpVal); + } +} + + +int GetTextGfxWidth (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) +{ + SIZE sizes; + TEXTMETRIC textMetrics; + HDC hdc = GetDC (hwndDlgItem); + + SelectObject(hdc, (HGDIOBJ) hFont); + + GetTextExtentPoint32W (hdc, text, wcslen (text), &sizes); + + GetTextMetrics(hdc, &textMetrics); // Necessary for non-TrueType raster fonts (tmOverhang) + + ReleaseDC (hwndDlgItem, hdc); + + return ((int) sizes.cx - (int) textMetrics.tmOverhang); +} + + +int GetTextGfxHeight (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) +{ + SIZE sizes; + HDC hdc = GetDC (hwndDlgItem); + + SelectObject(hdc, (HGDIOBJ) hFont); + + GetTextExtentPoint32W (hdc, text, wcslen (text), &sizes); + + ReleaseDC (hwndDlgItem, hdc); + + return ((int) sizes.cy); +} + + +std::string FitPathInGfxWidth (HWND hwnd, HFONT hFont, LONG width, const std::string &path) +{ + string newPath; + + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = width; + rect.bottom = LONG_MAX; + + HDC hdc = GetDC (hwnd); + SelectObject (hdc, (HGDIOBJ) hFont); + + char pathBuf[TC_MAX_PATH]; + strcpy_s (pathBuf, sizeof (pathBuf), path.c_str()); + + if (DrawText (hdc, pathBuf, path.size(), &rect, DT_CALCRECT | DT_MODIFYSTRING | DT_PATH_ELLIPSIS | DT_SINGLELINE) != 0) + newPath = pathBuf; + + ReleaseDC (hwnd, hdc); + return newPath; +} + + +static LRESULT CALLBACK HyperlinkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WNDPROC wp = (WNDPROC) GetWindowLongPtr (hwnd, GWL_USERDATA); + + switch (message) + { + case WM_SETCURSOR: + if (!bHyperLinkBeingTracked) + { + TRACKMOUSEEVENT trackMouseEvent; + + trackMouseEvent.cbSize = sizeof(trackMouseEvent); + trackMouseEvent.dwFlags = TME_LEAVE; + trackMouseEvent.hwndTrack = hwnd; + + bHyperLinkBeingTracked = TrackMouseEvent(&trackMouseEvent); + + HandCursor(); + } + return 0; + + case WM_MOUSELEAVE: + bHyperLinkBeingTracked = FALSE; + NormalCursor(); + return 0; + } + + return CallWindowProc (wp, hwnd, message, wParam, lParam); +} + + +BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId) +{ + HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); + + SendMessage (hwndCtrl, WM_SETFONT, (WPARAM) hUserUnderlineFont, 0); + + SetWindowLongPtr (hwndCtrl, GWL_USERDATA, (LONG_PTR) GetWindowLongPtr (hwndCtrl, GWL_WNDPROC)); + SetWindowLongPtr (hwndCtrl, GWL_WNDPROC, (LONG_PTR) HyperlinkProc); + + // Resize the field according to its actual length in pixels and move it if centered or right-aligned. + // This should be done again if the link text changes. + AccommodateTextField (hwndDlg, ctrlId, TRUE); + + return TRUE; +} + + +// Resizes a text field according to its actual width in pixels (font size is taken into account) and moves +// it accordingly if the field is centered or right-aligned. Should be used on all hyperlinks upon dialog init +// after localization (bFirstUpdate should be TRUE) and later whenever a hyperlink text changes (bFirstUpdate +// must be FALSE). +void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate) +{ + RECT rec, wrec, trec; + HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); + int width, origWidth, origHeight; + int horizSubOffset, vertOffset, alignPosDiff = 0; + wchar_t text [MAX_URL_LENGTH]; + WINDOWINFO windowInfo; + BOOL bBorderlessWindow = !(GetWindowLongPtr (hwndDlg, GWL_STYLE) & (WS_BORDER | WS_DLGFRAME)); + + // Resize the field according to its length and font size and move if centered or right-aligned + + GetWindowTextW (hwndCtrl, text, sizeof (text) / sizeof (wchar_t)); + + width = GetTextGfxWidth (hwndCtrl, text, hUserUnderlineFont); + + GetClientRect (hwndCtrl, &rec); + origWidth = rec.right; + origHeight = rec.bottom; + + if (width >= 0 + && (!bFirstUpdate || origWidth > width)) // The original width of the field is the maximum allowed size + { + horizSubOffset = origWidth - width; + + // Window coords + GetWindowRect(hwndDlg, &wrec); + GetClientRect(hwndDlg, &trec); + + // Vertical "title bar" offset + vertOffset = wrec.bottom - wrec.top - trec.bottom - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CYFIXEDFRAME)); + + // Text field coords + GetWindowRect(hwndCtrl, &rec); + + // Alignment offset + windowInfo.cbSize = sizeof(windowInfo); + GetWindowInfo (hwndCtrl, &windowInfo); + + if (windowInfo.dwStyle & SS_CENTER) + alignPosDiff = horizSubOffset / 2; + else if (windowInfo.dwStyle & SS_RIGHT) + alignPosDiff = horizSubOffset; + + // Resize/move + if (alignPosDiff > 0) + { + // Resize and move the text field + MoveWindow (hwndCtrl, + rec.left - wrec.left - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CXFIXEDFRAME)) + alignPosDiff, + rec.top - wrec.top - vertOffset, + origWidth - horizSubOffset, + origHeight, + TRUE); + } + else + { + // Resize the text field + SetWindowPos (hwndCtrl, 0, 0, 0, + origWidth - horizSubOffset, + origHeight, + SWP_NOMOVE | SWP_NOZORDER); + } + + SetWindowPos (hwndCtrl, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + InvalidateRect (hwndCtrl, NULL, TRUE); + } +} + + +// Protects an input field from having its content updated by a Paste action (call ToBootPwdField() to use this). +static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WNDPROC wp = (WNDPROC) GetWindowLongPtr (hwnd, GWL_USERDATA); + + switch (message) + { + case WM_PASTE: + return 1; + } + + return CallWindowProc (wp, hwnd, message, wParam, lParam); +} + + +// Protects an input field from having its content updated by a Paste action. Used for pre-boot password +// input fields (only the US keyboard layout is supported in pre-boot environment so we must prevent the +// user from pasting a password typed using a non-US keyboard layout). +void ToBootPwdField (HWND hwndDlg, UINT ctrlId) +{ + HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); + + SetWindowLongPtr (hwndCtrl, GWL_USERDATA, (LONG_PTR) GetWindowLongPtr (hwndCtrl, GWL_WNDPROC)); + SetWindowLongPtr (hwndCtrl, GWL_WNDPROC, (LONG_PTR) BootPwdFieldProc); +} + + + +// This function currently serves the following purposes: +// - Determines scaling factors for current screen DPI and GUI aspect ratio. +// - Determines how Windows skews the GUI aspect ratio (which happens when the user has a non-default DPI). +// The determined values must be used when performing some GUI operations and calculations. +BOOL CALLBACK AuxiliaryDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + HDC hDC = GetDC (hwndDlg); + + ScreenDPI = GetDeviceCaps (hDC, LOGPIXELSY); + ReleaseDC (hwndDlg, hDC); + + DPIScaleFactorX = 1; + DPIScaleFactorY = 1; + DlgAspectRatio = 1; + + if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) + { + // Windows skews the GUI aspect ratio if the user has a non-default DPI. Hence, working with + // actual screen DPI is redundant and leads to incorrect results. What really matters here is + // how Windows actually renders our GUI. This is determined by comparing the expected and current + // sizes of a hidden calibration text field. + + RECT trec; + + trec.right = 0; + trec.bottom = 0; + + GetClientRect (GetDlgItem (hwndDlg, IDC_ASPECT_RATIO_CALIBRATION_BOX), &trec); + + if (trec.right != 0 && trec.bottom != 0) + { + // The size of the 282x282 IDC_ASPECT_RATIO_CALIBRATION_BOX rendered at the default DPI (96) is 423x458 + DPIScaleFactorX = (double) trec.right / 423; + DPIScaleFactorY = (double) trec.bottom / 458; + DlgAspectRatio = DPIScaleFactorX / DPIScaleFactorY; + } + } + + EndDialog (hwndDlg, 0); + return 1; + } + + case WM_CLOSE: + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + static HBITMAP hbmTextualLogoBitmapRescaled = NULL; + + switch (msg) + { + case WM_INITDIALOG: + { + char szTmp[100]; + RECT rec; + + LocalizeDialog (hwndDlg, "IDD_ABOUT_DLG"); + + // Hyperlink + SetWindowText (GetDlgItem (hwndDlg, IDC_HOMEPAGE), "www.truecrypt.org"); + ToHyperlink (hwndDlg, IDC_HOMEPAGE); + + // Logo area background (must not keep aspect ratio; must retain Windows-imposed distortion) + GetClientRect (GetDlgItem (hwndDlg, IDC_ABOUT_LOGO_AREA), &rec); + SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, rec.right, rec.bottom, SWP_NOMOVE); + + // Resize the logo bitmap if the user has a non-default DPI + if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) + { + // Logo (must recreate and keep the original aspect ratio as Windows distorts it) + hbmTextualLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_TEXTUAL_LOGO_288DPI), + GetDlgItem (hwndDlg, IDC_TEXTUAL_LOGO_IMG), + 0, 0, 0, 0, FALSE, TRUE); + + SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + + // Version + SendMessage (GetDlgItem (hwndDlg, IDT_ABOUT_VERSION), WM_SETFONT, (WPARAM) hUserBoldFont, 0); + sprintf (szTmp, "TrueCrypt %s", VERSION_STRING); +#if (defined(_DEBUG) || defined(DEBUG)) + strcat (szTmp, " (debug)"); +#endif + SetDlgItemText (hwndDlg, IDT_ABOUT_VERSION, szTmp); + SetDlgItemText (hwndDlg, IDT_ABOUT_RELEASE, TC_STR_RELEASED_BY); + + // Credits + SendMessage (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), WM_SETFONT, (WPARAM) hUserFont, (LPARAM) 0); + SendMessage (hwndDlg, WM_APP, 0, 0); + return 1; + } + + case WM_APP: + SetWindowText (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), + "Portions of this software are based in part on the works of the following people: " + "Paul Le Roux, " + "Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, Niels Ferguson, " + "Lars Knudsen, Ross Anderson, Eli Biham, " + "Joan Daemen, Vincent Rijmen, " + "Phillip Rogaway, " + "Hans Dobbertin, Antoon Bosselaers, Bart Preneel, " + "Paulo Barreto, Brian Gladman, Wei Dai, Peter Gutmann, and many others.\r\n\r\n" + + "Portions of this software:\r\n" + "Copyright \xA9 2003-2009 TrueCrypt Foundation. All Rights Reserved.\r\n" + "Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\r\n" + "Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\r\n" + "Copyright \xA9 2002-2004 Mark Adler. All Rights Reserved.\r\n\r\n" + + "This software as a whole:\r\n" + "Copyright \xA9 2009 TrueCrypt Foundation. All rights reserved.\r\n\r\n" + + "A TrueCrypt Foundation Release"); + + return 1; + + case WM_COMMAND: + if (lw == IDOK || lw == IDCANCEL) + { + PostMessage (hwndDlg, WM_CLOSE, 0, 0); + return 1; + } + + if (lw == IDC_HOMEPAGE) + { + Applink ("main", TRUE, ""); + return 1; + } + + if (lw == IDC_DONATIONS) + { + Applink ("donate", FALSE, ""); + return 1; + } + + // Disallow modification of credits + if (HIWORD (wParam) == EN_UPDATE) + { + SendMessage (hwndDlg, WM_APP, 0, 0); + return 1; + } + + return 0; + + case WM_CLOSE: + /* Delete buffered bitmaps (if any) */ + if (hbmTextualLogoBitmapRescaled != NULL) + { + DeleteObject ((HGDIOBJ) hbmTextualLogoBitmapRescaled); + hbmTextualLogoBitmapRescaled = NULL; + } + + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + + +BOOL +IsButtonChecked (HWND hButton) +{ + if (SendMessage (hButton, BM_GETCHECK, 0, 0) == BST_CHECKED) + return TRUE; + else + return FALSE; +} + +void +CheckButton (HWND hButton) +{ + SendMessage (hButton, BM_SETCHECK, BST_CHECKED, 0); +} + + +void LeftPadString (char *szTmp, int len, int targetLen, char filler) +{ + int i; + + if (targetLen <= len) + return; + + for (i = targetLen-1; i >= (targetLen-len); i--) + szTmp [i] = szTmp [i-(targetLen-len)]; + + memset (szTmp, filler, targetLen-len); + szTmp [targetLen] = 0; +} + + +/***************************************************************************** + ToSBCS: converts a unicode string to Single Byte Character String (SBCS). + ***************************************************************************/ + +void +ToSBCS (LPWSTR lpszText) +{ + int j = wcslen (lpszText); + if (j == 0) + { + strcpy ((char *) lpszText, ""); + return; + } + else + { + char *lpszNewText = (char *) err_malloc (j + 1); + j = WideCharToMultiByte (CP_ACP, 0L, lpszText, -1, lpszNewText, j + 1, NULL, NULL); + if (j > 0) + strcpy ((char *) lpszText, lpszNewText); + else + strcpy ((char *) lpszText, ""); + free (lpszNewText); + } +} + +/***************************************************************************** + ToUNICODE: converts a SBCS string to a UNICODE string. + ***************************************************************************/ + +void +ToUNICODE (char *lpszText) +{ + int j = strlen (lpszText); + if (j == 0) + { + wcscpy ((LPWSTR) lpszText, (LPWSTR) WIDE ("")); + return; + } + else + { + LPWSTR lpszNewText = (LPWSTR) err_malloc ((j + 1) * 2); + j = MultiByteToWideChar (CP_ACP, 0L, lpszText, -1, lpszNewText, j + 1); + if (j > 0) + wcscpy ((LPWSTR) lpszText, lpszNewText); + else + wcscpy ((LPWSTR) lpszText, (LPWSTR) WIDE ("")); + free (lpszNewText); + } +} + +/* InitDialog - initialize the applications main dialog, this function should + be called only once in the dialogs WM_INITDIALOG message handler */ +void +InitDialog (HWND hwndDlg) +{ + NONCLIENTMETRICSW metric; + static BOOL aboutMenuAppended = FALSE; + + int nHeight; + LOGFONTW lf; + HMENU hMenu; + Font *font; + + /* Fonts */ + + // Normal + font = GetFont ("font_normal"); + + metric.cbSize = sizeof (metric); + SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(metric), &metric, 0); + + WindowTitleBarFont = CreateFontIndirectW (&metric.lfCaptionFont); + + metric.lfMessageFont.lfHeight = CompensateDPIFont (!font ? -11 : -font->Size); + metric.lfMessageFont.lfWidth = 0; + + if (font && wcscmp (font->FaceName, L"default") != 0) + { + wcsncpy ((WCHAR *)metric.lfMessageFont.lfFaceName, font->FaceName, sizeof (metric.lfMessageFont.lfFaceName)/2); + } + else if (IsOSAtLeast (WIN_VISTA)) + { + // Vista's new default font (size and spacing) breaks compatibility with Windows 2k/XP applications. + // Force use of Tahoma (as Microsoft does in many dialogs) until a native Vista look is implemented. + wcsncpy ((WCHAR *)metric.lfMessageFont.lfFaceName, L"Tahoma", sizeof (metric.lfMessageFont.lfFaceName)/2); + } + + hUserFont = CreateFontIndirectW (&metric.lfMessageFont); + + metric.lfMessageFont.lfUnderline = TRUE; + hUserUnderlineFont = CreateFontIndirectW (&metric.lfMessageFont); + + metric.lfMessageFont.lfUnderline = FALSE; + metric.lfMessageFont.lfWeight = FW_BOLD; + hUserBoldFont = CreateFontIndirectW (&metric.lfMessageFont); + + metric.lfMessageFont.lfUnderline = TRUE; + metric.lfMessageFont.lfWeight = FW_BOLD; + hUserUnderlineBoldFont = CreateFontIndirectW (&metric.lfMessageFont); + + // Fixed-size (hexadecimal digits) + nHeight = CompensateDPIFont (-12); + lf.lfHeight = nHeight; + lf.lfWidth = 0; + lf.lfEscapement = 0; + lf.lfOrientation = 0; + lf.lfWeight = FW_NORMAL; + lf.lfItalic = FALSE; + lf.lfUnderline = FALSE; + lf.lfStrikeOut = FALSE; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = PROOF_QUALITY; + lf.lfPitchAndFamily = FF_DONTCARE; + wcscpy (lf.lfFaceName, L"Courier New"); + hFixedDigitFont = CreateFontIndirectW (&lf); + if (hFixedDigitFont == NULL) + { + handleWin32Error (hwndDlg); + AbortProcess ("NOFONT"); + } + + // Bold + font = GetFont ("font_bold"); + + nHeight = CompensateDPIFont (!font ? -13 : -font->Size); + lf.lfHeight = nHeight; + lf.lfWeight = FW_BLACK; + wcsncpy (lf.lfFaceName, !font ? L"Arial" : font->FaceName, sizeof (lf.lfFaceName)/2); + hBoldFont = CreateFontIndirectW (&lf); + if (hBoldFont == NULL) + { + handleWin32Error (hwndDlg); + AbortProcess ("NOFONT"); + } + + // Title + font = GetFont ("font_title"); + + nHeight = CompensateDPIFont (!font ? -21 : -font->Size); + lf.lfHeight = nHeight; + lf.lfWeight = FW_REGULAR; + wcsncpy (lf.lfFaceName, !font ? L"Times New Roman" : font->FaceName, sizeof (lf.lfFaceName)/2); + hTitleFont = CreateFontIndirectW (&lf); + if (hTitleFont == NULL) + { + handleWin32Error (hwndDlg); + AbortProcess ("NOFONT"); + } + + // Fixed-size + font = GetFont ("font_fixed"); + + nHeight = CompensateDPIFont (!font ? -12 : -font->Size); + lf.lfHeight = nHeight; + lf.lfWidth = 0; + lf.lfEscapement = 0; + lf.lfOrientation = 0; + lf.lfWeight = FW_NORMAL; + lf.lfItalic = FALSE; + lf.lfUnderline = FALSE; + lf.lfStrikeOut = FALSE; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = PROOF_QUALITY; + lf.lfPitchAndFamily = FF_DONTCARE; + wcsncpy (lf.lfFaceName, !font ? L"Lucida Console" : font->FaceName, sizeof (lf.lfFaceName)/2); + hFixedFont = CreateFontIndirectW (&lf); + if (hFixedFont == NULL) + { + handleWin32Error (hwndDlg); + AbortProcess ("NOFONT"); + } + + if (!aboutMenuAppended) + { + hMenu = GetSystemMenu (hwndDlg, FALSE); + AppendMenu (hMenu, MF_SEPARATOR, 0, NULL); + AppendMenuW (hMenu, MF_ENABLED | MF_STRING, IDC_ABOUT, GetString ("ABOUTBOX")); + + aboutMenuAppended = TRUE; + } +} + +HDC CreateMemBitmap (HINSTANCE hInstance, HWND hwnd, char *resource) +{ + HBITMAP picture = LoadBitmap (hInstance, resource); + HDC viewDC = GetDC (hwnd), dcMem; + + dcMem = CreateCompatibleDC (viewDC); + + SetMapMode (dcMem, MM_TEXT); + + SelectObject (dcMem, picture); + + DeleteObject (picture); + + ReleaseDC (hwnd, viewDC); + + return dcMem; +} + + +/* Renders the specified bitmap at the specified location and stretches it to fit (anti-aliasing is applied). +If bDirectRender is FALSE and both nWidth and nHeight are zero, the width and height of hwndDest are +retrieved and adjusted according to screen DPI (the width and height of the resultant image are adjusted the +same way); furthermore, if bKeepAspectRatio is TRUE, the smaller DPI factor of the two (i.e. horiz. or vert.) +is used both for horiz. and vert. scaling (note that the overall GUI aspect ratio changes irregularly in +both directions depending on the DPI). If bDirectRender is TRUE, bKeepAspectRatio is ignored. +This function returns a handle to the scaled bitmap. When the bitmap is no longer needed, it should be +deleted by calling DeleteObject() with the handle passed as the parameter. +Known Windows issues: +- For some reason, anti-aliasing is not applied if the source bitmap contains less than 16K pixels. +- Windows 2000 may produce slightly inaccurate colors even when source, buffer, and target are 24-bit true color. */ +HBITMAP RenderBitmap (char *resource, HWND hwndDest, int x, int y, int nWidth, int nHeight, BOOL bDirectRender, BOOL bKeepAspectRatio) +{ + LRESULT lResult = 0; + + HDC hdcSrc = CreateMemBitmap (hInst, hwndDest, resource); + + HGDIOBJ picture = GetCurrentObject (hdcSrc, OBJ_BITMAP); + + HBITMAP hbmpRescaled; + BITMAP bitmap; + + HDC hdcRescaled; + + if (!bDirectRender && nWidth == 0 && nHeight == 0) + { + RECT rec; + + GetClientRect (hwndDest, &rec); + + if (bKeepAspectRatio) + { + if (DlgAspectRatio > 1) + { + // Do not fix this, it's correct. We use the Y scale factor intentionally for both + // directions to maintain aspect ratio (see above for more info). + nWidth = CompensateYDPI (rec.right); + nHeight = CompensateYDPI (rec.bottom); + } + else + { + // Do not fix this, it's correct. We use the X scale factor intentionally for both + // directions to maintain aspect ratio (see above for more info). + nWidth = CompensateXDPI (rec.right); + nHeight = CompensateXDPI (rec.bottom); + } + } + else + { + nWidth = CompensateXDPI (rec.right); + nHeight = CompensateYDPI (rec.bottom); + } + } + + GetObject (picture, sizeof (BITMAP), &bitmap); + + hdcRescaled = CreateCompatibleDC (hdcSrc); + + hbmpRescaled = CreateCompatibleBitmap (hdcSrc, nWidth, nHeight); + + SelectObject (hdcRescaled, hbmpRescaled); + + /* Anti-aliasing mode (HALFTONE is the only anti-aliasing algorithm natively supported by Windows 2000. + TODO: GDI+ offers higher quality -- InterpolationModeHighQualityBicubic) */ + SetStretchBltMode (hdcRescaled, HALFTONE); + + StretchBlt (hdcRescaled, + 0, + 0, + nWidth, + nHeight, + hdcSrc, + 0, + 0, + bitmap.bmWidth, + bitmap.bmHeight, + SRCCOPY); + + DeleteDC (hdcSrc); + + if (bDirectRender) + { + HDC hdcDest = GetDC (hwndDest); + + BitBlt (hdcDest, x, y, nWidth, nHeight, hdcRescaled, 0, 0, SRCCOPY); + DeleteDC (hdcDest); + } + else + { + lResult = SendMessage (hwndDest, (UINT) STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) (HANDLE) hbmpRescaled); + } + + if ((HGDIOBJ) lResult != NULL && (HGDIOBJ) lResult != (HGDIOBJ) hbmpRescaled) + DeleteObject ((HGDIOBJ) lResult); + + DeleteDC (hdcRescaled); + + return hbmpRescaled; +} + + +LRESULT CALLBACK +RedTick (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_CREATE) + { + } + else if (uMsg == WM_DESTROY) + { + } + else if (uMsg == WM_TIMER) + { + } + else if (uMsg == WM_PAINT) + { + PAINTSTRUCT tmp; + HPEN hPen; + HDC hDC; + BOOL bEndPaint; + RECT Rect; + + if (GetUpdateRect (hwnd, NULL, FALSE)) + { + hDC = BeginPaint (hwnd, &tmp); + bEndPaint = TRUE; + if (hDC == NULL) + return DefWindowProc (hwnd, uMsg, wParam, lParam); + } + else + { + hDC = GetDC (hwnd); + bEndPaint = FALSE; + } + + GetClientRect (hwnd, &Rect); + + hPen = CreatePen (PS_SOLID, 2, RGB (0, 255, 0)); + if (hPen != NULL) + { + HGDIOBJ hObj = SelectObject (hDC, hPen); + WORD bx = LOWORD (GetDialogBaseUnits ()); + WORD by = HIWORD (GetDialogBaseUnits ()); + + MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); + LineTo (hDC, Rect.right, Rect.top); + MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); + + LineTo (hDC, (3 * bx) / 4, (2 * by) / 8); + + SelectObject (hDC, hObj); + DeleteObject (hPen); + } + + if (bEndPaint) + EndPaint (hwnd, &tmp); + else + ReleaseDC (hwnd, hDC); + + return TRUE; + } + + return DefWindowProc (hwnd, uMsg, wParam, lParam); +} + +BOOL +RegisterRedTick (HINSTANCE hInstance) +{ + WNDCLASS wc; + ULONG rc; + + memset(&wc, 0 , sizeof wc); + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.cbClsExtra = 0; + wc.cbWndExtra = 4; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); + wc.hCursor = NULL; + wc.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH); + wc.lpszClassName = "REDTICK"; + wc.lpfnWndProc = &RedTick; + + rc = (ULONG) RegisterClass (&wc); + + return rc == 0 ? FALSE : TRUE; +} + +BOOL +UnregisterRedTick (HINSTANCE hInstance) +{ + return UnregisterClass ("REDTICK", hInstance); +} + +LRESULT CALLBACK +SplashDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return DefDlgProc (hwnd, uMsg, wParam, lParam); +} + +void +WaitCursor () +{ + static HCURSOR hcWait; + if (hcWait == NULL) + hcWait = LoadCursor (NULL, IDC_WAIT); + SetCursor (hcWait); + hCursor = hcWait; +} + +void +NormalCursor () +{ + static HCURSOR hcArrow; + if (hcArrow == NULL) + hcArrow = LoadCursor (NULL, IDC_ARROW); + SetCursor (hcArrow); + hCursor = NULL; +} + +void +ArrowWaitCursor () +{ + static HCURSOR hcArrowWait; + if (hcArrowWait == NULL) + hcArrowWait = LoadCursor (NULL, IDC_APPSTARTING); + SetCursor (hcArrowWait); + hCursor = hcArrowWait; +} + +void HandCursor () +{ + static HCURSOR hcHand; + if (hcHand == NULL) + hcHand = LoadCursor (NULL, IDC_HAND); + SetCursor (hcHand); + hCursor = hcHand; +} + +void +AddComboPair (HWND hComboBox, const char *lpszItem, int value) +{ + LPARAM nIndex; + + nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem); + nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value); +} + +void +AddComboPairW (HWND hComboBox, const wchar_t *lpszItem, int value) +{ + LPARAM nIndex; + + nIndex = SendMessageW (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem); + nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value); +} + +void +SelectAlgo (HWND hComboBox, int *algo_id) +{ + LPARAM nCount = SendMessage (hComboBox, CB_GETCOUNT, 0, 0); + LPARAM x, i; + + for (i = 0; i < nCount; i++) + { + x = SendMessage (hComboBox, CB_GETITEMDATA, i, 0); + if (x == (LPARAM) *algo_id) + { + SendMessage (hComboBox, CB_SETCURSEL, i, 0); + return; + } + } + + /* Something went wrong ; couldn't find the requested algo id so we drop + back to a default */ + + *algo_id = SendMessage (hComboBox, CB_GETITEMDATA, 0, 0); + + SendMessage (hComboBox, CB_SETCURSEL, 0, 0); + +} + +void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption) +{ + if (bNA) + { + AddComboPairW (hComboBox, GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"), TC_WIPE_NONE); + } + else + { + if (bInPlaceEncryption) + AddComboPairW (hComboBox, GetString ("WIPE_MODE_NONE"), TC_WIPE_NONE); + else + AddComboPairW (hComboBox, GetString ("WIPE_MODE_1_RAND"), TC_WIPE_1_RAND); + + AddComboPairW (hComboBox, GetString ("WIPE_MODE_3_DOD_5220"), TC_WIPE_3_DOD_5220); + AddComboPairW (hComboBox, GetString ("WIPE_MODE_7_DOD_5220"), TC_WIPE_7_DOD_5220); + AddComboPairW (hComboBox, GetString ("WIPE_MODE_35_GUTMANN"), TC_WIPE_35_GUTMANN); + } +} + +wchar_t *GetWipeModeName (WipeAlgorithmId modeId) +{ + switch (modeId) + { + case TC_WIPE_NONE: + return GetString ("WIPE_MODE_NONE"); + + case TC_WIPE_1_RAND: + return GetString ("WIPE_MODE_1_RAND"); + + case TC_WIPE_3_DOD_5220: + return GetString ("WIPE_MODE_3_DOD_5220"); + + case TC_WIPE_7_DOD_5220: + return GetString ("WIPE_MODE_7_DOD_5220"); + + case TC_WIPE_35_GUTMANN: + return GetString ("WIPE_MODE_35_GUTMANN"); + + default: + return GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"); + } +} + +wchar_t *GetPathType (const char *path, BOOL bUpperCase, BOOL *bIsPartition) +{ + if (strstr (path, "Partition") + && strstr (path, "Partition0") == NULL) + { + *bIsPartition = TRUE; + return GetString (bUpperCase ? "PARTITION_UPPER_CASE" : "PARTITION_LOWER_CASE"); + } + else if (strstr (path, "HarddiskVolume")) + { + *bIsPartition = TRUE; + return GetString (bUpperCase ? "VOLUME_UPPER_CASE" : "VOLUME_LOWER_CASE"); + } + + *bIsPartition = FALSE; + return GetString (bUpperCase ? "DEVICE_UPPER_CASE" : "DEVICE_LOWER_CASE"); +} + +LRESULT CALLBACK CustomDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_SETCURSOR && hCursor != NULL) + { + SetCursor (hCursor); + return TRUE; + } + + return DefDlgProc (hwnd, uMsg, wParam, lParam); +} + + +static BOOL IsReturnAddress (DWORD64 address) +{ + static size_t codeEnd = 0; + byte *sp = (byte *) address; + + if (codeEnd == 0) + { + MEMORY_BASIC_INFORMATION mi; + if (VirtualQuery ((LPCVOID) 0x401000, &mi, sizeof (mi)) >= sizeof (mi)) + codeEnd = (size_t) mi.BaseAddress + mi.RegionSize; + } + + if (address < 0x401000 + 8 || address > codeEnd) + return FALSE; + + return sp[-5] == 0xe8 // call ADDR + || (sp[-6] == 0xff && sp[-5] == 0x15) // call [ADDR] + || (sp[-2] == 0xff && (sp[-1] & 0xf0) == 0xd0); // call REG +} + + +typedef struct +{ + EXCEPTION_POINTERS *ExceptionPointers; + HANDLE ExceptionThread; + +} ExceptionHandlerThreadArgs; + + +void ExceptionHandlerThread (void *threadArg) +{ + ExceptionHandlerThreadArgs *args = (ExceptionHandlerThreadArgs *) threadArg; + + EXCEPTION_POINTERS *ep = args->ExceptionPointers; + DWORD addr; + DWORD exCode = ep->ExceptionRecord->ExceptionCode; + SYSTEM_INFO si; + wchar_t msg[8192]; + char modPath[MAX_PATH]; + int crc = 0; + char url[MAX_URL_LENGTH]; + char lpack[128]; + stringstream callStack; + addr = (DWORD) ep->ExceptionRecord->ExceptionAddress; + PDWORD sp = (PDWORD) ep->ContextRecord->Esp; + int frameNumber = 0; + + switch (exCode) + { + case STATUS_IN_PAGE_ERROR: + case 0xeedfade: + // Exception not caused by TrueCrypt + MessageBoxW (0, GetString ("EXCEPTION_REPORT_EXT"), + GetString ("EXCEPTION_REPORT_TITLE"), + MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); + return; + } + + // Call stack + HMODULE dbgDll = LoadLibrary ("dbghelp.dll"); + if (dbgDll) + { + typedef DWORD (__stdcall *SymGetOptions_t) (); + typedef DWORD (__stdcall *SymSetOptions_t) (DWORD SymOptions); + typedef BOOL (__stdcall *SymInitialize_t) (HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess); + typedef BOOL (__stdcall *StackWalk64_t) (DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + typedef BOOL (__stdcall * SymFromAddr_t) (HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol); + + SymGetOptions_t DbgHelpSymGetOptions = (SymGetOptions_t) GetProcAddress (dbgDll, "SymGetOptions"); + SymSetOptions_t DbgHelpSymSetOptions = (SymSetOptions_t) GetProcAddress (dbgDll, "SymSetOptions"); + SymInitialize_t DbgHelpSymInitialize = (SymInitialize_t) GetProcAddress (dbgDll, "SymInitialize"); + PFUNCTION_TABLE_ACCESS_ROUTINE64 DbgHelpSymFunctionTableAccess64 = (PFUNCTION_TABLE_ACCESS_ROUTINE64) GetProcAddress (dbgDll, "SymFunctionTableAccess64"); + PGET_MODULE_BASE_ROUTINE64 DbgHelpSymGetModuleBase64 = (PGET_MODULE_BASE_ROUTINE64) GetProcAddress (dbgDll, "SymGetModuleBase64"); + StackWalk64_t DbgHelpStackWalk64 = (StackWalk64_t) GetProcAddress (dbgDll, "StackWalk64"); + SymFromAddr_t DbgHelpSymFromAddr = (SymFromAddr_t) GetProcAddress (dbgDll, "SymFromAddr"); + + if (DbgHelpSymGetOptions && DbgHelpSymSetOptions && DbgHelpSymInitialize && DbgHelpSymFunctionTableAccess64 && DbgHelpSymGetModuleBase64 && DbgHelpStackWalk64 && DbgHelpSymFromAddr) + { + DbgHelpSymSetOptions (DbgHelpSymGetOptions() | SYMOPT_DEFERRED_LOADS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_NO_CPP); + + if (DbgHelpSymInitialize (GetCurrentProcess(), NULL, TRUE)) + { + STACKFRAME64 frame; + memset (&frame, 0, sizeof (frame)); + + frame.AddrPC.Offset = ep->ContextRecord->Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Offset = ep->ContextRecord->Esp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Offset = ep->ContextRecord->Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + + string lastSymbol; + + while (frameNumber < 32 && DbgHelpStackWalk64 (IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), args->ExceptionThread, &frame, ep->ContextRecord, NULL, DbgHelpSymFunctionTableAccess64, DbgHelpSymGetModuleBase64, NULL)) + { + if (!frame.AddrPC.Offset) + continue; + + ULONG64 symbolBuffer[(sizeof (SYMBOL_INFO) + MAX_SYM_NAME * sizeof (TCHAR) + sizeof (ULONG64) - 1) / sizeof (ULONG64)]; + memset (symbolBuffer, 0, sizeof (symbolBuffer)); + + PSYMBOL_INFO symbol = (PSYMBOL_INFO) symbolBuffer; + symbol->SizeOfStruct = sizeof (SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + if (DbgHelpSymFromAddr (GetCurrentProcess(), frame.AddrPC.Offset, NULL, symbol) && symbol->NameLen > 0) + { + for (size_t i = 0; i < symbol->NameLen; ++i) + { + if (!isalnum (symbol->Name[i])) + symbol->Name[i] = '_'; + } + + if (symbol->Name != lastSymbol) + callStack << "&st" << frameNumber++ << "=" << symbol->Name; + + lastSymbol = symbol->Name; + } + else if (frameNumber == 0 || IsReturnAddress (frame.AddrPC.Offset)) + { + callStack << "&st" << frameNumber++ << "=0x" << hex << frame.AddrPC.Offset << dec; + } + } + } + } + } + + // StackWalk64() may fail due to missing frame pointers + list retAddrs; + if (frameNumber == 0) + retAddrs.push_back (ep->ContextRecord->Eip); + + retAddrs.push_back (0); + + MEMORY_BASIC_INFORMATION mi; + VirtualQuery (sp, &mi, sizeof (mi)); + PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize); + int i = 0; + + while (retAddrs.size() < 16 && &sp[i] < stackTop) + { + if (IsReturnAddress (sp[i])) + { + bool duplicate = false; + foreach (DWORD prevAddr, retAddrs) + { + if (sp[i] == prevAddr) + { + duplicate = true; + break; + } + } + + if (!duplicate) + retAddrs.push_back (sp[i]); + } + i++; + } + + if (retAddrs.size() > 1) + { + foreach (DWORD addr, retAddrs) + { + callStack << "&st" << frameNumber++ << "=0x" << hex << addr << dec; + } + } + + // Checksum of the module + if (GetModuleFileName (NULL, modPath, sizeof (modPath))) + { + HANDLE h = CreateFile (modPath, FILE_READ_DATA | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h != INVALID_HANDLE_VALUE) + { + BY_HANDLE_FILE_INFORMATION fi; + if (GetFileInformationByHandle (h, &fi)) + { + char *buf = (char *) malloc (fi.nFileSizeLow); + if (buf) + { + DWORD bytesRead; + if (ReadFile (h, buf, fi.nFileSizeLow, &bytesRead, NULL) && bytesRead == fi.nFileSizeLow) + crc = GetCrc32 ((unsigned char *) buf, fi.nFileSizeLow); + free (buf); + } + } + CloseHandle (h); + } + } + + GetSystemInfo (&si); + + if (LocalizationActive) + sprintf_s (lpack, sizeof (lpack), "&langpack=%s_%s", GetPreferredLangId (), GetActiveLangPackVersion ()); + else + lpack[0] = 0; + + sprintf (url, TC_APPLINK_SECURE "&dest=err-report%s&os=%s&osver=%d.%d.%d&arch=%s&cpus=%d&app=%s&cksum=%x&dlg=%s&err=%x&addr=%x" + , lpack + , GetWindowsEdition().c_str() + , CurrentOSMajor + , CurrentOSMinor + , CurrentOSServicePack + , Is64BitOs () ? "x64" : "x86" + , si.dwNumberOfProcessors +#ifdef TCMOUNT + ,"main" +#endif +#ifdef VOLFORMAT + ,"format" +#endif +#ifdef SETUP + ,"setup" +#endif + , crc + , LastDialogId ? LastDialogId : "-" + , exCode + , addr); + + string urlStr = url + callStack.str(); + + _snwprintf (msg, array_capacity (msg), GetString ("EXCEPTION_REPORT"), urlStr.c_str()); + + if (IDYES == MessageBoxW (0, msg, GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1)) + ShellExecute (NULL, "open", urlStr.c_str(), NULL, NULL, SW_SHOWNORMAL); + else + UnhandledExceptionFilter (ep); +} + + +LONG __stdcall ExceptionHandler (EXCEPTION_POINTERS *ep) +{ + SetUnhandledExceptionFilter (NULL); + + ExceptionHandlerThreadArgs args; + args.ExceptionPointers = ep; + args.ExceptionThread = GetCurrentThread(); + + WaitForSingleObject ((HANDLE) _beginthread (ExceptionHandlerThread, 0, &args), INFINITE); + + return EXCEPTION_EXECUTE_HANDLER; +} + + +static LRESULT CALLBACK NonInstallUacWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc (hWnd, message, wParam, lParam); +} + + +// Mutex handling to prevent multiple instances of the wizard or main app from dealing with system encryption. +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL CreateSysEncMutex (void) +{ + return TCCreateMutex (&hSysEncMutex, TC_MUTEX_NAME_SYSENC); +} + + +BOOL InstanceHasSysEncMutex (void) +{ + return (hSysEncMutex != NULL); +} + + +// Mutex handling to prevent multiple instances of the wizard from dealing with system encryption +void CloseSysEncMutex (void) +{ + TCCloseMutex (&hSysEncMutex); +} + + +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL CreateNonSysInplaceEncMutex (void) +{ + return TCCreateMutex (&hNonSysInplaceEncMutex, TC_MUTEX_NAME_NONSYS_INPLACE_ENC); +} + + +BOOL InstanceHasNonSysInplaceEncMutex (void) +{ + return (hNonSysInplaceEncMutex != NULL); +} + + +void CloseNonSysInplaceEncMutex (void) +{ + TCCloseMutex (&hNonSysInplaceEncMutex); +} + + +// Returns TRUE if another instance of the wizard is preparing, resuming or performing non-system in-place encryption +BOOL NonSysInplaceEncInProgressElsewhere (void) +{ + return (!InstanceHasNonSysInplaceEncMutex () + && MutexExistsOnSystem (TC_MUTEX_NAME_NONSYS_INPLACE_ENC)); +} + + +// Mutex handling to prevent multiple instances of the wizard or main app from trying to install +// or register the driver or from trying to launch it in portable mode at the same time. +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL CreateDriverSetupMutex (void) +{ + return TCCreateMutex (&hDriverSetupMutex, TC_MUTEX_NAME_DRIVER_SETUP); +} + + +void CloseDriverSetupMutex (void) +{ + TCCloseMutex (&hDriverSetupMutex); +} + + +BOOL CreateAppSetupMutex (void) +{ + return TCCreateMutex (&hAppSetupMutex, TC_MUTEX_NAME_APP_SETUP); +} + + +void CloseAppSetupMutex (void) +{ + TCCloseMutex (&hAppSetupMutex); +} + + +BOOL IsTrueCryptInstallerRunning (void) +{ + return (MutexExistsOnSystem (TC_MUTEX_NAME_APP_SETUP)); +} + + +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL TCCreateMutex (volatile HANDLE *hMutex, char *name) +{ + if (*hMutex != NULL) + return TRUE; // This instance already has the mutex + + *hMutex = CreateMutex (NULL, TRUE, name); + if (*hMutex == NULL) + { + // In multi-user configurations, the OS returns "Access is denied" here when a user attempts + // to acquire the mutex if another user already has. However, on Vista, "Access is denied" is + // returned also if the mutex is owned by a process with admin rights while we have none. + + return FALSE; + } + + if (GetLastError () == ERROR_ALREADY_EXISTS) + { + ReleaseMutex (*hMutex); + CloseHandle (*hMutex); + + *hMutex = NULL; + return FALSE; + } + + return TRUE; +} + + +void TCCloseMutex (volatile HANDLE *hMutex) +{ + if (*hMutex != NULL) + { + if (ReleaseMutex (*hMutex) + && CloseHandle (*hMutex)) + *hMutex = NULL; + } +} + + +// Returns TRUE if a process running on the system has the specified mutex (otherwise FALSE). +BOOL MutexExistsOnSystem (char *name) +{ + if (name[0] == 0) + return FALSE; + + HANDLE hMutex = OpenMutex (MUTEX_ALL_ACCESS, FALSE, name); + + if (hMutex == NULL) + { + if (GetLastError () == ERROR_FILE_NOT_FOUND) + return FALSE; + + if (GetLastError () == ERROR_ACCESS_DENIED) // On Vista, this is returned if the owner of the mutex is elevated while we are not + return TRUE; + + // The call failed and it is not certain whether the mutex exists or not + return FALSE; + } + + CloseHandle (hMutex); + return TRUE; +} + + +BOOL LoadSysEncSettings (HWND hwndDlg) +{ + BOOL status = TRUE; + DWORD size = 0; + char *sysEncCfgFileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), &size); + char *xml = sysEncCfgFileBuf; + char paramName[100], paramVal[MAX_PATH]; + + // Defaults + int newSystemEncryptionStatus = SYSENC_STATUS_NONE; + WipeAlgorithmId newnWipeMode = TC_WIPE_NONE; + + if (!FileExists (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION))) + { + SystemEncryptionStatus = newSystemEncryptionStatus; + nWipeMode = newnWipeMode; + } + + if (xml == NULL) + { + return FALSE; + } + + while (xml = XmlFindElement (xml, "config")) + { + XmlGetAttributeText (xml, "key", paramName, sizeof (paramName)); + XmlGetNodeText (xml, paramVal, sizeof (paramVal)); + + if (strcmp (paramName, "SystemEncryptionStatus") == 0) + { + newSystemEncryptionStatus = atoi (paramVal); + } + else if (strcmp (paramName, "WipeMode") == 0) + { + newnWipeMode = (WipeAlgorithmId) atoi (paramVal); + } + + xml++; + } + + SystemEncryptionStatus = newSystemEncryptionStatus; + nWipeMode = newnWipeMode; + + free (sysEncCfgFileBuf); + return status; +} + + +// Returns the number of partitions where non-system in-place encryption is progress or had been in progress +// but was interrupted. In addition, via the passed pointer, returns the last selected wipe algorithm ID. +int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm) +{ + char *fileBuf = NULL; + char *fileBuf2 = NULL; + DWORD size, size2; + int count; + + *wipeAlgorithm = TC_WIPE_NONE; + + if (!FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) + return 0; + + if ((fileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), &size)) == NULL) + return 0; + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) + { + if ((fileBuf2 = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), &size2)) != NULL) + *wipeAlgorithm = (WipeAlgorithmId) atoi (fileBuf2); + } + + count = atoi (fileBuf); + + if (fileBuf != NULL) + TCfree (fileBuf); + + if (fileBuf2 != NULL) + TCfree (fileBuf2); + + return (count); +} + + +void RemoveNonSysInPlaceEncNotifications (void) +{ + if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) + remove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC)); + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) + remove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)); + + if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE) + ManageStartupSeqWiz (TRUE, ""); +} + + +void SavePostInstallTasksSettings (int command) +{ + FILE *f = NULL; + + switch (command) + { + case TC_POST_INSTALL_CFG_REMOVE_ALL: + remove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)); + remove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES)); + break; + + case TC_POST_INSTALL_CFG_TUTORIAL: + f = fopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL), "w"); + break; + + case TC_POST_INSTALL_CFG_RELEASE_NOTES: + f = fopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES), "w"); + break; + + default: + return; + } + + if (f == NULL) + return; + + if (fputs ("1", f) < 0) + { + // Error + fclose (f); + return; + } + + TCFlushFile (f); + + fclose (f); +} + + +void DoPostInstallTasks (void) +{ + BOOL bDone = FALSE; + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL))) + { + if (AskYesNo ("AFTER_INSTALL_TUTORIAL") == IDYES) + Applink ("beginnerstutorial", TRUE, ""); + + bDone = TRUE; + } + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES))) + { + if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES") == IDYES) + Applink ("releasenotes", TRUE, ""); + + bDone = TRUE; + } + + if (bDone) + SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL); +} + + +/* InitApp - initialize the application, this function is called once in the + applications WinMain function, but before the main dialog has been created */ +void InitApp (HINSTANCE hInstance, char *lpszCommandLine) +{ + WNDCLASS wc; + OSVERSIONINFO os; + char langId[6]; + + /* Save the instance handle for later */ + hInst = hInstance; + + /* Pull down the windows version */ + os.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + + if (GetVersionEx (&os) == FALSE) + AbortProcess ("NO_OS_VER"); + + CurrentOSMajor = os.dwMajorVersion; + CurrentOSMinor = os.dwMinorVersion; + + if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0) + nCurrentOS = WIN_2000; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1) + nCurrentOS = WIN_XP; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2) + { + OSVERSIONINFOEX osEx; + + osEx.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); + GetVersionEx ((LPOSVERSIONINFOA) &osEx); + + if (osEx.wProductType == VER_NT_SERVER || osEx.wProductType == VER_NT_DOMAIN_CONTROLLER) + nCurrentOS = WIN_SERVER_2003; + else + nCurrentOS = WIN_XP64; + } + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0) + { + OSVERSIONINFOEX osEx; + + osEx.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); + GetVersionEx ((LPOSVERSIONINFOA) &osEx); + + if (osEx.wProductType == VER_NT_SERVER || osEx.wProductType == VER_NT_DOMAIN_CONTROLLER) + nCurrentOS = WIN_SERVER_2008; + else + nCurrentOS = WIN_VISTA; + } + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1) + nCurrentOS = (IsServerOS() ? WIN_SERVER_2008_R2 : WIN_7); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4) + nCurrentOS = WIN_NT4; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0) + nCurrentOS = WIN_95; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10) + nCurrentOS = WIN_98; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90) + nCurrentOS = WIN_ME; + else if (os.dwPlatformId == VER_PLATFORM_WIN32s) + nCurrentOS = WIN_31; + else + nCurrentOS = WIN_UNKNOWN; + + CoInitialize (NULL); + +#ifndef SETUP + // Application ID + typedef HRESULT (WINAPI *SetAppId_t) (PCWSTR appID); + SetAppId_t setAppId = (SetAppId_t) GetProcAddress (GetModuleHandle ("shell32.dll"), "SetCurrentProcessExplicitAppUserModelID"); + + if (setAppId) + setAppId (TC_APPLICATION_ID); +#endif + + // Language + langId[0] = 0; + SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId))); + + if (langId[0] == 0) + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), NULL, + (DLGPROC) LanguageDlgProc, (LPARAM) 1); + + LoadLanguageFile (); + +#ifndef SETUP + // UAC elevation moniker cannot be used in portable mode. + // A new instance of the application must be created with elevated privileges. + if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ()) + { + char modPath[MAX_PATH], newCmdLine[4096]; + WNDCLASSEX wcex; + HWND hWnd; + + if (strstr (lpszCommandLine, "/q UAC ") == lpszCommandLine) + { + Error ("UAC_INIT_ERROR"); + exit (1); + } + + memset (&wcex, 0, sizeof (wcex)); + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.lpfnWndProc = (WNDPROC) NonInstallUacWndProc; + wcex.hInstance = hInstance; + wcex.lpszClassName = "TrueCrypt"; + RegisterClassEx (&wcex); + + // A small transparent window is necessary to bring the new instance to foreground + hWnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_LAYERED, + "TrueCrypt", "TrueCrypt", 0, + GetSystemMetrics (SM_CXSCREEN)/2, + GetSystemMetrics (SM_CYSCREEN)/2, + 1, 1, NULL, NULL, hInstance, NULL); + + SetLayeredWindowAttributes (hWnd, 0, 0, LWA_ALPHA); + ShowWindow (hWnd, SW_SHOWNORMAL); + + GetModuleFileName (NULL, modPath, sizeof (modPath)); + + strcpy (newCmdLine, "/q UAC "); + strcat_s (newCmdLine, sizeof (newCmdLine), lpszCommandLine); + + if ((int)ShellExecute (hWnd, "runas", modPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32) + exit (1); + + Sleep (2000); + exit (0); + } +#endif + + SetUnhandledExceptionFilter (ExceptionHandler); + + RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0; + + // OS version check + if (CurrentOSMajor < 5) + { + MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP); + exit (1); + } + else + { + OSVERSIONINFOEX osEx; + + // Service pack check & warnings about critical MS issues + osEx.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); + if (GetVersionEx ((LPOSVERSIONINFOA) &osEx) != 0) + { + CurrentOSServicePack = osEx.wServicePackMajor; + switch (nCurrentOS) + { + case WIN_2000: + if (osEx.wServicePackMajor < 3) + Warning ("LARGE_IDE_WARNING_2K"); + else + { + DWORD val = 0, size = sizeof(val); + HKEY hkey; + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Atapi\\Parameters", 0, KEY_READ, &hkey) == ERROR_SUCCESS + && (RegQueryValueEx (hkey, "EnableBigLba", 0, 0, (LPBYTE) &val, &size) != ERROR_SUCCESS + || val != 1)) + + { + Warning ("LARGE_IDE_WARNING_2K_REGISTRY"); + } + RegCloseKey (hkey); + } + break; + + case WIN_XP: + if (osEx.wServicePackMajor < 1) + { + HKEY k; + // PE environment does not report version of SP + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\minint", 0, KEY_READ, &k) != ERROR_SUCCESS) + Warning ("LARGE_IDE_WARNING_XP"); + else + RegCloseKey (k); + } + break; + } + } + + if (CurrentOSMajor == 6 && CurrentOSMinor == 1 + && osEx.dwBuildNumber > 0 && osEx.dwBuildNumber < 7600) + { + Error ("UNSUPPORTED_BETA_OS"); + exit (0); + } + } + + /* Get the attributes for the standard dialog class */ + if ((GetClassInfo (hInst, WINDOWS_DIALOG_CLASS, &wc)) == 0) + { + handleWin32Error (NULL); + AbortProcess ("INIT_REGISTER"); + } + +#ifndef SETUP + wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_TRUECRYPT_ICON)); +#else +#include "../setup/resource.h" + wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_SETUP)); +#endif + wc.lpszClassName = TC_DLG_CLASS; + wc.lpfnWndProc = &CustomDlgProc; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.cbWndExtra = DLGWINDOWEXTRA; + + hDlgClass = RegisterClass (&wc); + if (hDlgClass == 0) + { + handleWin32Error (NULL); + AbortProcess ("INIT_REGISTER"); + } + + wc.lpszClassName = TC_SPLASH_CLASS; + wc.lpfnWndProc = &SplashDlgProc; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.cbWndExtra = DLGWINDOWEXTRA; + + hSplashClass = RegisterClass (&wc); + if (hSplashClass == 0) + { + handleWin32Error (NULL); + AbortProcess ("INIT_REGISTER"); + } + + // Required for RichEdit text fields to work + if (LoadLibrary("Riched20.dll") == NULL) + { + // This error is fatal e.g. because legal notices could not be displayed + handleWin32Error (NULL); + AbortProcess ("INIT_RICHEDIT"); + } + + // DPI and GUI aspect ratio + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_AUXILIARY_DLG), NULL, + (DLGPROC) AuxiliaryDlgProc, (LPARAM) 1); + + InitHelpFileName (); + +#ifndef SETUP + if (!EncryptionThreadPoolStart()) + { + handleWin32Error (NULL); + exit (1); + } +#endif +} + +void InitHelpFileName (void) +{ + char *lpszTmp; + + GetModuleFileName (NULL, szHelpFile, sizeof (szHelpFile)); + lpszTmp = strrchr (szHelpFile, '\\'); + if (lpszTmp) + { + char szTemp[TC_MAX_PATH]; + + // Primary file name + if (strcmp (GetPreferredLangId(), "en") == 0 + || GetPreferredLangId() == NULL) + { + strcpy (++lpszTmp, "TrueCrypt User Guide.pdf"); + } + else + { + sprintf (szTemp, "TrueCrypt User Guide.%s.pdf", GetPreferredLangId()); + strcpy (++lpszTmp, szTemp); + } + + // Secondary file name (used when localized documentation is not found). + GetModuleFileName (NULL, szHelpFile2, sizeof (szHelpFile2)); + lpszTmp = strrchr (szHelpFile2, '\\'); + if (lpszTmp) + { + strcpy (++lpszTmp, "TrueCrypt User Guide.pdf"); + } + } +} + +BOOL OpenDevice (const char *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem) +{ + DWORD dwResult; + BOOL bResult; + + strcpy ((char *) &driver->wszFileName[0], lpszPath); + ToUNICODE ((char *) &driver->wszFileName[0]); + + driver->bDetectTCBootLoader = FALSE; + driver->DetectFilesystem = detectFilesystem; + + bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, + driver, sizeof (OPEN_TEST_STRUCT), + driver, sizeof (OPEN_TEST_STRUCT), + &dwResult, NULL); + + if (bResult == FALSE) + { + dwResult = GetLastError (); + + if (dwResult == ERROR_SHARING_VIOLATION || dwResult == ERROR_NOT_READY) + { + driver->TCBootLoaderDetected = FALSE; + driver->FilesystemDetected = FALSE; + return TRUE; + } + else + return FALSE; + } + + return TRUE; +} + + +// Tells the driver that it's running in portable mode +void NotifyDriverOfPortableMode (void) +{ + if (hDriver != INVALID_HANDLE_VALUE) + { + DWORD dwResult; + + DeviceIoControl (hDriver, TC_IOCTL_SET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL); + } +} + + +BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize) +{ + DWORD fileSystemFlags; + wchar_t root[] = { L'A' + (wchar_t) driveNo, L':', L'\\', 0 }; + + return GetVolumeInformationW (root, label, labelSize / 2, NULL, NULL, &fileSystemFlags, NULL, 0); +} + + +/* Stores the device path of the system partition in SysPartitionDevicePath and the device path of the system drive +in SysDriveDevicePath. +IMPORTANT: As this may take a very long time if called for the first time, it should be called only before performing + a dangerous operation (such as header backup restore or formatting a supposedly non-system device) never + at WM_INITDIALOG or any other GUI events -- instead call IsSystemDevicePath (path, hwndDlg, FALSE) for + very fast preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK + return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the user + selected the system partition/device. +After this function completes successfully, the results are cached for the rest of the session and repeated +executions complete very fast. Returns TRUE if successful (otherwise FALSE). */ +BOOL GetSysDevicePaths (HWND hwndDlg) +{ + if (!bCachedSysDevicePathsValid + || strlen (SysPartitionDevicePath) <= 1 + || strlen (SysDriveDevicePath) <= 1) + { + foreach (const HostDevice &device, GetAvailableHostDevices (false, true)) + { + if (device.ContainsSystem) + strcpy_s (device.IsPartition ? SysPartitionDevicePath : SysDriveDevicePath, TC_MAX_PATH, device.Path.c_str()); + } + + bCachedSysDevicePathsValid = 1; + } + + return (bCachedSysDevicePathsValid + && strlen (SysPartitionDevicePath) > 1 + && strlen (SysDriveDevicePath) > 1); +} + +/* Determines whether the device path is the path of the system partition or of the system drive (or neither). +If bReliableRequired is TRUE, very fast execution is guaranteed, but the results cannot be relied upon. +If it's FALSE and the function is called for the first time, execution may take up to one minute but the +results are reliable. +IMPORTANT: As the execution may take a very long time if called for the first time with bReliableRequired set + to TRUE, it should be called with bReliableRequired set to TRUE only before performing a dangerous + operation (such as header backup restore or formatting a supposedly non-system device) never at + WM_INITDIALOG or any other GUI events (use IsSystemDevicePath(path, hwndDlg, FALSE) for fast + preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK + return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the + user selected the system partition/device). +After this function completes successfully, the results are cached for the rest of the session, bReliableRequired +is ignored (TRUE implied), repeated executions complete very fast, and the results are always reliable. +Return codes: +1 - it is the system partition path (e.g. \Device\Harddisk0\Partition1) +2 - it is the system drive path (e.g. \Device\Harddisk0\Partition0) +0 - it's not the system partition/drive path +-1 - the result can't be determined, isn't reliable, or there was an error. */ +int IsSystemDevicePath (char *path, HWND hwndDlg, BOOL bReliableRequired) +{ + if (!bCachedSysDevicePathsValid + && bReliableRequired) + { + if (!GetSysDevicePaths (hwndDlg)) + return -1; + } + + if (strlen (SysPartitionDevicePath) <= 1 || strlen (SysDriveDevicePath) <= 1) + return -1; + + if (strncmp (path, SysPartitionDevicePath, max (strlen(path), strlen(SysPartitionDevicePath))) == 0) + return 1; + else if (strncmp (path, SysDriveDevicePath, max (strlen(path), strlen(SysDriveDevicePath))) == 0) + return 2; + + return 0; +} + + +wstring GetSysEncryptionPretestInfo2String (void) +{ + // This huge string is divided into smaller portions to make it easier for translators to + // re-translate it when a minor modification is made to it (the whole huge string will not be + // reverted to English, so they will have to translate only a small portion of it). + return (wstring (L"\n") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_1") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_2") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_3") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_4")); +} + + +wstring GetRescueDiskHelpString (void) +{ + // This huge string is divided into smaller portions to make it easier for translators to + // re-translate it when a minor modification is made to it (the whole huge string will not be + // reverted to English, so they will have to translate only a small portion of it). + return (wstring ( + GetString ("RESCUE_DISK_HELP_PORTION_1")) + + GetString ("RESCUE_DISK_HELP_PORTION_2") + + GetString ("RESCUE_DISK_HELP_PORTION_3") + + GetString ("RESCUE_DISK_HELP_PORTION_4") + + GetString ("RESCUE_DISK_HELP_PORTION_5") + + GetString ("RESCUE_DISK_HELP_PORTION_6") + + GetString ("RESCUE_DISK_HELP_PORTION_7") + + GetString ("RESCUE_DISK_HELP_PORTION_8") + + GetString ("RESCUE_DISK_HELP_PORTION_9")); +} + + +wstring GetDecoyOsInstructionsString (void) +{ + // This huge string is divided into smaller portions to make it easier for translators to + // re-translate it when a minor modification is made to it (the whole huge string will not be + // reverted to English, so they will have to translate only a small portion of it). + return (wstring ( + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_1")) + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_2") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_3") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_4") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_5") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_6") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_7") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_8") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_9") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_10") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_11") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_12") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_13") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_14") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_15") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_16") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_17") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_18")); +} + + +BOOL TextInfoDialogBox (int nID) +{ + return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_INFO_DIALOG_BOX_DLG), MainDlg, (DLGPROC) TextInfoDialogBoxDlgProc, (LPARAM) nID); +} + +BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + static int nID = 0; + + switch (msg) + { + case WM_INITDIALOG: + { + nID = (int) lParam; + + // Left margin for rich edit text field + SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); + + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_HIDE); + + switch (nID) + { + case TC_TBXID_LEGAL_NOTICES: + LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); + break; + + case TC_TBXID_SYS_ENCRYPTION_PRETEST: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + + case TC_TBXID_SYS_ENC_RESCUE_DISK: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + + case TC_TBXID_DECOY_OS_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + + case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + } + + SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); + } + return 0; + + case WM_COMMAND: + if (lw == IDOK || lw == IDCANCEL) + { + NormalCursor (); + EndDialog (hwndDlg, 0); + return 1; + } + + if (lw == IDC_PRINT) + { + switch (nID) + { + case TC_TBXID_SYS_ENCRYPTION_PRETEST: + PrintHardCopyTextUTF16 ((wchar_t *) GetSysEncryptionPretestInfo2String ().c_str(), "Pre-Boot Troubleshooting", GetSysEncryptionPretestInfo2String ().length () * 2); + break; + + case TC_TBXID_SYS_ENC_RESCUE_DISK: + PrintHardCopyTextUTF16 ((wchar_t *) GetRescueDiskHelpString ().c_str(), "TrueCrypt Rescue Disk Help", GetRescueDiskHelpString ().length () * 2); + break; + + case TC_TBXID_DECOY_OS_INSTRUCTIONS: + PrintHardCopyTextUTF16 ((wchar_t *) GetDecoyOsInstructionsString ().c_str(), "How to Create Decoy OS", GetDecoyOsInstructionsString ().length () * 2); + break; + + case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: + PrintHardCopyTextUTF16 (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS"), "How to Remove Extra Boot Partition", wcslen (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")) * 2); + break; + } + return 1; + } + + return 0; + + case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: + { + char *r = NULL; + + switch (nID) + { + case TC_TBXID_LEGAL_NOTICES: + LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); + r = GetLegalNotices (); + if (r != NULL) + { + SetWindowText (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), r); + free (r); + } + break; + + case TC_TBXID_SYS_ENCRYPTION_PRETEST: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetSysEncryptionPretestInfo2String ().c_str()); + break; + + case TC_TBXID_SYS_ENC_RESCUE_DISK: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetRescueDiskHelpString ().c_str()); + break; + + case TC_TBXID_DECOY_OS_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetDecoyOsInstructionsString ().c_str()); + break; + + case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")); + break; + } + } + return 1; + + case WM_CLOSE: + NormalCursor (); + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + + +char * GetLegalNotices () +{ + static char *resource; + static DWORD size; + char *buf = NULL; + + if (resource == NULL) + resource = (char *) MapResource ("Text", IDR_LICENSE, &size); + + if (resource != NULL) + { + buf = (char *) malloc (size + 1); + if (buf != NULL) + { + memcpy (buf, resource, size); + buf[size] = 0; + } + } + + return buf; +} + + +BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static char *lpszFileName; // This is actually a pointer to a GLOBAL array + static vector devices; + static map itemToDeviceMap; + + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + LVCOLUMNW LvCol; + HWND hList = GetDlgItem (hwndDlg, IDC_DEVICELIST); + + LocalizeDialog (hwndDlg, "IDD_RAWDEVICES_DLG"); + + SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP + ); + + memset (&LvCol,0,sizeof(LvCol)); + LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + LvCol.pszText = GetString ("DEVICE"); + LvCol.cx = CompensateXDPI (186); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("DRIVE"); + LvCol.cx = CompensateXDPI (38); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("SIZE"); + LvCol.cx = CompensateXDPI (64); + LvCol.fmt = LVCFMT_RIGHT; + SendMessage (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("VOLUME_LABEL"); + LvCol.cx = CompensateXDPI (128); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); + + devices.clear(); + itemToDeviceMap.clear(); + + WaitCursor(); + devices = GetAvailableHostDevices (false, true, false); + NormalCursor(); + + if (devices.empty()) + { + MessageBoxW (hwndDlg, GetString ("RAWDEVICES"), lpszTitle, ICON_HAND); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + int line = 1; + LVITEM item; + memset (&item, 0, sizeof (item)); + item.mask = LVIF_TEXT; + + foreach (const HostDevice &device, devices) + { + item.iSubItem = 1; + + if (device.ContainsSystem) + { + if (device.IsPartition) + strcpy_s (SysPartitionDevicePath, sizeof (SysPartitionDevicePath), device.Path.c_str()); + else + strcpy_s (SysDriveDevicePath, sizeof (SysDriveDevicePath), device.Path.c_str()); + } + + // Path + if (!device.IsPartition || device.DynamicVolume) + { + if (!device.Floppy && device.Size == 0) + continue; + + if (line > 1) + { + ListItemAdd (hList, item.iItem, ""); + item.iItem = line++; + } + + if (device.Floppy || device.DynamicVolume) + { + ListItemAdd (hList, item.iItem, (char *) device.Path.c_str()); + } + else + { + wchar_t s[1024]; + if (device.Removable) + wsprintfW (s, L"%s %d", GetString ("REMOVABLE_DISK"), device.SystemNumber); + else + wsprintfW (s, L"%s %d", GetString ("HARDDISK"), device.SystemNumber); + + if (!device.Partitions.empty()) + wcscat (s, L":"); + + ListItemAddW (hList, item.iItem, s); + } + } + else + { + ListItemAdd (hList, item.iItem, (char *) device.Path.c_str()); + } + + itemToDeviceMap[item.iItem] = device; + + // Size + if (device.Size != 0) + { + wchar_t size[100] = { 0 }; + GetSizeString (device.Size, size); + ListSubItemSetW (hList, item.iItem, 2, size); + } + + // Mount point + if (!device.MountPoint.empty()) + ListSubItemSet (hList, item.iItem, 1, (char *) device.MountPoint.c_str()); + + // Label + if (!device.Name.empty()) + ListSubItemSetW (hList, item.iItem, 3, (wchar_t *) device.Name.c_str()); + + item.iItem = line++; + } + + lpszFileName = (char *) lParam; + +#ifdef VOLFORMAT + EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); +#endif + return 1; + } + + case WM_COMMAND: + case WM_NOTIFY: + // catch non-device line selected + if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED )) + { + LVITEM LvItem; + memset(&LvItem,0,sizeof(LvItem)); + LvItem.mask = LVIF_TEXT | LVIF_PARAM; + LvItem.iItem = ((LPNMLISTVIEW) lParam)->iItem; + LvItem.pszText = lpszFileName; + LvItem.cchTextMax = TC_MAX_PATH; + + SendMessage (GetDlgItem (hwndDlg, IDC_DEVICELIST), LVM_GETITEM, LvItem.iItem, (LPARAM) &LvItem); + EnableWindow (GetDlgItem ((HWND) hwndDlg, IDOK), lpszFileName[0] != 0 && lpszFileName[0] != ' '); + + return 1; + } + + if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) + { + int selectedItem = ListView_GetSelectionMark (GetDlgItem (hwndDlg, IDC_DEVICELIST)); + + if (selectedItem == -1 || itemToDeviceMap.find (selectedItem) == itemToDeviceMap.end()) + return 1; // non-device line selected + + const HostDevice selectedDevice = itemToDeviceMap[selectedItem]; + strcpy_s (lpszFileName, TC_MAX_PATH, selectedDevice.Path.c_str()); + +#ifdef VOLFORMAT + if (selectedDevice.ContainsSystem && selectedDevice.IsPartition) + { + if (WizardMode != WIZARD_MODE_SYS_DEVICE) + { + if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE") == IDNO) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + bSysPartitionSelected = TRUE; + bSysDriveSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + + NormalCursor (); + EndDialog (hwndDlg, IDOK); + return 1; + } + else + { + // This should never be the case because the Select Device dialog is not available in this wizard mode + bSysPartitionSelected = TRUE; + bSysDriveSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + } + + if (!(selectedDevice.ContainsSystem && !selectedDevice.IsPartition)) + { + if (bWarnDeviceFormatAdvanced + && !bHiddenVolDirect + && AskWarnNoYes("FORMAT_DEVICE_FOR_ADVANCED_ONLY") == IDNO) + { + if (AskNoYes("CONFIRM_CHANGE_WIZARD_MODE_TO_FILE_CONTAINER") == IDYES) + { + SwitchWizardToFileContainerMode (); + } + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + if (!bHiddenVolDirect) + bWarnDeviceFormatAdvanced = FALSE; + } + +#else // #ifdef VOLFORMAT + + bSysPartitionSelected = (selectedDevice.ContainsSystem && selectedDevice.IsPartition); + bSysDriveSelected = FALSE; + +#endif // #ifdef VOLFORMAT + + if (!selectedDevice.IsPartition && !selectedDevice.Floppy) + { + // Whole device selected + +#ifdef VOLFORMAT + if (selectedDevice.ContainsSystem && !selectedDevice.IsPartition) + { + if (WizardMode != WIZARD_MODE_SYS_DEVICE) + { + if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE") == IDNO) + { + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + bSysDriveSelected = TRUE; + bSysPartitionSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + + NormalCursor (); + EndDialog (hwndDlg, IDOK); + return 1; + } + else + { + // This should never be the case because the Select Device dialog is not available in this wizard mode + bSysDriveSelected = TRUE; + bSysPartitionSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + } + + // Disallow format if the device contains partitions, but not if the partition is virtual or system + if (!selectedDevice.IsVirtualPartition + && !bHiddenVolDirect) + { + if (!selectedDevice.Partitions.empty()) + { + EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); + Error ("DEVICE_PARTITIONS_ERR_W_INPLACE_ENC_NOTE"); + return 1; + } + + if (AskWarnNoYes ("WHOLE_NONSYS_DEVICE_ENC_CONFIRM") == IDNO) + return 1; + } +#else // #ifdef VOLFORMAT + + bSysDriveSelected = (selectedDevice.ContainsSystem && !selectedDevice.IsPartition); + bSysPartitionSelected = FALSE; + +#endif // #ifdef VOLFORMAT + } + else + bSysDriveSelected = FALSE; + +#ifdef VOLFORMAT + bRemovableHostDevice = selectedDevice.Removable; +#endif + NormalCursor (); + EndDialog (hwndDlg, IDOK); + return 1; + } + + if (lw == IDCANCEL) + { + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + return 0; + } + return 0; +} + + +BOOL DoDriverInstall (HWND hwndDlg) +{ +#ifdef SETUP + if (SystemEncryptionUpgrade) + return TRUE; +#endif + + SC_HANDLE hManager, hService = NULL; + BOOL bOK = FALSE, bRet; + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + goto error; + +#ifdef SETUP + StatusMessage (hwndDlg, "INSTALLING_DRIVER"); +#endif + + hService = CreateService (hManager, "truecrypt", "truecrypt", + SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL, + !Is64BitOs () ? "System32\\drivers\\truecrypt.sys" : "SysWOW64\\drivers\\truecrypt.sys", + NULL, NULL, NULL, NULL, NULL); + + if (hService == NULL) + goto error; + else + CloseServiceHandle (hService); + + hService = OpenService (hManager, "truecrypt", SERVICE_ALL_ACCESS); + if (hService == NULL) + goto error; + +#ifdef SETUP + StatusMessage (hwndDlg, "STARTING_DRIVER"); +#endif + + bRet = StartService (hService, 0, NULL); + if (bRet == FALSE) + goto error; + + bOK = TRUE; + +error: + if (bOK == FALSE && GetLastError () != ERROR_SERVICE_ALREADY_RUNNING) + { + handleWin32Error (hwndDlg); + MessageBoxW (hwndDlg, GetString ("DRIVER_INSTALL_FAILED"), lpszTitle, MB_ICONHAND); + } + else + bOK = TRUE; + + if (hService != NULL) + CloseServiceHandle (hService); + + if (hManager != NULL) + CloseServiceHandle (hManager); + + return bOK; +} + + +// Install and start driver service and mark it for removal (non-install mode) +static int DriverLoad () +{ + HANDLE file; + WIN32_FIND_DATA find; + SC_HANDLE hManager, hService = NULL; + char driverPath[TC_MAX_PATH*2]; + BOOL res; + char *tmp; + + GetModuleFileName (NULL, driverPath, sizeof (driverPath)); + tmp = strrchr (driverPath, '\\'); + if (!tmp) + { + strcpy (driverPath, "."); + tmp = driverPath + 1; + } + + strcpy (tmp, !Is64BitOs () ? "\\truecrypt.sys" : "\\truecrypt-x64.sys"); + + file = FindFirstFile (driverPath, &find); + + if (file == INVALID_HANDLE_VALUE) + { + MessageBoxW (0, GetString ("DRIVER_NOT_FOUND"), lpszTitle, ICON_HAND); + return ERR_DONT_REPORT; + } + + FindClose (file); + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + { + if (GetLastError () == ERROR_ACCESS_DENIED) + { + MessageBoxW (0, GetString ("ADMIN_PRIVILEGES_DRIVER"), lpszTitle, ICON_HAND); + return ERR_DONT_REPORT; + } + + return ERR_OS_ERROR; + } + + hService = OpenService (hManager, "truecrypt", SERVICE_ALL_ACCESS); + if (hService != NULL) + { + // Remove stale service (driver is not loaded but service exists) + DeleteService (hService); + CloseServiceHandle (hService); + Sleep (500); + } + + hService = CreateService (hManager, "truecrypt", "truecrypt", + SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + driverPath, NULL, NULL, NULL, NULL, NULL); + + if (hService == NULL) + { + CloseServiceHandle (hManager); + return ERR_OS_ERROR; + } + + res = StartService (hService, 0, NULL); + DeleteService (hService); + + CloseServiceHandle (hManager); + CloseServiceHandle (hService); + + return !res ? ERR_OS_ERROR : ERROR_SUCCESS; +} + + +BOOL DriverUnload () +{ + MOUNT_LIST_STRUCT driver; + int refCount; + int volumesMounted; + DWORD dwResult; + BOOL bResult; + + SC_HANDLE hManager, hService = NULL; + BOOL bRet; + SERVICE_STATUS status; + int x; + BOOL driverUnloaded = FALSE; + + if (hDriver == INVALID_HANDLE_VALUE) + return TRUE; + + try + { + if (BootEncryption (NULL).GetStatus().DeviceFilterActive) + return FALSE; + } + catch (...) { } + + // Test for mounted volumes + bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL); + + if (!bResult) + { + bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL); + if (bResult) + volumesMounted = driver.ulMountedDrives; + } + + if (bResult) + { + if (volumesMounted != 0) + return FALSE; + } + else + return TRUE; + + // Test for any applications attached to driver + refCount = GetDriverRefCount (); + + if (refCount > 1) + return FALSE; + + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + + // Stop driver service + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + goto error; + + hService = OpenService (hManager, "truecrypt", SERVICE_ALL_ACCESS); + if (hService == NULL) + goto error; + + bRet = QueryServiceStatus (hService, &status); + if (bRet != TRUE) + goto error; + + if (status.dwCurrentState != SERVICE_STOPPED) + { + ControlService (hService, SERVICE_CONTROL_STOP, &status); + + for (x = 0; x < 10; x++) + { + bRet = QueryServiceStatus (hService, &status); + if (bRet != TRUE) + goto error; + + if (status.dwCurrentState == SERVICE_STOPPED) + { + driverUnloaded = TRUE; + break; + } + + Sleep (200); + } + } + else + driverUnloaded = TRUE; + +error: + if (hService != NULL) + CloseServiceHandle (hService); + + if (hManager != NULL) + CloseServiceHandle (hManager); + + if (driverUnloaded) + { + hDriver = INVALID_HANDLE_VALUE; + return TRUE; + } + + return FALSE; +} + + +int DriverAttach (void) +{ + /* Try to open a handle to the device driver. It will be closed later. */ + +#ifndef SETUP + + int nLoadRetryCount = 0; +start: + +#endif + + hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + + if (hDriver == INVALID_HANDLE_VALUE) + { +#ifndef SETUP + + LoadSysEncSettings (NULL); + + if (!CreateDriverSetupMutex ()) + { + // Another instance is already attempting to install, register or start the driver + + while (!CreateDriverSetupMutex ()) + { + Sleep (100); // Wait until the other instance finishes + } + + // Try to open a handle to the driver again (keep the mutex in case the other instance failed) + goto start; + } + else + { + // No other instance is currently attempting to install, register or start the driver + + if (SystemEncryptionStatus != SYSENC_STATUS_NONE) + { + // This is an inconsistent state. The config file indicates system encryption should be + // active, but the driver is not running. This may happen e.g. when the pretest fails and + // the user selects "Last Known Good Configuration" from the Windows boot menu. + // To fix this, we're going to reinstall the driver, start it, and register it for boot. + + if (DoDriverInstall (NULL)) + { + Sleep (1000); + hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + + try + { + BootEncryption bootEnc (NULL); + bootEnc.RegisterBootDriver (bootEnc.GetHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE ? true : false); + } + catch (Exception &e) + { + e.Show (NULL); + } + } + + CloseDriverSetupMutex (); + } + else + { + // Attempt to load the driver (non-install/portable mode) +load: + BOOL res = DriverLoad (); + + CloseDriverSetupMutex (); + + if (res != ERROR_SUCCESS) + return res; + + bPortableModeConfirmed = TRUE; + + hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + } + + if (bPortableModeConfirmed) + NotifyDriverOfPortableMode (); + } + +#endif // #ifndef SETUP + + if (hDriver == INVALID_HANDLE_VALUE) + return ERR_OS_ERROR; + } + + CloseDriverSetupMutex (); + + if (hDriver != INVALID_HANDLE_VALUE) + { + DWORD dwResult; + + BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); + + if (!bResult) + bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); + +#ifndef SETUP // Don't check version during setup to allow removal of another version + if (bResult == FALSE) + { + return ERR_OS_ERROR; + } + else if (DriverVersion != VERSION_NUM) + { + // Unload an incompatbile version of the driver loaded in non-install mode and load the required version + if (IsNonInstallMode () && CreateDriverSetupMutex () && DriverUnload () && nLoadRetryCount++ < 3) + goto load; + + CloseDriverSetupMutex (); + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + return ERR_DRIVER_VERSION; + } +#else + if (!bResult) + DriverVersion = 0; +#endif + } + + return 0; +} + + +void ResetCurrentDirectory () +{ + char p[MAX_PATH]; + if (!IsNonInstallMode () && SHGetFolderPath (NULL, CSIDL_PROFILE, NULL, 0, p) == ERROR_SUCCESS) + { + SetCurrentDirectory (p); + } + else + { + GetModPath (p, sizeof (p)); + SetCurrentDirectory (p); + } +} + + +BOOL BrowseFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter) +{ + return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter); +} + + +BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, char *initialDir, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension) +{ + OPENFILENAMEW ofn; + wchar_t file[TC_MAX_PATH] = { 0 }; + wchar_t wInitialDir[TC_MAX_PATH] = { 0 }; + wchar_t filter[1024]; + BOOL status = FALSE; + + CoInitialize (NULL); + + ZeroMemory (&ofn, sizeof (ofn)); + *lpszFileName = 0; + + if (initialDir) + { + swprintf_s (wInitialDir, sizeof (wInitialDir) / 2, L"%hs", initialDir); + ofn.lpstrInitialDir = wInitialDir; + } + + if (initialFileName) + wcscpy_s (file, array_capacity (file), initialFileName); + + ofn.lStructSize = sizeof (ofn); + ofn.hwndOwner = hwndDlg; + + wsprintfW (filter, L"%ls (*.*)%c*.*%c%ls (*.tc)%c*.tc%c%c", + GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); + ofn.lpstrFilter = browseFilter ? browseFilter : filter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = file; + ofn.nMaxFile = sizeof (file) / sizeof (file[0]); + ofn.lpstrTitle = GetString (stringId); + ofn.lpstrDefExt = defaultExtension; + ofn.Flags = OFN_HIDEREADONLY + | OFN_PATHMUSTEXIST + | (keepHistory ? 0 : OFN_DONTADDTORECENT) + | (saveMode ? OFN_OVERWRITEPROMPT : 0); + + if (!keepHistory) + CleanLastVisitedMRU (); + + if (!saveMode) + { + if (!GetOpenFileNameW (&ofn)) + goto ret; + } + else + { + if (!GetSaveFileNameW (&ofn)) + goto ret; + } + + WideCharToMultiByte (CP_ACP, 0, file, -1, lpszFileName, MAX_PATH, NULL, NULL); + + if (!keepHistory) + CleanLastVisitedMRU (); + + status = TRUE; + +ret: + ResetCurrentDirectory(); + CoUninitialize(); + + return status; +} + + +static char SelectMultipleFilesPath[131072]; +static int SelectMultipleFilesOffset; + +BOOL SelectMultipleFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory) +{ + OPENFILENAMEW ofn; + wchar_t file[0xffff * 2] = { 0 }; // The size must not exceed 0xffff*2 due to a bug in Windows 2000 and XP SP1 + wchar_t filter[1024]; + BOOL status = FALSE; + + CoInitialize (NULL); + + ZeroMemory (&ofn, sizeof (ofn)); + + *lpszFileName = 0; + ofn.lStructSize = sizeof (ofn); + ofn.hwndOwner = hwndDlg; + wsprintfW (filter, L"%ls (*.*)%c*.*%c%ls (*.tc)%c*.tc%c%c", + GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); + ofn.lpstrFilter = filter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = file; + ofn.nMaxFile = sizeof (file) / sizeof (file[0]); + ofn.lpstrTitle = GetString (stringId); + ofn.Flags = OFN_HIDEREADONLY + | OFN_EXPLORER + | OFN_PATHMUSTEXIST + | OFN_ALLOWMULTISELECT + | (keepHistory ? 0 : OFN_DONTADDTORECENT); + + if (!keepHistory) + CleanLastVisitedMRU (); + + if (!GetOpenFileNameW (&ofn)) + goto ret; + + if (file[ofn.nFileOffset - 1] != 0) + { + // Single file selected + WideCharToMultiByte (CP_ACP, 0, file, -1, lpszFileName, MAX_PATH, NULL, NULL); + SelectMultipleFilesOffset = 0; + } + else + { + // Multiple files selected + int n; + wchar_t *f = file; + char *s = SelectMultipleFilesPath; + while ((n = WideCharToMultiByte (CP_ACP, 0, f, -1, s, MAX_PATH, NULL, NULL)) > 1) + { + f += n; + s += n; + } + + SelectMultipleFilesOffset = ofn.nFileOffset; + SelectMultipleFilesNext (lpszFileName); + } + + if (!keepHistory) + CleanLastVisitedMRU (); + + status = TRUE; + +ret: + ResetCurrentDirectory(); + CoUninitialize(); + + return status; +} + + +BOOL SelectMultipleFilesNext (char *lpszFileName) +{ + if (SelectMultipleFilesOffset == 0) + return FALSE; + + strncpy (lpszFileName, SelectMultipleFilesPath, TC_MAX_PATH); + lpszFileName[TC_MAX_PATH - 1] = 0; + + if (lpszFileName[strlen (lpszFileName) - 1] != '\\') + strcat (lpszFileName, "\\"); + + strcat (lpszFileName, SelectMultipleFilesPath + SelectMultipleFilesOffset); + + SelectMultipleFilesOffset += strlen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1; + if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0) + SelectMultipleFilesOffset = 0; + + return TRUE; +} + + +static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) +{ + switch(uMsg) { + case BFFM_INITIALIZED: + { + /* WParam is TRUE since we are passing a path. + It would be FALSE if we were passing a pidl. */ + SendMessage (hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData); + break; + } + + case BFFM_SELCHANGED: + { + char szDir[TC_MAX_PATH]; + + /* Set the status window to the currently selected path. */ + if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) + { + SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir); + } + break; + } + + default: + break; + } + + return 0; +} + + +BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, char *dirName) +{ + BROWSEINFOW bi; + LPITEMIDLIST pidl; + LPMALLOC pMalloc; + BOOL bOK = FALSE; + + CoInitialize (NULL); + + if (SUCCEEDED (SHGetMalloc (&pMalloc))) + { + ZeroMemory (&bi, sizeof(bi)); + bi.hwndOwner = hwndDlg; + bi.pszDisplayName = 0; + bi.lpszTitle = GetString (lpszTitle); + bi.pidlRoot = 0; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM)dirName; + + pidl = SHBrowseForFolderW (&bi); + if (pidl != NULL) + { + if (SHGetPathFromIDList(pidl, dirName)) + { + bOK = TRUE; + } + + pMalloc->Free (pidl); + pMalloc->Release(); + } + } + + CoUninitialize(); + + return bOK; +} + + +std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) +{ + WCHAR szTmp[8192]; + + swprintf (szTmp, GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG")); + if (CheckCapsLock (hwndDlg, TRUE)) + wcscat (szTmp, GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); + +#ifdef TCMOUNT + if (TCBootLoaderOnInactiveSysEncDrive ()) + { + swprintf (szTmp, GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_OR_MODE_WRONG" : "PASSWORD_OR_MODE_WRONG")); + + if (CheckCapsLock (hwndDlg, TRUE)) + wcscat (szTmp, GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); + + wcscat (szTmp, GetString ("SYSENC_MOUNT_WITHOUT_PBA_NOTE")); + } +#endif + + return szTmp; +} + + +void handleError (HWND hwndDlg, int code) +{ + WCHAR szTmp[4096]; + + if (Silent) return; + + switch (code) + { + case ERR_OS_ERROR: + handleWin32Error (hwndDlg); + break; + case ERR_OUTOFMEMORY: + MessageBoxW (hwndDlg, GetString ("OUTOFMEMORY"), lpszTitle, ICON_HAND); + break; + + case ERR_PASSWORD_WRONG: + MessageBoxW (hwndDlg, GetWrongPasswordErrorMessage (hwndDlg).c_str(), lpszTitle, MB_ICONWARNING); + break; + + case ERR_DRIVE_NOT_FOUND: + MessageBoxW (hwndDlg, GetString ("NOT_FOUND"), lpszTitle, ICON_HAND); + break; + case ERR_FILES_OPEN: + MessageBoxW (hwndDlg, GetString ("OPENFILES_DRIVER"), lpszTitle, ICON_HAND); + break; + case ERR_FILES_OPEN_LOCK: + MessageBoxW (hwndDlg, GetString ("OPENFILES_LOCK"), lpszTitle, ICON_HAND); + break; + case ERR_VOL_SIZE_WRONG: + MessageBoxW (hwndDlg, GetString ("VOL_SIZE_WRONG"), lpszTitle, ICON_HAND); + break; + case ERR_COMPRESSION_NOT_SUPPORTED: + MessageBoxW (hwndDlg, GetString ("COMPRESSION_NOT_SUPPORTED"), lpszTitle, ICON_HAND); + break; + case ERR_PASSWORD_CHANGE_VOL_TYPE: + MessageBoxW (hwndDlg, GetString ("WRONG_VOL_TYPE"), lpszTitle, ICON_HAND); + break; + case ERR_VOL_SEEKING: + MessageBoxW (hwndDlg, GetString ("VOL_SEEKING"), lpszTitle, ICON_HAND); + break; + case ERR_CIPHER_INIT_FAILURE: + MessageBoxW (hwndDlg, GetString ("ERR_CIPHER_INIT_FAILURE"), lpszTitle, ICON_HAND); + break; + case ERR_CIPHER_INIT_WEAK_KEY: + MessageBoxW (hwndDlg, GetString ("ERR_CIPHER_INIT_WEAK_KEY"), lpszTitle, ICON_HAND); + break; + case ERR_VOL_ALREADY_MOUNTED: + MessageBoxW (hwndDlg, GetString ("VOL_ALREADY_MOUNTED"), lpszTitle, ICON_HAND); + break; + case ERR_FILE_OPEN_FAILED: + MessageBoxW (hwndDlg, GetString ("FILE_OPEN_FAILED"), lpszTitle, ICON_HAND); + break; + case ERR_VOL_MOUNT_FAILED: + MessageBoxW (hwndDlg, GetString ("VOL_MOUNT_FAILED"), lpszTitle, ICON_HAND); + break; + case ERR_NO_FREE_DRIVES: + MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND); + break; + case ERR_ACCESS_DENIED: + MessageBoxW (hwndDlg, GetString ("ACCESS_DENIED"), lpszTitle, ICON_HAND); + break; + + case ERR_DRIVER_VERSION: + wsprintfW (szTmp, GetString ("DRIVER_VERSION"), VERSION_STRING); + MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND); + break; + + case ERR_NEW_VERSION_REQUIRED: + MessageBoxW (hwndDlg, GetString ("NEW_VERSION_REQUIRED"), lpszTitle, ICON_HAND); + break; + + case ERR_SELF_TESTS_FAILED: + Error ("ERR_SELF_TESTS_FAILED"); + break; + + case ERR_VOL_FORMAT_BAD: + Error ("ERR_VOL_FORMAT_BAD"); + break; + + case ERR_ENCRYPTION_NOT_COMPLETED: + Error ("ERR_ENCRYPTION_NOT_COMPLETED"); + break; + + case ERR_NONSYS_INPLACE_ENC_INCOMPLETE: + Error ("ERR_NONSYS_INPLACE_ENC_INCOMPLETE"); + break; + + case ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG: + Error ("ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG"); + break; + + case ERR_PARAMETER_INCORRECT: + Error ("ERR_PARAMETER_INCORRECT"); + break; + + case ERR_USER_ABORT: + case ERR_DONT_REPORT: + // A non-error + break; + + default: + wsprintfW (szTmp, GetString ("ERR_UNKNOWN"), code); + MessageBoxW (hwndDlg, szTmp, lpszTitle, ICON_HAND); + } +} + +static BOOL CALLBACK LocalizeDialogEnum( HWND hwnd, LPARAM font) +{ + // Localization of controls + + if (LocalizationActive) + { + int ctrlId = GetDlgCtrlID (hwnd); + if (ctrlId != 0) + { + char name[10] = { 0 }; + GetClassName (hwnd, name, sizeof (name)); + + if (_stricmp (name, "Button") == 0 || _stricmp (name, "Static") == 0) + { + wchar_t *str = (wchar_t *) GetDictionaryValueByInt (ctrlId); + if (str != NULL) + SetWindowTextW (hwnd, str); + } + } + } + + // Font + SendMessage (hwnd, WM_SETFONT, (WPARAM) font, 0); + + return TRUE; +} + +void LocalizeDialog (HWND hwnd, char *stringId) +{ + LastDialogId = stringId; + SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) 'TRUE'); + SendMessage (hwnd, WM_SETFONT, (WPARAM) hUserFont, 0); + + if (stringId == NULL) + SetWindowText (hwnd, "TrueCrypt"); + else + SetWindowTextW (hwnd, GetString (stringId)); + + if (hUserFont != 0) + EnumChildWindows (hwnd, LocalizeDialogEnum, (LPARAM) hUserFont); +} + +void OpenVolumeExplorerWindow (int driveNo) +{ + char dosName[5]; + SHFILEINFO fInfo; + + sprintf (dosName, "%c:\\", (char) driveNo + 'A'); + + // Force explorer to discover the drive + SHGetFileInfo (dosName, 0, &fInfo, sizeof (fInfo), 0); + + ShellExecute (NULL, "open", dosName, NULL, NULL, SW_SHOWNORMAL); +} + +static BOOL explorerCloseSent; +static HWND explorerTopLevelWindow; + +static BOOL CALLBACK CloseVolumeExplorerWindowsChildEnum (HWND hwnd, LPARAM driveStr) +{ + char s[MAX_PATH]; + SendMessage (hwnd, WM_GETTEXT, sizeof (s), (LPARAM) s); + + if (strstr (s, (char *) driveStr) != NULL) + { + PostMessage (explorerTopLevelWindow, WM_CLOSE, 0, 0); + explorerCloseSent = TRUE; + return FALSE; + } + + return TRUE; +} + +static BOOL CALLBACK CloseVolumeExplorerWindowsEnum (HWND hwnd, LPARAM driveNo) +{ + char driveStr[10]; + char s[MAX_PATH]; + + sprintf (driveStr, "%c:\\", driveNo + 'A'); + + GetClassName (hwnd, s, sizeof s); + if (strcmp (s, "CabinetWClass") == 0) + { + GetWindowText (hwnd, s, sizeof s); + if (strstr (s, driveStr) != NULL) + { + PostMessage (hwnd, WM_CLOSE, 0, 0); + explorerCloseSent = TRUE; + return TRUE; + } + + explorerTopLevelWindow = hwnd; + EnumChildWindows (hwnd, CloseVolumeExplorerWindowsChildEnum, (LPARAM) driveStr); + } + + return TRUE; +} + +BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo) +{ + if (driveNo >= 0) + { + explorerCloseSent = FALSE; + EnumWindows (CloseVolumeExplorerWindowsEnum, (LPARAM) driveNo); + } + + return explorerCloseSent; +} + +void GetSizeString (unsigned __int64 size, wchar_t *str) +{ + static wchar_t *b, *kb, *mb, *gb, *tb, *pb; + static int serNo; + + if (b == NULL || serNo != LocalizationSerialNo) + { + serNo = LocalizationSerialNo; + kb = GetString ("KB"); + mb = GetString ("MB"); + gb = GetString ("GB"); + tb = GetString ("TB"); + pb = GetString ("PB"); + b = GetString ("BYTE"); + } + + if (size > 1024I64*1024*1024*1024*1024*99) + swprintf (str, L"%I64d %s", size/1024/1024/1024/1024/1024, pb); + else if (size > 1024I64*1024*1024*1024*1024) + swprintf (str, L"%.1f %s",(double)(size/1024.0/1024/1024/1024/1024), pb); + else if (size > 1024I64*1024*1024*1024*99) + swprintf (str, L"%I64d %s",size/1024/1024/1024/1024, tb); + else if (size > 1024I64*1024*1024*1024) + swprintf (str, L"%.1f %s",(double)(size/1024.0/1024/1024/1024), tb); + else if (size > 1024I64*1024*1024*99) + swprintf (str, L"%I64d %s",size/1024/1024/1024, gb); + else if (size > 1024I64*1024*1024) + swprintf (str, L"%.1f %s",(double)(size/1024.0/1024/1024), gb); + else if (size > 1024I64*1024*99) + swprintf (str, L"%I64d %s", size/1024/1024, mb); + else if (size > 1024I64*1024) + swprintf (str, L"%.1f %s",(double)(size/1024.0/1024), mb); + else if (size >= 1024I64) + swprintf (str, L"%I64d %s", size/1024, kb); + else + swprintf (str, L"%I64d %s", size, b); +} + +#ifndef SETUP +void GetSpeedString (unsigned __int64 speed, wchar_t *str) +{ + static wchar_t *b, *kb, *mb, *gb, *tb, *pb; + static int serNo; + + if (b == NULL || serNo != LocalizationSerialNo) + { + serNo = LocalizationSerialNo; + kb = GetString ("KB_PER_SEC"); + mb = GetString ("MB_PER_SEC"); + gb = GetString ("GB_PER_SEC"); + tb = GetString ("TB_PER_SEC"); + pb = GetString ("PB_PER_SEC"); + b = GetString ("B_PER_SEC"); + } + + if (speed > 1024I64*1024*1024*1024*1024*99) + swprintf (str, L"%I64d %s", speed/1024/1024/1024/1024/1024, pb); + else if (speed > 1024I64*1024*1024*1024*1024) + swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024/1024), pb); + else if (speed > 1024I64*1024*1024*1024*99) + swprintf (str, L"%I64d %s",speed/1024/1024/1024/1024, tb); + else if (speed > 1024I64*1024*1024*1024) + swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024), tb); + else if (speed > 1024I64*1024*1024*99) + swprintf (str, L"%I64d %s",speed/1024/1024/1024, gb); + else if (speed > 1024I64*1024*1024) + swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024/1024), gb); + else if (speed > 1024I64*1024*99) + swprintf (str, L"%I64d %s", speed/1024/1024, mb); + else if (speed > 1024I64*1024) + swprintf (str, L"%.1f %s",(double)(speed/1024.0/1024), mb); + else if (speed > 1024I64) + swprintf (str, L"%I64d %s", speed/1024, kb); + else + swprintf (str, L"%I64d %s", speed, b); +} + +static void DisplayBenchmarkResults (HWND hwndDlg) +{ + wchar_t item1[100]={0}; + LVITEMW LvItem; + HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); + int ea, i; + BOOL unsorted = TRUE; + BENCHMARK_REC tmp_line; + + /* Sort the list */ + + switch (benchmarkSortMethod) + { + case BENCHMARK_SORT_BY_SPEED: + + while (unsorted) + { + unsorted = FALSE; + for (i = 0; i < benchmarkTotalItems - 1; i++) + { + if (benchmarkTable[i].meanBytesPerSec < benchmarkTable[i+1].meanBytesPerSec) + { + unsorted = TRUE; + memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); + } + } + } + break; + + case BENCHMARK_SORT_BY_NAME: + + while (unsorted) + { + unsorted = FALSE; + for (i = 0; i < benchmarkTotalItems - 1; i++) + { + if (benchmarkTable[i].id > benchmarkTable[i+1].id) + { + unsorted = TRUE; + memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); + } + } + } + break; + } + + /* Render the results */ + + SendMessage (hList,LVM_DELETEALLITEMS,0,(LPARAM)&LvItem); + + for (i = 0; i < benchmarkTotalItems; i++) + { + ea = benchmarkTable[i].id; + + memset (&LvItem,0,sizeof(LvItem)); + LvItem.mask = LVIF_TEXT; + LvItem.iItem = i; + LvItem.iSubItem = 0; + LvItem.pszText = (LPWSTR) benchmarkTable[i].name; + SendMessageW (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + +#if PKCS5_BENCHMARKS + wcscpy (item1, L"-"); +#else + GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].encSpeed / benchmarkPerformanceFrequency.QuadPart)), item1); +#endif + LvItem.iSubItem = 1; + LvItem.pszText = item1; + + SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); + +#if PKCS5_BENCHMARKS + wcscpy (item1, L"-"); +#else + GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].decSpeed / benchmarkPerformanceFrequency.QuadPart)), item1); +#endif + LvItem.iSubItem = 2; + LvItem.pszText = item1; + + SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); + +#if PKCS5_BENCHMARKS + swprintf (item1, L"%d t", benchmarkTable[i].encSpeed); +#else + GetSpeedString (benchmarkTable[i].meanBytesPerSec, item1); +#endif + LvItem.iSubItem = 3; + LvItem.pszText = item1; + + SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); + } +} + +static BOOL PerformBenchmark(HWND hwndDlg) +{ + LARGE_INTEGER performanceCountStart, performanceCountEnd; + BYTE *lpTestBuffer; + PCRYPTO_INFO ci = NULL; + UINT64_STRUCT startDataUnitNo; + + startDataUnitNo.Value = 0; + +#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) + ci = crypto_open (); + if (!ci) + return FALSE; +#endif + + if (QueryPerformanceFrequency (&benchmarkPerformanceFrequency) == 0) + { + MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); + return FALSE; + } + + lpTestBuffer = (BYTE *) malloc(benchmarkBufferSize - (benchmarkBufferSize % 16)); + if (lpTestBuffer == NULL) + { + MessageBoxW (hwndDlg, GetString ("ERR_MEM_ALLOC"), lpszTitle, ICON_HAND); + return FALSE; + } + VirtualLock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); + + WaitCursor (); + benchmarkTotalItems = 0; + +#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) + // CPU "warm up" (an attempt to prevent skewed results on systems where CPU frequency + // gradually changes depending on CPU load). + ci->ea = EAGetFirst(); + if (!EAInit (ci->ea, ci->master_keydata, ci->ks)) + { + ci->mode = FIRST_MODE_OF_OPERATION_ID; + if (EAInitMode (ci)) + { + int i; + + for (i = 0; i < 2; i++) + { + EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + } + } + } +#endif + +#if HASH_FNC_BENCHMARKS + + /* Measures the speed at which each of the hash algorithms processes the message to produce + a single digest. + + The hash algorithm benchmarks are included here for development purposes only. Do not enable + them when building a public release (the benchmark GUI strings wouldn't make sense). */ + + { + BYTE *digest [MAX_DIGESTSIZE]; + WHIRLPOOL_CTX wctx; + RMD160_CTX rctx; + sha1_ctx sctx; + sha512_ctx s2ctx; + int hid; + + for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) + { + if (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + switch (hid) + { + case SHA1: + sha1_begin (&sctx); + sha1_hash (lpTestBuffer, benchmarkBufferSize, &sctx); + sha1_end ((unsigned char *) digest, &sctx); + break; + + case SHA512: + sha512_begin (&s2ctx); + sha512_hash (lpTestBuffer, benchmarkBufferSize, &s2ctx); + sha512_end ((unsigned char *) digest, &s2ctx); + break; + + case RIPEMD160: + RMD160Init(&rctx); + RMD160Update(&rctx, lpTestBuffer, benchmarkBufferSize); + RMD160Final((unsigned char *) digest, &rctx); + break; + + case WHIRLPOOL: + WHIRLPOOL_init (&wctx); + WHIRLPOOL_add (lpTestBuffer, benchmarkBufferSize * 8, &wctx); + WHIRLPOOL_finalize (&wctx, (unsigned char *) digest); + break; + } + + if (QueryPerformanceCounter (&performanceCountEnd) == 0) + goto counter_error; + + benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; + + benchmarkTable[benchmarkTotalItems].decSpeed = benchmarkTable[benchmarkTotalItems].encSpeed; + benchmarkTable[benchmarkTotalItems].id = hid; + benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; + sprintf (benchmarkTable[benchmarkTotalItems].name, "%s", HashGetName(hid)); + + benchmarkTotalItems++; + } + } + +#elif PKCS5_BENCHMARKS // #if HASH_FNC_BENCHMARKS + + /* Measures the time that it takes for the PKCS-5 routine to derive a header key using + each of the implemented PRF algorithms. + + The PKCS-5 benchmarks are included here for development purposes only. Do not enable + them when building a public release (the benchmark GUI strings wouldn't make sense). */ + { + int thid, i; + char dk[MASTER_KEYDATA_SIZE]; + char *tmp_salt = {"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"}; + + for (thid = FIRST_PRF_ID; thid <= LAST_PRF_ID; thid++) + { + if (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + for (i = 1; i <= 5; i++) + { + switch (thid) + { + case SHA1: + /* PKCS-5 test with HMAC-SHA-1 used as the PRF */ + derive_key_sha1 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); + break; + + case SHA512: + /* PKCS-5 test with HMAC-SHA-512 used as the PRF */ + derive_key_sha512 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); + break; + + case RIPEMD160: + /* PKCS-5 test with HMAC-RIPEMD-160 used as the PRF */ + derive_key_ripemd160 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); + break; + + case WHIRLPOOL: + /* PKCS-5 test with HMAC-Whirlpool used as the PRF */ + derive_key_whirlpool ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, FALSE), dk, MASTER_KEYDATA_SIZE); + break; + } + } + + if (QueryPerformanceCounter (&performanceCountEnd) == 0) + goto counter_error; + + benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; + benchmarkTable[benchmarkTotalItems].id = thid; + sprintf (benchmarkTable[benchmarkTotalItems].name, "%s", get_pkcs5_prf_name (thid)); + + benchmarkTotalItems++; + } + } + +#else // #elif PKCS5_BENCHMARKS + + /* Encryption algorithm benchmarks */ + + for (ci->ea = EAGetFirst(); ci->ea != 0; ci->ea = EAGetNext(ci->ea)) + { + if (!EAIsFormatEnabled (ci->ea)) + continue; + + EAInit (ci->ea, ci->master_keydata, ci->ks); + + ci->mode = FIRST_MODE_OF_OPERATION_ID; + EAInitMode (ci); + + if (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + + if (QueryPerformanceCounter (&performanceCountEnd) == 0) + goto counter_error; + + benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; + + if (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + + if (QueryPerformanceCounter (&performanceCountEnd) == 0) + goto counter_error; + + benchmarkTable[benchmarkTotalItems].decSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; + benchmarkTable[benchmarkTotalItems].id = ci->ea; + benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; + EAGetName (benchmarkTable[benchmarkTotalItems].name, ci->ea); + + benchmarkTotalItems++; + } + +#endif // #elif PKCS5_BENCHMARKS (#else) + + if (ci) + crypto_close (ci); + + VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); + + free(lpTestBuffer); + + benchmarkLastBufferSize = benchmarkBufferSize; + + DisplayBenchmarkResults(hwndDlg); + + EnableWindow (GetDlgItem (hwndDlg, IDC_PERFORM_BENCHMARK), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDCLOSE), TRUE); + + NormalCursor (); + return TRUE; + +counter_error: + + if (ci) + crypto_close (ci); + + VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); + + free(lpTestBuffer); + + NormalCursor (); + + EnableWindow (GetDlgItem (hwndDlg, IDC_PERFORM_BENCHMARK), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDCLOSE), TRUE); + + MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); + return FALSE; +} + + +BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + LPARAM nIndex; + HWND hCboxSortMethod = GetDlgItem (hwndDlg, IDC_BENCHMARK_SORT_METHOD); + HWND hCboxBufferSize = GetDlgItem (hwndDlg, IDC_BENCHMARK_BUFFER_SIZE); + + switch (msg) + { + case WM_INITDIALOG: + { + LVCOLUMNW LvCol; + wchar_t s[128]; + HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); + + LocalizeDialog (hwndDlg, "IDD_BENCHMARK_DLG"); + + benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; + benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; + + SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP + ); + + memset (&LvCol,0,sizeof(LvCol)); + LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + LvCol.pszText = GetString ("ALGORITHM"); + LvCol.cx = CompensateXDPI (114); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("ENCRYPTION"); + LvCol.cx = CompensateXDPI (80); + LvCol.fmt = LVCFMT_RIGHT; + SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("DECRYPTION"); + LvCol.cx = CompensateXDPI (80); + LvCol.fmt = LVCFMT_RIGHT; + SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("MEAN"); + LvCol.cx = CompensateXDPI (80); + LvCol.fmt = LVCFMT_RIGHT; + SendMessageW (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); + + /* Combo boxes */ + + // Sort method + + SendMessage (hCboxSortMethod, CB_RESETCONTENT, 0, 0); + + nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("ALPHABETICAL_CATEGORIZED")); + SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); + + nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("MEAN_SPEED")); + SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); + + SendMessage (hCboxSortMethod, CB_SETCURSEL, 1, 0); // Default sort method + + // Buffer size + + SendMessage (hCboxBufferSize, CB_RESETCONTENT, 0, 0); + + swprintf (s, L"100 %s", GetString ("KB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_KB); + + swprintf (s, L"500 %s", GetString ("KB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_KB); + + swprintf (s, L"1 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_MB); + + swprintf (s, L"5 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 5 * BYTES_PER_MB); + + swprintf (s, L"10 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 10 * BYTES_PER_MB); + + swprintf (s, L"50 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 50 * BYTES_PER_MB); + + swprintf (s, L"100 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_MB); + + swprintf (s, L"200 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 200 * BYTES_PER_MB); + + swprintf (s, L"500 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_MB); + + swprintf (s, L"1 %s", GetString ("GB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_GB); + + SendMessage (hCboxBufferSize, CB_SETCURSEL, 3, 0); // Default buffer size + + return 1; + } + break; + + case WM_COMMAND: + case WM_NOTIFY: + + if (lw == IDC_BENCHMARK_SORT_METHOD) + { + nIndex = SendMessage (hCboxSortMethod, CB_GETCURSEL, 0, 0); + if (nIndex != benchmarkSortMethod) + { + benchmarkSortMethod = nIndex; + DisplayBenchmarkResults (hwndDlg); + } + return 1; + } + + if (lw == IDC_PERFORM_BENCHMARK) + { + nIndex = SendMessage (hCboxBufferSize, CB_GETCURSEL, 0, 0); + benchmarkBufferSize = SendMessage (hCboxBufferSize, CB_GETITEMDATA, nIndex, 0); + + if (PerformBenchmark (hwndDlg) == FALSE) + { + EndDialog (hwndDlg, IDCLOSE); + } + return 1; + } + if (lw == IDCLOSE || lw == IDCANCEL) + { + EndDialog (hwndDlg, IDCLOSE); + return 1; + } + return 0; + + break; + + case WM_CLOSE: + EndDialog (hwndDlg, IDCLOSE); + return 1; + + break; + + } + return 0; +} + + +static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + static unsigned char randPool [RNG_POOL_SIZE]; + static unsigned char lastRandPool [RNG_POOL_SIZE]; + static char outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; + static BOOL bDisplayPoolContents = TRUE; + static BOOL bRandPoolDispAscii = FALSE; + int hash_algo = RandGetHashFunction(); + int hid; + + switch (msg) + { + case WM_INITDIALOG: + { + HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); + + VirtualLock (randPool, sizeof(randPool)); + VirtualLock (lastRandPool, sizeof(lastRandPool)); + VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); + + LocalizeDialog (hwndDlg, "IDD_RANDOM_POOL_ENRICHMENT"); + + SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); + for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) + { + if (!HashIsDeprecated (hid)) + AddComboPair (hComboBox, HashGetName(hid), hid); + } + SelectAlgo (hComboBox, &hash_algo); + + SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); + + SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); + SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + return 1; + } + + case WM_TIMER: + { + char tmp[4]; + unsigned char tmpByte; + int col, row; + + if (bDisplayPoolContents) + { + RandpeekBytes (randPool, sizeof (randPool)); + + if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) + { + outputDispBuffer[0] = 0; + + for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) + { + for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) + { + tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; + + sprintf (tmp, bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != '&') ? " %c " : " . ") : "%02X ", tmpByte); + strcat (outputDispBuffer, tmp); + } + strcat (outputDispBuffer, "\n"); + } + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + + memcpy (lastRandPool, randPool, sizeof(lastRandPool)); + } + } + return 1; + } + + case WM_COMMAND: + if (lw == IDC_CONTINUE) + lw = IDOK; + + if (lw == IDOK || lw == IDCLOSE || lw == IDCANCEL) + { + goto exit; + } + + if (lw == IDC_PRF_ID && hw == CBN_SELCHANGE) + { + hid = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETCURSEL, 0, 0); + hash_algo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETITEMDATA, hid, 0); + RandSetHashFunction (hash_algo); + return 1; + } + + if (lw == IDC_DISPLAY_POOL_CONTENTS) + { + if (!(bDisplayPoolContents = GetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS))) + { + char tmp[RNG_POOL_SIZE+1]; + + memset (tmp, ' ', sizeof(tmp)); + tmp [RNG_POOL_SIZE] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); + } + + return 1; + } + + return 0; + + case WM_CLOSE: + { + char tmp[RNG_POOL_SIZE+1]; +exit: + KillTimer (hwndDlg, 0xfd); + + burn (randPool, sizeof(randPool)); + burn (lastRandPool, sizeof(lastRandPool)); + burn (outputDispBuffer, sizeof(outputDispBuffer)); + + // Attempt to wipe the pool contents in the GUI text area + memset (tmp, 'X', RNG_POOL_SIZE); + tmp [RNG_POOL_SIZE] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); + + if (msg == WM_COMMAND && lw == IDOK) + EndDialog (hwndDlg, IDOK); + else + EndDialog (hwndDlg, IDCLOSE); + + return 1; + } + } + return 0; +} + + +void UserEnrichRandomPool (HWND hwndDlg) +{ + Randinit(); + + if (!IsRandomPoolEnrichedByUser()) + { + INT_PTR result = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RANDOM_POOL_ENRICHMENT), hwndDlg ? hwndDlg : MainDlg, (DLGPROC) RandomPoolEnrichementDlgProc, (LPARAM) 0); + SetRandomPoolEnrichedByUserStatus (result == IDOK); + } +} + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK +KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + static unsigned char randPool [RNG_POOL_SIZE]; + static unsigned char lastRandPool [RNG_POOL_SIZE]; + static char outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; + static BOOL bDisplayPoolContents = TRUE; + static BOOL bRandPoolDispAscii = FALSE; + int hash_algo = RandGetHashFunction(); + int hid; + + switch (msg) + { + case WM_INITDIALOG: + { + HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); + + VirtualLock (randPool, sizeof(randPool)); + VirtualLock (lastRandPool, sizeof(lastRandPool)); + VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); + + LocalizeDialog (hwndDlg, "IDD_KEYFILE_GENERATOR_DLG"); + + SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); + for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) + { + if (!HashIsDeprecated (hid)) + AddComboPair (hComboBox, HashGetName(hid), hid); + } + SelectAlgo (hComboBox, &hash_algo); + + SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); + +#ifndef VOLFORMAT + if (Randinit ()) + { + Error ("INIT_RAND"); + EndDialog (hwndDlg, IDCLOSE); + } +#endif + SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); + SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + return 1; + } + + case WM_TIMER: + { + char tmp[4]; + unsigned char tmpByte; + int col, row; + + if (bDisplayPoolContents) + { + RandpeekBytes (randPool, sizeof (randPool)); + + if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) + { + outputDispBuffer[0] = 0; + + for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) + { + for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) + { + tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; + + sprintf (tmp, bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != '&') ? " %c " : " . ") : "%02X ", tmpByte); + strcat (outputDispBuffer, tmp); + } + strcat (outputDispBuffer, "\n"); + } + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + + memcpy (lastRandPool, randPool, sizeof(lastRandPool)); + } + } + return 1; + } + + case WM_COMMAND: + + if (lw == IDCLOSE || lw == IDCANCEL) + { + goto exit; + } + + if (lw == IDC_PRF_ID && hw == CBN_SELCHANGE) + { + hid = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETCURSEL, 0, 0); + hash_algo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETITEMDATA, hid, 0); + RandSetHashFunction (hash_algo); + return 1; + } + + if (lw == IDC_DISPLAY_POOL_CONTENTS) + { + if (!(bDisplayPoolContents = GetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS))) + { + char tmp[RNG_POOL_SIZE+1]; + + memset (tmp, ' ', sizeof(tmp)); + tmp [RNG_POOL_SIZE] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); + } + return 1; + } + + if (lw == IDC_GENERATE_AND_SAVE_KEYFILE) + { + char szFileName [TC_MAX_PATH]; + unsigned char keyfile [MAX_PASSWORD]; + int fhKeyfile = -1; + + /* Select filename */ + if (!BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, TRUE, NULL)) + return 1; + + /* Conceive the file */ + if ((fhKeyfile = _open(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) + { + handleWin32Error (hwndDlg); + return 1; + } + + /* Generate the keyfile */ + WaitCursor(); + if (!RandgetBytes (keyfile, sizeof(keyfile), TRUE)) + { + _close (fhKeyfile); + DeleteFile (szFileName); + NormalCursor(); + return 1; + } + NormalCursor(); + + /* Write the keyfile */ + if (_write (fhKeyfile, keyfile, sizeof(keyfile)) == -1) + handleWin32Error (hwndDlg); + else + Info("KEYFILE_CREATED"); + + burn (keyfile, sizeof(keyfile)); + _close (fhKeyfile); + return 1; + } + return 0; + + case WM_CLOSE: + { + char tmp[RNG_POOL_SIZE+1]; +exit: + WaitCursor(); + KillTimer (hwndDlg, 0xfd); + +#ifndef VOLFORMAT + RandStop (FALSE); +#endif + /* Cleanup */ + + burn (randPool, sizeof(randPool)); + burn (lastRandPool, sizeof(lastRandPool)); + burn (outputDispBuffer, sizeof(outputDispBuffer)); + + // Attempt to wipe the pool contents in the GUI text area + memset (tmp, 'X', RNG_POOL_SIZE); + tmp [RNG_POOL_SIZE] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); + + EndDialog (hwndDlg, IDCLOSE); + NormalCursor (); + return 1; + } + } + return 0; +} + + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure +should return nonzero if it processes the message, and zero if it does +not. - see DialogProc */ +BOOL CALLBACK +CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static int idTestCipher = -1; /* Currently selected cipher for the test vector facility (none = -1). */ + static BOOL bXTSTestEnabled = FALSE; + + PCRYPTO_INFO ci; + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + + switch (uMsg) + { + case WM_INITDIALOG: + { + int ea; + char buf[100]; + + LocalizeDialog (hwndDlg, "IDD_CIPHER_TEST_DLG"); + + SendMessage(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), WM_SETFONT, (WPARAM)hBoldFont, MAKELPARAM(TRUE,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY), EM_LIMITTEXT, 128,0); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), EM_LIMITTEXT,64,0); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), EM_LIMITTEXT,64,0); + SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), EM_LIMITTEXT, 128,0); + SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), EM_LIMITTEXT,32,0); + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED, bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + + if (idTestCipher == -1) + idTestCipher = (int) lParam; + + SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_RESETCONTENT, 0, 0); + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (EAGetCipherCount (ea) == 1 && EAIsFormatEnabled (ea)) + AddComboPair (GetDlgItem (hwndDlg, IDC_CIPHER), EAGetName (buf, ea), EAGetFirstCipher (ea)); + } + + ResetCipherTest(hwndDlg, idTestCipher); + + SelectAlgo (GetDlgItem (hwndDlg, IDC_CIPHER), &idTestCipher); + + return 1; + } + + case WM_COMMAND: + + if (hw == CBN_SELCHANGE && lw == IDC_CIPHER) + { + idTestCipher = (int) SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETCURSEL, 0, 0), 0); + ResetCipherTest(hwndDlg, idTestCipher); + SendMessage (hwndDlg, WM_INITDIALOG, 0, 0); + return 1; + } + + if (hw == CBN_SELCHANGE && lw == IDC_KEY_SIZE) + { + // NOP + return 1; + } + + if (lw == IDC_RESET) + { + ResetCipherTest(hwndDlg, idTestCipher); + + return 1; + } + + if (lw == IDC_AUTO) + { + WaitCursor (); + if (!AutoTestAlgorithms()) + { + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); + SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_FAILED")); + } + else + { + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); + SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_PASSED")); + ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_SHOWNORMAL); + } + NormalCursor (); + + return 1; + + } + + if (lw == IDC_XTS_MODE_ENABLED) + { + bXTSTestEnabled = GetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED); + EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + if (bXTSTestEnabled) + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, 0,0); + } + + if (lw == IDOK || lw == IDC_ENCRYPT || lw == IDC_DECRYPT) + { + char key[128+1], inputtext[128+1], secondaryKey[64+1], dataUnitNo[16+1], szTmp[128+1]; + int ks, pt, n, tlen, blockNo = 0; + BOOL bEncrypt; + + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); + + ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETCURSEL, 0,0); + ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETITEMDATA, ks,0); + pt = (int) SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_GETITEMDATA, 0,0); + + bEncrypt = lw == IDC_ENCRYPT; + + memset(key,0,sizeof(key)); + memset(szTmp,0,sizeof(szTmp)); + n = GetWindowText(GetDlgItem(hwndDlg, IDC_KEY), szTmp, sizeof(szTmp)); + if (n != ks * 2) + { + Warning ("TEST_KEY_SIZE"); + return 1; + } + + for (n = 0; n < ks; n ++) + { + char szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = strtol(szTmp2, &ptr, 16); + + key[n] = (char) x; + } + + memset(inputtext, 0, sizeof(inputtext)); + memset(secondaryKey, 0, sizeof(secondaryKey)); + memset(dataUnitNo, 0, sizeof(dataUnitNo)); + memset(szTmp, 0, sizeof(szTmp)); + + if (bEncrypt) + { + n = GetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), szTmp, sizeof(szTmp)); + } + else + { + n = GetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), szTmp, sizeof(szTmp)); + } + + if (n != pt * 2) + { + if (bEncrypt) + { + Warning ("TEST_PLAINTEXT_SIZE"); + return 1; + } + else + { + Warning ("TEST_CIPHERTEXT_SIZE"); + return 1; + } + } + + for (n = 0; n < pt; n ++) + { + char szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = strtol(szTmp2, &ptr, 16); + + inputtext[n] = (char) x; + } + + // XTS + if (bXTSTestEnabled) + { + // Secondary key + + if (GetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), szTmp, sizeof(szTmp)) != 64) + { + Warning ("TEST_INCORRECT_SECONDARY_KEY_SIZE"); + return 1; + } + + for (n = 0; n < 64; n ++) + { + char szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = strtol(szTmp2, &ptr, 16); + + secondaryKey[n] = (char) x; + } + + // Data unit number + + tlen = GetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), szTmp, sizeof(szTmp)); + + if (tlen > 16 || tlen < 1) + { + Warning ("TEST_INCORRECT_TEST_DATA_UNIT_SIZE"); + return 1; + } + + LeftPadString (szTmp, tlen, 16, '0'); + + for (n = 0; n < 16; n ++) + { + char szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = strtol(szTmp2, &ptr, 16); + + dataUnitNo[n] = (char) x; + } + + // Block number + + blockNo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETCURSEL, 0, 0), 0); + } // if (bXTSTestEnabled) + + + /* Perform the actual tests */ + + if (ks != CB_ERR && pt != CB_ERR) + { + char tmp[128]; + int tmpRetVal; + + /* Copy the plain/ciphertext */ + memcpy(tmp,inputtext, pt); + + if (bXTSTestEnabled) + { + UINT64_STRUCT structDataUnitNo; + + /* XTS mode */ + + ci = crypto_open (); + if (!ci) + return 1; + + ci->mode = XTS; + + for (ci->ea = EAGetFirst (); ci->ea != 0 ; ci->ea = EAGetNext (ci->ea)) + if (EAGetCipherCount (ci->ea) == 1 && EAGetFirstCipher (ci->ea) == idTestCipher) + break; + + if ((tmpRetVal = EAInit (ci->ea, (unsigned char *) key, ci->ks)) != ERR_SUCCESS) + { + handleError (hwndDlg, tmpRetVal); + return 1; + } + + memcpy (&ci->k2, secondaryKey, sizeof (secondaryKey)); + if (!EAInitMode (ci)) + return 1; + + structDataUnitNo.Value = BE64(((unsigned __int64 *)dataUnitNo)[0]); + + if (bEncrypt) + EncryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); + else + DecryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); + + crypto_close (ci); + } + else + { + if (idTestCipher == BLOWFISH) + { + /* Deprecated/legacy */ + + /* Convert to little-endian, this is needed here and not in + above auto-tests because BF_ecb_encrypt above correctly converts + from big to little endian, and EncipherBlock does not! */ + LongReverse((unsigned int *) tmp, pt); + } + + CipherInit2(idTestCipher, key, ks_tmp, ks); + + if (bEncrypt) + { + EncipherBlock(idTestCipher, tmp, ks_tmp); + } + else + { + DecipherBlock(idTestCipher, tmp, ks_tmp); + } + + if (idTestCipher == BLOWFISH) + { + /* Deprecated/legacy */ + + /* Convert back to big-endian */ + LongReverse((unsigned int *) tmp, pt); + } + } + *szTmp = 0; + + for (n = 0; n < pt; n ++) + { + char szTmp2[3]; + sprintf(szTmp2, "%02x", (int)((unsigned char)tmp[n])); + strcat(szTmp, szTmp2); + } + + if (bEncrypt) + SetWindowText(GetDlgItem(hwndDlg,IDC_CIPHERTEXT), szTmp); + else + SetWindowText(GetDlgItem(hwndDlg,IDC_PLAINTEXT), szTmp); + } + + return 1; + } + + if (lw == IDCLOSE || lw == IDCANCEL) + { + idTestCipher = -1; + EndDialog (hwndDlg, 0); + return 1; + } + break; + + case WM_CLOSE: + idTestCipher = -1; + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + +void +ResetCipherTest(HWND hwndDlg, int idTestCipher) +{ + int ndx; + + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); + + EnableWindow(GetDlgItem(hwndDlg,IDC_KEY_SIZE), FALSE); + + /* Setup the keysize and plaintext sizes for the selected cipher */ + + SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); + SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_RESETCONTENT, 0,0); + SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_RESETCONTENT, 0,0); + + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) "64"); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 8); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); + + for (ndx = 0; ndx < BLOCKS_PER_XTS_DATA_UNIT; ndx++) + { + char tmpStr [16]; + + sprintf (tmpStr, "%d", ndx); + + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_ADDSTRING, 0,(LPARAM) tmpStr); + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETITEMDATA, ndx,(LPARAM) ndx); + } + + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETCURSEL, 0, 0); + + SetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), "0000000000000000000000000000000000000000000000000000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), "0"); + + if (idTestCipher == BLOWFISH) + { + /* Deprecated/legacy */ + + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "448"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 56); + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "256"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32); + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "128"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "64"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 8); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, 0,0); + SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + } + + + if (idTestCipher == CAST) + { + /* Deprecated/legacy */ + + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "128"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); + SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "00000000000000000000000000000000"); + } + + if (idTestCipher == TRIPLEDES) + { + /* Deprecated/legacy */ + + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "168"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 24); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); + SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "000000000000000000000000000000000000000000000000"); + } + + SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), "0000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), "0000000000000000"); + + if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH) + { + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) "256"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); + + SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); + ndx = SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) "128"); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); + + SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), "0000000000000000000000000000000000000000000000000000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), "00000000000000000000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), "00000000000000000000000000000000"); + } +} + +#endif // #ifndef SETUP + + +BOOL CALLBACK MultiChoiceDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + int nChoiceIDs [MAX_MULTI_CHOICES+1] = { IDC_MULTI_CHOICE_MSG, IDC_CHOICE1, IDC_CHOICE2, IDC_CHOICE3, + IDC_CHOICE4, IDC_CHOICE5, IDC_CHOICE6, IDC_CHOICE7, IDC_CHOICE8, IDC_CHOICE9, IDC_CHOICE10 }; + int nBaseButtonWidth = 0; + int nBaseButtonHeight = 0; + int nActiveChoices = -1; + int nStr = 0; + int vertSubOffset, horizSubOffset, vertMsgHeightOffset; + int vertOffset = 0; + int nLongestButtonCaptionWidth = 6; + int nLongestButtonCaptionCharLen = 1; + int nTextGfxLineHeight = 0; + int nMainTextLenInChars = 0; + int newLineSeqCount = 0; + RECT rec, wrec, wtrec, trec; + BOOL bResolve; + + WORD lw = LOWORD (wParam); + + switch (uMsg) + { + case WM_INITDIALOG: + { + char **pStr = (char **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; + char **pStrOrig = pStr; + wchar_t **pwStr = (wchar_t **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; + wchar_t **pwStrOrig = pwStr; + + LocalizeDialog (hwndDlg, NULL); + + SetWindowPos (hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + SetWindowPos (hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + bResolve = (*pStr == NULL); + + // Style + if (((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->bold) + { + SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_CHOICE_MSG), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + } + + // Process the strings + pStr++; + pwStr++; + + do + { + if (*pStr != 0) + { + SetWindowTextW (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), bResolve ? GetString(*pStr) : *pwStr); + + if (nStr > 0) + { + nLongestButtonCaptionWidth = max ( + GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_CHOICE1), + bResolve ? GetString(*pStr) : *pwStr, + hUserFont), + nLongestButtonCaptionWidth); + + nLongestButtonCaptionCharLen = max (nLongestButtonCaptionCharLen, + (int) wcslen ((const wchar_t *) (bResolve ? GetString(*pStr) : *pwStr))); + } + + nActiveChoices++; + pStr++; + pwStr++; + } + else + { + ShowWindow(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), SW_HIDE); + } + nStr++; + + } while (nStr < MAX_MULTI_CHOICES+1); + + // Length of main message in characters (not bytes) + nMainTextLenInChars = wcslen ((const wchar_t *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1))); + + if (nMainTextLenInChars > 200 + && nMainTextLenInChars / nLongestButtonCaptionCharLen >= 10) + { + // As the main text is longer than 200 characters, we will "pad" the widest button caption with + // spaces (if it is not wide enough) so as to increase the width of the whole dialog window. + // Otherwise, it would look too tall (dialog boxes look better when they are more wide than tall). + nLongestButtonCaptionWidth = CompensateXDPI (max ( + nLongestButtonCaptionWidth, + min (350, nMainTextLenInChars))); + } + + // Get the window coords + GetWindowRect(hwndDlg, &wrec); + + // Get the base button size + GetClientRect(GetDlgItem(hwndDlg, IDC_CHOICE1), &rec); + nBaseButtonWidth = rec.right + 2; + nBaseButtonHeight = rec.bottom + 2; + + // Increase in width based on the gfx length of the widest button caption + horizSubOffset = min (CompensateXDPI (500), max (0, nLongestButtonCaptionWidth + CompensateXDPI (50) - nBaseButtonWidth)); + + // Vertical "title bar" offset + GetClientRect(hwndDlg, &wtrec); + vertOffset = wrec.bottom - wrec.top - wtrec.bottom - GetSystemMetrics(SM_CYFIXEDFRAME); + + // Height/width of the message text + GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); + + // Determine the number of newlines contained in the message text + { + int64 offset = -1; + + do + { + offset = FindString ((char *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1)), + (char *) L"\n", + nMainTextLenInChars * 2, + wcslen (L"\n") * 2, + offset + 1); + + newLineSeqCount++; + + } while (offset != -1); + } + + nTextGfxLineHeight = GetTextGfxHeight (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), + bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), + hUserFont); + + vertMsgHeightOffset = ((GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), + bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), + hUserFont) / (trec.right + horizSubOffset) + 1) * nTextGfxLineHeight) - trec.bottom; + + vertMsgHeightOffset = min (CompensateYDPI (350), vertMsgHeightOffset + newLineSeqCount * nTextGfxLineHeight + (trec.bottom + vertMsgHeightOffset) / 10); // As reserve, we are adding 10% and the number of lines equal to the number of newlines in the message + + // Reduction in height according to the number of shown buttons + vertSubOffset = ((MAX_MULTI_CHOICES - nActiveChoices) * nBaseButtonHeight); + + if (horizSubOffset > 0 + || vertMsgHeightOffset > 0 + || vertOffset > 0) + { + // Resize/move each button if necessary + for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) + { + GetWindowRect(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), &rec); + + MoveWindow (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset + vertMsgHeightOffset, + nBaseButtonWidth + horizSubOffset, + nBaseButtonHeight, + TRUE); + } + + // Resize/move the remaining GUI elements + GetWindowRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &rec); + GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); + MoveWindow (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset, + trec.right + 2 + horizSubOffset, + trec.bottom + 2 + vertMsgHeightOffset, + TRUE); + + GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &rec); + GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &trec); + MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset, + trec.right + 2 + horizSubOffset, + trec.bottom + 2, + TRUE); + + GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &rec); + GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &trec); + MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset + vertMsgHeightOffset, + trec.right + 2 + horizSubOffset, + trec.bottom + 2, + TRUE); + } + + // Resize the window according to number of shown buttons and the longest button caption + MoveWindow (hwndDlg, + wrec.left - horizSubOffset / 2, + wrec.top + vertSubOffset / 2 - vertMsgHeightOffset / 2, + wrec.right - wrec.left + horizSubOffset, + wrec.bottom - wrec.top - vertSubOffset + 1 + vertMsgHeightOffset, + TRUE); + + return 1; + } + + case WM_COMMAND: + + if (lw == IDCLOSE || lw == IDCANCEL) + { + EndDialog (hwndDlg, 0); + return 1; + } + + for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) + { + if (lw == nChoiceIDs[nStr]) + { + EndDialog (hwndDlg, nStr); + return 1; + } + } + break; + + case WM_CLOSE: + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + + +BOOL CheckCapsLock (HWND hwnd, BOOL quiet) +{ + if ((GetKeyState(VK_CAPITAL) & 1) != 0) + { + if (!quiet) + { + MessageBoxW (hwnd, GetString ("CAPSLOCK_ON"), lpszTitle, MB_ICONEXCLAMATION); + } + return TRUE; + } + return FALSE; +} + + +// Checks whether the file extension is not used for executable files or similarly problematic, which often +// causes Windows and antivirus software to interfere with the container +BOOL CheckFileExtension (char *fileName) +{ + int i = 0; + char *ext = strrchr (fileName, '.'); + static char *problemFileExt[] = { + // These are protected by the Windows Resource Protection + ".asa", ".asp", ".aspx", ".ax", ".bas", ".bat", ".bin", ".cer", ".chm", ".clb", ".cmd", ".cnt", ".cnv", + ".com", ".cpl", ".cpx", ".crt", ".csh", ".dll", ".drv", ".dtd", ".exe", ".fxp", ".grp", ".h1s", ".hlp", + ".hta", ".ime", ".inf", ".ins", ".isp", ".its", ".js", ".jse", ".ksh", ".lnk", ".mad", ".maf", ".mag", + ".mam", ".man", ".maq", ".mar", ".mas", ".mat", ".mau", ".mav", ".maw", ".mda", ".mdb", ".mde", ".mdt", + ".mdw", ".mdz", ".msc", ".msi", ".msp", ".mst", ".mui", ".nls", ".ocx", ".ops", ".pal", ".pcd", ".pif", + ".prf", ".prg", ".pst", ".reg", ".scf", ".scr", ".sct", ".shb", ".shs", ".sys", ".tlb", ".tsp", ".url", + ".vb", ".vbe", ".vbs", ".vsmacros", ".vss", ".vst", ".vsw", ".ws", ".wsc", ".wsf", ".wsh", ".xsd", ".xsl", + // These additional file extensions are usually watched by antivirus programs + ".386", ".acm", ".ade", ".adp", ".ani", ".app", ".asd", ".asf", ".asx", ".awx", ".ax", ".boo", ".bz2", ".cdf", + ".class", ".dhtm", ".dhtml",".dlo", ".emf", ".eml", ".flt", ".fot", ".gz", ".hlp", ".htm", ".html", ".ini", + ".j2k", ".jar", ".jff", ".jif", ".jmh", ".jng", ".jp2", ".jpe", ".jpeg", ".jpg", ".lsp", ".mod", ".nws", + ".obj", ".olb", ".osd", ".ov1", ".ov2", ".ov3", ".ovl", ".ovl", ".ovr", ".pdr", ".pgm", ".php", ".pkg", + ".pl", ".png", ".pot", ".pps", ".ppt", ".ps1", ".ps1xml", ".psc1", ".rar", ".rpl", ".rtf", ".sbf", ".script", ".sh", ".sha", ".shtm", + ".shtml", ".spl", ".swf", ".tar", ".tgz", ".tmp", ".ttf", ".vcs", ".vlm", ".vxd", ".vxo", ".wiz", ".wll", ".wmd", + ".wmf", ".wms", ".wmz", ".wpc", ".wsc", ".wsh", ".wwk", ".xhtm", ".xhtml", ".xl", ".xml", ".zip", ".7z", 0}; + + if (!ext) + return FALSE; + + while (problemFileExt[i]) + { + if (!_stricmp (ext, problemFileExt[i++])) + return TRUE; + } + + return FALSE; +} + + +void IncreaseWrongPwdRetryCount (int count) +{ + WrongPwdRetryCounter += count; +} + + +void ResetWrongPwdRetryCount (void) +{ + WrongPwdRetryCounter = 0; +} + + +BOOL WrongPwdRetryCountOverLimit (void) +{ + return (WrongPwdRetryCounter > TC_TRY_HEADER_BAK_AFTER_NBR_WRONG_PWD_TRIES); +} + + +int GetFirstAvailableDrive () +{ + DWORD dwUsedDrives = GetLogicalDrives(); + int i; + + for (i = 3; i < 26; i++) + { + if (!(dwUsedDrives & 1 << i)) + return i; + } + + return -1; +} + + +int GetLastAvailableDrive () +{ + DWORD dwUsedDrives = GetLogicalDrives(); + int i; + + for (i = 25; i > 2; i--) + { + if (!(dwUsedDrives & 1 << i)) + return i; + } + + return -1; +} + + +BOOL IsDriveAvailable (int driveNo) +{ + return (GetLogicalDrives() & (1 << driveNo)) == 0; +} + + +BOOL IsDeviceMounted (char *deviceName) +{ + BOOL bResult = FALSE; + DWORD dwResult; + HANDLE dev = INVALID_HANDLE_VALUE; + + if ((dev = CreateFile (deviceName, + GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL)) != INVALID_HANDLE_VALUE) + { + bResult = DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL); + CloseHandle (dev); + } + + return bResult; +} + + +int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) +{ + UNMOUNT_STRUCT unmount; + DWORD dwResult; + + BOOL bResult; + + unmount.nDosDriveNo = nDosDriveNo; + unmount.ignoreOpenFiles = forced; + + bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_VOLUME, &unmount, + sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); + + if (bResult == FALSE) + { + handleWin32Error (hwndDlg); + return 1; + } + +#ifdef TCMOUNT + + if (unmount.nReturnCode == ERR_SUCCESS + && unmount.HiddenVolumeProtectionTriggered + && !VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo]) + { + wchar_t msg[4096]; + + VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] = TRUE; + swprintf (msg, GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), nDosDriveNo + 'A'); + SetForegroundWindow (hwndDlg); + MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + } + +#endif // #ifdef TCMOUNT + + return unmount.nReturnCode; +} + + +void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap) +{ + DEV_BROADCAST_VOLUME dbv; + DWORD dwResult; + LONG eventId = 0; + int i; + + if (DeviceChangeBroadcastDisabled) + return; + + if (message == DBT_DEVICEARRIVAL) + eventId = SHCNE_DRIVEADD; + else if (message == DBT_DEVICEREMOVECOMPLETE) + eventId = SHCNE_DRIVEREMOVED; + else if (IsOSAtLeast (WIN_7) && message == DBT_DEVICEREMOVEPENDING) // Explorer on Windows 7 holds open handles of all drives when 'Computer' is expanded in navigation pane. SHCNE_DRIVEREMOVED must be used as DBT_DEVICEREMOVEPENDING is ignored. + eventId = SHCNE_DRIVEREMOVED; + + if (driveMap == 0) + driveMap = (1 << nDosDriveNo); + + if (eventId != 0) + { + for (i = 0; i < 26; i++) + { + if (driveMap & (1 << i)) + { + char root[] = { (char) i + 'A', ':', '\\', 0 }; + SHChangeNotify (eventId, SHCNF_PATH, root, NULL); + + if (nCurrentOS == WIN_2000 && RemoteSession) + { + char target[32]; + wsprintf (target, "%ls%c", TC_MOUNT_PREFIX, i + 'A'); + root[2] = 0; + + if (message == DBT_DEVICEARRIVAL) + DefineDosDevice (DDD_RAW_TARGET_PATH, root, target); + else if (message == DBT_DEVICEREMOVECOMPLETE) + DefineDosDevice (DDD_RAW_TARGET_PATH| DDD_REMOVE_DEFINITION + | DDD_EXACT_MATCH_ON_REMOVE, root, target); + } + } + } + } + + dbv.dbcv_size = sizeof (dbv); + dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME; + dbv.dbcv_reserved = 0; + dbv.dbcv_unitmask = driveMap; + dbv.dbcv_flags = 0; + + UINT timeOut = 1000; + + // SHChangeNotify() works on Vista, so the Explorer does not require WM_DEVICECHANGE + if (CurrentOSMajor >= 6) + timeOut = 100; + + IgnoreWmDeviceChange = TRUE; + SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, timeOut, &dwResult); + + // Explorer prior Vista sometimes fails to register a new drive + if (CurrentOSMajor < 6 && message == DBT_DEVICEARRIVAL) + SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, 200, &dwResult); + + IgnoreWmDeviceChange = FALSE; +} + + +// Use only cached passwords if password = NULL +// +// Returns: +// -1 = user aborted mount / error +// 0 = mount failed +// 1 = mount OK +// 2 = mount OK in shared mode + +int MountVolume (HWND hwndDlg, + int driveNo, + char *volumePath, + Password *password, + BOOL cachePassword, + BOOL sharedAccess, + MountOptions *mountOptions, + BOOL quiet, + BOOL bReportWrongPassword) +{ + MOUNT_STRUCT mount; + DWORD dwResult; + BOOL bResult, bDevice; + char root[MAX_PATH]; + +#ifdef TCMOUNT + if (mountOptions->PartitionInInactiveSysEncScope) + { + if (!CheckSysEncMountWithoutPBA (volumePath, quiet)) + return -1; + } +#endif + + if (IsMountedVolume (volumePath)) + { + if (!quiet) + Error ("VOL_ALREADY_MOUNTED"); + return -1; + } + + if (!IsDriveAvailable (driveNo)) + { + if (!quiet) + Error ("DRIVE_LETTER_UNAVAILABLE"); + + return -1; + } + + // If using cached passwords, check cache status first + if (password == NULL && IsPasswordCacheEmpty ()) + return 0; + + ZeroMemory (&mount, sizeof (mount)); + mount.bExclusiveAccess = sharedAccess ? FALSE : TRUE; + mount.SystemFavorite = MountVolumesAsSystemFavorite; + mount.UseBackupHeader = mountOptions->UseBackupHeader; + mount.RecoveryMode = mountOptions->RecoveryMode; + +retry: + mount.nDosDriveNo = driveNo; + mount.bCache = cachePassword; + + mount.bPartitionInInactiveSysEncScope = FALSE; + + if (password != NULL) + mount.VolumePassword = *password; + else + mount.VolumePassword.Length = 0; + + if (!mountOptions->ReadOnly && mountOptions->ProtectHiddenVolume) + { + mount.ProtectedHidVolPassword = mountOptions->ProtectedHidVolPassword; + mount.bProtectHiddenVolume = TRUE; + } + else + mount.bProtectHiddenVolume = FALSE; + + mount.bMountReadOnly = mountOptions->ReadOnly; + mount.bMountRemovable = mountOptions->Removable; + mount.bPreserveTimestamp = mountOptions->PreserveTimestamp; + + mount.bMountManager = TRUE; + + // Windows 2000 mount manager causes problems with remounted volumes + if (CurrentOSMajor == 5 && CurrentOSMinor == 0) + mount.bMountManager = FALSE; + + string path = volumePath; + if (path.find ("\\\\?\\") == 0) + { + // Remove \\?\ prefix + path = path.substr (4); + strcpy_s (volumePath, TC_MAX_PATH, path.c_str()); + } + + if (path.find ("Volume{") == 0 && path.rfind ("}\\") == path.size() - 2) + { + // Resolve volume name + if (QueryDosDevice (path.substr (0, path.size() - 1).c_str(), volumePath, TC_MAX_PATH) != 0) + { + foreach (const HostDevice &device, GetAvailableHostDevices (true, true)) + { + if (!device.DynamicVolume) + { + wchar_t resolvedVolumePath[TC_MAX_PATH]; + + if (ResolveSymbolicLink (SingleStringToWide (device.Path).c_str(), resolvedVolumePath) + && SingleStringToWide (volumePath) == resolvedVolumePath) + { + strcpy_s (volumePath, TC_MAX_PATH, device.Path.c_str()); + break; + } + } + } + } + else + strcpy_s (volumePath, TC_MAX_PATH, path.c_str()); + } + + CreateFullVolumePath ((char *) mount.wszVolume, volumePath, &bDevice); + + if (!bDevice) + { + // UNC path + if (path.find ("\\\\") == 0) + { + strcpy_s ((char *)mount.wszVolume, array_capacity (mount.wszVolume), ("UNC" + path.substr (1)).c_str()); + } + + if (GetVolumePathName (volumePath, root, sizeof (root) - 1)) + { + DWORD bps, flags, d; + if (GetDiskFreeSpace (root, &d, &bps, &d, &d)) + mount.BytesPerSector = bps; + + // Read-only host filesystem + if (!mount.bMountReadOnly && GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) + mount.bMountReadOnly = (flags & FILE_READ_ONLY_VOLUME) != 0; + } + } + + ToUNICODE ((char *) mount.wszVolume); + + if (mountOptions->PartitionInInactiveSysEncScope) + { + if (mount.wszVolume == NULL || swscanf_s ((const wchar_t *) mount.wszVolume, + WIDE("\\Device\\Harddisk%d\\Partition"), + &mount.nPartitionInInactiveSysEncScopeDriveNo, + sizeof(mount.nPartitionInInactiveSysEncScopeDriveNo)) != 1) + { + return -1; + } + + mount.bPartitionInInactiveSysEncScope = TRUE; + } + + bResult = DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, &mount, + sizeof (mount), &mount, sizeof (mount), &dwResult, NULL); + + burn (&mount.VolumePassword, sizeof (mount.VolumePassword)); + burn (&mount.ProtectedHidVolPassword, sizeof (mount.ProtectedHidVolPassword)); + + if (bResult == FALSE) + { + // Volume already open by another process + if (GetLastError () == ERROR_SHARING_VIOLATION) + { + if (mount.bExclusiveAccess == FALSE) + { + if (!quiet) + Error ("FILE_IN_USE_FAILED"); + + return -1; + } + else + { + if (quiet) + { + mount.bExclusiveAccess = FALSE; + goto retry; + } + + // Ask user + if (IDYES == AskWarnNoYes ("FILE_IN_USE")) + { + mount.bExclusiveAccess = FALSE; + goto retry; + } + } + + return -1; + } + + if (!quiet) + handleWin32Error (hwndDlg); + + return -1; + } + + if (mount.nReturnCode != 0) + { + if (mount.nReturnCode == ERR_PASSWORD_WRONG) + { + // Do not report wrong password, if not instructed to + if (bReportWrongPassword) + { + IncreaseWrongPwdRetryCount (1); // We increase the count here only if bReportWrongPassword is TRUE, because "Auto-Mount All Devices" and other callers do it separately + + if (WrongPwdRetryCountOverLimit () + && !mount.UseBackupHeader) + { + // Retry using embedded header backup (if any) + mount.UseBackupHeader = TRUE; + goto retry; + } + + if (bDevice && mount.bProtectHiddenVolume) + { + int driveNo; + + if (sscanf (volumePath, "\\Device\\Harddisk%d\\Partition", &driveNo) == 1) + { + OPEN_TEST_STRUCT openTestStruct; + memset (&openTestStruct, 0, sizeof (openTestStruct)); + + openTestStruct.bDetectTCBootLoader = TRUE; + _snwprintf ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", driveNo); + + DWORD dwResult; + if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &dwResult, NULL) && openTestStruct.TCBootLoaderDetected) + WarningDirect ((GetWrongPasswordErrorMessage (hwndDlg) + L"\n\n" + GetString ("HIDDEN_VOL_PROT_PASSWORD_US_KEYB_LAYOUT")).c_str()); + else + handleError (hwndDlg, mount.nReturnCode); + } + } + else + handleError (hwndDlg, mount.nReturnCode); + } + + return 0; + } + + if (!quiet) + handleError (hwndDlg, mount.nReturnCode); + + return 0; + } + + // Mount successful + + if (mount.UseBackupHeader != mountOptions->UseBackupHeader + && mount.UseBackupHeader) + { + if (bReportWrongPassword && !Silent) + Warning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); + } + + LastMountedVolumeDirty = mount.FilesystemDirty; + + if (mount.FilesystemDirty) + { + wchar_t msg[1024]; + wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; + wsprintfW (msg, GetString ("MOUNTED_VOLUME_DIRTY"), mountPoint); + + if (AskWarnYesNoString (msg) == IDYES) + CheckFilesystem (driveNo, TRUE); + } + + if (mount.VolumeMountedReadOnlyAfterAccessDenied + && !Silent + && !bDevice + && !FileHasReadOnlyAttribute (volumePath) + && !IsFileOnReadOnlyFilesystem (volumePath)) + { + wchar_t msg[1024]; + wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; + wsprintfW (msg, GetString ("MOUNTED_CONTAINER_FORCED_READ_ONLY"), mountPoint); + + WarningDirect (msg); + } + + if (mount.VolumeMountedReadOnlyAfterAccessDenied + && !Silent + && bDevice) + { + wchar_t msg[1024]; + wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; + wsprintfW (msg, GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY"), mountPoint); + + WarningDirect (msg); + } + + if (mount.VolumeMountedReadOnlyAfterDeviceWriteProtected + && !Silent + && strstr (volumePath, "\\Device\\Harddisk") == volumePath) + { + wchar_t msg[1024]; + wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; + wsprintfW (msg, GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY_WRITE_PROTECTION"), mountPoint); + + WarningDirect (msg); + + if (CurrentOSMajor >= 6 + && strstr (volumePath, "\\Device\\HarddiskVolume") != volumePath + && AskNoYes ("ASK_REMOVE_DEVICE_WRITE_PROTECTION") == IDYES) + { + RemoveDeviceWriteProtection (hwndDlg, volumePath); + } + } + + ResetWrongPwdRetryCount (); + + BroadcastDeviceChange (DBT_DEVICEARRIVAL, driveNo, 0); + + if (mount.bExclusiveAccess == FALSE) + return 2; + + return 1; +} + + +BOOL UnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount) +{ + int result; + BOOL forced = forceUnmount; + int dismountMaxRetries = UNMOUNT_MAX_AUTO_RETRIES; + +retry: + BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, nDosDriveNo, 0); + + do + { + result = DriverUnmountVolume (hwndDlg, nDosDriveNo, forced); + + if (result == ERR_FILES_OPEN) + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + else + break; + + } while (--dismountMaxRetries > 0); + + if (result != 0) + { + if (result == ERR_FILES_OPEN && !Silent) + { + if (IDYES == AskWarnNoYes ("UNMOUNT_LOCK_FAILED")) + { + forced = TRUE; + goto retry; + } + + if (IsOSAtLeast (WIN_7)) + { + // Undo SHCNE_DRIVEREMOVED + char root[] = { (char) nDosDriveNo + 'A', ':', '\\', 0 }; + SHChangeNotify (SHCNE_DRIVEADD, SHCNF_PATH, root, NULL); + } + + return FALSE; + } + + Error ("UNMOUNT_FAILED"); + + return FALSE; + } + + BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, nDosDriveNo, 0); + + return TRUE; +} + + +BOOL IsPasswordCacheEmpty (void) +{ + DWORD dw; + return !DeviceIoControl (hDriver, TC_IOCTL_GET_PASSWORD_CACHE_STATUS, 0, 0, 0, 0, &dw, 0); +} + + +BOOL IsMountedVolume (const char *volname) +{ + MOUNT_LIST_STRUCT mlist; + DWORD dwResult; + int i; + char volume[TC_MAX_PATH*2+16]; + + strcpy (volume, volname); + + if (strstr (volname, "\\Device\\") != volname) + sprintf(volume, "\\??\\%s", volname); + ToUNICODE (volume); + + memset (&mlist, 0, sizeof (mlist)); + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, + sizeof (mlist), &mlist, sizeof (mlist), &dwResult, + NULL); + + for (i=0 ; i<26; i++) + if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume)) + return TRUE; + + return FALSE; +} + + +int GetMountedVolumeDriveNo (char *volname) +{ + MOUNT_LIST_STRUCT mlist; + DWORD dwResult; + int i; + char volume[TC_MAX_PATH*2+16]; + + if (volname == NULL) + return -1; + + strcpy (volume, volname); + + if (strstr (volname, "\\Device\\") != volname) + sprintf(volume, "\\??\\%s", volname); + ToUNICODE (volume); + + memset (&mlist, 0, sizeof (mlist)); + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, + sizeof (mlist), &mlist, sizeof (mlist), &dwResult, + NULL); + + for (i=0 ; i<26; i++) + if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume)) + return i; + + return -1; +} + + +BOOL IsAdmin (void) +{ + return IsUserAnAdmin (); +} + + +BOOL IsBuiltInAdmin () +{ + HANDLE procToken; + DWORD size; + + if (!IsAdmin() || !OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &procToken)) + return FALSE; + + finally_do_arg (HANDLE, procToken, { CloseHandle (finally_arg); }); + + if (GetTokenInformation (procToken, TokenUser, NULL, 0, &size) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return FALSE; + + TOKEN_USER *tokenUser = (TOKEN_USER *) malloc (size); + if (!tokenUser) + return FALSE; + + finally_do_arg (void *, tokenUser, { free (finally_arg); }); + + if (!GetTokenInformation (procToken, TokenUser, tokenUser, size, &size)) + return FALSE; + + return IsWellKnownSid (tokenUser->User.Sid, WinAccountAdministratorSid); +} + + +BOOL IsUacSupported () +{ + HKEY hkey; + DWORD value = 1, size = sizeof (DWORD); + + if (!IsOSAtLeast (WIN_VISTA)) + return FALSE; + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_READ, &hkey) == ERROR_SUCCESS) + { + if (RegQueryValueEx (hkey, "EnableLUA", 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS) + value = 1; + + RegCloseKey (hkey); + } + + return value != 0; +} + + +BOOL ResolveSymbolicLink (const wchar_t *symLinkName, PWSTR targetName) +{ + BOOL bResult; + DWORD dwResult; + RESOLVE_SYMLINK_STRUCT resolve; + + memset (&resolve, 0, sizeof(resolve)); + wcscpy ((PWSTR) &resolve.symLinkName, symLinkName); + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_RESOLVED_SYMLINK, &resolve, + sizeof (resolve), &resolve, sizeof (resolve), &dwResult, + NULL); + + wcscpy (targetName, (PWSTR) &resolve.targetName); + + return bResult; +} + + +BOOL GetPartitionInfo (const char *deviceName, PPARTITION_INFORMATION rpartInfo) +{ + BOOL bResult; + DWORD dwResult; + DISK_PARTITION_INFO_STRUCT dpi; + + memset (&dpi, 0, sizeof(dpi)); + wsprintfW ((PWSTR) &dpi.deviceName, L"%hs", deviceName); + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, &dpi, + sizeof (dpi), &dpi, sizeof (dpi), &dwResult, NULL); + + memcpy (rpartInfo, &dpi.partInfo, sizeof (PARTITION_INFORMATION)); + return bResult; +} + + +BOOL GetDeviceInfo (const char *deviceName, DISK_PARTITION_INFO_STRUCT *info) +{ + DWORD dwResult; + + memset (info, 0, sizeof(*info)); + wsprintfW ((PWSTR) &info->deviceName, L"%hs", deviceName); + + return DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, info, sizeof (*info), info, sizeof (*info), &dwResult, NULL); +} + + +BOOL GetDriveGeometry (const char *deviceName, PDISK_GEOMETRY diskGeometry) +{ + BOOL bResult; + DWORD dwResult; + DISK_GEOMETRY_STRUCT dg; + + memset (&dg, 0, sizeof(dg)); + wsprintfW ((PWSTR) &dg.deviceName, L"%hs", deviceName); + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_GEOMETRY, &dg, + sizeof (dg), &dg, sizeof (dg), &dwResult, NULL); + + memcpy (diskGeometry, &dg.diskGeometry, sizeof (DISK_GEOMETRY)); + return bResult; +} + + +// Returns drive letter number assigned to device (-1 if none) +int GetDiskDeviceDriveLetter (PWSTR deviceName) +{ + int i; + WCHAR link[MAX_PATH]; + WCHAR target[MAX_PATH]; + WCHAR device[MAX_PATH]; + + if (!ResolveSymbolicLink (deviceName, device)) + wcscpy (device, deviceName); + + for (i = 0; i < 26; i++) + { + WCHAR drive[] = { (WCHAR) i + 'A', ':', 0 }; + + wcscpy (link, L"\\DosDevices\\"); + wcscat (link, drive); + + ResolveSymbolicLink (link, target); + + if (wcscmp (device, target) == 0) + return i; + } + + return -1; +} + + +// WARNING: This function does NOT provide 100% reliable results -- do NOT use it for critical/dangerous operations! +// Return values: 0 - filesystem does not appear empty, 1 - filesystem appears empty, -1 - an error occurred +int FileSystemAppearsEmpty (const char *devicePath) +{ + float percentFreeSpace = 0.0; + __int64 occupiedBytes = 0; + + if (GetStatsFreeSpaceOnPartition (devicePath, &percentFreeSpace, &occupiedBytes, TRUE) != -1) + { + if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. + || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. + { + return 0; + } + else + return 1; + } + else + return -1; +} + + +// Returns the free space on the specified partition (volume) in bytes. If the 'occupiedBytes' pointer +// is not NULL, size of occupied space (in bytes) is written to the pointed location. In addition, if the +// 'percent' pointer is not NULL, % of free space is stored in the pointed location. If there's an error, +// returns -1. +__int64 GetStatsFreeSpaceOnPartition (const char *devicePath, float *percentFree, __int64 *occupiedBytes, BOOL silent) +{ + WCHAR devPath [MAX_PATH]; + int driveLetterNo = -1; + char szRootPath[4] = {0, ':', '\\', 0}; + ULARGE_INTEGER freeSpaceSize; + ULARGE_INTEGER totalNumberOfBytes; + ULARGE_INTEGER totalNumberOfFreeBytes; + + strcpy ((char *) devPath, devicePath); + ToUNICODE ((char *) devPath); + + driveLetterNo = GetDiskDeviceDriveLetter (devPath); + szRootPath[0] = (char) driveLetterNo + 'A'; + + + if (!GetDiskFreeSpaceEx (szRootPath, &freeSpaceSize, &totalNumberOfBytes, &totalNumberOfFreeBytes)) + { + if (!silent) + { + handleWin32Error (MainDlg); + Error ("CANNOT_CALC_SPACE"); + } + + return -1; + } + + + if (percentFree != NULL || occupiedBytes != NULL) + { + // Determine occupied space and % of free space + + PARTITION_INFORMATION partitionInfo; + + if (!GetPartitionInfo (devicePath, &partitionInfo)) + { + if (!silent) + { + handleWin32Error (MainDlg); + Error ("CANT_GET_VOLSIZE"); + } + return -1; + } + + if (occupiedBytes != NULL) + *occupiedBytes = partitionInfo.PartitionLength.QuadPart - freeSpaceSize.QuadPart; + + if (percentFree != NULL) + *percentFree = (float) ((double) freeSpaceSize.QuadPart / (double) partitionInfo.PartitionLength.QuadPart * 100.0); + } + + return freeSpaceSize.QuadPart; +} + + +// Returns -1 if there's an error. +__int64 GetDeviceSize (const char *devicePath) +{ + PARTITION_INFORMATION partitionInfo; + + if (!GetPartitionInfo (devicePath, &partitionInfo)) + return -1; + + return partitionInfo.PartitionLength.QuadPart; +} + + +HANDLE DismountDrive (char *devName, char *devicePath) +{ + DWORD dwResult; + HANDLE hVolume; + BOOL bResult = FALSE; + int attempt = UNMOUNT_MAX_AUTO_RETRIES; + int driveLetterNo = -1; + WCHAR devPath [MAX_PATH]; + + strcpy ((char *) devPath, devicePath); + ToUNICODE ((char *) devPath); + driveLetterNo = GetDiskDeviceDriveLetter (devPath); + + + hVolume = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hVolume == INVALID_HANDLE_VALUE) + return INVALID_HANDLE_VALUE; + + + // Try to lock the volume first so that dismount is not forced. + // If we fail, we will dismount anyway even if it needs to be forced. + + CloseVolumeExplorerWindows (MainDlg, driveLetterNo); + + while (!(bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) + { + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; + } + + + // Try to dismount the volume + + attempt = UNMOUNT_MAX_AUTO_RETRIES; + + while (!(bResult = DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) + { + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; + } + + if (!bResult) + CloseHandle (hVolume); + + return (bResult ? hVolume : INVALID_HANDLE_VALUE); +} + +// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the +// offset of the first occurrence of the string. The string and the buffer may contain zeroes, +// which do NOT terminate them. +int64 FindString (const char *buf, const char *str, int64 bufLen, size_t strLen, int64 startOffset) +{ + if (buf == NULL + || str == NULL + || strLen > bufLen + || bufLen < 1 + || strLen < 1 + || startOffset > bufLen - strLen) + { + return -1; + } + + for (int64 i = startOffset; i < bufLen - strLen; i++) + { + if (memcmp (buf + i, str, strLen) == 0) + return i; + } + + return -1; +} + +// Returns TRUE if the file exists (otherwise FALSE). +BOOL FileExists (const char *filePathPtr) +{ + char filePath [TC_MAX_PATH]; + + // Strip quotation marks (if any) + if (filePathPtr [0] == '"') + { + strcpy (filePath, filePathPtr + 1); + } + else + { + strcpy (filePath, filePathPtr); + } + + // Strip quotation marks (if any) + if (filePath [strlen (filePath) - 1] == '"') + filePath [strlen (filePath) - 1] = 0; + + return (_access (filePath, 0) != -1); +} + +// Searches the file from its end for the LAST occurrence of the string str. +// The string may contain zeroes, which do NOT terminate the string. +// If the string is found, its offset from the start of the file is returned. +// If the string isn't found or if any error occurs, -1 is returned. +__int64 FindStringInFile (const char *filePath, const char* str, int strLen) +{ + int bufSize = 64 * BYTES_PER_KB; + char *buffer = (char *) malloc (bufSize); + HANDLE src = NULL; + DWORD bytesRead; + BOOL readRetVal; + __int64 filePos = GetFileSize64 (filePath); + int bufPos = 0; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL bExit = FALSE; + int filePosStep; + __int64 retVal = -1; + + if (filePos <= 0 + || buffer == NULL + || strLen > bufSize + || strLen < 1) + return -1; + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return -1; + } + + filePosStep = bufSize - strLen + 1; + + do + { + filePos -= filePosStep; + + if (filePos < 0) + { + filePos = 0; + bExit = TRUE; + } + + seekOffset.QuadPart = filePos; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0 + || bytesRead == 0) + goto fsif_end; + + bufPos = bytesRead - strLen; + + while (bufPos > 0) + { + if (memcmp (buffer + bufPos, str, strLen) == 0) + { + // String found + retVal = filePos + bufPos; + goto fsif_end; + } + bufPos--; + } + + } while (!bExit); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED) +// so we need to use our own copy function +BOOL TCCopyFile (char *sourceFileName, char *destinationFile) +{ + __int8 *buffer; + HANDLE src, dst; + FILETIME fileTime; + DWORD bytesRead, bytesWritten; + BOOL res; + + src = CreateFile (sourceFileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + return FALSE; + + dst = CreateFile (destinationFile, + GENERIC_WRITE, + 0, NULL, CREATE_ALWAYS, 0, NULL); + + if (dst == INVALID_HANDLE_VALUE) + { + CloseHandle (src); + return FALSE; + } + + buffer = (char *) malloc (64 * 1024); + if (!buffer) + { + CloseHandle (src); + CloseHandle (dst); + return FALSE; + } + + while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL)) + { + if (bytesRead == 0) + { + res = 1; + break; + } + + if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL) + || bytesRead != bytesWritten) + { + res = 0; + break; + } + } + + GetFileTime (src, NULL, NULL, &fileTime); + SetFileTime (dst, NULL, NULL, &fileTime); + + CloseHandle (src); + CloseHandle (dst); + + free (buffer); + return res != 0; +} + +// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file +// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE). +BOOL SaveBufferToFile (char *inputBuffer, char *destinationFile, DWORD inputLength, BOOL bAppend) +{ + HANDLE dst; + DWORD bytesWritten; + BOOL res = TRUE; + + dst = CreateFile (destinationFile, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); + + if (dst == INVALID_HANDLE_VALUE) + { + handleWin32Error (MainDlg); + return FALSE; + } + + if (bAppend) + SetFilePointer (dst, 0, NULL, FILE_END); + + if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL) + || inputLength != bytesWritten) + { + res = FALSE; + } + + if (!res) + { + // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite + // of an existing file (it's not an error) + if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) ) + handleWin32Error (MainDlg); + } + + CloseHandle (dst); + FlushFileBuffers (dst); + + if (!res && !bAppend) + remove (destinationFile); + + return res; +} + + +// Proper flush for Windows systems. Returns TRUE if successful. +BOOL TCFlushFile (FILE *f) +{ + HANDLE hf = (HANDLE) _get_osfhandle (_fileno (f)); + + fflush (f); + + if (hf == INVALID_HANDLE_VALUE) + return FALSE; + + return FlushFileBuffers (hf) != 0; +} + + +// Prints a UTF-16 text (note that this involves a real printer, not a screen). +// textByteLen - length of the text in bytes +// title - printed as part of the page header and used as the filename for a temporary file +BOOL PrintHardCopyTextUTF16 (wchar_t *text, char *title, int textByteLen) +{ + char cl [MAX_PATH*3] = {"/p \""}; + char path [MAX_PATH * 2] = { 0 }; + char filename [MAX_PATH + 1] = { 0 }; + + strcpy (filename, title); + //strcat (filename, ".txt"); + + GetTempPath (sizeof (path), path); + + if (!FileExists (path)) + { + strcpy (path, GetConfigPath (filename)); + + if (strlen(path) < 2) + return FALSE; + } + else + { + strcat (path, filename); + } + + // Write the Unicode signature + if (!SaveBufferToFile ("\xFF\xFE", path, 2, FALSE)) + { + remove (path); + return FALSE; + } + + // Write the actual text + if (!SaveBufferToFile ((char *) text, path, textByteLen, TRUE)) + { + remove (path); + return FALSE; + } + + strcat (cl, path); + strcat (cl, "\""); + + WaitCursor (); + ShellExecute (NULL, "open", PRINT_TOOL, cl, NULL, SW_HIDE); + Sleep (6000); + NormalCursor(); + + remove (path); + + return TRUE; +} + + +BOOL IsNonInstallMode () +{ + HKEY hkey; + DWORD dw; + + if (bPortableModeConfirmed) + return TRUE; + + if (hDriver != INVALID_HANDLE_VALUE) + { + // The driver is running + if (DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dw, 0)) + { + bPortableModeConfirmed = TRUE; + return TRUE; + } + else + { + // This is also returned if we fail to determine the status (it does not mean that portable mode is disproved). + return FALSE; + } + } + else + { + // The tests in this block are necessary because this function is in some cases called before DriverAttach(). + + HANDLE hDriverTmp = CreateFile (WIN32_ROOT_PREFIX, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + + if (hDriverTmp == INVALID_HANDLE_VALUE) + { + // The driver was not found in the system path + + char path[MAX_PATH * 2] = { 0 }; + + // We can't use GetConfigPath() here because it would call us back (indirect recursion) + if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path))) + { + strcat (path, "\\TrueCrypt\\"); + strcat (path, TC_APPD_FILENAME_SYSTEM_ENCRYPTION); + + if (FileExists (path)) + { + // To maintain consistency and safety, if the system encryption config file exits, we cannot + // allow portable mode. (This happens e.g. when the pretest fails and the user selects + // "Last Known Good Configuration" from the Windows boot menu.) + + // However, if UAC elevation is needed, we have to confirm portable mode first (after we are elevated, we won't). + if (!IsAdmin () && IsUacSupported ()) + return TRUE; + + return FALSE; + } + } + + // As the driver was not found in the system path, we can predict that we will run in portable mode + return TRUE; + } + else + CloseHandle (hDriverTmp); + } + + // The following test may be unreliable in some cases (e.g. after the user selects restore "Last Known Good + // Configuration" from the Windows boot menu). + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt", 0, KEY_READ, &hkey) == ERROR_SUCCESS) + { + RegCloseKey (hkey); + return FALSE; + } + else + return TRUE; +} + + +LRESULT SetCheckBox (HWND hwndDlg, int dlgItem, BOOL state) +{ + return SendDlgItemMessage (hwndDlg, dlgItem, BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0); +} + + +BOOL GetCheckBox (HWND hwndDlg, int dlgItem) +{ + return IsButtonChecked (GetDlgItem (hwndDlg, dlgItem)); +} + + +// Adds or removes TrueCrypt.exe to/from the system startup sequence (with appropriate command line arguments) +void ManageStartupSeq (void) +{ + if (!IsNonInstallMode ()) + { + char regk [64]; + + // Split the string in order to prevent some antivirus packages from falsely reporting + // TrueCrypt.exe to contain a possible Trojan horse because of this string (heuristic scan). + sprintf (regk, "%s%s", "Software\\Microsoft\\Windows\\Curren", "tVersion\\Run"); + + if (bStartOnLogon || bMountDevicesOnLogon || bMountFavoritesOnLogon) + { + char exe[MAX_PATH * 2] = { '"' }; + + GetModuleFileName (NULL, exe + 1, sizeof (exe) - 1); + +#ifdef VOLFORMAT + { + char *tmp = NULL; + + if (tmp = strrchr (exe, '\\')) + strcpy (++tmp, "TrueCrypt.exe"); + } +#endif + strcat (exe, "\" /q preferences"); + + if (bMountDevicesOnLogon) strcat (exe, " /a devices"); + if (bMountFavoritesOnLogon) strcat (exe, " /a favorites"); + + WriteRegistryString (regk, "TrueCrypt", exe); + } + else + DeleteRegistryValue (regk, "TrueCrypt"); + } +} + + +// Adds or removes the TrueCrypt Volume Creation Wizard to/from the system startup sequence +void ManageStartupSeqWiz (BOOL bRemove, const char *arg) +{ + char regk [64]; + + // Split this string in order to prevent some low-quality antivirus software from falsely reporting + // our .exe files to contain a possible Trojan horse because of this string (heuristic scan). + sprintf (regk, "%s%s", "Software\\Microsoft\\Windows\\Curren", "tVersion\\Run"); + + if (!bRemove) + { + char exe[MAX_PATH * 2] = { '"' }; + GetModuleFileName (NULL, exe + 1, sizeof (exe) - 1); + +#ifndef VOLFORMAT + { + char *tmp = NULL; + + if (tmp = strrchr (exe, '\\')) + strcpy (++tmp, "TrueCrypt Format.exe"); + } +#endif + + if (strlen (arg) > 0) + { + strcat (exe, "\" "); + strcat (exe, arg); + } + + WriteRegistryString (regk, "TrueCrypt Format", exe); + } + else + DeleteRegistryValue (regk, "TrueCrypt Format"); +} + + +// Delete the last used Windows file selector path for TrueCrypt from the registry +void CleanLastVisitedMRU (void) +{ + WCHAR exeFilename[MAX_PATH]; + WCHAR *strToMatch; + + WCHAR strTmp[4096]; + char regPath[128]; + char key[64]; + int id, len; + + GetModuleFileNameW (NULL, exeFilename, sizeof (exeFilename) / sizeof(exeFilename[0])); + strToMatch = wcsrchr (exeFilename, '\\') + 1; + + sprintf (regPath, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisited%sMRU", IsOSAtLeast (WIN_VISTA) ? "Pidl" : ""); + + for (id = (IsOSAtLeast (WIN_VISTA) ? 0 : 'a'); id <= (IsOSAtLeast (WIN_VISTA) ? 1000 : 'z'); id++) + { + *strTmp = 0; + sprintf (key, (IsOSAtLeast (WIN_VISTA) ? "%d" : "%c"), id); + + if ((len = ReadRegistryBytes (regPath, key, (char *) strTmp, sizeof (strTmp))) > 0) + { + if (_wcsicmp (strTmp, strToMatch) == 0) + { + char buf[65536], bufout[sizeof (buf)]; + + // Overwrite the entry with zeroes while keeping its original size + memset (strTmp, 0, len); + if (!WriteRegistryBytes (regPath, key, (char *) strTmp, len)) + MessageBoxW (NULL, GetString ("CLEAN_WINMRU_FAILED"), lpszTitle, ICON_HAND); + + DeleteRegistryValue (regPath, key); + + // Remove ID from MRUList + if (IsOSAtLeast (WIN_VISTA)) + { + int *p = (int *)buf; + int *pout = (int *)bufout; + int l; + + l = len = ReadRegistryBytes ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", "MRUListEx", buf, sizeof (buf)); + while (l > 0) + { + l -= sizeof (int); + + if (*p == id) + { + p++; + len -= sizeof (int); + continue; + } + *pout++ = *p++; + } + + WriteRegistryBytes ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", "MRUListEx", bufout, len); + } + else + { + char *p = buf; + char *pout = bufout; + + ReadRegistryString ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", "MRUList", "", buf, sizeof (buf)); + while (*p) + { + if (*p == id) + { + p++; + continue; + } + *pout++ = *p++; + } + *pout++ = 0; + + WriteRegistryString ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", "MRUList", bufout); + } + + break; + } + } + } +} + + +#ifndef SETUP +void ClearHistory (HWND hwndDlgItem) +{ + ArrowWaitCursor (); + + ClearCombo (hwndDlgItem); + DumpCombo (hwndDlgItem, TRUE); + + CleanLastVisitedMRU (); + + NormalCursor (); +} +#endif // #ifndef SETUP + + +LRESULT ListItemAdd (HWND list, int index, char *string) +{ + LVITEM li; + memset (&li, 0, sizeof(li)); + + li.mask = LVIF_TEXT; + li.pszText = string; + li.iItem = index; + li.iSubItem = 0; + return ListView_InsertItem (list, &li); +} + + +LRESULT ListItemAddW (HWND list, int index, wchar_t *string) +{ + LVITEMW li; + memset (&li, 0, sizeof(li)); + + li.mask = LVIF_TEXT; + li.pszText = string; + li.iItem = index; + li.iSubItem = 0; + return SendMessageW (list, LVM_INSERTITEMW, 0, (LPARAM)(&li)); +} + + +LRESULT ListSubItemSet (HWND list, int index, int subIndex, char *string) +{ + LVITEM li; + memset (&li, 0, sizeof(li)); + + li.mask = LVIF_TEXT; + li.pszText = string; + li.iItem = index; + li.iSubItem = subIndex; + return ListView_SetItem (list, &li); +} + + +LRESULT ListSubItemSetW (HWND list, int index, int subIndex, wchar_t *string) +{ + LVITEMW li; + memset (&li, 0, sizeof(li)); + + li.mask = LVIF_TEXT; + li.pszText = string; + li.iItem = index; + li.iSubItem = subIndex; + return SendMessageW (list, LVM_SETITEMW, 0, (LPARAM)(&li)); +} + + +BOOL GetMountList (MOUNT_LIST_STRUCT *list) +{ + DWORD dwResult; + + memset (list, 0, sizeof (*list)); + return DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, list, + sizeof (*list), list, sizeof (*list), &dwResult, + NULL); +} + + +int GetDriverRefCount () +{ + DWORD dwResult; + BOOL bResult; + int refCount; + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, + sizeof (refCount), &dwResult, NULL); + + if (bResult) + return refCount; + else + return -1; +} + +// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been +// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). +BOOL LoadInt32 (char *filePath, unsigned __int32 *result, __int64 fileOffset) +{ + size_t bufSize = sizeof(__int32); + unsigned char *buffer = (unsigned char *) malloc (bufSize); + unsigned char *bufferPtr = buffer; + HANDLE src = NULL; + DWORD bytesRead; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL retVal = FALSE; + + if (buffer == NULL) + return -1; + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return FALSE; + } + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 + || bytesRead != bufSize) + goto fsif_end; + + + retVal = TRUE; + + *result = mgetLong(bufferPtr); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been +// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). +BOOL LoadInt16 (char *filePath, int *result, __int64 fileOffset) +{ + size_t bufSize = sizeof(__int16); + unsigned char *buffer = (unsigned char *) malloc (bufSize); + unsigned char *bufferPtr = buffer; + HANDLE src = NULL; + DWORD bytesRead; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL retVal = FALSE; + + if (buffer == NULL) + return -1; + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return FALSE; + } + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 + || bytesRead != bufSize) + goto fsif_end; + + + retVal = TRUE; + + *result = mgetWord(bufferPtr); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated. +char *LoadFile (const char *fileName, DWORD *size) +{ + char *buf; + HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + return NULL; + + *size = GetFileSize (h, NULL); + buf = (char *) malloc (*size + 1); + + if (buf == NULL) + { + CloseHandle (h); + return NULL; + } + + ZeroMemory (buf, *size + 1); + + if (!ReadFile (h, buf, *size, size, NULL)) + { + free (buf); + buf = NULL; + } + + CloseHandle (h); + return buf; +} + + +// Returns NULL if there's any error. +char *LoadFileBlock (char *fileName, __int64 fileOffset, size_t count) +{ + char *buf; + DWORD bytesRead = 0; + LARGE_INTEGER seekOffset, seekOffsetNew; + + HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + return NULL; + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + { + CloseHandle (h); + return NULL; + } + + buf = (char *) malloc (count); + + if (buf == NULL) + { + CloseHandle (h); + return NULL; + } + + ZeroMemory (buf, count); + + if (buf != NULL) + ReadFile (h, buf, count, &bytesRead, NULL); + + CloseHandle (h); + + if (bytesRead != count) + { + free (buf); + return NULL; + } + + return buf; +} + + +// Returns -1 if there is an error, or the size of the file. +__int64 GetFileSize64 (const char *path) +{ + HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + LARGE_INTEGER size; + + if (h == INVALID_HANDLE_VALUE) + return -1; + + if (GetFileSizeEx (h, &size) == 0) + return -1; + + CloseHandle (h); + + return size.QuadPart; +} + + +char *GetModPath (char *path, int maxSize) +{ + GetModuleFileName (NULL, path, maxSize); + strrchr (path, '\\')[1] = 0; + return path; +} + + +char *GetConfigPath (char *fileName) +{ + static char path[MAX_PATH * 2] = { 0 }; + + if (IsNonInstallMode ()) + { + GetModPath (path, sizeof (path)); + strcat (path, fileName); + + return path; + } + + if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) + { + strcat (path, "\\TrueCrypt\\"); + CreateDirectory (path, NULL); + strcat (path, fileName); + } + else + path[0] = 0; + + return path; +} + + +char *GetProgramConfigPath (char *fileName) +{ + static char path[MAX_PATH * 2] = { 0 }; + + if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) + { + strcat (path, "\\TrueCrypt\\"); + CreateDirectory (path, NULL); + strcat (path, fileName); + } + else + path[0] = 0; + + return path; +} + + +// Returns 0 if an error occurs or the drive letter (as an upper-case char) of the system partition (e.g. 'C'); +char GetSystemDriveLetter (void) +{ + char systemDir [MAX_PATH]; + + if (GetSystemDirectory (systemDir, sizeof (systemDir))) + return (char) (toupper (systemDir [0])); + else + return 0; +} + +int Info (char *stringId) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONINFORMATION); +} + + +int InfoTopMost (char *stringId) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int InfoDirect (const wchar_t *msg) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, msg, lpszTitle, MB_ICONINFORMATION); +} + + +int Warning (char *stringId) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING); +} + + +int WarningTopMost (char *stringId) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int WarningDirect (const wchar_t *warnMsg) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, warnMsg, lpszTitle, MB_ICONWARNING); +} + + +int Error (char *stringId) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR); +} + + +int ErrorTopMost (char *stringId) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int ErrorDirect (const wchar_t *errMsg) +{ + if (Silent) return 0; + return MessageBoxW (MainDlg, errMsg, lpszTitle, MB_ICONERROR); +} + + +int AskYesNo (char *stringId) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskYesNoString (const wchar_t *str) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, str, lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskNoYes (char *stringId) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); +} + + +int AskOkCancel (char *stringId) +{ + if (Silent) return IDCANCEL; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_OKCANCEL | MB_DEFBUTTON1); +} + + +int AskWarnYesNo (char *stringId) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskWarnNoYes (char *stringId) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); +} + + +int AskWarnNoYesString (const wchar_t *string) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); +} + + +int AskWarnYesNoString (const wchar_t *string) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskWarnOkCancel (char *stringId) +{ + if (Silent) return IDCANCEL; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1); +} + + +int AskWarnCancelOk (char *stringId) +{ + if (Silent) return IDCANCEL; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2); +} + + +int AskErrYesNo (char *stringId) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskErrNoYes (char *stringId) +{ + if (Silent) return IDNO; + return MessageBoxW (MainDlg, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON2); +} + + +// The function accepts two input formats: +// Input format 1: {0, "MESSAGE_STRING_ID", "BUTTON_1_STRING_ID", ... "LAST_BUTTON_STRING_ID", 0}; +// Input format 2: {L"", L"Message text", L"Button caption 1", ... L"Last button caption", 0}; +// The second format is to be used if any of the strings contains format specification (e.g. %s, %d) or +// in any other cases where a string needs to be resolved before calling this function. +// If the returned value is 0, the user closed the dialog window without making a choice. +// If the user made a choice, the returned value is the ordinal number of the choice (1..MAX_MULTI_CHOICES) +int AskMultiChoice (void *strings[], BOOL bBold) +{ + MULTI_CHOICE_DLGPROC_PARAMS params; + + params.strings = &strings[0]; + params.bold = bBold; + + return DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_MULTI_CHOICE_DLG), MainDlg, + (DLGPROC) MultiChoiceDialogProc, (LPARAM) ¶ms); +} + + +BOOL ConfigWriteBegin () +{ + DWORD size; + if (ConfigFileHandle != NULL) + return FALSE; + + if (ConfigBuffer == NULL) + ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); + + ConfigFileHandle = fopen (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), "w"); + if (ConfigFileHandle == NULL) + { + free (ConfigBuffer); + ConfigBuffer = NULL; + return FALSE; + } + XmlWriteHeader (ConfigFileHandle); + fputs ("\n\t", ConfigFileHandle); + + return TRUE; +} + + +BOOL ConfigWriteEnd () +{ + char *xml = ConfigBuffer; + char key[128], value[2048]; + + if (ConfigFileHandle == NULL) return FALSE; + + // Write unmodified values + while (xml && (xml = XmlFindElement (xml, "config"))) + { + XmlGetAttributeText (xml, "key", key, sizeof (key)); + XmlGetNodeText (xml, value, sizeof (value)); + + fprintf (ConfigFileHandle, "\n\t\t%s", key, value); + xml++; + } + + fputs ("\n\t", ConfigFileHandle); + XmlWriteFooter (ConfigFileHandle); + + TCFlushFile (ConfigFileHandle); + + fclose (ConfigFileHandle); + ConfigFileHandle = NULL; + + if (ConfigBuffer != NULL) + { + DWORD size; + free (ConfigBuffer); + ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); + } + + return TRUE; +} + + +BOOL ConfigWriteString (char *configKey, char *configValue) +{ + char *c; + if (ConfigFileHandle == NULL) + return FALSE; + + // Mark previous config value as updated + if (ConfigBuffer != NULL) + { + c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); + if (c != NULL) + c[1] = '!'; + } + + return 0 != fprintf ( + ConfigFileHandle, "\n\t\t%s", + configKey, configValue); +} + + +BOOL ConfigWriteInt (char *configKey, int configValue) +{ + char val[32]; + sprintf (val, "%d", configValue); + return ConfigWriteString (configKey, val); +} + + +static BOOL ConfigRead (char *configKey, char *configValue, int maxValueSize) +{ + DWORD size; + char *xml; + + if (ConfigBuffer == NULL) + ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); + + xml = ConfigBuffer; + if (xml != NULL) + { + xml = XmlFindElementByAttributeValue (xml, "config", "key", configKey); + if (xml != NULL) + { + XmlGetNodeText (xml, configValue, maxValueSize); + return TRUE; + } + } + + return FALSE; +} + + +int ConfigReadInt (char *configKey, int defaultValue) +{ + char s[32]; + + if (ConfigRead (configKey, s, sizeof (s))) + return atoi (s); + else + return defaultValue; +} + + +char *ConfigReadString (char *configKey, char *defaultValue, char *str, int maxLen) +{ + if (ConfigRead (configKey, str, maxLen)) + return str; + else + return defaultValue; +} + + +void OpenPageHelp (HWND hwndDlg, int nPage) +{ + int r = (int)ShellExecute (NULL, "open", szHelpFile, NULL, NULL, SW_SHOWNORMAL); + + if (r == ERROR_FILE_NOT_FOUND) + { + // Try the secondary help file + r = (int)ShellExecute (NULL, "open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL); + + if (r == ERROR_FILE_NOT_FOUND) + { + OpenOnlineHelp (); + return; + } + } + + if (r == SE_ERR_NOASSOC) + { + if (AskYesNo ("HELP_READER_ERROR") == IDYES) + OpenOnlineHelp (); + } +} + + +void OpenOnlineHelp () +{ + Applink ("help", TRUE, ""); +} + + +#ifndef SETUP + +void RestoreDefaultKeyFilesParam (void) +{ + KeyFileRemoveAll (&FirstKeyFile); + if (defaultKeyFilesParam.FirstKeyFile != NULL) + { + FirstKeyFile = KeyFileCloneAll (defaultKeyFilesParam.FirstKeyFile); + KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; + } + else + KeyFilesEnable = FALSE; +} + + +BOOL LoadDefaultKeyFilesParam (void) +{ + BOOL status = TRUE; + DWORD size; + char *defaultKeyfilesFile = LoadFile (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES), &size); + char *xml = defaultKeyfilesFile; + KeyFile *kf; + + if (xml == NULL) + return FALSE; + + KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); + + while (xml = XmlFindElement (xml, "keyfile")) + { + kf = (KeyFile *) malloc (sizeof (KeyFile)); + + if (XmlGetNodeText (xml, kf->FileName, sizeof (kf->FileName)) != NULL) + defaultKeyFilesParam.FirstKeyFile = KeyFileAdd (defaultKeyFilesParam.FirstKeyFile, kf); + else + free (kf); + + xml++; + } + + free (defaultKeyfilesFile); + KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; + + return status; +} + +#endif /* #ifndef SETUP */ + + +void Debug (char *format, ...) +{ + char buf[1024]; + va_list val; + + va_start(val, format); + _vsnprintf (buf, sizeof (buf), format, val); + va_end(val); + + OutputDebugString (buf); +} + + +void DebugMsgBox (char *format, ...) +{ + char buf[1024]; + va_list val; + + va_start(val, format); + _vsnprintf (buf, sizeof (buf), format, val); + va_end(val); + + MessageBox (MainDlg, buf, "TrueCrypt debug", 0); +} + + +BOOL IsOSAtLeast (OSVersionEnum reqMinOS) +{ + return IsOSVersionAtLeast (reqMinOS, 0); +} + + +// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack. +// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE. +// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE. +// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE. +BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack) +{ + /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */ + + if (CurrentOSMajor <= 0) + TC_THROW_FATAL_EXCEPTION; + + int major = 0, minor = 0; + + switch (reqMinOS) + { + case WIN_2000: major = 5; minor = 0; break; + case WIN_XP: major = 5; minor = 1; break; + case WIN_SERVER_2003: major = 5; minor = 2; break; + case WIN_VISTA: major = 6; minor = 0; break; + case WIN_7: major = 6; minor = 1; break; + + default: + TC_THROW_FATAL_EXCEPTION; + break; + } + + return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack) + >= (major << 16 | minor << 8 | reqMinServicePack)); +} + + +BOOL Is64BitOs () +{ + static BOOL isWow64 = FALSE; + static BOOL valid = FALSE; + typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process); + LPFN_ISWOW64PROCESS fnIsWow64Process; + + if (valid) + return isWow64; + + fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle("kernel32"), "IsWow64Process"); + + if (fnIsWow64Process != NULL) + if (!fnIsWow64Process (GetCurrentProcess(), &isWow64)) + isWow64 = FALSE; + + valid = TRUE; + return isWow64; +} + + +BOOL IsServerOS () +{ + OSVERSIONINFOEXA osVer; + osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXA); + GetVersionExA ((LPOSVERSIONINFOA) &osVer); + + return (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); +} + + +// Returns TRUE, if the currently running operating system is installed in a hidden volume. If it's not, or if +// there's an error, returns FALSE. +BOOL IsHiddenOSRunning (void) +{ + static BOOL statusCached = FALSE; + static BOOL hiddenOSRunning; + + if (!statusCached) + { + try + { + hiddenOSRunning = BootEncryption (MainDlg).IsHiddenSystemRunning(); + } + catch (...) + { + hiddenOSRunning = FALSE; + } + + statusCached = TRUE; + } + + return hiddenOSRunning; +} + + +BOOL RestartComputer (void) +{ + TOKEN_PRIVILEGES tokenPrivil; + HANDLE hTkn; + + if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn)) + { + return false; + } + + LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid); + tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tokenPrivil.PrivilegeCount = 1; + + AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0); + if (GetLastError() != ERROR_SUCCESS) + return false; + + if (!ExitWindowsEx (EWX_REBOOT | EWX_FORCE, + SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) + return false; + + return true; +} + + +std::string GetWindowsEdition () +{ + string osname = "win"; + + OSVERSIONINFOEXA osVer; + osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXA); + GetVersionExA ((LPOSVERSIONINFOA) &osVer); + + BOOL home = (osVer.wSuiteMask & VER_SUITE_PERSONAL); + BOOL server = (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); + + HKEY hkey; + char productName[300] = {0}; + DWORD productNameSize = sizeof (productName); + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) + { + if (RegQueryValueEx (hkey, "ProductName", 0, 0, (LPBYTE) &productName, &productNameSize) != ERROR_SUCCESS || productNameSize < 1) + productName[0] = 0; + + RegCloseKey (hkey); + } + + switch (nCurrentOS) + { + case WIN_2000: + osname += "2000"; + break; + + case WIN_XP: + case WIN_XP64: + osname += "xp"; + osname += home ? "-home" : "-pro"; + break; + + case WIN_SERVER_2003: + osname += "2003"; + break; + + case WIN_VISTA: + osname += "vista"; + break; + + case WIN_SERVER_2008: + osname += "2008"; + break; + + case WIN_7: + osname += "7"; + break; + + case WIN_SERVER_2008_R2: + osname += "2008r2"; + break; + + default: + stringstream s; + s << CurrentOSMajor << "." << CurrentOSMinor; + osname += s.str(); + break; + } + + if (server) + osname += "-server"; + + if (IsOSAtLeast (WIN_VISTA)) + { + if (home) + osname += "-home"; + else if (strstr (productName, "Standard") != 0) + osname += "-standard"; + else if (strstr (productName, "Professional") != 0) + osname += "-pro"; + else if (strstr (productName, "Business") != 0) + osname += "-business"; + else if (strstr (productName, "Enterprise") != 0) + osname += "-enterprise"; + else if (strstr (productName, "Datacenter") != 0) + osname += "-datacenter"; + else if (strstr (productName, "Ultimate") != 0) + osname += "-ultimate"; + } + + if (GetSystemMetrics (SM_STARTER)) + osname += "-starter"; + else if (strstr (productName, "Basic") != 0) + osname += "-basic"; + + if (Is64BitOs()) + osname += "-x64"; + + if (CurrentOSServicePack > 0) + { + stringstream s; + s << "-sp" << CurrentOSServicePack; + osname += s.str(); + } + + return osname; +} + + +void Applink (char *dest, BOOL bSendOS, char *extraOutput) +{ + char url [MAX_URL_LENGTH]; + + ArrowWaitCursor (); + + sprintf_s (url, sizeof (url), TC_APPLINK "%s%s&dest=%s", bSendOS ? ("&os=" + GetWindowsEdition()).c_str() : "", extraOutput, dest); + ShellExecute (NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); + + Sleep (200); + NormalCursor (); +} + + +char *RelativePath2Absolute (char *szFileName) +{ + if (szFileName[0] != '\\' + && strchr (szFileName, ':') == 0 + && strstr (szFileName, "Volume{") != szFileName) + { + char path[MAX_PATH*2]; + GetCurrentDirectory (MAX_PATH, path); + + if (path[strlen (path) - 1] != '\\') + strcat (path, "\\"); + + strcat (path, szFileName); + strncpy (szFileName, path, MAX_PATH-1); + } + + return szFileName; +} + + +void HandleDriveNotReadyError () +{ + HKEY hkey = 0; + DWORD value = 0, size = sizeof (DWORD); + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\MountMgr", + 0, KEY_READ, &hkey) != ERROR_SUCCESS) + return; + + if (RegQueryValueEx (hkey, "NoAutoMount", 0, 0, (LPBYTE) &value, &size) == ERROR_SUCCESS + && value != 0) + Warning ("SYS_AUTOMOUNT_DISABLED"); + else if (nCurrentOS == WIN_VISTA && CurrentOSServicePack < 1) + Warning ("SYS_ASSIGN_DRIVE_LETTER"); + else + Error ("ERR_HARDWARE_ERROR"); + + RegCloseKey (hkey); +} + + +BOOL CALLBACK CloseTCWindowsEnum (HWND hwnd, LPARAM lParam) +{ + if (GetWindowLongPtr (hwnd, GWLP_USERDATA) == (LONG_PTR) 'TRUE') + { + char name[1024] = { 0 }; + GetWindowText (hwnd, name, sizeof (name) - 1); + if (hwnd != MainDlg && strstr (name, "TrueCrypt")) + { + PostMessage (hwnd, TC_APPMSG_CLOSE_BKG_TASK, 0, 0); + + if (DriverVersion < 0x0430) + PostMessage (hwnd, WM_ENDSESSION, 0, 0); + + PostMessage (hwnd, WM_CLOSE, 0, 0); + + if (lParam != 0) + *((BOOL *)lParam) = TRUE; + } + } + return TRUE; +} + +BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam) +{ + if (*(HWND *)lParam == hwnd) + return TRUE; + + if (GetWindowLongPtr (hwnd, GWLP_USERDATA) == (LONG_PTR) 'TRUE') + { + char name[32] = { 0 }; + GetWindowText (hwnd, name, sizeof (name) - 1); + if (hwnd != MainDlg && strcmp (name, "TrueCrypt") == 0) + { + if (lParam != 0) + *((HWND *)lParam) = hwnd; + } + } + return TRUE; +} + + +BYTE *MapResource (char *resourceType, int resourceId, PDWORD size) +{ + HGLOBAL hResL; + HRSRC hRes; + + hRes = FindResource (NULL, MAKEINTRESOURCE(resourceId), resourceType); + hResL = LoadResource (NULL, hRes); + + if (size != NULL) + *size = SizeofResource (NULL, hRes); + + return (BYTE *) LockResource (hResL); +} + + +void InconsistencyResolved (char *techInfo) +{ + wchar_t finalMsg[8024]; + + wsprintfW (finalMsg, GetString ("INCONSISTENCY_RESOLVED"), techInfo); + MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); +} + + +void ReportUnexpectedState (char *techInfo) +{ + wchar_t finalMsg[8024]; + + wsprintfW (finalMsg, GetString ("UNEXPECTED_STATE"), techInfo); + MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); +} + + +#ifndef SETUP + +int OpenVolume (OpenVolumeContext *context, const char *volumePath, Password *password, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader) +{ + int status = ERR_PARAMETER_INCORRECT; + int volumeType; + char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; + char szDosDevice[TC_MAX_PATH]; + char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + LARGE_INTEGER headerOffset; + DWORD dwResult; + + context->VolumeIsOpen = FALSE; + context->CryptoInfo = NULL; + context->HostFileHandle = INVALID_HANDLE_VALUE; + context->TimestampsValid = FALSE; + + CreateFullVolumePath (szDiskFile, volumePath, &context->IsDevice); + + if (context->IsDevice) + { + status = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE); + if (status != 0) + return status; + + preserveTimestamps = FALSE; + } + else + strcpy (szCFDevice, szDiskFile); + + if (preserveTimestamps) + write = TRUE; + + context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (context->HostFileHandle == INVALID_HANDLE_VALUE) + { + status = ERR_OS_ERROR; + goto error; + } + + if (context->IsDevice) + { + // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, + // the NTFS driver guards hidden sectors and prevents e.g. header backup restore after the user + // accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS, etc.) + + DeviceIoControl (context->HostFileHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwResult, NULL); + } + + context->VolumeIsOpen = TRUE; + + // Remember the container modification/creation date and time + if (!context->IsDevice && preserveTimestamps) + { + if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0) + { + context->TimestampsValid = FALSE; + Warning ("GETFILETIME_FAILED_GENERIC"); + } + else + context->TimestampsValid = TRUE; + } + + // Determine host size + if (context->IsDevice) + { + PARTITION_INFORMATION diskInfo; + + if (GetPartitionInfo (volumePath, &diskInfo)) + { + context->HostSize = diskInfo.PartitionLength.QuadPart; + } + else + { + DISK_GEOMETRY driveInfo; + + if (!DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) + { + status = ERR_OS_ERROR; + goto error; + } + + context->HostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; + } + + if (context->HostSize == 0) + { + status = ERR_VOL_SIZE_WRONG; + goto error; + } + } + else + { + LARGE_INTEGER fileSize; + if (!GetFileSizeEx (context->HostFileHandle, &fileSize)) + { + status = ERR_OS_ERROR; + goto error; + } + + context->HostSize = fileSize.QuadPart; + } + + for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++) + { + // Seek the volume header + switch (volumeType) + { + case TC_VOLUME_TYPE_NORMAL: + headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; + break; + + case TC_VOLUME_TYPE_HIDDEN: + if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > context->HostSize) + continue; + + headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_SIZE : TC_HIDDEN_VOLUME_HEADER_OFFSET; + break; + + case TC_VOLUME_TYPE_HIDDEN_LEGACY: + if (useBackupHeader) + { + status = ERR_PASSWORD_WRONG; + goto error; + } + + headerOffset.QuadPart = context->HostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; + break; + } + + if (!SetFilePointerEx ((HANDLE) context->HostFileHandle, headerOffset, NULL, FILE_BEGIN)) + { + status = ERR_OS_ERROR; + goto error; + } + + // Read volume header + DWORD bytesRead; + if (!ReadFile (context->HostFileHandle, buffer, sizeof (buffer), &bytesRead, NULL)) + { + status = ERR_OS_ERROR; + goto error; + } + + if (bytesRead != sizeof (buffer) + && context->IsDevice) + { + // If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the + // filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is + // shorter than the partition). This can happen for example after the user quick-formats a dismounted + // partition-hosted TrueCrypt volume and then tries to read the embedded backup header. + + memset (buffer, 0, sizeof (buffer)); + } + + // Decrypt volume header + status = ReadVolumeHeader (FALSE, buffer, password, &context->CryptoInfo, NULL); + + if (status == ERR_PASSWORD_WRONG) + continue; // Try next volume type + + break; + } + + if (status == ERR_SUCCESS) + return status; + +error: + DWORD sysError = GetLastError (); + + CloseVolume (context); + + SetLastError (sysError); + return status; +} + + +void CloseVolume (OpenVolumeContext *context) +{ + if (!context->VolumeIsOpen) + return; + + if (context->HostFileHandle != INVALID_HANDLE_VALUE) + { + // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). + if (context->TimestampsValid) + { + if (!SetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime)) + { + handleWin32Error (NULL); + Warning ("SETFILETIME_FAILED_PW"); + } + } + + CloseHandle (context->HostFileHandle); + context->HostFileHandle = INVALID_HANDLE_VALUE; + } + + if (context->CryptoInfo) + { + crypto_close (context->CryptoInfo); + context->CryptoInfo = NULL; + } + + context->VolumeIsOpen = FALSE; +} + + +int ReEncryptVolumeHeader (char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, BOOL wipeMode) +{ + CRYPTO_INFO *newCryptoInfo = NULL; + + RandSetHashFunction (cryptoInfo->pkcs5); + + if (Randinit() != ERR_SUCCESS) + return ERR_PARAMETER_INCORRECT; + + UserEnrichRandomPool (NULL); + + int status = CreateVolumeHeaderInMemory (bBoot, + buffer, + cryptoInfo->ea, + cryptoInfo->mode, + password, + cryptoInfo->pkcs5, + (char *) cryptoInfo->master_keydata, + &newCryptoInfo, + cryptoInfo->VolumeSize.Value, + cryptoInfo->hiddenVolume ? cryptoInfo->hiddenVolumeSize : 0, + cryptoInfo->EncryptedAreaStart.Value, + cryptoInfo->EncryptedAreaLength.Value, + cryptoInfo->RequiredProgramVersion, + cryptoInfo->HeaderFlags, + wipeMode); + + if (newCryptoInfo != NULL) + crypto_close (newCryptoInfo); + + return status; +} + +#endif // !SETUP + + +BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) +{ + // GlobalMemoryStatusEx() cannot be used to determine if a paging file is active + + char data[65536]; + DWORD size = sizeof (data); + + if (IsPagingFileWildcardActive()) + return TRUE; + + if (ReadLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", data, &size) + && size > 12 && !checkNonWindowsPartitionsOnly) + return TRUE; + + if (!IsAdmin()) + AbortProcess ("UAC_INIT_ERROR"); + + for (char drive = 'C'; drive <= 'Z'; ++drive) + { + // Query geometry of the drive first to prevent "no medium" pop-ups + string drivePath = "\\\\.\\X:"; + drivePath[4] = drive; + + if (checkNonWindowsPartitionsOnly) + { + char sysDir[MAX_PATH]; + if (GetSystemDirectory (sysDir, sizeof (sysDir)) != 0 && toupper (sysDir[0]) == drive) + continue; + } + + HANDLE handle = CreateFile (drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (handle == INVALID_HANDLE_VALUE) + continue; + + DISK_GEOMETRY driveInfo; + DWORD dwResult; + + if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) + { + CloseHandle (handle); + continue; + } + + CloseHandle (handle); + + // Test if a paging file exists and is locked by another process + string path = "X:\\pagefile.sys"; + path[0] = drive; + + handle = CreateFile (path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if (handle != INVALID_HANDLE_VALUE) + CloseHandle (handle); + else if (GetLastError() == ERROR_SHARING_VIOLATION) + return TRUE; + } + + return FALSE; +} + + +BOOL IsPagingFileWildcardActive () +{ + char pagingFiles[65536]; + DWORD size = sizeof (pagingFiles); + char *mmKey = "System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"; + + if (!ReadLocalMachineRegistryString (mmKey, "PagingFiles", pagingFiles, &size)) + { + size = sizeof (pagingFiles); + if (!ReadLocalMachineRegistryMultiString (mmKey, "PagingFiles", pagingFiles, &size)) + size = 0; + } + + return size > 0 && strstr (pagingFiles, "?:\\") == pagingFiles; +} + + +BOOL DisablePagingFile () +{ + char empty[] = { 0, 0 }; + return WriteLocalMachineRegistryMultiString ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles", empty, sizeof (empty)); +} + + +std::wstring SingleStringToWide (const std::string &singleString) +{ + if (singleString.empty()) + return std::wstring(); + + WCHAR wbuf[65536]; + int wideLen = MultiByteToWideChar (CP_ACP, 0, singleString.c_str(), -1, wbuf, array_capacity (wbuf) - 1); + throw_sys_if (wideLen == 0); + + wbuf[wideLen] = 0; + return wbuf; +} + + +std::wstring Utf8StringToWide (const std::string &utf8String) +{ + if (utf8String.empty()) + return std::wstring(); + + WCHAR wbuf[65536]; + int wideLen = MultiByteToWideChar (CP_UTF8, 0, utf8String.c_str(), -1, wbuf, array_capacity (wbuf) - 1); + throw_sys_if (wideLen == 0); + + wbuf[wideLen] = 0; + return wbuf; +} + + +std::string WideToUtf8String (const std::wstring &wideString) +{ + if (wideString.empty()) + return std::string(); + + char buf[65536]; + int len = WideCharToMultiByte (CP_UTF8, 0, wideString.c_str(), -1, buf, array_capacity (buf) - 1, NULL, NULL); + throw_sys_if (len == 0); + + buf[len] = 0; + return buf; +} + + +std::string WideToSingleString (const std::wstring &wideString) +{ + if (wideString.empty()) + return std::string(); + + char buf[65536]; + int len = WideCharToMultiByte (CP_ACP, 0, wideString.c_str(), -1, buf, array_capacity (buf) - 1, NULL, NULL); + throw_sys_if (len == 0); + + buf[len] = 0; + return buf; +} + + +#ifndef SETUP + +BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + static string *password; + + switch (msg) + { + case WM_INITDIALOG: + { + password = (string *) lParam; + LocalizeDialog (hwndDlg, "IDD_TOKEN_PASSWORD"); + + wchar_t s[1024]; + wsprintfW (s, GetString ("ENTER_TOKEN_PASSWORD"), Utf8StringToWide (password->c_str()).c_str()); + SetWindowTextW (GetDlgItem (hwndDlg, IDT_TOKEN_PASSWORD_INFO), s); + + SendMessage (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), EM_LIMITTEXT, SecurityToken::MaxPasswordLength, 0); + + SetForegroundWindow (hwndDlg); + SetFocus (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD)); + } + return 0; + + case WM_COMMAND: + if (lw == IDCANCEL || lw == IDOK) + { + if (lw == IDOK) + { + wchar_t passwordWide[SecurityToken::MaxPasswordLength + 1]; + + if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), passwordWide, SecurityToken::MaxPasswordLength + 1) == 0) + { + handleWin32Error (hwndDlg); + break; + } + + char passwordUtf8[SecurityToken::MaxPasswordLength + 1]; + + int len = WideCharToMultiByte (CP_UTF8, 0, passwordWide, -1, passwordUtf8, array_capacity (passwordUtf8) - 1, nullptr, nullptr); + passwordUtf8[len] = 0; + *password = passwordUtf8; + + burn (passwordWide, sizeof (passwordWide)); + burn (passwordUtf8, sizeof (passwordUtf8)); + } + + // Attempt to wipe password stored in the input field buffer + char tmp[SecurityToken::MaxPasswordLength+1]; + memset (tmp, 'X', SecurityToken::MaxPasswordLength); + tmp[SecurityToken::MaxPasswordLength] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), tmp); + + EndDialog (hwndDlg, lw); + } + return 1; + } + + return 0; +} + + +struct NewSecurityTokenKeyfileDlgProcParams +{ + CK_SLOT_ID SlotId; + string Name; +}; + +static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static NewSecurityTokenKeyfileDlgProcParams *newParams; + + WORD lw = LOWORD (wParam); + switch (msg) + { + case WM_INITDIALOG: + { + LocalizeDialog (hwndDlg, "IDD_NEW_TOKEN_KEYFILE"); + + newParams = (NewSecurityTokenKeyfileDlgProcParams *) lParam; + + WaitCursor(); + finally_do ({ NormalCursor(); }); + + list tokens; + + try + { + tokens = SecurityToken::GetAvailableTokens(); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + if (tokens.empty()) + { + Error ("NO_TOKENS_FOUND"); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + foreach (const SecurityTokenInfo &token, tokens) + { + wstringstream tokenLabel; + tokenLabel << L"[" << token.SlotId << L"] " << token.Label; + + AddComboPairW (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token.SlotId); + } + + ComboBox_SetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), 0); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), Utf8StringToWide (newParams->Name).c_str()); + return 1; + } + + case WM_COMMAND: + switch (lw) + { + case IDOK: + { + int selectedToken = ComboBox_GetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN)); + if (selectedToken == CB_ERR) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + newParams->SlotId = ComboBox_GetItemData (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), selectedToken); + + wchar_t name[1024]; + if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0) + { + try + { + newParams->Name = WideToUtf8String (name); + } + catch (...) { } + } + + EndDialog (hwndDlg, IDOK); + return 1; + } + + case IDCANCEL: + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + if (HIWORD (wParam) == EN_CHANGE) + { + wchar_t name[2]; + EnableWindow (GetDlgItem (hwndDlg, IDOK), (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0)); + return 1; + } + } + + return 0; +} + + +static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector &keyfiles) +{ + HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); + LVITEMW lvItem; + int line = 0; + + ListView_DeleteAllItems (tokenListControl); + + foreach (const SecurityTokenKeyfile &keyfile, keyfiles) + { + memset (&lvItem, 0, sizeof(lvItem)); + lvItem.mask = LVIF_TEXT; + lvItem.iItem = line++; + + stringstream s; + s << keyfile.SlotId; + + ListItemAdd (tokenListControl, lvItem.iItem, (char *) s.str().c_str()); + ListSubItemSetW (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile.Token.Label.c_str()); + ListSubItemSetW (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile.Id.c_str()); + } + + BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); + EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); + EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); +} + + +static list SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector &keyfiles) +{ + HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); + list selectedKeyfiles; + + int itemId = -1; + while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1) + { + selectedKeyfiles.push_back (keyfiles[itemId]); + } + + return selectedKeyfiles; +} + + +BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static list *selectedTokenKeyfiles; + static vector keyfiles; + + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + selectedTokenKeyfiles = (list *) lParam; + + LVCOLUMNW LvCol; + HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); + + LocalizeDialog (hwndDlg, selectedTokenKeyfiles ? "SELECT_TOKEN_KEYFILES" : "IDD_TOKEN_KEYFILES"); + + SendMessage (tokenListControl,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP + ); + + memset (&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + LvCol.pszText = GetString ("TOKEN_SLOT_ID"); + LvCol.cx = CompensateXDPI (40); + LvCol.fmt = LVCFMT_CENTER; + SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 1, (LPARAM)&LvCol); + + LvCol.pszText = GetString ("TOKEN_NAME"); + LvCol.cx = CompensateXDPI (128); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 2, (LPARAM)&LvCol); + + LvCol.pszText = GetString ("TOKEN_DATA_OBJECT_LABEL"); + LvCol.cx = CompensateXDPI (180); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 3, (LPARAM)&LvCol); + + keyfiles.clear(); + + try + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + keyfiles = SecurityToken::GetAvailableKeyfiles(); + } + catch (UserAbort&) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + catch (Exception &e) + { + e.Show (hwndDlg); + + if (keyfiles.empty()) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + } + + SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); + return 1; + } + + case WM_COMMAND: + case WM_NOTIFY: + if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) + { + if (selectedTokenKeyfiles) + { + foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + { + selectedTokenKeyfiles->push_back (SecurityTokenKeyfilePath (keyfile)); + } + } + + EndDialog (hwndDlg, IDOK); + return 1; + } + + if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) + { + BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); + EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); + EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); + return 1; + } + + switch (lw) + { + case IDCANCEL: + EndDialog (hwndDlg, IDCANCEL); + return 1; + + case IDC_IMPORT_KEYFILE: + { + char keyfilePath[TC_MAX_PATH]; + + if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE, NULL)) + { + DWORD keyfileSize; + byte *keyfileData = (byte *) LoadFile (keyfilePath, &keyfileSize); + if (!keyfileData) + { + handleWin32Error (hwndDlg); + return 1; + } + + if (keyfileSize != 0) + { + NewSecurityTokenKeyfileDlgProcParams newParams; + newParams.Name = WideToUtf8String (SingleStringToWide (keyfilePath)); + + size_t lastBackSlash = newParams.Name.find_last_of ('\\'); + if (lastBackSlash != string::npos) + newParams.Name = newParams.Name.substr (lastBackSlash + 1); + + if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_NEW_TOKEN_KEYFILE), hwndDlg, (DLGPROC) NewSecurityTokenKeyfileDlgProc, (LPARAM) &newParams) == IDOK) + { + vector keyfileDataVector (keyfileSize); + memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize); + + try + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); + + keyfiles = SecurityToken::GetAvailableKeyfiles(); + SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + burn (&keyfileDataVector.front(), keyfileSize); + } + } + else + { + SetLastError (ERROR_HANDLE_EOF); + handleWin32Error (hwndDlg); + } + + burn (keyfileData, keyfileSize); + TCfree (keyfileData); + } + + return 1; + } + + case IDC_EXPORT: + { + try + { + foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + { + char keyfilePath[TC_MAX_PATH]; + + if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL)) + break; + + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + vector keyfileData; + + SecurityToken::GetKeyfileData (keyfile, keyfileData); + + if (keyfileData.empty()) + { + SetLastError (ERROR_HANDLE_EOF); + handleWin32Error (hwndDlg); + return 1; + } + + finally_do_arg (vector *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); }); + + if (!SaveBufferToFile ((char *) &keyfileData.front(), keyfilePath, keyfileData.size(), FALSE)) + throw SystemException (); + } + + Info ("KEYFILE_EXPORTED"); + } + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + return 1; + } + + case IDC_DELETE: + { + if (AskNoYes ("CONFIRM_SEL_FILES_DELETE") == IDNO) + return 1; + + try + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + { + SecurityToken::DeleteKeyfile (keyfile); + } + + keyfiles = SecurityToken::GetAvailableKeyfiles(); + SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + return 1; + } + } + + return 0; + } + return 0; +} + + +BOOL InitSecurityTokenLibrary () +{ + if (SecurityTokenLibraryPath[0] == 0) + { + Error ("NO_PKCS11_MODULE_SPECIFIED"); + return FALSE; + } + + struct PinRequestHandler : public GetPinFunctor + { + virtual void operator() (string &str) + { + if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PASSWORD), MainDlg, (DLGPROC) SecurityTokenPasswordDlgProc, (LPARAM) &str) == IDCANCEL) + throw UserAbort (SRC_POS); + + if (hCursor != NULL) + SetCursor (hCursor); + } + }; + + struct WarningHandler : public SendExceptionFunctor + { + virtual void operator() (const Exception &e) + { + e.Show (NULL); + } + }; + + try + { + SecurityToken::InitLibrary (SecurityTokenLibraryPath, auto_ptr (new PinRequestHandler), auto_ptr (new WarningHandler)); + } + catch (Exception &e) + { + e.Show (NULL); + Error ("PKCS11_MODULE_INIT_FAILED"); + return FALSE; + } + + return TRUE; +} + +#endif // !SETUP + +std::vector GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems) +{ + vector devices; + size_t device0Index; + + for (int devNumber = 0; devNumber < 64; devNumber++) + { + for (int partNumber = 0; partNumber < 32; partNumber++) + { + stringstream strm; + strm << "\\Device\\Harddisk" << devNumber << "\\Partition" << partNumber; + string devPathStr (strm.str()); + const char *devPath = devPathStr.c_str(); + + OPEN_TEST_STRUCT openTest; + if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0)) + { + if (partNumber == 0) + break; + + continue; + } + + HostDevice device; + device.SystemNumber = devNumber; + device.Path = devPath; + + PARTITION_INFORMATION partInfo; + + if (GetPartitionInfo (devPath, &partInfo)) + device.Size = partInfo.PartitionLength.QuadPart; + + device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; + + if (!noDeviceProperties) + { + DISK_GEOMETRY geometry; + + wstringstream ws; + ws << devPathStr.c_str(); + int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str()); + + if (driveNumber >= 0) + { + device.MountPoint += (char) (driveNumber + 'A'); + device.MountPoint += ":"; + + wchar_t name[64]; + if (GetDriveLabel (driveNumber, name, sizeof (name))) + device.Name = name; + + if (GetSystemDriveLetter() == 'A' + driveNumber) + device.ContainsSystem = true; + } + + if (partNumber == 0 && GetDriveGeometry (devPath, &geometry)) + device.Removable = (geometry.MediaType == RemovableMedia); + } + + if (partNumber == 0) + { + devices.push_back (device); + device0Index = devices.size() - 1; + } + else + { + HostDevice *device0 = &devices[device0Index]; + + // System creates a virtual partition1 for some storage devices without + // partition table. We try to detect this case by comparing sizes of + // partition0 and partition1. If they match, no partition of the device + // is displayed to the user to avoid confusion. Drive letter assigned by + // system to partition1 is assigned partition0 + if (partNumber == 1 && device0->Size == device.Size) + { + device0->IsVirtualPartition = true; + device0->MountPoint = device.MountPoint; + device0->Name = device.Name; + device0->Path = device.Path; + device0->HasUnencryptedFilesystem = device.HasUnencryptedFilesystem; + break; + } + + device.IsPartition = true; + device.SystemNumber = partNumber; + device.Removable = device0->Removable; + + if (device.ContainsSystem) + device0->ContainsSystem = true; + + if (singleList) + devices.push_back (device); + else + device0->Partitions.push_back (device); + } + } + } + + // Vista does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices + if (CurrentOSMajor >= 6) + { + for (int devNumber = 0; devNumber < 256; devNumber++) + { + stringstream strm; + strm << "\\Device\\HarddiskVolume" << devNumber; + string devPathStr (strm.str()); + const char *devPath = devPathStr.c_str(); + + OPEN_TEST_STRUCT openTest; + if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems)) + continue; + + DISK_PARTITION_INFO_STRUCT info; + if (GetDeviceInfo (devPath, &info) && info.IsDynamic) + { + HostDevice device; + device.DynamicVolume = true; + device.IsPartition = true; + device.SystemNumber = devNumber; + device.Path = devPath; + device.Size = info.partInfo.PartitionLength.QuadPart; + device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; + + if (!noDeviceProperties) + { + wstringstream ws; + ws << devPathStr.c_str(); + int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str()); + + if (driveNumber >= 0) + { + device.MountPoint += (char) (driveNumber + 'A'); + device.MountPoint += ":"; + + wchar_t name[64]; + if (GetDriveLabel (driveNumber, name, sizeof (name))) + device.Name = name; + + if (GetSystemDriveLetter() == 'A' + driveNumber) + device.ContainsSystem = true; + } + } + + devices.push_back (device); + } + } + } + + // Floppy drives + if (!noFloppy) + { + HostDevice floppy; + floppy.Floppy = true; + + char path[TC_MAX_PATH]; + + if (QueryDosDevice ("A:", path, sizeof (path)) != 0 && GetDriveType ("A:\\") == DRIVE_REMOVABLE) + { + floppy.MountPoint = "A:"; + floppy.Path = "\\Device\\Floppy0"; + devices.push_back (floppy); + } + + if (QueryDosDevice ("B:", path, sizeof (path)) != 0 && GetDriveType ("B:\\") == DRIVE_REMOVABLE) + { + floppy.MountPoint = "B:"; + floppy.Path = "\\Device\\Floppy1"; + devices.push_back (floppy); + } + } + + return devices; +} + + +BOOL FileHasReadOnlyAttribute (const char *path) +{ + DWORD attributes = GetFileAttributes (path); + return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY) != 0; +} + + +BOOL IsFileOnReadOnlyFilesystem (const char *path) +{ + char root[MAX_PATH]; + if (!GetVolumePathName (path, root, sizeof (root))) + return FALSE; + + DWORD flags, d; + if (!GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) + return FALSE; + + return (flags & FILE_READ_ONLY_VOLUME) ? TRUE : FALSE; +} + + +void CheckFilesystem (int driveNo, BOOL fixErrors) +{ + wchar_t msg[1024], param[1024]; + char driveRoot[] = { 'A' + (char) driveNo, ':', 0 }; + + if (fixErrors && AskWarnYesNo ("FILESYS_REPAIR_CONFIRM_BACKUP") == IDNO) + return; + + wsprintfW (msg, GetString (fixErrors ? "REPAIRING_FS" : "CHECKING_FS"), driveRoot); + wsprintfW (param, fixErrors ? L"/C echo %s & chkdsk %hs /F /X & pause" : L"/C echo %s & chkdsk %hs & pause", msg, driveRoot); + + ShellExecuteW (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", L"cmd.exe", param, NULL, SW_SHOW); +} + + +BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str) +{ + size_t strLen = strlen (str); + + if (bufferSize < strLen) + return FALSE; + + bufferSize -= strLen; + + for (size_t i = 0; i < bufferSize; ++i) + { + if (memcmp (buffer + i, str, strLen) == 0) + return TRUE; + } + + return FALSE; +} + + +#ifndef SETUP + +int AskNonSysInPlaceEncryptionResume () +{ + if (AskWarnYesNo ("NONSYS_INPLACE_ENC_RESUME_PROMPT") == IDYES) + return IDYES; + + char *multiChoiceStr[] = { 0, "ASK_NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL", "DO_NOT_PROMPT_ME", "KEEP_PROMPTING_ME", 0 }; + + switch (AskMultiChoice ((void **) multiChoiceStr, FALSE)) + { + case 1: + RemoveNonSysInPlaceEncNotifications(); + Warning ("NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL_NOTE"); + break; + + default: + // NOP + break; + } + + return IDNO; +} + +#endif // !SETUP + + +BOOL RemoveDeviceWriteProtection (HWND hwndDlg, char *devicePath) +{ + int driveNumber; + int partitionNumber; + + char temp[MAX_PATH*2]; + char cmdBatch[MAX_PATH*2]; + char diskpartScript[MAX_PATH*2]; + + if (sscanf (devicePath, "\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2) + return FALSE; + + if (GetTempPath (sizeof (temp), temp) == 0) + return FALSE; + + _snprintf (cmdBatch, sizeof (cmdBatch), "%s\\TrueCrypt_Write_Protection_Removal.cmd", temp); + _snprintf (diskpartScript, sizeof (diskpartScript), "%s\\TrueCrypt_Write_Protection_Removal.diskpart", temp); + + FILE *f = fopen (cmdBatch, "w"); + if (!f) + { + handleWin32Error (hwndDlg); + return FALSE; + } + + fprintf (f, "@diskpart /s \"%s\"\n@pause\n@del \"%s\" \"%s\"", diskpartScript, diskpartScript, cmdBatch); + fclose (f); + + f = fopen (diskpartScript, "w"); + if (!f) + { + handleWin32Error (hwndDlg); + DeleteFile (cmdBatch); + return FALSE; + } + + fprintf (f, "select disk %d\nattributes disk clear readonly\n", driveNumber); + + if (partitionNumber != 0) + fprintf (f, "select partition %d\nattributes volume clear readonly\n", partitionNumber); + + fprintf (f, "exit\n"); + fclose (f); + + ShellExecute (NULL, (!IsAdmin() && IsUacSupported()) ? "runas" : "open", cmdBatch, NULL, NULL, SW_SHOW); + + return TRUE; +} + + +static LRESULT CALLBACK EnableElevatedCursorChangeWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc (hWnd, message, wParam, lParam); +} + + +void EnableElevatedCursorChange (HWND parent) +{ + // Create a transparent window to work around a UAC issue preventing change of the cursor + if (UacElevated) + { + const char *className = "TrueCryptEnableElevatedCursorChange"; + WNDCLASSEX winClass; + HWND hWnd; + + memset (&winClass, 0, sizeof (winClass)); + winClass.cbSize = sizeof (WNDCLASSEX); + winClass.lpfnWndProc = (WNDPROC) EnableElevatedCursorChangeWndProc; + winClass.hInstance = hInst; + winClass.lpszClassName = className; + RegisterClassEx (&winClass); + + hWnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_LAYERED, className, "TrueCrypt UAC", 0, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), parent, NULL, hInst, NULL); + SetLayeredWindowAttributes (hWnd, 0, 1, LWA_ALPHA); + ShowWindow (hWnd, SW_SHOWNORMAL); + + DestroyWindow (hWnd); + UnregisterClass (className, hInst); + } +} + + +BOOL DisableFileCompression (HANDLE file) +{ + USHORT format; + DWORD bytesOut; + + if (!DeviceIoControl (file, FSCTL_GET_COMPRESSION, NULL, 0, &format, sizeof (format), &bytesOut, NULL)) + return FALSE; + + if (format == COMPRESSION_FORMAT_NONE) + return TRUE; + + format = COMPRESSION_FORMAT_NONE; + return DeviceIoControl (file, FSCTL_SET_COMPRESSION, &format, sizeof (format), NULL, 0, &bytesOut, NULL); +} + + +BOOL VolumePathExists (char *volumePath) +{ + OPEN_TEST_STRUCT openTest; + char upperCasePath[TC_MAX_PATH]; + + UpperCaseCopy (upperCasePath, volumePath); + + if (strstr (upperCasePath, "\\DEVICE\\") == upperCasePath) + return OpenDevice (volumePath, &openTest, FALSE); + + string path = volumePath; + if (path.find ("\\\\?\\Volume{") == 0 && path.rfind ("}\\") == path.size() - 2) + { + char devicePath[TC_MAX_PATH]; + if (QueryDosDevice (path.substr (4, path.size() - 5).c_str(), devicePath, TC_MAX_PATH) != 0) + return TRUE; + } + + return _access (volumePath, 0) == 0; +} + + +BOOL IsWindowsIsoBurnerAvailable () +{ + char path[MAX_PATH*2] = { 0 }; + + if (!IsOSAtLeast (WIN_7)) + { + return FALSE; + } + + if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_SYSTEM, NULL, 0, path))) + { + strcat (path, "\\" ISO_BURNER_TOOL); + + return (FileExists (path)); + } + + return FALSE; +} + + +BOOL LaunchWindowsIsoBurner (HWND hwnd, const char *isoPath) +{ + int r = (int) ShellExecute (hwnd, "open", ISO_BURNER_TOOL, (string ("\"") + isoPath + "\"").c_str(), NULL, SW_SHOWNORMAL); + + if (r <= 32) + { + SetLastError (r); + handleWin32Error (hwnd); + + return FALSE; + } + + return TRUE; +} diff --git a/Common/DLGCODE.H b/Common/DLGCODE.H index d39f3ef..93fe97a 100644 --- a/Common/DLGCODE.H +++ b/Common/DLGCODE.H @@ -1,509 +1,499 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TC_HEADER_DLGCODE -#define TC_HEADER_DLGCODE - -#include "Common.h" -#include "Apidrvr.h" -#include "Keyfiles.h" -#include "Wipe.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* IDs for dynamically generated GUI elements */ -enum dynamic_gui_element_ids -{ - IDPM_CHECK_FILESYS = 500001, - IDPM_REPAIR_FILESYS, - IDPM_OPEN_VOLUME, - IDPM_SELECT_FILE_AND_MOUNT, - IDPM_SELECT_DEVICE_AND_MOUNT, - IDM_SHOW_HIDE, - IDM_HOMEPAGE_SYSTRAY -}; - -enum -{ - TC_TBXID_LEGAL_NOTICES, - TC_TBXID_SYS_ENCRYPTION_PRETEST, - TC_TBXID_SYS_ENC_RESCUE_DISK, - TC_TBXID_DECOY_OS_INSTRUCTIONS -}; - -#define TC_MUTEX_NAME_SYSENC "Global\\TrueCrypt System Encryption Wizard" -#define TC_MUTEX_NAME_NONSYS_INPLACE_ENC "Global\\TrueCrypt In-Place Encryption Wizard" -#define TC_MUTEX_NAME_APP_SETUP "Global\\TrueCrypt Setup" -#define TC_MUTEX_NAME_DRIVER_SETUP "Global\\TrueCrypt Driver Setup" - -#define IDC_ABOUT 0x7fff /* ID for AboutBox on system menu in wm_user range */ - -#define EXCL_ACCESS_MAX_AUTO_RETRIES 500 -#define EXCL_ACCESS_AUTO_RETRY_DELAY 10 - -#define UNMOUNT_MAX_AUTO_RETRIES 10 -#define UNMOUNT_AUTO_RETRY_DELAY 50 - -// After the user receives the "Incorrect password" error this number of times in a row, we should automatically -// try using the embedded header backup (if any). This ensures that the "Incorrect password" message is reported faster -// initially (most such errors are really caused by supplying an incorrect password, not by header corruption). -#define TC_TRY_HEADER_BAK_AFTER_NBR_WRONG_PWD_TRIES 2 - -#define MAX_MULTI_CHOICES 10 /* Maximum number of options for mutliple-choice dialog */ - -#define TC_APPD_FILENAME_CONFIGURATION "Configuration.xml" -#define TC_APPD_FILENAME_SYSTEM_ENCRYPTION "System Encryption.xml" -#define TC_APPD_FILENAME_DEFAULT_KEYFILES "Default Keyfiles.xml" -#define TC_APPD_FILENAME_HISTORY "History.xml" -#define TC_APPD_FILENAME_FAVORITE_VOLUMES "Favorite Volumes.xml" -#define TC_APPD_FILENAME_NONSYS_INPLACE_ENC "In-Place Encryption" -#define TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE "In-Place Encryption Wipe Algo" -#define TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL "Post-Install Task - Tutorial" -#define TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES "Post-Install Task - Release Notes" - -#ifndef USER_DEFAULT_SCREEN_DPI -#define USER_DEFAULT_SCREEN_DPI 96 -#endif - -#if (USER_DEFAULT_SCREEN_DPI != 96) -# error Revision of GUI and graphics necessary, since everything assumes default screen DPI as 96 (note that 96 is the default on Windows 2000, XP, and Vista). -#endif - -enum -{ - TC_POST_INSTALL_CFG_REMOVE_ALL = 0, - TC_POST_INSTALL_CFG_TUTORIAL, - TC_POST_INSTALL_CFG_RELEASE_NOTES -}; - -typedef enum -{ - // IMPORTANT: If you add a new item here, update IsOSVersionAtLeast(). - - WIN_UNKNOWN = 0, - WIN_31, - WIN_95, - WIN_98, - WIN_ME, - WIN_NT3, - WIN_NT4, - WIN_2000, - WIN_XP, - WIN_XP64, - WIN_SERVER_2003, - WIN_VISTA, - WIN_SERVER_2008, - WIN_7 -} OSVersionEnum; - -extern char *LastDialogId; -extern char *ConfigBuffer; -extern char szHelpFile[TC_MAX_PATH]; -extern char szHelpFile2[TC_MAX_PATH]; -extern char SecurityTokenLibraryPath[TC_MAX_PATH]; -extern HFONT hFixedDigitFont; -extern HFONT hBoldFont; -extern HFONT hTitleFont; -extern HFONT hFixedFont; -extern HFONT hUserFont; -extern HFONT hUserUnderlineFont; -extern HFONT hUserBoldFont; -extern int ScreenDPI; -extern double DlgAspectRatio; -extern HWND MainDlg; -extern BOOL Silent; -extern BOOL bHistory; -extern BOOL bPreserveTimestamp; -extern BOOL bStartOnLogon; -extern BOOL bMountDevicesOnLogon; -extern BOOL bMountFavoritesOnLogon; -extern int HiddenSectorDetectionStatus; -extern wchar_t *lpszTitle; -extern OSVersionEnum nCurrentOS; -extern int CurrentOSMajor; -extern int CurrentOSMinor; -extern int CurrentOSServicePack; -extern BOOL RemoteSession; -extern HANDLE hDriver; -extern HINSTANCE hInst; -extern int SystemEncryptionStatus; -extern WipeAlgorithmId nWipeMode; -extern BOOL bSysPartitionSelected; -extern BOOL bSysDriveSelected; - -extern BOOL bHyperLinkBeingTracked; -extern BOOL bInPlaceEncNonSysPending; - -extern BOOL KeyFilesEnable; -extern KeyFile *FirstKeyFile; -extern KeyFilesDlgParam defaultKeyFilesParam; -extern BOOL UacElevated; -extern BOOL IgnoreWmDeviceChange; - - -enum tc_app_msg_ids -{ - /* WARNING: Changing these values or their meanings may cause incompatibility with other versions - (for example, if a new version of the TrueCrypt installer needed to shut down this version of - TrueCrypt during upgrade, it could fail or do something unwanted because the signal value would - be incorrect). When adding a new constant, verify that the value is unique within this block and - that it is less than WM_APP+16383. */ - - // Common (inter-app) - TC_APPMSG_CLOSE_BKG_TASK = WM_APP + 4, // Changing this value will prevent smooth upgrades from pre-5.x versions - TC_APPMSG_SYSENC_CONFIG_UPDATE = WM_APP + 101, - TC_APPMSG_TASKBAR_ICON = WM_APP + 102, - TC_APPMSG_LOAD_TEXT_BOX_CONTENT = WM_APP + 103, - // Mount - TC_APPMSG_MOUNT_ENABLE_DISABLE_CONTROLS = WM_APP + 201, - TC_APPMSG_MOUNT_SHOW_WINDOW = WM_APP + 202, - TC_APPMSG_PREBOOT_PASSWORD_MODE = WM_APP + 203, - TC_APPMSG_VOLUMES_DISMOUNTED_ON_POWER = WM_APP + 204, - // Format - TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED = WM_APP + 301, - TC_APPMSG_FORMAT_FINISHED = WM_APP + 302, - TC_APPMSG_FORMAT_USER_QUIT = WM_APP + 303, - TC_APPMSG_PERFORM_POST_WMINIT_TASKS = WM_APP + 304, - TC_APPMSG_PERFORM_POST_SYSENC_WMINIT_TASKS = WM_APP + 305, - TC_APPMSG_NONSYS_INPLACE_ENC_FINISHED = WM_APP + 306, - // Setup - TC_APPMSG_INSTALL_SUCCESS = WM_APP + 401, - TC_APPMSG_UNINSTALL_SUCCESS = WM_APP + 402, - TC_APPMSG_EXTRACTION_SUCCESS = WM_APP + 403, - TC_APPMSG_INSTALL_FAILURE = WM_APP + 404, - TC_APPMSG_UNINSTALL_FAILURE = WM_APP + 405, - TC_APPMSG_EXTRACTION_FAILURE = WM_APP + 406 -}; - -enum system_encryption_status -{ - /* WARNING: As these values are written to config files, if they or their meanings - are changed, incompatiblity with other versions may arise (upgrade, downgrade, etc.). - When adding a new constant, verify that the value is unique within this block. */ - SYSENC_STATUS_NONE = 0, - SYSENC_STATUS_PRETEST = 200, // This may also mean that the OS is to be (or has been) copied to a hidden volume (to create a hidden OS). - SYSENC_STATUS_ENCRYPTING = 400, - SYSENC_STATUS_DECRYPTING = 600 -}; - -enum vol_creation_wizard_modes -{ - WIZARD_MODE_FILE_CONTAINER = 0, - WIZARD_MODE_NONSYS_DEVICE, - WIZARD_MODE_SYS_DEVICE -}; - - -typedef struct -{ - BOOL VolumeIsOpen; - - CRYPTO_INFO *CryptoInfo; - BOOL IsDevice; - HANDLE HostFileHandle; - uint64 HostSize; - - BOOL TimestampsValid; - FILETIME CreationTime; - FILETIME LastWriteTime; - FILETIME LastAccessTime; - -} OpenVolumeContext; - - -#define DEFAULT_VOL_CREATION_WIZARD_MODE WIZARD_MODE_FILE_CONTAINER - -#define ICON_HAND MB_ICONHAND -#define YES_NO MB_YESNO - -#ifdef _UNICODE -#define WINMAIN wWinMain -#else -#define WINMAIN WinMain -#endif - -#define PRINT_TOOL "notepad" - -void cleanup ( void ); -void LowerCaseCopy ( char *lpszDest , const char *lpszSource ); -void UpperCaseCopy ( char *lpszDest , const char *lpszSource ); -void CreateFullVolumePath ( char *lpszDiskFile , const char *lpszFileName , BOOL *bDevice ); -int FakeDosNameForDevice ( const char *lpszDiskFile , char *lpszDosDevice , char *lpszCFDevice , BOOL bNameOnly ); -int RemoveFakeDosName ( char *lpszDiskFile , char *lpszDosDevice ); -void AbortProcess ( char *stringId ); -void AbortProcessSilent ( void ); -void *err_malloc ( size_t size ); -char *err_strdup ( char *lpszText ); -DWORD handleWin32Error ( HWND hwndDlg ); -BOOL IsDiskReadError (DWORD error); -BOOL IsDiskWriteError (DWORD error); -BOOL IsDiskError (DWORD error); -BOOL translateWin32Error ( wchar_t *lpszMsgBuf , int nWSizeOfBuf ); -BOOL CALLBACK AboutDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); -BOOL IsButtonChecked ( HWND hButton ); -void CheckButton ( HWND hButton ); -void LeftPadString (char *szTmp, int len, int targetLen, char filler); -void ToSBCS ( LPWSTR lpszText ); -void ToUNICODE ( char *lpszText ); -void InitDialog ( HWND hwndDlg ); -HDC CreateMemBitmap ( HINSTANCE hInstance , HWND hwnd , char *resource ); -HBITMAP RenderBitmap ( char *resource , HWND hwndDest , int x , int y , int nWidth , int nHeight , BOOL bDirectRender , BOOL bKeepAspectRatio); -LRESULT CALLBACK RedTick ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ); -BOOL RegisterRedTick ( HINSTANCE hInstance ); -BOOL UnregisterRedTick ( HINSTANCE hInstance ); -LRESULT CALLBACK SplashDlgProc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ); -void WaitCursor ( void ); -void NormalCursor ( void ); -void ArrowWaitCursor ( void ); -void HandCursor (); -void AddComboPair (HWND hComboBox, const char *lpszItem, int value); -void AddComboPairW (HWND hComboBox, const wchar_t *lpszItem, int value); -void SelectAlgo ( HWND hComboBox , int *nCipher ); -void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption); -wchar_t *GetWipeModeName (WipeAlgorithmId modeId); -wchar_t *GetPathType (const char *path, BOOL bUpperCase, BOOL *bIsPartition); -LRESULT CALLBACK CustomDlgProc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ); -BOOL TCCreateMutex (volatile HANDLE *hMutex, char *name); -void TCCloseMutex (volatile HANDLE *hMutex); -BOOL MutexExistsOnSystem (char *name); -BOOL CreateSysEncMutex (void); -BOOL InstanceHasSysEncMutex (void); -void CloseSysEncMutex (void); -BOOL CreateNonSysInplaceEncMutex (void); -BOOL InstanceHasNonSysInplaceEncMutex (void); -void CloseNonSysInplaceEncMutex (void); -BOOL NonSysInplaceEncInProgressElsewhere (void); -BOOL CreateDriverSetupMutex (void); -void CloseDriverSetupMutex (void); -BOOL CreateAppSetupMutex (void); -BOOL InstanceHasAppSetupMutex (void); -void CloseAppSetupMutex (void); -BOOL IsTrueCryptInstallerRunning (void); -BOOL LoadSysEncSettings (HWND hwndDlg); -int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm); -void RemoveNonSysInPlaceEncNotifications (void); -void SavePostInstallTasksSettings (int command); -void DoPostInstallTasks (void); -BOOL SysEncryptionOrDecryptionRequired (void); -void InitApp ( HINSTANCE hInstance, char *lpszCommandLine ); -void InitHelpFileName (void); -BOOL OpenDevice (const char *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem); -void NotifyDriverOfTravelerMode (void); -int GetAvailableFixedDisks ( HWND hComboBox , char *lpszRootPath ); -int GetAvailableRemovables ( HWND hComboBox , char *lpszRootPath ); -int IsSystemDevicePath (char *path, HWND hwndDlg, BOOL bReliableRequired); -BOOL CALLBACK RawDevicesDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); -BOOL TextInfoDialogBox (int nID); -BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -char * GetLegalNotices (); -BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -void UserEnrichRandomPool (HWND hwndDlg); -BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -BOOL CALLBACK MultiChoiceDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -int DriverAttach ( void ); -BOOL CALLBACK CipherTestDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); -void ResetCipherTest ( HWND hwndDlg , int idTestCipher ); -BOOL BrowseFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter); -BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, char *initialDir, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter); -BOOL BrowseDirectories (HWND hWnd, char *lpszTitle, char *dirName); -void handleError ( HWND hwndDlg , int code ); -void LocalizeDialog ( HWND hwnd, char *stringId ); -void OpenVolumeExplorerWindow (int driveNo); -static BOOL CALLBACK CloseVolumeExplorerWindowsEnum( HWND hwnd, LPARAM driveNo); -BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo); -BOOL CheckCapsLock (HWND hwnd, BOOL quiet); -BOOL CheckFileExtension (char *fileName); -void IncreaseWrongPwdRetryCount (int count); -void ResetWrongPwdRetryCount (void); -BOOL WrongPwdRetryCountOverLimit (void); -int GetFirstAvailableDrive (); -int GetLastAvailableDrive (); -BOOL IsDriveAvailable (int driveNo); -BOOL IsDeviceMounted (char *deviceName); -int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced); -void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap); -int MountVolume (HWND hwndDlg, int driveNo, char *volumePath, Password *password, BOOL cachePassword, BOOL sharedAccess, MountOptions *mountOptions, BOOL quiet, BOOL bReportWrongPassword); -BOOL UnmountVolume (HWND hwndDlg , int nDosDriveNo, BOOL forceUnmount); -BOOL IsPasswordCacheEmpty (void); -BOOL IsMountedVolume (const char *volname); -int GetMountedVolumeDriveNo (char *volname); -BOOL IsAdmin (void); -BOOL IsUacSupported (); -BOOL ResolveSymbolicLink (PWSTR symLinkName, PWSTR targetName); -int GetDiskDeviceDriveLetter (PWSTR deviceName); -int FileSystemAppearsEmpty (const char *devicePath); -__int64 GetStatsFreeSpaceOnPartition (const char *devicePath, float *percent, __int64 *occupiedBytes, BOOL silent); -__int64 GetDeviceSize (const char *devicePath); -HANDLE DismountDrive (char *devName, char *devicePath); -int64 FindString (const char *buf, const char *str, int64 bufLen, size_t strLen, int64 startOffset); -BOOL FileExists (const char *filePathPtr); -__int64 FindStringInFile (const char *filePath, const char *str, int strLen); -BOOL TCCopyFile (char *sourceFileName, char *destinationFile); -BOOL SaveBufferToFile (char *inputBuffer, char *destinationFile, DWORD inputLength, BOOL bAppend); -BOOL TCFlushFile (FILE *f); -BOOL PrintHardCopyTextUTF16 (wchar_t *text, char *title, int byteLen); -void GetSpeedString (unsigned __int64 speed, wchar_t *str); -BOOL IsNonInstallMode (); -BOOL DriverUnload (); -LRESULT SetCheckBox (HWND hwndDlg, int dlgItem, BOOL state); -BOOL GetCheckBox (HWND hwndDlg, int dlgItem); -void ManageStartupSeq (void); -void ManageStartupSeqWiz (BOOL bRemove, const char *arg); -void CleanLastVisitedMRU (void); -void ClearHistory (HWND hwndDlgItem); -LRESULT ListItemAdd (HWND list, int index, char *string); -LRESULT ListItemAddW (HWND list, int index, wchar_t *string); -LRESULT ListSubItemSet (HWND list, int index, int subIndex, char *string); -LRESULT ListSubItemSetW (HWND list, int index, int subIndex, wchar_t *string); -BOOL GetMountList (MOUNT_LIST_STRUCT *list); -int GetDriverRefCount (); -void GetSizeString (unsigned __int64 size, wchar_t *str); -__int64 GetFileSize64 (const char *path); -BOOL LoadInt16 (char *filePath, int *result, __int64 fileOffset); -BOOL LoadInt32 (char *filePath, unsigned __int32 *result, __int64 fileOffset); -char *LoadFile (const char *fileName, DWORD *size); -char *LoadFileBlock (char *fileName, __int64 fileOffset, int count); -char *GetModPath (char *path, int maxSize); -char *GetConfigPath (char *fileName); -char GetSystemDriveLetter (void); -void OpenPageHelp (HWND hwndDlg, int nPage); -int Info (char *stringId); -int InfoTopMost (char *stringId); -int InfoDirect (const wchar_t *msg); -int Warning (char *stringId); -int WarningTopMost (char *stringId); -int WarningDirect (const wchar_t *warnMsg); -int Error (char *stringId); -int ErrorDirect (const wchar_t *errMsg); -int ErrorTopMost (char *stringId); -int AskYesNo (char *stringId); -int AskNoYes (char *stringId); -int AskOkCancel (char *stringId); -int AskWarnYesNo (char *stringId); -int AskWarnNoYes (char *stringId); -int AskWarnNoYesString (wchar_t *string); -int AskWarnYesNoString (wchar_t *string); -int AskWarnOkCancel (char *stringId); -int AskWarnCancelOk (char *stringId); -int AskErrYesNo (char *stringId); -int AskErrNoYes (char *stringId); -int AskMultiChoice (void *strings[], BOOL bBold); -BOOL ConfigWriteBegin (); -BOOL ConfigWriteEnd (); -BOOL ConfigWriteString (char *configKey, char *configValue); -BOOL ConfigWriteInt (char *configKey, int configValue); -int ConfigReadInt (char *configKey, int defaultValue); -char *ConfigReadString (char *configKey, char *defaultValue, char *str, int maxLen); -void RestoreDefaultKeyFilesParam (void); -BOOL LoadDefaultKeyFilesParam (void); -void Debug (char *format, ...); -void DebugMsgBox (char *format, ...); -BOOL IsOSAtLeast (OSVersionEnum reqMinOS); -BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack); -BOOL Is64BitOs (); -BOOL IsHiddenOSRunning (void); -BOOL RestartComputer (void); -void Applink (char *dest, BOOL bSendOS, char *extraOutput); -char *RelativePath2Absolute (char *szFileName); -void HandleDriveNotReadyError (); -BOOL CALLBACK CloseTCWindowsEnum( HWND hwnd, LPARAM lParam); -BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam); -BYTE *MapResource (char *resourceType, int resourceId, PDWORD size); -void InconsistencyResolved (char *msg); -void ReportUnexpectedState (char *techInfo); -BOOL SelectMultipleFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory); -BOOL SelectMultipleFilesNext (char *lpszFileName); -void OpenOnlineHelp (); -BOOL GetPartitionInfo (const char *deviceName, PPARTITION_INFORMATION rpartInfo); -BOOL GetDeviceInfo (const char *deviceName, DISK_PARTITION_INFO_STRUCT *info); -BOOL GetDriveGeometry (const char *deviceName, PDISK_GEOMETRY diskGeometry); -BOOL IsVolumeDeviceHosted (char *lpszDiskFile); -int CompensateXDPI (int val); -int CompensateYDPI (int val); -int CompensateDPIFont (int val); -int GetTextGfxWidth (HWND hwndDlgItem, wchar_t *text, HFONT hFont); -int GetTextGfxHeight (HWND hwndDlgItem, wchar_t *text, HFONT hFont); -BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId); -void ToBootPwdField (HWND hwndDlg, UINT ctrlId); -void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate); -BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize); -BOOL DoDriverInstall (HWND hwndDlg); -int OpenVolume (OpenVolumeContext *context, const char *volumePath, Password *password, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader); -void CloseVolume (OpenVolumeContext *context); -int ReEncryptVolumeHeader (char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, BOOL wipeMode); -BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); -BOOL IsPagingFileWildcardActive (); -BOOL DisablePagingFile (); -BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -BOOL InitSecurityTokenLibrary (); -BOOL FileHasReadOnlyAttribute (const char *path); -BOOL IsFileOnReadOnlyFilesystem (const char *path); -void CheckFilesystem (int driveNo, BOOL fixErrors); -BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str); -int AskNonSysInPlaceEncryptionResume (); -BOOL RemoveDeviceWriteProtection (HWND hwndDlg, char *devicePath); -void EnableElevatedCursorChange (HWND parent); - -#ifdef __cplusplus -} - -#include -#include - -struct HostDevice -{ - HostDevice () - : - ContainsSystem (false), - DynamicVolume (false), - Floppy (false), - IsPartition (false), - IsVirtualPartition (false), - HasUnencryptedFilesystem (false), - Removable (false), - Size (0) - { - } - - ~HostDevice () { } - - bool ContainsSystem; - bool DynamicVolume; - bool Floppy; - bool IsPartition; - bool IsVirtualPartition; - bool HasUnencryptedFilesystem; - std::string MountPoint; - std::wstring Name; - std::string Path; - bool Removable; - uint64 Size; - uint32 SystemNumber; - - std::vector Partitions; -}; - -std::wstring SingleStringToWide (const std::string &singleString); -std::wstring Utf8StringToWide (const std::string &utf8String); -std::string WideToSingleString (const std::wstring &wideString); -std::string WideToUtf8String (const std::wstring &wideString); -std::vector GetAvailableHostDevices (bool noDeviceProperties = false, bool singleList = false, bool noFloppy = true, bool detectUnencryptedFilesystems = false); -std::string ToUpperCase (const std::string &str); -std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg); -std::string GetWindowsEdition (); - -#endif // __cplusplus - -#endif // TC_HEADER_DLGCODE +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_DLGCODE +#define TC_HEADER_DLGCODE + +#include "Common.h" +#include "Apidrvr.h" +#include "Keyfiles.h" +#include "Wipe.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* IDs for dynamically generated GUI elements */ +enum dynamic_gui_element_ids +{ + IDPM_CHECK_FILESYS = 500001, + IDPM_REPAIR_FILESYS, + IDPM_OPEN_VOLUME, + IDPM_SELECT_FILE_AND_MOUNT, + IDPM_SELECT_DEVICE_AND_MOUNT, + IDM_SHOW_HIDE, + IDM_HOMEPAGE_SYSTRAY +}; + +enum +{ + TC_TBXID_LEGAL_NOTICES, + TC_TBXID_SYS_ENCRYPTION_PRETEST, + TC_TBXID_SYS_ENC_RESCUE_DISK, + TC_TBXID_DECOY_OS_INSTRUCTIONS, + TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS +}; + +#define TC_APPLICATION_ID L"TrueCryptFoundation.TrueCrypt" + +#define TC_MUTEX_NAME_SYSENC "Global\\TrueCrypt System Encryption Wizard" +#define TC_MUTEX_NAME_NONSYS_INPLACE_ENC "Global\\TrueCrypt In-Place Encryption Wizard" +#define TC_MUTEX_NAME_APP_SETUP "Global\\TrueCrypt Setup" +#define TC_MUTEX_NAME_DRIVER_SETUP "Global\\TrueCrypt Driver Setup" + +#define IDC_ABOUT 0x7fff /* ID for AboutBox on system menu in wm_user range */ + +#define EXCL_ACCESS_MAX_AUTO_RETRIES 500 +#define EXCL_ACCESS_AUTO_RETRY_DELAY 10 + +#define UNMOUNT_MAX_AUTO_RETRIES 10 +#define UNMOUNT_AUTO_RETRY_DELAY 50 + +// After the user receives the "Incorrect password" error this number of times in a row, we should automatically +// try using the embedded header backup (if any). This ensures that the "Incorrect password" message is reported faster +// initially (most such errors are really caused by supplying an incorrect password, not by header corruption). +#define TC_TRY_HEADER_BAK_AFTER_NBR_WRONG_PWD_TRIES 2 + +#define MAX_MULTI_CHOICES 10 /* Maximum number of options for mutliple-choice dialog */ + +#define TC_APPD_FILENAME_CONFIGURATION "Configuration.xml" +#define TC_APPD_FILENAME_SYSTEM_ENCRYPTION "System Encryption.xml" +#define TC_APPD_FILENAME_DEFAULT_KEYFILES "Default Keyfiles.xml" +#define TC_APPD_FILENAME_HISTORY "History.xml" +#define TC_APPD_FILENAME_FAVORITE_VOLUMES "Favorite Volumes.xml" +#define TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES "System Favorite Volumes.xml" +#define TC_APPD_FILENAME_NONSYS_INPLACE_ENC "In-Place Encryption" +#define TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE "In-Place Encryption Wipe Algo" +#define TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL "Post-Install Task - Tutorial" +#define TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES "Post-Install Task - Release Notes" + +#ifndef USER_DEFAULT_SCREEN_DPI +#define USER_DEFAULT_SCREEN_DPI 96 +#endif + +#if (USER_DEFAULT_SCREEN_DPI != 96) +# error Revision of GUI and graphics necessary, since everything assumes default screen DPI as 96 (note that 96 is the default on Windows 2000, XP, and Vista). +#endif + +enum +{ + TC_POST_INSTALL_CFG_REMOVE_ALL = 0, + TC_POST_INSTALL_CFG_TUTORIAL, + TC_POST_INSTALL_CFG_RELEASE_NOTES +}; + +extern char *LastDialogId; +extern char *ConfigBuffer; +extern char szHelpFile[TC_MAX_PATH]; +extern char szHelpFile2[TC_MAX_PATH]; +extern char SecurityTokenLibraryPath[TC_MAX_PATH]; +extern HFONT hFixedDigitFont; +extern HFONT hBoldFont; +extern HFONT hTitleFont; +extern HFONT hFixedFont; +extern HFONT hUserFont; +extern HFONT hUserUnderlineFont; +extern HFONT hUserBoldFont; +extern HFONT WindowTitleBarFont; +extern int ScreenDPI; +extern double DlgAspectRatio; +extern HWND MainDlg; +extern BOOL Silent; +extern BOOL bHistory; +extern BOOL bPreserveTimestamp; +extern BOOL bStartOnLogon; +extern BOOL bMountDevicesOnLogon; +extern BOOL bMountFavoritesOnLogon; +extern int HiddenSectorDetectionStatus; +extern wchar_t *lpszTitle; +extern OSVersionEnum nCurrentOS; +extern int CurrentOSMajor; +extern int CurrentOSMinor; +extern int CurrentOSServicePack; +extern BOOL RemoteSession; +extern HANDLE hDriver; +extern HINSTANCE hInst; +extern int SystemEncryptionStatus; +extern WipeAlgorithmId nWipeMode; +extern BOOL bSysPartitionSelected; +extern BOOL bSysDriveSelected; + +extern BOOL bHyperLinkBeingTracked; +extern BOOL bInPlaceEncNonSysPending; + +extern BOOL KeyFilesEnable; +extern KeyFile *FirstKeyFile; +extern KeyFilesDlgParam defaultKeyFilesParam; +extern BOOL UacElevated; +extern BOOL IgnoreWmDeviceChange; +extern BOOL DeviceChangeBroadcastDisabled; +extern BOOL LastMountedVolumeDirty; +extern BOOL MountVolumesAsSystemFavorite; + + +enum tc_app_msg_ids +{ + /* WARNING: Changing these values or their meanings may cause incompatibility with other versions + (for example, if a new version of the TrueCrypt installer needed to shut down this version of + TrueCrypt during upgrade, it could fail or do something unwanted because the signal value would + be incorrect). When adding a new constant, verify that the value is unique within this block and + that it is less than WM_APP+16383. */ + + // Common (inter-app) + TC_APPMSG_CLOSE_BKG_TASK = WM_APP + 4, // Changing this value will prevent smooth upgrades from pre-5.x versions + TC_APPMSG_SYSENC_CONFIG_UPDATE = WM_APP + 101, + TC_APPMSG_TASKBAR_ICON = WM_APP + 102, + TC_APPMSG_LOAD_TEXT_BOX_CONTENT = WM_APP + 103, + // Mount + TC_APPMSG_MOUNT_ENABLE_DISABLE_CONTROLS = WM_APP + 201, + TC_APPMSG_MOUNT_SHOW_WINDOW = WM_APP + 202, + TC_APPMSG_PREBOOT_PASSWORD_MODE = WM_APP + 203, + // Format + TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED = WM_APP + 301, + TC_APPMSG_FORMAT_FINISHED = WM_APP + 302, + TC_APPMSG_FORMAT_USER_QUIT = WM_APP + 303, + TC_APPMSG_PERFORM_POST_WMINIT_TASKS = WM_APP + 304, + TC_APPMSG_PERFORM_POST_SYSENC_WMINIT_TASKS = WM_APP + 305, + TC_APPMSG_NONSYS_INPLACE_ENC_FINISHED = WM_APP + 306, + // Setup + TC_APPMSG_INSTALL_SUCCESS = WM_APP + 401, + TC_APPMSG_UNINSTALL_SUCCESS = WM_APP + 402, + TC_APPMSG_EXTRACTION_SUCCESS = WM_APP + 403, + TC_APPMSG_INSTALL_FAILURE = WM_APP + 404, + TC_APPMSG_UNINSTALL_FAILURE = WM_APP + 405, + TC_APPMSG_EXTRACTION_FAILURE = WM_APP + 406 +}; + +enum system_encryption_status +{ + /* WARNING: As these values are written to config files, if they or their meanings + are changed, incompatiblity with other versions may arise (upgrade, downgrade, etc.). + When adding a new constant, verify that the value is unique within this block. */ + SYSENC_STATUS_NONE = 0, + SYSENC_STATUS_PRETEST = 200, // This may also mean that the OS is to be (or has been) copied to a hidden volume (to create a hidden OS). + SYSENC_STATUS_ENCRYPTING = 400, + SYSENC_STATUS_DECRYPTING = 600 +}; + +enum vol_creation_wizard_modes +{ + WIZARD_MODE_FILE_CONTAINER = 0, + WIZARD_MODE_NONSYS_DEVICE, + WIZARD_MODE_SYS_DEVICE +}; + + +typedef struct +{ + BOOL VolumeIsOpen; + + CRYPTO_INFO *CryptoInfo; + BOOL IsDevice; + HANDLE HostFileHandle; + uint64 HostSize; + + BOOL TimestampsValid; + FILETIME CreationTime; + FILETIME LastWriteTime; + FILETIME LastAccessTime; + +} OpenVolumeContext; + + +#define DEFAULT_VOL_CREATION_WIZARD_MODE WIZARD_MODE_FILE_CONTAINER + +#define ICON_HAND MB_ICONHAND +#define YES_NO MB_YESNO + +#define ISO_BURNER_TOOL "isoburn.exe" +#define PRINT_TOOL "notepad" + +void cleanup ( void ); +void LowerCaseCopy ( char *lpszDest , const char *lpszSource ); +void UpperCaseCopy ( char *lpszDest , const char *lpszSource ); +void CreateFullVolumePath ( char *lpszDiskFile , const char *lpszFileName , BOOL *bDevice ); +int FakeDosNameForDevice ( const char *lpszDiskFile , char *lpszDosDevice , char *lpszCFDevice , BOOL bNameOnly ); +int RemoveFakeDosName ( char *lpszDiskFile , char *lpszDosDevice ); +void AbortProcess ( char *stringId ); +void AbortProcessSilent ( void ); +void *err_malloc ( size_t size ); +char *err_strdup ( char *lpszText ); +DWORD handleWin32Error ( HWND hwndDlg ); +BOOL IsDiskReadError (DWORD error); +BOOL IsDiskWriteError (DWORD error); +BOOL IsDiskError (DWORD error); +BOOL translateWin32Error ( wchar_t *lpszMsgBuf , int nWSizeOfBuf ); +BOOL CALLBACK AboutDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); +BOOL IsButtonChecked ( HWND hButton ); +void CheckButton ( HWND hButton ); +void LeftPadString (char *szTmp, int len, int targetLen, char filler); +void ToSBCS ( LPWSTR lpszText ); +void ToUNICODE ( char *lpszText ); +void InitDialog ( HWND hwndDlg ); +HDC CreateMemBitmap ( HINSTANCE hInstance , HWND hwnd , char *resource ); +HBITMAP RenderBitmap ( char *resource , HWND hwndDest , int x , int y , int nWidth , int nHeight , BOOL bDirectRender , BOOL bKeepAspectRatio); +LRESULT CALLBACK RedTick ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ); +BOOL RegisterRedTick ( HINSTANCE hInstance ); +BOOL UnregisterRedTick ( HINSTANCE hInstance ); +LRESULT CALLBACK SplashDlgProc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ); +void WaitCursor ( void ); +void NormalCursor ( void ); +void ArrowWaitCursor ( void ); +void HandCursor (); +void AddComboPair (HWND hComboBox, const char *lpszItem, int value); +void AddComboPairW (HWND hComboBox, const wchar_t *lpszItem, int value); +void SelectAlgo ( HWND hComboBox , int *nCipher ); +void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption); +wchar_t *GetWipeModeName (WipeAlgorithmId modeId); +wchar_t *GetPathType (const char *path, BOOL bUpperCase, BOOL *bIsPartition); +LRESULT CALLBACK CustomDlgProc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ); +BOOL TCCreateMutex (volatile HANDLE *hMutex, char *name); +void TCCloseMutex (volatile HANDLE *hMutex); +BOOL MutexExistsOnSystem (char *name); +BOOL CreateSysEncMutex (void); +BOOL InstanceHasSysEncMutex (void); +void CloseSysEncMutex (void); +BOOL CreateNonSysInplaceEncMutex (void); +BOOL InstanceHasNonSysInplaceEncMutex (void); +void CloseNonSysInplaceEncMutex (void); +BOOL NonSysInplaceEncInProgressElsewhere (void); +BOOL CreateDriverSetupMutex (void); +void CloseDriverSetupMutex (void); +BOOL CreateAppSetupMutex (void); +BOOL InstanceHasAppSetupMutex (void); +void CloseAppSetupMutex (void); +BOOL IsTrueCryptInstallerRunning (void); +BOOL LoadSysEncSettings (HWND hwndDlg); +int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm); +void RemoveNonSysInPlaceEncNotifications (void); +void SavePostInstallTasksSettings (int command); +void DoPostInstallTasks (void); +void InitApp ( HINSTANCE hInstance, char *lpszCommandLine ); +void InitHelpFileName (void); +BOOL OpenDevice (const char *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem); +void NotifyDriverOfPortableMode (void); +int GetAvailableFixedDisks ( HWND hComboBox , char *lpszRootPath ); +int GetAvailableRemovables ( HWND hComboBox , char *lpszRootPath ); +int IsSystemDevicePath (char *path, HWND hwndDlg, BOOL bReliableRequired); +BOOL CALLBACK RawDevicesDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); +BOOL TextInfoDialogBox (int nID); +BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +char * GetLegalNotices (); +BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +void UserEnrichRandomPool (HWND hwndDlg); +BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK MultiChoiceDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +int DriverAttach ( void ); +BOOL CALLBACK CipherTestDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); +void ResetCipherTest ( HWND hwndDlg , int idTestCipher ); +void ResetCurrentDirectory (); +BOOL BrowseFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter); +BOOL BrowseDirectories (HWND hWnd, char *lpszTitle, char *dirName); +void handleError ( HWND hwndDlg , int code ); +void LocalizeDialog ( HWND hwnd, char *stringId ); +void OpenVolumeExplorerWindow (int driveNo); +static BOOL CALLBACK CloseVolumeExplorerWindowsEnum( HWND hwnd, LPARAM driveNo); +BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo); +BOOL CheckCapsLock (HWND hwnd, BOOL quiet); +BOOL CheckFileExtension (char *fileName); +void IncreaseWrongPwdRetryCount (int count); +void ResetWrongPwdRetryCount (void); +BOOL WrongPwdRetryCountOverLimit (void); +int GetFirstAvailableDrive (); +int GetLastAvailableDrive (); +BOOL IsDriveAvailable (int driveNo); +BOOL IsDeviceMounted (char *deviceName); +int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced); +void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap); +int MountVolume (HWND hwndDlg, int driveNo, char *volumePath, Password *password, BOOL cachePassword, BOOL sharedAccess, MountOptions *mountOptions, BOOL quiet, BOOL bReportWrongPassword); +BOOL UnmountVolume (HWND hwndDlg , int nDosDriveNo, BOOL forceUnmount); +BOOL IsPasswordCacheEmpty (void); +BOOL IsMountedVolume (const char *volname); +int GetMountedVolumeDriveNo (char *volname); +BOOL IsAdmin (void); +BOOL IsBuiltInAdmin (); +BOOL IsUacSupported (); +BOOL ResolveSymbolicLink (const wchar_t *symLinkName, PWSTR targetName); +int GetDiskDeviceDriveLetter (PWSTR deviceName); +int FileSystemAppearsEmpty (const char *devicePath); +__int64 GetStatsFreeSpaceOnPartition (const char *devicePath, float *percent, __int64 *occupiedBytes, BOOL silent); +__int64 GetDeviceSize (const char *devicePath); +HANDLE DismountDrive (char *devName, char *devicePath); +int64 FindString (const char *buf, const char *str, int64 bufLen, size_t strLen, int64 startOffset); +BOOL FileExists (const char *filePathPtr); +__int64 FindStringInFile (const char *filePath, const char *str, int strLen); +BOOL TCCopyFile (char *sourceFileName, char *destinationFile); +BOOL SaveBufferToFile (char *inputBuffer, char *destinationFile, DWORD inputLength, BOOL bAppend); +BOOL TCFlushFile (FILE *f); +BOOL PrintHardCopyTextUTF16 (wchar_t *text, char *title, int byteLen); +void GetSpeedString (unsigned __int64 speed, wchar_t *str); +BOOL IsNonInstallMode (); +BOOL DriverUnload (); +LRESULT SetCheckBox (HWND hwndDlg, int dlgItem, BOOL state); +BOOL GetCheckBox (HWND hwndDlg, int dlgItem); +void ManageStartupSeq (void); +void ManageStartupSeqWiz (BOOL bRemove, const char *arg); +void CleanLastVisitedMRU (void); +void ClearHistory (HWND hwndDlgItem); +LRESULT ListItemAdd (HWND list, int index, char *string); +LRESULT ListItemAddW (HWND list, int index, wchar_t *string); +LRESULT ListSubItemSet (HWND list, int index, int subIndex, char *string); +LRESULT ListSubItemSetW (HWND list, int index, int subIndex, wchar_t *string); +BOOL GetMountList (MOUNT_LIST_STRUCT *list); +int GetDriverRefCount (); +void GetSizeString (unsigned __int64 size, wchar_t *str); +__int64 GetFileSize64 (const char *path); +BOOL LoadInt16 (char *filePath, int *result, __int64 fileOffset); +BOOL LoadInt32 (char *filePath, unsigned __int32 *result, __int64 fileOffset); +char *LoadFile (const char *fileName, DWORD *size); +char *LoadFileBlock (char *fileName, __int64 fileOffset, size_t count); +char *GetModPath (char *path, int maxSize); +char *GetConfigPath (char *fileName); +char *GetProgramConfigPath (char *fileName); +char GetSystemDriveLetter (void); +void OpenPageHelp (HWND hwndDlg, int nPage); +int Info (char *stringId); +int InfoTopMost (char *stringId); +int InfoDirect (const wchar_t *msg); +int Warning (char *stringId); +int WarningTopMost (char *stringId); +int WarningDirect (const wchar_t *warnMsg); +int Error (char *stringId); +int ErrorDirect (const wchar_t *errMsg); +int ErrorTopMost (char *stringId); +int AskYesNo (char *stringId); +int AskYesNoString (const wchar_t *str); +int AskNoYes (char *stringId); +int AskOkCancel (char *stringId); +int AskWarnYesNo (char *stringId); +int AskWarnNoYes (char *stringId); +int AskWarnNoYesString (const wchar_t *string); +int AskWarnYesNoString (const wchar_t *string); +int AskWarnOkCancel (char *stringId); +int AskWarnCancelOk (char *stringId); +int AskErrYesNo (char *stringId); +int AskErrNoYes (char *stringId); +int AskMultiChoice (void *strings[], BOOL bBold); +BOOL ConfigWriteBegin (); +BOOL ConfigWriteEnd (); +BOOL ConfigWriteString (char *configKey, char *configValue); +BOOL ConfigWriteInt (char *configKey, int configValue); +int ConfigReadInt (char *configKey, int defaultValue); +char *ConfigReadString (char *configKey, char *defaultValue, char *str, int maxLen); +void RestoreDefaultKeyFilesParam (void); +BOOL LoadDefaultKeyFilesParam (void); +void Debug (char *format, ...); +void DebugMsgBox (char *format, ...); +BOOL IsOSAtLeast (OSVersionEnum reqMinOS); +BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack); +BOOL Is64BitOs (); +BOOL IsServerOS (); +BOOL IsHiddenOSRunning (void); +BOOL RestartComputer (void); +void Applink (char *dest, BOOL bSendOS, char *extraOutput); +char *RelativePath2Absolute (char *szFileName); +void HandleDriveNotReadyError (); +BOOL CALLBACK CloseTCWindowsEnum( HWND hwnd, LPARAM lParam); +BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam); +BYTE *MapResource (char *resourceType, int resourceId, PDWORD size); +void InconsistencyResolved (char *msg); +void ReportUnexpectedState (char *techInfo); +BOOL SelectMultipleFiles (HWND hwndDlg, char *stringId, char *lpszFileName, BOOL keepHistory); +BOOL SelectMultipleFilesNext (char *lpszFileName); +void OpenOnlineHelp (); +BOOL GetPartitionInfo (const char *deviceName, PPARTITION_INFORMATION rpartInfo); +BOOL GetDeviceInfo (const char *deviceName, DISK_PARTITION_INFO_STRUCT *info); +BOOL GetDriveGeometry (const char *deviceName, PDISK_GEOMETRY diskGeometry); +BOOL IsVolumeDeviceHosted (char *lpszDiskFile); +int CompensateXDPI (int val); +int CompensateYDPI (int val); +int CompensateDPIFont (int val); +int GetTextGfxWidth (HWND hwndDlgItem, const wchar_t *text, HFONT hFont); +int GetTextGfxHeight (HWND hwndDlgItem, const wchar_t *text, HFONT hFont); +BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId); +void ToBootPwdField (HWND hwndDlg, UINT ctrlId); +void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate); +BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize); +BOOL DoDriverInstall (HWND hwndDlg); +int OpenVolume (OpenVolumeContext *context, const char *volumePath, Password *password, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader); +void CloseVolume (OpenVolumeContext *context); +int ReEncryptVolumeHeader (char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, BOOL wipeMode); +BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); +BOOL IsPagingFileWildcardActive (); +BOOL DisablePagingFile (); +BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL InitSecurityTokenLibrary (); +BOOL FileHasReadOnlyAttribute (const char *path); +BOOL IsFileOnReadOnlyFilesystem (const char *path); +void CheckFilesystem (int driveNo, BOOL fixErrors); +BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str); +int AskNonSysInPlaceEncryptionResume (); +BOOL RemoveDeviceWriteProtection (HWND hwndDlg, char *devicePath); +void EnableElevatedCursorChange (HWND parent); +BOOL DisableFileCompression (HANDLE file); +BOOL VolumePathExists (char *volumePath); +BOOL IsWindowsIsoBurnerAvailable (); +BOOL LaunchWindowsIsoBurner (HWND hwnd, const char *isoPath); + +#ifdef __cplusplus +} + +#include +#include + +struct HostDevice +{ + HostDevice () + : + ContainsSystem (false), + DynamicVolume (false), + Floppy (false), + IsPartition (false), + IsVirtualPartition (false), + HasUnencryptedFilesystem (false), + Removable (false), + Size (0) + { + } + + ~HostDevice () { } + + bool ContainsSystem; + bool DynamicVolume; + bool Floppy; + bool IsPartition; + bool IsVirtualPartition; + bool HasUnencryptedFilesystem; + std::string MountPoint; + std::wstring Name; + std::string Path; + bool Removable; + uint64 Size; + uint32 SystemNumber; + + std::vector Partitions; +}; + +BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, char *initialDir, char *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName = NULL, const wchar_t *defaultExtension = NULL); +std::wstring SingleStringToWide (const std::string &singleString); +std::wstring Utf8StringToWide (const std::string &utf8String); +std::string WideToSingleString (const std::wstring &wideString); +std::string WideToUtf8String (const std::wstring &wideString); +std::vector GetAvailableHostDevices (bool noDeviceProperties = false, bool singleList = false, bool noFloppy = true, bool detectUnencryptedFilesystems = false); +std::string ToUpperCase (const std::string &str); +std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg); +std::string GetWindowsEdition (); +std::string FitPathInGfxWidth (HWND hwnd, HFONT hFont, LONG width, const std::string &path); + +#endif // __cplusplus + +#endif // TC_HEADER_DLGCODE diff --git a/Common/Dictionary.c b/Common/Dictionary.c index d610898..cb3273c 100644 --- a/Common/Dictionary.c +++ b/Common/Dictionary.c @@ -1,107 +1,80 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "../Common/Dictionary.h" -#include - -static DictionaryEntry StringDictionary[4096]; -static int LastDictionaryEntry = -1; -static int MaxDictionaryEntry = sizeof (StringDictionary) / sizeof (DictionaryEntry) - 1; - -static void *DataPool = NULL; -static size_t DataPoolSize = 0; - -int AddDictionaryEntry (char *key, int intKey, void *value) -{ - int i; - if (LastDictionaryEntry >= MaxDictionaryEntry) return -1; - - // Replace identical key if it exists - for (i = 0; i <= LastDictionaryEntry; i++) - { - if ((StringDictionary[i].Key != NULL - && key != NULL - && strcmp (StringDictionary[i].Key, key) == 0) - || (key == NULL && StringDictionary[i].IntKey == intKey)) - { - StringDictionary[i].Key = key; - StringDictionary[i].IntKey = intKey; - StringDictionary[i].Value = value; - - return i; - } - } - - LastDictionaryEntry++; - - StringDictionary[LastDictionaryEntry].Key = key; - StringDictionary[LastDictionaryEntry].IntKey = intKey; - StringDictionary[LastDictionaryEntry].Value = value; - - return LastDictionaryEntry; -} - - -void *GetDictionaryValue (const char *key) -{ - int i; - for (i = 0; i <= LastDictionaryEntry; i++) - { - if (StringDictionary[i].Key != NULL - && strcmp (StringDictionary[i].Key, key) == 0) - return StringDictionary[i].Value; - } - - return NULL; -} - - -void *GetDictionaryValueByInt (int intKey) -{ - int i; - for (i = 0; i <= LastDictionaryEntry; i++) - { - if (StringDictionary[i].IntKey == intKey) - return StringDictionary[i].Value; - } - - return NULL; -} - - -void *AddPoolData (void *data, size_t dataSize) -{ - - if (DataPoolSize + dataSize > DATA_POOL_CAPACITY) return NULL; - - if (DataPool == NULL) - { - DataPool = malloc (DATA_POOL_CAPACITY); - if (DataPool == NULL) return NULL; - } - - memcpy ((BYTE *)DataPool + DataPoolSize, data, dataSize); - - //if (wcschr((WCHAR *)((BYTE *)DataPool + DataPoolSize), '%') == 0) - // _wcsupr ((WCHAR *)((BYTE *)DataPool + DataPoolSize)); - //else - // ((WCHAR *)((BYTE *)DataPool + DataPoolSize))[0] = L'*'; - - // Ensure 32-bit alignment for next entries - dataSize = (dataSize + 3) & (~(size_t)3); - - DataPoolSize += dataSize; - return (BYTE *)DataPool + DataPoolSize - dataSize; -} - - -void ClearDictionaryPool () -{ - DataPoolSize = 0; - LastDictionaryEntry = -1; +/* + Copyright (c) 2005-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "../Common/Dictionary.h" +#include +#include +#include + +using namespace std; + +static map StringKeyMap; +static map IntKeyMap; + +static void *DataPool = NULL; +static size_t DataPoolSize = 0; + + +void AddDictionaryEntry (char *key, int intKey, void *value) +{ + if (key) + StringKeyMap[key] = value; + + if (intKey != 0) + IntKeyMap[intKey] = value; +} + + +void *GetDictionaryValue (const char *key) +{ + map ::const_iterator i = StringKeyMap.find (key); + + if (i == StringKeyMap.end()) + return NULL; + + return i->second; +} + + +void *GetDictionaryValueByInt (int intKey) +{ + map ::const_iterator i = IntKeyMap.find (intKey); + + if (i == IntKeyMap.end()) + return NULL; + + return i->second; +} + + +void *AddPoolData (void *data, size_t dataSize) +{ + if (DataPoolSize + dataSize > DATA_POOL_CAPACITY) return NULL; + + if (DataPool == NULL) + { + DataPool = malloc (DATA_POOL_CAPACITY); + if (DataPool == NULL) return NULL; + } + + memcpy ((BYTE *)DataPool + DataPoolSize, data, dataSize); + + // Ensure 32-bit alignment for next entries + dataSize = (dataSize + 3) & (~(size_t)3); + + DataPoolSize += dataSize; + return (BYTE *)DataPool + DataPoolSize - dataSize; +} + + +void ClearDictionaryPool () +{ + DataPoolSize = 0; + StringKeyMap.clear(); + IntKeyMap.clear(); } \ No newline at end of file diff --git a/Common/Dictionary.h b/Common/Dictionary.h index 094107c..e576de9 100644 --- a/Common/Dictionary.h +++ b/Common/Dictionary.h @@ -1,37 +1,30 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef DICTIONARY_H -#define DICTIONARY_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define DATA_POOL_CAPACITY 1000000 - -typedef struct -{ - char *Key; - int IntKey; - void *Value; -} DictionaryEntry; - -int AddDictionaryEntry (char *key, int intKey, void *value); -void *GetDictionaryValue (const char *key); -void *GetDictionaryValueByInt (int intKey); -void *AddPoolData (void *data, size_t dataSize); -void ClearDictionaryPool (); - -#ifdef __cplusplus -} -#endif - -#endif +/* + Copyright (c) 2005-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef DICTIONARY_H +#define DICTIONARY_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DATA_POOL_CAPACITY 1000000 + +void AddDictionaryEntry (char *key, int intKey, void *value); +void *GetDictionaryValue (const char *key); +void *GetDictionaryValueByInt (int intKey); +void *AddPoolData (void *data, size_t dataSize); +void ClearDictionaryPool (); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Common/ENDIAN.C b/Common/ENDIAN.C index 6659548..66c0f3d 100644 --- a/Common/ENDIAN.C +++ b/Common/ENDIAN.C @@ -1,57 +1,57 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" -#include "Common/Endian.h" - - -unsigned __int16 MirrorBytes16 (unsigned __int16 x) -{ - return (x << 8) | (x >> 8); -} - - -unsigned __int32 MirrorBytes32 (unsigned __int32 x) -{ - unsigned __int32 n = (unsigned __int8) x; - n <<= 8; n |= (unsigned __int8) (x >> 8); - n <<= 8; n |= (unsigned __int8) (x >> 16); - return (n << 8) | (unsigned __int8) (x >> 24); -} - -#ifndef TC_NO_COMPILER_INT64 -uint64 MirrorBytes64 (uint64 x) -{ - uint64 n = (unsigned __int8) x; - n <<= 8; n |= (unsigned __int8) (x >> 8); - n <<= 8; n |= (unsigned __int8) (x >> 16); - n <<= 8; n |= (unsigned __int8) (x >> 24); - n <<= 8; n |= (unsigned __int8) (x >> 32); - n <<= 8; n |= (unsigned __int8) (x >> 40); - n <<= 8; n |= (unsigned __int8) (x >> 48); - return (n << 8) | (unsigned __int8) (x >> 56); -} -#endif - -void -LongReverse (unsigned __int32 *buffer, unsigned byteCount) -{ - unsigned __int32 value; - - byteCount /= sizeof (unsigned __int32); - while (byteCount--) - { - value = *buffer; - value = ((value & 0xFF00FF00L) >> 8) | \ - ((value & 0x00FF00FFL) << 8); - *buffer++ = (value << 16) | (value >> 16); - } -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" +#include "Common/Endian.h" + + +unsigned __int16 MirrorBytes16 (unsigned __int16 x) +{ + return (x << 8) | (x >> 8); +} + + +unsigned __int32 MirrorBytes32 (unsigned __int32 x) +{ + unsigned __int32 n = (unsigned __int8) x; + n <<= 8; n |= (unsigned __int8) (x >> 8); + n <<= 8; n |= (unsigned __int8) (x >> 16); + return (n << 8) | (unsigned __int8) (x >> 24); +} + +#ifndef TC_NO_COMPILER_INT64 +uint64 MirrorBytes64 (uint64 x) +{ + uint64 n = (unsigned __int8) x; + n <<= 8; n |= (unsigned __int8) (x >> 8); + n <<= 8; n |= (unsigned __int8) (x >> 16); + n <<= 8; n |= (unsigned __int8) (x >> 24); + n <<= 8; n |= (unsigned __int8) (x >> 32); + n <<= 8; n |= (unsigned __int8) (x >> 40); + n <<= 8; n |= (unsigned __int8) (x >> 48); + return (n << 8) | (unsigned __int8) (x >> 56); +} +#endif + +void +LongReverse (unsigned __int32 *buffer, unsigned byteCount) +{ + unsigned __int32 value; + + byteCount /= sizeof (unsigned __int32); + while (byteCount--) + { + value = *buffer; + value = ((value & 0xFF00FF00L) >> 8) | \ + ((value & 0x00FF00FFL) << 8); + *buffer++ = (value << 16) | (value >> 16); + } +} diff --git a/Common/ENDIAN.H b/Common/ENDIAN.H index 14ea798..24c68d6 100644 --- a/Common/ENDIAN.H +++ b/Common/ENDIAN.H @@ -1,147 +1,147 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TC_ENDIAN_H -#define TC_ENDIAN_H - -#include "Common/Tcdefs.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#ifdef _WIN32 - -# ifndef LITTLE_ENDIAN -# define LITTLE_ENDIAN 1234 -# endif -# ifndef BYTE_ORDER -# define BYTE_ORDER LITTLE_ENDIAN -# endif - -#elif !defined(BYTE_ORDER) - -# ifdef TC_MACOSX -# include -# elif defined (TC_BSD) -# include -# elif defined (TC_SOLARIS) -# include -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -# ifdef _BIG_ENDIAN -# define BYTE_ORDER BIG_ENDIAN -# else -# define BYTE_ORDER LITTLE_ENDIAN -# endif -# else -# include -# endif - -# ifndef BYTE_ORDER -# ifndef __BYTE_ORDER -# error Byte order cannot be determined (BYTE_ORDER undefined) -# endif - -# define BYTE_ORDER __BYTE_ORDER -# endif - -# ifndef LITTLE_ENDIAN -# define LITTLE_ENDIAN __LITTLE_ENDIAN -# endif - -# ifndef BIG_ENDIAN -# define BIG_ENDIAN __BIG_ENDIAN -# endif - -#endif // !BYTE_ORDER - -/* Macros to read and write 16, 32, and 64-bit quantities in a portable manner. - These functions are implemented as macros rather than true functions as - the need to adjust the memory pointers makes them somewhat painful to call - in user code */ - -#define mputInt64(memPtr,data) \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 56 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 48 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 40 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 32 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 24 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 16 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) - -#define mputLong(memPtr,data) \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 24 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 16 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) - -#define mputWord(memPtr,data) \ - *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ - *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) - -#define mputByte(memPtr,data) \ - *memPtr++ = ( unsigned char ) data - -#define mputBytes(memPtr,data,len) \ - memcpy (memPtr,data,len); \ - memPtr += len; - -#define mgetInt64(memPtr) \ - ( memPtr += 8, ( ( unsigned __int64 ) memPtr[ -8 ] << 56 ) | ( ( unsigned __int64 ) memPtr[ -7 ] << 48 ) | \ - ( ( unsigned __int64 ) memPtr[ -6 ] << 40 ) | ( ( unsigned __int64 ) memPtr[ -5 ] << 32 ) | \ - ( ( unsigned __int64 ) memPtr[ -4 ] << 24 ) | ( ( unsigned __int64 ) memPtr[ -3 ] << 16 ) | \ - ( ( unsigned __int64 ) memPtr[ -2 ] << 8 ) | ( unsigned __int64 ) memPtr[ -1 ] ) - -#define mgetLong(memPtr) \ - ( memPtr += 4, ( ( unsigned __int32 ) memPtr[ -4 ] << 24 ) | ( ( unsigned __int32 ) memPtr[ -3 ] << 16 ) | \ - ( ( unsigned __int32 ) memPtr[ -2 ] << 8 ) | ( unsigned __int32 ) memPtr[ -1 ] ) - -#define mgetWord(memPtr) \ - ( memPtr += 2, ( unsigned short ) memPtr[ -2 ] << 8 ) | ( ( unsigned short ) memPtr[ -1 ] ) - -#define mgetByte(memPtr) \ - ( ( unsigned char ) *memPtr++ ) - -#if BYTE_ORDER == BIG_ENDIAN -# define LE16(x) MirrorBytes16(x) -# define LE32(x) MirrorBytes32(x) -# define LE64(x) MirrorBytes64(x) -#else -# define LE16(x) (x) -# define LE32(x) (x) -# define LE64(x) (x) -#endif - -#if BYTE_ORDER == LITTLE_ENDIAN -# define BE16(x) MirrorBytes16(x) -# define BE32(x) MirrorBytes32(x) -# define BE64(x) MirrorBytes64(x) -#else -# define BE16(x) (x) -# define BE32(x) (x) -# define BE64(x) (x) -#endif - -unsigned __int16 MirrorBytes16 (unsigned __int16 x); -unsigned __int32 MirrorBytes32 (unsigned __int32 x); -#ifndef TC_NO_COMPILER_INT64 -uint64 MirrorBytes64 (uint64 x); -#endif -void LongReverse ( unsigned __int32 *buffer , unsigned byteCount ); - -#if defined(__cplusplus) -} -#endif - -#endif /* TC_ENDIAN_H */ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_ENDIAN_H +#define TC_ENDIAN_H + +#include "Common/Tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifdef _WIN32 + +# ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN 1234 +# endif +# ifndef BYTE_ORDER +# define BYTE_ORDER LITTLE_ENDIAN +# endif + +#elif !defined(BYTE_ORDER) + +# ifdef TC_MACOSX +# include +# elif defined (TC_BSD) +# include +# elif defined (TC_SOLARIS) +# include +# define LITTLE_ENDIAN 1234 +# define BIG_ENDIAN 4321 +# ifdef _BIG_ENDIAN +# define BYTE_ORDER BIG_ENDIAN +# else +# define BYTE_ORDER LITTLE_ENDIAN +# endif +# else +# include +# endif + +# ifndef BYTE_ORDER +# ifndef __BYTE_ORDER +# error Byte order cannot be determined (BYTE_ORDER undefined) +# endif + +# define BYTE_ORDER __BYTE_ORDER +# endif + +# ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# endif + +# ifndef BIG_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# endif + +#endif // !BYTE_ORDER + +/* Macros to read and write 16, 32, and 64-bit quantities in a portable manner. + These functions are implemented as macros rather than true functions as + the need to adjust the memory pointers makes them somewhat painful to call + in user code */ + +#define mputInt64(memPtr,data) \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 56 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 48 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 40 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 32 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 24 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 16 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) + +#define mputLong(memPtr,data) \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 24 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 16 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) + +#define mputWord(memPtr,data) \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) + +#define mputByte(memPtr,data) \ + *memPtr++ = ( unsigned char ) data + +#define mputBytes(memPtr,data,len) \ + memcpy (memPtr,data,len); \ + memPtr += len; + +#define mgetInt64(memPtr) \ + ( memPtr += 8, ( ( unsigned __int64 ) memPtr[ -8 ] << 56 ) | ( ( unsigned __int64 ) memPtr[ -7 ] << 48 ) | \ + ( ( unsigned __int64 ) memPtr[ -6 ] << 40 ) | ( ( unsigned __int64 ) memPtr[ -5 ] << 32 ) | \ + ( ( unsigned __int64 ) memPtr[ -4 ] << 24 ) | ( ( unsigned __int64 ) memPtr[ -3 ] << 16 ) | \ + ( ( unsigned __int64 ) memPtr[ -2 ] << 8 ) | ( unsigned __int64 ) memPtr[ -1 ] ) + +#define mgetLong(memPtr) \ + ( memPtr += 4, ( ( unsigned __int32 ) memPtr[ -4 ] << 24 ) | ( ( unsigned __int32 ) memPtr[ -3 ] << 16 ) | \ + ( ( unsigned __int32 ) memPtr[ -2 ] << 8 ) | ( unsigned __int32 ) memPtr[ -1 ] ) + +#define mgetWord(memPtr) \ + ( memPtr += 2, ( unsigned short ) memPtr[ -2 ] << 8 ) | ( ( unsigned short ) memPtr[ -1 ] ) + +#define mgetByte(memPtr) \ + ( ( unsigned char ) *memPtr++ ) + +#if BYTE_ORDER == BIG_ENDIAN +# define LE16(x) MirrorBytes16(x) +# define LE32(x) MirrorBytes32(x) +# define LE64(x) MirrorBytes64(x) +#else +# define LE16(x) (x) +# define LE32(x) (x) +# define LE64(x) (x) +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +# define BE16(x) MirrorBytes16(x) +# define BE32(x) MirrorBytes32(x) +# define BE64(x) MirrorBytes64(x) +#else +# define BE16(x) (x) +# define BE32(x) (x) +# define BE64(x) (x) +#endif + +unsigned __int16 MirrorBytes16 (unsigned __int16 x); +unsigned __int32 MirrorBytes32 (unsigned __int32 x); +#ifndef TC_NO_COMPILER_INT64 +uint64 MirrorBytes64 (uint64 x); +#endif +void LongReverse ( unsigned __int32 *buffer , unsigned byteCount ); + +#if defined(__cplusplus) +} +#endif + +#endif /* TC_ENDIAN_H */ diff --git a/Common/EncryptionThreadPool.c b/Common/EncryptionThreadPool.c index 9c8148f..5d4c6e8 100644 --- a/Common/EncryptionThreadPool.c +++ b/Common/EncryptionThreadPool.c @@ -1,493 +1,498 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "EncryptionThreadPool.h" -#include "Pkcs5.h" -#ifdef DEVICE_DRIVER -#include "Driver/Ntdriver.h" -#endif - -#define TC_ENC_THREAD_POOL_MAX_THREAD_COUNT 32 -#define TC_ENC_THREAD_POOL_QUEUE_SIZE (TC_ENC_THREAD_POOL_MAX_THREAD_COUNT * 2) - -#ifdef DEVICE_DRIVER - -#define TC_THREAD_HANDLE PKTHREAD -#define TC_THREAD_PROC VOID - -#define TC_SET_EVENT(EVENT) KeSetEvent (&EVENT, IO_DISK_INCREMENT, FALSE) -#define TC_CLEAR_EVENT(EVENT) KeClearEvent (&EVENT) - -#define TC_MUTEX FAST_MUTEX -#define TC_INIT_MUTEX(MUTEX) ExInitializeFastMutex (MUTEX) -#define TC_ACQUIRE_MUTEX(MUTEX) ExAcquireFastMutex (MUTEX) -#define TC_RELEASE_MUTEX(MUTEX) ExReleaseFastMutex (MUTEX) - -#else // !DEVICE_DRIVER - -#define TC_THREAD_HANDLE HANDLE -#define TC_THREAD_PROC unsigned __stdcall - -#define TC_SET_EVENT(EVENT) SetEvent (EVENT) -#define TC_CLEAR_EVENT(EVENT) ResetEvent (EVENT) - -#define TC_MUTEX CRITICAL_SECTION -#define TC_INIT_MUTEX(MUTEX) InitializeCriticalSectionAndSpinCount (MUTEX, 4000) -#define TC_ACQUIRE_MUTEX(MUTEX) EnterCriticalSection (MUTEX) -#define TC_RELEASE_MUTEX(MUTEX) LeaveCriticalSection (MUTEX) - -#endif // !DEVICE_DRIVER - - -typedef enum -{ - WorkItemFree, - WorkItemReady, - WorkItemBusy -} WorkItemState; - - -typedef struct EncryptionThreadPoolWorkItemStruct -{ - WorkItemState State; - EncryptionThreadPoolWorkType Type; - - TC_EVENT ItemCompletedEvent; - - struct EncryptionThreadPoolWorkItemStruct *FirstFragment; - LONG OutstandingFragmentCount; - - union - { - struct - { - PCRYPTO_INFO CryptoInfo; - byte *Data; - UINT64_STRUCT StartUnitNo; - TC_LARGEST_COMPILER_UINT UnitCount; - - } Encryption; - - struct - { - TC_EVENT *CompletionEvent; - LONG *CompletionFlag; - char *DerivedKey; - int IterationCount; - TC_EVENT *NoOutstandingWorkItemEvent; - LONG *OutstandingWorkItemCount; - char *Password; - int PasswordLength; - int Pkcs5Prf; - char *Salt; - - } KeyDerivation; - }; - -} EncryptionThreadPoolWorkItem; - - -static volatile BOOL ThreadPoolRunning = FALSE; -static volatile BOOL StopPending = FALSE; - -static size_t ThreadCount; -static TC_THREAD_HANDLE ThreadHandles[TC_ENC_THREAD_POOL_MAX_THREAD_COUNT]; - -static EncryptionThreadPoolWorkItem WorkItemQueue[TC_ENC_THREAD_POOL_QUEUE_SIZE]; - -static volatile int EnqueuePosition; -static volatile int DequeuePosition; - -static TC_MUTEX EnqueueMutex; -static TC_MUTEX DequeueMutex; - -static TC_EVENT WorkItemReadyEvent; -static TC_EVENT WorkItemCompletedEvent; - - -static WorkItemState GetWorkItemState (EncryptionThreadPoolWorkItem *workItem) -{ - return InterlockedExchangeAdd ((LONG *) &workItem->State, 0); -} - - -static void SetWorkItemState (EncryptionThreadPoolWorkItem *workItem, WorkItemState newState) -{ - InterlockedExchange ((LONG *) &workItem->State, (LONG) newState); -} - - -static TC_THREAD_PROC EncryptionThreadProc (void *threadArg) -{ - EncryptionThreadPoolWorkItem *workItem; - - while (!StopPending) - { - TC_ACQUIRE_MUTEX (&DequeueMutex); - - workItem = &WorkItemQueue[DequeuePosition++]; - - if (DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) - DequeuePosition = 0; - - while (!StopPending && GetWorkItemState (workItem) != WorkItemReady) - { - TC_WAIT_EVENT (WorkItemReadyEvent); - } - - SetWorkItemState (workItem, WorkItemBusy); - - TC_RELEASE_MUTEX (&DequeueMutex); - - if (StopPending) - break; - - switch (workItem->Type) - { - case DecryptDataUnitsWork: - DecryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo); - break; - - case EncryptDataUnitsWork: - EncryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo); - break; - - case DeriveKeyWork: - switch (workItem->KeyDerivation.Pkcs5Prf) - { - case RIPEMD160: - derive_key_ripemd160 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, - workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); - break; - - case SHA512: - derive_key_sha512 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, - workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); - break; - - case WHIRLPOOL: - derive_key_whirlpool (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, - workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); - break; - - case SHA1: - derive_key_sha1 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, - workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } - - InterlockedExchange (workItem->KeyDerivation.CompletionFlag, TRUE); - TC_SET_EVENT (*workItem->KeyDerivation.CompletionEvent); - - if (InterlockedDecrement (workItem->KeyDerivation.OutstandingWorkItemCount) == 0) - TC_SET_EVENT (*workItem->KeyDerivation.NoOutstandingWorkItemEvent); - - SetWorkItemState (workItem, WorkItemFree); - TC_SET_EVENT (WorkItemCompletedEvent); - continue; - - default: - TC_THROW_FATAL_EXCEPTION; - } - - if (workItem != workItem->FirstFragment) - { - SetWorkItemState (workItem, WorkItemFree); - TC_SET_EVENT (WorkItemCompletedEvent); - } - - if (InterlockedDecrement (&workItem->FirstFragment->OutstandingFragmentCount) == 0) - TC_SET_EVENT (workItem->FirstFragment->ItemCompletedEvent); - } - -#ifdef DEVICE_DRIVER - PsTerminateSystemThread (STATUS_SUCCESS); -#else - _endthreadex (0); - return 0; -#endif -} - - -BOOL EncryptionThreadPoolStart () -{ - size_t cpuCount, i; - - if (ThreadPoolRunning) - return TRUE; - -#ifdef DEVICE_DRIVER - cpuCount = GetCpuCount(); -#else - { - SYSTEM_INFO sysInfo; - GetSystemInfo (&sysInfo); - cpuCount = sysInfo.dwNumberOfProcessors; - } -#endif - - if (cpuCount < 2) - return TRUE; - - if (cpuCount > TC_ENC_THREAD_POOL_MAX_THREAD_COUNT) - cpuCount = TC_ENC_THREAD_POOL_MAX_THREAD_COUNT; - - StopPending = FALSE; - DequeuePosition = 0; - EnqueuePosition = 0; - -#ifdef DEVICE_DRIVER - KeInitializeEvent (&WorkItemReadyEvent, SynchronizationEvent, FALSE); - KeInitializeEvent (&WorkItemCompletedEvent, SynchronizationEvent, FALSE); -#else - WorkItemReadyEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!WorkItemReadyEvent) - return FALSE; - - WorkItemCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!WorkItemCompletedEvent) - { - CloseHandle (WorkItemReadyEvent); - return FALSE; - } -#endif - - TC_INIT_MUTEX (&DequeueMutex); - TC_INIT_MUTEX (&EnqueueMutex); - - memset (WorkItemQueue, 0, sizeof (WorkItemQueue)); - - for (i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) - { - WorkItemQueue[i].State = WorkItemFree; - -#ifdef DEVICE_DRIVER - KeInitializeEvent (&WorkItemQueue[i].ItemCompletedEvent, SynchronizationEvent, FALSE); -#else - WorkItemQueue[i].ItemCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!WorkItemQueue[i].ItemCompletedEvent) - { - EncryptionThreadPoolStop(); - return FALSE; - } -#endif - } - - for (ThreadCount = 0; ThreadCount < cpuCount; ++ThreadCount) - { -#ifdef DEVICE_DRIVER - if (!NT_SUCCESS (TCStartThread (EncryptionThreadProc, NULL, &ThreadHandles[ThreadCount]))) -#else - if (!(ThreadHandles[ThreadCount] = (HANDLE) _beginthreadex (NULL, 0, EncryptionThreadProc, NULL, 0, NULL))) -#endif - { - EncryptionThreadPoolStop(); - return FALSE; - } - } - - ThreadPoolRunning = TRUE; - return TRUE; -} - - -void EncryptionThreadPoolStop () -{ - size_t i; - - if (!ThreadPoolRunning) - return; - - StopPending = TRUE; - TC_SET_EVENT (WorkItemReadyEvent); - - for (i = 0; i < ThreadCount; ++i) - { -#ifdef DEVICE_DRIVER - TCStopThread (ThreadHandles[i], &WorkItemReadyEvent); -#else - TC_WAIT_EVENT (ThreadHandles[i]); -#endif - } - - ThreadCount = 0; - -#ifndef DEVICE_DRIVER - DeleteCriticalSection (&DequeueMutex); - DeleteCriticalSection (&EnqueueMutex); - - CloseHandle (WorkItemReadyEvent); - CloseHandle (WorkItemCompletedEvent); - - for (i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) - { - if (WorkItemQueue[i].ItemCompletedEvent) - CloseHandle (WorkItemQueue[i].ItemCompletedEvent); - } -#endif - - ThreadPoolRunning = FALSE; -} - - -void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, char *password, int passwordLength, char *salt, int iterationCount, char *derivedKey) -{ - EncryptionThreadPoolWorkItem *workItem; - - if (!ThreadPoolRunning) - TC_THROW_FATAL_EXCEPTION; - - TC_ACQUIRE_MUTEX (&EnqueueMutex); - - workItem = &WorkItemQueue[EnqueuePosition++]; - if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) - EnqueuePosition = 0; - - while (GetWorkItemState (workItem) != WorkItemFree) - { - TC_WAIT_EVENT (WorkItemCompletedEvent); - } - - workItem->Type = DeriveKeyWork; - workItem->KeyDerivation.CompletionEvent = completionEvent; - workItem->KeyDerivation.CompletionFlag = completionFlag; - workItem->KeyDerivation.DerivedKey = derivedKey; - workItem->KeyDerivation.IterationCount = iterationCount; - workItem->KeyDerivation.NoOutstandingWorkItemEvent = noOutstandingWorkItemEvent; - workItem->KeyDerivation.OutstandingWorkItemCount = outstandingWorkItemCount; - workItem->KeyDerivation.Password = password; - workItem->KeyDerivation.PasswordLength = passwordLength; - workItem->KeyDerivation.Pkcs5Prf = pkcs5Prf; - workItem->KeyDerivation.Salt = salt; - - InterlockedIncrement (outstandingWorkItemCount); - TC_CLEAR_EVENT (*noOutstandingWorkItemEvent); - - SetWorkItemState (workItem, WorkItemReady); - TC_SET_EVENT (WorkItemReadyEvent); - TC_RELEASE_MUTEX (&EnqueueMutex); -} - - -void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, TC_LARGEST_COMPILER_UINT unitCount, PCRYPTO_INFO cryptoInfo) -{ - size_t fragmentCount; - size_t unitsPerFragment; - size_t remainder; - - byte *fragmentData; - TC_LARGEST_COMPILER_UINT fragmentStartUnitNo; - - EncryptionThreadPoolWorkItem *workItem; - EncryptionThreadPoolWorkItem *firstFragmentWorkItem; - - if (unitCount == 0) - return; - - if (!ThreadPoolRunning || unitCount == 1) - { - switch (type) - { - case DecryptDataUnitsWork: - DecryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo); - break; - - case EncryptDataUnitsWork: - EncryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo); - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } - - return; - } - - if (unitCount <= ThreadCount) - { - fragmentCount = (size_t) unitCount; - unitsPerFragment = 1; - remainder = 0; - } - else - { - /* Note that it is not efficient to divide the data into fragments smaller than a few hundred bytes. - The reason is that the overhead associated with thread handling would in most cases make a multi-threaded - process actually slower than a single-threaded process. */ - - fragmentCount = ThreadCount; - unitsPerFragment = (size_t) unitCount / ThreadCount; - remainder = (size_t) unitCount % ThreadCount; - - if (remainder > 0) - ++unitsPerFragment; - } - - fragmentData = data; - fragmentStartUnitNo = startUnitNo->Value; - - TC_ACQUIRE_MUTEX (&EnqueueMutex); - firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition]; - - while (GetWorkItemState (firstFragmentWorkItem) != WorkItemFree) - { - TC_WAIT_EVENT (WorkItemCompletedEvent); - } - - firstFragmentWorkItem->OutstandingFragmentCount = fragmentCount; - - while (fragmentCount-- > 0) - { - workItem = &WorkItemQueue[EnqueuePosition++]; - if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) - EnqueuePosition = 0; - - while (GetWorkItemState (workItem) != WorkItemFree) - { - TC_WAIT_EVENT (WorkItemCompletedEvent); - } - - workItem->Type = type; - workItem->FirstFragment = firstFragmentWorkItem; - - workItem->Encryption.CryptoInfo = cryptoInfo; - workItem->Encryption.Data = fragmentData; - workItem->Encryption.UnitCount = unitsPerFragment; - workItem->Encryption.StartUnitNo.Value = fragmentStartUnitNo; - - fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE; - fragmentStartUnitNo += unitsPerFragment; - - if (remainder > 0 && --remainder == 0) - --unitsPerFragment; - - SetWorkItemState (workItem, WorkItemReady); - TC_SET_EVENT (WorkItemReadyEvent); - } - - TC_RELEASE_MUTEX (&EnqueueMutex); - - TC_WAIT_EVENT (firstFragmentWorkItem->ItemCompletedEvent); - SetWorkItemState (firstFragmentWorkItem, WorkItemFree); - TC_SET_EVENT (WorkItemCompletedEvent); -} - - -size_t GetEncryptionThreadCount () -{ - return ThreadPoolRunning ? ThreadCount : 0; -} - - -BOOL IsEncryptionThreadPoolRunning () -{ - return ThreadPoolRunning; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "EncryptionThreadPool.h" +#include "Pkcs5.h" +#ifdef DEVICE_DRIVER +#include "Driver/Ntdriver.h" +#endif + +#define TC_ENC_THREAD_POOL_MAX_THREAD_COUNT 64 +#define TC_ENC_THREAD_POOL_QUEUE_SIZE (TC_ENC_THREAD_POOL_MAX_THREAD_COUNT * 2) + +#ifdef DEVICE_DRIVER + +#define TC_THREAD_HANDLE PKTHREAD +#define TC_THREAD_PROC VOID + +#define TC_SET_EVENT(EVENT) KeSetEvent (&EVENT, IO_DISK_INCREMENT, FALSE) +#define TC_CLEAR_EVENT(EVENT) KeClearEvent (&EVENT) + +#define TC_MUTEX FAST_MUTEX +#define TC_ACQUIRE_MUTEX(MUTEX) ExAcquireFastMutex (MUTEX) +#define TC_RELEASE_MUTEX(MUTEX) ExReleaseFastMutex (MUTEX) + +#else // !DEVICE_DRIVER + +#define TC_THREAD_HANDLE HANDLE +#define TC_THREAD_PROC unsigned __stdcall + +#define TC_SET_EVENT(EVENT) SetEvent (EVENT) +#define TC_CLEAR_EVENT(EVENT) ResetEvent (EVENT) + +#define TC_MUTEX HANDLE +#define TC_ACQUIRE_MUTEX(MUTEX) WaitForSingleObject (*(MUTEX), INFINITE) +#define TC_RELEASE_MUTEX(MUTEX) ReleaseMutex (*(MUTEX)) + +#endif // !DEVICE_DRIVER + + +typedef enum +{ + WorkItemFree, + WorkItemReady, + WorkItemBusy +} WorkItemState; + + +typedef struct EncryptionThreadPoolWorkItemStruct +{ + WorkItemState State; + EncryptionThreadPoolWorkType Type; + + TC_EVENT ItemCompletedEvent; + + struct EncryptionThreadPoolWorkItemStruct *FirstFragment; + LONG OutstandingFragmentCount; + + union + { + struct + { + PCRYPTO_INFO CryptoInfo; + byte *Data; + UINT64_STRUCT StartUnitNo; + uint32 UnitCount; + + } Encryption; + + struct + { + TC_EVENT *CompletionEvent; + LONG *CompletionFlag; + char *DerivedKey; + int IterationCount; + TC_EVENT *NoOutstandingWorkItemEvent; + LONG *OutstandingWorkItemCount; + char *Password; + int PasswordLength; + int Pkcs5Prf; + char *Salt; + + } KeyDerivation; + }; + +} EncryptionThreadPoolWorkItem; + + +static volatile BOOL ThreadPoolRunning = FALSE; +static volatile BOOL StopPending = FALSE; + +static uint32 ThreadCount; +static TC_THREAD_HANDLE ThreadHandles[TC_ENC_THREAD_POOL_MAX_THREAD_COUNT]; + +static EncryptionThreadPoolWorkItem WorkItemQueue[TC_ENC_THREAD_POOL_QUEUE_SIZE]; + +static volatile int EnqueuePosition; +static volatile int DequeuePosition; + +static TC_MUTEX EnqueueMutex; +static TC_MUTEX DequeueMutex; + +static TC_EVENT WorkItemReadyEvent; +static TC_EVENT WorkItemCompletedEvent; + + +static WorkItemState GetWorkItemState (EncryptionThreadPoolWorkItem *workItem) +{ + return InterlockedExchangeAdd ((LONG *) &workItem->State, 0); +} + + +static void SetWorkItemState (EncryptionThreadPoolWorkItem *workItem, WorkItemState newState) +{ + InterlockedExchange ((LONG *) &workItem->State, (LONG) newState); +} + + +static TC_THREAD_PROC EncryptionThreadProc (void *threadArg) +{ + EncryptionThreadPoolWorkItem *workItem; + + while (!StopPending) + { + TC_ACQUIRE_MUTEX (&DequeueMutex); + + workItem = &WorkItemQueue[DequeuePosition++]; + + if (DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) + DequeuePosition = 0; + + while (!StopPending && GetWorkItemState (workItem) != WorkItemReady) + { + TC_WAIT_EVENT (WorkItemReadyEvent); + } + + SetWorkItemState (workItem, WorkItemBusy); + + TC_RELEASE_MUTEX (&DequeueMutex); + + if (StopPending) + break; + + switch (workItem->Type) + { + case DecryptDataUnitsWork: + DecryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo); + break; + + case EncryptDataUnitsWork: + EncryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo); + break; + + case DeriveKeyWork: + switch (workItem->KeyDerivation.Pkcs5Prf) + { + case RIPEMD160: + derive_key_ripemd160 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, + workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); + break; + + case SHA512: + derive_key_sha512 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, + workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); + break; + + case WHIRLPOOL: + derive_key_whirlpool (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, + workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); + break; + + case SHA1: + derive_key_sha1 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, + workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + + InterlockedExchange (workItem->KeyDerivation.CompletionFlag, TRUE); + TC_SET_EVENT (*workItem->KeyDerivation.CompletionEvent); + + if (InterlockedDecrement (workItem->KeyDerivation.OutstandingWorkItemCount) == 0) + TC_SET_EVENT (*workItem->KeyDerivation.NoOutstandingWorkItemEvent); + + SetWorkItemState (workItem, WorkItemFree); + TC_SET_EVENT (WorkItemCompletedEvent); + continue; + + default: + TC_THROW_FATAL_EXCEPTION; + } + + if (workItem != workItem->FirstFragment) + { + SetWorkItemState (workItem, WorkItemFree); + TC_SET_EVENT (WorkItemCompletedEvent); + } + + if (InterlockedDecrement (&workItem->FirstFragment->OutstandingFragmentCount) == 0) + TC_SET_EVENT (workItem->FirstFragment->ItemCompletedEvent); + } + +#ifdef DEVICE_DRIVER + PsTerminateSystemThread (STATUS_SUCCESS); +#else + _endthreadex (0); + return 0; +#endif +} + + +BOOL EncryptionThreadPoolStart () +{ + size_t cpuCount, i; + + if (ThreadPoolRunning) + return TRUE; + +#ifdef DEVICE_DRIVER + cpuCount = GetCpuCount(); +#else + { + SYSTEM_INFO sysInfo; + GetSystemInfo (&sysInfo); + cpuCount = sysInfo.dwNumberOfProcessors; + } +#endif + + if (cpuCount < 2) + return TRUE; + + if (cpuCount > TC_ENC_THREAD_POOL_MAX_THREAD_COUNT) + cpuCount = TC_ENC_THREAD_POOL_MAX_THREAD_COUNT; + + StopPending = FALSE; + DequeuePosition = 0; + EnqueuePosition = 0; + +#ifdef DEVICE_DRIVER + KeInitializeEvent (&WorkItemReadyEvent, SynchronizationEvent, FALSE); + KeInitializeEvent (&WorkItemCompletedEvent, SynchronizationEvent, FALSE); +#else + WorkItemReadyEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + if (!WorkItemReadyEvent) + return FALSE; + + WorkItemCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + if (!WorkItemCompletedEvent) + return FALSE; +#endif + +#ifdef DEVICE_DRIVER + ExInitializeFastMutex (&DequeueMutex); + ExInitializeFastMutex (&EnqueueMutex); +#else + DequeueMutex = CreateMutex (NULL, FALSE, NULL); + if (!DequeueMutex) + return FALSE; + + EnqueueMutex = CreateMutex (NULL, FALSE, NULL); + if (!EnqueueMutex) + return FALSE; +#endif + + memset (WorkItemQueue, 0, sizeof (WorkItemQueue)); + + for (i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) + { + WorkItemQueue[i].State = WorkItemFree; + +#ifdef DEVICE_DRIVER + KeInitializeEvent (&WorkItemQueue[i].ItemCompletedEvent, SynchronizationEvent, FALSE); +#else + WorkItemQueue[i].ItemCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + if (!WorkItemQueue[i].ItemCompletedEvent) + { + EncryptionThreadPoolStop(); + return FALSE; + } +#endif + } + + for (ThreadCount = 0; ThreadCount < cpuCount; ++ThreadCount) + { +#ifdef DEVICE_DRIVER + if (!NT_SUCCESS (TCStartThread (EncryptionThreadProc, NULL, &ThreadHandles[ThreadCount]))) +#else + if (!(ThreadHandles[ThreadCount] = (HANDLE) _beginthreadex (NULL, 0, EncryptionThreadProc, NULL, 0, NULL))) +#endif + { + EncryptionThreadPoolStop(); + return FALSE; + } + } + + ThreadPoolRunning = TRUE; + return TRUE; +} + + +void EncryptionThreadPoolStop () +{ + size_t i; + + if (!ThreadPoolRunning) + return; + + StopPending = TRUE; + TC_SET_EVENT (WorkItemReadyEvent); + + for (i = 0; i < ThreadCount; ++i) + { +#ifdef DEVICE_DRIVER + TCStopThread (ThreadHandles[i], &WorkItemReadyEvent); +#else + TC_WAIT_EVENT (ThreadHandles[i]); +#endif + } + + ThreadCount = 0; + +#ifndef DEVICE_DRIVER + CloseHandle (DequeueMutex); + CloseHandle (EnqueueMutex); + + CloseHandle (WorkItemReadyEvent); + CloseHandle (WorkItemCompletedEvent); + + for (i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) + { + if (WorkItemQueue[i].ItemCompletedEvent) + CloseHandle (WorkItemQueue[i].ItemCompletedEvent); + } +#endif + + ThreadPoolRunning = FALSE; +} + + +void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, char *password, int passwordLength, char *salt, int iterationCount, char *derivedKey) +{ + EncryptionThreadPoolWorkItem *workItem; + + if (!ThreadPoolRunning) + TC_THROW_FATAL_EXCEPTION; + + TC_ACQUIRE_MUTEX (&EnqueueMutex); + + workItem = &WorkItemQueue[EnqueuePosition++]; + if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) + EnqueuePosition = 0; + + while (GetWorkItemState (workItem) != WorkItemFree) + { + TC_WAIT_EVENT (WorkItemCompletedEvent); + } + + workItem->Type = DeriveKeyWork; + workItem->KeyDerivation.CompletionEvent = completionEvent; + workItem->KeyDerivation.CompletionFlag = completionFlag; + workItem->KeyDerivation.DerivedKey = derivedKey; + workItem->KeyDerivation.IterationCount = iterationCount; + workItem->KeyDerivation.NoOutstandingWorkItemEvent = noOutstandingWorkItemEvent; + workItem->KeyDerivation.OutstandingWorkItemCount = outstandingWorkItemCount; + workItem->KeyDerivation.Password = password; + workItem->KeyDerivation.PasswordLength = passwordLength; + workItem->KeyDerivation.Pkcs5Prf = pkcs5Prf; + workItem->KeyDerivation.Salt = salt; + + InterlockedIncrement (outstandingWorkItemCount); + TC_CLEAR_EVENT (*noOutstandingWorkItemEvent); + + SetWorkItemState (workItem, WorkItemReady); + TC_SET_EVENT (WorkItemReadyEvent); + TC_RELEASE_MUTEX (&EnqueueMutex); +} + + +void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo) +{ + uint32 fragmentCount; + uint32 unitsPerFragment; + uint32 remainder; + + byte *fragmentData; + uint64 fragmentStartUnitNo; + + EncryptionThreadPoolWorkItem *workItem; + EncryptionThreadPoolWorkItem *firstFragmentWorkItem; + + if (unitCount == 0) + return; + + if (!ThreadPoolRunning || unitCount == 1) + { + switch (type) + { + case DecryptDataUnitsWork: + DecryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo); + break; + + case EncryptDataUnitsWork: + EncryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + + return; + } + + if (unitCount <= ThreadCount) + { + fragmentCount = unitCount; + unitsPerFragment = 1; + remainder = 0; + } + else + { + /* Note that it is not efficient to divide the data into fragments smaller than a few hundred bytes. + The reason is that the overhead associated with thread handling would in most cases make a multi-threaded + process actually slower than a single-threaded process. */ + + fragmentCount = ThreadCount; + unitsPerFragment = unitCount / ThreadCount; + remainder = unitCount % ThreadCount; + + if (remainder > 0) + ++unitsPerFragment; + } + + fragmentData = data; + fragmentStartUnitNo = startUnitNo->Value; + + TC_ACQUIRE_MUTEX (&EnqueueMutex); + firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition]; + + while (GetWorkItemState (firstFragmentWorkItem) != WorkItemFree) + { + TC_WAIT_EVENT (WorkItemCompletedEvent); + } + + firstFragmentWorkItem->OutstandingFragmentCount = fragmentCount; + + while (fragmentCount-- > 0) + { + workItem = &WorkItemQueue[EnqueuePosition++]; + if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) + EnqueuePosition = 0; + + while (GetWorkItemState (workItem) != WorkItemFree) + { + TC_WAIT_EVENT (WorkItemCompletedEvent); + } + + workItem->Type = type; + workItem->FirstFragment = firstFragmentWorkItem; + + workItem->Encryption.CryptoInfo = cryptoInfo; + workItem->Encryption.Data = fragmentData; + workItem->Encryption.UnitCount = unitsPerFragment; + workItem->Encryption.StartUnitNo.Value = fragmentStartUnitNo; + + fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE; + fragmentStartUnitNo += unitsPerFragment; + + if (remainder > 0 && --remainder == 0) + --unitsPerFragment; + + SetWorkItemState (workItem, WorkItemReady); + TC_SET_EVENT (WorkItemReadyEvent); + } + + TC_RELEASE_MUTEX (&EnqueueMutex); + + TC_WAIT_EVENT (firstFragmentWorkItem->ItemCompletedEvent); + SetWorkItemState (firstFragmentWorkItem, WorkItemFree); + TC_SET_EVENT (WorkItemCompletedEvent); +} + + +size_t GetEncryptionThreadCount () +{ + return ThreadPoolRunning ? ThreadCount : 0; +} + + +BOOL IsEncryptionThreadPoolRunning () +{ + return ThreadPoolRunning; +} diff --git a/Common/EncryptionThreadPool.h b/Common/EncryptionThreadPool.h index c8adbc5..bcbda6c 100644 --- a/Common/EncryptionThreadPool.h +++ b/Common/EncryptionThreadPool.h @@ -1,37 +1,37 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_ENCRYPTION_THREAD_POOL -#define TC_HEADER_ENCRYPTION_THREAD_POOL - -#include "Tcdefs.h" -#include "Crypto.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum -{ - EncryptDataUnitsWork, - DecryptDataUnitsWork, - DeriveKeyWork -} EncryptionThreadPoolWorkType; - -void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, char *password, int passwordLength, char *salt, int iterationCount, char *derivedKey); -void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, TC_LARGEST_COMPILER_UINT unitCount, PCRYPTO_INFO cryptoInfo); -BOOL EncryptionThreadPoolStart (); -void EncryptionThreadPoolStop (); -size_t GetEncryptionThreadCount (); -BOOL IsEncryptionThreadPoolRunning (); - -#ifdef __cplusplus -} -#endif - -#endif // TC_HEADER_ENCRYPTION_THREAD_POOL +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_ENCRYPTION_THREAD_POOL +#define TC_HEADER_ENCRYPTION_THREAD_POOL + +#include "Tcdefs.h" +#include "Crypto.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + EncryptDataUnitsWork, + DecryptDataUnitsWork, + DeriveKeyWork +} EncryptionThreadPoolWorkType; + +void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, char *password, int passwordLength, char *salt, int iterationCount, char *derivedKey); +void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo); +BOOL EncryptionThreadPoolStart (); +void EncryptionThreadPoolStop (); +size_t GetEncryptionThreadCount (); +BOOL IsEncryptionThreadPoolRunning (); + +#ifdef __cplusplus +} +#endif + +#endif // TC_HEADER_ENCRYPTION_THREAD_POOL diff --git a/Common/Exception.h b/Common/Exception.h index 04c1864..d82896e 100644 --- a/Common/Exception.h +++ b/Common/Exception.h @@ -1,81 +1,81 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Common_Exception -#define TC_HEADER_Common_Exception - -#include "Platform/PlatformBase.h" -#include "Dlgcode.h" - -namespace TrueCrypt -{ - struct Exception - { - virtual void Show (HWND parent) const = 0; - }; - - struct SystemException : public Exception - { - SystemException () : ErrorCode (GetLastError()) { } - - void Show (HWND parent) const - { - SetLastError (ErrorCode); - handleWin32Error (parent); - } - - DWORD ErrorCode; - }; - - struct ErrorException : public Exception - { - ErrorException (char *langId) : ErrLangId (langId) { } - ErrorException (const wstring &errMsg) : ErrMsg (errMsg) { } - - void Show (HWND parent) const - { - if (ErrMsg.empty()) - ::Error (ErrLangId); - else - ::ErrorDirect (ErrMsg.c_str()); - } - - char *ErrLangId; - wstring ErrMsg; - }; - - struct ParameterIncorrect : public Exception - { - ParameterIncorrect (const char *srcPos) : SrcPos (srcPos) { } - - void Show (HWND parent) const - { - string msgBody = "Parameter incorrect.\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) + ")"; - MessageBox (parent, msgBody.c_str(), "TrueCrypt", MB_ICONERROR | MB_SETFOREGROUND); - } - - const char *SrcPos; - }; - - struct TimeOut : public Exception - { - TimeOut (const char *srcPos) { } - void Show (HWND parent) const { ErrorDirect (L"Timeout"); } - }; - - struct UserAbort : public Exception - { - UserAbort (const char *srcPos) { } - void Show (HWND parent) const { } - }; -} - -#define throw_sys_if(condition) do { if (condition) throw SystemException(); } while (false) - - -#endif // TC_HEADER_Common_Exception +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Common_Exception +#define TC_HEADER_Common_Exception + +#include "Platform/PlatformBase.h" +#include "Dlgcode.h" + +namespace TrueCrypt +{ + struct Exception + { + virtual void Show (HWND parent) const = 0; + }; + + struct SystemException : public Exception + { + SystemException () : ErrorCode (GetLastError()) { } + + void Show (HWND parent) const + { + SetLastError (ErrorCode); + handleWin32Error (parent); + } + + DWORD ErrorCode; + }; + + struct ErrorException : public Exception + { + ErrorException (char *langId) : ErrLangId (langId) { } + ErrorException (const wstring &errMsg) : ErrMsg (errMsg) { } + + void Show (HWND parent) const + { + if (ErrMsg.empty()) + ::Error (ErrLangId); + else + ::ErrorDirect (ErrMsg.c_str()); + } + + char *ErrLangId; + wstring ErrMsg; + }; + + struct ParameterIncorrect : public Exception + { + ParameterIncorrect (const char *srcPos) : SrcPos (srcPos) { } + + void Show (HWND parent) const + { + string msgBody = "Parameter incorrect.\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) + ")"; + MessageBox (parent, msgBody.c_str(), "TrueCrypt", MB_ICONERROR | MB_SETFOREGROUND); + } + + const char *SrcPos; + }; + + struct TimeOut : public Exception + { + TimeOut (const char *srcPos) { } + void Show (HWND parent) const { ErrorDirect (L"Timeout"); } + }; + + struct UserAbort : public Exception + { + UserAbort (const char *srcPos) { } + void Show (HWND parent) const { } + }; +} + +#define throw_sys_if(condition) do { if (condition) throw SystemException(); } while (false) + + +#endif // TC_HEADER_Common_Exception diff --git a/Common/FAT.C b/Common/FAT.C index 7ebbabb..54ddd04 100644 --- a/Common/FAT.C +++ b/Common/FAT.C @@ -1,421 +1,420 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include -#include -#include - -#include "Tcdefs.h" - -#include "Crypto.h" -#include "Common/Endian.h" -#include "Format.h" -#include "Fat.h" -#include "Progress.h" -#include "Random.h" - -void -GetFatParams (fatparams * ft) -{ - unsigned int fatsecs; - if(ft->cluster_size == 0) // 'Default' cluster size - { - if (ft->num_sectors * 512LL >= 256*BYTES_PER_GB) - ft->cluster_size = 128; - else if (ft->num_sectors * 512LL >= 64*BYTES_PER_GB) - ft->cluster_size = 64; - else if (ft->num_sectors * 512LL >= 16*BYTES_PER_GB) - ft->cluster_size = 32; - else if (ft->num_sectors * 512LL >= 8*BYTES_PER_GB) - ft->cluster_size = 16; - else if (ft->num_sectors * 512LL >= 128*BYTES_PER_MB) - ft->cluster_size = 8; - else if (ft->num_sectors * 512LL >= 64*BYTES_PER_MB) - ft->cluster_size = 4; - else if (ft->num_sectors * 512LL >= 32*BYTES_PER_MB) - ft->cluster_size = 2; - else - ft->cluster_size = 1; - } - - // Geometry always set to SECTORS/1/1 - ft->secs_track = 1; - ft->heads = 1; - - ft->dir_entries = 512; - ft->fats = 2; - ft->media = 0xf8; - ft->sector_size = SECTOR_SIZE; - ft->hidden = 0; - - ft->size_root_dir = ft->dir_entries * 32; - - // FAT12 - ft->size_fat = 12; - ft->reserved = 2; - fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; - ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 3)); - ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + SECTOR_SIZE - 1) / SECTOR_SIZE; - - if (ft->cluster_count >= 4085) // FAT16 - { - ft->size_fat = 16; - ft->reserved = 2; - fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; - ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 4)); - ft->fat_length = (ft->cluster_count * 2 + SECTOR_SIZE - 1) / SECTOR_SIZE; - } - - if(ft->cluster_count >= 65525) // FAT32 - { - ft->size_fat = 32; - ft->reserved = 32; - fatsecs = ft->num_sectors - ft->reserved; - ft->size_root_dir = ft->cluster_size * SECTOR_SIZE; - ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 8)); - ft->fat_length = (ft->cluster_count * 4 + SECTOR_SIZE - 1) / SECTOR_SIZE; - } - - if (ft->num_sectors >= 65536 || ft->size_fat == 32) - { - ft->sectors = 0; - ft->total_sect = ft->num_sectors; - } - else - { - ft->sectors = ft->num_sectors; - ft->total_sect = 0; - } -} - -void -PutBoot (fatparams * ft, unsigned char *boot) -{ - int cnt = 0; - - boot[cnt++] = 0xeb; /* boot jump */ - boot[cnt++] = 0x3c; - boot[cnt++] = 0x90; - memcpy (boot + cnt, "MSDOS5.0", 8); /* system id */ - cnt += 8; - *(__int16 *)(boot + cnt) = LE16(ft->sector_size); /* bytes per sector */ - cnt += 2; - boot[cnt++] = (__int8) ft->cluster_size; /* sectors per cluster */ - *(__int16 *)(boot + cnt) = LE16(ft->reserved); /* reserved sectors */ - cnt += 2; - boot[cnt++] = (__int8) ft->fats; /* 2 fats */ - - if(ft->size_fat == 32) - { - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - } - else - { - *(__int16 *)(boot + cnt) = LE16(ft->dir_entries); /* 512 root entries */ - cnt += 2; - } - - *(__int16 *)(boot + cnt) = LE16(ft->sectors); /* # sectors */ - cnt += 2; - boot[cnt++] = (__int8) ft->media; /* media byte */ - - if(ft->size_fat == 32) - { - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - } - else - { - *(__int16 *)(boot + cnt) = LE16(ft->fat_length); /* fat size */ - cnt += 2; - } - - *(__int16 *)(boot + cnt) = LE16(ft->secs_track); /* # sectors per track */ - cnt += 2; - *(__int16 *)(boot + cnt) = LE16(ft->heads); /* # heads */ - cnt += 2; - *(__int32 *)(boot + cnt) = LE32(ft->hidden); /* # hidden sectors */ - cnt += 4; - *(__int32 *)(boot + cnt) = LE32(ft->total_sect); /* # huge sectors */ - cnt += 4; - - if(ft->size_fat == 32) - { - *(__int32 *)(boot + cnt) = LE32(ft->fat_length); cnt += 4; /* fat size 32 */ - boot[cnt++] = 0x00; /* ExtFlags */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; /* FSVer */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x02; /* RootClus */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - boot[cnt++] = 0x01; /* FSInfo */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x06; /* BkBootSec */ - boot[cnt++] = 0x00; - memset(boot+cnt, 0, 12); cnt+=12; /* Reserved */ - } - - boot[cnt++] = 0x00; /* drive number */ // FIXED 80 > 00 - boot[cnt++] = 0x00; /* reserved */ - boot[cnt++] = 0x29; /* boot sig */ - - RandgetBytes (boot + cnt, 4, FALSE); /* vol id */ - cnt += 4; - - memcpy (boot + cnt, ft->volume_name, 11); /* vol title */ - cnt += 11; - - switch(ft->size_fat) /* filesystem type */ - { - case 12: memcpy (boot + cnt, "FAT12 ", 8); break; - case 16: memcpy (boot + cnt, "FAT16 ", 8); break; - case 32: memcpy (boot + cnt, "FAT32 ", 8); break; - } - cnt += 8; - - memset (boot + cnt, 0, ft->size_fat==32 ? 420:448); /* boot code */ - cnt += ft->size_fat==32 ? 420:448; - boot[cnt++] = 0x55; - boot[cnt++] = 0xaa; /* boot sig */ -} - - -/* FAT32 FSInfo */ -static PutFSInfo (unsigned char *sector, fatparams *ft) -{ - memset (sector, 0, 512); - sector[3]=0x41; /* LeadSig */ - sector[2]=0x61; - sector[1]=0x52; - sector[0]=0x52; - sector[484+3]=0x61; /* StrucSig */ - sector[484+2]=0x41; - sector[484+1]=0x72; - sector[484+0]=0x72; - - // Free cluster count - *(uint32 *)(sector + 488) = LE32 (ft->cluster_count - ft->size_root_dir / SECTOR_SIZE / ft->cluster_size); - - sector[492+3]=0xff; /* Nxt_Free */ - sector[492+2]=0xff; - sector[492+1]=0xff; - sector[492+0]=0xff; - sector[508+3]=0xaa; /* TrailSig */ - sector[508+2]=0x55; - sector[508+1]=0x00; - sector[508+0]=0x00; -} - - -int -FormatFat (unsigned __int64 startSector, fatparams * ft, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat) -{ - int write_buf_cnt = 0; - char sector[SECTOR_SIZE], *write_buf; - unsigned __int64 nSecNo = startSector; - int x, n; - int retVal; - char temporaryKey[MASTER_KEYDATA_SIZE]; - - LARGE_INTEGER startOffset; - LARGE_INTEGER newOffset; - - // Seek to start sector - startOffset.QuadPart = startSector * SECTOR_SIZE; - if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) - || newOffset.QuadPart != startOffset.QuadPart) - { - return ERR_VOL_SEEKING; - } - - /* Write the data area */ - - write_buf = (char *)TCalloc (WRITE_BUF_SIZE); - if (!write_buf) - return ERR_OUTOFMEMORY; - - memset (sector, 0, sizeof (sector)); - - PutBoot (ft, (unsigned char *) sector); - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - - /* fat32 boot area */ - if (ft->size_fat == 32) - { - /* fsinfo */ - PutFSInfo((unsigned char *) sector, ft); - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - - /* reserved */ - while (nSecNo - startSector < 6) - { - memset (sector, 0, sizeof (sector)); - sector[508+3]=0xaa; /* TrailSig */ - sector[508+2]=0x55; - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - } - - /* bootsector backup */ - memset (sector, 0, sizeof (sector)); - PutBoot (ft, (unsigned char *) sector); - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - - PutFSInfo((unsigned char *) sector, ft); - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - } - - /* reserved */ - while (nSecNo - startSector < (unsigned int)ft->reserved) - { - memset (sector, 0, sizeof (sector)); - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - } - - /* write fat */ - for (x = 1; x <= ft->fats; x++) - { - for (n = 0; n < ft->fat_length; n++) - { - memset (sector, 0, SECTOR_SIZE); - - if (n == 0) - { - unsigned char fat_sig[12]; - if (ft->size_fat == 32) - { - fat_sig[0] = (unsigned char) ft->media; - fat_sig[1] = fat_sig[2] = 0xff; - fat_sig[3] = 0x0f; - fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff; - fat_sig[7] = 0x0f; - fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff; - fat_sig[11] = 0x0f; - memcpy (sector, fat_sig, 12); - } - else if (ft->size_fat == 16) - { - fat_sig[0] = (unsigned char) ft->media; - fat_sig[1] = 0xff; - fat_sig[2] = 0xff; - fat_sig[3] = 0xff; - memcpy (sector, fat_sig, 4); - } - else if (ft->size_fat == 12) - { - fat_sig[0] = (unsigned char) ft->media; - fat_sig[1] = 0xff; - fat_sig[2] = 0xff; - fat_sig[3] = 0x00; - memcpy (sector, fat_sig, 4); - } - } - - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - } - } - - - /* write rootdir */ - for (x = 0; x < ft->size_root_dir / SECTOR_SIZE; x++) - { - memset (sector, 0, SECTOR_SIZE); - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - - } - - /* Fill the rest of the data area with random data */ - - if(!quickFormat) - { - if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo)) - goto fail; - - /* Generate a random temporary key set to be used for "dummy" encryption that will fill - the free disk space (data area) with random data. This is necessary for plausible - deniability of hidden volumes (and also reduces the amount of predictable plaintext - within the volume). */ - - // Temporary master key - if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE)) - goto fail; - - // Temporary secondary key (XTS mode) - if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE)) - goto fail; - - retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); - if (retVal != ERR_SUCCESS) - { - burn (temporaryKey, sizeof(temporaryKey)); - return retVal; - } - if (!EAInitMode (cryptoInfo)) - { - burn (temporaryKey, sizeof(temporaryKey)); - return ERR_MODE_INIT_FAILED; - } - - x = ft->num_sectors - ft->reserved - ft->size_root_dir / SECTOR_SIZE - ft->fat_length * 2; - while (x--) - { - /* Generate random plaintext. Note that reused plaintext blocks are not a concern here - since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do - occur commonly on media in the "real world", so it might actually be a fatal mistake - to try to avoid them completely. */ - -#if RNG_POOL_SIZE < SECTOR_SIZE -#error RNG_POOL_SIZE < SECTOR_SIZE -#endif - if (!RandpeekBytes (sector, SECTOR_SIZE)) - goto fail; - - // Encrypt the random plaintext and write it to the disk - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - } - UpdateProgressBar (nSecNo); - } - else - UpdateProgressBar (ft->num_sectors); - - if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo)) - goto fail; - - TCfree (write_buf); - burn (temporaryKey, sizeof(temporaryKey)); - return 0; - -fail: - - TCfree (write_buf); - burn (temporaryKey, sizeof(temporaryKey)); - return ERR_OS_ERROR; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include +#include +#include + +#include "Tcdefs.h" + +#include "Crypto.h" +#include "Common/Endian.h" +#include "Format.h" +#include "Fat.h" +#include "Progress.h" +#include "Random.h" + +void +GetFatParams (fatparams * ft) +{ + unsigned int fatsecs; + if(ft->cluster_size == 0) // 'Default' cluster size + { + if (ft->num_sectors * 512LL >= 256*BYTES_PER_GB) + ft->cluster_size = 128; + else if (ft->num_sectors * 512LL >= 64*BYTES_PER_GB) + ft->cluster_size = 64; + else if (ft->num_sectors * 512LL >= 16*BYTES_PER_GB) + ft->cluster_size = 32; + else if (ft->num_sectors * 512LL >= 8*BYTES_PER_GB) + ft->cluster_size = 16; + else if (ft->num_sectors * 512LL >= 128*BYTES_PER_MB) + ft->cluster_size = 8; + else if (ft->num_sectors * 512LL >= 64*BYTES_PER_MB) + ft->cluster_size = 4; + else if (ft->num_sectors * 512LL >= 32*BYTES_PER_MB) + ft->cluster_size = 2; + else + ft->cluster_size = 1; + } + + // Geometry always set to SECTORS/1/1 + ft->secs_track = 1; + ft->heads = 1; + + ft->dir_entries = 512; + ft->fats = 2; + ft->media = 0xf8; + ft->sector_size = SECTOR_SIZE; + ft->hidden = 0; + + ft->size_root_dir = ft->dir_entries * 32; + + // FAT12 + ft->size_fat = 12; + ft->reserved = 2; + fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; + ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 3)); + ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + SECTOR_SIZE - 1) / SECTOR_SIZE; + + if (ft->cluster_count >= 4085) // FAT16 + { + ft->size_fat = 16; + ft->reserved = 2; + fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; + ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 4)); + ft->fat_length = (ft->cluster_count * 2 + SECTOR_SIZE - 1) / SECTOR_SIZE; + } + + if(ft->cluster_count >= 65525) // FAT32 + { + ft->size_fat = 32; + ft->reserved = 32; + fatsecs = ft->num_sectors - ft->reserved; + ft->size_root_dir = ft->cluster_size * SECTOR_SIZE; + ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 8)); + ft->fat_length = (ft->cluster_count * 4 + SECTOR_SIZE - 1) / SECTOR_SIZE; + } + + if (ft->num_sectors >= 65536 || ft->size_fat == 32) + { + ft->sectors = 0; + ft->total_sect = ft->num_sectors; + } + else + { + ft->sectors = (uint16) ft->num_sectors; + ft->total_sect = 0; + } +} + +void +PutBoot (fatparams * ft, unsigned char *boot) +{ + int cnt = 0; + + boot[cnt++] = 0xeb; /* boot jump */ + boot[cnt++] = 0x3c; + boot[cnt++] = 0x90; + memcpy (boot + cnt, "MSDOS5.0", 8); /* system id */ + cnt += 8; + *(__int16 *)(boot + cnt) = LE16(ft->sector_size); /* bytes per sector */ + cnt += 2; + boot[cnt++] = (__int8) ft->cluster_size; /* sectors per cluster */ + *(__int16 *)(boot + cnt) = LE16(ft->reserved); /* reserved sectors */ + cnt += 2; + boot[cnt++] = (__int8) ft->fats; /* 2 fats */ + + if(ft->size_fat == 32) + { + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + } + else + { + *(__int16 *)(boot + cnt) = LE16(ft->dir_entries); /* 512 root entries */ + cnt += 2; + } + + *(__int16 *)(boot + cnt) = LE16(ft->sectors); /* # sectors */ + cnt += 2; + boot[cnt++] = (__int8) ft->media; /* media byte */ + + if(ft->size_fat == 32) + { + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + } + else + { + *(__int16 *)(boot + cnt) = LE16((uint16) ft->fat_length); /* fat size */ + cnt += 2; + } + + *(__int16 *)(boot + cnt) = LE16(ft->secs_track); /* # sectors per track */ + cnt += 2; + *(__int16 *)(boot + cnt) = LE16(ft->heads); /* # heads */ + cnt += 2; + *(__int32 *)(boot + cnt) = LE32(ft->hidden); /* # hidden sectors */ + cnt += 4; + *(__int32 *)(boot + cnt) = LE32(ft->total_sect); /* # huge sectors */ + cnt += 4; + + if(ft->size_fat == 32) + { + *(__int32 *)(boot + cnt) = LE32(ft->fat_length); cnt += 4; /* fat size 32 */ + boot[cnt++] = 0x00; /* ExtFlags */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; /* FSVer */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x02; /* RootClus */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + boot[cnt++] = 0x01; /* FSInfo */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x06; /* BkBootSec */ + boot[cnt++] = 0x00; + memset(boot+cnt, 0, 12); cnt+=12; /* Reserved */ + } + + boot[cnt++] = 0x00; /* drive number */ // FIXED 80 > 00 + boot[cnt++] = 0x00; /* reserved */ + boot[cnt++] = 0x29; /* boot sig */ + + RandgetBytes (boot + cnt, 4, FALSE); /* vol id */ + cnt += 4; + + memcpy (boot + cnt, ft->volume_name, 11); /* vol title */ + cnt += 11; + + switch(ft->size_fat) /* filesystem type */ + { + case 12: memcpy (boot + cnt, "FAT12 ", 8); break; + case 16: memcpy (boot + cnt, "FAT16 ", 8); break; + case 32: memcpy (boot + cnt, "FAT32 ", 8); break; + } + cnt += 8; + + memset (boot + cnt, 0, ft->size_fat==32 ? 420:448); /* boot code */ + cnt += ft->size_fat==32 ? 420:448; + boot[cnt++] = 0x55; + boot[cnt++] = 0xaa; /* boot sig */ +} + + +/* FAT32 FSInfo */ +static void PutFSInfo (unsigned char *sector, fatparams *ft) +{ + memset (sector, 0, 512); + sector[3]=0x41; /* LeadSig */ + sector[2]=0x61; + sector[1]=0x52; + sector[0]=0x52; + sector[484+3]=0x61; /* StrucSig */ + sector[484+2]=0x41; + sector[484+1]=0x72; + sector[484+0]=0x72; + + // Free cluster count + *(uint32 *)(sector + 488) = LE32 (ft->cluster_count - ft->size_root_dir / SECTOR_SIZE / ft->cluster_size); + + // Next free cluster + *(uint32 *)(sector + 492) = LE32 (2); + + sector[508+3]=0xaa; /* TrailSig */ + sector[508+2]=0x55; + sector[508+1]=0x00; + sector[508+0]=0x00; +} + + +int +FormatFat (unsigned __int64 startSector, fatparams * ft, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat) +{ + int write_buf_cnt = 0; + char sector[SECTOR_SIZE], *write_buf; + unsigned __int64 nSecNo = startSector; + int x, n; + int retVal; + char temporaryKey[MASTER_KEYDATA_SIZE]; + + LARGE_INTEGER startOffset; + LARGE_INTEGER newOffset; + + // Seek to start sector + startOffset.QuadPart = startSector * SECTOR_SIZE; + if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) + || newOffset.QuadPart != startOffset.QuadPart) + { + return ERR_VOL_SEEKING; + } + + /* Write the data area */ + + write_buf = (char *)TCalloc (FormatWriteBufferSize); + if (!write_buf) + return ERR_OUTOFMEMORY; + + memset (sector, 0, sizeof (sector)); + + PutBoot (ft, (unsigned char *) sector); + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + + /* fat32 boot area */ + if (ft->size_fat == 32) + { + /* fsinfo */ + PutFSInfo((unsigned char *) sector, ft); + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + + /* reserved */ + while (nSecNo - startSector < 6) + { + memset (sector, 0, sizeof (sector)); + sector[508+3]=0xaa; /* TrailSig */ + sector[508+2]=0x55; + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + } + + /* bootsector backup */ + memset (sector, 0, sizeof (sector)); + PutBoot (ft, (unsigned char *) sector); + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + + PutFSInfo((unsigned char *) sector, ft); + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + } + + /* reserved */ + while (nSecNo - startSector < (unsigned int)ft->reserved) + { + memset (sector, 0, sizeof (sector)); + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + } + + /* write fat */ + for (x = 1; x <= ft->fats; x++) + { + for (n = 0; n < ft->fat_length; n++) + { + memset (sector, 0, SECTOR_SIZE); + + if (n == 0) + { + unsigned char fat_sig[12]; + if (ft->size_fat == 32) + { + fat_sig[0] = (unsigned char) ft->media; + fat_sig[1] = fat_sig[2] = 0xff; + fat_sig[3] = 0x0f; + fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff; + fat_sig[7] = 0x0f; + fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff; + fat_sig[11] = 0x0f; + memcpy (sector, fat_sig, 12); + } + else if (ft->size_fat == 16) + { + fat_sig[0] = (unsigned char) ft->media; + fat_sig[1] = 0xff; + fat_sig[2] = 0xff; + fat_sig[3] = 0xff; + memcpy (sector, fat_sig, 4); + } + else if (ft->size_fat == 12) + { + fat_sig[0] = (unsigned char) ft->media; + fat_sig[1] = 0xff; + fat_sig[2] = 0xff; + fat_sig[3] = 0x00; + memcpy (sector, fat_sig, 4); + } + } + + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + } + } + + + /* write rootdir */ + for (x = 0; x < ft->size_root_dir / SECTOR_SIZE; x++) + { + memset (sector, 0, SECTOR_SIZE); + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + + } + + /* Fill the rest of the data area with random data */ + + if(!quickFormat) + { + if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo)) + goto fail; + + /* Generate a random temporary key set to be used for "dummy" encryption that will fill + the free disk space (data area) with random data. This is necessary for plausible + deniability of hidden volumes (and also reduces the amount of predictable plaintext + within the volume). */ + + // Temporary master key + if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE)) + goto fail; + + // Temporary secondary key (XTS mode) + if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE)) + goto fail; + + retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); + if (retVal != ERR_SUCCESS) + { + burn (temporaryKey, sizeof(temporaryKey)); + return retVal; + } + if (!EAInitMode (cryptoInfo)) + { + burn (temporaryKey, sizeof(temporaryKey)); + return ERR_MODE_INIT_FAILED; + } + + x = ft->num_sectors - ft->reserved - ft->size_root_dir / SECTOR_SIZE - ft->fat_length * 2; + while (x--) + { + /* Generate random plaintext. Note that reused plaintext blocks are not a concern here + since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do + occur commonly on media in the "real world", so it might actually be a fatal mistake + to try to avoid them completely. */ + +#if RNG_POOL_SIZE < SECTOR_SIZE +#error RNG_POOL_SIZE < SECTOR_SIZE +#endif + if (!RandpeekBytes (sector, SECTOR_SIZE)) + goto fail; + + // Encrypt the random plaintext and write it to the disk + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + } + UpdateProgressBar (nSecNo); + } + else + UpdateProgressBar (ft->num_sectors); + + if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo)) + goto fail; + + TCfree (write_buf); + burn (temporaryKey, sizeof(temporaryKey)); + return 0; + +fail: + + TCfree (write_buf); + burn (temporaryKey, sizeof(temporaryKey)); + return ERR_OS_ERROR; +} diff --git a/Common/FAT.H b/Common/FAT.H index 33cc00e..2905d9e 100644 --- a/Common/FAT.H +++ b/Common/FAT.H @@ -1,66 +1,66 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -typedef struct fatparams_t -{ - char volume_name[11]; - unsigned int num_sectors; /* total number of sectors */ - int cluster_count; /* number of clusters */ - int size_root_dir; /* size of the root directory in bytes */ - int size_fat; /* size of FAT */ - int fats; - int media; - int cluster_size; - int fat_length; - int dir_entries; - int sector_size; - int hidden; - __int16 reserved; - int sectors; - unsigned int total_sect; - - int heads; - int secs_track; - -} fatparams; - - -struct msdos_boot_sector -{ - unsigned char boot_jump[3]; /* Boot strap short or near jump */ - char system_id[8]; /* Name - can be used to special case - partition manager volumes */ - unsigned char sector_size[2]; /* bytes per logical sector */ - unsigned char cluster_size; /* sectors/cluster */ - unsigned short reserved;/* reserved sectors */ - unsigned char fats; /* number of FATs */ - unsigned char dir_entries[2]; /* root directory entries */ - unsigned char sectors[2]; /* number of sectors */ - unsigned char media; /* media code */ - unsigned short fat_length; /* sectors/FAT */ - unsigned short secs_track; /* sectors per track */ - unsigned short heads; /* number of heads */ - unsigned __int32 hidden; /* hidden sectors */ - unsigned __int32 total_sect; /* number of sectors (if sectors == 0) */ - unsigned char drive_number; /* BIOS drive number */ - unsigned char RESERVED; /* Unused */ - unsigned char ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */ - unsigned char volume_id[4]; /* Volume ID number */ - char volume_label[11]; /* Volume label */ - char fs_type[8]; /* Typically FAT12, FAT16, or FAT32 */ - unsigned char boot_code[448]; /* Boot code (or message) */ - unsigned short boot_sign; /* 0xAA55 */ -}; - - -void GetFatParams ( fatparams *ft ); -void PutBoot ( fatparams *ft , unsigned char *boot ); -int FormatFat (unsigned __int64 startSector, fatparams * ft, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat); +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +typedef struct fatparams_t +{ + char volume_name[11]; + unsigned int num_sectors; /* total number of sectors */ + int cluster_count; /* number of clusters */ + int size_root_dir; /* size of the root directory in bytes */ + int size_fat; /* size of FAT */ + int fats; + int media; + int cluster_size; + int fat_length; + uint16 dir_entries; + uint16 sector_size; + int hidden; + __int16 reserved; + uint16 sectors; + unsigned int total_sect; + + uint16 heads; + uint16 secs_track; + +} fatparams; + + +struct msdos_boot_sector +{ + unsigned char boot_jump[3]; /* Boot strap short or near jump */ + char system_id[8]; /* Name - can be used to special case + partition manager volumes */ + unsigned char sector_size[2]; /* bytes per logical sector */ + unsigned char cluster_size; /* sectors/cluster */ + unsigned short reserved;/* reserved sectors */ + unsigned char fats; /* number of FATs */ + unsigned char dir_entries[2]; /* root directory entries */ + unsigned char sectors[2]; /* number of sectors */ + unsigned char media; /* media code */ + unsigned short fat_length; /* sectors/FAT */ + unsigned short secs_track; /* sectors per track */ + unsigned short heads; /* number of heads */ + unsigned __int32 hidden; /* hidden sectors */ + unsigned __int32 total_sect; /* number of sectors (if sectors == 0) */ + unsigned char drive_number; /* BIOS drive number */ + unsigned char RESERVED; /* Unused */ + unsigned char ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */ + unsigned char volume_id[4]; /* Volume ID number */ + char volume_label[11]; /* Volume label */ + char fs_type[8]; /* Typically FAT12, FAT16, or FAT32 */ + unsigned char boot_code[448]; /* Boot code (or message) */ + unsigned short boot_sign; /* 0xAA55 */ +}; + + +void GetFatParams ( fatparams *ft ); +void PutBoot ( fatparams *ft , unsigned char *boot ); +int FormatFat (unsigned __int64 startSector, fatparams * ft, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat); diff --git a/Common/FORMAT.C b/Common/FORMAT.C index 3b63e7a..27da387 100644 --- a/Common/FORMAT.C +++ b/Common/FORMAT.C @@ -1,984 +1,993 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include -#include - -#include "Tcdefs.h" - -#include "Common.h" -#include "Crypto.h" -#include "Fat.h" -#include "Format.h" -#include "Random.h" -#include "Volumes.h" - -#include "Apidrvr.h" -#include "Dlgcode.h" -#include "Language.h" -#include "Progress.h" -#include "Resource.h" -#include "Format/FormatCom.h" -#include "Format/Tcformat.h" - - -uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize) -{ - uint64 reservedSize; - - if (hiddenVolume) - { - // Reserve free space at the end of the host filesystem - if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD) - reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE; - else - reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; // Ensure size of a hidden volume larger than TC_VOLUME_SMALL_SIZE_THRESHOLD is a multiple of the maximum supported sector size - } - else - { - reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE; - } - - if (volumeSize < reservedSize) - return 0; - - return volumeSize - reservedSize; -} - - -int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams) -{ - int nStatus; - PCRYPTO_INFO cryptoInfo = NULL; - HANDLE dev = INVALID_HANDLE_VALUE; - DWORD dwError; - char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - unsigned __int64 num_sectors, startSector; - fatparams ft; - FILETIME ftCreationTime; - FILETIME ftLastWriteTime; - FILETIME ftLastAccessTime; - BOOL bTimeStampValid = FALSE; - BOOL bInstantRetryOtherFilesys = FALSE; - char dosDev[TC_MAX_PATH] = { 0 }; - char devName[MAX_PATH] = { 0 }; - int driveLetter = -1; - WCHAR deviceName[MAX_PATH]; - uint64 dataOffset, dataAreaSize; - LARGE_INTEGER offset; - BOOL bFailedRequiredDASD = FALSE; - - - /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is - less than TC_MAX_FAT_FS_SIZE, the user is asked within this function whether he wants to instantly - retry FAT format instead (to avoid having to re-create the whole container again). If the user - answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed - and some destructive operations that were performed during the first attempt must be (and are) skipped. - Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format', - determine whether they (or their portions) need to be skipped during such a second attempt; if so, - use the 'bInstantRetryOtherFilesys' flag to skip them. */ - - if (volParams->hiddenVol) - { - dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size; - } - else - { - if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE) - return ERR_VOL_SIZE_WRONG; - - dataOffset = TC_VOLUME_DATA_OFFSET; - } - - dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size); - - num_sectors = dataAreaSize / SECTOR_SIZE; - - if (volParams->bDevice) - { - strcpy ((char *)deviceName, volParams->volumePath); - ToUNICODE ((char *)deviceName); - - driveLetter = GetDiskDeviceDriveLetter (deviceName); - } - - VirtualLock (header, sizeof (header)); - - nStatus = CreateVolumeHeaderInMemory (FALSE, - header, - volParams->ea, - FIRST_MODE_OF_OPERATION_ID, - volParams->password, - volParams->pkcs5, - NULL, - &cryptoInfo, - dataAreaSize, - volParams->hiddenVol ? dataAreaSize : 0, - dataOffset, - dataAreaSize, - 0, - volParams->headerFlags, - FALSE); - - if (nStatus != 0) - { - burn (header, sizeof (header)); - VirtualUnlock (header, sizeof (header)); - return nStatus; - } - -begin_format: - - if (volParams->bDevice) - { - /* Device-hosted volume */ - - DWORD dwResult; - int nPass; - - if (FakeDosNameForDevice (volParams->volumePath, dosDev, devName, FALSE) != 0) - return ERR_OS_ERROR; - - if (IsDeviceMounted (devName)) - { - if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE) - { - Error ("FORMAT_CANT_DISMOUNT_FILESYS"); - nStatus = ERR_DONT_REPORT; - goto error; - } - - /* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver - would otherwise prevent us from writing to hidden sectors). */ - - if (!DeviceIoControl (dev, - FSCTL_ALLOW_EXTENDED_DASD_IO, - NULL, - 0, - NULL, - 0, - &dwResult, - NULL)) - { - bFailedRequiredDASD = TRUE; - } - } - else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1) - { - // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition - // to which no drive letter has been assigned under the system. This problem can be worked - // around by assigning a drive letter to the partition temporarily. - - char szDriveLetter[] = { 'A', ':', 0 }; - char rootPath[] = { 'A', ':', '\\', 0 }; - char uniqVolName[MAX_PATH+1] = { 0 }; - int tmpDriveLetter = -1; - BOOL bResult = FALSE; - - tmpDriveLetter = GetFirstAvailableDrive (); - - if (tmpDriveLetter != -1) - { - rootPath[0] += tmpDriveLetter; - szDriveLetter[0] += tmpDriveLetter; - - if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath)) - { - bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH); - - DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE, - szDriveLetter, - volParams->volumePath); - - if (bResult - && SetVolumeMountPoint (rootPath, uniqVolName)) - { - // The drive letter can be removed now - DeleteVolumeMountPoint (rootPath); - } - } - } - } - - // For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be - // redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed, - // bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However, - // for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly - // send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result. - - DeviceIoControl (dev, - FSCTL_ALLOW_EXTENDED_DASD_IO, - NULL, - 0, - NULL, - 0, - &dwResult, - NULL); - - - // If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open - // so that the filesystem driver does not prevent us from formatting hidden sectors. - for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++) - { - int retryCount; - - retryCount = 0; - - // Try exclusive access mode first - // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries). - while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES) - { - dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - - if (retryCount > 1) - Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY); - } - - if (dev == INVALID_HANDLE_VALUE) - { - // Exclusive access denied -- retry in shared mode - dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (dev != INVALID_HANDLE_VALUE) - { - if (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2)) - { - nStatus = ERR_DONT_REPORT; - goto error; - } - } - else - { - handleWin32Error (volParams->hwndDlg); - Error ("CANT_ACCESS_VOL"); - nStatus = ERR_DONT_REPORT; - goto error; - } - } - - if (volParams->hiddenVol || bInstantRetryOtherFilesys) - break; // The following "quick format" operation would damage the outer volume - - if (nPass == 0) - { - char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE]; - DWORD bw; - - // Perform pseudo "quick format" so that the filesystem driver does not prevent us from - // formatting hidden sectors - memset (buf, 0, sizeof (buf)); - - if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - FlushFileBuffers (dev); - CloseHandle (dev); - dev = INVALID_HANDLE_VALUE; - } - } - - if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL)) - { - Error ("FORMAT_CANT_DISMOUNT_FILESYS"); - nStatus = ERR_DONT_REPORT; - goto error; - } - } - else - { - /* File-hosted volume */ - - // We could support FILE_ATTRIBUTE_HIDDEN as an option - // (Now if the container has hidden or system file attribute, the OS will not allow - // overwritting it; so the user will have to delete it manually). - dev = CreateFile (volParams->volumePath, GENERIC_WRITE, - (volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0, - NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); - - if (dev == INVALID_HANDLE_VALUE) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - if (!volParams->hiddenVol && !bInstantRetryOtherFilesys) - { - LARGE_INTEGER volumeSize; - volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE; - - if (volParams->sparseFileSwitch && volParams->quickFormat) - { - // Create as sparse file container - DWORD tmp; - if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - } - - // Preallocate the file - if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN) - || !SetEndOfFile (dev) - || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0) - { - nStatus = ERR_OS_ERROR; - goto error; - } - } - } - - if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp) - { - /* Remember the container timestamp (used to reset file date and time of file-hosted - containers to preserve plausible deniability of hidden volume) */ - if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) - { - bTimeStampValid = FALSE; - MessageBoxW (volParams->hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); - } - else - bTimeStampValid = TRUE; - } - - KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW); - - /* Volume header */ - - // Hidden volume setup - if (volParams->hiddenVol) - { - LARGE_INTEGER headerOffset; - - // Check hidden volume size - if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE) - { - nStatus = ERR_VOL_SIZE_WRONG; - goto error; - } - - // Seek to hidden volume header location - - headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET; - - if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - } - else if (bInstantRetryOtherFilesys) - { - // The previous file system format failed and the user wants to try again with a different file system. - // The volume header had been written successfully so we need to seek to the byte after the header. - - LARGE_INTEGER offset; - offset.QuadPart = TC_VOLUME_DATA_OFFSET; - if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - } - - if (!bInstantRetryOtherFilesys) - { - // Write the volume header - if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data - if (!volParams->hiddenVol) - { - byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - ZeroMemory (buf, sizeof (buf)); - if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR) - { - nStatus = ERR_OS_ERROR; - goto error; - } - } - } - - if (volParams->hiddenVol) - { - // Calculate data area position of hidden volume - cryptoInfo->hiddenVolumeOffset = dataOffset; - - // Validate the offset - if (dataOffset % SECTOR_SIZE != 0) - { - nStatus = ERR_VOL_SIZE_WRONG; - goto error; - } - - volParams->quickFormat = TRUE; // To entirely format a hidden volume would be redundant - } - - /* Data area */ - startSector = dataOffset / SECTOR_SIZE; - - // Format filesystem - - switch (volParams->fileSystem) - { - case FILESYS_NONE: - case FILESYS_NTFS: - - if (volParams->bDevice && !StartFormatWriteThread()) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat); - - if (volParams->bDevice) - StopFormatWriteThread(); - - break; - - case FILESYS_FAT: - if (num_sectors > 0xFFFFffff) - { - nStatus = ERR_VOL_SIZE_WRONG; - goto error; - } - - // Calculate the fats, root dir etc - ft.num_sectors = (unsigned int) (num_sectors); - ft.cluster_size = volParams->clusterSize; - memcpy (ft.volume_name, "NO NAME ", 11); - GetFatParams (&ft); - *(volParams->realClusterSize) = ft.cluster_size * SECTOR_SIZE; - - if (volParams->bDevice && !StartFormatWriteThread()) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat); - - if (volParams->bDevice) - StopFormatWriteThread(); - - break; - - default: - nStatus = ERR_PARAMETER_INCORRECT; - goto error; - } - - if (nStatus != ERR_SUCCESS) - goto error; - - // Write header backup - offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE; - - if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - nStatus = CreateVolumeHeaderInMemory (FALSE, - header, - volParams->ea, - FIRST_MODE_OF_OPERATION_ID, - volParams->password, - volParams->pkcs5, - cryptoInfo->master_keydata, - &cryptoInfo, - dataAreaSize, - volParams->hiddenVol ? dataAreaSize : 0, - dataOffset, - dataAreaSize, - 0, - volParams->headerFlags, - FALSE); - - if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - // Fill reserved header sectors (including the backup header area) with random data - if (!volParams->hiddenVol) - { - nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, FALSE); - - if (nStatus != ERR_SUCCESS) - goto error; - } - -error: - dwError = GetLastError(); - - burn (header, sizeof (header)); - VirtualUnlock (header, sizeof (header)); - - if (dev != INVALID_HANDLE_VALUE) - { - if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0) - { - // Remove preallocated part before closing file handle if format failed - if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0) - SetEndOfFile (dev); - } - - FlushFileBuffers (dev); - - if (bTimeStampValid) - { - // Restore the container timestamp (to preserve plausible deniability of the hidden volume) - if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) - MessageBoxW (volParams->hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); - } - - CloseHandle (dev); - dev = INVALID_HANDLE_VALUE; - } - - if (nStatus != 0) - { - SetLastError(dwError); - goto fv_end; - } - - if (volParams->fileSystem == FILESYS_NTFS) - { - // Quick-format volume as NTFS - int driveNo = GetLastAvailableDrive (); - MountOptions mountOptions; - int retCode; - - ZeroMemory (&mountOptions, sizeof (mountOptions)); - - if (driveNo == -1) - { - MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND); - MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); - - nStatus = ERR_NO_FREE_DRIVES; - goto fv_end; - } - - mountOptions.ReadOnly = FALSE; - mountOptions.Removable = FALSE; - mountOptions.ProtectHiddenVolume = FALSE; - mountOptions.PreserveTimestamp = bPreserveTimestamp; - mountOptions.PartitionInInactiveSysEncScope = FALSE; - mountOptions.UseBackupHeader = FALSE; - - if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1) - { - MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND); - MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); - nStatus = ERR_VOL_MOUNT_FAILED; - goto fv_end; - } - - if (!IsAdmin () && IsUacSupported ()) - retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize); - else - retCode = FormatNtfs (driveNo, volParams->clusterSize); - - if (retCode != TRUE) - { - if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE)) - MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); - - if (dataAreaSize <= TC_MAX_FAT_FS_SIZE) - { - if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES) - { - // NTFS format failed and the user wants to try FAT format immediately - volParams->fileSystem = FILESYS_FAT; - bInstantRetryOtherFilesys = TRUE; - volParams->quickFormat = TRUE; // Volume has already been successfully TC-formatted - volParams->clusterSize = 0; // Default cluster size - goto begin_format; - } - } - else - Error ("FORMAT_NTFS_FAILED"); - - nStatus = ERR_DONT_REPORT; - goto fv_end; - } - - if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE)) - MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); - } - -fv_end: - dwError = GetLastError(); - - if (dosDev[0]) - RemoveFakeDosName (volParams->volumePath, dosDev); - - crypto_close (cryptoInfo); - - SetLastError (dwError); - return nStatus; -} - - -int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat) -{ - int write_buf_cnt = 0; - char sector[SECTOR_SIZE], *write_buf; - unsigned __int64 nSecNo = startSector; - int retVal = 0; - DWORD err; - char temporaryKey[MASTER_KEYDATA_SIZE]; - char originalK2[MASTER_KEYDATA_SIZE]; - - LARGE_INTEGER startOffset; - LARGE_INTEGER newOffset; - - // Seek to start sector - startOffset.QuadPart = startSector * SECTOR_SIZE; - if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) - || newOffset.QuadPart != startOffset.QuadPart) - { - return ERR_OS_ERROR; - } - - write_buf = (char *)TCalloc (WRITE_BUF_SIZE); - if (!write_buf) - return ERR_OUTOFMEMORY; - - VirtualLock (temporaryKey, sizeof (temporaryKey)); - VirtualLock (originalK2, sizeof (originalK2)); - - memset (sector, 0, sizeof (sector)); - - // Remember the original secondary key (XTS mode) before generating a temporary one - memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2)); - - /* Fill the rest of the data area with random data */ - - if(!quickFormat) - { - /* Generate a random temporary key set to be used for "dummy" encryption that will fill - the free disk space (data area) with random data. This is necessary for plausible - deniability of hidden volumes. */ - - // Temporary master key - if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE)) - goto fail; - - // Temporary secondary key (XTS mode) - if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE)) - goto fail; - - retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); - if (retVal != ERR_SUCCESS) - goto fail; - - if (!EAInitMode (cryptoInfo)) - { - retVal = ERR_MODE_INIT_FAILED; - goto fail; - } - - while (num_sectors--) - { - /* Generate random plaintext. Note that reused plaintext blocks are not a concern here - since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do - occur commonly on media in the "real world", so it might actually be a fatal mistake - to try to avoid them completely. */ - -#if RNG_POOL_SIZE < SECTOR_SIZE -#error RNG_POOL_SIZE < SECTOR_SIZE -#endif - - if (!RandpeekBytes (sector, SECTOR_SIZE)) - goto fail; - - // Encrypt the random plaintext and write it to the disk - if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, - cryptoInfo) == FALSE) - goto fail; - } - - if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo)) - goto fail; - } - else - nSecNo = num_sectors; - - UpdateProgressBar (nSecNo); - - // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately - memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2)); - - // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately - retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks); - if (retVal != ERR_SUCCESS) - goto fail; - if (!EAInitMode (cryptoInfo)) - { - retVal = ERR_MODE_INIT_FAILED; - goto fail; - } - - burn (temporaryKey, sizeof(temporaryKey)); - burn (originalK2, sizeof(originalK2)); - VirtualUnlock (temporaryKey, sizeof (temporaryKey)); - VirtualUnlock (originalK2, sizeof (originalK2)); - TCfree (write_buf); - - return 0; - -fail: - err = GetLastError(); - - burn (temporaryKey, sizeof(temporaryKey)); - burn (originalK2, sizeof(originalK2)); - VirtualUnlock (temporaryKey, sizeof (temporaryKey)); - VirtualUnlock (originalK2, sizeof (originalK2)); - TCfree (write_buf); - - SetLastError (err); - return (retVal ? retVal : ERR_OS_ERROR); -} - - -volatile BOOLEAN FormatExResult; - -BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter) -{ - if (command == FMIFS_DONE) - FormatExResult = *(BOOLEAN *) parameter; - return TRUE; -} - -BOOL FormatNtfs (int driveNo, int clusterSize) -{ - WCHAR dir[8] = { driveNo + 'A', 0 }; - PFORMATEX FormatEx; - HMODULE hModule = LoadLibrary ("fmifs.dll"); - int i; - - if (hModule == NULL) - return FALSE; - - if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx"))) - { - FreeLibrary (hModule); - return FALSE; - } - - wcscat (dir, L":\\"); - - FormatExResult = FALSE; - - // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS. - // It often helps to retry several times. - for (i = 0; i < 10 && FormatExResult != TRUE; i++) - { - FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback); - } - - FreeLibrary (hModule); - return FormatExResult; -} - - -BOOL WriteSector (void *dev, char *sector, - char *write_buf, int *write_buf_cnt, - __int64 *nSecNo, PCRYPTO_INFO cryptoInfo) -{ - static __int32 updateTime = 0; - - (*nSecNo)++; - - memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE); - (*write_buf_cnt) += SECTOR_SIZE; - - if (*write_buf_cnt == WRITE_BUF_SIZE && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo)) - return FALSE; - - if (GetTickCount () - updateTime > 25) - { - if (UpdateProgressBar (*nSecNo)) - return FALSE; - - updateTime = GetTickCount (); - } - - return TRUE; - -} - - -static volatile BOOL WriteThreadRunning; -static volatile BOOL WriteThreadExitRequested; -static HANDLE WriteThreadHandle; - -static byte *WriteThreadBuffer; -static HANDLE WriteBufferEmptyEvent; -static HANDLE WriteBufferFullEvent; - -static volatile HANDLE WriteRequestHandle; -static volatile int WriteRequestSize; -static volatile DWORD WriteRequestResult; - - -static void __cdecl FormatWriteThreadProc (void *arg) -{ - DWORD bytesWritten; - - SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST); - - while (!WriteThreadExitRequested) - { - if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED) - { - handleWin32Error (NULL); - break; - } - - if (WriteThreadExitRequested) - break; - - if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL)) - WriteRequestResult = GetLastError(); - else - WriteRequestResult = ERROR_SUCCESS; - - if (!SetEvent (WriteBufferEmptyEvent)) - { - handleWin32Error (NULL); - break; - } - } - - WriteThreadRunning = FALSE; - _endthread(); -} - - -static BOOL StartFormatWriteThread () -{ - DWORD sysErr; - - WriteBufferEmptyEvent = NULL; - WriteBufferFullEvent = NULL; - WriteThreadBuffer = NULL; - - WriteBufferEmptyEvent = CreateEvent (NULL, FALSE, TRUE, NULL); - if (!WriteBufferEmptyEvent) - goto err; - - WriteBufferFullEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!WriteBufferFullEvent) - goto err; - - WriteThreadBuffer = TCalloc (WRITE_BUF_SIZE); - if (!WriteThreadBuffer) - { - SetLastError (ERROR_OUTOFMEMORY); - goto err; - } - - WriteThreadExitRequested = FALSE; - WriteRequestResult = ERROR_SUCCESS; - - WriteThreadHandle = (HANDLE) _beginthread (FormatWriteThreadProc, 0, NULL); - if ((uintptr_t) WriteThreadHandle == -1L) - goto err; - - WriteThreadRunning = TRUE; - return TRUE; - -err: - sysErr = GetLastError(); - - if (WriteBufferEmptyEvent) - CloseHandle (WriteBufferEmptyEvent); - if (WriteBufferFullEvent) - CloseHandle (WriteBufferFullEvent); - if (WriteThreadBuffer) - TCfree (WriteThreadBuffer); - - SetLastError (sysErr); - return FALSE; -} - - -static void StopFormatWriteThread () -{ - if (WriteThreadRunning) - { - WaitForSingleObject (WriteBufferEmptyEvent, INFINITE); - - WriteThreadExitRequested = TRUE; - SetEvent (WriteBufferFullEvent); - - WaitForSingleObject (WriteThreadHandle, INFINITE); - } - - CloseHandle (WriteBufferEmptyEvent); - CloseHandle (WriteBufferFullEvent); - TCfree (WriteThreadBuffer); -} - - -BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo) -{ - UINT64_STRUCT unitNo; - DWORD bytesWritten; - - if (*write_buf_cnt == 0) - return TRUE; - - unitNo.Value = (*nSecNo - *write_buf_cnt / SECTOR_SIZE) * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE; - - EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo); - - if (WriteThreadRunning) - { - if (WaitForSingleObject (WriteBufferEmptyEvent, INFINITE) == WAIT_FAILED) - return FALSE; - - if (WriteRequestResult != ERROR_SUCCESS) - { - SetEvent (WriteBufferEmptyEvent); - SetLastError (WriteRequestResult); - return FALSE; - } - - memcpy (WriteThreadBuffer, write_buf, *write_buf_cnt); - WriteRequestHandle = dev; - WriteRequestSize = *write_buf_cnt; - - if (!SetEvent (WriteBufferFullEvent)) - return FALSE; - } - else - { - if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL)) - return FALSE; - } - - *write_buf_cnt = 0; - return TRUE; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include +#include + +#include "Tcdefs.h" + +#include "Common.h" +#include "Crypto.h" +#include "Fat.h" +#include "Format.h" +#include "Random.h" +#include "Volumes.h" + +#include "Apidrvr.h" +#include "Dlgcode.h" +#include "Language.h" +#include "Progress.h" +#include "Resource.h" +#include "Format/FormatCom.h" +#include "Format/Tcformat.h" + +int FormatWriteBufferSize = 1024 * 1024; + + +uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize) +{ + uint64 reservedSize; + + if (hiddenVolume) + { + // Reserve free space at the end of the host filesystem + if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD) + reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE; + else + reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; // Ensure size of a hidden volume larger than TC_VOLUME_SMALL_SIZE_THRESHOLD is a multiple of the maximum supported sector size + } + else + { + reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE; + } + + if (volumeSize < reservedSize) + return 0; + + return volumeSize - reservedSize; +} + + +int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams) +{ + int nStatus; + PCRYPTO_INFO cryptoInfo = NULL; + HANDLE dev = INVALID_HANDLE_VALUE; + DWORD dwError; + char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + unsigned __int64 num_sectors, startSector; + fatparams ft; + FILETIME ftCreationTime; + FILETIME ftLastWriteTime; + FILETIME ftLastAccessTime; + BOOL bTimeStampValid = FALSE; + BOOL bInstantRetryOtherFilesys = FALSE; + char dosDev[TC_MAX_PATH] = { 0 }; + char devName[MAX_PATH] = { 0 }; + int driveLetter = -1; + WCHAR deviceName[MAX_PATH]; + uint64 dataOffset, dataAreaSize; + LARGE_INTEGER offset; + BOOL bFailedRequiredDASD = FALSE; + + + /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is + less than TC_MAX_FAT_FS_SIZE, the user is asked within this function whether he wants to instantly + retry FAT format instead (to avoid having to re-create the whole container again). If the user + answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed + and some destructive operations that were performed during the first attempt must be (and are) skipped. + Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format', + determine whether they (or their portions) need to be skipped during such a second attempt; if so, + use the 'bInstantRetryOtherFilesys' flag to skip them. */ + + if (volParams->hiddenVol) + { + dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size; + } + else + { + if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE) + return ERR_VOL_SIZE_WRONG; + + dataOffset = TC_VOLUME_DATA_OFFSET; + } + + dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size); + + num_sectors = dataAreaSize / SECTOR_SIZE; + + if (volParams->bDevice) + { + strcpy ((char *)deviceName, volParams->volumePath); + ToUNICODE ((char *)deviceName); + + driveLetter = GetDiskDeviceDriveLetter (deviceName); + } + + VirtualLock (header, sizeof (header)); + + nStatus = CreateVolumeHeaderInMemory (FALSE, + header, + volParams->ea, + FIRST_MODE_OF_OPERATION_ID, + volParams->password, + volParams->pkcs5, + NULL, + &cryptoInfo, + dataAreaSize, + volParams->hiddenVol ? dataAreaSize : 0, + dataOffset, + dataAreaSize, + 0, + volParams->headerFlags, + FALSE); + + if (nStatus != 0) + { + burn (header, sizeof (header)); + VirtualUnlock (header, sizeof (header)); + return nStatus; + } + +begin_format: + + if (volParams->bDevice) + { + /* Device-hosted volume */ + + DWORD dwResult; + int nPass; + + if (FakeDosNameForDevice (volParams->volumePath, dosDev, devName, FALSE) != 0) + return ERR_OS_ERROR; + + if (IsDeviceMounted (devName)) + { + if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE) + { + Error ("FORMAT_CANT_DISMOUNT_FILESYS"); + nStatus = ERR_DONT_REPORT; + goto error; + } + + /* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver + would otherwise prevent us from writing to hidden sectors). */ + + if (!DeviceIoControl (dev, + FSCTL_ALLOW_EXTENDED_DASD_IO, + NULL, + 0, + NULL, + 0, + &dwResult, + NULL)) + { + bFailedRequiredDASD = TRUE; + } + } + else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1) + { + // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition + // to which no drive letter has been assigned under the system. This problem can be worked + // around by assigning a drive letter to the partition temporarily. + + char szDriveLetter[] = { 'A', ':', 0 }; + char rootPath[] = { 'A', ':', '\\', 0 }; + char uniqVolName[MAX_PATH+1] = { 0 }; + int tmpDriveLetter = -1; + BOOL bResult = FALSE; + + tmpDriveLetter = GetFirstAvailableDrive (); + + if (tmpDriveLetter != -1) + { + rootPath[0] += (char) tmpDriveLetter; + szDriveLetter[0] += (char) tmpDriveLetter; + + if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath)) + { + bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH); + + DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE, + szDriveLetter, + volParams->volumePath); + + if (bResult + && SetVolumeMountPoint (rootPath, uniqVolName)) + { + // The drive letter can be removed now + DeleteVolumeMountPoint (rootPath); + } + } + } + } + + // For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be + // redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed, + // bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However, + // for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly + // send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result. + + DeviceIoControl (dev, + FSCTL_ALLOW_EXTENDED_DASD_IO, + NULL, + 0, + NULL, + 0, + &dwResult, + NULL); + + + // If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open + // so that the filesystem driver does not prevent us from formatting hidden sectors. + for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++) + { + int retryCount; + + retryCount = 0; + + // Try exclusive access mode first + // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries). + while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES) + { + dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + + if (retryCount > 1) + Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY); + } + + if (dev == INVALID_HANDLE_VALUE) + { + // Exclusive access denied -- retry in shared mode + dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (dev != INVALID_HANDLE_VALUE) + { + if (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2)) + { + nStatus = ERR_DONT_REPORT; + goto error; + } + } + else + { + handleWin32Error (volParams->hwndDlg); + Error ("CANT_ACCESS_VOL"); + nStatus = ERR_DONT_REPORT; + goto error; + } + } + + if (volParams->hiddenVol || bInstantRetryOtherFilesys) + break; // The following "quick format" operation would damage the outer volume + + if (nPass == 0) + { + char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE]; + DWORD bw; + + // Perform pseudo "quick format" so that the filesystem driver does not prevent us from + // formatting hidden sectors + memset (buf, 0, sizeof (buf)); + + if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + FlushFileBuffers (dev); + CloseHandle (dev); + dev = INVALID_HANDLE_VALUE; + } + } + + if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL)) + { + Error ("FORMAT_CANT_DISMOUNT_FILESYS"); + nStatus = ERR_DONT_REPORT; + goto error; + } + } + else + { + /* File-hosted volume */ + + dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE, + (volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0, + NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); + + if (dev == INVALID_HANDLE_VALUE) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + DisableFileCompression (dev); + + if (!volParams->hiddenVol && !bInstantRetryOtherFilesys) + { + LARGE_INTEGER volumeSize; + volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE; + + if (volParams->sparseFileSwitch && volParams->quickFormat) + { + // Create as sparse file container + DWORD tmp; + if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + } + + // Preallocate the file + if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN) + || !SetEndOfFile (dev) + || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0) + { + nStatus = ERR_OS_ERROR; + goto error; + } + } + } + + if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp) + { + /* Remember the container timestamp (used to reset file date and time of file-hosted + containers to preserve plausible deniability of hidden volume) */ + if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) + { + bTimeStampValid = FALSE; + MessageBoxW (volParams->hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); + } + else + bTimeStampValid = TRUE; + } + + KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW); + + /* Volume header */ + + // Hidden volume setup + if (volParams->hiddenVol) + { + LARGE_INTEGER headerOffset; + + // Check hidden volume size + if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE) + { + nStatus = ERR_VOL_SIZE_WRONG; + goto error; + } + + // Seek to hidden volume header location + + headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET; + + if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + } + else if (bInstantRetryOtherFilesys) + { + // The previous file system format failed and the user wants to try again with a different file system. + // The volume header had been written successfully so we need to seek to the byte after the header. + + LARGE_INTEGER offset; + offset.QuadPart = TC_VOLUME_DATA_OFFSET; + if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + } + + if (!bInstantRetryOtherFilesys) + { + // Write the volume header + if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data + if (!volParams->hiddenVol) + { + byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + ZeroMemory (buf, sizeof (buf)); + if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR) + { + nStatus = ERR_OS_ERROR; + goto error; + } + } + } + + if (volParams->hiddenVol) + { + // Calculate data area position of hidden volume + cryptoInfo->hiddenVolumeOffset = dataOffset; + + // Validate the offset + if (dataOffset % SECTOR_SIZE != 0) + { + nStatus = ERR_VOL_SIZE_WRONG; + goto error; + } + + volParams->quickFormat = TRUE; // To entirely format a hidden volume would be redundant + } + + /* Data area */ + startSector = dataOffset / SECTOR_SIZE; + + // Format filesystem + + switch (volParams->fileSystem) + { + case FILESYS_NONE: + case FILESYS_NTFS: + + if (volParams->bDevice && !StartFormatWriteThread()) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat); + + if (volParams->bDevice) + StopFormatWriteThread(); + + break; + + case FILESYS_FAT: + if (num_sectors > 0xFFFFffff) + { + nStatus = ERR_VOL_SIZE_WRONG; + goto error; + } + + // Calculate the fats, root dir etc + ft.num_sectors = (unsigned int) (num_sectors); + ft.cluster_size = volParams->clusterSize; + memcpy (ft.volume_name, "NO NAME ", 11); + GetFatParams (&ft); + *(volParams->realClusterSize) = ft.cluster_size * SECTOR_SIZE; + + if (volParams->bDevice && !StartFormatWriteThread()) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat); + + if (volParams->bDevice) + StopFormatWriteThread(); + + break; + + default: + nStatus = ERR_PARAMETER_INCORRECT; + goto error; + } + + if (nStatus != ERR_SUCCESS) + goto error; + + // Write header backup + offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE; + + if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + nStatus = CreateVolumeHeaderInMemory (FALSE, + header, + volParams->ea, + FIRST_MODE_OF_OPERATION_ID, + volParams->password, + volParams->pkcs5, + cryptoInfo->master_keydata, + &cryptoInfo, + dataAreaSize, + volParams->hiddenVol ? dataAreaSize : 0, + dataOffset, + dataAreaSize, + 0, + volParams->headerFlags, + FALSE); + + if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + // Fill reserved header sectors (including the backup header area) with random data + if (!volParams->hiddenVol) + { + nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, FALSE); + + if (nStatus != ERR_SUCCESS) + goto error; + } + +#ifndef DEBUG + if (volParams->quickFormat && volParams->fileSystem != FILESYS_NTFS) + Sleep (500); // User-friendly GUI +#endif + +error: + dwError = GetLastError(); + + burn (header, sizeof (header)); + VirtualUnlock (header, sizeof (header)); + + if (dev != INVALID_HANDLE_VALUE) + { + if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0) + { + // Remove preallocated part before closing file handle if format failed + if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0) + SetEndOfFile (dev); + } + + FlushFileBuffers (dev); + + if (bTimeStampValid) + { + // Restore the container timestamp (to preserve plausible deniability of the hidden volume) + if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) + MessageBoxW (volParams->hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); + } + + CloseHandle (dev); + dev = INVALID_HANDLE_VALUE; + } + + if (nStatus != 0) + { + SetLastError(dwError); + goto fv_end; + } + + if (volParams->fileSystem == FILESYS_NTFS) + { + // Quick-format volume as NTFS + int driveNo = GetLastAvailableDrive (); + MountOptions mountOptions; + int retCode; + + ZeroMemory (&mountOptions, sizeof (mountOptions)); + + if (driveNo == -1) + { + MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND); + MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); + + nStatus = ERR_NO_FREE_DRIVES; + goto fv_end; + } + + mountOptions.ReadOnly = FALSE; + mountOptions.Removable = FALSE; + mountOptions.ProtectHiddenVolume = FALSE; + mountOptions.PreserveTimestamp = bPreserveTimestamp; + mountOptions.PartitionInInactiveSysEncScope = FALSE; + mountOptions.UseBackupHeader = FALSE; + + if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1) + { + MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND); + MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); + nStatus = ERR_VOL_MOUNT_FAILED; + goto fv_end; + } + + if (!IsAdmin () && IsUacSupported ()) + retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize); + else + retCode = FormatNtfs (driveNo, volParams->clusterSize); + + if (retCode != TRUE) + { + if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE)) + MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); + + if (dataAreaSize <= TC_MAX_FAT_FS_SIZE) + { + if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES) + { + // NTFS format failed and the user wants to try FAT format immediately + volParams->fileSystem = FILESYS_FAT; + bInstantRetryOtherFilesys = TRUE; + volParams->quickFormat = TRUE; // Volume has already been successfully TC-formatted + volParams->clusterSize = 0; // Default cluster size + goto begin_format; + } + } + else + Error ("FORMAT_NTFS_FAILED"); + + nStatus = ERR_DONT_REPORT; + goto fv_end; + } + + if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE)) + MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); + } + +fv_end: + dwError = GetLastError(); + + if (dosDev[0]) + RemoveFakeDosName (volParams->volumePath, dosDev); + + crypto_close (cryptoInfo); + + SetLastError (dwError); + return nStatus; +} + + +int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat) +{ + int write_buf_cnt = 0; + char sector[SECTOR_SIZE], *write_buf; + unsigned __int64 nSecNo = startSector; + int retVal = 0; + DWORD err; + char temporaryKey[MASTER_KEYDATA_SIZE]; + char originalK2[MASTER_KEYDATA_SIZE]; + + LARGE_INTEGER startOffset; + LARGE_INTEGER newOffset; + + // Seek to start sector + startOffset.QuadPart = startSector * SECTOR_SIZE; + if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) + || newOffset.QuadPart != startOffset.QuadPart) + { + return ERR_OS_ERROR; + } + + write_buf = (char *)TCalloc (FormatWriteBufferSize); + if (!write_buf) + return ERR_OUTOFMEMORY; + + VirtualLock (temporaryKey, sizeof (temporaryKey)); + VirtualLock (originalK2, sizeof (originalK2)); + + memset (sector, 0, sizeof (sector)); + + // Remember the original secondary key (XTS mode) before generating a temporary one + memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2)); + + /* Fill the rest of the data area with random data */ + + if(!quickFormat) + { + /* Generate a random temporary key set to be used for "dummy" encryption that will fill + the free disk space (data area) with random data. This is necessary for plausible + deniability of hidden volumes. */ + + // Temporary master key + if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE)) + goto fail; + + // Temporary secondary key (XTS mode) + if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE)) + goto fail; + + retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); + if (retVal != ERR_SUCCESS) + goto fail; + + if (!EAInitMode (cryptoInfo)) + { + retVal = ERR_MODE_INIT_FAILED; + goto fail; + } + + while (num_sectors--) + { + /* Generate random plaintext. Note that reused plaintext blocks are not a concern here + since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do + occur commonly on media in the "real world", so it might actually be a fatal mistake + to try to avoid them completely. */ + +#if RNG_POOL_SIZE < SECTOR_SIZE +#error RNG_POOL_SIZE < SECTOR_SIZE +#endif + + if (!RandpeekBytes (sector, SECTOR_SIZE)) + goto fail; + + // Encrypt the random plaintext and write it to the disk + if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, + cryptoInfo) == FALSE) + goto fail; + } + + if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo)) + goto fail; + } + else + nSecNo = num_sectors; + + UpdateProgressBar (nSecNo); + + // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately + memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2)); + + // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately + retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks); + if (retVal != ERR_SUCCESS) + goto fail; + if (!EAInitMode (cryptoInfo)) + { + retVal = ERR_MODE_INIT_FAILED; + goto fail; + } + + burn (temporaryKey, sizeof(temporaryKey)); + burn (originalK2, sizeof(originalK2)); + VirtualUnlock (temporaryKey, sizeof (temporaryKey)); + VirtualUnlock (originalK2, sizeof (originalK2)); + TCfree (write_buf); + + return 0; + +fail: + err = GetLastError(); + + burn (temporaryKey, sizeof(temporaryKey)); + burn (originalK2, sizeof(originalK2)); + VirtualUnlock (temporaryKey, sizeof (temporaryKey)); + VirtualUnlock (originalK2, sizeof (originalK2)); + TCfree (write_buf); + + SetLastError (err); + return (retVal ? retVal : ERR_OS_ERROR); +} + + +volatile BOOLEAN FormatExResult; + +BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter) +{ + if (command == FMIFS_DONE) + FormatExResult = *(BOOLEAN *) parameter; + return TRUE; +} + +BOOL FormatNtfs (int driveNo, int clusterSize) +{ + WCHAR dir[8] = { (WCHAR) driveNo + 'A', 0 }; + PFORMATEX FormatEx; + HMODULE hModule = LoadLibrary ("fmifs.dll"); + int i; + + if (hModule == NULL) + return FALSE; + + if (!(FormatEx = (PFORMATEX) GetProcAddress (GetModuleHandle ("fmifs.dll"), "FormatEx"))) + { + FreeLibrary (hModule); + return FALSE; + } + + wcscat (dir, L":\\"); + + FormatExResult = FALSE; + + // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS. + // It often helps to retry several times. + for (i = 0; i < 50 && FormatExResult != TRUE; i++) + { + FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback); + } + + // The device may be referenced for some time after FormatEx() returns + Sleep (2000); + + FreeLibrary (hModule); + return FormatExResult; +} + + +BOOL WriteSector (void *dev, char *sector, + char *write_buf, int *write_buf_cnt, + __int64 *nSecNo, PCRYPTO_INFO cryptoInfo) +{ + static __int32 updateTime = 0; + + (*nSecNo)++; + + memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE); + (*write_buf_cnt) += SECTOR_SIZE; + + if (*write_buf_cnt == FormatWriteBufferSize && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo)) + return FALSE; + + if (GetTickCount () - updateTime > 25) + { + if (UpdateProgressBar (*nSecNo)) + return FALSE; + + updateTime = GetTickCount (); + } + + return TRUE; + +} + + +static volatile BOOL WriteThreadRunning; +static volatile BOOL WriteThreadExitRequested; +static HANDLE WriteThreadHandle; + +static byte *WriteThreadBuffer; +static HANDLE WriteBufferEmptyEvent; +static HANDLE WriteBufferFullEvent; + +static volatile HANDLE WriteRequestHandle; +static volatile int WriteRequestSize; +static volatile DWORD WriteRequestResult; + + +static void __cdecl FormatWriteThreadProc (void *arg) +{ + DWORD bytesWritten; + + SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + + while (!WriteThreadExitRequested) + { + if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED) + { + handleWin32Error (NULL); + break; + } + + if (WriteThreadExitRequested) + break; + + if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL)) + WriteRequestResult = GetLastError(); + else + WriteRequestResult = ERROR_SUCCESS; + + if (!SetEvent (WriteBufferEmptyEvent)) + { + handleWin32Error (NULL); + break; + } + } + + WriteThreadRunning = FALSE; + _endthread(); +} + + +static BOOL StartFormatWriteThread () +{ + DWORD sysErr; + + WriteBufferEmptyEvent = NULL; + WriteBufferFullEvent = NULL; + WriteThreadBuffer = NULL; + + WriteBufferEmptyEvent = CreateEvent (NULL, FALSE, TRUE, NULL); + if (!WriteBufferEmptyEvent) + goto err; + + WriteBufferFullEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + if (!WriteBufferFullEvent) + goto err; + + WriteThreadBuffer = TCalloc (FormatWriteBufferSize); + if (!WriteThreadBuffer) + { + SetLastError (ERROR_OUTOFMEMORY); + goto err; + } + + WriteThreadExitRequested = FALSE; + WriteRequestResult = ERROR_SUCCESS; + + WriteThreadHandle = (HANDLE) _beginthread (FormatWriteThreadProc, 0, NULL); + if ((uintptr_t) WriteThreadHandle == -1L) + goto err; + + WriteThreadRunning = TRUE; + return TRUE; + +err: + sysErr = GetLastError(); + + if (WriteBufferEmptyEvent) + CloseHandle (WriteBufferEmptyEvent); + if (WriteBufferFullEvent) + CloseHandle (WriteBufferFullEvent); + if (WriteThreadBuffer) + TCfree (WriteThreadBuffer); + + SetLastError (sysErr); + return FALSE; +} + + +static void StopFormatWriteThread () +{ + if (WriteThreadRunning) + { + WaitForSingleObject (WriteBufferEmptyEvent, INFINITE); + + WriteThreadExitRequested = TRUE; + SetEvent (WriteBufferFullEvent); + + WaitForSingleObject (WriteThreadHandle, INFINITE); + } + + CloseHandle (WriteBufferEmptyEvent); + CloseHandle (WriteBufferFullEvent); + TCfree (WriteThreadBuffer); +} + + +BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo) +{ + UINT64_STRUCT unitNo; + DWORD bytesWritten; + + if (*write_buf_cnt == 0) + return TRUE; + + unitNo.Value = (*nSecNo - *write_buf_cnt / SECTOR_SIZE) * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE; + + EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo); + + if (WriteThreadRunning) + { + if (WaitForSingleObject (WriteBufferEmptyEvent, INFINITE) == WAIT_FAILED) + return FALSE; + + if (WriteRequestResult != ERROR_SUCCESS) + { + SetEvent (WriteBufferEmptyEvent); + SetLastError (WriteRequestResult); + return FALSE; + } + + memcpy (WriteThreadBuffer, write_buf, *write_buf_cnt); + WriteRequestHandle = dev; + WriteRequestSize = *write_buf_cnt; + + if (!SetEvent (WriteBufferFullEvent)) + return FALSE; + } + else + { + if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL)) + return FALSE; + } + + *write_buf_cnt = 0; + return TRUE; +} diff --git a/Common/FORMAT.H b/Common/FORMAT.H index 4009925..640bfb4 100644 --- a/Common/FORMAT.H +++ b/Common/FORMAT.H @@ -1,72 +1,67 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TC_HEADER_Format -#define TC_HEADER_Format - -#include "Password.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - -// FMIFS -typedef BOOLEAN (__stdcall *PFMIFSCALLBACK)( int command, DWORD subCommand, PVOID parameter ); -typedef VOID (__stdcall *PFORMATEX)( PWCHAR DriveRoot, DWORD MediaFlag, PWCHAR Format, PWCHAR Label, BOOL QuickFormat, DWORD ClusterSize, PFMIFSCALLBACK Callback ); - -typedef struct -{ - BOOL bDevice; - BOOL hiddenVol; - char *volumePath; - unsigned __int64 size; - unsigned __int64 hiddenVolHostSize; - int ea; - int pkcs5; - uint32 headerFlags; - int fileSystem; - int clusterSize; - BOOL sparseFileSwitch; - BOOL quickFormat; - int *realClusterSize; - Password *password; - HWND hwndDlg; -} -FORMAT_VOL_PARAMETERS; - -#define FMIFS_DONE 0xB -#define FMIFS_HARDDISK 0xC - -int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams); -BOOL FormatNtfs (int driveNo, int clusterSize); - -#endif - -uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize); -int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void *dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat); -BOOL WriteSector ( void *dev , char *sector , char *write_buf , int *write_buf_cnt , __int64 *nSecNo , PCRYPTO_INFO cryptoInfo ); -BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo); -static BOOL StartFormatWriteThread (); -static void StopFormatWriteThread (); - -#define WRITE_BUF_SIZE (64 * 1024) // Write block size greater than 64 KB causes a performance drop when writing to files on XP/Vista (fixed in Windows 7) - -#define FILESYS_NONE 0 -#define FILESYS_FAT 1 -#define FILESYS_NTFS 2 - -#ifdef __cplusplus -} -#endif - -#endif // TC_HEADER_Format +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_Format +#define TC_HEADER_Format + +#include "Password.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// FMIFS +typedef BOOLEAN (__stdcall *PFMIFSCALLBACK)( int command, DWORD subCommand, PVOID parameter ); +typedef VOID (__stdcall *PFORMATEX)( PWCHAR DriveRoot, DWORD MediaFlag, PWCHAR Format, PWCHAR Label, BOOL QuickFormat, DWORD ClusterSize, PFMIFSCALLBACK Callback ); + +typedef struct +{ + BOOL bDevice; + BOOL hiddenVol; + char *volumePath; + unsigned __int64 size; + unsigned __int64 hiddenVolHostSize; + int ea; + int pkcs5; + uint32 headerFlags; + int fileSystem; + int clusterSize; + BOOL sparseFileSwitch; + BOOL quickFormat; + int *realClusterSize; + Password *password; + HWND hwndDlg; +} +FORMAT_VOL_PARAMETERS; + +#define FMIFS_DONE 0xB +#define FMIFS_HARDDISK 0xC + +extern int FormatWriteBufferSize; + +int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams); +BOOL FormatNtfs (int driveNo, int clusterSize); +uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize); +int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void *dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat); +BOOL WriteSector ( void *dev , char *sector , char *write_buf , int *write_buf_cnt , __int64 *nSecNo , PCRYPTO_INFO cryptoInfo ); +BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo); +static BOOL StartFormatWriteThread (); +static void StopFormatWriteThread (); + +#define FILESYS_NONE 0 +#define FILESYS_FAT 1 +#define FILESYS_NTFS 2 + +#ifdef __cplusplus +} +#endif + +#endif // TC_HEADER_Format diff --git a/Common/GfMul.c b/Common/GfMul.c index d450fed..04ae06b 100644 --- a/Common/GfMul.c +++ b/Common/GfMul.c @@ -1,892 +1,892 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 31/01/2004 - - My thanks to John Viega and David McGrew for their support in developing - this code and to David for testing it on a big-endain system. -*/ - -/* - Portions Copyright (c) 2005 TrueCrypt Foundation - - TrueCrypt Foundation made the following changes: - - - Added multiplication in the finite field GF(2^128) optimized for - cases involving a 64-bit operand. - - - Added multiplication in the finite field GF(2^64). - - - Added MSB-first mode. - - - Added basic test algorithms. - - - Removed GCM. -*/ - -#include -#include -#include "GfMul.h" -#include "Tcdefs.h" -#include "Common/Endian.h" - -/* BUFFER_ALIGN32 or BUFFER_ALIGN64 must be defined at this point to */ -/* enable faster operation by taking advantage of memory aligned values */ -/* NOTE: the BUFFER_ALIGN64 option has not been tested extensively */ - -#define BUFFER_ALIGN32 -#define UNROLL_LOOPS /* define to unroll some loops */ -#define IN_LINES /* define to use inline functions */ - /* in place of macros */ - -#define mode(x) GM_##x - -#if defined(__cplusplus) -extern "C" -{ -#endif - -typedef unsigned __int32 mode(32t); -typedef uint64 mode(64t); - -#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ -#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ - -#if BYTE_ORDER == LITTLE_ENDIAN -# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN -#endif - -#if BYTE_ORDER == BIG_ENDIAN -# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN -#endif - -#ifdef _MSC_VER -#pragma intrinsic(memcpy) -#define in_line __inline -#else -#define in_line -#endif - -#if 0 && defined(_MSC_VER) -#define rotl32 _lrotl -#define rotr32 _lrotr -#else -#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) -#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) -#endif - -#if !defined(bswap_32) -#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) -#endif - -#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) -#define SWAP_BYTES -#else -#undef SWAP_BYTES -#endif - -#if defined(SWAP_BYTES) - -#if defined ( IN_LINES ) - -in_line void bsw_32(void * p, unsigned int n) -{ unsigned int i = n; - while(i--) - ((mode(32t)*)p)[i] = bswap_32(((mode(32t)*)p)[i]); -} - -#else - -#define bsw_32(p,n) \ - { int _i = (n); while(_i--) ((mode(32t)*)p)[_i] = bswap_32(((mode(32t)*)p)[_i]); } - -#endif - -#else -#define bsw_32(p,n) -#endif - -/* These values are used to detect long word alignment in order */ -/* to speed up some GCM buffer operations. This facility may */ -/* not work on some machines */ - -#define lp08(x) ((unsigned char*)(x)) -#define lp32(x) ((mode(32t)*)(x)) -#define lp64(x) ((mode(64t)*)(x)) - -#define A32_MASK 3 -#define A64_MASK 7 -#define aligned32(x) (!(((mode(32t))(x)) & A32_MASK)) -#define aligned64(x) (!(((mode(32t))(x)) & A64_MASK)) - -#if defined( BUFFER_ALIGN32 ) - -#define ADR_MASK A32_MASK -#define aligned aligned32 -#define lp lp32 -#define lp_inc 4 - -#if defined( IN_LINES ) - -in_line void move_block_aligned( void *p, const void *q) -{ - lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1], - lp32(p)[2] = lp32(q)[2], lp32(p)[3] = lp32(q)[3]; -} - -in_line void move_block_aligned64( void *p, const void *q) -{ - lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1]; -} - -in_line void xor_block_aligned( void *p, const void *q) -{ - lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1], - lp32(p)[2] ^= lp32(q)[2], lp32(p)[3] ^= lp32(q)[3]; -} - -in_line void xor_block_aligned64( void *p, const void *q) -{ - lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1]; -} - -#else - -#define move_block_aligned(p,q) \ - lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1], \ - lp32(p)[2] = lp32(q)[2], lp32(p)[3] = lp32(q)[3] - -#define xor_block_aligned(p,q) \ - lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1], \ - lp32(p)[2] ^= lp32(q)[2], lp32(p)[3] ^= lp32(q)[3] - -#endif - -#elif defined( BUFFER_ALIGN64 ) - -#define ADR_MASK A64_MASK -#define aligned aligned64 -#define lp lp64 -#define lp_inc 8 - -#define move_block_aligned(p,q) \ - lp64(p)[0] = lp64(q)[0], lp64(p)[1] = lp64(q)[1] - -#define xor_block_aligned(p,q) \ - lp64(p)[0] ^= lp64(q)[0], lp64(p)[1] ^= lp64(q)[1] - -#else -#define aligned(x) 0 -#endif - -#define move_block(p,q) memcpy((p), (q), BLOCK_LEN) - -#define xor_block(p,q) \ - lp08(p)[ 0] ^= lp08(q)[ 0], lp08(p)[ 1] ^= lp08(q)[ 1], \ - lp08(p)[ 2] ^= lp08(q)[ 2], lp08(p)[ 3] ^= lp08(q)[ 3], \ - lp08(p)[ 4] ^= lp08(q)[ 4], lp08(p)[ 5] ^= lp08(q)[ 5], \ - lp08(p)[ 6] ^= lp08(q)[ 6], lp08(p)[ 7] ^= lp08(q)[ 7], \ - lp08(p)[ 8] ^= lp08(q)[ 8], lp08(p)[ 9] ^= lp08(q)[ 9], \ - lp08(p)[10] ^= lp08(q)[10], lp08(p)[11] ^= lp08(q)[11], \ - lp08(p)[12] ^= lp08(q)[12], lp08(p)[13] ^= lp08(q)[13], \ - lp08(p)[14] ^= lp08(q)[14], lp08(p)[15] ^= lp08(q)[15] - - -#define gf_dat(q) {\ - q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\ - q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\ - q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\ - q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0x1e), q(0x1f),\ - q(0x20), q(0x21), q(0x22), q(0x23), q(0x24), q(0x25), q(0x26), q(0x27),\ - q(0x28), q(0x29), q(0x2a), q(0x2b), q(0x2c), q(0x2d), q(0x2e), q(0x2f),\ - q(0x30), q(0x31), q(0x32), q(0x33), q(0x34), q(0x35), q(0x36), q(0x37),\ - q(0x38), q(0x39), q(0x3a), q(0x3b), q(0x3c), q(0x3d), q(0x3e), q(0x3f),\ - q(0x40), q(0x41), q(0x42), q(0x43), q(0x44), q(0x45), q(0x46), q(0x47),\ - q(0x48), q(0x49), q(0x4a), q(0x4b), q(0x4c), q(0x4d), q(0x4e), q(0x4f),\ - q(0x50), q(0x51), q(0x52), q(0x53), q(0x54), q(0x55), q(0x56), q(0x57),\ - q(0x58), q(0x59), q(0x5a), q(0x5b), q(0x5c), q(0x5d), q(0x5e), q(0x5f),\ - q(0x60), q(0x61), q(0x62), q(0x63), q(0x64), q(0x65), q(0x66), q(0x67),\ - q(0x68), q(0x69), q(0x6a), q(0x6b), q(0x6c), q(0x6d), q(0x6e), q(0x6f),\ - q(0x70), q(0x71), q(0x72), q(0x73), q(0x74), q(0x75), q(0x76), q(0x77),\ - q(0x78), q(0x79), q(0x7a), q(0x7b), q(0x7c), q(0x7d), q(0x7e), q(0x7f),\ - q(0x80), q(0x81), q(0x82), q(0x83), q(0x84), q(0x85), q(0x86), q(0x87),\ - q(0x88), q(0x89), q(0x8a), q(0x8b), q(0x8c), q(0x8d), q(0x8e), q(0x8f),\ - q(0x90), q(0x91), q(0x92), q(0x93), q(0x94), q(0x95), q(0x96), q(0x97),\ - q(0x98), q(0x99), q(0x9a), q(0x9b), q(0x9c), q(0x9d), q(0x9e), q(0x9f),\ - q(0xa0), q(0xa1), q(0xa2), q(0xa3), q(0xa4), q(0xa5), q(0xa6), q(0xa7),\ - q(0xa8), q(0xa9), q(0xaa), q(0xab), q(0xac), q(0xad), q(0xae), q(0xaf),\ - q(0xb0), q(0xb1), q(0xb2), q(0xb3), q(0xb4), q(0xb5), q(0xb6), q(0xb7),\ - q(0xb8), q(0xb9), q(0xba), q(0xbb), q(0xbc), q(0xbd), q(0xbe), q(0xbf),\ - q(0xc0), q(0xc1), q(0xc2), q(0xc3), q(0xc4), q(0xc5), q(0xc6), q(0xc7),\ - q(0xc8), q(0xc9), q(0xca), q(0xcb), q(0xcc), q(0xcd), q(0xce), q(0xcf),\ - q(0xd0), q(0xd1), q(0xd2), q(0xd3), q(0xd4), q(0xd5), q(0xd6), q(0xd7),\ - q(0xd8), q(0xd9), q(0xda), q(0xdb), q(0xdc), q(0xdd), q(0xde), q(0xdf),\ - q(0xe0), q(0xe1), q(0xe2), q(0xe3), q(0xe4), q(0xe5), q(0xe6), q(0xe7),\ - q(0xe8), q(0xe9), q(0xea), q(0xeb), q(0xec), q(0xed), q(0xee), q(0xef),\ - q(0xf0), q(0xf1), q(0xf2), q(0xf3), q(0xf4), q(0xf5), q(0xf6), q(0xf7),\ - q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) } - -/* given the value i in 0..255 as the byte overflow when a a field */ -/* element in GHASH is multipled by x^8, this function will return */ -/* the values that are generated in the lo 16-bit word of the field */ -/* value by applying the modular polynomial. The values lo_byte and */ -/* hi_byte are returned via the macro xp_fun(lo_byte, hi_byte) so */ -/* that the values can be assembled into memory as required by a */ -/* suitable definition of this macro operating on the table above */ - -#define xp(i) xp_fun( \ - (i & 0x80 ? 0xe1 : 0) ^ (i & 0x40 ? 0x70 : 0) ^ \ - (i & 0x20 ? 0x38 : 0) ^ (i & 0x10 ? 0x1c : 0) ^ \ - (i & 0x08 ? 0x0e : 0) ^ (i & 0x04 ? 0x07 : 0) ^ \ - (i & 0x02 ? 0x03 : 0) ^ (i & 0x01 ? 0x01 : 0), \ - (i & 0x80 ? 0x00 : 0) ^ (i & 0x40 ? 0x80 : 0) ^ \ - (i & 0x20 ? 0x40 : 0) ^ (i & 0x10 ? 0x20 : 0) ^ \ - (i & 0x08 ? 0x10 : 0) ^ (i & 0x04 ? 0x08 : 0) ^ \ - (i & 0x02 ? 0x84 : 0) ^ (i & 0x01 ? 0xc2 : 0) ) - -#define xp64(i) xp_fun( \ - (i & 0x80 ? 0xd8 : 0) ^ (i & 0x40 ? 0x6c : 0) ^ \ - (i & 0x20 ? 0x36 : 0) ^ (i & 0x10 ? 0x1b : 0) ^ \ - (i & 0x08 ? 0x0d : 0) ^ (i & 0x04 ? 0x06 : 0) ^ \ - (i & 0x02 ? 0x03 : 0) ^ (i & 0x01 ? 0x01 : 0), \ - (i & 0x80 ? 0x00 : 0) ^ (i & 0x40 ? 0x00 : 0) ^ \ - (i & 0x20 ? 0x00 : 0) ^ (i & 0x10 ? 0x00 : 0) ^ \ - (i & 0x08 ? 0x80 : 0) ^ (i & 0x04 ? 0xc0 : 0) ^ \ - (i & 0x02 ? 0x60 : 0) ^ (i & 0x01 ? 0xb0 : 0) ) - -static mode(32t) gf_poly[2] = { 0, 0xe1000000 }; -static mode(32t) gf_poly64[2] = { 0, 0xd8000000 }; - -/* Multiply of a GF128 field element by x. The field element */ -/* is held in an array of bytes in which field bits 8n..8n + 7 */ -/* are held in byte[n], with lower indexed bits placed in the */ -/* more numerically significant bit positions in bytes. */ - -/* This function multiples a field element x, in the polynomial */ -/* field representation. It uses 32-bit word operations to gain */ -/* speed but compensates for machine endianess and hence works */ -/* correctly on both styles of machine */ - -in_line void mul_x(mode(32t) x[4]) -{ mode(32t) t; - - bsw_32(x, 4); - - /* at this point the filed element bits 0..127 are set out */ - /* as follows in 32-bit words (where the most significant */ - /* (ms) numeric bits are to the left) */ - /* */ - /* x[0] x[1] x[2] x[3] */ - /* ms ls ms ls ms ls ms ls */ - /* field: 0 ... 31 32 .. 63 64 .. 95 96 .. 127 */ - - t = gf_poly[x[3] & 1]; /* bit 127 of the element */ - x[3] = (x[3] >> 1) | (x[2] << 31); /* shift bits up by one */ - x[2] = (x[2] >> 1) | (x[1] << 31); /* position */ - x[1] = (x[1] >> 1) | (x[0] << 31); /* if bit 7 is 1 xor in */ - x[0] = (x[0] >> 1) ^ t; /* the field polynomial */ - bsw_32(x, 4); -} - -in_line void mul_x64(mode(32t) x[2]) -{ mode(32t) t; - - bsw_32(x, 2); - - /* at this point the filed element bits 0..127 are set out */ - /* as follows in 32-bit words (where the most significant */ - /* (ms) numeric bits are to the left) */ - /* */ - /* x[0] x[1] x[2] x[3] */ - /* ms ls ms ls ms ls ms ls */ - /* field: 0 ... 31 32 .. 63 64 .. 95 96 .. 127 */ - - t = gf_poly64[x[1] & 1]; /* bit 127 of the element */ - /* shift bits up by one */ - /* position */ - x[1] = (x[1] >> 1) | (x[0] << 31); /* if bit 7 is 1 xor in */ - x[0] = (x[0] >> 1) ^ t; /* the field polynomial */ - bsw_32(x, 2); -} - -/* Multiply of a GF128 field element by x^8 using 32-bit words */ -/* for speed - machine endianess matters here */ - -#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) - -#define xp_fun(x,y) ((mode(32t))(x)) | (((mode(32t))(y)) << 8) -static const unsigned __int16 gft_le[256] = gf_dat(xp); -static const unsigned __int16 gft_le64[256] = gf_dat(xp64); - -in_line void mul_lex8(mode(32t) x[4]) /* mutiply with long words */ -{ mode(32t) t = (x[3] >> 24); /* in little endian format */ - x[3] = (x[3] << 8) | (x[2] >> 24); - x[2] = (x[2] << 8) | (x[1] >> 24); - x[1] = (x[1] << 8) | (x[0] >> 24); - x[0] = (x[0] << 8) ^ gft_le[t]; -} - -in_line void mul_lex8_64(mode(32t) x[2]) /* mutiply with long words */ -{ mode(32t) t = (x[1] >> 24); /* in little endian format */ - x[1] = (x[1] << 8) | (x[0] >> 24); - x[0] = (x[0] << 8) ^ gft_le64[t]; -} - -#endif - -#if 1 || (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) - -#undef xp_fun -#define xp_fun(x,y) ((mode(32t))(y)) | (((mode(32t))(x)) << 8) -static const unsigned __int16 gft_be[256] = gf_dat(xp); -static const unsigned __int16 gft_be64[256] = gf_dat(xp64); - -in_line void mul_bex8(mode(32t) x[4]) /* mutiply with long words */ -{ mode(32t) t = (x[3] & 0xff); /* in big endian format */ - x[3] = (x[3] >> 8) | (x[2] << 24); - x[2] = (x[2] >> 8) | (x[1] << 24); - x[1] = (x[1] >> 8) | (x[0] << 24); - x[0] = (x[0] >> 8) ^ (((mode(32t))gft_be[t]) << 16); -} - -in_line void mul_bex8_64(mode(32t) x[2]) /* mutiply with long words */ -{ mode(32t) t = (x[1] & 0xff); /* in big endian format */ - x[1] = (x[1] >> 8) | (x[0] << 24); - x[0] = (x[0] >> 8) ^ (((mode(32t))gft_be64[t]) << 16); -} - -#endif - -/* hence choose the correct version for the machine endianess */ - -#if PLATFORM_BYTE_ORDER == BRG_BIG_ENDIAN -#define mul_x8 mul_bex8 -#define mul_x8_64 mul_bex8_64 -#else -#define mul_x8 mul_lex8 -#define mul_x8_64 mul_lex8_64 -#endif - -/* different versions of the general gf_mul function are provided */ -/* here. Sadly none are very fast :-( */ - -void GfMul128 (void *a, const void* b) -{ mode(32t) r[CBLK_LEN >> 2], p[8][CBLK_LEN >> 2]; - int i; - - move_block_aligned(p[0], b); - bsw_32(p[0], 4); - for(i = 0; i < 7; ++i) - { - p[i + 1][3] = (p[i][3] >> 1) | (p[i][2] << 31); - p[i + 1][2] = (p[i][2] >> 1) | (p[i][1] << 31); - p[i + 1][1] = (p[i][1] >> 1) | (p[i][0] << 31); - p[i + 1][0] = (p[i][0] >> 1) ^ gf_poly[p[i][3] & 1]; - } - - memset(r, 0, CBLK_LEN); - for(i = 0; i < 16; ++i) - { - if(i) mul_bex8(r); /* order is always big endian here */ - - if(((unsigned char*)a)[15 - i] & 0x80) - xor_block_aligned(r, p[0]); - if(((unsigned char*)a)[15 - i] & 0x40) - xor_block_aligned(r, p[1]); - if(((unsigned char*)a)[15 - i] & 0x20) - xor_block_aligned(r, p[2]); - if(((unsigned char*)a)[15 - i] & 0x10) - xor_block_aligned(r, p[3]); - if(((unsigned char*)a)[15 - i] & 0x08) - xor_block_aligned(r, p[4]); - if(((unsigned char*)a)[15 - i] & 0x04) - xor_block_aligned(r, p[5]); - if(((unsigned char*)a)[15 - i] & 0x02) - xor_block_aligned(r, p[6]); - if(((unsigned char*)a)[15 - i] & 0x01) - xor_block_aligned(r, p[7]); - } - bsw_32(r, 4); - move_block_aligned(a, r); -} - -#if defined( UNROLL_LOOPS ) - -#define xor_8k(i) \ - xor_block_aligned(r, ctx->gf_t8k[i + i][a[i] & 15]); \ - xor_block_aligned(r, ctx->gf_t8k[i + i + 1][a[i] >> 4]) - - -void GfMul128Tab (unsigned char a[CBLK_LEN], GfCtx8k *ctx) -{ unsigned __int32 r[CBLK_LEN >> 2]; - - move_block_aligned(r, ctx->gf_t8k[0][a[0] & 15]); - xor_block_aligned(r, ctx->gf_t8k[1][a[0] >> 4]); - xor_8k( 1); xor_8k( 2); xor_8k( 3); - xor_8k( 4); xor_8k( 5); xor_8k( 6); xor_8k( 7); - xor_8k( 8); xor_8k( 9); xor_8k(10); xor_8k(11); - xor_8k(12); xor_8k(13); xor_8k(14); xor_8k(15); - move_block_aligned(a, r); -} - -#else - -void GfMul128Tab (unsigned char a[CBLK_LEN], GfCtx8k *ctx) -{ unsigned __int32 r[CBLK_LEN >> 2], *p; - int i; - - p = ctx->gf_t8k[0][a[0] & 15]; - memcpy(r, p, CBLK_LEN); - p = ctx->gf_t8k[1][a[0] >> 4]; - xor_block_aligned(r, p); - for(i = 1; i < CBLK_LEN; ++i) - { - xor_block_aligned(r, ctx->gf_t8k[i + i][a[i] & 15]); - xor_block_aligned(r, ctx->gf_t8k[i + i + 1][a[i] >> 4]); - } - memcpy(a, r, CBLK_LEN); -} - -#endif - -void compile_8k_table(unsigned __int8 *a, GfCtx8k *ctx) -{ int i, j, k; - - memset(ctx->gf_t8k, 0, 32 * 16 * 16); - for(i = 0; i < 2 * CBLK_LEN; ++i) - { - if(i == 0) - { - memcpy(ctx->gf_t8k[1][8], a, CBLK_LEN); - for(j = 4; j > 0; j >>= 1) - { - memcpy(ctx->gf_t8k[1][j], ctx->gf_t8k[1][j + j], CBLK_LEN); - mul_x(ctx->gf_t8k[1][j]); - } - memcpy(ctx->gf_t8k[0][8], ctx->gf_t8k[1][1], CBLK_LEN); - mul_x(ctx->gf_t8k[0][8]); - for(j = 4; j > 0; j >>= 1) - { - memcpy(ctx->gf_t8k[0][j], ctx->gf_t8k[0][j + j], CBLK_LEN); - mul_x(ctx->gf_t8k[0][j]); - } - } - else if(i > 1) - for(j = 8; j > 0; j >>= 1) - { - memcpy(ctx->gf_t8k[i][j], ctx->gf_t8k[i - 2][j], CBLK_LEN); - mul_x8(ctx->gf_t8k[i][j]); - } - - for(j = 2; j < 16; j += j) - { - mode(32t) *pj = ctx->gf_t8k[i][j]; - mode(32t) *pk = ctx->gf_t8k[i][1]; - mode(32t) *pl = ctx->gf_t8k[i][j + 1]; - - for(k = 1; k < j; ++k) - { - *pl++ = pj[0] ^ *pk++; - *pl++ = pj[1] ^ *pk++; - *pl++ = pj[2] ^ *pk++; - *pl++ = pj[3] ^ *pk++; - } - } - } -} - - -void compile_4k_table64(unsigned __int8 *a, GfCtx4k64 *ctx) -{ int i, j, k; - - memset(ctx->gf_t4k, 0, sizeof(ctx->gf_t4k)); - for(i = 0; i < 2 * CBLK_LEN8; ++i) - { - if(i == 0) - { - memcpy(ctx->gf_t4k[1][8], a, CBLK_LEN8); - for(j = 4; j > 0; j >>= 1) - { - memcpy(ctx->gf_t4k[1][j], ctx->gf_t4k[1][j + j], CBLK_LEN8); - mul_x64(ctx->gf_t4k[1][j]); - } - memcpy(ctx->gf_t4k[0][8], ctx->gf_t4k[1][1], CBLK_LEN8); - mul_x64(ctx->gf_t4k[0][8]); - for(j = 4; j > 0; j >>= 1) - { - memcpy(ctx->gf_t4k[0][j], ctx->gf_t4k[0][j + j], CBLK_LEN8); - mul_x64(ctx->gf_t4k[0][j]); - } - } - else if(i > 1) - for(j = 8; j > 0; j >>= 1) - { - memcpy(ctx->gf_t4k[i][j], ctx->gf_t4k[i - 2][j], CBLK_LEN8); - mul_x8_64(ctx->gf_t4k[i][j]); - } - - for(j = 2; j < 16; j += j) - { - mode(32t) *pj = ctx->gf_t4k[i][j]; - mode(32t) *pk = ctx->gf_t4k[i][1]; - mode(32t) *pl = ctx->gf_t4k[i][j + 1]; - - for(k = 1; k < j; ++k) - { - *pl++ = pj[0] ^ *pk++; - *pl++ = pj[1] ^ *pk++; - *pl++ = pj[2] ^ *pk++; - *pl++ = pj[3] ^ *pk++; - } - } - } -} - -static int IsBitSet128 (unsigned int bit, unsigned __int8 *a) -{ - return a[(127 - bit) / 8] & (0x80 >> ((127 - bit) % 8)); -} - -static int IsBitSet64 (unsigned int bit, unsigned __int8 *a) -{ - return a[(63 - bit) / 8] & (0x80 >> ((63 - bit) % 8)); -} - -static void SetBit128 (unsigned int bit, unsigned __int8 *a) -{ - a[(127 - bit) / 8] |= 0x80 >> ((127 - bit) % 8); -} - -static void SetBit64 (unsigned int bit, unsigned __int8 *a) -{ - a[(63 - bit) / 8] |= 0x80 >> ((63 - bit) % 8); -} - -void MirrorBits128 (unsigned __int8 *a) -{ - unsigned __int8 t[128 / 8]; - int i; - memset (t,0,16); - for (i = 0; i < 128; i++) - { - if (IsBitSet128(i, a)) - SetBit128 (127 - i, t); - } - memcpy (a, t, sizeof (t)); - burn (t,sizeof (t)); -} - -void MirrorBits64 (unsigned __int8 *a) -{ - unsigned __int8 t[64 / 8]; - int i; - memset (t,0,8); - for (i = 0; i < 64; i++) - { - if (IsBitSet64(i, a)) - SetBit64 (63 - i, t); - } - memcpy (a, t, sizeof (t)); - burn (t,sizeof (t)); -} - -/* Allocate and initialize speed optimization table - for multiplication by 64-bit operand in MSB-first mode */ -int Gf128Tab64Init (unsigned __int8 *a, GfCtx *ctx) -{ - GfCtx8k *ctx8k; - unsigned __int8 am[16]; - int i, j; - - ctx8k = (GfCtx8k *) TCalloc (sizeof (GfCtx8k)); - if (!ctx8k) - return FALSE; - - memcpy (am, a, 16); - MirrorBits128 (am); - compile_8k_table (am, ctx8k); - - /* Convert 8k LSB-first table to 4k MSB-first */ - for (i = 16; i < 32; i++) - { - for (j = 0; j < 16; j++) - { - int jm = 0; - jm |= (j & 0x1) << 3; - jm |= (j & 0x2) << 1; - jm |= (j & 0x4) >> 1; - jm |= (j & 0x8) >> 3; - - memcpy (&ctx->gf_t128[i-16][jm], (unsigned char *)&ctx8k->gf_t8k[31-i][j], 16); - MirrorBits128 ((unsigned char *)&ctx->gf_t128[i-16][jm]); - } - } - - burn (ctx8k ,sizeof (*ctx8k)); - burn (am, sizeof (am)); - TCfree (ctx8k); - return TRUE; -} - -int Gf64TabInit (unsigned __int8 *a, GfCtx *ctx) -{ - /* Deprecated/legacy */ - - GfCtx4k64 *ctx4k; - unsigned __int8 am[8]; - int i, j; - - ctx4k = (GfCtx4k64 *) TCalloc (sizeof (GfCtx4k64)); - if (!ctx4k) - return FALSE; - - memcpy (am, a, 8); - MirrorBits64 (am); - compile_4k_table64 (am, ctx4k); - - /* Convert LSB-first table to MSB-first */ - for (i = 0; i < 16; i++) - { - for (j = 0; j < 16; j++) - { - int jm = 0; - jm |= (j & 0x1) << 3; - jm |= (j & 0x2) << 1; - jm |= (j & 0x4) >> 1; - jm |= (j & 0x8) >> 3; - - memcpy (&ctx->gf_t64[i][jm], (unsigned char *)&ctx4k->gf_t4k[15-i][j], 8); - MirrorBits64 ((unsigned char *)&ctx->gf_t64[i][jm]); - } - } - - burn (ctx4k,sizeof (*ctx4k)); - burn (am, sizeof (am)); - TCfree (ctx4k); - return TRUE; -} - -#define xor_8kt64(i) \ - xor_block_aligned(r, ctx->gf_t128[i + i][a[i] & 15]); \ - xor_block_aligned(r, ctx->gf_t128[i + i + 1][a[i] >> 4]) - -/* Multiply a 128-bit number by a 64-bit number in the finite field GF(2^128) */ -void Gf128MulBy64Tab (unsigned __int8 a[8], unsigned __int8 p[16], GfCtx *ctx) -{ - unsigned __int32 r[CBLK_LEN >> 2]; - - move_block_aligned(r, ctx->gf_t128[7*2][a[7] & 15]); - xor_block_aligned(r, ctx->gf_t128[7*2+1][a[7] >> 4]); - - if (*(unsigned __int16 *)a) - { - xor_8kt64(0); - xor_8kt64(1); - } - if (a[2]) - { - xor_8kt64(2); - } - xor_8kt64(3); - xor_8kt64(4); - xor_8kt64(5); - xor_8kt64(6); - - move_block_aligned(p, r); -} - -#define xor_8k64(i) \ - xor_block_aligned64(r, ctx->gf_t64[i + i][a[i] & 15]); \ - xor_block_aligned64(r, ctx->gf_t64[i + i + 1][a[i] >> 4]) - -/* Multiply two 64-bit numbers in the finite field GF(2^64) */ -void Gf64MulTab (unsigned char a[8], unsigned char p[8], GfCtx *ctx) -{ - /* Deprecated/legacy */ - - unsigned __int32 r[CBLK_LEN8 >> 2]; - - move_block_aligned64(r, ctx->gf_t64[7*2][a[7] & 15]); - xor_block_aligned64(r, ctx->gf_t64[7*2+1][a[7] >> 4]); - - if (*(unsigned __int16 *)a) - { - xor_8k64(0); - xor_8k64(1); - } - if (a[2]) - { - xor_8k64(2); - } - xor_8k64(3); - xor_8k64(4); - xor_8k64(5); - xor_8k64(6); - - move_block_aligned64(p, r); -} - - -/* Basic algorithms for testing of optimized algorithms */ - -static void xor128 (uint64 *a, uint64 *b) -{ - *a++ ^= *b++; - *a ^= *b; -} - -static void shl128 (unsigned __int8 *a) -{ - int i, x = 0, xx; - for (i = 15; i >= 0; i--) - { - xx = (a[i] & 0x80) >> 7; - a[i] = (a[i] << 1) | x; - x = xx; - } -} - -static void GfMul128Basic (unsigned __int8 *a, unsigned __int8 *b, unsigned __int8 *p) -{ - int i; - unsigned __int8 la[16]; - memcpy (la, a, 16); - memset (p, 0, 16); - - for (i = 0; i < 128; i++) - { - if (IsBitSet128 (i, b)) - xor128 ((uint64 *)p, (uint64 *)la); - - if (la[0] & 0x80) - { - shl128 (la); - la[15] ^= 0x87; - } - else - { - shl128 (la); - } - } -} - -static void xor64 (uint64 *a, uint64 *b) -{ - *a ^= *b; -} - -static void shl64 (unsigned __int8 *a) -{ - int i, x = 0, xx; - for (i = 7; i >= 0; i--) - { - xx = (a[i] & 0x80) >> 7; - a[i] = (a[i] << 1) | x; - x = xx; - } -} - -static void GfMul64Basic (unsigned __int8 *a, unsigned __int8 *b, unsigned __int8* p) -{ - /* Deprecated/legacy */ - - int i; - unsigned __int8 la[8]; - memcpy (la, a, 8); - memset (p, 0, 8); - - for (i = 0; i < 64; i++) - { - if (IsBitSet64 (i, b)) - xor64 ((uint64 *)p, (uint64 *)la); - - if (la[0] & 0x80) - { - shl64 (la); - la[7] ^= 0x1b; - } - else - { - shl64 (la); - } - } -} - - -BOOL GfMulSelfTest () -{ - BOOL result = TRUE; - unsigned __int8 a[16]; - unsigned __int8 b[16]; - unsigned __int8 p1[16]; - unsigned __int8 p2[16]; - GfCtx *gfCtx = (GfCtx *) TCalloc (sizeof (GfCtx)); - int i, j; - - if (!gfCtx) - return FALSE; - - /* GF(2^64) - deprecated/legacy */ - for (i = 0; i < 0x100; i++) - { - for (j = 0; j < 8; j++) - { - a[j] = (unsigned __int8) i; - b[j] = a[j] ^ 0xff; - } - - GfMul64Basic (a, b, p1); - - Gf64TabInit (a, gfCtx); - Gf64MulTab (b, p2, gfCtx); - - if (memcmp (p1, p2, 8) != 0) - result = FALSE; - } - - /* GF(2^128) */ - for (i = 0; i < 0x100; i++) - { - for (j = 0; j < 16; j++) - { - a[j] = (unsigned __int8) i; - b[j] = j < 8 ? 0 : a[j] ^ 0xff; - } - - GfMul128Basic (a, b, p1); - - Gf128Tab64Init (a, gfCtx); - Gf128MulBy64Tab (b + 8, p2, gfCtx); - - if (memcmp (p1, p2, 16) != 0) - result = FALSE; - } - - TCfree (gfCtx); - return result; -} - -#if defined(__cplusplus) -} -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 31/01/2004 + + My thanks to John Viega and David McGrew for their support in developing + this code and to David for testing it on a big-endain system. +*/ + +/* + Portions Copyright (c) 2005 TrueCrypt Foundation + + TrueCrypt Foundation made the following changes: + + - Added multiplication in the finite field GF(2^128) optimized for + cases involving a 64-bit operand. + + - Added multiplication in the finite field GF(2^64). + + - Added MSB-first mode. + + - Added basic test algorithms. + + - Removed GCM. +*/ + +#include +#include +#include "GfMul.h" +#include "Tcdefs.h" +#include "Common/Endian.h" + +/* BUFFER_ALIGN32 or BUFFER_ALIGN64 must be defined at this point to */ +/* enable faster operation by taking advantage of memory aligned values */ +/* NOTE: the BUFFER_ALIGN64 option has not been tested extensively */ + +#define BUFFER_ALIGN32 +#define UNROLL_LOOPS /* define to unroll some loops */ +#define IN_LINES /* define to use inline functions */ + /* in place of macros */ + +#define mode(x) GM_##x + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef unsigned __int32 mode(32t); +typedef uint64 mode(64t); + +#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN +#endif + +#if BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN +#endif + +#ifdef _MSC_VER +#pragma intrinsic(memcpy) +#define in_line __inline +#else +#define in_line +#endif + +#if 0 && defined(_MSC_VER) +#define rotl32 _lrotl +#define rotr32 _lrotr +#else +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) +#endif + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#if defined(SWAP_BYTES) + +#if defined ( IN_LINES ) + +in_line void bsw_32(void * p, unsigned int n) +{ unsigned int i = n; + while(i--) + ((mode(32t)*)p)[i] = bswap_32(((mode(32t)*)p)[i]); +} + +#else + +#define bsw_32(p,n) \ + { int _i = (n); while(_i--) ((mode(32t)*)p)[_i] = bswap_32(((mode(32t)*)p)[_i]); } + +#endif + +#else +#define bsw_32(p,n) +#endif + +/* These values are used to detect long word alignment in order */ +/* to speed up some GCM buffer operations. This facility may */ +/* not work on some machines */ + +#define lp08(x) ((unsigned char*)(x)) +#define lp32(x) ((mode(32t)*)(x)) +#define lp64(x) ((mode(64t)*)(x)) + +#define A32_MASK 3 +#define A64_MASK 7 +#define aligned32(x) (!(((mode(32t))(x)) & A32_MASK)) +#define aligned64(x) (!(((mode(32t))(x)) & A64_MASK)) + +#if defined( BUFFER_ALIGN32 ) + +#define ADR_MASK A32_MASK +#define aligned aligned32 +#define lp lp32 +#define lp_inc 4 + +#if defined( IN_LINES ) + +in_line void move_block_aligned( void *p, const void *q) +{ + lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1], + lp32(p)[2] = lp32(q)[2], lp32(p)[3] = lp32(q)[3]; +} + +in_line void move_block_aligned64( void *p, const void *q) +{ + lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1]; +} + +in_line void xor_block_aligned( void *p, const void *q) +{ + lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1], + lp32(p)[2] ^= lp32(q)[2], lp32(p)[3] ^= lp32(q)[3]; +} + +in_line void xor_block_aligned64( void *p, const void *q) +{ + lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1]; +} + +#else + +#define move_block_aligned(p,q) \ + lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1], \ + lp32(p)[2] = lp32(q)[2], lp32(p)[3] = lp32(q)[3] + +#define xor_block_aligned(p,q) \ + lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1], \ + lp32(p)[2] ^= lp32(q)[2], lp32(p)[3] ^= lp32(q)[3] + +#endif + +#elif defined( BUFFER_ALIGN64 ) + +#define ADR_MASK A64_MASK +#define aligned aligned64 +#define lp lp64 +#define lp_inc 8 + +#define move_block_aligned(p,q) \ + lp64(p)[0] = lp64(q)[0], lp64(p)[1] = lp64(q)[1] + +#define xor_block_aligned(p,q) \ + lp64(p)[0] ^= lp64(q)[0], lp64(p)[1] ^= lp64(q)[1] + +#else +#define aligned(x) 0 +#endif + +#define move_block(p,q) memcpy((p), (q), BLOCK_LEN) + +#define xor_block(p,q) \ + lp08(p)[ 0] ^= lp08(q)[ 0], lp08(p)[ 1] ^= lp08(q)[ 1], \ + lp08(p)[ 2] ^= lp08(q)[ 2], lp08(p)[ 3] ^= lp08(q)[ 3], \ + lp08(p)[ 4] ^= lp08(q)[ 4], lp08(p)[ 5] ^= lp08(q)[ 5], \ + lp08(p)[ 6] ^= lp08(q)[ 6], lp08(p)[ 7] ^= lp08(q)[ 7], \ + lp08(p)[ 8] ^= lp08(q)[ 8], lp08(p)[ 9] ^= lp08(q)[ 9], \ + lp08(p)[10] ^= lp08(q)[10], lp08(p)[11] ^= lp08(q)[11], \ + lp08(p)[12] ^= lp08(q)[12], lp08(p)[13] ^= lp08(q)[13], \ + lp08(p)[14] ^= lp08(q)[14], lp08(p)[15] ^= lp08(q)[15] + + +#define gf_dat(q) {\ + q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\ + q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\ + q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\ + q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0x1e), q(0x1f),\ + q(0x20), q(0x21), q(0x22), q(0x23), q(0x24), q(0x25), q(0x26), q(0x27),\ + q(0x28), q(0x29), q(0x2a), q(0x2b), q(0x2c), q(0x2d), q(0x2e), q(0x2f),\ + q(0x30), q(0x31), q(0x32), q(0x33), q(0x34), q(0x35), q(0x36), q(0x37),\ + q(0x38), q(0x39), q(0x3a), q(0x3b), q(0x3c), q(0x3d), q(0x3e), q(0x3f),\ + q(0x40), q(0x41), q(0x42), q(0x43), q(0x44), q(0x45), q(0x46), q(0x47),\ + q(0x48), q(0x49), q(0x4a), q(0x4b), q(0x4c), q(0x4d), q(0x4e), q(0x4f),\ + q(0x50), q(0x51), q(0x52), q(0x53), q(0x54), q(0x55), q(0x56), q(0x57),\ + q(0x58), q(0x59), q(0x5a), q(0x5b), q(0x5c), q(0x5d), q(0x5e), q(0x5f),\ + q(0x60), q(0x61), q(0x62), q(0x63), q(0x64), q(0x65), q(0x66), q(0x67),\ + q(0x68), q(0x69), q(0x6a), q(0x6b), q(0x6c), q(0x6d), q(0x6e), q(0x6f),\ + q(0x70), q(0x71), q(0x72), q(0x73), q(0x74), q(0x75), q(0x76), q(0x77),\ + q(0x78), q(0x79), q(0x7a), q(0x7b), q(0x7c), q(0x7d), q(0x7e), q(0x7f),\ + q(0x80), q(0x81), q(0x82), q(0x83), q(0x84), q(0x85), q(0x86), q(0x87),\ + q(0x88), q(0x89), q(0x8a), q(0x8b), q(0x8c), q(0x8d), q(0x8e), q(0x8f),\ + q(0x90), q(0x91), q(0x92), q(0x93), q(0x94), q(0x95), q(0x96), q(0x97),\ + q(0x98), q(0x99), q(0x9a), q(0x9b), q(0x9c), q(0x9d), q(0x9e), q(0x9f),\ + q(0xa0), q(0xa1), q(0xa2), q(0xa3), q(0xa4), q(0xa5), q(0xa6), q(0xa7),\ + q(0xa8), q(0xa9), q(0xaa), q(0xab), q(0xac), q(0xad), q(0xae), q(0xaf),\ + q(0xb0), q(0xb1), q(0xb2), q(0xb3), q(0xb4), q(0xb5), q(0xb6), q(0xb7),\ + q(0xb8), q(0xb9), q(0xba), q(0xbb), q(0xbc), q(0xbd), q(0xbe), q(0xbf),\ + q(0xc0), q(0xc1), q(0xc2), q(0xc3), q(0xc4), q(0xc5), q(0xc6), q(0xc7),\ + q(0xc8), q(0xc9), q(0xca), q(0xcb), q(0xcc), q(0xcd), q(0xce), q(0xcf),\ + q(0xd0), q(0xd1), q(0xd2), q(0xd3), q(0xd4), q(0xd5), q(0xd6), q(0xd7),\ + q(0xd8), q(0xd9), q(0xda), q(0xdb), q(0xdc), q(0xdd), q(0xde), q(0xdf),\ + q(0xe0), q(0xe1), q(0xe2), q(0xe3), q(0xe4), q(0xe5), q(0xe6), q(0xe7),\ + q(0xe8), q(0xe9), q(0xea), q(0xeb), q(0xec), q(0xed), q(0xee), q(0xef),\ + q(0xf0), q(0xf1), q(0xf2), q(0xf3), q(0xf4), q(0xf5), q(0xf6), q(0xf7),\ + q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) } + +/* given the value i in 0..255 as the byte overflow when a a field */ +/* element in GHASH is multipled by x^8, this function will return */ +/* the values that are generated in the lo 16-bit word of the field */ +/* value by applying the modular polynomial. The values lo_byte and */ +/* hi_byte are returned via the macro xp_fun(lo_byte, hi_byte) so */ +/* that the values can be assembled into memory as required by a */ +/* suitable definition of this macro operating on the table above */ + +#define xp(i) xp_fun( \ + (i & 0x80 ? 0xe1 : 0) ^ (i & 0x40 ? 0x70 : 0) ^ \ + (i & 0x20 ? 0x38 : 0) ^ (i & 0x10 ? 0x1c : 0) ^ \ + (i & 0x08 ? 0x0e : 0) ^ (i & 0x04 ? 0x07 : 0) ^ \ + (i & 0x02 ? 0x03 : 0) ^ (i & 0x01 ? 0x01 : 0), \ + (i & 0x80 ? 0x00 : 0) ^ (i & 0x40 ? 0x80 : 0) ^ \ + (i & 0x20 ? 0x40 : 0) ^ (i & 0x10 ? 0x20 : 0) ^ \ + (i & 0x08 ? 0x10 : 0) ^ (i & 0x04 ? 0x08 : 0) ^ \ + (i & 0x02 ? 0x84 : 0) ^ (i & 0x01 ? 0xc2 : 0) ) + +#define xp64(i) xp_fun( \ + (i & 0x80 ? 0xd8 : 0) ^ (i & 0x40 ? 0x6c : 0) ^ \ + (i & 0x20 ? 0x36 : 0) ^ (i & 0x10 ? 0x1b : 0) ^ \ + (i & 0x08 ? 0x0d : 0) ^ (i & 0x04 ? 0x06 : 0) ^ \ + (i & 0x02 ? 0x03 : 0) ^ (i & 0x01 ? 0x01 : 0), \ + (i & 0x80 ? 0x00 : 0) ^ (i & 0x40 ? 0x00 : 0) ^ \ + (i & 0x20 ? 0x00 : 0) ^ (i & 0x10 ? 0x00 : 0) ^ \ + (i & 0x08 ? 0x80 : 0) ^ (i & 0x04 ? 0xc0 : 0) ^ \ + (i & 0x02 ? 0x60 : 0) ^ (i & 0x01 ? 0xb0 : 0) ) + +static mode(32t) gf_poly[2] = { 0, 0xe1000000 }; +static mode(32t) gf_poly64[2] = { 0, 0xd8000000 }; + +/* Multiply of a GF128 field element by x. The field element */ +/* is held in an array of bytes in which field bits 8n..8n + 7 */ +/* are held in byte[n], with lower indexed bits placed in the */ +/* more numerically significant bit positions in bytes. */ + +/* This function multiples a field element x, in the polynomial */ +/* field representation. It uses 32-bit word operations to gain */ +/* speed but compensates for machine endianess and hence works */ +/* correctly on both styles of machine */ + +in_line void mul_x(mode(32t) x[4]) +{ mode(32t) t; + + bsw_32(x, 4); + + /* at this point the filed element bits 0..127 are set out */ + /* as follows in 32-bit words (where the most significant */ + /* (ms) numeric bits are to the left) */ + /* */ + /* x[0] x[1] x[2] x[3] */ + /* ms ls ms ls ms ls ms ls */ + /* field: 0 ... 31 32 .. 63 64 .. 95 96 .. 127 */ + + t = gf_poly[x[3] & 1]; /* bit 127 of the element */ + x[3] = (x[3] >> 1) | (x[2] << 31); /* shift bits up by one */ + x[2] = (x[2] >> 1) | (x[1] << 31); /* position */ + x[1] = (x[1] >> 1) | (x[0] << 31); /* if bit 7 is 1 xor in */ + x[0] = (x[0] >> 1) ^ t; /* the field polynomial */ + bsw_32(x, 4); +} + +in_line void mul_x64(mode(32t) x[2]) +{ mode(32t) t; + + bsw_32(x, 2); + + /* at this point the filed element bits 0..127 are set out */ + /* as follows in 32-bit words (where the most significant */ + /* (ms) numeric bits are to the left) */ + /* */ + /* x[0] x[1] x[2] x[3] */ + /* ms ls ms ls ms ls ms ls */ + /* field: 0 ... 31 32 .. 63 64 .. 95 96 .. 127 */ + + t = gf_poly64[x[1] & 1]; /* bit 127 of the element */ + /* shift bits up by one */ + /* position */ + x[1] = (x[1] >> 1) | (x[0] << 31); /* if bit 7 is 1 xor in */ + x[0] = (x[0] >> 1) ^ t; /* the field polynomial */ + bsw_32(x, 2); +} + +/* Multiply of a GF128 field element by x^8 using 32-bit words */ +/* for speed - machine endianess matters here */ + +#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) + +#define xp_fun(x,y) ((mode(32t))(x)) | (((mode(32t))(y)) << 8) +static const unsigned __int16 gft_le[256] = gf_dat(xp); +static const unsigned __int16 gft_le64[256] = gf_dat(xp64); + +in_line void mul_lex8(mode(32t) x[4]) /* mutiply with long words */ +{ mode(32t) t = (x[3] >> 24); /* in little endian format */ + x[3] = (x[3] << 8) | (x[2] >> 24); + x[2] = (x[2] << 8) | (x[1] >> 24); + x[1] = (x[1] << 8) | (x[0] >> 24); + x[0] = (x[0] << 8) ^ gft_le[t]; +} + +in_line void mul_lex8_64(mode(32t) x[2]) /* mutiply with long words */ +{ mode(32t) t = (x[1] >> 24); /* in little endian format */ + x[1] = (x[1] << 8) | (x[0] >> 24); + x[0] = (x[0] << 8) ^ gft_le64[t]; +} + +#endif + +#if 1 || (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) + +#undef xp_fun +#define xp_fun(x,y) ((mode(32t))(y)) | (((mode(32t))(x)) << 8) +static const unsigned __int16 gft_be[256] = gf_dat(xp); +static const unsigned __int16 gft_be64[256] = gf_dat(xp64); + +in_line void mul_bex8(mode(32t) x[4]) /* mutiply with long words */ +{ mode(32t) t = (x[3] & 0xff); /* in big endian format */ + x[3] = (x[3] >> 8) | (x[2] << 24); + x[2] = (x[2] >> 8) | (x[1] << 24); + x[1] = (x[1] >> 8) | (x[0] << 24); + x[0] = (x[0] >> 8) ^ (((mode(32t))gft_be[t]) << 16); +} + +in_line void mul_bex8_64(mode(32t) x[2]) /* mutiply with long words */ +{ mode(32t) t = (x[1] & 0xff); /* in big endian format */ + x[1] = (x[1] >> 8) | (x[0] << 24); + x[0] = (x[0] >> 8) ^ (((mode(32t))gft_be64[t]) << 16); +} + +#endif + +/* hence choose the correct version for the machine endianess */ + +#if PLATFORM_BYTE_ORDER == BRG_BIG_ENDIAN +#define mul_x8 mul_bex8 +#define mul_x8_64 mul_bex8_64 +#else +#define mul_x8 mul_lex8 +#define mul_x8_64 mul_lex8_64 +#endif + +/* different versions of the general gf_mul function are provided */ +/* here. Sadly none are very fast :-( */ + +void GfMul128 (void *a, const void* b) +{ mode(32t) r[CBLK_LEN >> 2], p[8][CBLK_LEN >> 2]; + int i; + + move_block_aligned(p[0], b); + bsw_32(p[0], 4); + for(i = 0; i < 7; ++i) + { + p[i + 1][3] = (p[i][3] >> 1) | (p[i][2] << 31); + p[i + 1][2] = (p[i][2] >> 1) | (p[i][1] << 31); + p[i + 1][1] = (p[i][1] >> 1) | (p[i][0] << 31); + p[i + 1][0] = (p[i][0] >> 1) ^ gf_poly[p[i][3] & 1]; + } + + memset(r, 0, CBLK_LEN); + for(i = 0; i < 16; ++i) + { + if(i) mul_bex8(r); /* order is always big endian here */ + + if(((unsigned char*)a)[15 - i] & 0x80) + xor_block_aligned(r, p[0]); + if(((unsigned char*)a)[15 - i] & 0x40) + xor_block_aligned(r, p[1]); + if(((unsigned char*)a)[15 - i] & 0x20) + xor_block_aligned(r, p[2]); + if(((unsigned char*)a)[15 - i] & 0x10) + xor_block_aligned(r, p[3]); + if(((unsigned char*)a)[15 - i] & 0x08) + xor_block_aligned(r, p[4]); + if(((unsigned char*)a)[15 - i] & 0x04) + xor_block_aligned(r, p[5]); + if(((unsigned char*)a)[15 - i] & 0x02) + xor_block_aligned(r, p[6]); + if(((unsigned char*)a)[15 - i] & 0x01) + xor_block_aligned(r, p[7]); + } + bsw_32(r, 4); + move_block_aligned(a, r); +} + +#if defined( UNROLL_LOOPS ) + +#define xor_8k(i) \ + xor_block_aligned(r, ctx->gf_t8k[i + i][a[i] & 15]); \ + xor_block_aligned(r, ctx->gf_t8k[i + i + 1][a[i] >> 4]) + + +void GfMul128Tab (unsigned char a[CBLK_LEN], GfCtx8k *ctx) +{ unsigned __int32 r[CBLK_LEN >> 2]; + + move_block_aligned(r, ctx->gf_t8k[0][a[0] & 15]); + xor_block_aligned(r, ctx->gf_t8k[1][a[0] >> 4]); + xor_8k( 1); xor_8k( 2); xor_8k( 3); + xor_8k( 4); xor_8k( 5); xor_8k( 6); xor_8k( 7); + xor_8k( 8); xor_8k( 9); xor_8k(10); xor_8k(11); + xor_8k(12); xor_8k(13); xor_8k(14); xor_8k(15); + move_block_aligned(a, r); +} + +#else + +void GfMul128Tab (unsigned char a[CBLK_LEN], GfCtx8k *ctx) +{ unsigned __int32 r[CBLK_LEN >> 2], *p; + int i; + + p = ctx->gf_t8k[0][a[0] & 15]; + memcpy(r, p, CBLK_LEN); + p = ctx->gf_t8k[1][a[0] >> 4]; + xor_block_aligned(r, p); + for(i = 1; i < CBLK_LEN; ++i) + { + xor_block_aligned(r, ctx->gf_t8k[i + i][a[i] & 15]); + xor_block_aligned(r, ctx->gf_t8k[i + i + 1][a[i] >> 4]); + } + memcpy(a, r, CBLK_LEN); +} + +#endif + +void compile_8k_table(unsigned __int8 *a, GfCtx8k *ctx) +{ int i, j, k; + + memset(ctx->gf_t8k, 0, 32 * 16 * 16); + for(i = 0; i < 2 * CBLK_LEN; ++i) + { + if(i == 0) + { + memcpy(ctx->gf_t8k[1][8], a, CBLK_LEN); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t8k[1][j], ctx->gf_t8k[1][j + j], CBLK_LEN); + mul_x(ctx->gf_t8k[1][j]); + } + memcpy(ctx->gf_t8k[0][8], ctx->gf_t8k[1][1], CBLK_LEN); + mul_x(ctx->gf_t8k[0][8]); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t8k[0][j], ctx->gf_t8k[0][j + j], CBLK_LEN); + mul_x(ctx->gf_t8k[0][j]); + } + } + else if(i > 1) + for(j = 8; j > 0; j >>= 1) + { + memcpy(ctx->gf_t8k[i][j], ctx->gf_t8k[i - 2][j], CBLK_LEN); + mul_x8(ctx->gf_t8k[i][j]); + } + + for(j = 2; j < 16; j += j) + { + mode(32t) *pj = ctx->gf_t8k[i][j]; + mode(32t) *pk = ctx->gf_t8k[i][1]; + mode(32t) *pl = ctx->gf_t8k[i][j + 1]; + + for(k = 1; k < j; ++k) + { + *pl++ = pj[0] ^ *pk++; + *pl++ = pj[1] ^ *pk++; + *pl++ = pj[2] ^ *pk++; + *pl++ = pj[3] ^ *pk++; + } + } + } +} + + +void compile_4k_table64(unsigned __int8 *a, GfCtx4k64 *ctx) +{ int i, j, k; + + memset(ctx->gf_t4k, 0, sizeof(ctx->gf_t4k)); + for(i = 0; i < 2 * CBLK_LEN8; ++i) + { + if(i == 0) + { + memcpy(ctx->gf_t4k[1][8], a, CBLK_LEN8); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t4k[1][j], ctx->gf_t4k[1][j + j], CBLK_LEN8); + mul_x64(ctx->gf_t4k[1][j]); + } + memcpy(ctx->gf_t4k[0][8], ctx->gf_t4k[1][1], CBLK_LEN8); + mul_x64(ctx->gf_t4k[0][8]); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t4k[0][j], ctx->gf_t4k[0][j + j], CBLK_LEN8); + mul_x64(ctx->gf_t4k[0][j]); + } + } + else if(i > 1) + for(j = 8; j > 0; j >>= 1) + { + memcpy(ctx->gf_t4k[i][j], ctx->gf_t4k[i - 2][j], CBLK_LEN8); + mul_x8_64(ctx->gf_t4k[i][j]); + } + + for(j = 2; j < 16; j += j) + { + mode(32t) *pj = ctx->gf_t4k[i][j]; + mode(32t) *pk = ctx->gf_t4k[i][1]; + mode(32t) *pl = ctx->gf_t4k[i][j + 1]; + + for(k = 1; k < j; ++k) + { + *pl++ = pj[0] ^ *pk++; + *pl++ = pj[1] ^ *pk++; + *pl++ = pj[2] ^ *pk++; + *pl++ = pj[3] ^ *pk++; + } + } + } +} + +static int IsBitSet128 (unsigned int bit, unsigned __int8 *a) +{ + return a[(127 - bit) / 8] & (0x80 >> ((127 - bit) % 8)); +} + +static int IsBitSet64 (unsigned int bit, unsigned __int8 *a) +{ + return a[(63 - bit) / 8] & (0x80 >> ((63 - bit) % 8)); +} + +static void SetBit128 (unsigned int bit, unsigned __int8 *a) +{ + a[(127 - bit) / 8] |= 0x80 >> ((127 - bit) % 8); +} + +static void SetBit64 (unsigned int bit, unsigned __int8 *a) +{ + a[(63 - bit) / 8] |= 0x80 >> ((63 - bit) % 8); +} + +void MirrorBits128 (unsigned __int8 *a) +{ + unsigned __int8 t[128 / 8]; + int i; + memset (t,0,16); + for (i = 0; i < 128; i++) + { + if (IsBitSet128(i, a)) + SetBit128 (127 - i, t); + } + memcpy (a, t, sizeof (t)); + burn (t,sizeof (t)); +} + +void MirrorBits64 (unsigned __int8 *a) +{ + unsigned __int8 t[64 / 8]; + int i; + memset (t,0,8); + for (i = 0; i < 64; i++) + { + if (IsBitSet64(i, a)) + SetBit64 (63 - i, t); + } + memcpy (a, t, sizeof (t)); + burn (t,sizeof (t)); +} + +/* Allocate and initialize speed optimization table + for multiplication by 64-bit operand in MSB-first mode */ +int Gf128Tab64Init (unsigned __int8 *a, GfCtx *ctx) +{ + GfCtx8k *ctx8k; + unsigned __int8 am[16]; + int i, j; + + ctx8k = (GfCtx8k *) TCalloc (sizeof (GfCtx8k)); + if (!ctx8k) + return FALSE; + + memcpy (am, a, 16); + MirrorBits128 (am); + compile_8k_table (am, ctx8k); + + /* Convert 8k LSB-first table to 4k MSB-first */ + for (i = 16; i < 32; i++) + { + for (j = 0; j < 16; j++) + { + int jm = 0; + jm |= (j & 0x1) << 3; + jm |= (j & 0x2) << 1; + jm |= (j & 0x4) >> 1; + jm |= (j & 0x8) >> 3; + + memcpy (&ctx->gf_t128[i-16][jm], (unsigned char *)&ctx8k->gf_t8k[31-i][j], 16); + MirrorBits128 ((unsigned char *)&ctx->gf_t128[i-16][jm]); + } + } + + burn (ctx8k ,sizeof (*ctx8k)); + burn (am, sizeof (am)); + TCfree (ctx8k); + return TRUE; +} + +int Gf64TabInit (unsigned __int8 *a, GfCtx *ctx) +{ + /* Deprecated/legacy */ + + GfCtx4k64 *ctx4k; + unsigned __int8 am[8]; + int i, j; + + ctx4k = (GfCtx4k64 *) TCalloc (sizeof (GfCtx4k64)); + if (!ctx4k) + return FALSE; + + memcpy (am, a, 8); + MirrorBits64 (am); + compile_4k_table64 (am, ctx4k); + + /* Convert LSB-first table to MSB-first */ + for (i = 0; i < 16; i++) + { + for (j = 0; j < 16; j++) + { + int jm = 0; + jm |= (j & 0x1) << 3; + jm |= (j & 0x2) << 1; + jm |= (j & 0x4) >> 1; + jm |= (j & 0x8) >> 3; + + memcpy (&ctx->gf_t64[i][jm], (unsigned char *)&ctx4k->gf_t4k[15-i][j], 8); + MirrorBits64 ((unsigned char *)&ctx->gf_t64[i][jm]); + } + } + + burn (ctx4k,sizeof (*ctx4k)); + burn (am, sizeof (am)); + TCfree (ctx4k); + return TRUE; +} + +#define xor_8kt64(i) \ + xor_block_aligned(r, ctx->gf_t128[i + i][a[i] & 15]); \ + xor_block_aligned(r, ctx->gf_t128[i + i + 1][a[i] >> 4]) + +/* Multiply a 128-bit number by a 64-bit number in the finite field GF(2^128) */ +void Gf128MulBy64Tab (unsigned __int8 a[8], unsigned __int8 p[16], GfCtx *ctx) +{ + unsigned __int32 r[CBLK_LEN >> 2]; + + move_block_aligned(r, ctx->gf_t128[7*2][a[7] & 15]); + xor_block_aligned(r, ctx->gf_t128[7*2+1][a[7] >> 4]); + + if (*(unsigned __int16 *)a) + { + xor_8kt64(0); + xor_8kt64(1); + } + if (a[2]) + { + xor_8kt64(2); + } + xor_8kt64(3); + xor_8kt64(4); + xor_8kt64(5); + xor_8kt64(6); + + move_block_aligned(p, r); +} + +#define xor_8k64(i) \ + xor_block_aligned64(r, ctx->gf_t64[i + i][a[i] & 15]); \ + xor_block_aligned64(r, ctx->gf_t64[i + i + 1][a[i] >> 4]) + +/* Multiply two 64-bit numbers in the finite field GF(2^64) */ +void Gf64MulTab (unsigned char a[8], unsigned char p[8], GfCtx *ctx) +{ + /* Deprecated/legacy */ + + unsigned __int32 r[CBLK_LEN8 >> 2]; + + move_block_aligned64(r, ctx->gf_t64[7*2][a[7] & 15]); + xor_block_aligned64(r, ctx->gf_t64[7*2+1][a[7] >> 4]); + + if (*(unsigned __int16 *)a) + { + xor_8k64(0); + xor_8k64(1); + } + if (a[2]) + { + xor_8k64(2); + } + xor_8k64(3); + xor_8k64(4); + xor_8k64(5); + xor_8k64(6); + + move_block_aligned64(p, r); +} + + +/* Basic algorithms for testing of optimized algorithms */ + +static void xor128 (uint64 *a, uint64 *b) +{ + *a++ ^= *b++; + *a ^= *b; +} + +static void shl128 (unsigned __int8 *a) +{ + int i, x = 0, xx; + for (i = 15; i >= 0; i--) + { + xx = (a[i] & 0x80) >> 7; + a[i] = (char) ((a[i] << 1) | x); + x = xx; + } +} + +static void GfMul128Basic (unsigned __int8 *a, unsigned __int8 *b, unsigned __int8 *p) +{ + int i; + unsigned __int8 la[16]; + memcpy (la, a, 16); + memset (p, 0, 16); + + for (i = 0; i < 128; i++) + { + if (IsBitSet128 (i, b)) + xor128 ((uint64 *)p, (uint64 *)la); + + if (la[0] & 0x80) + { + shl128 (la); + la[15] ^= 0x87; + } + else + { + shl128 (la); + } + } +} + +static void xor64 (uint64 *a, uint64 *b) +{ + *a ^= *b; +} + +static void shl64 (unsigned __int8 *a) +{ + int i, x = 0, xx; + for (i = 7; i >= 0; i--) + { + xx = (a[i] & 0x80) >> 7; + a[i] = (char) ((a[i] << 1) | x); + x = xx; + } +} + +static void GfMul64Basic (unsigned __int8 *a, unsigned __int8 *b, unsigned __int8* p) +{ + /* Deprecated/legacy */ + + int i; + unsigned __int8 la[8]; + memcpy (la, a, 8); + memset (p, 0, 8); + + for (i = 0; i < 64; i++) + { + if (IsBitSet64 (i, b)) + xor64 ((uint64 *)p, (uint64 *)la); + + if (la[0] & 0x80) + { + shl64 (la); + la[7] ^= 0x1b; + } + else + { + shl64 (la); + } + } +} + + +BOOL GfMulSelfTest () +{ + BOOL result = TRUE; + unsigned __int8 a[16]; + unsigned __int8 b[16]; + unsigned __int8 p1[16]; + unsigned __int8 p2[16]; + GfCtx *gfCtx = (GfCtx *) TCalloc (sizeof (GfCtx)); + int i, j; + + if (!gfCtx) + return FALSE; + + /* GF(2^64) - deprecated/legacy */ + for (i = 0; i < 0x100; i++) + { + for (j = 0; j < 8; j++) + { + a[j] = (unsigned __int8) i; + b[j] = a[j] ^ 0xff; + } + + GfMul64Basic (a, b, p1); + + Gf64TabInit (a, gfCtx); + Gf64MulTab (b, p2, gfCtx); + + if (memcmp (p1, p2, 8) != 0) + result = FALSE; + } + + /* GF(2^128) */ + for (i = 0; i < 0x100; i++) + { + for (j = 0; j < 16; j++) + { + a[j] = (unsigned __int8) i; + b[j] = j < 8 ? 0 : a[j] ^ 0xff; + } + + GfMul128Basic (a, b, p1); + + Gf128Tab64Init (a, gfCtx); + Gf128MulBy64Tab (b + 8, p2, gfCtx); + + if (memcmp (p1, p2, 16) != 0) + result = FALSE; + } + + TCfree (gfCtx); + return result; +} + +#if defined(__cplusplus) +} +#endif diff --git a/Common/GfMul.h b/Common/GfMul.h index 50dee4b..9d828a0 100644 --- a/Common/GfMul.h +++ b/Common/GfMul.h @@ -1,76 +1,76 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 31/01/2004 -*/ - -/* Adapted for TrueCrypt by the TrueCrypt Foundation */ - -#ifndef _GCM_H -#define _GCM_H - -#include "Tcdefs.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define CBLK_LEN 16 /* encryption block length */ -#define CBLK_LEN8 8 - -typedef struct -{ - unsigned __int32 gf_t8k[CBLK_LEN * 2][16][CBLK_LEN / 4]; -} GfCtx8k; - -typedef struct -{ - unsigned __int32 gf_t4k[CBLK_LEN8 * 2][16][CBLK_LEN / 4]; -} GfCtx4k64; - -typedef struct -{ - /* union not used to support faster mounting */ - unsigned __int32 gf_t128[CBLK_LEN * 2 / 2][16][CBLK_LEN / 4]; - unsigned __int32 gf_t64[CBLK_LEN8 * 2][16][CBLK_LEN8 / 4]; -} GfCtx; - -typedef int ret_type; - -void GfMul128 (void *a, const void* b); -void GfMul128Tab(unsigned char a[16], GfCtx8k *ctx); -int Gf128Tab64Init (unsigned __int8 *a, GfCtx *ctx); -void Gf128MulBy64Tab (unsigned __int8 a[8], unsigned __int8 p[16], GfCtx *ctx); -int Gf64TabInit (unsigned __int8 *a, GfCtx *ctx); -void Gf64MulTab (unsigned char a[8], unsigned char p[8], GfCtx *ctx); -void MirrorBits128 (unsigned __int8 *a); -void MirrorBits64 (unsigned __int8 *a); -BOOL GfMulSelfTest (); - -#if defined(__cplusplus) -} -#endif - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 31/01/2004 +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#ifndef _GCM_H +#define _GCM_H + +#include "Tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define CBLK_LEN 16 /* encryption block length */ +#define CBLK_LEN8 8 + +typedef struct +{ + unsigned __int32 gf_t8k[CBLK_LEN * 2][16][CBLK_LEN / 4]; +} GfCtx8k; + +typedef struct +{ + unsigned __int32 gf_t4k[CBLK_LEN8 * 2][16][CBLK_LEN / 4]; +} GfCtx4k64; + +typedef struct +{ + /* union not used to support faster mounting */ + unsigned __int32 gf_t128[CBLK_LEN * 2 / 2][16][CBLK_LEN / 4]; + unsigned __int32 gf_t64[CBLK_LEN8 * 2][16][CBLK_LEN8 / 4]; +} GfCtx; + +typedef int ret_type; + +void GfMul128 (void *a, const void* b); +void GfMul128Tab(unsigned char a[16], GfCtx8k *ctx); +int Gf128Tab64Init (unsigned __int8 *a, GfCtx *ctx); +void Gf128MulBy64Tab (unsigned __int8 a[8], unsigned __int8 p[16], GfCtx *ctx); +int Gf64TabInit (unsigned __int8 *a, GfCtx *ctx); +void Gf64MulTab (unsigned char a[8], unsigned char p[8], GfCtx *ctx); +void MirrorBits128 (unsigned __int8 *a); +void MirrorBits64 (unsigned __int8 *a); +BOOL GfMulSelfTest (); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Common/Inflate.c b/Common/Inflate.c index 8b1504d..4f9dc8f 100644 --- a/Common/Inflate.c +++ b/Common/Inflate.c @@ -1,1306 +1,1308 @@ -/* inflate.c -- put in the public domain by Mark Adler */ - -/* Decompresses raw data compressed using the DEFLATE algorithm (RFC 1951) */ - -/* You can do whatever you like with this source file, though I would - prefer that if you modify it and redistribute it that you include - comments to that effect with your name and the date. Thank you. - - History: - vers date who what - ---- --------- -------------- ------------------------------------ - a ~~ Feb 92 M. Adler used full (large, one-step) lookup table - b1 21 Mar 92 M. Adler first version with partial lookup tables - b2 21 Mar 92 M. Adler fixed bug in fixed-code blocks - b3 22 Mar 92 M. Adler sped up match copies, cleaned up some - b4 25 Mar 92 M. Adler added prototypes; removed window[] (now - is the responsibility of unzip.h--also - changed name to slide[]), so needs diffs - for unzip.c and unzip.h (this allows - compiling in the small model on MSDOS); - fixed cast of q in huft_build(); - b5 26 Mar 92 M. Adler got rid of unintended macro recursion. - b6 27 Mar 92 M. Adler got rid of nextbyte() routine. fixed - bug in inflate_fixed(). - c1 30 Mar 92 M. Adler removed lbits, dbits environment variables. - changed BMAX to 16 for explode. Removed - OUTB usage, and replaced it with flush()-- - this was a 20% speed improvement! Added - an explode.c (to replace unimplod.c) that - uses the huft routines here. Removed - register union. - c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. - c3 10 Apr 92 M. Adler reduced memory of code tables made by - huft_build significantly (factor of two to - three). - c4 15 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy(). - worked around a Turbo C optimization bug. - c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing - the 32K window size for specialized - applications. - c6 31 May 92 M. Adler added some typecasts to eliminate warnings - c7 27 Jun 92 G. Roelofs added some more typecasts (444: MSC bug). - c8 5 Oct 92 J-l. Gailly added ifdef'd code to deal with PKZIP bug. - c9 9 Oct 92 M. Adler removed a memory error message (~line 416). - c10 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch, - removed old inflate, renamed inflate_entry - to inflate, added Mark's fix to a comment. - c10.5 14 Dec 92 M. Adler fix up error messages for incomplete trees. - c11 2 Jan 93 M. Adler fixed bug in detection of incomplete - tables, and removed assumption that EOB is - the longest code (bad assumption). - c12 3 Jan 93 M. Adler make tables for fixed blocks only once. - c13 5 Jan 93 M. Adler allow all zero length codes (pkzip 2.04c - outputs one zero length code for an empty - distance tree). - c14 12 Mar 93 M. Adler made inflate.c standalone with the - introduction of inflate.h. - c14b 16 Jul 93 G. Roelofs added (unsigned) typecast to w at 470. - c14c 19 Jul 93 J. Bush changed v[N_MAX], l[288], ll[28x+3x] arrays - to static for Amiga. - c14d 13 Aug 93 J-l. Gailly de-complicatified Mark's c[*p++]++ thing. - c14e 8 Oct 93 G. Roelofs changed memset() to memzero(). - c14f 22 Oct 93 G. Roelofs renamed quietflg to qflag; made Trace() - conditional; added inflate_free(). - c14g 28 Oct 93 G. Roelofs changed l/(lx+1) macro to pointer (Cray bug) - c14h 7 Dec 93 C. Ghisler huft_build() optimizations. - c14i 9 Jan 94 A. Verheijen set fixed_t{d,l} to NULL after freeing; - G. Roelofs check NEXTBYTE macro for EOF. - c14j 23 Jan 94 G. Roelofs removed Ghisler "optimizations"; ifdef'd - EOF check. - c14k 27 Feb 94 G. Roelofs added some typecasts to avoid warnings. - c14l 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines - to avoid bug in Encore compiler. - c14m 7 Jul 94 P. Kienitz modified to allow assembler version of - inflate_codes() (define ASM_INFLATECODES) - c14n 22 Jul 94 G. Roelofs changed fprintf to macro for DLL versions - c14o 23 Aug 94 C. Spieler added a newline to a debug statement; - G. Roelofs added another typecast to avoid MSC warning - c14p 4 Oct 94 G. Roelofs added (voidp *) cast to free() argument - c14q 30 Oct 94 G. Roelofs changed fprintf macro to MESSAGE() - c14r 1 Nov 94 G. Roelofs fixed possible redefinition of CHECK_EOF - c14s 7 May 95 S. Maxwell OS/2 DLL globals stuff incorporated; - P. Kienitz "fixed" ASM_INFLATECODES macro/prototype - c14t 18 Aug 95 G. Roelofs added inflate() to use zlib functions; - changed voidp to zvoid; moved huft_build() - and huft_free() to end of file - c14u 1 Oct 95 G. Roelofs moved G into definition of MESSAGE macro - c14v 8 Nov 95 P. Kienitz changed ASM_INFLATECODES to use a regular - call with __G__ instead of a macro - c15 3 Aug 96 M. Adler fixed bomb-bug on random input data (Adobe) - c15b 24 Aug 96 M. Adler more fixes for random input data - c15c 28 Mar 97 G. Roelofs changed USE_ZLIB fatal exit code from - PK_MEM2 to PK_MEM3 - c16 20 Apr 97 J. Altman added memzero(v[]) in huft_build() - c16b 29 Mar 98 C. Spieler modified DLL code for slide redirection - - fork 12 Dec 07 TrueCrypt Foundation Adapted for TrueCrypt - */ - - -/* - Inflate deflated (PKZIP's method 8 compressed) data. The compression - method searches for as much of the current string of bytes (up to a - length of 258) in the previous 32K bytes. If it doesn't find any - matches (of at least length 3), it codes the next byte. Otherwise, it - codes the length of the matched string and its distance backwards from - the current position. There is a single Huffman code that codes both - single bytes (called "literals") and match lengths. A second Huffman - code codes the distance information, which follows a length code. Each - length or distance code actually represents a base value and a number - of "extra" (sometimes zero) bits to get to add to the base value. At - the end of each deflated block is a special end-of-block (EOB) literal/ - length code. The decoding process is basically: get a literal/length - code; if EOB then done; if a literal, emit the decoded byte; if a - length then get the distance and emit the referred-to bytes from the - sliding window of previously emitted data. - - There are (currently) three kinds of inflate blocks: stored, fixed, and - dynamic. The compressor outputs a chunk of data at a time and decides - which method to use on a chunk-by-chunk basis. A chunk might typically - be 32K to 64K, uncompressed. If the chunk is uncompressible, then the - "stored" method is used. In this case, the bytes are simply stored as - is, eight bits per byte, with none of the above coding. The bytes are - preceded by a count, since there is no longer an EOB code. - - If the data are compressible, then either the fixed or dynamic methods - are used. In the dynamic method, the compressed data are preceded by - an encoding of the literal/length and distance Huffman codes that are - to be used to decode this block. The representation is itself Huffman - coded, and so is preceded by a description of that code. These code - descriptions take up a little space, and so for small blocks, there is - a predefined set of codes, called the fixed codes. The fixed method is - used if the block ends up smaller that way (usually for quite small - chunks); otherwise the dynamic method is used. In the latter case, the - codes are customized to the probabilities in the current block and so - can code it much better than the pre-determined fixed codes can. - - The Huffman codes themselves are decoded using a multi-level table - lookup, in order to maximize the speed of decoding plus the speed of - building the decoding tables. See the comments below that precede the - lbits and dbits tuning parameters. - - GRR: return values(?) - 0 OK - 1 incomplete table - 2 bad input - 3 not enough memory - */ - - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -/* #define DEBUG */ -#define INFMOD /* tell inflate.h to include code to be compiled */ -#include "inflate.h" - - -#ifndef WSIZE /* default is 32K */ -# define WSIZE 0x8000 /* window size--must be a power of two, and at least */ -#endif /* 32K for zip's deflate method */ - -#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) -# define wsize G._wsize /* wsize is a variable */ -#else -# define wsize WSIZE /* wsize is a constant */ -#endif - - -#ifndef NEXTBYTE /* default is to simply get a byte from stdin */ -# define NEXTBYTE getchar() -#endif - -#ifndef MESSAGE /* only used twice, for fixed strings--NOT general-purpose */ -# define MESSAGE(str,len,flag) fprintf(stderr,(char *)(str)) -#endif - -#ifndef FLUSH /* default is to simply write the buffer to stdout */ -# define FLUSH(n) fwrite(redirSlide, 1, n, stdout) /* return value not used */ -#endif -/* Warning: the fwrite above might not work on 16-bit compilers, since - 0x8000 might be interpreted as -32,768 by the library function. */ - -#ifndef Trace -# ifdef DEBUG -# define Trace(x) fprintf x -# else -# define Trace(x) -# endif -#endif - -G_struct G; -uch redirSlide [WSIZE]; - -/*---------------------------------------------------------------------------*/ -#ifdef USE_ZLIB - - -/* - GRR: return values for both original inflate() and inflate() - 0 OK - 1 incomplete table(?) - 2 bad input - 3 not enough memory - */ - -/**************************/ -/* Function inflate() */ -/**************************/ - -int inflate(__G) /* decompress an inflated entry using the zlib routines */ - __GDEF -{ - int err=Z_OK; - -#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) - if (G.redirect_slide) - wsize = G.redirect_size, redirSlide = G.redirect_buffer; - else - wsize = WSIZE, redirSlide = slide; -#endif - - G.dstrm.next_out = redirSlide; - G.dstrm.avail_out = wsize; - - G.dstrm.next_in = G.inptr; - G.dstrm.avail_in = G.incnt; - - if (!G.inflInit) { - unsigned i; - int windowBits; - - /* only need to test this stuff once */ - if (zlib_version[0] != ZLIB_VERSION[0]) { - Info(slide, 0x21, ((char *)slide, - "error: incompatible zlib version (expected %s, found %s)\n", - ZLIB_VERSION, zlib_version)); - return 3; - } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) - Info(slide, 0x21, ((char *)slide, - "warning: different zlib version (expected %s, using %s)\n", - ZLIB_VERSION, zlib_version)); - - /* windowBits = log2(wsize) */ - for (i = ((unsigned)wsize * 2 - 1), windowBits = 0; - !(i & 1); i >>= 1, ++windowBits); - if ((unsigned)windowBits > (unsigned)15) - windowBits = 15; - else if (windowBits < 8) - windowBits = 8; - - G.dstrm.zalloc = (alloc_func)Z_NULL; - G.dstrm.zfree = (free_func)Z_NULL; - - Trace((stderr, "initializing inflate()\n")); - err = inflateInit2(&G.dstrm, -windowBits); - - if (err == Z_MEM_ERROR) - return 3; - else if (err != Z_OK) - Trace((stderr, "oops! (inflateInit2() err = %d)\n", err)); - G.inflInit = 1; - } - -#ifdef FUNZIP - while (err != Z_STREAM_END) { -#else /* !FUNZIP */ - while (G.csize > 0) { - Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); -#endif /* ?FUNZIP */ - while (G.dstrm.avail_out > 0) { - err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); - - if (err == Z_DATA_ERROR) - return 2; - else if (err == Z_MEM_ERROR) - return 3; - else if (err != Z_OK && err != Z_STREAM_END) - Trace((stderr, "oops! (inflate(first loop) err = %d)\n", err)); - -#ifdef FUNZIP - if (err == Z_STREAM_END) /* "END-of-entry-condition" ? */ -#else /* !FUNZIP */ - if (G.csize <= 0L) /* "END-of-entry-condition" ? */ -#endif /* ?FUNZIP */ - break; - - if (G.dstrm.avail_in <= 0) { - if (fillinbuf(__G) == 0) - return 2; /* no "END-condition" yet, but no more data */ - - G.dstrm.next_in = G.inptr; - G.dstrm.avail_in = G.incnt; - } - Trace((stderr, " avail_in = %d\n", G.dstrm.avail_in)); - } - FLUSH(wsize - G.dstrm.avail_out); /* flush slide[] */ - Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", - (long)(wsize - G.dstrm.avail_out), - (long)(G.dstrm.next_out-(Bytef *)redirSlide))); - G.dstrm.next_out = redirSlide; - G.dstrm.avail_out = wsize; - } - - /* no more input, so loop until we have all output */ - Trace((stderr, "beginning final loop: err = %d\n", err)); - while (err != Z_STREAM_END) { - err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); - if (err == Z_DATA_ERROR) - return 2; - else if (err == Z_MEM_ERROR) - return 3; - else if (err == Z_BUF_ERROR) { /* DEBUG */ - Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n" - , G.zipfn, G.filename)); - break; - } else if (err != Z_OK && err != Z_STREAM_END) { - Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err)); - DESTROYGLOBALS() - EXIT(PK_MEM3); - } - FLUSH(wsize - G.dstrm.avail_out); /* final flush of slide[] */ - Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", - (long)(wsize - G.dstrm.avail_out), - (long)(G.dstrm.next_out-(Bytef *)redirSlide))); - G.dstrm.next_out = redirSlide; - G.dstrm.avail_out = wsize; - } - Trace((stderr, "total in = %ld, total out = %ld\n", G.dstrm.total_in, - G.dstrm.total_out)); - - G.inptr = (uch *)G.dstrm.next_in; - G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ - - err = inflateReset(&G.dstrm); - if (err != Z_OK) - Trace((stderr, "oops! (inflateReset() err = %d)\n", err)); - - return 0; -} - - -/*---------------------------------------------------------------------------*/ -#else /* !USE_ZLIB */ - - -/* Function prototypes */ -#ifndef OF -# ifdef __STDC__ -# define OF(a) a -# else -# define OF(a) () -# endif -#endif /* !OF */ -int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td, - int bl, int bd)); -static int inflate_stored OF((__GPRO)); -static int inflate_fixed OF((__GPRO)); -static int inflate_dynamic OF((__GPRO)); -static int inflate_block OF((__GPRO__ int *e)); - - -/* The inflate algorithm uses a sliding 32K byte window on the uncompressed - stream to find repeated byte strings. This is implemented here as a - circular buffer. The index is updated simply by incrementing and then - and'ing with 0x7fff (32K-1). */ -/* It is left to other modules to supply the 32K area. It is assumed - to be usable as if it were declared "uch slide[32768];" or as just - "uch *slide;" and then malloc'ed in the latter case. The definition - must be in unzip.h, included above. */ - - -/* unsigned wp; moved to globals.h */ /* current position in slide */ - - -/* Tables for deflate from PKZIP's appnote.txt. */ -static ZCONST unsigned border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -static ZCONST ush cplens[] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* note: see note #13 above about the 258 in this list. */ -static ZCONST ush cplext[] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ -static ZCONST ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -static ZCONST ush cpdext[] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - - -/* moved to consts.h (included in unzip.c), resp. funzip.c */ -#if 1 -/* And'ing with mask_bits[n] masks the lower n bits */ -ZCONST ush near mask_bits[] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; -#endif /* 0 */ - - -/* Macros for inflate() bit peeking and grabbing. - The usage is: - - NEEDBITS(j) - x = b & mask_bits[j]; - DUMPBITS(j) - - where NEEDBITS makes sure that b has at least j bits in it, and - DUMPBITS removes the bits from b. The macros use the variable k - for the number of bits in b. Normally, b and k are register - variables for speed and are initialized at the begining of a - routine that uses these macros from a global bit buffer and count. - - In order to not ask for more bits than there are in the compressed - stream, the Huffman tables are constructed to only ask for just - enough bits to make up the end-of-block code (value 256). Then no - bytes need to be "returned" to the buffer at the end of the last - block. See the huft_build() routine. - */ - -/* These have been moved to globals.h */ -#if 0 -ulg bb; /* bit buffer */ -unsigned bk; /* bits in bit buffer */ -#endif - -#ifndef CHECK_EOF -# define CHECK_EOF /* default as of 5.13/5.2 */ -#endif - -#ifndef CHECK_EOF -# define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<>=(n);k-=(n);} - - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - are not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - -static ZCONST int lbits = 9; /* bits in base literal/length lookup table */ -static ZCONST int dbits = 6; /* bits in base distance lookup table */ - - -#ifndef ASM_INFLATECODES - -int inflate_codes(__G__ tl, td, bl, bd) - __GDEF -struct huft *tl, *td; /* literal/length and distance decoder tables */ -int bl, bd; /* number of bits decoded by tl[] and td[] */ -/* inflate (decompress) the codes in a deflated (compressed) block. - Return an error code or zero if it all goes ok. */ -{ - register unsigned e; /* table entry flag/number of extra bits */ - unsigned n, d; /* length and index for copy */ - unsigned w; /* current window position */ - struct huft *t; /* pointer to table entry */ - unsigned ml, md; /* masks for bl and bd bits */ - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - - /* make local copies of globals */ - b = G.bb; /* initialize bit buffer */ - k = G.bk; - w = G.wp; /* initialize window position */ - - - /* inflate the coded data */ - ml = mask_bits[bl]; /* precompute masks for speed */ - md = mask_bits[bd]; - while (1) /* do until end of block */ - { - NEEDBITS((unsigned)bl) - if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) - do { - if (e == 99) - return 1; - DUMPBITS(t->b) - e -= 16; - NEEDBITS(e) - } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); - DUMPBITS(t->b) - if (e == 16) /* then it's a literal */ - { - redirSlide[w++] = (uch)t->v.n; - if (w == wsize) - { - FLUSH(w); - w = 0; - } - } - else /* it's an EOB or a length */ - { - /* exit if end of block */ - if (e == 15) - break; - - /* get length of block to copy */ - NEEDBITS(e) - n = t->v.n + ((unsigned)b & mask_bits[e]); - DUMPBITS(e); - - /* decode distance of block to copy */ - NEEDBITS((unsigned)bd) - if ((e = (t = td + ((unsigned)b & md))->e) > 16) - do { - if (e == 99) - return 1; - DUMPBITS(t->b) - e -= 16; - NEEDBITS(e) - } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); - DUMPBITS(t->b) - NEEDBITS(e) - d = w - t->v.n - ((unsigned)b & mask_bits[e]); - DUMPBITS(e) - - /* do the copy */ - do { -#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) - if (G.redirect_slide) {/* &= w/ wsize unnecessary & wrong if redirect */ - if (d >= wsize) - return 1; /* invalid compressed data */ - n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); - } - else -#endif - n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); -#ifndef NOMEMCPY - if (w - d >= e) /* (this test assumes unsigned comparison) */ - { - memcpy(redirSlide + w, redirSlide + d, e); - w += e; - d += e; - } - else /* do it slowly to avoid memcpy() overlap */ -#endif /* !NOMEMCPY */ - do { - redirSlide[w++] = redirSlide[d++]; - } while (--e); - if (w == wsize) - { - FLUSH(w); - w = 0; - } - } while (n); - } - } - - - /* restore the globals from the locals */ - G.wp = w; /* restore global window pointer */ - G.bb = b; /* restore global bit buffer */ - G.bk = k; - - - /* done */ - return 0; -} - -#endif /* ASM_INFLATECODES */ - - - -static int inflate_stored(__G) - __GDEF -/* "decompress" an inflated type 0 (stored) block. */ -{ - unsigned n; /* number of bytes in block */ - unsigned w; /* current window position */ - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - - /* make local copies of globals */ - Trace((stderr, "\nstored block")); - b = G.bb; /* initialize bit buffer */ - k = G.bk; - w = G.wp; /* initialize window position */ - - - /* go to byte boundary */ - n = k & 7; - DUMPBITS(n); - - - /* get the length and its complement */ - NEEDBITS(16) - n = ((unsigned)b & 0xffff); - DUMPBITS(16) - NEEDBITS(16) - if (n != (unsigned)((~b) & 0xffff)) - return 1; /* error in compressed data */ - DUMPBITS(16) - - - /* read and output the compressed data */ - while (n--) - { - NEEDBITS(8) - redirSlide[w++] = (uch)b; - if (w == wsize) - { - FLUSH(w); - w = 0; - } - DUMPBITS(8) - } - - - /* restore the globals from the locals */ - G.wp = w; /* restore global window pointer */ - G.bb = b; /* restore global bit buffer */ - G.bk = k; - return 0; -} - - -/* Globals for literal tables (built once) */ -/* Moved to globals.h */ -#if 0 -struct huft *fixed_tl = (struct huft *)NULL; -struct huft *fixed_td; -int fixed_bl, fixed_bd; -#endif - -static int inflate_fixed(__G) - __GDEF -/* decompress an inflated type 1 (fixed Huffman codes) block. We should - either replace this with a custom decoder, or at least precompute the - Huffman tables. */ -{ - /* if first time, set up tables for fixed blocks */ - Trace((stderr, "\nliteral block")); - if (G.fixed_tl == (struct huft *)NULL) - { - int i; /* temporary variable */ - unsigned l[288]; /* length list for huft_build */ - - /* literal table */ - for (i = 0; i < 144; i++) - l[i] = 8; - for (; i < 256; i++) - l[i] = 9; - for (; i < 280; i++) - l[i] = 7; - for (; i < 288; i++) /* make a complete, but wrong code set */ - l[i] = 8; - G.fixed_bl = 7; - if ((i = huft_build(__G__ l, 288, 257, cplens, cplext, - &G.fixed_tl, &G.fixed_bl)) != 0) - { - G.fixed_tl = (struct huft *)NULL; - return i; - } - - /* distance table */ - for (i = 0; i < 30; i++) /* make an incomplete code set */ - l[i] = 5; - G.fixed_bd = 5; - if ((i = huft_build(__G__ l, 30, 0, cpdist, cpdext, - &G.fixed_td, &G.fixed_bd)) > 1) - { - huft_free(G.fixed_tl); - G.fixed_tl = (struct huft *)NULL; - return i; - } - } - - /* decompress until an end-of-block code */ - return inflate_codes(__G__ G.fixed_tl, G.fixed_td, - G.fixed_bl, G.fixed_bd) != 0; -} - - - -static int inflate_dynamic(__G) - __GDEF -/* decompress an inflated type 2 (dynamic Huffman codes) block. */ -{ - int i; /* temporary variables */ - unsigned j; - unsigned l; /* last length */ - unsigned m; /* mask for bit lengths table */ - unsigned n; /* number of lengths to get */ - struct huft *tl; /* literal/length code table */ - struct huft *td; /* distance code table */ - int bl; /* lookup bits for tl */ - int bd; /* lookup bits for td */ - unsigned nb; /* number of bit length codes */ - unsigned nl; /* number of literal/length codes */ - unsigned nd; /* number of distance codes */ -#ifdef PKZIP_BUG_WORKAROUND - unsigned ll[288+32]; /* literal/length and distance code lengths */ -#else - unsigned ll[286+30]; /* literal/length and distance code lengths */ -#endif - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - - /* make local bit buffer */ - Trace((stderr, "\ndynamic block")); - b = G.bb; - k = G.bk; - - - /* read in table lengths */ - NEEDBITS(5) - nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ - DUMPBITS(5) - NEEDBITS(5) - nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ - DUMPBITS(5) - NEEDBITS(4) - nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ - DUMPBITS(4) -#ifdef PKZIP_BUG_WORKAROUND - if (nl > 288 || nd > 32) -#else - if (nl > 286 || nd > 30) -#endif - return 1; /* bad lengths */ - - - /* read in bit-length-code lengths */ - for (j = 0; j < nb; j++) - { - NEEDBITS(3) - ll[border[j]] = (unsigned)b & 7; - DUMPBITS(3) - } - for (; j < 19; j++) - ll[border[j]] = 0; - - - /* build decoding table for trees--single level, 7 bit lookup */ - bl = 7; - i = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl); - if (bl == 0) /* no bit lengths */ - i = 1; - if (i) - { - if (i == 1) - huft_free(tl); - return i; /* incomplete code set */ - } - - - /* read in literal and distance code lengths */ - n = nl + nd; - m = mask_bits[bl]; - i = l = 0; - while ((unsigned)i < n) - { - NEEDBITS((unsigned)bl) - j = (td = tl + ((unsigned)b & m))->b; - DUMPBITS(j) - j = td->v.n; - if (j < 16) /* length of code in bits (0..15) */ - ll[i++] = l = j; /* save last length in l */ - else if (j == 16) /* repeat last length 3 to 6 times */ - { - NEEDBITS(2) - j = 3 + ((unsigned)b & 3); - DUMPBITS(2) - if ((unsigned)i + j > n) - return 1; - while (j--) - ll[i++] = l; - } - else if (j == 17) /* 3 to 10 zero length codes */ - { - NEEDBITS(3) - j = 3 + ((unsigned)b & 7); - DUMPBITS(3) - if ((unsigned)i + j > n) - return 1; - while (j--) - ll[i++] = 0; - l = 0; - } - else /* j == 18: 11 to 138 zero length codes */ - { - NEEDBITS(7) - j = 11 + ((unsigned)b & 0x7f); - DUMPBITS(7) - if ((unsigned)i + j > n) - return 1; - while (j--) - ll[i++] = 0; - l = 0; - } - } - - - /* free decoding table for trees */ - huft_free(tl); - - - /* restore the global bit buffer */ - G.bb = b; - G.bk = k; - - - /* build the decoding tables for literal/length and distance codes */ - bl = lbits; - i = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl); - if (bl == 0) /* no literals or lengths */ - i = 1; - if (i) - { - if (i == 1) { - //if (!uO.qflag) - MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1); - huft_free(tl); - } - return i; /* incomplete code set */ - } - bd = dbits; - i = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd); - if (bd == 0 && nl > 257) /* lengths but no distances */ - { - //if (!uO.qflag) - MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); - huft_free(tl); - return 1; - } - if (i == 1) { -#ifdef PKZIP_BUG_WORKAROUND - i = 0; -#else - //if (!uO.qflag) - MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); - huft_free(td); -#endif - } - if (i) - { - huft_free(tl); - return i; - } - - - /* decompress until an end-of-block code */ - if (inflate_codes(__G__ tl, td, bl, bd)) - return 1; - - - /* free the decoding tables, return */ - huft_free(tl); - huft_free(td); - return 0; -} - - - -static int inflate_block(__G__ e) - __GDEF - int *e; /* last block flag */ -/* decompress an inflated block */ -{ - unsigned t; /* block type */ - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - - /* make local bit buffer */ - b = G.bb; - k = G.bk; - - - /* read in last block bit */ - NEEDBITS(1) - *e = (int)b & 1; - DUMPBITS(1) - - - /* read in block type */ - NEEDBITS(2) - t = (unsigned)b & 3; - DUMPBITS(2) - - - /* restore the global bit buffer */ - G.bb = b; - G.bk = k; - - - /* inflate that block type */ - if (t == 2) - return inflate_dynamic(__G); - if (t == 0) - return inflate_stored(__G); - if (t == 1) - return inflate_fixed(__G); - - - /* bad block type */ - return 2; -} - - - -int inflate(__G) - __GDEF -/* decompress an inflated entry */ -{ - int e; /* last block flag */ - int r; /* result code */ -//#ifdef DEBUG -// unsigned h = 0; /* maximum struct huft's malloc'ed */ -//#endif - -#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) - if (G.redirect_slide) - wsize = G.redirect_size, redirSlide = G.redirect_buffer; - else - wsize = WSIZE, redirSlide = slide; /* how they're #defined if !DLL */ -#endif - - /* initialize window, bit buffer */ - G.wp = 0; - G.bk = 0; - G.bb = 0; - - - /* decompress until the last block */ - do { -//#ifdef DEBUG -// G.hufts = 0; -//#endif - if ((r = inflate_block(__G__ &e)) != 0) - return r; -//#ifdef DEBUG -// if (G.hufts > h) -// h = G.hufts; -//#endif - } while (!e); - - - /* flush out redirSlide */ - FLUSH(G.wp); - - - /* return success */ - //Trace((stderr, "\n%u bytes in Huffman tables (%d/entry)\n", - // h * sizeof(struct huft), sizeof(struct huft))); - return 0; -} - - - -int inflate_free(__G) - __GDEF -{ - if (G.fixed_tl != (struct huft *)NULL) - { - huft_free(G.fixed_td); - huft_free(G.fixed_tl); - G.fixed_td = G.fixed_tl = (struct huft *)NULL; - } - return 0; -} - -#endif /* ?USE_ZLIB */ - - -/* - * GRR: moved huft_build() and huft_free() down here; used by explode() - * and fUnZip regardless of whether USE_ZLIB defined or not - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ -#define BMAX 16 /* maximum bit length of any code (16 for explode) */ -#define N_MAX 288 /* maximum number of codes in any set */ - - -int huft_build( - __GDEF - ZCONST unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ - unsigned n, /* number of codes (assumed <= N_MAX) */ - unsigned s, /* number of simple-valued codes (0..s-1) */ - ZCONST ush *d, /* list of base values for non-simple codes */ - ZCONST ush *e, /* list of extra bits for non-simple codes */ - struct huft **t, /* result: starting table */ - int *m /* maximum lookup bits, returns actual */ - ) -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return zero on success, one if - the given code set is incomplete (the tables are still built in this - case), two if the input is invalid (all zero length codes or an - oversubscribed set of lengths), and three if not enough memory. - The code with value 256 is special, and the tables are constructed - so that no bits beyond that code are fetched when that code is - decoded. */ -{ - unsigned a; /* counter for codes of length k */ - unsigned c[BMAX+1]; /* bit length count table */ - unsigned el; /* length of EOB code (value 256) */ - unsigned f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register unsigned i; /* counter, current code */ - register unsigned j; /* counter */ - register int k; /* number of bits in current code */ - int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */ - int *l = lx+1; /* stack of bits per table */ - register unsigned *p; /* pointer into c[], b[], or v[] */ - register struct huft *q; /* points to current table */ - struct huft r; /* table entry for structure assignment */ - struct huft *u[BMAX]; /* table stack */ - unsigned v[N_MAX]; /* values in order of bit length */ - register int w; /* bits before this table == (l * h) */ - unsigned x[BMAX+1]; /* bit offsets, then code stack */ - unsigned *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - unsigned z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */ - memset(c, 0, sizeof(c)); - p = (unsigned *)b; i = n; - do { - c[*p]++; p++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (struct huft *)NULL; - *m = 0; - return 0; - } - - - /* Find minimum and maximum length, bound *m by those */ - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((unsigned)*m < j) - *m = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((unsigned)*m > i) - *m = i; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return 2; /* bad input: more codes than bits */ - if ((y -= c[i]) < 0) - return 2; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - memset(v, 0, sizeof(v)); - p = (unsigned *)b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = l[-1] = 0; /* no bits decoded yet */ - u[0] = (struct huft *)NULL; /* just to keep compilers happy */ - q = (struct huft *)NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l[h]) - { - w += l[h++]; /* add bits already decoded */ - - /* compute minimum size table less than or equal to *m bits */ - z = (z = g - w) > (unsigned)*m ? *m : z; /* upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } - if ((unsigned)w + j > el && (unsigned)w < el) - j = el - w; /* make EOB code end at table */ - z = 1 << j; /* table entries for j-bit table */ - l[h] = j; /* set table size in stack */ - - /* allocate and link in new table */ - if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == - (struct huft *)NULL) - { - if (h) - huft_free(u[0]); - return 3; /* not enough memory */ - } -//#ifdef DEBUG -// G.hufts += z + 1; /* track memory usage */ -//#endif - *t = q + 1; /* link to list for huft_free() */ - *(t = &(q->v.t)) = (struct huft *)NULL; - u[h] = ++q; /* table starts after link */ - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.b = (uch)l[h-1]; /* bits to dump before this table */ - r.e = (uch)(16 + j); /* bits in this table */ - r.v.t = q; /* pointer to this table */ - j = (i & ((1 << w) - 1)) >> (w - l[h-1]); - u[h-1][j] = r; /* connect to last table */ - } - } - - /* set up table entry in r */ - r.b = (uch)(k - w); - if (p >= v + n) - r.e = 99; /* out of values--invalid code */ - else if (*p < s) - { - r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ - r.v.n = (ush)*p++; /* simple code is just the value */ - } - else - { - r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ - r.v.n = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - while ((i & ((1 << w) - 1)) != x[h]) - w -= l[--h]; /* don't need to update q */ - } - } - - - /* return actual size of base table */ - *m = l[0]; - - - /* Return true (1) if we were given an incomplete table */ - return y != 0 && g != 1; -} - - - -int huft_free (struct huft *t) - /* table to free */ -/* Free the malloc'ed tables built by huft_build(), which makes a linked - list of the tables it made, with the links in a dummy first entry of - each table. */ -{ - register struct huft *p, *q; - - - /* Go through linked list, freeing from the malloced (t[-1]) address. */ - p = t; - while (p != (struct huft *)NULL) - { - q = (--p)->v.t; - free((zvoid *)p); - p = q; - } - return 0; -} - - -// Main public function. Decompresses raw data compressed using the DEFLATE algorithm (RFC 1951 - e.g. zlib, gzip). -// Returns 0 if decompression fails or, if successful, returns the size of the decompressed data. -int DecompressDeflatedData (char *out, char *in, int inLength) -{ - G.outbufptr = out; - G.inptr = in; - G.incnt = inLength; - G.outCounter = 0; - - if (inflate(__G) != 0) - { - // Error decompressing - return 0; - } - return G.outCounter; -} - +/* inflate.c -- put in the public domain by Mark Adler */ + +/* Decompresses raw data compressed using the DEFLATE algorithm (RFC 1951) */ + +/* You can do whatever you like with this source file, though I would + prefer that if you modify it and redistribute it that you include + comments to that effect with your name and the date. Thank you. + + History: + vers date who what + ---- --------- -------------- ------------------------------------ + a ~~ Feb 92 M. Adler used full (large, one-step) lookup table + b1 21 Mar 92 M. Adler first version with partial lookup tables + b2 21 Mar 92 M. Adler fixed bug in fixed-code blocks + b3 22 Mar 92 M. Adler sped up match copies, cleaned up some + b4 25 Mar 92 M. Adler added prototypes; removed window[] (now + is the responsibility of unzip.h--also + changed name to slide[]), so needs diffs + for unzip.c and unzip.h (this allows + compiling in the small model on MSDOS); + fixed cast of q in huft_build(); + b5 26 Mar 92 M. Adler got rid of unintended macro recursion. + b6 27 Mar 92 M. Adler got rid of nextbyte() routine. fixed + bug in inflate_fixed(). + c1 30 Mar 92 M. Adler removed lbits, dbits environment variables. + changed BMAX to 16 for explode. Removed + OUTB usage, and replaced it with flush()-- + this was a 20% speed improvement! Added + an explode.c (to replace unimplod.c) that + uses the huft routines here. Removed + register union. + c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. + c3 10 Apr 92 M. Adler reduced memory of code tables made by + huft_build significantly (factor of two to + three). + c4 15 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy(). + worked around a Turbo C optimization bug. + c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing + the 32K window size for specialized + applications. + c6 31 May 92 M. Adler added some typecasts to eliminate warnings + c7 27 Jun 92 G. Roelofs added some more typecasts (444: MSC bug). + c8 5 Oct 92 J-l. Gailly added ifdef'd code to deal with PKZIP bug. + c9 9 Oct 92 M. Adler removed a memory error message (~line 416). + c10 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch, + removed old inflate, renamed inflate_entry + to inflate, added Mark's fix to a comment. + c10.5 14 Dec 92 M. Adler fix up error messages for incomplete trees. + c11 2 Jan 93 M. Adler fixed bug in detection of incomplete + tables, and removed assumption that EOB is + the longest code (bad assumption). + c12 3 Jan 93 M. Adler make tables for fixed blocks only once. + c13 5 Jan 93 M. Adler allow all zero length codes (pkzip 2.04c + outputs one zero length code for an empty + distance tree). + c14 12 Mar 93 M. Adler made inflate.c standalone with the + introduction of inflate.h. + c14b 16 Jul 93 G. Roelofs added (unsigned) typecast to w at 470. + c14c 19 Jul 93 J. Bush changed v[N_MAX], l[288], ll[28x+3x] arrays + to static for Amiga. + c14d 13 Aug 93 J-l. Gailly de-complicatified Mark's c[*p++]++ thing. + c14e 8 Oct 93 G. Roelofs changed memset() to memzero(). + c14f 22 Oct 93 G. Roelofs renamed quietflg to qflag; made Trace() + conditional; added inflate_free(). + c14g 28 Oct 93 G. Roelofs changed l/(lx+1) macro to pointer (Cray bug) + c14h 7 Dec 93 C. Ghisler huft_build() optimizations. + c14i 9 Jan 94 A. Verheijen set fixed_t{d,l} to NULL after freeing; + G. Roelofs check NEXTBYTE macro for EOF. + c14j 23 Jan 94 G. Roelofs removed Ghisler "optimizations"; ifdef'd + EOF check. + c14k 27 Feb 94 G. Roelofs added some typecasts to avoid warnings. + c14l 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines + to avoid bug in Encore compiler. + c14m 7 Jul 94 P. Kienitz modified to allow assembler version of + inflate_codes() (define ASM_INFLATECODES) + c14n 22 Jul 94 G. Roelofs changed fprintf to macro for DLL versions + c14o 23 Aug 94 C. Spieler added a newline to a debug statement; + G. Roelofs added another typecast to avoid MSC warning + c14p 4 Oct 94 G. Roelofs added (voidp *) cast to free() argument + c14q 30 Oct 94 G. Roelofs changed fprintf macro to MESSAGE() + c14r 1 Nov 94 G. Roelofs fixed possible redefinition of CHECK_EOF + c14s 7 May 95 S. Maxwell OS/2 DLL globals stuff incorporated; + P. Kienitz "fixed" ASM_INFLATECODES macro/prototype + c14t 18 Aug 95 G. Roelofs added inflate() to use zlib functions; + changed voidp to zvoid; moved huft_build() + and huft_free() to end of file + c14u 1 Oct 95 G. Roelofs moved G into definition of MESSAGE macro + c14v 8 Nov 95 P. Kienitz changed ASM_INFLATECODES to use a regular + call with __G__ instead of a macro + c15 3 Aug 96 M. Adler fixed bomb-bug on random input data (Adobe) + c15b 24 Aug 96 M. Adler more fixes for random input data + c15c 28 Mar 97 G. Roelofs changed USE_ZLIB fatal exit code from + PK_MEM2 to PK_MEM3 + c16 20 Apr 97 J. Altman added memzero(v[]) in huft_build() + c16b 29 Mar 98 C. Spieler modified DLL code for slide redirection + + fork 12 Dec 07 TrueCrypt Foundation Adapted for TrueCrypt + */ + + +/* + Inflate deflated (PKZIP's method 8 compressed) data. The compression + method searches for as much of the current string of bytes (up to a + length of 258) in the previous 32K bytes. If it doesn't find any + matches (of at least length 3), it codes the next byte. Otherwise, it + codes the length of the matched string and its distance backwards from + the current position. There is a single Huffman code that codes both + single bytes (called "literals") and match lengths. A second Huffman + code codes the distance information, which follows a length code. Each + length or distance code actually represents a base value and a number + of "extra" (sometimes zero) bits to get to add to the base value. At + the end of each deflated block is a special end-of-block (EOB) literal/ + length code. The decoding process is basically: get a literal/length + code; if EOB then done; if a literal, emit the decoded byte; if a + length then get the distance and emit the referred-to bytes from the + sliding window of previously emitted data. + + There are (currently) three kinds of inflate blocks: stored, fixed, and + dynamic. The compressor outputs a chunk of data at a time and decides + which method to use on a chunk-by-chunk basis. A chunk might typically + be 32K to 64K, uncompressed. If the chunk is uncompressible, then the + "stored" method is used. In this case, the bytes are simply stored as + is, eight bits per byte, with none of the above coding. The bytes are + preceded by a count, since there is no longer an EOB code. + + If the data are compressible, then either the fixed or dynamic methods + are used. In the dynamic method, the compressed data are preceded by + an encoding of the literal/length and distance Huffman codes that are + to be used to decode this block. The representation is itself Huffman + coded, and so is preceded by a description of that code. These code + descriptions take up a little space, and so for small blocks, there is + a predefined set of codes, called the fixed codes. The fixed method is + used if the block ends up smaller that way (usually for quite small + chunks); otherwise the dynamic method is used. In the latter case, the + codes are customized to the probabilities in the current block and so + can code it much better than the pre-determined fixed codes can. + + The Huffman codes themselves are decoded using a multi-level table + lookup, in order to maximize the speed of decoding plus the speed of + building the decoding tables. See the comments below that precede the + lbits and dbits tuning parameters. + + GRR: return values(?) + 0 OK + 1 incomplete table + 2 bad input + 3 not enough memory + */ + + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +/* #define DEBUG */ +#define INFMOD /* tell inflate.h to include code to be compiled */ +#include "inflate.h" + + +#ifndef WSIZE /* default is 32K */ +# define WSIZE 0x8000 /* window size--must be a power of two, and at least */ +#endif /* 32K for zip's deflate method */ + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) +# define wsize G._wsize /* wsize is a variable */ +#else +# define wsize WSIZE /* wsize is a constant */ +#endif + + +#ifndef NEXTBYTE /* default is to simply get a byte from stdin */ +# define NEXTBYTE getchar() +#endif + +#ifndef MESSAGE /* only used twice, for fixed strings--NOT general-purpose */ +# define MESSAGE(str,len,flag) fprintf(stderr,(char *)(str)) +#endif + +#ifndef FLUSH /* default is to simply write the buffer to stdout */ +# define FLUSH(n) fwrite(redirSlide, 1, n, stdout) /* return value not used */ +#endif +/* Warning: the fwrite above might not work on 16-bit compilers, since + 0x8000 might be interpreted as -32,768 by the library function. */ + +#ifndef Trace +# ifdef DEBUG +# define Trace(x) fprintf x +# else +# define Trace(x) +# endif +#endif + +G_struct G; +uch redirSlide [WSIZE]; + +/*---------------------------------------------------------------------------*/ +#ifdef USE_ZLIB + + +/* + GRR: return values for both original inflate() and inflate() + 0 OK + 1 incomplete table(?) + 2 bad input + 3 not enough memory + */ + +/**************************/ +/* Function inflate() */ +/**************************/ + +int inflate(__G) /* decompress an inflated entry using the zlib routines */ + __GDEF +{ + int err=Z_OK; + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) + wsize = G.redirect_size, redirSlide = G.redirect_buffer; + else + wsize = WSIZE, redirSlide = slide; +#endif + + G.dstrm.next_out = redirSlide; + G.dstrm.avail_out = wsize; + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + + if (!G.inflInit) { + unsigned i; + int windowBits; + + /* only need to test this stuff once */ + if (zlib_version[0] != ZLIB_VERSION[0]) { + Info(slide, 0x21, ((char *)slide, + "error: incompatible zlib version (expected %s, found %s)\n", + ZLIB_VERSION, zlib_version)); + return 3; + } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) + Info(slide, 0x21, ((char *)slide, + "warning: different zlib version (expected %s, using %s)\n", + ZLIB_VERSION, zlib_version)); + + /* windowBits = log2(wsize) */ + for (i = ((unsigned)wsize * 2 - 1), windowBits = 0; + !(i & 1); i >>= 1, ++windowBits); + if ((unsigned)windowBits > (unsigned)15) + windowBits = 15; + else if (windowBits < 8) + windowBits = 8; + + G.dstrm.zalloc = (alloc_func)Z_NULL; + G.dstrm.zfree = (free_func)Z_NULL; + + Trace((stderr, "initializing inflate()\n")); + err = inflateInit2(&G.dstrm, -windowBits); + + if (err == Z_MEM_ERROR) + return 3; + else if (err != Z_OK) + Trace((stderr, "oops! (inflateInit2() err = %d)\n", err)); + G.inflInit = 1; + } + +#ifdef FUNZIP + while (err != Z_STREAM_END) { +#else /* !FUNZIP */ + while (G.csize > 0) { + Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); +#endif /* ?FUNZIP */ + while (G.dstrm.avail_out > 0) { + err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); + + if (err == Z_DATA_ERROR) + return 2; + else if (err == Z_MEM_ERROR) + return 3; + else if (err != Z_OK && err != Z_STREAM_END) + Trace((stderr, "oops! (inflate(first loop) err = %d)\n", err)); + +#ifdef FUNZIP + if (err == Z_STREAM_END) /* "END-of-entry-condition" ? */ +#else /* !FUNZIP */ + if (G.csize <= 0L) /* "END-of-entry-condition" ? */ +#endif /* ?FUNZIP */ + break; + + if (G.dstrm.avail_in <= 0) { + if (fillinbuf(__G) == 0) + return 2; /* no "END-condition" yet, but no more data */ + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + } + Trace((stderr, " avail_in = %d\n", G.dstrm.avail_in)); + } + FLUSH(wsize - G.dstrm.avail_out); /* flush slide[] */ + Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", + (long)(wsize - G.dstrm.avail_out), + (long)(G.dstrm.next_out-(Bytef *)redirSlide))); + G.dstrm.next_out = redirSlide; + G.dstrm.avail_out = wsize; + } + + /* no more input, so loop until we have all output */ + Trace((stderr, "beginning final loop: err = %d\n", err)); + while (err != Z_STREAM_END) { + err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); + if (err == Z_DATA_ERROR) + return 2; + else if (err == Z_MEM_ERROR) + return 3; + else if (err == Z_BUF_ERROR) { /* DEBUG */ + Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n" + , G.zipfn, G.filename)); + break; + } else if (err != Z_OK && err != Z_STREAM_END) { + Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err)); + DESTROYGLOBALS() + EXIT(PK_MEM3); + } + FLUSH(wsize - G.dstrm.avail_out); /* final flush of slide[] */ + Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", + (long)(wsize - G.dstrm.avail_out), + (long)(G.dstrm.next_out-(Bytef *)redirSlide))); + G.dstrm.next_out = redirSlide; + G.dstrm.avail_out = wsize; + } + Trace((stderr, "total in = %ld, total out = %ld\n", G.dstrm.total_in, + G.dstrm.total_out)); + + G.inptr = (uch *)G.dstrm.next_in; + G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ + + err = inflateReset(&G.dstrm); + if (err != Z_OK) + Trace((stderr, "oops! (inflateReset() err = %d)\n", err)); + + return 0; +} + + +/*---------------------------------------------------------------------------*/ +#else /* !USE_ZLIB */ + + +/* Function prototypes */ +#ifndef OF +# ifdef __STDC__ +# define OF(a) a +# else +# define OF(a) () +# endif +#endif /* !OF */ +int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td, + int bl, int bd)); +static int inflate_stored OF((__GPRO)); +static int inflate_fixed OF((__GPRO)); +static int inflate_dynamic OF((__GPRO)); +static int inflate_block OF((__GPRO__ int *e)); + + +/* The inflate algorithm uses a sliding 32K byte window on the uncompressed + stream to find repeated byte strings. This is implemented here as a + circular buffer. The index is updated simply by incrementing and then + and'ing with 0x7fff (32K-1). */ +/* It is left to other modules to supply the 32K area. It is assumed + to be usable as if it were declared "uch slide[32768];" or as just + "uch *slide;" and then malloc'ed in the latter case. The definition + must be in unzip.h, included above. */ + + +/* unsigned wp; moved to globals.h */ /* current position in slide */ + + +/* Tables for deflate from PKZIP's appnote.txt. */ +static ZCONST unsigned border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +static ZCONST ush cplens[] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* note: see note #13 above about the 258 in this list. */ +static ZCONST ush cplext[] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ +static ZCONST ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +static ZCONST ush cpdext[] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + +/* moved to consts.h (included in unzip.c), resp. funzip.c */ +#if 1 +/* And'ing with mask_bits[n] masks the lower n bits */ +ZCONST ush near mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; +#endif /* 0 */ + + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed and are initialized at the begining of a + routine that uses these macros from a global bit buffer and count. + + In order to not ask for more bits than there are in the compressed + stream, the Huffman tables are constructed to only ask for just + enough bits to make up the end-of-block code (value 256). Then no + bytes need to be "returned" to the buffer at the end of the last + block. See the huft_build() routine. + */ + +/* These have been moved to globals.h */ +#if 0 +ulg bb; /* bit buffer */ +unsigned bk; /* bits in bit buffer */ +#endif + +#ifndef CHECK_EOF +# define CHECK_EOF /* default as of 5.13/5.2 */ +#endif + +#ifndef CHECK_EOF +# define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<>=(n);k-=(n);} + + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + are not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + +static ZCONST int lbits = 9; /* bits in base literal/length lookup table */ +static ZCONST int dbits = 6; /* bits in base distance lookup table */ + + +#ifndef ASM_INFLATECODES + +#pragma warning(disable:4131) + +int inflate_codes(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* literal/length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = G.bb; /* initialize bit buffer */ + k = G.bk; + w = G.wp; /* initialize window position */ + + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + while (1) /* do until end of block */ + { + NEEDBITS((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + FLUSH(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy */ + NEEDBITS((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + + /* do the copy */ + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) {/* &= w/ wsize unnecessary & wrong if redirect */ + if (d >= wsize) + return 1; /* invalid compressed data */ + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } + else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(redirSlide + w, redirSlide + d, e); + w += e; + d += e; + } + else /* do it slowly to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + redirSlide[w++] = redirSlide[d++]; + } while (--e); + if (w == wsize) + { + FLUSH(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + G.wp = w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + + + /* done */ + return 0; +} + +#endif /* ASM_INFLATECODES */ + + + +static int inflate_stored(__G) + __GDEF +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + Trace((stderr, "\nstored block")); + b = G.bb; /* initialize bit buffer */ + k = G.bk; + w = G.wp; /* initialize window position */ + + + /* go to byte boundary */ + n = k & 7; + DUMPBITS(n); + + + /* get the length and its complement */ + NEEDBITS(16) + n = ((unsigned)b & 0xffff); + DUMPBITS(16) + NEEDBITS(16) + if (n != (unsigned)((~b) & 0xffff)) + return 1; /* error in compressed data */ + DUMPBITS(16) + + + /* read and output the compressed data */ + while (n--) + { + NEEDBITS(8) + redirSlide[w++] = (uch)b; + if (w == wsize) + { + FLUSH(w); + w = 0; + } + DUMPBITS(8) + } + + + /* restore the globals from the locals */ + G.wp = w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + return 0; +} + + +/* Globals for literal tables (built once) */ +/* Moved to globals.h */ +#if 0 +struct huft *fixed_tl = (struct huft *)NULL; +struct huft *fixed_td; +int fixed_bl, fixed_bd; +#endif + +static int inflate_fixed(__G) + __GDEF +/* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ +{ + /* if first time, set up tables for fixed blocks */ + Trace((stderr, "\nliteral block")); + if (G.fixed_tl == (struct huft *)NULL) + { + int i; /* temporary variable */ + unsigned l[288]; /* length list for huft_build */ + + /* literal table */ + for (i = 0; i < 144; i++) + l[i] = 8; + for (; i < 256; i++) + l[i] = 9; + for (; i < 280; i++) + l[i] = 7; + for (; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + G.fixed_bl = 7; + if ((i = huft_build(__G__ l, 288, 257, cplens, cplext, + &G.fixed_tl, &G.fixed_bl)) != 0) + { + G.fixed_tl = (struct huft *)NULL; + return i; + } + + /* distance table */ + for (i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + G.fixed_bd = 5; + if ((i = huft_build(__G__ l, 30, 0, cpdist, cpdext, + &G.fixed_td, &G.fixed_bd)) > 1) + { + huft_free(G.fixed_tl); + G.fixed_tl = (struct huft *)NULL; + return i; + } + } + + /* decompress until an end-of-block code */ + return inflate_codes(__G__ G.fixed_tl, G.fixed_td, + G.fixed_bl, G.fixed_bd) != 0; +} + + + +static int inflate_dynamic(__G) + __GDEF +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local bit buffer */ + Trace((stderr, "\ndynamic block")); + b = G.bb; + k = G.bk; + + + /* read in table lengths */ + NEEDBITS(5) + nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ + DUMPBITS(5) + NEEDBITS(5) + nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ + DUMPBITS(5) + NEEDBITS(4) + nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ + DUMPBITS(4) +#ifdef PKZIP_BUG_WORKAROUND + if (nl > 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + return 1; /* bad lengths */ + + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + i = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl); + if (bl == 0) /* no bit lengths */ + i = 1; + if (i) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + + + /* free decoding table for trees */ + huft_free(tl); + + + /* restore the global bit buffer */ + G.bb = b; + G.bk = k; + + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + i = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl); + if (bl == 0) /* no literals or lengths */ + i = 1; + if (i) + { + if (i == 1) { + //if (!uO.qflag) + MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1); + huft_free(tl); + } + return i; /* incomplete code set */ + } + bd = dbits; + i = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd); + if (bd == 0 && nl > 257) /* lengths but no distances */ + { + //if (!uO.qflag) + MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); + huft_free(tl); + return 1; + } + if (i == 1) { +#ifdef PKZIP_BUG_WORKAROUND + i = 0; +#else + //if (!uO.qflag) + MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); + huft_free(td); +#endif + } + if (i) + { + huft_free(tl); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(__G__ tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +static int inflate_block(__G__ e) + __GDEF + int *e; /* last block flag */ +/* decompress an inflated block */ +{ + unsigned t; /* block type */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local bit buffer */ + b = G.bb; + k = G.bk; + + + /* read in last block bit */ + NEEDBITS(1) + *e = (int)b & 1; + DUMPBITS(1) + + + /* read in block type */ + NEEDBITS(2) + t = (unsigned)b & 3; + DUMPBITS(2) + + + /* restore the global bit buffer */ + G.bb = b; + G.bk = k; + + + /* inflate that block type */ + if (t == 2) + return inflate_dynamic(__G); + if (t == 0) + return inflate_stored(__G); + if (t == 1) + return inflate_fixed(__G); + + + /* bad block type */ + return 2; +} + + + +int inflate(__G) + __GDEF +/* decompress an inflated entry */ +{ + int e; /* last block flag */ + int r; /* result code */ +//#ifdef DEBUG +// unsigned h = 0; /* maximum struct huft's malloc'ed */ +//#endif + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) + wsize = G.redirect_size, redirSlide = G.redirect_buffer; + else + wsize = WSIZE, redirSlide = slide; /* how they're #defined if !DLL */ +#endif + + /* initialize window, bit buffer */ + G.wp = 0; + G.bk = 0; + G.bb = 0; + + + /* decompress until the last block */ + do { +//#ifdef DEBUG +// G.hufts = 0; +//#endif + if ((r = inflate_block(__G__ &e)) != 0) + return r; +//#ifdef DEBUG +// if (G.hufts > h) +// h = G.hufts; +//#endif + } while (!e); + + + /* flush out redirSlide */ + FLUSH(G.wp); + + + /* return success */ + //Trace((stderr, "\n%u bytes in Huffman tables (%d/entry)\n", + // h * sizeof(struct huft), sizeof(struct huft))); + return 0; +} + + + +int inflate_free(__G) + __GDEF +{ + if (G.fixed_tl != (struct huft *)NULL) + { + huft_free(G.fixed_td); + huft_free(G.fixed_tl); + G.fixed_td = G.fixed_tl = (struct huft *)NULL; + } + return 0; +} + +#endif /* ?USE_ZLIB */ + + +/* + * GRR: moved huft_build() and huft_free() down here; used by explode() + * and fUnZip regardless of whether USE_ZLIB defined or not + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + + +int huft_build( + __GDEF + ZCONST unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ + unsigned n, /* number of codes (assumed <= N_MAX) */ + unsigned s, /* number of simple-valued codes (0..s-1) */ + ZCONST ush *d, /* list of base values for non-simple codes */ + ZCONST ush *e, /* list of extra bits for non-simple codes */ + struct huft **t, /* result: starting table */ + int *m /* maximum lookup bits, returns actual */ + ) +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. + The code with value 256 is special, and the tables are constructed + so that no bits beyond that code are fetched when that code is + decoded. */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned el; /* length of EOB code (value 256) */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */ + int *l = lx+1; /* stack of bits per table */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */ + memset(c, 0, sizeof(c)); + p = (unsigned *)b; i = n; + do { + c[*p]++; p++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + + + /* Find minimum and maximum length, bound *m by those */ + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)*m < j) + *m = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)*m > i) + *m = i; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + memset(v, 0, sizeof(v)); + p = (unsigned *)b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = l[-1] = 0; /* no bits decoded yet */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l[h]) + { + w += l[h++]; /* add bits already decoded */ + + /* compute minimum size table less than or equal to *m bits */ + z = (z = g - w) > (unsigned)*m ? *m : z; /* upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + if ((unsigned)w + j > el && (unsigned)w < el) + j = el - w; /* make EOB code end at table */ + z = 1 << j; /* table entries for j-bit table */ + l[h] = j; /* set table size in stack */ + + /* allocate and link in new table */ + if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == + (struct huft *)NULL) + { + if (h) + huft_free(u[0]); + return 3; /* not enough memory */ + } +//#ifdef DEBUG +// G.hufts += z + 1; /* track memory usage */ +//#endif + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (uch)l[h-1]; /* bits to dump before this table */ + r.e = (uch)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = (i & ((1 << w) - 1)) >> (w - l[h-1]); + u[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (uch)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = (ush)*p++; /* simple code is just the value */ + } + else + { + r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + w -= l[--h]; /* don't need to update q */ + } + } + + + /* return actual size of base table */ + *m = l[0]; + + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + + +int huft_free (struct huft *t) + /* table to free */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free((zvoid *)p); + p = q; + } + return 0; +} + + +// Main public function. Decompresses raw data compressed using the DEFLATE algorithm (RFC 1951 - e.g. zlib, gzip). +// Returns 0 if decompression fails or, if successful, returns the size of the decompressed data. +int DecompressDeflatedData (char *out, char *in, int inLength) +{ + G.outbufptr = out; + G.inptr = in; + G.incnt = inLength; + G.outCounter = 0; + + if (inflate(__G) != 0) + { + // Error decompressing + return 0; + } + return G.outCounter; +} + diff --git a/Common/Inflate.h b/Common/Inflate.h index c2810c8..a0d4aa5 100644 --- a/Common/Inflate.h +++ b/Common/Inflate.h @@ -1,51 +1,51 @@ -#include -#include - -#define WSIZE 0x8000 // Window size -#define ZCONST const -#define OF(p) p - -typedef unsigned long ulg; -typedef unsigned char uch; -typedef unsigned short ush; -typedef void zvoid; - -typedef struct huft -{ - uch b, e; - union - { - ush n; - struct huft *t; - }v; -}; - -typedef struct -{ - uch *inptr, *outbufptr; - int incnt; - int outCounter; - - struct huft *fixed_tl; - struct huft *fixed_td; - int fixed_bl, fixed_bd; - - unsigned bk, wp; - ulg bb; -} G_struct; - -#define __GPRO void -#define __GPRO__ -#define __G -#define __G__ -#define __GDEF - - -#define FLUSH(cnt) { memcpy (G.outbufptr, redirSlide, cnt); G.outbufptr += cnt; G.outCounter += cnt; } -#define NEXTBYTE (((G.incnt--) >= 0) ? (*G.inptr++) : EOF) - - -int huft_free(struct huft *t); -int huft_build(__GDEF ZCONST unsigned *b, unsigned n, unsigned s, ZCONST ush *d, ZCONST ush *e, struct huft **t, int *m); - -int DecompressDeflatedData (char *out, char *in, int inLength); +#include +#include + +#define WSIZE 0x8000 // Window size +#define ZCONST const +#define OF(p) p + +typedef unsigned long ulg; +typedef unsigned char uch; +typedef unsigned short ush; +typedef void zvoid; + +typedef struct huft +{ + uch b, e; + union + { + ush n; + struct huft *t; + }v; +}; + +typedef struct +{ + uch *inptr, *outbufptr; + int incnt; + int outCounter; + + struct huft *fixed_tl; + struct huft *fixed_td; + int fixed_bl, fixed_bd; + + unsigned bk, wp; + ulg bb; +} G_struct; + +#define __GPRO void +#define __GPRO__ +#define __G +#define __G__ +#define __GDEF + + +#define FLUSH(cnt) { memcpy (G.outbufptr, redirSlide, cnt); G.outbufptr += cnt; G.outCounter += cnt; } +#define NEXTBYTE (((G.incnt--) >= 0) ? (*G.inptr++) : EOF) + + +int huft_free(struct huft *t); +int huft_build(__GDEF ZCONST unsigned *b, unsigned n, unsigned s, ZCONST ush *d, ZCONST ush *e, struct huft **t, int *m); + +int DecompressDeflatedData (char *out, char *in, int inLength); diff --git a/Common/Keyfiles.c b/Common/Keyfiles.c index 2096786..55461ac 100644 --- a/Common/Keyfiles.c +++ b/Common/Keyfiles.c @@ -1,660 +1,660 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include - -#include "Tcdefs.h" -#include "Keyfiles.h" -#include "Crc.h" - -#include -#include "Dlgcode.h" -#include "Language.h" -#include "SecurityToken.h" -#include "Common/resource.h" -#include "Platform/ForEach.h" - -using namespace TrueCrypt; - -#define stat _stat -#define S_IFDIR _S_IFDIR -#define snprintf _snprintf - - -KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile) -{ - KeyFile *kf = firstKeyFile; - - if (firstKeyFile != NULL) - { - while (kf->Next) - kf = kf->Next; - - kf->Next = keyFile; - } - else - firstKeyFile = keyFile; - - keyFile->Next = NULL; - - return firstKeyFile; -} - - -// Returns first keyfile, NULL if last keyfile was removed -static KeyFile *KeyFileRemove (KeyFile *firstKeyFile, KeyFile *keyFile) -{ - KeyFile *prevkf = NULL, *kf = firstKeyFile; - - if (firstKeyFile == NULL) return NULL; - do - { - if (kf == keyFile) - { - if (prevkf == NULL) - firstKeyFile = kf->Next; - else - prevkf->Next = kf->Next; - - burn (keyFile, sizeof(*keyFile)); // wipe - free (keyFile); - break; - } - prevkf = kf; - } - while (kf = kf->Next); - - return firstKeyFile; -} - - -void KeyFileRemoveAll (KeyFile **firstKeyFile) -{ - KeyFile *kf = *firstKeyFile; - while (kf != NULL) - { - KeyFile *d = kf; - kf = kf->Next; - burn (d, sizeof(*d)); // wipe - free (d); - } - - *firstKeyFile = NULL; -} - - -KeyFile *KeyFileClone (KeyFile *keyFile) -{ - KeyFile *clone; - - if (keyFile == NULL) return NULL; - - clone = (KeyFile *) malloc (sizeof (KeyFile)); - strcpy (clone->FileName, keyFile->FileName); - clone->Next = NULL; - return clone; -} - - -KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile) -{ - KeyFile *cloneFirstKeyFile = KeyFileClone (firstKeyFile); - KeyFile *kf; - - if (firstKeyFile == NULL) return NULL; - kf = firstKeyFile->Next; - while (kf != NULL) - { - KeyFileAdd (cloneFirstKeyFile, KeyFileClone (kf)); - kf = kf->Next; - } - - return cloneFirstKeyFile; -} - - -static BOOL KeyFileProcess (unsigned __int8 *keyPool, KeyFile *keyFile) -{ - FILE *f; - unsigned __int8 buffer[64 * 1024]; - unsigned __int32 crc = 0xffffffff; - int writePos = 0; - size_t bytesRead, totalRead = 0; - int status = TRUE; - - HANDLE src; - FILETIME ftCreationTime; - FILETIME ftLastWriteTime; - FILETIME ftLastAccessTime; - - BOOL bTimeStampValid = FALSE; - - /* Remember the last access time of the keyfile. It will be preserved in order to prevent - an adversary from determining which file may have been used as keyfile. */ - src = CreateFile (keyFile->FileName, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src != INVALID_HANDLE_VALUE) - { - if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)) - bTimeStampValid = TRUE; - else - Warning ("GETFILETIME_FAILED_KEYFILE"); - } - - f = fopen (keyFile->FileName, "rb"); - if (f == NULL) return FALSE; - - while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0) - { - size_t i; - - if (ferror (f)) - { - status = FALSE; - goto close; - } - - for (i = 0; i < bytesRead; i++) - { - crc = UPDC32 (buffer[i], crc); - - keyPool[writePos++] += (unsigned __int8) (crc >> 24); - keyPool[writePos++] += (unsigned __int8) (crc >> 16); - keyPool[writePos++] += (unsigned __int8) (crc >> 8); - keyPool[writePos++] += (unsigned __int8) crc; - - if (writePos >= KEYFILE_POOL_SIZE) - writePos = 0; - - if (++totalRead >= KEYFILE_MAX_READ_LEN) - goto close; - } - } - - if (ferror (f)) - { - status = FALSE; - } - else if (totalRead == 0) - { - status = FALSE; - SetLastError (ERROR_HANDLE_EOF); - } - -close: - DWORD err = GetLastError(); - fclose (f); - - if (bTimeStampValid && !IsFileOnReadOnlyFilesystem (keyFile->FileName)) - { - // Restore the keyfile timestamp - if (!SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)) - Warning ("SETFILETIME_FAILED_KEYFILE"); - CloseHandle (src); - } - - SetLastError (err); - return status; -} - - -BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile) -{ - BOOL status = TRUE; - KeyFile kfSubStruct; - KeyFile *kf; - KeyFile *kfSub = &kfSubStruct; - static unsigned __int8 keyPool [KEYFILE_POOL_SIZE]; - size_t i; - struct stat statStruct; - char searchPath [TC_MAX_PATH*2]; - struct _finddata_t fBuf; - intptr_t searchHandle; - - if (firstKeyFile == NULL) return TRUE; - - VirtualLock (keyPool, sizeof (keyPool)); - memset (keyPool, 0, sizeof (keyPool)); - - for (kf = firstKeyFile; kf != NULL; kf = kf->Next) - { - // Determine whether it's a security token path - try - { - if (SecurityToken::IsKeyfilePathValid (SingleStringToWide (kf->FileName))) - { - // Apply security token keyfile - vector keyfileData; - SecurityToken::GetKeyfileData (SecurityTokenKeyfile (SingleStringToWide (kf->FileName)), keyfileData); - - if (keyfileData.empty()) - { - SetLastError (ERROR_HANDLE_EOF); - handleWin32Error (MainDlg); - Error ("ERR_PROCESS_KEYFILE"); - status = FALSE; - continue; - } - - unsigned __int32 crc = 0xffffffff; - int writePos = 0; - size_t totalRead = 0; - - for (size_t i = 0; i < keyfileData.size(); i++) - { - crc = UPDC32 (keyfileData[i], crc); - - keyPool[writePos++] += (unsigned __int8) (crc >> 24); - keyPool[writePos++] += (unsigned __int8) (crc >> 16); - keyPool[writePos++] += (unsigned __int8) (crc >> 8); - keyPool[writePos++] += (unsigned __int8) crc; - - if (writePos >= KEYFILE_POOL_SIZE) - writePos = 0; - - if (++totalRead >= KEYFILE_MAX_READ_LEN) - break; - } - - burn (&keyfileData.front(), keyfileData.size()); - continue; - } - } - catch (Exception &e) - { - e.Show (NULL); - return FALSE; - } - - // Determine whether it's a path or a file - if (stat (kf->FileName, &statStruct) != 0) - { - handleWin32Error (MainDlg); - Error ("ERR_PROCESS_KEYFILE"); - status = FALSE; - continue; - } - - if (statStruct.st_mode & S_IFDIR) // If it's a directory - { - /* Find and process all keyfiles in the directory */ - - snprintf (searchPath, sizeof (searchPath), "%s\\*.*", kf->FileName); - if ((searchHandle = _findfirst (searchPath, &fBuf)) == -1) - { - handleWin32Error (MainDlg); - Error ("ERR_PROCESS_KEYFILE_PATH"); - status = FALSE; - continue; - } - - do - { - snprintf (kfSub->FileName, sizeof(kfSub->FileName), "%s%c%s", kf->FileName, - '\\', - fBuf.name - ); - - // Determine whether it's a path or a file - if (stat (kfSub->FileName, &statStruct) != 0) - { - handleWin32Error (MainDlg); - Error ("ERR_PROCESS_KEYFILE"); - status = FALSE; - continue; - } - else if (statStruct.st_mode & S_IFDIR) // If it's a directory - { - // Prevent recursive folder scanning - continue; - } - - - // Apply keyfile to the pool - if (!KeyFileProcess (keyPool, kfSub)) - { - handleWin32Error (MainDlg); - Error ("ERR_PROCESS_KEYFILE"); - status = FALSE; - } - - } while (_findnext (searchHandle, &fBuf) != -1); - _findclose (searchHandle); - - burn (&kfSubStruct, sizeof (kfSubStruct)); - - } - // Apply keyfile to the pool - else if (!KeyFileProcess (keyPool, kf)) - { - handleWin32Error (MainDlg); - Error ("ERR_PROCESS_KEYFILE"); - status = FALSE; - } - } - - /* Mix the keyfile pool contents into the password */ - - for (i = 0; i < sizeof (keyPool); i++) - { - if (i < password->Length) - password->Text[i] += keyPool[i]; - else - password->Text[i] = keyPool[i]; - } - - if (password->Length < (int)sizeof (keyPool)) - password->Length = sizeof (keyPool); - - burn (keyPool, sizeof (keyPool)); - - return status; -} - - -static void LoadKeyList (HWND hwndDlg, KeyFile *firstKeyFile) -{ - KeyFile *kf; - LVITEM LvItem; - int line = 0; - HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST); - - ListView_DeleteAllItems (hList); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVEALL), firstKeyFile != NULL); - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, firstKeyFile != NULL); - - for (kf = firstKeyFile; kf != NULL; kf = kf->Next) - { - memset (&LvItem,0,sizeof(LvItem)); - LvItem.mask = LVIF_TEXT|LVIF_PARAM; - LvItem.iItem = line++; - LvItem.iSubItem = 0; - LvItem.pszText = kf->FileName; - LvItem.lParam = (LPARAM) kf; - SendMessage (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); - } -} - -#if KEYFILE_POOL_SIZE % 4 != 0 -#error KEYFILE_POOL_SIZE must be a multiple of 4 -#endif - -BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static KeyFilesDlgParam *param; - static KeyFilesDlgParam origParam; - - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - LVCOLUMNW LvCol; - HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST); - - param = (KeyFilesDlgParam *) lParam; - origParam = *(KeyFilesDlgParam *) lParam; - - param->FirstKeyFile = KeyFileCloneAll (param->FirstKeyFile); - - LocalizeDialog (hwndDlg, "IDD_KEYFILES"); - DragAcceptFiles (hwndDlg, TRUE); - - SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP - ); - - memset (&LvCol,0,sizeof(LvCol)); - LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - LvCol.pszText = GetString ("KEYFILE"); - LvCol.cx = CompensateXDPI (374); - LvCol.fmt = LVCFMT_LEFT; - SendMessageW (hList, LVM_INSERTCOLUMNW, 0, (LPARAM)&LvCol); - - LoadKeyList (hwndDlg, param->FirstKeyFile); - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, param->EnableKeyFiles); - - SetWindowTextW(GetDlgItem(hwndDlg, IDT_KEYFILES_NOTE), GetString ("KEYFILES_NOTE")); - - ToHyperlink (hwndDlg, IDC_LINK_KEYFILES_INFO); - } - return 1; - - case WM_COMMAND: - - if (lw == IDC_KEYADD) - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory)) - { - do - { - param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); - LoadKeyList (hwndDlg, param->FirstKeyFile); - - kf = (KeyFile *) malloc (sizeof (KeyFile)); - } while (SelectMultipleFilesNext (kf->FileName)); - } - - free (kf); - return 1; - } - - if (lw == IDC_ADD_KEYFILE_PATH) - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - - if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName)) - { - param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); - LoadKeyList (hwndDlg, param->FirstKeyFile); - } - else - { - free (kf); - } - return 1; - } - - if (lw == IDC_TOKEN_FILES_ADD) - { - list selectedTokenKeyfiles; - if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) - { - foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str()); - - param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); - LoadKeyList (hwndDlg, param->FirstKeyFile); - } - } - - return 1; - } - - if (lw == IDC_KEYREMOVE) - { - HWND list = GetDlgItem (hwndDlg, IDC_KEYLIST); - LVITEM LvItem; - memset (&LvItem, 0, sizeof(LvItem)); - LvItem.mask = LVIF_PARAM; - LvItem.iItem = -1; - - while (-1 != (LvItem.iItem = ListView_GetNextItem (list, LvItem.iItem, LVIS_SELECTED))) - { - ListView_GetItem (list, &LvItem); - param->FirstKeyFile = KeyFileRemove (param->FirstKeyFile, (KeyFile *) LvItem.lParam); - } - - LoadKeyList (hwndDlg, param->FirstKeyFile); - return 1; - } - - if (lw == IDC_KEYREMOVEALL) - { - KeyFileRemoveAll (¶m->FirstKeyFile); - LoadKeyList (hwndDlg, NULL); - return 1; - } - - if (lw == IDC_GENERATE_KEYFILE) - { - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg, - (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0); - return 1; - } - - if (lw == IDC_LINK_KEYFILES_INFO) - { - Applink ("keyfiles", TRUE, ""); - } - - if (lw == IDOK) - { - param->EnableKeyFiles = IsButtonChecked (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE)); - EndDialog (hwndDlg, IDOK); - return 1; - } - - if (lw == IDCANCEL) - { - KeyFileRemoveAll (¶m->FirstKeyFile); - *param = origParam; - - EndDialog (hwndDlg, IDCLOSE); - return 1; - } - - case WM_DROPFILES: - { - HDROP hdrop = (HDROP) wParam; - - int i = 0, count = DragQueryFile (hdrop, -1, NULL, 0); - - while (count-- > 0) - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName)); - param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); - LoadKeyList (hwndDlg, param->FirstKeyFile); - } - - DragFinish (hdrop); - } - return 1; - - case WM_NOTIFY: - if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) - { - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), - ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_KEYLIST), -1, LVIS_SELECTED) != -1); - return 1; - } - break; - - case WM_CLOSE: - KeyFileRemoveAll (¶m->FirstKeyFile); - *param = origParam; - - EndDialog (hwndDlg, IDCLOSE); - return 1; - - break; - - } - - return 0; -} - - -#define IDM_KEYFILES_POPUP_ADD_FILES 9001 -#define IDM_KEYFILES_POPUP_ADD_DIR 9002 -#define IDM_KEYFILES_POPUP_ADD_TOKEN_FILES 9003 - -BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *param) -{ - HMENU popup = CreatePopupMenu (); - int sel; - BOOL status = FALSE; - - AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_FILES, GetString ("IDC_KEYADD")); - AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_DIR, GetString ("IDC_ADD_KEYFILE_PATH")); - AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_TOKEN_FILES, GetString ("IDC_TOKEN_FILES_ADD")); - - sel = TrackPopupMenu (popup, TPM_RETURNCMD | TPM_LEFTBUTTON, popupPosition.x, popupPosition.y, 0, hwndDlg, NULL); - - switch (sel) - { - case IDM_KEYFILES_POPUP_ADD_FILES: - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory)) - { - do - { - param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); - kf = (KeyFile *) malloc (sizeof (KeyFile)); - } while (SelectMultipleFilesNext (kf->FileName)); - - param->EnableKeyFiles = TRUE; - status = TRUE; - } - - free (kf); - } - break; - - case IDM_KEYFILES_POPUP_ADD_DIR: - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - - if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName)) - { - param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); - param->EnableKeyFiles = TRUE; - status = TRUE; - } - else - { - free (kf); - } - } - break; - - case IDM_KEYFILES_POPUP_ADD_TOKEN_FILES: - { - list selectedTokenKeyfiles; - if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) - { - foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str()); - - param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); - param->EnableKeyFiles = TRUE; - status = TRUE; - } - } - } - break; - } - - DestroyMenu (popup); - return status; -} +/* + Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include + +#include "Tcdefs.h" +#include "Keyfiles.h" +#include "Crc.h" + +#include +#include "Dlgcode.h" +#include "Language.h" +#include "SecurityToken.h" +#include "Common/resource.h" +#include "Platform/ForEach.h" + +using namespace TrueCrypt; + +#define stat _stat +#define S_IFDIR _S_IFDIR +#define snprintf _snprintf + + +KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile) +{ + KeyFile *kf = firstKeyFile; + + if (firstKeyFile != NULL) + { + while (kf->Next) + kf = kf->Next; + + kf->Next = keyFile; + } + else + firstKeyFile = keyFile; + + keyFile->Next = NULL; + + return firstKeyFile; +} + + +// Returns first keyfile, NULL if last keyfile was removed +static KeyFile *KeyFileRemove (KeyFile *firstKeyFile, KeyFile *keyFile) +{ + KeyFile *prevkf = NULL, *kf = firstKeyFile; + + if (firstKeyFile == NULL) return NULL; + do + { + if (kf == keyFile) + { + if (prevkf == NULL) + firstKeyFile = kf->Next; + else + prevkf->Next = kf->Next; + + burn (keyFile, sizeof(*keyFile)); // wipe + free (keyFile); + break; + } + prevkf = kf; + } + while (kf = kf->Next); + + return firstKeyFile; +} + + +void KeyFileRemoveAll (KeyFile **firstKeyFile) +{ + KeyFile *kf = *firstKeyFile; + while (kf != NULL) + { + KeyFile *d = kf; + kf = kf->Next; + burn (d, sizeof(*d)); // wipe + free (d); + } + + *firstKeyFile = NULL; +} + + +KeyFile *KeyFileClone (KeyFile *keyFile) +{ + KeyFile *clone; + + if (keyFile == NULL) return NULL; + + clone = (KeyFile *) malloc (sizeof (KeyFile)); + strcpy (clone->FileName, keyFile->FileName); + clone->Next = NULL; + return clone; +} + + +KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile) +{ + KeyFile *cloneFirstKeyFile = KeyFileClone (firstKeyFile); + KeyFile *kf; + + if (firstKeyFile == NULL) return NULL; + kf = firstKeyFile->Next; + while (kf != NULL) + { + KeyFileAdd (cloneFirstKeyFile, KeyFileClone (kf)); + kf = kf->Next; + } + + return cloneFirstKeyFile; +} + + +static BOOL KeyFileProcess (unsigned __int8 *keyPool, KeyFile *keyFile) +{ + FILE *f; + unsigned __int8 buffer[64 * 1024]; + unsigned __int32 crc = 0xffffffff; + int writePos = 0; + size_t bytesRead, totalRead = 0; + int status = TRUE; + + HANDLE src; + FILETIME ftCreationTime; + FILETIME ftLastWriteTime; + FILETIME ftLastAccessTime; + + BOOL bTimeStampValid = FALSE; + + /* Remember the last access time of the keyfile. It will be preserved in order to prevent + an adversary from determining which file may have been used as keyfile. */ + src = CreateFile (keyFile->FileName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src != INVALID_HANDLE_VALUE) + { + if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)) + bTimeStampValid = TRUE; + else + Warning ("GETFILETIME_FAILED_KEYFILE"); + } + + f = fopen (keyFile->FileName, "rb"); + if (f == NULL) return FALSE; + + while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0) + { + size_t i; + + if (ferror (f)) + { + status = FALSE; + goto close; + } + + for (i = 0; i < bytesRead; i++) + { + crc = UPDC32 (buffer[i], crc); + + keyPool[writePos++] += (unsigned __int8) (crc >> 24); + keyPool[writePos++] += (unsigned __int8) (crc >> 16); + keyPool[writePos++] += (unsigned __int8) (crc >> 8); + keyPool[writePos++] += (unsigned __int8) crc; + + if (writePos >= KEYFILE_POOL_SIZE) + writePos = 0; + + if (++totalRead >= KEYFILE_MAX_READ_LEN) + goto close; + } + } + + if (ferror (f)) + { + status = FALSE; + } + else if (totalRead == 0) + { + status = FALSE; + SetLastError (ERROR_HANDLE_EOF); + } + +close: + DWORD err = GetLastError(); + fclose (f); + + if (bTimeStampValid && !IsFileOnReadOnlyFilesystem (keyFile->FileName)) + { + // Restore the keyfile timestamp + if (!SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)) + Warning ("SETFILETIME_FAILED_KEYFILE"); + CloseHandle (src); + } + + SetLastError (err); + return status; +} + + +BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile) +{ + BOOL status = TRUE; + KeyFile kfSubStruct; + KeyFile *kf; + KeyFile *kfSub = &kfSubStruct; + static unsigned __int8 keyPool [KEYFILE_POOL_SIZE]; + size_t i; + struct stat statStruct; + char searchPath [TC_MAX_PATH*2]; + struct _finddata_t fBuf; + intptr_t searchHandle; + + if (firstKeyFile == NULL) return TRUE; + + VirtualLock (keyPool, sizeof (keyPool)); + memset (keyPool, 0, sizeof (keyPool)); + + for (kf = firstKeyFile; kf != NULL; kf = kf->Next) + { + // Determine whether it's a security token path + try + { + if (SecurityToken::IsKeyfilePathValid (SingleStringToWide (kf->FileName))) + { + // Apply security token keyfile + vector keyfileData; + SecurityToken::GetKeyfileData (SecurityTokenKeyfile (SingleStringToWide (kf->FileName)), keyfileData); + + if (keyfileData.empty()) + { + SetLastError (ERROR_HANDLE_EOF); + handleWin32Error (MainDlg); + Error ("ERR_PROCESS_KEYFILE"); + status = FALSE; + continue; + } + + unsigned __int32 crc = 0xffffffff; + int writePos = 0; + size_t totalRead = 0; + + for (size_t i = 0; i < keyfileData.size(); i++) + { + crc = UPDC32 (keyfileData[i], crc); + + keyPool[writePos++] += (unsigned __int8) (crc >> 24); + keyPool[writePos++] += (unsigned __int8) (crc >> 16); + keyPool[writePos++] += (unsigned __int8) (crc >> 8); + keyPool[writePos++] += (unsigned __int8) crc; + + if (writePos >= KEYFILE_POOL_SIZE) + writePos = 0; + + if (++totalRead >= KEYFILE_MAX_READ_LEN) + break; + } + + burn (&keyfileData.front(), keyfileData.size()); + continue; + } + } + catch (Exception &e) + { + e.Show (NULL); + return FALSE; + } + + // Determine whether it's a path or a file + if (stat (kf->FileName, &statStruct) != 0) + { + handleWin32Error (MainDlg); + Error ("ERR_PROCESS_KEYFILE"); + status = FALSE; + continue; + } + + if (statStruct.st_mode & S_IFDIR) // If it's a directory + { + /* Find and process all keyfiles in the directory */ + + snprintf (searchPath, sizeof (searchPath), "%s\\*.*", kf->FileName); + if ((searchHandle = _findfirst (searchPath, &fBuf)) == -1) + { + handleWin32Error (MainDlg); + Error ("ERR_PROCESS_KEYFILE_PATH"); + status = FALSE; + continue; + } + + do + { + snprintf (kfSub->FileName, sizeof(kfSub->FileName), "%s%c%s", kf->FileName, + '\\', + fBuf.name + ); + + // Determine whether it's a path or a file + if (stat (kfSub->FileName, &statStruct) != 0) + { + handleWin32Error (MainDlg); + Error ("ERR_PROCESS_KEYFILE"); + status = FALSE; + continue; + } + else if (statStruct.st_mode & S_IFDIR) // If it's a directory + { + // Prevent recursive folder scanning + continue; + } + + + // Apply keyfile to the pool + if (!KeyFileProcess (keyPool, kfSub)) + { + handleWin32Error (MainDlg); + Error ("ERR_PROCESS_KEYFILE"); + status = FALSE; + } + + } while (_findnext (searchHandle, &fBuf) != -1); + _findclose (searchHandle); + + burn (&kfSubStruct, sizeof (kfSubStruct)); + + } + // Apply keyfile to the pool + else if (!KeyFileProcess (keyPool, kf)) + { + handleWin32Error (MainDlg); + Error ("ERR_PROCESS_KEYFILE"); + status = FALSE; + } + } + + /* Mix the keyfile pool contents into the password */ + + for (i = 0; i < sizeof (keyPool); i++) + { + if (i < password->Length) + password->Text[i] += keyPool[i]; + else + password->Text[i] = keyPool[i]; + } + + if (password->Length < (int)sizeof (keyPool)) + password->Length = sizeof (keyPool); + + burn (keyPool, sizeof (keyPool)); + + return status; +} + + +static void LoadKeyList (HWND hwndDlg, KeyFile *firstKeyFile) +{ + KeyFile *kf; + LVITEM LvItem; + int line = 0; + HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST); + + ListView_DeleteAllItems (hList); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVEALL), firstKeyFile != NULL); + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, firstKeyFile != NULL); + + for (kf = firstKeyFile; kf != NULL; kf = kf->Next) + { + memset (&LvItem,0,sizeof(LvItem)); + LvItem.mask = LVIF_TEXT|LVIF_PARAM; + LvItem.iItem = line++; + LvItem.iSubItem = 0; + LvItem.pszText = kf->FileName; + LvItem.lParam = (LPARAM) kf; + SendMessage (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + } +} + +#if KEYFILE_POOL_SIZE % 4 != 0 +#error KEYFILE_POOL_SIZE must be a multiple of 4 +#endif + +BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static KeyFilesDlgParam *param; + static KeyFilesDlgParam origParam; + + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + LVCOLUMNW LvCol; + HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST); + + param = (KeyFilesDlgParam *) lParam; + origParam = *(KeyFilesDlgParam *) lParam; + + param->FirstKeyFile = KeyFileCloneAll (param->FirstKeyFile); + + LocalizeDialog (hwndDlg, "IDD_KEYFILES"); + DragAcceptFiles (hwndDlg, TRUE); + + SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP + ); + + memset (&LvCol,0,sizeof(LvCol)); + LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + LvCol.pszText = GetString ("KEYFILE"); + LvCol.cx = CompensateXDPI (374); + LvCol.fmt = LVCFMT_LEFT; + SendMessageW (hList, LVM_INSERTCOLUMNW, 0, (LPARAM)&LvCol); + + LoadKeyList (hwndDlg, param->FirstKeyFile); + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, param->EnableKeyFiles); + + SetWindowTextW(GetDlgItem(hwndDlg, IDT_KEYFILES_NOTE), GetString ("KEYFILES_NOTE")); + + ToHyperlink (hwndDlg, IDC_LINK_KEYFILES_INFO); + } + return 1; + + case WM_COMMAND: + + if (lw == IDC_KEYADD) + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory)) + { + do + { + param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); + LoadKeyList (hwndDlg, param->FirstKeyFile); + + kf = (KeyFile *) malloc (sizeof (KeyFile)); + } while (SelectMultipleFilesNext (kf->FileName)); + } + + free (kf); + return 1; + } + + if (lw == IDC_ADD_KEYFILE_PATH) + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + + if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName)) + { + param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); + LoadKeyList (hwndDlg, param->FirstKeyFile); + } + else + { + free (kf); + } + return 1; + } + + if (lw == IDC_TOKEN_FILES_ADD) + { + list selectedTokenKeyfiles; + if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) + { + foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str()); + + param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); + LoadKeyList (hwndDlg, param->FirstKeyFile); + } + } + + return 1; + } + + if (lw == IDC_KEYREMOVE) + { + HWND list = GetDlgItem (hwndDlg, IDC_KEYLIST); + LVITEM LvItem; + memset (&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_PARAM; + LvItem.iItem = -1; + + while (-1 != (LvItem.iItem = ListView_GetNextItem (list, LvItem.iItem, LVIS_SELECTED))) + { + ListView_GetItem (list, &LvItem); + param->FirstKeyFile = KeyFileRemove (param->FirstKeyFile, (KeyFile *) LvItem.lParam); + } + + LoadKeyList (hwndDlg, param->FirstKeyFile); + return 1; + } + + if (lw == IDC_KEYREMOVEALL) + { + KeyFileRemoveAll (¶m->FirstKeyFile); + LoadKeyList (hwndDlg, NULL); + return 1; + } + + if (lw == IDC_GENERATE_KEYFILE) + { + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg, + (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0); + return 1; + } + + if (lw == IDC_LINK_KEYFILES_INFO) + { + Applink ("keyfiles", TRUE, ""); + } + + if (lw == IDOK) + { + param->EnableKeyFiles = IsButtonChecked (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE)); + EndDialog (hwndDlg, IDOK); + return 1; + } + + if (lw == IDCANCEL) + { + KeyFileRemoveAll (¶m->FirstKeyFile); + *param = origParam; + + EndDialog (hwndDlg, IDCLOSE); + return 1; + } + + case WM_DROPFILES: + { + HDROP hdrop = (HDROP) wParam; + + int i = 0, count = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0); + + while (count-- > 0) + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName)); + param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); + LoadKeyList (hwndDlg, param->FirstKeyFile); + } + + DragFinish (hdrop); + } + return 1; + + case WM_NOTIFY: + if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) + { + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), + ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_KEYLIST), -1, LVIS_SELECTED) != -1); + return 1; + } + break; + + case WM_CLOSE: + KeyFileRemoveAll (¶m->FirstKeyFile); + *param = origParam; + + EndDialog (hwndDlg, IDCLOSE); + return 1; + + break; + + } + + return 0; +} + + +#define IDM_KEYFILES_POPUP_ADD_FILES 9001 +#define IDM_KEYFILES_POPUP_ADD_DIR 9002 +#define IDM_KEYFILES_POPUP_ADD_TOKEN_FILES 9003 + +BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *param) +{ + HMENU popup = CreatePopupMenu (); + int sel; + BOOL status = FALSE; + + AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_FILES, GetString ("IDC_KEYADD")); + AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_DIR, GetString ("IDC_ADD_KEYFILE_PATH")); + AppendMenuW (popup, MF_STRING, IDM_KEYFILES_POPUP_ADD_TOKEN_FILES, GetString ("IDC_TOKEN_FILES_ADD")); + + sel = TrackPopupMenu (popup, TPM_RETURNCMD | TPM_LEFTBUTTON, popupPosition.x, popupPosition.y, 0, hwndDlg, NULL); + + switch (sel) + { + case IDM_KEYFILES_POPUP_ADD_FILES: + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory)) + { + do + { + param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); + kf = (KeyFile *) malloc (sizeof (KeyFile)); + } while (SelectMultipleFilesNext (kf->FileName)); + + param->EnableKeyFiles = TRUE; + status = TRUE; + } + + free (kf); + } + break; + + case IDM_KEYFILES_POPUP_ADD_DIR: + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + + if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName)) + { + param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); + param->EnableKeyFiles = TRUE; + status = TRUE; + } + else + { + free (kf); + } + } + break; + + case IDM_KEYFILES_POPUP_ADD_TOKEN_FILES: + { + list selectedTokenKeyfiles; + if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) + { + foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + strcpy_s (kf->FileName, sizeof (kf->FileName), WideToSingleString (keyPath).c_str()); + + param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); + param->EnableKeyFiles = TRUE; + status = TRUE; + } + } + } + break; + } + + DestroyMenu (popup); + return status; +} diff --git a/Common/Keyfiles.h b/Common/Keyfiles.h index 63231fd..6cb2cc3 100644 --- a/Common/Keyfiles.h +++ b/Common/Keyfiles.h @@ -1,46 +1,46 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef KEYFILES_H -#define KEYFILES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "Common.h" - -#define KEYFILE_POOL_SIZE 64 -#define KEYFILE_MAX_READ_LEN (1024*1024) - -typedef struct KeyFileStruct -{ - char FileName[MAX_PATH]; - struct KeyFileStruct *Next; -} KeyFile; - -typedef struct -{ - BOOL EnableKeyFiles; - KeyFile *FirstKeyFile; -} KeyFilesDlgParam; - -KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile); -void KeyFileRemoveAll (KeyFile **firstKeyFile); -KeyFile *KeyFileClone (KeyFile *keyFile); -KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile); -BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile); - -BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *dialogParam); - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef KEYFILES_H */ +/* + Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef KEYFILES_H +#define KEYFILES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Common.h" + +#define KEYFILE_POOL_SIZE 64 +#define KEYFILE_MAX_READ_LEN (1024*1024) + +typedef struct KeyFileStruct +{ + char FileName[MAX_PATH]; + struct KeyFileStruct *Next; +} KeyFile; + +typedef struct +{ + BOOL EnableKeyFiles; + KeyFile *FirstKeyFile; +} KeyFilesDlgParam; + +KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile); +void KeyFileRemoveAll (KeyFile **firstKeyFile); +KeyFile *KeyFileClone (KeyFile *keyFile); +KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile); +BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile); + +BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *dialogParam); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef KEYFILES_H */ diff --git a/Common/Language.c b/Common/Language.c index e7a032f..914985e 100644 --- a/Common/Language.c +++ b/Common/Language.c @@ -1,515 +1,515 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Language.h" -#include "Dlgcode.h" -#include "Dictionary.h" -#include "Tcdefs.h" -#include "Xml.h" - -#include "../Common/Resource.h" - -#ifdef TCMOUNT -#include "../Mount/Resource.h" -#endif - -#ifdef VOLFORMAT -#include "../Format/Resource.h" -#endif - -#ifdef SETUP -#include "../Setup/Resource.h" -#endif - -BOOL LocalizationActive; -int LocalizationSerialNo; - -wchar_t UnknownString[1024]; -static char *LanguageFileBuffer; -static HANDLE LanguageFileFindHandle = INVALID_HANDLE_VALUE; -static char PreferredLangId[6]; -static char *LanguageResource; -static char *HeaderResource[2]; -static char ActiveLangPackVersion[6]; - -static char *MapFirstLanguageFile () -{ - if (LanguageFileFindHandle != INVALID_HANDLE_VALUE) - { - FindClose (LanguageFileFindHandle); - LanguageFileFindHandle = INVALID_HANDLE_VALUE; - } - - if (LanguageResource == NULL) - { - DWORD size; - LanguageResource = MapResource ("Xml", IDR_LANGUAGE, &size); - LanguageResource[size - 1] = 0; - } - - return LanguageResource; -} - - -static char *MapNextLanguageFile () -{ - wchar_t f[TC_MAX_PATH*2], *t; - WIN32_FIND_DATAW find; - HANDLE file; - DWORD read; - - if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) - { - GetModuleFileNameW (NULL, f, sizeof (f) / sizeof (f[0])); - t = wcsrchr (f, L'\\'); - if (t == NULL) return NULL; - - wcscpy (t, L"\\Language*.xml"); - - LanguageFileFindHandle = FindFirstFileW (f, &find); - } - else if (!FindNextFileW (LanguageFileFindHandle, &find)) - { - FindClose (LanguageFileFindHandle); - LanguageFileFindHandle = INVALID_HANDLE_VALUE; - return NULL; - } - - if (find.nFileSizeHigh != 0) return NULL; - - if (LanguageFileBuffer != NULL) free (LanguageFileBuffer); - LanguageFileBuffer = malloc(find.nFileSizeLow); - if (LanguageFileBuffer == NULL) return NULL; - - GetModuleFileNameW (NULL, f, sizeof (f) / sizeof(f[0])); - t = wcsrchr (f, L'\\'); - wcscpy (t + 1, find.cFileName); - - file = CreateFileW (f, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); - if (file == INVALID_HANDLE_VALUE) return NULL; - - ReadFile (file, LanguageFileBuffer, find.nFileSizeLow, &read, NULL); - CloseHandle (file); - if (read != find.nFileSizeLow) return NULL; - - return LanguageFileBuffer; -} - - -BOOL LoadLanguageFile () -{ - DWORD size; - BYTE *res; - char *xml, *header; - char langId[6] = "en", attr[32768], key[128]; - BOOL defaultLangParsed = FALSE, langFound = FALSE; - WCHAR wattr[32768]; - int i, intKey, len; - - char *xmlElements[] = {"control", "string", 0}; - -#ifdef TCMOUNT - int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_MOUNT_RSRC_HEADER, 0 }; -#endif - -#ifdef VOLFORMAT - int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_FORMAT_RSRC_HEADER, 0 }; -#endif - -#ifdef SETUP - int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_SETUP_RSRC_HEADER, 0 }; -#endif - - LocalizationActive = FALSE; - ActiveLangPackVersion[0] = 0; - ClearDictionaryPool (); - - if (PreferredLangId[0] != 0) - strcpy (langId, PreferredLangId); - - // Parse all available language files until preferred language is found - for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile ()) - { - xml = (char *) res; - xml = XmlFindElement (xml, "localization"); - if (!xml) - continue; - - // Required TrueCrypt version - XmlGetAttributeText (xml, "prog-version", attr, sizeof (attr)); - - // Check version of external language file - if (defaultLangParsed && strcmp (attr, VERSION_STRING) && strcmp (attr, "DEBUG")) - { - wchar_t m[2048]; - swprintf (m, L"The installed language pack is incompatible with this version of TrueCrypt (the language pack is for TrueCrypt %hs). A newer version may be available at www.truecrypt.org.\n\nTo prevent this message from being displayed, do any of the following:\n\n- Select 'Settings' > 'Language'; then select 'English' and click 'OK'.\n\n- Remove or replace the language pack with a compatible version (the language pack may reside e.g. in 'C:\\Program Files\\TrueCrypt' or '%%LOCALAPPDATA%%\\VirtualStore\\Program Files\\TrueCrypt', etc.)", attr); - MessageBoxW (NULL, m, L"TrueCrypt", MB_ICONERROR); - continue; - } - - // Search language id in language file - if (defaultLangParsed) - { - while (xml = XmlFindElement (xml, "language")) - { - XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); - if (strcmp (attr, langId) == 0) - { - XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion)); - langFound = TRUE; - break; - } - xml++; - } - - if (!langFound) continue; - } - - // Create font dictionary - xml = (char *) res; - while (xml = XmlFindElement (xml, "font")) - { - XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); - if (!defaultLangParsed - || strcmp (attr, langId) == 0) - { - Font font; - memset (&font, 0, sizeof (font)); - - XmlGetAttributeText (xml, "face", attr, sizeof (attr)); - - len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); - font.FaceName = AddPoolData ((void *) wattr, len * 2); - - XmlGetAttributeText (xml, "size", attr, sizeof (attr)); - sscanf (attr, "%d", &font.Size); - - strcpy (attr, "font_"); - XmlGetAttributeText (xml, "class", attr + 5, sizeof (attr) - 5); - AddDictionaryEntry ( - AddPoolData ((void *) attr, strlen (attr) + 1), 0, - AddPoolData ((void *) &font, sizeof(font))); - } - - xml++; - } - - // Create string and control dictionaries - for (i = 0; xmlElements[i] != 0; i++) - { - xml = (char *) res; - while (xml = XmlFindElement (xml, xmlElements[i])) - { - void *key; - void *text; - - XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); - if (!defaultLangParsed - || strcmp (attr, langId) == 0) - { - if (XmlGetAttributeText (xml, "key", attr, sizeof (attr))) - { - key = AddPoolData (attr, strlen (attr) + 1); - if (key == NULL) return FALSE; - - XmlGetNodeText (xml, attr, sizeof (attr)); - - // Parse \ escape sequences - { - char *in = attr, *out = attr; - while (*in) - { - if (*in == '\\') - { - in++; - switch (*in++) - { - case '\\': *out++ = '\\'; break; - case 't': *out++ = '\t'; break; - case 'n': *out++ = 13; *out++ = 10; break; - default: - MessageBox (0, key, "TrueCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR); - return FALSE; - } - } - else - *out++ = *in++; - } - *out = 0; - } - - // UTF8 => wide char - len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); - if (len == 0 || len == ERROR_NO_UNICODE_TRANSLATION) - { - MessageBox (0, key, "TrueCrypt: Error while decoding UTF-8 string", MB_ICONERROR); - return FALSE; - } - - // Add to dictionary - text = AddPoolData ((void *) wattr, len * 2); - if (text == NULL) return FALSE; - - AddDictionaryEntry ((char *) key, 0, text); - } - } - - xml++; - } - } - - if (langFound) - break; - - if (!defaultLangParsed) - { - defaultLangParsed = TRUE; - if (langId[0] == 0 || strcmp (langId, "en") == 0) - break; - } - } - - LocalizationActive = langFound && strcmp (langId, "en") != 0; - LocalizationSerialNo++; - - // Create control ID dictionary - - // Default controls - AddDictionaryEntry (NULL, 1, GetString ("IDOK")); - AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL")); - AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE")); - AddDictionaryEntry (NULL, 9, GetString ("IDHELP")); - - for (i = 0; headers[i] != 0; i++) - { - if (HeaderResource[i] == NULL) - { - HeaderResource[i] = MapResource ("Header", headers[i], &size); - *(HeaderResource[i] + size - 1) = 0; - } - - header = HeaderResource[i]; - if (header == NULL) return FALSE; - - do - { - if (sscanf (header, "#define %s %d", key, &intKey) == 2) - { - WCHAR *str = GetString (key); - - if (str != UnknownString) - AddDictionaryEntry (NULL, intKey, str); - } - - } while ((header = strchr (header, '\n') + 1) != (char *) 1); - } - - return TRUE; -} - - -// lParam = 1: auto mode -BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - char *xml; - char attr[2048], lastLangId[10]; - WCHAR wattr[2048]; - int len; - int langCount = 0; - BOOL defaultLangFound = FALSE; - - LocalizeDialog (hwndDlg, "IDD_LANGUAGE"); - ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS); - - for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile ()) - { - while (xml = XmlFindElement (xml, "language")) - { - XmlGetAttributeText (xml, "name", attr, sizeof (attr)); - len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); - - if (len != 0 && len != ERROR_NO_UNICODE_TRANSLATION - && (!defaultLangFound || wcscmp (wattr, L"English") != 0)) - { - int i = SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr); - if (i >= 0) - { - int id; - - // Encode language id in LPARAM - XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); - switch (strlen (attr)) - { - case 2: id = attr[0] | attr[1] << 8; break; - case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break; - default: continue; - } - - if (!defaultLangFound) - defaultLangFound = TRUE; - - SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id); - - if (strcmp (attr, PreferredLangId) == 0) - { - char credits [10000]; - WCHAR wcredits [10000]; - WCHAR wversion [20]; - wchar_t szVers [200]; - int nLen; - - SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0); - - // Language pack version - if (!ActiveLangPackVersion[0] || memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0) - { - swprintf (szVers, GetString("LANG_PACK_VERSION"), L"--"); - } - else - { - nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (wversion) / sizeof(wversion[0])); - if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) - swprintf (szVers, GetString("LANG_PACK_VERSION"), wversion); - } - SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers); - - // Translator credits - XmlGetAttributeText (xml, "translators", credits, sizeof (credits)); - nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits) / sizeof(wcredits[0])); - if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) - { - SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits); - } - } - - strcpy (lastLangId, attr); - langCount++; - } - } - - xml++; - } - } - - if (lParam == 1) - { - // Auto mode - if (langCount < 2) - EndDialog (hwndDlg, IDCANCEL); - - if (langCount == 2) - strcpy (PreferredLangId, lastLangId); - - EndDialog (hwndDlg, IDOK); - } - - return 1; - } - - case WM_COMMAND: - - if (lw == IDOK || hw == LBN_DBLCLK) - { - int i = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0); - - if (i >= 0) - { - int id = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0); - - if (id != LB_ERR) - { - char l[6]; - - // Decode language id from LPARAM - l[0] = id; - l[1] = id >> 8; - l[2] = 0; - - if ((id & 0xffff0000) != 0) - { - l[2] = '-'; - l[3] = id >> 16; - l[4] = id >> 24; - l[5] = 0; - } - - if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1) - strcpy (PreferredLangId, l); - } - } - - EndDialog (hwndDlg, IDOK); - return 1; - } - - if (lw == IDCANCEL) - { - EndDialog (hwndDlg, lw); - return 1; - } - - if (lw == IDC_GET_LANG_PACKS) - { - char tmpstr [256]; - - if (strlen (ActiveLangPackVersion) > 0 && strlen (GetPreferredLangId()) > 0) - sprintf (tmpstr, "&langpackversion=%s&lang=%s", ActiveLangPackVersion, GetPreferredLangId()); - else - tmpstr[0] = 0; - - Applink ("localizations", TRUE, tmpstr); - - return 1; - } - return 0; - } - - return 0; -} - - -char *GetPreferredLangId () -{ - return PreferredLangId; -} - - -void SetPreferredLangId (char *langId) -{ - strncpy (PreferredLangId, langId, 5); -} - - -char *GetActiveLangPackVersion () -{ - return ActiveLangPackVersion; -} - - -wchar_t *GetString (const char *stringId) -{ - WCHAR *str = (WCHAR *) GetDictionaryValue (stringId); - if (str != NULL) return str; - - wsprintfW (UnknownString, UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId); - return UnknownString; -} - - -Font *GetFont (char *fontType) -{ - return (Font *) GetDictionaryValue (fontType); - -} +/* + Copyright (c) 2005-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Language.h" +#include "Dlgcode.h" +#include "Dictionary.h" +#include "Tcdefs.h" +#include "Xml.h" + +#include "../Common/Resource.h" + +#ifdef TCMOUNT +#include "../Mount/Resource.h" +#endif + +#ifdef VOLFORMAT +#include "../Format/Resource.h" +#endif + +#ifdef SETUP +#include "../Setup/Resource.h" +#endif + +BOOL LocalizationActive; +int LocalizationSerialNo; + +wchar_t UnknownString[1024]; +static char *LanguageFileBuffer; +static HANDLE LanguageFileFindHandle = INVALID_HANDLE_VALUE; +static char PreferredLangId[6]; +static char *LanguageResource; +static char *HeaderResource[2]; +static char ActiveLangPackVersion[6]; + +static char *MapFirstLanguageFile () +{ + if (LanguageFileFindHandle != INVALID_HANDLE_VALUE) + { + FindClose (LanguageFileFindHandle); + LanguageFileFindHandle = INVALID_HANDLE_VALUE; + } + + if (LanguageResource == NULL) + { + DWORD size; + LanguageResource = MapResource ("Xml", IDR_LANGUAGE, &size); + LanguageResource[size - 1] = 0; + } + + return LanguageResource; +} + + +static char *MapNextLanguageFile () +{ + wchar_t f[TC_MAX_PATH*2], *t; + WIN32_FIND_DATAW find; + HANDLE file; + DWORD read; + + if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) + { + GetModuleFileNameW (NULL, f, sizeof (f) / sizeof (f[0])); + t = wcsrchr (f, L'\\'); + if (t == NULL) return NULL; + + wcscpy (t, L"\\Language*.xml"); + + LanguageFileFindHandle = FindFirstFileW (f, &find); + } + else if (!FindNextFileW (LanguageFileFindHandle, &find)) + { + FindClose (LanguageFileFindHandle); + LanguageFileFindHandle = INVALID_HANDLE_VALUE; + return NULL; + } + + if (find.nFileSizeHigh != 0) return NULL; + + if (LanguageFileBuffer != NULL) free (LanguageFileBuffer); + LanguageFileBuffer = malloc(find.nFileSizeLow); + if (LanguageFileBuffer == NULL) return NULL; + + GetModuleFileNameW (NULL, f, sizeof (f) / sizeof(f[0])); + t = wcsrchr (f, L'\\'); + wcscpy (t + 1, find.cFileName); + + file = CreateFileW (f, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file == INVALID_HANDLE_VALUE) return NULL; + + ReadFile (file, LanguageFileBuffer, find.nFileSizeLow, &read, NULL); + CloseHandle (file); + if (read != find.nFileSizeLow) return NULL; + + return LanguageFileBuffer; +} + + +BOOL LoadLanguageFile () +{ + DWORD size; + BYTE *res; + char *xml, *header; + char langId[6] = "en", attr[32768], key[128]; + BOOL defaultLangParsed = FALSE, langFound = FALSE; + WCHAR wattr[32768]; + int i, intKey, len; + + char *xmlElements[] = {"control", "string", 0}; + +#ifdef TCMOUNT + int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_MOUNT_RSRC_HEADER, 0 }; +#endif + +#ifdef VOLFORMAT + int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_FORMAT_RSRC_HEADER, 0 }; +#endif + +#ifdef SETUP + int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_SETUP_RSRC_HEADER, 0 }; +#endif + + LocalizationActive = FALSE; + ActiveLangPackVersion[0] = 0; + ClearDictionaryPool (); + + if (PreferredLangId[0] != 0) + strcpy (langId, PreferredLangId); + + // Parse all available language files until preferred language is found + for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile ()) + { + xml = (char *) res; + xml = XmlFindElement (xml, "localization"); + if (!xml) + continue; + + // Required TrueCrypt version + XmlGetAttributeText (xml, "prog-version", attr, sizeof (attr)); + + // Check version of external language file + if (defaultLangParsed && strcmp (attr, VERSION_STRING) && strcmp (attr, "DEBUG")) + { + wchar_t m[2048]; + swprintf (m, L"The installed language pack is incompatible with this version of TrueCrypt (the language pack is for TrueCrypt %hs). A newer version may be available at www.truecrypt.org.\n\nTo prevent this message from being displayed, do any of the following:\n\n- Select 'Settings' > 'Language'; then select 'English' and click 'OK'.\n\n- Remove or replace the language pack with a compatible version (the language pack may reside e.g. in 'C:\\Program Files\\TrueCrypt' or '%%LOCALAPPDATA%%\\VirtualStore\\Program Files\\TrueCrypt', etc.)", attr); + MessageBoxW (NULL, m, L"TrueCrypt", MB_ICONERROR); + continue; + } + + // Search language id in language file + if (defaultLangParsed) + { + while (xml = XmlFindElement (xml, "language")) + { + XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); + if (strcmp (attr, langId) == 0) + { + XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion)); + langFound = TRUE; + break; + } + xml++; + } + + if (!langFound) continue; + } + + // Create font dictionary + xml = (char *) res; + while (xml = XmlFindElement (xml, "font")) + { + XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); + if (!defaultLangParsed + || strcmp (attr, langId) == 0) + { + Font font; + memset (&font, 0, sizeof (font)); + + XmlGetAttributeText (xml, "face", attr, sizeof (attr)); + + len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); + font.FaceName = AddPoolData ((void *) wattr, len * 2); + + XmlGetAttributeText (xml, "size", attr, sizeof (attr)); + sscanf (attr, "%d", &font.Size); + + strcpy (attr, "font_"); + XmlGetAttributeText (xml, "class", attr + 5, sizeof (attr) - 5); + AddDictionaryEntry ( + AddPoolData ((void *) attr, strlen (attr) + 1), 0, + AddPoolData ((void *) &font, sizeof(font))); + } + + xml++; + } + + // Create string and control dictionaries + for (i = 0; xmlElements[i] != 0; i++) + { + xml = (char *) res; + while (xml = XmlFindElement (xml, xmlElements[i])) + { + void *key; + void *text; + + XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); + if (!defaultLangParsed + || strcmp (attr, langId) == 0) + { + if (XmlGetAttributeText (xml, "key", attr, sizeof (attr))) + { + key = AddPoolData (attr, strlen (attr) + 1); + if (key == NULL) return FALSE; + + XmlGetNodeText (xml, attr, sizeof (attr)); + + // Parse \ escape sequences + { + char *in = attr, *out = attr; + while (*in) + { + if (*in == '\\') + { + in++; + switch (*in++) + { + case '\\': *out++ = '\\'; break; + case 't': *out++ = '\t'; break; + case 'n': *out++ = 13; *out++ = 10; break; + default: + MessageBox (0, key, "TrueCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR); + return FALSE; + } + } + else + *out++ = *in++; + } + *out = 0; + } + + // UTF8 => wide char + len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); + if (len == 0 || len == ERROR_NO_UNICODE_TRANSLATION) + { + MessageBox (0, key, "TrueCrypt: Error while decoding UTF-8 string", MB_ICONERROR); + return FALSE; + } + + // Add to dictionary + text = AddPoolData ((void *) wattr, len * 2); + if (text == NULL) return FALSE; + + AddDictionaryEntry ((char *) key, 0, text); + } + } + + xml++; + } + } + + if (langFound) + break; + + if (!defaultLangParsed) + { + defaultLangParsed = TRUE; + if (langId[0] == 0 || strcmp (langId, "en") == 0) + break; + } + } + + LocalizationActive = langFound && strcmp (langId, "en") != 0; + LocalizationSerialNo++; + + // Create control ID dictionary + + // Default controls + AddDictionaryEntry (NULL, 1, GetString ("IDOK")); + AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL")); + AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE")); + AddDictionaryEntry (NULL, 9, GetString ("IDHELP")); + + for (i = 0; headers[i] != 0; i++) + { + if (HeaderResource[i] == NULL) + { + HeaderResource[i] = MapResource ("Header", headers[i], &size); + *(HeaderResource[i] + size - 1) = 0; + } + + header = HeaderResource[i]; + if (header == NULL) return FALSE; + + do + { + if (sscanf (header, "#define %s %d", key, &intKey) == 2) + { + WCHAR *str = GetString (key); + + if (str != UnknownString) + AddDictionaryEntry (NULL, intKey, str); + } + + } while ((header = strchr (header, '\n') + 1) != (char *) 1); + } + + return TRUE; +} + + +// lParam = 1: auto mode +BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + char *xml; + char attr[2048], lastLangId[10]; + WCHAR wattr[2048]; + int len; + int langCount = 0; + BOOL defaultLangFound = FALSE; + + LocalizeDialog (hwndDlg, "IDD_LANGUAGE"); + ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS); + + for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile ()) + { + while (xml = XmlFindElement (xml, "language")) + { + XmlGetAttributeText (xml, "name", attr, sizeof (attr)); + len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); + + if (len != 0 && len != ERROR_NO_UNICODE_TRANSLATION + && (!defaultLangFound || wcscmp (wattr, L"English") != 0)) + { + int i = SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr); + if (i >= 0) + { + int id; + + // Encode language id in LPARAM + XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); + switch (strlen (attr)) + { + case 2: id = attr[0] | attr[1] << 8; break; + case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break; + default: continue; + } + + if (!defaultLangFound) + defaultLangFound = TRUE; + + SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id); + + if (strcmp (attr, PreferredLangId) == 0) + { + char credits [10000]; + WCHAR wcredits [10000]; + WCHAR wversion [20]; + wchar_t szVers [200]; + int nLen; + + SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0); + + // Language pack version + if (!ActiveLangPackVersion[0] || memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0) + { + swprintf (szVers, GetString("LANG_PACK_VERSION"), L"--"); + } + else + { + nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (wversion) / sizeof(wversion[0])); + if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) + swprintf (szVers, GetString("LANG_PACK_VERSION"), wversion); + } + SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers); + + // Translator credits + XmlGetAttributeText (xml, "translators", credits, sizeof (credits)); + nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits) / sizeof(wcredits[0])); + if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) + { + SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits); + } + } + + strcpy (lastLangId, attr); + langCount++; + } + } + + xml++; + } + } + + if (lParam == 1) + { + // Auto mode + if (langCount < 2) + EndDialog (hwndDlg, IDCANCEL); + + if (langCount == 2) + strcpy (PreferredLangId, lastLangId); + + EndDialog (hwndDlg, IDOK); + } + + return 1; + } + + case WM_COMMAND: + + if (lw == IDOK || hw == LBN_DBLCLK) + { + int i = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0); + + if (i >= 0) + { + int id = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0); + + if (id != LB_ERR) + { + char l[6]; + + // Decode language id from LPARAM + l[0] = (char) id; + l[1] = (char) (id >> 8); + l[2] = 0; + + if ((id & 0xffff0000) != 0) + { + l[2] = '-'; + l[3] = (char) (id >> 16); + l[4] = id >> 24; + l[5] = 0; + } + + if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1) + strcpy (PreferredLangId, l); + } + } + + EndDialog (hwndDlg, IDOK); + return 1; + } + + if (lw == IDCANCEL) + { + EndDialog (hwndDlg, lw); + return 1; + } + + if (lw == IDC_GET_LANG_PACKS) + { + char tmpstr [256]; + + if (strlen (ActiveLangPackVersion) > 0 && strlen (GetPreferredLangId()) > 0) + sprintf (tmpstr, "&langpackversion=%s&lang=%s", ActiveLangPackVersion, GetPreferredLangId()); + else + tmpstr[0] = 0; + + Applink ("localizations", TRUE, tmpstr); + + return 1; + } + return 0; + } + + return 0; +} + + +char *GetPreferredLangId () +{ + return PreferredLangId; +} + + +void SetPreferredLangId (char *langId) +{ + strncpy (PreferredLangId, langId, 5); +} + + +char *GetActiveLangPackVersion () +{ + return ActiveLangPackVersion; +} + + +wchar_t *GetString (const char *stringId) +{ + WCHAR *str = (WCHAR *) GetDictionaryValue (stringId); + if (str != NULL) return str; + + wsprintfW (UnknownString, UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId); + return UnknownString; +} + + +Font *GetFont (char *fontType) +{ + return (Font *) GetDictionaryValue (fontType); + +} diff --git a/Common/Language.h b/Common/Language.h index 0c3ee5e..e978067 100644 --- a/Common/Language.h +++ b/Common/Language.h @@ -1,37 +1,37 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define UNKNOWN_STRING_ID L"[?]" - -extern BOOL LocalizationActive; -extern int LocalizationSerialNo; -extern wchar_t UnknownString[1024]; - -typedef struct -{ - wchar_t *FaceName; - int Size; -} Font; - -BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -wchar_t *GetString (const char *stringId); -Font *GetFont (char *fontType); -BOOL LoadLanguageFile (); -char *GetPreferredLangId (); -void SetPreferredLangId (char *langId); -char *GetActiveLangPackVersion (); - -#ifdef __cplusplus -} -#endif +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define UNKNOWN_STRING_ID L"[?]" + +extern BOOL LocalizationActive; +extern int LocalizationSerialNo; +extern wchar_t UnknownString[1024]; + +typedef struct +{ + wchar_t *FaceName; + int Size; +} Font; + +BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +wchar_t *GetString (const char *stringId); +Font *GetFont (char *fontType); +BOOL LoadLanguageFile (); +char *GetPreferredLangId (); +void SetPreferredLangId (char *langId); +char *GetActiveLangPackVersion (); + +#ifdef __cplusplus +} +#endif diff --git a/Common/Language.xml b/Common/Language.xml index 0fbb075..9294edd 100644 --- a/Common/Language.xml +++ b/Common/Language.xml @@ -1,1244 +1,1298 @@ - - - - - - - - - - - - Cancel - Install &for all users - Bro&wse... - Add TrueCrypt icon to &desktop - Associate the .tc file &extension with TrueCrypt - &Open the destination location when finished - Add TrueCrypt to &Start menu - Create System &Restore point - &Uninstall - &Extract - &Install - TrueCrypt Setup Wizard - Uninstall TrueCrypt - &Help - Please select or type the location where you want to place the extracted files: - Please select or type the location where you want to install the TrueCrypt program files. If the specified folder does not exist, it will be automatically created. - Click Uninstall to remove TrueCrypt from this system. - Abort - &Test - Create encrypted volume and format it - Encrypt partition in place - Display generated keys (their portions) - Display pool content - Download CD/DVD recording software - Create an encrypted file container - &GB - More information - Hi&dden TrueCrypt volume - More information about hidden volumes - Direct mode - Normal mode - &KB - U&se keyfiles - &Keyfiles.. - Information on hash algorithms - More information - &MB - More information - More information about system encryption - More information - Multi-boot - Encrypt a non-system partition/drive - Never &save history - Open Outer Volume - &Pause - Quick Format - &Display password - &Display password - Single-boot - Standard TrueCrypt volume - Hi&dden - Normal - Encrypt the system partition or entire system drive - Encrypt the Windows system partition - Encrypt the whole drive - &Benchmark - TrueCrypt Volume Creation Wizard - Cluster - 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. - &Confirm: - Done - Encryption Algorithm - Filesystem - Creates a virtual encrypted disk within a file. Recommended for inexperienced users. - Options - Hash Algorithm - Header Key: - Left - Master Key: - Select this option if there are two or more operating systems installed on this computer.\n\nFor example:\n- Windows XP and Windows XP\n- Windows XP and Windows Vista\n- Windows and Mac OS X\n- Windows and Linux\n- Windows, Linux and Mac OS X - Encrypts a non-system partition on any internal or external drive (e.g. a flash drive). Optionally, creates a hidden volume. - Current pool content (partial) - Pass - Password: - Progress: - Random Pool: - Select this option if there is only one operating system installed on this computer (even if it has multiple users). - Speed - Status - The keys, salt, and other data have been successfully generated. If you want to generate new keys, click Back and then Next. Otherwise, click Next to continue. - Encrypts the partition/drive where Windows is installed. Anyone who wants to gain access and use the system, read and write files, etc., will need to enter the correct password each time before Windows boots. Optionally, creates a hidden system. - Select this option to encrypt the partition where your Windows is installed and from which it boots. - Wipe mode: - Close - Allow pre-boot &authentication to be bypassed by pressing the Esc key (enables boot manager) - Do nothing - &Auto-mount TrueCrypt volume (specified below) - &Start TrueCrypt - Auto-&Detect Library - &Cache pre-boot authentication password in driver memory (for mounting of non-system volumes) - Browse... - Browse... - Cache passwords and keyfil&es in memory - Exit when there are no mounted volumes - &Close token session (log out) after a volume is successfully mounted - Include TrueCrypt Volume Creation Wizard - Create - &Create Volume - Do not &show any texts in the pre-boot authentication screen (except the below custom message) - Display confirmation message box after dismount - Play system notification sound after mount/dismount - Use keyfiles - Use keyfiles - E&xit - Alt - Control - Shift - Win - Assign - Remove - Keyfiles... - More Settings... - &Auto-Mount Devices - Mount Opti&ons... - Mount volume as read-&only - Keyfiles... - Enabled - Cache passwords in driver memory - Close all Explorer windows of volume being dismounted - Auto-dismount volume after no data has been read/written to it for - User logs off - Entering power saving mode - Screen saver is launched - Force auto-dismount even if volume contains open files or directories - Mount all device-hosted TrueCrypt volumes - Mount favorite volumes - Start TrueCrypt Background Task - Mount volumes as read-only - Mount volumes as removable media - Open Explorer window for successfully mounted volume - Wipe cached passwords on auto-dismount - Wipe cached passwords on exit - Preserve timestamps of file containers - Reset - Select D&evice... - Select &File... - Select &Library... - Display password - Display password - Open &Explorer window for mounted volume - &Cache password in driver memory - Di&smount All - &Volume Properties... - Volume &Tools... - &Wipe Cache - TrueCrypt - System-Wide Hot Keys - TrueCrypt - Change Password or Keyfiles - Enter TrueCrypt Volume Password - TrueCrypt - Preferences - TrueCrypt - System Encryption Settings - TrueCrypt - Security Token Preferences - TrueCrypt Traveler Disk Setup - TrueCrypt Volume Properties - About... - Add/Remove Keyfiles to/from Volume... - Backup Volume Header... - Benchmark... - Report a Bug... - Set Header Key Derivation Algorithm... - Change Volume Password... - Set Header Key Derivation Algorithm... - Change Password... - Clear Volume History - Close All Security Token Sessions - Contact... - Create Hidden Operating System... - Create Rescue Disk... - Create New Volume... - Default Keyfiles... - Donations... - Encrypt System Partition/Drive... - Frequently Asked Questions - Forums - Generate Random Keyfile... - User's Guide - &Homepage - Hot Keys... - Keyfile Generator - Language... - Legal Notices - Manage Security Token Keyfiles... - Auto-Mount All Device-Hosted Volumes - Mount Favorite Volumes - Mount Without Pre-Boot &Authentication... - Mount Volume - Mount Volume with Options - News - Online Help - Beginner's Tutorial - Permanently Decrypt System Partition/Drive - Preferences... - Refresh Drive Letters - Remove All Keyfiles from Volume... - Restore Volume Header... - Resume Interrupted Process - Save Currently Mounted Volumes as Favorite - Select Device... - Select File... - Set Default Keyfiles/Paths... - Resume Interrupted Process - System Encryption... - Properties... - Settings... - Downloads - Test Vectors... - Security Tokens... - Traveler Disk Setup... - Dismount All Mounted Volumes - Dismount Volume - Verify Rescue Disk - Version History - Volume Properties - Volume Creation Wizard - TrueCrypt Website - Wipe Cached Passwords - OK - Shortcut - AutoRun Configuration (autorun.inf) - Auto-Dismount - Dismount all when: - Boot Loader Screen Options - Confirm Password: - Current - Display this custom message in the pre-boot authentication screen (24 characters maximum): - Default Mount Options - Hot Key Options - File Settings - Key to assign: - Actions to perform upon log on to Windows - minutes - Mount volume as drive letter: - Mount Settings - New - Password: - PKCS #11 Library Path - PKCS-5 PRF: - Password Cache - Security Options - TrueCrypt Background Task - TrueCrypt volume to mount (relative to traveler disk root): - Upon insertion of traveler disk: - Create traveler disk files at (traveler disk root directory): - Volume - Windows - Add &Path... - &Auto-Test All - &Continue - &Decrypt - &Delete - Donations... - &Encrypt - &Export... - Generate and Save Keyfile... - &Generate Random Keyfile... - Download language pack - &Import Keyfile to Token... - Add &Files... - U&se keyfiles - &Keyfiles... - &Remove - Remove &All - What is hidden volume protection? - More information on keyfiles - Mount volume as removable &medium - Mount partition &using system encryption without pre-boot authentication - Benchmark - &Print - &Protect hidden volume against damage caused by writing to outer volume - &Reset - &Display password - Add &Token Files... - Use backup header embedded in &volume if available - XTS mode - About TrueCrypt - TrueCrypt - Encryption Algorithm Benchmark - TrueCrypt - Test Vectors - Command Line Help - TrueCrypt - Keyfiles - TrueCrypt - Keyfile Generator - TrueCrypt - Language - TrueCrypt - Mount Options - New Security Token Keyfile Properties - TrueCrypt - Random Pool Enrichment - Select a Partition or Device - Security Token Keyfiles - Security token password/PIN required - Active language pack - Speed is affected by CPU load and storage device characteristics.\n\nThese tests take place in RAM. - Buffer Size: - Cipher: - P&assword to hidden volume:\n(if empty, cache is used) - Hidden Volume Protection - Key size: - 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 - Translated by: - Plaintext size: - bits - Current pool content - Mixing PRF: - 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'. - Secondary key (hexadecimal) - Security token: - Sort Method: - Block number: - Ciphertext (hexadecimal) - Data unit number (64-bit hexadecimal, data unit size is 512 bytes) - Key (hexadecimal) - Plaintext (hexadecimal) - Keyfile name: - XTS mode - Disable Windows paging files - Exit - Cipher Configuration (all sizes in bytes) - Set Header Key Derivation Algorithm - Add/Remove Keyfiles to/from Volume - Remove All Keyfiles from Volume - Windows Explorer - Browse... - TrueCrypt - Keyfile Generator - S&ystem - &Volumes - &Keyfiles - T&ools - Settin&gs - &Help - Home&page - - &About... - The read-only attribute on your old volume could not be changed. Please check the file access permissions. - Error: Access denied.\n\nThe partition you are trying to access is either 0 sectors long, or it is the boot device. - In order to load the TrueCrypt driver, you need to be logged into an account with administrator privileges. - Please note that in order to encrypt/format a partition/device you need to be logged into an account with administrator privileges.\n\nThis does not apply to file-hosted volumes. - In order to create a hidden volume you need to be logged into an account with administrator privileges.\n\nContinue? - Please note that in order to format the volume as NTFS you need to be logged into an account with administrator privileges.\n\nWithout administrator privileges, you can format the volume as FAT. - FIPS-approved cipher (Rijndael, published in 1998) that may be used by U.S. government departments and agencies to protect classified information up to the Top Secret level. 256-bit key, 128-bit block, 14 rounds (AES-256). Mode of operation is XTS. - Volume is already mounted. - CAUTION: At least one encryption or hash algorithm failed the built-in automatic self-tests!\n\nTrueCrypt installation may be corrupted. - CAUTION: There is not enough data in the Random Number Generator pool to provide the requested amount of random data.\n\nYou should not proceed any further. Please select 'Report a Bug' from the Help menu, and report this error. - The drive is damaged (there is a physical defect on it) or a cable is damaged, or the memory is malfunctioning.\n\nPlease note that this is a problem with your hardware, not with TrueCrypt. Therefore, please do NOT report this as a bug/problem in TrueCrypt and please do NOT ask for help with this in the TrueCrypt Forums. Please contact your computer vendor's technical support team for assistance. Thank you.\n\nNote: If the error occurs repeatedly at the same place, it is very likely caused by a bad disk block, which should be possible to correct using third-party software (note that, in many cases, the 'chkdsk /r' command cannot correct it because it works only at the filesystem level; in some cases, the 'chkdsk' tool cannot even detect it). - Your system appears to be using custom chipset drivers containing a bug that prevents encryption of the whole system drive.\n\nPlease try updating or uninstalling any custom (non-Microsoft) chipset drivers before proceeding. If it does not help, try encrypting the system partition only. - Invalid drive letter. - Invalid path. - Cancel - Cannot access device. Make sure the selected device exists and is not used by system. - Warning: Caps Lock is on. This may cause you to enter your password incorrectly. - Volume Type - It may happen that you are forced by somebody to reveal the password to an encrypted volume. There are many situations where you cannot refuse to reveal the password (for example, due to extortion). Using a so-called hidden volume allows you to solve such situations without revealing the password to your volume. - Select this option if you want to create a normal TrueCrypt volume. - Please note that if you wish an operating system to be installed in a hidden partition-hosted volume, then the entire system drive cannot be encrypted using a single key. - Outer Volume Encryption Options - Hidden Volume Encryption Options - Encryption Options - WARNING: Failed to clear the path of the last selected volume/keyfile (remembered by file selector)! - Error: The container has been compressed at the filesystem level. TrueCrypt does not support compressed containers (note that compression of encrypted data is ineffective and redundant).\n\nPlease disable compression for the container by following these steps:\n1) Right-click the container in Windows Explorer (not in TrueCrypt).\n2) Select 'Properties'.\n3) In the 'Properties' dialog box, click 'Advanced'.\n4) In the 'Advanced Attributes' dialog box, disable the option 'Compress contents to save disk space' and click 'OK'.\n5) In the 'Properties' dialog box, click 'OK'. - Failed to create volume %hs - Size of %hs is %.2f bytes - Size of %hs is %.2f KB - Size of %hs is %.2f MB - Size of %hs is %.2f GB - Size of %hs is %.2f TB - Size of %hs is %.2f PB - WARNING: The device/partition is in use by the operating system or applications. Formatting the device/partition might cause data corruption and system instability.\n\nContinue? - Warning: The partition is in use by the operating system or applications. You should close any applications that might be using the partition (including antivirus software).\n\nContinue? - Error: The device/partition contains a file system that could not be dismounted. The file system may be in use by the operating system. Formatting the device/partition would very likely cause data corruption and system instability.\n\nTo solve this issue, we recommend that you first delete the partition and then recreate it without formatting. To do so, follow these steps:\n1) Right-click the 'Computer' (or 'My Computer') icon in the 'Start Menu' and select 'Manage'. The 'Computer Management' window should appear.\n2) In the 'Computer Management' window, select 'Storage' > 'Disk Management'.\n3) Right-click the partition you want to encrypt and select either 'Delete Partition', or 'Delete Volume', or 'Delete Logical Drive'.\n4) Click 'Yes'. If Windows asks you to restart the computer, do so. Then repeat the steps 1 and 2 and continue from the step 5.\n5) Right-click the unallocated/free space area and select either 'New Partition', or 'New Simple Volume', or 'New Logical Drive'.\n6) The 'New Partition Wizard' or 'New Simple Volume Wizard' window should appear now; follow its instructions. On the wizard page entitled 'Format Partition', select either 'Do not format this partition' or 'Do not format this volume'. In the same wizard, click 'Next' and then 'Finish'.\n7) Note that the device path you have selected in TrueCrypt may be wrong now. Therefore, exit the TrueCrypt Volume Creation Wizard (if it is still running) and then start it again.\n8) Try encrypting the device/partition again.\n\nIf TrueCrypt repeatedly fails to encrypt the device/partition, you may want to consider creating a file container instead. - Error: The filesystem could not be locked and/or dismounted. It may be in use by the operating system or applications (for example, antivirus software). Encrypting the partition might cause data corruption and system instability.\n\nPlease close any applications that might be using the filesystem (including antivirus software) and try again. If it does not help, please follow the below steps. - WARNING: Some of the mounted devices/partitions were already in use!\n\nIgnoring this can cause undesired results including system instability.\n\nWe strongly recommend that you close any application that might be using the devices/partitions. - The selected device contains partitions.\n\nFormatting the device might cause system instability and/or data corruption. Please either select a partition on the device, or remove all partitions on the device to enable TrueCrypt to format it safely. - The selected non-system device contains partitions.\n\nEncrypted device-hosted TrueCrypt volumes can be created within devices that do not contain any partitions (including hard disks and solid-state drives). A device that contains partitions can be entirely encrypted in place (using a single master key) only if it is the drive where Windows is installed and from which it boots.\n\nIf you want to encrypt the selected non-system device using a single master key, you will need to remove all partitions on the device first to enable TrueCrypt to format it safely (formatting a device that contains partitions might cause system instability and/or data corruption). Alternatively, you can encrypt each partition on the drive individually (each partition will be encrypted using a different master key).\n\nNote: If you want to remove all partitions from a GPT disk, you may need to convert it to a MBR disk (using e.g. the Computer Management tool) in order to remove hidden partitions. - Warning: If you encrypt the entire device (as opposed to encrypting only a partition on it), operating systems will consider the device as new, empty, and unformatted (as it will contain no partition table) and may spontaneously initialize the device (or ask you if you want to do so), which may damage the volume.\n\nTo avoid that you may want to consider creating a partition on the device and encrypting the partition instead.\n\nAre you sure want to encrypt the entire device? - IMPORTANT: Please keep in mind that this volume can NOT be mounted/accessed using the drive letter %c:, which is currently assigned to it!\n\nTo mount this volume, click 'Auto-Mount Devices' in the main TrueCrypt window (alternatively, in the main TrueCrypt window, click 'Select Device', then select this partition/device, and click 'Mount'). The volume will be mounted to a different drive letter, which you select from the list in the main TrueCrypt window.\n\nThe original drive letter %c: should be used only in case you need to remove encryption from the partition/device (e.g., if you no longer need encryption). In such a case, right-click the drive letter %c: in the 'Computer' (or 'My Computer') list and select 'Format'. Otherwise, the drive letter %c: should never be used (unless you remove it and assign it to another partition/device). - In-place encryption of non-system volumes is not supported on the version of the operating system you are currently using (it is supported only on Windows Vista and later versions of Windows).\n\nThe reason is that this version of Windows does not support shrinking of a filesystem (the filesystem needs to be shrunk to make space for the volume header and backup header). - The selected partition does not appear to contain an NTFS filesystem. Only partitions that contain an NTFS filesystem can be encrypted in place.\n\nNote: The reason is that Windows does not support shrinking of other types of filesystems (the filesystem needs to be shrunk to make space for the volume header and backup header). - The selected partition does not appear to contain an NTFS filesystem. Only partitions that contain an NTFS filesystem can be encrypted in place.\n\nIf you want to create an encrypted TrueCrypt volume within this partition, choose the option "Create encrypted volume and format it" (instead of the option "Encrypt partition in place"). - Error: The partition is too small. TrueCrypt cannot encrypt it in place. - To encrypt the data on this partition, please follow these steps:\n\n1) Create a TrueCrypt volume on an empty partition/device and then mount it.\n\n2) Copy all files from the partition that you originally wanted to encrypt to the mounted TrueCrypt volume (that has been created and mounted in step 1). That way, you will create a TrueCrypt-encrypted backup of the data.\n\n3) Create a TrueCrypt volume on the partition that you originally wanted to encrypt and make sure that (in the TrueCrypt wizard) you choose the option "Create encrypted volume and format it" (instead of the option "Encrypt partition in place"). Note that all data stored on the partition will be erased. After the volume is created, mount it.\n\n4) Copy all files from the mounted backup TrueCrypt volume (created and mounted in step 1) to the mounted TrueCrypt volume that has been created (and mounted) in step 3.\n\nAfter you complete these steps, the data will be encrypted and, in addition, there will be an encrypted backup of the data. - TrueCrypt can in-place encrypt only a partition, a dynamic volume, or an entire system drive.\n\nIf you want to create an encrypted TrueCrypt volume within the selected non-system device, choose the option "Create encrypted volume and format it" (instead of the option "Encrypt partition in place"). - Error: TrueCrypt can in-place encrypt only a partition, a dynamic volume, or an entire system drive. Please make sure the specified path is valid. - Error: Cannot shrink the filesystem (the filesystem needs to be shrunk to make space for the volume header and backup header).\n\nPossible causes and solutions:\n\n- Not enough free space on the volume. Please make sure no other application is writing to the filesystem.\n\n- Corrupted file system. Try to check it and fix any errors (right-click the corresponding drive letter in the 'Computer' list, then select Properties > Tools > 'Check Now', make sure the option 'Automatically fix file system errors' is enabled and click Start).\n\nIf the above steps do not help, please follow the below steps. - Error: There is not enough free space on the volume and so the filesystem cannot be shrunk (the filesystem needs to be shrunk to make space for the volume header and backup header).\n\nPlease delete any redundant files and empty the Recycle Bin so as to free at least 256 KB of space and then try again. Note that due to a Windows issue, the amount of free space reported by the Windows Explorer may be incorrect until the operating system is restarted. If restarting the system does not help, the file system may be corrupted. Try to check it and fix any errors (right-click the corresponding drive letter in the 'Computer' list, then select Properties > Tools > 'Check Now', make sure the option 'Automatically fix file system errors' is enabled and click Start).\n\nIf the above steps do not help, please follow the below steps. - Free space on drive %hs is %.2f bytes. - Free space on drive %hs is %.2f KB - Free space on drive %hs is %.2f MB - Free space on drive %hs is %.2f GB - Free space on drive %hs is %.2f TB - Free space on drive %hs is %.2f PB - Could not get available drive letters. - Error: TrueCrypt driver not found.\n\nPlease copy the files 'truecrypt.sys' and 'truecrypt-x64.sys' to the directory where the main TrueCrypt application (TrueCrypt.exe) is located. - An incompatible version of the TrueCrypt device driver is currently running.\n\nRequired version: TrueCrypt %hs - Error: Cipher initialization failure. - Error: A weak or a potentially weak key has been detected. The key will be discarded. Please try again. - A critical error has occurred and TrueCrypt must be terminated. If this is caused by a bug in TrueCrypt, we would like to fix it. To help us, you can send us an automatically generated error report containing the following items:\n\n- Program version\n- Operating system version\n- Type of CPU\n- TrueCrypt component name\n- Checksum of TrueCrypt executable\n- Symbolic name of dialog window\n- Error category\n- Error address\n- TrueCrypt call stack\n\nIf you select 'Yes', the following URL (which contains the entire error report) will be opened in your default Internet browser.\n\n%hs\n\nDo you want to send us the above error report? - A critical error has occurred in your system, which requires TrueCrypt to be terminated.\n\nNote that this error has not been caused by TrueCrypt (so the TrueCrypt developers cannot fix it). Please, check your system for possible problems (e.g., system configuration, network connection, failing hardware components). - TrueCrypt Critical Error - &Encrypt - &Decrypt - &Permanently Decrypt - Exit - Please create a logical drive for this extended partition, and then try again. - A TrueCrypt volume can reside in a file (called TrueCrypt container), which can reside on a hard disk, on a USB flash drive, etc. A TrueCrypt container is just like any normal file (it can be, for example, moved, copied and deleted as any normal file). Click 'Select File' to choose a filename for the container and to select the location where you wish the container to be created.\n\nWARNING: If you select an existing file, TrueCrypt will NOT encrypt it; the file will be deleted and replaced with the newly created TrueCrypt container. You will be able to encrypt existing files (later on) by moving them to the TrueCrypt container that you are about to create now. - Select the location of the outer volume to be created (within this volume the hidden volume will be created later on).\n\nA TrueCrypt volume can reside in a file (called TrueCrypt container), which can reside on a hard disk, on a USB flash drive, etc. A TrueCrypt container can be moved, copied and deleted as any normal file. Click 'Select File' to choose a filename for the container and to select the location where you wish the container to be created. If you select an existing file, TrueCrypt will NOT encrypt it; it will be deleted and replaced with the newly created container. You will be able to encrypt existing files (later on) by moving them to the TrueCrypt container you are about to create now. - Encrypted device-hosted TrueCrypt volumes can be created within partitions on hard disks, solid-state drives, USB memory sticks, and on any other supported storage devices. Partitions can also be encrypted in place.\n\nIn addition, encrypted device-hosted TrueCrypt volumes can be created within devices that do not contain any partitions (including hard disks and solid-state drives).\n\nNote: A device that contains partitions can be entirely encrypted in place (using a single key) only if it is the drive where Windows is installed and from which it boots. - A device-hosted TrueCrypt volume can be created within a hard disk partition, solid-state drive, USB memory stick, and other storage devices.\n\nWARNING: Note that the partition/device will be formatted and all data currently stored on it will be lost. - \nSelect the location of the outer volume to be created (within this volume the hidden volume will be created later on).\n\nOuter volumes can be created within partitions on hard disks, solid-state drives, USB memory sticks, and on any other supported storage devices. Outer volumes can also be created within devices that do not contain any partitions (including hard disks and solid-state drives).\n\nWARNING: Note that the partition/device will be formatted and all data currently stored on it will be lost. - \nSelect the location of the TrueCrypt volume within which you wish to create a hidden volume. - WARNING: The host file/device is already in use!\n\nIgnoring this can cause undesired results including system instability. All applications that might be using the host file/device (for example, antivirus or backup applications) should be closed before mounting the volume.\n\nContinue mounting? - Error: Cannot mount volume. The host file/device is already in use. Attempt to mount without exclusive access failed as well. - The file could not be opened. - Volume Location - Large Files - Do you intend to store files larger than 4 GB in this TrueCrypt volume? - Depending on your choice above, TrueCrypt will choose a suitable default file system for the TrueCrypt volume (you will be able to select a file system in the next step). - As you are creating an outer volume, you should consider choosing 'No'. If you choose 'Yes', the default filesystem will be NTFS, which is not as suitable for outer volumes as FAT (for example, the maximum possible size of the hidden volume will be significantly greater if the outer volume is formatted as FAT). Normally, FAT is the default for both hidden and normal volumes (so FAT volumes are not suspicious). However, if the user indicates intent to store files larger than 4 GB (which the FAT file system does not allow), then FAT is not the default. - Are you sure you want to choose 'Yes'? - Volume Creation Mode - This is the fastest way to create a partition-hosted or device-hosted TrueCrypt volume (in-place encryption, which is the other option, is slower because content of each sector has to be first read, encrypted, and then written). Any data currently stored on the selected partition/device will be lost (the data will NOT be encrypted; it will be overwritten with random data). If you want to encrypt existing data on a partition, choose the other option. - The entire selected partition and all data stored on it will be encrypted in place. If the partition is empty, you should choose the other option (the volume will be created much faster). - Note: - &Resume - &Defer - &Start - &Continue - &Format - &Wipe - Abort format? - Show more information - Do not show this again - The content of the partition/device has been successfully erased. - The content of the partition where the original system (of which the hidden system is a clone) resided has been successfully erased. - The system partition/drive has been successfully encrypted. - The system partition/drive has been successfully decrypted. - \n\nThe TrueCrypt volume has been created and is ready for use. If you wish to create another TrueCrypt volume, click Next. Otherwise, click Exit. - \n\nThe hidden TrueCrypt volume has been successfully created (the hidden operating system will reside within this hidden volume).\n\nClick Next to continue. - Volume Fully Encrypted - IMPORTANT: TO MOUNT THIS NEWLY CREATED TRUECRYPT VOLUME AND TO ACCESS DATA STORED IN IT, CLICK 'Auto-Mount Devices' IN THE MAIN TRUECRYPT WINDOW. After you enter the correct password (and/or supply correct keyfiles), the volume will be mounted to the drive letter you select from the list in the main TrueCrypt window (and you will be able to access the encrypted data via the selected drive letter).\n\nPLEASE REMEMBER OR WRITE DOWN THE ABOVE STEPS. YOU MUST FOLLOW THEM WHENEVER YOU WANT TO MOUNT THE VOLUME AND ACCESS DATA STORED IN IT. Alternatively, in the main TrueCrypt window, click 'Select Device', then select this partition/volume, and click 'Mount'.\n\nThe partition/volume has been successfully encrypted (it contains a fully encrypted TrueCrypt volume now) and is ready for use. - The TrueCrypt volume has been successfully created. - Volume Created - 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 Format to create the volume. - Click Format to create the outer volume. For more information, please refer to the documentation. - Outer Volume Format - Hidden Volume Format - Volume Format - WARNING: Could not get container timestamp! - WARNING: Could not get container timestamp!\n\nIf there is a hidden volume within this container, the plausible deniability of the hidden volume might be affected. - WARNING: Could not get container timestamp!\n\nIf you do not reset the timestamp using an external tool, we recommend that you do not create a hidden volume within this container. - WARNING: Could not get container timestamp!\n\nIf there is a hidden volume within this container, the plausible deniability of the hidden volume might be affected after changing or attempting to change the password. - WARNING: Could not get keyfile timestamp! Cannot preserve last access date/time.\n\nIt will be possible to tell that this file has been accessed. - Adobe Reader (or a compatible tool) is necessary to view or print the TrueCrypt User's Guide. Adobe Reader (freeware) can be downloaded at: www.adobe.com\n\nDo you want to view the online documentation instead? - If you select this option, the wizard will first help you create a normal TrueCrypt volume and then a hidden TrueCrypt volume within it. Inexperienced users should always select this option. - If you select this option, you will create a hidden volume within an existing TrueCrypt volume. It will be assumed that you have already created a TrueCrypt volume that is suitable to host the hidden volume. - Volume Creation Mode - Hidden Volume Created - The hidden TrueCrypt volume has been successfully created and is ready for use. If all the instructions have been followed and if precautions mentioned in the section "Security Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide are followed, it will be impossible to prove that the hidden volume exists, even when the outer volume is mounted.\n\nWARNING: IF YOU DO NOT PROTECT THE HIDDEN VOLUME (FOR INFORMATION ON HOW TO DO SO, REFER TO THE SECTION "PROTECTION OF HIDDEN VOLUMES AGAINST DAMAGE" IN THE TRUECRYPT USER'S GUIDE), DO NOT WRITE TO THE OUTER VOLUME. OTHERWISE, YOU MAY OVERWRITE AND DAMAGE THE HIDDEN VOLUME! - You have started the hidden operating system. As you may have noticed, the hidden operating system appears to be installed on the same partition as the original operating system. However, in reality, it is installed within the partition behind it (in the hidden volume). All read and write operations are being transparently redirected from the original system partition to the hidden volume.\n\nNeither the operating system nor applications will know that data written to and read from the system partition are actually written to and read from the partition behind it (from/to a hidden volume). Any such data is encrypted and decrypted on the fly as usual (with an encryption key different from the one that will be used for the decoy operating system).\n\n\nPlease click Next to continue. - The outer volume has been created and mounted as drive %hc:. To this outer volume you should now copy some sensitive-looking files that you actually do NOT want to hide. They will be there for anyone forcing you to disclose the password for the first partition behind the system partition, where both the outer volume and the hidden volume (containing the hidden operating system) will reside. You will be able to reveal the password for this outer volume, and the existence of the hidden volume (and of the hidden operating system) will remain secret.\n\nIMPORTANT: The files you copy to the outer volume should not occupy more than %s. Otherwise, there may not be enough free space on the outer volume for the hidden volume (and you will not be able to continue). After you finish copying, click Next (do not dismount the volume). - Outer volume has been successfully created and mounted as drive %hc:. To this volume you should now copy some sensitive-looking files that you actually do NOT want to hide. The files will be there for anyone forcing you to disclose your password. You will reveal only the password for this outer volume, not for the hidden one. The files that you really care about will be stored in the hidden volume, which will be created later on. When you finish copying, click Next. Do not dismount the volume.\n\nNote: After you click Next, cluster bitmap of the outer volume will be scanned to determine the size of uninterrupted area of free space whose end is aligned with the end of the volume. This area will accommodate the hidden volume, so it will limit its maximum possible size. Cluster bitmap scanning ensures that no data on the outer volume are overwritten by the hidden volume. - Outer Volume Contents - \n\nIn the next steps, you will set the options for the outer volume (within which the hidden volume will be created later on). - \n\nIn the next steps, you will create a so-called outer TrueCrypt volume within the first partition behind the system partition (as was explained in one of the previous steps). - Outer Volume - In the following steps, you will set the options and password for the hidden volume, which will contain the hidden operating system.\n\nRemark: The cluster bitmap of the outer volume has been scanned in order to determine the size of uninterrupted area of free space whose end is aligned with the end of the outer volume. This area will accommodate the hidden volume, so it limits its maximum possible size. The maximum possible size of the hidden volume has been determined and confirmed to be greater than the size of the system partition (which is required, because the entire content of the system partition will need to be copied to the hidden volume). This ensures that no data currently stored on the outer volume will be overwritten by data written to the area of the hidden volume. - IMPORTANT: Please remember the algorithms that you select in this step. You will have to select the same algorithms for the decoy system. Otherwise, the hidden system will be inaccessible! (The decoy system must be encrypted with the same encryption algorithm as the hidden system.)\n\nNote: The reason is that the decoy system and the hidden system will share a single boot loader, which supports only a single algorithm, selected by the user (for each algorithm, there is a special version of the TrueCrypt Boot Loader). - \n\nThe volume cluster bitmap has been scanned and the maximum possible size of the hidden volume has been determined. In the next steps you will set the options, the size, and the password for the hidden volume. - Hidden Volume - The hidden volume is now protected against damage until the outer volume is dismounted.\n\nWARNING: If any data is attempted to be saved to the hidden volume area, TrueCrypt will start write-protecting the entire volume (both the outer and the hidden part) until it is dismounted. This may cause filesystem corruption on the outer volume, which (if repeated) might adversely affect plausible deniability of the hidden volume. Therefore, you should make every effort to avoid writing to the hidden volume area. Any data being saved to the hidden volume area will not be saved and will be lost. Windows may report this as a write error ("Delayed Write Failed" or "The parameter is incorrect"). - Each of the hidden volumes within the newly mounted volumes is now protected against damage until dismounted.\n\nWARNING: If any data is attempted to be saved to protected hidden volume area of any of these volumes, TrueCrypt will start write-protecting the entire volume (both the outer and the hidden part) until it is dismounted. This may cause filesystem corruption on the outer volume, which (if repeated) might adversely affect plausible deniability of the hidden volume. Therefore, you should make every effort to avoid writing to the hidden volume area. Any data being saved to protected hidden volume areas will not be saved and will be lost. Windows may report this as a write error ("Delayed Write Failed" or "The parameter is incorrect"). - WARNING: Data were attempted to be saved to the hidden volume area of the volume mounted as %c:! TrueCrypt prevented these data from being saved in order to protect the hidden volume. This may have caused filesystem corruption on the outer volume and Windows may have reported a write error ("Delayed Write Failed" or "The parameter is incorrect"). The entire volume (both the outer and the hidden part) will be write-protected until it is dismounted. If this is not the first time TrueCrypt has prevented data from being saved to the hidden volume area of this volume, plausible deniability of this hidden volume might be adversely affected (due to possible unusual correlated inconsistencies within the outer volume file system). Therefore, you should consider creating a new TrueCrypt volume (with Quick Format disabled) and moving files from this volume to the new volume; this volume should be securely erased (both the outer and the hidden part). We strongly recommend that you restart the operating system now. - For security reasons, when a hidden operating system is running, you can create only hidden TrueCrypt volumes. - For security reasons, when a hidden operating system is running, hidden volumes can be created only in the 'direct' mode (because outer volumes must always be mounted as read-only).\n\nTo create a hidden volume securely, follow these steps:\n\n1) Boot the decoy system.\n\n2) Create a normal TrueCrypt volume and, to this volume, copy some sensitive-looking files that you actually do NOT want to hide (the volume will become the outer volume).\n\n3) Boot the hidden system and start the TrueCrypt Volume Creation Wizard.\n\n4) If the volume is file-hosted, move it to the system partition or to another hidden volume (otherwise, the newly created hidden volume would be mounted as read-only and could not be formatted).\n\n5) Follow the instructions in the wizard so as to select the 'direct' hidden volume creation mode.\n\n6) In the wizard, select the volume you created in step 2 and then follow the instructions to create a hidden volume within it. - For security reasons, when a hidden operating system is running, local unencrypted filesystems and non-hidden TrueCrypt volumes are mounted as read-only (no data can be written to such filesystems or TrueCrypt volumes).\n\nData is allowed to be written to any filesystem that resides within a hidden TrueCrypt volume (provided that the hidden volume is not located in a container stored on an unencrypted filesystem or on any other read-only filesystem). - There are three main reasons why such countermeasures have been implemented:\n\n- It enables the creation of a secure platform for mounting of hidden TrueCrypt volumes. Note that we officially recommend that hidden volumes are mounted only when a hidden operating system is running. (For more information, see the subsection 'Security Precautions Pertaining to Hidden Volumes' in the documentation.)\n\n- In some cases, it is possible to determine that, at a certain time, a particular filesystem was not mounted under (or that a particular file on the filesystem was not saved or accessed from within) a particular instance of an operating system (e.g. by analyzing and comparing filesystem journals, file timestamps, application logs, error logs, etc). This might indicate that a hidden operating system is installed on the computer. The countermeasures prevent these issues.\n\n- It protects the integrity of a filesystem that is mounted under both the decoy system and the hidden system when one or both of the systems are/is hibernated. - Note: If you need to securely transfer files from the decoy system to the hidden system, follow these steps:\n1) Start the decoy system.\n2) Save the files to an unencrypted volume or to an outer/normal TrueCrypt volume.\n3) Start the hidden system.\n4) If you saved the files to a TrueCrypt volume, mount it (it will be automatically mounted as read-only).\n5) Copy the files to the hidden system partition or to another hidden volume. - Your computer must be restarted.\n\nDo you want to restart it now? - Installation can be completed only after your computer is restarted.\n\nNote that, for security reasons, this installation wizard cannot be closed until the computer is restarted.\n\nDo you want to restart the computer now? - An error occurred when obtaining the system encryption status. - Cannot initialize application components for system encryption. - Unable to initialize the application. Failed to create a required mutex object. - Failed to initialize the random number generator! - Unable to initialize the application. Failed to register the Dialog class. - Error: Failed to load the Rich Edit system library. - TrueCrypt Volume Creation Wizard - Maximum possible hidden volume size for this volume is %.2f bytes. - Maximum possible hidden volume size for this volume is %.2f KB. - Maximum possible hidden volume size for this volume is %.2f MB. - Maximum possible hidden volume size for this volume is %.2f GB. - Volume password/keyfiles cannot be changed while the volume is mounted. Please dismount the volume first. - The header key derivation algorithm cannot be changed while the volume is mounted. Please dismount the volume first. - &Mount - A newer version of TrueCrypt is required to mount this volume. - Error: Volume Creation Wizard not found.\n\nPlease make sure that the file 'TrueCrypt Format.exe' is in the folder from which 'TrueCrypt.exe' was launched. If it is not, please reinstall TrueCrypt, or locate 'TrueCrypt Format.exe' on your disk and run it. - &Next > - &Finish - Restart - &Install - E&xtract - Unable to connect to the TrueCrypt device driver. TrueCrypt cannot work if the device driver is not running.\n\nPlease note that, due to a Windows issue, it may be necessary to log off or restart the system before the device driver can be loaded. - Error occurred when loading/preparing fonts. - The drive letter was not found or no drive letter was specified. - Drive letter not available. - No file selected! - No drive letters available. - No free drive letter for the outer volume! Volume creation cannot continue. - Could not determine your operating system version or you are using an unsupported operating system. - No path selected! - Not enough free space for the hidden volume! Volume creation cannot continue. - Error: The files you copied to the outer volume occupy too much space. Therefore, there is not enough free space on the outer volume for the hidden volume.\n\nNote that the hidden volume must be as large as the system partition (the partition where the currently running operating system is installed). The reason is that the hidden operating system needs to be created by copying the content of the system partition to the hidden volume.\n\n\nThe process of creation of the hidden operating system cannot continue. - The driver is unable to dismount the volume. Some files located on the volume are probably still open. - Unable to lock the volume. There are still open files on the volume. Therefore, it cannot be dismounted. - TrueCrypt cannot lock the volume because it is in use by the system or applications (there may be open files on the volume).\n\nDo you want to force dismount on the volume? - Select a TrueCrypt Volume - Specify Path and File Name - Select Path - Select PKCS #11 Library - Out of Memory - IMPORTANT: We strongly recommend that inexperienced users create a TrueCrypt file container on the selected device/partition, instead of attempting to encrypt the entire device/partition.\n\nWhen you create a TrueCrypt file container (as opposed to encrypting a device or partition) there is, for example, no risk of destroying a large number of files. Note that a TrueCrypt file container (even though it contains a virtual encrypted disk) is actually just like any normal file. Therefore, it can be, for example, easily renamed, moved, or copied as any normal file. For more information, see the chapter Beginner's Tutorial in the TrueCrypt User Guide.\n\nAre you sure you want to encrypt the entire device/partition? - WARNING: The file '%hs' already exists!\n\nIMPORTANT: TRUECRYPT WILL NOT ENCRYPT THE FILE, BUT IT WILL DELETE IT. Are you sure you want to delete the file and replace it with a new TrueCrypt container? - CAUTION: ALL FILES CURRENTLY STORED ON THE SELECTED %s '%hs'%s WILL BE ERASED AND LOST (THEY WILL NOT BE ENCRYPTED)!\n\nAre you sure you want to proceed with format? - WARNING: You will not be able to mount the volume or access any files stored on it until it has been fully encrypted.\n\nAre you sure you want to start encrypting the selected %s '%hs'%s? - WARNING: Please note that if power supply is suddenly interrupted while encrypting existing data in place, or when the operating system crashes due to a software error or hardware malfunction while TrueCrypt is encrypting existing data in place, portions of the data will be corrupted or lost. Therefore, before you start encrypting, please make sure that you have backup copies of the files you want to encrypt.\n\nDo you have such a backup? - CAUTION: ANY FILES CURRENTLY STORED ON THE PARTITION '%hs'%s (I.E. ON THE FIRST PARTITION BEHIND THE SYSTEM PARTITION) WILL BE ERASED AND LOST (THEY WILL NOT BE ENCRYPTED)!\n\nAre you sure you want to proceed with format? - WARNING: THE SELECTED PARTITION CONTAINS A LARGE AMOUNT OF DATA! Any files stored on the partition will be erased and lost (they will NOT be encrypted)! - Erase any files stored on the partition by creating a TrueCrypt volume within it - Password - Password and/or keyfile(s) successfully changed.\n\nIMPORTANT: Please make sure you have read the section 'Changing Passwords and Keyfiles' in the chapter 'Security Precautions' in the TrueCrypt User Guide. - IMPORTANT: If you did not destroy your TrueCrypt Rescue Disk, your system partition/drive can still be decrypted using the old password (by booting the TrueCrypt Rescue Disk and entering the old password). You should create a new TrueCrypt Rescue Disk and then destroy the old one.\n\nDo you want to create a new TrueCrypt Rescue Disk? - Note that your TrueCrypt Rescue Disk still uses the previous algorithm. If you consider the previous algorithm insecure, you should create a new TrueCrypt Rescue Disk and then destroy the old one.\n\nDo you want to create a new TrueCrypt Rescue Disk? - Any kind of file (for example, .mp3, .jpg, .zip, .avi) may be used as a TrueCrypt keyfile. Note that TrueCrypt never modifies the keyfile contents. You can select more than one keyfile (the order does not matter). If you add a folder, all files found in it will be used as keyfiles. Click 'Add Token Files' to select keyfiles stored on security tokens or smart cards (or to import keyfiles to security tokens or smart cards). - Keyfile(s) successfully added/removed. - Keyfile exported. - Header key derivation algorithm successfully set. - Please enter the password and/or keyfile(s) for the non-system volume where you want to resume the process of in-place encryption.\n\n\nRemark: After you click Next, TrueCrypt will attempt to find all non-system volumes where the process of encryption has been interrupted and where the TrueCrypt volume header can be decrypted using the supplied password and/or keyfile(s). If more than one such volume is found, you will need to select one of them in the next step. - Please select one of the listed volumes. The list contains every accessible non-system volume where the process of encryption has been interrupted and whose header could be decrypted using the supplied password and/or keyfile(s). - It is very important that you choose a good password. You should avoid choosing one that contains only a single word that can be found in a dictionary (or a combination of 2, 3, or 4 such words). It should not contain any names or dates of birth. It should not be easy to guess. A good password is a random combination of upper and lower case letters, numbers, and special characters, such as @ ^ = $ * + etc. We recommend choosing a password consisting of more than 20 characters (the longer, the better). The maximum possible length is 64 characters. - Please choose a password for the hidden volume. - Please choose a password for the hidden operating system (i.e. for the hidden volume). - IMPORTANT: The password that you choose for the hidden operating system in this step must be substantially different from the other two passwords (i.e. from the password for the outer volume and from the password for the decoy operating system). - Please enter the password for the volume within which you wish to create a hidden volume.\n\nAfter you click Next, TrueCrypt will attempt to mount the volume. As soon as the volume is mounted, its cluster bitmap will be scanned to determine the size of the uninterrupted area of free space (if there is any) whose end is aligned with the end of the volume. This area will accommodate the hidden volume and therefore will limit its maximum possible size. Cluster map scanning is necessary to ensure that no data on the outer volume will be overwritten by the hidden volume. - \nPlease choose a password for the outer volume. This will be the password that you will be able to reveal to an adversary if you are asked or forced to do so.\n\nIMPORTANT: The password must be substantially different from the one you will choose for the hidden volume.\n\nNote: The maximum possible password length is 64 characters. - Please choose a password for the outer volume. This will be the password you will be able to reveal to anyone forcing you to disclose the password for the first partition behind the system partition, where both the outer volume and the hidden volume (containing the hidden operating system) will reside. The existence of the hidden volume (and of the hidden operating system) will remain secret. Note that this password is not for the decoy operating system.\n\nIMPORTANT: The password must be substantially different from the one you will choose for the hidden volume (i.e. for the hidden operating system). - Outer Volume Password - Hidden Volume Password - Password for Hidden Operating System - WARNING: Short passwords are easy to crack using brute force techniques!\n\nWe recommend choosing a password consisting of more than 20 characters. Are you sure you want to use a short password? - Volume Password - Incorrect password or not a TrueCrypt volume. - Incorrect keyfile(s) and/or password or not a TrueCrypt volume. - Wrong mount mode, incorrect password, or not a TrueCrypt volume. - Wrong mount mode, incorrect keyfile(s) and/or password, or not a TrueCrypt volume. - Incorrect password or no TrueCrypt volume found. - Incorrect keyfile(s)/password or no TrueCrypt volume found. - \n\nWarning: Caps Lock is on. This may cause you to enter your password incorrectly. - If you are attempting to protect a hidden volume containing a hidden system, please make sure you are using the standard US keyboard layout when typing the password for the hidden volume. This is required due to the fact that the password needs to be typed in the pre-boot environment (before Windows starts) where non-US Windows keyboard layouts are not available. - TrueCrypt has not found any volume where non-system encryption has been interrupted and where the volume header can be decrypted using the supplied password and/or keyfile(s).\n\nPlease make sure the password and/or keyfile(s) are correct and that the partition/volume is not being used by the system or applications (including antivirus software). - \n\nNote: If you are attempting to mount a partition located on an encrypted system drive without pre-boot authentication or to mount the encrypted system partition of an operating system that is not running, you can do so by selecting 'System' > 'Mount Without Pre-Boot Authentication'. - In this mode, you cannot mount a partition located on a drive whose portion is within the key scope of active system encryption.\n\nBefore you can mount this partition in this mode, you need to either boot an operating system installed on a different drive (encrypted or unencrypted) or boot an unencrypted operating system. - < &Back - Unable to list raw devices installed on your system! - The volume '%hs' exists, and is read-only. Are you sure you want to replace it? - Select destination directory - Select Keyfile - Select a keyfile search path. WARNING: Note that only the path will be remembered, not the filenames! - 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. - WARNING: Failed to restore container timestamp (file modification/access date/time)!\n\nThe plausible deniability of the hidden volume might be affected. - WARNING: Failed to restore container timestamp!\n\nIf you do not reset the timestamp using an external tool, we recommend that you do not create a hidden volume within this container. - WARNING: Failed to restore container timestamp (file modification/access date/time)!\n\nIf there is a hidden volume within this container, the plausible deniability of the hidden volume might be affected. - WARNING: Failed to restore keyfile timestamp! Cannot preserve last access date/time.\n\nIt will be possible to tell that this file has been accessed. - 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 275 KB. The minimum possible size of an NTFS volume is 2829 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 305 KB. - Please specify the size of the hidden volume to create. The minimum possible size of a hidden volume is 23 KB (or 2701 KB if it is formatted as NTFS). The maximum possible size you can specify for the hidden volume is displayed above. - Outer Volume Size - Hidden Volume Size - Please verify that the size of the selected device/partition shown above is correct and click Next. - The outer volume and the hidden volume (containing the hidden operating system) will reside within the above partition. It should be the first partition behind the system partition.\n\nPlease verify that the size of the partition and its number shown above are correct, and if they are, click Next. - \n\nNote that the minimum possible size of a volume within which a hidden volume is intended to be created is 305 KB. - Volume Size - Dynamic - CAUTION: SELF-TEST FAILED! - Self-tests of all algorithms passed - The data unit number that you supplied is too long or short. - The secondary key that you supplied is too long or short. - The test ciphertext you have supplied is too long or short. - The test key you have supplied is too long or short. - The test plaintext you have supplied is too long or short. - Two ciphers in a cascade operating in XTS mode. Each block is first encrypted with %hs (%d-bit key) and then with %hs (%d-bit key). Each cipher uses its own key. All keys are mutually independent. - Three ciphers in a cascade operating in XTS mode. Each block is first encrypted with %hs (%d-bit key), then with %hs (%d-bit key), and finally with %hs (%d-bit key). Each cipher uses its own key. All keys are mutually independent. - Note that, depending on the operating system configuration, these auto-run and auto-mount features may work only when the traveler disk files are created on a non-writable CD/DVD-like medium. Also note that this is not a bug in TrueCrypt (it is a limitation of Windows). - TrueCrypt traveler disk has been successfully created.\n\nNote that you need administrator privileges to run TrueCrypt in traveler mode. Also note that, after examining the registry file, it may be possible to tell that TrueCrypt was run on a Windows system even if it is run in traveler mode. - TrueCrypt Traveler Disk - Designed by Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson. Published in 1998. 256-bit key, 128-bit block. Mode of operation is XTS. Twofish was one of the AES finalists. - More information on %hs - Unknown - An unspecified or unknown error occurred. - The device driver returned an unrecognized error, code = %d - Some volumes contain files or folders being used by applications or system.\n\nForce dismount? - &Dismount - Dismount failed! - Volume contains files or folders being used by applications or system.\n\nForce dismount? - The volume you are trying to mount is already mounted. - The format of this volume not recognized. The volume might be corrupted. - An error occurred when attempting to mount volume. - Error seeking location within volume. - Error: Incorrect volume size. - The volume is too small - it is an invalid volume. - WARNING: You should use Quick Format only in the following cases:\n\n1) The device contains random data (e.g. has already been securely and fully encrypted).\n2) You are going to use all available space immediately.\n3) You are not concerned with security (testing).\n\nAre you sure you want to use Quick Format? - Dynamic container is a pre-allocated NTFS sparse file whose physical size (actual disk space used) grows as new data is added to it.\n\nWARNING: Performance of sparse-file-hosted volumes is significantly worse than performance of regular volumes. Sparse-file-hosted volumes are also less secure, because it is possible to tell which volume sectors are unused. Furthermore, sparse-file-hosted volumes cannot provide plausible deniability (host a hidden volume). Also note that if data is written to a sparse file container when there is not enough free space in the host file system, the encrypted file system may get corrupted.\n\nAre you sure you want to create a sparse-file-hosted volume? - Note that the size of the dynamic container reported by Windows and by TrueCrypt will always be equal to its maximum size. To find out current physical size of the container (actual disk space it uses), right-click the container file (in a Windows Explorer window, not in TrueCrypt), then select 'Properties' and see the 'Size on disk' value. - Passwords stored in the device driver cache have been wiped. - TrueCrypt cannot change the password for a foreign volume. - Please select a free drive letter from the list. - Please select a mounted volume in the drive letter list. - Error: Cannot create autorun.inf - Error while processing keyfile! - Error processing keyfile path! - TrueCrypt does not support this operating system. - Error: TrueCrypt supports only stable (non-beta) versions of this operating system. - Error: Cannot allocate memory. - Error: Could not retrieve value of performance counter. - Error: Bad volume format. - Error: You supplied a password for a hidden volume (not for a normal volume). - For security reasons, a hidden volume cannot be created within a TrueCrypt volume containing a filesystem that has been encrypted in place (because the free space on the volume has not been filled with random data). - TrueCrypt - Legal Notices - All Files - TrueCrypt Volumes - Library Modules - NTFS formatting cannot continue. - Cannot mount volume. - Cannot dismount volume. - Windows failed to format the volume as NTFS.\n\nPlease select a different type of file system (if possible) and try again. Alternatively, you could leave the volume unformatted (select 'None' as the filesystem), exit this wizard, mount the volume, and then use either a system or a third-party tool to format the mounted volume (the volume will remain encrypted). - Windows failed to format the volume as NTFS.\n\nDo you want to format the volume as FAT instead? - Default - sector - block - Partition - partition - PARTITION - Device - device - DEVICE - Volume - volume - VOLUME - The selected cluster size is too small for this volume size. A greater cluster size will be used instead. - Error: Cannot get volume size!\n\nMake sure the selected volume is not being used by the system or an application. - Hidden volumes shall not be created within dynamic (sparse file) containers. To achieve plausible deniability, the hidden volume shall be created within a regular volume. - The TrueCrypt Volume Creation Wizard can create a hidden volume only within a FAT or NTFS volume. - Under Windows 2000, the TrueCrypt Volume Creation Wizard can create a hidden volume only within a FAT volume. - Note: The FAT file system is more suitable for outer volumes than the NTFS file system (for example, the maximum possible size of the hidden volume would very likely have been significantly greater if the outer volume had been formatted as FAT). - Note that the FAT file system is more suitable for outer volumes than the NTFS file system. For example, the maximum possible size of the hidden volume will very likely be significantly greater if the outer volume is formatted as FAT (the reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume can reside only in the second half of the outer volume).\n\nAre you sure you want to format the outer volume as NTFS? - Do you want to format the volume as FAT instead? - Error: The partition for the hidden operating system (i.e. the first partition behind the system partition) must be at least 5% larger than the system partition (the system partition is the one where the currently running operating system is installed). - Error: The partition for the hidden operating system (i.e. the first partition behind the system partition) must be at least 110% (2.1 times) larger than the system partition (the system partition is the one where the currently running operating system is installed). The reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume (which is to contain a clone of the system partition) can reside only in the second half of the partition. - Error: If the outer volume is formatted as NTFS, it must be at least 110% (2.1 times) larger than the system partition. The reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume (which is to contain a clone of the system partition) can reside only in the second half of the outer volume.\n\nNote: The outer volume needs to reside within the same partition as the hidden operating system (i.e. within the first partition behind the system partition). - Error: There is no partition behind the system partition.\n\nNote that before you can create a hidden operating system, you need to create a partition for it on the system drive. It must be the first partition behind the system partition and it must be at least 5% larger than the system partition (the system partition is the one where the currently running operating system is installed). However, if the outer volume (not to be confused with the system partition) is formatted as NTFS, the partition for the hidden operating system must be at least 110% (2.1 times) larger than the system partition (the reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume, which is to contain a clone of the system partition, can reside only in the second half of the partition). - Remark: It is not practical (and therefore is not supported) to install operating systems in two TrueCrypt volumes that are embedded within a single partition, because using the outer operating system would often require data to be written to the area of the hidden operating system (and if such write operations were prevented using the hidden volume protection feature, it would inherently cause system crashes, i.e. 'Blue Screen' errors). - For information on how to create and manage partitions, please refer to the documentation supplied with your operating system or contact your computer vendor's technical support team for assistance. - Error: The currently running operating system is not installed on the boot partition (first Active partition). This is not supported. - You indicated that you intend to store files larger than 4 GB in this TrueCrypt volume. However, you chose the FAT file system, on which files larger than 4 GB cannot be stored.\n\nAre you sure you want to format the outer volume as FAT? - Error: Cannot access the volume!\n\nMake sure that the selected volume exists, that it is not mounted or being used by the system or an application, that you have read/write permission for the volume, and that it is not write-protected. - Error: Cannot access the volume and/or obtain information about the volume.\n\nMake sure that the selected volume exists, that it is not being used by the system or applications, that you have read/write permission for the volume, and that it is not write-protected. - Error: Cannot access the volume and/or obtain information about the volume. Make sure that the selected volume exists, that it is not being used by the system or applications, that you have read/write permission for the volume, and that it is not write-protected.\n\nIf the problem persists, it might help to follow the below steps. - An error prevented TrueCrypt from encrypting the partition. Please try fixing any previously reported problems and then try again. If the problems persist, it might help to follow the below steps. - An error prevented TrueCrypt from resuming the process of encryption of the partition.\n\nPlease try fixing any previously reported problems and then try resuming the process again. Note that the volume cannot be mounted until it has been fully encrypted. - Error: Cannot dismount the outer volume!\n\nVolume cannot be dismounted if it contains files or folders being used by a program or the system.\n\nPlease close any program that might be using files or directories on the volume and click Retry. - Error: Cannot obtain information about the outer volume!\nVolume creation cannot continue. - Error: Cannot access the outer volume! Volume creation cannot continue. - Error: Cannot mount the outer volume! Volume creation cannot continue. - Error: Cannot get volume cluster bitmap! Volume creation cannot continue. - Alphabetical/Categorized - Mean Speed (Descending) - Algorithm - Encryption - Decryption - Mean - Drive - Size - Encryption Algorithm - Encryption algorithm - Type - Value - Property - Location - bytes - Hidden - Outer - Normal - System - System - Hidden (system) - Read-Only - Hidden Volume - System drive - System drive (encrypting - %.2f%% done) - System drive (decrypting - %.2f%% done) - System drive (%.2f%% encrypted) - System partition - Hidden system partition - System partition (encrypting - %.2f%% done) - System partition (decrypting - %.2f%% done) - System partition (%.2f%% encrypted) - Yes (damage prevented!) - None - Active - Primary Key Size - Secondary Key Size (XTS Mode) - Tweak Key Size (LRW Mode) - bits - Block Size - Mode - PKCS-5 PRF - PKCS-5 Iteration Count - Volume Created - Header Last Modified - (%I64d days ago) - Volume Format Version - Embedded Backup Header - First available - removable - Removable Disk - Harddisk - Unchanged - Wizard Mode - Select one of the modes. If you are not sure which to select, use the default mode. - Select this option if you want to install or update TrueCrypt on this system. - If you select this option, all files will be extracted from this package but nothing will be installed on the system. Do not select it if you intend to encrypt the system partition or system drive. Selecting this option can be useful, for example, if you want to run TrueCrypt in so-called traveler (portable) mode. TrueCrypt does not have to be installed on the operating system under which it is run. After all files are extracted, you can directly run the extracted file 'TrueCrypt.exe' (then TrueCrypt will run in traveler mode). You can also move the extracted files to other computers. - Setup Options - Here you can set various options to control the installation process. - Installing - Please wait while TrueCrypt is being installed. - TrueCrypt Installed - TrueCrypt has been successfully installed. You can click Finish and run TrueCrypt now. - TrueCrypt has been successfully installed. - Extraction Options - Here you can set various options to control the extraction process. - Please wait while files are being extracted. - Extraction Complete - All files have been successfully extracted to the destination location. - If the specified folder does not exist, it will be automatically created. - Do you want to view release notes for the current (latest stable) version of TrueCrypt? - If you have never used TrueCrypt before, we recommend that you read the chapter Beginner's Tutorial in the TrueCrypt User Guide. Do you want to view the tutorial? - Please select an action to perform from the following: - Repair/Reinstall - Uninstall - Please select installation directory - To successfully install/uninstall TrueCrypt, you must have administrator privileges. Do you want to continue? - TrueCrypt Installer is currently running on this system and performing or preparing installation or update of TrueCrypt. Before you proceed, please wait for it to finish or close it. If you cannot close it, please restart your computer before proceeding. - Installation failed. - Uninstallation failed. - This distribution package is damaged. Please try downloading it again (preferably from the official TrueCrypt website at www.truecrypt.org). - Cannot write file %hs - Extracting - Cannot read data from the package. - Cannot verify the integrity of this distribution package. - Extraction failed. - The installation has been rolled back. - TrueCrypt has been successfully installed. - TrueCrypt has been successfully updated. - TrueCrypt has been upgraded to a new version. Before you can start using it, your computer must be restarted.\n\nDo you want to restart it now? - TrueCrypt has been successfully uninstalled.\n\nClick 'Finish' to remove the TrueCrypt installer and the folder %hs. Note that the folder will not be removed if it contains any files that were not installed by the TrueCrypt installer or created by TrueCrypt. - Removing TrueCrypt registry entries - Adding registry entry - Removing application-specific data - Installing - Copying - Stopping - Removing - Service - Adding icon - Creating System Restore point - Failed to create System Restore point! - Updating boot loader - Failed to install '%hs'. %hs\nDo you want to continue installing? - Failed to uninstall '%hs'. %hs\nDo you want to continue uninstalling? - Installation completed. - The folder '%hs' could not be created - The TrueCrypt device driver cannot be unloaded.\n\nPlease close all open TrueCrypt windows first. If it does not help, please restart Windows and then try again. - All TrueCrypt volumes must be dismounted before installing or uninstalling TrueCrypt. - An obsolete version of TrueCrypt is currently installed on this system. It needs to be uninstalled before you can install this new version of TrueCrypt.\n\nAs soon as you close this message box, the uninstaller of the old version will be launched. After you uninstall the old version of TrueCrypt, run the installer of the new version of TrueCrypt again. - The installation of the registry entries has failed - The installation of the device driver has failed. Please restart Windows and then try installing TrueCrypt again. - Starting TrueCrypt device driver - Uninstallation of the device driver has failed. Please note that, due to a Windows issue, it may be necessary to log off or restart the system before the device driver can be uninstalled (or reinstalled). - Installing TrueCrypt device driver - Stopping TrueCrypt device driver - Uninstalling TrueCrypt device driver - Registration of the User Account Control support library failed. - Unregistration of the User Account Control support library failed. - Note that if you decide to run TrueCrypt in traveler mode (as opposed to running an installed copy of TrueCrypt), the system will ask you for permission to run TrueCrypt (UAC prompt) every time you attempt to run it.\n\nThe reason is that when you run TrueCrypt in traveler mode, TrueCrypt needs to load and start the TrueCrypt device driver. TrueCrypt needs a device driver to provide transparent on-the-fly encryption/decryption, and users without administrator privileges cannot start device drivers in Windows. Therefore, the system will ask you for permission to run TrueCrypt with administrator privileges (UAC prompt).\n\nNote that if you install TrueCrypt on the system (as opposed to running TrueCrypt in traveler mode), the system will NOT ask you for permission to run TrueCrypt (UAC prompt) every time you attempt to run it.\n\nAre you sure you want to extract the files? - Warning: This instance of the Volume Creation Wizard has administrator privileges.\n\nYour new volume may be created with permissions that will not allow you to write to the volume when it is mounted. If you want to avoid that, close this instance of the Volume Creation Wizard and launch a new one without administrator privileges.\n\nDo you want to close this instance of the Volume Creation Wizard? - Error: Cannot display license. - Outer(!) - days - hours - minutes - s - Open - Dismount - Show TrueCrypt - Hide TrueCrypt - Data Read since Mount - Data Written since Mount - Encrypted Portion - 100% (fully encrypted) - 0% (not encrypted) - %.3f%% - 100% - Waiting - Preparing - Resizing - Encrypting - Decrypting - Finalizing - Paused - Finished - Error - Favorite volumes saved. - Enter password for %hs - 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. - WARNING: The header of this volume is damaged! TrueCrypt 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. - For security reasons, you will have to enter the correct password (and/or supply the correct keyfiles) for the volume.\n\nNote: If the volume contains a hidden volume, you will have to enter the correct password (and/or supply the correct keyfiles) for the outer volume first. Afterwards, if you choose to back up the header of the hidden volume, you will have to enter the correct password (and/or supply the correct keyfiles) for the hidden volume. - Are you sure you want to create volume header backup for %hs?\n\nAfter you click Yes, you will prompted for a filename for the header backup.\n\nNote: Both the standard and the hidden volume headers will be re-encrypted using a new salt and stored in the backup file. If there is no hidden volume within this volume, the area reserved for the hidden volume header in the backup file will be filled with random data (to preserve plausible deniability). When restoring a volume header from the backup file, you will need to enter the correct password (and/or to supply the correct keyfiles) that was/were valid when the volume header backup was created. The password (and/or keyfiles) will also automatically determine the type of the volume header to restore, i.e. standard or hidden (note that TrueCrypt determines the type through the process of trial and error). - Are you sure you want to restore volume header of %hs?\n\nWARNING: Restoring a volume header also restores the volume password that was valid when the backup was created. Moreover, if keyfile(s) were/was necessary to mount the volume when the backup was created, the same keyfile(s) will be necessary to mount the volume again after the volume header is restored.\n\nAfter you click Yes, you will select the header backup file. - Does the volume contain a hidden volume? - The volume contains a hidden volume - The volume does not contain a hidden volume - Please select the type of volume header backup you want to use: - Restore the volume header from the backup embedded in the volume - Restore the volume header from an external backup file - The size of the volume header backup file is incorrect. - There is no backup header embedded in this volume (note that only volumes created by TrueCrypt 6.0 or later contain embedded backup headers). - You are attempting to back up the header of the system partition/drive. This is not allowed. Backup/restore operations pertaining to the system partition/drive can be performed only using the TrueCrypt Rescue Disk.\n\nDo you want to create a TrueCrypt Rescue Disk? - You are attempting to restore the header of a virtual TrueCrypt volume but you selected the system partition/drive. This is not allowed. Backup/restore operations pertaining to the system partition/drive can be performed only using the TrueCrypt Rescue Disk.\n\nDo you want to create a TrueCrypt Rescue Disk? - After you click OK, you will select a filename for the new TrueCrypt Rescue Disk ISO image and the location where you wish to place it. - The Rescue Disk image has been created and stored in this file:\n%hs\n\nNow you need to write (burn) the Rescue Disk to a CD or DVD.\n\nIMPORTANT: Note that the file must be written to the CD/DVD as an ISO disk image (not as an individual file). For information on how to do so, please refer to the documentation of your CD/DVD recording software.\n\nAfter you burn the Rescue Disk, select 'System' > 'Verify Rescue Disk' to verify that the Rescue Disk has been correctly burned. - Please insert your TrueCrypt Rescue Disk into your CD/DVD drive and click OK to verify it. - The TrueCrypt Rescue Disk has been successfully verified. - Cannot verify that the Rescue Disk has been correctly burned.\n\nIf you have burned the Rescue Disk, please eject and reinsert the CD/DVD; then try again. If this does not help, please try other CD/DVD recording software and/or medium.\n\nIf you attempted to verify a TrueCrypt Rescue Disk created for a different master key, password, salt, etc., please note that such Rescue Disk will always fail this verification. To create a new Rescue Disk fully compatible with your current configuration, select 'System' > 'Create Rescue Disk'. - Error creating TrueCrypt Rescue Disk. - TrueCrypt Rescue Disk cannot be created when a hidden operating system is running.\n\nTo create a TrueCrypt Rescue Disk, boot the decoy operating system and then select 'System' > 'Create Rescue Disk'. - Cannot verify that the Rescue Disk has been correctly burned.\n\nIf you have burned the Rescue Disk, please eject and reinsert the CD/DVD; then click Next to try again. If this does not help, please try other CD/DVD recording software and/or medium.\n\nIf you have not burned the Rescue Disk yet, please do so, and then click Next.\n\nIf you attempted to verify a TrueCrypt Rescue Disk created before you started this wizard, please note that such Rescue Disk cannot be used because it was created for a different master key. You need to burn the newly generated Rescue Disk. - Save all currently mounted volumes and their drive letters to the Favorite Volumes list?\n\nNote: If no volumes are mounted, the Favorite Volumes list will be deleted. - Please dismount the volume before proceeding. - Error: Cannot set timer. - Check Filesystem - Repair Filesystem - P&roperties - Hidden Volume Protected - N/A - Yes - No - 1 - 2 or more - Mode of Operation - Label: - Size: - Path: - Drive Letter: - Error: Password must contain only ASCII characters.\n\nNon-ASCII characters in password might cause the volume to be impossible to mount when your system configuration changes.\n\nThe following characters are allowed:\n\n ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \\ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w k y z { | } ~ - Warning: Password contains non-ASCII characters. This may cause the volume to be impossible to mount when your system configuration changes.\n\nYou should replace all non-ASCII characters in the password with ASCII characters. To do so, click 'Volumes' -> 'Change Volume Password'.\n\nThe following are ASCII characters:\n\n ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \\ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w k y z { | } ~ - WARNING: We strongly recommend that you avoid file extensions that are used for executable files (such as .exe, .sys, or .dll) and other similarly problematic file extensions. Using such file extensions causes Windows and antivirus software to interfere with the container, which adversely affects the performance of the volume and may also cause other serious problems.\n\nWe strongly recommend that you remove the file extension or change it (e.g., to '.tc').\n\nAre you sure you want to use the problematic file extension? - WARNING: This container has a file extension that is used for executable files (such as .exe, .sys, or .dll) or some other file extension that is similarly problematic. It will very likely cause Windows and antivirus software to interfere with the container, which will adversely affect the performance of the volume and may also cause other serious problems.\n\nWe strongly recommend that you remove the file extension of the container or change it (e.g., to '.tc') after you dismount the volume. - Homepage - WARNING: It appears that you have not applied any Service Pack to your Windows installation. You should not write to IDE disks larger than 128 GB under Windows XP to which you did not apply Service Pack 1 or later! If you do, data on the disk (no matter if it is a TrueCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in TrueCrypt. - WARNING: It appears that you have not applied Service Pack 3 or later to your Windows installation. You should not write to IDE disks larger than 128 GB under Windows 2000 to which you did not apply Service Pack 3 or later! If you do, data on the disk (no matter if it is a TrueCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in TrueCrypt.\n\nNote: You may also need to enable the 48-bit LBA support in the registry; for more information, see http://support.microsoft.com/kb/305098/EN-US - WARNING: 48-bit LBA ATAPI support is disabled on your system. Therefore, you should not write to IDE disks larger than 128 GB! If you do, data on the disk (no matter if it is a TrueCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a limitation of TrueCrypt.\n\nTo enable the 48-bit LBA support, add the 'EnableBigLba' registry value in the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\atapi\\Parameters and set it to 1.\n\nFor more information, see http://support.microsoft.com/kb/305098 - Error: Files larger than 4 GB cannot be stored on a FAT32 file system. Therefore, file-hosted TrueCrypt volumes (containers) stored on a FAT32 file system cannot be larger than 4 GB.\n\nIf you need a larger volume, create it on an NTFS file system (or, if you use Windows Vista SP1 or later, on an exFAT file system) or, instead of creating a file-hosted volume, encrypt an entire partition or device. - WARNING: If you want to be able to add more data/files to the outer volume in future, you should consider choosing a smaller size for the hidden volume.\n\nAre you sure you want to continue with the size you specified? - No volume selected.\n\nClick 'Select Device' or 'Select File' to select a TrueCrypt volume. - No partition selected.\n\nClick 'Select Device' to select a dismounted partition that normally requires pre-boot authentication (for example, a partition located on the encrypted system drive of another operating system, which is not running, or the encrypted system partition of another operating system).\n\nNote: The selected partition will be mounted as a regular TrueCrypt volume without pre-boot authentication. This is useful e.g. for backup or repair operations. - WARNING: If default keyfiles are set and enabled, volumes that are not using these keyfiles will be impossible to mount. Therefore, after you enable default keyfiles, keep in mind to uncheck the 'Use keyfiles' checkbox (below a password input field) whenever mounting such volumes.\n\nAre you sure you want to save the selected keyfiles/paths as default? - Auto-Mount Devices - Dismount All - Wipe Cache - Dismount All & Wipe Cache - Force Dismount All & Wipe Cache - Force Dismount All, Wipe Cache & Exit - Mount Favorite Volumes - Show/Hide Main TrueCrypt Window - (Click here and press a key) - Action - Shortcut - Error: This shortcut is reserved. Please choose a different shortcut. - Error: Shortcut already in use. - WARNING: One or more TrueCrypt system-wide hot keys will not work!\n\nPlease make sure that other applications and the operating system do not use the same shortcut(s) as TrueCrypt. - An error or incompatibility prevents TrueCrypt from encrypting the hibernation file. Therefore, hibernation has been prevented.\n\nNote: When a computer hibernates (or enters a power-saving mode), the content of its system memory is written to a hibernation storage file residing on the system drive. TrueCrypt would not be able to prevent encryption keys and the contents of sensitive files opened in RAM from being saved unencrypted to the hibernation storage file. - All mounted TrueCrypt volumes have been dismounted. - All mounted TrueCrypt volumes have been auto-dismounted.\n\nNote: You can disable or configure auto-dismount in the 'Auto-Dismount' section of the Preferences window (select Settings -> Preferences). - Attempt to dismount all mounted TrueCrypt volumes completed. - All mounted TrueCrypt volumes have been dismounted and password cache has been wiped. - WARNING: If timestamps are not preserved, plausible deniability of hidden volumes may be adversely affected!\n\nAre you sure you do not want container timestamps to be preserved? - WARNING: If the TrueCrypt Background Task is disabled, the following functions will be disabled whenever you exit TrueCrypt:\n\n1) Hot keys\n2) Auto-dismount (e.g., upon log off, inadvertent host device removal, time-out, etc.)\n3) Notifications (e.g., when damage to hidden volume is prevented)\n4) Tray icon\n\nNote: You may shut down the Background Task anytime by right-clicking the TrueCrypt tray icon and selecting 'Exit'.\n\nAre you sure you want to disable the TrueCrypt Background Task? - WARNING: If this option is disabled, volumes containing open files/directories will not be possible to auto-dismount.\n\nAre you sure you want to disable this option? - WARNING: Volumes containing open files/directories will NOT be auto-dismounted.\n\nTo prevent this, enable the following option in this dialog window: 'Force auto-dismount even if volume contains open files or directories' - WARNING: When the notebook battery power is low, Windows may omit sending the appropriate messages to running applications when the computer is entering power saving mode. Therefore, TrueCrypt may fail to auto-dismount volumes in such cases. - You have scheduled the process of encryption of a partition/volume. The process has not been completed yet.\n\nDo you want to resume the process now? - You have scheduled the process of encryption or decryption of the system partition/drive. The process has not been completed yet.\n\nDo you want to start (resume) the process now? - Do you want to be prompted about whether you want to resume the currently scheduled processes of encryption of non-system partitions/volumes? - Yes, keep prompting me - No, do not prompt me - IMPORTANT: Keep in mind that you can resume the process of encryption of any non-system partition/volume by selecting 'Volumes' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. - You have scheduled the process of encryption or decryption of the system partition/drive. However, pre-boot authentication failed (or was bypassed).\n\nNote: If you decrypted the system partition/drive in the pre-boot environment, you may need to finalize the process by selecting 'System' > 'Permanently Decrypt System Partition/Drive' from the menu bar of the main TrueCrypt window. - WARNING: If TrueCrypt exits now, the following functions will be disabled:\n\n1) Hot keys\n2) Auto-dismount (e.g., upon log off, inadvertent host device removal, time-out, etc.)\n3) Notifications (e.g., when damage to hidden volume is prevented)\n\nNote: If you do not wish TrueCrypt to run in the background, disable the TrueCrypt Background Task in the Preferences (and, if necessary, disable the automatic start of TrueCrypt in the Preferences).\n\nAre you sure you want TrueCrypt to exit? - Exit? - TrueCrypt does not have sufficient information to determine whether to encrypt or decrypt. - TrueCrypt does not have sufficient information to determine whether to encrypt or decrypt.\n\nNote: If you decrypted the system partition/drive in the pre-boot environment, you may need to finalize the process by clicking Decrypt. - Do you want to interrupt and postpone the process of encryption of the partition/volume?\n\nNote: Keep in mind that the volume cannot be mounted until it has been fully encrypted. You will be able to resume the process of encryption and it will continue from the point it was stopped. You can do so, for example, by selecting 'Volumes' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. - Do you want to interrupt and postpone the process of encryption of the system partition/drive?\n\nNote: You will be able to resume the process and it will continue from the point it was stopped. You can do so, for example, by selecting 'System' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. If you want to permanently terminate or reverse the encryption process, select 'System' > 'Permanently Decrypt System Partition/Drive'. - Do you want to interrupt and postpone the process of decryption of the system partition/drive?\n\nNote: You will be able to resume the process and it will continue from the point it was stopped. You can do so, for example, by selecting 'System' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. If you want to reverse the decryption process (and start encrypting), select 'System' > 'Encrypt System Partition/Drive'. - Error: Failed to interrupt the process of encryption/decryption of the system partition/drive. - Error: Failed to interrupt the process of wiping. - Error: Failed to resume the process of encryption/decryption of the system partition/drive. - Error: Failed to start the process of wiping. - Inconsistency resolved.\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n%hs) - Error: Unexpected state.\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n%hs) - There is no process/task to resume. - WARNING: TrueCrypt Background Task is disabled. After you exit TrueCrypt, you will not be notified if damage to hidden volume is prevented.\n\nNote: You may shut down the Background Task anytime by right-clicking the TrueCrypt tray icon and selecting 'Exit'.\n\nEnable TrueCrypt Background Task? - Language pack version: %s - Checking the file system on the TrueCrypt volume mounted as %hs... - Attempting to repair the file system on the TrueCrypt volume mounted as %hs... - Warning: This volume is encrypted in CBC mode. Due to security issues, CBC mode has been deprecated since TrueCrypt 4.1.\n\nWe strongly recommend that you move data from this TrueCrypt volume to a new volume created by this version of TrueCrypt. After you do so, you should securely erase or destroy the old volume. For more information, please see the Version History in the documentation or the release notices distributed with TrueCrypt 4.1 or later. - Warning: This volume is encrypted with a legacy encryption algorithm.\n\nAll 64-bit-block encryption algorithms (e.g., Blowfish, CAST-128, or Triple DES) are deprecated. It will be possible to mount this volume using future versions of TrueCrypt. However, there will be no further enhancements to the implementations of these legacy encryption algorithms. We recommend that you create a new TrueCrypt volume encrypted with a 128-bit-block encryption algorithm (e.g., AES, Serpent, Twofish, etc.) and that you move all files from this volume to the new volume. - Your system is not configured to auto-mount new volumes. It may be impossible to mount device-hosted TrueCrypt volumes. Auto-mounting can be enabled by executing the following command and restarting the system.\n\nmountvol.exe /E - Please assign a drive letter to the partition/device before proceeding ('Control Panel' > 'System and Maintenance' > 'Administrative Tools' - 'Create and format hard disk partitions').\n\nNote that this is a requirement of the operating system. - Mount TrueCrypt volume - Dismount all TrueCrypt volumes - TrueCrypt failed to obtain Administrator privileges. - Access was denied by the operating system.\n\nPossible cause: The operating system requires that you have read/write permission (or administrator privileges) for certain folders, files, and devices, in order for you to be allowed to read and write data to/from them. Normally, a user without administrator privileges is allowed to create, read and modify files in his or her Documents folder. - Error: The device uses a sector size other than 512 bytes.\n\nIt is currently not possible to create device-hosted volumes on devices that use a sector size other than 512 bytes. However, note that you can create a file-hosted volume (container) on this device. - Error: Unsupported sector size. - The TrueCrypt Boot Loader requires at least 32 KBytes of free space at the beginning of the system drive (the TrueCrypt Boot Loader needs to be stored in that area). Unfortunately, your drive does not meet this condition.\n\nPlease do NOT report this as a bug/problem in TrueCrypt. To solve this problem, you will need to repartition your disk and leave the first 32 KBytes of the disk free (in most cases, you will need to delete and recreate the first partition). We recommend that you use the Microsoft partition manager that is available e.g. when you are installing Windows. - The feature is not supported on the version of the operating system you are currently using. - TrueCrypt does not support encryption of a system partition/drive on the version of the operating system you are currently using. - Before you can encrypt the system partition/drive on Windows Vista, you need to install Service Pack 1 or higher for Windows Vista (no such Service Pack has been installed on this system yet).\n\nNote: Service Pack 1 for Windows Vista resolved an issue causing a shortage of free base memory during system boot. - Please note that Service Pack 1 for Windows Vista resolved an issue that caused a shortage of free base memory during system boot. TrueCrypt 6.2 and later versions have been designed to take advantage of this improvement. Therefore, we recommend you to install Service Pack 1 or higher before upgrading TrueCrypt.\n\nDo you want to upgrade TrueCrypt now? - Error: This feature requires TrueCrypt to be installed on the system (you are running TrueCrypt in traveler/portable mode).\n\nPlease install TrueCrypt and then try again. - Error: Windows is not installed on the drive from which it boots. This is not supported. - Your system drive has a GUID partition table (GPT). Currently, only drives with a MBR partition table are supported. - CAUTION: The TrueCrypt Boot Loader is already installed on your system drive!\n\nIt is possible that another system on your computer is already encrypted.\n\nWARNING: PROCEEDING WITH ENCRYPTION OF THE CURRENTLY RUNNING SYSTEM MAY MAKE OTHER SYSTEM(S) IMPOSSIBLE TO START AND RELATED DATA INACCESSIBLE.\n\nAre you sure you want to continue? - Failed to restore the original system loader.\n\nPlease use your TrueCrypt Rescue Disk ('Repair Options' > 'Restore original system loader') or Windows installation medium to replace the TrueCrypt Boot Loader with the Windows system loader. - The original system loader will not be stored on the Rescue Disk (probable cause: missing backup file). - Failed to write the MBR sector.\n\nYour BIOS may be configured to protect the MBR sector. Check your BIOS settings (press F2, Delete, or Esc, after powering on your computer) for MBR/antivirus protection. - The required version of the TrueCrypt Boot Loader is currently not installed. This may prevent some of the settings from being saved. - Note: In some situations, you may wish to prevent a person (adversary) that is watching you start the computer from knowing that you use TrueCrypt. The above options allow you to do that by customizing the TrueCrypt boot loader screen. If you enable the first option, no texts will be displayed by the boot loader (not even when you enter the wrong password). The computer will appear to be "frozen" while you can type your password. In addition, a custom message can be displayed to mislead the adversary. For example, fake error messages such as "Missing operating system" (which is normally displayed by the Windows boot loader if it finds no Windows boot partition). It is, however, important to note that if the adversary can analyze the content of the hard drive, he can still find out that it contains the TrueCrypt boot loader. - WARNING: Please keep in mind that if you enable this option, the TrueCrypt boot loader will not display any texts (not even when you enter the wrong password). The computer will appear to be "frozen" (unresponsive) while you can type your password (the cursor will NOT move and no asterisk will be displayed when you press a key).\n\nAre you sure you want to enable this option? - Your system partition/drive appears to be fully encrypted. - TrueCrypt does not support encrypting a system drive that has been converted to a dynamic disk. - The system drive contains extended (logical) partitions.\n\nYou can encrypt an entire system drive containing extended (logical) partitions only on Windows Vista (or later versions of Windows). On Windows XP, you can encrypt an entire system drive provided that it contains only primary partitions. - WARNING: As you are running Windows XP/2003, after you start encrypting the drive, you must NOT create any extended (logical) partitions on it (you may create only primary partitions). Any extended partition on the drive would be inaccessible after you start encrypting.\n\nNote: If this limitation is not acceptable, you can go back and choose to encrypt only the system partition instead of the entire drive (and, in addition to that, you can create partition-hosted TrueCrypt volumes within any non-system partitions on the drive).\n\nAlternatively, if this limitation is not acceptable, you may want to consider upgrading to Windows Vista or a later version of Windows (you can encrypt an entire system drive containing extended/logical partitions only on Windows Vista or later). - Do you want to encrypt the system partition instead of the entire drive?\n\nNote that you can create partition-hosted TrueCrypt volumes within any non-system partitions on the drive (in addition to encrypting the system partition). - As your system drive contains only a single partition that occupies the whole drive, it is preferable (more secure) to encrypt the entire drive including the free "slack" space that typically surrounds such a partition.\n\nDo you want to encrypt the entire system drive? - Your system is configured to store temporary files on a non-system partition.\n\nTemporary files may be stored only on the system partition. - Your user profile files are not stored on the system partition.\n\nUser profile files may be stored only on the system partition. - There is/are paging file(s) on non-system partitions.\n\nPaging files may be located only on the system partition. - Do you want to configure Windows to create paging files only on the Windows partition now?\n\nNote that if you click 'Yes', the computer will be restarted. Then start TrueCrypt and try creating the hidden OS again. - Otherwise, plausible deniability of the hidden operating system might be adversely affected.\n\nNote: If an adversary analyzed the content of such files (residing on a non-system partition), he might find out that you used this wizard in the hidden-system-creation mode (which might indicate the existence of a hidden operating system on your computer). Also note that any such files stored on the system partition will be securely erased by TrueCrypt during the process of creation of the hidden operating system. - WARNING: During the process of creation of the hidden operating system, you will be required to fully reinstall the currently running system (in order to create a decoy system securely).\n\nNote: The currently running operating system and the entire content of the system partition will be copied to the hidden volume (in order to create the hidden system).\n\n\nAre you sure you will be able to install Windows using a Windows Setup CD/DVD (or using a service partition)? - For security reasons, if the currently running operating system requires activation, it must be activated before proceeding. Note that the hidden operating system will be created by copying the content of the system partition to a hidden volume (so if this operating system is not activated, the hidden operating system will not be activated either). For more information, see the section "Security Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide.\n\nImportant: Before proceeding, please make sure you have read the section "Security Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide.\n\n\nDoes the currently running operating system meet the above condition? - Warning: There is unallocated space between the system partition and the first partition behind it. After you create the hidden operating system, you must not create any new partitions in that unallocated space. Otherwise, the hidden operating system will be impossible to boot (until you delete such newly created partitions). - This algorithm is currently not supported for system encryption. - Keyfiles are currently not supported for system encryption. - Warning: TrueCrypt could not restore the original keyboard layout. This may cause you to enter a password incorrectly. - Error: Cannot set the keyboard layout for TrueCrypt to the standard US keyboard layout.\n\nNote that the password needs to be typed in the pre-boot environment (before Windows starts) where non-US Windows keyboard layouts are not available. Therefore, the password must always be typed using the standard US keyboard layout. - As TrueCrypt temporarily changed the keyboard layout to the standard US keyboard layout, it is not possible to type characters by pressing keys while the right Alt key is held down. However, you can type most of such characters by pressing appropriate keys while the Shift key is held down. - TrueCrypt prevented change of keyboard layout. - Note: The password will need to be typed in the pre-boot environment (before Windows starts) where non-US Windows keyboard layouts are not available. Therefore, the password must always be typed using the standard US keyboard layout. However, it is important to note that you do NOT need a real US keyboard. TrueCrypt automatically ensures that you can safely type the password (right now and in the pre-boot environment) even if you do NOT have a real US keyboard. - Before you can encrypt the partition/drive, you must create a TrueCrypt Rescue Disk (TRD), which serves the following purposes:\n\n- If the TrueCrypt Boot Loader, master key, or other critical data gets damaged, the TRD allows you to restore it (note, however, that you will still have to enter the correct password then).\n\n- If the TrueCrypt Boot Loader gets damaged or infected with malware, you can avoid running it by booting directly from the TRD.\n\n- If Windows gets damaged and cannot start, the TRD allows you to permanently decrypt the partition/drive before Windows starts.\n\n- The TRD will contain a backup of the present content of the first drive track (which typically contains a system loader or boot manager) and will allow you to restore it if necessary. - The Rescue Disk image has been created and stored in this file:\n%hs\n\nNow you need to write (burn) the Rescue Disk to a CD or DVD.\n\nIMPORTANT: Note that the file must be written to the CD/DVD as an ISO disk image (not as an individual file). For information on how to do so, please refer to the documentation of your CD/DVD recording software. If you do not have any CD/DVD recording software that can write the ISO disk image to a CD/DVD, click the link below to download such free software.\n\nAfter you burn the Rescue Disk, click Next to verify that the Rescue Disk has been correctly burned. - The Rescue Disk image has been created and stored in this file:\n%hs\n\nNow you should either write (burn) the Rescue Disk to a CD/DVD or move the ISO image to a safe location for later use.\n\nIf you do not have any CD/DVD recording software that can write the ISO disk image to a CD/DVD, you can click the link below to download such free software.\n\nClick Next to continue. - WARNING: If you already created a TrueCrypt Rescue Disk in the past, it cannot be reused for this system partition/drive because it was created for a different master key! Every time you encrypt a system partition/drive, you must create a new TrueCrypt Rescue Disk for it even if you use the same password. - Error: Cannot save system encryption settings. - Cannot initiate the system encryption pretest. - Cannot initiate the process of creation of the hidden operating system. - Wipe Mode - On some types of storage media, when data is overwritten with other data, it may be possible to recover the overwritten data using techniques such as magnetic force microscopy. This also applies to data that are overwritten with their encrypted form (which happens when TrueCrypt initially encrypts an unencrypted partition or drive). According to some studies and governmental publications, recovery of overwritten data can be prevented (or made very difficult) by overwritting the data with pseudorandom and certain non-random data a certain number of times. Therefore, if you believe that an adversary might be able to use such techniques to recover the data you intend encrypt, you may want to select one of the wipe modes (existing data will NOT be lost). Note that wiping will NOT be performed after the partition/drive is encrypted. When the partition/drive is fully encrypted, no unencrypted data is written to it. Any data being written to it is first encrypted on the fly in memory and only then is the (encrypted) data written to the disk. - On some types of storage media, when data is overwritten with other data (e.g. when the data is erased), it may be possible to recover the overwritten data using techniques such as magnetic force microscopy. According to some studies and governmental publications, recovery of overwritten data can be prevented (or made very difficult) by overwritting the data with pseudorandom and certain non-random data a certain number of times. Therefore, if you believe that an adversary might be able to use such techniques to recover the data that is to be erased, you may want to select one of the multi-pass wipe modes.\n\nNote: The more wipe passes you use, the longer it takes to erase the data. - Wiping - \nNote: You can interrupt the process of wiping, shut down your computer, start the hidden system again and then resume the process (this wizard will be launched automatically). However, if you interrupt it, the entire process of wiping will have to start from the beginning. - \n\nNote: If you interrupt the process of wiping and then attempt to resume it, the entire process will have to start from the beginning. - Do you want to abort the process of wiping? - Warning: The entire content of the selected partition/device will be erased and lost. - The entire content of the partition where the original system resides will be erased.\n\nNote: The entire content of the partition that is to be erased has been copied to this hidden system partition. - WARNING: Note that when you choose e.g. the 3-pass wipe mode, the time necessary to encrypt the partition/drive will be up to 4 times longer. Likewise, if you choose the 35-pass wipe mode, it will be up to 36 times longer (it might even take several weeks).\n\nHowever, please note that wiping will NOT be performed after the partition/drive is fully encrypted. When the partition/drive is fully encrypted, no unencrypted data is written to it. Any data being written to it is first encrypted on the fly in memory and only then is the (encrypted) data written to the disk (so the performance will NOT be affected).\n\nAre you sure you want to use the wipe mode? - None (fastest) - 1-pass (random data) - 3-pass (US DoD 5220.22-M) - 7-pass (US DoD 5220.22-M) - 35-pass ("Gutmann") - Number of Operating Systems - WARNING: Inexperienced users should never attempt to encrypt Windows in multi-boot configurations.\n\nContinue? - Boot Drive - Is the currently running operating system installed on the boot drive?\n\nNote: Sometimes, Windows is not installed on the same drive as the Windows boot loader (boot partition). If that is the case, select 'No'. - TrueCrypt currently does not support encrypting an operating system that does not boot from the drive on which it is installed. - Number of System Drives - How many drives contain an operating system?\n\nNote: For example, if you have any operating system (e.g. Windows, Mac OS X, Linux, etc.) installed on your primary drive and any additional operating system installed on your secondary drive, select '2 or more'. - TrueCrypt currently does not support encrypting a whole drive that contains multiple operating systems.\n\nPossible Solutions:\n\n- You can still encrypt one of the systems if you go back and choose to encrypt only a single system partition (as opposed to choosing to encrypt the entire system drive).\n\n- Alternatively, you will be able to encrypt the entire drive if you move some of the systems to other drives leaving only one system on the drive you want to encrypt. - Multiple Systems on Single Drive - Are there any other operating systems installed on the drive on which the currently running operating system is installed?\n\nNote: For example, if the currently running operating system is installed on the drive #0, which contains several partitions, and if one of the partitions contains Windows and another partition contains any additional operating system (e.g. Windows, Mac OS X, Linux, etc.), select 'Yes'. - Non-Windows Boot Loader - Is a non-Windows boot loader (or boot manager) installed in the master boot record (MBR)?\n\nNote: For example, if the first track of the boot drive contains GRUB, LILO, XOSL, or some other non-Windows boot manager (or boot loader), select 'Yes'. - Multi-Boot - TrueCrypt currently does not support multi-boot configurations where a non-Windows boot loader is installed in the Master Boot Record.\n\nPossible Solutions:\n\n- If you use a boot manager to boot Windows and Linux, move the boot manager (typically, GRUB) from the Master Boot Record to a partition. Then start this wizard again and encrypt the system partition/drive. Note that the TrueCrypt Boot Loader will become your primary boot manager and it will allow you to launch the original boot manager (e.g. GRUB) as your secondary boot manager (by pressing Esc in the TrueCrypt Boot Loader screen) and thus you will be able boot Linux. - If the currently running operating system is installed on the boot partition, then, after you encrypt it, you will need to enter the correct password even if you want to start any other unencrypted Windows system(s) (as they will share a single encrypted Windows boot loader/manager).\n\nIn contrast, if the currently running operating system is not installed on the boot partition (or if the Windows boot loader/manager is not used by any other system), then, after you encrypt this system, you will not need to enter the correct password to boot the other unencrypted system(s) -- you will only need to press the Esc key to start the unencrypted system (if there are multiple unencrypted systems, you will also need to choose which system to start in the TrueCrypt Boot Manager menu).\n\nNote: Typically, the earliest installed Windows system is installed on the boot partition. - If there are any Windows Vista operating systems in your multi-boot configuration, please make sure they have been upgraded to Service Pack 1 or higher. TrueCrypt Boot Loader might fail to boot Windows Vista with no Service Pack installed.\n\nPlease note that Service Pack 1 for Windows Vista resolved an issue causing a shortage of free base memory during system boot. - Encryption of Host Protected Area - At the end of many drives, there is an area that is normally hidden from the operating system (such areas are usually referred to as Host Protected Areas). However, some programs can read and write data from/to such areas.\n\nWARNING: Some computer manufacturers may use such areas to store tools and data for RAID, system recovery, system setup, diagnostic, or other purposes. If such tools or data must be accessible before booting, the hidden area should NOT be encrypted (choose 'No' above).\n\nDo you want TrueCrypt to detect and encrypt such a hidden area (if any) at the end of the system drive? - Type of System Encryption - Select this option if you merely want to encrypt the system partition or the entire system drive. - It may happen that you are forced by somebody to decrypt the operating system. There are many situations where you cannot refuse to do so (for example, due to extortion). If you select this option, you will create a hidden operating system whose existence will be impossible to prove (provided that certain guidelines are followed). Thus, you will not have to decrypt or reveal the password to the hidden operating system. For a detailed explanation, please click the link below. - It may happen that you are forced by somebody to decrypt the operating system. There are many situations where you cannot refuse to do so (for example, due to extortion).\n\nUsing this wizard, you can create a hidden operating system whose existence will be impossible to prove (provided that certain guidelines are followed). Thus, you will not have to decrypt or reveal the password for the hidden operating system. - Hidden Operating System - In the following steps, you will create two TrueCrypt volumes (outer and hidden) within the first partition behind the system partition. The hidden volume will contain the hidden operating system (OS). TrueCrypt will create the hidden OS by copying the content of the system partition (where the currently running OS is installed) to the hidden volume. To the outer volume, you will copy some sensitive looking files that you actually do NOT want to hide. They will be there for anyone forcing you to disclose the password for the hidden OS partition. You can reveal the password for the outer volume within the hidden OS partition (the existence of the hidden OS remains secret).\n\nFinally, on the system partition of the currently running OS, you will install a new OS, so-called decoy OS, and encrypt it. It must not contain sensitive data and will be there for anyone forcing you to reveal your pre-boot authentication password. In total, there will be three passwords. Two of them can be disclosed (for the decoy OS and outer volume). If you use the third one, the hidden OS will start. - Detecting Hidden Sectors - Please wait while TrueCrypt is detecting possible hidden sectors at the end of the system drive. Note that it may take a long time to complete.\n\nNote: In very rare cases, on some computers, the system may become unresponsive during this detection process. If it happens, restart the computer, start TrueCrypt, repeat the previous steps but skip this detection process. Note that this issue is not caused by a bug in TrueCrypt. - Area to Encrypt - Select this option if you want to encrypt the entire drive on which your Windows is installed and from which it boots. The whole drive, including all its partitions, will be encrypted except the first track where the TrueCrypt Boot Loader will reside. Anyone who wants to access a system installed on the drive, or files stored on the drive, will need to enter the correct password each time before the system starts. This option cannot be used to encrypt a secondary or external drive if Windows is not installed on it and does not boot from it. - Collecting Random Data - Keys Generated - Rescue Disk Recording - Rescue Disk Created - System Encryption Pretest - Rescue Disk Verified - \nThe TrueCrypt Rescue Disk has been successfully verified. Please remove it from the drive now and store it in a safe place.\n\nClick Next to continue. - WARNING: During the next steps, the TrueCrypt Rescue Disk must not be in the drive. Otherwise, it will not be possible to complete the steps correctly.\n\nPlease remove it from the drive now and store it in a safe place. Then click OK. - Warning: Due to technical limitations of the pre-boot environment, texts displayed by TrueCrypt in the pre-boot environment (i.e. before Windows starts) cannot be localized. The TrueCrypt Boot Loader user interface is completely in English.\n\nContinue? - Before encrypting your system partition or drive, TrueCrypt needs to verify that everything works correctly.\n\nAfter you click Test, all the necessary components (for example, the pre-boot authentication component, i.e. the TrueCrypt Boot Loader) will be installed and your computer will be restarted. Then you will have to enter your password in the TrueCrypt Boot Loader screen that will appear before Windows starts. After Windows starts, you will be automatically informed about the result of this pretest.\n\nThe following device will be modified: Drive #%d\n\n\nIf you click Cancel now, nothing will be installed and the pretest will not be performed. - IMPORTANT NOTES -- PLEASE READ OR PRINT (click 'Print'):\n\nNote that none of your files will be encrypted before you successfully restart your computer and start Windows. Thus, if anything fails, your data will NOT be lost. However, if something does go wrong, you might encounter difficulties in starting your Windows. Therefore, please read (and, if possible, print) the following guidelines on what to do if your Windows cannot start after you restart the computer.\n\nWhat to Do If Windows Cannot Start\n------------------------------------------------\n\nNote: These instructions are valid only if you have not started encrypting.\n\n- If Windows does not start after you enter the correct password (or if you repeatedly enter the correct password but TrueCrypt says that the password is incorrect), do not panic. Restart (power off and on) the computer, and in the TrueCrypt Boot Loader screen, press the Esc key on your keyboard (and if you have multiple systems, choose which to start). Then your Windows should start (provided that it is not encrypted) and TrueCrypt will automatically ask whether you want to uninstall the pre-boot authentication component. Note that the previous steps do NOT work if the system partition/drive is encrypted (nobody can start Windows or access encrypted data on the drive without the correct password even if he or she follows the previous steps).\n\n- If the previous steps do not help or if the TrueCrypt Boot Loader screen does not appear (before Windows starts), insert the TrueCrypt Rescue Disk into your CD/DVD drive and restart your computer. If the TrueCrypt Rescue Disk screen does not appear (or if you do not see the 'Repair Options' item in the 'Keyboard Controls' section of the TrueCrypt Rescue Disk screen), it is possible that your BIOS is configured to attempt to boot from hard drives before CD/DVD drives. If that is the case, restart your computer, press F2 or Delete (as soon as you see a BIOS start-up screen), and wait until a BIOS configuration screen appears. If no BIOS configuration screen appears, restart (reset) the computer again and start pressing F2 or Delete repeatedly as soon as you restart (reset) the computer. When a BIOS configuration screen appears, configure your BIOS to boot from the CD/DVD drive first (for information on how to do so, please refer to the documentation for your BIOS/motherboard or contact your computer vendor's technical support team for assistance). Then restart your computer. The TrueCrypt Rescue Disk screen should appear now. In the TrueCrypt Rescue Disk screen, select 'Repair Options' by pressing F8 on your keyboard. From the 'Repair Options' menu, select 'Restore original system loader'. Then remove the Rescue Disk from your CD/DVD drive and restart your computer. Your Windows should start normally (provided that it is not encrypted).\n\nNote that the previous steps do NOT work if the system partition/drive is encrypted (nobody can start Windows or access encrypted data on the drive without the correct password even if he or she follows the previous steps).\n\n\nNote that even if you lose your TrueCrypt Rescue Disk and an attacker finds it, he or she will NOT be able to decrypt the system partition or drive without the correct password. - Pretest Completed - The pretest has been successfully completed.\n\nWARNING: Please note that if power supply is suddenly interrupted while encrypting existing data in place, or when the operating system crashes due to a software error or hardware malfunction while TrueCrypt is encrypting existing data in place, portions of the data will be corrupted or lost. Therefore, before you start encrypting, please make sure that you have backup copies of the files you want to encrypt. If you do not, please back up the files now (you can click Defer, back up the files, then run TrueCrypt again anytime, and select 'System' > 'Resume Interrupted Process' to start encrypting).\n\nWhen ready, click Encrypt to start encrypting. - You can click Pause or Defer anytime to interrupt the process of encryption or decryption, exit this wizard, restart or shut down your computer, and then resume the process, which will continue from the point it was stopped. To prevent slowdown when the system or applications write or read data from the system drive, TrueCrypt automatically waits until the data are written or read (see Status above) and then automatically continues encrypting or decrypting. - \n\nYou can click Pause or Defer anytime to interrupt the process of encryption, exit this wizard, restart or shut down your computer, and then resume the process, which will continue from the point it was stopped. Note that the volume cannot be mounted until it has been fully encrypted. - Hidden System Started - Original System - Windows creates (typically, without your knowledge or consent) various log files, temporary files, etc., on the system partition. It also saves the content of RAM to hibernation and paging files located on the system partition. Therefore, if an adversary analyzed files stored on the partition where the original system (of which the hidden system is a clone) resides, he might find out, for example, that you used the TrueCrypt wizard in the hidden-system-creation mode (which might indicate the existence of a hidden operating system on your computer).\n\nTo prevent such issues, TrueCrypt will, in the next steps, securely erase the entire content of the partition where the original system resides. Afterwards, in order to achieve plausible deniability, you will need to install a new system on the partition and encrypt it. Thus you will create the decoy system and the whole process of creation of the hidden operating system will be completed. - The hidden operating system has been successfully created. However, before you can start using it (and achieve plausible deniability), you need to securely erase (using TrueCrypt) the entire content of the partition where the currently running operating system is installed. Before you can do that, you need to restart the computer and, in the TrueCrypt Boot Loader screen (which appears before Windows starts), enter the pre-boot authentication password for the hidden operating system. Then, after the hidden system starts, the TrueCrypt wizard will be launched automatically.\n\nNote: If you choose to terminate the process of creation of the hidden operating system now, you will NOT be able to resume the process and the hidden system will NOT be accessible (because the TrueCrypt Boot Loader will be removed). - You have scheduled the process of creation of a hidden operating system. The process has not been completed yet. To complete it, you need to restart the computer and, in the TrueCrypt Boot Loader screen (which appears before Windows starts), enter the password for the hidden operating system.\n\nNote: If you choose to terminate the process of creation of the hidden operating system now, you will NOT be able to resume the process. - Restart the computer and proceed - Permanently terminate the process of creation of the hidden operating system - Do nothing now and ask again later - \nIF POSSIBLE, PLEASE PRINT THIS TEXT (click 'Print' below).\n\n\nHow and When to Use TrueCrypt Rescue Disk (After Encrypting)\n-------------------------------------------------------------------------------------\n\nI. How to Boot TrueCrypt Rescue Disk\n\nTo boot a TrueCrypt Rescue Disk, insert it into your CD/DVD drive and restart your computer. If the TrueCrypt Rescue Disk screen does not appear (or if you do not see the 'Repair Options' item in the 'Keyboard Controls' section of the screen), it is possible that your BIOS is configured to attempt to boot from hard drives before CD/DVD drives. If that is the case, restart your computer, press F2 or Delete (as soon as you see a BIOS start-up screen), and wait until a BIOS configuration screen appears. If no BIOS configuration screen appears, restart (reset) the computer again and start pressing F2 or Delete repeatedly as soon as you restart (reset) the computer. When a BIOS configuration screen appears, configure your BIOS to boot from the CD/DVD drive first (for information on how to do so, please refer to the documentation for your BIOS/motherboard or contact your computer vendor's technical support team for assistance). Then restart your computer. The TrueCrypt Rescue Disk screen should appear now. Note: In the TrueCrypt Rescue Disk screen, you can select 'Repair Options' by pressing F8 on your keyboard.\n\n\nII. When and How to Use TrueCrypt Rescue Disk (After Encrypting)\n\n1) If the TrueCrypt Boot Loader screen does not appear after you start your computer (or if your Windows does not boot), the TrueCrypt Boot Loader may be damaged. The TrueCrypt Rescue Disk allows you to restore it and thus to regain access to your encrypted system and data (however, note that you will still have to enter the correct password then). In the Rescue Disk screen, select 'Repair Options' > 'Restore TrueCrypt Boot Loader'. Then press 'Y' to confirm the action, remove the Rescue Disk from your CD/DVD drive and restart your computer.\n\n2) If you repeatedly enter the correct password but TrueCrypt says that the password is incorrect, the master key or other critical data may be damaged. The TrueCrypt Rescue Disk allows you to restore them and thus to regain access to your encrypted system and data (however, note that you will still have to enter the correct password then). In the Rescue Disk screen, select 'Repair Options' > 'Restore key data'. Then enter your password, press 'Y' to confirm the action, remove the Rescue Disk from your CD/DVD drive, and restart your computer.\n\n3) If the TrueCrypt Boot Loader is damaged or infected with malware, you can avoid running it by booting directly from the TrueCrypt Rescue Disk. Insert your Rescue Disk into your CD/DVD drive and then enter your password in the Rescue Disk screen.\n\n4) If Windows is damaged and cannot start, the TrueCrypt Rescue Disk allows you to permanently decrypt the partition/drive before Windows starts. In the Rescue Disk screen, select 'Repair Options' > 'Permanently decrypt system partition/drive'. Enter the correct password and wait until decryption is complete. Then you can e.g. boot your MS Windows setup CD/DVD to repair your Windows.\n\nNote: Alternatively, if Windows is damaged (cannot start) and you need to repair it (or access files on it), you can avoid decrypting the system partition/drive by following these steps: If you have multiple operating systems installed on your computer, boot the one that does not require pre-boot authentication. If you do not have multiple operating systems installed on your computer, you can boot a WinPE or BartPE CD/DVD or you can connect your system drive as a secondary or external drive to another computer and then boot the operating system installed on the computer. After you boot a system, run TrueCrypt, click 'Select Device', select the affected system partition, click 'OK', select 'System' > 'Mount Without Pre-Boot Authentication', enter your pre-boot authentication password and click 'OK'. The partition will be mounted as a regular TrueCrypt volume (data will be on-the-fly decrypted/encrypted in RAM on access, as usual).\n\n\nNote that even if you lose your TrueCrypt Rescue Disk and an attacker finds it, he or she will NOT be able to decrypt the system partition or drive without the correct password. - \n\nI M P O R T A N T -- PLEASE PRINT THIS TEXT IF POSSIBLE (click 'Print' below).\n\n\nNote: This text will be automatically displayed each time you start the hidden system until you start creating the decoy system.\n\n\nHow to Create Decoy System Safely and Securely\n----------------------------------------------------------------------------\n\nIn order to achieve plausible deniability, you need to create the decoy operating system now. To do so, follow these steps:\n\n1) For security reasons, shut down your computer and leave it powered off for several minutes. This is required to clear the memory, which contains sensitive data. Then turn on the computer but do not boot the hidden system.\n\n2) Install Windows on the partition whose content has been erased (i.e. on the partition where the original system, of which the hidden system is a clone, was installed).\n\nIMPORTANT: WHEN YOU START INSTALLING THE DECOY SYSTEM, THE HIDDEN SYSTEM WILL *NOT* BE POSSIBLE TO BOOT (because the TrueCrypt Boot Loader will be erased by the Windows system installer). THIS IS NORMAL AND EXPECTED. PLEASE DO NOT PANIC. YOU WILL BE ABLE TO BOOT THE HIDDEN SYSTEM AGAIN AS SOON AS YOU START ENCRYPTING THE DECOY SYSTEM (because TrueCrypt will then automatically install the TrueCrypt Boot Loader on the system drive).\n\nImportant: The size of the decoy system partition must remain the same as the size of the hidden volume (this condition is now met). Moreover, you must not create any partition between the decoy system partition and the partition where the hidden system resides.\n\n3) Boot the decoy system (which you installed in step 2 and install TrueCrypt on it).\n\nKeep in mind that the decoy system must never contain any sensitive data.\n\n4) On the decoy system, run TrueCrypt and select 'System' > 'Encrypt System Partition/Drive'. The TrueCrypt Volume Creation Wizard window should appear.\n\nThe following steps apply to the TrueCrypt Volume Creation Wizard.\n\n5) In the TrueCrypt Volume Creation Wizard, do NOT select the 'Hidden' option. Leave the 'Normal' option selected and click 'Next'.\n\n6) Select the option 'Encrypt the Windows system partition' and then click 'Next'.\n\n7) If there are only the hidden system and the decoy system installed on the computer, select the option 'Single-boot' (if there are more than these two systems installed on the computer, select 'Multi-boot'). Then click 'Next'.\n\n8) IMPORTANT: In this step, FOR THE DECOY SYSTEM, YOU MUST SELECT THE SAME ENCRYPTION ALGORITHM AND HASH ALGORITHM THAT YOU SELECTED FOR THE HIDDEN SYSTEM! OTHERWISE, THE HIDDEN SYSTEM WILL BE INACCESSIBLE! In other words, the decoy system must be encrypted with the same encryption algorithm as the hidden system. Note: The reason is that the decoy system and the hidden system will share a single boot loader, which supports only a single algorithm, selected by the user (for each algorithm, there is a special version of the TrueCrypt Boot Loader).\n\n9) In this step, choose a password for the decoy operating system. This will be the password that you will be able to reveal to an adversary if you are asked or forced to disclose your pre-boot authentication password (the other password you can reveal is the one for the outer volume). The existence of the third password (i.e. of the pre-boot authentication password for the hidden operating system) will remain secret.\n\nImportant: The password you choose for the decoy system must be substantially different from the one you chose for the hidden volume (i.e. for the hidden operating system).\n\n10) Follow the remaining instructions in the wizard so as to encrypt the decoy operating system.\n\n\n\nAfter Decoy System Is Created\n------------------------------------------------\n\nAfter you encrypt the decoy system, the whole process of creation of the hidden operating system will be completed and you will be able to use these three passwords:\n\n1) Pre-boot authentication password for the hidden operating system.\n\n2) Pre-boot authentication password for the decoy operating system.\n\n3) Password for the outer volume.\n\nIf you want to start the hidden operating system, you will just need to enter the password for the hidden operating system in the TrueCrypt Boot Loader screen (which appears after you turn on or restart your computer).\n\nIf you want to start the decoy operating system, you will just need to enter the password for the decoy operating system in the TrueCrypt Boot Loader screen.\n\nThe password for the decoy system can be disclosed to anyone forcing you to reveal your pre-boot authentication password. The existence of the hidden volume (and of the hidden operating system) will remain secret.\n\nThe third password (for the outer volume) can be disclosed to anyone forcing you to reveal the password for the first partition behind the system partition, where both the outer volume and the hidden volume (containing the hidden operating system) reside. The existence of the hidden volume (and of the hidden operating system) will remain secret.\n\n\nIf you revealed the password for the decoy system to an adversary and he asked you why the free space of the (decoy) system partition contains random data, you could answer, for example: "The partition previously contained a system encrypted by TrueCrypt, but I forgot the pre-boot authentication password (or the system was damaged and stopped booting), so I had to reinstall Windows and encrypt the partition again."\n\n\nIf all the instructions are followed and if precautions mentioned in the section "Security Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide are followed, it will be impossible to prove that the hidden volume and hidden operating system exist, even when the outer volume is mounted or when the decoy operating system is decrypted or started.\n\nIf you print this text (strongly recommended), you should destroy the paper after you have created the decoy system and after you have understood all the information contained in the text (otherwise, if the paper was found, it might indicate that there is a hidden operating system on this computer).\n\nWARNING: IF YOU DO NOT PROTECT THE HIDDEN VOLUME (for information on how to do so, refer to the section "Protection of Hidden Volumes Against Damage" in the TrueCrypt User's Guide), DO NOT WRITE TO THE OUTER VOLUME (note that the decoy operating system is NOT installed in the outer volume). OTHERWISE, YOU MAY OVERWRITE AND DAMAGE THE HIDDEN VOLUME (AND THE HIDDEN OPERATING SYSTEM WITHIN IT)! - Operating System Cloning - In the next steps, TrueCrypt will create the hidden operating system by copying the content of the system partition to the hidden volume (data being copied will be encrypted on the fly with an encryption key different from the one that will be used for the decoy operating system).\n\nPlease note that the process will be performed in the pre-boot environment (before Windows starts) and it may take a long time to complete; several hours or even several days (depending on the size of the system partition and on the performance of your computer).\n\nYou will be able to interrupt the process, shut down your computer, start the operating system and then resume the process. However, if you interrupt it, the entire process of copying the system will have to start from the beginning (because the content of the system partition must not change during cloning). - Do you want to cancel the entire process of creation of the hidden operating system?\n\nNote: You will NOT be able to resume the process if you cancel it now. - Do you want to cancel the system encryption pretest? - The TrueCrypt system encryption pretest failed. Do you want to try again?\n\nIf you select 'No', the pre-boot authentication component will be uninstalled.\n\nNote: If the TrueCrypt Boot Loader did not ask you to enter the password before Windows started, it is possible that your operating system does not boot from the drive on which it is installed. This is not supported. - The system partition/drive does not appear to be encrypted (neither partially nor fully). - Your system partition/drive is encrypted (partially or fully).\n\nPlease decrypt your system partition/drive entirely before proceeding. To do so, select 'System' > 'Permanently Decrypt System Partition/Drive' from the menu bar of the main TrueCrypt window. - Your system partition/drive is currently being encrypted, decrypted, or otherwise modified. Please interrupt the encryption/decryption/modification process (or wait until it is complete) before proceeding. - An instance of the TrueCrypt Volume Creation Wizard is currently running on this system and performing or preparing encryption/decryption of the system partition/drive. Before you proceed, please wait for it to finish or close it. If you cannot close it, please restart your computer before proceeding. - The process of encryption or decryption of the system partition/drive has not been completed. Please wait until it is complete before proceeding. - Error: The process of encryption of the partition/drive has not been completed. It must be completed first. - Error: The process of encryption of the partition/volume has not been completed. It must be completed first.\n\nNote: To resume the process, select 'Volumes' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. - The password is correct, TrueCrypt has successfully decrypted the volume header and detected that this volume is a hidden system volume. However, you cannot modify the header of a hidden system volume this way.\n\nTo change the password for a hidden system volume, boot the operating system residing in the hidden volume, and then select 'System' > 'Change Password' from the menu bar of the main TrueCrypt window.\n\nTo set the header key derivation algorithm, boot the hidden operating system and then select 'System' > 'Set Header Key Derivation Algorithm'. - TrueCrypt does not support in-place decryption of a hidden system partition.\n\nNote: If you want to decrypt the decoy system partition, boot the decoy system, and then select 'System' > 'Permanently Decrypt System Partition/Drive' from the menu bar of the main TrueCrypt window. - Error: Incorrect/invalid parameter. - You have selected a partition or a device but the wizard mode you selected is suitable only for file containers.\n\nDo you want to change the wizard mode? - Do you want to create a TrueCrypt file container instead? - You have selected the system partition/drive, but the wizard mode you selected is suitable only for non-system partitions/drives.\n\nDo you want to set up pre-boot authentication (which means that you will need to enter your password each time before Windows boots/starts) and encrypt the system partition/drive? - Are you sure you want to permanently decrypt the system partition/drive? - CAUTION: If you permanently decrypt the system partition/drive, unencrypted data will be written to it.\n\nAre you really sure you want to permanently decrypt the system partition/drive? - Warning: If you use a cascade of ciphers for system encryption, you may encounter the following issues:\n\n1) The TrueCrypt Boot Loader is larger than normal and, therefore, there is not enough space in the first drive track for a backup of the TrueCrypt Boot Loader. Hence, whenever it gets damaged (which often happens, for example, during inappropriately designed anti-piracy activation procedures of certain programs), you will need to use the TrueCrypt Rescue Disk to boot or to repair the TrueCrypt Boot Loader.\n\n2) On some computers, resuming from hibernation takes longer.\n\nThese potential issues can be prevented by choosing a non-cascade encryption algorithm (e.g. AES).\n\nAre you sure you want to use a cascade of ciphers? - If you encounter any of the previously described problems, decrypt the partition/drive (if it is encrypted) and then try encrypting it again using a non-cascade encryption algorithm (e.g. AES). - WARNING: For safety and security reasons, you should update TrueCrypt on the decoy operating system before you update it on the hidden operating system.\n\nTo do so, boot the decoy system and run the TrueCrypt installer from within it. Then boot the hidden system and run the installer from within it as well.\n\nNote: The decoy system and the hidden system share a single boot loader. If you upgraded TrueCrypt only on the hidden system (but not on the decoy system), the decoy system would contain a TrueCrypt driver and TrueCrypt applications whose version numbers are different from the version number of the TrueCrypt Boot Loader. Such a discrepancy might indicate that there is a hidden operating system on this computer.\n\n\nDo you want to continue? (Not recommended.) - The version number of the TrueCrypt Boot Loader that booted this operating system is different from the version number of the TrueCrypt driver (and of the TrueCrypt applications) installed on this system.\n\nYou should run the TrueCrypt installer (whose version number is the same as the one of the TrueCrypt Boot Loader) to update TrueCrypt on this operating system. - The TrueCrypt Boot Loader has been upgraded.\n\nIt is strongly recommended that you create a new TrueCrypt Rescue Disk (which will contain the new version of the TrueCrypt Boot Loader) by selecting 'System' > 'Create Rescue Disk' after you restart your computer. - The TrueCrypt Boot Loader has been upgraded.\n\nIt is strongly recommended that you boot the decoy operating system and then create a new TrueCrypt Rescue Disk (which will contain the new version of the TrueCrypt Boot Loader) by selecting 'System' > 'Create Rescue Disk'. - Failed to upgrade the TrueCrypt Boot Loader. - TrueCrypt failed to detect the real size of the system drive and, therefore, the size reported by the operating system (which may be smaller than the real size) will be used. Also note that this is not a bug in TrueCrypt. - WARNING: It appears that TrueCrypt has already tried to detect hidden sectors on this system drive. If you encountered any problems during the previous detection process, you can avoid the problems by skipping the detection of hidden sectors now. Note that if you do so, TrueCrypt will use the size reported by the operating system (which may be smaller than the real size of the drive).\n\nNote that this issue is not caused by a bug in TrueCrypt. - Skip detection of hidden sectors (use the size reported by the operating system) - Try to detect hidden sectors again - Error: Content of one or more sectors on the disk cannot be read (probably due to a physical defect).\n\nThe process of in-place encryption can continue only when the sectors have been made readable again. TrueCrypt can attempt to make these sectors readable by writing zeros to the sectors (subsequently such all-zero blocks would be encrypted). However, note that any data stored in the unreadable sectors will be lost. If you want to avoid that, you can attempt to recover portions of the corrupted data using appropriate third-party tools.\n\nNote: In case of physically damaged sectors (as opposed to mere data corruption and checksum errors) most types of storage devices internally reallocate the sectors when data is attempted to be written to them (so the existing data in the damaged sectors may remain unencrypted on the drive).\n\nDo you want TrueCrypt to write zeroes to unreadable sectors? - Error: Content of one or more sectors on the disk cannot be read (probably due to a physical defect).\n\nTo be able to proceed with decryption, TrueCrypt will have to discard the content of the unreadable sectors (the content will be replaced with pseudorandom data). Please note that, before proceeding, you can attempt to recover portions of any corrupted data using appropriate third-party tools.\n\nDo you want TrueCrypt to discard data in the unreadable sectors now? - Note: TrueCrypt has replaced the content of %I64d unreadable sectors (%s) with encrypted all-zero plaintext blocks. - Enter password/PIN for token '%s': - In order to allow TrueCrypt to access a security token or smart card, you need to install a PKCS #11 software library for the token or smart card first. Such a library may be supplied with the device or it may be available for download from the website of the vendor or other third parties.\n\nAfter you install the library, you can either select it manually by clicking 'Select Library' or you can let TrueCrypt find and select it automatically by clicking 'Auto-Detect Library' (only the Windows system directory will be searched). - Note: For the filename and location of the PKCS #11 library installed for your security token or smart card, please refer to the documentation supplied with the token, card, or third-party software.\n\nClick 'OK' to select the path and filename. - In order to allow TrueCrypt to access a security token or smart card, you need to select a PKCS #11 software library for the token/card first. To do so, select 'Settings' > 'Security Tokens'. - Failed to initialize PKCS #11 security token library.\n\nPlease make sure the specified path and filename refer to a valid PKCS #11 library. To specify a PKCS #11 library path and filename, select 'Settings' > 'Security Tokens'. - No PKCS #11 library has been found in the Windows system directory.\n\nPlease make sure that a PKCS #11 library for your security token (or for your smart card) is installed (such a library may be supplied with the token/card or it may be available for download from the website of the vendor or other third parties). If it is installed in a directory other than the Windows system directory, click 'Select Library' to locate the library (e.g. in the folder where the software for the token/card is installed). - No security token found.\n\nPlease make sure your security token is connected to your computer and the correct device driver for your token is installed. - Security token keyfile not found. - A security token keyfile with the same name already exists. - Do you want to delete the selected files? - Security token keyfile path is invalid. - Security token error - Password for security token is incorrect. - The security token does not have enough memory/space to perform the requested operation.\n\nIf you are attempting to import a keyfile, you should select a smaller file or use a keyfile generated by TrueCrypt (select 'Keyfiles' > 'Generate Random Keyfile'). - All open security token sessions have been closed. - Select Security Token Keyfiles - Slot - Token name - File name - Please note that pre-boot authentication passwords are always typed using the standard US keyboard layout. Therefore, a volume that uses a password typed using a non-US keyboard layout may be impossible to mount using a cached pre-boot authentication password. Note that this is not a bug in TrueCrypt. - Error while parsing command line. - Rescue Disk - Select &File and Mount... - Select &Device and Mount... - Warning: The filesystem on the volume mounted as '%s' was not cleanly dismounted and thus may contain errors. Using a corrupted filesystem can cause data loss or data corruption.\n\nNote: Before you physically remove or switch off a device (such as a USB flash drive or an external hard drive) where a mounted TrueCrypt volume resides, you should always dismount the TrueCrypt volume in TrueCrypt first.\n\n\nDo you want Windows to attempt to detect and fix errors (if any) on the filesystem? - Warning: Repairing a damaged filesystem using the Microsoft 'chkdsk' tool might cause loss of files in damaged areas. Therefore, it is recommended that you first back up the files stored on the TrueCrypt volume to another, healthy, TrueCrypt volume.\n\nDo you want to repair the filesystem now? - Volume '%s' has been mounted as read-only because write access was denied.\n\nPlease make sure the security permissions of the file container allow you to write to it (right-click the container and select Properties > Security).\n\nIf you intend to keep your volume read-only, set the read-only attribute of the container (right-click the container and select Properties > Read-only), which will suppress this warning. - Volume '%s' had to be mounted as read-only because write access was denied.\n\nPlease make sure no other application (e.g. antivirus software) is accessing the partition/device on which the volume is hosted. - Volume '%s' has been mounted as read-only because the operating system reported the host device to be write-protected.\n\nPlease note that some custom chipset drivers have been reported to cause writable media to falsely appear write-protected. This problem is not caused by TrueCrypt. It may be solved by updating or uninstalling any custom (non-Microsoft) chipset drivers that are currently installed on this system. - Do you want TrueCrypt to attempt to disable write protection of the partition/drive? - Test - Keyfile - Name - Backspace - Tab - Clear - Enter - Pause - Caps Lock - Spacebar - Page Up - Page Down - End - Home - Left Arrow - Up Arrow - Right Arrow - Down Arrow - Select Key - Print Key - Execute Key - Print Screen - Insert - Delete - Applications Key - Sleep - Num Lock - Scroll Lock - Browser Back - Browser Forward - Browser Refresh - Browser Stop - Browser Search - Browser Favorites - Browser Home - Mute - Volume Down - Volume Up - Next Track - Previous Track - Stop Media - Play/Pause Media - Start Mail Key - Select Media Key - Application 1 - Application 2 - Attn - CrSel - ExSel - Play - Zoom - NumPad - Shift - Control - Alt - Win - B - KB - MB - GB - TB - PB - B/s - KB/s - MB/s - GB/s - TB/s - PB/s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + Cancel + Install &for all users + Bro&wse... + Add TrueCrypt icon to &desktop + Associate the .tc file &extension with TrueCrypt + &Open the destination location when finished + Add TrueCrypt to &Start menu + Create System &Restore point + &Uninstall + &Extract + &Install + TrueCrypt Setup Wizard + Uninstall TrueCrypt + &Help + Please select or type the location where you want to place the extracted files: + Please select or type the location where you want to install the TrueCrypt program files. If the specified folder does not exist, it will be automatically created. + Click Uninstall to remove TrueCrypt from this system. + Abort + &Test + Create encrypted volume and format it + Encrypt partition in place + Display generated keys (their portions) + Display pool content + Download CD/DVD recording software + Create an encrypted file container + &GB + More information + Hi&dden TrueCrypt volume + More information about hidden volumes + Direct mode + Normal mode + &KB + U&se keyfiles + &Keyfiles.. + Information on hash algorithms + More information + &MB + More information + More information about system encryption + More information + Multi-boot + Encrypt a non-system partition/drive + Never &save history + Open Outer Volume + &Pause + Quick Format + &Display password + &Display password + Single-boot + Standard TrueCrypt volume + Hi&dden + Normal + Encrypt the system partition or entire system drive + Encrypt the Windows system partition + Encrypt the whole drive + &Benchmark + TrueCrypt Volume Creation Wizard + Cluster + 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. + &Confirm: + Done + Encryption Algorithm + Filesystem + Creates a virtual encrypted disk within a file. Recommended for inexperienced users. + Options + Hash Algorithm + Header Key: + Left + Master Key: + Select this option if there are two or more operating systems installed on this computer.\n\nFor example:\n- Windows XP and Windows XP\n- Windows XP and Windows Vista\n- Windows and Mac OS X\n- Windows and Linux\n- Windows, Linux and Mac OS X + Encrypts a non-system partition on any internal or external drive (e.g. a flash drive). Optionally, creates a hidden volume. + Current pool content (partial) + Pass + Password: + Progress: + Random Pool: + Select this option if there is only one operating system installed on this computer (even if it has multiple users). + Speed + Status + The keys, salt, and other data have been successfully generated. If you want to generate new keys, click Back and then Next. Otherwise, click Next to continue. + Encrypts the partition/drive where Windows is installed. Anyone who wants to gain access and use the system, read and write files, etc., will need to enter the correct password each time before Windows boots. Optionally, creates a hidden system. + Select this option to encrypt the partition where the currently running Windows operating system is installed. + Wipe mode: + Close + Allow pre-boot &authentication to be bypassed by pressing the Esc key (enables boot manager) + Do nothing + &Auto-mount TrueCrypt volume (specified below) + &Start TrueCrypt + Auto-&Detect Library + &Cache pre-boot authentication password in driver memory (for mounting of non-system volumes) + Browse... + Browse... + Cache passwords and keyfil&es in memory + Exit when there are no mounted volumes + &Close token session (log out) after a volume is successfully mounted + Include TrueCrypt Volume Creation Wizard + Create + &Create Volume + Do not &show any texts in the pre-boot authentication screen (except the below custom message) + Allow only administrators to view and dismount system favorite volumes in TrueCrypt + Display confirmation message box after dismount + Play system notification sound after mount/dismount + Use keyfiles + Use keyfiles + E&xit + Alt + Control + Shift + Win + Assign + Remove + Keyfiles... + More Settings... + &Auto-Mount Devices + Mount Opti&ons... + Mount volume as read-&only + Mount system favorite volumes when Windows starts (in the initial phase of the start procedure) + Keyfiles... + Enabled + Cache passwords in driver memory + Close all Explorer windows of volume being dismounted + Auto-dismount volume after no data has been read/written to it for + User logs off + Entering power saving mode + Screen saver is launched + Force auto-dismount even if volume contains open files or directories + Mount all device-hosted TrueCrypt volumes + Mount favorite volumes + Start TrueCrypt Background Task + Mount volumes as read-only + Mount volumes as removable media + Open Explorer window for successfully mounted volume + Wipe cached passwords on auto-dismount + Wipe cached passwords on exit + Preserve timestamps of file containers + Reset + Select D&evice... + Select &File... + Select &Library... + Display password + Display password + Open &Explorer window for mounted volume + &Cache password in driver memory + Di&smount All + &Volume Properties... + Volume &Tools... + &Wipe Cache + TrueCrypt - System-Wide Hot Keys + TrueCrypt + Change Password or Keyfiles + Enter TrueCrypt Volume Password + TrueCrypt - Preferences + TrueCrypt - System Encryption Settings + TrueCrypt - System Favorite Volumes - Options + TrueCrypt - Security Token Preferences + TrueCrypt Traveler Disk Setup + TrueCrypt Volume Properties + About... + Add/Remove Keyfiles to/from Volume... + Backup Volume Header... + Benchmark... + Report a Bug... + Set Header Key Derivation Algorithm... + Change Volume Password... + Set Header Key Derivation Algorithm... + Change Password... + Clear Volume History + Close All Security Token Sessions + Contact... + Create Hidden Operating System... + Create Rescue Disk... + Create New Volume... + Default Keyfiles... + Donations... + Encrypt System Partition/Drive... + Frequently Asked Questions + Forums + Generate Random Keyfile... + User's Guide + &Homepage + Hot Keys... + Keyfile Generator + Language... + Legal Notices + Manage Security Token Keyfiles... + Auto-Mount All Device-Hosted Volumes + Mount Favorite Volumes + Mount Without Pre-Boot &Authentication... + Mount Volume + Mount Volume with Options + News + Online Help + Beginner's Tutorial + Permanently Decrypt System Partition/Drive + Preferences... + Refresh Drive Letters + Remove All Keyfiles from Volume... + Restore Volume Header... + Resume Interrupted Process + Save Currently Mounted Volumes as Favorites + Save Currently Mounted Volumes as System Favorites + Select Device... + Select File... + Set Default Keyfiles/Paths... + Resume Interrupted Process + System Encryption... + Properties... + Settings... + System Favorite Volumes... + Downloads + Test Vectors... + Security Tokens... + Traveler Disk Setup... + Dismount All Mounted Volumes + Dismount Volume + Verify Rescue Disk + Version History + Volume Properties + Volume Creation Wizard + TrueCrypt Website + Wipe Cached Passwords + OK + Shortcut + AutoRun Configuration (autorun.inf) + Auto-Dismount + Dismount all when: + Boot Loader Screen Options + Confirm Password: + Current + Display this custom message in the pre-boot authentication screen (24 characters maximum): + Default Mount Options + Hot Key Options + File Settings + Key to assign: + Actions to perform upon log on to Windows + minutes + Mount volume as drive letter: + Mount Settings + New + Password: + PKCS #11 Library Path + PKCS-5 PRF: + Password Cache + Security Options + System Favorite Volumes Options + TrueCrypt Background Task + TrueCrypt volume to mount (relative to traveler disk root): + Upon insertion of traveler disk: + Create traveler disk files at (traveler disk root directory): + Volume + Windows + Add &Path... + &Auto-Test All + &Continue + &Decrypt + &Delete + Donations... + &Encrypt + &Export... + Generate and Save Keyfile... + &Generate Random Keyfile... + Download language pack + &Import Keyfile to Token... + Add &Files... + U&se keyfiles + &Keyfiles... + &Remove + Remove &All + What is hidden volume protection? + More information on keyfiles + Mount volume as removable &medium + Mount partition &using system encryption without pre-boot authentication + Benchmark + &Print + &Protect hidden volume against damage caused by writing to outer volume + &Reset + &Display password + Add &Token Files... + Use backup header embedded in &volume if available + XTS mode + About TrueCrypt + TrueCrypt - Encryption Algorithm Benchmark + TrueCrypt - Test Vectors + Command Line Help + TrueCrypt - Keyfiles + TrueCrypt - Keyfile Generator + TrueCrypt - Language + TrueCrypt - Mount Options + New Security Token Keyfile Properties + TrueCrypt - Random Pool Enrichment + Select a Partition or Device + Security Token Keyfiles + Security token password/PIN required + Active language pack + Speed is affected by CPU load and storage device characteristics.\n\nThese tests take place in RAM. + Buffer Size: + Cipher: + P&assword to hidden volume:\n(if empty, cache is used) + Hidden Volume Protection + Key size: + 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 + Translated by: + Plaintext size: + bits + Current pool content + Mixing PRF: + 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'. + Secondary key (hexadecimal) + Security token: + Sort Method: + Block number: + Ciphertext (hexadecimal) + Data unit number (64-bit hexadecimal, data unit size is 512 bytes) + Key (hexadecimal) + Plaintext (hexadecimal) + Keyfile name: + XTS mode + System Favorite Volumes... + Disable Windows paging files + Exit + Cipher Configuration (all sizes in bytes) + Set Header Key Derivation Algorithm + Add/Remove Keyfiles to/from Volume + Remove All Keyfiles from Volume + Windows Explorer + Browse... + TrueCrypt - Keyfile Generator + S&ystem + &Volumes + &Keyfiles + T&ools + Settin&gs + &Help + Home&page + + &About... + The read-only attribute on your old volume could not be changed. Please check the file access permissions. + Error: Access denied.\n\nThe partition you are trying to access is either 0 sectors long, or it is the boot device. + Administrator + In order to load the TrueCrypt driver, you need to be logged into an account with administrator privileges. + Please note that in order to encrypt/format a partition/device you need to be logged into an account with administrator privileges.\n\nThis does not apply to file-hosted volumes. + In order to create a hidden volume you need to be logged into an account with administrator privileges.\n\nContinue? + Please note that in order to format the volume as NTFS you need to be logged into an account with administrator privileges.\n\nWithout administrator privileges, you can format the volume as FAT. + FIPS-approved cipher (Rijndael, published in 1998) that may be used by U.S. government departments and agencies to protect classified information up to the Top Secret level. 256-bit key, 128-bit block, 14 rounds (AES-256). Mode of operation is XTS. + Volume is already mounted. + CAUTION: At least one encryption or hash algorithm failed the built-in automatic self-tests!\n\nTrueCrypt installation may be corrupted. + CAUTION: There is not enough data in the Random Number Generator pool to provide the requested amount of random data.\n\nYou should not proceed any further. Please select 'Report a Bug' from the Help menu, and report this error. + The drive is damaged (there is a physical defect on it) or a cable is damaged, or the memory is malfunctioning.\n\nPlease note that this is a problem with your hardware, not with TrueCrypt. Therefore, please do NOT report this as a bug/problem in TrueCrypt and please do NOT ask for help with this in the TrueCrypt Forums. Please contact your computer vendor's technical support team for assistance. Thank you.\n\nNote: If the error occurs repeatedly at the same place, it is very likely caused by a bad disk block, which should be possible to correct using third-party software (note that, in many cases, the 'chkdsk /r' command cannot correct it because it works only at the filesystem level; in some cases, the 'chkdsk' tool cannot even detect it). + Your system appears to be using custom chipset drivers containing a bug that prevents encryption of the whole system drive.\n\nPlease try updating or uninstalling any custom (non-Microsoft) chipset drivers before proceeding. If it does not help, try encrypting the system partition only. + Invalid drive letter. + Invalid path. + Cancel + Cannot access device. Make sure the selected device exists and is not used by system. + Warning: Caps Lock is on. This may cause you to enter your password incorrectly. + Volume Type + It may happen that you are forced by somebody to reveal the password to an encrypted volume. There are many situations where you cannot refuse to reveal the password (for example, due to extortion). Using a so-called hidden volume allows you to solve such situations without revealing the password to your volume. + Select this option if you want to create a normal TrueCrypt volume. + Please note that if you wish an operating system to be installed in a hidden partition-hosted volume, then the entire system drive cannot be encrypted using a single key. + Outer Volume Encryption Options + Hidden Volume Encryption Options + Encryption Options + WARNING: Failed to clear the path of the last selected volume/keyfile (remembered by file selector)! + Error: The container has been compressed at the filesystem level. TrueCrypt does not support compressed containers (note that compression of encrypted data is ineffective and redundant).\n\nPlease disable compression for the container by following these steps:\n1) Right-click the container in Windows Explorer (not in TrueCrypt).\n2) Select 'Properties'.\n3) In the 'Properties' dialog box, click 'Advanced'.\n4) In the 'Advanced Attributes' dialog box, disable the option 'Compress contents to save disk space' and click 'OK'.\n5) In the 'Properties' dialog box, click 'OK'. + Failed to create volume %hs + Size of %hs is %.2f bytes + Size of %hs is %.2f KB + Size of %hs is %.2f MB + Size of %hs is %.2f GB + Size of %hs is %.2f TB + Size of %hs is %.2f PB + WARNING: The device/partition is in use by the operating system or applications. Formatting the device/partition might cause data corruption and system instability.\n\nContinue? + Warning: The partition is in use by the operating system or applications. You should close any applications that might be using the partition (including antivirus software).\n\nContinue? + Error: The device/partition contains a file system that could not be dismounted. The file system may be in use by the operating system. Formatting the device/partition would very likely cause data corruption and system instability.\n\nTo solve this issue, we recommend that you first delete the partition and then recreate it without formatting. To do so, follow these steps:\n1) Right-click the 'Computer' (or 'My Computer') icon in the 'Start Menu' and select 'Manage'. The 'Computer Management' window should appear.\n2) In the 'Computer Management' window, select 'Storage' > 'Disk Management'.\n3) Right-click the partition you want to encrypt and select either 'Delete Partition', or 'Delete Volume', or 'Delete Logical Drive'.\n4) Click 'Yes'. If Windows asks you to restart the computer, do so. Then repeat the steps 1 and 2 and continue from the step 5.\n5) Right-click the unallocated/free space area and select either 'New Partition', or 'New Simple Volume', or 'New Logical Drive'.\n6) The 'New Partition Wizard' or 'New Simple Volume Wizard' window should appear now; follow its instructions. On the wizard page entitled 'Format Partition', select either 'Do not format this partition' or 'Do not format this volume'. In the same wizard, click 'Next' and then 'Finish'.\n7) Note that the device path you have selected in TrueCrypt may be wrong now. Therefore, exit the TrueCrypt Volume Creation Wizard (if it is still running) and then start it again.\n8) Try encrypting the device/partition again.\n\nIf TrueCrypt repeatedly fails to encrypt the device/partition, you may want to consider creating a file container instead. + Error: The filesystem could not be locked and/or dismounted. It may be in use by the operating system or applications (for example, antivirus software). Encrypting the partition might cause data corruption and system instability.\n\nPlease close any applications that might be using the filesystem (including antivirus software) and try again. If it does not help, please follow the below steps. + WARNING: Some of the mounted devices/partitions were already in use!\n\nIgnoring this can cause undesired results including system instability.\n\nWe strongly recommend that you close any application that might be using the devices/partitions. + The selected device contains partitions.\n\nFormatting the device might cause system instability and/or data corruption. Please either select a partition on the device, or remove all partitions on the device to enable TrueCrypt to format it safely. + The selected non-system device contains partitions.\n\nEncrypted device-hosted TrueCrypt volumes can be created within devices that do not contain any partitions (including hard disks and solid-state drives). A device that contains partitions can be entirely encrypted in place (using a single master key) only if it is the drive where Windows is installed and from which it boots.\n\nIf you want to encrypt the selected non-system device using a single master key, you will need to remove all partitions on the device first to enable TrueCrypt to format it safely (formatting a device that contains partitions might cause system instability and/or data corruption). Alternatively, you can encrypt each partition on the drive individually (each partition will be encrypted using a different master key).\n\nNote: If you want to remove all partitions from a GPT disk, you may need to convert it to a MBR disk (using e.g. the Computer Management tool) in order to remove hidden partitions. + Warning: If you encrypt the entire device (as opposed to encrypting only a partition on it), operating systems will consider the device as new, empty, and unformatted (as it will contain no partition table) and may spontaneously initialize the device (or ask you if you want to do so), which may damage the volume.\n\nTo avoid that you may want to consider creating a partition on the device and encrypting the partition instead.\n\nAre you sure want to encrypt the entire device? + IMPORTANT: Please keep in mind that this volume can NOT be mounted/accessed using the drive letter %c:, which is currently assigned to it!\n\nTo mount this volume, click 'Auto-Mount Devices' in the main TrueCrypt window (alternatively, in the main TrueCrypt window, click 'Select Device', then select this partition/device, and click 'Mount'). The volume will be mounted to a different drive letter, which you select from the list in the main TrueCrypt window.\n\nThe original drive letter %c: should be used only in case you need to remove encryption from the partition/device (e.g., if you no longer need encryption). In such a case, right-click the drive letter %c: in the 'Computer' (or 'My Computer') list and select 'Format'. Otherwise, the drive letter %c: should never be used (unless you remove it and assign it to another partition/device). + In-place encryption of non-system volumes is not supported on the version of the operating system you are currently using (it is supported only on Windows Vista and later versions of Windows).\n\nThe reason is that this version of Windows does not support shrinking of a filesystem (the filesystem needs to be shrunk to make space for the volume header and backup header). + The selected partition does not appear to contain an NTFS filesystem. Only partitions that contain an NTFS filesystem can be encrypted in place.\n\nNote: The reason is that Windows does not support shrinking of other types of filesystems (the filesystem needs to be shrunk to make space for the volume header and backup header). + The selected partition does not appear to contain an NTFS filesystem. Only partitions that contain an NTFS filesystem can be encrypted in place.\n\nIf you want to create an encrypted TrueCrypt volume within this partition, choose the option "Create encrypted volume and format it" (instead of the option "Encrypt partition in place"). + Error: The partition is too small. TrueCrypt cannot encrypt it in place. + To encrypt the data on this partition, please follow these steps:\n\n1) Create a TrueCrypt volume on an empty partition/device and then mount it.\n\n2) Copy all files from the partition that you originally wanted to encrypt to the mounted TrueCrypt volume (that has been created and mounted in step 1). That way, you will create a TrueCrypt-encrypted backup of the data.\n\n3) Create a TrueCrypt volume on the partition that you originally wanted to encrypt and make sure that (in the TrueCrypt wizard) you choose the option "Create encrypted volume and format it" (instead of the option "Encrypt partition in place"). Note that all data stored on the partition will be erased. After the volume is created, mount it.\n\n4) Copy all files from the mounted backup TrueCrypt volume (created and mounted in step 1) to the mounted TrueCrypt volume that has been created (and mounted) in step 3.\n\nAfter you complete these steps, the data will be encrypted and, in addition, there will be an encrypted backup of the data. + TrueCrypt can in-place encrypt only a partition, a dynamic volume, or an entire system drive.\n\nIf you want to create an encrypted TrueCrypt volume within the selected non-system device, choose the option "Create encrypted volume and format it" (instead of the option "Encrypt partition in place"). + Error: TrueCrypt can in-place encrypt only a partition, a dynamic volume, or an entire system drive. Please make sure the specified path is valid. + Error: Cannot shrink the filesystem (the filesystem needs to be shrunk to make space for the volume header and backup header).\n\nPossible causes and solutions:\n\n- Not enough free space on the volume. Please make sure no other application is writing to the filesystem.\n\n- Corrupted file system. Try to check it and fix any errors (right-click the corresponding drive letter in the 'Computer' list, then select Properties > Tools > 'Check Now', make sure the option 'Automatically fix file system errors' is enabled and click Start).\n\nIf the above steps do not help, please follow the below steps. + Error: There is not enough free space on the volume and so the filesystem cannot be shrunk (the filesystem needs to be shrunk to make space for the volume header and backup header).\n\nPlease delete any redundant files and empty the Recycle Bin so as to free at least 256 KB of space and then try again. Note that due to a Windows issue, the amount of free space reported by the Windows Explorer may be incorrect until the operating system is restarted. If restarting the system does not help, the file system may be corrupted. Try to check it and fix any errors (right-click the corresponding drive letter in the 'Computer' list, then select Properties > Tools > 'Check Now', make sure the option 'Automatically fix file system errors' is enabled and click Start).\n\nIf the above steps do not help, please follow the below steps. + Free space on drive %hs is %.2f bytes. + Free space on drive %hs is %.2f KB + Free space on drive %hs is %.2f MB + Free space on drive %hs is %.2f GB + Free space on drive %hs is %.2f TB + Free space on drive %hs is %.2f PB + Could not get available drive letters. + Error: TrueCrypt driver not found.\n\nPlease copy the files 'truecrypt.sys' and 'truecrypt-x64.sys' to the directory where the main TrueCrypt application (TrueCrypt.exe) is located. + An incompatible version of the TrueCrypt device driver is currently running.\n\nRequired version: TrueCrypt %hs + Error: Cipher initialization failure. + Error: A weak or a potentially weak key has been detected. The key will be discarded. Please try again. + A critical error has occurred and TrueCrypt must be terminated. If this is caused by a bug in TrueCrypt, we would like to fix it. To help us, you can send us an automatically generated error report containing the following items:\n\n- Program version\n- Operating system version\n- Type of CPU\n- TrueCrypt component name\n- Checksum of TrueCrypt executable\n- Symbolic name of dialog window\n- Error category\n- Error address\n- TrueCrypt call stack\n\nIf you select 'Yes', the following URL (which contains the entire error report) will be opened in your default Internet browser.\n\n%hs\n\nDo you want to send us the above error report? + A critical error has occurred in your system, which requires TrueCrypt to be terminated.\n\nNote that this error has not been caused by TrueCrypt (so the TrueCrypt developers cannot fix it). Please, check your system for possible problems (e.g., system configuration, network connection, failing hardware components). + TrueCrypt Critical Error + &Encrypt + &Decrypt + &Permanently Decrypt + Exit + Please create a logical drive for this extended partition, and then try again. + A TrueCrypt volume can reside in a file (called TrueCrypt container), which can reside on a hard disk, on a USB flash drive, etc. A TrueCrypt container is just like any normal file (it can be, for example, moved or deleted as any normal file). Click 'Select File' to choose a filename for the container and to select the location where you wish the container to be created.\n\nWARNING: If you select an existing file, TrueCrypt will NOT encrypt it; the file will be deleted and replaced with the newly created TrueCrypt container. You will be able to encrypt existing files (later on) by moving them to the TrueCrypt container that you are about to create now. + Select the location of the outer volume to be created (within this volume the hidden volume will be created later on).\n\nA TrueCrypt volume can reside in a file (called TrueCrypt container), which can reside on a hard disk, on a USB flash drive, etc. A TrueCrypt container can be moved or deleted as any normal file. Click 'Select File' to choose a filename for the container and to select the location where you wish the container to be created. If you select an existing file, TrueCrypt will NOT encrypt it; it will be deleted and replaced with the newly created container. You will be able to encrypt existing files (later on) by moving them to the TrueCrypt container you are about to create now. + Encrypted device-hosted TrueCrypt volumes can be created within partitions on hard disks, solid-state drives, USB memory sticks, and on any other supported storage devices. Partitions can also be encrypted in place.\n\nIn addition, encrypted device-hosted TrueCrypt volumes can be created within devices that do not contain any partitions (including hard disks and solid-state drives).\n\nNote: A device that contains partitions can be entirely encrypted in place (using a single key) only if it is the drive where Windows is installed and from which it boots. + A device-hosted TrueCrypt volume can be created within a hard disk partition, solid-state drive, USB memory stick, and other storage devices.\n\nWARNING: Note that the partition/device will be formatted and all data currently stored on it will be lost. + \nSelect the location of the outer volume to be created (within this volume the hidden volume will be created later on).\n\nOuter volumes can be created within partitions on hard disks, solid-state drives, USB memory sticks, and on any other supported storage devices. Outer volumes can also be created within devices that do not contain any partitions (including hard disks and solid-state drives).\n\nWARNING: Note that the partition/device will be formatted and all data currently stored on it will be lost. + \nSelect the location of the TrueCrypt volume within which you wish to create a hidden volume. + WARNING: The host file/device is already in use!\n\nIgnoring this can cause undesired results including system instability. All applications that might be using the host file/device (for example, antivirus or backup applications) should be closed before mounting the volume.\n\nContinue mounting? + Error: Cannot mount volume. The host file/device is already in use. Attempt to mount without exclusive access failed as well. + The file could not be opened. + Volume Location + Large Files + Do you intend to store files larger than 4 GB in this TrueCrypt volume? + Depending on your choice above, TrueCrypt will choose a suitable default file system for the TrueCrypt volume (you will be able to select a file system in the next step). + As you are creating an outer volume, you should consider choosing 'No'. If you choose 'Yes', the default filesystem will be NTFS, which is not as suitable for outer volumes as FAT (for example, the maximum possible size of the hidden volume will be significantly greater if the outer volume is formatted as FAT). Normally, FAT is the default for both hidden and normal volumes (so FAT volumes are not suspicious). However, if the user indicates intent to store files larger than 4 GB (which the FAT file system does not allow), then FAT is not the default. + Are you sure you want to choose 'Yes'? + Volume Creation Mode + This is the fastest way to create a partition-hosted or device-hosted TrueCrypt volume (in-place encryption, which is the other option, is slower because content of each sector has to be first read, encrypted, and then written). Any data currently stored on the selected partition/device will be lost (the data will NOT be encrypted; it will be overwritten with random data). If you want to encrypt existing data on a partition, choose the other option. + The entire selected partition and all data stored on it will be encrypted in place. If the partition is empty, you should choose the other option (the volume will be created much faster). + Note: + &Resume + &Defer + &Start + &Continue + &Format + &Wipe + Abort format? + Show more information + Do not show this again + The content of the partition/device has been successfully erased. + The content of the partition where the original system (of which the hidden system is a clone) resided has been successfully erased. + Please make sure the version of Windows you are going to install (on the wiped partition) is the same as the version of Windows you are currently running. This is required due to the fact that both systems will share a common boot partition. + The system partition/drive has been successfully encrypted.\n\nNote: If there are non-system TrueCrypt volumes that you need to have mounted automatically every time Windows starts, you can set it up by mounting them and selecting 'Volumes' > 'Save Currently Mounted Volumes as System Favorites'). + The system partition/drive has been successfully decrypted. + \n\nThe TrueCrypt volume has been created and is ready for use. If you wish to create another TrueCrypt volume, click Next. Otherwise, click Exit. + \n\nThe hidden TrueCrypt volume has been successfully created (the hidden operating system will reside within this hidden volume).\n\nClick Next to continue. + Volume Fully Encrypted + IMPORTANT: TO MOUNT THIS NEWLY CREATED TRUECRYPT VOLUME AND TO ACCESS DATA STORED IN IT, CLICK 'Auto-Mount Devices' IN THE MAIN TRUECRYPT WINDOW. After you enter the correct password (and/or supply correct keyfiles), the volume will be mounted to the drive letter you select from the list in the main TrueCrypt window (and you will be able to access the encrypted data via the selected drive letter).\n\nPLEASE REMEMBER OR WRITE DOWN THE ABOVE STEPS. YOU MUST FOLLOW THEM WHENEVER YOU WANT TO MOUNT THE VOLUME AND ACCESS DATA STORED IN IT. Alternatively, in the main TrueCrypt window, click 'Select Device', then select this partition/volume, and click 'Mount'.\n\nThe partition/volume has been successfully encrypted (it contains a fully encrypted TrueCrypt volume now) and is ready for use. + The TrueCrypt volume has been successfully created. + Volume Created + 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 Format to create the volume. + Click Format to create the outer volume. For more information, please refer to the documentation. + Outer Volume Format + Hidden Volume Format + Volume Format + WARNING: Could not get container timestamp! + WARNING: Could not get container timestamp!\n\nIf there is a hidden volume within this container, the plausible deniability of the hidden volume might be affected. + WARNING: Could not get container timestamp!\n\nIf you do not reset the timestamp using an external tool, we recommend that you do not create a hidden volume within this container. + WARNING: Could not get container timestamp!\n\nIf there is a hidden volume within this container, the plausible deniability of the hidden volume might be affected after changing or attempting to change the password. + WARNING: Could not get keyfile timestamp! Cannot preserve last access date/time.\n\nIt will be possible to tell that this file has been accessed. + Adobe Reader (or a compatible tool) is necessary to view or print the TrueCrypt User's Guide. Adobe Reader (freeware) can be downloaded at: www.adobe.com\n\nDo you want to view the online documentation instead? + If you select this option, the wizard will first help you create a normal TrueCrypt volume and then a hidden TrueCrypt volume within it. Inexperienced users should always select this option. + If you select this option, you will create a hidden volume within an existing TrueCrypt volume. It will be assumed that you have already created a TrueCrypt volume that is suitable to host the hidden volume. + Volume Creation Mode + Hidden Volume Created + The hidden TrueCrypt volume has been successfully created and is ready for use. If all the instructions have been followed and if the precautions and requirements listed in the section "Security Requirements and Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide are followed, it will be impossible to prove that the hidden volume exists, even when the outer volume is mounted.\n\nWARNING: IF YOU DO NOT PROTECT THE HIDDEN VOLUME (FOR INFORMATION ON HOW TO DO SO, REFER TO THE SECTION "PROTECTION OF HIDDEN VOLUMES AGAINST DAMAGE" IN THE TRUECRYPT USER'S GUIDE), DO NOT WRITE TO THE OUTER VOLUME. OTHERWISE, YOU MAY OVERWRITE AND DAMAGE THE HIDDEN VOLUME! + You have started the hidden operating system. As you may have noticed, the hidden operating system appears to be installed on the same partition as the original operating system. However, in reality, it is installed within the partition behind it (in the hidden volume). All read and write operations are being transparently redirected from the original system partition to the hidden volume.\n\nNeither the operating system nor applications will know that data written to and read from the system partition are actually written to and read from the partition behind it (from/to a hidden volume). Any such data is encrypted and decrypted on the fly as usual (with an encryption key different from the one that will be used for the decoy operating system).\n\n\nPlease click Next to continue. + The outer volume has been created and mounted as drive %hc:. To this outer volume you should now copy some sensitive-looking files that you actually do NOT want to hide. They will be there for anyone forcing you to disclose the password for the first partition behind the system partition, where both the outer volume and the hidden volume (containing the hidden operating system) will reside. You will be able to reveal the password for this outer volume, and the existence of the hidden volume (and of the hidden operating system) will remain secret.\n\nIMPORTANT: The files you copy to the outer volume should not occupy more than %s. Otherwise, there may not be enough free space on the outer volume for the hidden volume (and you will not be able to continue). After you finish copying, click Next (do not dismount the volume). + Outer volume has been successfully created and mounted as drive %hc:. To this volume you should now copy some sensitive-looking files that you actually do NOT want to hide. The files will be there for anyone forcing you to disclose your password. You will reveal only the password for this outer volume, not for the hidden one. The files that you really care about will be stored in the hidden volume, which will be created later on. When you finish copying, click Next. Do not dismount the volume.\n\nNote: After you click Next, cluster bitmap of the outer volume will be scanned to determine the size of uninterrupted area of free space whose end is aligned with the end of the volume. This area will accommodate the hidden volume, so it will limit its maximum possible size. Cluster bitmap scanning ensures that no data on the outer volume are overwritten by the hidden volume. + Outer Volume Contents + \n\nIn the next steps, you will set the options for the outer volume (within which the hidden volume will be created later on). + \n\nIn the next steps, you will create a so-called outer TrueCrypt volume within the first partition behind the system partition (as was explained in one of the previous steps). + Outer Volume + In the following steps, you will set the options and password for the hidden volume, which will contain the hidden operating system.\n\nRemark: The cluster bitmap of the outer volume has been scanned in order to determine the size of uninterrupted area of free space whose end is aligned with the end of the outer volume. This area will accommodate the hidden volume, so it limits its maximum possible size. The maximum possible size of the hidden volume has been determined and confirmed to be greater than the size of the system partition (which is required, because the entire content of the system partition will need to be copied to the hidden volume). This ensures that no data currently stored on the outer volume will be overwritten by data written to the area of the hidden volume. + IMPORTANT: Please remember the algorithms that you select in this step. You will have to select the same algorithms for the decoy system. Otherwise, the hidden system will be inaccessible! (The decoy system must be encrypted with the same encryption algorithm as the hidden system.)\n\nNote: The reason is that the decoy system and the hidden system will share a single boot loader, which supports only a single algorithm, selected by the user (for each algorithm, there is a special version of the TrueCrypt Boot Loader). + \n\nThe volume cluster bitmap has been scanned and the maximum possible size of the hidden volume has been determined. In the next steps you will set the options, the size, and the password for the hidden volume. + Hidden Volume + The hidden volume is now protected against damage until the outer volume is dismounted.\n\nWARNING: If any data is attempted to be saved to the hidden volume area, TrueCrypt will start write-protecting the entire volume (both the outer and the hidden part) until it is dismounted. This may cause filesystem corruption on the outer volume, which (if repeated) might adversely affect plausible deniability of the hidden volume. Therefore, you should make every effort to avoid writing to the hidden volume area. Any data being saved to the hidden volume area will not be saved and will be lost. Windows may report this as a write error ("Delayed Write Failed" or "The parameter is incorrect"). + Each of the hidden volumes within the newly mounted volumes is now protected against damage until dismounted.\n\nWARNING: If any data is attempted to be saved to protected hidden volume area of any of these volumes, TrueCrypt will start write-protecting the entire volume (both the outer and the hidden part) until it is dismounted. This may cause filesystem corruption on the outer volume, which (if repeated) might adversely affect plausible deniability of the hidden volume. Therefore, you should make every effort to avoid writing to the hidden volume area. Any data being saved to protected hidden volume areas will not be saved and will be lost. Windows may report this as a write error ("Delayed Write Failed" or "The parameter is incorrect"). + WARNING: Data were attempted to be saved to the hidden volume area of the volume mounted as %c:! TrueCrypt prevented these data from being saved in order to protect the hidden volume. This may have caused filesystem corruption on the outer volume and Windows may have reported a write error ("Delayed Write Failed" or "The parameter is incorrect"). The entire volume (both the outer and the hidden part) will be write-protected until it is dismounted. If this is not the first time TrueCrypt has prevented data from being saved to the hidden volume area of this volume, plausible deniability of this hidden volume might be adversely affected (due to possible unusual correlated inconsistencies within the outer volume file system). Therefore, you should consider creating a new TrueCrypt volume (with Quick Format disabled) and moving files from this volume to the new volume; this volume should be securely erased (both the outer and the hidden part). We strongly recommend that you restart the operating system now. + For security reasons, when a hidden operating system is running, you can create only hidden TrueCrypt volumes. + For security reasons, when a hidden operating system is running, hidden volumes can be created only in the 'direct' mode (because outer volumes must always be mounted as read-only). To create a hidden volume securely, follow these steps:\n\n1) Boot the decoy system.\n\n2) Create a normal TrueCrypt volume and, to this volume, copy some sensitive-looking files that you actually do NOT want to hide (the volume will become the outer volume).\n\n3) Boot the hidden system and start the TrueCrypt Volume Creation Wizard. If the volume is file-hosted, move it to the system partition or to another hidden volume (otherwise, the newly created hidden volume would be mounted as read-only and could not be formatted). Follow the instructions in the wizard so as to select the 'direct' hidden volume creation mode.\n\n4) In the wizard, select the volume you created in step 2 and then follow the instructions to create a hidden volume within it. + For security reasons, when a hidden operating system is running, local unencrypted filesystems and non-hidden TrueCrypt volumes are mounted as read-only (no data can be written to such filesystems or TrueCrypt volumes).\n\nData is allowed to be written to any filesystem that resides within a hidden TrueCrypt volume (provided that the hidden volume is not located in a container stored on an unencrypted filesystem or on any other read-only filesystem). + There are three main reasons why such countermeasures have been implemented:\n\n- It enables the creation of a secure platform for mounting of hidden TrueCrypt volumes. Note that we officially recommend that hidden volumes are mounted only when a hidden operating system is running. (For more information, see the subsection 'Security Requirements and Precautions Pertaining to Hidden Volumes' in the documentation.)\n\n- In some cases, it is possible to determine that, at a certain time, a particular filesystem was not mounted under (or that a particular file on the filesystem was not saved or accessed from within) a particular instance of an operating system (e.g. by analyzing and comparing filesystem journals, file timestamps, application logs, error logs, etc). This might indicate that a hidden operating system is installed on the computer. The countermeasures prevent these issues.\n\n- It prevents data corruption and allows safe hibernation. When Windows resumes from hibernation, it assumes that all mounted filesystems are in the same state as when the system entered hibernation. TrueCrypt ensures this by write-protecting any filesystem accessible both from within the decoy and hidden systems. Without such protection, the filesystem could become corrupted when mounted by one system while the other system is hibernated. + Note: If you need to securely transfer files from the decoy system to the hidden system, follow these steps:\n1) Start the decoy system.\n2) Save the files to an unencrypted volume or to an outer/normal TrueCrypt volume.\n3) Start the hidden system.\n4) If you saved the files to a TrueCrypt volume, mount it (it will be automatically mounted as read-only).\n5) Copy the files to the hidden system partition or to another hidden volume. + Your computer must be restarted.\n\nDo you want to restart it now? + An error occurred when obtaining the system encryption status. + Cannot initialize application components for system encryption. + Unable to initialize the application. Failed to create a required mutex object. + Failed to initialize the random number generator! + Unable to initialize the application. Failed to register the Dialog class. + Error: Failed to load the Rich Edit system library. + TrueCrypt Volume Creation Wizard + Maximum possible hidden volume size for this volume is %.2f bytes. + Maximum possible hidden volume size for this volume is %.2f KB. + Maximum possible hidden volume size for this volume is %.2f MB. + Maximum possible hidden volume size for this volume is %.2f GB. + Volume password/keyfiles cannot be changed while the volume is mounted. Please dismount the volume first. + The header key derivation algorithm cannot be changed while the volume is mounted. Please dismount the volume first. + &Mount + A newer version of TrueCrypt is required to mount this volume. + Error: Volume Creation Wizard not found.\n\nPlease make sure that the file 'TrueCrypt Format.exe' is in the folder from which 'TrueCrypt.exe' was launched. If it is not, please reinstall TrueCrypt, or locate 'TrueCrypt Format.exe' on your disk and run it. + &Next > + &Finish + Restart + &Install + E&xtract + Unable to connect to the TrueCrypt device driver. TrueCrypt cannot work if the device driver is not running.\n\nPlease note that, due to a Windows issue, it may be necessary to log off or restart the system before the device driver can be loaded. + Error occurred when loading/preparing fonts. + The drive letter was not found or no drive letter was specified. + Drive letter not available. + No file selected! + No drive letters available. + No free drive letter for the outer volume! Volume creation cannot continue. + Could not determine your operating system version or you are using an unsupported operating system. + No path selected! + Not enough free space for the hidden volume! Volume creation cannot continue. + Error: The files you copied to the outer volume occupy too much space. Therefore, there is not enough free space on the outer volume for the hidden volume.\n\nNote that the hidden volume must be as large as the system partition (the partition where the currently running operating system is installed). The reason is that the hidden operating system needs to be created by copying the content of the system partition to the hidden volume.\n\n\nThe process of creation of the hidden operating system cannot continue. + The driver is unable to dismount the volume. Some files located on the volume are probably still open. + Unable to lock the volume. There are still open files on the volume. Therefore, it cannot be dismounted. + TrueCrypt cannot lock the volume because it is in use by the system or applications (there may be open files on the volume).\n\nDo you want to force dismount on the volume? + Select a TrueCrypt Volume + Specify Path and File Name + Select Path + Select PKCS #11 Library + Out of Memory + IMPORTANT: We strongly recommend that inexperienced users create a TrueCrypt file container on the selected device/partition, instead of attempting to encrypt the entire device/partition.\n\nWhen you create a TrueCrypt file container (as opposed to encrypting a device or partition) there is, for example, no risk of destroying a large number of files. Note that a TrueCrypt file container (even though it contains a virtual encrypted disk) is actually just like any normal file. For more information, see the chapter Beginner's Tutorial in the TrueCrypt User Guide.\n\nAre you sure you want to encrypt the entire device/partition? + WARNING: The file '%hs' already exists!\n\nIMPORTANT: TRUECRYPT WILL NOT ENCRYPT THE FILE, BUT IT WILL DELETE IT. Are you sure you want to delete the file and replace it with a new TrueCrypt container? + CAUTION: ALL FILES CURRENTLY STORED ON THE SELECTED %s '%hs'%s WILL BE ERASED AND LOST (THEY WILL NOT BE ENCRYPTED)!\n\nAre you sure you want to proceed with format? + WARNING: You will not be able to mount the volume or access any files stored on it until it has been fully encrypted.\n\nAre you sure you want to start encrypting the selected %s '%hs'%s? + WARNING: Please note that if power supply is suddenly interrupted while encrypting existing data in place, or when the operating system crashes due to a software error or hardware malfunction while TrueCrypt is encrypting existing data in place, portions of the data will be corrupted or lost. Therefore, before you start encrypting, please make sure that you have backup copies of the files you want to encrypt.\n\nDo you have such a backup? + CAUTION: ANY FILES CURRENTLY STORED ON THE PARTITION '%hs'%s (I.E. ON THE FIRST PARTITION BEHIND THE SYSTEM PARTITION) WILL BE ERASED AND LOST (THEY WILL NOT BE ENCRYPTED)!\n\nAre you sure you want to proceed with format? + WARNING: THE SELECTED PARTITION CONTAINS A LARGE AMOUNT OF DATA! Any files stored on the partition will be erased and lost (they will NOT be encrypted)! + Erase any files stored on the partition by creating a TrueCrypt volume within it + Password + Password and/or keyfile(s) successfully changed.\n\nIMPORTANT: Please make sure you have read the section 'Changing Passwords and Keyfiles' in the chapter 'Security Requirements and Precautions' in the TrueCrypt User Guide. + IMPORTANT: If you did not destroy your TrueCrypt Rescue Disk, your system partition/drive can still be decrypted using the old password (by booting the TrueCrypt Rescue Disk and entering the old password). You should create a new TrueCrypt Rescue Disk and then destroy the old one.\n\nDo you want to create a new TrueCrypt Rescue Disk? + Note that your TrueCrypt Rescue Disk still uses the previous algorithm. If you consider the previous algorithm insecure, you should create a new TrueCrypt Rescue Disk and then destroy the old one.\n\nDo you want to create a new TrueCrypt Rescue Disk? + Any kind of file (for example, .mp3, .jpg, .zip, .avi) may be used as a TrueCrypt keyfile. Note that TrueCrypt never modifies the keyfile contents. You can select more than one keyfile (the order does not matter). If you add a folder, all files found in it will be used as keyfiles. Click 'Add Token Files' to select keyfiles stored on security tokens or smart cards (or to import keyfiles to security tokens or smart cards). + Keyfile(s) successfully added/removed. + Keyfile exported. + Header key derivation algorithm successfully set. + Please enter the password and/or keyfile(s) for the non-system volume where you want to resume the process of in-place encryption.\n\n\nRemark: After you click Next, TrueCrypt will attempt to find all non-system volumes where the process of encryption has been interrupted and where the TrueCrypt volume header can be decrypted using the supplied password and/or keyfile(s). If more than one such volume is found, you will need to select one of them in the next step. + Please select one of the listed volumes. The list contains every accessible non-system volume where the process of encryption has been interrupted and whose header could be decrypted using the supplied password and/or keyfile(s). + It is very important that you choose a good password. You should avoid choosing one that contains only a single word that can be found in a dictionary (or a combination of 2, 3, or 4 such words). It should not contain any names or dates of birth. It should not be easy to guess. A good password is a random combination of upper and lower case letters, numbers, and special characters, such as @ ^ = $ * + etc. We recommend choosing a password consisting of more than 20 characters (the longer, the better). The maximum possible length is 64 characters. + Please choose a password for the hidden volume. + Please choose a password for the hidden operating system (i.e. for the hidden volume). + IMPORTANT: The password that you choose for the hidden operating system in this step must be substantially different from the other two passwords (i.e. from the password for the outer volume and from the password for the decoy operating system). + Please enter the password for the volume within which you wish to create a hidden volume.\n\nAfter you click Next, TrueCrypt will attempt to mount the volume. As soon as the volume is mounted, its cluster bitmap will be scanned to determine the size of the uninterrupted area of free space (if there is any) whose end is aligned with the end of the volume. This area will accommodate the hidden volume and therefore will limit its maximum possible size. Cluster map scanning is necessary to ensure that no data on the outer volume will be overwritten by the hidden volume. + \nPlease choose a password for the outer volume. This will be the password that you will be able to reveal to an adversary if you are asked or forced to do so.\n\nIMPORTANT: The password must be substantially different from the one you will choose for the hidden volume.\n\nNote: The maximum possible password length is 64 characters. + Please choose a password for the outer volume. This will be the password you will be able to reveal to anyone forcing you to disclose the password for the first partition behind the system partition, where both the outer volume and the hidden volume (containing the hidden operating system) will reside. The existence of the hidden volume (and of the hidden operating system) will remain secret. Note that this password is not for the decoy operating system.\n\nIMPORTANT: The password must be substantially different from the one you will choose for the hidden volume (i.e. for the hidden operating system). + Outer Volume Password + Hidden Volume Password + Password for Hidden Operating System + WARNING: Short passwords are easy to crack using brute force techniques!\n\nWe recommend choosing a password consisting of more than 20 characters. Are you sure you want to use a short password? + Volume Password + Incorrect password or not a TrueCrypt volume. + Incorrect keyfile(s) and/or password or not a TrueCrypt volume. + Wrong mount mode, incorrect password, or not a TrueCrypt volume. + Wrong mount mode, incorrect keyfile(s) and/or password, or not a TrueCrypt volume. + Incorrect password or no TrueCrypt volume found. + Incorrect keyfile(s)/password or no TrueCrypt volume found. + \n\nWarning: Caps Lock is on. This may cause you to enter your password incorrectly. + If you are attempting to protect a hidden volume containing a hidden system, please make sure you are using the standard US keyboard layout when typing the password for the hidden volume. This is required due to the fact that the password needs to be typed in the pre-boot environment (before Windows starts) where non-US Windows keyboard layouts are not available. + TrueCrypt has not found any volume where non-system encryption has been interrupted and where the volume header can be decrypted using the supplied password and/or keyfile(s).\n\nPlease make sure the password and/or keyfile(s) are correct and that the partition/volume is not being used by the system or applications (including antivirus software). + \n\nNote: If you are attempting to mount a partition located on an encrypted system drive without pre-boot authentication or to mount the encrypted system partition of an operating system that is not running, you can do so by selecting 'System' > 'Mount Without Pre-Boot Authentication'. + In this mode, you cannot mount a partition located on a drive whose portion is within the key scope of active system encryption.\n\nBefore you can mount this partition in this mode, you need to either boot an operating system installed on a different drive (encrypted or unencrypted) or boot an unencrypted operating system. + < &Back + Unable to list raw devices installed on your system! + The volume '%hs' exists, and is read-only. Are you sure you want to replace it? + Select destination directory + Select Keyfile + Select a keyfile search path. WARNING: Note that only the path will be remembered, not the filenames! + 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. + WARNING: Failed to restore container timestamp (file modification/access date/time)!\n\nThe plausible deniability of the hidden volume might be affected. + WARNING: Failed to restore container timestamp!\n\nIf you do not reset the timestamp using an external tool, we recommend that you do not create a hidden volume within this container. + WARNING: Failed to restore container timestamp (file modification/access date/time)!\n\nIf there is a hidden volume within this container, the plausible deniability of the hidden volume might be affected. + WARNING: Failed to restore keyfile timestamp! Cannot preserve last access date/time.\n\nIt will be possible to tell that this file has been accessed. + 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 275 KB. The minimum possible size of an NTFS volume is 2829 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 305 KB. + Please specify the size of the hidden volume to create. The minimum possible size of a hidden volume is 23 KB (or 2701 KB if it is formatted as NTFS). The maximum possible size you can specify for the hidden volume is displayed above. + Outer Volume Size + Hidden Volume Size + Please verify that the size of the selected device/partition shown above is correct and click Next. + The outer volume and the hidden volume (containing the hidden operating system) will reside within the above partition. It should be the first partition behind the system partition.\n\nPlease verify that the size of the partition and its number shown above are correct, and if they are, click Next. + \n\nNote that the minimum possible size of a volume within which a hidden volume is intended to be created is 305 KB. + Volume Size + Dynamic + CAUTION: SELF-TEST FAILED! + Self-tests of all algorithms passed + The data unit number that you supplied is too long or short. + The secondary key that you supplied is too long or short. + The test ciphertext you have supplied is too long or short. + The test key you have supplied is too long or short. + The test plaintext you have supplied is too long or short. + Two ciphers in a cascade operating in XTS mode. Each block is first encrypted with %hs (%d-bit key) and then with %hs (%d-bit key). Each cipher uses its own key. All keys are mutually independent. + Three ciphers in a cascade operating in XTS mode. Each block is first encrypted with %hs (%d-bit key), then with %hs (%d-bit key), and finally with %hs (%d-bit key). Each cipher uses its own key. All keys are mutually independent. + Note that, depending on the operating system configuration, these auto-run and auto-mount features may work only when the traveler disk files are created on a non-writable CD/DVD-like medium. Also note that this is not a bug in TrueCrypt (it is a limitation of Windows). + TrueCrypt traveler disk has been successfully created.\n\nNote that you need administrator privileges to run TrueCrypt in portable mode. Also note that, after examining the registry file, it may be possible to tell that TrueCrypt was run on a Windows system even if it is run in portable mode. + TrueCrypt Traveler Disk + Designed by Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson. Published in 1998. 256-bit key, 128-bit block. Mode of operation is XTS. Twofish was one of the AES finalists. + More information on %hs + Unknown + An unspecified or unknown error occurred. + The device driver returned an unrecognized error, code = %d + Some volumes contain files or folders being used by applications or system.\n\nForce dismount? + &Dismount + Dismount failed! + Volume contains files or folders being used by applications or system.\n\nForce dismount? + The volume you are trying to mount is already mounted. + The format of this volume not recognized. The volume might be corrupted. + An error occurred when attempting to mount volume. + Error seeking location within volume. + Error: Incorrect volume size. + The volume is too small - it is an invalid volume. + WARNING: You should use Quick Format only in the following cases:\n\n1) The device contains random data (e.g. has already been securely and fully encrypted).\n2) You are going to use all available space immediately.\n3) You are not concerned with security (testing).\n\nAre you sure you want to use Quick Format? + Dynamic container is a pre-allocated NTFS sparse file whose physical size (actual disk space used) grows as new data is added to it.\n\nWARNING: Performance of sparse-file-hosted volumes is significantly worse than performance of regular volumes. Sparse-file-hosted volumes are also less secure, because it is possible to tell which volume sectors are unused. Furthermore, sparse-file-hosted volumes cannot provide plausible deniability (host a hidden volume). Also note that if data is written to a sparse file container when there is not enough free space in the host file system, the encrypted file system may get corrupted.\n\nAre you sure you want to create a sparse-file-hosted volume? + Note that the size of the dynamic container reported by Windows and by TrueCrypt will always be equal to its maximum size. To find out current physical size of the container (actual disk space it uses), right-click the container file (in a Windows Explorer window, not in TrueCrypt), then select 'Properties' and see the 'Size on disk' value. + Passwords stored in the device driver cache have been wiped. + TrueCrypt cannot change the password for a foreign volume. + Please select a free drive letter from the list. + Please select a mounted volume in the drive letter list. + Error: Cannot create autorun.inf + Error while processing keyfile! + Error processing keyfile path! + TrueCrypt does not support this operating system. + Error: TrueCrypt supports only stable versions of this operating system (beta/RC versions are not supported). + Error: Cannot allocate memory. + Error: Could not retrieve value of performance counter. + Error: Bad volume format. + Error: You supplied a password for a hidden volume (not for a normal volume). + For security reasons, a hidden volume cannot be created within a TrueCrypt volume containing a filesystem that has been encrypted in place (because the free space on the volume has not been filled with random data). + TrueCrypt - Legal Notices + All Files + TrueCrypt Volumes + Library Modules + NTFS formatting cannot continue. + Cannot mount volume. + Cannot dismount volume. + Windows failed to format the volume as NTFS.\n\nPlease select a different type of file system (if possible) and try again. Alternatively, you could leave the volume unformatted (select 'None' as the filesystem), exit this wizard, mount the volume, and then use either a system or a third-party tool to format the mounted volume (the volume will remain encrypted). + Windows failed to format the volume as NTFS.\n\nDo you want to format the volume as FAT instead? + Default + sector + block + Partition + partition + PARTITION + Device + device + DEVICE + Volume + volume + VOLUME + The selected cluster size is too small for this volume size. A greater cluster size will be used instead. + Error: Cannot get volume size!\n\nMake sure the selected volume is not being used by the system or an application. + Hidden volumes shall not be created within dynamic (sparse file) containers. To achieve plausible deniability, the hidden volume shall be created within a regular volume. + The TrueCrypt Volume Creation Wizard can create a hidden volume only within a FAT or NTFS volume. + Under Windows 2000, the TrueCrypt Volume Creation Wizard can create a hidden volume only within a FAT volume. + Note: The FAT file system is more suitable for outer volumes than the NTFS file system (for example, the maximum possible size of the hidden volume would very likely have been significantly greater if the outer volume had been formatted as FAT). + Note that the FAT file system is more suitable for outer volumes than the NTFS file system. For example, the maximum possible size of the hidden volume will very likely be significantly greater if the outer volume is formatted as FAT (the reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume can reside only in the second half of the outer volume).\n\nAre you sure you want to format the outer volume as NTFS? + Do you want to format the volume as FAT instead? + Error: The partition for the hidden operating system (i.e. the first partition behind the system partition) must be at least 5% larger than the system partition (the system partition is the one where the currently running operating system is installed). + Error: The partition for the hidden operating system (i.e. the first partition behind the system partition) must be at least 110% (2.1 times) larger than the system partition (the system partition is the one where the currently running operating system is installed). The reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume (which is to contain a clone of the system partition) can reside only in the second half of the partition. + Error: If the outer volume is formatted as NTFS, it must be at least 110% (2.1 times) larger than the system partition. The reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume (which is to contain a clone of the system partition) can reside only in the second half of the outer volume.\n\nNote: The outer volume needs to reside within the same partition as the hidden operating system (i.e. within the first partition behind the system partition). + Error: There is no partition behind the system partition.\n\nNote that before you can create a hidden operating system, you need to create a partition for it on the system drive. It must be the first partition behind the system partition and it must be at least 5% larger than the system partition (the system partition is the one where the currently running operating system is installed). However, if the outer volume (not to be confused with the system partition) is formatted as NTFS, the partition for the hidden operating system must be at least 110% (2.1 times) larger than the system partition (the reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume, which is to contain a clone of the system partition, can reside only in the second half of the partition). + Remark: It is not practical (and therefore is not supported) to install operating systems in two TrueCrypt volumes that are embedded within a single partition, because using the outer operating system would often require data to be written to the area of the hidden operating system (and if such write operations were prevented using the hidden volume protection feature, it would inherently cause system crashes, i.e. 'Blue Screen' errors). + For information on how to create and manage partitions, please refer to the documentation supplied with your operating system or contact your computer vendor's technical support team for assistance. + Error: The currently running operating system is not installed on the boot partition (first Active partition). This is not supported. + You indicated that you intend to store files larger than 4 GB in this TrueCrypt volume. However, you chose the FAT file system, on which files larger than 4 GB cannot be stored.\n\nAre you sure you want to format the outer volume as FAT? + Error: Cannot access the volume!\n\nMake sure that the selected volume exists, that it is not mounted or being used by the system or an application, that you have read/write permission for the volume, and that it is not write-protected. + Error: Cannot access the volume and/or obtain information about the volume.\n\nMake sure that the selected volume exists, that it is not being used by the system or applications, that you have read/write permission for the volume, and that it is not write-protected. + Error: Cannot access the volume and/or obtain information about the volume. Make sure that the selected volume exists, that it is not being used by the system or applications, that you have read/write permission for the volume, and that it is not write-protected.\n\nIf the problem persists, it might help to follow the below steps. + An error prevented TrueCrypt from encrypting the partition. Please try fixing any previously reported problems and then try again. If the problems persist, it might help to follow the below steps. + An error prevented TrueCrypt from resuming the process of encryption of the partition.\n\nPlease try fixing any previously reported problems and then try resuming the process again. Note that the volume cannot be mounted until it has been fully encrypted. + Error: Cannot dismount the outer volume!\n\nVolume cannot be dismounted if it contains files or folders being used by a program or the system.\n\nPlease close any program that might be using files or directories on the volume and click Retry. + Error: Cannot obtain information about the outer volume!\nVolume creation cannot continue. + Error: Cannot access the outer volume! Volume creation cannot continue. + Error: Cannot mount the outer volume! Volume creation cannot continue. + Error: Cannot get volume cluster bitmap! Volume creation cannot continue. + Alphabetical/Categorized + Mean Speed (Descending) + Algorithm + Encryption + Decryption + Mean + Drive + Size + Encryption Algorithm + Encryption algorithm + Type + Value + Property + Location + bytes + Hidden + Outer + Normal + System + System + Hidden (system) + Read-Only + Hidden Volume + System drive + System drive (encrypting - %.2f%% done) + System drive (decrypting - %.2f%% done) + System drive (%.2f%% encrypted) + System partition + Hidden system partition + System partition (encrypting - %.2f%% done) + System partition (decrypting - %.2f%% done) + System partition (%.2f%% encrypted) + Yes (damage prevented!) + None + Active + Primary Key Size + Secondary Key Size (XTS Mode) + Tweak Key Size (LRW Mode) + bits + Block Size + Mode + PKCS-5 PRF + PKCS-5 Iteration Count + Volume Created + Header Last Modified + (%I64d days ago) + Volume Format Version + Embedded Backup Header + First available + removable + Removable Disk + Harddisk + Unchanged + Wizard Mode + Select one of the modes. If you are not sure which to select, use the default mode. + Select this option if you want to install TrueCrypt on this system. + Select this option if you want to upgrade TrueCrypt on this system. Note that you can do so even if the system partition/drive is encrypted. + If you select this option, all files will be extracted from this package but nothing will be installed on the system. Do not select it if you intend to encrypt the system partition or system drive. Selecting this option can be useful, for example, if you want to run TrueCrypt in so-called portable mode. TrueCrypt does not have to be installed on the operating system under which it is run. After all files are extracted, you can directly run the extracted file 'TrueCrypt.exe' (then TrueCrypt will run in portable mode). + Setup Options + Here you can set various options to control the installation process. + Installing + Please wait while TrueCrypt is being installed. + TrueCrypt Installed + TrueCrypt has been successfully installed. You can click Finish and run TrueCrypt now. + TrueCrypt has been successfully installed. + Extraction Options + Here you can set various options to control the extraction process. + Please wait while files are being extracted. + Extraction Complete + All files have been successfully extracted to the destination location. + If the specified folder does not exist, it will be automatically created. + Do you want to view release notes for the current (latest stable) version of TrueCrypt? + If you have never used TrueCrypt before, we recommend that you read the chapter Beginner's Tutorial in the TrueCrypt User Guide. Do you want to view the tutorial? + Please select an action to perform from the following: + Repair/Reinstall + Upgrade + Uninstall + Please select installation directory + To successfully install/uninstall TrueCrypt, you must have administrator privileges. Do you want to continue? + TrueCrypt Installer is currently running on this system and performing or preparing installation or update of TrueCrypt. Before you proceed, please wait for it to finish or close it. If you cannot close it, please restart your computer before proceeding. + Installation failed. + Uninstallation failed. + This distribution package is damaged. Please try downloading it again (preferably from the official TrueCrypt website at www.truecrypt.org). + Cannot write file %hs + Extracting + Cannot read data from the package. + Cannot verify the integrity of this distribution package. + Extraction failed. + The installation has been rolled back. + TrueCrypt has been successfully installed. + TrueCrypt has been successfully updated. + TrueCrypt has been upgraded to a new version. Before you can start using it, your computer must be restarted.\n\nDo you want to restart it now? + TrueCrypt has been successfully uninstalled.\n\nClick 'Finish' to remove the TrueCrypt installer and the folder %hs. Note that the folder will not be removed if it contains any files that were not installed by the TrueCrypt installer or created by TrueCrypt. + Removing TrueCrypt registry entries + Adding registry entry + Removing application-specific data + Installing + Copying + Stopping + Removing + Service + Adding icon + Creating System Restore point + Failed to create System Restore point! + Updating boot loader + Failed to install '%hs'. %hs\nDo you want to continue installing? + Failed to uninstall '%hs'. %hs\nDo you want to continue uninstalling? + Installation completed. + The folder '%hs' could not be created + The TrueCrypt device driver cannot be unloaded.\n\nPlease close all open TrueCrypt windows first. If it does not help, please restart Windows and then try again. + All TrueCrypt volumes must be dismounted before installing or uninstalling TrueCrypt. + An obsolete version of TrueCrypt is currently installed on this system. It needs to be uninstalled before you can install this new version of TrueCrypt.\n\nAs soon as you close this message box, the uninstaller of the old version will be launched. After you uninstall the old version of TrueCrypt, run the installer of the new version of TrueCrypt again. + The installation of the registry entries has failed + The installation of the device driver has failed. Please restart Windows and then try installing TrueCrypt again. + Starting TrueCrypt device driver + Uninstallation of the device driver has failed. Please note that, due to a Windows issue, it may be necessary to log off or restart the system before the device driver can be uninstalled (or reinstalled). + Installing TrueCrypt device driver + Stopping TrueCrypt device driver + Uninstalling TrueCrypt device driver + Registration of the User Account Control support library failed. + Unregistration of the User Account Control support library failed. + Note that if you decide to run TrueCrypt in portable mode (as opposed to running an installed copy of TrueCrypt), the system will ask you for permission to run TrueCrypt (UAC prompt) every time you attempt to run it.\n\nThe reason is that when you run TrueCrypt in portable mode, TrueCrypt needs to load and start the TrueCrypt device driver. TrueCrypt needs a device driver to provide transparent on-the-fly encryption/decryption, and users without administrator privileges cannot start device drivers in Windows. Therefore, the system will ask you for permission to run TrueCrypt with administrator privileges (UAC prompt).\n\nNote that if you install TrueCrypt on the system (as opposed to running TrueCrypt in portable mode), the system will NOT ask you for permission to run TrueCrypt (UAC prompt) every time you attempt to run it.\n\nAre you sure you want to extract the files? + Warning: This instance of the Volume Creation Wizard has administrator privileges.\n\nYour new volume may be created with permissions that will not allow you to write to the volume when it is mounted. If you want to avoid that, close this instance of the Volume Creation Wizard and launch a new one without administrator privileges.\n\nDo you want to close this instance of the Volume Creation Wizard? + Error: Cannot display license. + Outer(!) + days + hours + minutes + s + Open + Dismount + Show TrueCrypt + Hide TrueCrypt + Data Read since Mount + Data Written since Mount + Encrypted Portion + 100% (fully encrypted) + 0% (not encrypted) + %.3f%% + 100% + Waiting + Preparing + Resizing + Encrypting + Decrypting + Finalizing + Paused + Finished + Error + Favorite volumes saved. + System favorite volumes saved.\n\nTo enable mounting of system favorite volumes when the system starts, please select 'Settings' > 'System Favorite Volumes' > 'Mount system favorite volumes when Windows starts'. + Enter password for %hs + 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. + WARNING: The header of this volume is damaged! TrueCrypt 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. + For security reasons, you will have to enter the correct password (and/or supply the correct keyfiles) for the volume.\n\nNote: If the volume contains a hidden volume, you will have to enter the correct password (and/or supply the correct keyfiles) for the outer volume first. Afterwards, if you choose to back up the header of the hidden volume, you will have to enter the correct password (and/or supply the correct keyfiles) for the hidden volume. + Are you sure you want to create volume header backup for %hs?\n\nAfter you click Yes, you will prompted for a filename for the header backup.\n\nNote: Both the standard and the hidden volume headers will be re-encrypted using a new salt and stored in the backup file. If there is no hidden volume within this volume, the area reserved for the hidden volume header in the backup file will be filled with random data (to preserve plausible deniability). When restoring a volume header from the backup file, you will need to enter the correct password (and/or to supply the correct keyfiles) that was/were valid when the volume header backup was created. The password (and/or keyfiles) will also automatically determine the type of the volume header to restore, i.e. standard or hidden (note that TrueCrypt determines the type through the process of trial and error). + Are you sure you want to restore volume header of %hs?\n\nWARNING: Restoring a volume header also restores the volume password that was valid when the backup was created. Moreover, if keyfile(s) were/was necessary to mount the volume when the backup was created, the same keyfile(s) will be necessary to mount the volume again after the volume header is restored.\n\nAfter you click Yes, you will select the header backup file. + Does the volume contain a hidden volume? + The volume contains a hidden volume + The volume does not contain a hidden volume + Please select the type of volume header backup you want to use: + Restore the volume header from the backup embedded in the volume + Restore the volume header from an external backup file + The size of the volume header backup file is incorrect. + There is no backup header embedded in this volume (note that only volumes created by TrueCrypt 6.0 or later contain embedded backup headers). + You are attempting to back up the header of the system partition/drive. This is not allowed. Backup/restore operations pertaining to the system partition/drive can be performed only using the TrueCrypt Rescue Disk.\n\nDo you want to create a TrueCrypt Rescue Disk? + You are attempting to restore the header of a virtual TrueCrypt volume but you selected the system partition/drive. This is not allowed. Backup/restore operations pertaining to the system partition/drive can be performed only using the TrueCrypt Rescue Disk.\n\nDo you want to create a TrueCrypt Rescue Disk? + After you click OK, you will select a filename for the new TrueCrypt Rescue Disk ISO image and the location where you wish to place it. + The Rescue Disk image has been created and stored in this file:\n%hs\n\nNow you need to burn the Rescue Disk image to a CD or DVD.\n\nIMPORTANT: Note that the file must be written to the CD/DVD as an ISO disk image (not as an individual file). For information on how to do so, please refer to the documentation of your CD/DVD recording software.\n\nAfter you burn the Rescue Disk, select 'System' > 'Verify Rescue Disk' to verify that it has been correctly burned. + The Rescue Disk image has been created and stored in this file:\n%hs\n\nNow you need to burn the Rescue Disk image to a CD or DVD.\n\nDo you want to launch the Microsoft Windows Disc Image Burner now?\n\nNote: After you burn the Rescue Disk, select 'System' > 'Verify Rescue Disk' to verify that it has been correctly burned. + Please insert your TrueCrypt Rescue Disk into your CD/DVD drive and click OK to verify it. + The TrueCrypt Rescue Disk has been successfully verified. + Cannot verify that the Rescue Disk has been correctly burned.\n\nIf you have burned the Rescue Disk, please eject and reinsert the CD/DVD; then try again. If this does not help, please try other CD/DVD recording software and/or medium.\n\nIf you attempted to verify a TrueCrypt Rescue Disk created for a different master key, password, salt, etc., please note that such Rescue Disk will always fail this verification. To create a new Rescue Disk fully compatible with your current configuration, select 'System' > 'Create Rescue Disk'. + Error creating TrueCrypt Rescue Disk. + TrueCrypt Rescue Disk cannot be created when a hidden operating system is running.\n\nTo create a TrueCrypt Rescue Disk, boot the decoy operating system and then select 'System' > 'Create Rescue Disk'. + Cannot verify that the Rescue Disk has been correctly burned.\n\nIf you have burned the Rescue Disk, please eject and reinsert the CD/DVD; then click Next to try again. If this does not help, please try another medium%s.\n\nIf you have not burned the Rescue Disk yet, please do so, and then click Next.\n\nIf you attempted to verify a TrueCrypt Rescue Disk created before you started this wizard, please note that such Rescue Disk cannot be used, because it was created for a different master key. You need to burn the newly generated Rescue Disk. + and/or other CD/DVD recording software + The system partition/drive does not appear to be encrypted.\n\nSystem favorite volumes can be mounted using only a pre-boot authentication password. Therefore, to enable use of system favorite volumes, you need to encrypt the system partition/drive first. + Save all currently mounted volumes and their drive letters to the Favorite Volumes list?\n\nNote: If no volumes are mounted, the Favorite Volumes list will be deleted. + Save all currently mounted volumes and their drive letters to the System Favorite Volumes list?\n\nNote: If no volumes are mounted, the System Favorite Volumes list will be deleted. + Please dismount the volume before proceeding. + Error: Cannot set timer. + Check Filesystem + Repair Filesystem + P&roperties + Hidden Volume Protected + N/A + Yes + No + 1 + 2 or more + Mode of Operation + Label: + Size: + Path: + Drive Letter: + Error: Password must contain only ASCII characters.\n\nNon-ASCII characters in password might cause the volume to be impossible to mount when your system configuration changes.\n\nThe following characters are allowed:\n\n ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \\ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w k y z { | } ~ + Warning: Password contains non-ASCII characters. This may cause the volume to be impossible to mount when your system configuration changes.\n\nYou should replace all non-ASCII characters in the password with ASCII characters. To do so, click 'Volumes' -> 'Change Volume Password'.\n\nThe following are ASCII characters:\n\n ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \\ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w k y z { | } ~ + WARNING: We strongly recommend that you avoid file extensions that are used for executable files (such as .exe, .sys, or .dll) and other similarly problematic file extensions. Using such file extensions causes Windows and antivirus software to interfere with the container, which adversely affects the performance of the volume and may also cause other serious problems.\n\nWe strongly recommend that you remove the file extension or change it (e.g., to '.tc').\n\nAre you sure you want to use the problematic file extension? + WARNING: This container has a file extension that is used for executable files (such as .exe, .sys, or .dll) or some other file extension that is similarly problematic. It will very likely cause Windows and antivirus software to interfere with the container, which will adversely affect the performance of the volume and may also cause other serious problems.\n\nWe strongly recommend that you remove the file extension of the container or change it (e.g., to '.tc') after you dismount the volume. + Homepage + WARNING: It appears that you have not applied any Service Pack to your Windows installation. You should not write to IDE disks larger than 128 GB under Windows XP to which you did not apply Service Pack 1 or later! If you do, data on the disk (no matter if it is a TrueCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in TrueCrypt. + WARNING: It appears that you have not applied Service Pack 3 or later to your Windows installation. You should not write to IDE disks larger than 128 GB under Windows 2000 to which you did not apply Service Pack 3 or later! If you do, data on the disk (no matter if it is a TrueCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in TrueCrypt.\n\nNote: You may also need to enable the 48-bit LBA support in the registry; for more information, see http://support.microsoft.com/kb/305098/EN-US + WARNING: 48-bit LBA ATAPI support is disabled on your system. Therefore, you should not write to IDE disks larger than 128 GB! If you do, data on the disk (no matter if it is a TrueCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a limitation of TrueCrypt.\n\nTo enable the 48-bit LBA support, add the 'EnableBigLba' registry value in the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\atapi\\Parameters and set it to 1.\n\nFor more information, see http://support.microsoft.com/kb/305098 + Error: Files larger than 4 GB cannot be stored on a FAT32 file system. Therefore, file-hosted TrueCrypt volumes (containers) stored on a FAT32 file system cannot be larger than 4 GB.\n\nIf you need a larger volume, create it on an NTFS file system (or, if you use Windows Vista SP1 or later, on an exFAT file system) or, instead of creating a file-hosted volume, encrypt an entire partition or device. + WARNING: If you want to be able to add more data/files to the outer volume in future, you should consider choosing a smaller size for the hidden volume.\n\nAre you sure you want to continue with the size you specified? + No volume selected.\n\nClick 'Select Device' or 'Select File' to select a TrueCrypt volume. + No partition selected.\n\nClick 'Select Device' to select a dismounted partition that normally requires pre-boot authentication (for example, a partition located on the encrypted system drive of another operating system, which is not running, or the encrypted system partition of another operating system).\n\nNote: The selected partition will be mounted as a regular TrueCrypt volume without pre-boot authentication. This is useful e.g. for backup or repair operations. + WARNING: If default keyfiles are set and enabled, volumes that are not using these keyfiles will be impossible to mount. Therefore, after you enable default keyfiles, keep in mind to uncheck the 'Use keyfiles' checkbox (below a password input field) whenever mounting such volumes.\n\nAre you sure you want to save the selected keyfiles/paths as default? + Auto-Mount Devices + Dismount All + Wipe Cache + Dismount All & Wipe Cache + Force Dismount All & Wipe Cache + Force Dismount All, Wipe Cache & Exit + Mount Favorite Volumes + Show/Hide Main TrueCrypt Window + (Click here and press a key) + Action + Shortcut + Error: This shortcut is reserved. Please choose a different shortcut. + Error: Shortcut already in use. + WARNING: One or more TrueCrypt system-wide hot keys will not work!\n\nPlease make sure that other applications and the operating system do not use the same shortcut(s) as TrueCrypt. + An error or incompatibility prevents TrueCrypt from encrypting the hibernation file. Therefore, hibernation has been prevented.\n\nNote: When a computer hibernates (or enters a power-saving mode), the content of its system memory is written to a hibernation storage file residing on the system drive. TrueCrypt would not be able to prevent encryption keys and the contents of sensitive files opened in RAM from being saved unencrypted to the hibernation storage file. + Hibernation has been prevented.\n\nTrueCrypt does not support hibernation on hidden operating systems that use an extra boot partition. Please note that the boot partition is shared by both the decoy and the hidden system. Therefore, in order to prevent data leaks and problems while resuming from hibernation, TrueCrypt has to prevent the hidden system from writing to the shared boot partition and from hibernating. + All mounted TrueCrypt volumes have been dismounted. + Attempt to dismount all mounted TrueCrypt volumes completed. + All mounted TrueCrypt volumes have been dismounted and password cache has been wiped. + WARNING: If timestamps are not preserved, plausible deniability of hidden volumes may be adversely affected!\n\nAre you sure you do not want container timestamps to be preserved? + WARNING: If the TrueCrypt Background Task is disabled, the following functions will be disabled whenever you exit TrueCrypt:\n\n1) Hot keys\n2) Auto-dismount (e.g., upon log off, inadvertent host device removal, time-out, etc.)\n3) Notifications (e.g., when damage to hidden volume is prevented)\n4) Tray icon\n\nNote: You may shut down the Background Task anytime by right-clicking the TrueCrypt tray icon and selecting 'Exit'.\n\nAre you sure you want to disable the TrueCrypt Background Task? + WARNING: If this option is disabled, volumes containing open files/directories will not be possible to auto-dismount.\n\nAre you sure you want to disable this option? + WARNING: Volumes containing open files/directories will NOT be auto-dismounted.\n\nTo prevent this, enable the following option in this dialog window: 'Force auto-dismount even if volume contains open files or directories' + WARNING: When the notebook battery power is low, Windows may omit sending the appropriate messages to running applications when the computer is entering power saving mode. Therefore, TrueCrypt may fail to auto-dismount volumes in such cases. + You have scheduled the process of encryption of a partition/volume. The process has not been completed yet.\n\nDo you want to resume the process now? + You have scheduled the process of encryption or decryption of the system partition/drive. The process has not been completed yet.\n\nDo you want to start (resume) the process now? + Do you want to be prompted about whether you want to resume the currently scheduled processes of encryption of non-system partitions/volumes? + Yes, keep prompting me + No, do not prompt me + IMPORTANT: Keep in mind that you can resume the process of encryption of any non-system partition/volume by selecting 'Volumes' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. + You have scheduled the process of encryption or decryption of the system partition/drive. However, pre-boot authentication failed (or was bypassed).\n\nNote: If you decrypted the system partition/drive in the pre-boot environment, you may need to finalize the process by selecting 'System' > 'Permanently Decrypt System Partition/Drive' from the menu bar of the main TrueCrypt window. + WARNING: If TrueCrypt exits now, the following functions will be disabled:\n\n1) Hot keys\n2) Auto-dismount (e.g., upon log off, inadvertent host device removal, time-out, etc.)\n3) Notifications (e.g., when damage to hidden volume is prevented)\n\nNote: If you do not wish TrueCrypt to run in the background, disable the TrueCrypt Background Task in the Preferences (and, if necessary, disable the automatic start of TrueCrypt in the Preferences).\n\nAre you sure you want TrueCrypt to exit? + Exit? + TrueCrypt does not have sufficient information to determine whether to encrypt or decrypt. + TrueCrypt does not have sufficient information to determine whether to encrypt or decrypt.\n\nNote: If you decrypted the system partition/drive in the pre-boot environment, you may need to finalize the process by clicking Decrypt. + Do you want to interrupt and postpone the process of encryption of the partition/volume?\n\nNote: Keep in mind that the volume cannot be mounted until it has been fully encrypted. You will be able to resume the process of encryption and it will continue from the point it was stopped. You can do so, for example, by selecting 'Volumes' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. + Do you want to interrupt and postpone the process of encryption of the system partition/drive?\n\nNote: You will be able to resume the process and it will continue from the point it was stopped. You can do so, for example, by selecting 'System' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. If you want to permanently terminate or reverse the encryption process, select 'System' > 'Permanently Decrypt System Partition/Drive'. + Do you want to interrupt and postpone the process of decryption of the system partition/drive?\n\nNote: You will be able to resume the process and it will continue from the point it was stopped. You can do so, for example, by selecting 'System' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. If you want to reverse the decryption process (and start encrypting), select 'System' > 'Encrypt System Partition/Drive'. + Error: Failed to interrupt the process of encryption/decryption of the system partition/drive. + Error: Failed to interrupt the process of wiping. + Error: Failed to resume the process of encryption/decryption of the system partition/drive. + Error: Failed to start the process of wiping. + Inconsistency resolved.\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n%hs) + Error: Unexpected state.\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n%hs) + There is no process/task to resume. + WARNING: TrueCrypt Background Task is disabled. After you exit TrueCrypt, you will not be notified if damage to hidden volume is prevented.\n\nNote: You may shut down the Background Task anytime by right-clicking the TrueCrypt tray icon and selecting 'Exit'.\n\nEnable TrueCrypt Background Task? + Language pack version: %s + Checking the file system on the TrueCrypt volume mounted as %hs... + Attempting to repair the file system on the TrueCrypt volume mounted as %hs... + Warning: This volume is encrypted in CBC mode. Due to security issues, CBC mode has been deprecated since TrueCrypt 4.1.\n\nWe strongly recommend that you move data from this TrueCrypt volume to a new volume created by this version of TrueCrypt. After you do so, you should securely erase or destroy the old volume. For more information, please see the Version History in the documentation or the release notices distributed with TrueCrypt 4.1 or later. + Warning: This volume is encrypted with a legacy encryption algorithm.\n\nAll 64-bit-block encryption algorithms (e.g., Blowfish, CAST-128, or Triple DES) are deprecated. It will be possible to mount this volume using future versions of TrueCrypt. However, there will be no further enhancements to the implementations of these legacy encryption algorithms. We recommend that you create a new TrueCrypt volume encrypted with a 128-bit-block encryption algorithm (e.g., AES, Serpent, Twofish, etc.) and that you move all files from this volume to the new volume. + Your system is not configured to auto-mount new volumes. It may be impossible to mount device-hosted TrueCrypt volumes. Auto-mounting can be enabled by executing the following command and restarting the system.\n\nmountvol.exe /E + Please assign a drive letter to the partition/device before proceeding ('Control Panel' > 'System and Maintenance' > 'Administrative Tools' - 'Create and format hard disk partitions').\n\nNote that this is a requirement of the operating system. + Mount TrueCrypt volume + Dismount all TrueCrypt volumes + TrueCrypt failed to obtain Administrator privileges. + Access was denied by the operating system.\n\nPossible cause: The operating system requires that you have read/write permission (or administrator privileges) for certain folders, files, and devices, in order for you to be allowed to read and write data to/from them. Normally, a user without administrator privileges is allowed to create, read and modify files in his or her Documents folder. + Error: The device uses a sector size other than 512 bytes.\n\nIt is currently not possible to create device-hosted volumes on devices that use a sector size other than 512 bytes. However, note that you can create a file-hosted volume (container) on this device. + Error: Unsupported sector size. + The TrueCrypt Boot Loader requires at least 32 KBytes of free space at the beginning of the system drive (the TrueCrypt Boot Loader needs to be stored in that area). Unfortunately, your drive does not meet this condition.\n\nPlease do NOT report this as a bug/problem in TrueCrypt. To solve this problem, you will need to repartition your disk and leave the first 32 KBytes of the disk free (in most cases, you will need to delete and recreate the first partition). We recommend that you use the Microsoft partition manager that is available e.g. when you are installing Windows. + The feature is not supported on the version of the operating system you are currently using. + TrueCrypt does not support encryption of a system partition/drive on the version of the operating system you are currently using. + Before you can encrypt the system partition/drive on Windows Vista, you need to install Service Pack 1 or higher for Windows Vista (no such Service Pack has been installed on this system yet).\n\nNote: Service Pack 1 for Windows Vista resolved an issue causing a shortage of free base memory during system boot. + Please note that Service Pack 1 for Windows Vista resolved an issue that caused a shortage of free base memory during system boot. TrueCrypt 6.2 and later versions have been designed to take advantage of this improvement. Therefore, we recommend you to install Service Pack 1 or higher before upgrading TrueCrypt.\n\nDo you want to upgrade TrueCrypt now? + Error: This feature requires TrueCrypt to be installed on the system (you are running TrueCrypt in portable mode).\n\nPlease install TrueCrypt and then try again. + WARNING: Windows does not appear to be installed on the drive from which it boots. This is not supported.\n\nYou should continue only if you are sure that Windows is installed on the drive from which it boots.\n\nDo you want to continue? + Your system drive has a GUID partition table (GPT). Currently, only drives with a MBR partition table are supported. + CAUTION: The TrueCrypt Boot Loader is already installed on your system drive!\n\nIt is possible that another system on your computer is already encrypted.\n\nWARNING: PROCEEDING WITH ENCRYPTION OF THE CURRENTLY RUNNING SYSTEM MAY MAKE OTHER SYSTEM(S) IMPOSSIBLE TO START AND RELATED DATA INACCESSIBLE.\n\nAre you sure you want to continue? + Failed to restore the original system loader.\n\nPlease use your TrueCrypt Rescue Disk ('Repair Options' > 'Restore original system loader') or Windows installation medium to replace the TrueCrypt Boot Loader with the Windows system loader. + The original system loader will not be stored on the Rescue Disk (probable cause: missing backup file). + Failed to write the MBR sector.\n\nYour BIOS may be configured to protect the MBR sector. Check your BIOS settings (press F2, Delete, or Esc, after powering on your computer) for MBR/antivirus protection. + The required version of the TrueCrypt Boot Loader is currently not installed. This may prevent some of the settings from being saved. + Note: In some situations, you may wish to prevent a person (adversary) that is watching you start the computer from knowing that you use TrueCrypt. The above options allow you to do that by customizing the TrueCrypt boot loader screen. If you enable the first option, no texts will be displayed by the boot loader (not even when you enter the wrong password). The computer will appear to be "frozen" while you can type your password. In addition, a custom message can be displayed to mislead the adversary. For example, fake error messages such as "Missing operating system" (which is normally displayed by the Windows boot loader if it finds no Windows boot partition). It is, however, important to note that if the adversary can analyze the content of the hard drive, he can still find out that it contains the TrueCrypt boot loader. + WARNING: Please keep in mind that if you enable this option, the TrueCrypt boot loader will not display any texts (not even when you enter the wrong password). The computer will appear to be "frozen" (unresponsive) while you can type your password (the cursor will NOT move and no asterisk will be displayed when you press a key).\n\nAre you sure you want to enable this option? + Your system partition/drive appears to be fully encrypted. + TrueCrypt does not support encrypting a system drive that has been converted to a dynamic disk. + The system drive contains extended (logical) partitions.\n\nYou can encrypt an entire system drive containing extended (logical) partitions only on Windows Vista (or later versions of Windows). On Windows XP, you can encrypt an entire system drive provided that it contains only primary partitions. + WARNING: As you are running Windows XP/2003, after you start encrypting the drive, you must NOT create any extended (logical) partitions on it (you may create only primary partitions). Any extended partition on the drive would be inaccessible after you start encrypting.\n\nNote: If this limitation is not acceptable, you can go back and choose to encrypt only the system partition instead of the entire drive (and, in addition to that, you can create partition-hosted TrueCrypt volumes within any non-system partitions on the drive).\n\nAlternatively, if this limitation is not acceptable, you may want to consider upgrading to Windows Vista or a later version of Windows (you can encrypt an entire system drive containing extended/logical partitions only on Windows Vista or later). + Do you want to encrypt the system partition instead of the entire drive?\n\nNote that you can create partition-hosted TrueCrypt volumes within any non-system partitions on the drive (in addition to encrypting the system partition). + As your system drive contains only a single partition that occupies the whole drive, it is preferable (more secure) to encrypt the entire drive including the free "slack" space that typically surrounds such a partition.\n\nDo you want to encrypt the entire system drive? + Your system is configured to store temporary files on a non-system partition.\n\nTemporary files may be stored only on the system partition. + Your user profile files are not stored on the system partition.\n\nUser profile files may be stored only on the system partition. + There is/are paging file(s) on non-system partitions.\n\nPaging files may be located only on the system partition. + Do you want to configure Windows to create paging files only on the Windows partition now?\n\nNote that if you click 'Yes', the computer will be restarted. Then start TrueCrypt and try creating the hidden OS again. + Otherwise, plausible deniability of the hidden operating system might be adversely affected.\n\nNote: If an adversary analyzed the content of such files (residing on a non-system partition), he might find out that you used this wizard in the hidden-system-creation mode (which might indicate the existence of a hidden operating system on your computer). Also note that any such files stored on the system partition will be securely erased by TrueCrypt during the process of creation of the hidden operating system. + WARNING: During the process of creation of the hidden operating system, you will be required to fully reinstall the currently running system (in order to create a decoy system securely).\n\nNote: The currently running operating system and the entire content of the system partition will be copied to the hidden volume (in order to create the hidden system).\n\n\nAre you sure you will be able to install Windows using a Windows Setup CD/DVD (or using a service partition)? + For security reasons, if the currently running operating system requires activation, it must be activated before proceeding. Note that the hidden operating system will be created by copying the content of the system partition to a hidden volume (so if this operating system is not activated, the hidden operating system will not be activated either). For more information, see the section "Security Requirements and Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide.\n\nImportant: Before proceeding, please make sure you have read the section "Security Requirements and Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide.\n\n\nDoes the currently running operating system meet the above condition? + Your system uses an extra boot partition. TrueCrypt does not support hibernation on hidden operating systems that use an extra boot partition (decoy systems can be hibernated without any problems).\n\nPlease note that the boot partition would be shared by both the decoy and the hidden system. Therefore, in order to prevent data leaks and problems while resuming from hibernation, TrueCrypt has to prevent the hidden system from writing to the shared boot partition and from hibernating.\n\n\nDo you want to continue? If you select 'No', instructions for removing the extra boot partition will be displayed. + \nThe extra boot partition can be removed before installing Windows. To do so, follow these steps:\n\n1) Boot your Windows installation disc.\n\n2) In the Windows installer screen, click 'Install now' > 'Custom (advanced)'.\n\n3) Click 'Drive Options'.\n\n4) Select the main system partition and delete it by clicking 'Delete' and 'OK'.\n\n5) Select the 'System Reserved' partition, click 'Extend', and increase its size so that the operating system can be installed to it.\n\n6) Click 'Apply' and 'OK'.\n\n7) Install Windows on the 'System Reserved' partition.\n\n\nShould an attacker ask why you removed the extra boot partition, you can answer that you wanted to prevent any possible data leaks to the unencrypted boot partition.\n\nNote: You can print this text by clicking the 'Print' button below. If you print this text, you should destroy the paper after removing the extra boot partition (otherwise, if the paper was found, it might indicate that there is a hidden operating system on this computer). + Warning: There is unallocated space between the system partition and the first partition behind it. After you create the hidden operating system, you must not create any new partitions in that unallocated space. Otherwise, the hidden operating system will be impossible to boot (until you delete such newly created partitions). + This algorithm is currently not supported for system encryption. + Keyfiles are currently not supported for system encryption. + Warning: TrueCrypt could not restore the original keyboard layout. This may cause you to enter a password incorrectly. + Error: Cannot set the keyboard layout for TrueCrypt to the standard US keyboard layout.\n\nNote that the password needs to be typed in the pre-boot environment (before Windows starts) where non-US Windows keyboard layouts are not available. Therefore, the password must always be typed using the standard US keyboard layout. + As TrueCrypt temporarily changed the keyboard layout to the standard US keyboard layout, it is not possible to type characters by pressing keys while the right Alt key is held down. However, you can type most of such characters by pressing appropriate keys while the Shift key is held down. + TrueCrypt prevented change of keyboard layout. + Note: The password will need to be typed in the pre-boot environment (before Windows starts) where non-US Windows keyboard layouts are not available. Therefore, the password must always be typed using the standard US keyboard layout. However, it is important to note that you do NOT need a real US keyboard. TrueCrypt automatically ensures that you can safely type the password (right now and in the pre-boot environment) even if you do NOT have a real US keyboard. + Before you can encrypt the partition/drive, you must create a TrueCrypt Rescue Disk (TRD), which serves the following purposes:\n\n- If the TrueCrypt Boot Loader, master key, or other critical data gets damaged, the TRD allows you to restore it (note, however, that you will still have to enter the correct password then).\n\n- If Windows gets damaged and cannot start, the TRD allows you to permanently decrypt the partition/drive before Windows starts.\n\n- The TRD will contain a backup of the present content of the first drive track (which typically contains a system loader or boot manager) and will allow you to restore it if necessary.\n\nThe TrueCrypt Rescue Disk ISO image will be created in the location specified below. + After you click OK, Microsoft Windows Disc Image Burner will be launched. Please use it to burn the TrueCrypt Rescue Disk ISO image to a CD or DVD.\n\nAfter you do so, return to the TrueCrypt Volume Creation Wizard and follow its instructions. + The Rescue Disk image has been created and stored in this file:\n%hs\n\nNow you need to burn it to a CD or DVD.\n\n%lsAfter you burn the Rescue Disk, click Next to verify that it has been correctly burned. + The Rescue Disk image has been created and stored in this file:\n%hs\n\nNow you should either burn the image to a CD/DVD or move it to a safe location for later use.\n\n%lsClick Next to continue. + IMPORTANT: Note that the file must be written to the CD/DVD as an ISO disk image (not as an individual file). For information on how to do so, please refer to the documentation of your CD/DVD recording software. If you do not have any CD/DVD recording software that can write the ISO disk image to a CD/DVD, click the link below to download such free software.\n\n + Launch Microsoft Windows Disc Image Burner + WARNING: If you already created a TrueCrypt Rescue Disk in the past, it cannot be reused for this system partition/drive because it was created for a different master key! Every time you encrypt a system partition/drive, you must create a new TrueCrypt Rescue Disk for it even if you use the same password. + Error: Cannot save system encryption settings. + Cannot initiate the system encryption pretest. + Cannot initiate the process of creation of the hidden operating system. + Wipe Mode + On some types of storage media, when data is overwritten with other data, it may be possible to recover the overwritten data using techniques such as magnetic force microscopy. This also applies to data that are overwritten with their encrypted form (which happens when TrueCrypt initially encrypts an unencrypted partition or drive). According to some studies and governmental publications, recovery of overwritten data can be prevented (or made very difficult) by overwritting the data with pseudorandom and certain non-random data a certain number of times. Therefore, if you believe that an adversary might be able to use such techniques to recover the data you intend encrypt, you may want to select one of the wipe modes (existing data will NOT be lost). Note that wiping will NOT be performed after the partition/drive is encrypted. When the partition/drive is fully encrypted, no unencrypted data is written to it. Any data being written to it is first encrypted on the fly in memory and only then is the (encrypted) data written to the disk. + On some types of storage media, when data is overwritten with other data (e.g. when the data is erased), it may be possible to recover the overwritten data using techniques such as magnetic force microscopy. According to some studies and governmental publications, recovery of overwritten data can be prevented (or made very difficult) by overwritting the data with pseudorandom and certain non-random data a certain number of times. Therefore, if you believe that an adversary might be able to use such techniques to recover the data that is to be erased, you may want to select one of the multi-pass wipe modes.\n\nNote: The more wipe passes you use, the longer it takes to erase the data. + Wiping + \nNote: You can interrupt the process of wiping, shut down your computer, start the hidden system again and then resume the process (this wizard will be launched automatically). However, if you interrupt it, the entire process of wiping will have to start from the beginning. + \n\nNote: If you interrupt the process of wiping and then attempt to resume it, the entire process will have to start from the beginning. + Do you want to abort the process of wiping? + Warning: The entire content of the selected partition/device will be erased and lost. + The entire content of the partition where the original system resides will be erased.\n\nNote: The entire content of the partition that is to be erased has been copied to this hidden system partition. + WARNING: Note that when you choose e.g. the 3-pass wipe mode, the time necessary to encrypt the partition/drive will be up to 4 times longer. Likewise, if you choose the 35-pass wipe mode, it will be up to 36 times longer (it might even take several weeks).\n\nHowever, please note that wiping will NOT be performed after the partition/drive is fully encrypted. When the partition/drive is fully encrypted, no unencrypted data is written to it. Any data being written to it is first encrypted on the fly in memory and only then is the (encrypted) data written to the disk (so the performance will NOT be affected).\n\nAre you sure you want to use the wipe mode? + None (fastest) + 1-pass (random data) + 3-pass (US DoD 5220.22-M) + 7-pass (US DoD 5220.22-M) + 35-pass ("Gutmann") + Number of Operating Systems + Multi-boot configurations are not supported when creating a hidden operating system. + WARNING: Inexperienced users should never attempt to encrypt Windows in multi-boot configurations.\n\nContinue? + Boot Drive + Is the currently running operating system installed on the boot drive?\n\nNote: Sometimes, Windows is not installed on the same drive as the Windows boot loader (boot partition). If that is the case, select 'No'. + TrueCrypt currently does not support encrypting an operating system that does not boot from the drive on which it is installed. + Number of System Drives + How many drives contain an operating system?\n\nNote: For example, if you have any operating system (e.g. Windows, Mac OS X, Linux, etc.) installed on your primary drive and any additional operating system installed on your secondary drive, select '2 or more'. + TrueCrypt currently does not support encrypting a whole drive that contains multiple operating systems.\n\nPossible Solutions:\n\n- You can still encrypt one of the systems if you go back and choose to encrypt only a single system partition (as opposed to choosing to encrypt the entire system drive).\n\n- Alternatively, you will be able to encrypt the entire drive if you move some of the systems to other drives leaving only one system on the drive you want to encrypt. + Multiple Systems on Single Drive + Are there any other operating systems installed on the drive on which the currently running operating system is installed?\n\nNote: For example, if the currently running operating system is installed on the drive #0, which contains several partitions, and if one of the partitions contains Windows and another partition contains any additional operating system (e.g. Windows, Mac OS X, Linux, etc.), select 'Yes'. + Non-Windows Boot Loader + Is a non-Windows boot loader (or boot manager) installed in the master boot record (MBR)?\n\nNote: For example, if the first track of the boot drive contains GRUB, LILO, XOSL, or some other non-Windows boot manager (or boot loader), select 'Yes'. + Multi-Boot + TrueCrypt currently does not support multi-boot configurations where a non-Windows boot loader is installed in the Master Boot Record.\n\nPossible Solutions:\n\n- If you use a boot manager to boot Windows and Linux, move the boot manager (typically, GRUB) from the Master Boot Record to a partition. Then start this wizard again and encrypt the system partition/drive. Note that the TrueCrypt Boot Loader will become your primary boot manager and it will allow you to launch the original boot manager (e.g. GRUB) as your secondary boot manager (by pressing Esc in the TrueCrypt Boot Loader screen) and thus you will be able boot Linux. + If the currently running operating system is installed on the boot partition, then, after you encrypt it, you will need to enter the correct password even if you want to start any other unencrypted Windows system(s) (as they will share a single encrypted Windows boot loader/manager).\n\nIn contrast, if the currently running operating system is not installed on the boot partition (or if the Windows boot loader/manager is not used by any other system), then, after you encrypt this system, you will not need to enter the correct password to boot the other unencrypted system(s) -- you will only need to press the Esc key to start the unencrypted system (if there are multiple unencrypted systems, you will also need to choose which system to start in the TrueCrypt Boot Manager menu).\n\nNote: Typically, the earliest installed Windows system is installed on the boot partition. + If there are any Windows Vista operating systems in your multi-boot configuration, please make sure they have been upgraded to Service Pack 1 or higher. TrueCrypt Boot Loader might fail to boot Windows Vista with no Service Pack installed.\n\nPlease note that Service Pack 1 for Windows Vista resolved an issue causing a shortage of free base memory during system boot. + Encryption of Host Protected Area + At the end of many drives, there is an area that is normally hidden from the operating system (such areas are usually referred to as Host Protected Areas). However, some programs can read and write data from/to such areas.\n\nWARNING: Some computer manufacturers may use such areas to store tools and data for RAID, system recovery, system setup, diagnostic, or other purposes. If such tools or data must be accessible before booting, the hidden area should NOT be encrypted (choose 'No' above).\n\nDo you want TrueCrypt to detect and encrypt such a hidden area (if any) at the end of the system drive? + Type of System Encryption + Select this option if you merely want to encrypt the system partition or the entire system drive. + It may happen that you are forced by somebody to decrypt the operating system. There are many situations where you cannot refuse to do so (for example, due to extortion). If you select this option, you will create a hidden operating system whose existence will be impossible to prove (provided that certain guidelines are followed). Thus, you will not have to decrypt or reveal the password to the hidden operating system. For a detailed explanation, please click the link below. + It may happen that you are forced by somebody to decrypt the operating system. There are many situations where you cannot refuse to do so (for example, due to extortion).\n\nUsing this wizard, you can create a hidden operating system whose existence will be impossible to prove (provided that certain guidelines are followed). Thus, you will not have to decrypt or reveal the password for the hidden operating system. + Hidden Operating System + In the following steps, you will create two TrueCrypt volumes (outer and hidden) within the first partition behind the system partition. The hidden volume will contain the hidden operating system (OS). TrueCrypt will create the hidden OS by copying the content of the system partition (where the currently running OS is installed) to the hidden volume. To the outer volume, you will copy some sensitive looking files that you actually do NOT want to hide. They will be there for anyone forcing you to disclose the password for the hidden OS partition. You can reveal the password for the outer volume within the hidden OS partition (the existence of the hidden OS remains secret).\n\nFinally, on the system partition of the currently running OS, you will install a new OS, so-called decoy OS, and encrypt it. It must not contain sensitive data and will be there for anyone forcing you to reveal your pre-boot authentication password. In total, there will be three passwords. Two of them can be disclosed (for the decoy OS and outer volume). If you use the third one, the hidden OS will start. + Detecting Hidden Sectors + Please wait while TrueCrypt is detecting possible hidden sectors at the end of the system drive. Note that it may take a long time to complete.\n\nNote: In very rare cases, on some computers, the system may become unresponsive during this detection process. If it happens, restart the computer, start TrueCrypt, repeat the previous steps but skip this detection process. Note that this issue is not caused by a bug in TrueCrypt. + Area to Encrypt + Select this option if you want to encrypt the entire drive on which the currently running Windows system is installed. The whole drive, including all its partitions, will be encrypted except the first track where the TrueCrypt Boot Loader will reside. Anyone who wants to access a system installed on the drive, or files stored on the drive, will need to enter the correct password each time before the system starts. This option cannot be used to encrypt a secondary or external drive if Windows is not installed on it and does not boot from it. + Collecting Random Data + Keys Generated + Rescue Disk Recording + Rescue Disk Created + System Encryption Pretest + Rescue Disk Verified + \nThe TrueCrypt Rescue Disk has been successfully verified. Please remove it from the drive now and store it in a safe place.\n\nClick Next to continue. + WARNING: During the next steps, the TrueCrypt Rescue Disk must not be in the drive. Otherwise, it will not be possible to complete the steps correctly.\n\nPlease remove it from the drive now and store it in a safe place. Then click OK. + Warning: Due to technical limitations of the pre-boot environment, texts displayed by TrueCrypt in the pre-boot environment (i.e. before Windows starts) cannot be localized. The TrueCrypt Boot Loader user interface is completely in English.\n\nContinue? + Before encrypting your system partition or drive, TrueCrypt needs to verify that everything works correctly.\n\nAfter you click Test, all the necessary components (for example, the pre-boot authentication component, i.e. the TrueCrypt Boot Loader) will be installed and your computer will be restarted. Then you will have to enter your password in the TrueCrypt Boot Loader screen that will appear before Windows starts. After Windows starts, you will be automatically informed about the result of this pretest.\n\nThe following device will be modified: Drive #%d\n\n\nIf you click Cancel now, nothing will be installed and the pretest will not be performed. + IMPORTANT NOTES -- PLEASE READ OR PRINT (click 'Print'):\n\nNote that none of your files will be encrypted before you successfully restart your computer and start Windows. Thus, if anything fails, your data will NOT be lost. However, if something does go wrong, you might encounter difficulties in starting Windows. Therefore, please read (and, if possible, print) the following guidelines on what to do if Windows cannot start after you restart the computer.\n\n + What to Do If Windows Cannot Start\n------------------------------------------------\n\nNote: These instructions are valid only if you have not started encrypting.\n\n- If Windows does not start after you enter the correct password (or if you repeatedly enter the correct password but TrueCrypt says that the password is incorrect), do not panic. Restart (power off and on) the computer, and in the TrueCrypt Boot Loader screen, press the Esc key on your keyboard (and if you have multiple systems, choose which to start). Then Windows should start (provided that it is not encrypted) and TrueCrypt will automatically ask whether you want to uninstall the pre-boot authentication component. Note that the previous steps do NOT work if the system partition/drive is encrypted (nobody can start Windows or access encrypted data on the drive without the correct password even if he or she follows the previous steps).\n\n + - If the previous steps do not help or if the TrueCrypt Boot Loader screen does not appear (before Windows starts), insert the TrueCrypt Rescue Disk into your CD/DVD drive and restart your computer. If the TrueCrypt Rescue Disk screen does not appear (or if you do not see the 'Repair Options' item in the 'Keyboard Controls' section of the TrueCrypt Rescue Disk screen), it is possible that your BIOS is configured to attempt to boot from hard drives before CD/DVD drives. If that is the case, restart your computer, press F2 or Delete (as soon as you see a BIOS start-up screen), and wait until a BIOS configuration screen appears. If no BIOS configuration screen appears, restart (reset) the computer again and start pressing F2 or Delete repeatedly as soon as you restart (reset) the computer. When a BIOS configuration screen appears, configure your BIOS to boot from the CD/DVD drive first (for information on how to do so, please refer to the documentation for your BIOS/motherboard or contact your computer vendor's technical support team for assistance). Then restart your computer. The TrueCrypt Rescue Disk screen should appear now. In the TrueCrypt Rescue Disk screen, select 'Repair Options' by pressing F8 on your keyboard. From the 'Repair Options' menu, select 'Restore original system loader'. Then remove the Rescue Disk from your CD/DVD drive and restart your computer. Windows should start normally (provided that it is not encrypted).\n\n + Note that the previous steps do NOT work if the system partition/drive is encrypted (nobody can start Windows or access encrypted data on the drive without the correct password even if he or she follows the previous steps).\n\n\nNote that even if you lose your TrueCrypt Rescue Disk and an attacker finds it, he or she will NOT be able to decrypt the system partition or drive without the correct password. + Pretest Completed + The pretest has been successfully completed.\n\nWARNING: Please note that if power supply is suddenly interrupted while encrypting existing data in place, or when the operating system crashes due to a software error or hardware malfunction while TrueCrypt is encrypting existing data in place, portions of the data will be corrupted or lost. Therefore, before you start encrypting, please make sure that you have backup copies of the files you want to encrypt. If you do not, please back up the files now (you can click Defer, back up the files, then run TrueCrypt again anytime, and select 'System' > 'Resume Interrupted Process' to start encrypting).\n\nWhen ready, click Encrypt to start encrypting. + You can click Pause or Defer anytime to interrupt the process of encryption or decryption, exit this wizard, restart or shut down your computer, and then resume the process, which will continue from the point it was stopped. To prevent slowdown when the system or applications write or read data from the system drive, TrueCrypt automatically waits until the data is written or read (see Status above) and then automatically continues encrypting or decrypting. + \n\nYou can click Pause or Defer anytime to interrupt the process of encryption, exit this wizard, restart or shut down your computer, and then resume the process, which will continue from the point it was stopped. Note that the volume cannot be mounted until it has been fully encrypted. + Hidden System Started + Original System + Windows creates (typically, without your knowledge or consent) various log files, temporary files, etc., on the system partition. It also saves the content of RAM to hibernation and paging files located on the system partition. Therefore, if an adversary analyzed files stored on the partition where the original system (of which the hidden system is a clone) resides, he might find out, for example, that you used the TrueCrypt wizard in the hidden-system-creation mode (which might indicate the existence of a hidden operating system on your computer).\n\nTo prevent such issues, TrueCrypt will, in the next steps, securely erase the entire content of the partition where the original system resides. Afterwards, in order to achieve plausible deniability, you will need to install a new system on the partition and encrypt it. Thus you will create the decoy system and the whole process of creation of the hidden operating system will be completed. + The hidden operating system has been successfully created. However, before you can start using it (and achieve plausible deniability), you need to securely erase (using TrueCrypt) the entire content of the partition where the currently running operating system is installed. Before you can do that, you need to restart the computer and, in the TrueCrypt Boot Loader screen (which appears before Windows starts), enter the pre-boot authentication password for the hidden operating system. Then, after the hidden system starts, the TrueCrypt wizard will be launched automatically.\n\nNote: If you choose to terminate the process of creation of the hidden operating system now, you will NOT be able to resume the process and the hidden system will NOT be accessible (because the TrueCrypt Boot Loader will be removed). + You have scheduled the process of creation of a hidden operating system. The process has not been completed yet. To complete it, you need to restart the computer and, in the TrueCrypt Boot Loader screen (which appears before Windows starts), enter the password for the hidden operating system.\n\nNote: If you choose to terminate the process of creation of the hidden operating system now, you will NOT be able to resume the process. + Restart the computer and proceed + Permanently terminate the process of creation of the hidden operating system + Do nothing now and ask again later + \nIF POSSIBLE, PLEASE PRINT THIS TEXT (click 'Print' below).\n\n\nHow and When to Use TrueCrypt Rescue Disk (After Encrypting)\n-----------------------------------------------------------------------------------\n\n + I. How to Boot TrueCrypt Rescue Disk\n\nTo boot a TrueCrypt Rescue Disk, insert it into your CD/DVD drive and restart your computer. If the TrueCrypt Rescue Disk screen does not appear (or if you do not see the 'Repair Options' item in the 'Keyboard Controls' section of the screen), it is possible that your BIOS is configured to attempt to boot from hard drives before CD/DVD drives. If that is the case, restart your computer, press F2 or Delete (as soon as you see a BIOS start-up screen), and wait until a BIOS configuration screen appears. If no BIOS configuration screen appears, restart (reset) the computer again and start pressing F2 or Delete repeatedly as soon as you restart (reset) the computer. When a BIOS configuration screen appears, configure your BIOS to boot from the CD/DVD drive first (for information on how to do so, please refer to the documentation for your BIOS/motherboard or contact your computer vendor's technical support team for assistance). Then restart your computer. The TrueCrypt Rescue Disk screen should appear now. Note: In the TrueCrypt Rescue Disk screen, you can select 'Repair Options' by pressing F8 on your keyboard.\n\n\n + II. When and How to Use TrueCrypt Rescue Disk (After Encrypting)\n\n + 1) If the TrueCrypt Boot Loader screen does not appear after you start your computer (or if Windows does not boot), the TrueCrypt Boot Loader may be damaged. The TrueCrypt Rescue Disk allows you to restore it and thus to regain access to your encrypted system and data (however, note that you will still have to enter the correct password then). In the Rescue Disk screen, select 'Repair Options' > 'Restore TrueCrypt Boot Loader'. Then press 'Y' to confirm the action, remove the Rescue Disk from your CD/DVD drive and restart your computer.\n\n + 2) If you repeatedly enter the correct password but TrueCrypt says that the password is incorrect, the master key or other critical data may be damaged. The TrueCrypt Rescue Disk allows you to restore them and thus to regain access to your encrypted system and data (however, note that you will still have to enter the correct password then). In the Rescue Disk screen, select 'Repair Options' > 'Restore key data'. Then enter your password, press 'Y' to confirm the action, remove the Rescue Disk from your CD/DVD drive, and restart your computer.\n\n + 3) If the TrueCrypt Boot Loader is damaged, you can avoid running it by booting directly from the TrueCrypt Rescue Disk. Insert your Rescue Disk into your CD/DVD drive and then enter your password in the Rescue Disk screen.\n\n + 4) If Windows is damaged and cannot start, the TrueCrypt Rescue Disk allows you to permanently decrypt the partition/drive before Windows starts. In the Rescue Disk screen, select 'Repair Options' > 'Permanently decrypt system partition/drive'. Enter the correct password and wait until decryption is complete. Then you can e.g. boot your MS Windows setup CD/DVD to repair your Windows installation.\n\n + Note: Alternatively, if Windows is damaged (cannot start) and you need to repair it (or access files on it), you can avoid decrypting the system partition/drive by following these steps: If you have multiple operating systems installed on your computer, boot the one that does not require pre-boot authentication. If you do not have multiple operating systems installed on your computer, you can boot a WinPE or BartPE CD/DVD or you can connect your system drive as a secondary or external drive to another computer and then boot the operating system installed on the computer. After you boot a system, run TrueCrypt, click 'Select Device', select the affected system partition, click 'OK', select 'System' > 'Mount Without Pre-Boot Authentication', enter your pre-boot authentication password and click 'OK'. The partition will be mounted as a regular TrueCrypt volume (data will be on-the-fly decrypted/encrypted in RAM on access, as usual).\n\n\n + Note that even if you lose your TrueCrypt Rescue Disk and an attacker finds it, he or she will NOT be able to decrypt the system partition or drive without the correct password. + \n\nI M P O R T A N T -- PLEASE PRINT THIS TEXT IF POSSIBLE (click 'Print' below).\n\n\nNote: This text will be automatically displayed each time you start the hidden system until you start creating the decoy system.\n\n\n + How to Create Decoy System Safely and Securely\n----------------------------------------------------------------------------\n\nIn order to achieve plausible deniability, you need to create the decoy operating system now. To do so, follow these steps:\n\n + 1) For security reasons, shut down your computer and leave it powered off for several minutes. This is required to clear the memory, which contains sensitive data. Then turn on the computer but do not boot the hidden system.\n\n + 2) Install Windows on the partition whose content has been erased (i.e. on the partition where the original system, of which the hidden system is a clone, was installed).\n\nIMPORTANT: WHEN YOU START INSTALLING THE DECOY SYSTEM, THE HIDDEN SYSTEM WILL *NOT* BE POSSIBLE TO BOOT (because the TrueCrypt Boot Loader will be erased by the Windows system installer). THIS IS NORMAL AND EXPECTED. PLEASE DO NOT PANIC. YOU WILL BE ABLE TO BOOT THE HIDDEN SYSTEM AGAIN AS SOON AS YOU START ENCRYPTING THE DECOY SYSTEM (because TrueCrypt will then automatically install the TrueCrypt Boot Loader on the system drive).\n\nImportant: The size of the decoy system partition must remain the same as the size of the hidden volume (this condition is now met). Moreover, you must not create any partition between the decoy system partition and the partition where the hidden system resides.\n\n + 3) Boot the decoy system (which you installed in step 2 and install TrueCrypt on it).\n\nKeep in mind that the decoy system must never contain any sensitive data.\n\n + 4) On the decoy system, run TrueCrypt and select 'System' > 'Encrypt System Partition/Drive'. The TrueCrypt Volume Creation Wizard window should appear.\n\nThe following steps apply to the TrueCrypt Volume Creation Wizard.\n\n + 5) In the TrueCrypt Volume Creation Wizard, do NOT select the 'Hidden' option. Leave the 'Normal' option selected and click 'Next'.\n\n + 6) Select the option 'Encrypt the Windows system partition' and then click 'Next'.\n\n + 7) If there are only the hidden system and the decoy system installed on the computer, select the option 'Single-boot' (if there are more than these two systems installed on the computer, select 'Multi-boot'). Then click 'Next'.\n\n + 8) IMPORTANT: In this step, FOR THE DECOY SYSTEM, YOU MUST SELECT THE SAME ENCRYPTION ALGORITHM AND HASH ALGORITHM THAT YOU SELECTED FOR THE HIDDEN SYSTEM! OTHERWISE, THE HIDDEN SYSTEM WILL BE INACCESSIBLE! In other words, the decoy system must be encrypted with the same encryption algorithm as the hidden system. Note: The reason is that the decoy system and the hidden system will share a single boot loader, which supports only a single algorithm, selected by the user (for each algorithm, there is a special version of the TrueCrypt Boot Loader).\n\n + 9) In this step, choose a password for the decoy operating system. This will be the password that you will be able to reveal to an adversary if you are asked or forced to disclose your pre-boot authentication password (the other password you can reveal is the one for the outer volume). The existence of the third password (i.e. of the pre-boot authentication password for the hidden operating system) will remain secret.\n\nImportant: The password you choose for the decoy system must be substantially different from the one you chose for the hidden volume (i.e. for the hidden operating system).\n\n + 10) Follow the remaining instructions in the wizard so as to encrypt the decoy operating system.\n\n\n\n + After Decoy System Is Created\n------------------------------------------------\n\nAfter you encrypt the decoy system, the whole process of creation of the hidden operating system will be completed and you will be able to use these three passwords:\n\n1) Pre-boot authentication password for the hidden operating system.\n\n2) Pre-boot authentication password for the decoy operating system.\n\n3) Password for the outer volume.\n\n + If you want to start the hidden operating system, you will just need to enter the password for the hidden operating system in the TrueCrypt Boot Loader screen (which appears after you turn on or restart your computer).\n\nIf you want to start the decoy operating system, you will just need to enter the password for the decoy operating system in the TrueCrypt Boot Loader screen.\n\nThe password for the decoy system can be disclosed to anyone forcing you to reveal your pre-boot authentication password. The existence of the hidden volume (and of the hidden operating system) will remain secret.\n\n + The third password (for the outer volume) can be disclosed to anyone forcing you to reveal the password for the first partition behind the system partition, where both the outer volume and the hidden volume (containing the hidden operating system) reside. The existence of the hidden volume (and of the hidden operating system) will remain secret.\n\n\n + If you revealed the password for the decoy system to an adversary and he asked you why the free space of the (decoy) system partition contains random data, you could answer, for example: "The partition previously contained a system encrypted by TrueCrypt, but I forgot the pre-boot authentication password (or the system was damaged and stopped booting), so I had to reinstall Windows and encrypt the partition again."\n\n\n + If all the instructions are followed and if the precautions and requirements listed in the section "Security Requirements and Precautions Pertaining to Hidden Volumes" in the TrueCrypt User's Guide are followed, it will be impossible to prove that the hidden volume and hidden operating system exist, even when the outer volume is mounted or when the decoy operating system is decrypted or started.\n\nIf you print this text (strongly recommended), you should destroy the paper after you have created the decoy system and after you have understood all the information contained in the text (otherwise, if the paper was found, it might indicate that there is a hidden operating system on this computer).\n\n + WARNING: IF YOU DO NOT PROTECT THE HIDDEN VOLUME (for information on how to do so, refer to the section "Protection of Hidden Volumes Against Damage" in the TrueCrypt User's Guide), DO NOT WRITE TO THE OUTER VOLUME (note that the decoy operating system is NOT installed in the outer volume). OTHERWISE, YOU MAY OVERWRITE AND DAMAGE THE HIDDEN VOLUME (AND THE HIDDEN OPERATING SYSTEM WITHIN IT)! + Operating System Cloning + In the next steps, TrueCrypt will create the hidden operating system by copying the content of the system partition to the hidden volume (data being copied will be encrypted on the fly with an encryption key different from the one that will be used for the decoy operating system).\n\nPlease note that the process will be performed in the pre-boot environment (before Windows starts) and it may take a long time to complete; several hours or even several days (depending on the size of the system partition and on the performance of your computer).\n\nYou will be able to interrupt the process, shut down your computer, start the operating system and then resume the process. However, if you interrupt it, the entire process of copying the system will have to start from the beginning (because the content of the system partition must not change during cloning). + Do you want to cancel the entire process of creation of the hidden operating system?\n\nNote: You will NOT be able to resume the process if you cancel it now. + Do you want to cancel the system encryption pretest? + The TrueCrypt system encryption pretest failed. Do you want to try again?\n\nIf you select 'No', the pre-boot authentication component will be uninstalled.\n\nNote: If the TrueCrypt Boot Loader did not ask you to enter the password before Windows started, it is possible that your operating system does not boot from the drive on which it is installed. This is not supported. + The system partition/drive does not appear to be encrypted (neither partially nor fully). + Your system partition/drive is encrypted (partially or fully).\n\nPlease decrypt your system partition/drive entirely before proceeding. To do so, select 'System' > 'Permanently Decrypt System Partition/Drive' from the menu bar of the main TrueCrypt window. + When the system partition/drive is encrypted (partially or fully), you cannot downgrade TrueCrypt (but you can upgrade it or reinstall the same version). + Your system partition/drive is currently being encrypted, decrypted, or otherwise modified. Please interrupt the encryption/decryption/modification process (or wait until it is complete) before proceeding. + An instance of the TrueCrypt Volume Creation Wizard is currently running on this system and performing or preparing encryption/decryption of the system partition/drive. Before you proceed, please wait for it to finish or close it. If you cannot close it, please restart your computer before proceeding. + The process of encryption or decryption of the system partition/drive has not been completed. Please wait until it is complete before proceeding. + Error: The process of encryption of the partition/drive has not been completed. It must be completed first. + Error: The process of encryption of the partition/volume has not been completed. It must be completed first.\n\nNote: To resume the process, select 'Volumes' > 'Resume Interrupted Process' from the menu bar of the main TrueCrypt window. + The password is correct, TrueCrypt has successfully decrypted the volume header and detected that this volume is a hidden system volume. However, you cannot modify the header of a hidden system volume this way.\n\nTo change the password for a hidden system volume, boot the operating system residing in the hidden volume, and then select 'System' > 'Change Password' from the menu bar of the main TrueCrypt window.\n\nTo set the header key derivation algorithm, boot the hidden operating system and then select 'System' > 'Set Header Key Derivation Algorithm'. + TrueCrypt does not support in-place decryption of a hidden system partition.\n\nNote: If you want to decrypt the decoy system partition, boot the decoy system, and then select 'System' > 'Permanently Decrypt System Partition/Drive' from the menu bar of the main TrueCrypt window. + Error: Incorrect/invalid parameter. + You have selected a partition or a device but the wizard mode you selected is suitable only for file containers.\n\nDo you want to change the wizard mode? + Do you want to create a TrueCrypt file container instead? + You have selected the system partition/drive, but the wizard mode you selected is suitable only for non-system partitions/drives.\n\nDo you want to set up pre-boot authentication (which means that you will need to enter your password each time before Windows boots/starts) and encrypt the system partition/drive? + Are you sure you want to permanently decrypt the system partition/drive? + CAUTION: If you permanently decrypt the system partition/drive, unencrypted data will be written to it.\n\nAre you really sure you want to permanently decrypt the system partition/drive? + Warning: If you use a cascade of ciphers for system encryption, you may encounter the following issues:\n\n1) The TrueCrypt Boot Loader is larger than normal and, therefore, there is not enough space in the first drive track for a backup of the TrueCrypt Boot Loader. Hence, whenever it gets damaged (which often happens, for example, during inappropriately designed anti-piracy activation procedures of certain programs), you will need to use the TrueCrypt Rescue Disk to boot or to repair the TrueCrypt Boot Loader.\n\n2) On some computers, resuming from hibernation takes longer.\n\nThese potential issues can be prevented by choosing a non-cascade encryption algorithm (e.g. AES).\n\nAre you sure you want to use a cascade of ciphers? + If you encounter any of the previously described problems, decrypt the partition/drive (if it is encrypted) and then try encrypting it again using a non-cascade encryption algorithm (e.g. AES). + WARNING: For safety and security reasons, you should update TrueCrypt on the decoy operating system before you update it on the hidden operating system.\n\nTo do so, boot the decoy system and run the TrueCrypt installer from within it. Then boot the hidden system and run the installer from within it as well.\n\nNote: The decoy system and the hidden system share a single boot loader. If you upgraded TrueCrypt only on the hidden system (but not on the decoy system), the decoy system would contain a TrueCrypt driver and TrueCrypt applications whose version numbers are different from the version number of the TrueCrypt Boot Loader. Such a discrepancy might indicate that there is a hidden operating system on this computer.\n\n\nDo you want to continue? (Not recommended.) + The version number of the TrueCrypt Boot Loader that booted this operating system is different from the version number of the TrueCrypt driver (and of the TrueCrypt applications) installed on this system.\n\nYou should run the TrueCrypt installer (whose version number is the same as the one of the TrueCrypt Boot Loader) to update TrueCrypt on this operating system. + The TrueCrypt Boot Loader has been upgraded.\n\nIt is strongly recommended that you create a new TrueCrypt Rescue Disk (which will contain the new version of the TrueCrypt Boot Loader) by selecting 'System' > 'Create Rescue Disk' after you restart your computer. + The TrueCrypt Boot Loader has been upgraded.\n\nIt is strongly recommended that you boot the decoy operating system and then create a new TrueCrypt Rescue Disk (which will contain the new version of the TrueCrypt Boot Loader) by selecting 'System' > 'Create Rescue Disk'. + Failed to upgrade the TrueCrypt Boot Loader. + TrueCrypt failed to detect the real size of the system drive and, therefore, the size reported by the operating system (which may be smaller than the real size) will be used. Also note that this is not a bug in TrueCrypt. + WARNING: It appears that TrueCrypt has already tried to detect hidden sectors on this system drive. If you encountered any problems during the previous detection process, you can avoid the problems by skipping the detection of hidden sectors now. Note that if you do so, TrueCrypt will use the size reported by the operating system (which may be smaller than the real size of the drive).\n\nNote that this issue is not caused by a bug in TrueCrypt. + Skip detection of hidden sectors (use the size reported by the operating system) + Try to detect hidden sectors again + Error: Content of one or more sectors on the disk cannot be read (probably due to a physical defect).\n\nThe process of in-place encryption can continue only when the sectors have been made readable again. TrueCrypt can attempt to make these sectors readable by writing zeros to the sectors (subsequently such all-zero blocks would be encrypted). However, note that any data stored in the unreadable sectors will be lost. If you want to avoid that, you can attempt to recover portions of the corrupted data using appropriate third-party tools.\n\nNote: In case of physically damaged sectors (as opposed to mere data corruption and checksum errors) most types of storage devices internally reallocate the sectors when data is attempted to be written to them (so the existing data in the damaged sectors may remain unencrypted on the drive).\n\nDo you want TrueCrypt to write zeroes to unreadable sectors? + Error: Content of one or more sectors on the disk cannot be read (probably due to a physical defect).\n\nTo be able to proceed with decryption, TrueCrypt will have to discard the content of the unreadable sectors (the content will be replaced with pseudorandom data). Please note that, before proceeding, you can attempt to recover portions of any corrupted data using appropriate third-party tools.\n\nDo you want TrueCrypt to discard data in the unreadable sectors now? + Note: TrueCrypt has replaced the content of %I64d unreadable sectors (%s) with encrypted all-zero plaintext blocks. + Enter password/PIN for token '%s': + In order to allow TrueCrypt to access a security token or smart card, you need to install a PKCS #11 software library for the token or smart card first. Such a library may be supplied with the device or it may be available for download from the website of the vendor or other third parties.\n\nAfter you install the library, you can either select it manually by clicking 'Select Library' or you can let TrueCrypt find and select it automatically by clicking 'Auto-Detect Library' (only the Windows system directory will be searched). + Note: For the filename and location of the PKCS #11 library installed for your security token or smart card, please refer to the documentation supplied with the token, card, or third-party software.\n\nClick 'OK' to select the path and filename. + In order to allow TrueCrypt to access a security token or smart card, you need to select a PKCS #11 software library for the token/card first. To do so, select 'Settings' > 'Security Tokens'. + Failed to initialize PKCS #11 security token library.\n\nPlease make sure the specified path and filename refer to a valid PKCS #11 library. To specify a PKCS #11 library path and filename, select 'Settings' > 'Security Tokens'. + No PKCS #11 library has been found in the Windows system directory.\n\nPlease make sure that a PKCS #11 library for your security token (or for your smart card) is installed (such a library may be supplied with the token/card or it may be available for download from the website of the vendor or other third parties). If it is installed in a directory other than the Windows system directory, click 'Select Library' to locate the library (e.g. in the folder where the software for the token/card is installed). + No security token found.\n\nPlease make sure your security token is connected to your computer and the correct device driver for your token is installed. + Security token keyfile not found. + A security token keyfile with the same name already exists. + Do you want to delete the selected files? + Security token keyfile path is invalid. + Security token error + Password for security token is incorrect. + The security token does not have enough memory/space to perform the requested operation.\n\nIf you are attempting to import a keyfile, you should select a smaller file or use a keyfile generated by TrueCrypt (select 'Keyfiles' > 'Generate Random Keyfile'). + All open security token sessions have been closed. + Select Security Token Keyfiles + Slot + Token name + File name + Please note that pre-boot authentication passwords are always typed using the standard US keyboard layout. Therefore, a volume that uses a password typed using a non-US keyboard layout may be impossible to mount using a cached pre-boot authentication password. Note that this is not a bug in TrueCrypt. + System favorite volumes will be mounted using the pre-boot authentication password. If any system favorite volume uses a different password, it will not be mounted. + IMPORTANT: Please keep in mind that if this option is enabled and TrueCrypt does not have administrator privileges, mounted system favorite volumes are NOT displayed in the TrueCrypt application window and they cannot be dismounted. Therefore, if you need e.g. to dismount a system favorite volume, please right-click the TrueCrypt icon (in the Start menu) and select 'Run as administrator' first. The same limitation applies to the 'Dismount All' function, 'Auto-Dismount' functions, 'Dismount All' hot keys, etc. + This setting takes effect only after the operating system is restarted. + Error while parsing command line. + Rescue Disk + Select &File and Mount... + Select &Device and Mount... + Warning: The filesystem on the volume mounted as '%s' was not cleanly dismounted and thus may contain errors. Using a corrupted filesystem can cause data loss or data corruption.\n\nNote: Before you physically remove or switch off a device (such as a USB flash drive or an external hard drive) where a mounted TrueCrypt volume resides, you should always dismount the TrueCrypt volume in TrueCrypt first.\n\n\nDo you want Windows to attempt to detect and fix errors (if any) on the filesystem? + Warning: One or more system favorite volumes were not cleanly dismounted and thus may contain filesystem errors. Please see the system event log for further details.\n\nUsing a corrupted filesystem can cause data loss or data corruption. You should check the affected system favorite volume(s) for errors (right-click each of them in TrueCrypt and select 'Repair Filesystem'). + Warning: Repairing a damaged filesystem using the Microsoft 'chkdsk' tool might cause loss of files in damaged areas. Therefore, it is recommended that you first back up the files stored on the TrueCrypt volume to another, healthy, TrueCrypt volume.\n\nDo you want to repair the filesystem now? + Volume '%s' has been mounted as read-only because write access was denied.\n\nPlease make sure the security permissions of the file container allow you to write to it (right-click the container and select Properties > Security).\n\nNote that, due to a Windows issue, you may see this warning even after setting the appropriate security permissions. This is not caused by a bug in TrueCrypt. A possible solution is to move your container to, e.g., your 'Documents' folder.\n\nIf you intend to keep your volume read-only, set the read-only attribute of the container (right-click the container and select Properties > Read-only), which will suppress this warning. + Volume '%s' had to be mounted as read-only because write access was denied.\n\nPlease make sure no other application (e.g. antivirus software) is accessing the partition/device on which the volume is hosted. + Volume '%s' has been mounted as read-only because the operating system reported the host device to be write-protected.\n\nPlease note that some custom chipset drivers have been reported to cause writable media to falsely appear write-protected. This problem is not caused by TrueCrypt. It may be solved by updating or uninstalling any custom (non-Microsoft) chipset drivers that are currently installed on this system. + Do you want TrueCrypt to attempt to disable write protection of the partition/drive? + Test + Keyfile + Name + Backspace + Tab + Clear + Enter + Pause + Caps Lock + Spacebar + Page Up + Page Down + End + Home + Left Arrow + Up Arrow + Right Arrow + Down Arrow + Select Key + Print Key + Execute Key + Print Screen + Insert + Delete + Applications Key + Sleep + Num Lock + Scroll Lock + Browser Back + Browser Forward + Browser Refresh + Browser Stop + Browser Search + Browser Favorites + Browser Home + Mute + Volume Down + Volume Up + Next Track + Previous Track + Stop Media + Play/Pause Media + Start Mail Key + Select Media Key + Application 1 + Application 2 + Attn + CrSel + ExSel + Play + Zoom + NumPad + Shift + Control + Alt + Win + B + KB + MB + GB + TB + PB + B/s + KB/s + MB/s + GB/s + TB/s + PB/s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Common/Makefile b/Common/Makefile index 5acbbd2..53b9a3d 100644 --- a/Common/Makefile +++ b/Common/Makefile @@ -1 +1 @@ -!INCLUDE $(NTMAKEENV)\makefile.def +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/Common/PASSWORD.C b/Common/PASSWORD.C index aff766d..6d51f6f 100644 --- a/Common/PASSWORD.C +++ b/Common/PASSWORD.C @@ -1,425 +1,425 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#include "Crypto.h" -#include "Volumes.h" -#include "Password.h" -#include "Dlgcode.h" -#include "Language.h" -#include "Pkcs5.h" -#include "Endian.h" -#include "Random.h" - -#include - -void VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword, - HWND hVerify, unsigned char *szPassword, - char *szVerify, - BOOL keyFilesEnabled) -{ - char szTmp1[MAX_PASSWORD + 1]; - char szTmp2[MAX_PASSWORD + 1]; - int k = GetWindowTextLength (hPassword); - BOOL bEnable = FALSE; - - if (hwndDlg); /* Remove warning */ - - GetWindowText (hPassword, szTmp1, sizeof (szTmp1)); - GetWindowText (hVerify, szTmp2, sizeof (szTmp2)); - - if (strcmp (szTmp1, szTmp2) != 0) - bEnable = FALSE; - else - { - if (k >= MIN_PASSWORD || keyFilesEnabled) - bEnable = TRUE; - else - bEnable = FALSE; - } - - if (szPassword != NULL) - memcpy (szPassword, szTmp1, sizeof (szTmp1)); - - if (szVerify != NULL) - memcpy (szVerify, szTmp2, sizeof (szTmp2)); - - burn (szTmp1, sizeof (szTmp1)); - burn (szTmp2, sizeof (szTmp2)); - - EnableWindow (hButton, bEnable); -} - - -BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw) -{ - int i, len; - - if (hPassword == NULL) - { - unsigned char *pw; - len = ptrPw->Length; - pw = (unsigned char *) ptrPw->Text; - - for (i = 0; i < len; i++) - { - if (pw[i] >= 0x7f || pw[i] < 0x20) // A non-ASCII or non-printable character? - return FALSE; - } - } - else - { - wchar_t s[MAX_PASSWORD + 1]; - len = GetWindowTextLength (hPassword); - - if (len > MAX_PASSWORD) - return FALSE; - - GetWindowTextW (hPassword, s, sizeof (s) / sizeof (wchar_t)); - - for (i = 0; i < len; i++) - { - if (s[i] >= 0x7f || s[i] < 0x20) // A non-ASCII or non-printable character? - break; - } - - burn (s, sizeof(s)); - - if (i < len) - return FALSE; - } - - return TRUE; -} - - -BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem) -{ - if (GetWindowTextLength (hwndItem) < PASSWORD_LEN_WARNING) - { -#ifndef _DEBUG - if (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES) - return FALSE; -#endif - } - return TRUE; -} - -int ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg) -{ - int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR; - char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; - char szDosDevice[TC_MAX_PATH]; - char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - PCRYPTO_INFO cryptoInfo = NULL, ci = NULL; - void *dev = INVALID_HANDLE_VALUE; - DWORD dwError; - BOOL bDevice; - unsigned __int64 hostSize = 0; - int volumeType; - int wipePass; - FILETIME ftCreationTime; - FILETIME ftLastWriteTime; - FILETIME ftLastAccessTime; - BOOL bTimeStampValid = FALSE; - LARGE_INTEGER headerOffset; - BOOL backupHeader; - - if (oldPassword->Length == 0 || newPassword->Length == 0) return -1; - - WaitCursor (); - - CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice); - - if (bDevice == FALSE) - { - strcpy (szCFDevice, szDiskFile); - } - else - { - nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE); - - if (nDosLinkCreated != 0) - goto error; - } - - dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (dev == INVALID_HANDLE_VALUE) - goto error; - - if (bDevice) - { - /* This is necessary to determine the hidden volume header offset */ - - if (dev == INVALID_HANDLE_VALUE) - { - goto error; - } - else - { - PARTITION_INFORMATION diskInfo; - DWORD dwResult; - BOOL bResult; - - bResult = GetPartitionInfo (lpszVolume, &diskInfo); - - if (bResult) - { - hostSize = diskInfo.PartitionLength.QuadPart; - } - else - { - DISK_GEOMETRY driveInfo; - - bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, - &driveInfo, sizeof (driveInfo), &dwResult, NULL); - - if (!bResult) - goto error; - - hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * - driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; - } - - if (hostSize == 0) - { - nStatus = ERR_VOL_SIZE_WRONG; - goto error; - } - } - } - else - { - LARGE_INTEGER fileSize; - if (!GetFileSizeEx (dev, &fileSize)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - hostSize = fileSize.QuadPart; - } - - if (Randinit ()) - goto error; - - if (!bDevice && bPreserveTimestamp) - { - /* Remember the container modification/creation date and time, (used to reset file date and time of - file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability - of hidden volumes (last password change time is stored in the volume header). */ - - if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) - { - bTimeStampValid = FALSE; - MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); - } - else - bTimeStampValid = TRUE; - } - - for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++) - { - // Seek the volume header - switch (volumeType) - { - case TC_VOLUME_TYPE_NORMAL: - headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET; - break; - - case TC_VOLUME_TYPE_HIDDEN: - if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize) - continue; - - headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET; - break; - - case TC_VOLUME_TYPE_HIDDEN_LEGACY: - headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; - break; - } - - if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - /* Read in volume header */ - nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer)); - if (nStatus != sizeof (buffer)) - { - // Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS - memset (buffer, 0, sizeof (buffer)); - } - - /* Try to decrypt the header */ - - nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL); - if (nStatus == ERR_CIPHER_INIT_WEAK_KEY) - nStatus = 0; // We can ignore this error here - - if (nStatus == ERR_PASSWORD_WRONG) - { - continue; // Try next volume type - } - else if (nStatus != 0) - { - cryptoInfo = NULL; - goto error; - } - else - break; - } - - if (nStatus != 0) - { - cryptoInfo = NULL; - goto error; - } - - if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) - { - nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG; - goto error; - } - - // Change the PKCS-5 PRF if requested by user - if (pkcs5 != 0) - cryptoInfo->pkcs5 = pkcs5; - - RandSetHashFunction (cryptoInfo->pkcs5); - - NormalCursor(); - UserEnrichRandomPool (hwndDlg); - EnableElevatedCursorChange (hwndDlg); - WaitCursor(); - - /* Re-encrypt the volume header */ - backupHeader = FALSE; - - while (TRUE) - { - /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using - techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy - to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22 - times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might - impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the - valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman - recommends. During each pass we will write a valid working header. Each pass will use the same master - key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only - item that will be different for each pass will be the salt. This is sufficient to cause each "version" - of the header to differ substantially and in a random manner from the versions written during the - other passes. */ - - for (wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) - { - // Prepare new volume header - nStatus = CreateVolumeHeaderInMemory (FALSE, - buffer, - cryptoInfo->ea, - cryptoInfo->mode, - newPassword, - cryptoInfo->pkcs5, - cryptoInfo->master_keydata, - &ci, - cryptoInfo->VolumeSize.Value, - (volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) ? cryptoInfo->hiddenVolumeSize : 0, - cryptoInfo->EncryptedAreaStart.Value, - cryptoInfo->EncryptedAreaLength.Value, - cryptoInfo->RequiredProgramVersion, - cryptoInfo->HeaderFlags, - wipePass < PRAND_DISK_WIPE_PASSES - 1); - - if (ci != NULL) - crypto_close (ci); - - if (nStatus != 0) - goto error; - - if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - nStatus = _lwrite ((HFILE) dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - if (nStatus != TC_VOLUME_HEADER_EFFECTIVE_SIZE) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - if (bDevice - && !cryptoInfo->LegacyVolume - && !cryptoInfo->hiddenVolume - && cryptoInfo->HeaderVersion == 4 - && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0 - && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0) - { - nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader); - if (nStatus != ERR_SUCCESS) - goto error; - } - - FlushFileBuffers (dev); - } - - if (backupHeader || cryptoInfo->LegacyVolume) - break; - - backupHeader = TRUE; - headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE; - } - - /* Password successfully changed */ - nStatus = 0; - -error: - dwError = GetLastError (); - - burn (buffer, sizeof (buffer)); - - if (cryptoInfo != NULL) - crypto_close (cryptoInfo); - - if (bTimeStampValid) - { - // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). - if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) - MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); - } - - if (dev != INVALID_HANDLE_VALUE) - CloseHandle ((HANDLE) dev); - - if (nDosLinkCreated == 0) - RemoveFakeDosName (szDiskFile, szDosDevice); - - RandStop (FALSE); - NormalCursor (); - - SetLastError (dwError); - - if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED - && bDevice - && !UacElevated - && IsUacSupported ()) - return nStatus; - - if (nStatus != 0) - handleError (hwndDlg, nStatus); - - return nStatus; -} - +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#include "Crypto.h" +#include "Volumes.h" +#include "Password.h" +#include "Dlgcode.h" +#include "Language.h" +#include "Pkcs5.h" +#include "Endian.h" +#include "Random.h" + +#include + +void VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword, + HWND hVerify, unsigned char *szPassword, + char *szVerify, + BOOL keyFilesEnabled) +{ + char szTmp1[MAX_PASSWORD + 1]; + char szTmp2[MAX_PASSWORD + 1]; + int k = GetWindowTextLength (hPassword); + BOOL bEnable = FALSE; + + if (hwndDlg); /* Remove warning */ + + GetWindowText (hPassword, szTmp1, sizeof (szTmp1)); + GetWindowText (hVerify, szTmp2, sizeof (szTmp2)); + + if (strcmp (szTmp1, szTmp2) != 0) + bEnable = FALSE; + else + { + if (k >= MIN_PASSWORD || keyFilesEnabled) + bEnable = TRUE; + else + bEnable = FALSE; + } + + if (szPassword != NULL) + memcpy (szPassword, szTmp1, sizeof (szTmp1)); + + if (szVerify != NULL) + memcpy (szVerify, szTmp2, sizeof (szTmp2)); + + burn (szTmp1, sizeof (szTmp1)); + burn (szTmp2, sizeof (szTmp2)); + + EnableWindow (hButton, bEnable); +} + + +BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw) +{ + int i, len; + + if (hPassword == NULL) + { + unsigned char *pw; + len = ptrPw->Length; + pw = (unsigned char *) ptrPw->Text; + + for (i = 0; i < len; i++) + { + if (pw[i] >= 0x7f || pw[i] < 0x20) // A non-ASCII or non-printable character? + return FALSE; + } + } + else + { + wchar_t s[MAX_PASSWORD + 1]; + len = GetWindowTextLength (hPassword); + + if (len > MAX_PASSWORD) + return FALSE; + + GetWindowTextW (hPassword, s, sizeof (s) / sizeof (wchar_t)); + + for (i = 0; i < len; i++) + { + if (s[i] >= 0x7f || s[i] < 0x20) // A non-ASCII or non-printable character? + break; + } + + burn (s, sizeof(s)); + + if (i < len) + return FALSE; + } + + return TRUE; +} + + +BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem) +{ + if (GetWindowTextLength (hwndItem) < PASSWORD_LEN_WARNING) + { +#ifndef _DEBUG + if (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES) + return FALSE; +#endif + } + return TRUE; +} + +int ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg) +{ + int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR; + char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; + char szDosDevice[TC_MAX_PATH]; + char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + PCRYPTO_INFO cryptoInfo = NULL, ci = NULL; + void *dev = INVALID_HANDLE_VALUE; + DWORD dwError; + BOOL bDevice; + unsigned __int64 hostSize = 0; + int volumeType; + int wipePass; + FILETIME ftCreationTime; + FILETIME ftLastWriteTime; + FILETIME ftLastAccessTime; + BOOL bTimeStampValid = FALSE; + LARGE_INTEGER headerOffset; + BOOL backupHeader; + + if (oldPassword->Length == 0 || newPassword->Length == 0) return -1; + + WaitCursor (); + + CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice); + + if (bDevice == FALSE) + { + strcpy (szCFDevice, szDiskFile); + } + else + { + nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE); + + if (nDosLinkCreated != 0) + goto error; + } + + dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (dev == INVALID_HANDLE_VALUE) + goto error; + + if (bDevice) + { + /* This is necessary to determine the hidden volume header offset */ + + if (dev == INVALID_HANDLE_VALUE) + { + goto error; + } + else + { + PARTITION_INFORMATION diskInfo; + DWORD dwResult; + BOOL bResult; + + bResult = GetPartitionInfo (lpszVolume, &diskInfo); + + if (bResult) + { + hostSize = diskInfo.PartitionLength.QuadPart; + } + else + { + DISK_GEOMETRY driveInfo; + + bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, + &driveInfo, sizeof (driveInfo), &dwResult, NULL); + + if (!bResult) + goto error; + + hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * + driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; + } + + if (hostSize == 0) + { + nStatus = ERR_VOL_SIZE_WRONG; + goto error; + } + } + } + else + { + LARGE_INTEGER fileSize; + if (!GetFileSizeEx (dev, &fileSize)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + hostSize = fileSize.QuadPart; + } + + if (Randinit ()) + goto error; + + if (!bDevice && bPreserveTimestamp) + { + /* Remember the container modification/creation date and time, (used to reset file date and time of + file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability + of hidden volumes (last password change time is stored in the volume header). */ + + if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) + { + bTimeStampValid = FALSE; + MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); + } + else + bTimeStampValid = TRUE; + } + + for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++) + { + // Seek the volume header + switch (volumeType) + { + case TC_VOLUME_TYPE_NORMAL: + headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET; + break; + + case TC_VOLUME_TYPE_HIDDEN: + if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize) + continue; + + headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET; + break; + + case TC_VOLUME_TYPE_HIDDEN_LEGACY: + headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; + break; + } + + if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + /* Read in volume header */ + nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer)); + if (nStatus != sizeof (buffer)) + { + // Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS + memset (buffer, 0, sizeof (buffer)); + } + + /* Try to decrypt the header */ + + nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL); + if (nStatus == ERR_CIPHER_INIT_WEAK_KEY) + nStatus = 0; // We can ignore this error here + + if (nStatus == ERR_PASSWORD_WRONG) + { + continue; // Try next volume type + } + else if (nStatus != 0) + { + cryptoInfo = NULL; + goto error; + } + else + break; + } + + if (nStatus != 0) + { + cryptoInfo = NULL; + goto error; + } + + if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) + { + nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG; + goto error; + } + + // Change the PKCS-5 PRF if requested by user + if (pkcs5 != 0) + cryptoInfo->pkcs5 = pkcs5; + + RandSetHashFunction (cryptoInfo->pkcs5); + + NormalCursor(); + UserEnrichRandomPool (hwndDlg); + EnableElevatedCursorChange (hwndDlg); + WaitCursor(); + + /* Re-encrypt the volume header */ + backupHeader = FALSE; + + while (TRUE) + { + /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using + techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy + to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22 + times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might + impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the + valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman + recommends. During each pass we will write a valid working header. Each pass will use the same master + key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only + item that will be different for each pass will be the salt. This is sufficient to cause each "version" + of the header to differ substantially and in a random manner from the versions written during the + other passes. */ + + for (wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++) + { + // Prepare new volume header + nStatus = CreateVolumeHeaderInMemory (FALSE, + buffer, + cryptoInfo->ea, + cryptoInfo->mode, + newPassword, + cryptoInfo->pkcs5, + cryptoInfo->master_keydata, + &ci, + cryptoInfo->VolumeSize.Value, + (volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) ? cryptoInfo->hiddenVolumeSize : 0, + cryptoInfo->EncryptedAreaStart.Value, + cryptoInfo->EncryptedAreaLength.Value, + cryptoInfo->RequiredProgramVersion, + cryptoInfo->HeaderFlags, + wipePass < PRAND_DISK_WIPE_PASSES - 1); + + if (ci != NULL) + crypto_close (ci); + + if (nStatus != 0) + goto error; + + if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + nStatus = _lwrite ((HFILE) dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + if (nStatus != TC_VOLUME_HEADER_EFFECTIVE_SIZE) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + if (bDevice + && !cryptoInfo->LegacyVolume + && !cryptoInfo->hiddenVolume + && cryptoInfo->HeaderVersion == 4 + && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0 + && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0) + { + nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader); + if (nStatus != ERR_SUCCESS) + goto error; + } + + FlushFileBuffers (dev); + } + + if (backupHeader || cryptoInfo->LegacyVolume) + break; + + backupHeader = TRUE; + headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE; + } + + /* Password successfully changed */ + nStatus = 0; + +error: + dwError = GetLastError (); + + burn (buffer, sizeof (buffer)); + + if (cryptoInfo != NULL) + crypto_close (cryptoInfo); + + if (bTimeStampValid) + { + // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). + if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) + MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); + } + + if (dev != INVALID_HANDLE_VALUE) + CloseHandle ((HANDLE) dev); + + if (nDosLinkCreated == 0) + RemoveFakeDosName (szDiskFile, szDosDevice); + + RandStop (FALSE); + NormalCursor (); + + SetLastError (dwError); + + if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED + && bDevice + && !UacElevated + && IsUacSupported ()) + return nStatus; + + if (nStatus != 0) + handleError (hwndDlg, nStatus); + + return nStatus; +} + diff --git a/Common/PASSWORD.H b/Common/PASSWORD.H index 5a3a12c..310e1e3 100644 --- a/Common/PASSWORD.H +++ b/Common/PASSWORD.H @@ -1,46 +1,46 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef PASSWORD_H -#define PASSWORD_H - -// User text input limits -#define MIN_PASSWORD 1 // Minimum possible password length -#define MAX_PASSWORD 64 // Maximum possible password length - -#define PASSWORD_LEN_WARNING 20 // Display a warning when a password is shorter than this - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - // Modifying this structure can introduce incompatibility with previous versions - unsigned __int32 Length; - unsigned char Text[MAX_PASSWORD + 1]; - char Pad[3]; // keep 64-bit alignment -} Password; - -#if defined(_WIN32) && !defined(NT4_DRIVER) - -void VerifyPasswordAndUpdate ( HWND hwndDlg , HWND hButton , HWND hPassword , HWND hVerify , unsigned char *szPassword , char *szVerify, BOOL keyFilesEnabled ); -BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem); -BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw); -int ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg); - -#endif // defined(_WIN32) && !defined(NT4_DRIVER) - -#ifdef __cplusplus -} -#endif - -#endif // PASSWORD_H +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef PASSWORD_H +#define PASSWORD_H + +// User text input limits +#define MIN_PASSWORD 1 // Minimum possible password length +#define MAX_PASSWORD 64 // Maximum possible password length + +#define PASSWORD_LEN_WARNING 20 // Display a warning when a password is shorter than this + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + // Modifying this structure can introduce incompatibility with previous versions + unsigned __int32 Length; + unsigned char Text[MAX_PASSWORD + 1]; + char Pad[3]; // keep 64-bit alignment +} Password; + +#if defined(_WIN32) && !defined(NT4_DRIVER) + +void VerifyPasswordAndUpdate ( HWND hwndDlg , HWND hButton , HWND hPassword , HWND hVerify , unsigned char *szPassword , char *szVerify, BOOL keyFilesEnabled ); +BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem); +BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw); +int ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg); + +#endif // defined(_WIN32) && !defined(NT4_DRIVER) + +#ifdef __cplusplus +} +#endif + +#endif // PASSWORD_H diff --git a/Common/PKCS5.C b/Common/PKCS5.C index 6d344c0..140eec7 100644 --- a/Common/PKCS5.C +++ b/Common/PKCS5.C @@ -1,642 +1,642 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#include -#include "Rmd160.h" -#ifndef TC_WINDOWS_BOOT -#include "Sha1.h" -#include "Sha2.h" -#include "Whirlpool.h" -#endif -#include "Pkcs5.h" -#include "Crypto.h" - -void hmac_truncate - ( - char *d1, /* data to be truncated */ - char *d2, /* truncated data */ - int len /* length in bytes to keep */ -) -{ - int i; - for (i = 0; i < len; i++) - d2[i] = d1[i]; -} - -#ifndef TC_WINDOWS_BOOT - -void hmac_sha512 -( - char *k, /* secret key */ - int lk, /* length of the key in bytes */ - char *d, /* data */ - int ld, /* length of data in bytes */ - char *out, /* output buffer, at least "t" bytes */ - int t -) -{ - sha512_ctx ictx, octx; - char isha[SHA512_DIGESTSIZE], osha[SHA512_DIGESTSIZE]; - char key[SHA512_DIGESTSIZE]; - char buf[SHA512_BLOCKSIZE]; - int i; - - /* If the key is longer than the hash algorithm block size, - let key = sha512(key), as per HMAC specifications. */ - if (lk > SHA512_BLOCKSIZE) - { - sha512_ctx tctx; - - sha512_begin (&tctx); - sha512_hash ((unsigned char *) k, lk, &tctx); - sha512_end ((unsigned char *) key, &tctx); - - k = key; - lk = SHA512_DIGESTSIZE; - - burn (&tctx, sizeof(tctx)); // Prevent leaks - } - - /**** Inner Digest ****/ - - sha512_begin (&ictx); - - /* Pad the key for inner digest */ - for (i = 0; i < lk; ++i) - buf[i] = (char) (k[i] ^ 0x36); - for (i = lk; i < SHA512_BLOCKSIZE; ++i) - buf[i] = 0x36; - - sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, &ictx); - sha512_hash ((unsigned char *) d, ld, &ictx); - - sha512_end ((unsigned char *) isha, &ictx); - - /**** Outer Digest ****/ - - sha512_begin (&octx); - - for (i = 0; i < lk; ++i) - buf[i] = (char) (k[i] ^ 0x5C); - for (i = lk; i < SHA512_BLOCKSIZE; ++i) - buf[i] = 0x5C; - - sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, &octx); - sha512_hash ((unsigned char *) isha, SHA512_DIGESTSIZE, &octx); - - sha512_end ((unsigned char *) osha, &octx); - - /* truncate and print the results */ - t = t > SHA512_DIGESTSIZE ? SHA512_DIGESTSIZE : t; - hmac_truncate (osha, out, t); - - /* Prevent leaks */ - burn (&ictx, sizeof(ictx)); - burn (&octx, sizeof(octx)); - burn (isha, sizeof(isha)); - burn (osha, sizeof(osha)); - burn (buf, sizeof(buf)); - burn (key, sizeof(key)); -} - - -void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) -{ - char j[SHA512_DIGESTSIZE], k[SHA512_DIGESTSIZE]; - char init[128]; - char counter[4]; - int c, i; - - /* iteration 1 */ - memset (counter, 0, 4); - counter[3] = (char) b; - memcpy (init, salt, salt_len); /* salt */ - memcpy (&init[salt_len], counter, 4); /* big-endian block number */ - hmac_sha512 (pwd, pwd_len, init, salt_len + 4, j, SHA512_DIGESTSIZE); - memcpy (u, j, SHA512_DIGESTSIZE); - - /* remaining iterations */ - for (c = 1; c < iterations; c++) - { - hmac_sha512 (pwd, pwd_len, j, SHA512_DIGESTSIZE, k, SHA512_DIGESTSIZE); - for (i = 0; i < SHA512_DIGESTSIZE; i++) - { - u[i] ^= k[i]; - j[i] = k[i]; - } - } - - /* Prevent possible leaks. */ - burn (j, sizeof(j)); - burn (k, sizeof(k)); -} - - -void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) -{ - char u[SHA512_DIGESTSIZE]; - int b, l, r; - - if (dklen % SHA512_DIGESTSIZE) - { - l = 1 + dklen / SHA512_DIGESTSIZE; - } - else - { - l = dklen / SHA512_DIGESTSIZE; - } - - r = dklen - (l - 1) * SHA512_DIGESTSIZE; - - /* first l - 1 blocks */ - for (b = 1; b < l; b++) - { - derive_u_sha512 (pwd, pwd_len, salt, salt_len, iterations, u, b); - memcpy (dk, u, SHA512_DIGESTSIZE); - dk += SHA512_DIGESTSIZE; - } - - /* last block */ - derive_u_sha512 (pwd, pwd_len, salt, salt_len, iterations, u, b); - memcpy (dk, u, r); - - - /* Prevent possible leaks. */ - burn (u, sizeof(u)); -} - - -/* Deprecated/legacy */ -void hmac_sha1 -( - char *k, /* secret key */ - int lk, /* length of the key in bytes */ - char *d, /* data */ - int ld, /* length of data in bytes */ - char *out, /* output buffer, at least "t" bytes */ - int t -) -{ - sha1_ctx ictx, octx; - char isha[SHA1_DIGESTSIZE], osha[SHA1_DIGESTSIZE]; - char key[SHA1_DIGESTSIZE]; - char buf[SHA1_BLOCKSIZE]; - int i; - - /* If the key is longer than the hash algorithm block size, - let key = sha1(key), as per HMAC specifications. */ - if (lk > SHA1_BLOCKSIZE) - { - sha1_ctx tctx; - - sha1_begin (&tctx); - sha1_hash ((unsigned char *) k, lk, &tctx); - sha1_end ((unsigned char *) key, &tctx); - - k = key; - lk = SHA1_DIGESTSIZE; - - burn (&tctx, sizeof(tctx)); // Prevent leaks - } - - /**** Inner Digest ****/ - - sha1_begin (&ictx); - - /* Pad the key for inner digest */ - for (i = 0; i < lk; ++i) - buf[i] = (char) (k[i] ^ 0x36); - for (i = lk; i < SHA1_BLOCKSIZE; ++i) - buf[i] = 0x36; - - sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &ictx); - sha1_hash ((unsigned char *) d, ld, &ictx); - - sha1_end ((unsigned char *) isha, &ictx); - - /**** Outer Digest ****/ - - sha1_begin (&octx); - - for (i = 0; i < lk; ++i) - buf[i] = (char) (k[i] ^ 0x5C); - for (i = lk; i < SHA1_BLOCKSIZE; ++i) - buf[i] = 0x5C; - - sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &octx); - sha1_hash ((unsigned char *) isha, SHA1_DIGESTSIZE, &octx); - - sha1_end ((unsigned char *) osha, &octx); - - /* truncate and print the results */ - t = t > SHA1_DIGESTSIZE ? SHA1_DIGESTSIZE : t; - hmac_truncate (osha, out, t); - - /* Prevent leaks */ - burn (&ictx, sizeof(ictx)); - burn (&octx, sizeof(octx)); - burn (isha, sizeof(isha)); - burn (osha, sizeof(osha)); - burn (buf, sizeof(buf)); - burn (key, sizeof(key)); -} - - -/* Deprecated/legacy */ -void derive_u_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) -{ - char j[SHA1_DIGESTSIZE], k[SHA1_DIGESTSIZE]; - char init[128]; - char counter[4]; - int c, i; - - /* iteration 1 */ - memset (counter, 0, 4); - counter[3] = (char) b; - memcpy (init, salt, salt_len); /* salt */ - memcpy (&init[salt_len], counter, 4); /* big-endian block number */ - hmac_sha1 (pwd, pwd_len, init, salt_len + 4, j, SHA1_DIGESTSIZE); - memcpy (u, j, SHA1_DIGESTSIZE); - - /* remaining iterations */ - for (c = 1; c < iterations; c++) - { - hmac_sha1 (pwd, pwd_len, j, SHA1_DIGESTSIZE, k, SHA1_DIGESTSIZE); - for (i = 0; i < SHA1_DIGESTSIZE; i++) - { - u[i] ^= k[i]; - j[i] = k[i]; - } - } - - /* Prevent possible leaks. */ - burn (j, sizeof(j)); - burn (k, sizeof(k)); -} - - -/* Deprecated/legacy */ -void derive_key_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) -{ - char u[SHA1_DIGESTSIZE]; - int b, l, r; - - if (dklen % SHA1_DIGESTSIZE) - { - l = 1 + dklen / SHA1_DIGESTSIZE; - } - else - { - l = dklen / SHA1_DIGESTSIZE; - } - - r = dklen - (l - 1) * SHA1_DIGESTSIZE; - - /* first l - 1 blocks */ - for (b = 1; b < l; b++) - { - derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); - memcpy (dk, u, SHA1_DIGESTSIZE); - dk += SHA1_DIGESTSIZE; - } - - /* last block */ - derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); - memcpy (dk, u, r); - - - /* Prevent possible leaks. */ - burn (u, sizeof(u)); -} - -#endif // TC_WINDOWS_BOOT - -void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest) -{ - RMD160_CTX context; - unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ - unsigned char k_opad[65]; /* outer padding - key XORd with opad */ - unsigned char tk[RIPEMD160_DIGESTSIZE]; - int i; - - /* If the key is longer than the hash algorithm block size, - let key = ripemd160(key), as per HMAC specifications. */ - if (keylen > RIPEMD160_BLOCKSIZE) - { - RMD160_CTX tctx; - - RMD160Init(&tctx); - RMD160Update(&tctx, (const unsigned char *) key, keylen); - RMD160Final(tk, &tctx); - - key = (char *) tk; - keylen = RIPEMD160_DIGESTSIZE; - - burn (&tctx, sizeof(tctx)); // Prevent leaks - } - - /* - - RMD160(K XOR opad, RMD160(K XOR ipad, text)) - - where K is an n byte key - ipad is the byte 0x36 repeated RIPEMD160_BLOCKSIZE times - opad is the byte 0x5c repeated RIPEMD160_BLOCKSIZE times - and text is the data being protected */ - - - /* start out by storing key in pads */ - memset(k_ipad, 0x36, sizeof(k_ipad)); - memset(k_opad, 0x5c, sizeof(k_opad)); - - /* XOR key with ipad and opad values */ - for (i=0; i WHIRLPOOL_BLOCKSIZE) - { - WHIRLPOOL_CTX tctx; - - WHIRLPOOL_init (&tctx); - WHIRLPOOL_add ((unsigned char *) k, lk * 8, &tctx); - WHIRLPOOL_finalize (&tctx, (unsigned char *) key); - - k = key; - lk = WHIRLPOOL_DIGESTSIZE; - - burn (&tctx, sizeof(tctx)); // Prevent leaks - } - - /**** Inner Digest ****/ - - WHIRLPOOL_init (&ictx); - - /* Pad the key for inner digest */ - for (i = 0; i < lk; ++i) - buf[i] = (char) (k[i] ^ 0x36); - for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) - buf[i] = 0x36; - - WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &ictx); - WHIRLPOOL_add ((unsigned char *) d, ld * 8, &ictx); - - WHIRLPOOL_finalize (&ictx, (unsigned char *) iwhi); - - /**** Outer Digest ****/ - - WHIRLPOOL_init (&octx); - - for (i = 0; i < lk; ++i) - buf[i] = (char) (k[i] ^ 0x5C); - for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) - buf[i] = 0x5C; - - WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &octx); - WHIRLPOOL_add ((unsigned char *) iwhi, WHIRLPOOL_DIGESTSIZE * 8, &octx); - - WHIRLPOOL_finalize (&octx, (unsigned char *) owhi); - - /* truncate and print the results */ - t = t > WHIRLPOOL_DIGESTSIZE ? WHIRLPOOL_DIGESTSIZE : t; - hmac_truncate (owhi, out, t); - - /* Prevent possible leaks. */ - burn (&ictx, sizeof(ictx)); - burn (&octx, sizeof(octx)); - burn (owhi, sizeof(owhi)); - burn (iwhi, sizeof(iwhi)); - burn (buf, sizeof(buf)); - burn (key, sizeof(key)); -} - -void derive_u_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) -{ - char j[WHIRLPOOL_DIGESTSIZE], k[WHIRLPOOL_DIGESTSIZE]; - char init[128]; - char counter[4]; - int c, i; - - /* iteration 1 */ - memset (counter, 0, 4); - counter[3] = (char) b; - memcpy (init, salt, salt_len); /* salt */ - memcpy (&init[salt_len], counter, 4); /* big-endian block number */ - hmac_whirlpool (pwd, pwd_len, init, salt_len + 4, j, WHIRLPOOL_DIGESTSIZE); - memcpy (u, j, WHIRLPOOL_DIGESTSIZE); - - /* remaining iterations */ - for (c = 1; c < iterations; c++) - { - hmac_whirlpool (pwd, pwd_len, j, WHIRLPOOL_DIGESTSIZE, k, WHIRLPOOL_DIGESTSIZE); - for (i = 0; i < WHIRLPOOL_DIGESTSIZE; i++) - { - u[i] ^= k[i]; - j[i] = k[i]; - } - } - - /* Prevent possible leaks. */ - burn (j, sizeof(j)); - burn (k, sizeof(k)); -} - -void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) -{ - char u[WHIRLPOOL_DIGESTSIZE]; - int b, l, r; - - if (dklen % WHIRLPOOL_DIGESTSIZE) - { - l = 1 + dklen / WHIRLPOOL_DIGESTSIZE; - } - else - { - l = dklen / WHIRLPOOL_DIGESTSIZE; - } - - r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE; - - /* first l - 1 blocks */ - for (b = 1; b < l; b++) - { - derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); - memcpy (dk, u, WHIRLPOOL_DIGESTSIZE); - dk += WHIRLPOOL_DIGESTSIZE; - } - - /* last block */ - derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); - memcpy (dk, u, r); - - - /* Prevent possible leaks. */ - burn (u, sizeof(u)); -} - - -char *get_pkcs5_prf_name (int pkcs5_prf_id) -{ - switch (pkcs5_prf_id) - { - case SHA512: - return "HMAC-SHA-512"; - - case SHA1: // Deprecated/legacy - return "HMAC-SHA-1"; - - case RIPEMD160: - return "HMAC-RIPEMD-160"; - - case WHIRLPOOL: - return "HMAC-Whirlpool"; - - default: - return "(Unknown)"; - } -} - -#endif //!TC_WINDOWS_BOOT - - -int get_pkcs5_iteration_count (int pkcs5_prf_id, BOOL bBoot) -{ - switch (pkcs5_prf_id) - { - case RIPEMD160: - return (bBoot ? 1000 : 2000); - -#ifndef TC_WINDOWS_BOOT - - case SHA512: - return 1000; - - case SHA1: // Deprecated/legacy - return 2000; - - case WHIRLPOOL: - return 1000; -#endif - - default: - TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID - } - return 0; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#include +#include "Rmd160.h" +#ifndef TC_WINDOWS_BOOT +#include "Sha1.h" +#include "Sha2.h" +#include "Whirlpool.h" +#endif +#include "Pkcs5.h" +#include "Crypto.h" + +void hmac_truncate + ( + char *d1, /* data to be truncated */ + char *d2, /* truncated data */ + int len /* length in bytes to keep */ +) +{ + int i; + for (i = 0; i < len; i++) + d2[i] = d1[i]; +} + +#ifndef TC_WINDOWS_BOOT + +void hmac_sha512 +( + char *k, /* secret key */ + int lk, /* length of the key in bytes */ + char *d, /* data */ + int ld, /* length of data in bytes */ + char *out, /* output buffer, at least "t" bytes */ + int t +) +{ + sha512_ctx ictx, octx; + char isha[SHA512_DIGESTSIZE], osha[SHA512_DIGESTSIZE]; + char key[SHA512_DIGESTSIZE]; + char buf[SHA512_BLOCKSIZE]; + int i; + + /* If the key is longer than the hash algorithm block size, + let key = sha512(key), as per HMAC specifications. */ + if (lk > SHA512_BLOCKSIZE) + { + sha512_ctx tctx; + + sha512_begin (&tctx); + sha512_hash ((unsigned char *) k, lk, &tctx); + sha512_end ((unsigned char *) key, &tctx); + + k = key; + lk = SHA512_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /**** Inner Digest ****/ + + sha512_begin (&ictx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x36); + for (i = lk; i < SHA512_BLOCKSIZE; ++i) + buf[i] = 0x36; + + sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, &ictx); + sha512_hash ((unsigned char *) d, ld, &ictx); + + sha512_end ((unsigned char *) isha, &ictx); + + /**** Outer Digest ****/ + + sha512_begin (&octx); + + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x5C); + for (i = lk; i < SHA512_BLOCKSIZE; ++i) + buf[i] = 0x5C; + + sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, &octx); + sha512_hash ((unsigned char *) isha, SHA512_DIGESTSIZE, &octx); + + sha512_end ((unsigned char *) osha, &octx); + + /* truncate and print the results */ + t = t > SHA512_DIGESTSIZE ? SHA512_DIGESTSIZE : t; + hmac_truncate (osha, out, t); + + /* Prevent leaks */ + burn (&ictx, sizeof(ictx)); + burn (&octx, sizeof(octx)); + burn (isha, sizeof(isha)); + burn (osha, sizeof(osha)); + burn (buf, sizeof(buf)); + burn (key, sizeof(key)); +} + + +void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) +{ + char j[SHA512_DIGESTSIZE], k[SHA512_DIGESTSIZE]; + char init[128]; + char counter[4]; + int c, i; + + /* iteration 1 */ + memset (counter, 0, 4); + counter[3] = (char) b; + memcpy (init, salt, salt_len); /* salt */ + memcpy (&init[salt_len], counter, 4); /* big-endian block number */ + hmac_sha512 (pwd, pwd_len, init, salt_len + 4, j, SHA512_DIGESTSIZE); + memcpy (u, j, SHA512_DIGESTSIZE); + + /* remaining iterations */ + for (c = 1; c < iterations; c++) + { + hmac_sha512 (pwd, pwd_len, j, SHA512_DIGESTSIZE, k, SHA512_DIGESTSIZE); + for (i = 0; i < SHA512_DIGESTSIZE; i++) + { + u[i] ^= k[i]; + j[i] = k[i]; + } + } + + /* Prevent possible leaks. */ + burn (j, sizeof(j)); + burn (k, sizeof(k)); +} + + +void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) +{ + char u[SHA512_DIGESTSIZE]; + int b, l, r; + + if (dklen % SHA512_DIGESTSIZE) + { + l = 1 + dklen / SHA512_DIGESTSIZE; + } + else + { + l = dklen / SHA512_DIGESTSIZE; + } + + r = dklen - (l - 1) * SHA512_DIGESTSIZE; + + /* first l - 1 blocks */ + for (b = 1; b < l; b++) + { + derive_u_sha512 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, SHA512_DIGESTSIZE); + dk += SHA512_DIGESTSIZE; + } + + /* last block */ + derive_u_sha512 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, r); + + + /* Prevent possible leaks. */ + burn (u, sizeof(u)); +} + + +/* Deprecated/legacy */ +void hmac_sha1 +( + char *k, /* secret key */ + int lk, /* length of the key in bytes */ + char *d, /* data */ + int ld, /* length of data in bytes */ + char *out, /* output buffer, at least "t" bytes */ + int t +) +{ + sha1_ctx ictx, octx; + char isha[SHA1_DIGESTSIZE], osha[SHA1_DIGESTSIZE]; + char key[SHA1_DIGESTSIZE]; + char buf[SHA1_BLOCKSIZE]; + int i; + + /* If the key is longer than the hash algorithm block size, + let key = sha1(key), as per HMAC specifications. */ + if (lk > SHA1_BLOCKSIZE) + { + sha1_ctx tctx; + + sha1_begin (&tctx); + sha1_hash ((unsigned char *) k, lk, &tctx); + sha1_end ((unsigned char *) key, &tctx); + + k = key; + lk = SHA1_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /**** Inner Digest ****/ + + sha1_begin (&ictx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x36); + for (i = lk; i < SHA1_BLOCKSIZE; ++i) + buf[i] = 0x36; + + sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &ictx); + sha1_hash ((unsigned char *) d, ld, &ictx); + + sha1_end ((unsigned char *) isha, &ictx); + + /**** Outer Digest ****/ + + sha1_begin (&octx); + + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x5C); + for (i = lk; i < SHA1_BLOCKSIZE; ++i) + buf[i] = 0x5C; + + sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &octx); + sha1_hash ((unsigned char *) isha, SHA1_DIGESTSIZE, &octx); + + sha1_end ((unsigned char *) osha, &octx); + + /* truncate and print the results */ + t = t > SHA1_DIGESTSIZE ? SHA1_DIGESTSIZE : t; + hmac_truncate (osha, out, t); + + /* Prevent leaks */ + burn (&ictx, sizeof(ictx)); + burn (&octx, sizeof(octx)); + burn (isha, sizeof(isha)); + burn (osha, sizeof(osha)); + burn (buf, sizeof(buf)); + burn (key, sizeof(key)); +} + + +/* Deprecated/legacy */ +void derive_u_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) +{ + char j[SHA1_DIGESTSIZE], k[SHA1_DIGESTSIZE]; + char init[128]; + char counter[4]; + int c, i; + + /* iteration 1 */ + memset (counter, 0, 4); + counter[3] = (char) b; + memcpy (init, salt, salt_len); /* salt */ + memcpy (&init[salt_len], counter, 4); /* big-endian block number */ + hmac_sha1 (pwd, pwd_len, init, salt_len + 4, j, SHA1_DIGESTSIZE); + memcpy (u, j, SHA1_DIGESTSIZE); + + /* remaining iterations */ + for (c = 1; c < iterations; c++) + { + hmac_sha1 (pwd, pwd_len, j, SHA1_DIGESTSIZE, k, SHA1_DIGESTSIZE); + for (i = 0; i < SHA1_DIGESTSIZE; i++) + { + u[i] ^= k[i]; + j[i] = k[i]; + } + } + + /* Prevent possible leaks. */ + burn (j, sizeof(j)); + burn (k, sizeof(k)); +} + + +/* Deprecated/legacy */ +void derive_key_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) +{ + char u[SHA1_DIGESTSIZE]; + int b, l, r; + + if (dklen % SHA1_DIGESTSIZE) + { + l = 1 + dklen / SHA1_DIGESTSIZE; + } + else + { + l = dklen / SHA1_DIGESTSIZE; + } + + r = dklen - (l - 1) * SHA1_DIGESTSIZE; + + /* first l - 1 blocks */ + for (b = 1; b < l; b++) + { + derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, SHA1_DIGESTSIZE); + dk += SHA1_DIGESTSIZE; + } + + /* last block */ + derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, r); + + + /* Prevent possible leaks. */ + burn (u, sizeof(u)); +} + +#endif // TC_WINDOWS_BOOT + +void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest) +{ + RMD160_CTX context; + unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ + unsigned char k_opad[65]; /* outer padding - key XORd with opad */ + unsigned char tk[RIPEMD160_DIGESTSIZE]; + int i; + + /* If the key is longer than the hash algorithm block size, + let key = ripemd160(key), as per HMAC specifications. */ + if (keylen > RIPEMD160_BLOCKSIZE) + { + RMD160_CTX tctx; + + RMD160Init(&tctx); + RMD160Update(&tctx, (const unsigned char *) key, keylen); + RMD160Final(tk, &tctx); + + key = (char *) tk; + keylen = RIPEMD160_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /* + + RMD160(K XOR opad, RMD160(K XOR ipad, text)) + + where K is an n byte key + ipad is the byte 0x36 repeated RIPEMD160_BLOCKSIZE times + opad is the byte 0x5c repeated RIPEMD160_BLOCKSIZE times + and text is the data being protected */ + + + /* start out by storing key in pads */ + memset(k_ipad, 0x36, sizeof(k_ipad)); + memset(k_opad, 0x5c, sizeof(k_opad)); + + /* XOR key with ipad and opad values */ + for (i=0; i WHIRLPOOL_BLOCKSIZE) + { + WHIRLPOOL_CTX tctx; + + WHIRLPOOL_init (&tctx); + WHIRLPOOL_add ((unsigned char *) k, lk * 8, &tctx); + WHIRLPOOL_finalize (&tctx, (unsigned char *) key); + + k = key; + lk = WHIRLPOOL_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /**** Inner Digest ****/ + + WHIRLPOOL_init (&ictx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x36); + for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) + buf[i] = 0x36; + + WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &ictx); + WHIRLPOOL_add ((unsigned char *) d, ld * 8, &ictx); + + WHIRLPOOL_finalize (&ictx, (unsigned char *) iwhi); + + /**** Outer Digest ****/ + + WHIRLPOOL_init (&octx); + + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x5C); + for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) + buf[i] = 0x5C; + + WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &octx); + WHIRLPOOL_add ((unsigned char *) iwhi, WHIRLPOOL_DIGESTSIZE * 8, &octx); + + WHIRLPOOL_finalize (&octx, (unsigned char *) owhi); + + /* truncate and print the results */ + t = t > WHIRLPOOL_DIGESTSIZE ? WHIRLPOOL_DIGESTSIZE : t; + hmac_truncate (owhi, out, t); + + /* Prevent possible leaks. */ + burn (&ictx, sizeof(ictx)); + burn (&octx, sizeof(octx)); + burn (owhi, sizeof(owhi)); + burn (iwhi, sizeof(iwhi)); + burn (buf, sizeof(buf)); + burn (key, sizeof(key)); +} + +void derive_u_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) +{ + char j[WHIRLPOOL_DIGESTSIZE], k[WHIRLPOOL_DIGESTSIZE]; + char init[128]; + char counter[4]; + int c, i; + + /* iteration 1 */ + memset (counter, 0, 4); + counter[3] = (char) b; + memcpy (init, salt, salt_len); /* salt */ + memcpy (&init[salt_len], counter, 4); /* big-endian block number */ + hmac_whirlpool (pwd, pwd_len, init, salt_len + 4, j, WHIRLPOOL_DIGESTSIZE); + memcpy (u, j, WHIRLPOOL_DIGESTSIZE); + + /* remaining iterations */ + for (c = 1; c < iterations; c++) + { + hmac_whirlpool (pwd, pwd_len, j, WHIRLPOOL_DIGESTSIZE, k, WHIRLPOOL_DIGESTSIZE); + for (i = 0; i < WHIRLPOOL_DIGESTSIZE; i++) + { + u[i] ^= k[i]; + j[i] = k[i]; + } + } + + /* Prevent possible leaks. */ + burn (j, sizeof(j)); + burn (k, sizeof(k)); +} + +void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) +{ + char u[WHIRLPOOL_DIGESTSIZE]; + int b, l, r; + + if (dklen % WHIRLPOOL_DIGESTSIZE) + { + l = 1 + dklen / WHIRLPOOL_DIGESTSIZE; + } + else + { + l = dklen / WHIRLPOOL_DIGESTSIZE; + } + + r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE; + + /* first l - 1 blocks */ + for (b = 1; b < l; b++) + { + derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, WHIRLPOOL_DIGESTSIZE); + dk += WHIRLPOOL_DIGESTSIZE; + } + + /* last block */ + derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, r); + + + /* Prevent possible leaks. */ + burn (u, sizeof(u)); +} + + +char *get_pkcs5_prf_name (int pkcs5_prf_id) +{ + switch (pkcs5_prf_id) + { + case SHA512: + return "HMAC-SHA-512"; + + case SHA1: // Deprecated/legacy + return "HMAC-SHA-1"; + + case RIPEMD160: + return "HMAC-RIPEMD-160"; + + case WHIRLPOOL: + return "HMAC-Whirlpool"; + + default: + return "(Unknown)"; + } +} + +#endif //!TC_WINDOWS_BOOT + + +int get_pkcs5_iteration_count (int pkcs5_prf_id, BOOL bBoot) +{ + switch (pkcs5_prf_id) + { + case RIPEMD160: + return (bBoot ? 1000 : 2000); + +#ifndef TC_WINDOWS_BOOT + + case SHA512: + return 1000; + + case SHA1: // Deprecated/legacy + return 2000; + + case WHIRLPOOL: + return 1000; +#endif + + default: + TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID + } + return 0; +} diff --git a/Common/PKCS5.H b/Common/PKCS5.H index e03adf7..345cb21 100644 --- a/Common/PKCS5.H +++ b/Common/PKCS5.H @@ -1,41 +1,41 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TC_HEADER_PKCS5 -#define TC_HEADER_PKCS5 - -#include "Tcdefs.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -void hmac_sha512 (char *k, int lk, char *d, int ld, char *out, int t); -void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); -void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); -void hmac_sha1 (char *k, int lk, char *d, int ld, char *out, int t); -void derive_u_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); -void derive_key_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); -void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest); -void derive_u_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); -void derive_key_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); -void hmac_whirlpool (char *k, int lk, char *d, int ld, char *out, int t); -void derive_u_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); -void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); -int get_pkcs5_iteration_count (int pkcs5_prf_id, BOOL bBoot); -char *get_pkcs5_prf_name (int pkcs5_prf_id); - -#if defined(__cplusplus) -} -#endif - -#endif // TC_HEADER_PKCS5 +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_PKCS5 +#define TC_HEADER_PKCS5 + +#include "Tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +void hmac_sha512 (char *k, int lk, char *d, int ld, char *out, int t); +void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +void hmac_sha1 (char *k, int lk, char *d, int ld, char *out, int t); +void derive_u_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest); +void derive_u_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +void hmac_whirlpool (char *k, int lk, char *d, int ld, char *out, int t); +void derive_u_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +int get_pkcs5_iteration_count (int pkcs5_prf_id, BOOL bBoot); +char *get_pkcs5_prf_name (int pkcs5_prf_id); + +#if defined(__cplusplus) +} +#endif + +#endif // TC_HEADER_PKCS5 diff --git a/Common/PROGRESS.C b/Common/PROGRESS.C index f88415b..c18d14e 100644 --- a/Common/PROGRESS.C +++ b/Common/PROGRESS.C @@ -1,130 +1,130 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" -#include "Language.h" -#include "Dlgcode.h" -#include "Progress.h" -#include "../Format/Tcformat.h" -#include "../Format/FormatCom.h" -#include "../Format/resource.h" - -ULONG prevTime, startTime; -__int64 totalSectors; -__int64 resumedPointBytesDone; -BOOL bProgressBarReverse = FALSE; -BOOL bRWThroughput = FALSE; -BOOL bShowStatus = FALSE; -BOOL bPercentMode = FALSE; - -static wchar_t *seconds, *minutes, *hours, *days; - - -// If bIOThroughput is TRUE, the speed reflects the amount of data read AND written per second (rather than -// the speed of the "transform cursor"). -void InitProgressBar (__int64 totalSecs, __int64 bytesDone, BOOL bReverse, BOOL bIOThroughput, BOOL bDisplayStatus, BOOL bShowPercent) -{ - HWND hProgressBar = GetDlgItem (hCurPage, nPbar); - SendMessage (hProgressBar, PBM_SETRANGE32, 0, 10000); - SendMessage (hProgressBar, PBM_SETSTEP, 1, 0); - - bProgressBarReverse = bReverse; - bRWThroughput = bIOThroughput; - bShowStatus = bDisplayStatus; - bPercentMode = bShowPercent; - - seconds = GetString ("SECONDS"); - minutes = GetString ("MINUTES"); - hours = GetString ("HOURS"); - days = GetString ("DAYS"); - - prevTime = startTime = GetTickCount (); - totalSectors = totalSecs; - resumedPointBytesDone = bytesDone; -} - - -BOOL UpdateProgressBar (__int64 nSecNo) -{ - return UpdateProgressBarProc (nSecNo); -} - - -BOOL UpdateProgressBarProc (__int64 nSecNo) -{ - wchar_t text[100]; - wchar_t speed[100]; - HWND hProgressBar = GetDlgItem (hCurPage, nPbar); - int time = GetTickCount (); - int elapsed = (time - startTime) / 1000; - - uint64 bytesDone = (bProgressBarReverse ? ((totalSectors - nSecNo) * SECTOR_SIZE) : ((nSecNo) * SECTOR_SIZE)); - uint64 bytesPerSec = (bProgressBarReverse ? (resumedPointBytesDone - nSecNo * SECTOR_SIZE) : (bytesDone - resumedPointBytesDone)) / (elapsed + 1); - - if (bPercentMode) - { - double perc = (double) (100.0 * (bProgressBarReverse ? ((double) (totalSectors - nSecNo)) : ((double) nSecNo)) / (totalSectors == 0 ? 0.0001 : ((double) totalSectors))); - - if (perc > 99.999999999) - wcscpy (text, GetString ("PROCESSED_PORTION_100_PERCENT")); - else - _snwprintf (text, sizeof text/2, GetString ("PROCESSED_PORTION_X_PERCENT"), perc); - - wcscat (speed, L" "); - } - else - { - GetSizeString (bytesDone, text); - if (bytesDone < (unsigned __int64) BYTES_PER_MB * 1000000) - swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_MB, GetString ("MB")); - else if (bytesDone < (unsigned __int64) BYTES_PER_GB * 1000000) - swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_GB, GetString ("GB")); - else if (bytesDone < (unsigned __int64) BYTES_PER_TB * 1000000) - swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_TB, GetString ("TB")); - else - swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_PB, GetString ("PB")); - } - - SetWindowTextW (GetDlgItem (hCurPage, IDC_BYTESWRITTEN), text); - - if (!bShowStatus) - { - GetSpeedString (bRWThroughput ? bytesPerSec*2 : bytesPerSec, speed); - wcscat (speed, L" "); - SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), speed); - } - - if (nSecNo < totalSectors) - { - int64 sec = (int64) ((bProgressBarReverse ? nSecNo : (totalSectors - nSecNo)) / ((bytesPerSec == 0 ? 0.001 : bytesPerSec) / SECTOR_SIZE)); - - if (bytesPerSec == 0 || sec > 60 * 60 * 24 * 999) - swprintf (text, L"%s ", GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE")); - else if (sec >= 60 * 60 * 24 * 2) - swprintf (text, L"%I64d %s ", sec / (60 * 24 * 60), days); - else if (sec >= 120 * 60) - swprintf (text, L"%I64d %s ", sec / (60 * 60), hours); - else if (sec >= 120) - swprintf (text, L"%I64d %s ", sec / 60, minutes); - else - swprintf (text, L"%I64d %s ", sec, seconds); - - SetWindowTextW (GetDlgItem (hCurPage, IDC_TIMEREMAIN), text); - } - - prevTime = time; - - SendMessage (hProgressBar, PBM_SETPOS, - (int) (10000.0 * (bProgressBarReverse ? (totalSectors - nSecNo) : nSecNo) / (totalSectors == 0 ? 1 : totalSectors)), - 0); - - return bVolTransformThreadCancel; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" +#include "Language.h" +#include "Dlgcode.h" +#include "Progress.h" +#include "../Format/Tcformat.h" +#include "../Format/FormatCom.h" +#include "../Format/resource.h" + +ULONG prevTime, startTime; +__int64 totalSectors; +__int64 resumedPointBytesDone; +BOOL bProgressBarReverse = FALSE; +BOOL bRWThroughput = FALSE; +BOOL bShowStatus = FALSE; +BOOL bPercentMode = FALSE; + +static wchar_t *seconds, *minutes, *hours, *days; + + +// If bIOThroughput is TRUE, the speed reflects the amount of data read AND written per second (rather than +// the speed of the "transform cursor"). +void InitProgressBar (__int64 totalSecs, __int64 bytesDone, BOOL bReverse, BOOL bIOThroughput, BOOL bDisplayStatus, BOOL bShowPercent) +{ + HWND hProgressBar = GetDlgItem (hCurPage, nPbar); + SendMessage (hProgressBar, PBM_SETRANGE32, 0, 10000); + SendMessage (hProgressBar, PBM_SETSTEP, 1, 0); + + bProgressBarReverse = bReverse; + bRWThroughput = bIOThroughput; + bShowStatus = bDisplayStatus; + bPercentMode = bShowPercent; + + seconds = GetString ("SECONDS"); + minutes = GetString ("MINUTES"); + hours = GetString ("HOURS"); + days = GetString ("DAYS"); + + prevTime = startTime = GetTickCount (); + totalSectors = totalSecs; + resumedPointBytesDone = bytesDone; +} + + +BOOL UpdateProgressBar (__int64 nSecNo) +{ + return UpdateProgressBarProc (nSecNo); +} + + +BOOL UpdateProgressBarProc (__int64 nSecNo) +{ + wchar_t text[100]; + wchar_t speed[100]; + HWND hProgressBar = GetDlgItem (hCurPage, nPbar); + int time = GetTickCount (); + int elapsed = (time - startTime) / 1000; + + uint64 bytesDone = (bProgressBarReverse ? ((totalSectors - nSecNo) * SECTOR_SIZE) : ((nSecNo) * SECTOR_SIZE)); + uint64 bytesPerSec = (bProgressBarReverse ? (resumedPointBytesDone - nSecNo * SECTOR_SIZE) : (bytesDone - resumedPointBytesDone)) / (elapsed + 1); + + if (bPercentMode) + { + double perc = (double) (100.0 * (bProgressBarReverse ? ((double) (totalSectors - nSecNo)) : ((double) nSecNo)) / (totalSectors == 0 ? 0.0001 : ((double) totalSectors))); + + if (perc > 99.999999999) + wcscpy (text, GetString ("PROCESSED_PORTION_100_PERCENT")); + else + _snwprintf (text, sizeof text/2, GetString ("PROCESSED_PORTION_X_PERCENT"), perc); + + wcscat (speed, L" "); + } + else + { + GetSizeString (bytesDone, text); + if (bytesDone < (unsigned __int64) BYTES_PER_MB * 1000000) + swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_MB, GetString ("MB")); + else if (bytesDone < (unsigned __int64) BYTES_PER_GB * 1000000) + swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_GB, GetString ("GB")); + else if (bytesDone < (unsigned __int64) BYTES_PER_TB * 1000000) + swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_TB, GetString ("TB")); + else + swprintf(text, L"%I64d %s ", bytesDone / BYTES_PER_PB, GetString ("PB")); + } + + SetWindowTextW (GetDlgItem (hCurPage, IDC_BYTESWRITTEN), text); + + if (!bShowStatus) + { + GetSpeedString (bRWThroughput ? bytesPerSec*2 : bytesPerSec, speed); + wcscat (speed, L" "); + SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), speed); + } + + if (nSecNo < totalSectors) + { + int64 sec = (int64) ((bProgressBarReverse ? nSecNo : (totalSectors - nSecNo)) / ((bytesPerSec == 0 ? 0.001 : bytesPerSec) / SECTOR_SIZE)); + + if (bytesPerSec == 0 || sec > 60 * 60 * 24 * 999) + swprintf (text, L"%s ", GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE")); + else if (sec >= 60 * 60 * 24 * 2) + swprintf (text, L"%I64d %s ", sec / (60 * 24 * 60), days); + else if (sec >= 120 * 60) + swprintf (text, L"%I64d %s ", sec / (60 * 60), hours); + else if (sec >= 120) + swprintf (text, L"%I64d %s ", sec / 60, minutes); + else + swprintf (text, L"%I64d %s ", sec, seconds); + + SetWindowTextW (GetDlgItem (hCurPage, IDC_TIMEREMAIN), text); + } + + prevTime = time; + + SendMessage (hProgressBar, PBM_SETPOS, + (int) (10000.0 * (bProgressBarReverse ? (totalSectors - nSecNo) : nSecNo) / (totalSectors == 0 ? 1 : totalSectors)), + 0); + + return bVolTransformThreadCancel; +} diff --git a/Common/PROGRESS.H b/Common/PROGRESS.H index 6c67dcb..f7804c8 100644 --- a/Common/PROGRESS.H +++ b/Common/PROGRESS.H @@ -1,22 +1,22 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifdef __cplusplus -extern "C" { -#endif - -void InitProgressBar (__int64 totalSecs, __int64 bytesDone, BOOL bReverse, BOOL bIOThroughput, BOOL bDisplayStatus, BOOL bShowPercent); -BOOL UpdateProgressBar ( __int64 nSecNo ); -BOOL UpdateProgressBarProc (__int64 nSecNo); - -#ifdef __cplusplus -} -#endif +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifdef __cplusplus +extern "C" { +#endif + +void InitProgressBar (__int64 totalSecs, __int64 bytesDone, BOOL bReverse, BOOL bIOThroughput, BOOL bDisplayStatus, BOOL bShowPercent); +BOOL UpdateProgressBar ( __int64 nSecNo ); +BOOL UpdateProgressBarProc (__int64 nSecNo); + +#ifdef __cplusplus +} +#endif diff --git a/Common/RANDOM.C b/Common/RANDOM.C index fd973ce..a7c9608 100644 --- a/Common/RANDOM.C +++ b/Common/RANDOM.C @@ -1,783 +1,774 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" -#include "Crc.h" -#include "Random.h" - -static unsigned __int8 buffer[RNG_POOL_SIZE]; -static unsigned char *pRandPool = NULL; -static BOOL bRandDidInit = FALSE; -static int nRandIndex = 0, randPoolReadIndex = 0; -static int HashFunction = DEFAULT_HASH_ALGORITHM; -static BOOL bDidSlowPoll = FALSE; -BOOL volatile bFastPollEnabled = TRUE; /* Used to reduce CPU load when performing benchmarks */ -BOOL volatile bRandmixEnabled = TRUE; /* Used to reduce CPU load when performing benchmarks */ -static BOOL RandomPoolEnrichedByUser = FALSE; - -/* Macro to add a single byte to the pool */ -#define RandaddByte(x) {\ - if (nRandIndex == RNG_POOL_SIZE) nRandIndex = 0;\ - pRandPool[nRandIndex] = (unsigned char) ((unsigned char)x + pRandPool[nRandIndex]); \ - if (nRandIndex % RANDMIX_BYTE_INTERVAL == 0) Randmix();\ - nRandIndex++; \ - } - -/* Macro to add four bytes to the pool */ -#define RandaddInt32(x) RandAddInt((unsigned __int32)x); - -void RandAddInt (unsigned __int32 x) -{ - RandaddByte(x); - RandaddByte((x >> 8)); - RandaddByte((x >> 16)); - RandaddByte((x >> 24)); -} - -#include -#include "Dlgcode.h" - -HHOOK hMouse = NULL; /* Mouse hook for the random number generator */ -HHOOK hKeyboard = NULL; /* Keyboard hook for the random number generator */ - -/* Variables for thread control, the thread is used to gather up info about - the system in in the background */ -CRITICAL_SECTION critRandProt; /* The critical section */ -BOOL volatile bThreadTerminate = FALSE; /* This variable is shared among thread's so its made volatile */ - -/* Network library handle for the SlowPoll function */ -HANDLE hNetAPI32 = NULL; - -// CryptoAPI -BOOL CryptoAPIAvailable = FALSE; -HCRYPTPROV hCryptProv; - - -/* Init the random number generator, setup the hooks, and start the thread */ -int -Randinit () -{ - if(bRandDidInit) return 0; - - InitializeCriticalSection (&critRandProt); - - bRandDidInit = TRUE; - - if (pRandPool == NULL) - { - pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE); - if (pRandPool == NULL) - goto error; - - bDidSlowPoll = FALSE; - RandomPoolEnrichedByUser = FALSE; - - memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE); - VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE); - } - - hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ()); - if (hKeyboard == 0) handleWin32Error (0); - - hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ()); - if (hMouse == 0) - { - handleWin32Error (0); - goto error; - } - - if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0) - && !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) - CryptoAPIAvailable = FALSE; - else - CryptoAPIAvailable = TRUE; - - if (_beginthread (ThreadSafeThreadFunction, 0, NULL) == -1) - goto error; - - return 0; - -error: - RandStop (TRUE); - return 1; -} - -/* Close everything down, including the thread which is closed down by - setting a flag which eventually causes the thread function to exit */ -void RandStop (BOOL freePool) -{ - if (!bRandDidInit && freePool && pRandPool) - goto freePool; - - if (bRandDidInit == FALSE) - return; - - EnterCriticalSection (&critRandProt); - - if (hMouse != 0) - UnhookWindowsHookEx (hMouse); - if (hKeyboard != 0) - UnhookWindowsHookEx (hKeyboard); - - bThreadTerminate = TRUE; - - LeaveCriticalSection (&critRandProt); - - for (;;) - { - Sleep (250); - EnterCriticalSection (&critRandProt); - if (bThreadTerminate == FALSE) - { - LeaveCriticalSection (&critRandProt); - break; - } - LeaveCriticalSection (&critRandProt); - } - - if (hNetAPI32 != 0) - { - FreeLibrary (hNetAPI32); - hNetAPI32 = NULL; - } - - if (CryptoAPIAvailable) - { - CryptReleaseContext (hCryptProv, 0); - CryptoAPIAvailable = FALSE; - } - - hMouse = NULL; - hKeyboard = NULL; - bThreadTerminate = FALSE; - DeleteCriticalSection (&critRandProt); - - bRandDidInit = FALSE; - -freePool: - if (freePool) - { - bDidSlowPoll = FALSE; - RandomPoolEnrichedByUser = FALSE; - - if (pRandPool != NULL) - { - burn (pRandPool, RANDOMPOOL_ALLOCSIZE); - TCfree (pRandPool); - pRandPool = NULL; - } - } -} - -BOOL IsRandomNumberGeneratorStarted () -{ - return bRandDidInit; -} - -void RandSetHashFunction (int hash_algo_id) -{ - if (HashIsDeprecated (hash_algo_id)) - hash_algo_id = DEFAULT_HASH_ALGORITHM; - - HashFunction = hash_algo_id; -} - -int RandGetHashFunction (void) -{ - return HashFunction; -} - -void SetRandomPoolEnrichedByUserStatus (BOOL enriched) -{ - RandomPoolEnrichedByUser = enriched; -} - -BOOL IsRandomPoolEnrichedByUser () -{ - return RandomPoolEnrichedByUser; -} - -/* The random pool mixing function */ -BOOL Randmix () -{ - if (bRandmixEnabled) - { - unsigned char hashOutputBuffer [MAX_DIGESTSIZE]; - WHIRLPOOL_CTX wctx; - RMD160_CTX rctx; - sha512_ctx sctx; - int poolIndex, digestIndex, digestSize; - - switch (HashFunction) - { - case RIPEMD160: - digestSize = RIPEMD160_DIGESTSIZE; - break; - - case SHA512: - digestSize = SHA512_DIGESTSIZE; - break; - - case WHIRLPOOL: - digestSize = WHIRLPOOL_DIGESTSIZE; - break; - - default: - TC_THROW_FATAL_EXCEPTION; - } - - if (RNG_POOL_SIZE % digestSize) - TC_THROW_FATAL_EXCEPTION; - - for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize) - { - /* Compute the message digest of the entire pool using the selected hash function. */ - switch (HashFunction) - { - case RIPEMD160: - RMD160Init(&rctx); - RMD160Update(&rctx, pRandPool, RNG_POOL_SIZE); - RMD160Final(hashOutputBuffer, &rctx); - break; - - case SHA512: - sha512_begin (&sctx); - sha512_hash (pRandPool, RNG_POOL_SIZE, &sctx); - sha512_end (hashOutputBuffer, &sctx); - break; - - case WHIRLPOOL: - WHIRLPOOL_init (&wctx); - WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx); - WHIRLPOOL_finalize (&wctx, hashOutputBuffer); - break; - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } - - /* XOR the resultant message digest to the pool at the poolIndex position. */ - for (digestIndex = 0; digestIndex < digestSize; digestIndex++) - { - pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex]; - } - } - - /* Prevent leaks */ - burn (hashOutputBuffer, MAX_DIGESTSIZE); - switch (HashFunction) - { - case RIPEMD160: - burn (&rctx, sizeof(rctx)); - break; - - case SHA512: - burn (&sctx, sizeof(sctx)); - break; - - case WHIRLPOOL: - burn (&wctx, sizeof(wctx)); - break; - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } - } - return TRUE; -} - -/* Add a buffer to the pool */ -void -RandaddBuf (void *buf, int len) -{ - int i; - for (i = 0; i < len; i++) - { - RandaddByte (((unsigned char *) buf)[i]); - } -} - -BOOL -RandpeekBytes (unsigned char *buf, int len) -{ - if (!bRandDidInit) - return FALSE; - - if (len > RNG_POOL_SIZE) - { - Error ("ERR_NOT_ENOUGH_RANDOM_DATA"); - len = RNG_POOL_SIZE; - } - - EnterCriticalSection (&critRandProt); - memcpy (buf, pRandPool, len); - LeaveCriticalSection (&critRandProt); - - return TRUE; -} - - -/* Get len random bytes from the pool (max. RNG_POOL_SIZE bytes per a single call) */ -BOOL -RandgetBytes (unsigned char *buf, int len, BOOL forceSlowPoll) -{ - int i; - BOOL ret = TRUE; - - if (!bRandDidInit || HashFunction == 0) - TC_THROW_FATAL_EXCEPTION; - - EnterCriticalSection (&critRandProt); - - if (bDidSlowPoll == FALSE || forceSlowPoll) - { - if (!SlowPoll ()) - ret = FALSE; - else - bDidSlowPoll = TRUE; - } - - if (!FastPoll ()) - ret = FALSE; - - /* There's never more than RNG_POOL_SIZE worth of randomess */ - if (len > RNG_POOL_SIZE) - { - Error ("ERR_NOT_ENOUGH_RANDOM_DATA"); - len = RNG_POOL_SIZE; - return FALSE; - } - - // Requested number of bytes is copied from pool to output buffer, - // pool is rehashed, and output buffer is XORed with new data from pool - for (i = 0; i < len; i++) - { - buf[i] = pRandPool[randPoolReadIndex++]; - if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; - } - - /* Invert the pool */ - for (i = 0; i < RNG_POOL_SIZE / 4; i++) - { - ((unsigned __int32 *) pRandPool)[i] = ~((unsigned __int32 *) pRandPool)[i]; - } - - // Mix the pool - if (!FastPoll ()) - ret = FALSE; - - // XOR the current pool content into the output buffer to prevent pool state leaks - for (i = 0; i < len; i++) - { - buf[i] ^= pRandPool[randPoolReadIndex++]; - if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; - } - - LeaveCriticalSection (&critRandProt); - - if (!ret) - TC_THROW_FATAL_EXCEPTION; - - return ret; -} - -/* Capture the mouse, and as long as the event is not the same as the last - two events, add the crc of the event, and the crc of the time difference - between this event and the last + the current time to the pool. - The role of CRC-32 is merely to perform diffusion. Note that the output - of CRC-32 is subsequently processed using a cryptographically secure hash - algorithm. */ -LRESULT CALLBACK -MouseProc (int nCode, WPARAM wParam, LPARAM lParam) -{ - static DWORD dwLastTimer; - static unsigned __int32 lastCrc, lastCrc2; - MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam; - - if (nCode < 0) - return CallNextHookEx (hMouse, nCode, wParam, lParam); - else - { - DWORD dwTimer = GetTickCount (); - DWORD j = dwLastTimer - dwTimer; - unsigned __int32 crc = 0L; - int i; - - dwLastTimer = dwTimer; - - for (i = 0; i < sizeof (MOUSEHOOKSTRUCT); i++) - { - crc = UPDC32 (((unsigned char *) lpMouse)[i], crc); - } - - if (crc != lastCrc && crc != lastCrc2) - { - unsigned __int32 timeCrc = 0L; - - for (i = 0; i < 4; i++) - { - timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc); - } - - for (i = 0; i < 4; i++) - { - timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc); - } - - EnterCriticalSection (&critRandProt); - RandaddInt32 ((unsigned __int32) (crc + timeCrc)); - LeaveCriticalSection (&critRandProt); - } - lastCrc2 = lastCrc; - lastCrc = crc; - - } - return 0; -} - -/* Capture the keyboard, as long as the event is not the same as the last two - events, add the crc of the event to the pool along with the crc of the time - difference between this event and the last. The role of CRC-32 is merely to - perform diffusion. Note that the output of CRC-32 is subsequently processed - using a cryptographically secure hash algorithm. */ -LRESULT CALLBACK -KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam) -{ - static int lLastKey, lLastKey2; - static DWORD dwLastTimer; - int nKey = (lParam & 0x00ff0000) >> 16; - int nCapture = 0; - - if (nCode < 0) - return CallNextHookEx (hMouse, nCode, wParam, lParam); - - if ((lParam & 0x0000ffff) == 1 && !(lParam & 0x20000000) && - (lParam & 0x80000000)) - { - if (nKey != lLastKey) - nCapture = 1; /* Capture this key */ - else if (nKey != lLastKey2) - nCapture = 1; /* Allow for one repeat */ - } - if (nCapture) - { - DWORD dwTimer = GetTickCount (); - DWORD j = dwLastTimer - dwTimer; - unsigned __int32 timeCrc = 0L; - int i; - - dwLastTimer = dwTimer; - lLastKey2 = lLastKey; - lLastKey = nKey; - - for (i = 0; i < 4; i++) - { - timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc); - } - - for (i = 0; i < 4; i++) - { - timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc); - } - - EnterCriticalSection (&critRandProt); - RandaddInt32 ((unsigned __int32) (crc32int(&lParam) + timeCrc)); - LeaveCriticalSection (&critRandProt); - } - - return CallNextHookEx (hMouse, nCode, wParam, lParam); -} - -/* This is the thread function which will poll the system for randomness */ -void -ThreadSafeThreadFunction (void *dummy) -{ - if (dummy); /* Remove unused parameter warning */ - - for (;;) - { - EnterCriticalSection (&critRandProt); - - if (bThreadTerminate) - { - bThreadTerminate = FALSE; - LeaveCriticalSection (&critRandProt); - _endthread (); - } - else if (bFastPollEnabled) - { - FastPoll (); - } - - LeaveCriticalSection (&critRandProt); - - Sleep (FASTPOLL_INTERVAL); - } -} - -/* Type definitions for function pointers to call NetAPI32 functions */ - -typedef - DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService, - DWORD dwLevel, DWORD dwOptions, - LPBYTE * lpBuffer); -typedef - DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer); -typedef - DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer); - -NETSTATISTICSGET pNetStatisticsGet = NULL; -NETAPIBUFFERSIZE pNetApiBufferSize = NULL; -NETAPIBUFFERFREE pNetApiBufferFree = NULL; - - -/* This is the slowpoll function which gathers up network/hard drive - performance data for the random pool */ -BOOL SlowPoll (void) -{ - static int isWorkstation = -1; - static int cbPerfData = 0x10000; - HANDLE hDevice; - LPBYTE lpBuffer; - DWORD dwSize, status; - LPWSTR lpszLanW, lpszLanS; - int nDrive; - - /* Find out whether this is an NT server or workstation if necessary */ - if (isWorkstation == -1) - { - HKEY hKey; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", - 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - unsigned char szValue[32]; - dwSize = sizeof (szValue); - - isWorkstation = TRUE; - status = RegQueryValueEx (hKey, "ProductType", 0, NULL, - szValue, &dwSize); - - if (status == ERROR_SUCCESS && _stricmp ((char *) szValue, "WinNT")) - /* Note: There are (at least) three cases for - ProductType: WinNT = NT Workstation, - ServerNT = NT Server, LanmanNT = NT Server - acting as a Domain Controller */ - isWorkstation = FALSE; - - RegCloseKey (hKey); - } - } - /* Initialize the NetAPI32 function pointers if necessary */ - if (hNetAPI32 == NULL) - { - /* Obtain a handle to the module containing the Lan Manager - functions */ - hNetAPI32 = LoadLibrary ("NETAPI32.DLL"); - if (hNetAPI32 != NULL) - { - /* Now get pointers to the functions */ - pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32, - "NetStatisticsGet"); - pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32, - "NetApiBufferSize"); - pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32, - "NetApiBufferFree"); - - /* Make sure we got valid pointers for every NetAPI32 - function */ - if (pNetStatisticsGet == NULL || - pNetApiBufferSize == NULL || - pNetApiBufferFree == NULL) - { - /* Free the library reference and reset the - static handle */ - FreeLibrary (hNetAPI32); - hNetAPI32 = NULL; - } - } - } - - /* Get network statistics. Note: Both NT Workstation and NT Server - by default will be running both the workstation and server - services. The heuristic below is probably useful though on the - assumption that the majority of the network traffic will be via - the appropriate service */ - lpszLanW = (LPWSTR) WIDE ("LanmanWorkstation"); - lpszLanS = (LPWSTR) WIDE ("LanmanServer"); - if (hNetAPI32 && - pNetStatisticsGet (NULL, - isWorkstation ? lpszLanW : lpszLanS, - 0, 0, &lpBuffer) == 0) - { - pNetApiBufferSize (lpBuffer, &dwSize); - RandaddBuf ((unsigned char *) lpBuffer, dwSize); - pNetApiBufferFree (lpBuffer); - } - - /* Get disk I/O statistics for all the hard drives */ - for (nDrive = 0;; nDrive++) - { - DISK_PERFORMANCE diskPerformance; - char szDevice[24]; - - /* Check whether we can access this device */ - sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive); - hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (hDevice == INVALID_HANDLE_VALUE) - break; - - - /* Note: This only works if you have turned on the disk - performance counters with 'diskperf -y'. These counters - are off by default */ - if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, - &diskPerformance, sizeof (DISK_PERFORMANCE), - &dwSize, NULL)) - { - RandaddBuf ((unsigned char *) &diskPerformance, dwSize); - } - CloseHandle (hDevice); - } - - // CryptoAPI - if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) - RandaddBuf (buffer, sizeof (buffer)); - - burn(buffer, sizeof (buffer)); - Randmix(); - return TRUE; -} - - -/* This is the fastpoll function which gathers up info by calling various api's */ -BOOL FastPoll (void) -{ - int nOriginalRandIndex = nRandIndex; - static BOOL addedFixedItems = FALSE; - FILETIME creationTime, exitTime, kernelTime, userTime; - DWORD minimumWorkingSetSize, maximumWorkingSetSize; - LARGE_INTEGER performanceCount; - MEMORYSTATUS memoryStatus; - HANDLE handle; - POINT point; - - /* Get various basic pieces of system information */ - RandaddInt32 (GetActiveWindow ()); /* Handle of active window */ - RandaddInt32 (GetCapture ()); /* Handle of window with mouse - capture */ - RandaddInt32 (GetClipboardOwner ()); /* Handle of clipboard owner */ - RandaddInt32 (GetClipboardViewer ()); /* Handle of start of - clpbd.viewer list */ - RandaddInt32 (GetCurrentProcess ()); /* Pseudohandle of current - process */ - RandaddInt32 (GetCurrentProcessId ()); /* Current process ID */ - RandaddInt32 (GetCurrentThread ()); /* Pseudohandle of current - thread */ - RandaddInt32 (GetCurrentThreadId ()); /* Current thread ID */ - RandaddInt32 (GetCurrentTime ()); /* Milliseconds since Windows - started */ - RandaddInt32 (GetDesktopWindow ()); /* Handle of desktop window */ - RandaddInt32 (GetFocus ()); /* Handle of window with kb.focus */ - RandaddInt32 (GetInputState ()); /* Whether sys.queue has any events */ - RandaddInt32 (GetMessagePos ()); /* Cursor pos.for last message */ - RandaddInt32 (GetMessageTime ()); /* 1 ms time for last message */ - RandaddInt32 (GetOpenClipboardWindow ()); /* Handle of window with - clpbd.open */ - RandaddInt32 (GetProcessHeap ()); /* Handle of process heap */ - RandaddInt32 (GetProcessWindowStation ()); /* Handle of procs - window station */ - RandaddInt32 (GetQueueStatus (QS_ALLEVENTS)); /* Types of events in - input queue */ - - /* Get multiword system information */ - GetCaretPos (&point); /* Current caret position */ - RandaddBuf ((unsigned char *) &point, sizeof (POINT)); - GetCursorPos (&point); /* Current mouse cursor position */ - RandaddBuf ((unsigned char *) &point, sizeof (POINT)); - - /* Get percent of memory in use, bytes of physical memory, bytes of - free physical memory, bytes in paging file, free bytes in paging - file, user bytes of address space, and free user bytes */ - memoryStatus.dwLength = sizeof (MEMORYSTATUS); - GlobalMemoryStatus (&memoryStatus); - RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS)); - - /* Get thread and process creation time, exit time, time in kernel - mode, and time in user mode in 100ns intervals */ - handle = GetCurrentThread (); - GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); - RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); - RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); - RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); - RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); - handle = GetCurrentProcess (); - GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); - RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); - RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); - RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); - RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); - - /* Get the minimum and maximum working set size for the current - process */ - GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, - &maximumWorkingSetSize); - RandaddInt32 (minimumWorkingSetSize); - RandaddInt32 (maximumWorkingSetSize); - - /* The following are fixed for the lifetime of the process so we only - add them once */ - if (addedFixedItems == 0) - { - STARTUPINFO startupInfo; - - /* Get name of desktop, console window title, new window - position and size, window flags, and handles for stdin, - stdout, and stderr */ - startupInfo.cb = sizeof (STARTUPINFO); - GetStartupInfo (&startupInfo); - RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO)); - addedFixedItems = TRUE; - } - /* The docs say QPC can fail if appropriate hardware is not - available. It works on 486 & Pentium boxes, but hasn't been tested - for 386 or RISC boxes */ - if (QueryPerformanceCounter (&performanceCount)) - RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER)); - else - { - /* Millisecond accuracy at best... */ - DWORD dwTicks = GetTickCount (); - RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks)); - } - - // CryptoAPI - if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) - RandaddBuf (buffer, sizeof (buffer)); - - /* Apply the pool mixing function */ - Randmix(); - - /* Restore the original pool cursor position. If this wasn't done, mouse coordinates - could be written to a limited area of the pool, especially when moving the mouse - uninterruptedly. The severity of the problem would depend on the length of data - written by FastPoll (if it was equal to the size of the pool, mouse coordinates - would be written only to a particular 4-byte area, whenever moving the mouse - uninterruptedly). */ - nRandIndex = nOriginalRandIndex; - - return TRUE; -} - +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" +#include "Crc.h" +#include "Random.h" + +static unsigned __int8 buffer[RNG_POOL_SIZE]; +static unsigned char *pRandPool = NULL; +static BOOL bRandDidInit = FALSE; +static int nRandIndex = 0, randPoolReadIndex = 0; +static int HashFunction = DEFAULT_HASH_ALGORITHM; +static BOOL bDidSlowPoll = FALSE; +BOOL volatile bFastPollEnabled = TRUE; /* Used to reduce CPU load when performing benchmarks */ +BOOL volatile bRandmixEnabled = TRUE; /* Used to reduce CPU load when performing benchmarks */ +static BOOL RandomPoolEnrichedByUser = FALSE; +static HANDLE PeriodicFastPollThreadHandle = NULL; + +/* Macro to add a single byte to the pool */ +#define RandaddByte(x) {\ + if (nRandIndex == RNG_POOL_SIZE) nRandIndex = 0;\ + pRandPool[nRandIndex] = (unsigned char) ((unsigned char)x + pRandPool[nRandIndex]); \ + if (nRandIndex % RANDMIX_BYTE_INTERVAL == 0) Randmix();\ + nRandIndex++; \ + } + +/* Macro to add four bytes to the pool */ +#define RandaddInt32(x) RandAddInt((unsigned __int32)x); + +void RandAddInt (unsigned __int32 x) +{ + RandaddByte(x); + RandaddByte((x >> 8)); + RandaddByte((x >> 16)); + RandaddByte((x >> 24)); +} + +#include +#include "Dlgcode.h" + +HHOOK hMouse = NULL; /* Mouse hook for the random number generator */ +HHOOK hKeyboard = NULL; /* Keyboard hook for the random number generator */ + +/* Variables for thread control, the thread is used to gather up info about + the system in in the background */ +CRITICAL_SECTION critRandProt; /* The critical section */ +BOOL volatile bThreadTerminate = FALSE; /* This variable is shared among thread's so its made volatile */ + +/* Network library handle for the SlowPoll function */ +HANDLE hNetAPI32 = NULL; + +// CryptoAPI +BOOL CryptoAPIAvailable = FALSE; +HCRYPTPROV hCryptProv; + + +/* Init the random number generator, setup the hooks, and start the thread */ +int +Randinit () +{ + if(bRandDidInit) return 0; + + InitializeCriticalSection (&critRandProt); + + bRandDidInit = TRUE; + + if (pRandPool == NULL) + { + pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE); + if (pRandPool == NULL) + goto error; + + bDidSlowPoll = FALSE; + RandomPoolEnrichedByUser = FALSE; + + memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE); + VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE); + } + + hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ()); + if (hKeyboard == 0) handleWin32Error (0); + + hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ()); + if (hMouse == 0) + { + handleWin32Error (0); + goto error; + } + + if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0) + && !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) + CryptoAPIAvailable = FALSE; + else + CryptoAPIAvailable = TRUE; + + if (!(PeriodicFastPollThreadHandle = (HANDLE) _beginthreadex (NULL, 0, PeriodicFastPollThreadProc, NULL, 0, NULL))) + goto error; + + return 0; + +error: + RandStop (TRUE); + return 1; +} + +/* Close everything down, including the thread which is closed down by + setting a flag which eventually causes the thread function to exit */ +void RandStop (BOOL freePool) +{ + if (!bRandDidInit && freePool && pRandPool) + goto freePool; + + if (bRandDidInit == FALSE) + return; + + EnterCriticalSection (&critRandProt); + + if (hMouse != 0) + UnhookWindowsHookEx (hMouse); + if (hKeyboard != 0) + UnhookWindowsHookEx (hKeyboard); + + bThreadTerminate = TRUE; + + LeaveCriticalSection (&critRandProt); + + if (PeriodicFastPollThreadHandle) + WaitForSingleObject (PeriodicFastPollThreadHandle, INFINITE); + + if (hNetAPI32 != 0) + { + FreeLibrary (hNetAPI32); + hNetAPI32 = NULL; + } + + if (CryptoAPIAvailable) + { + CryptReleaseContext (hCryptProv, 0); + CryptoAPIAvailable = FALSE; + } + + hMouse = NULL; + hKeyboard = NULL; + bThreadTerminate = FALSE; + DeleteCriticalSection (&critRandProt); + + bRandDidInit = FALSE; + +freePool: + if (freePool) + { + bDidSlowPoll = FALSE; + RandomPoolEnrichedByUser = FALSE; + + if (pRandPool != NULL) + { + burn (pRandPool, RANDOMPOOL_ALLOCSIZE); + TCfree (pRandPool); + pRandPool = NULL; + } + } +} + +BOOL IsRandomNumberGeneratorStarted () +{ + return bRandDidInit; +} + +void RandSetHashFunction (int hash_algo_id) +{ + if (HashIsDeprecated (hash_algo_id)) + hash_algo_id = DEFAULT_HASH_ALGORITHM; + + HashFunction = hash_algo_id; +} + +int RandGetHashFunction (void) +{ + return HashFunction; +} + +void SetRandomPoolEnrichedByUserStatus (BOOL enriched) +{ + RandomPoolEnrichedByUser = enriched; +} + +BOOL IsRandomPoolEnrichedByUser () +{ + return RandomPoolEnrichedByUser; +} + +/* The random pool mixing function */ +BOOL Randmix () +{ + if (bRandmixEnabled) + { + unsigned char hashOutputBuffer [MAX_DIGESTSIZE]; + WHIRLPOOL_CTX wctx; + RMD160_CTX rctx; + sha512_ctx sctx; + int poolIndex, digestIndex, digestSize; + + switch (HashFunction) + { + case RIPEMD160: + digestSize = RIPEMD160_DIGESTSIZE; + break; + + case SHA512: + digestSize = SHA512_DIGESTSIZE; + break; + + case WHIRLPOOL: + digestSize = WHIRLPOOL_DIGESTSIZE; + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + + if (RNG_POOL_SIZE % digestSize) + TC_THROW_FATAL_EXCEPTION; + + for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize) + { + /* Compute the message digest of the entire pool using the selected hash function. */ + switch (HashFunction) + { + case RIPEMD160: + RMD160Init(&rctx); + RMD160Update(&rctx, pRandPool, RNG_POOL_SIZE); + RMD160Final(hashOutputBuffer, &rctx); + break; + + case SHA512: + sha512_begin (&sctx); + sha512_hash (pRandPool, RNG_POOL_SIZE, &sctx); + sha512_end (hashOutputBuffer, &sctx); + break; + + case WHIRLPOOL: + WHIRLPOOL_init (&wctx); + WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx); + WHIRLPOOL_finalize (&wctx, hashOutputBuffer); + break; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + + /* XOR the resultant message digest to the pool at the poolIndex position. */ + for (digestIndex = 0; digestIndex < digestSize; digestIndex++) + { + pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex]; + } + } + + /* Prevent leaks */ + burn (hashOutputBuffer, MAX_DIGESTSIZE); + switch (HashFunction) + { + case RIPEMD160: + burn (&rctx, sizeof(rctx)); + break; + + case SHA512: + burn (&sctx, sizeof(sctx)); + break; + + case WHIRLPOOL: + burn (&wctx, sizeof(wctx)); + break; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + } + return TRUE; +} + +/* Add a buffer to the pool */ +void +RandaddBuf (void *buf, int len) +{ + int i; + for (i = 0; i < len; i++) + { + RandaddByte (((unsigned char *) buf)[i]); + } +} + +BOOL +RandpeekBytes (unsigned char *buf, int len) +{ + if (!bRandDidInit) + return FALSE; + + if (len > RNG_POOL_SIZE) + { + Error ("ERR_NOT_ENOUGH_RANDOM_DATA"); + len = RNG_POOL_SIZE; + } + + EnterCriticalSection (&critRandProt); + memcpy (buf, pRandPool, len); + LeaveCriticalSection (&critRandProt); + + return TRUE; +} + + +/* Get len random bytes from the pool (max. RNG_POOL_SIZE bytes per a single call) */ +BOOL +RandgetBytes (unsigned char *buf, int len, BOOL forceSlowPoll) +{ + int i; + BOOL ret = TRUE; + + if (!bRandDidInit || HashFunction == 0) + TC_THROW_FATAL_EXCEPTION; + + EnterCriticalSection (&critRandProt); + + if (bDidSlowPoll == FALSE || forceSlowPoll) + { + if (!SlowPoll ()) + ret = FALSE; + else + bDidSlowPoll = TRUE; + } + + if (!FastPoll ()) + ret = FALSE; + + /* There's never more than RNG_POOL_SIZE worth of randomess */ + if (len > RNG_POOL_SIZE) + { + Error ("ERR_NOT_ENOUGH_RANDOM_DATA"); + len = RNG_POOL_SIZE; + return FALSE; + } + + // Requested number of bytes is copied from pool to output buffer, + // pool is rehashed, and output buffer is XORed with new data from pool + for (i = 0; i < len; i++) + { + buf[i] = pRandPool[randPoolReadIndex++]; + if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; + } + + /* Invert the pool */ + for (i = 0; i < RNG_POOL_SIZE / 4; i++) + { + ((unsigned __int32 *) pRandPool)[i] = ~((unsigned __int32 *) pRandPool)[i]; + } + + // Mix the pool + if (!FastPoll ()) + ret = FALSE; + + // XOR the current pool content into the output buffer to prevent pool state leaks + for (i = 0; i < len; i++) + { + buf[i] ^= pRandPool[randPoolReadIndex++]; + if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; + } + + LeaveCriticalSection (&critRandProt); + + if (!ret) + TC_THROW_FATAL_EXCEPTION; + + return ret; +} + +/* Capture the mouse, and as long as the event is not the same as the last + two events, add the crc of the event, and the crc of the time difference + between this event and the last + the current time to the pool. + The role of CRC-32 is merely to perform diffusion. Note that the output + of CRC-32 is subsequently processed using a cryptographically secure hash + algorithm. */ +LRESULT CALLBACK +MouseProc (int nCode, WPARAM wParam, LPARAM lParam) +{ + static DWORD dwLastTimer; + static unsigned __int32 lastCrc, lastCrc2; + MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam; + + if (nCode < 0) + return CallNextHookEx (hMouse, nCode, wParam, lParam); + else + { + DWORD dwTimer = GetTickCount (); + DWORD j = dwLastTimer - dwTimer; + unsigned __int32 crc = 0L; + int i; + + dwLastTimer = dwTimer; + + for (i = 0; i < sizeof (MOUSEHOOKSTRUCT); i++) + { + crc = UPDC32 (((unsigned char *) lpMouse)[i], crc); + } + + if (crc != lastCrc && crc != lastCrc2) + { + unsigned __int32 timeCrc = 0L; + + for (i = 0; i < 4; i++) + { + timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc); + } + + for (i = 0; i < 4; i++) + { + timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc); + } + + EnterCriticalSection (&critRandProt); + RandaddInt32 ((unsigned __int32) (crc + timeCrc)); + LeaveCriticalSection (&critRandProt); + } + lastCrc2 = lastCrc; + lastCrc = crc; + + } + return 0; +} + +/* Capture the keyboard, as long as the event is not the same as the last two + events, add the crc of the event to the pool along with the crc of the time + difference between this event and the last. The role of CRC-32 is merely to + perform diffusion. Note that the output of CRC-32 is subsequently processed + using a cryptographically secure hash algorithm. */ +LRESULT CALLBACK +KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam) +{ + static int lLastKey, lLastKey2; + static DWORD dwLastTimer; + int nKey = (lParam & 0x00ff0000) >> 16; + int nCapture = 0; + + if (nCode < 0) + return CallNextHookEx (hMouse, nCode, wParam, lParam); + + if ((lParam & 0x0000ffff) == 1 && !(lParam & 0x20000000) && + (lParam & 0x80000000)) + { + if (nKey != lLastKey) + nCapture = 1; /* Capture this key */ + else if (nKey != lLastKey2) + nCapture = 1; /* Allow for one repeat */ + } + if (nCapture) + { + DWORD dwTimer = GetTickCount (); + DWORD j = dwLastTimer - dwTimer; + unsigned __int32 timeCrc = 0L; + int i; + + dwLastTimer = dwTimer; + lLastKey2 = lLastKey; + lLastKey = nKey; + + for (i = 0; i < 4; i++) + { + timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc); + } + + for (i = 0; i < 4; i++) + { + timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc); + } + + EnterCriticalSection (&critRandProt); + RandaddInt32 ((unsigned __int32) (crc32int(&lParam) + timeCrc)); + LeaveCriticalSection (&critRandProt); + } + + return CallNextHookEx (hMouse, nCode, wParam, lParam); +} + +/* This is the thread function which will poll the system for randomness */ +static unsigned __stdcall PeriodicFastPollThreadProc (void *dummy) +{ + if (dummy); /* Remove unused parameter warning */ + + for (;;) + { + EnterCriticalSection (&critRandProt); + + if (bThreadTerminate) + { + bThreadTerminate = FALSE; + LeaveCriticalSection (&critRandProt); + _endthreadex (0); + } + else if (bFastPollEnabled) + { + FastPoll (); + } + + LeaveCriticalSection (&critRandProt); + + Sleep (FASTPOLL_INTERVAL); + } +} + +/* Type definitions for function pointers to call NetAPI32 functions */ + +typedef + DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService, + DWORD dwLevel, DWORD dwOptions, + LPBYTE * lpBuffer); +typedef + DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer); +typedef + DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer); + +NETSTATISTICSGET pNetStatisticsGet = NULL; +NETAPIBUFFERSIZE pNetApiBufferSize = NULL; +NETAPIBUFFERFREE pNetApiBufferFree = NULL; + + +/* This is the slowpoll function which gathers up network/hard drive + performance data for the random pool */ +BOOL SlowPoll (void) +{ + static int isWorkstation = -1; + static int cbPerfData = 0x10000; + HANDLE hDevice; + LPBYTE lpBuffer; + DWORD dwSize, status; + LPWSTR lpszLanW, lpszLanS; + int nDrive; + + /* Find out whether this is an NT server or workstation if necessary */ + if (isWorkstation == -1) + { + HKEY hKey; + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + unsigned char szValue[32]; + dwSize = sizeof (szValue); + + isWorkstation = TRUE; + status = RegQueryValueEx (hKey, "ProductType", 0, NULL, + szValue, &dwSize); + + if (status == ERROR_SUCCESS && _stricmp ((char *) szValue, "WinNT")) + /* Note: There are (at least) three cases for + ProductType: WinNT = NT Workstation, + ServerNT = NT Server, LanmanNT = NT Server + acting as a Domain Controller */ + isWorkstation = FALSE; + + RegCloseKey (hKey); + } + } + /* Initialize the NetAPI32 function pointers if necessary */ + if (hNetAPI32 == NULL) + { + /* Obtain a handle to the module containing the Lan Manager + functions */ + hNetAPI32 = LoadLibrary ("NETAPI32.DLL"); + if (hNetAPI32 != NULL) + { + /* Now get pointers to the functions */ + pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32, + "NetStatisticsGet"); + pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32, + "NetApiBufferSize"); + pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32, + "NetApiBufferFree"); + + /* Make sure we got valid pointers for every NetAPI32 + function */ + if (pNetStatisticsGet == NULL || + pNetApiBufferSize == NULL || + pNetApiBufferFree == NULL) + { + /* Free the library reference and reset the + static handle */ + FreeLibrary (hNetAPI32); + hNetAPI32 = NULL; + } + } + } + + /* Get network statistics. Note: Both NT Workstation and NT Server + by default will be running both the workstation and server + services. The heuristic below is probably useful though on the + assumption that the majority of the network traffic will be via + the appropriate service */ + lpszLanW = (LPWSTR) WIDE ("LanmanWorkstation"); + lpszLanS = (LPWSTR) WIDE ("LanmanServer"); + if (hNetAPI32 && + pNetStatisticsGet (NULL, + isWorkstation ? lpszLanW : lpszLanS, + 0, 0, &lpBuffer) == 0) + { + pNetApiBufferSize (lpBuffer, &dwSize); + RandaddBuf ((unsigned char *) lpBuffer, dwSize); + pNetApiBufferFree (lpBuffer); + } + + /* Get disk I/O statistics for all the hard drives */ + for (nDrive = 0;; nDrive++) + { + DISK_PERFORMANCE diskPerformance; + char szDevice[24]; + + /* Check whether we can access this device */ + sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive); + hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + break; + + + /* Note: This only works if you have turned on the disk + performance counters with 'diskperf -y'. These counters + are off by default */ + if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, + &diskPerformance, sizeof (DISK_PERFORMANCE), + &dwSize, NULL)) + { + RandaddBuf ((unsigned char *) &diskPerformance, dwSize); + } + CloseHandle (hDevice); + } + + // CryptoAPI + if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) + RandaddBuf (buffer, sizeof (buffer)); + + burn(buffer, sizeof (buffer)); + Randmix(); + return TRUE; +} + + +/* This is the fastpoll function which gathers up info by calling various api's */ +BOOL FastPoll (void) +{ + int nOriginalRandIndex = nRandIndex; + static BOOL addedFixedItems = FALSE; + FILETIME creationTime, exitTime, kernelTime, userTime; + DWORD minimumWorkingSetSize, maximumWorkingSetSize; + LARGE_INTEGER performanceCount; + MEMORYSTATUS memoryStatus; + HANDLE handle; + POINT point; + + /* Get various basic pieces of system information */ + RandaddInt32 (GetActiveWindow ()); /* Handle of active window */ + RandaddInt32 (GetCapture ()); /* Handle of window with mouse + capture */ + RandaddInt32 (GetClipboardOwner ()); /* Handle of clipboard owner */ + RandaddInt32 (GetClipboardViewer ()); /* Handle of start of + clpbd.viewer list */ + RandaddInt32 (GetCurrentProcess ()); /* Pseudohandle of current + process */ + RandaddInt32 (GetCurrentProcessId ()); /* Current process ID */ + RandaddInt32 (GetCurrentThread ()); /* Pseudohandle of current + thread */ + RandaddInt32 (GetCurrentThreadId ()); /* Current thread ID */ + RandaddInt32 (GetCurrentTime ()); /* Milliseconds since Windows + started */ + RandaddInt32 (GetDesktopWindow ()); /* Handle of desktop window */ + RandaddInt32 (GetFocus ()); /* Handle of window with kb.focus */ + RandaddInt32 (GetInputState ()); /* Whether sys.queue has any events */ + RandaddInt32 (GetMessagePos ()); /* Cursor pos.for last message */ + RandaddInt32 (GetMessageTime ()); /* 1 ms time for last message */ + RandaddInt32 (GetOpenClipboardWindow ()); /* Handle of window with + clpbd.open */ + RandaddInt32 (GetProcessHeap ()); /* Handle of process heap */ + RandaddInt32 (GetProcessWindowStation ()); /* Handle of procs + window station */ + RandaddInt32 (GetQueueStatus (QS_ALLEVENTS)); /* Types of events in + input queue */ + + /* Get multiword system information */ + GetCaretPos (&point); /* Current caret position */ + RandaddBuf ((unsigned char *) &point, sizeof (POINT)); + GetCursorPos (&point); /* Current mouse cursor position */ + RandaddBuf ((unsigned char *) &point, sizeof (POINT)); + + /* Get percent of memory in use, bytes of physical memory, bytes of + free physical memory, bytes in paging file, free bytes in paging + file, user bytes of address space, and free user bytes */ + memoryStatus.dwLength = sizeof (MEMORYSTATUS); + GlobalMemoryStatus (&memoryStatus); + RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS)); + + /* Get thread and process creation time, exit time, time in kernel + mode, and time in user mode in 100ns intervals */ + handle = GetCurrentThread (); + GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); + RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); + RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); + RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); + RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); + handle = GetCurrentProcess (); + GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); + RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); + RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); + RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); + RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); + + /* Get the minimum and maximum working set size for the current + process */ + GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, + &maximumWorkingSetSize); + RandaddInt32 (minimumWorkingSetSize); + RandaddInt32 (maximumWorkingSetSize); + + /* The following are fixed for the lifetime of the process so we only + add them once */ + if (addedFixedItems == 0) + { + STARTUPINFO startupInfo; + + /* Get name of desktop, console window title, new window + position and size, window flags, and handles for stdin, + stdout, and stderr */ + startupInfo.cb = sizeof (STARTUPINFO); + GetStartupInfo (&startupInfo); + RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO)); + addedFixedItems = TRUE; + } + /* The docs say QPC can fail if appropriate hardware is not + available. It works on 486 & Pentium boxes, but hasn't been tested + for 386 or RISC boxes */ + if (QueryPerformanceCounter (&performanceCount)) + RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER)); + else + { + /* Millisecond accuracy at best... */ + DWORD dwTicks = GetTickCount (); + RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks)); + } + + // CryptoAPI + if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) + RandaddBuf (buffer, sizeof (buffer)); + + /* Apply the pool mixing function */ + Randmix(); + + /* Restore the original pool cursor position. If this wasn't done, mouse coordinates + could be written to a limited area of the pool, especially when moving the mouse + uninterruptedly. The severity of the problem would depend on the length of data + written by FastPoll (if it was equal to the size of the pool, mouse coordinates + would be written only to a particular 4-byte area, whenever moving the mouse + uninterruptedly). */ + nRandIndex = nOriginalRandIndex; + + return TRUE; +} + diff --git a/Common/RANDOM.H b/Common/RANDOM.H index 4b85060..c917f14 100644 --- a/Common/RANDOM.H +++ b/Common/RANDOM.H @@ -1,61 +1,61 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - - -#include "Crypto.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* RNG defines & pool pointers */ -#define RNG_POOL_SIZE 640 // Must be divisible by the size of the output of each of the implemented hash functions. (in bytes) -#if RNG_POOL_SIZE % SHA512_DIGESTSIZE || RNG_POOL_SIZE % WHIRLPOOL_DIGESTSIZE || RNG_POOL_SIZE % RIPEMD160_DIGESTSIZE -#error RNG_POOL_SIZE must be divisible by the size of the output of each of the implemented hash functions. -#endif - -#define RANDOMPOOL_ALLOCSIZE RNG_POOL_SIZE - -// After every RANDMIX_BYTE_INTERVAL-th byte written to the pool, the pool mixing function is applied to the entire pool -#define RANDMIX_BYTE_INTERVAL 16 - -// FastPoll interval (in milliseconds) -#define FASTPOLL_INTERVAL 500 - -void RandAddInt ( unsigned __int32 x ); -int Randinit ( void ); -void RandStop (BOOL freePool); -BOOL IsRandomNumberGeneratorStarted (); -void RandSetHashFunction ( int hash_algo_id ); -int RandGetHashFunction (void); -void SetRandomPoolEnrichedByUserStatus (BOOL enriched); -BOOL IsRandomPoolEnrichedByUser (); -BOOL Randmix ( void ); -void RandaddBuf ( void *buf , int len ); -BOOL FastPoll ( void ); -BOOL SlowPoll ( void ); -BOOL RandpeekBytes ( unsigned char *buf , int len ); -BOOL RandgetBytes ( unsigned char *buf , int len, BOOL forceSlowPoll ); - -#ifdef _WIN32 - -extern BOOL volatile bFastPollEnabled; -extern BOOL volatile bRandmixEnabled; - -LRESULT CALLBACK MouseProc ( int nCode , WPARAM wParam , LPARAM lParam ); -LRESULT CALLBACK KeyboardProc ( int nCode , WPARAM wParam , LPARAM lParam ); -void ThreadSafeThreadFunction ( void *dummy ); - -#endif - -#ifdef __cplusplus -} -#endif +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + + +#include "Crypto.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* RNG defines & pool pointers */ +#define RNG_POOL_SIZE 640 // Must be divisible by the size of the output of each of the implemented hash functions. (in bytes) +#if RNG_POOL_SIZE % SHA512_DIGESTSIZE || RNG_POOL_SIZE % WHIRLPOOL_DIGESTSIZE || RNG_POOL_SIZE % RIPEMD160_DIGESTSIZE +#error RNG_POOL_SIZE must be divisible by the size of the output of each of the implemented hash functions. +#endif + +#define RANDOMPOOL_ALLOCSIZE RNG_POOL_SIZE + +// After every RANDMIX_BYTE_INTERVAL-th byte written to the pool, the pool mixing function is applied to the entire pool +#define RANDMIX_BYTE_INTERVAL 16 + +// FastPoll interval (in milliseconds) +#define FASTPOLL_INTERVAL 500 + +void RandAddInt ( unsigned __int32 x ); +int Randinit ( void ); +void RandStop (BOOL freePool); +BOOL IsRandomNumberGeneratorStarted (); +void RandSetHashFunction ( int hash_algo_id ); +int RandGetHashFunction (void); +void SetRandomPoolEnrichedByUserStatus (BOOL enriched); +BOOL IsRandomPoolEnrichedByUser (); +BOOL Randmix ( void ); +void RandaddBuf ( void *buf , int len ); +BOOL FastPoll ( void ); +BOOL SlowPoll ( void ); +BOOL RandpeekBytes ( unsigned char *buf , int len ); +BOOL RandgetBytes ( unsigned char *buf , int len, BOOL forceSlowPoll ); + +#ifdef _WIN32 + +extern BOOL volatile bFastPollEnabled; +extern BOOL volatile bRandmixEnabled; + +LRESULT CALLBACK MouseProc ( int nCode , WPARAM wParam , LPARAM lParam ); +LRESULT CALLBACK KeyboardProc ( int nCode , WPARAM wParam , LPARAM lParam ); +static unsigned __stdcall PeriodicFastPollThreadProc (void *dummy); + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/Common/Registry.c b/Common/Registry.c index d7f473d..0fa0660 100644 --- a/Common/Registry.c +++ b/Common/Registry.c @@ -1,238 +1,238 @@ -/* - Copyright (c) 2004-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Tcdefs.h" -#include "Registry.h" - -BOOL ReadLocalMachineRegistryDword (char *subKey, char *name, DWORD *value) -{ - HKEY hkey = 0; - DWORD size = sizeof (*value); - DWORD type; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS) - return FALSE; - - if (RegQueryValueEx (hkey, name, NULL, &type, (BYTE *) value, &size) != ERROR_SUCCESS) - { - RegCloseKey (hkey); - return FALSE; - } - - RegCloseKey (hkey); - return type == REG_DWORD; -} - -BOOL ReadLocalMachineRegistryMultiString (char *subKey, char *name, char *value, DWORD *size) -{ - HKEY hkey = 0; - DWORD type; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS) - return FALSE; - - if (RegQueryValueEx (hkey, name, NULL, &type, (BYTE *) value, size) != ERROR_SUCCESS) - { - RegCloseKey (hkey); - return FALSE; - } - - RegCloseKey (hkey); - return type == REG_MULTI_SZ; -} - -BOOL ReadLocalMachineRegistryString (char *subKey, char *name, char *str, DWORD *size) -{ - HKEY hkey = 0; - DWORD type; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS) - return FALSE; - - if (RegQueryValueEx (hkey, name, NULL, &type, (BYTE *) str, size) != ERROR_SUCCESS) - { - RegCloseKey (hkey); - return FALSE; - } - - RegCloseKey (hkey); - return type == REG_SZ; -} - -int ReadRegistryInt (char *subKey, char *name, int defaultValue) -{ - HKEY hkey = 0; - DWORD value, size = sizeof (DWORD); - - if (RegOpenKeyEx (HKEY_CURRENT_USER, subKey, - 0, KEY_READ, &hkey) != ERROR_SUCCESS) - return defaultValue; - - if (RegQueryValueEx (hkey, name, 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS) - value = defaultValue; - - RegCloseKey (hkey); - return value; -} - -char *ReadRegistryString (char *subKey, char *name, char *defaultValue, char *str, int maxLen) -{ - HKEY hkey = 0; - char value[MAX_PATH*4]; - DWORD size = sizeof (value); - - strncpy (str, defaultValue, maxLen-1); - - ZeroMemory (value, sizeof value); - if (RegOpenKeyEx (HKEY_CURRENT_USER, subKey, - 0, KEY_READ, &hkey) == ERROR_SUCCESS) - if (RegQueryValueEx (hkey, name, 0, 0, (LPBYTE) &value, &size) == ERROR_SUCCESS) - strncpy (str, value, maxLen-1); - - RegCloseKey (hkey); - return str; -} - -DWORD ReadRegistryBytes (char *path, char *name, char *value, int maxLen) -{ - HKEY hkey = 0; - DWORD size = maxLen; - BOOL success = FALSE; - - if (RegOpenKeyEx (HKEY_CURRENT_USER, path, 0, KEY_READ, &hkey) != ERROR_SUCCESS) - return 0; - - success = (RegQueryValueEx (hkey, name, 0, 0, (LPBYTE) value, &size) == ERROR_SUCCESS); - RegCloseKey (hkey); - - return success ? size : 0; -} - -void WriteRegistryInt (char *subKey, char *name, int value) -{ - HKEY hkey = 0; - DWORD disp; - - if (RegCreateKeyEx (HKEY_CURRENT_USER, subKey, - 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp) != ERROR_SUCCESS) - return; - - RegSetValueEx (hkey, name, 0, REG_DWORD, (BYTE *) &value, sizeof value); - RegCloseKey (hkey); -} - -BOOL WriteLocalMachineRegistryDword (char *subKey, char *name, DWORD value) -{ - HKEY hkey = 0; - DWORD disp; - LONG status; - - if ((status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, subKey, - 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp)) != ERROR_SUCCESS) - { - SetLastError (status); - return FALSE; - } - - if ((status = RegSetValueEx (hkey, name, 0, REG_DWORD, (BYTE *) &value, sizeof value)) != ERROR_SUCCESS) - { - RegCloseKey (hkey); - SetLastError (status); - return FALSE; - } - - RegCloseKey (hkey); - return TRUE; -} - -BOOL WriteLocalMachineRegistryMultiString (char *subKey, char *name, char *multiString, DWORD size) -{ - HKEY hkey = 0; - DWORD disp; - LONG status; - - if ((status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, subKey, - 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp)) != ERROR_SUCCESS) - { - SetLastError (status); - return FALSE; - } - - if ((status = RegSetValueEx (hkey, name, 0, REG_MULTI_SZ, (BYTE *) multiString, size)) != ERROR_SUCCESS) - { - RegCloseKey (hkey); - SetLastError (status); - return FALSE; - } - - RegCloseKey (hkey); - return TRUE; -} - -BOOL WriteLocalMachineRegistryString (char *subKey, char *name, char *str, DWORD size) -{ - HKEY hkey = 0; - DWORD disp; - LONG status; - - if ((status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, subKey, - 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp)) != ERROR_SUCCESS) - { - SetLastError (status); - return FALSE; - } - - if ((status = RegSetValueEx (hkey, name, 0, REG_SZ, (BYTE *) str, size)) != ERROR_SUCCESS) - { - RegCloseKey (hkey); - SetLastError (status); - return FALSE; - } - - RegCloseKey (hkey); - return TRUE; -} - -void WriteRegistryString (char *subKey, char *name, char *str) -{ - HKEY hkey = 0; - DWORD disp; - - if (RegCreateKeyEx (HKEY_CURRENT_USER, subKey, - 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp) != ERROR_SUCCESS) - return; - - RegSetValueEx (hkey, name, 0, REG_SZ, (BYTE *) str, strlen (str) + 1); - RegCloseKey (hkey); -} - -BOOL WriteRegistryBytes (char *path, char *name, char *str, DWORD size) -{ - HKEY hkey = 0; - DWORD disp; - BOOL res; - - if (RegCreateKeyEx (HKEY_CURRENT_USER, path, - 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp) != ERROR_SUCCESS) - return FALSE; - - res = RegSetValueEx (hkey, name, 0, REG_BINARY, (BYTE *) str, size); - RegCloseKey (hkey); - return res == ERROR_SUCCESS; -} - -void DeleteRegistryValue (char *subKey, char *name) -{ - HKEY hkey = 0; - - if (RegOpenKeyEx (HKEY_CURRENT_USER, subKey, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS) - return; - - RegDeleteValue (hkey, name); - RegCloseKey (hkey); +/* + Copyright (c) 2004-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Tcdefs.h" +#include "Registry.h" + +BOOL ReadLocalMachineRegistryDword (char *subKey, char *name, DWORD *value) +{ + HKEY hkey = 0; + DWORD size = sizeof (*value); + DWORD type; + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS) + return FALSE; + + if (RegQueryValueEx (hkey, name, NULL, &type, (BYTE *) value, &size) != ERROR_SUCCESS) + { + RegCloseKey (hkey); + return FALSE; + } + + RegCloseKey (hkey); + return type == REG_DWORD; +} + +BOOL ReadLocalMachineRegistryMultiString (char *subKey, char *name, char *value, DWORD *size) +{ + HKEY hkey = 0; + DWORD type; + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS) + return FALSE; + + if (RegQueryValueEx (hkey, name, NULL, &type, (BYTE *) value, size) != ERROR_SUCCESS) + { + RegCloseKey (hkey); + return FALSE; + } + + RegCloseKey (hkey); + return type == REG_MULTI_SZ; +} + +BOOL ReadLocalMachineRegistryString (char *subKey, char *name, char *str, DWORD *size) +{ + HKEY hkey = 0; + DWORD type; + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS) + return FALSE; + + if (RegQueryValueEx (hkey, name, NULL, &type, (BYTE *) str, size) != ERROR_SUCCESS) + { + RegCloseKey (hkey); + return FALSE; + } + + RegCloseKey (hkey); + return type == REG_SZ; +} + +int ReadRegistryInt (char *subKey, char *name, int defaultValue) +{ + HKEY hkey = 0; + DWORD value, size = sizeof (DWORD); + + if (RegOpenKeyEx (HKEY_CURRENT_USER, subKey, + 0, KEY_READ, &hkey) != ERROR_SUCCESS) + return defaultValue; + + if (RegQueryValueEx (hkey, name, 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS) + value = defaultValue; + + RegCloseKey (hkey); + return value; +} + +char *ReadRegistryString (char *subKey, char *name, char *defaultValue, char *str, int maxLen) +{ + HKEY hkey = 0; + char value[MAX_PATH*4]; + DWORD size = sizeof (value); + + strncpy (str, defaultValue, maxLen-1); + + ZeroMemory (value, sizeof value); + if (RegOpenKeyEx (HKEY_CURRENT_USER, subKey, + 0, KEY_READ, &hkey) == ERROR_SUCCESS) + if (RegQueryValueEx (hkey, name, 0, 0, (LPBYTE) &value, &size) == ERROR_SUCCESS) + strncpy (str, value, maxLen-1); + + RegCloseKey (hkey); + return str; +} + +DWORD ReadRegistryBytes (char *path, char *name, char *value, int maxLen) +{ + HKEY hkey = 0; + DWORD size = maxLen; + BOOL success = FALSE; + + if (RegOpenKeyEx (HKEY_CURRENT_USER, path, 0, KEY_READ, &hkey) != ERROR_SUCCESS) + return 0; + + success = (RegQueryValueEx (hkey, name, 0, 0, (LPBYTE) value, &size) == ERROR_SUCCESS); + RegCloseKey (hkey); + + return success ? size : 0; +} + +void WriteRegistryInt (char *subKey, char *name, int value) +{ + HKEY hkey = 0; + DWORD disp; + + if (RegCreateKeyEx (HKEY_CURRENT_USER, subKey, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp) != ERROR_SUCCESS) + return; + + RegSetValueEx (hkey, name, 0, REG_DWORD, (BYTE *) &value, sizeof value); + RegCloseKey (hkey); +} + +BOOL WriteLocalMachineRegistryDword (char *subKey, char *name, DWORD value) +{ + HKEY hkey = 0; + DWORD disp; + LONG status; + + if ((status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, subKey, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp)) != ERROR_SUCCESS) + { + SetLastError (status); + return FALSE; + } + + if ((status = RegSetValueEx (hkey, name, 0, REG_DWORD, (BYTE *) &value, sizeof value)) != ERROR_SUCCESS) + { + RegCloseKey (hkey); + SetLastError (status); + return FALSE; + } + + RegCloseKey (hkey); + return TRUE; +} + +BOOL WriteLocalMachineRegistryMultiString (char *subKey, char *name, char *multiString, DWORD size) +{ + HKEY hkey = 0; + DWORD disp; + LONG status; + + if ((status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, subKey, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp)) != ERROR_SUCCESS) + { + SetLastError (status); + return FALSE; + } + + if ((status = RegSetValueEx (hkey, name, 0, REG_MULTI_SZ, (BYTE *) multiString, size)) != ERROR_SUCCESS) + { + RegCloseKey (hkey); + SetLastError (status); + return FALSE; + } + + RegCloseKey (hkey); + return TRUE; +} + +BOOL WriteLocalMachineRegistryString (char *subKey, char *name, char *str, DWORD size) +{ + HKEY hkey = 0; + DWORD disp; + LONG status; + + if ((status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, subKey, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp)) != ERROR_SUCCESS) + { + SetLastError (status); + return FALSE; + } + + if ((status = RegSetValueEx (hkey, name, 0, REG_SZ, (BYTE *) str, size)) != ERROR_SUCCESS) + { + RegCloseKey (hkey); + SetLastError (status); + return FALSE; + } + + RegCloseKey (hkey); + return TRUE; +} + +void WriteRegistryString (char *subKey, char *name, char *str) +{ + HKEY hkey = 0; + DWORD disp; + + if (RegCreateKeyEx (HKEY_CURRENT_USER, subKey, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp) != ERROR_SUCCESS) + return; + + RegSetValueEx (hkey, name, 0, REG_SZ, (BYTE *) str, strlen (str) + 1); + RegCloseKey (hkey); +} + +BOOL WriteRegistryBytes (char *path, char *name, char *str, DWORD size) +{ + HKEY hkey = 0; + DWORD disp; + BOOL res; + + if (RegCreateKeyEx (HKEY_CURRENT_USER, path, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &disp) != ERROR_SUCCESS) + return FALSE; + + res = RegSetValueEx (hkey, name, 0, REG_BINARY, (BYTE *) str, size); + RegCloseKey (hkey); + return res == ERROR_SUCCESS; +} + +void DeleteRegistryValue (char *subKey, char *name) +{ + HKEY hkey = 0; + + if (RegOpenKeyEx (HKEY_CURRENT_USER, subKey, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS) + return; + + RegDeleteValue (hkey, name); + RegCloseKey (hkey); } \ No newline at end of file diff --git a/Common/Registry.h b/Common/Registry.h index fc9eac0..6a2e999 100644 --- a/Common/Registry.h +++ b/Common/Registry.h @@ -1,29 +1,29 @@ -/* - Copyright (c) 2004-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -BOOL ReadLocalMachineRegistryDword (char *subKey, char *name, DWORD *value); -BOOL ReadLocalMachineRegistryMultiString (char *subKey, char *name, char *value, DWORD *size); -BOOL ReadLocalMachineRegistryString (char *subKey, char *name, char *value, DWORD *size); -int ReadRegistryInt (char *subKey, char *name, int defaultValue); -char *ReadRegistryString (char *subKey, char *name, char *defaultValue, char *str, int maxLen); -DWORD ReadRegistryBytes (char *path, char *name, char *value, int maxLen); -void WriteRegistryInt (char *subKey, char *name, int value); -BOOL WriteLocalMachineRegistryDword (char *subKey, char *name, DWORD value); -BOOL WriteLocalMachineRegistryMultiString (char *subKey, char *name, char *multiString, DWORD size); -BOOL WriteLocalMachineRegistryString (char *subKey, char *name, char *str, DWORD size); -void WriteRegistryString (char *subKey, char *name, char *str); -BOOL WriteRegistryBytes (char *path, char *name, char *str, DWORD size); -void DeleteRegistryValue (char *subKey, char *name); - -#ifdef __cplusplus -} -#endif +/* + Copyright (c) 2004-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL ReadLocalMachineRegistryDword (char *subKey, char *name, DWORD *value); +BOOL ReadLocalMachineRegistryMultiString (char *subKey, char *name, char *value, DWORD *size); +BOOL ReadLocalMachineRegistryString (char *subKey, char *name, char *value, DWORD *size); +int ReadRegistryInt (char *subKey, char *name, int defaultValue); +char *ReadRegistryString (char *subKey, char *name, char *defaultValue, char *str, int maxLen); +DWORD ReadRegistryBytes (char *path, char *name, char *value, int maxLen); +void WriteRegistryInt (char *subKey, char *name, int value); +BOOL WriteLocalMachineRegistryDword (char *subKey, char *name, DWORD value); +BOOL WriteLocalMachineRegistryMultiString (char *subKey, char *name, char *multiString, DWORD size); +BOOL WriteLocalMachineRegistryString (char *subKey, char *name, char *str, DWORD size); +void WriteRegistryString (char *subKey, char *name, char *str); +BOOL WriteRegistryBytes (char *path, char *name, char *str, DWORD size); +void DeleteRegistryValue (char *subKey, char *name); + +#ifdef __cplusplus +} +#endif diff --git a/Common/SecurityToken.cpp b/Common/SecurityToken.cpp index 2f6774e..a8a256b 100644 --- a/Common/SecurityToken.cpp +++ b/Common/SecurityToken.cpp @@ -1,761 +1,761 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/Finally.h" -#include "Platform/ForEach.h" - -#if !defined (TC_WINDOWS) || defined (TC_PROTOTYPE) -# include "Platform/SerializerFactory.h" -# include "Platform/StringConverter.h" -# include "Platform/SystemException.h" -#else -# include "Dictionary.h" -# include "Language.h" -#endif - -#ifdef TC_UNIX -# include -#endif - -#include "SecurityToken.h" - -#ifndef burn -# define burn Memory::Erase -#endif - -using namespace std; - -namespace TrueCrypt -{ - SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path) - { - wstring pathStr = path; - unsigned long slotId; - - if (swscanf (pathStr.c_str(), TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) - throw InvalidSecurityTokenKeyfilePath(); - - SlotId = slotId; - - size_t keyIdPos = pathStr.find (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/"); - if (keyIdPos == string::npos) - throw InvalidSecurityTokenKeyfilePath(); - - Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size()); - - vector keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id); - - if (keyfiles.empty()) - throw SecurityTokenKeyfileNotFound(); - - *this = keyfiles.front(); - } - - SecurityTokenKeyfile::operator SecurityTokenKeyfilePath () const - { - wstringstream path; - path << TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/" << SlotId << L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/" << Id; - return path.str(); - } - - void SecurityToken::CheckLibraryStatus () - { - if (!Initialized) - throw SecurityTokenLibraryNotInitialized(); - } - - void SecurityToken::CloseLibrary () - { - if (Initialized) - { - CloseAllSessions(); - Pkcs11Functions->C_Finalize (NULL_PTR); - -#ifdef TC_WINDOWS - FreeLibrary (Pkcs11LibraryHandle); -#else - dlclose (Pkcs11LibraryHandle); -#endif - Initialized = false; - } - } - - void SecurityToken::CloseAllSessions () throw () - { - if (!Initialized) - return; - - typedef pair SessionMapPair; - - foreach (SessionMapPair p, Sessions) - { - try - { - CloseSession (p.first); - } - catch (...) { } - } - } - - void SecurityToken::CloseSession (CK_SLOT_ID slotId) - { - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); - - Pkcs11Functions->C_CloseSession (Sessions[slotId].Handle); - Sessions.erase (Sessions.find (slotId)); - } - - void SecurityToken::CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name) - { - if (name.empty()) - throw ParameterIncorrect (SRC_POS); - - LoginUserIfRequired (slotId); - - foreach (const SecurityTokenKeyfile &keyfile, GetAvailableKeyfiles (&slotId)) - { - if (keyfile.IdUtf8 == name) - throw SecurityTokenKeyfileAlreadyExists(); - } - - CK_OBJECT_CLASS dataClass = CKO_DATA; - CK_BBOOL trueVal = CK_TRUE; - - CK_ATTRIBUTE keyfileTemplate[] = - { - { CKA_CLASS, &dataClass, sizeof (dataClass) }, - { CKA_TOKEN, &trueVal, sizeof (trueVal) }, - { CKA_PRIVATE, &trueVal, sizeof (trueVal) }, - { CKA_LABEL, (CK_UTF8CHAR *) name.c_str(), name.size() }, - { CKA_VALUE, &keyfileData.front(), keyfileData.size() } - }; - - CK_OBJECT_HANDLE keyfileHandle; - - CK_RV status = Pkcs11Functions->C_CreateObject (Sessions[slotId].Handle, keyfileTemplate, array_capacity (keyfileTemplate), &keyfileHandle); - - switch (status) - { - case CKR_DATA_LEN_RANGE: - status = CKR_DEVICE_MEMORY; - break; - - case CKR_SESSION_READ_ONLY: - status = CKR_TOKEN_WRITE_PROTECTED; - break; - } - - if (status != CKR_OK) - throw Pkcs11Exception (status); - - // Some tokens report success even if the new object was truncated to fit in the available memory - vector objectData; - - GetObjectAttribute (slotId, keyfileHandle, CKA_VALUE, objectData); - finally_do_arg (vector *, &objectData, { burn (&finally_arg->front(), finally_arg->size()); }); - - if (objectData.size() != keyfileData.size()) - { - Pkcs11Functions->C_DestroyObject (Sessions[slotId].Handle, keyfileHandle); - throw Pkcs11Exception (CKR_DEVICE_MEMORY); - } - } - - void SecurityToken::DeleteKeyfile (const SecurityTokenKeyfile &keyfile) - { - LoginUserIfRequired (keyfile.SlotId); - - CK_RV status = Pkcs11Functions->C_DestroyObject (Sessions[keyfile.SlotId].Handle, keyfile.Handle); - if (status != CKR_OK) - throw Pkcs11Exception (status); - } - - vector SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter) - { - bool unrecognizedTokenPresent = false; - vector keyfiles; - - foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) - { - SecurityTokenInfo token; - - if (slotIdFilter && *slotIdFilter != slotId) - continue; - - try - { - LoginUserIfRequired (slotId); - token = GetTokenInfo (slotId); - } - catch (UserAbort &) - { - continue; - } - catch (Pkcs11Exception &e) - { - if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) - { - unrecognizedTokenPresent = true; - continue; - } - - throw; - } - - foreach (const CK_OBJECT_HANDLE &dataHandle, GetObjects (slotId, CKO_DATA)) - { - SecurityTokenKeyfile keyfile; - keyfile.Handle = dataHandle; - keyfile.SlotId = slotId; - keyfile.Token = token; - - vector privateAttrib; - GetObjectAttribute (slotId, dataHandle, CKA_PRIVATE, privateAttrib); - - if (privateAttrib.size() == sizeof (CK_BBOOL) && *(CK_BBOOL *) &privateAttrib.front() != CK_TRUE) - continue; - - vector label; - GetObjectAttribute (slotId, dataHandle, CKA_LABEL, label); - label.push_back (0); - - keyfile.IdUtf8 = (char *) &label.front(); - -#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) - keyfile.Id = Utf8StringToWide ((const char *) &label.front()); -#else - keyfile.Id = StringConverter::ToWide ((const char *) &label.front()); -#endif - if (keyfile.Id.empty() || (!keyfileIdFilter.empty() && keyfileIdFilter != keyfile.Id)) - continue; - - keyfiles.push_back (keyfile); - - if (!keyfileIdFilter.empty()) - break; - } - } - - if (keyfiles.empty() && unrecognizedTokenPresent) - throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); - - return keyfiles; - } - - list SecurityToken::GetAvailableTokens () - { - bool unrecognizedTokenPresent = false; - list tokens; - - foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) - { - try - { - tokens.push_back (GetTokenInfo (slotId)); - } - catch (Pkcs11Exception &e) - { - if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) - { - unrecognizedTokenPresent = true; - continue; - } - - throw; - } - } - - if (tokens.empty() && unrecognizedTokenPresent) - throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); - - return tokens; - } - - SecurityTokenInfo SecurityToken::GetTokenInfo (CK_SLOT_ID slotId) - { - CK_TOKEN_INFO info; - CK_RV status = Pkcs11Functions->C_GetTokenInfo (slotId, &info); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - SecurityTokenInfo token; - token.SlotId = slotId; - token.Flags = info.flags; - - char label[sizeof (info.label) + 1]; - memset (label, 0, sizeof (label)); - memcpy (label, info.label, sizeof (info.label)); - - token.LabelUtf8 = label; - - size_t lastSpace = token.LabelUtf8.find_last_not_of (' '); - if (lastSpace == string::npos) - token.LabelUtf8.clear(); - else - token.LabelUtf8 = token.LabelUtf8.substr (0, lastSpace + 1); - -#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) - token.Label = Utf8StringToWide (token.LabelUtf8); -#else - token.Label = StringConverter::ToWide (token.LabelUtf8); -#endif - return token; - } - - void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData) - { - LoginUserIfRequired (keyfile.SlotId); - GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData); - } - - vector SecurityToken::GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass) - { - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); - - CK_ATTRIBUTE findTemplate; - findTemplate.type = CKA_CLASS; - findTemplate.pValue = &objectClass; - findTemplate.ulValueLen = sizeof (objectClass); - - CK_RV status = Pkcs11Functions->C_FindObjectsInit (Sessions[slotId].Handle, &findTemplate, 1); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - finally_do_arg (CK_SLOT_ID, slotId, { Pkcs11Functions->C_FindObjectsFinal (Sessions[finally_arg].Handle); }); - - CK_ULONG objectCount; - vector objects; - - while (true) - { - CK_OBJECT_HANDLE object; - CK_RV status = Pkcs11Functions->C_FindObjects (Sessions[slotId].Handle, &object, 1, &objectCount); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - if (objectCount != 1) - break; - - objects.push_back (object); - } - - return objects; - } - - void SecurityToken::GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector &attributeValue) - { - attributeValue.clear(); - - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); - - CK_ATTRIBUTE attribute; - attribute.type = attributeType; - attribute.pValue = NULL_PTR; - - CK_RV status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - if (attribute.ulValueLen == 0) - return; - - attributeValue = vector (attribute.ulValueLen); - attribute.pValue = &attributeValue.front(); - - status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); - if (status != CKR_OK) - throw Pkcs11Exception (status); - } - - list SecurityToken::GetTokenSlots () - { - CheckLibraryStatus(); - - list slots; - CK_ULONG slotCount; - - CK_RV status = Pkcs11Functions->C_GetSlotList (TRUE, NULL_PTR, &slotCount); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - if (slotCount > 0) - { - vector slotArray (slotCount); - status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - for (size_t i = 0; i < slotCount; i++) - { - CK_SLOT_INFO slotInfo; - status = Pkcs11Functions->C_GetSlotInfo (slotArray[i], &slotInfo); - - if (status != CKR_OK || !(slotInfo.flags & CKF_TOKEN_PRESENT)) - continue; - - slots.push_back (slotArray[i]); - } - } - - return slots; - } - - bool SecurityToken::IsKeyfilePathValid (const wstring &securityTokenKeyfilePath) - { - return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0; - } - - void SecurityToken::Login (CK_SLOT_ID slotId, const string &pin) - { - if (Sessions.find (slotId) == Sessions.end()) - OpenSession (slotId); - else if (Sessions[slotId].UserLoggedIn) - return; - - CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin.c_str(), pin.size()); - - if (status != CKR_OK) - throw Pkcs11Exception (status); - - Sessions[slotId].UserLoggedIn = true; - } - - void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId) - { - CheckLibraryStatus(); - CK_RV status; - - if (Sessions.find (slotId) == Sessions.end()) - { - OpenSession (slotId); - } - else - { - CK_SESSION_INFO sessionInfo; - status = Pkcs11Functions->C_GetSessionInfo (Sessions[slotId].Handle, &sessionInfo); - - if (status == CKR_OK) - { - Sessions[slotId].UserLoggedIn = (sessionInfo.state == CKS_RO_USER_FUNCTIONS || sessionInfo.state == CKS_RW_USER_FUNCTIONS); - } - else - { - try - { - CloseSession (slotId); - } - catch (...) { } - OpenSession (slotId); - } - } - - SecurityTokenInfo tokenInfo = GetTokenInfo (slotId); - - while (!Sessions[slotId].UserLoggedIn && (tokenInfo.Flags & CKF_LOGIN_REQUIRED)) - { - try - { - if (tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH) - { - status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0); - if (status != CKR_OK) - throw Pkcs11Exception (status); - } - else - { - string pin = tokenInfo.LabelUtf8; - if (tokenInfo.Label.empty()) - { - stringstream s; - s << "#" << slotId; - pin = s.str(); - } - - finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); }); - - (*PinCallback) (pin); - Login (slotId, pin); - } - - Sessions[slotId].UserLoggedIn = true; - } - catch (Pkcs11Exception &e) - { - CK_RV error = e.GetErrorCode(); - - if (error == CKR_USER_ALREADY_LOGGED_IN) - { - break; - } - else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)) - { - (*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT)); - continue; - } - - throw; - } - } - } - - void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback) - { - if (Initialized) - CloseLibrary(); - -#ifdef TC_WINDOWS - Pkcs11LibraryHandle = LoadLibraryA (pkcs11LibraryPath.c_str()); -#else - Pkcs11LibraryHandle = dlopen (pkcs11LibraryPath.c_str(), RTLD_NOW | RTLD_LOCAL); -#endif - throw_sys_if (!Pkcs11LibraryHandle); - - typedef CK_RV (*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); -#ifdef TC_WINDOWS - C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) GetProcAddress (Pkcs11LibraryHandle, "C_GetFunctionList"); -#else - C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) dlsym (Pkcs11LibraryHandle, "C_GetFunctionList"); -#endif - - if (!C_GetFunctionList) - throw SecurityTokenLibraryNotInitialized(); - - CK_RV status = C_GetFunctionList (&Pkcs11Functions); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - status = Pkcs11Functions->C_Initialize (NULL_PTR); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - PinCallback = pinCallback; - WarningCallback = warningCallback; - - Initialized = true; - } - - void SecurityToken::OpenSession (CK_SLOT_ID slotId) - { - if (Sessions.find (slotId) != Sessions.end()) - return; - - CK_SESSION_HANDLE session; - - CK_FLAGS flags = CKF_SERIAL_SESSION; - - if (!(GetTokenInfo (slotId).Flags & CKF_WRITE_PROTECTED)) - flags |= CKF_RW_SESSION; - - CK_RV status = Pkcs11Functions->C_OpenSession (slotId, flags, NULL_PTR, NULL_PTR, &session); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - Sessions[slotId].Handle = session; - } - - Pkcs11Exception::operator string () const - { - if (ErrorCode == CKR_OK) - return string(); - - static const struct - { - int ErrorCode; - const char *ErrorString; - } ErrorStrings[] = - { -# define TC_TOKEN_ERR(CODE) { CODE, #CODE }, - - TC_TOKEN_ERR (CKR_CANCEL) - TC_TOKEN_ERR (CKR_HOST_MEMORY) - TC_TOKEN_ERR (CKR_SLOT_ID_INVALID) - TC_TOKEN_ERR (CKR_GENERAL_ERROR) - TC_TOKEN_ERR (CKR_FUNCTION_FAILED) - TC_TOKEN_ERR (CKR_ARGUMENTS_BAD) - TC_TOKEN_ERR (CKR_NO_EVENT) - TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS) - TC_TOKEN_ERR (CKR_CANT_LOCK) - TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY) - TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE) - TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID) - TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID) - TC_TOKEN_ERR (CKR_DATA_INVALID) - TC_TOKEN_ERR (CKR_DATA_LEN_RANGE) - TC_TOKEN_ERR (CKR_DEVICE_ERROR) - TC_TOKEN_ERR (CKR_DEVICE_MEMORY) - TC_TOKEN_ERR (CKR_DEVICE_REMOVED) - TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID) - TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE) - TC_TOKEN_ERR (CKR_FUNCTION_CANCELED) - TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL) - TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED) - TC_TOKEN_ERR (CKR_KEY_CHANGED) - TC_TOKEN_ERR (CKR_KEY_NEEDED) - TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE) - TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED) - TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE) - TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE) - TC_TOKEN_ERR (CKR_MECHANISM_INVALID) - TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID) - TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_OPERATION_ACTIVE) - TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_PIN_INCORRECT) - TC_TOKEN_ERR (CKR_PIN_INVALID) - TC_TOKEN_ERR (CKR_PIN_LEN_RANGE) - TC_TOKEN_ERR (CKR_PIN_EXPIRED) - TC_TOKEN_ERR (CKR_PIN_LOCKED) - TC_TOKEN_ERR (CKR_SESSION_CLOSED) - TC_TOKEN_ERR (CKR_SESSION_COUNT) - TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_SESSION_READ_ONLY) - TC_TOKEN_ERR (CKR_SESSION_EXISTS) - TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS) - TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS) - TC_TOKEN_ERR (CKR_SIGNATURE_INVALID) - TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE) - TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE) - TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT) - TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT) - TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED) - TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_USER_TYPE_INVALID) - TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES) - TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID) - TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_RANDOM_NO_RNG) - TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID) - TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL) - TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID) - TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE) - TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE) - TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED) - TC_TOKEN_ERR (CKR_MUTEX_BAD) - TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED) - TC_TOKEN_ERR (CKR_NEW_PIN_MODE) - TC_TOKEN_ERR (CKR_NEXT_OTP) - TC_TOKEN_ERR (CKR_FUNCTION_REJECTED) - -#undef TC_TOKEN_ERR - }; - - - for (size_t i = 0; i < array_capacity (ErrorStrings); ++i) - { - if (ErrorStrings[i].ErrorCode == ErrorCode) - return ErrorStrings[i].ErrorString; - } - - stringstream s; - s << "0x" << hex << ErrorCode; - return s.str(); - - } - -#ifdef TC_HEADER_Common_Exception - void Pkcs11Exception::Show (HWND parent) const - { - string errorString = string (*this); - - if (!errorString.empty()) - { - wstringstream subjectErrorCode; - if (SubjectErrorCodeValid) - subjectErrorCode << L": " << SubjectErrorCode; - - if (!GetDictionaryValue (errorString.c_str())) - { - if (errorString.find ("CKR_") == 0) - { - errorString = errorString.substr (4); - for (size_t i = 0; i < errorString.size(); ++i) - { - if (errorString[i] == '_') - errorString[i] = ' '; - } - } - wchar_t err[8192]; - wsprintfW (err, L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str()); - ErrorDirect (err); - } - else - { - wstring err = GetString (errorString.c_str()); - - if (SubjectErrorCodeValid) - err += L"\n\nError code" + subjectErrorCode.str(); - - ErrorDirect (err.c_str()); - } - } - } -#endif // TC_HEADER_Common_Exception - - auto_ptr SecurityToken::PinCallback; - auto_ptr SecurityToken::WarningCallback; - - bool SecurityToken::Initialized; - CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions; - map SecurityToken::Sessions; - -#ifdef TC_WINDOWS - HMODULE SecurityToken::Pkcs11LibraryHandle; -#else - void *SecurityToken::Pkcs11LibraryHandle; -#endif - -#ifdef TC_HEADER_Platform_Exception - - void Pkcs11Exception::Deserialize (shared_ptr stream) - { - Exception::Deserialize (stream); - Serializer sr (stream); - uint64 code; - sr.Deserialize ("ErrorCode", code); - sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Deserialize ("SubjectErrorCode", SubjectErrorCode); - ErrorCode = (CK_RV) code; - } - - void Pkcs11Exception::Serialize (shared_ptr stream) const - { - Exception::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("ErrorCode", (uint64) ErrorCode); - sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Serialize ("SubjectErrorCode", SubjectErrorCode); - } - -# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -# undef TC_EXCEPTION_NODECL -# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SecurityTokenException); - -#endif -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/Finally.h" +#include "Platform/ForEach.h" + +#if !defined (TC_WINDOWS) || defined (TC_PROTOTYPE) +# include "Platform/SerializerFactory.h" +# include "Platform/StringConverter.h" +# include "Platform/SystemException.h" +#else +# include "Dictionary.h" +# include "Language.h" +#endif + +#ifdef TC_UNIX +# include +#endif + +#include "SecurityToken.h" + +#ifndef burn +# define burn Memory::Erase +#endif + +using namespace std; + +namespace TrueCrypt +{ + SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path) + { + wstring pathStr = path; + unsigned long slotId; + + if (swscanf (pathStr.c_str(), TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) + throw InvalidSecurityTokenKeyfilePath(); + + SlotId = slotId; + + size_t keyIdPos = pathStr.find (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/"); + if (keyIdPos == string::npos) + throw InvalidSecurityTokenKeyfilePath(); + + Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size()); + + vector keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id); + + if (keyfiles.empty()) + throw SecurityTokenKeyfileNotFound(); + + *this = keyfiles.front(); + } + + SecurityTokenKeyfile::operator SecurityTokenKeyfilePath () const + { + wstringstream path; + path << TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/" << SlotId << L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/" << Id; + return path.str(); + } + + void SecurityToken::CheckLibraryStatus () + { + if (!Initialized) + throw SecurityTokenLibraryNotInitialized(); + } + + void SecurityToken::CloseLibrary () + { + if (Initialized) + { + CloseAllSessions(); + Pkcs11Functions->C_Finalize (NULL_PTR); + +#ifdef TC_WINDOWS + FreeLibrary (Pkcs11LibraryHandle); +#else + dlclose (Pkcs11LibraryHandle); +#endif + Initialized = false; + } + } + + void SecurityToken::CloseAllSessions () throw () + { + if (!Initialized) + return; + + typedef pair SessionMapPair; + + foreach (SessionMapPair p, Sessions) + { + try + { + CloseSession (p.first); + } + catch (...) { } + } + } + + void SecurityToken::CloseSession (CK_SLOT_ID slotId) + { + if (Sessions.find (slotId) == Sessions.end()) + throw ParameterIncorrect (SRC_POS); + + Pkcs11Functions->C_CloseSession (Sessions[slotId].Handle); + Sessions.erase (Sessions.find (slotId)); + } + + void SecurityToken::CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name) + { + if (name.empty()) + throw ParameterIncorrect (SRC_POS); + + LoginUserIfRequired (slotId); + + foreach (const SecurityTokenKeyfile &keyfile, GetAvailableKeyfiles (&slotId)) + { + if (keyfile.IdUtf8 == name) + throw SecurityTokenKeyfileAlreadyExists(); + } + + CK_OBJECT_CLASS dataClass = CKO_DATA; + CK_BBOOL trueVal = CK_TRUE; + + CK_ATTRIBUTE keyfileTemplate[] = + { + { CKA_CLASS, &dataClass, sizeof (dataClass) }, + { CKA_TOKEN, &trueVal, sizeof (trueVal) }, + { CKA_PRIVATE, &trueVal, sizeof (trueVal) }, + { CKA_LABEL, (CK_UTF8CHAR *) name.c_str(), name.size() }, + { CKA_VALUE, &keyfileData.front(), keyfileData.size() } + }; + + CK_OBJECT_HANDLE keyfileHandle; + + CK_RV status = Pkcs11Functions->C_CreateObject (Sessions[slotId].Handle, keyfileTemplate, array_capacity (keyfileTemplate), &keyfileHandle); + + switch (status) + { + case CKR_DATA_LEN_RANGE: + status = CKR_DEVICE_MEMORY; + break; + + case CKR_SESSION_READ_ONLY: + status = CKR_TOKEN_WRITE_PROTECTED; + break; + } + + if (status != CKR_OK) + throw Pkcs11Exception (status); + + // Some tokens report success even if the new object was truncated to fit in the available memory + vector objectData; + + GetObjectAttribute (slotId, keyfileHandle, CKA_VALUE, objectData); + finally_do_arg (vector *, &objectData, { burn (&finally_arg->front(), finally_arg->size()); }); + + if (objectData.size() != keyfileData.size()) + { + Pkcs11Functions->C_DestroyObject (Sessions[slotId].Handle, keyfileHandle); + throw Pkcs11Exception (CKR_DEVICE_MEMORY); + } + } + + void SecurityToken::DeleteKeyfile (const SecurityTokenKeyfile &keyfile) + { + LoginUserIfRequired (keyfile.SlotId); + + CK_RV status = Pkcs11Functions->C_DestroyObject (Sessions[keyfile.SlotId].Handle, keyfile.Handle); + if (status != CKR_OK) + throw Pkcs11Exception (status); + } + + vector SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter) + { + bool unrecognizedTokenPresent = false; + vector keyfiles; + + foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) + { + SecurityTokenInfo token; + + if (slotIdFilter && *slotIdFilter != slotId) + continue; + + try + { + LoginUserIfRequired (slotId); + token = GetTokenInfo (slotId); + } + catch (UserAbort &) + { + continue; + } + catch (Pkcs11Exception &e) + { + if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) + { + unrecognizedTokenPresent = true; + continue; + } + + throw; + } + + foreach (const CK_OBJECT_HANDLE &dataHandle, GetObjects (slotId, CKO_DATA)) + { + SecurityTokenKeyfile keyfile; + keyfile.Handle = dataHandle; + keyfile.SlotId = slotId; + keyfile.Token = token; + + vector privateAttrib; + GetObjectAttribute (slotId, dataHandle, CKA_PRIVATE, privateAttrib); + + if (privateAttrib.size() == sizeof (CK_BBOOL) && *(CK_BBOOL *) &privateAttrib.front() != CK_TRUE) + continue; + + vector label; + GetObjectAttribute (slotId, dataHandle, CKA_LABEL, label); + label.push_back (0); + + keyfile.IdUtf8 = (char *) &label.front(); + +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) + keyfile.Id = Utf8StringToWide ((const char *) &label.front()); +#else + keyfile.Id = StringConverter::ToWide ((const char *) &label.front()); +#endif + if (keyfile.Id.empty() || (!keyfileIdFilter.empty() && keyfileIdFilter != keyfile.Id)) + continue; + + keyfiles.push_back (keyfile); + + if (!keyfileIdFilter.empty()) + break; + } + } + + if (keyfiles.empty() && unrecognizedTokenPresent) + throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); + + return keyfiles; + } + + list SecurityToken::GetAvailableTokens () + { + bool unrecognizedTokenPresent = false; + list tokens; + + foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) + { + try + { + tokens.push_back (GetTokenInfo (slotId)); + } + catch (Pkcs11Exception &e) + { + if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) + { + unrecognizedTokenPresent = true; + continue; + } + + throw; + } + } + + if (tokens.empty() && unrecognizedTokenPresent) + throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); + + return tokens; + } + + SecurityTokenInfo SecurityToken::GetTokenInfo (CK_SLOT_ID slotId) + { + CK_TOKEN_INFO info; + CK_RV status = Pkcs11Functions->C_GetTokenInfo (slotId, &info); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + SecurityTokenInfo token; + token.SlotId = slotId; + token.Flags = info.flags; + + char label[sizeof (info.label) + 1]; + memset (label, 0, sizeof (label)); + memcpy (label, info.label, sizeof (info.label)); + + token.LabelUtf8 = label; + + size_t lastSpace = token.LabelUtf8.find_last_not_of (' '); + if (lastSpace == string::npos) + token.LabelUtf8.clear(); + else + token.LabelUtf8 = token.LabelUtf8.substr (0, lastSpace + 1); + +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) + token.Label = Utf8StringToWide (token.LabelUtf8); +#else + token.Label = StringConverter::ToWide (token.LabelUtf8); +#endif + return token; + } + + void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData) + { + LoginUserIfRequired (keyfile.SlotId); + GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData); + } + + vector SecurityToken::GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass) + { + if (Sessions.find (slotId) == Sessions.end()) + throw ParameterIncorrect (SRC_POS); + + CK_ATTRIBUTE findTemplate; + findTemplate.type = CKA_CLASS; + findTemplate.pValue = &objectClass; + findTemplate.ulValueLen = sizeof (objectClass); + + CK_RV status = Pkcs11Functions->C_FindObjectsInit (Sessions[slotId].Handle, &findTemplate, 1); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + finally_do_arg (CK_SLOT_ID, slotId, { Pkcs11Functions->C_FindObjectsFinal (Sessions[finally_arg].Handle); }); + + CK_ULONG objectCount; + vector objects; + + while (true) + { + CK_OBJECT_HANDLE object; + CK_RV status = Pkcs11Functions->C_FindObjects (Sessions[slotId].Handle, &object, 1, &objectCount); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + if (objectCount != 1) + break; + + objects.push_back (object); + } + + return objects; + } + + void SecurityToken::GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector &attributeValue) + { + attributeValue.clear(); + + if (Sessions.find (slotId) == Sessions.end()) + throw ParameterIncorrect (SRC_POS); + + CK_ATTRIBUTE attribute; + attribute.type = attributeType; + attribute.pValue = NULL_PTR; + + CK_RV status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + if (attribute.ulValueLen == 0) + return; + + attributeValue = vector (attribute.ulValueLen); + attribute.pValue = &attributeValue.front(); + + status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); + if (status != CKR_OK) + throw Pkcs11Exception (status); + } + + list SecurityToken::GetTokenSlots () + { + CheckLibraryStatus(); + + list slots; + CK_ULONG slotCount; + + CK_RV status = Pkcs11Functions->C_GetSlotList (TRUE, NULL_PTR, &slotCount); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + if (slotCount > 0) + { + vector slotArray (slotCount); + status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + for (size_t i = 0; i < slotCount; i++) + { + CK_SLOT_INFO slotInfo; + status = Pkcs11Functions->C_GetSlotInfo (slotArray[i], &slotInfo); + + if (status != CKR_OK || !(slotInfo.flags & CKF_TOKEN_PRESENT)) + continue; + + slots.push_back (slotArray[i]); + } + } + + return slots; + } + + bool SecurityToken::IsKeyfilePathValid (const wstring &securityTokenKeyfilePath) + { + return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0; + } + + void SecurityToken::Login (CK_SLOT_ID slotId, const string &pin) + { + if (Sessions.find (slotId) == Sessions.end()) + OpenSession (slotId); + else if (Sessions[slotId].UserLoggedIn) + return; + + CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin.c_str(), pin.size()); + + if (status != CKR_OK) + throw Pkcs11Exception (status); + + Sessions[slotId].UserLoggedIn = true; + } + + void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId) + { + CheckLibraryStatus(); + CK_RV status; + + if (Sessions.find (slotId) == Sessions.end()) + { + OpenSession (slotId); + } + else + { + CK_SESSION_INFO sessionInfo; + status = Pkcs11Functions->C_GetSessionInfo (Sessions[slotId].Handle, &sessionInfo); + + if (status == CKR_OK) + { + Sessions[slotId].UserLoggedIn = (sessionInfo.state == CKS_RO_USER_FUNCTIONS || sessionInfo.state == CKS_RW_USER_FUNCTIONS); + } + else + { + try + { + CloseSession (slotId); + } + catch (...) { } + OpenSession (slotId); + } + } + + SecurityTokenInfo tokenInfo = GetTokenInfo (slotId); + + while (!Sessions[slotId].UserLoggedIn && (tokenInfo.Flags & CKF_LOGIN_REQUIRED)) + { + try + { + if (tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH) + { + status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0); + if (status != CKR_OK) + throw Pkcs11Exception (status); + } + else + { + string pin = tokenInfo.LabelUtf8; + if (tokenInfo.Label.empty()) + { + stringstream s; + s << "#" << slotId; + pin = s.str(); + } + + finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); }); + + (*PinCallback) (pin); + Login (slotId, pin); + } + + Sessions[slotId].UserLoggedIn = true; + } + catch (Pkcs11Exception &e) + { + CK_RV error = e.GetErrorCode(); + + if (error == CKR_USER_ALREADY_LOGGED_IN) + { + break; + } + else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)) + { + (*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT)); + continue; + } + + throw; + } + } + } + + void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback) + { + if (Initialized) + CloseLibrary(); + +#ifdef TC_WINDOWS + Pkcs11LibraryHandle = LoadLibraryA (pkcs11LibraryPath.c_str()); +#else + Pkcs11LibraryHandle = dlopen (pkcs11LibraryPath.c_str(), RTLD_NOW | RTLD_LOCAL); +#endif + throw_sys_if (!Pkcs11LibraryHandle); + + typedef CK_RV (*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); +#ifdef TC_WINDOWS + C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) GetProcAddress (Pkcs11LibraryHandle, "C_GetFunctionList"); +#else + C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) dlsym (Pkcs11LibraryHandle, "C_GetFunctionList"); +#endif + + if (!C_GetFunctionList) + throw SecurityTokenLibraryNotInitialized(); + + CK_RV status = C_GetFunctionList (&Pkcs11Functions); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + status = Pkcs11Functions->C_Initialize (NULL_PTR); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + PinCallback = pinCallback; + WarningCallback = warningCallback; + + Initialized = true; + } + + void SecurityToken::OpenSession (CK_SLOT_ID slotId) + { + if (Sessions.find (slotId) != Sessions.end()) + return; + + CK_SESSION_HANDLE session; + + CK_FLAGS flags = CKF_SERIAL_SESSION; + + if (!(GetTokenInfo (slotId).Flags & CKF_WRITE_PROTECTED)) + flags |= CKF_RW_SESSION; + + CK_RV status = Pkcs11Functions->C_OpenSession (slotId, flags, NULL_PTR, NULL_PTR, &session); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + Sessions[slotId].Handle = session; + } + + Pkcs11Exception::operator string () const + { + if (ErrorCode == CKR_OK) + return string(); + + static const struct + { + CK_RV ErrorCode; + const char *ErrorString; + } ErrorStrings[] = + { +# define TC_TOKEN_ERR(CODE) { CODE, #CODE }, + + TC_TOKEN_ERR (CKR_CANCEL) + TC_TOKEN_ERR (CKR_HOST_MEMORY) + TC_TOKEN_ERR (CKR_SLOT_ID_INVALID) + TC_TOKEN_ERR (CKR_GENERAL_ERROR) + TC_TOKEN_ERR (CKR_FUNCTION_FAILED) + TC_TOKEN_ERR (CKR_ARGUMENTS_BAD) + TC_TOKEN_ERR (CKR_NO_EVENT) + TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS) + TC_TOKEN_ERR (CKR_CANT_LOCK) + TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY) + TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE) + TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID) + TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID) + TC_TOKEN_ERR (CKR_DATA_INVALID) + TC_TOKEN_ERR (CKR_DATA_LEN_RANGE) + TC_TOKEN_ERR (CKR_DEVICE_ERROR) + TC_TOKEN_ERR (CKR_DEVICE_MEMORY) + TC_TOKEN_ERR (CKR_DEVICE_REMOVED) + TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID) + TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE) + TC_TOKEN_ERR (CKR_FUNCTION_CANCELED) + TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL) + TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED) + TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE) + TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED) + TC_TOKEN_ERR (CKR_KEY_CHANGED) + TC_TOKEN_ERR (CKR_KEY_NEEDED) + TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE) + TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED) + TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE) + TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE) + TC_TOKEN_ERR (CKR_MECHANISM_INVALID) + TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID) + TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_OPERATION_ACTIVE) + TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED) + TC_TOKEN_ERR (CKR_PIN_INCORRECT) + TC_TOKEN_ERR (CKR_PIN_INVALID) + TC_TOKEN_ERR (CKR_PIN_LEN_RANGE) + TC_TOKEN_ERR (CKR_PIN_EXPIRED) + TC_TOKEN_ERR (CKR_PIN_LOCKED) + TC_TOKEN_ERR (CKR_SESSION_CLOSED) + TC_TOKEN_ERR (CKR_SESSION_COUNT) + TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED) + TC_TOKEN_ERR (CKR_SESSION_READ_ONLY) + TC_TOKEN_ERR (CKR_SESSION_EXISTS) + TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS) + TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS) + TC_TOKEN_ERR (CKR_SIGNATURE_INVALID) + TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE) + TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE) + TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT) + TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT) + TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED) + TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED) + TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE) + TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN) + TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN) + TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED) + TC_TOKEN_ERR (CKR_USER_TYPE_INVALID) + TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN) + TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES) + TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID) + TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE) + TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE) + TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED) + TC_TOKEN_ERR (CKR_RANDOM_NO_RNG) + TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID) + TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL) + TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID) + TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE) + TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE) + TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED) + TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED) + TC_TOKEN_ERR (CKR_MUTEX_BAD) + TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED) + TC_TOKEN_ERR (CKR_NEW_PIN_MODE) + TC_TOKEN_ERR (CKR_NEXT_OTP) + TC_TOKEN_ERR (CKR_FUNCTION_REJECTED) + +#undef TC_TOKEN_ERR + }; + + + for (size_t i = 0; i < array_capacity (ErrorStrings); ++i) + { + if (ErrorStrings[i].ErrorCode == ErrorCode) + return ErrorStrings[i].ErrorString; + } + + stringstream s; + s << "0x" << hex << ErrorCode; + return s.str(); + + } + +#ifdef TC_HEADER_Common_Exception + void Pkcs11Exception::Show (HWND parent) const + { + string errorString = string (*this); + + if (!errorString.empty()) + { + wstringstream subjectErrorCode; + if (SubjectErrorCodeValid) + subjectErrorCode << L": " << SubjectErrorCode; + + if (!GetDictionaryValue (errorString.c_str())) + { + if (errorString.find ("CKR_") == 0) + { + errorString = errorString.substr (4); + for (size_t i = 0; i < errorString.size(); ++i) + { + if (errorString[i] == '_') + errorString[i] = ' '; + } + } + wchar_t err[8192]; + wsprintfW (err, L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str()); + ErrorDirect (err); + } + else + { + wstring err = GetString (errorString.c_str()); + + if (SubjectErrorCodeValid) + err += L"\n\nError code" + subjectErrorCode.str(); + + ErrorDirect (err.c_str()); + } + } + } +#endif // TC_HEADER_Common_Exception + + auto_ptr SecurityToken::PinCallback; + auto_ptr SecurityToken::WarningCallback; + + bool SecurityToken::Initialized; + CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions; + map SecurityToken::Sessions; + +#ifdef TC_WINDOWS + HMODULE SecurityToken::Pkcs11LibraryHandle; +#else + void *SecurityToken::Pkcs11LibraryHandle; +#endif + +#ifdef TC_HEADER_Platform_Exception + + void Pkcs11Exception::Deserialize (shared_ptr stream) + { + Exception::Deserialize (stream); + Serializer sr (stream); + uint64 code; + sr.Deserialize ("ErrorCode", code); + sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); + sr.Deserialize ("SubjectErrorCode", SubjectErrorCode); + ErrorCode = (CK_RV) code; + } + + void Pkcs11Exception::Serialize (shared_ptr stream) const + { + Exception::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("ErrorCode", (uint64) ErrorCode); + sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); + sr.Serialize ("SubjectErrorCode", SubjectErrorCode); + } + +# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +# undef TC_EXCEPTION_NODECL +# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SecurityTokenException); + +#endif +} diff --git a/Common/SecurityToken.h b/Common/SecurityToken.h index 40bf75e..284c490 100644 --- a/Common/SecurityToken.h +++ b/Common/SecurityToken.h @@ -1,216 +1,216 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Common_SecurityToken -#define TC_HEADER_Common_SecurityToken - -#include "Platform/PlatformBase.h" -#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) -# include "Exception.h" -#else -# include "Platform/Exception.h" -#endif - -#ifndef NULL_PTR -# define NULL_PTR 0 -#endif -#define CK_PTR * -#define CK_CALLBACK_FUNCTION(RET_TYPE, NAME) RET_TYPE (* NAME) - -#ifdef TC_WINDOWS - -# include - -# define CK_DEFINE_FUNCTION(RET_TYPE, NAME) RET_TYPE __declspec(dllexport) NAME -# define CK_DECLARE_FUNCTION(RET_TYPE, NAME) RET_TYPE __declspec(dllimport) NAME -# define CK_DECLARE_FUNCTION_POINTER(RET_TYPE, NAME) RET_TYPE __declspec(dllimport) (* NAME) - -# pragma pack(push, cryptoki, 1) -# include -# pragma pack(pop, cryptoki) - -#else // !TC_WINDOWS - -# define CK_DEFINE_FUNCTION(RET_TYPE, NAME) RET_TYPE NAME -# define CK_DECLARE_FUNCTION(RET_TYPE, NAME) RET_TYPE NAME -# define CK_DECLARE_FUNCTION_POINTER(RET_TYPE, NAME) RET_TYPE (* NAME) - -# include - -#endif // !TC_WINDOWS - - -#define TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX L"token://" -#define TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"slot" -#define TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"file" - -namespace TrueCrypt -{ - struct SecurityTokenInfo - { - CK_SLOT_ID SlotId; - CK_FLAGS Flags; - wstring Label; - string LabelUtf8; - }; - - struct SecurityTokenKeyfilePath - { - SecurityTokenKeyfilePath () { } - SecurityTokenKeyfilePath (const wstring &path) : Path (path) { } - operator wstring () const { return Path; } - wstring Path; - }; - - struct SecurityTokenKeyfile - { - SecurityTokenKeyfile () { } - SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path); - - operator SecurityTokenKeyfilePath () const; - - CK_OBJECT_HANDLE Handle; - wstring Id; - string IdUtf8; - CK_SLOT_ID SlotId; - SecurityTokenInfo Token; - }; - - struct Pkcs11Exception : public Exception - { - Pkcs11Exception (CK_RV errorCode = (CK_RV) -1) - : ErrorCode (errorCode), - SubjectErrorCodeValid (false) - { - } - - Pkcs11Exception (CK_RV errorCode, uint64 subjectErrorCode) - : ErrorCode (errorCode), - SubjectErrorCodeValid (true), - SubjectErrorCode (subjectErrorCode) - { - } - -#ifdef TC_HEADER_Platform_Exception - virtual ~Pkcs11Exception () throw () { } - TC_SERIALIZABLE_EXCEPTION (Pkcs11Exception); -#else - void Show (HWND parent) const; -#endif - operator string () const; - CK_RV GetErrorCode () const { return ErrorCode; } - - protected: - CK_RV ErrorCode; - bool SubjectErrorCodeValid; - uint64 SubjectErrorCode; - }; - - -#ifdef TC_HEADER_Platform_Exception - -#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) - -#undef TC_EXCEPTION_SET -#define TC_EXCEPTION_SET \ - TC_EXCEPTION_NODECL (Pkcs11Exception); \ - TC_EXCEPTION (InvalidSecurityTokenKeyfilePath); \ - TC_EXCEPTION (SecurityTokenLibraryNotInitialized); \ - TC_EXCEPTION (SecurityTokenKeyfileAlreadyExists); \ - TC_EXCEPTION (SecurityTokenKeyfileNotFound); - - TC_EXCEPTION_SET; - -#undef TC_EXCEPTION - -#else // !TC_HEADER_Platform_Exception - - struct SecurityTokenLibraryNotInitialized : public Exception - { - void Show (HWND parent) const { Error (SecurityTokenLibraryPath[0] == 0 ? "NO_PKCS11_MODULE_SPECIFIED" : "PKCS11_MODULE_INIT_FAILED"); } - }; - - struct InvalidSecurityTokenKeyfilePath : public Exception - { - void Show (HWND parent) const { Error ("INVALID_TOKEN_KEYFILE_PATH"); } - }; - - struct SecurityTokenKeyfileAlreadyExists : public Exception - { - void Show (HWND parent) const { Error ("TOKEN_KEYFILE_ALREADY_EXISTS"); } - }; - - struct SecurityTokenKeyfileNotFound : public Exception - { - void Show (HWND parent) const { Error ("TOKEN_KEYFILE_NOT_FOUND"); } - }; - -#endif // !TC_HEADER_Platform_Exception - - - struct Pkcs11Session - { - Pkcs11Session () : UserLoggedIn (false) { } - - CK_SESSION_HANDLE Handle; - bool UserLoggedIn; - }; - - struct GetPinFunctor - { - virtual ~GetPinFunctor () { } - virtual void operator() (string &str) = 0; - }; - - struct SendExceptionFunctor - { - virtual ~SendExceptionFunctor () { } - virtual void operator() (const Exception &e) = 0; - }; - - class SecurityToken - { - public: - static void CloseAllSessions () throw (); - static void CloseLibrary (); - static void CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name); - static void DeleteKeyfile (const SecurityTokenKeyfile &keyfile); - static vector GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring()); - static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData); - static list GetAvailableTokens (); - static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId); - static void InitLibrary (const string &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback); - static bool IsInitialized () { return Initialized; } - static bool IsKeyfilePathValid (const wstring &securityTokenKeyfilePath); - - static const size_t MaxPasswordLength = 128; - - protected: - static void CloseSession (CK_SLOT_ID slotId); - static vector GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass); - static void GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector &attributeValue); - static list GetTokenSlots (); - static void Login (CK_SLOT_ID slotId, const string &pin); - static void LoginUserIfRequired (CK_SLOT_ID slotId); - static void OpenSession (CK_SLOT_ID slotId); - static void CheckLibraryStatus (); - - static bool Initialized; - static auto_ptr PinCallback; - static CK_FUNCTION_LIST_PTR Pkcs11Functions; -#ifdef TC_WINDOWS - static HMODULE Pkcs11LibraryHandle; -#else - static void *Pkcs11LibraryHandle; -#endif - static map Sessions; - static auto_ptr WarningCallback; - }; -} - -#endif // TC_HEADER_Common_SecurityToken +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Common_SecurityToken +#define TC_HEADER_Common_SecurityToken + +#include "Platform/PlatformBase.h" +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) +# include "Exception.h" +#else +# include "Platform/Exception.h" +#endif + +#ifndef NULL_PTR +# define NULL_PTR 0 +#endif +#define CK_PTR * +#define CK_CALLBACK_FUNCTION(RET_TYPE, NAME) RET_TYPE (* NAME) + +#ifdef TC_WINDOWS + +# include + +# define CK_DEFINE_FUNCTION(RET_TYPE, NAME) RET_TYPE __declspec(dllexport) NAME +# define CK_DECLARE_FUNCTION(RET_TYPE, NAME) RET_TYPE __declspec(dllimport) NAME +# define CK_DECLARE_FUNCTION_POINTER(RET_TYPE, NAME) RET_TYPE __declspec(dllimport) (* NAME) + +# pragma pack(push, cryptoki, 1) +# include +# pragma pack(pop, cryptoki) + +#else // !TC_WINDOWS + +# define CK_DEFINE_FUNCTION(RET_TYPE, NAME) RET_TYPE NAME +# define CK_DECLARE_FUNCTION(RET_TYPE, NAME) RET_TYPE NAME +# define CK_DECLARE_FUNCTION_POINTER(RET_TYPE, NAME) RET_TYPE (* NAME) + +# include + +#endif // !TC_WINDOWS + + +#define TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX L"token://" +#define TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"slot" +#define TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"file" + +namespace TrueCrypt +{ + struct SecurityTokenInfo + { + CK_SLOT_ID SlotId; + CK_FLAGS Flags; + wstring Label; + string LabelUtf8; + }; + + struct SecurityTokenKeyfilePath + { + SecurityTokenKeyfilePath () { } + SecurityTokenKeyfilePath (const wstring &path) : Path (path) { } + operator wstring () const { return Path; } + wstring Path; + }; + + struct SecurityTokenKeyfile + { + SecurityTokenKeyfile () { } + SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path); + + operator SecurityTokenKeyfilePath () const; + + CK_OBJECT_HANDLE Handle; + wstring Id; + string IdUtf8; + CK_SLOT_ID SlotId; + SecurityTokenInfo Token; + }; + + struct Pkcs11Exception : public Exception + { + Pkcs11Exception (CK_RV errorCode = (CK_RV) -1) + : ErrorCode (errorCode), + SubjectErrorCodeValid (false) + { + } + + Pkcs11Exception (CK_RV errorCode, uint64 subjectErrorCode) + : ErrorCode (errorCode), + SubjectErrorCodeValid (true), + SubjectErrorCode (subjectErrorCode) + { + } + +#ifdef TC_HEADER_Platform_Exception + virtual ~Pkcs11Exception () throw () { } + TC_SERIALIZABLE_EXCEPTION (Pkcs11Exception); +#else + void Show (HWND parent) const; +#endif + operator string () const; + CK_RV GetErrorCode () const { return ErrorCode; } + + protected: + CK_RV ErrorCode; + bool SubjectErrorCodeValid; + uint64 SubjectErrorCode; + }; + + +#ifdef TC_HEADER_Platform_Exception + +#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) + +#undef TC_EXCEPTION_SET +#define TC_EXCEPTION_SET \ + TC_EXCEPTION_NODECL (Pkcs11Exception); \ + TC_EXCEPTION (InvalidSecurityTokenKeyfilePath); \ + TC_EXCEPTION (SecurityTokenLibraryNotInitialized); \ + TC_EXCEPTION (SecurityTokenKeyfileAlreadyExists); \ + TC_EXCEPTION (SecurityTokenKeyfileNotFound); + + TC_EXCEPTION_SET; + +#undef TC_EXCEPTION + +#else // !TC_HEADER_Platform_Exception + + struct SecurityTokenLibraryNotInitialized : public Exception + { + void Show (HWND parent) const { Error (SecurityTokenLibraryPath[0] == 0 ? "NO_PKCS11_MODULE_SPECIFIED" : "PKCS11_MODULE_INIT_FAILED"); } + }; + + struct InvalidSecurityTokenKeyfilePath : public Exception + { + void Show (HWND parent) const { Error ("INVALID_TOKEN_KEYFILE_PATH"); } + }; + + struct SecurityTokenKeyfileAlreadyExists : public Exception + { + void Show (HWND parent) const { Error ("TOKEN_KEYFILE_ALREADY_EXISTS"); } + }; + + struct SecurityTokenKeyfileNotFound : public Exception + { + void Show (HWND parent) const { Error ("TOKEN_KEYFILE_NOT_FOUND"); } + }; + +#endif // !TC_HEADER_Platform_Exception + + + struct Pkcs11Session + { + Pkcs11Session () : UserLoggedIn (false) { } + + CK_SESSION_HANDLE Handle; + bool UserLoggedIn; + }; + + struct GetPinFunctor + { + virtual ~GetPinFunctor () { } + virtual void operator() (string &str) = 0; + }; + + struct SendExceptionFunctor + { + virtual ~SendExceptionFunctor () { } + virtual void operator() (const Exception &e) = 0; + }; + + class SecurityToken + { + public: + static void CloseAllSessions () throw (); + static void CloseLibrary (); + static void CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name); + static void DeleteKeyfile (const SecurityTokenKeyfile &keyfile); + static vector GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring()); + static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData); + static list GetAvailableTokens (); + static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId); + static void InitLibrary (const string &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback); + static bool IsInitialized () { return Initialized; } + static bool IsKeyfilePathValid (const wstring &securityTokenKeyfilePath); + + static const size_t MaxPasswordLength = 128; + + protected: + static void CloseSession (CK_SLOT_ID slotId); + static vector GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass); + static void GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector &attributeValue); + static list GetTokenSlots (); + static void Login (CK_SLOT_ID slotId, const string &pin); + static void LoginUserIfRequired (CK_SLOT_ID slotId); + static void OpenSession (CK_SLOT_ID slotId); + static void CheckLibraryStatus (); + + static bool Initialized; + static auto_ptr PinCallback; + static CK_FUNCTION_LIST_PTR Pkcs11Functions; +#ifdef TC_WINDOWS + static HMODULE Pkcs11LibraryHandle; +#else + static void *Pkcs11LibraryHandle; +#endif + static map Sessions; + static auto_ptr WarningCallback; + }; +} + +#endif // TC_HEADER_Common_SecurityToken diff --git a/Common/TCDEFS.H b/Common/TCDEFS.H index dc4d783..02170c0 100644 --- a/Common/TCDEFS.H +++ b/Common/TCDEFS.H @@ -1,347 +1,305 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TCDEFS_H -#define TCDEFS_H - -#define TC_APP_NAME "TrueCrypt" - -// Version displayed to user -#define VERSION_STRING "6.2a" - -// Version number to compare against driver -#define VERSION_NUM 0x062a - -// Sector size of encrypted filesystem, which may differ from sector size of host filesystem/device -#define SECTOR_SIZE 512 - -// "Second generation standard" sector size -#define SECTOR_SIZE_GEN2_STANDARD 4096 - -#define BYTES_PER_KB 1024LL -#define BYTES_PER_MB 1048576LL -#define BYTES_PER_GB 1073741824LL -#define BYTES_PER_TB 1099511627776LL -#define BYTES_PER_PB 1125899906842624LL - -/* GUI/driver errors */ - -#define WIDE(x) (LPWSTR)L##x - -#ifdef _MSC_VER - -typedef __int8 int8; -typedef __int16 int16; -typedef __int32 int32; -typedef unsigned __int8 byte; -typedef unsigned __int16 uint16; -typedef unsigned __int32 uint32; - -#ifdef TC_NO_COMPILER_INT64 -typedef unsigned __int32 TC_LARGEST_COMPILER_UINT; -#else -typedef unsigned __int64 TC_LARGEST_COMPILER_UINT; -typedef __int64 int64; -typedef unsigned __int64 uint64; -#endif - -#else // !_MSC_VER - -#include -#include - -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; -typedef uint8_t byte; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; - -#if UCHAR_MAX != 0xffU -#error UCHAR_MAX != 0xff -#endif -#define __int8 char - -#if USHRT_MAX != 0xffffU -#error USHRT_MAX != 0xffff -#endif -#define __int16 short - -#if UINT_MAX != 0xffffffffU -#error UINT_MAX != 0xffffffff -#endif -#define __int32 int - -typedef uint64 TC_LARGEST_COMPILER_UINT; - -#define BOOL int -#ifndef FALSE -#define FALSE 0 -#define TRUE 1 -#endif - -#endif // !_MSC_VER - -#define TC_INT_TYPES_DEFINED - -// Integer types required by Cryptolib -typedef unsigned __int8 uint_8t; -typedef unsigned __int16 uint_16t; -typedef unsigned __int32 uint_32t; -#ifndef TC_NO_COMPILER_INT64 -typedef uint64 uint_64t; -#endif - -typedef union -{ - struct - { - unsigned __int32 LowPart; - unsigned __int32 HighPart; - }; -#ifndef TC_NO_COMPILER_INT64 - uint64 Value; -#endif - -} UINT64_STRUCT; - -#ifdef TC_WINDOWS_BOOT -# define TC_THROW_FATAL_EXCEPTION ThrowFatalException (__LINE__) -#elif defined (NT4_DRIVER) -# define TC_THROW_FATAL_EXCEPTION KeBugCheckEx (SECURITY_SYSTEM, __LINE__, 0, 0, 'TC') -#else -# define TC_THROW_FATAL_EXCEPTION *(char *) 0 = 0 -#endif - -#ifdef NT4_DRIVER - -#pragma warning( disable : 4201 ) -#pragma warning( disable : 4214 ) -#pragma warning( disable : 4115 ) -#pragma warning( disable : 4100 ) -#pragma warning( disable : 4101 ) -#pragma warning( disable : 4057 ) -#pragma warning( disable : 4244 ) -#pragma warning( disable : 4514 ) -#pragma warning( disable : 4127 ) - - -#include -#include /* Standard header file for nt drivers */ - -#ifndef TC_LOCAL_WIN32_WINNT_OVERRIDE -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 /* Does not apply to user-space apps */ -#endif - -#include /* Standard I/O control codes */ -#include - -#pragma warning( default : 4201 ) -#pragma warning( default : 4214 ) -#pragma warning( default : 4115 ) -#pragma warning( default : 4100 ) -#pragma warning( default : 4101 ) -#pragma warning( default : 4057 ) -#pragma warning( default : 4244 ) -#pragma warning( default : 4127 ) - -/* #pragma warning( default : 4514 ) this warning remains disabled */ - -#define TCalloc(size) ((void *) ExAllocatePoolWithTag( NonPagedPool, size, 'MMCT' )) -#define TCfree(memblock) ExFreePoolWithTag( memblock, 'MMCT' ) - -#define DEVICE_DRIVER - -#ifndef BOOL -typedef int BOOL; -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE !TRUE -#endif - -/* Define dummies for the drivers */ -typedef int HFILE; -typedef unsigned int WPARAM; -typedef unsigned __int32 LPARAM; -#define CALLBACK - -#ifndef UINT -typedef unsigned int UINT; -#endif - -#ifndef LRESULT -typedef unsigned __int32 LRESULT; -#endif -/* NT4_DRIVER */ - -#else - -#define TCalloc malloc -#define TCfree free - -#ifdef _WIN32 - -#pragma warning( disable : 4201 ) -#pragma warning( disable : 4214 ) -#pragma warning( disable : 4115 ) -#pragma warning( disable : 4514 ) - -#ifndef TC_LOCAL_WIN32_WINNT_OVERRIDE -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 /* Does not apply to the driver */ -#endif - -#include /* Windows header */ -#include /* The common controls */ -#include /* Process control */ -#include -#include /* For sprintf */ - -#pragma warning( default : 4201 ) -#pragma warning( default : 4214 ) -#pragma warning( default : 4115 ) - -/* #pragma warning( default : 4514 ) this warning remains disabled */ - -/* This is needed to fix a bug with VC 5, the TCHAR macro _ttoi64 maps - incorrectly to atoLL when it should be _atoi64 */ -#define atoi64 _atoi64 - -#endif /* _WIN32 */ - -#endif /* NT4_DRIVER */ - -#ifndef TC_TO_STRING -# define TC_TO_STRING2(n) #n -# define TC_TO_STRING(n) TC_TO_STRING2(n) -#endif - -#ifdef DEVICE_DRIVER -# if defined (DEBUG) || 0 -# if 1 // DbgPrintEx is not available on Windows 2000 -# define Dump DbgPrint -# else -# define Dump(...) DbgPrintEx (DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __VA_ARGS__) -# endif -# define DumpMem(...) DumpMemory (__VA_ARGS__) -# else -# define Dump(...) ((void) 0) -# define DumpMem(...) ((void) 0) -# endif -#endif - -#if !defined (trace_msg) && !defined (TC_WINDOWS_BOOT) -# ifdef DEBUG -# ifdef DEVICE_DRIVER -# define trace_msg Dump -# elif defined (_WIN32) -# define trace_msg(...) do { char msg[2048]; _snprintf (msg, sizeof (msg), __VA_ARGS__); OutputDebugString (msg); } while (0) -# endif -# define trace_point trace_msg (__FUNCTION__ ":" TC_TO_STRING(__LINE__) "\n") -# else -# define trace_msg(...) -# define trace_point -# endif -#endif - -#ifdef DEVICE_DRIVER -# define TC_EVENT KEVENT -# define TC_WAIT_EVENT(EVENT) KeWaitForSingleObject (&EVENT, Executive, KernelMode, FALSE, NULL) -#elif defined (_WIN32) -# define TC_EVENT HANDLE -# define TC_WAIT_EVENT(EVENT) WaitForSingleObject (EVENT, INFINITE) -#endif - -#ifdef _WIN32 -#define burn(mem,size) do { volatile char *burnm = (volatile char *)(mem); int burnc = size; RtlSecureZeroMemory (mem, size); while (burnc--) *burnm++ = 0; } while (0) -#else -#define burn(mem,size) do { volatile char *burnm = (volatile char *)(mem); int burnc = size; while (burnc--) *burnm++ = 0; } while (0) -#endif - -// The size of the memory area to wipe is in bytes amd it must be a multiple of 8. -#ifndef TC_NO_COMPILER_INT64 -# define FAST_ERASE64(mem,size) do { volatile uint64 *burnm = (volatile uint64 *)(mem); int burnc = size >> 3; while (burnc--) *burnm++ = 0; } while (0) -#else -# define FAST_ERASE64(mem,size) do { volatile unsigned __int32 *burnm = (volatile unsigned __int32 *)(mem); int burnc = size >> 2; while (burnc--) *burnm++ = 0; } while (0) -#endif - -#ifdef TC_WINDOWS_BOOT -# ifndef max -# define max(a,b) (((a) > (b)) ? (a) : (b)) -# endif -# undef burn -# define burn EraseMemory -#endif - -#ifdef MAX_PATH -#define TC_MAX_PATH MAX_PATH -#else -#define TC_MAX_PATH 260 /* Includes the null terminator */ -#endif - -#define MAX_URL_LENGTH 2084 /* Internet Explorer limit. Includes the terminating null character. */ - -#define TC_HOMEPAGE "http://www.truecrypt.org/" -#define TC_APPLINK "http://www.truecrypt.org/applink?version=" VERSION_STRING -#define TC_APPLINK_SECURE "https://www.truecrypt.org/applink?version=" VERSION_STRING - -enum -{ - /* WARNING: ADD ANY NEW CODES AT THE END (DO NOT INSERT THEM BETWEEN EXISTING). DO *NOT* DELETE ANY - EXISTING CODES! Changing these values or their meanings may cause incompatibility with other versions - (for example, if a new version of the TrueCrypt installer receives an error code from an installed - driver whose version is lower, it will report and interpret the error incorrectly). */ - - ERR_SUCCESS = 0, - ERR_OS_ERROR = 1, - ERR_OUTOFMEMORY = 2, - ERR_PASSWORD_WRONG = 3, - ERR_VOL_FORMAT_BAD = 4, - ERR_DRIVE_NOT_FOUND = 5, - ERR_FILES_OPEN = 6, - ERR_VOL_SIZE_WRONG = 7, - ERR_COMPRESSION_NOT_SUPPORTED = 8, - ERR_PASSWORD_CHANGE_VOL_TYPE = 9, - ERR_PASSWORD_CHANGE_VOL_VERSION = 10, - ERR_VOL_SEEKING = 11, - ERR_VOL_WRITING = 12, - ERR_FILES_OPEN_LOCK = 13, - ERR_VOL_READING = 14, - ERR_DRIVER_VERSION = 15, - ERR_NEW_VERSION_REQUIRED = 16, - ERR_CIPHER_INIT_FAILURE = 17, - ERR_CIPHER_INIT_WEAK_KEY = 18, - ERR_SELF_TESTS_FAILED = 19, - ERR_SECTOR_SIZE_INCOMPATIBLE = 20, - ERR_VOL_ALREADY_MOUNTED = 21, - ERR_NO_FREE_DRIVES = 22, - ERR_FILE_OPEN_FAILED = 23, - ERR_VOL_MOUNT_FAILED = 24, - DEPRECATED_ERR_INVALID_DEVICE = 25, - ERR_ACCESS_DENIED = 26, - ERR_MODE_INIT_FAILED = 27, - ERR_DONT_REPORT = 28, - ERR_ENCRYPTION_NOT_COMPLETED = 29, - ERR_PARAMETER_INCORRECT = 30, - ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG = 31, - ERR_NONSYS_INPLACE_ENC_INCOMPLETE = 32, - ERR_USER_ABORT = 33 -}; - -#endif // #ifndef TCDEFS_H +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TCDEFS_H +#define TCDEFS_H + +#define TC_APP_NAME "TrueCrypt" + +// Version displayed to user +#define VERSION_STRING "6.3" + +// Version number to compare against driver +#define VERSION_NUM 0x0630 + +// Release date +#define TC_STR_RELEASE_DATE "October 21, 2009" + +// Sector size of encrypted filesystem, which may differ from sector size of host filesystem/device +#define SECTOR_SIZE 512 + +// "Second generation standard" sector size +#define SECTOR_SIZE_GEN2_STANDARD 4096 + +#define BYTES_PER_KB 1024LL +#define BYTES_PER_MB 1048576LL +#define BYTES_PER_GB 1073741824LL +#define BYTES_PER_TB 1099511627776LL +#define BYTES_PER_PB 1125899906842624LL + +/* GUI/driver errors */ + +#define WIDE(x) (LPWSTR)L##x + +#ifdef _MSC_VER + +typedef __int8 int8; +typedef __int16 int16; +typedef __int32 int32; +typedef unsigned __int8 byte; +typedef unsigned __int16 uint16; +typedef unsigned __int32 uint32; + +#ifdef TC_NO_COMPILER_INT64 +typedef unsigned __int32 TC_LARGEST_COMPILER_UINT; +#else +typedef unsigned __int64 TC_LARGEST_COMPILER_UINT; +typedef __int64 int64; +typedef unsigned __int64 uint64; +#endif + +#else // !_MSC_VER + +#include +#include + +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; +typedef uint8_t byte; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; + +#if UCHAR_MAX != 0xffU +#error UCHAR_MAX != 0xff +#endif +#define __int8 char + +#if USHRT_MAX != 0xffffU +#error USHRT_MAX != 0xffff +#endif +#define __int16 short + +#if UINT_MAX != 0xffffffffU +#error UINT_MAX != 0xffffffff +#endif +#define __int32 int + +typedef uint64 TC_LARGEST_COMPILER_UINT; + +#define BOOL int +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#endif // !_MSC_VER + +#define TC_INT_TYPES_DEFINED + +// Integer types required by Cryptolib +typedef unsigned __int8 uint_8t; +typedef unsigned __int16 uint_16t; +typedef unsigned __int32 uint_32t; +#ifndef TC_NO_COMPILER_INT64 +typedef uint64 uint_64t; +#endif + +typedef union +{ + struct + { + unsigned __int32 LowPart; + unsigned __int32 HighPart; + }; +#ifndef TC_NO_COMPILER_INT64 + uint64 Value; +#endif + +} UINT64_STRUCT; + +#ifdef TC_WINDOWS_BOOT + +# ifdef __cplusplus +extern "C" +# endif +void ThrowFatalException (int line); + +# define TC_THROW_FATAL_EXCEPTION ThrowFatalException (__LINE__) +#elif defined (NT4_DRIVER) +# define TC_THROW_FATAL_EXCEPTION KeBugCheckEx (SECURITY_SYSTEM, __LINE__, 0, 0, 'TC') +#else +# define TC_THROW_FATAL_EXCEPTION *(char *) 0 = 0 +#endif + +#ifdef NT4_DRIVER + +#include +#include /* Standard header file for nt drivers */ +#include /* Standard I/O control codes */ + +#define TCalloc(size) ((void *) ExAllocatePoolWithTag( NonPagedPool, size, 'MMCT' )) +#define TCfree(memblock) ExFreePoolWithTag( memblock, 'MMCT' ) + +#define DEVICE_DRIVER + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE !TRUE +#endif + +#else /* !NT4_DRIVER */ + +#define TCalloc malloc +#define TCfree free + +#ifdef _WIN32 + +#ifndef TC_LOCAL_WIN32_WINNT_OVERRIDE +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 /* Does not apply to the driver */ +#endif + +#include /* Windows header */ +#include /* The common controls */ +#include /* Process control */ +#include +#include /* For sprintf */ + +#endif /* _WIN32 */ + +#endif /* !NT4_DRIVER */ + +#ifndef TC_TO_STRING +# define TC_TO_STRING2(n) #n +# define TC_TO_STRING(n) TC_TO_STRING2(n) +#endif + +#ifdef DEVICE_DRIVER +# if defined (DEBUG) || 0 +# if 1 // DbgPrintEx is not available on Windows 2000 +# define Dump DbgPrint +# else +# define Dump(...) DbgPrintEx (DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __VA_ARGS__) +# endif +# define DumpMem(...) DumpMemory (__VA_ARGS__) +# else +# define Dump(...) ((void) 0) +# define DumpMem(...) ((void) 0) +# endif +#endif + +#if !defined (trace_msg) && !defined (TC_WINDOWS_BOOT) +# ifdef DEBUG +# ifdef DEVICE_DRIVER +# define trace_msg Dump +# elif defined (_WIN32) +# define trace_msg(...) do { char msg[2048]; _snprintf (msg, sizeof (msg), __VA_ARGS__); OutputDebugString (msg); } while (0) +# endif +# define trace_point trace_msg (__FUNCTION__ ":" TC_TO_STRING(__LINE__) "\n") +# else +# define trace_msg(...) +# define trace_point +# endif +#endif + +#ifdef DEVICE_DRIVER +# define TC_EVENT KEVENT +# define TC_WAIT_EVENT(EVENT) KeWaitForSingleObject (&EVENT, Executive, KernelMode, FALSE, NULL) +#elif defined (_WIN32) +# define TC_EVENT HANDLE +# define TC_WAIT_EVENT(EVENT) WaitForSingleObject (EVENT, INFINITE) +#endif + +#ifdef _WIN32 +#define burn(mem,size) do { volatile char *burnm = (volatile char *)(mem); int burnc = size; RtlSecureZeroMemory (mem, size); while (burnc--) *burnm++ = 0; } while (0) +#else +#define burn(mem,size) do { volatile char *burnm = (volatile char *)(mem); int burnc = size; while (burnc--) *burnm++ = 0; } while (0) +#endif + +// The size of the memory area to wipe is in bytes amd it must be a multiple of 8. +#ifndef TC_NO_COMPILER_INT64 +# define FAST_ERASE64(mem,size) do { volatile uint64 *burnm = (volatile uint64 *)(mem); int burnc = size >> 3; while (burnc--) *burnm++ = 0; } while (0) +#else +# define FAST_ERASE64(mem,size) do { volatile unsigned __int32 *burnm = (volatile unsigned __int32 *)(mem); int burnc = size >> 2; while (burnc--) *burnm++ = 0; } while (0) +#endif + +#ifdef TC_WINDOWS_BOOT +# ifndef max +# define max(a,b) (((a) > (b)) ? (a) : (b)) +# endif + +# ifdef __cplusplus +extern "C" +# endif +void EraseMemory (void *memory, int size); + +# undef burn +# define burn EraseMemory +#endif + +#ifdef MAX_PATH +#define TC_MAX_PATH MAX_PATH +#else +#define TC_MAX_PATH 260 /* Includes the null terminator */ +#endif + +#define TC_STR_RELEASED_BY "Released by TrueCrypt Foundation on " TC_STR_RELEASE_DATE + +#define MAX_URL_LENGTH 2084 /* Internet Explorer limit. Includes the terminating null character. */ + +#define TC_HOMEPAGE "http://www.truecrypt.org/" +#define TC_APPLINK "http://www.truecrypt.org/applink?version=" VERSION_STRING +#define TC_APPLINK_SECURE "https://www.truecrypt.org/applink?version=" VERSION_STRING + +enum +{ + /* WARNING: ADD ANY NEW CODES AT THE END (DO NOT INSERT THEM BETWEEN EXISTING). DO *NOT* DELETE ANY + EXISTING CODES! Changing these values or their meanings may cause incompatibility with other versions + (for example, if a new version of the TrueCrypt installer receives an error code from an installed + driver whose version is lower, it will report and interpret the error incorrectly). */ + + ERR_SUCCESS = 0, + ERR_OS_ERROR = 1, + ERR_OUTOFMEMORY = 2, + ERR_PASSWORD_WRONG = 3, + ERR_VOL_FORMAT_BAD = 4, + ERR_DRIVE_NOT_FOUND = 5, + ERR_FILES_OPEN = 6, + ERR_VOL_SIZE_WRONG = 7, + ERR_COMPRESSION_NOT_SUPPORTED = 8, + ERR_PASSWORD_CHANGE_VOL_TYPE = 9, + ERR_PASSWORD_CHANGE_VOL_VERSION = 10, + ERR_VOL_SEEKING = 11, + ERR_VOL_WRITING = 12, + ERR_FILES_OPEN_LOCK = 13, + ERR_VOL_READING = 14, + ERR_DRIVER_VERSION = 15, + ERR_NEW_VERSION_REQUIRED = 16, + ERR_CIPHER_INIT_FAILURE = 17, + ERR_CIPHER_INIT_WEAK_KEY = 18, + ERR_SELF_TESTS_FAILED = 19, + ERR_SECTOR_SIZE_INCOMPATIBLE = 20, + ERR_VOL_ALREADY_MOUNTED = 21, + ERR_NO_FREE_DRIVES = 22, + ERR_FILE_OPEN_FAILED = 23, + ERR_VOL_MOUNT_FAILED = 24, + DEPRECATED_ERR_INVALID_DEVICE = 25, + ERR_ACCESS_DENIED = 26, + ERR_MODE_INIT_FAILED = 27, + ERR_DONT_REPORT = 28, + ERR_ENCRYPTION_NOT_COMPLETED = 29, + ERR_PARAMETER_INCORRECT = 30, + ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG = 31, + ERR_NONSYS_INPLACE_ENC_INCOMPLETE = 32, + ERR_USER_ABORT = 33 +}; + +#endif // #ifndef TCDEFS_H diff --git a/Common/Tests.c b/Common/Tests.c index 76786ce..3d2ec42 100644 --- a/Common/Tests.c +++ b/Common/Tests.c @@ -1,1675 +1,1677 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" -#include "Crc.h" -#include "Crypto.h" -#include "Common/Endian.h" -#include "Tests.h" -#include "Xts.h" -#include -#include "Pkcs5.h" - -typedef struct { - unsigned __int8 key1[32]; - unsigned __int8 key2[32]; - unsigned __int8 dataUnitNo[8]; - unsigned int blockNo; - unsigned __int8 plaintext[ENCRYPTION_DATA_UNIT_SIZE]; - unsigned __int8 ciphertext[ENCRYPTION_DATA_UNIT_SIZE]; -} XTS_TEST; - -#define XTS_TEST_COUNT 5 - -XTS_TEST XTS_vectors[XTS_TEST_COUNT] = { -/* XTS-AES-256 */ -{ - // IEEE 1619 - Vector 10 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b, - 0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd, - 0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0, - 0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca, - 0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0, - 0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f, - 0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec, - 0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a, - 0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1, - 0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae, - 0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29, - 0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac, - 0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f, - 0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85, - 0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa, - 0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51 - } -}, -{ - // IEEE 1619 - Vector 11 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11, - 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2, - 0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d, - 0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01, - 0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79, - 0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a, - 0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6, - 0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80, - 0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a, - 0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0, - 0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75, - 0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63, - 0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a, - 0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68, - 0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90, - 0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03 - } -}, -{ - // IEEE 1619 - Vector 12 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00, - 0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49, - 0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8, - 0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1, - 0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf, - 0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e, - 0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6, - 0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79, - 0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0, - 0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64, - 0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d, - 0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a, - 0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2, - 0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce, - 0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36, - 0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26 - } -}, -{ - // IEEE 1619 - Vector 13 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5, - 0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1, - 0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac, - 0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e, - 0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3, - 0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5, - 0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9, - 0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c, - 0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53, - 0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7, - 0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf, - 0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00, - 0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60, - 0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55, - 0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c, - 0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20 - } -}, -{ - // IEEE 1619 - Vector 14 - - /* This vector must always be the last one in XTS_vectors[] because TestSectorBufEncryption() relies on it. */ - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23, - 0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80, - 0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04, - 0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4, - 0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b, - 0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34, - 0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8, - 0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff, - 0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b, - 0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6, - 0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa, - 0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc, - 0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a, - 0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46, - 0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde, - 0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9 - } -} }; // XTS_TEST XTS_vectors[] - - -BOOL XTSAesTest (PCRYPTO_INFO ci) -{ - unsigned __int8 p[ENCRYPTION_DATA_UNIT_SIZE]; - UINT64_STRUCT dataUnitNo; - int i; - - for (i = 0; i < XTS_TEST_COUNT; i++) - { - ci->ea = EAGetByName ("AES"); - if (ci->ea == 0) - return FALSE; - - ci->mode = XTS; - - if (EAInit (ci->ea, XTS_vectors[i].key1, ci->ks) != ERR_SUCCESS) - return FALSE; - - memcpy (&ci->k2, XTS_vectors[i].key2, sizeof (XTS_vectors[i].key2)); - - if (!EAInitMode (ci)) - return FALSE; - - memcpy (p, XTS_vectors[i].plaintext, sizeof (p)); - - dataUnitNo.Value = BE64 (*((unsigned __int64 *) XTS_vectors[i].dataUnitNo)); - - EncryptBufferXTS (p, sizeof (p), &dataUnitNo, XTS_vectors[i].blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, AES); - - if (memcmp (XTS_vectors[i].ciphertext, p, sizeof (p)) != 0) - return FALSE; - } - - return TRUE; -} - -/* Blowfish Test Vectors (deprecated/legacy) */ - -/* Blowfish test vectors from www.counterpane.com/blowfish.html */ - -#define BF_TEST_COUNT 34 - -typedef struct { - unsigned char key[8]; - unsigned char plaintext[8]; - unsigned char ciphertext[8]; - } BF_TEST; - -BF_TEST bf_ecb_vectors[BF_TEST_COUNT] = { -"\x00\x00\x00\x00\x00\x00\x00\x00","\x00\x00\x00\x00\x00\x00\x00\x00","\x4E\xF9\x97\x45\x61\x98\xDD\x78", -"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x51\x86\x6F\xD5\xB8\x5E\xCB\x8A", -"\x30\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x01","\x7D\x85\x6F\x9A\x61\x30\x63\xF2", -"\x11\x11\x11\x11\x11\x11\x11\x11","\x11\x11\x11\x11\x11\x11\x11\x11","\x24\x66\xDD\x87\x8B\x96\x3C\x9D", -"\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x11\x11\x11\x11\x11\x11\x11\x11","\x61\xF9\xC3\x80\x22\x81\xB0\x96", -"\x11\x11\x11\x11\x11\x11\x11\x11","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x7D\x0C\xC6\x30\xAF\xDA\x1E\xC7", -"\x00\x00\x00\x00\x00\x00\x00\x00","\x00\x00\x00\x00\x00\x00\x00\x00","\x4E\xF9\x97\x45\x61\x98\xDD\x78", -"\xFE\xDC\xBA\x98\x76\x54\x32\x10","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x0A\xCE\xAB\x0F\xC6\xA0\xA2\x8D", -"\x7C\xA1\x10\x45\x4A\x1A\x6E\x57","\x01\xA1\xD6\xD0\x39\x77\x67\x42","\x59\xC6\x82\x45\xEB\x05\x28\x2B", -"\x01\x31\xD9\x61\x9D\xC1\x37\x6E","\x5C\xD5\x4C\xA8\x3D\xEF\x57\xDA","\xB1\xB8\xCC\x0B\x25\x0F\x09\xA0", -"\x07\xA1\x13\x3E\x4A\x0B\x26\x86","\x02\x48\xD4\x38\x06\xF6\x71\x72","\x17\x30\xE5\x77\x8B\xEA\x1D\xA4", -"\x38\x49\x67\x4C\x26\x02\x31\x9E","\x51\x45\x4B\x58\x2D\xDF\x44\x0A","\xA2\x5E\x78\x56\xCF\x26\x51\xEB", -"\x04\xB9\x15\xBA\x43\xFE\xB5\xB6","\x42\xFD\x44\x30\x59\x57\x7F\xA2","\x35\x38\x82\xB1\x09\xCE\x8F\x1A", -"\x01\x13\xB9\x70\xFD\x34\xF2\xCE","\x05\x9B\x5E\x08\x51\xCF\x14\x3A","\x48\xF4\xD0\x88\x4C\x37\x99\x18", -"\x01\x70\xF1\x75\x46\x8F\xB5\xE6","\x07\x56\xD8\xE0\x77\x47\x61\xD2","\x43\x21\x93\xB7\x89\x51\xFC\x98", -"\x43\x29\x7F\xAD\x38\xE3\x73\xFE","\x76\x25\x14\xB8\x29\xBF\x48\x6A","\x13\xF0\x41\x54\xD6\x9D\x1A\xE5", -"\x07\xA7\x13\x70\x45\xDA\x2A\x16","\x3B\xDD\x11\x90\x49\x37\x28\x02","\x2E\xED\xDA\x93\xFF\xD3\x9C\x79", -"\x04\x68\x91\x04\xC2\xFD\x3B\x2F","\x26\x95\x5F\x68\x35\xAF\x60\x9A","\xD8\x87\xE0\x39\x3C\x2D\xA6\xE3", -"\x37\xD0\x6B\xB5\x16\xCB\x75\x46","\x16\x4D\x5E\x40\x4F\x27\x52\x32","\x5F\x99\xD0\x4F\x5B\x16\x39\x69", -"\x1F\x08\x26\x0D\x1A\xC2\x46\x5E","\x6B\x05\x6E\x18\x75\x9F\x5C\xCA","\x4A\x05\x7A\x3B\x24\xD3\x97\x7B", -"\x58\x40\x23\x64\x1A\xBA\x61\x76","\x00\x4B\xD6\xEF\x09\x17\x60\x62","\x45\x20\x31\xC1\xE4\xFA\xDA\x8E", -"\x02\x58\x16\x16\x46\x29\xB0\x07","\x48\x0D\x39\x00\x6E\xE7\x62\xF2","\x75\x55\xAE\x39\xF5\x9B\x87\xBD", -"\x49\x79\x3E\xBC\x79\xB3\x25\x8F","\x43\x75\x40\xC8\x69\x8F\x3C\xFA","\x53\xC5\x5F\x9C\xB4\x9F\xC0\x19", -"\x4F\xB0\x5E\x15\x15\xAB\x73\xA7","\x07\x2D\x43\xA0\x77\x07\x52\x92","\x7A\x8E\x7B\xFA\x93\x7E\x89\xA3", -"\x49\xE9\x5D\x6D\x4C\xA2\x29\xBF","\x02\xFE\x55\x77\x81\x17\xF1\x2A","\xCF\x9C\x5D\x7A\x49\x86\xAD\xB5", -"\x01\x83\x10\xDC\x40\x9B\x26\xD6","\x1D\x9D\x5C\x50\x18\xF7\x28\xC2","\xD1\xAB\xB2\x90\x65\x8B\xC7\x78", -"\x1C\x58\x7F\x1C\x13\x92\x4F\xEF","\x30\x55\x32\x28\x6D\x6F\x29\x5A","\x55\xCB\x37\x74\xD1\x3E\xF2\x01", -"\x01\x01\x01\x01\x01\x01\x01\x01","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\xFA\x34\xEC\x48\x47\xB2\x68\xB2", -"\x1F\x1F\x1F\x1F\x0E\x0E\x0E\x0E","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\xA7\x90\x79\x51\x08\xEA\x3C\xAE", -"\xE0\xFE\xE0\xFE\xF1\xFE\xF1\xFE","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\xC3\x9E\x07\x2D\x9F\xAC\x63\x1D", -"\x00\x00\x00\x00\x00\x00\x00\x00","\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x01\x49\x33\xE0\xCD\xAF\xF6\xE4", -"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x00\x00\x00\x00\x00\x00\x00\x00","\xF2\x1E\x9A\x77\xB7\x1C\x49\xBC", -"\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x00\x00\x00\x00\x00\x00\x00\x00","\x24\x59\x46\x88\x57\x54\x36\x9A", -"\xFE\xDC\xBA\x98\x76\x54\x32\x10","\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x6B\x5C\x5A\x9C\x5D\x9E\x0A\x5A" -}; - - -#define TRIPLEDES_TEST_COUNT 1 - -typedef struct { - unsigned char key[24]; - unsigned char plaintext[8]; - unsigned char ciphertext[8]; - } TRIPLEDES_TEST; - -TRIPLEDES_TEST tripledes_vectors[TRIPLEDES_TEST_COUNT] = { -0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, -0x76, 0x54, 0x32, 0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, - -0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, - -0xde, 0x0b, 0x7c, 0x06, 0xae, 0x5e, 0x0e, 0xd5 -}; - -/* CAST-128 Test Vectors from RFC2144 (deprecated/legacy) */ - -#define CAST_TEST_COUNT 1 - -typedef struct { - unsigned char key[16]; - unsigned char plaintext[8]; - unsigned char ciphertext[8]; - } CAST_TEST; - - -CAST_TEST cast_ecb_vectors[CAST_TEST_COUNT] = { - "\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45\x67\x89\x34\x56\x78\x9A", - "\x01\x23\x45\x67\x89\xAB\xCD\xEF", - "\x23\x8B\x4F\xE5\x84\x7E\x44\xB2" - }; - -// AES ECB test vectors FIPS-197 - -#define AES_TEST_COUNT 1 - -typedef struct { - unsigned char key[32]; - unsigned char plaintext[16]; - unsigned char ciphertext[16]; - } AES_TEST; - -AES_TEST aes_ecb_vectors[AES_TEST_COUNT] = { -0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, -0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, - -0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff, - -0x8e,0xa2,0xb7,0xca,0x51,0x67,0x45,0xbf,0xea,0xfc,0x49,0x90,0x4b,0x49,0x60,0x89 -}; - -// Serpent ECB test vectors - -#define SERPENT_TEST_COUNT 1 - -typedef struct { - unsigned char key[32]; - unsigned char plaintext[16]; - unsigned char ciphertext[16]; - } SERPENT_TEST; - -SERPENT_TEST serpent_vectors[SERPENT_TEST_COUNT] = { -0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - -0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c -}; - -// Twofish ECB test vectors - -#define TWOFISH_TEST_COUNT 1 - -typedef struct { - unsigned char key[32]; - unsigned char plaintext[16]; - unsigned char ciphertext[16]; - } TWOFISH_TEST; - -TWOFISH_TEST twofish_vectors[TWOFISH_TEST_COUNT] = { -0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, -0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F, - -0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6, -0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA -}; - -/* Test vectors from FIPS 198a, RFC 4231, RFC 2104, RFC 2202, and other sources. */ - -char *hmac_sha512_test_keys[] = -{ - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - "Jefe", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", -}; - -char *hmac_sha512_test_data[] = -{ - "Hi There", - "what do ya want for nothing?", - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - "Test Using Larger Than Block-Size Key - Hash Key First", - "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", -}; - -char *hmac_sha512_test_vectors[] = -{ - "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54", - "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37", - "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb", - "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd", - "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98", - "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58", -}; - -char *hmac_sha1_test_keys[] = -{ - // Deprecated/legacy - "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3", - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - "Jefe", - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" -}; - -char *hmac_sha1_test_data[] = -{ - // Deprecated/legacy - "Sample #3", - "Hi There", - "what do ya want for nothing?", - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" -}; - -char *hmac_sha1_test_vectors[] = -{ - // Deprecated/legacy - "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", - "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00", - "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79", - "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3" -}; - -char *hmac_ripemd160_test_keys[] = -{ - "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x01\x23\x45\x67", - "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10\x00\x11\x22\x33", -}; - -char *hmac_ripemd160_test_data[] = -{ - "message digest", - "12345678901234567890123456789012345678901234567890123456789012345678901234567890", -}; - -char *hmac_ripemd160_test_vectors[] = -{ - "\xf8\x36\x62\xcc\x8d\x33\x9c\x22\x7e\x60\x0f\xcd\x63\x6c\x57\xd2\x57\x1b\x1c\x34", - "\x85\xf1\x64\x70\x3e\x61\xa6\x31\x31\xbe\x7e\x45\x95\x8e\x07\x94\x12\x39\x04\xf9", -}; - -char *hmac_whirlpool_test_key = -{ - "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF" -}; - -char *hmac_whirlpool_test_data = -{ - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" -}; - -char *hmac_whirlpool_test_vectors = -{ - "\x03\x91\xd2\x80\x00\xb6\x62\xbb\xb8\xe6\x23\x3e\xe8\x6c\xf2\xb2\x84\x74\x4c\x73" - "\x8b\x58\x00\xba\x28\x12\xed\x52\x6f\xe3\x15\x3a\xb1\xba\xe7\xe2\x36\xbe\x96\x54" - "\x49\x3f\x19\xfa\xce\xa6\x44\x1f\x60\xf5\xf0\x18\x93\x09\x11\xa5\xe5\xce\xd8\xf2" - "\x6a\xbf\xa4\x02" -}; - -unsigned char ks_tmp[MAX_EXPANDED_KEY]; - -void CipherInit2(int cipher, void* key, void* ks, int key_len) -{ - switch (cipher) - { - case BLOWFISH: - /* Deprecated/legacy */ - BlowfishSetKey (ks, key_len, key); - break; - - case AES: - CipherInit(cipher,key,ks); - break; - - case CAST: - /* Deprecated/legacy */ - CipherInit(cipher,key,ks); - break; - - case SERPENT: - CipherInit(cipher,key,ks); - break; - - case TRIPLEDES: - /* Deprecated/legacy */ - CipherInit(cipher,key,ks); - break; - - case TWOFISH: - CipherInit(cipher,key,ks); - break; - - default: - /* Unknown/wrong ID */ - TC_THROW_FATAL_EXCEPTION; - } -} - - -/* Deprecated/legacy */ -typedef struct { - unsigned __int8 key1[32]; - unsigned __int8 key2[16]; - unsigned __int8 index[16]; - unsigned __int8 plaintext[16]; - unsigned __int8 ciphertext[16]; -} LRW_TEST; - -#define LRW_TEST_COUNT 2 - -/* Deprecated/legacy */ -LRW_TEST lrw_vectors[LRW_TEST_COUNT] = { - { - { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c, 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d, - 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21, 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89 }, - { 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1, 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, - { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e, 0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b } - }, - { - { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d, 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8, - 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d, 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7 }, - { 0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4, 0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, - { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, - { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f, 0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 } - } -}; - - -BOOL LRWAesTest (PCRYPTO_INFO ci) -{ - /* Deprecated/legacy */ - - unsigned __int8 p[16]; - int i; - - for (i = 0; i < LRW_TEST_COUNT; i++) - { - ci->ea = EAGetByName ("AES"); - if (ci->ea == 0) - return FALSE; - - ci->mode = LRW; - - if (EAInit (ci->ea, lrw_vectors[i].key1, ci->ks) != ERR_SUCCESS) - return FALSE; - - memcpy (&ci->k2, lrw_vectors[i].key2, sizeof (lrw_vectors[i].key2)); - if (!EAInitMode (ci)) - return FALSE; - - memcpy (p, lrw_vectors[i].plaintext, sizeof (p)); - - EncryptBufferLRW128 (p, sizeof (p), BE64(((unsigned __int64 *)(lrw_vectors[i].index))[1]), ci); - - if (memcmp (lrw_vectors[i].ciphertext, p, sizeof (p)) != 0) - return FALSE; - } - - return TRUE; -} - - -BOOL TestSectorBufEncryption (PCRYPTO_INFO ci) -{ - unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 4]; - unsigned int i; - char name[64]; - unsigned __int32 crc; - UINT64_STRUCT unitNo; - TC_LARGEST_COMPILER_UINT nbrUnits; - unsigned __int64 writeOffset; - int testCase = 0; - int nTestsPerformed = 0; - - static unsigned char key1[] = - { - 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, - 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 - }; - - if (!TestLegacySectorBufEncryption (ci)) - return FALSE; - - - /* Encryption/decryption of data units (typically, volume data sectors) */ - - nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; - - ci->mode = XTS; // Other modes of operation are tested in TestLegacySectorBufEncryption() - - /* The buffer can accommodate 4 data units and we'll test 4 cases by "scrolling". The data unit 0xFFFFFFFFFF - will "move" from the start of the buffer to its end. For a 512-byte data unit, the byte offset 562949953420800 - corresponds to the data unit 0xFFFFFFFFFF. */ - for (writeOffset = 562949953420800LL; - writeOffset > 562949953420800LL - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE; - writeOffset -= ENCRYPTION_DATA_UNIT_SIZE) - { - unitNo.Value = writeOffset / ENCRYPTION_DATA_UNIT_SIZE; - - // Test all EAs that support this mode of operation - for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea)) - { - if (!EAIsModeSupported (ci->ea, ci->mode)) - continue; - - EAGetName (name, ci->ea); - - if (EAInit (ci->ea, key1, ci->ks) != ERR_SUCCESS) - return FALSE; - - for (i = 0; i < sizeof (ci->k2); i++) - ci->k2[i] = (unsigned char) i; - - memcpy (&ci->k2, XTS_vectors[XTS_TEST_COUNT-1].key2, sizeof (XTS_vectors[XTS_TEST_COUNT-1].key2)); - - if (!EAInitMode (ci)) - return FALSE; - - // Each data unit will contain the same plaintext - for (i = 0; i < nbrUnits; i++) - { - memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, - XTS_vectors[XTS_TEST_COUNT-1].plaintext, - ENCRYPTION_DATA_UNIT_SIZE); - } - - EncryptDataUnits (buf, &unitNo, nbrUnits, ci); - - crc = GetCrc32 (buf, sizeof (buf)); - - if (strcmp (name, "AES") == 0) - { - // Verify the ciphertext of the "moving" data unit using the IEEE test vector #14 - if (memcmp (XTS_vectors[XTS_TEST_COUNT-1].ciphertext, - (unsigned char *) buf + testCase * ENCRYPTION_DATA_UNIT_SIZE, - ENCRYPTION_DATA_UNIT_SIZE) != 0) - { - return FALSE; - } - - // CRC of all data units in the buffer for each test case - switch (testCase) - { - case 0: - if (crc != 0x888f2990) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0xea28ea34) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0xe058f5a2) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0x10473dc9) - return FALSE; - nTestsPerformed++; - break; - } - } - else if (strcmp (name, "Serpent") == 0) - { - switch (testCase) - { - case 0: - if (crc != 0x7edfecb3) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0x357baaaa) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0xc7b9fca5) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0xb5263e0c) - return FALSE; - nTestsPerformed++; - break; - } - } - else if (strcmp (name, "Twofish") == 0) - { - switch (testCase) - { - case 0: - if (crc != 0x91525124) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0x2895cc47) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0x6bee346d) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0xb1c45759) - return FALSE; - nTestsPerformed++; - break; - } - } - else if (strcmp (name, "AES-Twofish") == 0) - { - switch (testCase) - { - case 0: - if (crc != 0x6cea7fa2) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0x69052c4c) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0x88db8de5) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0xf16fd8c5) - return FALSE; - nTestsPerformed++; - break; - } - } - else if (strcmp (name, "AES-Twofish-Serpent") == 0) - { - switch (testCase) - { - case 0: - if (crc != 0xa2d7d82a) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0xdbf76412) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0xdf0ea03e) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0xdadedff7) - return FALSE; - nTestsPerformed++; - break; - } - } - else if (strcmp (name, "Serpent-AES") == 0) - { - switch (testCase) - { - case 0: - if (crc != 0x6dd133b3) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0x0e5717d2) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0x39f83cd9) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0x8a79fa2c) - return FALSE; - nTestsPerformed++; - break; - } - } - else if (strcmp (name, "Serpent-Twofish-AES") == 0) - { - switch (testCase) - { - case 0: - if (crc != 0xe536daf8) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0x3ae89e7f) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0x2cc1301a) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0xcac7bdc7) - return FALSE; - nTestsPerformed++; - break; - } - } - else if (strcmp (name, "Twofish-Serpent") == 0) - { - switch (testCase) - { - case 0: - if (crc != 0x2686c859) - return FALSE; - nTestsPerformed++; - break; - case 1: - if (crc != 0x8a201780) - return FALSE; - nTestsPerformed++; - break; - case 2: - if (crc != 0x8dd13796) - return FALSE; - nTestsPerformed++; - break; - case 3: - if (crc != 0xe95196cb) - return FALSE; - nTestsPerformed++; - break; - } - } - - if (crc == 0x9f5edd58) - return FALSE; - - DecryptDataUnits (buf, &unitNo, nbrUnits, ci); - - if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) - return FALSE; - - nTestsPerformed++; - } - testCase++; - } - - /* Encryption/decryption of a buffer (typically, a volume header) */ - - nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; - - // Test all EAs that support this mode of operation - for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea)) - { - if (!EAIsModeSupported (ci->ea, ci->mode)) - continue; - - EAGetName (name, ci->ea); - - if (EAInit (ci->ea, key1, ci->ks) != ERR_SUCCESS) - return FALSE; - - memcpy (&ci->k2, XTS_vectors[XTS_TEST_COUNT-1].key2, sizeof (XTS_vectors[XTS_TEST_COUNT-1].key2)); - - if (!EAInitMode (ci)) - return FALSE; - - // Each data unit will contain the same plaintext - for (i = 0; i < nbrUnits; i++) - { - memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, - XTS_vectors[XTS_TEST_COUNT-1].plaintext, - ENCRYPTION_DATA_UNIT_SIZE); - } - - EncryptBuffer (buf, sizeof (buf), ci); - - crc = GetCrc32 (buf, sizeof (buf)); - - if (strcmp (name, "AES") == 0) - { - if (crc != 0x33b91fab) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent") == 0) - { - if (crc != 0x3494d480) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Twofish") == 0) - { - if (crc != 0xc4d65b46) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish") == 0) - { - if (crc != 0x14ce7385) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish-Serpent") == 0) - { - if (crc != 0x0ec81bf7) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-AES") == 0) - { - if (crc != 0x42f919ad) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-Twofish-AES") == 0) - { - if (crc != 0x208d5c58) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Twofish-Serpent") == 0) - { - if (crc != 0xbe78cec1) - return FALSE; - nTestsPerformed++; - } - - if (crc == 0x9f5edd58) - return FALSE; - - DecryptBuffer (buf, sizeof (buf), ci); - - if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) - return FALSE; - - nTestsPerformed++; - } - - return (nTestsPerformed == 80); -} - - -BOOL TestLegacySectorBufEncryption (PCRYPTO_INFO ci) -{ - unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 2]; - unsigned int i; - char name[64]; - unsigned __int32 crc; - UINT64_STRUCT unitNo; - TC_LARGEST_COMPILER_UINT nbrUnits; - int blockSize; - BOOL lrw64InitDone = FALSE; - BOOL lrw128InitDone = FALSE; - int nTestsPerformed = 0; - - unitNo.Value = 0x0234567890ABCDEFull; - nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; - - for (i = 0; i < sizeof (buf); i++) - buf[i] = (unsigned char) i; - - for (i = 0; i < sizeof (ci->k2); i++) - ci->k2[i] = (unsigned char) i; - - // Test all EAs - for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea)) - { - EAGetName (name, ci->ea); - blockSize = CipherGetBlockSize (EAGetFirstCipher (ci->ea)); - - if (EAInit (ci->ea, (unsigned char *)buf, ci->ks) == ERR_CIPHER_INIT_FAILURE) - return FALSE; - - // Test all deprecated modes of operation - for (ci->mode = EAGetFirstMode (ci->ea); - ci->mode != 0; - ci->mode = EAGetNextMode (ci->ea, ci->mode)) - { - // Skip modes that are not deprecated - if (ci->mode == XTS) - continue; - - if (ci->mode == LRW - && (blockSize == 8 && !lrw64InitDone || blockSize == 16 && !lrw128InitDone )) - { - if (!EAInitMode (ci)) - return FALSE; - - if (blockSize == 8) - lrw64InitDone = TRUE; - else if (blockSize == 16) - lrw128InitDone = TRUE; - } - - EncryptDataUnits (buf, &unitNo, nbrUnits, ci); - crc = GetCrc32 (buf, sizeof (buf)); - - switch (ci->mode) - { - case LRW: // Deprecated/legacy - if (strcmp (name, "AES") == 0) - { - if (crc != 0x5237acf9) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy - { - if (crc != 0xf94d5300) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "CAST5") == 0) // Deprecated/legacy - { - if (crc != 0x33971e82) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent") == 0) - { - if (crc != 0x7fb86805) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Triple DES") == 0) // Deprecated/legacy - { - if (crc != 0x2b20bb84) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Twofish") == 0) - { - if (crc != 0xa9de0f0b) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish") == 0) - { - if (crc != 0x4ed0fd80) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish-Serpent") == 0) - { - if (crc != 0xea04b3cf) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-AES") == 0) - { - if (crc != 0x0d33596a) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-Twofish-AES") == 0) - { - if (crc != 0x2845d0e3) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Twofish-Serpent") == 0) - { - if (crc != 0xca65c5cd) - return FALSE; - nTestsPerformed++; - } - break; - - case CBC: // Deprecated/legacy - case INNER_CBC: // Deprecated/legacy - case OUTER_CBC: // Deprecated/legacy - if (strcmp (name, "AES") == 0) - { - if (crc != 0x2274f53d) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy - { - if (crc != 0x033899a1) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "CAST5") == 0) // Deprecated/legacy - { - if (crc != 0x331cecc7) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent") == 0) - { - if (crc != 0x42dff3d4) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Triple DES") == 0) // Deprecated/legacy - { - if (crc != 0xfe497d0c) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Blowfish") == 0) // Deprecated/legacy - { - if (crc != 0xa7a80c84) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Blowfish-Serpent") == 0) // Deprecated/legacy - { - if (crc != 0xa0584562) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish") == 0) - { - if (crc != 0x3c226444) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish-Serpent") == 0) - { - if (crc != 0x5e5e77fd) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-AES") == 0) - { - if (crc != 0x57c612d5) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-Twofish-AES") == 0) - { - if (crc != 0x081e045a) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Twofish-Serpent") == 0) - { - if (crc != 0xa7b659f3) - return FALSE; - nTestsPerformed++; - } - break; - } - - if (crc == 0xb70b4c26) - return FALSE; - - DecryptDataUnits (buf, &unitNo, nbrUnits, ci); - - if (GetCrc32 (buf, sizeof (buf)) != 0xb70b4c26) - return FALSE; - - nTestsPerformed++; - - EncryptBuffer (buf, sizeof (buf), ci); - crc = GetCrc32 (buf, sizeof (buf)); - - switch (ci->mode) - { - case LRW: // Deprecated/legacy - if (strcmp (name, "AES") == 0) - { - if (crc != 0x5ae1e3d8) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy - { - if (crc != 0x2738426f) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish-Serpent") == 0) - { - if (crc != 0x14f2948a) - return FALSE; - nTestsPerformed++; - } - break; - - case CBC: // Deprecated/legacy - case INNER_CBC: // Deprecated/legacy - case OUTER_CBC: // Deprecated/legacy - if (strcmp (name, "AES") == 0) - { - if (crc != 0x960f740e) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy - { - if (crc != 0x7e1cfabb) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "CAST5") == 0) // Deprecated/legacy - { - if (crc != 0xeaae21c8) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent") == 0) - { - if (crc != 0xa8139d62) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Triple DES") == 0) // Deprecated/legacy - { - if (crc != 0xecf5d7d0) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Blowfish") == 0) // Deprecated/legacy - { - if (crc != 0xb70171b6) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Blowfish-Serpent") == 0) // Deprecated/legacy - { - if (crc != 0x1e749a87) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish") == 0) - { - if (crc != 0xb4b8bb9b) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "AES-Twofish-Serpent") == 0) - { - if (crc != 0x76b6c1cb) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-AES") == 0) - { - if (crc != 0x634f12ed) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Serpent-Twofish-AES") == 0) - { - if (crc != 0xe54bc1b9) - return FALSE; - nTestsPerformed++; - } - else if (strcmp (name, "Twofish-Serpent") == 0) - { - if (crc != 0x21cdb382) - return FALSE; - nTestsPerformed++; - } - break; - } - - if (crc == 0xb70b4c26) - return FALSE; - - DecryptBuffer (buf, sizeof (buf), ci); - - if (GetCrc32 (buf, sizeof (buf)) != 0xb70b4c26) - return FALSE; - - nTestsPerformed++; - } - } - return (nTestsPerformed == 86); -} - - -BOOL AutoTestAlgorithms (void) -{ - PCRYPTO_INFO ci; - char key[32]; - unsigned char tmp[16]; - BOOL bFailed = FALSE; - int i; - - ci = crypto_open (); - if (!ci) - return FALSE; - - memset (ci, 0, sizeof (*ci)); - - /* Blowfish (deprecated/legacy) */ - - for (i=0;ikey)); - memcpy(tmp, tripledes_vectors[i].plaintext, sizeof(tripledes_vectors->plaintext)); - - CipherInit(cipher, key, ks_tmp); - - EncipherBlock(cipher, tmp, ks_tmp); - if (memcmp(tripledes_vectors[i].ciphertext, tmp, sizeof(tripledes_vectors->ciphertext)) != 0) - break; - - DecipherBlock(cipher, tmp, ks_tmp); - if (memcmp(tripledes_vectors[i].plaintext, tmp, sizeof(tripledes_vectors->plaintext)) != 0) - break; - } - if (i != TRIPLEDES_TEST_COUNT) - bFailed = TRUE; - - - /* AES */ - - for (i = 0; i < AES_TEST_COUNT; i++) - { - int cipher = AES; - memcpy(key, aes_ecb_vectors[i].key, 32); - memcpy(tmp, aes_ecb_vectors[i].plaintext, 16); - CipherInit(cipher, key, ks_tmp); - - EncipherBlock(cipher, tmp, ks_tmp); - if (memcmp(aes_ecb_vectors[i].ciphertext, tmp, 16) != 0) - break; - - DecipherBlock(cipher, tmp, ks_tmp); - if (memcmp(aes_ecb_vectors[i].plaintext, tmp, 16) != 0) - break; - } - if (i != AES_TEST_COUNT) - bFailed = TRUE; - - - /* Serpent */ - - for (i = 0; i < SERPENT_TEST_COUNT; i++) - { - int cipher = SERPENT; - memcpy(key, serpent_vectors[i].key, 32); - memcpy(tmp, serpent_vectors[i].plaintext, 16); - CipherInit(cipher, key, ks_tmp); - - EncipherBlock(cipher, tmp, ks_tmp); - if (memcmp(serpent_vectors[i].ciphertext, tmp, 16) != 0) - break; - - DecipherBlock(cipher, tmp, ks_tmp); - if (memcmp(serpent_vectors[i].plaintext, tmp, 16) != 0) - break; - } - if (i != SERPENT_TEST_COUNT) - bFailed = TRUE; - - - /* Twofish */ - - for (i = 0; i < TWOFISH_TEST_COUNT; i++) - { - int cipher = TWOFISH; - memcpy(key, twofish_vectors[i].key, 32); - memcpy(tmp, twofish_vectors[i].plaintext, 16); - CipherInit(cipher, key, ks_tmp); - - EncipherBlock(cipher, tmp, ks_tmp); - if (memcmp(twofish_vectors[i].ciphertext, tmp, 16) != 0) - break; - - DecipherBlock(cipher, tmp, ks_tmp); - if (memcmp(twofish_vectors[i].plaintext, tmp, 16) != 0) - break; - } - if (i != TWOFISH_TEST_COUNT) - bFailed = TRUE; - - - /* PKCS #5 and HMACs */ - if (!test_pkcs5 ()) - bFailed = TRUE; - - /* CRC-32 */ - if (!crc32_selftests ()) - bFailed = TRUE; - - /* GF multiplicator */ -#if 0 - if (!GfMulSelfTest ()) - bFailed = TRUE; -#endif - - /* XTS-AES */ - if (!XTSAesTest (ci)) - bFailed = TRUE; - - /* LRW-AES (deprecated/legacy) */ - if (!LRWAesTest (ci)) - bFailed = TRUE; - - /* Sector and buffer related algorithms */ - if (!TestSectorBufEncryption (ci)) - bFailed = TRUE; - - crypto_close (ci); - return !bFailed; -} - -BOOL test_hmac_sha512 () -{ - unsigned int i; - int nTestsPerformed = 0; - - for (i = 0; i < sizeof (hmac_sha512_test_data) / sizeof(char *); i++) - { - char digest[SHA512_DIGESTSIZE]; - hmac_sha512 (hmac_sha512_test_keys[i], strlen (hmac_sha512_test_keys[i]), hmac_sha512_test_data[i], strlen (hmac_sha512_test_data[i]), digest, SHA512_DIGESTSIZE); - if (memcmp (digest, hmac_sha512_test_vectors[i], SHA512_DIGESTSIZE) != 0) - return FALSE; - else - nTestsPerformed++; - } - - return (nTestsPerformed == 6); -} - -BOOL test_hmac_sha1 () -{ - // Deprecated/legacy - - int nTestsPerformed = 0; - int i; - - for (i = 0; i < 3; i++) - { - char digest[SHA1_DIGESTSIZE]; - hmac_sha1 (hmac_sha1_test_keys[i], strlen (hmac_sha1_test_keys[i]), hmac_sha1_test_data[i], strlen (hmac_sha1_test_data[i]), digest, SHA1_DIGESTSIZE); - if (memcmp (digest, hmac_sha1_test_vectors[i], SHA1_DIGESTSIZE) != 0) - return FALSE; - else - nTestsPerformed++; - } - - return (nTestsPerformed == 3); -} - -BOOL test_hmac_ripemd160 () -{ - int nTestsPerformed = 0; - unsigned int i; - - for (i = 0; i < sizeof (hmac_ripemd160_test_data) / sizeof(char *); i++) - { - char digest[RIPEMD160_DIGESTSIZE]; - hmac_ripemd160 (hmac_ripemd160_test_keys[i], RIPEMD160_DIGESTSIZE, hmac_ripemd160_test_data[i], strlen (hmac_ripemd160_test_data[i]), digest); - if (memcmp (digest, hmac_ripemd160_test_vectors[i], RIPEMD160_DIGESTSIZE) != 0) - return FALSE; - else - nTestsPerformed++; - } - - return (nTestsPerformed == 2); -} - -BOOL test_hmac_whirlpool () -{ - unsigned char digest[WHIRLPOOL_DIGESTSIZE]; - - hmac_whirlpool (hmac_whirlpool_test_key, 64, hmac_whirlpool_test_data, strlen (hmac_whirlpool_test_data), digest, WHIRLPOOL_DIGESTSIZE); - if (memcmp (digest, hmac_whirlpool_test_vectors, WHIRLPOOL_DIGESTSIZE) != 0) - return FALSE; - - return TRUE; -} - -BOOL test_pkcs5 () -{ - char dk[144]; - - /* HMAC-SHA-512 tests */ - if (!test_hmac_sha512()) - return FALSE; - - /* HMAC-SHA-1 tests (deprecated/legacy) */ - if (test_hmac_sha1() == FALSE) - return FALSE; - - /* HMAC-RIPEMD-160 tests */ - if (test_hmac_ripemd160() == FALSE) - return FALSE; - - /* HMAC-Whirlpool tests */ - if (test_hmac_whirlpool() == FALSE) - return FALSE; - - /* PKCS-5 test 1 with HMAC-SHA-512 used as the PRF */ - derive_key_sha512 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); - if (memcmp (dk, "\x13\x64\xae\xf8", 4) != 0) - return FALSE; - - /* PKCS-5 test 2 with HMAC-SHA-512 used as the PRF (derives a key longer than the underlying - hash output size and block size) */ - derive_key_sha512 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 144); - if (memcmp (dk, "\x13\x64\xae\xf8\x0d\xf5\x57\x6c\x30\xd5\x71\x4c\xa7\x75\x3f\xfd\x00\xe5\x25\x8b\x39\xc7\x44\x7f\xce\x23\x3d\x08\x75\xe0\x2f\x48\xd6\x30\xd7\x00\xb6\x24\xdb\xe0\x5a\xd7\x47\xef\x52\xca\xa6\x34\x83\x47\xe5\xcb\xe9\x87\xf1\x20\x59\x6a\xe6\xa9\xcf\x51\x78\xc6\xb6\x23\xa6\x74\x0d\xe8\x91\xbe\x1a\xd0\x28\xcc\xce\x16\x98\x9a\xbe\xfb\xdc\x78\xc9\xe1\x7d\x72\x67\xce\xe1\x61\x56\x5f\x96\x68\xe6\xe1\xdd\xf4\xbf\x1b\x80\xe0\x19\x1c\xf4\xc4\xd3\xdd\xd5\xd5\x57\x2d\x83\xc7\xa3\x37\x87\xf4\x4e\xe0\xf6\xd8\x6d\x65\xdc\xa0\x52\xa3\x13\xbe\x81\xfc\x30\xbe\x7d\x69\x58\x34\xb6\xdd\x41\xc6", 144) != 0) - return FALSE; - - /* PKCS-5 test 1 with HMAC-SHA-1 (deprecated/legacy) used as the PRF (derives a key longer than the underlying hash) */ - derive_key_sha1 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 48); - if (memcmp (dk, "\x5c\x75\xce\xf0\x1a\x96\x0d\xf7\x4c\xb6\xb4\x9b\x9e\x38\xe6\xb5\x3b\x11\x80\xe3\x2f\xf7\xe0\xdd\xaa\xca\x8f\x81\x27\xf6\x9f\x4f\x1d\xc8\x2f\x48\x2d\xdb\x1a\x0a\xca\x90\xcb\x80\xb9\x2e\x90\x9e", 48) != 0) - return FALSE; - - /* PKCS-5 test 2 with HMAC-SHA-1 (deprecated/legacy) used as the PRF */ - derive_key_sha1 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); - if (memcmp (dk, "\x5c\x75\xce\xf0", 4) != 0) - return FALSE; - -#if 0 // This test is disabled because it uses 1200 iterations (to prevent startup slowdown) - /* PKCS-5 test 3 with HMAC-SHA-1 (deprecated/legacy) used as the PRF */ - derive_key_sha1 ("password", 8, "ATHENA.MIT.EDUraeburn", 21, 1200, dk, 16); - if (memcmp (dk, "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b", 16) != 0) - return FALSE; -#endif - - /* PKCS-5 test 1 with HMAC-RIPEMD-160 used as the PRF */ - derive_key_ripemd160 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); - if (memcmp (dk, "\x7a\x3d\x7c\x03", 4) != 0) - return FALSE; - - /* PKCS-5 test 2 with HMAC-RIPEMD-160 used as the PRF (derives a key longer than the underlying hash) */ - derive_key_ripemd160 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 48); - if (memcmp (dk, "\x7a\x3d\x7c\x03\xe7\x26\x6b\xf8\x3d\x78\xfb\x29\xd2\x64\x1f\x56\xea\xf0\xe5\xf5\xcc\xc4\x3a\x31\xa8\x84\x70\xbf\xbd\x6f\x8e\x78\x24\x5a\xc0\x0a\xf6\xfa\xf0\xf6\xe9\x00\x47\x5f\x73\xce\xe1\x43", 48) != 0) - return FALSE; - - /* PKCS-5 test 1 with HMAC-Whirlpool used as the PRF */ - derive_key_whirlpool ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); - if (memcmp (dk, "\x50\x7c\x36\x6f", 4) != 0) - return FALSE; - - /* PKCS-5 test 2 with HMAC-Whirlpool used as the PRF (derives a key longer than the underlying hash) */ - derive_key_whirlpool ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 96); - if (memcmp (dk, "\x50\x7c\x36\x6f\xee\x10\x2e\x9a\xe2\x8a\xd5\x82\x72\x7d\x27\x0f\xe8\x4d\x7f\x68\x7a\xcf\xb5\xe7\x43\x67\xaa\x98\x93\x52\x2b\x09\x6e\x42\xdf\x2c\x59\x4a\x91\x6d\x7e\x10\xae\xb2\x1a\x89\x8f\xb9\x8f\xe6\x31\xa9\xd8\x9f\x98\x26\xf4\xda\xcd\x7d\x65\x65\xde\x10\x95\x91\xb4\x84\x26\xae\x43\xa1\x00\x5b\x1e\xb8\x38\x97\xa4\x1e\x4b\xd2\x65\x64\xbc\xfa\x1f\x35\x85\xdb\x4f\x97\x65\x6f\xbd\x24", 96) != 0) - return FALSE; - - return TRUE; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" +#include "Crc.h" +#include "Crypto.h" +#include "Common/Endian.h" +#include "Tests.h" +#include "Xts.h" +#include +#include "Pkcs5.h" + +typedef struct { + unsigned __int8 key1[32]; + unsigned __int8 key2[32]; + unsigned __int8 dataUnitNo[8]; + unsigned int blockNo; + unsigned __int8 plaintext[ENCRYPTION_DATA_UNIT_SIZE]; + unsigned __int8 ciphertext[ENCRYPTION_DATA_UNIT_SIZE]; +} XTS_TEST; + +#define XTS_TEST_COUNT 5 + +XTS_TEST XTS_vectors[XTS_TEST_COUNT] = { +/* XTS-AES-256 */ +{ + // IEEE 1619 - Vector 10 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b, + 0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd, + 0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0, + 0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca, + 0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0, + 0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f, + 0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec, + 0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a, + 0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1, + 0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae, + 0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29, + 0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac, + 0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f, + 0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85, + 0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa, + 0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51 + } +}, +{ + // IEEE 1619 - Vector 11 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11, + 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2, + 0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d, + 0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01, + 0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79, + 0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a, + 0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6, + 0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80, + 0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a, + 0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0, + 0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75, + 0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63, + 0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a, + 0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68, + 0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90, + 0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03 + } +}, +{ + // IEEE 1619 - Vector 12 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00, + 0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49, + 0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8, + 0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1, + 0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf, + 0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e, + 0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6, + 0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79, + 0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0, + 0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64, + 0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d, + 0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a, + 0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2, + 0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce, + 0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36, + 0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26 + } +}, +{ + // IEEE 1619 - Vector 13 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5, + 0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1, + 0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac, + 0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e, + 0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3, + 0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5, + 0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9, + 0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c, + 0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53, + 0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7, + 0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf, + 0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00, + 0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60, + 0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55, + 0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c, + 0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20 + } +}, +{ + // IEEE 1619 - Vector 14 + + /* This vector must always be the last one in XTS_vectors[] because TestSectorBufEncryption() relies on it. */ + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23, + 0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80, + 0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04, + 0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4, + 0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b, + 0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34, + 0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8, + 0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff, + 0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b, + 0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6, + 0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa, + 0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc, + 0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a, + 0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46, + 0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde, + 0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9 + } +} }; // XTS_TEST XTS_vectors[] + + +BOOL XTSAesTest (PCRYPTO_INFO ci) +{ + unsigned __int8 p[ENCRYPTION_DATA_UNIT_SIZE]; + UINT64_STRUCT dataUnitNo; + int i; + + for (i = 0; i < XTS_TEST_COUNT; i++) + { + ci->ea = EAGetByName ("AES"); + if (ci->ea == 0) + return FALSE; + + ci->mode = XTS; + + if (EAInit (ci->ea, XTS_vectors[i].key1, ci->ks) != ERR_SUCCESS) + return FALSE; + + memcpy (&ci->k2, XTS_vectors[i].key2, sizeof (XTS_vectors[i].key2)); + + if (!EAInitMode (ci)) + return FALSE; + + memcpy (p, XTS_vectors[i].plaintext, sizeof (p)); + + dataUnitNo.Value = BE64 (*((unsigned __int64 *) XTS_vectors[i].dataUnitNo)); + + EncryptBufferXTS (p, sizeof (p), &dataUnitNo, XTS_vectors[i].blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, AES); + + if (memcmp (XTS_vectors[i].ciphertext, p, sizeof (p)) != 0) + return FALSE; + } + + return TRUE; +} + +/* Blowfish Test Vectors (deprecated/legacy) */ + +/* Blowfish test vectors from www.counterpane.com/blowfish.html */ + +#define BF_TEST_COUNT 34 + +typedef struct { + unsigned char key[8]; + unsigned char plaintext[8]; + unsigned char ciphertext[8]; + } BF_TEST; + +#pragma warning(disable:4295) + +BF_TEST bf_ecb_vectors[BF_TEST_COUNT] = { +"\x00\x00\x00\x00\x00\x00\x00\x00","\x00\x00\x00\x00\x00\x00\x00\x00","\x4E\xF9\x97\x45\x61\x98\xDD\x78", +"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x51\x86\x6F\xD5\xB8\x5E\xCB\x8A", +"\x30\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x01","\x7D\x85\x6F\x9A\x61\x30\x63\xF2", +"\x11\x11\x11\x11\x11\x11\x11\x11","\x11\x11\x11\x11\x11\x11\x11\x11","\x24\x66\xDD\x87\x8B\x96\x3C\x9D", +"\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x11\x11\x11\x11\x11\x11\x11\x11","\x61\xF9\xC3\x80\x22\x81\xB0\x96", +"\x11\x11\x11\x11\x11\x11\x11\x11","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x7D\x0C\xC6\x30\xAF\xDA\x1E\xC7", +"\x00\x00\x00\x00\x00\x00\x00\x00","\x00\x00\x00\x00\x00\x00\x00\x00","\x4E\xF9\x97\x45\x61\x98\xDD\x78", +"\xFE\xDC\xBA\x98\x76\x54\x32\x10","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x0A\xCE\xAB\x0F\xC6\xA0\xA2\x8D", +"\x7C\xA1\x10\x45\x4A\x1A\x6E\x57","\x01\xA1\xD6\xD0\x39\x77\x67\x42","\x59\xC6\x82\x45\xEB\x05\x28\x2B", +"\x01\x31\xD9\x61\x9D\xC1\x37\x6E","\x5C\xD5\x4C\xA8\x3D\xEF\x57\xDA","\xB1\xB8\xCC\x0B\x25\x0F\x09\xA0", +"\x07\xA1\x13\x3E\x4A\x0B\x26\x86","\x02\x48\xD4\x38\x06\xF6\x71\x72","\x17\x30\xE5\x77\x8B\xEA\x1D\xA4", +"\x38\x49\x67\x4C\x26\x02\x31\x9E","\x51\x45\x4B\x58\x2D\xDF\x44\x0A","\xA2\x5E\x78\x56\xCF\x26\x51\xEB", +"\x04\xB9\x15\xBA\x43\xFE\xB5\xB6","\x42\xFD\x44\x30\x59\x57\x7F\xA2","\x35\x38\x82\xB1\x09\xCE\x8F\x1A", +"\x01\x13\xB9\x70\xFD\x34\xF2\xCE","\x05\x9B\x5E\x08\x51\xCF\x14\x3A","\x48\xF4\xD0\x88\x4C\x37\x99\x18", +"\x01\x70\xF1\x75\x46\x8F\xB5\xE6","\x07\x56\xD8\xE0\x77\x47\x61\xD2","\x43\x21\x93\xB7\x89\x51\xFC\x98", +"\x43\x29\x7F\xAD\x38\xE3\x73\xFE","\x76\x25\x14\xB8\x29\xBF\x48\x6A","\x13\xF0\x41\x54\xD6\x9D\x1A\xE5", +"\x07\xA7\x13\x70\x45\xDA\x2A\x16","\x3B\xDD\x11\x90\x49\x37\x28\x02","\x2E\xED\xDA\x93\xFF\xD3\x9C\x79", +"\x04\x68\x91\x04\xC2\xFD\x3B\x2F","\x26\x95\x5F\x68\x35\xAF\x60\x9A","\xD8\x87\xE0\x39\x3C\x2D\xA6\xE3", +"\x37\xD0\x6B\xB5\x16\xCB\x75\x46","\x16\x4D\x5E\x40\x4F\x27\x52\x32","\x5F\x99\xD0\x4F\x5B\x16\x39\x69", +"\x1F\x08\x26\x0D\x1A\xC2\x46\x5E","\x6B\x05\x6E\x18\x75\x9F\x5C\xCA","\x4A\x05\x7A\x3B\x24\xD3\x97\x7B", +"\x58\x40\x23\x64\x1A\xBA\x61\x76","\x00\x4B\xD6\xEF\x09\x17\x60\x62","\x45\x20\x31\xC1\xE4\xFA\xDA\x8E", +"\x02\x58\x16\x16\x46\x29\xB0\x07","\x48\x0D\x39\x00\x6E\xE7\x62\xF2","\x75\x55\xAE\x39\xF5\x9B\x87\xBD", +"\x49\x79\x3E\xBC\x79\xB3\x25\x8F","\x43\x75\x40\xC8\x69\x8F\x3C\xFA","\x53\xC5\x5F\x9C\xB4\x9F\xC0\x19", +"\x4F\xB0\x5E\x15\x15\xAB\x73\xA7","\x07\x2D\x43\xA0\x77\x07\x52\x92","\x7A\x8E\x7B\xFA\x93\x7E\x89\xA3", +"\x49\xE9\x5D\x6D\x4C\xA2\x29\xBF","\x02\xFE\x55\x77\x81\x17\xF1\x2A","\xCF\x9C\x5D\x7A\x49\x86\xAD\xB5", +"\x01\x83\x10\xDC\x40\x9B\x26\xD6","\x1D\x9D\x5C\x50\x18\xF7\x28\xC2","\xD1\xAB\xB2\x90\x65\x8B\xC7\x78", +"\x1C\x58\x7F\x1C\x13\x92\x4F\xEF","\x30\x55\x32\x28\x6D\x6F\x29\x5A","\x55\xCB\x37\x74\xD1\x3E\xF2\x01", +"\x01\x01\x01\x01\x01\x01\x01\x01","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\xFA\x34\xEC\x48\x47\xB2\x68\xB2", +"\x1F\x1F\x1F\x1F\x0E\x0E\x0E\x0E","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\xA7\x90\x79\x51\x08\xEA\x3C\xAE", +"\xE0\xFE\xE0\xFE\xF1\xFE\xF1\xFE","\x01\x23\x45\x67\x89\xAB\xCD\xEF","\xC3\x9E\x07\x2D\x9F\xAC\x63\x1D", +"\x00\x00\x00\x00\x00\x00\x00\x00","\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x01\x49\x33\xE0\xCD\xAF\xF6\xE4", +"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x00\x00\x00\x00\x00\x00\x00\x00","\xF2\x1E\x9A\x77\xB7\x1C\x49\xBC", +"\x01\x23\x45\x67\x89\xAB\xCD\xEF","\x00\x00\x00\x00\x00\x00\x00\x00","\x24\x59\x46\x88\x57\x54\x36\x9A", +"\xFE\xDC\xBA\x98\x76\x54\x32\x10","\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF","\x6B\x5C\x5A\x9C\x5D\x9E\x0A\x5A" +}; + + +#define TRIPLEDES_TEST_COUNT 1 + +typedef struct { + unsigned char key[24]; + unsigned char plaintext[8]; + unsigned char ciphertext[8]; + } TRIPLEDES_TEST; + +TRIPLEDES_TEST tripledes_vectors[TRIPLEDES_TEST_COUNT] = { +0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, +0x76, 0x54, 0x32, 0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, + +0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + +0xde, 0x0b, 0x7c, 0x06, 0xae, 0x5e, 0x0e, 0xd5 +}; + +/* CAST-128 Test Vectors from RFC2144 (deprecated/legacy) */ + +#define CAST_TEST_COUNT 1 + +typedef struct { + unsigned char key[16]; + unsigned char plaintext[8]; + unsigned char ciphertext[8]; + } CAST_TEST; + + +CAST_TEST cast_ecb_vectors[CAST_TEST_COUNT] = { + "\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45\x67\x89\x34\x56\x78\x9A", + "\x01\x23\x45\x67\x89\xAB\xCD\xEF", + "\x23\x8B\x4F\xE5\x84\x7E\x44\xB2" + }; + +// AES ECB test vectors FIPS-197 + +#define AES_TEST_COUNT 1 + +typedef struct { + unsigned char key[32]; + unsigned char plaintext[16]; + unsigned char ciphertext[16]; + } AES_TEST; + +AES_TEST aes_ecb_vectors[AES_TEST_COUNT] = { +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, +0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + +0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff, + +0x8e,0xa2,0xb7,0xca,0x51,0x67,0x45,0xbf,0xea,0xfc,0x49,0x90,0x4b,0x49,0x60,0x89 +}; + +// Serpent ECB test vectors + +#define SERPENT_TEST_COUNT 1 + +typedef struct { + unsigned char key[32]; + unsigned char plaintext[16]; + unsigned char ciphertext[16]; + } SERPENT_TEST; + +SERPENT_TEST serpent_vectors[SERPENT_TEST_COUNT] = { +0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + +0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c +}; + +// Twofish ECB test vectors + +#define TWOFISH_TEST_COUNT 1 + +typedef struct { + unsigned char key[32]; + unsigned char plaintext[16]; + unsigned char ciphertext[16]; + } TWOFISH_TEST; + +TWOFISH_TEST twofish_vectors[TWOFISH_TEST_COUNT] = { +0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, +0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F, + +0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6, +0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA +}; + +/* Test vectors from FIPS 198a, RFC 4231, RFC 2104, RFC 2202, and other sources. */ + +char *hmac_sha512_test_keys[] = +{ + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "Jefe", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", +}; + +char *hmac_sha512_test_data[] = +{ + "Hi There", + "what do ya want for nothing?", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + "Test Using Larger Than Block-Size Key - Hash Key First", + "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", +}; + +char *hmac_sha512_test_vectors[] = +{ + "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54", + "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37", + "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb", + "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd", + "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98", + "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58", +}; + +char *hmac_sha1_test_keys[] = +{ + // Deprecated/legacy + "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" +}; + +char *hmac_sha1_test_data[] = +{ + // Deprecated/legacy + "Sample #3", + "Hi There", + "what do ya want for nothing?", + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" +}; + +char *hmac_sha1_test_vectors[] = +{ + // Deprecated/legacy + "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", + "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00", + "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79", + "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3" +}; + +char *hmac_ripemd160_test_keys[] = +{ + "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x01\x23\x45\x67", + "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10\x00\x11\x22\x33", +}; + +char *hmac_ripemd160_test_data[] = +{ + "message digest", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890", +}; + +char *hmac_ripemd160_test_vectors[] = +{ + "\xf8\x36\x62\xcc\x8d\x33\x9c\x22\x7e\x60\x0f\xcd\x63\x6c\x57\xd2\x57\x1b\x1c\x34", + "\x85\xf1\x64\x70\x3e\x61\xa6\x31\x31\xbe\x7e\x45\x95\x8e\x07\x94\x12\x39\x04\xf9", +}; + +char *hmac_whirlpool_test_key = +{ + "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF" +}; + +char *hmac_whirlpool_test_data = +{ + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +}; + +char *hmac_whirlpool_test_vectors = +{ + "\x03\x91\xd2\x80\x00\xb6\x62\xbb\xb8\xe6\x23\x3e\xe8\x6c\xf2\xb2\x84\x74\x4c\x73" + "\x8b\x58\x00\xba\x28\x12\xed\x52\x6f\xe3\x15\x3a\xb1\xba\xe7\xe2\x36\xbe\x96\x54" + "\x49\x3f\x19\xfa\xce\xa6\x44\x1f\x60\xf5\xf0\x18\x93\x09\x11\xa5\xe5\xce\xd8\xf2" + "\x6a\xbf\xa4\x02" +}; + +unsigned char ks_tmp[MAX_EXPANDED_KEY]; + +void CipherInit2(int cipher, void* key, void* ks, int key_len) +{ + switch (cipher) + { + case BLOWFISH: + /* Deprecated/legacy */ + BlowfishSetKey (ks, key_len, key); + break; + + case AES: + CipherInit(cipher,key,ks); + break; + + case CAST: + /* Deprecated/legacy */ + CipherInit(cipher,key,ks); + break; + + case SERPENT: + CipherInit(cipher,key,ks); + break; + + case TRIPLEDES: + /* Deprecated/legacy */ + CipherInit(cipher,key,ks); + break; + + case TWOFISH: + CipherInit(cipher,key,ks); + break; + + default: + /* Unknown/wrong ID */ + TC_THROW_FATAL_EXCEPTION; + } +} + + +/* Deprecated/legacy */ +typedef struct { + unsigned __int8 key1[32]; + unsigned __int8 key2[16]; + unsigned __int8 index[16]; + unsigned __int8 plaintext[16]; + unsigned __int8 ciphertext[16]; +} LRW_TEST; + +#define LRW_TEST_COUNT 2 + +/* Deprecated/legacy */ +LRW_TEST lrw_vectors[LRW_TEST_COUNT] = { + { + { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c, 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d, + 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21, 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89 }, + { 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1, 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e, 0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b } + }, + { + { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d, 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8, + 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d, 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7 }, + { 0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4, 0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f, 0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 } + } +}; + + +BOOL LRWAesTest (PCRYPTO_INFO ci) +{ + /* Deprecated/legacy */ + + unsigned __int8 p[16]; + int i; + + for (i = 0; i < LRW_TEST_COUNT; i++) + { + ci->ea = EAGetByName ("AES"); + if (ci->ea == 0) + return FALSE; + + ci->mode = LRW; + + if (EAInit (ci->ea, lrw_vectors[i].key1, ci->ks) != ERR_SUCCESS) + return FALSE; + + memcpy (&ci->k2, lrw_vectors[i].key2, sizeof (lrw_vectors[i].key2)); + if (!EAInitMode (ci)) + return FALSE; + + memcpy (p, lrw_vectors[i].plaintext, sizeof (p)); + + EncryptBufferLRW128 (p, sizeof (p), BE64(((unsigned __int64 *)(lrw_vectors[i].index))[1]), ci); + + if (memcmp (lrw_vectors[i].ciphertext, p, sizeof (p)) != 0) + return FALSE; + } + + return TRUE; +} + + +BOOL TestSectorBufEncryption (PCRYPTO_INFO ci) +{ + unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 4]; + unsigned int i; + char name[64]; + unsigned __int32 crc; + UINT64_STRUCT unitNo; + uint32 nbrUnits; + unsigned __int64 writeOffset; + int testCase = 0; + int nTestsPerformed = 0; + + static unsigned char key1[] = + { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 + }; + + if (!TestLegacySectorBufEncryption (ci)) + return FALSE; + + + /* Encryption/decryption of data units (typically, volume data sectors) */ + + nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; + + ci->mode = XTS; // Other modes of operation are tested in TestLegacySectorBufEncryption() + + /* The buffer can accommodate 4 data units and we'll test 4 cases by "scrolling". The data unit 0xFFFFFFFFFF + will "move" from the start of the buffer to its end. For a 512-byte data unit, the byte offset 562949953420800 + corresponds to the data unit 0xFFFFFFFFFF. */ + for (writeOffset = 562949953420800ULL; + writeOffset > 562949953420800ULL - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE; + writeOffset -= ENCRYPTION_DATA_UNIT_SIZE) + { + unitNo.Value = writeOffset / ENCRYPTION_DATA_UNIT_SIZE; + + // Test all EAs that support this mode of operation + for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea)) + { + if (!EAIsModeSupported (ci->ea, ci->mode)) + continue; + + EAGetName (name, ci->ea); + + if (EAInit (ci->ea, key1, ci->ks) != ERR_SUCCESS) + return FALSE; + + for (i = 0; i < sizeof (ci->k2); i++) + ci->k2[i] = (unsigned char) i; + + memcpy (&ci->k2, XTS_vectors[XTS_TEST_COUNT-1].key2, sizeof (XTS_vectors[XTS_TEST_COUNT-1].key2)); + + if (!EAInitMode (ci)) + return FALSE; + + // Each data unit will contain the same plaintext + for (i = 0; i < nbrUnits; i++) + { + memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, + XTS_vectors[XTS_TEST_COUNT-1].plaintext, + ENCRYPTION_DATA_UNIT_SIZE); + } + + EncryptDataUnits (buf, &unitNo, nbrUnits, ci); + + crc = GetCrc32 (buf, sizeof (buf)); + + if (strcmp (name, "AES") == 0) + { + // Verify the ciphertext of the "moving" data unit using the IEEE test vector #14 + if (memcmp (XTS_vectors[XTS_TEST_COUNT-1].ciphertext, + (unsigned char *) buf + testCase * ENCRYPTION_DATA_UNIT_SIZE, + ENCRYPTION_DATA_UNIT_SIZE) != 0) + { + return FALSE; + } + + // CRC of all data units in the buffer for each test case + switch (testCase) + { + case 0: + if (crc != 0x888f2990) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0xea28ea34) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0xe058f5a2) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0x10473dc9) + return FALSE; + nTestsPerformed++; + break; + } + } + else if (strcmp (name, "Serpent") == 0) + { + switch (testCase) + { + case 0: + if (crc != 0x7edfecb3) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0x357baaaa) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0xc7b9fca5) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0xb5263e0c) + return FALSE; + nTestsPerformed++; + break; + } + } + else if (strcmp (name, "Twofish") == 0) + { + switch (testCase) + { + case 0: + if (crc != 0x91525124) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0x2895cc47) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0x6bee346d) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0xb1c45759) + return FALSE; + nTestsPerformed++; + break; + } + } + else if (strcmp (name, "AES-Twofish") == 0) + { + switch (testCase) + { + case 0: + if (crc != 0x6cea7fa2) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0x69052c4c) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0x88db8de5) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0xf16fd8c5) + return FALSE; + nTestsPerformed++; + break; + } + } + else if (strcmp (name, "AES-Twofish-Serpent") == 0) + { + switch (testCase) + { + case 0: + if (crc != 0xa2d7d82a) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0xdbf76412) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0xdf0ea03e) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0xdadedff7) + return FALSE; + nTestsPerformed++; + break; + } + } + else if (strcmp (name, "Serpent-AES") == 0) + { + switch (testCase) + { + case 0: + if (crc != 0x6dd133b3) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0x0e5717d2) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0x39f83cd9) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0x8a79fa2c) + return FALSE; + nTestsPerformed++; + break; + } + } + else if (strcmp (name, "Serpent-Twofish-AES") == 0) + { + switch (testCase) + { + case 0: + if (crc != 0xe536daf8) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0x3ae89e7f) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0x2cc1301a) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0xcac7bdc7) + return FALSE; + nTestsPerformed++; + break; + } + } + else if (strcmp (name, "Twofish-Serpent") == 0) + { + switch (testCase) + { + case 0: + if (crc != 0x2686c859) + return FALSE; + nTestsPerformed++; + break; + case 1: + if (crc != 0x8a201780) + return FALSE; + nTestsPerformed++; + break; + case 2: + if (crc != 0x8dd13796) + return FALSE; + nTestsPerformed++; + break; + case 3: + if (crc != 0xe95196cb) + return FALSE; + nTestsPerformed++; + break; + } + } + + if (crc == 0x9f5edd58) + return FALSE; + + DecryptDataUnits (buf, &unitNo, nbrUnits, ci); + + if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) + return FALSE; + + nTestsPerformed++; + } + testCase++; + } + + /* Encryption/decryption of a buffer (typically, a volume header) */ + + nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; + + // Test all EAs that support this mode of operation + for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea)) + { + if (!EAIsModeSupported (ci->ea, ci->mode)) + continue; + + EAGetName (name, ci->ea); + + if (EAInit (ci->ea, key1, ci->ks) != ERR_SUCCESS) + return FALSE; + + memcpy (&ci->k2, XTS_vectors[XTS_TEST_COUNT-1].key2, sizeof (XTS_vectors[XTS_TEST_COUNT-1].key2)); + + if (!EAInitMode (ci)) + return FALSE; + + // Each data unit will contain the same plaintext + for (i = 0; i < nbrUnits; i++) + { + memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, + XTS_vectors[XTS_TEST_COUNT-1].plaintext, + ENCRYPTION_DATA_UNIT_SIZE); + } + + EncryptBuffer (buf, sizeof (buf), ci); + + crc = GetCrc32 (buf, sizeof (buf)); + + if (strcmp (name, "AES") == 0) + { + if (crc != 0x33b91fab) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent") == 0) + { + if (crc != 0x3494d480) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Twofish") == 0) + { + if (crc != 0xc4d65b46) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish") == 0) + { + if (crc != 0x14ce7385) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish-Serpent") == 0) + { + if (crc != 0x0ec81bf7) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-AES") == 0) + { + if (crc != 0x42f919ad) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-Twofish-AES") == 0) + { + if (crc != 0x208d5c58) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Twofish-Serpent") == 0) + { + if (crc != 0xbe78cec1) + return FALSE; + nTestsPerformed++; + } + + if (crc == 0x9f5edd58) + return FALSE; + + DecryptBuffer (buf, sizeof (buf), ci); + + if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) + return FALSE; + + nTestsPerformed++; + } + + return (nTestsPerformed == 80); +} + + +BOOL TestLegacySectorBufEncryption (PCRYPTO_INFO ci) +{ + unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 2]; + unsigned int i; + char name[64]; + unsigned __int32 crc; + UINT64_STRUCT unitNo; + uint32 nbrUnits; + int blockSize; + BOOL lrw64InitDone = FALSE; + BOOL lrw128InitDone = FALSE; + int nTestsPerformed = 0; + + unitNo.Value = 0x0234567890ABCDEFull; + nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; + + for (i = 0; i < sizeof (buf); i++) + buf[i] = (unsigned char) i; + + for (i = 0; i < sizeof (ci->k2); i++) + ci->k2[i] = (unsigned char) i; + + // Test all EAs + for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea)) + { + EAGetName (name, ci->ea); + blockSize = CipherGetBlockSize (EAGetFirstCipher (ci->ea)); + + if (EAInit (ci->ea, (unsigned char *)buf, ci->ks) == ERR_CIPHER_INIT_FAILURE) + return FALSE; + + // Test all deprecated modes of operation + for (ci->mode = EAGetFirstMode (ci->ea); + ci->mode != 0; + ci->mode = EAGetNextMode (ci->ea, ci->mode)) + { + // Skip modes that are not deprecated + if (ci->mode == XTS) + continue; + + if (ci->mode == LRW + && (blockSize == 8 && !lrw64InitDone || blockSize == 16 && !lrw128InitDone )) + { + if (!EAInitMode (ci)) + return FALSE; + + if (blockSize == 8) + lrw64InitDone = TRUE; + else if (blockSize == 16) + lrw128InitDone = TRUE; + } + + EncryptDataUnits (buf, &unitNo, nbrUnits, ci); + crc = GetCrc32 (buf, sizeof (buf)); + + switch (ci->mode) + { + case LRW: // Deprecated/legacy + if (strcmp (name, "AES") == 0) + { + if (crc != 0x5237acf9) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy + { + if (crc != 0xf94d5300) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "CAST5") == 0) // Deprecated/legacy + { + if (crc != 0x33971e82) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent") == 0) + { + if (crc != 0x7fb86805) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Triple DES") == 0) // Deprecated/legacy + { + if (crc != 0x2b20bb84) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Twofish") == 0) + { + if (crc != 0xa9de0f0b) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish") == 0) + { + if (crc != 0x4ed0fd80) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish-Serpent") == 0) + { + if (crc != 0xea04b3cf) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-AES") == 0) + { + if (crc != 0x0d33596a) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-Twofish-AES") == 0) + { + if (crc != 0x2845d0e3) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Twofish-Serpent") == 0) + { + if (crc != 0xca65c5cd) + return FALSE; + nTestsPerformed++; + } + break; + + case CBC: // Deprecated/legacy + case INNER_CBC: // Deprecated/legacy + case OUTER_CBC: // Deprecated/legacy + if (strcmp (name, "AES") == 0) + { + if (crc != 0x2274f53d) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy + { + if (crc != 0x033899a1) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "CAST5") == 0) // Deprecated/legacy + { + if (crc != 0x331cecc7) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent") == 0) + { + if (crc != 0x42dff3d4) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Triple DES") == 0) // Deprecated/legacy + { + if (crc != 0xfe497d0c) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Blowfish") == 0) // Deprecated/legacy + { + if (crc != 0xa7a80c84) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Blowfish-Serpent") == 0) // Deprecated/legacy + { + if (crc != 0xa0584562) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish") == 0) + { + if (crc != 0x3c226444) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish-Serpent") == 0) + { + if (crc != 0x5e5e77fd) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-AES") == 0) + { + if (crc != 0x57c612d5) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-Twofish-AES") == 0) + { + if (crc != 0x081e045a) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Twofish-Serpent") == 0) + { + if (crc != 0xa7b659f3) + return FALSE; + nTestsPerformed++; + } + break; + } + + if (crc == 0xb70b4c26) + return FALSE; + + DecryptDataUnits (buf, &unitNo, nbrUnits, ci); + + if (GetCrc32 (buf, sizeof (buf)) != 0xb70b4c26) + return FALSE; + + nTestsPerformed++; + + EncryptBuffer (buf, sizeof (buf), ci); + crc = GetCrc32 (buf, sizeof (buf)); + + switch (ci->mode) + { + case LRW: // Deprecated/legacy + if (strcmp (name, "AES") == 0) + { + if (crc != 0x5ae1e3d8) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy + { + if (crc != 0x2738426f) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish-Serpent") == 0) + { + if (crc != 0x14f2948a) + return FALSE; + nTestsPerformed++; + } + break; + + case CBC: // Deprecated/legacy + case INNER_CBC: // Deprecated/legacy + case OUTER_CBC: // Deprecated/legacy + if (strcmp (name, "AES") == 0) + { + if (crc != 0x960f740e) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Blowfish") == 0) // Deprecated/legacy + { + if (crc != 0x7e1cfabb) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "CAST5") == 0) // Deprecated/legacy + { + if (crc != 0xeaae21c8) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent") == 0) + { + if (crc != 0xa8139d62) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Triple DES") == 0) // Deprecated/legacy + { + if (crc != 0xecf5d7d0) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Blowfish") == 0) // Deprecated/legacy + { + if (crc != 0xb70171b6) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Blowfish-Serpent") == 0) // Deprecated/legacy + { + if (crc != 0x1e749a87) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish") == 0) + { + if (crc != 0xb4b8bb9b) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "AES-Twofish-Serpent") == 0) + { + if (crc != 0x76b6c1cb) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-AES") == 0) + { + if (crc != 0x634f12ed) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Serpent-Twofish-AES") == 0) + { + if (crc != 0xe54bc1b9) + return FALSE; + nTestsPerformed++; + } + else if (strcmp (name, "Twofish-Serpent") == 0) + { + if (crc != 0x21cdb382) + return FALSE; + nTestsPerformed++; + } + break; + } + + if (crc == 0xb70b4c26) + return FALSE; + + DecryptBuffer (buf, sizeof (buf), ci); + + if (GetCrc32 (buf, sizeof (buf)) != 0xb70b4c26) + return FALSE; + + nTestsPerformed++; + } + } + return (nTestsPerformed == 86); +} + + +BOOL AutoTestAlgorithms (void) +{ + PCRYPTO_INFO ci; + char key[32]; + unsigned char tmp[16]; + BOOL bFailed = FALSE; + int i; + + ci = crypto_open (); + if (!ci) + return FALSE; + + memset (ci, 0, sizeof (*ci)); + + /* Blowfish (deprecated/legacy) */ + + for (i=0;ikey)); + memcpy(tmp, tripledes_vectors[i].plaintext, sizeof(tripledes_vectors->plaintext)); + + CipherInit(cipher, key, ks_tmp); + + EncipherBlock(cipher, tmp, ks_tmp); + if (memcmp(tripledes_vectors[i].ciphertext, tmp, sizeof(tripledes_vectors->ciphertext)) != 0) + break; + + DecipherBlock(cipher, tmp, ks_tmp); + if (memcmp(tripledes_vectors[i].plaintext, tmp, sizeof(tripledes_vectors->plaintext)) != 0) + break; + } + if (i != TRIPLEDES_TEST_COUNT) + bFailed = TRUE; + + + /* AES */ + + for (i = 0; i < AES_TEST_COUNT; i++) + { + int cipher = AES; + memcpy(key, aes_ecb_vectors[i].key, 32); + memcpy(tmp, aes_ecb_vectors[i].plaintext, 16); + CipherInit(cipher, key, ks_tmp); + + EncipherBlock(cipher, tmp, ks_tmp); + if (memcmp(aes_ecb_vectors[i].ciphertext, tmp, 16) != 0) + break; + + DecipherBlock(cipher, tmp, ks_tmp); + if (memcmp(aes_ecb_vectors[i].plaintext, tmp, 16) != 0) + break; + } + if (i != AES_TEST_COUNT) + bFailed = TRUE; + + + /* Serpent */ + + for (i = 0; i < SERPENT_TEST_COUNT; i++) + { + int cipher = SERPENT; + memcpy(key, serpent_vectors[i].key, 32); + memcpy(tmp, serpent_vectors[i].plaintext, 16); + CipherInit(cipher, key, ks_tmp); + + EncipherBlock(cipher, tmp, ks_tmp); + if (memcmp(serpent_vectors[i].ciphertext, tmp, 16) != 0) + break; + + DecipherBlock(cipher, tmp, ks_tmp); + if (memcmp(serpent_vectors[i].plaintext, tmp, 16) != 0) + break; + } + if (i != SERPENT_TEST_COUNT) + bFailed = TRUE; + + + /* Twofish */ + + for (i = 0; i < TWOFISH_TEST_COUNT; i++) + { + int cipher = TWOFISH; + memcpy(key, twofish_vectors[i].key, 32); + memcpy(tmp, twofish_vectors[i].plaintext, 16); + CipherInit(cipher, key, ks_tmp); + + EncipherBlock(cipher, tmp, ks_tmp); + if (memcmp(twofish_vectors[i].ciphertext, tmp, 16) != 0) + break; + + DecipherBlock(cipher, tmp, ks_tmp); + if (memcmp(twofish_vectors[i].plaintext, tmp, 16) != 0) + break; + } + if (i != TWOFISH_TEST_COUNT) + bFailed = TRUE; + + + /* PKCS #5 and HMACs */ + if (!test_pkcs5 ()) + bFailed = TRUE; + + /* CRC-32 */ + if (!crc32_selftests ()) + bFailed = TRUE; + + /* GF multiplicator */ +#if 0 + if (!GfMulSelfTest ()) + bFailed = TRUE; +#endif + + /* XTS-AES */ + if (!XTSAesTest (ci)) + bFailed = TRUE; + + /* LRW-AES (deprecated/legacy) */ + if (!LRWAesTest (ci)) + bFailed = TRUE; + + /* Sector and buffer related algorithms */ + if (!TestSectorBufEncryption (ci)) + bFailed = TRUE; + + crypto_close (ci); + return !bFailed; +} + +BOOL test_hmac_sha512 () +{ + unsigned int i; + int nTestsPerformed = 0; + + for (i = 0; i < sizeof (hmac_sha512_test_data) / sizeof(char *); i++) + { + char digest[SHA512_DIGESTSIZE]; + hmac_sha512 (hmac_sha512_test_keys[i], (int) strlen (hmac_sha512_test_keys[i]), hmac_sha512_test_data[i], (int) strlen (hmac_sha512_test_data[i]), digest, SHA512_DIGESTSIZE); + if (memcmp (digest, hmac_sha512_test_vectors[i], SHA512_DIGESTSIZE) != 0) + return FALSE; + else + nTestsPerformed++; + } + + return (nTestsPerformed == 6); +} + +BOOL test_hmac_sha1 () +{ + // Deprecated/legacy + + int nTestsPerformed = 0; + int i; + + for (i = 0; i < 3; i++) + { + char digest[SHA1_DIGESTSIZE]; + hmac_sha1 (hmac_sha1_test_keys[i], (int) strlen (hmac_sha1_test_keys[i]), hmac_sha1_test_data[i], (int) strlen (hmac_sha1_test_data[i]), digest, SHA1_DIGESTSIZE); + if (memcmp (digest, hmac_sha1_test_vectors[i], SHA1_DIGESTSIZE) != 0) + return FALSE; + else + nTestsPerformed++; + } + + return (nTestsPerformed == 3); +} + +BOOL test_hmac_ripemd160 () +{ + int nTestsPerformed = 0; + unsigned int i; + + for (i = 0; i < sizeof (hmac_ripemd160_test_data) / sizeof(char *); i++) + { + char digest[RIPEMD160_DIGESTSIZE]; + hmac_ripemd160 (hmac_ripemd160_test_keys[i], RIPEMD160_DIGESTSIZE, hmac_ripemd160_test_data[i], (int) strlen (hmac_ripemd160_test_data[i]), digest); + if (memcmp (digest, hmac_ripemd160_test_vectors[i], RIPEMD160_DIGESTSIZE) != 0) + return FALSE; + else + nTestsPerformed++; + } + + return (nTestsPerformed == 2); +} + +BOOL test_hmac_whirlpool () +{ + unsigned char digest[WHIRLPOOL_DIGESTSIZE]; + + hmac_whirlpool (hmac_whirlpool_test_key, 64, hmac_whirlpool_test_data, (int) strlen (hmac_whirlpool_test_data), digest, WHIRLPOOL_DIGESTSIZE); + if (memcmp (digest, hmac_whirlpool_test_vectors, WHIRLPOOL_DIGESTSIZE) != 0) + return FALSE; + + return TRUE; +} + +BOOL test_pkcs5 () +{ + char dk[144]; + + /* HMAC-SHA-512 tests */ + if (!test_hmac_sha512()) + return FALSE; + + /* HMAC-SHA-1 tests (deprecated/legacy) */ + if (test_hmac_sha1() == FALSE) + return FALSE; + + /* HMAC-RIPEMD-160 tests */ + if (test_hmac_ripemd160() == FALSE) + return FALSE; + + /* HMAC-Whirlpool tests */ + if (test_hmac_whirlpool() == FALSE) + return FALSE; + + /* PKCS-5 test 1 with HMAC-SHA-512 used as the PRF */ + derive_key_sha512 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); + if (memcmp (dk, "\x13\x64\xae\xf8", 4) != 0) + return FALSE; + + /* PKCS-5 test 2 with HMAC-SHA-512 used as the PRF (derives a key longer than the underlying + hash output size and block size) */ + derive_key_sha512 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 144); + if (memcmp (dk, "\x13\x64\xae\xf8\x0d\xf5\x57\x6c\x30\xd5\x71\x4c\xa7\x75\x3f\xfd\x00\xe5\x25\x8b\x39\xc7\x44\x7f\xce\x23\x3d\x08\x75\xe0\x2f\x48\xd6\x30\xd7\x00\xb6\x24\xdb\xe0\x5a\xd7\x47\xef\x52\xca\xa6\x34\x83\x47\xe5\xcb\xe9\x87\xf1\x20\x59\x6a\xe6\xa9\xcf\x51\x78\xc6\xb6\x23\xa6\x74\x0d\xe8\x91\xbe\x1a\xd0\x28\xcc\xce\x16\x98\x9a\xbe\xfb\xdc\x78\xc9\xe1\x7d\x72\x67\xce\xe1\x61\x56\x5f\x96\x68\xe6\xe1\xdd\xf4\xbf\x1b\x80\xe0\x19\x1c\xf4\xc4\xd3\xdd\xd5\xd5\x57\x2d\x83\xc7\xa3\x37\x87\xf4\x4e\xe0\xf6\xd8\x6d\x65\xdc\xa0\x52\xa3\x13\xbe\x81\xfc\x30\xbe\x7d\x69\x58\x34\xb6\xdd\x41\xc6", 144) != 0) + return FALSE; + + /* PKCS-5 test 1 with HMAC-SHA-1 (deprecated/legacy) used as the PRF (derives a key longer than the underlying hash) */ + derive_key_sha1 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 48); + if (memcmp (dk, "\x5c\x75\xce\xf0\x1a\x96\x0d\xf7\x4c\xb6\xb4\x9b\x9e\x38\xe6\xb5\x3b\x11\x80\xe3\x2f\xf7\xe0\xdd\xaa\xca\x8f\x81\x27\xf6\x9f\x4f\x1d\xc8\x2f\x48\x2d\xdb\x1a\x0a\xca\x90\xcb\x80\xb9\x2e\x90\x9e", 48) != 0) + return FALSE; + + /* PKCS-5 test 2 with HMAC-SHA-1 (deprecated/legacy) used as the PRF */ + derive_key_sha1 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); + if (memcmp (dk, "\x5c\x75\xce\xf0", 4) != 0) + return FALSE; + +#if 0 // This test is disabled because it uses 1200 iterations (to prevent startup slowdown) + /* PKCS-5 test 3 with HMAC-SHA-1 (deprecated/legacy) used as the PRF */ + derive_key_sha1 ("password", 8, "ATHENA.MIT.EDUraeburn", 21, 1200, dk, 16); + if (memcmp (dk, "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b", 16) != 0) + return FALSE; +#endif + + /* PKCS-5 test 1 with HMAC-RIPEMD-160 used as the PRF */ + derive_key_ripemd160 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); + if (memcmp (dk, "\x7a\x3d\x7c\x03", 4) != 0) + return FALSE; + + /* PKCS-5 test 2 with HMAC-RIPEMD-160 used as the PRF (derives a key longer than the underlying hash) */ + derive_key_ripemd160 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 48); + if (memcmp (dk, "\x7a\x3d\x7c\x03\xe7\x26\x6b\xf8\x3d\x78\xfb\x29\xd2\x64\x1f\x56\xea\xf0\xe5\xf5\xcc\xc4\x3a\x31\xa8\x84\x70\xbf\xbd\x6f\x8e\x78\x24\x5a\xc0\x0a\xf6\xfa\xf0\xf6\xe9\x00\x47\x5f\x73\xce\xe1\x43", 48) != 0) + return FALSE; + + /* PKCS-5 test 1 with HMAC-Whirlpool used as the PRF */ + derive_key_whirlpool ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); + if (memcmp (dk, "\x50\x7c\x36\x6f", 4) != 0) + return FALSE; + + /* PKCS-5 test 2 with HMAC-Whirlpool used as the PRF (derives a key longer than the underlying hash) */ + derive_key_whirlpool ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 96); + if (memcmp (dk, "\x50\x7c\x36\x6f\xee\x10\x2e\x9a\xe2\x8a\xd5\x82\x72\x7d\x27\x0f\xe8\x4d\x7f\x68\x7a\xcf\xb5\xe7\x43\x67\xaa\x98\x93\x52\x2b\x09\x6e\x42\xdf\x2c\x59\x4a\x91\x6d\x7e\x10\xae\xb2\x1a\x89\x8f\xb9\x8f\xe6\x31\xa9\xd8\x9f\x98\x26\xf4\xda\xcd\x7d\x65\x65\xde\x10\x95\x91\xb4\x84\x26\xae\x43\xa1\x00\x5b\x1e\xb8\x38\x97\xa4\x1e\x4b\xd2\x65\x64\xbc\xfa\x1f\x35\x85\xdb\x4f\x97\x65\x6f\xbd\x24", 96) != 0) + return FALSE; + + return TRUE; +} diff --git a/Common/Tests.h b/Common/Tests.h index 06fead2..1977879 100644 --- a/Common/Tests.h +++ b/Common/Tests.h @@ -1,30 +1,30 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifdef __cplusplus -extern "C" { -#endif - -extern unsigned char ks_tmp[MAX_EXPANDED_KEY]; - -void CipherInit2(int cipher, void* key, void* ks, int key_len); -BOOL test_hmac_sha512 (void); -BOOL test_hmac_sha1 (void); -BOOL test_hmac_ripemd160 (void); -BOOL test_hmac_whirlpool (void); -BOOL test_pkcs5 (void); -BOOL TestSectorBufEncryption (); -BOOL TestLegacySectorBufEncryption (); -BOOL AutoTestAlgorithms (void); - -#ifdef __cplusplus -} -#endif +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned char ks_tmp[MAX_EXPANDED_KEY]; + +void CipherInit2(int cipher, void* key, void* ks, int key_len); +BOOL test_hmac_sha512 (void); +BOOL test_hmac_sha1 (void); +BOOL test_hmac_ripemd160 (void); +BOOL test_hmac_whirlpool (void); +BOOL test_pkcs5 (void); +BOOL TestSectorBufEncryption (); +BOOL TestLegacySectorBufEncryption (); +BOOL AutoTestAlgorithms (void); + +#ifdef __cplusplus +} +#endif diff --git a/Common/VOLUMES.C b/Common/VOLUMES.C index 6f9dbb8..9ed826e 100644 --- a/Common/VOLUMES.C +++ b/Common/VOLUMES.C @@ -1,1027 +1,1030 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#ifndef TC_WINDOWS_BOOT -#include -#include -#include -#include -#include -#include "EncryptionThreadPool.h" -#endif - -#include -#include -#include "Random.h" - -#include "Crc.h" -#include "Crypto.h" -#include "Endian.h" -#include "Volumes.h" -#include "Pkcs5.h" - - -/* Volume header v4 structure (used since TrueCrypt 6.0): */ -// -// Offset Length Description -// ------------------------------------------ -// Unencrypted: -// 0 64 Salt -// Encrypted: -// 64 4 ASCII string 'TRUE' -// 68 2 Header version -// 70 2 Required program version -// 72 4 CRC-32 checksum of the (decrypted) bytes 256-511 -// 76 8 Reserved (set to zero) -// 84 8 Reserved (set to zero) -// 92 8 Size of hidden volume in bytes (0 = normal volume) -// 100 8 Size of the volume in bytes (identical with field 92 for hidden volumes, valid if field 70 >= 0x600 or flag bit 0 == 1) -// 108 8 Byte offset of the start of the master key scope (valid if field 70 >= 0x600 or flag bit 0 == 1) -// 116 8 Size of the encrypted area within the master key scope (valid if field 70 >= 0x600 or flag bit 0 == 1) -// 124 4 Flags: bit 0 set = system encryption; bit 1 set = non-system in-place encryption, bits 2-31 are reserved -// 128 124 Reserved (set to zero) -// 252 4 CRC-32 checksum of the (decrypted) bytes 64-251 -// 256 256 Concatenated primary master key(s) and secondary master key(s) (XTS mode) - - -/* Deprecated/legacy volume header v3 structure (used by TrueCrypt 5.x): */ -// -// Offset Length Description -// ------------------------------------------ -// Unencrypted: -// 0 64 Salt -// Encrypted: -// 64 4 ASCII string 'TRUE' -// 68 2 Header version -// 70 2 Required program version -// 72 4 CRC-32 checksum of the (decrypted) bytes 256-511 -// 76 8 Volume creation time -// 84 8 Header creation time -// 92 8 Size of hidden volume in bytes (0 = normal volume) -// 100 8 Size of the volume in bytes (identical with field 92 for hidden volumes) -// 108 8 Start byte offset of the encrypted area of the volume -// 116 8 Size of the encrypted area of the volume in bytes -// 124 132 Reserved (set to zero) -// 256 256 Concatenated primary master key(s) and secondary master key(s) (XTS mode) - - -/* Deprecated/legacy volume header v2 structure (used before TrueCrypt 5.0): */ -// -// Offset Length Description -// ------------------------------------------ -// Unencrypted: -// 0 64 Salt -// Encrypted: -// 64 4 ASCII string 'TRUE' -// 68 2 Header version -// 70 2 Required program version -// 72 4 CRC-32 checksum of the (decrypted) bytes 256-511 -// 76 8 Volume creation time -// 84 8 Header creation time -// 92 8 Size of hidden volume in bytes (0 = normal volume) -// 100 156 Reserved (set to zero) -// 256 32 For LRW (deprecated/legacy), secondary key -// For CBC (deprecated/legacy), data used to generate IV and whitening values -// 288 224 Master key(s) - - - -uint16 GetHeaderField16 (byte *header, int offset) -{ - return BE16 (*(uint16 *) (header + offset)); -} - - -uint32 GetHeaderField32 (byte *header, int offset) -{ - return BE32 (*(uint32 *) (header + offset)); -} - - -UINT64_STRUCT GetHeaderField64 (byte *header, int offset) -{ - UINT64_STRUCT uint64Struct; - -#ifndef TC_NO_COMPILER_INT64 - uint64Struct.Value = BE64 (*(uint64 *) (header + offset)); -#else - uint64Struct.HighPart = BE32 (*(uint32 *) (header + offset)); - uint64Struct.LowPart = BE32 (*(uint32 *) (header + offset + 4)); -#endif - return uint64Struct; -} - - -#ifndef TC_WINDOWS_BOOT - -typedef struct -{ - char DerivedKey[MASTER_KEYDATA_SIZE]; - BOOL Free; - LONG KeyReady; - int Pkcs5Prf; -} KeyDerivationWorkItem; - - -BOOL ReadVolumeHeaderRecoveryMode = FALSE; - -int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo) -{ - char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - KEY_INFO keyInfo; - PCRYPTO_INFO cryptoInfo; - char dk[MASTER_KEYDATA_SIZE]; - int enqPkcs5Prf, pkcs5_prf; - uint16 headerVersion; - int status = ERR_PARAMETER_INCORRECT; - int primaryKeyOffset; - - TC_EVENT keyDerivationCompletedEvent; - TC_EVENT noOutstandingWorkItemEvent; - KeyDerivationWorkItem *keyDerivationWorkItems; - KeyDerivationWorkItem *item; - int pkcs5PrfCount = LAST_PRF_ID - FIRST_PRF_ID + 1; - int encryptionThreadCount = GetEncryptionThreadCount(); - int queuedWorkItems = 0; - LONG outstandingWorkItemCount = 0; - int i; - - if (retHeaderCryptoInfo != NULL) - { - cryptoInfo = retHeaderCryptoInfo; - } - else - { - cryptoInfo = *retInfo = crypto_open (); - if (cryptoInfo == NULL) - return ERR_OUTOFMEMORY; - } - - if (encryptionThreadCount > 1) - { - keyDerivationWorkItems = TCalloc (sizeof (KeyDerivationWorkItem) * pkcs5PrfCount); - if (!keyDerivationWorkItems) - return ERR_OUTOFMEMORY; - - for (i = 0; i < pkcs5PrfCount; ++i) - keyDerivationWorkItems[i].Free = TRUE; - -#ifdef DEVICE_DRIVER - KeInitializeEvent (&keyDerivationCompletedEvent, SynchronizationEvent, FALSE); - KeInitializeEvent (&noOutstandingWorkItemEvent, SynchronizationEvent, TRUE); -#else - keyDerivationCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!keyDerivationCompletedEvent) - { - TCfree (keyDerivationWorkItems); - return ERR_OUTOFMEMORY; - } - - noOutstandingWorkItemEvent = CreateEvent (NULL, FALSE, TRUE, NULL); - if (!noOutstandingWorkItemEvent) - { - CloseHandle (keyDerivationCompletedEvent); - TCfree (keyDerivationWorkItems); - return ERR_OUTOFMEMORY; - } -#endif - } - -#ifndef DEVICE_DRIVER - VirtualLock (&keyInfo, sizeof (keyInfo)); - VirtualLock (&dk, sizeof (dk)); -#endif - - crypto_loadkey (&keyInfo, password->Text, (int) password->Length); - - // PKCS5 is used to derive the primary header key(s) and secondary header key(s) (XTS mode) from the password - memcpy (keyInfo.salt, encryptedHeader + HEADER_SALT_OFFSET, PKCS5_SALT_SIZE); - - // Test all available PKCS5 PRFs - for (enqPkcs5Prf = FIRST_PRF_ID; enqPkcs5Prf <= LAST_PRF_ID || queuedWorkItems > 0; ++enqPkcs5Prf) - { - BOOL lrw64InitDone = FALSE; // Deprecated/legacy - BOOL lrw128InitDone = FALSE; // Deprecated/legacy - - if (encryptionThreadCount > 1) - { - // Enqueue key derivation on thread pool - if (queuedWorkItems < encryptionThreadCount && enqPkcs5Prf <= LAST_PRF_ID) - { - for (i = 0; i < pkcs5PrfCount; ++i) - { - item = &keyDerivationWorkItems[i]; - if (item->Free) - { - item->Free = FALSE; - item->KeyReady = FALSE; - item->Pkcs5Prf = enqPkcs5Prf; - - EncryptionThreadPoolBeginKeyDerivation (&keyDerivationCompletedEvent, &noOutstandingWorkItemEvent, - &item->KeyReady, &outstandingWorkItemCount, enqPkcs5Prf, keyInfo.userKey, - keyInfo.keyLength, keyInfo.salt, get_pkcs5_iteration_count (enqPkcs5Prf, bBoot), item->DerivedKey); - - ++queuedWorkItems; - break; - } - } - - if (enqPkcs5Prf < LAST_PRF_ID) - continue; - } - else - --enqPkcs5Prf; - - // Wait for completion of a key derivation - while (queuedWorkItems > 0) - { - for (i = 0; i < pkcs5PrfCount; ++i) - { - item = &keyDerivationWorkItems[i]; - if (!item->Free && InterlockedExchangeAdd (&item->KeyReady, 0) == TRUE) - { - pkcs5_prf = item->Pkcs5Prf; - keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, bBoot); - memcpy (dk, item->DerivedKey, sizeof (dk)); - - item->Free = TRUE; - --queuedWorkItems; - goto KeyReady; - } - } - - if (queuedWorkItems > 0) - TC_WAIT_EVENT (keyDerivationCompletedEvent); - } - continue; -KeyReady: ; - } - else - { - pkcs5_prf = enqPkcs5Prf; - keyInfo.noIterations = get_pkcs5_iteration_count (enqPkcs5Prf, bBoot); - - switch (pkcs5_prf) - { - case RIPEMD160: - derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - case SHA512: - derive_key_sha512 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - case SHA1: - // Deprecated/legacy - derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - case WHIRLPOOL: - derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } - } - - // Test all available modes of operation - for (cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID; - cryptoInfo->mode <= LAST_MODE_OF_OPERATION; - cryptoInfo->mode++) - { - switch (cryptoInfo->mode) - { - case LRW: - case CBC: - case INNER_CBC: - case OUTER_CBC: - - // For LRW (deprecated/legacy), copy the tweak key - // For CBC (deprecated/legacy), copy the IV/whitening seed - memcpy (cryptoInfo->k2, dk, LEGACY_VOL_IV_SIZE); - primaryKeyOffset = LEGACY_VOL_IV_SIZE; - break; - - default: - primaryKeyOffset = 0; - } - - // Test all available encryption algorithms - for (cryptoInfo->ea = EAGetFirst (); - cryptoInfo->ea != 0; - cryptoInfo->ea = EAGetNext (cryptoInfo->ea)) - { - int blockSize; - - if (!EAIsModeSupported (cryptoInfo->ea, cryptoInfo->mode)) - continue; // This encryption algorithm has never been available with this mode of operation - - blockSize = CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea)); - - status = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks); - if (status == ERR_CIPHER_INIT_FAILURE) - goto err; - - // Init objects related to the mode of operation - - if (cryptoInfo->mode == XTS) - { - // Copy the secondary key (if cascade, multiple concatenated) - memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); - - // Secondary key schedule - if (!EAInitMode (cryptoInfo)) - { - status = ERR_MODE_INIT_FAILED; - goto err; - } - } - else if (cryptoInfo->mode == LRW - && (blockSize == 8 && !lrw64InitDone || blockSize == 16 && !lrw128InitDone)) - { - // Deprecated/legacy - - if (!EAInitMode (cryptoInfo)) - { - status = ERR_MODE_INIT_FAILED; - goto err; - } - - if (blockSize == 8) - lrw64InitDone = TRUE; - else if (blockSize == 16) - lrw128InitDone = TRUE; - } - - // Copy the header for decryption - memcpy (header, encryptedHeader, sizeof (header)); - - // Try to decrypt header - - DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); - - // Magic 'TRUE' - if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545) - continue; - - // Header version - headerVersion = GetHeaderField16 (header, TC_HEADER_OFFSET_VERSION); - - if (headerVersion > VOLUME_HEADER_VERSION) - { - status = ERR_NEW_VERSION_REQUIRED; - goto err; - } - - // Check CRC of the header fields - if (!ReadVolumeHeaderRecoveryMode - && headerVersion >= 4 - && GetHeaderField32 (header, TC_HEADER_OFFSET_HEADER_CRC) != GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) - continue; - - // Required program version - cryptoInfo->RequiredProgramVersion = GetHeaderField16 (header, TC_HEADER_OFFSET_REQUIRED_VERSION); - cryptoInfo->LegacyVolume = cryptoInfo->RequiredProgramVersion < 0x600; - - // Check CRC of the key set - if (!ReadVolumeHeaderRecoveryMode - && GetHeaderField32 (header, TC_HEADER_OFFSET_KEY_AREA_CRC) != GetCrc32 (header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE)) - continue; - - // Now we have the correct password, cipher, hash algorithm, and volume type - - // Check the version required to handle this volume - if (cryptoInfo->RequiredProgramVersion > VERSION_NUM) - { - status = ERR_NEW_VERSION_REQUIRED; - goto err; - } - - // Header version - cryptoInfo->HeaderVersion = headerVersion; - - // Volume creation time (legacy) - cryptoInfo->volume_creation_time = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_CREATION_TIME).Value; - - // Header creation time (legacy) - cryptoInfo->header_creation_time = GetHeaderField64 (header, TC_HEADER_OFFSET_MODIFICATION_TIME).Value; - - // Hidden volume size (if any) - cryptoInfo->hiddenVolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE).Value; - - // Hidden volume status - cryptoInfo->hiddenVolume = (cryptoInfo->hiddenVolumeSize != 0); - - // Volume size - cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_SIZE); - - // Encrypted area size and length - cryptoInfo->EncryptedAreaStart = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_START); - cryptoInfo->EncryptedAreaLength = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH); - - // Flags - cryptoInfo->HeaderFlags = GetHeaderField32 (header, TC_HEADER_OFFSET_FLAGS); - - // Preserve scheduled header keys if requested - if (retHeaderCryptoInfo) - { - if (retInfo == NULL) - { - cryptoInfo->pkcs5 = pkcs5_prf; - cryptoInfo->noIterations = keyInfo.noIterations; - goto ret; - } - - cryptoInfo = *retInfo = crypto_open (); - if (cryptoInfo == NULL) - { - status = ERR_OUTOFMEMORY; - goto err; - } - - memcpy (cryptoInfo, retHeaderCryptoInfo, sizeof (*cryptoInfo)); - } - - // Master key data - memcpy (keyInfo.master_keydata, header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE); - memcpy (cryptoInfo->master_keydata, keyInfo.master_keydata, MASTER_KEYDATA_SIZE); - - // PKCS #5 - memcpy (cryptoInfo->salt, keyInfo.salt, PKCS5_SALT_SIZE); - cryptoInfo->pkcs5 = pkcs5_prf; - cryptoInfo->noIterations = keyInfo.noIterations; - - // Init the cipher with the decrypted master key - status = EAInit (cryptoInfo->ea, keyInfo.master_keydata + primaryKeyOffset, cryptoInfo->ks); - if (status == ERR_CIPHER_INIT_FAILURE) - goto err; - - switch (cryptoInfo->mode) - { - case LRW: - case CBC: - case INNER_CBC: - case OUTER_CBC: - - // For LRW (deprecated/legacy), the tweak key - // For CBC (deprecated/legacy), the IV/whitening seed - memcpy (cryptoInfo->k2, keyInfo.master_keydata, LEGACY_VOL_IV_SIZE); - break; - - default: - // The secondary master key (if cascade, multiple concatenated) - memcpy (cryptoInfo->k2, keyInfo.master_keydata + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); - - } - - if (!EAInitMode (cryptoInfo)) - { - status = ERR_MODE_INIT_FAILED; - goto err; - } - - status = ERR_SUCCESS; - goto ret; - } - } - } - status = ERR_PASSWORD_WRONG; - -err: - if (cryptoInfo != retHeaderCryptoInfo) - { - crypto_close(cryptoInfo); - *retInfo = NULL; - } - -ret: - burn (&keyInfo, sizeof (keyInfo)); - burn (dk, sizeof(dk)); - -#ifndef DEVICE_DRIVER - VirtualUnlock (&keyInfo, sizeof (keyInfo)); - VirtualUnlock (&dk, sizeof (dk)); -#endif - - if (encryptionThreadCount > 1) - { - TC_WAIT_EVENT (noOutstandingWorkItemEvent); - - burn (keyDerivationWorkItems, sizeof (KeyDerivationWorkItem) * pkcs5PrfCount); - TCfree (keyDerivationWorkItems); - -#ifndef DEVICE_DRIVER - CloseHandle (keyDerivationCompletedEvent); - CloseHandle (noOutstandingWorkItemEvent); -#endif - } - - return status; -} - -#else // TC_WINDOWS_BOOT - -int ReadVolumeHeader (BOOL bBoot, char *header, Password *password, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo) -{ -#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE - char dk[32 * 2]; // 2 * 256-bit key - char masterKey[32 * 2]; -#else - char dk[32 * 2 * 3]; // 6 * 256-bit key - char masterKey[32 * 2 * 3]; -#endif - - PCRYPTO_INFO cryptoInfo; - int status; - - if (retHeaderCryptoInfo != NULL) - cryptoInfo = retHeaderCryptoInfo; - else - cryptoInfo = *retInfo = crypto_open (); - - // PKCS5 PRF - derive_key_ripemd160 (password->Text, (int) password->Length, header + HEADER_SALT_OFFSET, - PKCS5_SALT_SIZE, bBoot ? 1000 : 2000, dk, sizeof (dk)); - - // Mode of operation - cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID; - - // Test all available encryption algorithms - for (cryptoInfo->ea = EAGetFirst (); cryptoInfo->ea != 0; cryptoInfo->ea = EAGetNext (cryptoInfo->ea)) - { - status = EAInit (cryptoInfo->ea, dk, cryptoInfo->ks); - if (status == ERR_CIPHER_INIT_FAILURE) - goto err; - - // Secondary key schedule - EAInit (cryptoInfo->ea, dk + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2); - - // Try to decrypt header - DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); - - // Check magic 'TRUE' and CRC-32 of header fields and master keydata - if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545 - || (GetHeaderField16 (header, TC_HEADER_OFFSET_VERSION) >= 4 && GetHeaderField32 (header, TC_HEADER_OFFSET_HEADER_CRC) != GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) - || GetHeaderField32 (header, TC_HEADER_OFFSET_KEY_AREA_CRC) != GetCrc32 (header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE)) - { - EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); - continue; - } - - // Header decrypted - status = 0; - - // Hidden volume status - cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE); - cryptoInfo->hiddenVolume = (cryptoInfo->VolumeSize.LowPart != 0 || cryptoInfo->VolumeSize.HighPart != 0); - - // Volume size - cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_SIZE); - - // Encrypted area size and length - cryptoInfo->EncryptedAreaStart = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_START); - cryptoInfo->EncryptedAreaLength = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH); - - // Flags - cryptoInfo->HeaderFlags = GetHeaderField32 (header, TC_HEADER_OFFSET_FLAGS); - - memcpy (masterKey, header + HEADER_MASTER_KEYDATA_OFFSET, sizeof (masterKey)); - EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); - - if (retHeaderCryptoInfo) - goto ret; - - // Init the encryption algorithm with the decrypted master key - status = EAInit (cryptoInfo->ea, masterKey, cryptoInfo->ks); - if (status == ERR_CIPHER_INIT_FAILURE) - goto err; - - // The secondary master key (if cascade, multiple concatenated) - EAInit (cryptoInfo->ea, masterKey + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2); - goto ret; - } - - status = ERR_PASSWORD_WRONG; - -err: - if (cryptoInfo != retHeaderCryptoInfo) - { - crypto_close(cryptoInfo); - *retInfo = NULL; - } - -ret: - burn (dk, sizeof(dk)); - burn (masterKey, sizeof(masterKey)); - return status; -} - -#endif // TC_WINDOWS_BOOT - - -#if !defined (DEVICE_DRIVER) && !defined (TC_WINDOWS_BOOT) - -#ifdef VOLFORMAT -# include "../Format/TcFormat.h" -# include "Dlgcode.h" -#endif - -// Creates a volume header in memory -int CreateVolumeHeaderInMemory (BOOL bBoot, char *header, int ea, int mode, Password *password, - int pkcs5_prf, char *masterKeydata, PCRYPTO_INFO *retInfo, - unsigned __int64 volumeSize, unsigned __int64 hiddenVolumeSize, - unsigned __int64 encryptedAreaStart, unsigned __int64 encryptedAreaLength, uint16 requiredProgramVersion, uint32 headerFlags, BOOL bWipeMode) -{ - unsigned char *p = (unsigned char *) header; - static KEY_INFO keyInfo; - - int nUserKeyLen = password->Length; - PCRYPTO_INFO cryptoInfo = crypto_open (); - static char dk[MASTER_KEYDATA_SIZE]; - int x; - int retVal = 0; - int primaryKeyOffset; - - if (cryptoInfo == NULL) - return ERR_OUTOFMEMORY; - - memset (header, 0, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - - VirtualLock (&keyInfo, sizeof (keyInfo)); - VirtualLock (&dk, sizeof (dk)); - - /* Encryption setup */ - - if (masterKeydata == NULL) - { - // We have no master key data (creating a new volume) so we'll use the TrueCrypt RNG to generate them - - int bytesNeeded; - - switch (mode) - { - case LRW: - case CBC: - case INNER_CBC: - case OUTER_CBC: - - // Deprecated/legacy modes of operation - bytesNeeded = LEGACY_VOL_IV_SIZE + EAGetKeySize (ea); - - /* In fact, this should never be the case since new volumes are not supposed to use - any deprecated mode of operation. */ - return ERR_VOL_FORMAT_BAD; - - default: - bytesNeeded = EAGetKeySize (ea) * 2; // Size of primary + secondary key(s) - } - - if (!RandgetBytes (keyInfo.master_keydata, bytesNeeded, TRUE)) - return ERR_CIPHER_INIT_WEAK_KEY; - } - else - { - // We already have existing master key data (the header is being re-encrypted) - memcpy (keyInfo.master_keydata, masterKeydata, MASTER_KEYDATA_SIZE); - } - - // User key - memcpy (keyInfo.userKey, password->Text, nUserKeyLen); - keyInfo.keyLength = nUserKeyLen; - keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, bBoot); - - // User selected encryption algorithm - cryptoInfo->ea = ea; - - // Mode of operation - cryptoInfo->mode = mode; - - // Salt for header key derivation - if (!RandgetBytes (keyInfo.salt, PKCS5_SALT_SIZE, !bWipeMode)) - return ERR_CIPHER_INIT_WEAK_KEY; - - // PBKDF2 (PKCS5) is used to derive primary header key(s) and secondary header key(s) (XTS) from the password/keyfiles - switch (pkcs5_prf) - { - case SHA512: - derive_key_sha512 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - case SHA1: - // Deprecated/legacy - derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - case RIPEMD160: - derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - case WHIRLPOOL: - derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, - PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); - break; - - default: - // Unknown/wrong ID - TC_THROW_FATAL_EXCEPTION; - } - - /* Header setup */ - - // Salt - mputBytes (p, keyInfo.salt, PKCS5_SALT_SIZE); - - // Magic - mputLong (p, 0x54525545); - - // Header version - mputWord (p, VOLUME_HEADER_VERSION); - cryptoInfo->HeaderVersion = VOLUME_HEADER_VERSION; - - // Required program version to handle this volume - switch (mode) - { - case LRW: - // Deprecated/legacy - mputWord (p, 0x0410); - break; - case OUTER_CBC: - case INNER_CBC: - // Deprecated/legacy - mputWord (p, 0x0300); - break; - case CBC: - // Deprecated/legacy - mputWord (p, hiddenVolumeSize > 0 ? 0x0300 : 0x0100); - break; - default: - mputWord (p, requiredProgramVersion != 0 ? requiredProgramVersion : TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION); - } - - // CRC of the master key data - x = GetCrc32(keyInfo.master_keydata, MASTER_KEYDATA_SIZE); - mputLong (p, x); - - // Reserved fields - p += 2 * 8; - - // Size of hidden volume (if any) - cryptoInfo->hiddenVolumeSize = hiddenVolumeSize; - mputInt64 (p, cryptoInfo->hiddenVolumeSize); - - cryptoInfo->hiddenVolume = cryptoInfo->hiddenVolumeSize != 0; - - // Volume size - cryptoInfo->VolumeSize.Value = volumeSize; - mputInt64 (p, volumeSize); - - // Encrypted area start - cryptoInfo->EncryptedAreaStart.Value = encryptedAreaStart; - mputInt64 (p, encryptedAreaStart); - - // Encrypted area size - cryptoInfo->EncryptedAreaLength.Value = encryptedAreaLength; - mputInt64 (p, encryptedAreaLength); - - // Flags - cryptoInfo->HeaderFlags = headerFlags; - mputLong (p, headerFlags); - - // CRC of the header fields - x = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); - p = header + TC_HEADER_OFFSET_HEADER_CRC; - mputLong (p, x); - - // The master key data - memcpy (header + HEADER_MASTER_KEYDATA_OFFSET, keyInfo.master_keydata, MASTER_KEYDATA_SIZE); - - - /* Header encryption */ - - switch (mode) - { - case LRW: - case CBC: - case INNER_CBC: - case OUTER_CBC: - - // For LRW (deprecated/legacy), the tweak key - // For CBC (deprecated/legacy), the IV/whitening seed - memcpy (cryptoInfo->k2, dk, LEGACY_VOL_IV_SIZE); - primaryKeyOffset = LEGACY_VOL_IV_SIZE; - break; - - default: - // The secondary key (if cascade, multiple concatenated) - memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); - primaryKeyOffset = 0; - } - - retVal = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks); - if (retVal != ERR_SUCCESS) - return retVal; - - // Mode of operation - if (!EAInitMode (cryptoInfo)) - return ERR_OUTOFMEMORY; - - - // Encrypt the entire header (except the salt) - EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, - HEADER_ENCRYPTED_DATA_SIZE, - cryptoInfo); - - - /* cryptoInfo setup for further use (disk format) */ - - // Init with the master key(s) - retVal = EAInit (cryptoInfo->ea, keyInfo.master_keydata + primaryKeyOffset, cryptoInfo->ks); - if (retVal != ERR_SUCCESS) - return retVal; - - memcpy (cryptoInfo->master_keydata, keyInfo.master_keydata, MASTER_KEYDATA_SIZE); - - switch (cryptoInfo->mode) - { - case LRW: - case CBC: - case INNER_CBC: - case OUTER_CBC: - - // For LRW (deprecated/legacy), the tweak key - // For CBC (deprecated/legacy), the IV/whitening seed - memcpy (cryptoInfo->k2, keyInfo.master_keydata, LEGACY_VOL_IV_SIZE); - break; - - default: - // The secondary master key (if cascade, multiple concatenated) - memcpy (cryptoInfo->k2, keyInfo.master_keydata + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); - } - - // Mode of operation - if (!EAInitMode (cryptoInfo)) - return ERR_OUTOFMEMORY; - - -#ifdef VOLFORMAT - if (showKeys && !bInPlaceEncNonSys) - { - BOOL dots3 = FALSE; - int i, j; - - j = EAGetKeySize (ea); - - if (j > NBR_KEY_BYTES_TO_DISPLAY) - { - dots3 = TRUE; - j = NBR_KEY_BYTES_TO_DISPLAY; - } - - MasterKeyGUIView[0] = 0; - for (i = 0; i < j; i++) - { - char tmp2[8] = {0}; - sprintf (tmp2, "%02X", (int) (unsigned char) keyInfo.master_keydata[i + primaryKeyOffset]); - strcat (MasterKeyGUIView, tmp2); - } - - if (dots3) - { - strcat (MasterKeyGUIView, "..."); - } - - SendMessage (hMasterKey, WM_SETTEXT, 0, (LPARAM) MasterKeyGUIView); - - HeaderKeyGUIView[0] = 0; - for (i = 0; i < NBR_KEY_BYTES_TO_DISPLAY; i++) - { - char tmp2[8]; - sprintf (tmp2, "%02X", (int) (unsigned char) dk[primaryKeyOffset + i]); - strcat (HeaderKeyGUIView, tmp2); - } - - if (dots3) - { - strcat (HeaderKeyGUIView, "..."); - } - - SendMessage (hHeaderKey, WM_SETTEXT, 0, (LPARAM) HeaderKeyGUIView); - } -#endif // #ifdef VOLFORMAT - - burn (dk, sizeof(dk)); - burn (&keyInfo, sizeof (keyInfo)); - - *retInfo = cryptoInfo; - return 0; -} - - -// Writes randomly generated data to unused/reserved header areas. -// When bPrimaryOnly is TRUE, then only the primary header area (not the backup header area) is filled with random data. -// When bBackupOnly is TRUE, only the backup header area (not the primary header area) is filled with random data. -int WriteRandomDataToReservedHeaderAreas (HANDLE dev, CRYPTO_INFO *cryptoInfo, uint64 dataAreaSize, BOOL bPrimaryOnly, BOOL bBackupOnly) -{ - char temporaryKey[MASTER_KEYDATA_SIZE]; - char originalK2[MASTER_KEYDATA_SIZE]; - - byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - - LARGE_INTEGER offset; - int nStatus = ERR_SUCCESS; - DWORD dwError; - BOOL backupHeaders = bBackupOnly; - - if (bPrimaryOnly && bBackupOnly) - TC_THROW_FATAL_EXCEPTION; - - memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2)); - - while (TRUE) - { - // Temporary keys - if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE) - || !RandgetBytes (cryptoInfo->k2, sizeof (cryptoInfo->k2), FALSE)) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto final_seq; - } - - nStatus = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); - if (nStatus != ERR_SUCCESS) - goto final_seq; - - if (!EAInitMode (cryptoInfo)) - { - nStatus = ERR_MODE_INIT_FAILED; - goto final_seq; - } - - offset.QuadPart = backupHeaders ? dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; - offset.QuadPart += TC_VOLUME_HEADER_EFFECTIVE_SIZE; - - if (!SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto final_seq; - } - - EncryptBuffer (buf, sizeof (buf), cryptoInfo); - - if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR) - { - nStatus = ERR_OS_ERROR; - goto final_seq; - } - - if (backupHeaders || bPrimaryOnly) - break; - - backupHeaders = TRUE; - } - - memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2)); - - nStatus = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks); - if (nStatus != ERR_SUCCESS) - goto final_seq; - - if (!EAInitMode (cryptoInfo)) - { - nStatus = ERR_MODE_INIT_FAILED; - goto final_seq; - } - -final_seq: - - dwError = GetLastError(); - - burn (temporaryKey, sizeof (temporaryKey)); - burn (originalK2, sizeof (originalK2)); - - if (nStatus != ERR_SUCCESS) - SetLastError (dwError); - - return nStatus; -} - -#endif // !defined (DEVICE_DRIVER) && !defined (TC_WINDOWS_BOOT) +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#ifndef TC_WINDOWS_BOOT +#include +#include +#include +#include +#include "EncryptionThreadPool.h" +#endif + +#include +#include +#include + +#ifndef DEVICE_DRIVER +#include "Random.h" +#endif + +#include "Crc.h" +#include "Crypto.h" +#include "Endian.h" +#include "Volumes.h" +#include "Pkcs5.h" + + +/* Volume header v4 structure (used since TrueCrypt 6.0): */ +// +// Offset Length Description +// ------------------------------------------ +// Unencrypted: +// 0 64 Salt +// Encrypted: +// 64 4 ASCII string 'TRUE' +// 68 2 Header version +// 70 2 Required program version +// 72 4 CRC-32 checksum of the (decrypted) bytes 256-511 +// 76 8 Reserved (set to zero) +// 84 8 Reserved (set to zero) +// 92 8 Size of hidden volume in bytes (0 = normal volume) +// 100 8 Size of the volume in bytes (identical with field 92 for hidden volumes, valid if field 70 >= 0x600 or flag bit 0 == 1) +// 108 8 Byte offset of the start of the master key scope (valid if field 70 >= 0x600 or flag bit 0 == 1) +// 116 8 Size of the encrypted area within the master key scope (valid if field 70 >= 0x600 or flag bit 0 == 1) +// 124 4 Flags: bit 0 set = system encryption; bit 1 set = non-system in-place encryption, bits 2-31 are reserved +// 128 124 Reserved (set to zero) +// 252 4 CRC-32 checksum of the (decrypted) bytes 64-251 +// 256 256 Concatenated primary master key(s) and secondary master key(s) (XTS mode) + + +/* Deprecated/legacy volume header v3 structure (used by TrueCrypt 5.x): */ +// +// Offset Length Description +// ------------------------------------------ +// Unencrypted: +// 0 64 Salt +// Encrypted: +// 64 4 ASCII string 'TRUE' +// 68 2 Header version +// 70 2 Required program version +// 72 4 CRC-32 checksum of the (decrypted) bytes 256-511 +// 76 8 Volume creation time +// 84 8 Header creation time +// 92 8 Size of hidden volume in bytes (0 = normal volume) +// 100 8 Size of the volume in bytes (identical with field 92 for hidden volumes) +// 108 8 Start byte offset of the encrypted area of the volume +// 116 8 Size of the encrypted area of the volume in bytes +// 124 132 Reserved (set to zero) +// 256 256 Concatenated primary master key(s) and secondary master key(s) (XTS mode) + + +/* Deprecated/legacy volume header v2 structure (used before TrueCrypt 5.0): */ +// +// Offset Length Description +// ------------------------------------------ +// Unencrypted: +// 0 64 Salt +// Encrypted: +// 64 4 ASCII string 'TRUE' +// 68 2 Header version +// 70 2 Required program version +// 72 4 CRC-32 checksum of the (decrypted) bytes 256-511 +// 76 8 Volume creation time +// 84 8 Header creation time +// 92 8 Size of hidden volume in bytes (0 = normal volume) +// 100 156 Reserved (set to zero) +// 256 32 For LRW (deprecated/legacy), secondary key +// For CBC (deprecated/legacy), data used to generate IV and whitening values +// 288 224 Master key(s) + + + +uint16 GetHeaderField16 (byte *header, int offset) +{ + return BE16 (*(uint16 *) (header + offset)); +} + + +uint32 GetHeaderField32 (byte *header, int offset) +{ + return BE32 (*(uint32 *) (header + offset)); +} + + +UINT64_STRUCT GetHeaderField64 (byte *header, int offset) +{ + UINT64_STRUCT uint64Struct; + +#ifndef TC_NO_COMPILER_INT64 + uint64Struct.Value = BE64 (*(uint64 *) (header + offset)); +#else + uint64Struct.HighPart = BE32 (*(uint32 *) (header + offset)); + uint64Struct.LowPart = BE32 (*(uint32 *) (header + offset + 4)); +#endif + return uint64Struct; +} + + +#ifndef TC_WINDOWS_BOOT + +typedef struct +{ + char DerivedKey[MASTER_KEYDATA_SIZE]; + BOOL Free; + LONG KeyReady; + int Pkcs5Prf; +} KeyDerivationWorkItem; + + +BOOL ReadVolumeHeaderRecoveryMode = FALSE; + +int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo) +{ + char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + KEY_INFO keyInfo; + PCRYPTO_INFO cryptoInfo; + char dk[MASTER_KEYDATA_SIZE]; + int enqPkcs5Prf, pkcs5_prf; + uint16 headerVersion; + int status = ERR_PARAMETER_INCORRECT; + int primaryKeyOffset; + + TC_EVENT keyDerivationCompletedEvent; + TC_EVENT noOutstandingWorkItemEvent; + KeyDerivationWorkItem *keyDerivationWorkItems; + KeyDerivationWorkItem *item; + int pkcs5PrfCount = LAST_PRF_ID - FIRST_PRF_ID + 1; + size_t encryptionThreadCount = GetEncryptionThreadCount(); + size_t queuedWorkItems = 0; + LONG outstandingWorkItemCount = 0; + int i; + + if (retHeaderCryptoInfo != NULL) + { + cryptoInfo = retHeaderCryptoInfo; + } + else + { + cryptoInfo = *retInfo = crypto_open (); + if (cryptoInfo == NULL) + return ERR_OUTOFMEMORY; + } + + if (encryptionThreadCount > 1) + { + keyDerivationWorkItems = TCalloc (sizeof (KeyDerivationWorkItem) * pkcs5PrfCount); + if (!keyDerivationWorkItems) + return ERR_OUTOFMEMORY; + + for (i = 0; i < pkcs5PrfCount; ++i) + keyDerivationWorkItems[i].Free = TRUE; + +#ifdef DEVICE_DRIVER + KeInitializeEvent (&keyDerivationCompletedEvent, SynchronizationEvent, FALSE); + KeInitializeEvent (&noOutstandingWorkItemEvent, SynchronizationEvent, TRUE); +#else + keyDerivationCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + if (!keyDerivationCompletedEvent) + { + TCfree (keyDerivationWorkItems); + return ERR_OUTOFMEMORY; + } + + noOutstandingWorkItemEvent = CreateEvent (NULL, FALSE, TRUE, NULL); + if (!noOutstandingWorkItemEvent) + { + CloseHandle (keyDerivationCompletedEvent); + TCfree (keyDerivationWorkItems); + return ERR_OUTOFMEMORY; + } +#endif + } + +#ifndef DEVICE_DRIVER + VirtualLock (&keyInfo, sizeof (keyInfo)); + VirtualLock (&dk, sizeof (dk)); +#endif + + crypto_loadkey (&keyInfo, password->Text, (int) password->Length); + + // PKCS5 is used to derive the primary header key(s) and secondary header key(s) (XTS mode) from the password + memcpy (keyInfo.salt, encryptedHeader + HEADER_SALT_OFFSET, PKCS5_SALT_SIZE); + + // Test all available PKCS5 PRFs + for (enqPkcs5Prf = FIRST_PRF_ID; enqPkcs5Prf <= LAST_PRF_ID || queuedWorkItems > 0; ++enqPkcs5Prf) + { + BOOL lrw64InitDone = FALSE; // Deprecated/legacy + BOOL lrw128InitDone = FALSE; // Deprecated/legacy + + if (encryptionThreadCount > 1) + { + // Enqueue key derivation on thread pool + if (queuedWorkItems < encryptionThreadCount && enqPkcs5Prf <= LAST_PRF_ID) + { + for (i = 0; i < pkcs5PrfCount; ++i) + { + item = &keyDerivationWorkItems[i]; + if (item->Free) + { + item->Free = FALSE; + item->KeyReady = FALSE; + item->Pkcs5Prf = enqPkcs5Prf; + + EncryptionThreadPoolBeginKeyDerivation (&keyDerivationCompletedEvent, &noOutstandingWorkItemEvent, + &item->KeyReady, &outstandingWorkItemCount, enqPkcs5Prf, keyInfo.userKey, + keyInfo.keyLength, keyInfo.salt, get_pkcs5_iteration_count (enqPkcs5Prf, bBoot), item->DerivedKey); + + ++queuedWorkItems; + break; + } + } + + if (enqPkcs5Prf < LAST_PRF_ID) + continue; + } + else + --enqPkcs5Prf; + + // Wait for completion of a key derivation + while (queuedWorkItems > 0) + { + for (i = 0; i < pkcs5PrfCount; ++i) + { + item = &keyDerivationWorkItems[i]; + if (!item->Free && InterlockedExchangeAdd (&item->KeyReady, 0) == TRUE) + { + pkcs5_prf = item->Pkcs5Prf; + keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, bBoot); + memcpy (dk, item->DerivedKey, sizeof (dk)); + + item->Free = TRUE; + --queuedWorkItems; + goto KeyReady; + } + } + + if (queuedWorkItems > 0) + TC_WAIT_EVENT (keyDerivationCompletedEvent); + } + continue; +KeyReady: ; + } + else + { + pkcs5_prf = enqPkcs5Prf; + keyInfo.noIterations = get_pkcs5_iteration_count (enqPkcs5Prf, bBoot); + + switch (pkcs5_prf) + { + case RIPEMD160: + derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + case SHA512: + derive_key_sha512 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + case SHA1: + // Deprecated/legacy + derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + case WHIRLPOOL: + derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + } + + // Test all available modes of operation + for (cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID; + cryptoInfo->mode <= LAST_MODE_OF_OPERATION; + cryptoInfo->mode++) + { + switch (cryptoInfo->mode) + { + case LRW: + case CBC: + case INNER_CBC: + case OUTER_CBC: + + // For LRW (deprecated/legacy), copy the tweak key + // For CBC (deprecated/legacy), copy the IV/whitening seed + memcpy (cryptoInfo->k2, dk, LEGACY_VOL_IV_SIZE); + primaryKeyOffset = LEGACY_VOL_IV_SIZE; + break; + + default: + primaryKeyOffset = 0; + } + + // Test all available encryption algorithms + for (cryptoInfo->ea = EAGetFirst (); + cryptoInfo->ea != 0; + cryptoInfo->ea = EAGetNext (cryptoInfo->ea)) + { + int blockSize; + + if (!EAIsModeSupported (cryptoInfo->ea, cryptoInfo->mode)) + continue; // This encryption algorithm has never been available with this mode of operation + + blockSize = CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea)); + + status = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks); + if (status == ERR_CIPHER_INIT_FAILURE) + goto err; + + // Init objects related to the mode of operation + + if (cryptoInfo->mode == XTS) + { + // Copy the secondary key (if cascade, multiple concatenated) + memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); + + // Secondary key schedule + if (!EAInitMode (cryptoInfo)) + { + status = ERR_MODE_INIT_FAILED; + goto err; + } + } + else if (cryptoInfo->mode == LRW + && (blockSize == 8 && !lrw64InitDone || blockSize == 16 && !lrw128InitDone)) + { + // Deprecated/legacy + + if (!EAInitMode (cryptoInfo)) + { + status = ERR_MODE_INIT_FAILED; + goto err; + } + + if (blockSize == 8) + lrw64InitDone = TRUE; + else if (blockSize == 16) + lrw128InitDone = TRUE; + } + + // Copy the header for decryption + memcpy (header, encryptedHeader, sizeof (header)); + + // Try to decrypt header + + DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); + + // Magic 'TRUE' + if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545) + continue; + + // Header version + headerVersion = GetHeaderField16 (header, TC_HEADER_OFFSET_VERSION); + + if (headerVersion > VOLUME_HEADER_VERSION) + { + status = ERR_NEW_VERSION_REQUIRED; + goto err; + } + + // Check CRC of the header fields + if (!ReadVolumeHeaderRecoveryMode + && headerVersion >= 4 + && GetHeaderField32 (header, TC_HEADER_OFFSET_HEADER_CRC) != GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) + continue; + + // Required program version + cryptoInfo->RequiredProgramVersion = GetHeaderField16 (header, TC_HEADER_OFFSET_REQUIRED_VERSION); + cryptoInfo->LegacyVolume = cryptoInfo->RequiredProgramVersion < 0x600; + + // Check CRC of the key set + if (!ReadVolumeHeaderRecoveryMode + && GetHeaderField32 (header, TC_HEADER_OFFSET_KEY_AREA_CRC) != GetCrc32 (header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE)) + continue; + + // Now we have the correct password, cipher, hash algorithm, and volume type + + // Check the version required to handle this volume + if (cryptoInfo->RequiredProgramVersion > VERSION_NUM) + { + status = ERR_NEW_VERSION_REQUIRED; + goto err; + } + + // Header version + cryptoInfo->HeaderVersion = headerVersion; + + // Volume creation time (legacy) + cryptoInfo->volume_creation_time = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_CREATION_TIME).Value; + + // Header creation time (legacy) + cryptoInfo->header_creation_time = GetHeaderField64 (header, TC_HEADER_OFFSET_MODIFICATION_TIME).Value; + + // Hidden volume size (if any) + cryptoInfo->hiddenVolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE).Value; + + // Hidden volume status + cryptoInfo->hiddenVolume = (cryptoInfo->hiddenVolumeSize != 0); + + // Volume size + cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_SIZE); + + // Encrypted area size and length + cryptoInfo->EncryptedAreaStart = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_START); + cryptoInfo->EncryptedAreaLength = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH); + + // Flags + cryptoInfo->HeaderFlags = GetHeaderField32 (header, TC_HEADER_OFFSET_FLAGS); + + // Preserve scheduled header keys if requested + if (retHeaderCryptoInfo) + { + if (retInfo == NULL) + { + cryptoInfo->pkcs5 = pkcs5_prf; + cryptoInfo->noIterations = keyInfo.noIterations; + goto ret; + } + + cryptoInfo = *retInfo = crypto_open (); + if (cryptoInfo == NULL) + { + status = ERR_OUTOFMEMORY; + goto err; + } + + memcpy (cryptoInfo, retHeaderCryptoInfo, sizeof (*cryptoInfo)); + } + + // Master key data + memcpy (keyInfo.master_keydata, header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE); + memcpy (cryptoInfo->master_keydata, keyInfo.master_keydata, MASTER_KEYDATA_SIZE); + + // PKCS #5 + memcpy (cryptoInfo->salt, keyInfo.salt, PKCS5_SALT_SIZE); + cryptoInfo->pkcs5 = pkcs5_prf; + cryptoInfo->noIterations = keyInfo.noIterations; + + // Init the cipher with the decrypted master key + status = EAInit (cryptoInfo->ea, keyInfo.master_keydata + primaryKeyOffset, cryptoInfo->ks); + if (status == ERR_CIPHER_INIT_FAILURE) + goto err; + + switch (cryptoInfo->mode) + { + case LRW: + case CBC: + case INNER_CBC: + case OUTER_CBC: + + // For LRW (deprecated/legacy), the tweak key + // For CBC (deprecated/legacy), the IV/whitening seed + memcpy (cryptoInfo->k2, keyInfo.master_keydata, LEGACY_VOL_IV_SIZE); + break; + + default: + // The secondary master key (if cascade, multiple concatenated) + memcpy (cryptoInfo->k2, keyInfo.master_keydata + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); + + } + + if (!EAInitMode (cryptoInfo)) + { + status = ERR_MODE_INIT_FAILED; + goto err; + } + + status = ERR_SUCCESS; + goto ret; + } + } + } + status = ERR_PASSWORD_WRONG; + +err: + if (cryptoInfo != retHeaderCryptoInfo) + { + crypto_close(cryptoInfo); + *retInfo = NULL; + } + +ret: + burn (&keyInfo, sizeof (keyInfo)); + burn (dk, sizeof(dk)); + +#ifndef DEVICE_DRIVER + VirtualUnlock (&keyInfo, sizeof (keyInfo)); + VirtualUnlock (&dk, sizeof (dk)); +#endif + + if (encryptionThreadCount > 1) + { + TC_WAIT_EVENT (noOutstandingWorkItemEvent); + + burn (keyDerivationWorkItems, sizeof (KeyDerivationWorkItem) * pkcs5PrfCount); + TCfree (keyDerivationWorkItems); + +#ifndef DEVICE_DRIVER + CloseHandle (keyDerivationCompletedEvent); + CloseHandle (noOutstandingWorkItemEvent); +#endif + } + + return status; +} + +#else // TC_WINDOWS_BOOT + +int ReadVolumeHeader (BOOL bBoot, char *header, Password *password, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo) +{ +#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + char dk[32 * 2]; // 2 * 256-bit key + char masterKey[32 * 2]; +#else + char dk[32 * 2 * 3]; // 6 * 256-bit key + char masterKey[32 * 2 * 3]; +#endif + + PCRYPTO_INFO cryptoInfo; + int status; + + if (retHeaderCryptoInfo != NULL) + cryptoInfo = retHeaderCryptoInfo; + else + cryptoInfo = *retInfo = crypto_open (); + + // PKCS5 PRF + derive_key_ripemd160 (password->Text, (int) password->Length, header + HEADER_SALT_OFFSET, + PKCS5_SALT_SIZE, bBoot ? 1000 : 2000, dk, sizeof (dk)); + + // Mode of operation + cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID; + + // Test all available encryption algorithms + for (cryptoInfo->ea = EAGetFirst (); cryptoInfo->ea != 0; cryptoInfo->ea = EAGetNext (cryptoInfo->ea)) + { + status = EAInit (cryptoInfo->ea, dk, cryptoInfo->ks); + if (status == ERR_CIPHER_INIT_FAILURE) + goto err; + + // Secondary key schedule + EAInit (cryptoInfo->ea, dk + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2); + + // Try to decrypt header + DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); + + // Check magic 'TRUE' and CRC-32 of header fields and master keydata + if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545 + || (GetHeaderField16 (header, TC_HEADER_OFFSET_VERSION) >= 4 && GetHeaderField32 (header, TC_HEADER_OFFSET_HEADER_CRC) != GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) + || GetHeaderField32 (header, TC_HEADER_OFFSET_KEY_AREA_CRC) != GetCrc32 (header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE)) + { + EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); + continue; + } + + // Header decrypted + status = 0; + + // Hidden volume status + cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE); + cryptoInfo->hiddenVolume = (cryptoInfo->VolumeSize.LowPart != 0 || cryptoInfo->VolumeSize.HighPart != 0); + + // Volume size + cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_SIZE); + + // Encrypted area size and length + cryptoInfo->EncryptedAreaStart = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_START); + cryptoInfo->EncryptedAreaLength = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH); + + // Flags + cryptoInfo->HeaderFlags = GetHeaderField32 (header, TC_HEADER_OFFSET_FLAGS); + + memcpy (masterKey, header + HEADER_MASTER_KEYDATA_OFFSET, sizeof (masterKey)); + EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo); + + if (retHeaderCryptoInfo) + goto ret; + + // Init the encryption algorithm with the decrypted master key + status = EAInit (cryptoInfo->ea, masterKey, cryptoInfo->ks); + if (status == ERR_CIPHER_INIT_FAILURE) + goto err; + + // The secondary master key (if cascade, multiple concatenated) + EAInit (cryptoInfo->ea, masterKey + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2); + goto ret; + } + + status = ERR_PASSWORD_WRONG; + +err: + if (cryptoInfo != retHeaderCryptoInfo) + { + crypto_close(cryptoInfo); + *retInfo = NULL; + } + +ret: + burn (dk, sizeof(dk)); + burn (masterKey, sizeof(masterKey)); + return status; +} + +#endif // TC_WINDOWS_BOOT + + +#if !defined (DEVICE_DRIVER) && !defined (TC_WINDOWS_BOOT) + +#ifdef VOLFORMAT +# include "../Format/TcFormat.h" +# include "Dlgcode.h" +#endif + +// Creates a volume header in memory +int CreateVolumeHeaderInMemory (BOOL bBoot, char *header, int ea, int mode, Password *password, + int pkcs5_prf, char *masterKeydata, PCRYPTO_INFO *retInfo, + unsigned __int64 volumeSize, unsigned __int64 hiddenVolumeSize, + unsigned __int64 encryptedAreaStart, unsigned __int64 encryptedAreaLength, uint16 requiredProgramVersion, uint32 headerFlags, BOOL bWipeMode) +{ + unsigned char *p = (unsigned char *) header; + static KEY_INFO keyInfo; + + int nUserKeyLen = password->Length; + PCRYPTO_INFO cryptoInfo = crypto_open (); + static char dk[MASTER_KEYDATA_SIZE]; + int x; + int retVal = 0; + int primaryKeyOffset; + + if (cryptoInfo == NULL) + return ERR_OUTOFMEMORY; + + memset (header, 0, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + + VirtualLock (&keyInfo, sizeof (keyInfo)); + VirtualLock (&dk, sizeof (dk)); + + /* Encryption setup */ + + if (masterKeydata == NULL) + { + // We have no master key data (creating a new volume) so we'll use the TrueCrypt RNG to generate them + + int bytesNeeded; + + switch (mode) + { + case LRW: + case CBC: + case INNER_CBC: + case OUTER_CBC: + + // Deprecated/legacy modes of operation + bytesNeeded = LEGACY_VOL_IV_SIZE + EAGetKeySize (ea); + + /* In fact, this should never be the case since new volumes are not supposed to use + any deprecated mode of operation. */ + return ERR_VOL_FORMAT_BAD; + + default: + bytesNeeded = EAGetKeySize (ea) * 2; // Size of primary + secondary key(s) + } + + if (!RandgetBytes (keyInfo.master_keydata, bytesNeeded, TRUE)) + return ERR_CIPHER_INIT_WEAK_KEY; + } + else + { + // We already have existing master key data (the header is being re-encrypted) + memcpy (keyInfo.master_keydata, masterKeydata, MASTER_KEYDATA_SIZE); + } + + // User key + memcpy (keyInfo.userKey, password->Text, nUserKeyLen); + keyInfo.keyLength = nUserKeyLen; + keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, bBoot); + + // User selected encryption algorithm + cryptoInfo->ea = ea; + + // Mode of operation + cryptoInfo->mode = mode; + + // Salt for header key derivation + if (!RandgetBytes (keyInfo.salt, PKCS5_SALT_SIZE, !bWipeMode)) + return ERR_CIPHER_INIT_WEAK_KEY; + + // PBKDF2 (PKCS5) is used to derive primary header key(s) and secondary header key(s) (XTS) from the password/keyfiles + switch (pkcs5_prf) + { + case SHA512: + derive_key_sha512 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + case SHA1: + // Deprecated/legacy + derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + case RIPEMD160: + derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + case WHIRLPOOL: + derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize()); + break; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + + /* Header setup */ + + // Salt + mputBytes (p, keyInfo.salt, PKCS5_SALT_SIZE); + + // Magic + mputLong (p, 0x54525545); + + // Header version + mputWord (p, VOLUME_HEADER_VERSION); + cryptoInfo->HeaderVersion = VOLUME_HEADER_VERSION; + + // Required program version to handle this volume + switch (mode) + { + case LRW: + // Deprecated/legacy + mputWord (p, 0x0410); + break; + case OUTER_CBC: + case INNER_CBC: + // Deprecated/legacy + mputWord (p, 0x0300); + break; + case CBC: + // Deprecated/legacy + mputWord (p, hiddenVolumeSize > 0 ? 0x0300 : 0x0100); + break; + default: + mputWord (p, requiredProgramVersion != 0 ? requiredProgramVersion : TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION); + } + + // CRC of the master key data + x = GetCrc32(keyInfo.master_keydata, MASTER_KEYDATA_SIZE); + mputLong (p, x); + + // Reserved fields + p += 2 * 8; + + // Size of hidden volume (if any) + cryptoInfo->hiddenVolumeSize = hiddenVolumeSize; + mputInt64 (p, cryptoInfo->hiddenVolumeSize); + + cryptoInfo->hiddenVolume = cryptoInfo->hiddenVolumeSize != 0; + + // Volume size + cryptoInfo->VolumeSize.Value = volumeSize; + mputInt64 (p, volumeSize); + + // Encrypted area start + cryptoInfo->EncryptedAreaStart.Value = encryptedAreaStart; + mputInt64 (p, encryptedAreaStart); + + // Encrypted area size + cryptoInfo->EncryptedAreaLength.Value = encryptedAreaLength; + mputInt64 (p, encryptedAreaLength); + + // Flags + cryptoInfo->HeaderFlags = headerFlags; + mputLong (p, headerFlags); + + // CRC of the header fields + x = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); + p = header + TC_HEADER_OFFSET_HEADER_CRC; + mputLong (p, x); + + // The master key data + memcpy (header + HEADER_MASTER_KEYDATA_OFFSET, keyInfo.master_keydata, MASTER_KEYDATA_SIZE); + + + /* Header encryption */ + + switch (mode) + { + case LRW: + case CBC: + case INNER_CBC: + case OUTER_CBC: + + // For LRW (deprecated/legacy), the tweak key + // For CBC (deprecated/legacy), the IV/whitening seed + memcpy (cryptoInfo->k2, dk, LEGACY_VOL_IV_SIZE); + primaryKeyOffset = LEGACY_VOL_IV_SIZE; + break; + + default: + // The secondary key (if cascade, multiple concatenated) + memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); + primaryKeyOffset = 0; + } + + retVal = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks); + if (retVal != ERR_SUCCESS) + return retVal; + + // Mode of operation + if (!EAInitMode (cryptoInfo)) + return ERR_OUTOFMEMORY; + + + // Encrypt the entire header (except the salt) + EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, + HEADER_ENCRYPTED_DATA_SIZE, + cryptoInfo); + + + /* cryptoInfo setup for further use (disk format) */ + + // Init with the master key(s) + retVal = EAInit (cryptoInfo->ea, keyInfo.master_keydata + primaryKeyOffset, cryptoInfo->ks); + if (retVal != ERR_SUCCESS) + return retVal; + + memcpy (cryptoInfo->master_keydata, keyInfo.master_keydata, MASTER_KEYDATA_SIZE); + + switch (cryptoInfo->mode) + { + case LRW: + case CBC: + case INNER_CBC: + case OUTER_CBC: + + // For LRW (deprecated/legacy), the tweak key + // For CBC (deprecated/legacy), the IV/whitening seed + memcpy (cryptoInfo->k2, keyInfo.master_keydata, LEGACY_VOL_IV_SIZE); + break; + + default: + // The secondary master key (if cascade, multiple concatenated) + memcpy (cryptoInfo->k2, keyInfo.master_keydata + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); + } + + // Mode of operation + if (!EAInitMode (cryptoInfo)) + return ERR_OUTOFMEMORY; + + +#ifdef VOLFORMAT + if (showKeys && !bInPlaceEncNonSys) + { + BOOL dots3 = FALSE; + int i, j; + + j = EAGetKeySize (ea); + + if (j > NBR_KEY_BYTES_TO_DISPLAY) + { + dots3 = TRUE; + j = NBR_KEY_BYTES_TO_DISPLAY; + } + + MasterKeyGUIView[0] = 0; + for (i = 0; i < j; i++) + { + char tmp2[8] = {0}; + sprintf (tmp2, "%02X", (int) (unsigned char) keyInfo.master_keydata[i + primaryKeyOffset]); + strcat (MasterKeyGUIView, tmp2); + } + + if (dots3) + { + strcat (MasterKeyGUIView, "..."); + } + + SendMessage (hMasterKey, WM_SETTEXT, 0, (LPARAM) MasterKeyGUIView); + + HeaderKeyGUIView[0] = 0; + for (i = 0; i < NBR_KEY_BYTES_TO_DISPLAY; i++) + { + char tmp2[8]; + sprintf (tmp2, "%02X", (int) (unsigned char) dk[primaryKeyOffset + i]); + strcat (HeaderKeyGUIView, tmp2); + } + + if (dots3) + { + strcat (HeaderKeyGUIView, "..."); + } + + SendMessage (hHeaderKey, WM_SETTEXT, 0, (LPARAM) HeaderKeyGUIView); + } +#endif // #ifdef VOLFORMAT + + burn (dk, sizeof(dk)); + burn (&keyInfo, sizeof (keyInfo)); + + *retInfo = cryptoInfo; + return 0; +} + + +// Writes randomly generated data to unused/reserved header areas. +// When bPrimaryOnly is TRUE, then only the primary header area (not the backup header area) is filled with random data. +// When bBackupOnly is TRUE, only the backup header area (not the primary header area) is filled with random data. +int WriteRandomDataToReservedHeaderAreas (HANDLE dev, CRYPTO_INFO *cryptoInfo, uint64 dataAreaSize, BOOL bPrimaryOnly, BOOL bBackupOnly) +{ + char temporaryKey[MASTER_KEYDATA_SIZE]; + char originalK2[MASTER_KEYDATA_SIZE]; + + byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + + LARGE_INTEGER offset; + int nStatus = ERR_SUCCESS; + DWORD dwError; + BOOL backupHeaders = bBackupOnly; + + if (bPrimaryOnly && bBackupOnly) + TC_THROW_FATAL_EXCEPTION; + + memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2)); + + while (TRUE) + { + // Temporary keys + if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE) + || !RandgetBytes (cryptoInfo->k2, sizeof (cryptoInfo->k2), FALSE)) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto final_seq; + } + + nStatus = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks); + if (nStatus != ERR_SUCCESS) + goto final_seq; + + if (!EAInitMode (cryptoInfo)) + { + nStatus = ERR_MODE_INIT_FAILED; + goto final_seq; + } + + offset.QuadPart = backupHeaders ? dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; + offset.QuadPart += TC_VOLUME_HEADER_EFFECTIVE_SIZE; + + if (!SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto final_seq; + } + + EncryptBuffer (buf, sizeof (buf), cryptoInfo); + + if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR) + { + nStatus = ERR_OS_ERROR; + goto final_seq; + } + + if (backupHeaders || bPrimaryOnly) + break; + + backupHeaders = TRUE; + } + + memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2)); + + nStatus = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks); + if (nStatus != ERR_SUCCESS) + goto final_seq; + + if (!EAInitMode (cryptoInfo)) + { + nStatus = ERR_MODE_INIT_FAILED; + goto final_seq; + } + +final_seq: + + dwError = GetLastError(); + + burn (temporaryKey, sizeof (temporaryKey)); + burn (originalK2, sizeof (originalK2)); + + if (nStatus != ERR_SUCCESS) + SetLastError (dwError); + + return nStatus; +} + +#endif // !defined (DEVICE_DRIVER) && !defined (TC_WINDOWS_BOOT) diff --git a/Common/VOLUMES.H b/Common/VOLUMES.H index 40edeb7..8fb5aa0 100644 --- a/Common/VOLUMES.H +++ b/Common/VOLUMES.H @@ -1,136 +1,136 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TC_HEADER_Common_Volumes -#define TC_HEADER_Common_Volumes - -#ifdef __cplusplus -extern "C" { -#endif - -// Volume header version -#define VOLUME_HEADER_VERSION 0x0004 - -// Version number written to volume header during format; -// specifies the minimum program version required to mount the volume -#define TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION 0x0600 - -// Version number written (encrypted) to the key data area of an encrypted system partition/drive; -// specifies the minimum program version required to decrypt the system partition/drive -#define TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION 0x0500 - -// Current volume format version (created by TrueCrypt 6.0+) -#define TC_VOLUME_FORMAT_VERSION 2 - -// Version number of volume format created by TrueCrypt 1.0-5.1a -#define TC_VOLUME_FORMAT_VERSION_PRE_6_0 1 - -// Volume header sizes -#define TC_VOLUME_HEADER_SIZE (64 * 1024L) -#define TC_VOLUME_HEADER_EFFECTIVE_SIZE 512 -#define TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE 512 -#define TC_VOLUME_HEADER_SIZE_LEGACY 512 - -#define TC_VOLUME_HEADER_GROUP_SIZE (2 * TC_VOLUME_HEADER_SIZE) -#define TC_TOTAL_VOLUME_HEADERS_SIZE (4 * TC_VOLUME_HEADER_SIZE) - -// Volume offsets -#define TC_VOLUME_HEADER_OFFSET 0 -#define TC_HIDDEN_VOLUME_HEADER_OFFSET TC_VOLUME_HEADER_SIZE - -#define TC_MAX_VOLUME_SECTOR_SIZE (2 * TC_VOLUME_HEADER_SIZE) - -#define TC_VOLUME_SMALL_SIZE_THRESHOLD (2 * BYTES_PER_MB) // Volume sizes below this threshold are considered small - -#define TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE SECTOR_SIZE_GEN2_STANDARD // FAT file system fills the last sector with zeroes (marked as free; observed when quick format was performed using the OS format tool). -#define TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH TC_MAX_VOLUME_SECTOR_SIZE // Reserved area size used for hidden volumes larger than TC_VOLUME_SMALL_SIZE_THRESHOLD - -#define TC_VOLUME_DATA_OFFSET TC_VOLUME_HEADER_GROUP_SIZE - -/* The offset, in bytes, of the hidden volume header position from the end of the file (a positive value). - The extra offset (SECTOR_SIZE * 2) was added because FAT file system fills the last sector with zeroes - (marked as free; observed when quick format was performed using the OS format tool). One extra sector was - added to the offset for future expandability (should the header size increase, or should header backup be - introduced). */ -#define TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY (TC_VOLUME_HEADER_SIZE_LEGACY + SECTOR_SIZE * 2) - -#define TC_MAX_128BIT_BLOCK_VOLUME_SIZE BYTES_PER_PB // Security bound (128-bit block XTS mode) - -// Filesystem size limits -#define TC_MIN_FAT_FS_SIZE (37 * SECTOR_SIZE) -#define TC_MAX_FAT_FS_SIZE 0x20000000000LL -#define TC_MIN_NTFS_FS_SIZE 2634752 -#define TC_MAX_NTFS_FS_SIZE (128LL * BYTES_PER_TB) // NTFS volume can theoretically be up to 16 exabytes, but Windows XP and 2003 limit the size to that addressable with 32-bit clusters, i.e. max size is 128 TB (if 64-KB clusters are used). - -// Volume size limits -#define TC_MIN_VOLUME_SIZE (TC_TOTAL_VOLUME_HEADERS_SIZE + TC_MIN_FAT_FS_SIZE) -#define TC_MIN_VOLUME_SIZE_LEGACY TC_MIN_FAT_FS_SIZE -#define TC_MAX_VOLUME_SIZE_GENERAL 0x7fffFFFFffffFFFFLL // Signed 64-bit integer file offset values -#define TC_MAX_VOLUME_SIZE TC_MAX_128BIT_BLOCK_VOLUME_SIZE - -#define TC_MIN_HIDDEN_VOLUME_SIZE (TC_MIN_FAT_FS_SIZE + TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE) - -#define TC_MIN_HIDDEN_VOLUME_HOST_SIZE (TC_MIN_VOLUME_SIZE + TC_MIN_HIDDEN_VOLUME_SIZE + 2 * SECTOR_SIZE_GEN2_STANDARD) -#define TC_MAX_HIDDEN_VOLUME_HOST_SIZE (TC_MAX_NTFS_FS_SIZE - TC_TOTAL_VOLUME_HEADERS_SIZE) - -#ifndef TC_NO_COMPILER_INT64 -# if TC_MAX_VOLUME_SIZE > TC_MAX_VOLUME_SIZE_GENERAL -# error TC_MAX_VOLUME_SIZE > TC_MAX_VOLUME_SIZE_GENERAL -# endif -#endif - -#define HEADER_ENCRYPTED_DATA_SIZE (TC_VOLUME_HEADER_EFFECTIVE_SIZE - HEADER_ENCRYPTED_DATA_OFFSET) - -// Volume header field offsets -#define HEADER_SALT_OFFSET 0 -#define HEADER_ENCRYPTED_DATA_OFFSET PKCS5_SALT_SIZE -#define HEADER_MASTER_KEYDATA_OFFSET 256 - -#define TC_HEADER_OFFSET_MAGIC 64 -#define TC_HEADER_OFFSET_VERSION 68 -#define TC_HEADER_OFFSET_REQUIRED_VERSION 70 -#define TC_HEADER_OFFSET_KEY_AREA_CRC 72 -#define TC_HEADER_OFFSET_VOLUME_CREATION_TIME 76 -#define TC_HEADER_OFFSET_MODIFICATION_TIME 84 -#define TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE 92 -#define TC_HEADER_OFFSET_VOLUME_SIZE 100 -#define TC_HEADER_OFFSET_ENCRYPTED_AREA_START 108 -#define TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH 116 -#define TC_HEADER_OFFSET_FLAGS 124 -#define TC_HEADER_OFFSET_HEADER_CRC 252 - -// Volume header flags -#define TC_HEADER_FLAG_ENCRYPTED_SYSTEM 0x1 -#define TC_HEADER_FLAG_NONSYS_INPLACE_ENC 0x2 // The volume has been created using non-system in-place encryption - - -#ifndef TC_HEADER_Volume_VolumeHeader - -#include "Password.h" - -extern BOOL ReadVolumeHeaderRecoveryMode; - -uint16 GetHeaderField16 (byte *header, int offset); -uint32 GetHeaderField32 (byte *header, int offset); -UINT64_STRUCT GetHeaderField64 (byte *header, int offset); -int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo); -#ifndef TC_WINDOWS_BOOT -int CreateVolumeHeaderInMemory (BOOL bBoot, char *encryptedHeader, int ea, int mode, Password *password, int pkcs5_prf, char *masterKeydata, PCRYPTO_INFO *retInfo, unsigned __int64 volumeSize, unsigned __int64 hiddenVolumeSize, unsigned __int64 encryptedAreaStart, unsigned __int64 encryptedAreaLength, uint16 requiredProgramVersion, uint32 headerFlags, BOOL bWipeMode); -int WriteRandomDataToReservedHeaderAreas (HANDLE dev, CRYPTO_INFO *cryptoInfo, uint64 dataAreaSize, BOOL bPrimaryOnly, BOOL bBackupOnly); -#endif - -#endif // !TC_HEADER_Volume_VolumeHeader - -#ifdef __cplusplus -} -#endif - -#endif // TC_HEADER_Common_Volumes +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_Common_Volumes +#define TC_HEADER_Common_Volumes + +#ifdef __cplusplus +extern "C" { +#endif + +// Volume header version +#define VOLUME_HEADER_VERSION 0x0004 + +// Version number written to volume header during format; +// specifies the minimum program version required to mount the volume +#define TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION 0x0600 + +// Version number written (encrypted) to the key data area of an encrypted system partition/drive; +// specifies the minimum program version required to decrypt the system partition/drive +#define TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION 0x0500 + +// Current volume format version (created by TrueCrypt 6.0+) +#define TC_VOLUME_FORMAT_VERSION 2 + +// Version number of volume format created by TrueCrypt 1.0-5.1a +#define TC_VOLUME_FORMAT_VERSION_PRE_6_0 1 + +// Volume header sizes +#define TC_VOLUME_HEADER_SIZE (64 * 1024L) +#define TC_VOLUME_HEADER_EFFECTIVE_SIZE 512 +#define TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE 512 +#define TC_VOLUME_HEADER_SIZE_LEGACY 512 + +#define TC_VOLUME_HEADER_GROUP_SIZE (2 * TC_VOLUME_HEADER_SIZE) +#define TC_TOTAL_VOLUME_HEADERS_SIZE (4 * TC_VOLUME_HEADER_SIZE) + +// Volume offsets +#define TC_VOLUME_HEADER_OFFSET 0 +#define TC_HIDDEN_VOLUME_HEADER_OFFSET TC_VOLUME_HEADER_SIZE + +#define TC_MAX_VOLUME_SECTOR_SIZE (2 * TC_VOLUME_HEADER_SIZE) + +#define TC_VOLUME_SMALL_SIZE_THRESHOLD (2 * BYTES_PER_MB) // Volume sizes below this threshold are considered small + +#define TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE SECTOR_SIZE_GEN2_STANDARD // FAT file system fills the last sector with zeroes (marked as free; observed when quick format was performed using the OS format tool). +#define TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH TC_MAX_VOLUME_SECTOR_SIZE // Reserved area size used for hidden volumes larger than TC_VOLUME_SMALL_SIZE_THRESHOLD + +#define TC_VOLUME_DATA_OFFSET TC_VOLUME_HEADER_GROUP_SIZE + +/* The offset, in bytes, of the hidden volume header position from the end of the file (a positive value). + The extra offset (SECTOR_SIZE * 2) was added because FAT file system fills the last sector with zeroes + (marked as free; observed when quick format was performed using the OS format tool). One extra sector was + added to the offset for future expandability (should the header size increase, or should header backup be + introduced). */ +#define TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY (TC_VOLUME_HEADER_SIZE_LEGACY + SECTOR_SIZE * 2) + +#define TC_MAX_128BIT_BLOCK_VOLUME_SIZE BYTES_PER_PB // Security bound (128-bit block XTS mode) + +// Filesystem size limits +#define TC_MIN_FAT_FS_SIZE (37 * SECTOR_SIZE) +#define TC_MAX_FAT_FS_SIZE 0x20000000000LL +#define TC_MIN_NTFS_FS_SIZE 2634752 +#define TC_MAX_NTFS_FS_SIZE (128LL * BYTES_PER_TB) // NTFS volume can theoretically be up to 16 exabytes, but Windows XP and 2003 limit the size to that addressable with 32-bit clusters, i.e. max size is 128 TB (if 64-KB clusters are used). + +// Volume size limits +#define TC_MIN_VOLUME_SIZE (TC_TOTAL_VOLUME_HEADERS_SIZE + TC_MIN_FAT_FS_SIZE) +#define TC_MIN_VOLUME_SIZE_LEGACY TC_MIN_FAT_FS_SIZE +#define TC_MAX_VOLUME_SIZE_GENERAL 0x7fffFFFFffffFFFFLL // Signed 64-bit integer file offset values +#define TC_MAX_VOLUME_SIZE TC_MAX_128BIT_BLOCK_VOLUME_SIZE + +#define TC_MIN_HIDDEN_VOLUME_SIZE (TC_MIN_FAT_FS_SIZE + TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE) + +#define TC_MIN_HIDDEN_VOLUME_HOST_SIZE (TC_MIN_VOLUME_SIZE + TC_MIN_HIDDEN_VOLUME_SIZE + 2 * SECTOR_SIZE_GEN2_STANDARD) +#define TC_MAX_HIDDEN_VOLUME_HOST_SIZE (TC_MAX_NTFS_FS_SIZE - TC_TOTAL_VOLUME_HEADERS_SIZE) + +#ifndef TC_NO_COMPILER_INT64 +# if TC_MAX_VOLUME_SIZE > TC_MAX_VOLUME_SIZE_GENERAL +# error TC_MAX_VOLUME_SIZE > TC_MAX_VOLUME_SIZE_GENERAL +# endif +#endif + +#define HEADER_ENCRYPTED_DATA_SIZE (TC_VOLUME_HEADER_EFFECTIVE_SIZE - HEADER_ENCRYPTED_DATA_OFFSET) + +// Volume header field offsets +#define HEADER_SALT_OFFSET 0 +#define HEADER_ENCRYPTED_DATA_OFFSET PKCS5_SALT_SIZE +#define HEADER_MASTER_KEYDATA_OFFSET 256 + +#define TC_HEADER_OFFSET_MAGIC 64 +#define TC_HEADER_OFFSET_VERSION 68 +#define TC_HEADER_OFFSET_REQUIRED_VERSION 70 +#define TC_HEADER_OFFSET_KEY_AREA_CRC 72 +#define TC_HEADER_OFFSET_VOLUME_CREATION_TIME 76 +#define TC_HEADER_OFFSET_MODIFICATION_TIME 84 +#define TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE 92 +#define TC_HEADER_OFFSET_VOLUME_SIZE 100 +#define TC_HEADER_OFFSET_ENCRYPTED_AREA_START 108 +#define TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH 116 +#define TC_HEADER_OFFSET_FLAGS 124 +#define TC_HEADER_OFFSET_HEADER_CRC 252 + +// Volume header flags +#define TC_HEADER_FLAG_ENCRYPTED_SYSTEM 0x1 +#define TC_HEADER_FLAG_NONSYS_INPLACE_ENC 0x2 // The volume has been created using non-system in-place encryption + + +#ifndef TC_HEADER_Volume_VolumeHeader + +#include "Password.h" + +extern BOOL ReadVolumeHeaderRecoveryMode; + +uint16 GetHeaderField16 (byte *header, int offset); +uint32 GetHeaderField32 (byte *header, int offset); +UINT64_STRUCT GetHeaderField64 (byte *header, int offset); +int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo); +#ifndef TC_WINDOWS_BOOT +int CreateVolumeHeaderInMemory (BOOL bBoot, char *encryptedHeader, int ea, int mode, Password *password, int pkcs5_prf, char *masterKeydata, PCRYPTO_INFO *retInfo, unsigned __int64 volumeSize, unsigned __int64 hiddenVolumeSize, unsigned __int64 encryptedAreaStart, unsigned __int64 encryptedAreaLength, uint16 requiredProgramVersion, uint32 headerFlags, BOOL bWipeMode); +int WriteRandomDataToReservedHeaderAreas (HANDLE dev, CRYPTO_INFO *cryptoInfo, uint64 dataAreaSize, BOOL bPrimaryOnly, BOOL bBackupOnly); +#endif + +#endif // !TC_HEADER_Volume_VolumeHeader + +#ifdef __cplusplus +} +#endif + +#endif // TC_HEADER_Common_Volumes diff --git a/Common/Wipe.c b/Common/Wipe.c index 8ebafb3..bc9a56d 100644 --- a/Common/Wipe.c +++ b/Common/Wipe.c @@ -1,187 +1,187 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Tcdefs.h" -#include "Wipe.h" - - -static BOOL Wipe1PseudoRandom (int pass, byte *buffer, size_t size) -{ - return FALSE; -} - - -// Fill buffer with wipe patterns defined in "National Industrial Security Program Operating Manual", US DoD 5220.22-M. -// Return: FALSE = buffer must be filled with random data - -static BOOL Wipe3Dod5220 (int pass, byte *buffer, size_t size) -{ - byte wipeChar; - - switch (pass) - { - case 1: - wipeChar = 0; - break; - - case 2: - wipeChar = 0xff; - break; - - default: - return FALSE; - } - - memset (buffer, wipeChar, size); - return TRUE; -} - - -static BOOL Wipe7Dod5220 (int pass, byte randChars[TC_WIPE_RAND_CHAR_COUNT], byte *buffer, size_t size) -{ - byte wipeChar; - - switch (pass) - { - case 1: - wipeChar = randChars[0]; - break; - - case 2: - wipeChar = ~randChars[0]; - break; - - case 4: - wipeChar = randChars[1]; - break; - - case 5: - wipeChar = randChars[2]; - break; - - case 6: - wipeChar = ~randChars[2]; - break; - - default: - return FALSE; - } - - memset (buffer, wipeChar, size); - return TRUE; -} - - -// Fill the buffer with wipe patterns defined in the paper "Secure Deletion of Data from Magnetic and Solid-State Memory" by Peter Gutmann. -// Return: FALSE = buffer must be filled with random data - -static BOOL Wipe35Gutmann (int pass, byte *buffer, size_t size) -{ - byte wipePat3[] = { 0x92, 0x49, 0x24 }; - int wipePat3Pos; - size_t i; - - switch (pass) - { - case 5: - memset (buffer, 0x55, size); - break; - - case 6: - memset (buffer, 0xaa, size); - break; - - case 7: - case 26: - case 29: - wipePat3Pos = 0; - goto wipe3; - - case 8: - case 27: - case 30: - wipePat3Pos = 1; - goto wipe3; - - case 9: - case 28: - case 31: - wipePat3Pos = 2; - goto wipe3; - -wipe3: - if (pass >= 29) - { - wipePat3[0] = ~wipePat3[0]; - wipePat3[1] = ~wipePat3[1]; - wipePat3[2] = ~wipePat3[2]; - } - - for (i = 0; i < size; ++i) - { - buffer[i] = wipePat3[wipePat3Pos++ % 3]; - } - break; - - default: - if (pass >= 10 && pass <= 25) - memset (buffer, (pass - 10) * 0x11, size); - else - return FALSE; - } - - return TRUE; -} - - -size_t GetWipePassCount (WipeAlgorithmId algorithm) -{ - switch (algorithm) - { - case TC_WIPE_1_RAND: - return 1; - - case TC_WIPE_3_DOD_5220: - return 3; - - case TC_WIPE_7_DOD_5220: - return 7; - - case TC_WIPE_35_GUTMANN: - return 35; - - default: - TC_THROW_FATAL_EXCEPTION; - } - - return 0; // Prevent compiler warnings -} - - -BOOL WipeBuffer (WipeAlgorithmId algorithm, byte randChars[TC_WIPE_RAND_CHAR_COUNT], int pass, byte *buffer, size_t size) -{ - switch (algorithm) - { - case TC_WIPE_1_RAND: - return Wipe1PseudoRandom (pass, buffer, size); - - case TC_WIPE_3_DOD_5220: - return Wipe3Dod5220 (pass, buffer, size); - - case TC_WIPE_7_DOD_5220: - return Wipe7Dod5220 (pass, randChars, buffer, size); - - case TC_WIPE_35_GUTMANN: - return Wipe35Gutmann (pass, buffer, size); - - default: - TC_THROW_FATAL_EXCEPTION; - } - - return FALSE; // Prevent compiler warnings -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Tcdefs.h" +#include "Wipe.h" + + +static BOOL Wipe1PseudoRandom (int pass, byte *buffer, size_t size) +{ + return FALSE; +} + + +// Fill buffer with wipe patterns defined in "National Industrial Security Program Operating Manual", US DoD 5220.22-M. +// Return: FALSE = buffer must be filled with random data + +static BOOL Wipe3Dod5220 (int pass, byte *buffer, size_t size) +{ + byte wipeChar; + + switch (pass) + { + case 1: + wipeChar = 0; + break; + + case 2: + wipeChar = 0xff; + break; + + default: + return FALSE; + } + + memset (buffer, wipeChar, size); + return TRUE; +} + + +static BOOL Wipe7Dod5220 (int pass, byte randChars[TC_WIPE_RAND_CHAR_COUNT], byte *buffer, size_t size) +{ + byte wipeChar; + + switch (pass) + { + case 1: + wipeChar = randChars[0]; + break; + + case 2: + wipeChar = ~randChars[0]; + break; + + case 4: + wipeChar = randChars[1]; + break; + + case 5: + wipeChar = randChars[2]; + break; + + case 6: + wipeChar = ~randChars[2]; + break; + + default: + return FALSE; + } + + memset (buffer, wipeChar, size); + return TRUE; +} + + +// Fill the buffer with wipe patterns defined in the paper "Secure Deletion of Data from Magnetic and Solid-State Memory" by Peter Gutmann. +// Return: FALSE = buffer must be filled with random data + +static BOOL Wipe35Gutmann (int pass, byte *buffer, size_t size) +{ + byte wipePat3[] = { 0x92, 0x49, 0x24 }; + int wipePat3Pos; + size_t i; + + switch (pass) + { + case 5: + memset (buffer, 0x55, size); + break; + + case 6: + memset (buffer, 0xaa, size); + break; + + case 7: + case 26: + case 29: + wipePat3Pos = 0; + goto wipe3; + + case 8: + case 27: + case 30: + wipePat3Pos = 1; + goto wipe3; + + case 9: + case 28: + case 31: + wipePat3Pos = 2; + goto wipe3; + +wipe3: + if (pass >= 29) + { + wipePat3[0] = ~wipePat3[0]; + wipePat3[1] = ~wipePat3[1]; + wipePat3[2] = ~wipePat3[2]; + } + + for (i = 0; i < size; ++i) + { + buffer[i] = wipePat3[wipePat3Pos++ % 3]; + } + break; + + default: + if (pass >= 10 && pass <= 25) + memset (buffer, (pass - 10) * 0x11, size); + else + return FALSE; + } + + return TRUE; +} + + +int GetWipePassCount (WipeAlgorithmId algorithm) +{ + switch (algorithm) + { + case TC_WIPE_1_RAND: + return 1; + + case TC_WIPE_3_DOD_5220: + return 3; + + case TC_WIPE_7_DOD_5220: + return 7; + + case TC_WIPE_35_GUTMANN: + return 35; + + default: + TC_THROW_FATAL_EXCEPTION; + } + + return 0; // Prevent compiler warnings +} + + +BOOL WipeBuffer (WipeAlgorithmId algorithm, byte randChars[TC_WIPE_RAND_CHAR_COUNT], int pass, byte *buffer, size_t size) +{ + switch (algorithm) + { + case TC_WIPE_1_RAND: + return Wipe1PseudoRandom (pass, buffer, size); + + case TC_WIPE_3_DOD_5220: + return Wipe3Dod5220 (pass, buffer, size); + + case TC_WIPE_7_DOD_5220: + return Wipe7Dod5220 (pass, randChars, buffer, size); + + case TC_WIPE_35_GUTMANN: + return Wipe35Gutmann (pass, buffer, size); + + default: + TC_THROW_FATAL_EXCEPTION; + } + + return FALSE; // Prevent compiler warnings +} diff --git a/Common/Wipe.h b/Common/Wipe.h index 1b5a13f..3268155 100644 --- a/Common/Wipe.h +++ b/Common/Wipe.h @@ -1,40 +1,40 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Common_Wipe -#define TC_HEADER_Common_Wipe - -#include "Tcdefs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum -{ - /* WARNING: As these values are written to config files, if they or their meanings - are changed, incompatiblity with other versions may arise (upgrade, downgrade, etc.). - When adding a new constant, verify that the value is unique within this block. */ - TC_WIPE_NONE = 0, - TC_WIPE_1_RAND = 100, - TC_WIPE_3_DOD_5220 = 300, - TC_WIPE_7_DOD_5220 = 700, - TC_WIPE_35_GUTMANN = 3500 - -} WipeAlgorithmId; - -#define TC_WIPE_RAND_CHAR_COUNT 3 - -size_t GetWipePassCount (WipeAlgorithmId algorithm); -BOOL WipeBuffer (WipeAlgorithmId algorithm, byte randChars[TC_WIPE_RAND_CHAR_COUNT], int pass, byte *buffer, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif // TC_HEADER_Common_Wipe +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Common_Wipe +#define TC_HEADER_Common_Wipe + +#include "Tcdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + /* WARNING: As these values are written to config files, if they or their meanings + are changed, incompatiblity with other versions may arise (upgrade, downgrade, etc.). + When adding a new constant, verify that the value is unique within this block. */ + TC_WIPE_NONE = 0, + TC_WIPE_1_RAND = 100, + TC_WIPE_3_DOD_5220 = 300, + TC_WIPE_7_DOD_5220 = 700, + TC_WIPE_35_GUTMANN = 3500 + +} WipeAlgorithmId; + +#define TC_WIPE_RAND_CHAR_COUNT 3 + +int GetWipePassCount (WipeAlgorithmId algorithm); +BOOL WipeBuffer (WipeAlgorithmId algorithm, byte randChars[TC_WIPE_RAND_CHAR_COUNT], int pass, byte *buffer, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif // TC_HEADER_Common_Wipe diff --git a/Common/Xml.c b/Common/Xml.c index b521bb6..5ebd3e5 100644 --- a/Common/Xml.c +++ b/Common/Xml.c @@ -1,219 +1,219 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include "Xml.h" - - -static BOOL BeginsWith (char *string, char *subString) -{ - while (*string++ == *subString++) - { - if (*subString == 0) return TRUE; - if (*string == 0) return FALSE; - } - - return FALSE; -} - - -char *XmlNextNode (char *xmlNode) -{ - char *t = xmlNode + 1; - while ((t = strchr (t, '<')) != NULL) - { - if (t[1] != '/') - return t; - - t++; - } - - return NULL; -} - - -char *XmlFindElement (char *xmlNode, char *nodeName) -{ - char *t = xmlNode; - size_t nameLen = strlen (nodeName); - - do - { - if (BeginsWith (t + 1, nodeName) - && (t[nameLen + 1] == '>' - || t[nameLen + 1] == ' ')) return t; - - } while (t = XmlNextNode (t)); - - return NULL; -} - - -char *XmlFindElementByAttributeValue (char *xml, char *nodeName, char *attrName, char *attrValue) -{ - char attr[2048]; - - while (xml = XmlFindElement (xml, nodeName)) - { - XmlGetAttributeText (xml, attrName, attr, sizeof (attr)); - if (strcmp (attr, attrValue) == 0) - return xml; - - xml++; - } - - return NULL; -} - - -char *XmlGetAttributeText (char *xmlNode, char *xmlAttrName, char *xmlAttrValue, int xmlAttrValueSize) -{ - char *t = xmlNode; - char *e = xmlNode; - int l = 0; - - xmlAttrValue[0] = 0; - if (t[0] != '<') return NULL; - - e = strchr (e, '>'); - if (e == NULL) return NULL; - - while ((t = strstr (t, xmlAttrName)) && t < e) - { - char *o = t + strlen (xmlAttrName); - if (t[-1] == ' ' - && - (BeginsWith (o, "=\"") - || BeginsWith (o, "= \"") - || BeginsWith (o, " =\"") - || BeginsWith (o, " = \"")) - ) - break; - - t++; - } - - if (t == NULL || t > e) return NULL; - - t = strchr (t, '"') + 1; - e = strchr (t, '"'); - l = (int)(e - t); - if (e == NULL || l > xmlAttrValueSize) return NULL; - - memcpy (xmlAttrValue, t, l); - xmlAttrValue[l] = 0; - - return xmlAttrValue; -} - - -char *XmlGetNodeText (char *xmlNode, char *xmlText, int xmlTextSize) -{ - char *t = xmlNode; - char *e = xmlNode + 1; - int l = 0, i = 0, j = 0; - - xmlText[0] = 0; - - if (t[0] != '<') - return NULL; - - t = strchr (t, '>') + 1; - if (t == (char *)1) return NULL; - - e = strchr (e, '<'); - if (e == NULL) return NULL; - - l = (int)(e - t); - if (e == NULL || l > xmlTextSize) return NULL; - - while (i < l) - { - if (BeginsWith (&t[i], "<")) - { - xmlText[j++] = '<'; - i += 4; - continue; - } - if (BeginsWith (&t[i], ">")) - { - xmlText[j++] = '>'; - i += 4; - continue; - } - if (BeginsWith (&t[i], "&")) - { - xmlText[j++] = '&'; - i += 5; - continue; - } - xmlText[j++] = t[i++]; - } - xmlText[j] = 0; - - return t; -} - - -char *XmlQuoteText (char *textSrc, char *textDst, int textDstMaxSize) -{ - char *textDstLast = textDst + textDstMaxSize - 1; - - if (textDstMaxSize == 0) - return NULL; - - while (*textSrc != 0 && textDst <= textDstLast) - { - char c = *textSrc++; - switch (c) - { - case '&': - if (textDst + 6 > textDstLast) - return NULL; - strcpy (textDst, "&"); - textDst += 5; - continue; - - case '>': - if (textDst + 5 > textDstLast) - return NULL; - strcpy (textDst, ">"); - textDst += 4; - continue; - - case '<': - if (textDst + 5 > textDstLast) - return NULL; - strcpy (textDst, "<"); - textDst += 4; - continue; - - default: - *textDst++ = c; - } - } - - if (textDst > textDstLast) - return NULL; - - *textDst = 0; - return textDst; -} - - -int XmlWriteHeader (FILE *file) -{ - return fputs ("\n", file); -} - - -int XmlWriteFooter (FILE *file) -{ - return fputs ("\n", file); -} +/* + Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include "Xml.h" + + +static BOOL BeginsWith (char *string, char *subString) +{ + while (*string++ == *subString++) + { + if (*subString == 0) return TRUE; + if (*string == 0) return FALSE; + } + + return FALSE; +} + + +char *XmlNextNode (char *xmlNode) +{ + char *t = xmlNode + 1; + while ((t = strchr (t, '<')) != NULL) + { + if (t[1] != '/') + return t; + + t++; + } + + return NULL; +} + + +char *XmlFindElement (char *xmlNode, char *nodeName) +{ + char *t = xmlNode; + size_t nameLen = strlen (nodeName); + + do + { + if (BeginsWith (t + 1, nodeName) + && (t[nameLen + 1] == '>' + || t[nameLen + 1] == ' ')) return t; + + } while (t = XmlNextNode (t)); + + return NULL; +} + + +char *XmlFindElementByAttributeValue (char *xml, char *nodeName, char *attrName, char *attrValue) +{ + char attr[2048]; + + while (xml = XmlFindElement (xml, nodeName)) + { + XmlGetAttributeText (xml, attrName, attr, sizeof (attr)); + if (strcmp (attr, attrValue) == 0) + return xml; + + xml++; + } + + return NULL; +} + + +char *XmlGetAttributeText (char *xmlNode, char *xmlAttrName, char *xmlAttrValue, int xmlAttrValueSize) +{ + char *t = xmlNode; + char *e = xmlNode; + int l = 0; + + xmlAttrValue[0] = 0; + if (t[0] != '<') return NULL; + + e = strchr (e, '>'); + if (e == NULL) return NULL; + + while ((t = strstr (t, xmlAttrName)) && t < e) + { + char *o = t + strlen (xmlAttrName); + if (t[-1] == ' ' + && + (BeginsWith (o, "=\"") + || BeginsWith (o, "= \"") + || BeginsWith (o, " =\"") + || BeginsWith (o, " = \"")) + ) + break; + + t++; + } + + if (t == NULL || t > e) return NULL; + + t = strchr (t, '"') + 1; + e = strchr (t, '"'); + l = (int)(e - t); + if (e == NULL || l > xmlAttrValueSize) return NULL; + + memcpy (xmlAttrValue, t, l); + xmlAttrValue[l] = 0; + + return xmlAttrValue; +} + + +char *XmlGetNodeText (char *xmlNode, char *xmlText, int xmlTextSize) +{ + char *t = xmlNode; + char *e = xmlNode + 1; + int l = 0, i = 0, j = 0; + + xmlText[0] = 0; + + if (t[0] != '<') + return NULL; + + t = strchr (t, '>') + 1; + if (t == (char *)1) return NULL; + + e = strchr (e, '<'); + if (e == NULL) return NULL; + + l = (int)(e - t); + if (e == NULL || l > xmlTextSize) return NULL; + + while (i < l) + { + if (BeginsWith (&t[i], "<")) + { + xmlText[j++] = '<'; + i += 4; + continue; + } + if (BeginsWith (&t[i], ">")) + { + xmlText[j++] = '>'; + i += 4; + continue; + } + if (BeginsWith (&t[i], "&")) + { + xmlText[j++] = '&'; + i += 5; + continue; + } + xmlText[j++] = t[i++]; + } + xmlText[j] = 0; + + return t; +} + + +char *XmlQuoteText (char *textSrc, char *textDst, int textDstMaxSize) +{ + char *textDstLast = textDst + textDstMaxSize - 1; + + if (textDstMaxSize == 0) + return NULL; + + while (*textSrc != 0 && textDst <= textDstLast) + { + char c = *textSrc++; + switch (c) + { + case '&': + if (textDst + 6 > textDstLast) + return NULL; + strcpy (textDst, "&"); + textDst += 5; + continue; + + case '>': + if (textDst + 5 > textDstLast) + return NULL; + strcpy (textDst, ">"); + textDst += 4; + continue; + + case '<': + if (textDst + 5 > textDstLast) + return NULL; + strcpy (textDst, "<"); + textDst += 4; + continue; + + default: + *textDst++ = c; + } + } + + if (textDst > textDstLast) + return NULL; + + *textDst = 0; + return textDst; +} + + +int XmlWriteHeader (FILE *file) +{ + return fputs ("\n", file); +} + + +int XmlWriteFooter (FILE *file) +{ + return fputs ("\n", file); +} diff --git a/Common/Xml.h b/Common/Xml.h index 7b1811f..b51e1f8 100644 --- a/Common/Xml.h +++ b/Common/Xml.h @@ -1,24 +1,24 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -char *XmlNextNode (char *xmlNode); -char *XmlFindElement (char *xmlNode, char *nodeName); -char *XmlGetAttributeText (char *xmlNode, char *xmlAttrName, char *xmlAttrValue, int xmlAttrValueSize); -char *XmlGetNodeText (char *xmlNode, char *xmlText, int xmlTextSize); -int XmlWriteHeader (FILE *file); -int XmlWriteFooter (FILE *file); -char *XmlFindElementByAttributeValue (char *xml, char *nodeName, char *attrName, char *attrValue); -char *XmlQuoteText (char *textSrc, char *textDst, int textDstMaxSize); - -#ifdef __cplusplus -} -#endif +/* + Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +char *XmlNextNode (char *xmlNode); +char *XmlFindElement (char *xmlNode, char *nodeName); +char *XmlGetAttributeText (char *xmlNode, char *xmlAttrName, char *xmlAttrValue, int xmlAttrValueSize); +char *XmlGetNodeText (char *xmlNode, char *xmlText, int xmlTextSize); +int XmlWriteHeader (FILE *file); +int XmlWriteFooter (FILE *file); +char *XmlFindElementByAttributeValue (char *xml, char *nodeName, char *attrName, char *attrValue); +char *XmlQuoteText (char *textSrc, char *textDst, int textDstMaxSize); + +#ifdef __cplusplus +} +#endif diff --git a/Common/Xts.c b/Common/Xts.c index 204ea96..4975144 100644 --- a/Common/Xts.c +++ b/Common/Xts.c @@ -1,439 +1,442 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -/* If native 64-bit data types are not available, define TC_NO_COMPILER_INT64. - -For big-endian platforms define BYTE_ORDER as BIG_ENDIAN. */ - - -#ifdef TC_MINIMIZE_CODE_SIZE -// Preboot/boot version -# ifndef TC_NO_COMPILER_INT64 -# define TC_NO_COMPILER_INT64 -# endif -# pragma optimize ("tl", on) -#endif - - -#include "Xts.h" - - -#ifndef TC_NO_COMPILER_INT64 - -// length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size -// ks: the primary key schedule -// ks2: the secondary key schedule -// startDataUnitNo: The sequential number of the data unit with which the buffer starts. -// startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit startDataUnitNo. -// When encrypting the data unit from its first block, startCipherBlockNo is 0. -// The startCipherBlockNo value applies only to the first data unit in the buffer; each successive -// data unit is encrypted from its first block. The start of the buffer does not have to be -// aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it -// is not aligned, startCipherBlockNo must reflect the misalignment accordingly. -void EncryptBufferXTS (unsigned __int8 *buffer, - TC_LARGEST_COMPILER_UINT length, - const UINT64_STRUCT *startDataUnitNo, - unsigned int startCipherBlockNo, - unsigned __int8 *ks, - unsigned __int8 *ks2, - int cipher) -{ - unsigned __int8 finalCarry; - unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; - unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; - unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; - unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; - unsigned int startBlock = startCipherBlockNo, endBlock, block; - TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; - - /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the - finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block - number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented - as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if - the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is - derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */ - - // Convert the 64-bit data unit number into a little-endian 16-byte array. - // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. - dataUnitNo = startDataUnitNo->Value; - *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); - *((unsigned __int64 *) byteBufUnitNo + 1) = 0; - - if (length % BYTES_PER_XTS_BLOCK) - TC_THROW_FATAL_EXCEPTION; - - blockCount = length / BYTES_PER_XTS_BLOCK; - - // Process all blocks in the buffer - while (blockCount > 0) - { - if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) - endBlock = startBlock + (unsigned int) blockCount; - else - endBlock = BLOCKS_PER_XTS_DATA_UNIT; - - whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; - - // Encrypt the data unit number using the secondary key (in order to generate the first - // whitening value for this data unit) - *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); - *(whiteningValuePtr64 + 1) = 0; - EncipherBlock (cipher, whiteningValue, ks2); - - // Generate (and apply) subsequent whitening values for blocks in this data unit and - // encrypt all relevant blocks in this data unit - for (block = 0; block < endBlock; block++) - { - if (block >= startBlock) - { - // Pre-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr-- ^= *whiteningValuePtr64--; - - // Actual encryption - EncipherBlock (cipher, bufPtr, ks); - - // Post-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr++ ^= *whiteningValuePtr64; - } - else - whiteningValuePtr64++; - - // Derive the next whitening value - -#if BYTE_ORDER == LITTLE_ENDIAN - - // Little-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x8000000000000000) ? - 135 : 0; - - *whiteningValuePtr64-- <<= 1; - - if (*whiteningValuePtr64 & 0x8000000000000000) - *(whiteningValuePtr64 + 1) |= 1; - - *whiteningValuePtr64 <<= 1; -#else - - // Big-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x80) ? - 135 : 0; - - *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); - - whiteningValuePtr64--; - - if (*whiteningValuePtr64 & 0x80) - *(whiteningValuePtr64 + 1) |= 0x0100000000000000; - - *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); -#endif - - whiteningValue[0] ^= finalCarry; - } - - blockCount -= endBlock - startBlock; - startBlock = 0; - dataUnitNo++; - *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); - } - - FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); -} - - -// For descriptions of the input parameters, see EncryptBufferXTS(). -void DecryptBufferXTS (unsigned __int8 *buffer, - TC_LARGEST_COMPILER_UINT length, - const UINT64_STRUCT *startDataUnitNo, - unsigned int startCipherBlockNo, - unsigned __int8 *ks, - unsigned __int8 *ks2, - int cipher) -{ - unsigned __int8 finalCarry; - unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; - unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; - unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; - unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; - unsigned int startBlock = startCipherBlockNo, endBlock, block; - TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; - - // Convert the 64-bit data unit number into a little-endian 16-byte array. - // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. - dataUnitNo = startDataUnitNo->Value; - *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); - *((unsigned __int64 *) byteBufUnitNo + 1) = 0; - - if (length % BYTES_PER_XTS_BLOCK) - TC_THROW_FATAL_EXCEPTION; - - blockCount = length / BYTES_PER_XTS_BLOCK; - - // Process all blocks in the buffer - while (blockCount > 0) - { - if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) - endBlock = startBlock + (unsigned int) blockCount; - else - endBlock = BLOCKS_PER_XTS_DATA_UNIT; - - whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; - - // Encrypt the data unit number using the secondary key (in order to generate the first - // whitening value for this data unit) - *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); - *(whiteningValuePtr64 + 1) = 0; - EncipherBlock (cipher, whiteningValue, ks2); - - // Generate (and apply) subsequent whitening values for blocks in this data unit and - // decrypt all relevant blocks in this data unit - for (block = 0; block < endBlock; block++) - { - if (block >= startBlock) - { - // Post-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr-- ^= *whiteningValuePtr64--; - - // Actual decryption - DecipherBlock (cipher, bufPtr, ks); - - // Pre-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr++ ^= *whiteningValuePtr64; - } - else - whiteningValuePtr64++; - - // Derive the next whitening value - -#if BYTE_ORDER == LITTLE_ENDIAN - - // Little-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x8000000000000000) ? - 135 : 0; - - *whiteningValuePtr64-- <<= 1; - - if (*whiteningValuePtr64 & 0x8000000000000000) - *(whiteningValuePtr64 + 1) |= 1; - - *whiteningValuePtr64 <<= 1; - -#else - // Big-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x80) ? - 135 : 0; - - *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); - - whiteningValuePtr64--; - - if (*whiteningValuePtr64 & 0x80) - *(whiteningValuePtr64 + 1) |= 0x0100000000000000; - - *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); -#endif - - whiteningValue[0] ^= finalCarry; - } - - blockCount -= endBlock - startBlock; - startBlock = 0; - dataUnitNo++; - *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); - } - - FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); -} - - - -#else // TC_NO_COMPILER_INT64 - -/* ---- The following code is to be used only when native 64-bit data types are not available. ---- */ - -#if BYTE_ORDER == BIG_ENDIAN -#error The TC_NO_COMPILER_INT64 version of the XTS code is not compatible with big-endian platforms -#endif - - -// Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit -// environments/platforms) into a little-endian 16-byte array. -static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32) -{ - unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf; - - *bufPtr32++ = lowInt32; - *bufPtr32++ = highInt32; - - // We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes - *bufPtr32++ = 0; - *bufPtr32 = 0; -} - - -// Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters, -// see the 64-bit version of EncryptBufferXTS(). -static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer, - TC_LARGEST_COMPILER_UINT length, - const UINT64_STRUCT *startDataUnitNo, - unsigned int startBlock, - unsigned __int8 *ks, - unsigned __int8 *ks2, - int cipher, - BOOL decryption) -{ - TC_LARGEST_COMPILER_UINT blockCount; - UINT64_STRUCT dataUnitNo; - unsigned int block; - unsigned int endBlock; - unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; - unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; - unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer; - unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; - unsigned __int8 finalCarry; - unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1; - - // Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms - dataUnitNo.HighPart = startDataUnitNo->HighPart; - dataUnitNo.LowPart = startDataUnitNo->LowPart; - - blockCount = length / BYTES_PER_XTS_BLOCK; - - // Convert the 64-bit data unit number into a little-endian 16-byte array. - // (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.) - Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); - - // Generate whitening values for all blocks in the buffer - while (blockCount > 0) - { - if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) - endBlock = startBlock + (unsigned int) blockCount; - else - endBlock = BLOCKS_PER_XTS_DATA_UNIT; - - // Encrypt the data unit number using the secondary key (in order to generate the first - // whitening value for this data unit) - memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK); - EncipherBlock (cipher, whiteningValue, ks2); - - // Generate (and apply) subsequent whitening values for blocks in this data unit and - // encrypt/decrypt all relevant blocks in this data unit - for (block = 0; block < endBlock; block++) - { - if (block >= startBlock) - { - whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; - - // Whitening - *bufPtr32++ ^= *whiteningValuePtr32++; - *bufPtr32++ ^= *whiteningValuePtr32++; - *bufPtr32++ ^= *whiteningValuePtr32++; - *bufPtr32 ^= *whiteningValuePtr32; - - bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1; - - // Actual encryption/decryption - if (decryption) - DecipherBlock (cipher, bufPtr32, ks); - else - EncipherBlock (cipher, bufPtr32, ks); - - whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; - - // Whitening - *bufPtr32++ ^= *whiteningValuePtr32++; - *bufPtr32++ ^= *whiteningValuePtr32++; - *bufPtr32++ ^= *whiteningValuePtr32++; - *bufPtr32++ ^= *whiteningValuePtr32; - } - - // Derive the next whitening value - - finalCarry = 0; - - for (whiteningValuePtr32 = finalDwordWhiteningValuePtr; - whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue; - whiteningValuePtr32--) - { - if (*whiteningValuePtr32 & 0x80000000) // If the following shift results in a carry - { - if (whiteningValuePtr32 != finalDwordWhiteningValuePtr) // If not processing the highest double word - { - // A regular carry - *(whiteningValuePtr32 + 1) |= 1; - } - else - { - // The highest byte shift will result in a carry - finalCarry = 135; - } - } - - *whiteningValuePtr32 <<= 1; - } - - whiteningValue[0] ^= finalCarry; - } - - blockCount -= endBlock - startBlock; - startBlock = 0; - - // Increase the data unit number by one - if (!++dataUnitNo.LowPart) - { - dataUnitNo.HighPart++; - } - - // Convert the 64-bit data unit number into a little-endian 16-byte array. - Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); - } - - FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); -} - - -// For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS() above. -void EncryptBufferXTS (unsigned __int8 *buffer, - TC_LARGEST_COMPILER_UINT length, - const UINT64_STRUCT *startDataUnitNo, - unsigned int startCipherBlockNo, - unsigned __int8 *ks, - unsigned __int8 *ks2, - int cipher) -{ - // Encrypt all plaintext blocks in the buffer - EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, FALSE); -} - - -// For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS(). -void DecryptBufferXTS (unsigned __int8 *buffer, - TC_LARGEST_COMPILER_UINT length, - const UINT64_STRUCT *startDataUnitNo, - unsigned int startCipherBlockNo, - unsigned __int8 *ks, - unsigned __int8 *ks2, - int cipher) -{ - // Decrypt all ciphertext blocks in the buffer - EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, TRUE); -} - -#endif // TC_NO_COMPILER_INT64 +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +/* If native 64-bit data types are not available, define TC_NO_COMPILER_INT64. + +For big-endian platforms define BYTE_ORDER as BIG_ENDIAN. */ + + +#ifdef TC_MINIMIZE_CODE_SIZE +// Preboot/boot version +# ifndef TC_NO_COMPILER_INT64 +# define TC_NO_COMPILER_INT64 +# endif +# pragma optimize ("tl", on) +#endif + +#ifdef TC_NO_COMPILER_INT64 +# include +#endif + +#include "Xts.h" + + +#ifndef TC_NO_COMPILER_INT64 + +// length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size +// ks: the primary key schedule +// ks2: the secondary key schedule +// startDataUnitNo: The sequential number of the data unit with which the buffer starts. +// startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit startDataUnitNo. +// When encrypting the data unit from its first block, startCipherBlockNo is 0. +// The startCipherBlockNo value applies only to the first data unit in the buffer; each successive +// data unit is encrypted from its first block. The start of the buffer does not have to be +// aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it +// is not aligned, startCipherBlockNo must reflect the misalignment accordingly. +void EncryptBufferXTS (unsigned __int8 *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startCipherBlockNo, + unsigned __int8 *ks, + unsigned __int8 *ks2, + int cipher) +{ + unsigned __int8 finalCarry; + unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; + unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; + unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; + unsigned int startBlock = startCipherBlockNo, endBlock, block; + TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; + + /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the + finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block + number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented + as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if + the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is + derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */ + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. + dataUnitNo = startDataUnitNo->Value; + *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); + *((unsigned __int64 *) byteBufUnitNo + 1) = 0; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Process all blocks in the buffer + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); + *(whiteningValuePtr64 + 1) = 0; + EncipherBlock (cipher, whiteningValue, ks2); + + // Generate (and apply) subsequent whitening values for blocks in this data unit and + // encrypt all relevant blocks in this data unit + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + // Pre-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr-- ^= *whiteningValuePtr64--; + + // Actual encryption + EncipherBlock (cipher, bufPtr, ks); + + // Post-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr++ ^= *whiteningValuePtr64; + } + else + whiteningValuePtr64++; + + // Derive the next whitening value + +#if BYTE_ORDER == LITTLE_ENDIAN + + // Little-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x8000000000000000) ? + 135 : 0; + + *whiteningValuePtr64-- <<= 1; + + if (*whiteningValuePtr64 & 0x8000000000000000) + *(whiteningValuePtr64 + 1) |= 1; + + *whiteningValuePtr64 <<= 1; +#else + + // Big-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x80) ? + 135 : 0; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); + + whiteningValuePtr64--; + + if (*whiteningValuePtr64 & 0x80) + *(whiteningValuePtr64 + 1) |= 0x0100000000000000; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); +#endif + + whiteningValue[0] ^= finalCarry; + } + + blockCount -= endBlock - startBlock; + startBlock = 0; + dataUnitNo++; + *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); + } + + FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); +} + + +// For descriptions of the input parameters, see EncryptBufferXTS(). +void DecryptBufferXTS (unsigned __int8 *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startCipherBlockNo, + unsigned __int8 *ks, + unsigned __int8 *ks2, + int cipher) +{ + unsigned __int8 finalCarry; + unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; + unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; + unsigned __int64 *bufPtr = (unsigned __int64 *) buffer; + unsigned int startBlock = startCipherBlockNo, endBlock, block; + TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. + dataUnitNo = startDataUnitNo->Value; + *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); + *((unsigned __int64 *) byteBufUnitNo + 1) = 0; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Process all blocks in the buffer + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + whiteningValuePtr64 = (unsigned __int64 *) whiteningValue; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + *whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo); + *(whiteningValuePtr64 + 1) = 0; + EncipherBlock (cipher, whiteningValue, ks2); + + // Generate (and apply) subsequent whitening values for blocks in this data unit and + // decrypt all relevant blocks in this data unit + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + // Post-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr-- ^= *whiteningValuePtr64--; + + // Actual decryption + DecipherBlock (cipher, bufPtr, ks); + + // Pre-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr++ ^= *whiteningValuePtr64; + } + else + whiteningValuePtr64++; + + // Derive the next whitening value + +#if BYTE_ORDER == LITTLE_ENDIAN + + // Little-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x8000000000000000) ? + 135 : 0; + + *whiteningValuePtr64-- <<= 1; + + if (*whiteningValuePtr64 & 0x8000000000000000) + *(whiteningValuePtr64 + 1) |= 1; + + *whiteningValuePtr64 <<= 1; + +#else + // Big-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x80) ? + 135 : 0; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); + + whiteningValuePtr64--; + + if (*whiteningValuePtr64 & 0x80) + *(whiteningValuePtr64 + 1) |= 0x0100000000000000; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); +#endif + + whiteningValue[0] ^= finalCarry; + } + + blockCount -= endBlock - startBlock; + startBlock = 0; + dataUnitNo++; + *((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo); + } + + FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); +} + + + +#else // TC_NO_COMPILER_INT64 + +/* ---- The following code is to be used only when native 64-bit data types are not available. ---- */ + +#if BYTE_ORDER == BIG_ENDIAN +#error The TC_NO_COMPILER_INT64 version of the XTS code is not compatible with big-endian platforms +#endif + + +// Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit +// environments/platforms) into a little-endian 16-byte array. +static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32) +{ + unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf; + + *bufPtr32++ = lowInt32; + *bufPtr32++ = highInt32; + + // We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes + *bufPtr32++ = 0; + *bufPtr32 = 0; +} + + +// Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters, +// see the 64-bit version of EncryptBufferXTS(). +static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startBlock, + unsigned __int8 *ks, + unsigned __int8 *ks2, + int cipher, + BOOL decryption) +{ + TC_LARGEST_COMPILER_UINT blockCount; + UINT64_STRUCT dataUnitNo; + unsigned int block; + unsigned int endBlock; + unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK]; + unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer; + unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; + unsigned __int8 finalCarry; + unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1; + + // Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms + dataUnitNo.HighPart = startDataUnitNo->HighPart; + dataUnitNo.LowPart = startDataUnitNo->LowPart; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.) + Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); + + // Generate whitening values for all blocks in the buffer + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK); + EncipherBlock (cipher, whiteningValue, ks2); + + // Generate (and apply) subsequent whitening values for blocks in this data unit and + // encrypt/decrypt all relevant blocks in this data unit + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; + + // Whitening + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32 ^= *whiteningValuePtr32; + + bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1; + + // Actual encryption/decryption + if (decryption) + DecipherBlock (cipher, bufPtr32, ks); + else + EncipherBlock (cipher, bufPtr32, ks); + + whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; + + // Whitening + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32; + } + + // Derive the next whitening value + + finalCarry = 0; + + for (whiteningValuePtr32 = finalDwordWhiteningValuePtr; + whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue; + whiteningValuePtr32--) + { + if (*whiteningValuePtr32 & 0x80000000) // If the following shift results in a carry + { + if (whiteningValuePtr32 != finalDwordWhiteningValuePtr) // If not processing the highest double word + { + // A regular carry + *(whiteningValuePtr32 + 1) |= 1; + } + else + { + // The highest byte shift will result in a carry + finalCarry = 135; + } + } + + *whiteningValuePtr32 <<= 1; + } + + whiteningValue[0] ^= finalCarry; + } + + blockCount -= endBlock - startBlock; + startBlock = 0; + + // Increase the data unit number by one + if (!++dataUnitNo.LowPart) + { + dataUnitNo.HighPart++; + } + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); + } + + FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); +} + + +// For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS() above. +void EncryptBufferXTS (unsigned __int8 *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startCipherBlockNo, + unsigned __int8 *ks, + unsigned __int8 *ks2, + int cipher) +{ + // Encrypt all plaintext blocks in the buffer + EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, FALSE); +} + + +// For descriptions of the input parameters, see the 64-bit version of EncryptBufferXTS(). +void DecryptBufferXTS (unsigned __int8 *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startCipherBlockNo, + unsigned __int8 *ks, + unsigned __int8 *ks2, + int cipher) +{ + // Decrypt all ciphertext blocks in the buffer + EncryptDecryptBufferXTS32 (buffer, length, startDataUnitNo, startCipherBlockNo, ks, ks2, cipher, TRUE); +} + +#endif // TC_NO_COMPILER_INT64 diff --git a/Common/Xts.h b/Common/Xts.h index 945ff9b..81dd43f 100644 --- a/Common/Xts.h +++ b/Common/Xts.h @@ -1,76 +1,76 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef XTS_H -#define XTS_H - -// Header files (optional) - -#include "Tcdefs.h" -#include "Common/Endian.h" -#include "Crypto.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Macros - -#ifndef LITTLE_ENDIAN -# define LITTLE_ENDIAN 1 -#endif - -#ifndef BIG_ENDIAN -# define BIG_ENDIAN 2 -#endif - -#ifndef BYTE_ORDER -# define BYTE_ORDER LITTLE_ENDIAN -#endif - -#ifndef LE64 -# if BYTE_ORDER == LITTLE_ENDIAN -# define LE64(x) (x) -# endif -#endif - -// Custom data types - -#ifndef TC_LARGEST_COMPILER_UINT -# ifdef TC_NO_COMPILER_INT64 - typedef unsigned __int32 TC_LARGEST_COMPILER_UINT; -# else - typedef unsigned __int64 TC_LARGEST_COMPILER_UINT; -# endif -#endif - -#ifndef TCDEFS_H -typedef union -{ - struct - { - unsigned __int32 LowPart; - unsigned __int32 HighPart; - }; -# ifndef TC_NO_COMPILER_INT64 - unsigned __int64 Value; -# endif - -} UINT64_STRUCT; -#endif - -// Public function prototypes - -void EncryptBufferXTS (unsigned __int8 *buffer, TC_LARGEST_COMPILER_UINT length, const UINT64_STRUCT *startDataUnitNo, unsigned int startCipherBlockNo, unsigned __int8 *ks, unsigned __int8 *ks2, int cipher); -void DecryptBufferXTS (unsigned __int8 *buffer, TC_LARGEST_COMPILER_UINT length, const UINT64_STRUCT *startDataUnitNo, unsigned int startCipherBlockNo, unsigned __int8 *ks, unsigned __int8 *ks2, int cipher); - -#ifdef __cplusplus -} -#endif - -#endif // #ifndef XTS_H +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef XTS_H +#define XTS_H + +// Header files (optional) + +#include "Tcdefs.h" +#include "Common/Endian.h" +#include "Crypto.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Macros + +#ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN 1 +#endif + +#ifndef BIG_ENDIAN +# define BIG_ENDIAN 2 +#endif + +#ifndef BYTE_ORDER +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#ifndef LE64 +# if BYTE_ORDER == LITTLE_ENDIAN +# define LE64(x) (x) +# endif +#endif + +// Custom data types + +#ifndef TC_LARGEST_COMPILER_UINT +# ifdef TC_NO_COMPILER_INT64 + typedef unsigned __int32 TC_LARGEST_COMPILER_UINT; +# else + typedef unsigned __int64 TC_LARGEST_COMPILER_UINT; +# endif +#endif + +#ifndef TCDEFS_H +typedef union +{ + struct + { + unsigned __int32 LowPart; + unsigned __int32 HighPart; + }; +# ifndef TC_NO_COMPILER_INT64 + unsigned __int64 Value; +# endif + +} UINT64_STRUCT; +#endif + +// Public function prototypes + +void EncryptBufferXTS (unsigned __int8 *buffer, TC_LARGEST_COMPILER_UINT length, const UINT64_STRUCT *startDataUnitNo, unsigned int startCipherBlockNo, unsigned __int8 *ks, unsigned __int8 *ks2, int cipher); +void DecryptBufferXTS (unsigned __int8 *buffer, TC_LARGEST_COMPILER_UINT length, const UINT64_STRUCT *startDataUnitNo, unsigned int startCipherBlockNo, unsigned __int8 *ks, unsigned __int8 *ks2, int cipher); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef XTS_H diff --git a/Common/resource.h b/Common/resource.h index 1034b17..3099921 100644 --- a/Common/resource.h +++ b/Common/resource.h @@ -1,167 +1,168 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Common.rc -// -#define IDI_TRUECRYPT_ICON 501 -#define IDI_TRUECRYPT_VOL_ICON 502 -#define IDD_BENCHMARK_DLG 503 -#define IDD_MOUNT_OPTIONS 504 -#define IDD_KEYFILES 505 -#define IDR_LANGUAGE 506 -#define IDI_TRUECRYPT 507 -#define IDD_ABOUT_DLG 508 -#define IDD_COMMANDHELP_DLG 509 -#define IDD_RAWDEVICES_DLG 510 -#define IDC_HOMEPAGE 511 -#define IDR_COMMON_RSRC_HEADER 512 -#define IDD_LANGUAGE 513 -#define IDD_CIPHER_TEST_DLG 514 -#define IDR_LICENSE 515 -#define IDD_AUXILIARY_DLG 516 -#define IDB_TEXTUAL_LOGO_BKG 517 -#define IDB_TEXTUAL_LOGO_96DPI 518 -#define IDB_TEXTUAL_LOGO_288DPI 519 -#define IDR_BOOT_SECTOR 520 -#define IDR_BOOT_SECTOR_AES 521 -#define IDR_BOOT_SECTOR_SERPENT 522 -#define IDR_BOOT_SECTOR_TWOFISH 523 -#define IDR_BOOT_LOADER_DECOMPRESSOR 524 -#define IDR_BOOT_LOADER 525 -#define IDR_BOOT_LOADER_AES 526 -#define IDR_BOOT_LOADER_SERPENT 527 -#define IDR_BOOT_LOADER_TWOFISH 528 -#define IDR_RESCUE_BOOT_SECTOR 529 -#define IDR_RESCUE_BOOT_SECTOR_AES 530 -#define IDR_RESCUE_BOOT_SECTOR_SERPENT 531 -#define IDR_RESCUE_BOOT_SECTOR_TWOFISH 532 -#define IDR_RESCUE_LOADER 533 -#define IDR_RESCUE_LOADER_AES 534 -#define IDR_RESCUE_LOADER_SERPENT 535 -#define IDR_RESCUE_LOADER_TWOFISH 536 -#define IDD_TOKEN_PASSWORD 537 -#define IDD_TOKEN_KEYFILES 538 -#define IDD_NEW_TOKEN_KEYFILE 539 -#define IDD_RANDOM_POOL_ENRICHMENT 540 -#define IDT_TOKEN_PASSWORD 5000 -#define IDC_PRINT 5001 -#define IDC_KEY 5002 -#define IDC_PLAINTEXT 5003 -#define IDC_CIPHERTEXT 5004 -#define IDC_INFO_BOX_TEXT 5005 -#define IDC_SECONDARY_KEY 5006 -#define IDD_TEXT_INFO_DIALOG_BOX_DLG 5007 -#define IDC_TEST_DATA_UNIT_NUMBER 5008 -#define IDD_KEYFILE_GENERATOR 5009 -#define IDC_CIPHER 5010 -#define IDD_MULTI_CHOICE_DLG 5011 -#define IDC_TEST_BLOCK_NUMBER 5012 -#define IDC_POOL_CONTENTS 5013 -#define IDC_PRF_ID 5014 -#define IDC_KEY_SIZE 5015 -#define IDC_PLAINTEXT_SIZE 5016 -#define IDC_REDTICK 5017 -#define IDC_TESTS_MESSAGE 5018 -#define IDC_RESET 5019 -#define IDC_AUTO 5020 -#define IDC_DECRYPT 5021 -#define IDT_TEST_KEY 5022 -#define IDT_TEST_PLAINTEXT 5023 -#define IDT_PRF 5024 -#define IDT_XTS_MODE 5025 -#define IDT_TEST_CIPHERTEXT 5026 -#define IDT_KEY 5027 -#define IDT_PLAINTEXT 5028 -#define IDC_ENCRYPT 5029 -#define IDT_KEY_UNIT 5030 -#define IDT_CIPHER 5031 -#define IDT_PLAINTEXT_SIZE_UNIT 5032 -#define IDC_DEVICELIST 5033 -#define IDT_TEST_BLOCK_NUMBER 5034 -#define IDT_SECONDARY_KEY 5035 -#define IDC_PERFORM_BENCHMARK 5036 -#define IDT_TEST_DATA_UNIT_NUMBER 5037 -#define IDC_KEYFILES_HIDVOL_PROT 5038 -#define IDC_KEYLIST 5039 -#define IDC_ABOUT_BKG 5040 -#define IDT_ABOUT_VERSION 5041 -#define IDT_BOX_BENCHMARK_INFO 5042 -#define IDC_ABOUT_CREDITS 5043 -#define IDT_SORT_METHOD 5044 -#define IDC_MOUNT_READONLY 5045 -#define IDC_MOUNT_REMOVABLE 5046 -#define IDC_PROTECT_HIDDEN_VOL 5047 -#define IDC_COMMANDHELP_TEXT 5048 -#define IDC_USE_EMBEDDED_HEADER_BAK 5049 -#define IDC_MOUNT_SYSENC_PART_WITHOUT_PBA 5050 -#define IDT_HIDDEN_PROT_PASSWD 5051 -#define IDC_RESULTS 5052 -#define IDC_KEYADD 5053 -#define IDC_KEYREMOVE 5054 -#define IDC_KEYREMOVEALL 5055 -#define IDC_KEYFILES_ENABLE 5056 -#define IDT_HIDDEN_VOL_PROTECTION 5057 -#define IDC_ADD_KEYFILE_PATH 5058 -#define IDC_BENCHMARK_BUFFER_SIZE 5059 -#define IDC_SHOW_PASSWORD_MO 5060 -#define IDC_GENERATE_KEYFILE 5061 -#define IDC_BENCHMARK_SORT_METHOD 5062 -#define IDC_PASSWORD_PROT_HIDVOL 5063 -#define IDT_BUFFER_SIZE 5064 -#define IDC_LANGLIST 5065 -#define IDC_KEYFILES_ENABLE_HIDVOL_PROT 5066 -#define IDT_KEYFILES_NOTE 5067 -#define IDT_KEYFILE_WARNING 5068 -#define IDT_KEYFILE_GENERATOR_NOTE 5069 -#define IDC_GENERATE_AND_SAVE_KEYFILE 5070 -#define IDT_POOL_CONTENTS 5071 -#define IDC_GET_LANG_PACKS 5072 -#define IDT_LANGPACK_AUTHORS 5073 -#define IDC_LANGPACK_CREDITS 5074 -#define IDC_LANGPACK_VERSION 5075 -#define IDT_ACTIVE_LANG_PACK 5076 -#define IDC_DISPLAY_POOL_CONTENTS 5077 -#define IDC_XTS_MODE_ENABLED 5078 -#define IDC_MULTI_CHOICE_MSG 5079 -#define IDC_CHOICE1 5080 -#define IDC_CHOICE5 5081 -#define IDC_CHOICE2 5082 -#define IDC_CHOICE3 5083 -#define IDC_CHOICE4 5084 -#define IDC_CHOICE6 5085 -#define IDC_CHOICE7 5086 -#define IDC_CHOICE8 5087 -#define IDC_CHOICE9 5088 -#define IDC_CHOICE10 5089 -#define IDC_MC_DLG_HR1 5090 -#define IDC_MC_DLG_HR2 5091 -#define IDC_DONATIONS 5092 -#define IDC_LINK_HIDVOL_PROTECTION_INFO 5093 -#define IDC_LINK_KEYFILES_INFO 5094 -#define IDC_TEXTUAL_LOGO_IMG 5095 -#define IDC_ASPECT_RATIO_CALIBRATION_BOX 5096 -#define IDC_ABOUT_LOGO_AREA 5097 -#define IDC_TOKEN_PASSWORD 5098 -#define IDC_TOKEN_FILE_LIST 5099 -#define IDC_TOKEN_FILES_ADD 5100 -#define IDC_EXPORT 5101 -#define IDC_DELETE 5102 -#define IDC_IMPORT_KEYFILE 5103 -#define IDC_SELECTED_TOKEN 5104 -#define IDT_SECURITY_TOKEN 5105 -#define IDT_TOKEN_KEYFILE_NAME 5106 -#define IDC_TOKEN_KEYFILE_NAME 5107 -#define IDT_TOKEN_PASSWORD_INFO 5108 -#define IDT_RANDOM_POOL_ENRICHMENT_NOTE 5109 -#define IDC_CONTINUE 5110 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 541 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 5111 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Common.rc +// +#define IDI_TRUECRYPT_ICON 501 +#define IDI_TRUECRYPT_VOL_ICON 502 +#define IDD_BENCHMARK_DLG 503 +#define IDD_MOUNT_OPTIONS 504 +#define IDD_KEYFILES 505 +#define IDR_LANGUAGE 506 +#define IDI_TRUECRYPT 507 +#define IDD_ABOUT_DLG 508 +#define IDD_COMMANDHELP_DLG 509 +#define IDD_RAWDEVICES_DLG 510 +#define IDC_HOMEPAGE 511 +#define IDR_COMMON_RSRC_HEADER 512 +#define IDD_LANGUAGE 513 +#define IDD_CIPHER_TEST_DLG 514 +#define IDR_LICENSE 515 +#define IDD_AUXILIARY_DLG 516 +#define IDB_TEXTUAL_LOGO_BKG 517 +#define IDB_TEXTUAL_LOGO_96DPI 518 +#define IDB_TEXTUAL_LOGO_288DPI 519 +#define IDR_BOOT_SECTOR 520 +#define IDR_BOOT_SECTOR_AES 521 +#define IDR_BOOT_SECTOR_SERPENT 522 +#define IDR_BOOT_SECTOR_TWOFISH 523 +#define IDR_BOOT_LOADER_DECOMPRESSOR 524 +#define IDR_BOOT_LOADER 525 +#define IDR_BOOT_LOADER_AES 526 +#define IDR_BOOT_LOADER_SERPENT 527 +#define IDR_BOOT_LOADER_TWOFISH 528 +#define IDR_RESCUE_BOOT_SECTOR 529 +#define IDR_RESCUE_BOOT_SECTOR_AES 530 +#define IDR_RESCUE_BOOT_SECTOR_SERPENT 531 +#define IDR_RESCUE_BOOT_SECTOR_TWOFISH 532 +#define IDR_RESCUE_LOADER 533 +#define IDR_RESCUE_LOADER_AES 534 +#define IDR_RESCUE_LOADER_SERPENT 535 +#define IDR_RESCUE_LOADER_TWOFISH 536 +#define IDD_TOKEN_PASSWORD 537 +#define IDD_TOKEN_KEYFILES 538 +#define IDD_NEW_TOKEN_KEYFILE 539 +#define IDD_RANDOM_POOL_ENRICHMENT 540 +#define IDT_TOKEN_PASSWORD 5000 +#define IDC_PRINT 5001 +#define IDC_KEY 5002 +#define IDC_PLAINTEXT 5003 +#define IDC_CIPHERTEXT 5004 +#define IDC_INFO_BOX_TEXT 5005 +#define IDC_SECONDARY_KEY 5006 +#define IDD_TEXT_INFO_DIALOG_BOX_DLG 5007 +#define IDC_TEST_DATA_UNIT_NUMBER 5008 +#define IDD_KEYFILE_GENERATOR 5009 +#define IDC_CIPHER 5010 +#define IDD_MULTI_CHOICE_DLG 5011 +#define IDC_TEST_BLOCK_NUMBER 5012 +#define IDC_POOL_CONTENTS 5013 +#define IDC_PRF_ID 5014 +#define IDC_KEY_SIZE 5015 +#define IDC_PLAINTEXT_SIZE 5016 +#define IDC_REDTICK 5017 +#define IDC_TESTS_MESSAGE 5018 +#define IDC_RESET 5019 +#define IDC_AUTO 5020 +#define IDC_DECRYPT 5021 +#define IDT_TEST_KEY 5022 +#define IDT_TEST_PLAINTEXT 5023 +#define IDT_PRF 5024 +#define IDT_XTS_MODE 5025 +#define IDT_TEST_CIPHERTEXT 5026 +#define IDT_KEY 5027 +#define IDT_PLAINTEXT 5028 +#define IDC_ENCRYPT 5029 +#define IDT_KEY_UNIT 5030 +#define IDT_CIPHER 5031 +#define IDT_PLAINTEXT_SIZE_UNIT 5032 +#define IDC_DEVICELIST 5033 +#define IDT_TEST_BLOCK_NUMBER 5034 +#define IDT_SECONDARY_KEY 5035 +#define IDC_PERFORM_BENCHMARK 5036 +#define IDT_TEST_DATA_UNIT_NUMBER 5037 +#define IDC_KEYFILES_HIDVOL_PROT 5038 +#define IDC_KEYLIST 5039 +#define IDC_ABOUT_BKG 5040 +#define IDT_ABOUT_VERSION 5041 +#define IDT_BOX_BENCHMARK_INFO 5042 +#define IDC_ABOUT_CREDITS 5043 +#define IDT_SORT_METHOD 5044 +#define IDC_MOUNT_READONLY 5045 +#define IDC_MOUNT_REMOVABLE 5046 +#define IDC_PROTECT_HIDDEN_VOL 5047 +#define IDC_COMMANDHELP_TEXT 5048 +#define IDC_USE_EMBEDDED_HEADER_BAK 5049 +#define IDC_MOUNT_SYSENC_PART_WITHOUT_PBA 5050 +#define IDT_HIDDEN_PROT_PASSWD 5051 +#define IDC_RESULTS 5052 +#define IDC_KEYADD 5053 +#define IDC_KEYREMOVE 5054 +#define IDC_KEYREMOVEALL 5055 +#define IDC_KEYFILES_ENABLE 5056 +#define IDT_HIDDEN_VOL_PROTECTION 5057 +#define IDC_ADD_KEYFILE_PATH 5058 +#define IDC_BENCHMARK_BUFFER_SIZE 5059 +#define IDC_SHOW_PASSWORD_MO 5060 +#define IDC_GENERATE_KEYFILE 5061 +#define IDC_BENCHMARK_SORT_METHOD 5062 +#define IDC_PASSWORD_PROT_HIDVOL 5063 +#define IDT_BUFFER_SIZE 5064 +#define IDC_LANGLIST 5065 +#define IDC_KEYFILES_ENABLE_HIDVOL_PROT 5066 +#define IDT_KEYFILES_NOTE 5067 +#define IDT_KEYFILE_WARNING 5068 +#define IDT_KEYFILE_GENERATOR_NOTE 5069 +#define IDC_GENERATE_AND_SAVE_KEYFILE 5070 +#define IDT_POOL_CONTENTS 5071 +#define IDC_GET_LANG_PACKS 5072 +#define IDT_LANGPACK_AUTHORS 5073 +#define IDC_LANGPACK_CREDITS 5074 +#define IDC_LANGPACK_VERSION 5075 +#define IDT_ACTIVE_LANG_PACK 5076 +#define IDC_DISPLAY_POOL_CONTENTS 5077 +#define IDC_XTS_MODE_ENABLED 5078 +#define IDC_MULTI_CHOICE_MSG 5079 +#define IDC_CHOICE1 5080 +#define IDC_CHOICE5 5081 +#define IDC_CHOICE2 5082 +#define IDC_CHOICE3 5083 +#define IDC_CHOICE4 5084 +#define IDC_CHOICE6 5085 +#define IDC_CHOICE7 5086 +#define IDC_CHOICE8 5087 +#define IDC_CHOICE9 5088 +#define IDC_CHOICE10 5089 +#define IDC_MC_DLG_HR1 5090 +#define IDC_MC_DLG_HR2 5091 +#define IDC_DONATIONS 5092 +#define IDC_LINK_HIDVOL_PROTECTION_INFO 5093 +#define IDC_LINK_KEYFILES_INFO 5094 +#define IDC_TEXTUAL_LOGO_IMG 5095 +#define IDC_ASPECT_RATIO_CALIBRATION_BOX 5096 +#define IDC_ABOUT_LOGO_AREA 5097 +#define IDC_TOKEN_PASSWORD 5098 +#define IDC_TOKEN_FILE_LIST 5099 +#define IDC_TOKEN_FILES_ADD 5100 +#define IDC_EXPORT 5101 +#define IDC_DELETE 5102 +#define IDC_IMPORT_KEYFILE 5103 +#define IDC_SELECTED_TOKEN 5104 +#define IDT_SECURITY_TOKEN 5105 +#define IDT_TOKEN_KEYFILE_NAME 5106 +#define IDC_TOKEN_KEYFILE_NAME 5107 +#define IDT_TOKEN_PASSWORD_INFO 5108 +#define IDT_RANDOM_POOL_ENRICHMENT_NOTE 5109 +#define IDC_CONTINUE 5110 +#define IDT_ABOUT_RELEASE 5111 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 541 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 5112 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Core/Core.h b/Core/Core.h index fe99084..4686d0b 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -1,20 +1,20 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_Core -#define TC_HEADER_Core_Core - -#include "CoreBase.h" - -namespace TrueCrypt -{ - extern auto_ptr Core; - extern auto_ptr CoreDirect; -} - -#endif // TC_HEADER_Core_Core +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_Core +#define TC_HEADER_Core_Core + +#include "CoreBase.h" + +namespace TrueCrypt +{ + extern auto_ptr Core; + extern auto_ptr CoreDirect; +} + +#endif // TC_HEADER_Core_Core diff --git a/Core/Core.make b/Core/Core.make index 142e8b4..6812abb 100644 --- a/Core/Core.make +++ b/Core/Core.make @@ -1,27 +1,27 @@ -# -# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -OBJS := -OBJS += CoreBase.o -OBJS += CoreException.o -OBJS += FatFormatter.o -OBJS += HostDevice.o -OBJS += MountOptions.o -OBJS += RandomNumberGenerator.o -OBJS += VolumeCreator.o -OBJS += Unix/CoreService.o -OBJS += Unix/CoreServiceRequest.o -OBJS += Unix/CoreServiceResponse.o -OBJS += Unix/CoreUnix.o -OBJS += Unix/$(PLATFORM)/Core$(PLATFORM).o -OBJS += Unix/$(PLATFORM)/Core$(PLATFORM).o -ifeq "$(PLATFORM)" "MacOSX" -OBJS += Unix/FreeBSD/CoreFreeBSD.o -endif - -include $(BUILD_INC)/Makefile.inc +# +# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +OBJS := +OBJS += CoreBase.o +OBJS += CoreException.o +OBJS += FatFormatter.o +OBJS += HostDevice.o +OBJS += MountOptions.o +OBJS += RandomNumberGenerator.o +OBJS += VolumeCreator.o +OBJS += Unix/CoreService.o +OBJS += Unix/CoreServiceRequest.o +OBJS += Unix/CoreServiceResponse.o +OBJS += Unix/CoreUnix.o +OBJS += Unix/$(PLATFORM)/Core$(PLATFORM).o +OBJS += Unix/$(PLATFORM)/Core$(PLATFORM).o +ifeq "$(PLATFORM)" "MacOSX" +OBJS += Unix/FreeBSD/CoreFreeBSD.o +endif + +include $(BUILD_INC)/Makefile.inc diff --git a/Core/CoreBase.cpp b/Core/CoreBase.cpp index 4f3025b..9b3630d 100644 --- a/Core/CoreBase.cpp +++ b/Core/CoreBase.cpp @@ -1,203 +1,203 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include - -#include "CoreBase.h" -#include "RandomNumberGenerator.h" -#include "Volume/Volume.h" - -namespace TrueCrypt -{ - CoreBase::CoreBase () - : DeviceChangeInProgress (false) - { - } - - CoreBase::~CoreBase () - { - } - - void CoreBase::ChangePassword (shared_ptr openVolume, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf) const - { - if ((!newPassword || newPassword->Size() < 1) && (!newKeyfiles || newKeyfiles->empty())) - throw PasswordEmpty (SRC_POS); - - if (!newPkcs5Kdf) - newPkcs5Kdf = openVolume->GetPkcs5Kdf(); - - if ((openVolume->GetHeader()->GetFlags() & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) != 0 - && openVolume->GetType() == VolumeType::Hidden - && openVolume->GetPath().IsDevice()) - { - throw EncryptedSystemRequired (SRC_POS); - } - - RandomNumberGenerator::SetHash (newPkcs5Kdf->GetHash()); - - SecureBuffer newSalt (openVolume->GetSaltSize()); - SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); - - shared_ptr password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword)); - - bool backupHeader = false; - while (true) - { - for (int i = 1; i <= SecureWipePassCount; i++) - { - if (i == SecureWipePassCount) - RandomNumberGenerator::GetData (newSalt); - else - RandomNumberGenerator::GetDataFast (newSalt); - - newPkcs5Kdf->DeriveKey (newHeaderKey, *password, newSalt); - - openVolume->ReEncryptHeader (backupHeader, newSalt, newHeaderKey, newPkcs5Kdf); - openVolume->GetFile()->Flush(); - } - - if (!openVolume->GetLayout()->HasBackupHeader() || backupHeader) - break; - - backupHeader = true; - } - } - - void CoreBase::ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf) const - { - shared_ptr volume = OpenVolume (volumePath, preserveTimestamps, password, keyfiles); - ChangePassword (volume, newPassword, newKeyfiles, newPkcs5Kdf); - } - - void CoreBase::CoalesceSlotNumberAndMountPoint (MountOptions &options) const - { - if (options.SlotNumber < GetFirstSlotNumber()) - { - if (options.MountPoint && !options.MountPoint->IsEmpty()) - options.SlotNumber = MountPointToSlotNumber (*options.MountPoint); - else - options.SlotNumber = GetFirstFreeSlotNumber(); - } - - if (!IsSlotNumberAvailable (options.SlotNumber)) -#ifdef TC_WINDOWS - throw DriveLetterUnavailable (SRC_POS); -#else - throw VolumeSlotUnavailable (SRC_POS); -#endif - if (!options.NoFilesystem && (!options.MountPoint || options.MountPoint->IsEmpty())) - options.MountPoint.reset (new DirectoryPath (SlotNumberToMountPoint (options.SlotNumber))); - } - - void CoreBase::CreateKeyfile (const FilePath &keyfilePath) const - { - SecureBuffer keyfileBuffer (VolumePassword::MaxSize); - RandomNumberGenerator::GetData (keyfileBuffer); - - File keyfile; - keyfile.Open (keyfilePath, File::CreateWrite); - keyfile.Write (keyfileBuffer); - } - - VolumeSlotNumber CoreBase::GetFirstFreeSlotNumber (VolumeSlotNumber startFrom) const - { - if (startFrom < GetFirstSlotNumber()) - startFrom = GetFirstSlotNumber(); - - set usedSlotNumbers; - - foreach_ref (const VolumeInfo &volume, GetMountedVolumes()) - usedSlotNumbers.insert (volume.SlotNumber); - - for (VolumeSlotNumber slotNumber = startFrom; slotNumber <= GetLastSlotNumber(); ++slotNumber) - { - if (usedSlotNumbers.find (slotNumber) == usedSlotNumbers.end() - && IsMountPointAvailable (SlotNumberToMountPoint (slotNumber))) - return slotNumber; - } -#ifdef TC_WINDOWS - throw DriveLetterUnavailable (SRC_POS); -#else - throw VolumeSlotUnavailable (SRC_POS); -#endif - } - - shared_ptr CoreBase::GetMountedVolume (const VolumePath &volumePath) const - { - VolumeInfoList volumes = GetMountedVolumes (volumePath); - if (volumes.empty()) - return shared_ptr (); - else - return volumes.front(); - } - - shared_ptr CoreBase::GetMountedVolume (VolumeSlotNumber slot) const - { - foreach (shared_ptr volume, GetMountedVolumes()) - { - if (volume->SlotNumber == slot) - return volume; - } - - return shared_ptr (); - } - - bool CoreBase::IsSlotNumberAvailable (VolumeSlotNumber slotNumber) const - { - if (!IsMountPointAvailable (SlotNumberToMountPoint (slotNumber))) - return false; - - foreach_ref (const VolumeInfo &volume, GetMountedVolumes()) - { - if (volume.SlotNumber == slotNumber) - return false; - } - - return true; - } - - bool CoreBase::IsVolumeMounted (const VolumePath &volumePath) const - { - return GetMountedVolume (volumePath); - } - - shared_ptr CoreBase::OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const - { - make_shared_auto (Volume, volume); - volume->Open (*volumePath, preserveTimestamps, password, keyfiles, protection, protectionPassword, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); - return volume; - } - - void CoreBase::RandomizeEncryptionAlgorithmKey (shared_ptr encryptionAlgorithm) const - { - SecureBuffer eaKey (encryptionAlgorithm->GetKeySize()); - RandomNumberGenerator::GetData (eaKey); - encryptionAlgorithm->SetKey (eaKey); - - SecureBuffer modeKey (encryptionAlgorithm->GetMode()->GetKeySize()); - RandomNumberGenerator::GetData (modeKey); - encryptionAlgorithm->GetMode()->SetKey (modeKey); - } - - void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, shared_ptr keyfiles) const - { - shared_ptr pkcs5Kdf = header->GetPkcs5Kdf(); - - RandomNumberGenerator::SetHash (pkcs5Kdf->GetHash()); - - SecureBuffer newSalt (header->GetSaltSize()); - SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); - - shared_ptr passwordKey (Keyfile::ApplyListToPassword (keyfiles, password)); - - RandomNumberGenerator::GetData (newSalt); - pkcs5Kdf->DeriveKey (newHeaderKey, *passwordKey, newSalt); - - header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, pkcs5Kdf); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include + +#include "CoreBase.h" +#include "RandomNumberGenerator.h" +#include "Volume/Volume.h" + +namespace TrueCrypt +{ + CoreBase::CoreBase () + : DeviceChangeInProgress (false) + { + } + + CoreBase::~CoreBase () + { + } + + void CoreBase::ChangePassword (shared_ptr openVolume, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf) const + { + if ((!newPassword || newPassword->Size() < 1) && (!newKeyfiles || newKeyfiles->empty())) + throw PasswordEmpty (SRC_POS); + + if (!newPkcs5Kdf) + newPkcs5Kdf = openVolume->GetPkcs5Kdf(); + + if ((openVolume->GetHeader()->GetFlags() & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) != 0 + && openVolume->GetType() == VolumeType::Hidden + && openVolume->GetPath().IsDevice()) + { + throw EncryptedSystemRequired (SRC_POS); + } + + RandomNumberGenerator::SetHash (newPkcs5Kdf->GetHash()); + + SecureBuffer newSalt (openVolume->GetSaltSize()); + SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); + + shared_ptr password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword)); + + bool backupHeader = false; + while (true) + { + for (int i = 1; i <= SecureWipePassCount; i++) + { + if (i == SecureWipePassCount) + RandomNumberGenerator::GetData (newSalt); + else + RandomNumberGenerator::GetDataFast (newSalt); + + newPkcs5Kdf->DeriveKey (newHeaderKey, *password, newSalt); + + openVolume->ReEncryptHeader (backupHeader, newSalt, newHeaderKey, newPkcs5Kdf); + openVolume->GetFile()->Flush(); + } + + if (!openVolume->GetLayout()->HasBackupHeader() || backupHeader) + break; + + backupHeader = true; + } + } + + void CoreBase::ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf) const + { + shared_ptr volume = OpenVolume (volumePath, preserveTimestamps, password, keyfiles); + ChangePassword (volume, newPassword, newKeyfiles, newPkcs5Kdf); + } + + void CoreBase::CoalesceSlotNumberAndMountPoint (MountOptions &options) const + { + if (options.SlotNumber < GetFirstSlotNumber()) + { + if (options.MountPoint && !options.MountPoint->IsEmpty()) + options.SlotNumber = MountPointToSlotNumber (*options.MountPoint); + else + options.SlotNumber = GetFirstFreeSlotNumber(); + } + + if (!IsSlotNumberAvailable (options.SlotNumber)) +#ifdef TC_WINDOWS + throw DriveLetterUnavailable (SRC_POS); +#else + throw VolumeSlotUnavailable (SRC_POS); +#endif + if (!options.NoFilesystem && (!options.MountPoint || options.MountPoint->IsEmpty())) + options.MountPoint.reset (new DirectoryPath (SlotNumberToMountPoint (options.SlotNumber))); + } + + void CoreBase::CreateKeyfile (const FilePath &keyfilePath) const + { + SecureBuffer keyfileBuffer (VolumePassword::MaxSize); + RandomNumberGenerator::GetData (keyfileBuffer); + + File keyfile; + keyfile.Open (keyfilePath, File::CreateWrite); + keyfile.Write (keyfileBuffer); + } + + VolumeSlotNumber CoreBase::GetFirstFreeSlotNumber (VolumeSlotNumber startFrom) const + { + if (startFrom < GetFirstSlotNumber()) + startFrom = GetFirstSlotNumber(); + + set usedSlotNumbers; + + foreach_ref (const VolumeInfo &volume, GetMountedVolumes()) + usedSlotNumbers.insert (volume.SlotNumber); + + for (VolumeSlotNumber slotNumber = startFrom; slotNumber <= GetLastSlotNumber(); ++slotNumber) + { + if (usedSlotNumbers.find (slotNumber) == usedSlotNumbers.end() + && IsMountPointAvailable (SlotNumberToMountPoint (slotNumber))) + return slotNumber; + } +#ifdef TC_WINDOWS + throw DriveLetterUnavailable (SRC_POS); +#else + throw VolumeSlotUnavailable (SRC_POS); +#endif + } + + shared_ptr CoreBase::GetMountedVolume (const VolumePath &volumePath) const + { + VolumeInfoList volumes = GetMountedVolumes (volumePath); + if (volumes.empty()) + return shared_ptr (); + else + return volumes.front(); + } + + shared_ptr CoreBase::GetMountedVolume (VolumeSlotNumber slot) const + { + foreach (shared_ptr volume, GetMountedVolumes()) + { + if (volume->SlotNumber == slot) + return volume; + } + + return shared_ptr (); + } + + bool CoreBase::IsSlotNumberAvailable (VolumeSlotNumber slotNumber) const + { + if (!IsMountPointAvailable (SlotNumberToMountPoint (slotNumber))) + return false; + + foreach_ref (const VolumeInfo &volume, GetMountedVolumes()) + { + if (volume.SlotNumber == slotNumber) + return false; + } + + return true; + } + + bool CoreBase::IsVolumeMounted (const VolumePath &volumePath) const + { + return GetMountedVolume (volumePath); + } + + shared_ptr CoreBase::OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const + { + make_shared_auto (Volume, volume); + volume->Open (*volumePath, preserveTimestamps, password, keyfiles, protection, protectionPassword, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); + return volume; + } + + void CoreBase::RandomizeEncryptionAlgorithmKey (shared_ptr encryptionAlgorithm) const + { + SecureBuffer eaKey (encryptionAlgorithm->GetKeySize()); + RandomNumberGenerator::GetData (eaKey); + encryptionAlgorithm->SetKey (eaKey); + + SecureBuffer modeKey (encryptionAlgorithm->GetMode()->GetKeySize()); + RandomNumberGenerator::GetData (modeKey); + encryptionAlgorithm->GetMode()->SetKey (modeKey); + } + + void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, shared_ptr keyfiles) const + { + shared_ptr pkcs5Kdf = header->GetPkcs5Kdf(); + + RandomNumberGenerator::SetHash (pkcs5Kdf->GetHash()); + + SecureBuffer newSalt (header->GetSaltSize()); + SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); + + shared_ptr passwordKey (Keyfile::ApplyListToPassword (keyfiles, password)); + + RandomNumberGenerator::GetData (newSalt); + pkcs5Kdf->DeriveKey (newHeaderKey, *passwordKey, newSalt); + + header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, pkcs5Kdf); + } +} diff --git a/Core/CoreBase.h b/Core/CoreBase.h index 38877ca..8565ace 100644 --- a/Core/CoreBase.h +++ b/Core/CoreBase.h @@ -1,97 +1,97 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_CoreBase -#define TC_HEADER_Core_CoreBase - -#include "Platform/Platform.h" -#include "Platform/Functor.h" -#include "Platform/User.h" -#include "Common/Crypto.h" -#include "Volume/Keyfile.h" -#include "Volume/VolumeInfo.h" -#include "Volume/Volume.h" -#include "Volume/VolumePassword.h" -#include "CoreException.h" -#include "HostDevice.h" -#include "MountOptions.h" - -namespace TrueCrypt -{ - class CoreBase - { - public: - virtual ~CoreBase (); - - virtual void ChangePassword (shared_ptr openVolume, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf = shared_ptr ()) const; - virtual void ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf = shared_ptr ()) const; - virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const = 0; - virtual void CoalesceSlotNumberAndMountPoint (MountOptions &options) const; - virtual void CreateKeyfile (const FilePath &keyfilePath) const; - virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const = 0; - virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false) = 0; - virtual bool FilesystemSupportsLargeFiles (const FilePath &filePath) const = 0; - virtual DirectoryPath GetDeviceMountPoint (const DevicePath &devicePath) const = 0; - virtual VolumeSlotNumber GetFirstFreeSlotNumber (VolumeSlotNumber startFrom = 0) const; - virtual VolumeSlotNumber GetFirstSlotNumber () const { return 1; } - virtual VolumeSlotNumber GetLastSlotNumber () const { return 32; } - virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const = 0; - virtual FilePath GetApplicationExecutablePath () const { return ApplicationExecutablePath; } - virtual uint64 GetDeviceSize (const DevicePath &devicePath) const = 0; - virtual int GetOSMajorVersion () const = 0; - virtual int GetOSMinorVersion () const = 0; - virtual shared_ptr GetMountedVolume (const VolumePath &volumePath) const; - virtual shared_ptr GetMountedVolume (VolumeSlotNumber slot) const; - virtual VolumeInfoList GetMountedVolumes (const VolumePath &volumePath = VolumePath()) const = 0; - virtual bool HasAdminPrivileges () const = 0; - virtual void Init () { } - virtual bool IsDeviceChangeInProgress () const { return DeviceChangeInProgress; } - virtual bool IsDevicePresent (const DevicePath &device) const = 0; - virtual bool IsInTravelMode () const = 0; - virtual bool IsMountPointAvailable (const DirectoryPath &mountPoint) const = 0; - virtual bool IsOSVersion (int major, int minor) const = 0; - virtual bool IsOSVersionLower (int major, int minor) const = 0; - virtual bool IsPasswordCacheEmpty () const = 0; - virtual bool IsSlotNumberAvailable (VolumeSlotNumber slotNumber) const; - virtual bool IsSlotNumberValid (VolumeSlotNumber slotNumber) const { return slotNumber >= GetFirstSlotNumber() && slotNumber <= GetLastSlotNumber(); } - virtual bool IsVolumeMounted (const VolumePath &volumePath) const; - virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const = 0; - virtual shared_ptr MountVolume (MountOptions &options) = 0; - virtual shared_ptr OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const; - virtual void RandomizeEncryptionAlgorithmKey (shared_ptr encryptionAlgorithm) const; - virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, shared_ptr keyfiles) const; - virtual void SetAdminPasswordCallback (shared_ptr functor) { } - virtual void SetApplicationExecutablePath (const FilePath &path) { ApplicationExecutablePath = path; } - virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const = 0; - virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const = 0; - virtual void WipePasswordCache () const = 0; - - Event VolumeDismountedEvent; - Event VolumeMountedEvent; - Event WarningEvent; - - protected: - CoreBase (); - - static const int SecureWipePassCount = PRAND_DISK_WIPE_PASSES; - bool DeviceChangeInProgress; - FilePath ApplicationExecutablePath; - - private: - CoreBase (const CoreBase &); - CoreBase &operator= (const CoreBase &); - }; - - struct VolumeEventArgs : EventArgs - { - VolumeEventArgs (shared_ptr volume) : mVolume (volume) { } - shared_ptr mVolume; - }; -} - -#endif // TC_HEADER_Core_CoreBase +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_CoreBase +#define TC_HEADER_Core_CoreBase + +#include "Platform/Platform.h" +#include "Platform/Functor.h" +#include "Platform/User.h" +#include "Common/Crypto.h" +#include "Volume/Keyfile.h" +#include "Volume/VolumeInfo.h" +#include "Volume/Volume.h" +#include "Volume/VolumePassword.h" +#include "CoreException.h" +#include "HostDevice.h" +#include "MountOptions.h" + +namespace TrueCrypt +{ + class CoreBase + { + public: + virtual ~CoreBase (); + + virtual void ChangePassword (shared_ptr openVolume, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf = shared_ptr ()) const; + virtual void ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf = shared_ptr ()) const; + virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const = 0; + virtual void CoalesceSlotNumberAndMountPoint (MountOptions &options) const; + virtual void CreateKeyfile (const FilePath &keyfilePath) const; + virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const = 0; + virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false) = 0; + virtual bool FilesystemSupportsLargeFiles (const FilePath &filePath) const = 0; + virtual DirectoryPath GetDeviceMountPoint (const DevicePath &devicePath) const = 0; + virtual VolumeSlotNumber GetFirstFreeSlotNumber (VolumeSlotNumber startFrom = 0) const; + virtual VolumeSlotNumber GetFirstSlotNumber () const { return 1; } + virtual VolumeSlotNumber GetLastSlotNumber () const { return 64; } + virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const = 0; + virtual FilePath GetApplicationExecutablePath () const { return ApplicationExecutablePath; } + virtual uint64 GetDeviceSize (const DevicePath &devicePath) const = 0; + virtual int GetOSMajorVersion () const = 0; + virtual int GetOSMinorVersion () const = 0; + virtual shared_ptr GetMountedVolume (const VolumePath &volumePath) const; + virtual shared_ptr GetMountedVolume (VolumeSlotNumber slot) const; + virtual VolumeInfoList GetMountedVolumes (const VolumePath &volumePath = VolumePath()) const = 0; + virtual bool HasAdminPrivileges () const = 0; + virtual void Init () { } + virtual bool IsDeviceChangeInProgress () const { return DeviceChangeInProgress; } + virtual bool IsDevicePresent (const DevicePath &device) const = 0; + virtual bool IsInPortableMode () const = 0; + virtual bool IsMountPointAvailable (const DirectoryPath &mountPoint) const = 0; + virtual bool IsOSVersion (int major, int minor) const = 0; + virtual bool IsOSVersionLower (int major, int minor) const = 0; + virtual bool IsPasswordCacheEmpty () const = 0; + virtual bool IsSlotNumberAvailable (VolumeSlotNumber slotNumber) const; + virtual bool IsSlotNumberValid (VolumeSlotNumber slotNumber) const { return slotNumber >= GetFirstSlotNumber() && slotNumber <= GetLastSlotNumber(); } + virtual bool IsVolumeMounted (const VolumePath &volumePath) const; + virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const = 0; + virtual shared_ptr MountVolume (MountOptions &options) = 0; + virtual shared_ptr OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const; + virtual void RandomizeEncryptionAlgorithmKey (shared_ptr encryptionAlgorithm) const; + virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, shared_ptr keyfiles) const; + virtual void SetAdminPasswordCallback (shared_ptr functor) { } + virtual void SetApplicationExecutablePath (const FilePath &path) { ApplicationExecutablePath = path; } + virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const = 0; + virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const = 0; + virtual void WipePasswordCache () const = 0; + + Event VolumeDismountedEvent; + Event VolumeMountedEvent; + Event WarningEvent; + + protected: + CoreBase (); + + static const int SecureWipePassCount = PRAND_DISK_WIPE_PASSES; + bool DeviceChangeInProgress; + FilePath ApplicationExecutablePath; + + private: + CoreBase (const CoreBase &); + CoreBase &operator= (const CoreBase &); + }; + + struct VolumeEventArgs : EventArgs + { + VolumeEventArgs (shared_ptr volume) : mVolume (volume) { } + shared_ptr mVolume; + }; +} + +#endif // TC_HEADER_Core_CoreBase diff --git a/Core/CoreException.cpp b/Core/CoreException.cpp index bc295c6..037f7ee 100644 --- a/Core/CoreException.cpp +++ b/Core/CoreException.cpp @@ -1,29 +1,29 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "CoreException.h" -#include "Platform/SerializerFactory.h" - -namespace TrueCrypt -{ - void ElevationFailed::Deserialize (shared_ptr stream) - { - ExecutedProcessFailed::Deserialize (stream); - } - - void ElevationFailed::Serialize (shared_ptr stream) const - { - ExecutedProcessFailed::Serialize (stream); - } - -#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -#undef TC_EXCEPTION_NODECL -#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (CoreException); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "CoreException.h" +#include "Platform/SerializerFactory.h" + +namespace TrueCrypt +{ + void ElevationFailed::Deserialize (shared_ptr stream) + { + ExecutedProcessFailed::Deserialize (stream); + } + + void ElevationFailed::Serialize (shared_ptr stream) const + { + ExecutedProcessFailed::Serialize (stream); + } + +#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +#undef TC_EXCEPTION_NODECL +#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (CoreException); +} diff --git a/Core/CoreException.h b/Core/CoreException.h index 0581439..c719d17 100644 --- a/Core/CoreException.h +++ b/Core/CoreException.h @@ -1,50 +1,51 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_CoreException -#define TC_HEADER_Core_CoreException - -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - struct ElevationFailed : public ExecutedProcessFailed - { - ElevationFailed () { } - ElevationFailed (const string &message, const string &command, int exitCode, const string &errorOutput) - : ExecutedProcessFailed (message, command, exitCode, errorOutput) { } - TC_SERIALIZABLE_EXCEPTION (ElevationFailed); - }; - - TC_EXCEPTION_DECL (RootDeviceUnavailable, SystemException); - -#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) - -#undef TC_EXCEPTION_SET -#define TC_EXCEPTION_SET \ - TC_EXCEPTION_NODECL (ElevationFailed); \ - TC_EXCEPTION_NODECL (RootDeviceUnavailable); \ - TC_EXCEPTION (DriveLetterUnavailable); \ - TC_EXCEPTION (DriverError); \ - TC_EXCEPTION (EncryptedSystemRequired); \ - TC_EXCEPTION (HigherFuseVersionRequired); \ - TC_EXCEPTION (KernelCryptoServiceTestFailed); \ - TC_EXCEPTION (LoopDeviceSetupFailed); \ - TC_EXCEPTION (MountPointRequired); \ - TC_EXCEPTION (MountPointUnavailable); \ - TC_EXCEPTION (NoDriveLetterAvailable); \ - TC_EXCEPTION (UnsupportedSectorSize); \ - TC_EXCEPTION (VolumeAlreadyMounted); \ - TC_EXCEPTION (VolumeSlotUnavailable); - - TC_EXCEPTION_SET; - -#undef TC_EXCEPTION -} - -#endif // TC_HEADER_Core_CoreException +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_CoreException +#define TC_HEADER_Core_CoreException + +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + struct ElevationFailed : public ExecutedProcessFailed + { + ElevationFailed () { } + ElevationFailed (const string &message, const string &command, int exitCode, const string &errorOutput) + : ExecutedProcessFailed (message, command, exitCode, errorOutput) { } + TC_SERIALIZABLE_EXCEPTION (ElevationFailed); + }; + + TC_EXCEPTION_DECL (RootDeviceUnavailable, SystemException); + +#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) + +#undef TC_EXCEPTION_SET +#define TC_EXCEPTION_SET \ + TC_EXCEPTION_NODECL (ElevationFailed); \ + TC_EXCEPTION_NODECL (RootDeviceUnavailable); \ + TC_EXCEPTION (DriveLetterUnavailable); \ + TC_EXCEPTION (DriverError); \ + TC_EXCEPTION (EncryptedSystemRequired); \ + TC_EXCEPTION (HigherFuseVersionRequired); \ + TC_EXCEPTION (KernelCryptoServiceTestFailed); \ + TC_EXCEPTION (LoopDeviceSetupFailed); \ + TC_EXCEPTION (MountPointRequired); \ + TC_EXCEPTION (MountPointUnavailable); \ + TC_EXCEPTION (NoDriveLetterAvailable); \ + TC_EXCEPTION (TemporaryDirectoryFailure); \ + TC_EXCEPTION (UnsupportedSectorSize); \ + TC_EXCEPTION (VolumeAlreadyMounted); \ + TC_EXCEPTION (VolumeSlotUnavailable); + + TC_EXCEPTION_SET; + +#undef TC_EXCEPTION +} + +#endif // TC_HEADER_Core_CoreException diff --git a/Core/FatFormatter.cpp b/Core/FatFormatter.cpp index 9d04c63..d65f3a5 100644 --- a/Core/FatFormatter.cpp +++ b/Core/FatFormatter.cpp @@ -1,345 +1,345 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include -#include "Common/Tcdefs.h" -#include "Platform/Platform.h" -#include "FatFormatter.h" -#include "RandomNumberGenerator.h" - -namespace TrueCrypt -{ - struct fatparams - { - char volume_name[11]; - uint32 num_sectors; /* total number of sectors */ - uint32 cluster_count; /* number of clusters */ - uint32 size_root_dir; /* size of the root directory in bytes */ - uint32 size_fat; /* size of FAT */ - uint32 fats; - uint32 media; - uint32 cluster_size; - uint32 fat_length; - uint16 dir_entries; - uint16 sector_size; - uint32 hidden; - uint16 reserved; - uint16 sectors; - uint32 total_sect; - - uint16 heads; - uint16 secs_track; - - }; - - static void GetFatParams (fatparams * ft) - { - uint32 fatsecs; - if(ft->cluster_size == 0) // 'Default' cluster size - { - if (ft->num_sectors * 512LL >= 256*BYTES_PER_GB) - ft->cluster_size = 128; - else if (ft->num_sectors * 512LL >= 64*BYTES_PER_GB) - ft->cluster_size = 64; - else if (ft->num_sectors * 512LL >= 16*BYTES_PER_GB) - ft->cluster_size = 32; - else if (ft->num_sectors * 512LL >= 8*BYTES_PER_GB) - ft->cluster_size = 16; - else if (ft->num_sectors * 512LL >= 128*BYTES_PER_MB) - ft->cluster_size = 8; - else if (ft->num_sectors * 512LL >= 64*BYTES_PER_MB) - ft->cluster_size = 4; - else if (ft->num_sectors * 512LL >= 32*BYTES_PER_MB) - ft->cluster_size = 2; - else - ft->cluster_size = 1; - } - - // Geometry always set to SECTORS/1/1 - ft->secs_track = 1; - ft->heads = 1; - - ft->dir_entries = 512; - ft->fats = 2; - ft->media = 0xf8; - ft->sector_size = SECTOR_SIZE; - ft->hidden = 0; - - ft->size_root_dir = ft->dir_entries * 32; - - // FAT12 - ft->size_fat = 12; - ft->reserved = 2; - fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; - ft->cluster_count = (int) (((int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 3)); - ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + SECTOR_SIZE - 1) / SECTOR_SIZE; - - if (ft->cluster_count >= 4085) // FAT16 - { - ft->size_fat = 16; - ft->reserved = 2; - fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; - ft->cluster_count = (int) (((int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 4)); - ft->fat_length = (ft->cluster_count * 2 + SECTOR_SIZE - 1) / SECTOR_SIZE; - } - - if(ft->cluster_count >= 65525) // FAT32 - { - ft->size_fat = 32; - ft->reserved = 32; - fatsecs = ft->num_sectors - ft->reserved; - ft->size_root_dir = ft->cluster_size * SECTOR_SIZE; - ft->cluster_count = (int) (((int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 8)); - ft->fat_length = (ft->cluster_count * 4 + SECTOR_SIZE - 1) / SECTOR_SIZE; - } - - if (ft->num_sectors >= 65536 || ft->size_fat == 32) - { - ft->sectors = 0; - ft->total_sect = ft->num_sectors; - } - else - { - ft->sectors = (uint16) ft->num_sectors; - ft->total_sect = 0; - } - } - - static void PutBoot (fatparams * ft, byte *boot, uint32 volumeId) - { - int cnt = 0; - - boot[cnt++] = 0xeb; /* boot jump */ - boot[cnt++] = 0x3c; - boot[cnt++] = 0x90; - memcpy (boot + cnt, "MSDOS5.0", 8); /* system id */ - cnt += 8; - *(int16 *)(boot + cnt) = Endian::Little (ft->sector_size); /* bytes per sector */ - cnt += 2; - boot[cnt++] = (int8) ft->cluster_size; /* sectors per cluster */ - *(int16 *)(boot + cnt) = Endian::Little (ft->reserved); /* reserved sectors */ - cnt += 2; - boot[cnt++] = (int8) ft->fats; /* 2 fats */ - - if(ft->size_fat == 32) - { - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - } - else - { - *(int16 *)(boot + cnt) = Endian::Little (ft->dir_entries); /* 512 root entries */ - cnt += 2; - } - - *(int16 *)(boot + cnt) = Endian::Little (ft->sectors); /* # sectors */ - cnt += 2; - boot[cnt++] = (int8) ft->media; /* media byte */ - - if(ft->size_fat == 32) - { - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - } - else - { - *(uint16 *)(boot + cnt) = Endian::Little ((uint16) ft->fat_length); /* fat size */ - cnt += 2; - } - - *(int16 *)(boot + cnt) = Endian::Little (ft->secs_track); /* # sectors per track */ - cnt += 2; - *(int16 *)(boot + cnt) = Endian::Little (ft->heads); /* # heads */ - cnt += 2; - *(int32 *)(boot + cnt) = Endian::Little (ft->hidden); /* # hidden sectors */ - cnt += 4; - *(int32 *)(boot + cnt) = Endian::Little (ft->total_sect); /* # huge sectors */ - cnt += 4; - - if(ft->size_fat == 32) - { - *(int32 *)(boot + cnt) = Endian::Little (ft->fat_length); cnt += 4; /* fat size 32 */ - boot[cnt++] = 0x00; /* ExtFlags */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; /* FSVer */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x02; /* RootClus */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - boot[cnt++] = 0x00; - boot[cnt++] = 0x01; /* FSInfo */ - boot[cnt++] = 0x00; - boot[cnt++] = 0x06; /* BkBootSec */ - boot[cnt++] = 0x00; - memset(boot+cnt, 0, 12); cnt+=12; /* Reserved */ - } - - boot[cnt++] = 0x00; /* drive number */ // FIXED 80 > 00 - boot[cnt++] = 0x00; /* reserved */ - boot[cnt++] = 0x29; /* boot sig */ - - *(int32 *)(boot + cnt) = volumeId; - cnt += 4; - - memcpy (boot + cnt, ft->volume_name, 11); /* vol title */ - cnt += 11; - - switch(ft->size_fat) /* filesystem type */ - { - case 12: memcpy (boot + cnt, "FAT12 ", 8); break; - case 16: memcpy (boot + cnt, "FAT16 ", 8); break; - case 32: memcpy (boot + cnt, "FAT32 ", 8); break; - } - cnt += 8; - - memset (boot + cnt, 0, ft->size_fat==32 ? 420:448); /* boot code */ - cnt += ft->size_fat==32 ? 420:448; - boot[cnt++] = 0x55; - boot[cnt++] = 0xaa; /* boot sig */ - } - - - /* FAT32 FSInfo */ - static void PutFSInfo (byte *sector, fatparams *ft) - { - memset (sector, 0, 512); - sector[3] = 0x41; /* LeadSig */ - sector[2] = 0x61; - sector[1] = 0x52; - sector[0] = 0x52; - sector[484+3] = 0x61; /* StrucSig */ - sector[484+2] = 0x41; - sector[484+1] = 0x72; - sector[484+0] = 0x72; - - // Free cluster count - *(uint32 *)(sector + 488) = Endian::Little (ft->cluster_count - ft->size_root_dir / SECTOR_SIZE / ft->cluster_size); - - // Next free cluster - *(uint32 *)(sector + 492) = Endian::Little ((uint32) 2); - - sector[508+3] = 0xaa; /* TrailSig */ - sector[508+2] = 0x55; - sector[508+1] = 0x00; - sector[508+0] = 0x00; - } - - void FatFormatter::Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize) - { - fatparams fatParams; - - if (deviceSize / SECTOR_SIZE > 0xffffFFFF) - throw ParameterIncorrect (SRC_POS); - - fatParams.num_sectors = (uint32) (deviceSize / SECTOR_SIZE); - fatParams.cluster_size = clusterSize / SECTOR_SIZE; - memcpy (fatParams.volume_name, "NO NAME ", 11); - GetFatParams (&fatParams); - fatparams *ft = &fatParams; - - SecureBuffer sector (SECTOR_SIZE); - uint32 sectorNumber = 0; - - /* Write the data area */ - - sector.Zero(); - - uint32 volumeId; - RandomNumberGenerator::GetDataFast (BufferPtr ((byte *) &volumeId, sizeof (volumeId))); - - PutBoot (ft, (byte *) sector, volumeId); - writeSector (sector); ++sectorNumber; - - /* fat32 boot area */ - if (ft->size_fat == 32) - { - /* fsinfo */ - PutFSInfo((byte *) sector, ft); - writeSector (sector); ++sectorNumber; - - /* reserved */ - while (sectorNumber < 6) - { - sector.Zero(); - sector[508+3] = 0xaa; /* TrailSig */ - sector[508+2] = 0x55; - writeSector (sector); ++sectorNumber; - } - - /* bootsector backup */ - sector.Zero(); - PutBoot (ft, (byte *) sector, volumeId); - writeSector (sector); ++sectorNumber; - - PutFSInfo((byte *) sector, ft); - writeSector (sector); ++sectorNumber; - } - - /* reserved */ - while (sectorNumber < (uint32)ft->reserved) - { - sector.Zero(); - writeSector (sector); ++sectorNumber; - } - - /* write fat */ - for (uint32 x = 1; x <= ft->fats; x++) - { - for (uint32 n = 0; n < ft->fat_length; n++) - { - sector.Zero(); - - if (n == 0) - { - byte fat_sig[12]; - if (ft->size_fat == 32) - { - fat_sig[0] = (byte) ft->media; - fat_sig[1] = fat_sig[2] = 0xff; - fat_sig[3] = 0x0f; - fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff; - fat_sig[7] = 0x0f; - fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff; - fat_sig[11] = 0x0f; - memcpy (sector, fat_sig, 12); - } - else if (ft->size_fat == 16) - { - fat_sig[0] = (byte) ft->media; - fat_sig[1] = 0xff; - fat_sig[2] = 0xff; - fat_sig[3] = 0xff; - memcpy (sector, fat_sig, 4); - } - else if (ft->size_fat == 12) - { - fat_sig[0] = (byte) ft->media; - fat_sig[1] = 0xff; - fat_sig[2] = 0xff; - fat_sig[3] = 0x00; - memcpy (sector, fat_sig, 4); - } - } - - if (!writeSector (sector)) - return; - } - } - - /* write rootdir */ - for (uint32 x = 0; x < ft->size_root_dir / SECTOR_SIZE; x++) - { - sector.Zero(); - if (!writeSector (sector)) - return; - } - } -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include +#include "Common/Tcdefs.h" +#include "Platform/Platform.h" +#include "FatFormatter.h" +#include "RandomNumberGenerator.h" + +namespace TrueCrypt +{ + struct fatparams + { + char volume_name[11]; + uint32 num_sectors; /* total number of sectors */ + uint32 cluster_count; /* number of clusters */ + uint32 size_root_dir; /* size of the root directory in bytes */ + uint32 size_fat; /* size of FAT */ + uint32 fats; + uint32 media; + uint32 cluster_size; + uint32 fat_length; + uint16 dir_entries; + uint16 sector_size; + uint32 hidden; + uint16 reserved; + uint16 sectors; + uint32 total_sect; + + uint16 heads; + uint16 secs_track; + + }; + + static void GetFatParams (fatparams * ft) + { + uint32 fatsecs; + if(ft->cluster_size == 0) // 'Default' cluster size + { + if (ft->num_sectors * 512LL >= 256*BYTES_PER_GB) + ft->cluster_size = 128; + else if (ft->num_sectors * 512LL >= 64*BYTES_PER_GB) + ft->cluster_size = 64; + else if (ft->num_sectors * 512LL >= 16*BYTES_PER_GB) + ft->cluster_size = 32; + else if (ft->num_sectors * 512LL >= 8*BYTES_PER_GB) + ft->cluster_size = 16; + else if (ft->num_sectors * 512LL >= 128*BYTES_PER_MB) + ft->cluster_size = 8; + else if (ft->num_sectors * 512LL >= 64*BYTES_PER_MB) + ft->cluster_size = 4; + else if (ft->num_sectors * 512LL >= 32*BYTES_PER_MB) + ft->cluster_size = 2; + else + ft->cluster_size = 1; + } + + // Geometry always set to SECTORS/1/1 + ft->secs_track = 1; + ft->heads = 1; + + ft->dir_entries = 512; + ft->fats = 2; + ft->media = 0xf8; + ft->sector_size = SECTOR_SIZE; + ft->hidden = 0; + + ft->size_root_dir = ft->dir_entries * 32; + + // FAT12 + ft->size_fat = 12; + ft->reserved = 2; + fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; + ft->cluster_count = (int) (((int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 3)); + ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + SECTOR_SIZE - 1) / SECTOR_SIZE; + + if (ft->cluster_count >= 4085) // FAT16 + { + ft->size_fat = 16; + ft->reserved = 2; + fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE - 1) / SECTOR_SIZE - ft->reserved; + ft->cluster_count = (int) (((int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 4)); + ft->fat_length = (ft->cluster_count * 2 + SECTOR_SIZE - 1) / SECTOR_SIZE; + } + + if(ft->cluster_count >= 65525) // FAT32 + { + ft->size_fat = 32; + ft->reserved = 32; + fatsecs = ft->num_sectors - ft->reserved; + ft->size_root_dir = ft->cluster_size * SECTOR_SIZE; + ft->cluster_count = (int) (((int64) fatsecs * SECTOR_SIZE) / (ft->cluster_size * SECTOR_SIZE + 8)); + ft->fat_length = (ft->cluster_count * 4 + SECTOR_SIZE - 1) / SECTOR_SIZE; + } + + if (ft->num_sectors >= 65536 || ft->size_fat == 32) + { + ft->sectors = 0; + ft->total_sect = ft->num_sectors; + } + else + { + ft->sectors = (uint16) ft->num_sectors; + ft->total_sect = 0; + } + } + + static void PutBoot (fatparams * ft, byte *boot, uint32 volumeId) + { + int cnt = 0; + + boot[cnt++] = 0xeb; /* boot jump */ + boot[cnt++] = 0x3c; + boot[cnt++] = 0x90; + memcpy (boot + cnt, "MSDOS5.0", 8); /* system id */ + cnt += 8; + *(int16 *)(boot + cnt) = Endian::Little (ft->sector_size); /* bytes per sector */ + cnt += 2; + boot[cnt++] = (int8) ft->cluster_size; /* sectors per cluster */ + *(int16 *)(boot + cnt) = Endian::Little (ft->reserved); /* reserved sectors */ + cnt += 2; + boot[cnt++] = (int8) ft->fats; /* 2 fats */ + + if(ft->size_fat == 32) + { + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + } + else + { + *(int16 *)(boot + cnt) = Endian::Little (ft->dir_entries); /* 512 root entries */ + cnt += 2; + } + + *(int16 *)(boot + cnt) = Endian::Little (ft->sectors); /* # sectors */ + cnt += 2; + boot[cnt++] = (int8) ft->media; /* media byte */ + + if(ft->size_fat == 32) + { + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + } + else + { + *(uint16 *)(boot + cnt) = Endian::Little ((uint16) ft->fat_length); /* fat size */ + cnt += 2; + } + + *(int16 *)(boot + cnt) = Endian::Little (ft->secs_track); /* # sectors per track */ + cnt += 2; + *(int16 *)(boot + cnt) = Endian::Little (ft->heads); /* # heads */ + cnt += 2; + *(int32 *)(boot + cnt) = Endian::Little (ft->hidden); /* # hidden sectors */ + cnt += 4; + *(int32 *)(boot + cnt) = Endian::Little (ft->total_sect); /* # huge sectors */ + cnt += 4; + + if(ft->size_fat == 32) + { + *(int32 *)(boot + cnt) = Endian::Little (ft->fat_length); cnt += 4; /* fat size 32 */ + boot[cnt++] = 0x00; /* ExtFlags */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; /* FSVer */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x02; /* RootClus */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + boot[cnt++] = 0x00; + boot[cnt++] = 0x01; /* FSInfo */ + boot[cnt++] = 0x00; + boot[cnt++] = 0x06; /* BkBootSec */ + boot[cnt++] = 0x00; + memset(boot+cnt, 0, 12); cnt+=12; /* Reserved */ + } + + boot[cnt++] = 0x00; /* drive number */ // FIXED 80 > 00 + boot[cnt++] = 0x00; /* reserved */ + boot[cnt++] = 0x29; /* boot sig */ + + *(int32 *)(boot + cnt) = volumeId; + cnt += 4; + + memcpy (boot + cnt, ft->volume_name, 11); /* vol title */ + cnt += 11; + + switch(ft->size_fat) /* filesystem type */ + { + case 12: memcpy (boot + cnt, "FAT12 ", 8); break; + case 16: memcpy (boot + cnt, "FAT16 ", 8); break; + case 32: memcpy (boot + cnt, "FAT32 ", 8); break; + } + cnt += 8; + + memset (boot + cnt, 0, ft->size_fat==32 ? 420:448); /* boot code */ + cnt += ft->size_fat==32 ? 420:448; + boot[cnt++] = 0x55; + boot[cnt++] = 0xaa; /* boot sig */ + } + + + /* FAT32 FSInfo */ + static void PutFSInfo (byte *sector, fatparams *ft) + { + memset (sector, 0, 512); + sector[3] = 0x41; /* LeadSig */ + sector[2] = 0x61; + sector[1] = 0x52; + sector[0] = 0x52; + sector[484+3] = 0x61; /* StrucSig */ + sector[484+2] = 0x41; + sector[484+1] = 0x72; + sector[484+0] = 0x72; + + // Free cluster count + *(uint32 *)(sector + 488) = Endian::Little (ft->cluster_count - ft->size_root_dir / SECTOR_SIZE / ft->cluster_size); + + // Next free cluster + *(uint32 *)(sector + 492) = Endian::Little ((uint32) 2); + + sector[508+3] = 0xaa; /* TrailSig */ + sector[508+2] = 0x55; + sector[508+1] = 0x00; + sector[508+0] = 0x00; + } + + void FatFormatter::Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize) + { + fatparams fatParams; + + if (deviceSize / SECTOR_SIZE > 0xffffFFFF) + throw ParameterIncorrect (SRC_POS); + + fatParams.num_sectors = (uint32) (deviceSize / SECTOR_SIZE); + fatParams.cluster_size = clusterSize / SECTOR_SIZE; + memcpy (fatParams.volume_name, "NO NAME ", 11); + GetFatParams (&fatParams); + fatparams *ft = &fatParams; + + SecureBuffer sector (SECTOR_SIZE); + uint32 sectorNumber = 0; + + /* Write the data area */ + + sector.Zero(); + + uint32 volumeId; + RandomNumberGenerator::GetDataFast (BufferPtr ((byte *) &volumeId, sizeof (volumeId))); + + PutBoot (ft, (byte *) sector, volumeId); + writeSector (sector); ++sectorNumber; + + /* fat32 boot area */ + if (ft->size_fat == 32) + { + /* fsinfo */ + PutFSInfo((byte *) sector, ft); + writeSector (sector); ++sectorNumber; + + /* reserved */ + while (sectorNumber < 6) + { + sector.Zero(); + sector[508+3] = 0xaa; /* TrailSig */ + sector[508+2] = 0x55; + writeSector (sector); ++sectorNumber; + } + + /* bootsector backup */ + sector.Zero(); + PutBoot (ft, (byte *) sector, volumeId); + writeSector (sector); ++sectorNumber; + + PutFSInfo((byte *) sector, ft); + writeSector (sector); ++sectorNumber; + } + + /* reserved */ + while (sectorNumber < (uint32)ft->reserved) + { + sector.Zero(); + writeSector (sector); ++sectorNumber; + } + + /* write fat */ + for (uint32 x = 1; x <= ft->fats; x++) + { + for (uint32 n = 0; n < ft->fat_length; n++) + { + sector.Zero(); + + if (n == 0) + { + byte fat_sig[12]; + if (ft->size_fat == 32) + { + fat_sig[0] = (byte) ft->media; + fat_sig[1] = fat_sig[2] = 0xff; + fat_sig[3] = 0x0f; + fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff; + fat_sig[7] = 0x0f; + fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff; + fat_sig[11] = 0x0f; + memcpy (sector, fat_sig, 12); + } + else if (ft->size_fat == 16) + { + fat_sig[0] = (byte) ft->media; + fat_sig[1] = 0xff; + fat_sig[2] = 0xff; + fat_sig[3] = 0xff; + memcpy (sector, fat_sig, 4); + } + else if (ft->size_fat == 12) + { + fat_sig[0] = (byte) ft->media; + fat_sig[1] = 0xff; + fat_sig[2] = 0xff; + fat_sig[3] = 0x00; + memcpy (sector, fat_sig, 4); + } + } + + if (!writeSector (sector)) + return; + } + } + + /* write rootdir */ + for (uint32 x = 0; x < ft->size_root_dir / SECTOR_SIZE; x++) + { + sector.Zero(); + if (!writeSector (sector)) + return; + } + } +} diff --git a/Core/FatFormatter.h b/Core/FatFormatter.h index 6a289ba..3fc8633 100644 --- a/Core/FatFormatter.h +++ b/Core/FatFormatter.h @@ -1,29 +1,29 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_FatFormatter -#define TC_HEADER_Core_FatFormatter - -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - class FatFormatter - { - public: - struct WriteSectorCallback - { - virtual ~WriteSectorCallback () { } - virtual bool operator() (const BufferPtr §or) = 0; - }; - - static void Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize); - }; -} - -#endif // TC_HEADER_Core_FatFormatter +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_FatFormatter +#define TC_HEADER_Core_FatFormatter + +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + class FatFormatter + { + public: + struct WriteSectorCallback + { + virtual ~WriteSectorCallback () { } + virtual bool operator() (const BufferPtr §or) = 0; + }; + + static void Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize); + }; +} + +#endif // TC_HEADER_Core_FatFormatter diff --git a/Core/HostDevice.cpp b/Core/HostDevice.cpp index 40297e4..9cd2122 100644 --- a/Core/HostDevice.cpp +++ b/Core/HostDevice.cpp @@ -1,47 +1,47 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "HostDevice.h" -#include "Platform/SerializerFactory.h" - -namespace TrueCrypt -{ - void HostDevice::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - MountPoint = sr.DeserializeWString ("MountPoint"); - sr.Deserialize ("Name", Name); - Path = sr.DeserializeWString ("Path"); - sr.Deserialize ("Removable", Removable); - sr.Deserialize ("Size", Size); - sr.Deserialize ("SystemNumber", SystemNumber); - - uint32 partitionCount; - sr.Deserialize ("Partitions", partitionCount); - for (uint32 i = 0; i < partitionCount; i++) - Partitions.push_back (Serializable::DeserializeNew (stream)); - } - - void HostDevice::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("MountPoint", wstring (MountPoint)); - sr.Serialize ("Name", Name); - sr.Serialize ("Path", wstring (Path)); - sr.Serialize ("Removable", Removable); - sr.Serialize ("Size", Size); - sr.Serialize ("SystemNumber", SystemNumber); - - sr.Serialize ("Partitions", (uint32) Partitions.size()); - foreach_ref (const HostDevice &partition, Partitions) - partition.Serialize (stream); - } - - TC_SERIALIZER_FACTORY_ADD_CLASS (HostDevice); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "HostDevice.h" +#include "Platform/SerializerFactory.h" + +namespace TrueCrypt +{ + void HostDevice::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + MountPoint = sr.DeserializeWString ("MountPoint"); + sr.Deserialize ("Name", Name); + Path = sr.DeserializeWString ("Path"); + sr.Deserialize ("Removable", Removable); + sr.Deserialize ("Size", Size); + sr.Deserialize ("SystemNumber", SystemNumber); + + uint32 partitionCount; + sr.Deserialize ("Partitions", partitionCount); + for (uint32 i = 0; i < partitionCount; i++) + Partitions.push_back (Serializable::DeserializeNew (stream)); + } + + void HostDevice::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("MountPoint", wstring (MountPoint)); + sr.Serialize ("Name", Name); + sr.Serialize ("Path", wstring (Path)); + sr.Serialize ("Removable", Removable); + sr.Serialize ("Size", Size); + sr.Serialize ("SystemNumber", SystemNumber); + + sr.Serialize ("Partitions", (uint32) Partitions.size()); + foreach_ref (const HostDevice &partition, Partitions) + partition.Serialize (stream); + } + + TC_SERIALIZER_FACTORY_ADD_CLASS (HostDevice); +} diff --git a/Core/HostDevice.h b/Core/HostDevice.h index 5d8bbbe..ca17087 100644 --- a/Core/HostDevice.h +++ b/Core/HostDevice.h @@ -1,45 +1,45 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_HostDevice -#define TC_HEADER_Core_HostDevice - -#include "Platform/Platform.h" -#include "Platform/Serializable.h" - -namespace TrueCrypt -{ - struct HostDevice; - typedef list < shared_ptr > HostDeviceList; - - struct HostDevice : public Serializable - { - HostDevice () - : Removable (false), - Size (0) - { - } - - virtual ~HostDevice () - { - } - - TC_SERIALIZABLE (HostDevice); - - DirectoryPath MountPoint; - wstring Name; - DevicePath Path; - bool Removable; - uint64 Size; - uint32 SystemNumber; - - HostDeviceList Partitions; - }; -} - -#endif // TC_HEADER_Core_HostDevice +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_HostDevice +#define TC_HEADER_Core_HostDevice + +#include "Platform/Platform.h" +#include "Platform/Serializable.h" + +namespace TrueCrypt +{ + struct HostDevice; + typedef list < shared_ptr > HostDeviceList; + + struct HostDevice : public Serializable + { + HostDevice () + : Removable (false), + Size (0) + { + } + + virtual ~HostDevice () + { + } + + TC_SERIALIZABLE (HostDevice); + + DirectoryPath MountPoint; + wstring Name; + DevicePath Path; + bool Removable; + uint64 Size; + uint32 SystemNumber; + + HostDeviceList Partitions; + }; +} + +#endif // TC_HEADER_Core_HostDevice diff --git a/Core/MountOptions.cpp b/Core/MountOptions.cpp index 47f7c6b..cf91a91 100644 --- a/Core/MountOptions.cpp +++ b/Core/MountOptions.cpp @@ -1,126 +1,126 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "MountOptions.h" -#include "Platform/MemoryStream.h" -#include "Platform/SerializerFactory.h" - -namespace TrueCrypt -{ - void MountOptions::CopyFrom (const MountOptions &other) - { -#define TC_CLONE(NAME) NAME = other.NAME -#define TC_CLONE_SHARED(TYPE,NAME) NAME = other.NAME ? make_shared (*other.NAME) : shared_ptr () - - TC_CLONE (CachePassword); - TC_CLONE (FilesystemOptions); - TC_CLONE (FilesystemType); - TC_CLONE_SHARED (KeyfileList, Keyfiles); - TC_CLONE_SHARED (DirectoryPath, MountPoint); - TC_CLONE (NoFilesystem); - TC_CLONE (NoKernelCrypto); - TC_CLONE_SHARED (VolumePassword, Password); - TC_CLONE_SHARED (VolumePath, Path); - TC_CLONE (PartitionInSystemEncryptionScope); - TC_CLONE (PreserveTimestamps); - TC_CLONE (Protection); - TC_CLONE_SHARED (VolumePassword, ProtectionPassword); - TC_CLONE_SHARED (KeyfileList, ProtectionKeyfiles); - TC_CLONE (Removable); - TC_CLONE (SharedAccessAllowed); - TC_CLONE (SlotNumber); - TC_CLONE (UseBackupHeaders); - } - - void MountOptions::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - - sr.Deserialize ("CachePassword", CachePassword); - sr.Deserialize ("FilesystemOptions", FilesystemOptions); - sr.Deserialize ("FilesystemType", FilesystemType); - - Keyfiles = Keyfile::DeserializeList (stream, "Keyfiles"); - - if (!sr.DeserializeBool ("MountPointNull")) - MountPoint.reset (new DirectoryPath (sr.DeserializeWString ("MountPoint"))); - else - MountPoint.reset(); - - sr.Deserialize ("NoFilesystem", NoFilesystem); - sr.Deserialize ("NoKernelCrypto", NoKernelCrypto); - - if (!sr.DeserializeBool ("PasswordNull")) - Password = Serializable::DeserializeNew (stream); - else - Password.reset(); - - if (!sr.DeserializeBool ("PathNull")) - Path.reset (new VolumePath (sr.DeserializeWString ("Path"))); - else - Path.reset(); - - sr.Deserialize ("PartitionInSystemEncryptionScope", PartitionInSystemEncryptionScope); - sr.Deserialize ("PreserveTimestamps", PreserveTimestamps); - - Protection = static_cast (sr.DeserializeInt32 ("Protection")); - - if (!sr.DeserializeBool ("ProtectionPasswordNull")) - ProtectionPassword = Serializable::DeserializeNew (stream); - else - ProtectionPassword.reset(); - - ProtectionKeyfiles = Keyfile::DeserializeList (stream, "ProtectionKeyfiles"); - sr.Deserialize ("Removable", Removable); - sr.Deserialize ("SharedAccessAllowed", SharedAccessAllowed); - sr.Deserialize ("SlotNumber", SlotNumber); - sr.Deserialize ("UseBackupHeaders", UseBackupHeaders); - } - - void MountOptions::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - - sr.Serialize ("CachePassword", CachePassword); - sr.Serialize ("FilesystemOptions", FilesystemOptions); - sr.Serialize ("FilesystemType", FilesystemType); - Keyfile::SerializeList (stream, "Keyfiles", Keyfiles); - - sr.Serialize ("MountPointNull", MountPoint == nullptr); - if (MountPoint) - sr.Serialize ("MountPoint", wstring (*MountPoint)); - - sr.Serialize ("NoFilesystem", NoFilesystem); - sr.Serialize ("NoKernelCrypto", NoKernelCrypto); - - sr.Serialize ("PasswordNull", Password == nullptr); - if (Password) - Password->Serialize (stream); - - sr.Serialize ("PathNull", Path == nullptr); - if (Path) - sr.Serialize ("Path", wstring (*Path)); - - sr.Serialize ("PartitionInSystemEncryptionScope", PartitionInSystemEncryptionScope); - sr.Serialize ("PreserveTimestamps", PreserveTimestamps); - sr.Serialize ("Protection", static_cast (Protection)); - - sr.Serialize ("ProtectionPasswordNull", ProtectionPassword == nullptr); - if (ProtectionPassword) - ProtectionPassword->Serialize (stream); - - Keyfile::SerializeList (stream, "ProtectionKeyfiles", ProtectionKeyfiles); - sr.Serialize ("Removable", Removable); - sr.Serialize ("SharedAccessAllowed", SharedAccessAllowed); - sr.Serialize ("SlotNumber", SlotNumber); - sr.Serialize ("UseBackupHeaders", UseBackupHeaders); - } - - TC_SERIALIZER_FACTORY_ADD_CLASS (MountOptions); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "MountOptions.h" +#include "Platform/MemoryStream.h" +#include "Platform/SerializerFactory.h" + +namespace TrueCrypt +{ + void MountOptions::CopyFrom (const MountOptions &other) + { +#define TC_CLONE(NAME) NAME = other.NAME +#define TC_CLONE_SHARED(TYPE,NAME) NAME = other.NAME ? make_shared (*other.NAME) : shared_ptr () + + TC_CLONE (CachePassword); + TC_CLONE (FilesystemOptions); + TC_CLONE (FilesystemType); + TC_CLONE_SHARED (KeyfileList, Keyfiles); + TC_CLONE_SHARED (DirectoryPath, MountPoint); + TC_CLONE (NoFilesystem); + TC_CLONE (NoKernelCrypto); + TC_CLONE_SHARED (VolumePassword, Password); + TC_CLONE_SHARED (VolumePath, Path); + TC_CLONE (PartitionInSystemEncryptionScope); + TC_CLONE (PreserveTimestamps); + TC_CLONE (Protection); + TC_CLONE_SHARED (VolumePassword, ProtectionPassword); + TC_CLONE_SHARED (KeyfileList, ProtectionKeyfiles); + TC_CLONE (Removable); + TC_CLONE (SharedAccessAllowed); + TC_CLONE (SlotNumber); + TC_CLONE (UseBackupHeaders); + } + + void MountOptions::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + + sr.Deserialize ("CachePassword", CachePassword); + sr.Deserialize ("FilesystemOptions", FilesystemOptions); + sr.Deserialize ("FilesystemType", FilesystemType); + + Keyfiles = Keyfile::DeserializeList (stream, "Keyfiles"); + + if (!sr.DeserializeBool ("MountPointNull")) + MountPoint.reset (new DirectoryPath (sr.DeserializeWString ("MountPoint"))); + else + MountPoint.reset(); + + sr.Deserialize ("NoFilesystem", NoFilesystem); + sr.Deserialize ("NoKernelCrypto", NoKernelCrypto); + + if (!sr.DeserializeBool ("PasswordNull")) + Password = Serializable::DeserializeNew (stream); + else + Password.reset(); + + if (!sr.DeserializeBool ("PathNull")) + Path.reset (new VolumePath (sr.DeserializeWString ("Path"))); + else + Path.reset(); + + sr.Deserialize ("PartitionInSystemEncryptionScope", PartitionInSystemEncryptionScope); + sr.Deserialize ("PreserveTimestamps", PreserveTimestamps); + + Protection = static_cast (sr.DeserializeInt32 ("Protection")); + + if (!sr.DeserializeBool ("ProtectionPasswordNull")) + ProtectionPassword = Serializable::DeserializeNew (stream); + else + ProtectionPassword.reset(); + + ProtectionKeyfiles = Keyfile::DeserializeList (stream, "ProtectionKeyfiles"); + sr.Deserialize ("Removable", Removable); + sr.Deserialize ("SharedAccessAllowed", SharedAccessAllowed); + sr.Deserialize ("SlotNumber", SlotNumber); + sr.Deserialize ("UseBackupHeaders", UseBackupHeaders); + } + + void MountOptions::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + + sr.Serialize ("CachePassword", CachePassword); + sr.Serialize ("FilesystemOptions", FilesystemOptions); + sr.Serialize ("FilesystemType", FilesystemType); + Keyfile::SerializeList (stream, "Keyfiles", Keyfiles); + + sr.Serialize ("MountPointNull", MountPoint == nullptr); + if (MountPoint) + sr.Serialize ("MountPoint", wstring (*MountPoint)); + + sr.Serialize ("NoFilesystem", NoFilesystem); + sr.Serialize ("NoKernelCrypto", NoKernelCrypto); + + sr.Serialize ("PasswordNull", Password == nullptr); + if (Password) + Password->Serialize (stream); + + sr.Serialize ("PathNull", Path == nullptr); + if (Path) + sr.Serialize ("Path", wstring (*Path)); + + sr.Serialize ("PartitionInSystemEncryptionScope", PartitionInSystemEncryptionScope); + sr.Serialize ("PreserveTimestamps", PreserveTimestamps); + sr.Serialize ("Protection", static_cast (Protection)); + + sr.Serialize ("ProtectionPasswordNull", ProtectionPassword == nullptr); + if (ProtectionPassword) + ProtectionPassword->Serialize (stream); + + Keyfile::SerializeList (stream, "ProtectionKeyfiles", ProtectionKeyfiles); + sr.Serialize ("Removable", Removable); + sr.Serialize ("SharedAccessAllowed", SharedAccessAllowed); + sr.Serialize ("SlotNumber", SlotNumber); + sr.Serialize ("UseBackupHeaders", UseBackupHeaders); + } + + TC_SERIALIZER_FACTORY_ADD_CLASS (MountOptions); +} diff --git a/Core/MountOptions.h b/Core/MountOptions.h index 0728094..4e04728 100644 --- a/Core/MountOptions.h +++ b/Core/MountOptions.h @@ -1,68 +1,68 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_MountOptions -#define TC_HEADER_Core_MountOptions - -#include "Platform/Serializable.h" -#include "Volume/Keyfile.h" -#include "Volume/Volume.h" -#include "Volume/VolumeSlot.h" -#include "Volume/VolumePassword.h" - -namespace TrueCrypt -{ - struct MountOptions : public Serializable - { - MountOptions () - : - CachePassword (false), - NoFilesystem (false), - NoKernelCrypto (false), - PartitionInSystemEncryptionScope (false), - PreserveTimestamps (true), - Protection (VolumeProtection::None), - Removable (false), - SharedAccessAllowed (false), - SlotNumber (0), - UseBackupHeaders (false) - { - } - - MountOptions (const MountOptions &other) { CopyFrom (other); } - virtual ~MountOptions () { } - - MountOptions &operator= (const MountOptions &other) { CopyFrom (other); return *this; } - - TC_SERIALIZABLE (MountOptions); - - bool CachePassword; - wstring FilesystemOptions; - wstring FilesystemType; - shared_ptr Keyfiles; - shared_ptr MountPoint; - bool NoFilesystem; - bool NoKernelCrypto; - shared_ptr Password; - bool PartitionInSystemEncryptionScope; - shared_ptr Path; - bool PreserveTimestamps; - VolumeProtection::Enum Protection; - shared_ptr ProtectionPassword; - shared_ptr ProtectionKeyfiles; - bool Removable; - bool SharedAccessAllowed; - VolumeSlotNumber SlotNumber; - bool UseBackupHeaders; - - protected: - void CopyFrom (const MountOptions &other); - }; -} - -#endif // TC_HEADER_Core_MountOptions +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_MountOptions +#define TC_HEADER_Core_MountOptions + +#include "Platform/Serializable.h" +#include "Volume/Keyfile.h" +#include "Volume/Volume.h" +#include "Volume/VolumeSlot.h" +#include "Volume/VolumePassword.h" + +namespace TrueCrypt +{ + struct MountOptions : public Serializable + { + MountOptions () + : + CachePassword (false), + NoFilesystem (false), + NoKernelCrypto (false), + PartitionInSystemEncryptionScope (false), + PreserveTimestamps (true), + Protection (VolumeProtection::None), + Removable (false), + SharedAccessAllowed (false), + SlotNumber (0), + UseBackupHeaders (false) + { + } + + MountOptions (const MountOptions &other) { CopyFrom (other); } + virtual ~MountOptions () { } + + MountOptions &operator= (const MountOptions &other) { CopyFrom (other); return *this; } + + TC_SERIALIZABLE (MountOptions); + + bool CachePassword; + wstring FilesystemOptions; + wstring FilesystemType; + shared_ptr Keyfiles; + shared_ptr MountPoint; + bool NoFilesystem; + bool NoKernelCrypto; + shared_ptr Password; + bool PartitionInSystemEncryptionScope; + shared_ptr Path; + bool PreserveTimestamps; + VolumeProtection::Enum Protection; + shared_ptr ProtectionPassword; + shared_ptr ProtectionKeyfiles; + bool Removable; + bool SharedAccessAllowed; + VolumeSlotNumber SlotNumber; + bool UseBackupHeaders; + + protected: + void CopyFrom (const MountOptions &other); + }; +} + +#endif // TC_HEADER_Core_MountOptions diff --git a/Core/RandomNumberGenerator.cpp b/Core/RandomNumberGenerator.cpp index b660627..8f6e338 100644 --- a/Core/RandomNumberGenerator.cpp +++ b/Core/RandomNumberGenerator.cpp @@ -1,210 +1,210 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_WINDOWS -#include -#include -#include -#endif - -#include "RandomNumberGenerator.h" -#include "Volume/Crc32.h" - -namespace TrueCrypt -{ - void RandomNumberGenerator::AddSystemDataToPool (bool fast) - { - SecureBuffer buffer (PoolSize); - -#ifdef TC_WINDOWS -#ifndef DEBUG - throw NotImplemented (SRC_POS); -#endif -#else - int urandom = open ("/dev/urandom", O_RDONLY); - throw_sys_sub_if (urandom == -1, L"/dev/urandom"); - finally_do_arg (int, urandom, { close (finally_arg); }); - - throw_sys_sub_if (read (urandom, buffer, buffer.Size()) == -1, L"/dev/urandom"); - AddToPool (buffer); - - if (!fast) - { - // Read all bytes available in /dev/random up to buffer size - int random = open ("/dev/random", O_RDONLY | O_NONBLOCK); - throw_sys_sub_if (random == -1, L"/dev/random"); - finally_do_arg (int, random, { close (finally_arg); }); - - throw_sys_sub_if (read (random, buffer, buffer.Size()) == -1 && errno != EAGAIN, L"/dev/random"); - AddToPool (buffer); - } -#endif - } - - void RandomNumberGenerator::AddToPool (const ConstBufferPtr &data) - { - if (!Running) - throw NotInitialized (SRC_POS); - - ScopeLock lock (AccessMutex); - - for (size_t i = 0; i < data.Size(); ++i) - { - Pool[WriteOffset++] += data[i]; - - if (WriteOffset >= PoolSize) - WriteOffset = 0; - - if (++BytesAddedSincePoolHashMix >= MaxBytesAddedBeforePoolHashMix) - HashMixPool(); - } - } - - void RandomNumberGenerator::GetData (const BufferPtr &buffer, bool fast) - { - if (!Running) - throw NotInitialized (SRC_POS); - - ScopeLock lock (AccessMutex); - - // Poll system for data - AddSystemDataToPool (fast); - HashMixPool(); - - // Transfer bytes from pool to output buffer - for (size_t i = 0; i < buffer.Size(); ++i) - { - buffer[i] += Pool[ReadOffset++]; - - if (ReadOffset >= PoolSize) - ReadOffset = 0; - } - - // Invert and mix the pool - for (size_t i = 0; i < Pool.Size(); ++i) - { - Pool[i] = ~Pool[i]; - } - - AddSystemDataToPool (true); - HashMixPool(); - - // XOR the current pool content into the output buffer to prevent pool state leaks - for (size_t i = 0; i < buffer.Size(); ++i) - { - buffer[i] ^= Pool[ReadOffset++]; - - if (ReadOffset >= PoolSize) - ReadOffset = 0; - } - } - - shared_ptr RandomNumberGenerator::GetHash () - { - ScopeLock lock (AccessMutex); - return PoolHash; - } - - void RandomNumberGenerator::HashMixPool () - { - BytesAddedSincePoolHashMix = 0; - - for (size_t poolPos = 0; poolPos < Pool.Size(); ) - { - // Compute the message digest of the entire pool using the selected hash function - SecureBuffer digest (PoolHash->GetDigestSize()); - PoolHash->ProcessData (Pool); - PoolHash->GetDigest (digest); - - // Add the message digest to the pool - for (size_t digestPos = 0; digestPos < digest.Size() && poolPos < Pool.Size(); ++digestPos) - { - Pool[poolPos++] += digest[digestPos]; - } - } - } - - void RandomNumberGenerator::SetHash (shared_ptr hash) - { - ScopeLock lock (AccessMutex); - PoolHash = hash; - } - - void RandomNumberGenerator::Start () - { - ScopeLock lock (AccessMutex); - - if (IsRunning()) - return; - - BytesAddedSincePoolHashMix = 0; - ReadOffset = 0; - WriteOffset = 0; - Running = true; - EnrichedByUser = false; - - Pool.Allocate (PoolSize); - Test(); - - if (!PoolHash) - { - // First hash algorithm is the default one - PoolHash = Hash::GetAvailableAlgorithms().front(); - } - - AddSystemDataToPool (true); - } - - void RandomNumberGenerator::Stop () - { - ScopeLock lock (AccessMutex); - - if (Pool.IsAllocated()) - Pool.Free (); - - PoolHash.reset(); - - EnrichedByUser = false; - Running = false; - } - - void RandomNumberGenerator::Test () - { - shared_ptr origPoolHash = PoolHash; - PoolHash.reset (new Ripemd160()); - - Pool.Zero(); - Buffer buffer (1); - for (int i = 0; i < PoolSize * 10; ++i) - { - buffer[0] = (byte) i; - AddToPool (buffer); - } - - if (Crc32::ProcessBuffer (Pool) != 0x10efc817) - throw TestFailed (SRC_POS); - - buffer.Allocate (PoolSize); - buffer.CopyFrom (PeekPool()); - AddToPool (buffer); - - if (Crc32::ProcessBuffer (Pool) != 0x1e3d0d72) - throw TestFailed (SRC_POS); - - PoolHash = origPoolHash; - } - - Mutex RandomNumberGenerator::AccessMutex; - size_t RandomNumberGenerator::BytesAddedSincePoolHashMix; - bool RandomNumberGenerator::EnrichedByUser; - SecureBuffer RandomNumberGenerator::Pool; - shared_ptr RandomNumberGenerator::PoolHash; - size_t RandomNumberGenerator::ReadOffset; - bool RandomNumberGenerator::Running = false; - size_t RandomNumberGenerator::WriteOffset; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_WINDOWS +#include +#include +#include +#endif + +#include "RandomNumberGenerator.h" +#include "Volume/Crc32.h" + +namespace TrueCrypt +{ + void RandomNumberGenerator::AddSystemDataToPool (bool fast) + { + SecureBuffer buffer (PoolSize); + +#ifdef TC_WINDOWS +#ifndef DEBUG + throw NotImplemented (SRC_POS); +#endif +#else + int urandom = open ("/dev/urandom", O_RDONLY); + throw_sys_sub_if (urandom == -1, L"/dev/urandom"); + finally_do_arg (int, urandom, { close (finally_arg); }); + + throw_sys_sub_if (read (urandom, buffer, buffer.Size()) == -1, L"/dev/urandom"); + AddToPool (buffer); + + if (!fast) + { + // Read all bytes available in /dev/random up to buffer size + int random = open ("/dev/random", O_RDONLY | O_NONBLOCK); + throw_sys_sub_if (random == -1, L"/dev/random"); + finally_do_arg (int, random, { close (finally_arg); }); + + throw_sys_sub_if (read (random, buffer, buffer.Size()) == -1 && errno != EAGAIN, L"/dev/random"); + AddToPool (buffer); + } +#endif + } + + void RandomNumberGenerator::AddToPool (const ConstBufferPtr &data) + { + if (!Running) + throw NotInitialized (SRC_POS); + + ScopeLock lock (AccessMutex); + + for (size_t i = 0; i < data.Size(); ++i) + { + Pool[WriteOffset++] += data[i]; + + if (WriteOffset >= PoolSize) + WriteOffset = 0; + + if (++BytesAddedSincePoolHashMix >= MaxBytesAddedBeforePoolHashMix) + HashMixPool(); + } + } + + void RandomNumberGenerator::GetData (const BufferPtr &buffer, bool fast) + { + if (!Running) + throw NotInitialized (SRC_POS); + + ScopeLock lock (AccessMutex); + + // Poll system for data + AddSystemDataToPool (fast); + HashMixPool(); + + // Transfer bytes from pool to output buffer + for (size_t i = 0; i < buffer.Size(); ++i) + { + buffer[i] += Pool[ReadOffset++]; + + if (ReadOffset >= PoolSize) + ReadOffset = 0; + } + + // Invert and mix the pool + for (size_t i = 0; i < Pool.Size(); ++i) + { + Pool[i] = ~Pool[i]; + } + + AddSystemDataToPool (true); + HashMixPool(); + + // XOR the current pool content into the output buffer to prevent pool state leaks + for (size_t i = 0; i < buffer.Size(); ++i) + { + buffer[i] ^= Pool[ReadOffset++]; + + if (ReadOffset >= PoolSize) + ReadOffset = 0; + } + } + + shared_ptr RandomNumberGenerator::GetHash () + { + ScopeLock lock (AccessMutex); + return PoolHash; + } + + void RandomNumberGenerator::HashMixPool () + { + BytesAddedSincePoolHashMix = 0; + + for (size_t poolPos = 0; poolPos < Pool.Size(); ) + { + // Compute the message digest of the entire pool using the selected hash function + SecureBuffer digest (PoolHash->GetDigestSize()); + PoolHash->ProcessData (Pool); + PoolHash->GetDigest (digest); + + // Add the message digest to the pool + for (size_t digestPos = 0; digestPos < digest.Size() && poolPos < Pool.Size(); ++digestPos) + { + Pool[poolPos++] += digest[digestPos]; + } + } + } + + void RandomNumberGenerator::SetHash (shared_ptr hash) + { + ScopeLock lock (AccessMutex); + PoolHash = hash; + } + + void RandomNumberGenerator::Start () + { + ScopeLock lock (AccessMutex); + + if (IsRunning()) + return; + + BytesAddedSincePoolHashMix = 0; + ReadOffset = 0; + WriteOffset = 0; + Running = true; + EnrichedByUser = false; + + Pool.Allocate (PoolSize); + Test(); + + if (!PoolHash) + { + // First hash algorithm is the default one + PoolHash = Hash::GetAvailableAlgorithms().front(); + } + + AddSystemDataToPool (true); + } + + void RandomNumberGenerator::Stop () + { + ScopeLock lock (AccessMutex); + + if (Pool.IsAllocated()) + Pool.Free (); + + PoolHash.reset(); + + EnrichedByUser = false; + Running = false; + } + + void RandomNumberGenerator::Test () + { + shared_ptr origPoolHash = PoolHash; + PoolHash.reset (new Ripemd160()); + + Pool.Zero(); + Buffer buffer (1); + for (size_t i = 0; i < PoolSize * 10; ++i) + { + buffer[0] = (byte) i; + AddToPool (buffer); + } + + if (Crc32::ProcessBuffer (Pool) != 0x10efc817) + throw TestFailed (SRC_POS); + + buffer.Allocate (PoolSize); + buffer.CopyFrom (PeekPool()); + AddToPool (buffer); + + if (Crc32::ProcessBuffer (Pool) != 0x1e3d0d72) + throw TestFailed (SRC_POS); + + PoolHash = origPoolHash; + } + + Mutex RandomNumberGenerator::AccessMutex; + size_t RandomNumberGenerator::BytesAddedSincePoolHashMix; + bool RandomNumberGenerator::EnrichedByUser; + SecureBuffer RandomNumberGenerator::Pool; + shared_ptr RandomNumberGenerator::PoolHash; + size_t RandomNumberGenerator::ReadOffset; + bool RandomNumberGenerator::Running = false; + size_t RandomNumberGenerator::WriteOffset; +} diff --git a/Core/RandomNumberGenerator.h b/Core/RandomNumberGenerator.h index 7c03656..754bbe5 100644 --- a/Core/RandomNumberGenerator.h +++ b/Core/RandomNumberGenerator.h @@ -1,55 +1,55 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_RandomNumberGenerator -#define TC_HEADER_Core_RandomNumberGenerator - -#include "Platform/Platform.h" -#include "Volume/Hash.h" -#include "Common/Random.h" - -namespace TrueCrypt -{ - class RandomNumberGenerator - { - public: - static void AddToPool (const ConstBufferPtr &buffer); - static void GetData (const BufferPtr &buffer) { GetData (buffer, false); } - static void GetDataFast (const BufferPtr &buffer) { GetData (buffer, true); } - static shared_ptr GetHash (); - static bool IsEnrichedByUser () { return EnrichedByUser; } - static bool IsRunning () { return Running; } - static ConstBufferPtr PeekPool () { return Pool; } - static void SetEnrichedByUserStatus (bool enriched) { EnrichedByUser = enriched; } - static void SetHash (shared_ptr hash); - static void Start (); - static void Stop (); - - static const size_t PoolSize = RNG_POOL_SIZE; - - protected: - static void AddSystemDataToPool (bool fast); - static void GetData (const BufferPtr &buffer, bool fast); - static void HashMixPool (); - static void Test (); - RandomNumberGenerator (); - - static const size_t MaxBytesAddedBeforePoolHashMix = RANDMIX_BYTE_INTERVAL; - - static Mutex AccessMutex; - static size_t BytesAddedSincePoolHashMix; - static bool EnrichedByUser; - static SecureBuffer Pool; - static shared_ptr PoolHash; - static size_t ReadOffset; - static bool Running; - static size_t WriteOffset; - }; -} - -#endif // TC_HEADER_Core_RandomNumberGenerator +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_RandomNumberGenerator +#define TC_HEADER_Core_RandomNumberGenerator + +#include "Platform/Platform.h" +#include "Volume/Hash.h" +#include "Common/Random.h" + +namespace TrueCrypt +{ + class RandomNumberGenerator + { + public: + static void AddToPool (const ConstBufferPtr &buffer); + static void GetData (const BufferPtr &buffer) { GetData (buffer, false); } + static void GetDataFast (const BufferPtr &buffer) { GetData (buffer, true); } + static shared_ptr GetHash (); + static bool IsEnrichedByUser () { return EnrichedByUser; } + static bool IsRunning () { return Running; } + static ConstBufferPtr PeekPool () { return Pool; } + static void SetEnrichedByUserStatus (bool enriched) { EnrichedByUser = enriched; } + static void SetHash (shared_ptr hash); + static void Start (); + static void Stop (); + + static const size_t PoolSize = RNG_POOL_SIZE; + + protected: + static void AddSystemDataToPool (bool fast); + static void GetData (const BufferPtr &buffer, bool fast); + static void HashMixPool (); + static void Test (); + RandomNumberGenerator (); + + static const size_t MaxBytesAddedBeforePoolHashMix = RANDMIX_BYTE_INTERVAL; + + static Mutex AccessMutex; + static size_t BytesAddedSincePoolHashMix; + static bool EnrichedByUser; + static SecureBuffer Pool; + static shared_ptr PoolHash; + static size_t ReadOffset; + static bool Running; + static size_t WriteOffset; + }; +} + +#endif // TC_HEADER_Core_RandomNumberGenerator diff --git a/Core/Unix/CoreService.cpp b/Core/Unix/CoreService.cpp index 022a551..f9e2023 100644 --- a/Core/Unix/CoreService.cpp +++ b/Core/Unix/CoreService.cpp @@ -1,523 +1,523 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "CoreService.h" -#include -#include -#include "Platform/FileStream.h" -#include "Platform/MemoryStream.h" -#include "Platform/Serializable.h" -#include "Platform/SystemLog.h" -#include "Platform/Thread.h" -#include "Platform/Unix/Poller.h" -#include "Core/Core.h" -#include "CoreUnix.h" -#include "CoreServiceRequest.h" -#include "CoreServiceResponse.h" - -namespace TrueCrypt -{ - template - auto_ptr CoreService::GetResponse () - { - auto_ptr deserializedObject (Serializable::DeserializeNew (ServiceOutputStream)); - - Exception *deserializedException = dynamic_cast (deserializedObject.get()); - if (deserializedException) - deserializedException->Throw(); - - if (dynamic_cast (deserializedObject.get()) == nullptr) - throw ParameterIncorrect (SRC_POS); - - return auto_ptr (dynamic_cast (deserializedObject.release())); - } - - void CoreService::ProcessElevatedRequests () - { - int pid = fork(); - throw_sys_if (pid == -1); - if (pid == 0) - { - try - { - int f = open ("/dev/null", 0); - throw_sys_sub_if (f == -1, "/dev/null"); - throw_sys_if (dup2 (f, STDERR_FILENO) == -1); - - // Wait for sync code - while (true) - { - byte b; - throw_sys_if (read (STDIN_FILENO, &b, 1) != 1); - if (b != 0x00) - continue; - - throw_sys_if (read (STDIN_FILENO, &b, 1) != 1); - if (b != 0x11) - continue; - - throw_sys_if (read (STDIN_FILENO, &b, 1) != 1); - if (b == 0x22) - break; - } - - ElevatedPrivileges = true; - ProcessRequests (STDIN_FILENO, STDOUT_FILENO); - _exit (0); - } - catch (exception &e) - { -#ifdef DEBUG - SystemLog::WriteException (e); -#endif - } - catch (...) { } - _exit (1); - } - } - - void CoreService::ProcessRequests (int inputFD, int outputFD) - { - try - { - Core = CoreDirect; - - shared_ptr inputStream (new FileStream (inputFD != -1 ? inputFD : InputPipe->GetReadFD())); - shared_ptr outputStream (new FileStream (outputFD != -1 ? outputFD : OutputPipe->GetWriteFD())); - - while (true) - { - shared_ptr request = Serializable::DeserializeNew (inputStream); - - try - { - // ExitRequest - if (dynamic_cast (request.get()) != nullptr) - { - if (ElevatedServiceAvailable) - request->Serialize (ServiceInputStream); - return; - } - - if (!ElevatedPrivileges && request->ElevateUserPrivileges) - { - if (!ElevatedServiceAvailable) - { - finally_do_arg (string *, &request->AdminPassword, { StringConverter::Erase (*finally_arg); }); - - CoreService::StartElevated (*request); - ElevatedServiceAvailable = true; - } - - request->Serialize (ServiceInputStream); - GetResponse ()->Serialize (outputStream); - continue; - } - - // CheckFilesystemRequest - CheckFilesystemRequest *checkRequest = dynamic_cast (request.get()); - if (checkRequest) - { - Core->CheckFilesystem (checkRequest->MountedVolumeInfo, checkRequest->Repair); - - CheckFilesystemResponse().Serialize (outputStream); - continue; - } - - // DismountFilesystemRequest - DismountFilesystemRequest *dismountFsRequest = dynamic_cast (request.get()); - if (dismountFsRequest) - { - Core->DismountFilesystem (dismountFsRequest->MountPoint, dismountFsRequest->Force); - - DismountFilesystemResponse().Serialize (outputStream); - continue; - } - - // DismountVolumeRequest - DismountVolumeRequest *dismountRequest = dynamic_cast (request.get()); - if (dismountRequest) - { - DismountVolumeResponse response; - response.DismountedVolumeInfo = Core->DismountVolume (dismountRequest->MountedVolumeInfo, dismountRequest->IgnoreOpenFiles, dismountRequest->SyncVolumeInfo); - response.Serialize (outputStream); - continue; - } - - // GetDeviceSizeRequest - GetDeviceSizeRequest *getDeviceSizeRequest = dynamic_cast (request.get()); - if (getDeviceSizeRequest) - { - GetDeviceSizeResponse response; - response.Size = Core->GetDeviceSize (getDeviceSizeRequest->Path); - response.Serialize (outputStream); - continue; - } - - // GetHostDevicesRequest - GetHostDevicesRequest *getHostDevicesRequest = dynamic_cast (request.get()); - if (getHostDevicesRequest) - { - GetHostDevicesResponse response; - response.HostDevices = Core->GetHostDevices (getHostDevicesRequest->PathListOnly); - response.Serialize (outputStream); - continue; - } - - // MountVolumeRequest - MountVolumeRequest *mountRequest = dynamic_cast (request.get()); - if (mountRequest) - { - MountVolumeResponse ( - Core->MountVolume (*mountRequest->Options) - ).Serialize (outputStream); - - continue; - } - - // SetFileOwnerRequest - SetFileOwnerRequest *setFileOwnerRequest = dynamic_cast (request.get()); - if (setFileOwnerRequest) - { - CoreUnix *coreUnix = dynamic_cast (Core.get()); - if (!coreUnix) - throw ParameterIncorrect (SRC_POS); - - coreUnix->SetFileOwner (setFileOwnerRequest->Path, setFileOwnerRequest->Owner); - SetFileOwnerResponse().Serialize (outputStream); - continue; - } - - throw ParameterIncorrect (SRC_POS); - } - catch (Exception &e) - { - e.Serialize (outputStream); - } - catch (exception &e) - { - ExternalException (SRC_POS, StringConverter::ToExceptionString (e)).Serialize (outputStream); - } - } - } - catch (exception &e) - { -#ifdef DEBUG - SystemLog::WriteException (e); -#endif - throw; - } - } - - void CoreService::RequestCheckFilesystem (shared_ptr mountedVolume, bool repair) - { - CheckFilesystemRequest request (mountedVolume, repair); - SendRequest (request); - } - - void CoreService::RequestDismountFilesystem (const DirectoryPath &mountPoint, bool force) - { - DismountFilesystemRequest request (mountPoint, force); - SendRequest (request); - } - - shared_ptr CoreService::RequestDismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) - { - DismountVolumeRequest request (mountedVolume, ignoreOpenFiles, syncVolumeInfo); - return SendRequest (request)->DismountedVolumeInfo; - } - - uint64 CoreService::RequestGetDeviceSize (const DevicePath &devicePath) - { - GetDeviceSizeRequest request (devicePath); - return SendRequest (request)->Size; - } - - HostDeviceList CoreService::RequestGetHostDevices (bool pathListOnly) - { - GetHostDevicesRequest request (pathListOnly); - return SendRequest (request)->HostDevices; - } - - shared_ptr CoreService::RequestMountVolume (MountOptions &options) - { - MountVolumeRequest request (&options); - return SendRequest (request)->MountedVolumeInfo; - } - - void CoreService::RequestSetFileOwner (const FilesystemPath &path, const UserId &owner) - { - SetFileOwnerRequest request (path, owner); - SendRequest (request); - } - - template - auto_ptr CoreService::SendRequest (CoreServiceRequest &request) - { - static Mutex mutex; - ScopeLock lock (mutex); - - if (request.RequiresElevation()) - { - request.ElevateUserPrivileges = true; - request.FastElevation = !ElevatedServiceAvailable; - request.ApplicationExecutablePath = Core->GetApplicationExecutablePath(); - - while (!ElevatedServiceAvailable) - { - try - { - request.Serialize (ServiceInputStream); - auto_ptr response (GetResponse ()); - ElevatedServiceAvailable = true; - return response; - } - catch (ElevationFailed &e) - { - if (!request.FastElevation) - { - ExceptionEventArgs args (e); - Core->WarningEvent.Raise (args); - } - - request.FastElevation = false; - (*AdminPasswordCallback) (request.AdminPassword); - } - } - } - - finally_do_arg (string *, &request.AdminPassword, { StringConverter::Erase (*finally_arg); }); - - request.Serialize (ServiceInputStream); - return GetResponse (); - } - - void CoreService::Start () - { - InputPipe.reset (new Pipe()); - OutputPipe.reset (new Pipe()); - - int pid = fork(); - throw_sys_if (pid == -1); - - if (pid == 0) - { - try - { - ProcessRequests(); - _exit (0); - } - catch (...) { } - _exit (1); - } - - ServiceInputStream = shared_ptr (new FileStream (InputPipe->GetWriteFD())); - ServiceOutputStream = shared_ptr (new FileStream (OutputPipe->GetReadFD())); - } - - void CoreService::StartElevated (const CoreServiceRequest &request) - { - auto_ptr inPipe (new Pipe()); - auto_ptr outPipe (new Pipe()); - Pipe errPipe; - - int forkedPid = fork(); - throw_sys_if (forkedPid == -1); - - if (forkedPid == 0) - { - try - { - try - { - throw_sys_if (dup2 (inPipe->GetReadFD(), STDIN_FILENO) == -1); - throw_sys_if (dup2 (outPipe->GetWriteFD(), STDOUT_FILENO) == -1); - throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1); - - string appPath = request.ApplicationExecutablePath; - if (appPath.empty()) - appPath = "truecrypt"; - - const char *args[] = { "sudo", "-S", "-p", "", appPath.c_str(), TC_CORE_SERVICE_CMDLINE_OPTION, nullptr }; - execvp (args[0], ((char* const*) args)); - throw SystemException (SRC_POS, args[0]); - } - catch (Exception &) - { - throw; - } - catch (exception &e) - { - throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e)); - } - catch (...) - { - throw UnknownException (SRC_POS); - } - } - catch (Exception &e) - { - try - { - shared_ptr outputStream (new FileStream (errPipe.GetWriteFD())); - e.Serialize (outputStream); - } - catch (...) { } - } - - _exit (1); - } - - vector adminPassword (request.AdminPassword.size() + 1); - int timeout = 6000; - - if (request.FastElevation) - { - string dummyPassword = "dummy\n"; - adminPassword = vector (dummyPassword.size()); - Memory::Copy (&adminPassword.front(), dummyPassword.c_str(), dummyPassword.size()); - timeout = 1000; - } - else - { - Memory::Copy (&adminPassword.front(), request.AdminPassword.c_str(), request.AdminPassword.size()); - adminPassword[request.AdminPassword.size()] = '\n'; - } - - if (write (inPipe->GetWriteFD(), &adminPassword.front(), adminPassword.size())) { } // Errors ignored - - Memory::Erase (&adminPassword.front(), adminPassword.size()); - - throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, O_NONBLOCK) == -1); - throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); - - vector buffer (4096), errOutput (4096); - buffer.clear (); - errOutput.clear (); - - Poller poller (outPipe->GetReadFD(), errPipe.GetReadFD()); - int status, waitRes; - int exitCode = 1; - - try - { - do - { - ssize_t bytesRead = 0; - foreach (int fd, poller.WaitForData (timeout)) - { - bytesRead = read (fd, &buffer[0], buffer.capacity()); - if (bytesRead > 0 && fd == errPipe.GetReadFD()) - { - errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead); - - if (bytesRead > 5 && bytesRead < 80) // Short message captured - timeout = 200; - } - } - - if (bytesRead == 0) - { - waitRes = waitpid (forkedPid, &status, 0); - break; - } - - } while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0); - - errOutput.push_back (0); - } - catch (TimeOut&) - { - if ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0) - { - inPipe->Close(); - outPipe->Close(); - errPipe.Close(); - - if (request.FastElevation) - { - // Prevent defunct process - struct WaitFunctor : public Functor - { - WaitFunctor (int pid) : Pid (pid) { } - virtual void operator() () - { - int status; - for (int t = 0; t < 10 && waitpid (Pid, &status, WNOHANG) == 0; t++) - Thread::Sleep (1000); - } - int Pid; - }; - Thread thread; - thread.Start (new WaitFunctor (forkedPid)); - - throw ElevationFailed (SRC_POS, "sudo", 1, ""); - } - - waitRes = waitpid (forkedPid, &status, 0); - } - } - - if (!errOutput.empty()) - { - auto_ptr deserializedObject; - Exception *deserializedException = nullptr; - - try - { - shared_ptr stream (new MemoryStream (ConstBufferPtr ((byte *) &errOutput[0], errOutput.size()))); - deserializedObject.reset (Serializable::DeserializeNew (stream)); - deserializedException = dynamic_cast (deserializedObject.get()); - } - catch (...) { } - - if (deserializedException) - deserializedException->Throw(); - } - - throw_sys_if (waitRes == -1); - exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1); - if (exitCode != 0) - { - string strErrOutput; - strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end()); - throw ElevationFailed (SRC_POS, "sudo", exitCode, strErrOutput); - } - - throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, 0) == -1); - - ServiceInputStream = shared_ptr (new FileStream (inPipe->GetWriteFD())); - ServiceOutputStream = shared_ptr (new FileStream (outPipe->GetReadFD())); - - // Send sync code - byte sync[] = { 0, 0x11, 0x22 }; - ServiceInputStream->Write (ConstBufferPtr (sync, array_capacity (sync))); - - AdminInputPipe = inPipe; - AdminOutputPipe = outPipe; - } - - void CoreService::Stop () - { - ExitRequest exitRequest; - exitRequest.Serialize (ServiceInputStream); - } - - shared_ptr CoreService::AdminPasswordCallback; - - auto_ptr CoreService::AdminInputPipe; - auto_ptr CoreService::AdminOutputPipe; - - auto_ptr CoreService::InputPipe; - auto_ptr CoreService::OutputPipe; - shared_ptr CoreService::ServiceInputStream; - shared_ptr CoreService::ServiceOutputStream; - - bool CoreService::ElevatedPrivileges = false; - bool CoreService::ElevatedServiceAvailable = false; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "CoreService.h" +#include +#include +#include "Platform/FileStream.h" +#include "Platform/MemoryStream.h" +#include "Platform/Serializable.h" +#include "Platform/SystemLog.h" +#include "Platform/Thread.h" +#include "Platform/Unix/Poller.h" +#include "Core/Core.h" +#include "CoreUnix.h" +#include "CoreServiceRequest.h" +#include "CoreServiceResponse.h" + +namespace TrueCrypt +{ + template + auto_ptr CoreService::GetResponse () + { + auto_ptr deserializedObject (Serializable::DeserializeNew (ServiceOutputStream)); + + Exception *deserializedException = dynamic_cast (deserializedObject.get()); + if (deserializedException) + deserializedException->Throw(); + + if (dynamic_cast (deserializedObject.get()) == nullptr) + throw ParameterIncorrect (SRC_POS); + + return auto_ptr (dynamic_cast (deserializedObject.release())); + } + + void CoreService::ProcessElevatedRequests () + { + int pid = fork(); + throw_sys_if (pid == -1); + if (pid == 0) + { + try + { + int f = open ("/dev/null", 0); + throw_sys_sub_if (f == -1, "/dev/null"); + throw_sys_if (dup2 (f, STDERR_FILENO) == -1); + + // Wait for sync code + while (true) + { + byte b; + throw_sys_if (read (STDIN_FILENO, &b, 1) != 1); + if (b != 0x00) + continue; + + throw_sys_if (read (STDIN_FILENO, &b, 1) != 1); + if (b != 0x11) + continue; + + throw_sys_if (read (STDIN_FILENO, &b, 1) != 1); + if (b == 0x22) + break; + } + + ElevatedPrivileges = true; + ProcessRequests (STDIN_FILENO, STDOUT_FILENO); + _exit (0); + } + catch (exception &e) + { +#ifdef DEBUG + SystemLog::WriteException (e); +#endif + } + catch (...) { } + _exit (1); + } + } + + void CoreService::ProcessRequests (int inputFD, int outputFD) + { + try + { + Core = CoreDirect; + + shared_ptr inputStream (new FileStream (inputFD != -1 ? inputFD : InputPipe->GetReadFD())); + shared_ptr outputStream (new FileStream (outputFD != -1 ? outputFD : OutputPipe->GetWriteFD())); + + while (true) + { + shared_ptr request = Serializable::DeserializeNew (inputStream); + + try + { + // ExitRequest + if (dynamic_cast (request.get()) != nullptr) + { + if (ElevatedServiceAvailable) + request->Serialize (ServiceInputStream); + return; + } + + if (!ElevatedPrivileges && request->ElevateUserPrivileges) + { + if (!ElevatedServiceAvailable) + { + finally_do_arg (string *, &request->AdminPassword, { StringConverter::Erase (*finally_arg); }); + + CoreService::StartElevated (*request); + ElevatedServiceAvailable = true; + } + + request->Serialize (ServiceInputStream); + GetResponse ()->Serialize (outputStream); + continue; + } + + // CheckFilesystemRequest + CheckFilesystemRequest *checkRequest = dynamic_cast (request.get()); + if (checkRequest) + { + Core->CheckFilesystem (checkRequest->MountedVolumeInfo, checkRequest->Repair); + + CheckFilesystemResponse().Serialize (outputStream); + continue; + } + + // DismountFilesystemRequest + DismountFilesystemRequest *dismountFsRequest = dynamic_cast (request.get()); + if (dismountFsRequest) + { + Core->DismountFilesystem (dismountFsRequest->MountPoint, dismountFsRequest->Force); + + DismountFilesystemResponse().Serialize (outputStream); + continue; + } + + // DismountVolumeRequest + DismountVolumeRequest *dismountRequest = dynamic_cast (request.get()); + if (dismountRequest) + { + DismountVolumeResponse response; + response.DismountedVolumeInfo = Core->DismountVolume (dismountRequest->MountedVolumeInfo, dismountRequest->IgnoreOpenFiles, dismountRequest->SyncVolumeInfo); + response.Serialize (outputStream); + continue; + } + + // GetDeviceSizeRequest + GetDeviceSizeRequest *getDeviceSizeRequest = dynamic_cast (request.get()); + if (getDeviceSizeRequest) + { + GetDeviceSizeResponse response; + response.Size = Core->GetDeviceSize (getDeviceSizeRequest->Path); + response.Serialize (outputStream); + continue; + } + + // GetHostDevicesRequest + GetHostDevicesRequest *getHostDevicesRequest = dynamic_cast (request.get()); + if (getHostDevicesRequest) + { + GetHostDevicesResponse response; + response.HostDevices = Core->GetHostDevices (getHostDevicesRequest->PathListOnly); + response.Serialize (outputStream); + continue; + } + + // MountVolumeRequest + MountVolumeRequest *mountRequest = dynamic_cast (request.get()); + if (mountRequest) + { + MountVolumeResponse ( + Core->MountVolume (*mountRequest->Options) + ).Serialize (outputStream); + + continue; + } + + // SetFileOwnerRequest + SetFileOwnerRequest *setFileOwnerRequest = dynamic_cast (request.get()); + if (setFileOwnerRequest) + { + CoreUnix *coreUnix = dynamic_cast (Core.get()); + if (!coreUnix) + throw ParameterIncorrect (SRC_POS); + + coreUnix->SetFileOwner (setFileOwnerRequest->Path, setFileOwnerRequest->Owner); + SetFileOwnerResponse().Serialize (outputStream); + continue; + } + + throw ParameterIncorrect (SRC_POS); + } + catch (Exception &e) + { + e.Serialize (outputStream); + } + catch (exception &e) + { + ExternalException (SRC_POS, StringConverter::ToExceptionString (e)).Serialize (outputStream); + } + } + } + catch (exception &e) + { +#ifdef DEBUG + SystemLog::WriteException (e); +#endif + throw; + } + } + + void CoreService::RequestCheckFilesystem (shared_ptr mountedVolume, bool repair) + { + CheckFilesystemRequest request (mountedVolume, repair); + SendRequest (request); + } + + void CoreService::RequestDismountFilesystem (const DirectoryPath &mountPoint, bool force) + { + DismountFilesystemRequest request (mountPoint, force); + SendRequest (request); + } + + shared_ptr CoreService::RequestDismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) + { + DismountVolumeRequest request (mountedVolume, ignoreOpenFiles, syncVolumeInfo); + return SendRequest (request)->DismountedVolumeInfo; + } + + uint64 CoreService::RequestGetDeviceSize (const DevicePath &devicePath) + { + GetDeviceSizeRequest request (devicePath); + return SendRequest (request)->Size; + } + + HostDeviceList CoreService::RequestGetHostDevices (bool pathListOnly) + { + GetHostDevicesRequest request (pathListOnly); + return SendRequest (request)->HostDevices; + } + + shared_ptr CoreService::RequestMountVolume (MountOptions &options) + { + MountVolumeRequest request (&options); + return SendRequest (request)->MountedVolumeInfo; + } + + void CoreService::RequestSetFileOwner (const FilesystemPath &path, const UserId &owner) + { + SetFileOwnerRequest request (path, owner); + SendRequest (request); + } + + template + auto_ptr CoreService::SendRequest (CoreServiceRequest &request) + { + static Mutex mutex; + ScopeLock lock (mutex); + + if (request.RequiresElevation()) + { + request.ElevateUserPrivileges = true; + request.FastElevation = !ElevatedServiceAvailable; + request.ApplicationExecutablePath = Core->GetApplicationExecutablePath(); + + while (!ElevatedServiceAvailable) + { + try + { + request.Serialize (ServiceInputStream); + auto_ptr response (GetResponse ()); + ElevatedServiceAvailable = true; + return response; + } + catch (ElevationFailed &e) + { + if (!request.FastElevation) + { + ExceptionEventArgs args (e); + Core->WarningEvent.Raise (args); + } + + request.FastElevation = false; + (*AdminPasswordCallback) (request.AdminPassword); + } + } + } + + finally_do_arg (string *, &request.AdminPassword, { StringConverter::Erase (*finally_arg); }); + + request.Serialize (ServiceInputStream); + return GetResponse (); + } + + void CoreService::Start () + { + InputPipe.reset (new Pipe()); + OutputPipe.reset (new Pipe()); + + int pid = fork(); + throw_sys_if (pid == -1); + + if (pid == 0) + { + try + { + ProcessRequests(); + _exit (0); + } + catch (...) { } + _exit (1); + } + + ServiceInputStream = shared_ptr (new FileStream (InputPipe->GetWriteFD())); + ServiceOutputStream = shared_ptr (new FileStream (OutputPipe->GetReadFD())); + } + + void CoreService::StartElevated (const CoreServiceRequest &request) + { + auto_ptr inPipe (new Pipe()); + auto_ptr outPipe (new Pipe()); + Pipe errPipe; + + int forkedPid = fork(); + throw_sys_if (forkedPid == -1); + + if (forkedPid == 0) + { + try + { + try + { + throw_sys_if (dup2 (inPipe->GetReadFD(), STDIN_FILENO) == -1); + throw_sys_if (dup2 (outPipe->GetWriteFD(), STDOUT_FILENO) == -1); + throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1); + + string appPath = request.ApplicationExecutablePath; + if (appPath.empty()) + appPath = "truecrypt"; + + const char *args[] = { "sudo", "-S", "-p", "", appPath.c_str(), TC_CORE_SERVICE_CMDLINE_OPTION, nullptr }; + execvp (args[0], ((char* const*) args)); + throw SystemException (SRC_POS, args[0]); + } + catch (Exception &) + { + throw; + } + catch (exception &e) + { + throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e)); + } + catch (...) + { + throw UnknownException (SRC_POS); + } + } + catch (Exception &e) + { + try + { + shared_ptr outputStream (new FileStream (errPipe.GetWriteFD())); + e.Serialize (outputStream); + } + catch (...) { } + } + + _exit (1); + } + + vector adminPassword (request.AdminPassword.size() + 1); + int timeout = 6000; + + if (request.FastElevation) + { + string dummyPassword = "dummy\n"; + adminPassword = vector (dummyPassword.size()); + Memory::Copy (&adminPassword.front(), dummyPassword.c_str(), dummyPassword.size()); + timeout = 1000; + } + else + { + Memory::Copy (&adminPassword.front(), request.AdminPassword.c_str(), request.AdminPassword.size()); + adminPassword[request.AdminPassword.size()] = '\n'; + } + + if (write (inPipe->GetWriteFD(), &adminPassword.front(), adminPassword.size())) { } // Errors ignored + + Memory::Erase (&adminPassword.front(), adminPassword.size()); + + throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, O_NONBLOCK) == -1); + throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); + + vector buffer (4096), errOutput (4096); + buffer.clear (); + errOutput.clear (); + + Poller poller (outPipe->GetReadFD(), errPipe.GetReadFD()); + int status, waitRes; + int exitCode = 1; + + try + { + do + { + ssize_t bytesRead = 0; + foreach (int fd, poller.WaitForData (timeout)) + { + bytesRead = read (fd, &buffer[0], buffer.capacity()); + if (bytesRead > 0 && fd == errPipe.GetReadFD()) + { + errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead); + + if (bytesRead > 5 && bytesRead < 80) // Short message captured + timeout = 200; + } + } + + if (bytesRead == 0) + { + waitRes = waitpid (forkedPid, &status, 0); + break; + } + + } while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0); + + errOutput.push_back (0); + } + catch (TimeOut&) + { + if ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0) + { + inPipe->Close(); + outPipe->Close(); + errPipe.Close(); + + if (request.FastElevation) + { + // Prevent defunct process + struct WaitFunctor : public Functor + { + WaitFunctor (int pid) : Pid (pid) { } + virtual void operator() () + { + int status; + for (int t = 0; t < 10 && waitpid (Pid, &status, WNOHANG) == 0; t++) + Thread::Sleep (1000); + } + int Pid; + }; + Thread thread; + thread.Start (new WaitFunctor (forkedPid)); + + throw ElevationFailed (SRC_POS, "sudo", 1, ""); + } + + waitRes = waitpid (forkedPid, &status, 0); + } + } + + if (!errOutput.empty()) + { + auto_ptr deserializedObject; + Exception *deserializedException = nullptr; + + try + { + shared_ptr stream (new MemoryStream (ConstBufferPtr ((byte *) &errOutput[0], errOutput.size()))); + deserializedObject.reset (Serializable::DeserializeNew (stream)); + deserializedException = dynamic_cast (deserializedObject.get()); + } + catch (...) { } + + if (deserializedException) + deserializedException->Throw(); + } + + throw_sys_if (waitRes == -1); + exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1); + if (exitCode != 0) + { + string strErrOutput; + strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end()); + throw ElevationFailed (SRC_POS, "sudo", exitCode, strErrOutput); + } + + throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, 0) == -1); + + ServiceInputStream = shared_ptr (new FileStream (inPipe->GetWriteFD())); + ServiceOutputStream = shared_ptr (new FileStream (outPipe->GetReadFD())); + + // Send sync code + byte sync[] = { 0, 0x11, 0x22 }; + ServiceInputStream->Write (ConstBufferPtr (sync, array_capacity (sync))); + + AdminInputPipe = inPipe; + AdminOutputPipe = outPipe; + } + + void CoreService::Stop () + { + ExitRequest exitRequest; + exitRequest.Serialize (ServiceInputStream); + } + + shared_ptr CoreService::AdminPasswordCallback; + + auto_ptr CoreService::AdminInputPipe; + auto_ptr CoreService::AdminOutputPipe; + + auto_ptr CoreService::InputPipe; + auto_ptr CoreService::OutputPipe; + shared_ptr CoreService::ServiceInputStream; + shared_ptr CoreService::ServiceOutputStream; + + bool CoreService::ElevatedPrivileges = false; + bool CoreService::ElevatedServiceAvailable = false; +} diff --git a/Core/Unix/CoreService.h b/Core/Unix/CoreService.h index 3f72771..5531765 100644 --- a/Core/Unix/CoreService.h +++ b/Core/Unix/CoreService.h @@ -1,62 +1,62 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_Unix_CoreService -#define TC_HEADER_Core_Unix_CoreService - -#include "CoreServiceRequest.h" -#include "Platform/Stream.h" -#include "Platform/Unix/Pipe.h" -#include "Core/Core.h" - -namespace TrueCrypt -{ - // This service facilitates process forking and elevation of user privileges - class CoreService - { - public: - static void ProcessElevatedRequests (); - static void ProcessRequests (int inputFD = -1, int outputFD = -1); - static void RequestCheckFilesystem (shared_ptr mountedVolume, bool repair); - static void RequestDismountFilesystem (const DirectoryPath &mountPoint, bool force); - static shared_ptr RequestDismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false); - static uint64 RequestGetDeviceSize (const DevicePath &devicePath); - static HostDeviceList RequestGetHostDevices (bool pathListOnly); - static shared_ptr RequestMountVolume (MountOptions &options); - static void RequestSetFileOwner (const FilesystemPath &path, const UserId &owner); - static void SetAdminPasswordCallback (shared_ptr functor) { AdminPasswordCallback = functor; } - static void Start (); - static void Stop (); - - protected: - template static auto_ptr GetResponse (); - template static auto_ptr SendRequest (CoreServiceRequest &request); - static void StartElevated (const CoreServiceRequest &request); - - static shared_ptr AdminPasswordCallback; - - static auto_ptr AdminInputPipe; - static auto_ptr AdminOutputPipe; - - static auto_ptr InputPipe; - static auto_ptr OutputPipe; - static shared_ptr ServiceInputStream; - static shared_ptr ServiceOutputStream; - - static bool ElevatedPrivileges; - static bool ElevatedServiceAvailable; - static bool Running; - - private: - CoreService (); - }; - -#define TC_CORE_SERVICE_CMDLINE_OPTION "--core-service" -} - -#endif // TC_HEADER_Core_Unix_CoreService +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_Unix_CoreService +#define TC_HEADER_Core_Unix_CoreService + +#include "CoreServiceRequest.h" +#include "Platform/Stream.h" +#include "Platform/Unix/Pipe.h" +#include "Core/Core.h" + +namespace TrueCrypt +{ + // This service facilitates process forking and elevation of user privileges + class CoreService + { + public: + static void ProcessElevatedRequests (); + static void ProcessRequests (int inputFD = -1, int outputFD = -1); + static void RequestCheckFilesystem (shared_ptr mountedVolume, bool repair); + static void RequestDismountFilesystem (const DirectoryPath &mountPoint, bool force); + static shared_ptr RequestDismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false); + static uint64 RequestGetDeviceSize (const DevicePath &devicePath); + static HostDeviceList RequestGetHostDevices (bool pathListOnly); + static shared_ptr RequestMountVolume (MountOptions &options); + static void RequestSetFileOwner (const FilesystemPath &path, const UserId &owner); + static void SetAdminPasswordCallback (shared_ptr functor) { AdminPasswordCallback = functor; } + static void Start (); + static void Stop (); + + protected: + template static auto_ptr GetResponse (); + template static auto_ptr SendRequest (CoreServiceRequest &request); + static void StartElevated (const CoreServiceRequest &request); + + static shared_ptr AdminPasswordCallback; + + static auto_ptr AdminInputPipe; + static auto_ptr AdminOutputPipe; + + static auto_ptr InputPipe; + static auto_ptr OutputPipe; + static shared_ptr ServiceInputStream; + static shared_ptr ServiceOutputStream; + + static bool ElevatedPrivileges; + static bool ElevatedServiceAvailable; + static bool Running; + + private: + CoreService (); + }; + +#define TC_CORE_SERVICE_CMDLINE_OPTION "--core-service" +} + +#endif // TC_HEADER_Core_Unix_CoreService diff --git a/Core/Unix/CoreServiceProxy.h b/Core/Unix/CoreServiceProxy.h index 6cd7122..d30e37c 100644 --- a/Core/Unix/CoreServiceProxy.h +++ b/Core/Unix/CoreServiceProxy.h @@ -1,147 +1,147 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_Windows_CoreServiceProxy -#define TC_HEADER_Core_Windows_CoreServiceProxy - -#include "CoreService.h" -#include "Volume/VolumePasswordCache.h" - -namespace TrueCrypt -{ - template - class CoreServiceProxy : public T - { - public: - CoreServiceProxy () { } - virtual ~CoreServiceProxy () { } - - virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair) const - { - CoreService::RequestCheckFilesystem (mountedVolume, repair); - } - - virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const - { - CoreService::RequestDismountFilesystem (mountPoint, force); - } - - virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false) - { - shared_ptr dismountedVolumeInfo = CoreService::RequestDismountVolume (mountedVolume, ignoreOpenFiles, syncVolumeInfo); - - VolumeEventArgs eventArgs (dismountedVolumeInfo); - T::VolumeDismountedEvent.Raise (eventArgs); - - return dismountedVolumeInfo; - } - - virtual uint64 GetDeviceSize (const DevicePath &devicePath) const - { - return CoreService::RequestGetDeviceSize (devicePath); - } - -#ifndef TC_LINUX - virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const - { - if (pathListOnly) - return T::GetHostDevices (pathListOnly); - else - return CoreService::RequestGetHostDevices (pathListOnly); - } -#endif - virtual bool IsPasswordCacheEmpty () const { return VolumePasswordCache::IsEmpty(); } - - virtual shared_ptr MountVolume (MountOptions &options) - { - shared_ptr mountedVolume; - - if (!VolumePasswordCache::IsEmpty() - && (!options.Password || options.Password->IsEmpty()) - && (!options.Keyfiles || options.Keyfiles->empty())) - { - finally_do_arg (MountOptions*, &options, { if (finally_arg->Password) finally_arg->Password.reset(); }); - - PasswordIncorrect passwordException; - foreach (shared_ptr password, VolumePasswordCache::GetPasswords()) - { - try - { - options.Password = password; - mountedVolume = CoreService::RequestMountVolume (options); - break; - } - catch (PasswordIncorrect &e) - { - passwordException = e; - } - } - - if (!mountedVolume) - passwordException.Throw(); - } - else - { - MountOptions newOptions = options; - - newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); - if (newOptions.Keyfiles) - newOptions.Keyfiles->clear(); - - newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword); - if (newOptions.ProtectionKeyfiles) - newOptions.ProtectionKeyfiles->clear(); - - try - { - mountedVolume = CoreService::RequestMountVolume (newOptions); - } - catch (ProtectionPasswordIncorrect &e) - { - if (options.ProtectionKeyfiles && !options.ProtectionKeyfiles->empty()) - throw ProtectionPasswordKeyfilesIncorrect (e.what()); - throw; - } - catch (PasswordIncorrect &e) - { - if (options.Keyfiles && !options.Keyfiles->empty()) - throw PasswordKeyfilesIncorrect (e.what()); - throw; - } - - if (options.CachePassword - && ((options.Password && !options.Password->IsEmpty()) || (options.Keyfiles && !options.Keyfiles->empty()))) - { - VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password)); - } - } - - VolumeEventArgs eventArgs (mountedVolume); - T::VolumeMountedEvent.Raise (eventArgs); - - return mountedVolume; - } - - virtual void SetAdminPasswordCallback (shared_ptr functor) - { - CoreService::SetAdminPasswordCallback (functor); - } - - virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const - { - CoreService::RequestSetFileOwner (path, owner); - } - - virtual void WipePasswordCache () const - { - VolumePasswordCache::Clear(); - } - }; -} - -#endif // TC_HEADER_Core_Windows_CoreServiceProxy +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_Windows_CoreServiceProxy +#define TC_HEADER_Core_Windows_CoreServiceProxy + +#include "CoreService.h" +#include "Volume/VolumePasswordCache.h" + +namespace TrueCrypt +{ + template + class CoreServiceProxy : public T + { + public: + CoreServiceProxy () { } + virtual ~CoreServiceProxy () { } + + virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair) const + { + CoreService::RequestCheckFilesystem (mountedVolume, repair); + } + + virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const + { + CoreService::RequestDismountFilesystem (mountPoint, force); + } + + virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false) + { + shared_ptr dismountedVolumeInfo = CoreService::RequestDismountVolume (mountedVolume, ignoreOpenFiles, syncVolumeInfo); + + VolumeEventArgs eventArgs (dismountedVolumeInfo); + T::VolumeDismountedEvent.Raise (eventArgs); + + return dismountedVolumeInfo; + } + + virtual uint64 GetDeviceSize (const DevicePath &devicePath) const + { + return CoreService::RequestGetDeviceSize (devicePath); + } + +#ifndef TC_LINUX + virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const + { + if (pathListOnly) + return T::GetHostDevices (pathListOnly); + else + return CoreService::RequestGetHostDevices (pathListOnly); + } +#endif + virtual bool IsPasswordCacheEmpty () const { return VolumePasswordCache::IsEmpty(); } + + virtual shared_ptr MountVolume (MountOptions &options) + { + shared_ptr mountedVolume; + + if (!VolumePasswordCache::IsEmpty() + && (!options.Password || options.Password->IsEmpty()) + && (!options.Keyfiles || options.Keyfiles->empty())) + { + finally_do_arg (MountOptions*, &options, { if (finally_arg->Password) finally_arg->Password.reset(); }); + + PasswordIncorrect passwordException; + foreach (shared_ptr password, VolumePasswordCache::GetPasswords()) + { + try + { + options.Password = password; + mountedVolume = CoreService::RequestMountVolume (options); + break; + } + catch (PasswordIncorrect &e) + { + passwordException = e; + } + } + + if (!mountedVolume) + passwordException.Throw(); + } + else + { + MountOptions newOptions = options; + + newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); + if (newOptions.Keyfiles) + newOptions.Keyfiles->clear(); + + newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword); + if (newOptions.ProtectionKeyfiles) + newOptions.ProtectionKeyfiles->clear(); + + try + { + mountedVolume = CoreService::RequestMountVolume (newOptions); + } + catch (ProtectionPasswordIncorrect &e) + { + if (options.ProtectionKeyfiles && !options.ProtectionKeyfiles->empty()) + throw ProtectionPasswordKeyfilesIncorrect (e.what()); + throw; + } + catch (PasswordIncorrect &e) + { + if (options.Keyfiles && !options.Keyfiles->empty()) + throw PasswordKeyfilesIncorrect (e.what()); + throw; + } + + if (options.CachePassword + && ((options.Password && !options.Password->IsEmpty()) || (options.Keyfiles && !options.Keyfiles->empty()))) + { + VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password)); + } + } + + VolumeEventArgs eventArgs (mountedVolume); + T::VolumeMountedEvent.Raise (eventArgs); + + return mountedVolume; + } + + virtual void SetAdminPasswordCallback (shared_ptr functor) + { + CoreService::SetAdminPasswordCallback (functor); + } + + virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const + { + CoreService::RequestSetFileOwner (path, owner); + } + + virtual void WipePasswordCache () const + { + VolumePasswordCache::Clear(); + } + }; +} + +#endif // TC_HEADER_Core_Windows_CoreServiceProxy diff --git a/Core/Unix/CoreServiceRequest.cpp b/Core/Unix/CoreServiceRequest.cpp index 8586ee1..a0b45a5 100644 --- a/Core/Unix/CoreServiceRequest.cpp +++ b/Core/Unix/CoreServiceRequest.cpp @@ -1,248 +1,248 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include "CoreServiceRequest.h" -#include "Platform/SerializerFactory.h" - -namespace TrueCrypt -{ - void CoreServiceRequest::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - sr.Deserialize ("AdminPassword", AdminPassword); - ApplicationExecutablePath = sr.DeserializeWString ("ApplicationExecutablePath"); - sr.Deserialize ("ElevateUserPrivileges", ElevateUserPrivileges); - sr.Deserialize ("FastElevation", FastElevation); - } - - void CoreServiceRequest::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("AdminPassword", AdminPassword); - sr.Serialize ("ApplicationExecutablePath", wstring (ApplicationExecutablePath)); - sr.Serialize ("ElevateUserPrivileges", ElevateUserPrivileges); - sr.Serialize ("FastElevation", FastElevation); - } - - // CheckFilesystemRequest - void CheckFilesystemRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - Serializer sr (stream); - MountedVolumeInfo = Serializable::DeserializeNew (stream); - sr.Deserialize ("Repair", Repair); - } - - bool CheckFilesystemRequest::RequiresElevation () const - { -#ifdef TC_MACOSX - return false; -#endif - return !Core->HasAdminPrivileges(); - } - - void CheckFilesystemRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - Serializer sr (stream); - MountedVolumeInfo->Serialize (stream); - sr.Serialize ("Repair", Repair); - } - - // DismountFilesystemRequest - void DismountFilesystemRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - Serializer sr (stream); - sr.Deserialize ("Force", Force); - MountPoint = sr.DeserializeWString ("MountPoint"); - } - - bool DismountFilesystemRequest::RequiresElevation () const - { - return !Core->HasAdminPrivileges(); - } - - void DismountFilesystemRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("Force", Force); - sr.Serialize ("MountPoint", wstring (MountPoint)); - } - - // DismountVolumeRequest - void DismountVolumeRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - Serializer sr (stream); - sr.Deserialize ("IgnoreOpenFiles", IgnoreOpenFiles); - sr.Deserialize ("SyncVolumeInfo", SyncVolumeInfo); - MountedVolumeInfo = Serializable::DeserializeNew (stream); - } - - bool DismountVolumeRequest::RequiresElevation () const - { -#ifdef TC_MACOSX - if (MountedVolumeInfo->Path.IsDevice()) - { - try - { - File file; - file.Open (MountedVolumeInfo->Path, File::OpenReadWrite); - } - catch (...) - { - return true; - } - } - - return false; -#endif - return !Core->HasAdminPrivileges(); - } - - void DismountVolumeRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("IgnoreOpenFiles", IgnoreOpenFiles); - sr.Serialize ("SyncVolumeInfo", SyncVolumeInfo); - MountedVolumeInfo->Serialize (stream); - } - - // GetDeviceSizeRequest - void GetDeviceSizeRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - Serializer sr (stream); - Path = sr.DeserializeWString ("Path"); - } - - bool GetDeviceSizeRequest::RequiresElevation () const - { - return !Core->HasAdminPrivileges(); - } - - void GetDeviceSizeRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("Path", wstring (Path)); - } - - // GetHostDevicesRequest - void GetHostDevicesRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - Serializer sr (stream); - sr.Deserialize ("PathListOnly", PathListOnly); - } - - bool GetHostDevicesRequest::RequiresElevation () const - { - return !Core->HasAdminPrivileges(); - } - - void GetHostDevicesRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("PathListOnly", PathListOnly); - } - - // ExitRequest - void ExitRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - } - - void ExitRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - } - - // MountVolumeRequest - void MountVolumeRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - Serializer sr (stream); - DeserializedOptions = Serializable::DeserializeNew (stream); - Options = DeserializedOptions.get(); - } - - bool MountVolumeRequest::RequiresElevation () const - { -#ifdef TC_MACOSX - if (Options->Path->IsDevice()) - { - try - { - File file; - file.Open (*Options->Path, File::OpenReadWrite); - } - catch (...) - { - return true; - } - } - - return false; -#endif - return !Core->HasAdminPrivileges(); - } - - void MountVolumeRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - Serializer sr (stream); - Options->Serialize (stream); - } - - // SetFileOwnerRequest - void SetFileOwnerRequest::Deserialize (shared_ptr stream) - { - CoreServiceRequest::Deserialize (stream); - Serializer sr (stream); - - uint64 owner; - sr.Deserialize ("Owner", owner); - Owner.SystemId = static_cast (owner); - - Path = sr.DeserializeWString ("Path"); - } - - bool SetFileOwnerRequest::RequiresElevation () const - { - return !Core->HasAdminPrivileges(); - } - - void SetFileOwnerRequest::Serialize (shared_ptr stream) const - { - CoreServiceRequest::Serialize (stream); - Serializer sr (stream); - - uint64 owner = Owner.SystemId; - sr.Serialize ("Owner", owner); - - sr.Serialize ("Path", wstring (Path)); - } - - - TC_SERIALIZER_FACTORY_ADD_CLASS (CoreServiceRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (CheckFilesystemRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (DismountFilesystemRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (DismountVolumeRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (ExitRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeRequest); - TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerRequest); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include "CoreServiceRequest.h" +#include "Platform/SerializerFactory.h" + +namespace TrueCrypt +{ + void CoreServiceRequest::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + sr.Deserialize ("AdminPassword", AdminPassword); + ApplicationExecutablePath = sr.DeserializeWString ("ApplicationExecutablePath"); + sr.Deserialize ("ElevateUserPrivileges", ElevateUserPrivileges); + sr.Deserialize ("FastElevation", FastElevation); + } + + void CoreServiceRequest::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("AdminPassword", AdminPassword); + sr.Serialize ("ApplicationExecutablePath", wstring (ApplicationExecutablePath)); + sr.Serialize ("ElevateUserPrivileges", ElevateUserPrivileges); + sr.Serialize ("FastElevation", FastElevation); + } + + // CheckFilesystemRequest + void CheckFilesystemRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + MountedVolumeInfo = Serializable::DeserializeNew (stream); + sr.Deserialize ("Repair", Repair); + } + + bool CheckFilesystemRequest::RequiresElevation () const + { +#ifdef TC_MACOSX + return false; +#endif + return !Core->HasAdminPrivileges(); + } + + void CheckFilesystemRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + MountedVolumeInfo->Serialize (stream); + sr.Serialize ("Repair", Repair); + } + + // DismountFilesystemRequest + void DismountFilesystemRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + sr.Deserialize ("Force", Force); + MountPoint = sr.DeserializeWString ("MountPoint"); + } + + bool DismountFilesystemRequest::RequiresElevation () const + { + return !Core->HasAdminPrivileges(); + } + + void DismountFilesystemRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("Force", Force); + sr.Serialize ("MountPoint", wstring (MountPoint)); + } + + // DismountVolumeRequest + void DismountVolumeRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + sr.Deserialize ("IgnoreOpenFiles", IgnoreOpenFiles); + sr.Deserialize ("SyncVolumeInfo", SyncVolumeInfo); + MountedVolumeInfo = Serializable::DeserializeNew (stream); + } + + bool DismountVolumeRequest::RequiresElevation () const + { +#ifdef TC_MACOSX + if (MountedVolumeInfo->Path.IsDevice()) + { + try + { + File file; + file.Open (MountedVolumeInfo->Path, File::OpenReadWrite); + } + catch (...) + { + return true; + } + } + + return false; +#endif + return !Core->HasAdminPrivileges(); + } + + void DismountVolumeRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("IgnoreOpenFiles", IgnoreOpenFiles); + sr.Serialize ("SyncVolumeInfo", SyncVolumeInfo); + MountedVolumeInfo->Serialize (stream); + } + + // GetDeviceSizeRequest + void GetDeviceSizeRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + Path = sr.DeserializeWString ("Path"); + } + + bool GetDeviceSizeRequest::RequiresElevation () const + { + return !Core->HasAdminPrivileges(); + } + + void GetDeviceSizeRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("Path", wstring (Path)); + } + + // GetHostDevicesRequest + void GetHostDevicesRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + sr.Deserialize ("PathListOnly", PathListOnly); + } + + bool GetHostDevicesRequest::RequiresElevation () const + { + return !Core->HasAdminPrivileges(); + } + + void GetHostDevicesRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("PathListOnly", PathListOnly); + } + + // ExitRequest + void ExitRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + } + + void ExitRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + } + + // MountVolumeRequest + void MountVolumeRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + DeserializedOptions = Serializable::DeserializeNew (stream); + Options = DeserializedOptions.get(); + } + + bool MountVolumeRequest::RequiresElevation () const + { +#ifdef TC_MACOSX + if (Options->Path->IsDevice()) + { + try + { + File file; + file.Open (*Options->Path, File::OpenReadWrite); + } + catch (...) + { + return true; + } + } + + return false; +#endif + return !Core->HasAdminPrivileges(); + } + + void MountVolumeRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + Options->Serialize (stream); + } + + // SetFileOwnerRequest + void SetFileOwnerRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + + uint64 owner; + sr.Deserialize ("Owner", owner); + Owner.SystemId = static_cast (owner); + + Path = sr.DeserializeWString ("Path"); + } + + bool SetFileOwnerRequest::RequiresElevation () const + { + return !Core->HasAdminPrivileges(); + } + + void SetFileOwnerRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + + uint64 owner = Owner.SystemId; + sr.Serialize ("Owner", owner); + + sr.Serialize ("Path", wstring (Path)); + } + + + TC_SERIALIZER_FACTORY_ADD_CLASS (CoreServiceRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (CheckFilesystemRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (DismountFilesystemRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (DismountVolumeRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (ExitRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeRequest); + TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerRequest); +} diff --git a/Core/Unix/CoreServiceRequest.h b/Core/Unix/CoreServiceRequest.h index e79a3f1..e3f50ce 100644 --- a/Core/Unix/CoreServiceRequest.h +++ b/Core/Unix/CoreServiceRequest.h @@ -1,125 +1,125 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_Unix_CoreServiceRequest -#define TC_HEADER_Core_Unix_CoreServiceRequest - -#include "Platform/Serializable.h" -#include "Core/Core.h" - -namespace TrueCrypt -{ - struct CoreServiceRequest : public Serializable - { - CoreServiceRequest () : ElevateUserPrivileges (false), FastElevation (false) { } - TC_SERIALIZABLE (CoreServiceRequest); - - virtual bool RequiresElevation () const { return false; } - - string AdminPassword; - FilePath ApplicationExecutablePath; - bool ElevateUserPrivileges; - bool FastElevation; - }; - - struct CheckFilesystemRequest : CoreServiceRequest - { - CheckFilesystemRequest () { } - CheckFilesystemRequest (shared_ptr volumeInfo, bool repair) - : MountedVolumeInfo (volumeInfo), Repair (repair) { } - TC_SERIALIZABLE (CheckFilesystemRequest); - - virtual bool RequiresElevation () const; - - shared_ptr MountedVolumeInfo; - bool Repair; - }; - - struct DismountFilesystemRequest : CoreServiceRequest - { - DismountFilesystemRequest () { } - DismountFilesystemRequest (const DirectoryPath &mountPoint, bool force) - : Force (force), MountPoint (mountPoint) { } - TC_SERIALIZABLE (DismountFilesystemRequest); - - virtual bool RequiresElevation () const; - - bool Force; - DirectoryPath MountPoint; - }; - - struct DismountVolumeRequest : CoreServiceRequest - { - DismountVolumeRequest () { } - DismountVolumeRequest (shared_ptr volumeInfo, bool ignoreOpenFiles, bool syncVolumeInfo) - : IgnoreOpenFiles (ignoreOpenFiles), MountedVolumeInfo (volumeInfo), SyncVolumeInfo (syncVolumeInfo) { } - TC_SERIALIZABLE (DismountVolumeRequest); - - virtual bool RequiresElevation () const; - - bool IgnoreOpenFiles; - shared_ptr MountedVolumeInfo; - bool SyncVolumeInfo; - }; - - struct GetDeviceSizeRequest : CoreServiceRequest - { - GetDeviceSizeRequest () { } - GetDeviceSizeRequest (const DevicePath &path) : Path (path) { } - TC_SERIALIZABLE (GetDeviceSizeRequest); - - virtual bool RequiresElevation () const; - - DevicePath Path; - }; - - struct GetHostDevicesRequest : CoreServiceRequest - { - GetHostDevicesRequest () { } - GetHostDevicesRequest (bool pathListOnly) : PathListOnly (pathListOnly) { } - TC_SERIALIZABLE (GetHostDevicesRequest); - - virtual bool RequiresElevation () const; - - bool PathListOnly; - }; - - struct ExitRequest : CoreServiceRequest - { - TC_SERIALIZABLE (ExitRequest); - }; - - struct MountVolumeRequest : CoreServiceRequest - { - MountVolumeRequest () { } - MountVolumeRequest (MountOptions *options) : Options (options) { } - TC_SERIALIZABLE (MountVolumeRequest); - - virtual bool RequiresElevation () const; - - MountOptions *Options; - - protected: - shared_ptr DeserializedOptions; - }; - - - struct SetFileOwnerRequest : CoreServiceRequest - { - SetFileOwnerRequest () { } - SetFileOwnerRequest (const FilesystemPath &path, const UserId &owner) : Owner (owner), Path (path) { } - TC_SERIALIZABLE (SetFileOwnerRequest); - - virtual bool RequiresElevation () const; - - UserId Owner; - FilesystemPath Path; - }; -} - -#endif // TC_HEADER_Core_Unix_CoreServiceRequest +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_Unix_CoreServiceRequest +#define TC_HEADER_Core_Unix_CoreServiceRequest + +#include "Platform/Serializable.h" +#include "Core/Core.h" + +namespace TrueCrypt +{ + struct CoreServiceRequest : public Serializable + { + CoreServiceRequest () : ElevateUserPrivileges (false), FastElevation (false) { } + TC_SERIALIZABLE (CoreServiceRequest); + + virtual bool RequiresElevation () const { return false; } + + string AdminPassword; + FilePath ApplicationExecutablePath; + bool ElevateUserPrivileges; + bool FastElevation; + }; + + struct CheckFilesystemRequest : CoreServiceRequest + { + CheckFilesystemRequest () { } + CheckFilesystemRequest (shared_ptr volumeInfo, bool repair) + : MountedVolumeInfo (volumeInfo), Repair (repair) { } + TC_SERIALIZABLE (CheckFilesystemRequest); + + virtual bool RequiresElevation () const; + + shared_ptr MountedVolumeInfo; + bool Repair; + }; + + struct DismountFilesystemRequest : CoreServiceRequest + { + DismountFilesystemRequest () { } + DismountFilesystemRequest (const DirectoryPath &mountPoint, bool force) + : Force (force), MountPoint (mountPoint) { } + TC_SERIALIZABLE (DismountFilesystemRequest); + + virtual bool RequiresElevation () const; + + bool Force; + DirectoryPath MountPoint; + }; + + struct DismountVolumeRequest : CoreServiceRequest + { + DismountVolumeRequest () { } + DismountVolumeRequest (shared_ptr volumeInfo, bool ignoreOpenFiles, bool syncVolumeInfo) + : IgnoreOpenFiles (ignoreOpenFiles), MountedVolumeInfo (volumeInfo), SyncVolumeInfo (syncVolumeInfo) { } + TC_SERIALIZABLE (DismountVolumeRequest); + + virtual bool RequiresElevation () const; + + bool IgnoreOpenFiles; + shared_ptr MountedVolumeInfo; + bool SyncVolumeInfo; + }; + + struct GetDeviceSizeRequest : CoreServiceRequest + { + GetDeviceSizeRequest () { } + GetDeviceSizeRequest (const DevicePath &path) : Path (path) { } + TC_SERIALIZABLE (GetDeviceSizeRequest); + + virtual bool RequiresElevation () const; + + DevicePath Path; + }; + + struct GetHostDevicesRequest : CoreServiceRequest + { + GetHostDevicesRequest () { } + GetHostDevicesRequest (bool pathListOnly) : PathListOnly (pathListOnly) { } + TC_SERIALIZABLE (GetHostDevicesRequest); + + virtual bool RequiresElevation () const; + + bool PathListOnly; + }; + + struct ExitRequest : CoreServiceRequest + { + TC_SERIALIZABLE (ExitRequest); + }; + + struct MountVolumeRequest : CoreServiceRequest + { + MountVolumeRequest () { } + MountVolumeRequest (MountOptions *options) : Options (options) { } + TC_SERIALIZABLE (MountVolumeRequest); + + virtual bool RequiresElevation () const; + + MountOptions *Options; + + protected: + shared_ptr DeserializedOptions; + }; + + + struct SetFileOwnerRequest : CoreServiceRequest + { + SetFileOwnerRequest () { } + SetFileOwnerRequest (const FilesystemPath &path, const UserId &owner) : Owner (owner), Path (path) { } + TC_SERIALIZABLE (SetFileOwnerRequest); + + virtual bool RequiresElevation () const; + + UserId Owner; + FilesystemPath Path; + }; +} + +#endif // TC_HEADER_Core_Unix_CoreServiceRequest diff --git a/Core/Unix/CoreServiceResponse.cpp b/Core/Unix/CoreServiceResponse.cpp index eb3e83b..2677ff1 100644 --- a/Core/Unix/CoreServiceResponse.cpp +++ b/Core/Unix/CoreServiceResponse.cpp @@ -1,104 +1,104 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "CoreServiceResponse.h" -#include "Platform/SerializerFactory.h" - -namespace TrueCrypt -{ - // CheckFilesystemResponse - void CheckFilesystemResponse::Deserialize (shared_ptr stream) - { - } - - void CheckFilesystemResponse::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - } - - // DismountFilesystemResponse - void DismountFilesystemResponse::Deserialize (shared_ptr stream) - { - } - - void DismountFilesystemResponse::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - } - - // DismountVolumeResponse - void DismountVolumeResponse::Deserialize (shared_ptr stream) - { - DismountedVolumeInfo = Serializable::DeserializeNew (stream); - } - - void DismountVolumeResponse::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - DismountedVolumeInfo->Serialize (stream); - } - - // GetDeviceSizeResponse - void GetDeviceSizeResponse::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - sr.Deserialize ("Size", Size); - } - - void GetDeviceSizeResponse::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("Size", Size); - } - - // GetHostDevicesResponse - void GetHostDevicesResponse::Deserialize (shared_ptr stream) - { - Serializable::DeserializeList (stream, HostDevices); - } - - void GetHostDevicesResponse::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializable::SerializeList (stream, HostDevices); - } - - // MountVolumeResponse - void MountVolumeResponse::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - MountedVolumeInfo = Serializable::DeserializeNew (stream); - } - - void MountVolumeResponse::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - MountedVolumeInfo->Serialize (stream); - } - - // SetFileOwnerResponse - void SetFileOwnerResponse::Deserialize (shared_ptr stream) - { - } - - void SetFileOwnerResponse::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - } - - TC_SERIALIZER_FACTORY_ADD_CLASS (CheckFilesystemResponse); - TC_SERIALIZER_FACTORY_ADD_CLASS (DismountFilesystemResponse); - TC_SERIALIZER_FACTORY_ADD_CLASS (DismountVolumeResponse); - TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeResponse); - TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesResponse); - TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeResponse); - TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerResponse); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "CoreServiceResponse.h" +#include "Platform/SerializerFactory.h" + +namespace TrueCrypt +{ + // CheckFilesystemResponse + void CheckFilesystemResponse::Deserialize (shared_ptr stream) + { + } + + void CheckFilesystemResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + } + + // DismountFilesystemResponse + void DismountFilesystemResponse::Deserialize (shared_ptr stream) + { + } + + void DismountFilesystemResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + } + + // DismountVolumeResponse + void DismountVolumeResponse::Deserialize (shared_ptr stream) + { + DismountedVolumeInfo = Serializable::DeserializeNew (stream); + } + + void DismountVolumeResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + DismountedVolumeInfo->Serialize (stream); + } + + // GetDeviceSizeResponse + void GetDeviceSizeResponse::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + sr.Deserialize ("Size", Size); + } + + void GetDeviceSizeResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("Size", Size); + } + + // GetHostDevicesResponse + void GetHostDevicesResponse::Deserialize (shared_ptr stream) + { + Serializable::DeserializeList (stream, HostDevices); + } + + void GetHostDevicesResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializable::SerializeList (stream, HostDevices); + } + + // MountVolumeResponse + void MountVolumeResponse::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + MountedVolumeInfo = Serializable::DeserializeNew (stream); + } + + void MountVolumeResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + MountedVolumeInfo->Serialize (stream); + } + + // SetFileOwnerResponse + void SetFileOwnerResponse::Deserialize (shared_ptr stream) + { + } + + void SetFileOwnerResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + } + + TC_SERIALIZER_FACTORY_ADD_CLASS (CheckFilesystemResponse); + TC_SERIALIZER_FACTORY_ADD_CLASS (DismountFilesystemResponse); + TC_SERIALIZER_FACTORY_ADD_CLASS (DismountVolumeResponse); + TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeResponse); + TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesResponse); + TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeResponse); + TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerResponse); +} diff --git a/Core/Unix/CoreServiceResponse.h b/Core/Unix/CoreServiceResponse.h index 485823e..a34fbbf 100644 --- a/Core/Unix/CoreServiceResponse.h +++ b/Core/Unix/CoreServiceResponse.h @@ -1,75 +1,75 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_Unix_CoreServiceResponse -#define TC_HEADER_Core_Unix_CoreServiceResponse - -#include "Platform/Serializable.h" -#include "Core/Core.h" - -namespace TrueCrypt -{ - struct CoreServiceResponse : public Serializable - { - }; - - struct CheckFilesystemResponse : CoreServiceResponse - { - CheckFilesystemResponse () { } - TC_SERIALIZABLE (CheckFilesystemResponse); - }; - - struct DismountFilesystemResponse : CoreServiceResponse - { - DismountFilesystemResponse () { } - TC_SERIALIZABLE (DismountFilesystemResponse); - }; - - struct DismountVolumeResponse : CoreServiceResponse - { - DismountVolumeResponse () { } - TC_SERIALIZABLE (DismountVolumeResponse); - - shared_ptr DismountedVolumeInfo; - }; - - struct GetDeviceSizeResponse : CoreServiceResponse - { - GetDeviceSizeResponse () { } - GetDeviceSizeResponse (uint64 size) : Size (size) { } - TC_SERIALIZABLE (GetDeviceSizeResponse); - - uint64 Size; - }; - - struct GetHostDevicesResponse : CoreServiceResponse - { - GetHostDevicesResponse () { } - GetHostDevicesResponse (const HostDeviceList &hostDevices) : HostDevices (hostDevices) { } - TC_SERIALIZABLE (GetHostDevicesResponse); - - HostDeviceList HostDevices; - }; - - struct MountVolumeResponse : CoreServiceResponse - { - MountVolumeResponse () { } - MountVolumeResponse (shared_ptr volumeInfo) : MountedVolumeInfo (volumeInfo) { } - TC_SERIALIZABLE (MountVolumeResponse); - - shared_ptr MountedVolumeInfo; - }; - - struct SetFileOwnerResponse : CoreServiceResponse - { - SetFileOwnerResponse () { } - TC_SERIALIZABLE (SetFileOwnerResponse); - }; -} - -#endif // TC_HEADER_Core_Unix_CoreServiceResponse +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_Unix_CoreServiceResponse +#define TC_HEADER_Core_Unix_CoreServiceResponse + +#include "Platform/Serializable.h" +#include "Core/Core.h" + +namespace TrueCrypt +{ + struct CoreServiceResponse : public Serializable + { + }; + + struct CheckFilesystemResponse : CoreServiceResponse + { + CheckFilesystemResponse () { } + TC_SERIALIZABLE (CheckFilesystemResponse); + }; + + struct DismountFilesystemResponse : CoreServiceResponse + { + DismountFilesystemResponse () { } + TC_SERIALIZABLE (DismountFilesystemResponse); + }; + + struct DismountVolumeResponse : CoreServiceResponse + { + DismountVolumeResponse () { } + TC_SERIALIZABLE (DismountVolumeResponse); + + shared_ptr DismountedVolumeInfo; + }; + + struct GetDeviceSizeResponse : CoreServiceResponse + { + GetDeviceSizeResponse () { } + GetDeviceSizeResponse (uint64 size) : Size (size) { } + TC_SERIALIZABLE (GetDeviceSizeResponse); + + uint64 Size; + }; + + struct GetHostDevicesResponse : CoreServiceResponse + { + GetHostDevicesResponse () { } + GetHostDevicesResponse (const HostDeviceList &hostDevices) : HostDevices (hostDevices) { } + TC_SERIALIZABLE (GetHostDevicesResponse); + + HostDeviceList HostDevices; + }; + + struct MountVolumeResponse : CoreServiceResponse + { + MountVolumeResponse () { } + MountVolumeResponse (shared_ptr volumeInfo) : MountedVolumeInfo (volumeInfo) { } + TC_SERIALIZABLE (MountVolumeResponse); + + shared_ptr MountedVolumeInfo; + }; + + struct SetFileOwnerResponse : CoreServiceResponse + { + SetFileOwnerResponse () { } + TC_SERIALIZABLE (SetFileOwnerResponse); + }; +} + +#endif // TC_HEADER_Core_Unix_CoreServiceResponse diff --git a/Core/Unix/CoreUnix.cpp b/Core/Unix/CoreUnix.cpp index 4aa31f9..d0c0fce 100644 --- a/Core/Unix/CoreUnix.cpp +++ b/Core/Unix/CoreUnix.cpp @@ -1,592 +1,592 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "CoreUnix.h" -#include -#include -#include -#include -#include -#include -#include -#include "Platform/FileStream.h" -#include "Driver/Fuse/FuseService.h" -#include "Volume/VolumePasswordCache.h" - -namespace TrueCrypt -{ - CoreUnix::CoreUnix () - { - signal (SIGPIPE, SIG_IGN); - - char *loc = setlocale (LC_ALL, ""); - if (!loc || string (loc) == "C") - setlocale (LC_ALL, "en_US.UTF-8"); - } - - CoreUnix::~CoreUnix () - { - } - - void CoreUnix::CheckFilesystem (shared_ptr mountedVolume, bool repair) const - { - if (!mountedVolume->MountPoint.IsEmpty()) - DismountFilesystem (mountedVolume->MountPoint, false); - - list args; - - args.push_back ("-T"); - args.push_back ("fsck"); - - args.push_back ("-e"); - - string xargs = "fsck "; - -#ifdef TC_LINUX - if (!repair) - xargs += "-n "; - else - xargs += "-r "; -#endif - - xargs += string (mountedVolume->VirtualDevice) + "; echo '[Done]'; read W"; - args.push_back (xargs); - - try - { - Process::Execute ("xterm", args, 1000); - } catch (TimeOut&) { } - } - - void CoreUnix::DismountFilesystem (const DirectoryPath &mountPoint, bool force) const - { - list args; - -#ifdef TC_MACOSX - if (force) - args.push_back ("-f"); -#endif - args.push_back ("--"); - args.push_back (mountPoint); - - Process::Execute ("umount", args); - } - - shared_ptr CoreUnix::DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) - { - if (!mountedVolume->MountPoint.IsEmpty()) - { - DismountFilesystem (mountedVolume->MountPoint, ignoreOpenFiles); - - // Delete mount directory if a default path has been used - if (string (mountedVolume->MountPoint).find (GetDefaultMountPointPrefix()) == 0) - mountedVolume->MountPoint.Delete(); - } - - try - { - DismountNativeVolume (mountedVolume); - } - catch (NotApplicable &) { } - - if (!mountedVolume->LoopDevice.IsEmpty()) - { - try - { - DetachLoopDevice (mountedVolume->LoopDevice); - } - catch (ExecutedProcessFailed&) { } - } - - if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly) - { - sync(); - VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path); - - if (ml.size() > 0) - mountedVolume = ml.front(); - } - - list args; - args.push_back ("--"); - args.push_back (mountedVolume->AuxMountPoint); - - for (int t = 0; true; t++) - { - try - { - Process::Execute ("umount", args); - break; - } - catch (ExecutedProcessFailed&) - { - if (t > 10) - throw; - Thread::Sleep (200); - } - } - - try - { - mountedVolume->AuxMountPoint.Delete(); - } - catch (...) { } - - VolumeEventArgs eventArgs (mountedVolume); - VolumeDismountedEvent.Raise (eventArgs); - - return mountedVolume; - } - - bool CoreUnix::FilesystemSupportsLargeFiles (const FilePath &filePath) const - { - string path = filePath; - size_t pos; - - while ((pos = path.find_last_of ('/')) != string::npos) - { - path = path.substr (0, pos); - - if (path.empty()) - break; - - try - { - MountedFilesystemList filesystems = GetMountedFilesystems (DevicePath(), path); - if (!filesystems.empty()) - { - const MountedFilesystem &fs = *filesystems.front(); - - if (fs.Type == "fat" - || fs.Type == "fat32" - || fs.Type == "vfat" - || fs.Type == "fatfs" - || fs.Type == "msdos" - || fs.Type == "msdosfs" - || fs.Type == "umsdos" - || fs.Type == "dos" - || fs.Type == "dosfs" - || fs.Type == "pcfs" - ) - { - return false; - } - - return true; - } - } - catch (...) { } - } - - return true; // Prevent errors if the filesystem cannot be identified - } - - bool CoreUnix::FilesystemSupportsUnixPermissions (const DevicePath &devicePath) const - { - File device; - device.Open (devicePath); - - Buffer bootSector (device.GetDeviceSectorSize()); - device.SeekAt (0); - device.ReadCompleteBuffer (bootSector); - - byte *b = bootSector.Ptr(); - - return memcmp (b + 3, "NTFS", 4) != 0 - && memcmp (b + 54, "FAT", 3) != 0 - && memcmp (b + 82, "FAT32", 5) != 0 - && memcmp (b + 3, "EXFAT", 5) != 0; - } - - string CoreUnix::GetDefaultMountPointPrefix () const - { - const char *envPrefix = getenv ("TRUECRYPT_MOUNT_PREFIX"); - if (envPrefix && !string (envPrefix).empty()) - return envPrefix; - - if (FilesystemPath ("/media").IsDirectory()) - return "/media/truecrypt"; - - if (FilesystemPath ("/mnt").IsDirectory()) - return "/mnt/truecrypt"; - - return GetTempDirectory() + "/truecrypt_mnt"; - } - - uint64 CoreUnix::GetDeviceSize (const DevicePath &devicePath) const - { - File dev; - dev.Open (devicePath); - return dev.Length(); - } - - DirectoryPath CoreUnix::GetDeviceMountPoint (const DevicePath &devicePath) const - { - DevicePath devPath = devicePath; -#ifdef TC_MACOSX - if (string (devPath).find ("/dev/rdisk") != string::npos) - devPath = string ("/dev/") + string (devicePath).substr (6); -#endif - MountedFilesystemList mountedFilesystems = GetMountedFilesystems (devPath); - - if (mountedFilesystems.size() < 1) - return DirectoryPath(); - - return mountedFilesystems.front()->MountPoint; - } - - VolumeInfoList CoreUnix::GetMountedVolumes (const VolumePath &volumePath) const - { - VolumeInfoList volumes; - - foreach_ref (const MountedFilesystem &mf, GetMountedFilesystems ()) - { - if (string (mf.MountPoint).find (GetFuseMountDirPrefix()) == string::npos) - continue; - - shared_ptr mountedVol; - try - { - shared_ptr controlFile (new File); - controlFile->Open (string (mf.MountPoint) + FuseService::GetControlPath()); - - shared_ptr controlFileStream (new FileStream (controlFile)); - mountedVol = Serializable::DeserializeNew (controlFileStream); - } - catch (...) - { - continue; - } - - if (!volumePath.IsEmpty() && wstring (mountedVol->Path).compare (volumePath) != 0) - continue; - - mountedVol->AuxMountPoint = mf.MountPoint; - - if (!mountedVol->VirtualDevice.IsEmpty()) - { - MountedFilesystemList mpl = GetMountedFilesystems (mountedVol->VirtualDevice); - - if (mpl.size() > 0) - mountedVol->MountPoint = mpl.front()->MountPoint; - } - - volumes.push_back (mountedVol); - - if (!volumePath.IsEmpty()) - break; - } - - return volumes; - } - - gid_t CoreUnix::GetRealGroupId () const - { - const char *env = getenv ("SUDO_GID"); - if (env) - { - try - { - string s (env); - return static_cast (StringConverter::ToUInt64 (s)); - } - catch (...) { } - } - - return getgid(); - } - - uid_t CoreUnix::GetRealUserId () const - { - const char *env = getenv ("SUDO_UID"); - if (env) - { - try - { - string s (env); - return static_cast (StringConverter::ToUInt64 (s)); - } - catch (...) { } - } - - return getuid(); - } - - string CoreUnix::GetTempDirectory () const - { - char *envDir = getenv ("TMPDIR"); - return envDir ? envDir : "/tmp"; - } - - bool CoreUnix::IsMountPointAvailable (const DirectoryPath &mountPoint) const - { - return GetMountedFilesystems (DevicePath(), mountPoint).size() == 0; - } - - void CoreUnix::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const - { - if (GetMountedFilesystems (DevicePath(), mountPoint).size() > 0) - throw MountPointUnavailable (SRC_POS); - - list args; - string options; - - if (!filesystemType.empty()) - { -#ifdef TC_SOLARIS - args.push_back ("-F"); -#else - args.push_back ("-t"); -#endif - args.push_back (filesystemType); - } - - if (readOnly) - options = "-oro"; - - if (!systemMountOptions.empty()) - { - if (options.empty()) - options = "-o"; - else - options += ","; - - options += systemMountOptions; - } - - if (!options.empty()) - args.push_back (options); - - args.push_back ("--"); - args.push_back (devicePath); - args.push_back (mountPoint); - - Process::Execute ("mount", args); - } - - VolumeSlotNumber CoreUnix::MountPointToSlotNumber (const DirectoryPath &mountPoint) const - { - string mountPointStr (mountPoint); - if (mountPointStr.find (GetDefaultMountPointPrefix()) == 0) - { - try - { - return StringConverter::ToUInt32 (StringConverter::GetTrailingNumber (mountPointStr)); - } - catch (...) { } - } - return GetFirstFreeSlotNumber(); - } - - shared_ptr CoreUnix::MountVolume (MountOptions &options) - { - CoalesceSlotNumberAndMountPoint (options); - - if (IsVolumeMounted (*options.Path)) - throw VolumeAlreadyMounted (SRC_POS); - - shared_ptr volume; - - while (true) - { - try - { - volume = OpenVolume ( - options.Path, - options.PreserveTimestamps, - options.Password, - options.Keyfiles, - options.Protection, - options.ProtectionPassword, - options.ProtectionKeyfiles, - options.SharedAccessAllowed, - VolumeType::Unknown, - options.UseBackupHeaders, - options.PartitionInSystemEncryptionScope - ); - - options.Password.reset(); - } - catch (SystemException &e) - { - if (options.Protection != VolumeProtection::ReadOnly - && (e.GetErrorCode() == EROFS || e.GetErrorCode() == EACCES || e.GetErrorCode() == EPERM)) - { - // Read-only filesystem - options.Protection = VolumeProtection::ReadOnly; - continue; - } - - throw; - } - - break; - } - - // Find a free mount point for FUSE service - MountedFilesystemList mountedFilesystems = GetMountedFilesystems (); - string fuseMountPoint; - for (int i = 1; true; i++) - { - stringstream path; - path << GetTempDirectory() << "/" << GetFuseMountDirPrefix() << i; - FilesystemPath fsPath (path.str()); - - bool inUse = false; - - foreach_ref (const MountedFilesystem &mf, mountedFilesystems) - { - if (mf.MountPoint == path.str()) - { - inUse = true; - break; - } - } - - if (!inUse) - { - try - { - if (fsPath.IsDirectory()) - fsPath.Delete(); - - throw_sys_sub_if (mkdir (path.str().c_str(), S_IRUSR | S_IXUSR) == -1, path.str()); - - fuseMountPoint = fsPath; - break; - } - catch (...) - { - if (i > 255) - throw; - } - } - } - - try - { - FuseService::Mount (volume, options.SlotNumber, fuseMountPoint); - } - catch (...) - { - try - { - DirectoryPath (fuseMountPoint).Delete(); - } - catch (...) { } - throw; - } - - try - { - // Create a mount directory if a default path has been specified - bool mountDirCreated = false; - string mountPoint; - if (!options.NoFilesystem && options.MountPoint) - { - mountPoint = *options.MountPoint; - -#ifndef TC_MACOSX - if (mountPoint.find (GetDefaultMountPointPrefix()) == 0 && !options.MountPoint->IsDirectory()) - { - Directory::Create (*options.MountPoint); - try - { - throw_sys_sub_if (chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()) == -1, mountPoint); - } catch (ParameterIncorrect&) { } - - mountDirCreated = true; - } -#endif - } - - try - { - try - { - MountVolumeNative (volume, options, fuseMountPoint); - } - catch (NotApplicable&) - { - MountAuxVolumeImage (fuseMountPoint, options); - } - } - catch (...) - { - if (mountDirCreated) - remove (mountPoint.c_str()); - throw; - } - } - catch (...) - { - try - { - VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); - if (mountedVolumes.size() > 0) - { - shared_ptr mountedVolume (mountedVolumes.front()); - DismountVolume (mountedVolume); - } - } - catch (...) { } - throw; - } - - VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); - if (mountedVolumes.size() != 1) - throw ParameterIncorrect (SRC_POS); - - VolumeEventArgs eventArgs (mountedVolumes.front()); - VolumeMountedEvent.Raise (eventArgs); - - return mountedVolumes.front(); - } - - void CoreUnix::MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const - { - DevicePath loopDev = AttachFileToLoopDevice (string (auxMountPoint) + FuseService::GetVolumeImagePath(), options.Protection == VolumeProtection::ReadOnly); - - try - { - FuseService::SendAuxDeviceInfo (auxMountPoint, loopDev, loopDev); - } - catch (...) - { - try - { - DetachLoopDevice (loopDev); - } - catch (...) { } - throw; - } - - if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty()) - { - MountFilesystem (loopDev, *options.MountPoint, - StringConverter::ToSingle (options.FilesystemType), - options.Protection == VolumeProtection::ReadOnly, - StringConverter::ToSingle (options.FilesystemOptions)); - } - } - - void CoreUnix::SetFileOwner (const FilesystemPath &path, const UserId &owner) const - { - throw_sys_if (chown (string (path).c_str(), owner.SystemId, (gid_t) -1) == -1); - } - - DirectoryPath CoreUnix::SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const - { - if (slotNumber < GetFirstSlotNumber() || slotNumber > GetLastSlotNumber()) - throw ParameterIncorrect (SRC_POS); - - stringstream s; - s << GetDefaultMountPointPrefix() << slotNumber; - return s.str(); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "CoreUnix.h" +#include +#include +#include +#include +#include +#include +#include +#include "Platform/FileStream.h" +#include "Driver/Fuse/FuseService.h" +#include "Volume/VolumePasswordCache.h" + +namespace TrueCrypt +{ + CoreUnix::CoreUnix () + { + signal (SIGPIPE, SIG_IGN); + + char *loc = setlocale (LC_ALL, ""); + if (!loc || string (loc) == "C") + setlocale (LC_ALL, "en_US.UTF-8"); + } + + CoreUnix::~CoreUnix () + { + } + + void CoreUnix::CheckFilesystem (shared_ptr mountedVolume, bool repair) const + { + if (!mountedVolume->MountPoint.IsEmpty()) + DismountFilesystem (mountedVolume->MountPoint, false); + + list args; + + args.push_back ("-T"); + args.push_back ("fsck"); + + args.push_back ("-e"); + + string xargs = "fsck "; + +#ifdef TC_LINUX + if (!repair) + xargs += "-n "; + else + xargs += "-r "; +#endif + + xargs += string (mountedVolume->VirtualDevice) + "; echo '[Done]'; read W"; + args.push_back (xargs); + + try + { + Process::Execute ("xterm", args, 1000); + } catch (TimeOut&) { } + } + + void CoreUnix::DismountFilesystem (const DirectoryPath &mountPoint, bool force) const + { + list args; + +#ifdef TC_MACOSX + if (force) + args.push_back ("-f"); +#endif + args.push_back ("--"); + args.push_back (mountPoint); + + Process::Execute ("umount", args); + } + + shared_ptr CoreUnix::DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) + { + if (!mountedVolume->MountPoint.IsEmpty()) + { + DismountFilesystem (mountedVolume->MountPoint, ignoreOpenFiles); + + // Delete mount directory if a default path has been used + if (string (mountedVolume->MountPoint).find (GetDefaultMountPointPrefix()) == 0) + mountedVolume->MountPoint.Delete(); + } + + try + { + DismountNativeVolume (mountedVolume); + } + catch (NotApplicable &) { } + + if (!mountedVolume->LoopDevice.IsEmpty()) + { + try + { + DetachLoopDevice (mountedVolume->LoopDevice); + } + catch (ExecutedProcessFailed&) { } + } + + if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly) + { + sync(); + VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path); + + if (ml.size() > 0) + mountedVolume = ml.front(); + } + + list args; + args.push_back ("--"); + args.push_back (mountedVolume->AuxMountPoint); + + for (int t = 0; true; t++) + { + try + { + Process::Execute ("umount", args); + break; + } + catch (ExecutedProcessFailed&) + { + if (t > 10) + throw; + Thread::Sleep (200); + } + } + + try + { + mountedVolume->AuxMountPoint.Delete(); + } + catch (...) { } + + VolumeEventArgs eventArgs (mountedVolume); + VolumeDismountedEvent.Raise (eventArgs); + + return mountedVolume; + } + + bool CoreUnix::FilesystemSupportsLargeFiles (const FilePath &filePath) const + { + string path = filePath; + size_t pos; + + while ((pos = path.find_last_of ('/')) != string::npos) + { + path = path.substr (0, pos); + + if (path.empty()) + break; + + try + { + MountedFilesystemList filesystems = GetMountedFilesystems (DevicePath(), path); + if (!filesystems.empty()) + { + const MountedFilesystem &fs = *filesystems.front(); + + if (fs.Type == "fat" + || fs.Type == "fat32" + || fs.Type == "vfat" + || fs.Type == "fatfs" + || fs.Type == "msdos" + || fs.Type == "msdosfs" + || fs.Type == "umsdos" + || fs.Type == "dos" + || fs.Type == "dosfs" + || fs.Type == "pcfs" + ) + { + return false; + } + + return true; + } + } + catch (...) { } + } + + return true; // Prevent errors if the filesystem cannot be identified + } + + bool CoreUnix::FilesystemSupportsUnixPermissions (const DevicePath &devicePath) const + { + File device; + device.Open (devicePath); + + Buffer bootSector (device.GetDeviceSectorSize()); + device.SeekAt (0); + device.ReadCompleteBuffer (bootSector); + + byte *b = bootSector.Ptr(); + + return memcmp (b + 3, "NTFS", 4) != 0 + && memcmp (b + 54, "FAT", 3) != 0 + && memcmp (b + 82, "FAT32", 5) != 0 + && memcmp (b + 3, "EXFAT", 5) != 0; + } + + string CoreUnix::GetDefaultMountPointPrefix () const + { + const char *envPrefix = getenv ("TRUECRYPT_MOUNT_PREFIX"); + if (envPrefix && !string (envPrefix).empty()) + return envPrefix; + + if (FilesystemPath ("/media").IsDirectory()) + return "/media/truecrypt"; + + if (FilesystemPath ("/mnt").IsDirectory()) + return "/mnt/truecrypt"; + + return GetTempDirectory() + "/truecrypt_mnt"; + } + + uint64 CoreUnix::GetDeviceSize (const DevicePath &devicePath) const + { + File dev; + dev.Open (devicePath); + return dev.Length(); + } + + DirectoryPath CoreUnix::GetDeviceMountPoint (const DevicePath &devicePath) const + { + DevicePath devPath = devicePath; +#ifdef TC_MACOSX + if (string (devPath).find ("/dev/rdisk") != string::npos) + devPath = string ("/dev/") + string (devicePath).substr (6); +#endif + MountedFilesystemList mountedFilesystems = GetMountedFilesystems (devPath); + + if (mountedFilesystems.size() < 1) + return DirectoryPath(); + + return mountedFilesystems.front()->MountPoint; + } + + VolumeInfoList CoreUnix::GetMountedVolumes (const VolumePath &volumePath) const + { + VolumeInfoList volumes; + + foreach_ref (const MountedFilesystem &mf, GetMountedFilesystems ()) + { + if (string (mf.MountPoint).find (GetFuseMountDirPrefix()) == string::npos) + continue; + + shared_ptr mountedVol; + try + { + shared_ptr controlFile (new File); + controlFile->Open (string (mf.MountPoint) + FuseService::GetControlPath()); + + shared_ptr controlFileStream (new FileStream (controlFile)); + mountedVol = Serializable::DeserializeNew (controlFileStream); + } + catch (...) + { + continue; + } + + if (!volumePath.IsEmpty() && wstring (mountedVol->Path).compare (volumePath) != 0) + continue; + + mountedVol->AuxMountPoint = mf.MountPoint; + + if (!mountedVol->VirtualDevice.IsEmpty()) + { + MountedFilesystemList mpl = GetMountedFilesystems (mountedVol->VirtualDevice); + + if (mpl.size() > 0) + mountedVol->MountPoint = mpl.front()->MountPoint; + } + + volumes.push_back (mountedVol); + + if (!volumePath.IsEmpty()) + break; + } + + return volumes; + } + + gid_t CoreUnix::GetRealGroupId () const + { + const char *env = getenv ("SUDO_GID"); + if (env) + { + try + { + string s (env); + return static_cast (StringConverter::ToUInt64 (s)); + } + catch (...) { } + } + + return getgid(); + } + + uid_t CoreUnix::GetRealUserId () const + { + const char *env = getenv ("SUDO_UID"); + if (env) + { + try + { + string s (env); + return static_cast (StringConverter::ToUInt64 (s)); + } + catch (...) { } + } + + return getuid(); + } + + string CoreUnix::GetTempDirectory () const + { + char *envDir = getenv ("TMPDIR"); + return envDir ? envDir : "/tmp"; + } + + bool CoreUnix::IsMountPointAvailable (const DirectoryPath &mountPoint) const + { + return GetMountedFilesystems (DevicePath(), mountPoint).size() == 0; + } + + void CoreUnix::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const + { + if (GetMountedFilesystems (DevicePath(), mountPoint).size() > 0) + throw MountPointUnavailable (SRC_POS); + + list args; + string options; + + if (!filesystemType.empty()) + { +#ifdef TC_SOLARIS + args.push_back ("-F"); +#else + args.push_back ("-t"); +#endif + args.push_back (filesystemType); + } + + if (readOnly) + options = "-oro"; + + if (!systemMountOptions.empty()) + { + if (options.empty()) + options = "-o"; + else + options += ","; + + options += systemMountOptions; + } + + if (!options.empty()) + args.push_back (options); + + args.push_back ("--"); + args.push_back (devicePath); + args.push_back (mountPoint); + + Process::Execute ("mount", args); + } + + VolumeSlotNumber CoreUnix::MountPointToSlotNumber (const DirectoryPath &mountPoint) const + { + string mountPointStr (mountPoint); + if (mountPointStr.find (GetDefaultMountPointPrefix()) == 0) + { + try + { + return StringConverter::ToUInt32 (StringConverter::GetTrailingNumber (mountPointStr)); + } + catch (...) { } + } + return GetFirstFreeSlotNumber(); + } + + shared_ptr CoreUnix::MountVolume (MountOptions &options) + { + CoalesceSlotNumberAndMountPoint (options); + + if (IsVolumeMounted (*options.Path)) + throw VolumeAlreadyMounted (SRC_POS); + + shared_ptr volume; + + while (true) + { + try + { + volume = OpenVolume ( + options.Path, + options.PreserveTimestamps, + options.Password, + options.Keyfiles, + options.Protection, + options.ProtectionPassword, + options.ProtectionKeyfiles, + options.SharedAccessAllowed, + VolumeType::Unknown, + options.UseBackupHeaders, + options.PartitionInSystemEncryptionScope + ); + + options.Password.reset(); + } + catch (SystemException &e) + { + if (options.Protection != VolumeProtection::ReadOnly + && (e.GetErrorCode() == EROFS || e.GetErrorCode() == EACCES || e.GetErrorCode() == EPERM)) + { + // Read-only filesystem + options.Protection = VolumeProtection::ReadOnly; + continue; + } + + throw; + } + + break; + } + + // Find a free mount point for FUSE service + MountedFilesystemList mountedFilesystems = GetMountedFilesystems (); + string fuseMountPoint; + for (int i = 1; true; i++) + { + stringstream path; + path << GetTempDirectory() << "/" << GetFuseMountDirPrefix() << i; + FilesystemPath fsPath (path.str()); + + bool inUse = false; + + foreach_ref (const MountedFilesystem &mf, mountedFilesystems) + { + if (mf.MountPoint == path.str()) + { + inUse = true; + break; + } + } + + if (!inUse) + { + try + { + if (fsPath.IsDirectory()) + fsPath.Delete(); + + throw_sys_sub_if (mkdir (path.str().c_str(), S_IRUSR | S_IXUSR) == -1, path.str()); + + fuseMountPoint = fsPath; + break; + } + catch (...) + { + if (i > 255) + throw TemporaryDirectoryFailure (SRC_POS, StringConverter::ToWide (path.str())); + } + } + } + + try + { + FuseService::Mount (volume, options.SlotNumber, fuseMountPoint); + } + catch (...) + { + try + { + DirectoryPath (fuseMountPoint).Delete(); + } + catch (...) { } + throw; + } + + try + { + // Create a mount directory if a default path has been specified + bool mountDirCreated = false; + string mountPoint; + if (!options.NoFilesystem && options.MountPoint) + { + mountPoint = *options.MountPoint; + +#ifndef TC_MACOSX + if (mountPoint.find (GetDefaultMountPointPrefix()) == 0 && !options.MountPoint->IsDirectory()) + { + Directory::Create (*options.MountPoint); + try + { + throw_sys_sub_if (chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()) == -1, mountPoint); + } catch (ParameterIncorrect&) { } + + mountDirCreated = true; + } +#endif + } + + try + { + try + { + MountVolumeNative (volume, options, fuseMountPoint); + } + catch (NotApplicable&) + { + MountAuxVolumeImage (fuseMountPoint, options); + } + } + catch (...) + { + if (mountDirCreated) + remove (mountPoint.c_str()); + throw; + } + } + catch (...) + { + try + { + VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); + if (mountedVolumes.size() > 0) + { + shared_ptr mountedVolume (mountedVolumes.front()); + DismountVolume (mountedVolume); + } + } + catch (...) { } + throw; + } + + VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); + if (mountedVolumes.size() != 1) + throw ParameterIncorrect (SRC_POS); + + VolumeEventArgs eventArgs (mountedVolumes.front()); + VolumeMountedEvent.Raise (eventArgs); + + return mountedVolumes.front(); + } + + void CoreUnix::MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const + { + DevicePath loopDev = AttachFileToLoopDevice (string (auxMountPoint) + FuseService::GetVolumeImagePath(), options.Protection == VolumeProtection::ReadOnly); + + try + { + FuseService::SendAuxDeviceInfo (auxMountPoint, loopDev, loopDev); + } + catch (...) + { + try + { + DetachLoopDevice (loopDev); + } + catch (...) { } + throw; + } + + if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty()) + { + MountFilesystem (loopDev, *options.MountPoint, + StringConverter::ToSingle (options.FilesystemType), + options.Protection == VolumeProtection::ReadOnly, + StringConverter::ToSingle (options.FilesystemOptions)); + } + } + + void CoreUnix::SetFileOwner (const FilesystemPath &path, const UserId &owner) const + { + throw_sys_if (chown (string (path).c_str(), owner.SystemId, (gid_t) -1) == -1); + } + + DirectoryPath CoreUnix::SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const + { + if (slotNumber < GetFirstSlotNumber() || slotNumber > GetLastSlotNumber()) + throw ParameterIncorrect (SRC_POS); + + stringstream s; + s << GetDefaultMountPointPrefix() << slotNumber; + return s.str(); + } +} diff --git a/Core/Unix/CoreUnix.h b/Core/Unix/CoreUnix.h index 439e8be..09662c8 100644 --- a/Core/Unix/CoreUnix.h +++ b/Core/Unix/CoreUnix.h @@ -1,68 +1,68 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_CoreUnix -#define TC_HEADER_Core_CoreUnix - -#include "System.h" -#include "Platform/Unix/Process.h" -#include "Core/CoreBase.h" -#include "Core/Unix/MountedFilesystem.h" - -namespace TrueCrypt -{ - class CoreUnix : public CoreBase - { - public: - CoreUnix (); - virtual ~CoreUnix (); - - virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const; - virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const; - virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false); - virtual bool FilesystemSupportsLargeFiles (const FilePath &filePath) const; - virtual DirectoryPath GetDeviceMountPoint (const DevicePath &devicePath) const; - virtual uint64 GetDeviceSize (const DevicePath &devicePath) const; - virtual int GetOSMajorVersion () const { throw NotApplicable (SRC_POS); } - virtual int GetOSMinorVersion () const { throw NotApplicable (SRC_POS); } - virtual VolumeInfoList GetMountedVolumes (const VolumePath &volumePath = VolumePath()) const; - virtual bool IsDevicePresent (const DevicePath &device) const { throw NotApplicable (SRC_POS); } - virtual bool IsInTravelMode () const { return false; } - virtual bool IsMountPointAvailable (const DirectoryPath &mountPoint) const; - virtual bool IsOSVersion (int major, int minor) const { throw NotApplicable (SRC_POS); } - virtual bool IsOSVersionLower (int major, int minor) const { throw NotApplicable (SRC_POS); } - virtual bool IsPasswordCacheEmpty () const { throw NotApplicable (SRC_POS); } - virtual bool HasAdminPrivileges () const { return getuid() == 0 || geteuid() == 0; } - virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const; - virtual shared_ptr MountVolume (MountOptions &options); - virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const; - virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const; - virtual void WipePasswordCache () const { throw NotApplicable (SRC_POS); } - - protected: - virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const { throw NotApplicable (SRC_POS); } - virtual void DetachLoopDevice (const DevicePath &devicePath) const { throw NotApplicable (SRC_POS); } - virtual void DismountNativeVolume (shared_ptr mountedVolume) const { throw NotApplicable (SRC_POS); } - virtual bool FilesystemSupportsUnixPermissions (const DevicePath &devicePath) const; - virtual string GetDefaultMountPointPrefix () const; - virtual string GetFuseMountDirPrefix () const { return ".truecrypt_aux_mnt"; } - virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const = 0; - virtual uid_t GetRealUserId () const; - virtual gid_t GetRealGroupId () const; - virtual string GetTempDirectory () const; - virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; - virtual void MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const; - virtual void MountVolumeNative (shared_ptr volume, MountOptions &options, const DirectoryPath &auxMountPoint) const { throw NotApplicable (SRC_POS); } - - private: - CoreUnix (const CoreUnix &); - CoreUnix &operator= (const CoreUnix &); - }; -} - -#endif // TC_HEADER_Core_CoreUnix +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_CoreUnix +#define TC_HEADER_Core_CoreUnix + +#include "System.h" +#include "Platform/Unix/Process.h" +#include "Core/CoreBase.h" +#include "Core/Unix/MountedFilesystem.h" + +namespace TrueCrypt +{ + class CoreUnix : public CoreBase + { + public: + CoreUnix (); + virtual ~CoreUnix (); + + virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const; + virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const; + virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false); + virtual bool FilesystemSupportsLargeFiles (const FilePath &filePath) const; + virtual DirectoryPath GetDeviceMountPoint (const DevicePath &devicePath) const; + virtual uint64 GetDeviceSize (const DevicePath &devicePath) const; + virtual int GetOSMajorVersion () const { throw NotApplicable (SRC_POS); } + virtual int GetOSMinorVersion () const { throw NotApplicable (SRC_POS); } + virtual VolumeInfoList GetMountedVolumes (const VolumePath &volumePath = VolumePath()) const; + virtual bool IsDevicePresent (const DevicePath &device) const { throw NotApplicable (SRC_POS); } + virtual bool IsInPortableMode () const { return false; } + virtual bool IsMountPointAvailable (const DirectoryPath &mountPoint) const; + virtual bool IsOSVersion (int major, int minor) const { throw NotApplicable (SRC_POS); } + virtual bool IsOSVersionLower (int major, int minor) const { throw NotApplicable (SRC_POS); } + virtual bool IsPasswordCacheEmpty () const { throw NotApplicable (SRC_POS); } + virtual bool HasAdminPrivileges () const { return getuid() == 0 || geteuid() == 0; } + virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const; + virtual shared_ptr MountVolume (MountOptions &options); + virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const; + virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const; + virtual void WipePasswordCache () const { throw NotApplicable (SRC_POS); } + + protected: + virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const { throw NotApplicable (SRC_POS); } + virtual void DetachLoopDevice (const DevicePath &devicePath) const { throw NotApplicable (SRC_POS); } + virtual void DismountNativeVolume (shared_ptr mountedVolume) const { throw NotApplicable (SRC_POS); } + virtual bool FilesystemSupportsUnixPermissions (const DevicePath &devicePath) const; + virtual string GetDefaultMountPointPrefix () const; + virtual string GetFuseMountDirPrefix () const { return ".truecrypt_aux_mnt"; } + virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const = 0; + virtual uid_t GetRealUserId () const; + virtual gid_t GetRealGroupId () const; + virtual string GetTempDirectory () const; + virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; + virtual void MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const; + virtual void MountVolumeNative (shared_ptr volume, MountOptions &options, const DirectoryPath &auxMountPoint) const { throw NotApplicable (SRC_POS); } + + private: + CoreUnix (const CoreUnix &); + CoreUnix &operator= (const CoreUnix &); + }; +} + +#endif // TC_HEADER_Core_CoreUnix diff --git a/Core/Unix/FreeBSD/CoreFreeBSD.cpp b/Core/Unix/FreeBSD/CoreFreeBSD.cpp index 2ce73bc..9b7d8ad 100644 --- a/Core/Unix/FreeBSD/CoreFreeBSD.cpp +++ b/Core/Unix/FreeBSD/CoreFreeBSD.cpp @@ -1,202 +1,202 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "CoreFreeBSD.h" -#include "Core/Unix/CoreServiceProxy.h" - -namespace TrueCrypt -{ - CoreFreeBSD::CoreFreeBSD () - { - } - - CoreFreeBSD::~CoreFreeBSD () - { - } - - DevicePath CoreFreeBSD::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const - { - list args; - args.push_back ("-a"); - args.push_back ("-t"); - args.push_back ("vnode"); - - if (readOnly) - { - args.push_back ("-o"); - args.push_back ("readonly"); - } - - args.push_back ("-f"); - args.push_back (filePath); - - string dev = StringConverter::Trim (Process::Execute ("mdconfig", args)); - - if (dev.find ("/") == string::npos) - dev = string ("/dev/") + dev; - - return dev; - } - - void CoreFreeBSD::DetachLoopDevice (const DevicePath &devicePath) const - { - list args; - args.push_back ("-d"); - args.push_back ("-u"); - args.push_back (StringConverter::GetTrailingNumber (devicePath)); - - for (int t = 0; true; t++) - { - try - { - Process::Execute ("mdconfig", args); - break; - } - catch (ExecutedProcessFailed&) - { - if (t > 5) - throw; - Thread::Sleep (200); - } - } - } - - HostDeviceList CoreFreeBSD::GetHostDevices (bool pathListOnly) const - { - HostDeviceList devices; -#ifdef TC_MACOSX - const string busType = "rdisk"; -#else - foreach (const string &busType, StringConverter::Split ("ad da")) -#endif - { - for (int devNumber = 0; devNumber < 64; devNumber++) - { - stringstream devPath; - devPath << "/dev/" << busType << devNumber; - - if (FilesystemPath (devPath.str()).IsBlockDevice() || FilesystemPath (devPath.str()).IsCharacterDevice()) - { - make_shared_auto (HostDevice, device); - device->Path = devPath.str(); - if (!pathListOnly) - { - try - { - device->Size = GetDeviceSize (device->Path); - } - catch (...) - { - device->Size = 0; - } - device->MountPoint = GetDeviceMountPoint (device->Path); - device->SystemNumber = 0; - } - devices.push_back (device); - - for (int partNumber = 1; partNumber < 32; partNumber++) - { -#ifdef TC_MACOSX - const string partLetter = ""; -#else - foreach (const string &partLetter, StringConverter::Split (",a,b,c,d,e,f,g,h", ",", true)) -#endif - { - stringstream partPath; - partPath << devPath.str() << "s" << partNumber << partLetter; - - if (FilesystemPath (partPath.str()).IsBlockDevice() || FilesystemPath (partPath.str()).IsCharacterDevice()) - { - make_shared_auto (HostDevice, partition); - partition->Path = partPath.str(); - if (!pathListOnly) - { - try - { - partition->Size = GetDeviceSize (partition->Path); - } - catch (...) - { - partition->Size = 0; - } - partition->MountPoint = GetDeviceMountPoint (partition->Path); - partition->SystemNumber = 0; - } - - device->Partitions.push_back (partition); - } - } - } - } - } - } - - return devices; - } - - MountedFilesystemList CoreFreeBSD::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const - { - - static Mutex mutex; - ScopeLock sl (mutex); - - struct statfs *sysMountList; - int count = getmntinfo (&sysMountList, MNT_NOWAIT); - throw_sys_if (count == 0); - - MountedFilesystemList mountedFilesystems; - - for (int i = 0; i < count; i++) - { - make_shared_auto (MountedFilesystem, mf); - - if (sysMountList[i].f_mntfromname[0]) - mf->Device = DevicePath (sysMountList[i].f_mntfromname); - else - continue; - - if (sysMountList[i].f_mntonname[0]) - mf->MountPoint = DirectoryPath (sysMountList[i].f_mntonname); - - mf->Type = sysMountList[i].f_fstypename; - - if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint)) - mountedFilesystems.push_back (mf); - } - - return mountedFilesystems; - } - - void CoreFreeBSD::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const - { - try - { - // Try to mount FAT by default as mount is unable to probe filesystem type on BSD - CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType.empty() ? "msdos" : filesystemType, readOnly, systemMountOptions); - } - catch (ExecutedProcessFailed&) - { - if (!filesystemType.empty()) - throw; - - CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions); - } - } - -#ifdef TC_FREEBSD - auto_ptr Core (new CoreServiceProxy ); - auto_ptr CoreDirect (new CoreFreeBSD); -#endif -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "CoreFreeBSD.h" +#include "Core/Unix/CoreServiceProxy.h" + +namespace TrueCrypt +{ + CoreFreeBSD::CoreFreeBSD () + { + } + + CoreFreeBSD::~CoreFreeBSD () + { + } + + DevicePath CoreFreeBSD::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const + { + list args; + args.push_back ("-a"); + args.push_back ("-t"); + args.push_back ("vnode"); + + if (readOnly) + { + args.push_back ("-o"); + args.push_back ("readonly"); + } + + args.push_back ("-f"); + args.push_back (filePath); + + string dev = StringConverter::Trim (Process::Execute ("mdconfig", args)); + + if (dev.find ("/") == string::npos) + dev = string ("/dev/") + dev; + + return dev; + } + + void CoreFreeBSD::DetachLoopDevice (const DevicePath &devicePath) const + { + list args; + args.push_back ("-d"); + args.push_back ("-u"); + args.push_back (StringConverter::GetTrailingNumber (devicePath)); + + for (int t = 0; true; t++) + { + try + { + Process::Execute ("mdconfig", args); + break; + } + catch (ExecutedProcessFailed&) + { + if (t > 5) + throw; + Thread::Sleep (200); + } + } + } + + HostDeviceList CoreFreeBSD::GetHostDevices (bool pathListOnly) const + { + HostDeviceList devices; +#ifdef TC_MACOSX + const string busType = "rdisk"; +#else + foreach (const string &busType, StringConverter::Split ("ad da")) +#endif + { + for (int devNumber = 0; devNumber < 64; devNumber++) + { + stringstream devPath; + devPath << "/dev/" << busType << devNumber; + + if (FilesystemPath (devPath.str()).IsBlockDevice() || FilesystemPath (devPath.str()).IsCharacterDevice()) + { + make_shared_auto (HostDevice, device); + device->Path = devPath.str(); + if (!pathListOnly) + { + try + { + device->Size = GetDeviceSize (device->Path); + } + catch (...) + { + device->Size = 0; + } + device->MountPoint = GetDeviceMountPoint (device->Path); + device->SystemNumber = 0; + } + devices.push_back (device); + + for (int partNumber = 1; partNumber < 32; partNumber++) + { +#ifdef TC_MACOSX + const string partLetter = ""; +#else + foreach (const string &partLetter, StringConverter::Split (",a,b,c,d,e,f,g,h", ",", true)) +#endif + { + stringstream partPath; + partPath << devPath.str() << "s" << partNumber << partLetter; + + if (FilesystemPath (partPath.str()).IsBlockDevice() || FilesystemPath (partPath.str()).IsCharacterDevice()) + { + make_shared_auto (HostDevice, partition); + partition->Path = partPath.str(); + if (!pathListOnly) + { + try + { + partition->Size = GetDeviceSize (partition->Path); + } + catch (...) + { + partition->Size = 0; + } + partition->MountPoint = GetDeviceMountPoint (partition->Path); + partition->SystemNumber = 0; + } + + device->Partitions.push_back (partition); + } + } + } + } + } + } + + return devices; + } + + MountedFilesystemList CoreFreeBSD::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const + { + + static Mutex mutex; + ScopeLock sl (mutex); + + struct statfs *sysMountList; + int count = getmntinfo (&sysMountList, MNT_NOWAIT); + throw_sys_if (count == 0); + + MountedFilesystemList mountedFilesystems; + + for (int i = 0; i < count; i++) + { + make_shared_auto (MountedFilesystem, mf); + + if (sysMountList[i].f_mntfromname[0]) + mf->Device = DevicePath (sysMountList[i].f_mntfromname); + else + continue; + + if (sysMountList[i].f_mntonname[0]) + mf->MountPoint = DirectoryPath (sysMountList[i].f_mntonname); + + mf->Type = sysMountList[i].f_fstypename; + + if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint)) + mountedFilesystems.push_back (mf); + } + + return mountedFilesystems; + } + + void CoreFreeBSD::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const + { + try + { + // Try to mount FAT by default as mount is unable to probe filesystem type on BSD + CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType.empty() ? "msdos" : filesystemType, readOnly, systemMountOptions); + } + catch (ExecutedProcessFailed&) + { + if (!filesystemType.empty()) + throw; + + CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions); + } + } + +#ifdef TC_FREEBSD + auto_ptr Core (new CoreServiceProxy ); + auto_ptr CoreDirect (new CoreFreeBSD); +#endif +} diff --git a/Core/Unix/FreeBSD/CoreFreeBSD.h b/Core/Unix/FreeBSD/CoreFreeBSD.h index 0fc68a8..9ab4e21 100644 --- a/Core/Unix/FreeBSD/CoreFreeBSD.h +++ b/Core/Unix/FreeBSD/CoreFreeBSD.h @@ -1,37 +1,37 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_CoreFreeBSD -#define TC_HEADER_Core_CoreFreeBSD - -#include "System.h" -#include "Core/Unix/CoreUnix.h" - -namespace TrueCrypt -{ - class CoreFreeBSD : public CoreUnix - { - public: - CoreFreeBSD (); - virtual ~CoreFreeBSD (); - - virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const; - - protected: - virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const; - virtual void DetachLoopDevice (const DevicePath &devicePath) const; - virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const; - virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; - - private: - CoreFreeBSD (const CoreFreeBSD &); - CoreFreeBSD &operator= (const CoreFreeBSD &); - }; -} - -#endif // TC_HEADER_Core_CoreFreeBSD +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_CoreFreeBSD +#define TC_HEADER_Core_CoreFreeBSD + +#include "System.h" +#include "Core/Unix/CoreUnix.h" + +namespace TrueCrypt +{ + class CoreFreeBSD : public CoreUnix + { + public: + CoreFreeBSD (); + virtual ~CoreFreeBSD (); + + virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const; + + protected: + virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const; + virtual void DetachLoopDevice (const DevicePath &devicePath) const; + virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const; + virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; + + private: + CoreFreeBSD (const CoreFreeBSD &); + CoreFreeBSD &operator= (const CoreFreeBSD &); + }; +} + +#endif // TC_HEADER_Core_CoreFreeBSD diff --git a/Core/Unix/FreeBSD/System.h b/Core/Unix/FreeBSD/System.h index 4cfb836..771c042 100644 --- a/Core/Unix/FreeBSD/System.h +++ b/Core/Unix/FreeBSD/System.h @@ -1,12 +1,12 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_FreeBSD_System -#define TC_HEADER_Platform_FreeBSD_System - -#endif // TC_HEADER_Platform_FreeBSD_System +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_FreeBSD_System +#define TC_HEADER_Platform_FreeBSD_System + +#endif // TC_HEADER_Platform_FreeBSD_System diff --git a/Core/Unix/Linux/CoreLinux.cpp b/Core/Unix/Linux/CoreLinux.cpp index d6a107e..70bf6c1 100644 --- a/Core/Unix/Linux/CoreLinux.cpp +++ b/Core/Unix/Linux/CoreLinux.cpp @@ -1,465 +1,466 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "CoreLinux.h" -#include "Platform/SystemInfo.h" -#include "Platform/TextReader.h" -#include "Volume/EncryptionModeLRW.h" -#include "Volume/EncryptionModeXTS.h" -#include "Driver/Fuse/FuseService.h" -#include "Core/Unix/CoreServiceProxy.h" - -namespace TrueCrypt -{ - CoreLinux::CoreLinux () - { - } - - CoreLinux::~CoreLinux () - { - } - - DevicePath CoreLinux::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const - { - list loopPaths; - loopPaths.push_back ("/dev/loop"); - loopPaths.push_back ("/dev/loop/"); - loopPaths.push_back ("/dev/.static/dev/loop"); - - for (int devIndex = 0; devIndex < 256; devIndex++) - { - string loopDev; - foreach (const string &loopPath, loopPaths) - { - loopDev = loopPath + StringConverter::ToSingle (devIndex); - if (FilesystemPath (loopDev).IsBlockDevice()) - break; - } - - if (loopDev.empty()) - continue; - - list args; - - list ::iterator readOnlyArg; - if (readOnly) - { - args.push_back ("-r"); - readOnlyArg = --args.end(); - } - - args.push_back ("--"); - args.push_back (loopDev); - args.push_back (filePath); - - try - { - Process::Execute ("losetup", args); - return loopDev; - } - catch (ExecutedProcessFailed&) - { - if (readOnly) - { - try - { - args.erase (readOnlyArg); - Process::Execute ("losetup", args); - return loopDev; - } - catch (ExecutedProcessFailed&) { } - } - } - } - - throw LoopDeviceSetupFailed (SRC_POS, wstring (filePath)); - } - - void CoreLinux::DetachLoopDevice (const DevicePath &devicePath) const - { - list args; - args.push_back ("-d"); - args.push_back (devicePath); - - for (int t = 0; true; t++) - { - try - { - Process::Execute ("losetup", args); - break; - } - catch (ExecutedProcessFailed&) - { - if (t > 5) - throw; - Thread::Sleep (200); - } - } - } - - void CoreLinux::DismountNativeVolume (shared_ptr mountedVolume) const - { - string devPath = mountedVolume->VirtualDevice; - - if (devPath.find ("/dev/mapper/truecrypt") != 0) - throw NotApplicable (SRC_POS); - - size_t devCount = 0; - while (FilesystemPath (devPath).IsBlockDevice()) - { - list dmsetupArgs; - dmsetupArgs.push_back ("remove"); - dmsetupArgs.push_back (StringConverter::Split (devPath, "/").back()); - - for (int t = 0; true; t++) - { - try - { - Process::Execute ("dmsetup", dmsetupArgs); - break; - } - catch (...) - { - if (t > 20) - throw; - - Thread::Sleep (100); - } - } - - for (int t = 0; FilesystemPath (devPath).IsBlockDevice() && t < 20; t++) - { - Thread::Sleep (100); - } - - devPath = string (mountedVolume->VirtualDevice) + "_" + StringConverter::ToSingle (devCount++); - } - } - - HostDeviceList CoreLinux::GetHostDevices (bool pathListOnly) const - { - HostDeviceList devices; - TextReader tr ("/proc/partitions"); - - string line; - while (tr.ReadLine (line)) - { - vector fields = StringConverter::Split (line); - - if (fields.size() != 4 - || fields[3].find ("loop") != string::npos // skip loop devices - || fields[3].find ("ram") != string::npos // skip RAM devices - || fields[2] == "1" // skip extended partitions - ) - continue; - - try - { - StringConverter::ToUInt32 (fields[0]); - } - catch (...) - { - continue; - } - - try - { - make_shared_auto (HostDevice, hostDevice); - - hostDevice->Path = string (fields[3].find ("/dev/") == string::npos ? "/dev/" : "") + fields[3]; - - if (!pathListOnly) - { - hostDevice->Size = StringConverter::ToUInt64 (fields[2]) * 1024; - hostDevice->MountPoint = GetDeviceMountPoint (hostDevice->Path); - hostDevice->SystemNumber = 0; - } - - try - { - StringConverter::GetTrailingNumber (fields[3]); - if (devices.size() > 0) - { - HostDevice &prevDev = **--devices.end(); - if (string (hostDevice->Path).find (prevDev.Path) == 0) - { - prevDev.Partitions.push_back (hostDevice); - continue; - } - } - } - catch (...) { } - - devices.push_back (hostDevice); - continue; - } - catch (...) - { - continue; - } - } - - return devices; - } - - MountedFilesystemList CoreLinux::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const - { - MountedFilesystemList mountedFilesystems; - - FILE *mtab = fopen ("/etc/mtab", "r"); - - if (!mtab) - mtab = fopen ("/proc/mounts", "r"); - - throw_sys_sub_if (!mtab, "/proc/mounts"); - finally_do_arg (FILE *, mtab, { fclose (finally_arg); }); - - static Mutex mutex; - ScopeLock sl (mutex); - - struct mntent *entry; - while ((entry = getmntent (mtab)) != nullptr) - { - make_shared_auto (MountedFilesystem, mf); - - if (entry->mnt_fsname) - mf->Device = DevicePath (entry->mnt_fsname); - else - continue; - - if (entry->mnt_dir) - mf->MountPoint = DirectoryPath (entry->mnt_dir); - - if (entry->mnt_type) - mf->Type = entry->mnt_type; - - if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint)) - mountedFilesystems.push_back (mf); - } - - return mountedFilesystems; - } - - void CoreLinux::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const - { - bool fsMounted = false; - - try - { - if (!FilesystemSupportsUnixPermissions (devicePath)) - { - stringstream userMountOptions; - userMountOptions << "uid=" << GetRealUserId() << ",gid=" << GetRealGroupId() << ",umask=077" << (!systemMountOptions.empty() ? "," : ""); - - CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, userMountOptions.str() + systemMountOptions); - fsMounted = true; - } - } - catch (...) { } - - if (!fsMounted) - CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions); - } - - void CoreLinux::MountVolumeNative (shared_ptr volume, MountOptions &options, const DirectoryPath &auxMountPoint) const - { - bool xts = (typeid (*volume->GetEncryptionMode()) == typeid (EncryptionModeXTS)); - bool lrw = (typeid (*volume->GetEncryptionMode()) == typeid (EncryptionModeLRW)); - - if (options.NoKernelCrypto - || (!xts && (!lrw || volume->GetEncryptionAlgorithm()->GetCiphers().size() > 1 || volume->GetEncryptionAlgorithm()->GetMinBlockSize() != 16)) - || volume->GetProtectionType() == VolumeProtection::HiddenVolumeReadOnly) - { - throw NotApplicable (SRC_POS); - } - - vector osVersion = SystemInfo::GetVersion(); - - if (osVersion.size() >= 3 && osVersion[0] == 2 && osVersion[1] == 6 && osVersion[2] < (xts ? 24 : 20)) - throw NotApplicable (SRC_POS); - - // Load device mapper kernel module - list execArgs; - foreach (const string &dmModule, StringConverter::Split ("dm_mod dm-mod dm")) - { - execArgs.clear(); - execArgs.push_back (dmModule); - - try - { - Process::Execute ("modprobe", execArgs); - break; - } - catch (...) { } - } - - bool loopDevAttached = false; - bool nativeDevCreated = false; - bool filesystemMounted = false; - - // Attach volume to loopback device if required - VolumePath volumePath = volume->GetPath(); - if (!volumePath.IsDevice() || (options.Path->IsDevice() && volume->GetFile()->GetDeviceSectorSize() != ENCRYPTION_DATA_UNIT_SIZE)) - { - volumePath = AttachFileToLoopDevice (volumePath, options.Protection == VolumeProtection::ReadOnly); - loopDevAttached = true; - } - - string nativeDevPath; - - try - { - // Create virtual device using device mapper - size_t nativeDevCount = 0; - size_t secondaryKeyOffset = volume->GetEncryptionMode()->GetKey().Size(); - size_t cipherCount = volume->GetEncryptionAlgorithm()->GetCiphers().size(); - - foreach_reverse_ref (const Cipher &cipher, volume->GetEncryptionAlgorithm()->GetCiphers()) - { - stringstream dmCreateArgs; - dmCreateArgs << "0 " << volume->GetSize() / ENCRYPTION_DATA_UNIT_SIZE << " crypt "; - - // Mode - dmCreateArgs << StringConverter::ToLower (StringConverter::ToSingle (cipher.GetName())) << (xts ? "-xts-plain " : "-lrw-benbi "); - - size_t keyArgOffset = dmCreateArgs.str().size(); - dmCreateArgs << setw (cipher.GetKeySize() * (xts ? 4 : 2) + (xts ? 0 : 16 * 2)) << 0 << setw (0); - - // Sector and data unit offset - uint64 startSector = volume->GetLayout()->GetDataOffset (volume->GetHostSize()) / ENCRYPTION_DATA_UNIT_SIZE; - - dmCreateArgs << ' ' << (xts ? startSector + volume->GetEncryptionMode()->GetSectorOffset() : 0) << ' '; - if (nativeDevCount == 0) - dmCreateArgs << string (volumePath) << ' ' << startSector; - else - dmCreateArgs << nativeDevPath << " 0"; - - SecureBuffer dmCreateArgsBuf (dmCreateArgs.str().size()); - dmCreateArgsBuf.CopyFrom (ConstBufferPtr ((byte *) dmCreateArgs.str().c_str(), dmCreateArgs.str().size())); - - // Keys - const SecureBuffer &cipherKey = cipher.GetKey(); - secondaryKeyOffset -= cipherKey.Size(); - ConstBufferPtr secondaryKey = volume->GetEncryptionMode()->GetKey().GetRange (xts ? secondaryKeyOffset : 0, xts ? cipherKey.Size() : 16); - - SecureBuffer hexStr (3); - for (size_t i = 0; i < cipherKey.Size(); ++i) - { - sprintf ((char *) hexStr.Ptr(), "%02x", (int) cipherKey[i]); - dmCreateArgsBuf.GetRange (keyArgOffset + i * 2, 2).CopyFrom (hexStr.GetRange (0, 2)); - - if (lrw && i >= 16) - continue; - - sprintf ((char *) hexStr.Ptr(), "%02x", (int) secondaryKey[i]); - dmCreateArgsBuf.GetRange (keyArgOffset + cipherKey.Size() * 2 + i * 2, 2).CopyFrom (hexStr.GetRange (0, 2)); - } - - stringstream nativeDevName; - nativeDevName << "truecrypt" << options.SlotNumber; - - if (nativeDevCount != cipherCount - 1) - nativeDevName << "_" << cipherCount - nativeDevCount - 2; - - nativeDevPath = "/dev/mapper/" + nativeDevName.str(); - - execArgs.clear(); - execArgs.push_back ("create"); - execArgs.push_back (nativeDevName.str()); - - Process::Execute ("dmsetup", execArgs, -1, nullptr, &dmCreateArgsBuf); - - // Wait for the device to be created - for (int t = 0; true; t++) - { - try - { - FilesystemPath (nativeDevPath).GetType(); - break; - } - catch (...) - { - if (t > 20) - throw; - - Thread::Sleep (100); - } - } - - nativeDevCreated = true; - ++nativeDevCount; - } - - // Test whether the device mapper is able to read and decrypt the last sector - SecureBuffer lastSectorBuf (volume->GetSectorSize()); - uint64 lastSectorOffset = volume->GetSize() - volume->GetSectorSize(); - - File nativeDev; - nativeDev.Open (nativeDevPath); - nativeDev.ReadAt (lastSectorBuf, lastSectorOffset); - - SecureBuffer lastSectorBuf2 (volume->GetSectorSize()); - volume->ReadSectors (lastSectorBuf2, lastSectorOffset); - - if (memcmp (lastSectorBuf.Ptr(), lastSectorBuf2.Ptr(), volume->GetSectorSize()) != 0) - throw KernelCryptoServiceTestFailed (SRC_POS); - - // Mount filesystem - if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty()) - { - MountFilesystem (nativeDevPath, *options.MountPoint, - StringConverter::ToSingle (options.FilesystemType), - options.Protection == VolumeProtection::ReadOnly, - StringConverter::ToSingle (options.FilesystemOptions)); - - filesystemMounted = true; - } - - FuseService::SendAuxDeviceInfo (auxMountPoint, nativeDevPath, volumePath); - } - catch (...) - { - try - { - if (filesystemMounted) - DismountFilesystem (*options.MountPoint, true); - } - catch (...) { } - - try - { - if (nativeDevCreated) - { - make_shared_auto (VolumeInfo, vol); - vol->VirtualDevice = nativeDevPath; - DismountNativeVolume (vol); - } - } - catch (...) { } - - try - { - if (loopDevAttached) - DetachLoopDevice (volumePath); - } - catch (...) { } - - throw; - } - } - - auto_ptr Core (new CoreServiceProxy ); - auto_ptr CoreDirect (new CoreLinux); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "CoreLinux.h" +#include "Platform/SystemInfo.h" +#include "Platform/TextReader.h" +#include "Volume/EncryptionModeLRW.h" +#include "Volume/EncryptionModeXTS.h" +#include "Driver/Fuse/FuseService.h" +#include "Core/Unix/CoreServiceProxy.h" + +namespace TrueCrypt +{ + CoreLinux::CoreLinux () + { + } + + CoreLinux::~CoreLinux () + { + } + + DevicePath CoreLinux::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const + { + list loopPaths; + loopPaths.push_back ("/dev/loop"); + loopPaths.push_back ("/dev/loop/"); + loopPaths.push_back ("/dev/.static/dev/loop"); + + for (int devIndex = 0; devIndex < 256; devIndex++) + { + string loopDev; + foreach (const string &loopPath, loopPaths) + { + loopDev = loopPath + StringConverter::ToSingle (devIndex); + if (FilesystemPath (loopDev).IsBlockDevice()) + break; + } + + if (loopDev.empty()) + continue; + + list args; + + list ::iterator readOnlyArg; + if (readOnly) + { + args.push_back ("-r"); + readOnlyArg = --args.end(); + } + + args.push_back ("--"); + args.push_back (loopDev); + args.push_back (filePath); + + try + { + Process::Execute ("losetup", args); + return loopDev; + } + catch (ExecutedProcessFailed&) + { + if (readOnly) + { + try + { + args.erase (readOnlyArg); + Process::Execute ("losetup", args); + return loopDev; + } + catch (ExecutedProcessFailed&) { } + } + } + } + + throw LoopDeviceSetupFailed (SRC_POS, wstring (filePath)); + } + + void CoreLinux::DetachLoopDevice (const DevicePath &devicePath) const + { + list args; + args.push_back ("-d"); + args.push_back (devicePath); + + for (int t = 0; true; t++) + { + try + { + Process::Execute ("losetup", args); + break; + } + catch (ExecutedProcessFailed&) + { + if (t > 5) + throw; + Thread::Sleep (200); + } + } + } + + void CoreLinux::DismountNativeVolume (shared_ptr mountedVolume) const + { + string devPath = mountedVolume->VirtualDevice; + + if (devPath.find ("/dev/mapper/truecrypt") != 0) + throw NotApplicable (SRC_POS); + + size_t devCount = 0; + while (FilesystemPath (devPath).IsBlockDevice()) + { + list dmsetupArgs; + dmsetupArgs.push_back ("remove"); + dmsetupArgs.push_back (StringConverter::Split (devPath, "/").back()); + + for (int t = 0; true; t++) + { + try + { + Process::Execute ("dmsetup", dmsetupArgs); + break; + } + catch (...) + { + if (t > 20) + throw; + + Thread::Sleep (100); + } + } + + for (int t = 0; FilesystemPath (devPath).IsBlockDevice() && t < 20; t++) + { + Thread::Sleep (100); + } + + devPath = string (mountedVolume->VirtualDevice) + "_" + StringConverter::ToSingle (devCount++); + } + } + + HostDeviceList CoreLinux::GetHostDevices (bool pathListOnly) const + { + HostDeviceList devices; + TextReader tr ("/proc/partitions"); + + string line; + while (tr.ReadLine (line)) + { + vector fields = StringConverter::Split (line); + + if (fields.size() != 4 + || fields[3].find ("loop") == 0 // skip loop devices + || fields[3].find ("ram") == 0 // skip RAM devices + || fields[3].find ("dm-") == 0 // skip device mapper devices + || fields[2] == "1" // skip extended partitions + ) + continue; + + try + { + StringConverter::ToUInt32 (fields[0]); + } + catch (...) + { + continue; + } + + try + { + make_shared_auto (HostDevice, hostDevice); + + hostDevice->Path = string (fields[3].find ("/dev/") == string::npos ? "/dev/" : "") + fields[3]; + + if (!pathListOnly) + { + hostDevice->Size = StringConverter::ToUInt64 (fields[2]) * 1024; + hostDevice->MountPoint = GetDeviceMountPoint (hostDevice->Path); + hostDevice->SystemNumber = 0; + } + + try + { + StringConverter::GetTrailingNumber (fields[3]); + if (devices.size() > 0) + { + HostDevice &prevDev = **--devices.end(); + if (string (hostDevice->Path).find (prevDev.Path) == 0) + { + prevDev.Partitions.push_back (hostDevice); + continue; + } + } + } + catch (...) { } + + devices.push_back (hostDevice); + continue; + } + catch (...) + { + continue; + } + } + + return devices; + } + + MountedFilesystemList CoreLinux::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const + { + MountedFilesystemList mountedFilesystems; + + FILE *mtab = fopen ("/etc/mtab", "r"); + + if (!mtab) + mtab = fopen ("/proc/mounts", "r"); + + throw_sys_sub_if (!mtab, "/proc/mounts"); + finally_do_arg (FILE *, mtab, { fclose (finally_arg); }); + + static Mutex mutex; + ScopeLock sl (mutex); + + struct mntent *entry; + while ((entry = getmntent (mtab)) != nullptr) + { + make_shared_auto (MountedFilesystem, mf); + + if (entry->mnt_fsname) + mf->Device = DevicePath (entry->mnt_fsname); + else + continue; + + if (entry->mnt_dir) + mf->MountPoint = DirectoryPath (entry->mnt_dir); + + if (entry->mnt_type) + mf->Type = entry->mnt_type; + + if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint)) + mountedFilesystems.push_back (mf); + } + + return mountedFilesystems; + } + + void CoreLinux::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const + { + bool fsMounted = false; + + try + { + if (!FilesystemSupportsUnixPermissions (devicePath)) + { + stringstream userMountOptions; + userMountOptions << "uid=" << GetRealUserId() << ",gid=" << GetRealGroupId() << ",umask=077" << (!systemMountOptions.empty() ? "," : ""); + + CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, userMountOptions.str() + systemMountOptions); + fsMounted = true; + } + } + catch (...) { } + + if (!fsMounted) + CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions); + } + + void CoreLinux::MountVolumeNative (shared_ptr volume, MountOptions &options, const DirectoryPath &auxMountPoint) const + { + bool xts = (typeid (*volume->GetEncryptionMode()) == typeid (EncryptionModeXTS)); + bool lrw = (typeid (*volume->GetEncryptionMode()) == typeid (EncryptionModeLRW)); + + if (options.NoKernelCrypto + || (!xts && (!lrw || volume->GetEncryptionAlgorithm()->GetCiphers().size() > 1 || volume->GetEncryptionAlgorithm()->GetMinBlockSize() != 16)) + || volume->GetProtectionType() == VolumeProtection::HiddenVolumeReadOnly) + { + throw NotApplicable (SRC_POS); + } + + vector osVersion = SystemInfo::GetVersion(); + + if (osVersion.size() >= 3 && osVersion[0] == 2 && osVersion[1] == 6 && osVersion[2] < (xts ? 24 : 20)) + throw NotApplicable (SRC_POS); + + // Load device mapper kernel module + list execArgs; + foreach (const string &dmModule, StringConverter::Split ("dm_mod dm-mod dm")) + { + execArgs.clear(); + execArgs.push_back (dmModule); + + try + { + Process::Execute ("modprobe", execArgs); + break; + } + catch (...) { } + } + + bool loopDevAttached = false; + bool nativeDevCreated = false; + bool filesystemMounted = false; + + // Attach volume to loopback device if required + VolumePath volumePath = volume->GetPath(); + if (!volumePath.IsDevice() || (options.Path->IsDevice() && volume->GetFile()->GetDeviceSectorSize() != ENCRYPTION_DATA_UNIT_SIZE)) + { + volumePath = AttachFileToLoopDevice (volumePath, options.Protection == VolumeProtection::ReadOnly); + loopDevAttached = true; + } + + string nativeDevPath; + + try + { + // Create virtual device using device mapper + size_t nativeDevCount = 0; + size_t secondaryKeyOffset = volume->GetEncryptionMode()->GetKey().Size(); + size_t cipherCount = volume->GetEncryptionAlgorithm()->GetCiphers().size(); + + foreach_reverse_ref (const Cipher &cipher, volume->GetEncryptionAlgorithm()->GetCiphers()) + { + stringstream dmCreateArgs; + dmCreateArgs << "0 " << volume->GetSize() / ENCRYPTION_DATA_UNIT_SIZE << " crypt "; + + // Mode + dmCreateArgs << StringConverter::ToLower (StringConverter::ToSingle (cipher.GetName())) << (xts ? "-xts-plain " : "-lrw-benbi "); + + size_t keyArgOffset = dmCreateArgs.str().size(); + dmCreateArgs << setw (cipher.GetKeySize() * (xts ? 4 : 2) + (xts ? 0 : 16 * 2)) << 0 << setw (0); + + // Sector and data unit offset + uint64 startSector = volume->GetLayout()->GetDataOffset (volume->GetHostSize()) / ENCRYPTION_DATA_UNIT_SIZE; + + dmCreateArgs << ' ' << (xts ? startSector + volume->GetEncryptionMode()->GetSectorOffset() : 0) << ' '; + if (nativeDevCount == 0) + dmCreateArgs << string (volumePath) << ' ' << startSector; + else + dmCreateArgs << nativeDevPath << " 0"; + + SecureBuffer dmCreateArgsBuf (dmCreateArgs.str().size()); + dmCreateArgsBuf.CopyFrom (ConstBufferPtr ((byte *) dmCreateArgs.str().c_str(), dmCreateArgs.str().size())); + + // Keys + const SecureBuffer &cipherKey = cipher.GetKey(); + secondaryKeyOffset -= cipherKey.Size(); + ConstBufferPtr secondaryKey = volume->GetEncryptionMode()->GetKey().GetRange (xts ? secondaryKeyOffset : 0, xts ? cipherKey.Size() : 16); + + SecureBuffer hexStr (3); + for (size_t i = 0; i < cipherKey.Size(); ++i) + { + sprintf ((char *) hexStr.Ptr(), "%02x", (int) cipherKey[i]); + dmCreateArgsBuf.GetRange (keyArgOffset + i * 2, 2).CopyFrom (hexStr.GetRange (0, 2)); + + if (lrw && i >= 16) + continue; + + sprintf ((char *) hexStr.Ptr(), "%02x", (int) secondaryKey[i]); + dmCreateArgsBuf.GetRange (keyArgOffset + cipherKey.Size() * 2 + i * 2, 2).CopyFrom (hexStr.GetRange (0, 2)); + } + + stringstream nativeDevName; + nativeDevName << "truecrypt" << options.SlotNumber; + + if (nativeDevCount != cipherCount - 1) + nativeDevName << "_" << cipherCount - nativeDevCount - 2; + + nativeDevPath = "/dev/mapper/" + nativeDevName.str(); + + execArgs.clear(); + execArgs.push_back ("create"); + execArgs.push_back (nativeDevName.str()); + + Process::Execute ("dmsetup", execArgs, -1, nullptr, &dmCreateArgsBuf); + + // Wait for the device to be created + for (int t = 0; true; t++) + { + try + { + FilesystemPath (nativeDevPath).GetType(); + break; + } + catch (...) + { + if (t > 20) + throw; + + Thread::Sleep (100); + } + } + + nativeDevCreated = true; + ++nativeDevCount; + } + + // Test whether the device mapper is able to read and decrypt the last sector + SecureBuffer lastSectorBuf (volume->GetSectorSize()); + uint64 lastSectorOffset = volume->GetSize() - volume->GetSectorSize(); + + File nativeDev; + nativeDev.Open (nativeDevPath); + nativeDev.ReadAt (lastSectorBuf, lastSectorOffset); + + SecureBuffer lastSectorBuf2 (volume->GetSectorSize()); + volume->ReadSectors (lastSectorBuf2, lastSectorOffset); + + if (memcmp (lastSectorBuf.Ptr(), lastSectorBuf2.Ptr(), volume->GetSectorSize()) != 0) + throw KernelCryptoServiceTestFailed (SRC_POS); + + // Mount filesystem + if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty()) + { + MountFilesystem (nativeDevPath, *options.MountPoint, + StringConverter::ToSingle (options.FilesystemType), + options.Protection == VolumeProtection::ReadOnly, + StringConverter::ToSingle (options.FilesystemOptions)); + + filesystemMounted = true; + } + + FuseService::SendAuxDeviceInfo (auxMountPoint, nativeDevPath, volumePath); + } + catch (...) + { + try + { + if (filesystemMounted) + DismountFilesystem (*options.MountPoint, true); + } + catch (...) { } + + try + { + if (nativeDevCreated) + { + make_shared_auto (VolumeInfo, vol); + vol->VirtualDevice = nativeDevPath; + DismountNativeVolume (vol); + } + } + catch (...) { } + + try + { + if (loopDevAttached) + DetachLoopDevice (volumePath); + } + catch (...) { } + + throw; + } + } + + auto_ptr Core (new CoreServiceProxy ); + auto_ptr CoreDirect (new CoreLinux); +} diff --git a/Core/Unix/Linux/CoreLinux.h b/Core/Unix/Linux/CoreLinux.h index d02cb7d..e614b33 100644 --- a/Core/Unix/Linux/CoreLinux.h +++ b/Core/Unix/Linux/CoreLinux.h @@ -1,39 +1,39 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_CoreLinux -#define TC_HEADER_Core_CoreLinux - -#include "System.h" -#include "Core/Unix/CoreUnix.h" - -namespace TrueCrypt -{ - class CoreLinux : public CoreUnix - { - public: - CoreLinux (); - virtual ~CoreLinux (); - - virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const; - - protected: - virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const; - virtual void DetachLoopDevice (const DevicePath &devicePath) const; - virtual void DismountNativeVolume (shared_ptr mountedVolume) const; - virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const; - virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; - virtual void MountVolumeNative (shared_ptr volume, MountOptions &options, const DirectoryPath &auxMountPoint) const; - - private: - CoreLinux (const CoreLinux &); - CoreLinux &operator= (const CoreLinux &); - }; -} - -#endif // TC_HEADER_Core_CoreLinux +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_CoreLinux +#define TC_HEADER_Core_CoreLinux + +#include "System.h" +#include "Core/Unix/CoreUnix.h" + +namespace TrueCrypt +{ + class CoreLinux : public CoreUnix + { + public: + CoreLinux (); + virtual ~CoreLinux (); + + virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const; + + protected: + virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const; + virtual void DetachLoopDevice (const DevicePath &devicePath) const; + virtual void DismountNativeVolume (shared_ptr mountedVolume) const; + virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const; + virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; + virtual void MountVolumeNative (shared_ptr volume, MountOptions &options, const DirectoryPath &auxMountPoint) const; + + private: + CoreLinux (const CoreLinux &); + CoreLinux &operator= (const CoreLinux &); + }; +} + +#endif // TC_HEADER_Core_CoreLinux diff --git a/Core/Unix/Linux/System.h b/Core/Unix/Linux/System.h index 46f86a8..86e7e86 100644 --- a/Core/Unix/Linux/System.h +++ b/Core/Unix/Linux/System.h @@ -1,12 +1,12 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Linux_System -#define TC_HEADER_Platform_Linux_System - -#endif // TC_HEADER_Platform_Linux_System +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Linux_System +#define TC_HEADER_Platform_Linux_System + +#endif // TC_HEADER_Platform_Linux_System diff --git a/Core/Unix/MacOSX/CoreMacOSX.cpp b/Core/Unix/MacOSX/CoreMacOSX.cpp index da7ffaa..d6f6df7 100644 --- a/Core/Unix/MacOSX/CoreMacOSX.cpp +++ b/Core/Unix/MacOSX/CoreMacOSX.cpp @@ -1,203 +1,215 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "CoreMacOSX.h" -#include "Driver/Fuse/FuseService.h" -#include "Core/Unix/CoreServiceProxy.h" - -namespace TrueCrypt -{ - CoreMacOSX::CoreMacOSX () - { - } - - CoreMacOSX::~CoreMacOSX () - { - } - - shared_ptr CoreMacOSX::DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) - { - if (!mountedVolume->VirtualDevice.IsEmpty() && mountedVolume->VirtualDevice.IsBlockDevice()) - { - list args; - args.push_back ("detach"); - args.push_back (mountedVolume->VirtualDevice); - - if (ignoreOpenFiles) - args.push_back ("-force"); - - try - { - Process::Execute ("hdiutil", args); - } - catch (ExecutedProcessFailed &e) - { - if (e.GetErrorOutput().find("49153") != string::npos) - throw MountedVolumeInUse (SRC_POS); - throw; - } - } - - if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly) - { - sync(); - VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path); - - if (ml.size() > 0) - mountedVolume = ml.front(); - } - - list args; - args.push_back ("--"); - args.push_back (mountedVolume->AuxMountPoint); - - for (int t = 0; true; t++) - { - try - { - Process::Execute ("umount", args); - break; - } - catch (ExecutedProcessFailed&) - { - if (t > 10) - throw; - Thread::Sleep (200); - } - } - - try - { - mountedVolume->AuxMountPoint.Delete(); - } - catch (...) { } - - return mountedVolume; - } - - void CoreMacOSX::CheckFilesystem (shared_ptr mountedVolume, bool repair) const - { - list args; - args.push_back ("/Applications/Utilities/Disk Utility.app"); - Process::Execute ("open", args); - } - - void CoreMacOSX::MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const - { - // Check FUSE version - char fuseVersionString[MAXHOSTNAMELEN + 1] = { 0 }; - size_t fuseVersionStringLength = MAXHOSTNAMELEN; - - if (sysctlbyname ("macfuse.version.number", fuseVersionString, &fuseVersionStringLength, NULL, 0) != 0) - throw HigherFuseVersionRequired (SRC_POS); - - vector fuseVersion = StringConverter::Split (string (fuseVersionString), "."); - if (fuseVersion.size() < 2) - throw HigherFuseVersionRequired (SRC_POS); - - uint32 fuseVersionMajor = StringConverter::ToUInt32 (fuseVersion[0]); - uint32 fuseVersionMinor = StringConverter::ToUInt32 (fuseVersion[1]); - - if (fuseVersionMajor < 1 || (fuseVersionMajor == 1 && fuseVersionMinor < 3)) - throw HigherFuseVersionRequired (SRC_POS); - - // Mount volume image - string volImage = string (auxMountPoint) + FuseService::GetVolumeImagePath(); - - list args; - args.push_back ("attach"); - args.push_back (volImage); - args.push_back ("-plist"); - args.push_back ("-noautofsck"); - - if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty()) - { - args.push_back ("-mount"); - args.push_back ("required"); - - // Let the system specify mount point except when the user specified a non-default one - if (string (*options.MountPoint).find (GetDefaultMountPointPrefix()) != 0) - { - args.push_back ("-mountpoint"); - args.push_back (*options.MountPoint); - } - } - else - args.push_back ("-nomount"); - - if (options.Protection == VolumeProtection::ReadOnly) - args.push_back ("-readonly"); - - string xml; - - while (true) - { - try - { - xml = Process::Execute ("hdiutil", args); - break; - } - catch (ExecutedProcessFailed &e) - { - if (e.GetErrorOutput().find ("noautofsck") != string::npos) - { - args.remove ("-noautofsck"); - continue; - } - - throw; - } - } - - size_t p = xml.find ("dev-entry"); - if (p == string::npos) - throw ParameterIncorrect (SRC_POS); - - p = xml.find ("", p); - if (p == string::npos) - throw ParameterIncorrect (SRC_POS); - p += 8; - - size_t e = xml.find ("", p); - if (e == string::npos) - throw ParameterIncorrect (SRC_POS); - - DevicePath virtualDev = StringConverter::Trim (xml.substr (p, e - p)); - - try - { - FuseService::SendAuxDeviceInfo (auxMountPoint, virtualDev); - } - catch (...) - { - try - { - list args; - args.push_back ("detach"); - args.push_back (volImage); - args.push_back ("-force"); - - Process::Execute ("hdiutil", args); - } - catch (ExecutedProcessFailed&) { } - throw; - } - } - - auto_ptr Core (new CoreServiceProxy ); - auto_ptr CoreDirect (new CoreMacOSX); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "CoreMacOSX.h" +#include "Driver/Fuse/FuseService.h" +#include "Core/Unix/CoreServiceProxy.h" + +namespace TrueCrypt +{ + CoreMacOSX::CoreMacOSX () + { + } + + CoreMacOSX::~CoreMacOSX () + { + } + + shared_ptr CoreMacOSX::DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) + { + if (!mountedVolume->VirtualDevice.IsEmpty() && mountedVolume->VirtualDevice.IsBlockDevice()) + { + list args; + args.push_back ("detach"); + args.push_back (mountedVolume->VirtualDevice); + + if (ignoreOpenFiles) + args.push_back ("-force"); + + try + { + Process::Execute ("hdiutil", args); + } + catch (ExecutedProcessFailed &e) + { + if (!ignoreOpenFiles) + { + string err = e.GetErrorOutput(); + + if (err.find ("couldn't unmount") != string::npos + || err.find ("busy") != string::npos + || err.find ("49153") != string::npos) + { + throw MountedVolumeInUse (SRC_POS); + } + } + + throw; + } + } + + if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly) + { + sync(); + VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path); + + if (ml.size() > 0) + mountedVolume = ml.front(); + } + + list args; + args.push_back ("--"); + args.push_back (mountedVolume->AuxMountPoint); + + for (int t = 0; true; t++) + { + try + { + Process::Execute ("umount", args); + break; + } + catch (ExecutedProcessFailed&) + { + if (t > 10) + throw; + Thread::Sleep (200); + } + } + + try + { + mountedVolume->AuxMountPoint.Delete(); + } + catch (...) { } + + return mountedVolume; + } + + void CoreMacOSX::CheckFilesystem (shared_ptr mountedVolume, bool repair) const + { + list args; + args.push_back ("/Applications/Utilities/Disk Utility.app"); + Process::Execute ("open", args); + } + + void CoreMacOSX::MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const + { + // Check FUSE version + char fuseVersionString[MAXHOSTNAMELEN + 1] = { 0 }; + size_t fuseVersionStringLength = MAXHOSTNAMELEN; + + if (sysctlbyname ("macfuse.version.number", fuseVersionString, &fuseVersionStringLength, NULL, 0) != 0) + throw HigherFuseVersionRequired (SRC_POS); + + vector fuseVersion = StringConverter::Split (string (fuseVersionString), "."); + if (fuseVersion.size() < 2) + throw HigherFuseVersionRequired (SRC_POS); + + uint32 fuseVersionMajor = StringConverter::ToUInt32 (fuseVersion[0]); + uint32 fuseVersionMinor = StringConverter::ToUInt32 (fuseVersion[1]); + + if (fuseVersionMajor < 1 || (fuseVersionMajor == 1 && fuseVersionMinor < 3)) + throw HigherFuseVersionRequired (SRC_POS); + + // Mount volume image + string volImage = string (auxMountPoint) + FuseService::GetVolumeImagePath(); + + list args; + args.push_back ("attach"); + args.push_back (volImage); + args.push_back ("-plist"); + args.push_back ("-noautofsck"); + args.push_back ("-imagekey"); + args.push_back ("diskimage-class=CRawDiskImage"); + + if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty()) + { + args.push_back ("-mount"); + args.push_back ("required"); + + // Let the system specify mount point except when the user specified a non-default one + if (string (*options.MountPoint).find (GetDefaultMountPointPrefix()) != 0) + { + args.push_back ("-mountpoint"); + args.push_back (*options.MountPoint); + } + } + else + args.push_back ("-nomount"); + + if (options.Protection == VolumeProtection::ReadOnly) + args.push_back ("-readonly"); + + string xml; + + while (true) + { + try + { + xml = Process::Execute ("hdiutil", args); + break; + } + catch (ExecutedProcessFailed &e) + { + if (e.GetErrorOutput().find ("noautofsck") != string::npos) + { + args.remove ("-noautofsck"); + continue; + } + + throw; + } + } + + size_t p = xml.find ("dev-entry"); + if (p == string::npos) + throw ParameterIncorrect (SRC_POS); + + p = xml.find ("", p); + if (p == string::npos) + throw ParameterIncorrect (SRC_POS); + p += 8; + + size_t e = xml.find ("", p); + if (e == string::npos) + throw ParameterIncorrect (SRC_POS); + + DevicePath virtualDev = StringConverter::Trim (xml.substr (p, e - p)); + + try + { + FuseService::SendAuxDeviceInfo (auxMountPoint, virtualDev); + } + catch (...) + { + try + { + list args; + args.push_back ("detach"); + args.push_back (volImage); + args.push_back ("-force"); + + Process::Execute ("hdiutil", args); + } + catch (ExecutedProcessFailed&) { } + throw; + } + } + + auto_ptr Core (new CoreServiceProxy ); + auto_ptr CoreDirect (new CoreMacOSX); +} diff --git a/Core/Unix/MacOSX/CoreMacOSX.h b/Core/Unix/MacOSX/CoreMacOSX.h index 8daab40..e9ab42b 100644 --- a/Core/Unix/MacOSX/CoreMacOSX.h +++ b/Core/Unix/MacOSX/CoreMacOSX.h @@ -1,36 +1,36 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_CoreMacOSX -#define TC_HEADER_Core_CoreMacOSX - -#include "System.h" -#include "Core/Unix/FreeBSD/CoreFreeBSD.h" - -namespace TrueCrypt -{ - class CoreMacOSX : public CoreFreeBSD - { - public: - CoreMacOSX (); - virtual ~CoreMacOSX (); - - virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const; - virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false); - virtual string GetDefaultMountPointPrefix () const { return "/Volumes/truecrypt"; } - - protected: - virtual void MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const; - - private: - CoreMacOSX (const CoreMacOSX &); - CoreMacOSX &operator= (const CoreMacOSX &); - }; -} - -#endif // TC_HEADER_Core_CoreMacOSX +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_CoreMacOSX +#define TC_HEADER_Core_CoreMacOSX + +#include "System.h" +#include "Core/Unix/FreeBSD/CoreFreeBSD.h" + +namespace TrueCrypt +{ + class CoreMacOSX : public CoreFreeBSD + { + public: + CoreMacOSX (); + virtual ~CoreMacOSX (); + + virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const; + virtual shared_ptr DismountVolume (shared_ptr mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false); + virtual string GetDefaultMountPointPrefix () const { return "/Volumes/truecrypt"; } + + protected: + virtual void MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const; + + private: + CoreMacOSX (const CoreMacOSX &); + CoreMacOSX &operator= (const CoreMacOSX &); + }; +} + +#endif // TC_HEADER_Core_CoreMacOSX diff --git a/Core/Unix/MacOSX/System.h b/Core/Unix/MacOSX/System.h index 6af5d0d..0602970 100644 --- a/Core/Unix/MacOSX/System.h +++ b/Core/Unix/MacOSX/System.h @@ -1,12 +1,12 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_MacOSX_System -#define TC_HEADER_Platform_MacOSX_System - -#endif // TC_HEADER_Platform_MacOSX_System +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_MacOSX_System +#define TC_HEADER_Platform_MacOSX_System + +#endif // TC_HEADER_Platform_MacOSX_System diff --git a/Core/Unix/MountedFilesystem.h b/Core/Unix/MountedFilesystem.h index b68560d..0cec27c 100644 --- a/Core/Unix/MountedFilesystem.h +++ b/Core/Unix/MountedFilesystem.h @@ -1,27 +1,27 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_Unix_MountedFilesystem -#define TC_HEADER_Core_Unix_MountedFilesystem - -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - struct MountedFilesystem - { - public: - DevicePath Device; - DirectoryPath MountPoint; - string Type; - }; - - typedef list < shared_ptr > MountedFilesystemList; -} - -#endif // TC_HEADER_Core_Unix_MountedFilesystem +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_Unix_MountedFilesystem +#define TC_HEADER_Core_Unix_MountedFilesystem + +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + struct MountedFilesystem + { + public: + DevicePath Device; + DirectoryPath MountPoint; + string Type; + }; + + typedef list < shared_ptr > MountedFilesystemList; +} + +#endif // TC_HEADER_Core_Unix_MountedFilesystem diff --git a/Core/Unix/Solaris/CoreSolaris.cpp b/Core/Unix/Solaris/CoreSolaris.cpp index 2365107..240ec93 100644 --- a/Core/Unix/Solaris/CoreSolaris.cpp +++ b/Core/Unix/Solaris/CoreSolaris.cpp @@ -1,174 +1,174 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include -#include -#include "CoreSolaris.h" -#include "Core/Unix/CoreServiceProxy.h" - -namespace TrueCrypt -{ - CoreSolaris::CoreSolaris () - { - } - - CoreSolaris::~CoreSolaris () - { - } - - DevicePath CoreSolaris::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const - { - list args; - args.push_back ("-a"); - args.push_back (filePath); - - return StringConverter::Trim (Process::Execute ("lofiadm", args)); - } - - void CoreSolaris::DetachLoopDevice (const DevicePath &devicePath) const - { - list args; - args.push_back ("-d"); - args.push_back (devicePath); - - for (int t = 0; true; t++) - { - try - { - Process::Execute ("lofiadm", args); - break; - } - catch (ExecutedProcessFailed&) - { - if (t > 5) - throw; - Thread::Sleep (200); - } - } - } - - HostDeviceList CoreSolaris::GetHostDevices (bool pathListOnly) const - { - HostDeviceList devices; - - foreach_ref (const FilePath &devPath, Directory::GetFilePaths ("/dev/rdsk", false)) - { - string drivePath = devPath; - if (drivePath.rfind ("p0") == drivePath.size() - 2) - { - make_shared_auto (HostDevice, device); - device->Path = drivePath; - - try - { - device->Size = GetDeviceSize (device->Path); - } - catch (...) - { - device->Size = 0; - } - - if (device->Size == 0) - continue; - - device->MountPoint = GetDeviceMountPoint (device->Path); - device->SystemNumber = 0; - - devices.push_back (device); - - for (int partNumber = 1; partNumber <= 32; partNumber++) - { - stringstream partPath; - partPath << drivePath.substr (0, drivePath.size() - 1) << partNumber; - - if (FilesystemPath (partPath.str()).IsBlockDevice() || FilesystemPath (partPath.str()).IsCharacterDevice()) - { - make_shared_auto (HostDevice, partition); - partition->Path = partPath.str(); - - try - { - partition->Size = GetDeviceSize (partition->Path); - } - catch (...) - { - partition->Size = 0; - } - - if (partition->Size == 0) - continue; - - partition->MountPoint = GetDeviceMountPoint (partition->Path); - partition->SystemNumber = 0; - - device->Partitions.push_back (partition); - } - } - } - } - - return devices; - } - - MountedFilesystemList CoreSolaris::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const - { - MountedFilesystemList mountedFilesystems; - - FILE *mtab = fopen ("/etc/mnttab", "r"); - throw_sys_sub_if (!mtab, "/etc/mnttab"); - finally_do_arg (FILE *, mtab, { fclose (finally_arg); }); - - int getmntentResult; - struct mnttab entry; - while ((getmntentResult = getmntent (mtab, &entry)) == 0) - { - make_shared_auto (MountedFilesystem, mf); - - if (entry.mnt_special) - mf->Device = DevicePath (entry.mnt_special); - else - continue; - - if (entry.mnt_mountp) - mf->MountPoint = DirectoryPath (entry.mnt_mountp); - - if (entry.mnt_fstype) - mf->Type = entry.mnt_fstype; - - if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint)) - mountedFilesystems.push_back (mf); - } - - throw_sys_if (getmntentResult > 0); - - return mountedFilesystems; - } - - void CoreSolaris::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const - { - try - { - // Try to mount FAT by default as mount is unable to probe filesystem type on Solaris - CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType.empty() ? "pcfs" : filesystemType, readOnly, systemMountOptions); - } - catch (ExecutedProcessFailed&) - { - if (!filesystemType.empty()) - throw; - - CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions); - } - } - - auto_ptr Core (new CoreServiceProxy ); - auto_ptr CoreDirect (new CoreSolaris); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include +#include +#include "CoreSolaris.h" +#include "Core/Unix/CoreServiceProxy.h" + +namespace TrueCrypt +{ + CoreSolaris::CoreSolaris () + { + } + + CoreSolaris::~CoreSolaris () + { + } + + DevicePath CoreSolaris::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const + { + list args; + args.push_back ("-a"); + args.push_back (filePath); + + return StringConverter::Trim (Process::Execute ("lofiadm", args)); + } + + void CoreSolaris::DetachLoopDevice (const DevicePath &devicePath) const + { + list args; + args.push_back ("-d"); + args.push_back (devicePath); + + for (int t = 0; true; t++) + { + try + { + Process::Execute ("lofiadm", args); + break; + } + catch (ExecutedProcessFailed&) + { + if (t > 5) + throw; + Thread::Sleep (200); + } + } + } + + HostDeviceList CoreSolaris::GetHostDevices (bool pathListOnly) const + { + HostDeviceList devices; + + foreach_ref (const FilePath &devPath, Directory::GetFilePaths ("/dev/rdsk", false)) + { + string drivePath = devPath; + if (drivePath.rfind ("p0") == drivePath.size() - 2) + { + make_shared_auto (HostDevice, device); + device->Path = drivePath; + + try + { + device->Size = GetDeviceSize (device->Path); + } + catch (...) + { + device->Size = 0; + } + + if (device->Size == 0) + continue; + + device->MountPoint = GetDeviceMountPoint (device->Path); + device->SystemNumber = 0; + + devices.push_back (device); + + for (int partNumber = 1; partNumber <= 32; partNumber++) + { + stringstream partPath; + partPath << drivePath.substr (0, drivePath.size() - 1) << partNumber; + + if (FilesystemPath (partPath.str()).IsBlockDevice() || FilesystemPath (partPath.str()).IsCharacterDevice()) + { + make_shared_auto (HostDevice, partition); + partition->Path = partPath.str(); + + try + { + partition->Size = GetDeviceSize (partition->Path); + } + catch (...) + { + partition->Size = 0; + } + + if (partition->Size == 0) + continue; + + partition->MountPoint = GetDeviceMountPoint (partition->Path); + partition->SystemNumber = 0; + + device->Partitions.push_back (partition); + } + } + } + } + + return devices; + } + + MountedFilesystemList CoreSolaris::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const + { + MountedFilesystemList mountedFilesystems; + + FILE *mtab = fopen ("/etc/mnttab", "r"); + throw_sys_sub_if (!mtab, "/etc/mnttab"); + finally_do_arg (FILE *, mtab, { fclose (finally_arg); }); + + int getmntentResult; + struct mnttab entry; + while ((getmntentResult = getmntent (mtab, &entry)) == 0) + { + make_shared_auto (MountedFilesystem, mf); + + if (entry.mnt_special) + mf->Device = DevicePath (entry.mnt_special); + else + continue; + + if (entry.mnt_mountp) + mf->MountPoint = DirectoryPath (entry.mnt_mountp); + + if (entry.mnt_fstype) + mf->Type = entry.mnt_fstype; + + if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint)) + mountedFilesystems.push_back (mf); + } + + throw_sys_if (getmntentResult > 0); + + return mountedFilesystems; + } + + void CoreSolaris::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const + { + try + { + // Try to mount FAT by default as mount is unable to probe filesystem type on Solaris + CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType.empty() ? "pcfs" : filesystemType, readOnly, systemMountOptions); + } + catch (ExecutedProcessFailed&) + { + if (!filesystemType.empty()) + throw; + + CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions); + } + } + + auto_ptr Core (new CoreServiceProxy ); + auto_ptr CoreDirect (new CoreSolaris); +} diff --git a/Core/Unix/Solaris/CoreSolaris.h b/Core/Unix/Solaris/CoreSolaris.h index 8866105..8a4148d 100644 --- a/Core/Unix/Solaris/CoreSolaris.h +++ b/Core/Unix/Solaris/CoreSolaris.h @@ -1,37 +1,37 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Core_CoreSolaris -#define TC_HEADER_Core_CoreSolaris - -#include "System.h" -#include "Core/Unix/CoreUnix.h" - -namespace TrueCrypt -{ - class CoreSolaris : public CoreUnix - { - public: - CoreSolaris (); - virtual ~CoreSolaris (); - - virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const; - - protected: - virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const; - virtual void DetachLoopDevice (const DevicePath &devicePath) const; - virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const; - virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; - - private: - CoreSolaris (const CoreSolaris &); - CoreSolaris &operator= (const CoreSolaris &); - }; -} - -#endif // TC_HEADER_Core_CoreSolaris +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Core_CoreSolaris +#define TC_HEADER_Core_CoreSolaris + +#include "System.h" +#include "Core/Unix/CoreUnix.h" + +namespace TrueCrypt +{ + class CoreSolaris : public CoreUnix + { + public: + CoreSolaris (); + virtual ~CoreSolaris (); + + virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const; + + protected: + virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const; + virtual void DetachLoopDevice (const DevicePath &devicePath) const; + virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const; + virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const; + + private: + CoreSolaris (const CoreSolaris &); + CoreSolaris &operator= (const CoreSolaris &); + }; +} + +#endif // TC_HEADER_Core_CoreSolaris diff --git a/Core/Unix/Solaris/System.h b/Core/Unix/Solaris/System.h index 0aadb29..f804e0a 100644 --- a/Core/Unix/Solaris/System.h +++ b/Core/Unix/Solaris/System.h @@ -1,12 +1,12 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Solaris_System -#define TC_HEADER_Platform_Solaris_System - -#endif // TC_HEADER_Platform_Solaris_System +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Solaris_System +#define TC_HEADER_Platform_Solaris_System + +#endif // TC_HEADER_Platform_Solaris_System diff --git a/Core/Unix/System.h b/Core/Unix/System.h index 78e3d50..2611d1c 100644 --- a/Core/Unix/System.h +++ b/Core/Unix/System.h @@ -1,12 +1,12 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Unix_System -#define TC_HEADER_Platform_Unix_System - -#endif // TC_HEADER_Platform_Unix_System +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Unix_System +#define TC_HEADER_Platform_Unix_System + +#endif // TC_HEADER_Platform_Unix_System diff --git a/Core/VolumeCreator.cpp b/Core/VolumeCreator.cpp index 3e72d10..7216b79 100644 --- a/Core/VolumeCreator.cpp +++ b/Core/VolumeCreator.cpp @@ -1,329 +1,329 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Volume/EncryptionTest.h" -#include "Volume/EncryptionModeXTS.h" -#include "Core.h" - -#ifdef TC_UNIX -#include -#include -#include -#endif - -#include "VolumeCreator.h" -#include "FatFormatter.h" - -namespace TrueCrypt -{ - VolumeCreator::VolumeCreator () - : SizeDone (0) - { - } - - VolumeCreator::~VolumeCreator () - { - } - - void VolumeCreator::Abort () - { - AbortRequested = true; - } - - void VolumeCreator::CheckResult () - { - if (ThreadException) - ThreadException->Throw(); - } - - void VolumeCreator::CreationThread () - { - try - { - uint64 endOffset; - uint64 filesystemSize = Layout->GetDataSize (HostSize); - - if (filesystemSize < 1) - throw ParameterIncorrect (SRC_POS); - - DataStart = Layout->GetDataOffset (HostSize); - WriteOffset = DataStart; - endOffset = DataStart + Layout->GetDataSize (HostSize); - - VolumeFile->SeekAt (DataStart); - - // Create filesystem - if (Options->Filesystem == VolumeCreationOptions::FilesystemType::FAT) - { - if (filesystemSize < TC_MIN_FAT_FS_SIZE || filesystemSize > TC_MAX_FAT_FS_SIZE) - throw ParameterIncorrect (SRC_POS); - - struct WriteSectorCallback : public FatFormatter::WriteSectorCallback - { - WriteSectorCallback (VolumeCreator *creator) : Creator (creator), OutputBuffer (File::GetOptimalWriteSize()), OutputBufferWritePos (0) { } - - virtual bool operator() (const BufferPtr §or) - { - OutputBuffer.GetRange (OutputBufferWritePos, sector.Size()).CopyFrom (sector); - OutputBufferWritePos += sector.Size(); - - if (OutputBufferWritePos >= OutputBuffer.Size()) - FlushOutputBuffer(); - - return !Creator->AbortRequested; - } - - void FlushOutputBuffer () - { - if (OutputBufferWritePos > 0) - { - Creator->Options->EA->EncryptSectors (OutputBuffer.GetRange (0, OutputBufferWritePos), - Creator->WriteOffset / SECTOR_SIZE, OutputBufferWritePos / SECTOR_SIZE, SECTOR_SIZE); - - Creator->VolumeFile->Write (OutputBuffer.GetRange (0, OutputBufferWritePos)); - - Creator->WriteOffset += OutputBufferWritePos; - Creator->SizeDone.Set (Creator->WriteOffset - Creator->DataStart); - - OutputBufferWritePos = 0; - } - } - - VolumeCreator *Creator; - SecureBuffer OutputBuffer; - size_t OutputBufferWritePos; - }; - - WriteSectorCallback sectorWriter (this); - FatFormatter::Format (sectorWriter, filesystemSize, Options->FilesystemClusterSize); - sectorWriter.FlushOutputBuffer(); - } - - if (!Options->Quick) - { - // Empty sectors are encrypted with different key to randomize plaintext - Core->RandomizeEncryptionAlgorithmKey (Options->EA); - - SecureBuffer outputBuffer (File::GetOptimalWriteSize()); - uint64 dataFragmentLength = outputBuffer.Size(); - - while (!AbortRequested && WriteOffset < endOffset) - { - if (WriteOffset + dataFragmentLength > endOffset) - dataFragmentLength = endOffset - WriteOffset; - - outputBuffer.Zero(); - Options->EA->EncryptSectors (outputBuffer, WriteOffset / SECTOR_SIZE, dataFragmentLength / SECTOR_SIZE, SECTOR_SIZE); - VolumeFile->Write (outputBuffer, (size_t) dataFragmentLength); - - WriteOffset += dataFragmentLength; - SizeDone.Set (WriteOffset - DataStart); - } - } - - if (!AbortRequested) - { - SizeDone.Set (Options->Size); - - // Backup header - SecureBuffer backupHeader (Layout->GetHeaderSize()); - - SecureBuffer backupHeaderSalt (VolumeHeader::GetSaltSize()); - RandomNumberGenerator::GetData (backupHeaderSalt); - - Options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, backupHeaderSalt); - - Layout->GetHeader()->EncryptNew (backupHeader, backupHeaderSalt, HeaderKey, Options->VolumeHeaderKdf); - - if (Options->Quick || Options->Type == VolumeType::Hidden) - VolumeFile->SeekEnd (Layout->GetBackupHeaderOffset()); - - VolumeFile->Write (backupHeader); - - if (Options->Type == VolumeType::Normal) - { - // Write random data to space reserved for hidden volume backup header - Core->RandomizeEncryptionAlgorithmKey (Options->EA); - Options->EA->Encrypt (backupHeader); - - VolumeFile->Write (backupHeader); - } - - VolumeFile->Flush(); - } - } - catch (Exception &e) - { - ThreadException.reset (e.CloneNew()); - } - catch (exception &e) - { - ThreadException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e))); - } - catch (...) - { - ThreadException.reset (new UnknownException (SRC_POS)); - } - - VolumeFile.reset(); - mProgressInfo.CreationInProgress = false; - } - - void VolumeCreator::CreateVolume (shared_ptr options) - { - EncryptionTest::TestAll(); - - { -#ifdef TC_UNIX - // Temporarily take ownership of a device if the user is not an administrator - UserId origDeviceOwner ((uid_t) -1); - - if (!Core->HasAdminPrivileges() && options->Path.IsDevice()) - { - origDeviceOwner = FilesystemPath (wstring (options->Path)).GetOwner(); - Core->SetFileOwner (options->Path, UserId (getuid())); - } - - finally_do_arg2 (FilesystemPath, options->Path, UserId, origDeviceOwner, - { - if (finally_arg2.SystemId != (uid_t) -1) - Core->SetFileOwner (finally_arg, finally_arg2); - }); -#endif - - VolumeFile.reset (new File); - VolumeFile->Open (options->Path, - (options->Path.IsDevice() || options->Type == VolumeType::Hidden) ? File::OpenReadWrite : File::CreateReadWrite, - File::ShareNone); - - HostSize = VolumeFile->Length(); - } - - try - { - // Test sector size - if (options->Path.IsDevice() && VolumeFile->GetDeviceSectorSize() != SECTOR_SIZE) - throw UnsupportedSectorSize (SRC_POS); - - // Volume layout - switch (options->Type) - { - case VolumeType::Normal: - Layout.reset (new VolumeLayoutV2Normal()); - break; - - case VolumeType::Hidden: - Layout.reset (new VolumeLayoutV2Hidden()); - - if (HostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE) - throw ParameterIncorrect (SRC_POS); - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - - // Volume header - shared_ptr header (Layout->GetHeader()); - SecureBuffer headerBuffer (Layout->GetHeaderSize()); - - VolumeHeaderCreationOptions headerOptions; - headerOptions.EA = options->EA; - headerOptions.Kdf = options->VolumeHeaderKdf; - headerOptions.Type = options->Type; - - if (options->Type == VolumeType::Hidden) - headerOptions.VolumeDataStart = HostSize - Layout->GetHeaderSize() * 2 - options->Size; - else - headerOptions.VolumeDataStart = Layout->GetHeaderSize() * 2; - - headerOptions.VolumeDataSize = Layout->GetMaxDataSize (options->Size); - - if (headerOptions.VolumeDataSize < 1) - throw ParameterIncorrect (SRC_POS); - - // Master data key - MasterKey.Allocate (options->EA->GetKeySize() * 2); - RandomNumberGenerator::GetData (MasterKey); - headerOptions.DataKey = MasterKey; - - // PKCS5 salt - SecureBuffer salt (VolumeHeader::GetSaltSize()); - RandomNumberGenerator::GetData (salt); - headerOptions.Salt = salt; - - // Header key - HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize()); - PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password); - options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, salt); - headerOptions.HeaderKey = HeaderKey; - - header->Create (headerBuffer, headerOptions); - - // Write new header - if (Layout->GetHeaderOffset() >= 0) - VolumeFile->SeekAt (Layout->GetHeaderOffset()); - else - VolumeFile->SeekEnd (Layout->GetHeaderOffset()); - - VolumeFile->Write (headerBuffer); - - if (options->Type == VolumeType::Normal) - { - // Write random data to space reserved for hidden volume header - Core->RandomizeEncryptionAlgorithmKey (options->EA); - options->EA->Encrypt (headerBuffer); - - VolumeFile->Write (headerBuffer); - } - - // Data area keys - options->EA->SetKey (MasterKey.GetRange (0, options->EA->GetKeySize())); - shared_ptr mode (new EncryptionModeXTS ()); - mode->SetKey (MasterKey.GetRange (options->EA->GetKeySize(), options->EA->GetKeySize())); - options->EA->SetMode (mode); - - Options = options; - AbortRequested = false; - - mProgressInfo.CreationInProgress = true; - - struct ThreadFunctor : public Functor - { - ThreadFunctor (VolumeCreator *creator) : Creator (creator) { } - virtual void operator() () - { - Creator->CreationThread (); - } - VolumeCreator *Creator; - }; - - Thread thread; - thread.Start (new ThreadFunctor (this)); - } - catch (...) - { - VolumeFile.reset(); - throw; - } - } - - VolumeCreator::KeyInfo VolumeCreator::GetKeyInfo () const - { - KeyInfo info; - info.HeaderKey = HeaderKey; - info.MasterKey = MasterKey; - return info; - } - - VolumeCreator::ProgressInfo VolumeCreator::GetProgressInfo () - { - mProgressInfo.SizeDone = SizeDone.Get(); - return mProgressInfo; - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Volume/EncryptionTest.h" +#include "Volume/EncryptionModeXTS.h" +#include "Core.h" + +#ifdef TC_UNIX +#include +#include +#include +#endif + +#include "VolumeCreator.h" +#include "FatFormatter.h" + +namespace TrueCrypt +{ + VolumeCreator::VolumeCreator () + : SizeDone (0) + { + } + + VolumeCreator::~VolumeCreator () + { + } + + void VolumeCreator::Abort () + { + AbortRequested = true; + } + + void VolumeCreator::CheckResult () + { + if (ThreadException) + ThreadException->Throw(); + } + + void VolumeCreator::CreationThread () + { + try + { + uint64 endOffset; + uint64 filesystemSize = Layout->GetDataSize (HostSize); + + if (filesystemSize < 1) + throw ParameterIncorrect (SRC_POS); + + DataStart = Layout->GetDataOffset (HostSize); + WriteOffset = DataStart; + endOffset = DataStart + Layout->GetDataSize (HostSize); + + VolumeFile->SeekAt (DataStart); + + // Create filesystem + if (Options->Filesystem == VolumeCreationOptions::FilesystemType::FAT) + { + if (filesystemSize < TC_MIN_FAT_FS_SIZE || filesystemSize > TC_MAX_FAT_FS_SIZE) + throw ParameterIncorrect (SRC_POS); + + struct WriteSectorCallback : public FatFormatter::WriteSectorCallback + { + WriteSectorCallback (VolumeCreator *creator) : Creator (creator), OutputBuffer (File::GetOptimalWriteSize()), OutputBufferWritePos (0) { } + + virtual bool operator() (const BufferPtr §or) + { + OutputBuffer.GetRange (OutputBufferWritePos, sector.Size()).CopyFrom (sector); + OutputBufferWritePos += sector.Size(); + + if (OutputBufferWritePos >= OutputBuffer.Size()) + FlushOutputBuffer(); + + return !Creator->AbortRequested; + } + + void FlushOutputBuffer () + { + if (OutputBufferWritePos > 0) + { + Creator->Options->EA->EncryptSectors (OutputBuffer.GetRange (0, OutputBufferWritePos), + Creator->WriteOffset / SECTOR_SIZE, OutputBufferWritePos / SECTOR_SIZE, SECTOR_SIZE); + + Creator->VolumeFile->Write (OutputBuffer.GetRange (0, OutputBufferWritePos)); + + Creator->WriteOffset += OutputBufferWritePos; + Creator->SizeDone.Set (Creator->WriteOffset - Creator->DataStart); + + OutputBufferWritePos = 0; + } + } + + VolumeCreator *Creator; + SecureBuffer OutputBuffer; + size_t OutputBufferWritePos; + }; + + WriteSectorCallback sectorWriter (this); + FatFormatter::Format (sectorWriter, filesystemSize, Options->FilesystemClusterSize); + sectorWriter.FlushOutputBuffer(); + } + + if (!Options->Quick) + { + // Empty sectors are encrypted with different key to randomize plaintext + Core->RandomizeEncryptionAlgorithmKey (Options->EA); + + SecureBuffer outputBuffer (File::GetOptimalWriteSize()); + uint64 dataFragmentLength = outputBuffer.Size(); + + while (!AbortRequested && WriteOffset < endOffset) + { + if (WriteOffset + dataFragmentLength > endOffset) + dataFragmentLength = endOffset - WriteOffset; + + outputBuffer.Zero(); + Options->EA->EncryptSectors (outputBuffer, WriteOffset / SECTOR_SIZE, dataFragmentLength / SECTOR_SIZE, SECTOR_SIZE); + VolumeFile->Write (outputBuffer, (size_t) dataFragmentLength); + + WriteOffset += dataFragmentLength; + SizeDone.Set (WriteOffset - DataStart); + } + } + + if (!AbortRequested) + { + SizeDone.Set (Options->Size); + + // Backup header + SecureBuffer backupHeader (Layout->GetHeaderSize()); + + SecureBuffer backupHeaderSalt (VolumeHeader::GetSaltSize()); + RandomNumberGenerator::GetData (backupHeaderSalt); + + Options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, backupHeaderSalt); + + Layout->GetHeader()->EncryptNew (backupHeader, backupHeaderSalt, HeaderKey, Options->VolumeHeaderKdf); + + if (Options->Quick || Options->Type == VolumeType::Hidden) + VolumeFile->SeekEnd (Layout->GetBackupHeaderOffset()); + + VolumeFile->Write (backupHeader); + + if (Options->Type == VolumeType::Normal) + { + // Write random data to space reserved for hidden volume backup header + Core->RandomizeEncryptionAlgorithmKey (Options->EA); + Options->EA->Encrypt (backupHeader); + + VolumeFile->Write (backupHeader); + } + + VolumeFile->Flush(); + } + } + catch (Exception &e) + { + ThreadException.reset (e.CloneNew()); + } + catch (exception &e) + { + ThreadException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e))); + } + catch (...) + { + ThreadException.reset (new UnknownException (SRC_POS)); + } + + VolumeFile.reset(); + mProgressInfo.CreationInProgress = false; + } + + void VolumeCreator::CreateVolume (shared_ptr options) + { + EncryptionTest::TestAll(); + + { +#ifdef TC_UNIX + // Temporarily take ownership of a device if the user is not an administrator + UserId origDeviceOwner ((uid_t) -1); + + if (!Core->HasAdminPrivileges() && options->Path.IsDevice()) + { + origDeviceOwner = FilesystemPath (wstring (options->Path)).GetOwner(); + Core->SetFileOwner (options->Path, UserId (getuid())); + } + + finally_do_arg2 (FilesystemPath, options->Path, UserId, origDeviceOwner, + { + if (finally_arg2.SystemId != (uid_t) -1) + Core->SetFileOwner (finally_arg, finally_arg2); + }); +#endif + + VolumeFile.reset (new File); + VolumeFile->Open (options->Path, + (options->Path.IsDevice() || options->Type == VolumeType::Hidden) ? File::OpenReadWrite : File::CreateReadWrite, + File::ShareNone); + + HostSize = VolumeFile->Length(); + } + + try + { + // Test sector size + if (options->Path.IsDevice() && VolumeFile->GetDeviceSectorSize() != SECTOR_SIZE) + throw UnsupportedSectorSize (SRC_POS); + + // Volume layout + switch (options->Type) + { + case VolumeType::Normal: + Layout.reset (new VolumeLayoutV2Normal()); + break; + + case VolumeType::Hidden: + Layout.reset (new VolumeLayoutV2Hidden()); + + if (HostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE) + throw ParameterIncorrect (SRC_POS); + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + + // Volume header + shared_ptr header (Layout->GetHeader()); + SecureBuffer headerBuffer (Layout->GetHeaderSize()); + + VolumeHeaderCreationOptions headerOptions; + headerOptions.EA = options->EA; + headerOptions.Kdf = options->VolumeHeaderKdf; + headerOptions.Type = options->Type; + + if (options->Type == VolumeType::Hidden) + headerOptions.VolumeDataStart = HostSize - Layout->GetHeaderSize() * 2 - options->Size; + else + headerOptions.VolumeDataStart = Layout->GetHeaderSize() * 2; + + headerOptions.VolumeDataSize = Layout->GetMaxDataSize (options->Size); + + if (headerOptions.VolumeDataSize < 1) + throw ParameterIncorrect (SRC_POS); + + // Master data key + MasterKey.Allocate (options->EA->GetKeySize() * 2); + RandomNumberGenerator::GetData (MasterKey); + headerOptions.DataKey = MasterKey; + + // PKCS5 salt + SecureBuffer salt (VolumeHeader::GetSaltSize()); + RandomNumberGenerator::GetData (salt); + headerOptions.Salt = salt; + + // Header key + HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize()); + PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password); + options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, salt); + headerOptions.HeaderKey = HeaderKey; + + header->Create (headerBuffer, headerOptions); + + // Write new header + if (Layout->GetHeaderOffset() >= 0) + VolumeFile->SeekAt (Layout->GetHeaderOffset()); + else + VolumeFile->SeekEnd (Layout->GetHeaderOffset()); + + VolumeFile->Write (headerBuffer); + + if (options->Type == VolumeType::Normal) + { + // Write random data to space reserved for hidden volume header + Core->RandomizeEncryptionAlgorithmKey (options->EA); + options->EA->Encrypt (headerBuffer); + + VolumeFile->Write (headerBuffer); + } + + // Data area keys + options->EA->SetKey (MasterKey.GetRange (0, options->EA->GetKeySize())); + shared_ptr mode (new EncryptionModeXTS ()); + mode->SetKey (MasterKey.GetRange (options->EA->GetKeySize(), options->EA->GetKeySize())); + options->EA->SetMode (mode); + + Options = options; + AbortRequested = false; + + mProgressInfo.CreationInProgress = true; + + struct ThreadFunctor : public Functor + { + ThreadFunctor (VolumeCreator *creator) : Creator (creator) { } + virtual void operator() () + { + Creator->CreationThread (); + } + VolumeCreator *Creator; + }; + + Thread thread; + thread.Start (new ThreadFunctor (this)); + } + catch (...) + { + VolumeFile.reset(); + throw; + } + } + + VolumeCreator::KeyInfo VolumeCreator::GetKeyInfo () const + { + KeyInfo info; + info.HeaderKey = HeaderKey; + info.MasterKey = MasterKey; + return info; + } + + VolumeCreator::ProgressInfo VolumeCreator::GetProgressInfo () + { + mProgressInfo.SizeDone = SizeDone.Get(); + return mProgressInfo; + } +} diff --git a/Core/VolumeCreator.h b/Core/VolumeCreator.h index a756a1d..070803b 100644 --- a/Core/VolumeCreator.h +++ b/Core/VolumeCreator.h @@ -1,117 +1,117 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_VolumeCreator -#define TC_HEADER_Volume_VolumeCreator - -#include "Platform/Platform.h" -#include "Volume/Volume.h" -#include "RandomNumberGenerator.h" - -namespace TrueCrypt -{ - - struct VolumeCreationOptions - { - VolumePath Path; - VolumeType::Enum Type; - uint64 Size; - shared_ptr Password; - shared_ptr Keyfiles; - shared_ptr VolumeHeaderKdf; - shared_ptr EA; - bool Quick; - - struct FilesystemType - { - enum Enum - { - Unknown = 0, - None, - FAT, - NTFS, - Ext2, - Ext3, - MacOsExt, - UFS - }; - - static Enum GetPlatformNative () - { -#ifdef TC_WINDOWS - return VolumeCreationOptions::FilesystemType::NTFS; -#elif defined (TC_LINUX) - return VolumeCreationOptions::FilesystemType::Ext3; -#elif defined (TC_MACOSX) - return VolumeCreationOptions::FilesystemType::MacOsExt; -#elif defined (TC_FREEBSD) || defined (TC_SOLARIS) - return VolumeCreationOptions::FilesystemType::UFS; -#else - return VolumeCreationOptions::FilesystemType::FAT; -#endif - } - }; - - FilesystemType::Enum Filesystem; - uint32 FilesystemClusterSize; - }; - - class VolumeCreator - { - public: - - struct ProgressInfo - { - bool CreationInProgress; - uint64 TotalSize; - uint64 SizeDone; - }; - - struct KeyInfo - { - ConstBufferPtr HeaderKey; - ConstBufferPtr MasterKey; - }; - - VolumeCreator (); - virtual ~VolumeCreator (); - - void Abort (); - void CheckResult (); - void CreateVolume (shared_ptr options); - KeyInfo GetKeyInfo () const; - ProgressInfo GetProgressInfo (); - - protected: - void CreationThread (); - - volatile bool AbortRequested; - volatile bool CreationInProgress; - uint64 DataStart; - uint64 HostSize; - shared_ptr Options; - shared_ptr ThreadException; - uint64 VolumeSize; - - shared_ptr Layout; - shared_ptr VolumeFile; - SharedVal SizeDone; - uint64 WriteOffset; - ProgressInfo mProgressInfo; - - SecureBuffer HeaderKey; - shared_ptr PasswordKey; - SecureBuffer MasterKey; - - private: - VolumeCreator (const VolumeCreator &); - VolumeCreator &operator= (const VolumeCreator &); - }; -} - -#endif // TC_HEADER_Volume_VolumeCreator +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_VolumeCreator +#define TC_HEADER_Volume_VolumeCreator + +#include "Platform/Platform.h" +#include "Volume/Volume.h" +#include "RandomNumberGenerator.h" + +namespace TrueCrypt +{ + + struct VolumeCreationOptions + { + VolumePath Path; + VolumeType::Enum Type; + uint64 Size; + shared_ptr Password; + shared_ptr Keyfiles; + shared_ptr VolumeHeaderKdf; + shared_ptr EA; + bool Quick; + + struct FilesystemType + { + enum Enum + { + Unknown = 0, + None, + FAT, + NTFS, + Ext2, + Ext3, + MacOsExt, + UFS + }; + + static Enum GetPlatformNative () + { +#ifdef TC_WINDOWS + return VolumeCreationOptions::FilesystemType::NTFS; +#elif defined (TC_LINUX) + return VolumeCreationOptions::FilesystemType::Ext3; +#elif defined (TC_MACOSX) + return VolumeCreationOptions::FilesystemType::MacOsExt; +#elif defined (TC_FREEBSD) || defined (TC_SOLARIS) + return VolumeCreationOptions::FilesystemType::UFS; +#else + return VolumeCreationOptions::FilesystemType::FAT; +#endif + } + }; + + FilesystemType::Enum Filesystem; + uint32 FilesystemClusterSize; + }; + + class VolumeCreator + { + public: + + struct ProgressInfo + { + bool CreationInProgress; + uint64 TotalSize; + uint64 SizeDone; + }; + + struct KeyInfo + { + ConstBufferPtr HeaderKey; + ConstBufferPtr MasterKey; + }; + + VolumeCreator (); + virtual ~VolumeCreator (); + + void Abort (); + void CheckResult (); + void CreateVolume (shared_ptr options); + KeyInfo GetKeyInfo () const; + ProgressInfo GetProgressInfo (); + + protected: + void CreationThread (); + + volatile bool AbortRequested; + volatile bool CreationInProgress; + uint64 DataStart; + uint64 HostSize; + shared_ptr Options; + shared_ptr ThreadException; + uint64 VolumeSize; + + shared_ptr Layout; + shared_ptr VolumeFile; + SharedVal SizeDone; + uint64 WriteOffset; + ProgressInfo mProgressInfo; + + SecureBuffer HeaderKey; + shared_ptr PasswordKey; + SecureBuffer MasterKey; + + private: + VolumeCreator (const VolumeCreator &); + VolumeCreator &operator= (const VolumeCreator &); + }; +} + +#endif // TC_HEADER_Volume_VolumeCreator diff --git a/Crypto/Aes.h b/Crypto/Aes.h index a717f0b..6a63d6f 100644 --- a/Crypto/Aes.h +++ b/Crypto/Aes.h @@ -1,215 +1,215 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 20/12/2007 - - This file contains the definitions required to use AES in C. See aesopt.h - for optimisation details. -*/ - -/* Adapted by the TrueCrypt Foundation */ - -#ifndef _AES_H -#define _AES_H - -#include "Common/Tcdefs.h" - -#ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 -#define EXIT_FAILURE 1 -#endif -#define INT_RETURN int - -#if defined(__cplusplus) -extern "C" -{ -#endif - -// #define AES_128 /* define if AES with 128 bit keys is needed */ -// #define AES_192 /* define if AES with 192 bit keys is needed */ -#define AES_256 /* define if AES with 256 bit keys is needed */ -// #define AES_VAR /* define if a variable key size is needed */ -// #define AES_MODES /* define if support is needed for modes */ - -/* The following must also be set in assembler files if being used */ - -#define AES_ENCRYPT /* if support for encryption is needed */ -#define AES_DECRYPT /* if support for decryption is needed */ -#define AES_ERR_CHK /* for parameter checks & error return codes */ -#define AES_REV_DKS /* define to reverse decryption key schedule */ - -#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ -#define N_COLS 4 /* the number of columns in the state */ - -/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ -/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ -/* or 44, 52 or 60 32-bit words. */ - -#if defined( AES_VAR ) || defined( AES_256 ) -#define KS_LENGTH 60 -#elif defined( AES_192 ) -#define KS_LENGTH 52 -#else -#define KS_LENGTH 44 -#endif - -#if defined( AES_ERR_CHK ) -#define AES_RETURN INT_RETURN -#else -#define AES_RETURN VOID_RETURN -#endif - -/* the character array 'inf' in the following structures is used */ -/* to hold AES context information. This AES code uses cx->inf.b[0] */ -/* to hold the number of rounds multiplied by 16. The other three */ -/* elements can be used by code that implements additional modes */ - -typedef union -{ uint_32t l; - uint_8t b[4]; -} aes_inf; - -typedef struct -{ uint_32t ks[KS_LENGTH]; - aes_inf inf; -} aes_encrypt_ctx; - -typedef struct -{ uint_32t ks[KS_LENGTH]; - aes_inf inf; -} aes_decrypt_ctx; - -/* This routine must be called before first use if non-static */ -/* tables are being used */ - -AES_RETURN aes_init(void); - -/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ -/* those in the range 128 <= key_len <= 256 are given in bits */ - -#if defined( AES_ENCRYPT ) - -#if defined(AES_128) || defined(AES_VAR) -AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); -#endif - -#if defined(AES_192) || defined(AES_VAR) -AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); -#endif - -#if defined(AES_256) || defined(AES_VAR) -AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); -#endif - -#if defined(AES_VAR) -AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); -#endif - -AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); - -#endif - -#if defined( AES_DECRYPT ) - -#if defined(AES_128) || defined(AES_VAR) -AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); -#endif - -#if defined(AES_192) || defined(AES_VAR) -AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); -#endif - -#if defined(AES_256) || defined(AES_VAR) -AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); -#endif - -#if defined(AES_VAR) -AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); -#endif - -AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); - -#endif - -#if defined(AES_MODES) - -/* Multiple calls to the following subroutines for multiple block */ -/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ -/* long messages incremantally provided that the context AND the iv */ -/* are preserved between all such calls. For the ECB and CBC modes */ -/* each individual call within a series of incremental calls must */ -/* process only full blocks (i.e. len must be a multiple of 16) but */ -/* the CFB, OFB and CTR mode calls can handle multiple incremental */ -/* calls of any length. Each mode is reset when a new AES key is */ -/* set but ECB and CBC operations can be reset without setting a */ -/* new key by setting a new IV value. To reset CFB, OFB and CTR */ -/* without setting the key, aes_mode_reset() must be called and the */ -/* IV must be set. NOTE: All these calls update the IV on exit so */ -/* this has to be reset if a new operation with the same IV as the */ -/* previous one is required (or decryption follows encryption with */ -/* the same IV array). */ - -AES_RETURN aes_test_alignment_detection(unsigned int n); - -AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, const aes_encrypt_ctx cx[1]); - -AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, const aes_decrypt_ctx cx[1]); - -AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); - -AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); - -AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); - -AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx cx[1]); - -AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx cx[1]); - -#define aes_ofb_encrypt aes_ofb_crypt -#define aes_ofb_decrypt aes_ofb_crypt - -AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx cx[1]); - -typedef void cbuf_inc(unsigned char *cbuf); - -#define aes_ctr_encrypt aes_ctr_crypt -#define aes_ctr_decrypt aes_ctr_crypt - -AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); - -#endif - -#if defined(__cplusplus) -} -#endif - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + + This file contains the definitions required to use AES in C. See aesopt.h + for optimisation details. +*/ + +/* Adapted by the TrueCrypt Foundation */ + +#ifndef _AES_H +#define _AES_H + +#include "Common/Tcdefs.h" + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#endif +#define INT_RETURN int + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// #define AES_128 /* define if AES with 128 bit keys is needed */ +// #define AES_192 /* define if AES with 192 bit keys is needed */ +#define AES_256 /* define if AES with 256 bit keys is needed */ +// #define AES_VAR /* define if a variable key size is needed */ +// #define AES_MODES /* define if support is needed for modes */ + +/* The following must also be set in assembler files if being used */ + +#define AES_ENCRYPT /* if support for encryption is needed */ +#define AES_DECRYPT /* if support for decryption is needed */ +#define AES_ERR_CHK /* for parameter checks & error return codes */ +#define AES_REV_DKS /* define to reverse decryption key schedule */ + +#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ +#define N_COLS 4 /* the number of columns in the state */ + +/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ +/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ +/* or 44, 52 or 60 32-bit words. */ + +#if defined( AES_VAR ) || defined( AES_256 ) +#define KS_LENGTH 60 +#elif defined( AES_192 ) +#define KS_LENGTH 52 +#else +#define KS_LENGTH 44 +#endif + +#if defined( AES_ERR_CHK ) +#define AES_RETURN INT_RETURN +#else +#define AES_RETURN VOID_RETURN +#endif + +/* the character array 'inf' in the following structures is used */ +/* to hold AES context information. This AES code uses cx->inf.b[0] */ +/* to hold the number of rounds multiplied by 16. The other three */ +/* elements can be used by code that implements additional modes */ + +typedef union +{ uint_32t l; + uint_8t b[4]; +} aes_inf; + +typedef struct +{ uint_32t ks[KS_LENGTH]; + aes_inf inf; +} aes_encrypt_ctx; + +typedef struct +{ uint_32t ks[KS_LENGTH]; + aes_inf inf; +} aes_decrypt_ctx; + +/* This routine must be called before first use if non-static */ +/* tables are being used */ + +AES_RETURN aes_init(void); + +/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ +/* those in the range 128 <= key_len <= 256 are given in bits */ + +#if defined( AES_ENCRYPT ) + +#if defined(AES_128) || defined(AES_VAR) +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined(AES_192) || defined(AES_VAR) +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined(AES_256) || defined(AES_VAR) +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined(AES_VAR) +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); +#endif + +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); + +#endif + +#if defined( AES_DECRYPT ) + +#if defined(AES_128) || defined(AES_VAR) +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined(AES_192) || defined(AES_VAR) +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined(AES_256) || defined(AES_VAR) +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined(AES_VAR) +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); +#endif + +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); + +#endif + +#if defined(AES_MODES) + +/* Multiple calls to the following subroutines for multiple block */ +/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ +/* long messages incremantally provided that the context AND the iv */ +/* are preserved between all such calls. For the ECB and CBC modes */ +/* each individual call within a series of incremental calls must */ +/* process only full blocks (i.e. len must be a multiple of 16) but */ +/* the CFB, OFB and CTR mode calls can handle multiple incremental */ +/* calls of any length. Each mode is reset when a new AES key is */ +/* set but ECB and CBC operations can be reset without setting a */ +/* new key by setting a new IV value. To reset CFB, OFB and CTR */ +/* without setting the key, aes_mode_reset() must be called and the */ +/* IV must be set. NOTE: All these calls update the IV on exit so */ +/* this has to be reset if a new operation with the same IV as the */ +/* previous one is required (or decryption follows encryption with */ +/* the same IV array). */ + +AES_RETURN aes_test_alignment_detection(unsigned int n); + +AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +#define aes_ofb_encrypt aes_ofb_crypt +#define aes_ofb_decrypt aes_ofb_crypt + +AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +typedef void cbuf_inc(unsigned char *cbuf); + +#define aes_ctr_encrypt aes_ctr_crypt +#define aes_ctr_decrypt aes_ctr_crypt + +AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Crypto/AesSmall.c b/Crypto/AesSmall.c index 696f357..edd98a9 100644 --- a/Crypto/AesSmall.c +++ b/Crypto/AesSmall.c @@ -1,953 +1,953 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue 09/09/2006 - - This is an AES implementation that uses only 8-bit byte operations on the - cipher state (there are options to use 32-bit types if available). - - The combination of mix columns and byte substitution used here is based on - that developed by Karl Malbrain. His contribution is acknowledged. - */ - -/* Adapted by TrueCrypt Foundation: - - Macro-generated tables were replaced with static data to enable compiling - with MSVC++ 1.5 which runs out of resources when expanding large macros. -*/ - -#pragma optimize ("t", on) - -/* define if you have a fast memcpy function on your system */ -#if 1 -# define HAVE_MEMCPY -# include -# if defined( _MSC_VER ) -# ifndef DEBUG -# pragma intrinsic( memcpy ) -# endif -# endif -#endif - -/* define if you have fast 32-bit types on your system */ -#if 1 -# define HAVE_UINT_32T -#endif - -/* alternative versions (test for performance on your system) */ -#if 0 -# define VERSION_1 -#endif - -#include "AesSmall.h" - -#define WPOLY 0x011b -#define DPOLY 0x008d -#define f1(x) (x) -#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) -#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) -#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ - ^ (((x>>5) & 4) * WPOLY)) -#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) - -#define f3(x) (f2(x) ^ x) -#define f9(x) (f8(x) ^ x) -#define fb(x) (f8(x) ^ f2(x) ^ x) -#define fd(x) (f8(x) ^ f4(x) ^ x) -#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) - -static const uint_8t s_box[256] = { - 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, - 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, - 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, - 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, - 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, - 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, - 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, - 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, - 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, - 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, - 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, - 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, - 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, - 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, - 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, - 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, - 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, - 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, - 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, - 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, - 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, - 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, - 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, - 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, - 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, - 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, - 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, - 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, - 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, - 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, - 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, - 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 -}; - -static const uint_8t inv_s_box[256] = { - 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38, - 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, - 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87, - 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, - 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d, - 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, - 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2, - 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, - 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16, - 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, - 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda, - 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, - 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a, - 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, - 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02, - 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, - 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea, - 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, - 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85, - 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, - 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89, - 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, - 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20, - 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, - 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31, - 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, - 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d, - 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, - 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0, - 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, - 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26, - 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d -}; - -static const uint_8t gfm2_s_box[256] = { - 0xc6,0xf8,0xee,0xf6,0xff,0xd6,0xde,0x91, - 0x60,0x02,0xce,0x56,0xe7,0xb5,0x4d,0xec, - 0x8f,0x1f,0x89,0xfa,0xef,0xb2,0x8e,0xfb, - 0x41,0xb3,0x5f,0x45,0x23,0x53,0xe4,0x9b, - 0x75,0xe1,0x3d,0x4c,0x6c,0x7e,0xf5,0x83, - 0x68,0x51,0xd1,0xf9,0xe2,0xab,0x62,0x2a, - 0x08,0x95,0x46,0x9d,0x30,0x37,0x0a,0x2f, - 0x0e,0x24,0x1b,0xdf,0xcd,0x4e,0x7f,0xea, - 0x12,0x1d,0x58,0x34,0x36,0xdc,0xb4,0x5b, - 0xa4,0x76,0xb7,0x7d,0x52,0xdd,0x5e,0x13, - 0xa6,0xb9,0x00,0xc1,0x40,0xe3,0x79,0xb6, - 0xd4,0x8d,0x67,0x72,0x94,0x98,0xb0,0x85, - 0xbb,0xc5,0x4f,0xed,0x86,0x9a,0x66,0x11, - 0x8a,0xe9,0x04,0xfe,0xa0,0x78,0x25,0x4b, - 0xa2,0x5d,0x80,0x05,0x3f,0x21,0x70,0xf1, - 0x63,0x77,0xaf,0x42,0x20,0xe5,0xfd,0xbf, - 0x81,0x18,0x26,0xc3,0xbe,0x35,0x88,0x2e, - 0x93,0x55,0xfc,0x7a,0xc8,0xba,0x32,0xe6, - 0xc0,0x19,0x9e,0xa3,0x44,0x54,0x3b,0x0b, - 0x8c,0xc7,0x6b,0x28,0xa7,0xbc,0x16,0xad, - 0xdb,0x64,0x74,0x14,0x92,0x0c,0x48,0xb8, - 0x9f,0xbd,0x43,0xc4,0x39,0x31,0xd3,0xf2, - 0xd5,0x8b,0x6e,0xda,0x01,0xb1,0x9c,0x49, - 0xd8,0xac,0xf3,0xcf,0xca,0xf4,0x47,0x10, - 0x6f,0xf0,0x4a,0x5c,0x38,0x57,0x73,0x97, - 0xcb,0xa1,0xe8,0x3e,0x96,0x61,0x0d,0x0f, - 0xe0,0x7c,0x71,0xcc,0x90,0x06,0xf7,0x1c, - 0xc2,0x6a,0xae,0x69,0x17,0x99,0x3a,0x27, - 0xd9,0xeb,0x2b,0x22,0xd2,0xa9,0x07,0x33, - 0x2d,0x3c,0x15,0xc9,0x87,0xaa,0x50,0xa5, - 0x03,0x59,0x09,0x1a,0x65,0xd7,0x84,0xd0, - 0x82,0x29,0x5a,0x1e,0x7b,0xa8,0x6d,0x2c -}; - -static const uint_8t gfm3_s_box[256] = { - 0xa5,0x84,0x99,0x8d,0x0d,0xbd,0xb1,0x54, - 0x50,0x03,0xa9,0x7d,0x19,0x62,0xe6,0x9a, - 0x45,0x9d,0x40,0x87,0x15,0xeb,0xc9,0x0b, - 0xec,0x67,0xfd,0xea,0xbf,0xf7,0x96,0x5b, - 0xc2,0x1c,0xae,0x6a,0x5a,0x41,0x02,0x4f, - 0x5c,0xf4,0x34,0x08,0x93,0x73,0x53,0x3f, - 0x0c,0x52,0x65,0x5e,0x28,0xa1,0x0f,0xb5, - 0x09,0x36,0x9b,0x3d,0x26,0x69,0xcd,0x9f, - 0x1b,0x9e,0x74,0x2e,0x2d,0xb2,0xee,0xfb, - 0xf6,0x4d,0x61,0xce,0x7b,0x3e,0x71,0x97, - 0xf5,0x68,0x00,0x2c,0x60,0x1f,0xc8,0xed, - 0xbe,0x46,0xd9,0x4b,0xde,0xd4,0xe8,0x4a, - 0x6b,0x2a,0xe5,0x16,0xc5,0xd7,0x55,0x94, - 0xcf,0x10,0x06,0x81,0xf0,0x44,0xba,0xe3, - 0xf3,0xfe,0xc0,0x8a,0xad,0xbc,0x48,0x04, - 0xdf,0xc1,0x75,0x63,0x30,0x1a,0x0e,0x6d, - 0x4c,0x14,0x35,0x2f,0xe1,0xa2,0xcc,0x39, - 0x57,0xf2,0x82,0x47,0xac,0xe7,0x2b,0x95, - 0xa0,0x98,0xd1,0x7f,0x66,0x7e,0xab,0x83, - 0xca,0x29,0xd3,0x3c,0x79,0xe2,0x1d,0x76, - 0x3b,0x56,0x4e,0x1e,0xdb,0x0a,0x6c,0xe4, - 0x5d,0x6e,0xef,0xa6,0xa8,0xa4,0x37,0x8b, - 0x32,0x43,0x59,0xb7,0x8c,0x64,0xd2,0xe0, - 0xb4,0xfa,0x07,0x25,0xaf,0x8e,0xe9,0x18, - 0xd5,0x88,0x6f,0x72,0x24,0xf1,0xc7,0x51, - 0x23,0x7c,0x9c,0x21,0xdd,0xdc,0x86,0x85, - 0x90,0x42,0xc4,0xaa,0xd8,0x05,0x01,0x12, - 0xa3,0x5f,0xf9,0xd0,0x91,0x58,0x27,0xb9, - 0x38,0x13,0xb3,0x33,0xbb,0x70,0x89,0xa7, - 0xb6,0x22,0x92,0x20,0x49,0xff,0x78,0x7a, - 0x8f,0xf8,0x80,0x17,0xda,0x31,0xc6,0xb8, - 0xc3,0xb0,0x77,0x11,0xcb,0xfc,0xd6,0x3a -}; - -static const uint_8t gfmul_9[256] = { - 0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f, - 0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77, - 0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf, - 0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7, - 0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04, - 0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c, - 0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94, - 0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc, - 0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49, - 0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01, - 0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9, - 0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91, - 0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72, - 0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a, - 0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2, - 0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa, - 0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3, - 0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b, - 0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43, - 0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b, - 0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8, - 0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0, - 0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78, - 0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30, - 0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5, - 0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed, - 0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35, - 0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d, - 0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e, - 0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6, - 0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e, - 0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46 -}; - -static const uint_8t gfmul_b[256] = { - 0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31, - 0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69, - 0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81, - 0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9, - 0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a, - 0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12, - 0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa, - 0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2, - 0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7, - 0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f, - 0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77, - 0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f, - 0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc, - 0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4, - 0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c, - 0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54, - 0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6, - 0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e, - 0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76, - 0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e, - 0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd, - 0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5, - 0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d, - 0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55, - 0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30, - 0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68, - 0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80, - 0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8, - 0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b, - 0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13, - 0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb, - 0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3 -}; - -static const uint_8t gfmul_d[256] = { - 0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23, - 0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b, - 0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3, - 0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b, - 0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98, - 0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0, - 0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48, - 0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20, - 0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e, - 0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26, - 0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e, - 0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6, - 0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5, - 0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d, - 0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25, - 0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d, - 0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9, - 0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91, - 0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29, - 0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41, - 0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42, - 0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a, - 0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92, - 0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa, - 0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94, - 0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc, - 0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44, - 0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c, - 0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f, - 0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47, - 0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff, - 0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97 -}; - -static const uint_8t gfmul_e[256] = { - 0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a, - 0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a, - 0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca, - 0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba, - 0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1, - 0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81, - 0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11, - 0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61, - 0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87, - 0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7, - 0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67, - 0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17, - 0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c, - 0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c, - 0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc, - 0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc, - 0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b, - 0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b, - 0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b, - 0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb, - 0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0, - 0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0, - 0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50, - 0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20, - 0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6, - 0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6, - 0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26, - 0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56, - 0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d, - 0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d, - 0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd, - 0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d -}; - -#if defined( HAVE_UINT_32T ) - typedef unsigned long uint_32t; -#endif - -#if defined( HAVE_MEMCPY ) -# define block_copy(d, s, l) memcpy(d, s, l) -# define block16_copy(d, s) memcpy(d, s, N_BLOCK) -#else -# define block_copy(d, s, l) copy_block(d, s, l) -# define block16_copy(d, s) copy_block16(d, s) -#endif - -/* block size 'nn' must be a multiple of four */ - -static void copy_block16( void *d, const void *s ) -{ -#if defined( HAVE_UINT_32T ) - ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0]; - ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1]; - ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2]; - ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3]; -#else - ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0]; - ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1]; - ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2]; - ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3]; - ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4]; - ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5]; - ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6]; - ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7]; - ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8]; - ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9]; - ((uint_8t*)d)[10] = ((uint_8t*)s)[10]; - ((uint_8t*)d)[11] = ((uint_8t*)s)[11]; - ((uint_8t*)d)[12] = ((uint_8t*)s)[12]; - ((uint_8t*)d)[13] = ((uint_8t*)s)[13]; - ((uint_8t*)d)[14] = ((uint_8t*)s)[14]; - ((uint_8t*)d)[15] = ((uint_8t*)s)[15]; -#endif -} - -static void copy_block( void * d, void *s, uint_8t nn ) -{ - while( nn-- ) - *((uint_8t*)d)++ = *((uint_8t*)s)++; -} - -static void xor_block( void *d, const void *s ) -{ -#if defined( HAVE_UINT_32T ) - ((uint_32t*)d)[ 0] ^= ((uint_32t*)s)[ 0]; - ((uint_32t*)d)[ 1] ^= ((uint_32t*)s)[ 1]; - ((uint_32t*)d)[ 2] ^= ((uint_32t*)s)[ 2]; - ((uint_32t*)d)[ 3] ^= ((uint_32t*)s)[ 3]; -#else - ((uint_8t*)d)[ 0] ^= ((uint_8t*)s)[ 0]; - ((uint_8t*)d)[ 1] ^= ((uint_8t*)s)[ 1]; - ((uint_8t*)d)[ 2] ^= ((uint_8t*)s)[ 2]; - ((uint_8t*)d)[ 3] ^= ((uint_8t*)s)[ 3]; - ((uint_8t*)d)[ 4] ^= ((uint_8t*)s)[ 4]; - ((uint_8t*)d)[ 5] ^= ((uint_8t*)s)[ 5]; - ((uint_8t*)d)[ 6] ^= ((uint_8t*)s)[ 6]; - ((uint_8t*)d)[ 7] ^= ((uint_8t*)s)[ 7]; - ((uint_8t*)d)[ 8] ^= ((uint_8t*)s)[ 8]; - ((uint_8t*)d)[ 9] ^= ((uint_8t*)s)[ 9]; - ((uint_8t*)d)[10] ^= ((uint_8t*)s)[10]; - ((uint_8t*)d)[11] ^= ((uint_8t*)s)[11]; - ((uint_8t*)d)[12] ^= ((uint_8t*)s)[12]; - ((uint_8t*)d)[13] ^= ((uint_8t*)s)[13]; - ((uint_8t*)d)[14] ^= ((uint_8t*)s)[14]; - ((uint_8t*)d)[15] ^= ((uint_8t*)s)[15]; -#endif -} - -static void copy_and_key( void *d, const void *s, const void *k ) -{ -#if defined( HAVE_UINT_32T ) - ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0] ^ ((uint_32t*)k)[ 0]; - ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1] ^ ((uint_32t*)k)[ 1]; - ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2] ^ ((uint_32t*)k)[ 2]; - ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3] ^ ((uint_32t*)k)[ 3]; -#elif 1 - ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0] ^ ((uint_8t*)k)[ 0]; - ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1] ^ ((uint_8t*)k)[ 1]; - ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2] ^ ((uint_8t*)k)[ 2]; - ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3] ^ ((uint_8t*)k)[ 3]; - ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4] ^ ((uint_8t*)k)[ 4]; - ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5] ^ ((uint_8t*)k)[ 5]; - ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6] ^ ((uint_8t*)k)[ 6]; - ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7] ^ ((uint_8t*)k)[ 7]; - ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8] ^ ((uint_8t*)k)[ 8]; - ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9] ^ ((uint_8t*)k)[ 9]; - ((uint_8t*)d)[10] = ((uint_8t*)s)[10] ^ ((uint_8t*)k)[10]; - ((uint_8t*)d)[11] = ((uint_8t*)s)[11] ^ ((uint_8t*)k)[11]; - ((uint_8t*)d)[12] = ((uint_8t*)s)[12] ^ ((uint_8t*)k)[12]; - ((uint_8t*)d)[13] = ((uint_8t*)s)[13] ^ ((uint_8t*)k)[13]; - ((uint_8t*)d)[14] = ((uint_8t*)s)[14] ^ ((uint_8t*)k)[14]; - ((uint_8t*)d)[15] = ((uint_8t*)s)[15] ^ ((uint_8t*)k)[15]; -#else - block16_copy(d, s); - xor_block(d, k); -#endif -} - -static void add_round_key( uint_8t d[N_BLOCK], const uint_8t k[N_BLOCK] ) -{ - xor_block(d, k); -} - -static void shift_sub_rows( uint_8t st[N_BLOCK] ) -{ uint_8t tt; - - st[ 0] = s_box[st[ 0]]; st[ 4] = s_box[st[ 4]]; - st[ 8] = s_box[st[ 8]]; st[12] = s_box[st[12]]; - - tt = st[1]; st[ 1] = s_box[st[ 5]]; st[ 5] = s_box[st[ 9]]; - st[ 9] = s_box[st[13]]; st[13] = s_box[ tt ]; - - tt = st[2]; st[ 2] = s_box[st[10]]; st[10] = s_box[ tt ]; - tt = st[6]; st[ 6] = s_box[st[14]]; st[14] = s_box[ tt ]; - - tt = st[15]; st[15] = s_box[st[11]]; st[11] = s_box[st[ 7]]; - st[ 7] = s_box[st[ 3]]; st[ 3] = s_box[ tt ]; -} - -static void inv_shift_sub_rows( uint_8t st[N_BLOCK] ) -{ uint_8t tt; - - st[ 0] = inv_s_box[st[ 0]]; st[ 4] = inv_s_box[st[ 4]]; - st[ 8] = inv_s_box[st[ 8]]; st[12] = inv_s_box[st[12]]; - - tt = st[13]; st[13] = inv_s_box[st[9]]; st[ 9] = inv_s_box[st[5]]; - st[ 5] = inv_s_box[st[1]]; st[ 1] = inv_s_box[ tt ]; - - tt = st[2]; st[ 2] = inv_s_box[st[10]]; st[10] = inv_s_box[ tt ]; - tt = st[6]; st[ 6] = inv_s_box[st[14]]; st[14] = inv_s_box[ tt ]; - - tt = st[3]; st[ 3] = inv_s_box[st[ 7]]; st[ 7] = inv_s_box[st[11]]; - st[11] = inv_s_box[st[15]]; st[15] = inv_s_box[ tt ]; -} - -#if defined( VERSION_1 ) - static void mix_sub_columns( uint_8t dt[N_BLOCK] ) - { uint_8t st[N_BLOCK]; - block16_copy(st, dt); -#else - static void mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] ) - { -#endif - dt[ 0] = gfm2_s_box[st[0]] ^ gfm3_s_box[st[5]] ^ s_box[st[10]] ^ s_box[st[15]]; - dt[ 1] = s_box[st[0]] ^ gfm2_s_box[st[5]] ^ gfm3_s_box[st[10]] ^ s_box[st[15]]; - dt[ 2] = s_box[st[0]] ^ s_box[st[5]] ^ gfm2_s_box[st[10]] ^ gfm3_s_box[st[15]]; - dt[ 3] = gfm3_s_box[st[0]] ^ s_box[st[5]] ^ s_box[st[10]] ^ gfm2_s_box[st[15]]; - - dt[ 4] = gfm2_s_box[st[4]] ^ gfm3_s_box[st[9]] ^ s_box[st[14]] ^ s_box[st[3]]; - dt[ 5] = s_box[st[4]] ^ gfm2_s_box[st[9]] ^ gfm3_s_box[st[14]] ^ s_box[st[3]]; - dt[ 6] = s_box[st[4]] ^ s_box[st[9]] ^ gfm2_s_box[st[14]] ^ gfm3_s_box[st[3]]; - dt[ 7] = gfm3_s_box[st[4]] ^ s_box[st[9]] ^ s_box[st[14]] ^ gfm2_s_box[st[3]]; - - dt[ 8] = gfm2_s_box[st[8]] ^ gfm3_s_box[st[13]] ^ s_box[st[2]] ^ s_box[st[7]]; - dt[ 9] = s_box[st[8]] ^ gfm2_s_box[st[13]] ^ gfm3_s_box[st[2]] ^ s_box[st[7]]; - dt[10] = s_box[st[8]] ^ s_box[st[13]] ^ gfm2_s_box[st[2]] ^ gfm3_s_box[st[7]]; - dt[11] = gfm3_s_box[st[8]] ^ s_box[st[13]] ^ s_box[st[2]] ^ gfm2_s_box[st[7]]; - - dt[12] = gfm2_s_box[st[12]] ^ gfm3_s_box[st[1]] ^ s_box[st[6]] ^ s_box[st[11]]; - dt[13] = s_box[st[12]] ^ gfm2_s_box[st[1]] ^ gfm3_s_box[st[6]] ^ s_box[st[11]]; - dt[14] = s_box[st[12]] ^ s_box[st[1]] ^ gfm2_s_box[st[6]] ^ gfm3_s_box[st[11]]; - dt[15] = gfm3_s_box[st[12]] ^ s_box[st[1]] ^ s_box[st[6]] ^ gfm2_s_box[st[11]]; - } - -#if defined( VERSION_1 ) - static void inv_mix_sub_columns( uint_8t dt[N_BLOCK] ) - { uint_8t st[N_BLOCK]; - block16_copy(st, dt); -#else - static void inv_mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] ) - { -#endif - dt[ 0] = inv_s_box[gfmul_e[st[ 0]] ^ gfmul_b[st[ 1]] ^ gfmul_d[st[ 2]] ^ gfmul_9[st[ 3]]]; - dt[ 5] = inv_s_box[gfmul_9[st[ 0]] ^ gfmul_e[st[ 1]] ^ gfmul_b[st[ 2]] ^ gfmul_d[st[ 3]]]; - dt[10] = inv_s_box[gfmul_d[st[ 0]] ^ gfmul_9[st[ 1]] ^ gfmul_e[st[ 2]] ^ gfmul_b[st[ 3]]]; - dt[15] = inv_s_box[gfmul_b[st[ 0]] ^ gfmul_d[st[ 1]] ^ gfmul_9[st[ 2]] ^ gfmul_e[st[ 3]]]; - - dt[ 4] = inv_s_box[gfmul_e[st[ 4]] ^ gfmul_b[st[ 5]] ^ gfmul_d[st[ 6]] ^ gfmul_9[st[ 7]]]; - dt[ 9] = inv_s_box[gfmul_9[st[ 4]] ^ gfmul_e[st[ 5]] ^ gfmul_b[st[ 6]] ^ gfmul_d[st[ 7]]]; - dt[14] = inv_s_box[gfmul_d[st[ 4]] ^ gfmul_9[st[ 5]] ^ gfmul_e[st[ 6]] ^ gfmul_b[st[ 7]]]; - dt[ 3] = inv_s_box[gfmul_b[st[ 4]] ^ gfmul_d[st[ 5]] ^ gfmul_9[st[ 6]] ^ gfmul_e[st[ 7]]]; - - dt[ 8] = inv_s_box[gfmul_e[st[ 8]] ^ gfmul_b[st[ 9]] ^ gfmul_d[st[10]] ^ gfmul_9[st[11]]]; - dt[13] = inv_s_box[gfmul_9[st[ 8]] ^ gfmul_e[st[ 9]] ^ gfmul_b[st[10]] ^ gfmul_d[st[11]]]; - dt[ 2] = inv_s_box[gfmul_d[st[ 8]] ^ gfmul_9[st[ 9]] ^ gfmul_e[st[10]] ^ gfmul_b[st[11]]]; - dt[ 7] = inv_s_box[gfmul_b[st[ 8]] ^ gfmul_d[st[ 9]] ^ gfmul_9[st[10]] ^ gfmul_e[st[11]]]; - - dt[12] = inv_s_box[gfmul_e[st[12]] ^ gfmul_b[st[13]] ^ gfmul_d[st[14]] ^ gfmul_9[st[15]]]; - dt[ 1] = inv_s_box[gfmul_9[st[12]] ^ gfmul_e[st[13]] ^ gfmul_b[st[14]] ^ gfmul_d[st[15]]]; - dt[ 6] = inv_s_box[gfmul_d[st[12]] ^ gfmul_9[st[13]] ^ gfmul_e[st[14]] ^ gfmul_b[st[15]]]; - dt[11] = inv_s_box[gfmul_b[st[12]] ^ gfmul_d[st[13]] ^ gfmul_9[st[14]] ^ gfmul_e[st[15]]]; - } - -#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) - -/* Set the cipher key for the pre-keyed version */ - -return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] ) -{ - uint_8t cc, rc, hi; - - switch( keylen ) - { - case 16: - case 128: - keylen = 16; - break; - case 24: - case 192: - keylen = 24; - break; - case 32: - case 256: - keylen = 32; - break; - default: - ctx->rnd = 0; - return -1; - } - block_copy(ctx->ksch, key, keylen); - hi = (keylen + 28) << 2; - ctx->rnd = (hi >> 4) - 1; - for( cc = keylen, rc = 1; cc < hi; cc += 4 ) - { uint_8t tt, t0, t1, t2, t3; - - t0 = ctx->ksch[cc - 4]; - t1 = ctx->ksch[cc - 3]; - t2 = ctx->ksch[cc - 2]; - t3 = ctx->ksch[cc - 1]; - if( cc % keylen == 0 ) - { - tt = t0; - t0 = s_box[t1] ^ rc; - t1 = s_box[t2]; - t2 = s_box[t3]; - t3 = s_box[tt]; - rc = f2(rc); - } - else if( keylen > 24 && cc % keylen == 16 ) - { - t0 = s_box[t0]; - t1 = s_box[t1]; - t2 = s_box[t2]; - t3 = s_box[t3]; - } - tt = cc - keylen; - ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; - ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; - ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; - ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; - } - return 0; -} - -#endif - -#if defined( AES_ENC_PREKEYED ) - -/* Encrypt a single block of 16 bytes */ - -return_type aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) -{ - if( ctx->rnd ) - { - uint_8t s1[N_BLOCK], r; - copy_and_key( s1, in, ctx->ksch ); - - for( r = 1 ; r < ctx->rnd ; ++r ) -#if defined( VERSION_1 ) - { - mix_sub_columns( s1 ); - add_round_key( s1, ctx->ksch + r * N_BLOCK); - } -#else - { uint_8t s2[N_BLOCK]; - mix_sub_columns( s2, s1 ); - copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK); - } -#endif - shift_sub_rows( s1 ); - copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); - } - else - return -1; - return 0; -} - -#endif - -#if defined( AES_DEC_PREKEYED ) - -/* Decrypt a single block of 16 bytes */ - -return_type aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) -{ - if( ctx->rnd ) - { - uint_8t s1[N_BLOCK], r; - copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); - inv_shift_sub_rows( s1 ); - - for( r = ctx->rnd ; --r ; ) -#if defined( VERSION_1 ) - { - add_round_key( s1, ctx->ksch + r * N_BLOCK ); - inv_mix_sub_columns( s1 ); - } -#else - { uint_8t s2[N_BLOCK]; - copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK ); - inv_mix_sub_columns( s1, s2 ); - } -#endif - copy_and_key( out, s1, ctx->ksch ); - } - else - return -1; - return 0; -} - -#endif - -#if defined( AES_ENC_128_OTFK ) - -/* The 'on the fly' encryption key update for for 128 bit keys */ - -static void update_encrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc ) -{ uint_8t cc; - - k[0] ^= s_box[k[13]] ^ *rc; - k[1] ^= s_box[k[14]]; - k[2] ^= s_box[k[15]]; - k[3] ^= s_box[k[12]]; - *rc = f2( *rc ); - - for(cc = 4; cc < 16; cc += 4 ) - { - k[cc + 0] ^= k[cc - 4]; - k[cc + 1] ^= k[cc - 3]; - k[cc + 2] ^= k[cc - 2]; - k[cc + 3] ^= k[cc - 1]; - } -} - -/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ - -void aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], - const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) -{ uint_8t s1[N_BLOCK], r, rc = 1; - - if(o_key != key) - block16_copy( o_key, key ); - copy_and_key( s1, in, o_key ); - - for( r = 1 ; r < 10 ; ++r ) -#if defined( VERSION_1 ) - { - mix_sub_columns( s1 ); - update_encrypt_key_128( o_key, &rc ); - add_round_key( s1, o_key ); - } -#else - { uint_8t s2[N_BLOCK]; - mix_sub_columns( s2, s1 ); - update_encrypt_key_128( o_key, &rc ); - copy_and_key( s1, s2, o_key ); - } -#endif - - shift_sub_rows( s1 ); - update_encrypt_key_128( o_key, &rc ); - copy_and_key( out, s1, o_key ); -} - -#endif - -#if defined( AES_DEC_128_OTFK ) - -/* The 'on the fly' decryption key update for for 128 bit keys */ - -static void update_decrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc ) -{ uint_8t cc; - - for( cc = 12; cc > 0; cc -= 4 ) - { - k[cc + 0] ^= k[cc - 4]; - k[cc + 1] ^= k[cc - 3]; - k[cc + 2] ^= k[cc - 2]; - k[cc + 3] ^= k[cc - 1]; - } - *rc = d2(*rc); - k[0] ^= s_box[k[13]] ^ *rc; - k[1] ^= s_box[k[14]]; - k[2] ^= s_box[k[15]]; - k[3] ^= s_box[k[12]]; -} - -/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ - -void aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], - const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) -{ - uint_8t s1[N_BLOCK], r, rc = 0x6c; - if(o_key != key) - block16_copy( o_key, key ); - - copy_and_key( s1, in, o_key ); - inv_shift_sub_rows( s1 ); - - for( r = 10 ; --r ; ) -#if defined( VERSION_1 ) - { - update_decrypt_key_128( o_key, &rc ); - add_round_key( s1, o_key ); - inv_mix_sub_columns( s1 ); - } -#else - { uint_8t s2[N_BLOCK]; - update_decrypt_key_128( o_key, &rc ); - copy_and_key( s2, s1, o_key ); - inv_mix_sub_columns( s1, s2 ); - } -#endif - update_decrypt_key_128( o_key, &rc ); - copy_and_key( out, s1, o_key ); -} - -#endif - -#if defined( AES_ENC_256_OTFK ) - -/* The 'on the fly' encryption key update for for 256 bit keys */ - -static void update_encrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc ) -{ uint_8t cc; - - k[0] ^= s_box[k[29]] ^ *rc; - k[1] ^= s_box[k[30]]; - k[2] ^= s_box[k[31]]; - k[3] ^= s_box[k[28]]; - *rc = f2( *rc ); - - for(cc = 4; cc < 16; cc += 4) - { - k[cc + 0] ^= k[cc - 4]; - k[cc + 1] ^= k[cc - 3]; - k[cc + 2] ^= k[cc - 2]; - k[cc + 3] ^= k[cc - 1]; - } - - k[16] ^= s_box[k[12]]; - k[17] ^= s_box[k[13]]; - k[18] ^= s_box[k[14]]; - k[19] ^= s_box[k[15]]; - - for( cc = 20; cc < 32; cc += 4 ) - { - k[cc + 0] ^= k[cc - 4]; - k[cc + 1] ^= k[cc - 3]; - k[cc + 2] ^= k[cc - 2]; - k[cc + 3] ^= k[cc - 1]; - } -} - -/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ - -void aes_encrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], - const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] ) -{ - uint_8t s1[N_BLOCK], r, rc = 1; - if(o_key != key) - { - block16_copy( o_key, key ); - block16_copy( o_key + 16, key + 16 ); - } - copy_and_key( s1, in, o_key ); - - for( r = 1 ; r < 14 ; ++r ) -#if defined( VERSION_1 ) - { - mix_sub_columns(s1); - if( r & 1 ) - add_round_key( s1, o_key + 16 ); - else - { - update_encrypt_key_256( o_key, &rc ); - add_round_key( s1, o_key ); - } - } -#else - { uint_8t s2[N_BLOCK]; - mix_sub_columns( s2, s1 ); - if( r & 1 ) - copy_and_key( s1, s2, o_key + 16 ); - else - { - update_encrypt_key_256( o_key, &rc ); - copy_and_key( s1, s2, o_key ); - } - } -#endif - - shift_sub_rows( s1 ); - update_encrypt_key_256( o_key, &rc ); - copy_and_key( out, s1, o_key ); -} - -#endif - -#if defined( AES_DEC_256_OTFK ) - -/* The 'on the fly' encryption key update for for 256 bit keys */ - -static void update_decrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc ) -{ uint_8t cc; - - for(cc = 28; cc > 16; cc -= 4) - { - k[cc + 0] ^= k[cc - 4]; - k[cc + 1] ^= k[cc - 3]; - k[cc + 2] ^= k[cc - 2]; - k[cc + 3] ^= k[cc - 1]; - } - - k[16] ^= s_box[k[12]]; - k[17] ^= s_box[k[13]]; - k[18] ^= s_box[k[14]]; - k[19] ^= s_box[k[15]]; - - for(cc = 12; cc > 0; cc -= 4) - { - k[cc + 0] ^= k[cc - 4]; - k[cc + 1] ^= k[cc - 3]; - k[cc + 2] ^= k[cc - 2]; - k[cc + 3] ^= k[cc - 1]; - } - - *rc = d2(*rc); - k[0] ^= s_box[k[29]] ^ *rc; - k[1] ^= s_box[k[30]]; - k[2] ^= s_box[k[31]]; - k[3] ^= s_box[k[28]]; -} - -/* Decrypt a single block of 16 bytes with 'on the fly' - 256 bit keying -*/ -void aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], - const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] ) -{ - uint_8t s1[N_BLOCK], r, rc = 0x80; - - if(o_key != key) - { - block16_copy( o_key, key ); - block16_copy( o_key + 16, key + 16 ); - } - - copy_and_key( s1, in, o_key ); - inv_shift_sub_rows( s1 ); - - for( r = 14 ; --r ; ) -#if defined( VERSION_1 ) - { - if( ( r & 1 ) ) - { - update_decrypt_key_256( o_key, &rc ); - add_round_key( s1, o_key + 16 ); - } - else - add_round_key( s1, o_key ); - inv_mix_sub_columns( s1 ); - } -#else - { uint_8t s2[N_BLOCK]; - if( ( r & 1 ) ) - { - update_decrypt_key_256( o_key, &rc ); - copy_and_key( s2, s1, o_key + 16 ); - } - else - copy_and_key( s2, s1, o_key ); - inv_mix_sub_columns( s1, s2 ); - } -#endif - copy_and_key( out, s1, o_key ); -} - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state (there are options to use 32-bit types if available). + + The combination of mix columns and byte substitution used here is based on + that developed by Karl Malbrain. His contribution is acknowledged. + */ + +/* Adapted by TrueCrypt Foundation: + - Macro-generated tables were replaced with static data to enable compiling + with MSVC++ 1.5 which runs out of resources when expanding large macros. +*/ + +#pragma optimize ("t", on) + +/* define if you have a fast memcpy function on your system */ +#if 1 +# define HAVE_MEMCPY +# include +# if defined( _MSC_VER ) +# ifndef DEBUG +# pragma intrinsic( memcpy ) +# endif +# endif +#endif + +/* define if you have fast 32-bit types on your system */ +#if 1 +# define HAVE_UINT_32T +#endif + +/* alternative versions (test for performance on your system) */ +#if 0 +# define VERSION_1 +#endif + +#include "AesSmall.h" + +#define WPOLY 0x011b +#define DPOLY 0x008d +#define f1(x) (x) +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +static const uint_8t s_box[256] = { + 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, + 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, + 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, + 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, + 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, + 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, + 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, + 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, + 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, + 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, + 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, + 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, + 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, + 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, + 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, + 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, + 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, + 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, + 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, + 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, + 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, + 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, + 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, + 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, + 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, + 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, + 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, + 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, + 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, + 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, + 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, + 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 +}; + +static const uint_8t inv_s_box[256] = { + 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38, + 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, + 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87, + 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, + 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d, + 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, + 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2, + 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, + 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16, + 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, + 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda, + 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, + 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a, + 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, + 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02, + 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, + 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea, + 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, + 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85, + 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, + 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89, + 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, + 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20, + 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, + 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31, + 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, + 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d, + 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, + 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0, + 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, + 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26, + 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d +}; + +static const uint_8t gfm2_s_box[256] = { + 0xc6,0xf8,0xee,0xf6,0xff,0xd6,0xde,0x91, + 0x60,0x02,0xce,0x56,0xe7,0xb5,0x4d,0xec, + 0x8f,0x1f,0x89,0xfa,0xef,0xb2,0x8e,0xfb, + 0x41,0xb3,0x5f,0x45,0x23,0x53,0xe4,0x9b, + 0x75,0xe1,0x3d,0x4c,0x6c,0x7e,0xf5,0x83, + 0x68,0x51,0xd1,0xf9,0xe2,0xab,0x62,0x2a, + 0x08,0x95,0x46,0x9d,0x30,0x37,0x0a,0x2f, + 0x0e,0x24,0x1b,0xdf,0xcd,0x4e,0x7f,0xea, + 0x12,0x1d,0x58,0x34,0x36,0xdc,0xb4,0x5b, + 0xa4,0x76,0xb7,0x7d,0x52,0xdd,0x5e,0x13, + 0xa6,0xb9,0x00,0xc1,0x40,0xe3,0x79,0xb6, + 0xd4,0x8d,0x67,0x72,0x94,0x98,0xb0,0x85, + 0xbb,0xc5,0x4f,0xed,0x86,0x9a,0x66,0x11, + 0x8a,0xe9,0x04,0xfe,0xa0,0x78,0x25,0x4b, + 0xa2,0x5d,0x80,0x05,0x3f,0x21,0x70,0xf1, + 0x63,0x77,0xaf,0x42,0x20,0xe5,0xfd,0xbf, + 0x81,0x18,0x26,0xc3,0xbe,0x35,0x88,0x2e, + 0x93,0x55,0xfc,0x7a,0xc8,0xba,0x32,0xe6, + 0xc0,0x19,0x9e,0xa3,0x44,0x54,0x3b,0x0b, + 0x8c,0xc7,0x6b,0x28,0xa7,0xbc,0x16,0xad, + 0xdb,0x64,0x74,0x14,0x92,0x0c,0x48,0xb8, + 0x9f,0xbd,0x43,0xc4,0x39,0x31,0xd3,0xf2, + 0xd5,0x8b,0x6e,0xda,0x01,0xb1,0x9c,0x49, + 0xd8,0xac,0xf3,0xcf,0xca,0xf4,0x47,0x10, + 0x6f,0xf0,0x4a,0x5c,0x38,0x57,0x73,0x97, + 0xcb,0xa1,0xe8,0x3e,0x96,0x61,0x0d,0x0f, + 0xe0,0x7c,0x71,0xcc,0x90,0x06,0xf7,0x1c, + 0xc2,0x6a,0xae,0x69,0x17,0x99,0x3a,0x27, + 0xd9,0xeb,0x2b,0x22,0xd2,0xa9,0x07,0x33, + 0x2d,0x3c,0x15,0xc9,0x87,0xaa,0x50,0xa5, + 0x03,0x59,0x09,0x1a,0x65,0xd7,0x84,0xd0, + 0x82,0x29,0x5a,0x1e,0x7b,0xa8,0x6d,0x2c +}; + +static const uint_8t gfm3_s_box[256] = { + 0xa5,0x84,0x99,0x8d,0x0d,0xbd,0xb1,0x54, + 0x50,0x03,0xa9,0x7d,0x19,0x62,0xe6,0x9a, + 0x45,0x9d,0x40,0x87,0x15,0xeb,0xc9,0x0b, + 0xec,0x67,0xfd,0xea,0xbf,0xf7,0x96,0x5b, + 0xc2,0x1c,0xae,0x6a,0x5a,0x41,0x02,0x4f, + 0x5c,0xf4,0x34,0x08,0x93,0x73,0x53,0x3f, + 0x0c,0x52,0x65,0x5e,0x28,0xa1,0x0f,0xb5, + 0x09,0x36,0x9b,0x3d,0x26,0x69,0xcd,0x9f, + 0x1b,0x9e,0x74,0x2e,0x2d,0xb2,0xee,0xfb, + 0xf6,0x4d,0x61,0xce,0x7b,0x3e,0x71,0x97, + 0xf5,0x68,0x00,0x2c,0x60,0x1f,0xc8,0xed, + 0xbe,0x46,0xd9,0x4b,0xde,0xd4,0xe8,0x4a, + 0x6b,0x2a,0xe5,0x16,0xc5,0xd7,0x55,0x94, + 0xcf,0x10,0x06,0x81,0xf0,0x44,0xba,0xe3, + 0xf3,0xfe,0xc0,0x8a,0xad,0xbc,0x48,0x04, + 0xdf,0xc1,0x75,0x63,0x30,0x1a,0x0e,0x6d, + 0x4c,0x14,0x35,0x2f,0xe1,0xa2,0xcc,0x39, + 0x57,0xf2,0x82,0x47,0xac,0xe7,0x2b,0x95, + 0xa0,0x98,0xd1,0x7f,0x66,0x7e,0xab,0x83, + 0xca,0x29,0xd3,0x3c,0x79,0xe2,0x1d,0x76, + 0x3b,0x56,0x4e,0x1e,0xdb,0x0a,0x6c,0xe4, + 0x5d,0x6e,0xef,0xa6,0xa8,0xa4,0x37,0x8b, + 0x32,0x43,0x59,0xb7,0x8c,0x64,0xd2,0xe0, + 0xb4,0xfa,0x07,0x25,0xaf,0x8e,0xe9,0x18, + 0xd5,0x88,0x6f,0x72,0x24,0xf1,0xc7,0x51, + 0x23,0x7c,0x9c,0x21,0xdd,0xdc,0x86,0x85, + 0x90,0x42,0xc4,0xaa,0xd8,0x05,0x01,0x12, + 0xa3,0x5f,0xf9,0xd0,0x91,0x58,0x27,0xb9, + 0x38,0x13,0xb3,0x33,0xbb,0x70,0x89,0xa7, + 0xb6,0x22,0x92,0x20,0x49,0xff,0x78,0x7a, + 0x8f,0xf8,0x80,0x17,0xda,0x31,0xc6,0xb8, + 0xc3,0xb0,0x77,0x11,0xcb,0xfc,0xd6,0x3a +}; + +static const uint_8t gfmul_9[256] = { + 0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f, + 0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77, + 0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf, + 0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7, + 0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04, + 0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c, + 0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94, + 0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc, + 0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49, + 0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01, + 0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9, + 0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91, + 0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72, + 0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a, + 0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2, + 0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa, + 0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3, + 0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b, + 0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43, + 0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b, + 0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8, + 0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0, + 0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78, + 0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30, + 0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5, + 0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed, + 0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35, + 0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d, + 0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e, + 0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6, + 0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e, + 0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46 +}; + +static const uint_8t gfmul_b[256] = { + 0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31, + 0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69, + 0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81, + 0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9, + 0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a, + 0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12, + 0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa, + 0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2, + 0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7, + 0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f, + 0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77, + 0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f, + 0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc, + 0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4, + 0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c, + 0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54, + 0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6, + 0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e, + 0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76, + 0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e, + 0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd, + 0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5, + 0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d, + 0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55, + 0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30, + 0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68, + 0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80, + 0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8, + 0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b, + 0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13, + 0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb, + 0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3 +}; + +static const uint_8t gfmul_d[256] = { + 0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23, + 0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b, + 0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3, + 0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b, + 0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98, + 0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0, + 0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48, + 0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20, + 0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e, + 0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26, + 0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e, + 0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6, + 0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5, + 0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d, + 0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25, + 0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d, + 0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9, + 0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91, + 0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29, + 0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41, + 0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42, + 0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a, + 0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92, + 0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa, + 0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94, + 0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc, + 0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44, + 0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c, + 0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f, + 0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47, + 0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff, + 0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97 +}; + +static const uint_8t gfmul_e[256] = { + 0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a, + 0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a, + 0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca, + 0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba, + 0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1, + 0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81, + 0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11, + 0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61, + 0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87, + 0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7, + 0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67, + 0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17, + 0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c, + 0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c, + 0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc, + 0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc, + 0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b, + 0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b, + 0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b, + 0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb, + 0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0, + 0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0, + 0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50, + 0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20, + 0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6, + 0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6, + 0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26, + 0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56, + 0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d, + 0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d, + 0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd, + 0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d +}; + +#if defined( HAVE_UINT_32T ) + typedef unsigned long uint_32t; +#endif + +#if defined( HAVE_MEMCPY ) +# define block_copy(d, s, l) memcpy(d, s, l) +# define block16_copy(d, s) memcpy(d, s, N_BLOCK) +#else +# define block_copy(d, s, l) copy_block(d, s, l) +# define block16_copy(d, s) copy_block16(d, s) +#endif + +/* block size 'nn' must be a multiple of four */ + +static void copy_block16( void *d, const void *s ) +{ +#if defined( HAVE_UINT_32T ) + ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0]; + ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1]; + ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2]; + ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3]; +#else + ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0]; + ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1]; + ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2]; + ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3]; + ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4]; + ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5]; + ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6]; + ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7]; + ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8]; + ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9]; + ((uint_8t*)d)[10] = ((uint_8t*)s)[10]; + ((uint_8t*)d)[11] = ((uint_8t*)s)[11]; + ((uint_8t*)d)[12] = ((uint_8t*)s)[12]; + ((uint_8t*)d)[13] = ((uint_8t*)s)[13]; + ((uint_8t*)d)[14] = ((uint_8t*)s)[14]; + ((uint_8t*)d)[15] = ((uint_8t*)s)[15]; +#endif +} + +static void copy_block( void * d, void *s, uint_8t nn ) +{ + while( nn-- ) + *((uint_8t*)d)++ = *((uint_8t*)s)++; +} + +static void xor_block( void *d, const void *s ) +{ +#if defined( HAVE_UINT_32T ) + ((uint_32t*)d)[ 0] ^= ((uint_32t*)s)[ 0]; + ((uint_32t*)d)[ 1] ^= ((uint_32t*)s)[ 1]; + ((uint_32t*)d)[ 2] ^= ((uint_32t*)s)[ 2]; + ((uint_32t*)d)[ 3] ^= ((uint_32t*)s)[ 3]; +#else + ((uint_8t*)d)[ 0] ^= ((uint_8t*)s)[ 0]; + ((uint_8t*)d)[ 1] ^= ((uint_8t*)s)[ 1]; + ((uint_8t*)d)[ 2] ^= ((uint_8t*)s)[ 2]; + ((uint_8t*)d)[ 3] ^= ((uint_8t*)s)[ 3]; + ((uint_8t*)d)[ 4] ^= ((uint_8t*)s)[ 4]; + ((uint_8t*)d)[ 5] ^= ((uint_8t*)s)[ 5]; + ((uint_8t*)d)[ 6] ^= ((uint_8t*)s)[ 6]; + ((uint_8t*)d)[ 7] ^= ((uint_8t*)s)[ 7]; + ((uint_8t*)d)[ 8] ^= ((uint_8t*)s)[ 8]; + ((uint_8t*)d)[ 9] ^= ((uint_8t*)s)[ 9]; + ((uint_8t*)d)[10] ^= ((uint_8t*)s)[10]; + ((uint_8t*)d)[11] ^= ((uint_8t*)s)[11]; + ((uint_8t*)d)[12] ^= ((uint_8t*)s)[12]; + ((uint_8t*)d)[13] ^= ((uint_8t*)s)[13]; + ((uint_8t*)d)[14] ^= ((uint_8t*)s)[14]; + ((uint_8t*)d)[15] ^= ((uint_8t*)s)[15]; +#endif +} + +static void copy_and_key( void *d, const void *s, const void *k ) +{ +#if defined( HAVE_UINT_32T ) + ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0] ^ ((uint_32t*)k)[ 0]; + ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1] ^ ((uint_32t*)k)[ 1]; + ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2] ^ ((uint_32t*)k)[ 2]; + ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3] ^ ((uint_32t*)k)[ 3]; +#elif 1 + ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0] ^ ((uint_8t*)k)[ 0]; + ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1] ^ ((uint_8t*)k)[ 1]; + ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2] ^ ((uint_8t*)k)[ 2]; + ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3] ^ ((uint_8t*)k)[ 3]; + ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4] ^ ((uint_8t*)k)[ 4]; + ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5] ^ ((uint_8t*)k)[ 5]; + ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6] ^ ((uint_8t*)k)[ 6]; + ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7] ^ ((uint_8t*)k)[ 7]; + ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8] ^ ((uint_8t*)k)[ 8]; + ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9] ^ ((uint_8t*)k)[ 9]; + ((uint_8t*)d)[10] = ((uint_8t*)s)[10] ^ ((uint_8t*)k)[10]; + ((uint_8t*)d)[11] = ((uint_8t*)s)[11] ^ ((uint_8t*)k)[11]; + ((uint_8t*)d)[12] = ((uint_8t*)s)[12] ^ ((uint_8t*)k)[12]; + ((uint_8t*)d)[13] = ((uint_8t*)s)[13] ^ ((uint_8t*)k)[13]; + ((uint_8t*)d)[14] = ((uint_8t*)s)[14] ^ ((uint_8t*)k)[14]; + ((uint_8t*)d)[15] = ((uint_8t*)s)[15] ^ ((uint_8t*)k)[15]; +#else + block16_copy(d, s); + xor_block(d, k); +#endif +} + +static void add_round_key( uint_8t d[N_BLOCK], const uint_8t k[N_BLOCK] ) +{ + xor_block(d, k); +} + +static void shift_sub_rows( uint_8t st[N_BLOCK] ) +{ uint_8t tt; + + st[ 0] = s_box[st[ 0]]; st[ 4] = s_box[st[ 4]]; + st[ 8] = s_box[st[ 8]]; st[12] = s_box[st[12]]; + + tt = st[1]; st[ 1] = s_box[st[ 5]]; st[ 5] = s_box[st[ 9]]; + st[ 9] = s_box[st[13]]; st[13] = s_box[ tt ]; + + tt = st[2]; st[ 2] = s_box[st[10]]; st[10] = s_box[ tt ]; + tt = st[6]; st[ 6] = s_box[st[14]]; st[14] = s_box[ tt ]; + + tt = st[15]; st[15] = s_box[st[11]]; st[11] = s_box[st[ 7]]; + st[ 7] = s_box[st[ 3]]; st[ 3] = s_box[ tt ]; +} + +static void inv_shift_sub_rows( uint_8t st[N_BLOCK] ) +{ uint_8t tt; + + st[ 0] = inv_s_box[st[ 0]]; st[ 4] = inv_s_box[st[ 4]]; + st[ 8] = inv_s_box[st[ 8]]; st[12] = inv_s_box[st[12]]; + + tt = st[13]; st[13] = inv_s_box[st[9]]; st[ 9] = inv_s_box[st[5]]; + st[ 5] = inv_s_box[st[1]]; st[ 1] = inv_s_box[ tt ]; + + tt = st[2]; st[ 2] = inv_s_box[st[10]]; st[10] = inv_s_box[ tt ]; + tt = st[6]; st[ 6] = inv_s_box[st[14]]; st[14] = inv_s_box[ tt ]; + + tt = st[3]; st[ 3] = inv_s_box[st[ 7]]; st[ 7] = inv_s_box[st[11]]; + st[11] = inv_s_box[st[15]]; st[15] = inv_s_box[ tt ]; +} + +#if defined( VERSION_1 ) + static void mix_sub_columns( uint_8t dt[N_BLOCK] ) + { uint_8t st[N_BLOCK]; + block16_copy(st, dt); +#else + static void mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] ) + { +#endif + dt[ 0] = gfm2_s_box[st[0]] ^ gfm3_s_box[st[5]] ^ s_box[st[10]] ^ s_box[st[15]]; + dt[ 1] = s_box[st[0]] ^ gfm2_s_box[st[5]] ^ gfm3_s_box[st[10]] ^ s_box[st[15]]; + dt[ 2] = s_box[st[0]] ^ s_box[st[5]] ^ gfm2_s_box[st[10]] ^ gfm3_s_box[st[15]]; + dt[ 3] = gfm3_s_box[st[0]] ^ s_box[st[5]] ^ s_box[st[10]] ^ gfm2_s_box[st[15]]; + + dt[ 4] = gfm2_s_box[st[4]] ^ gfm3_s_box[st[9]] ^ s_box[st[14]] ^ s_box[st[3]]; + dt[ 5] = s_box[st[4]] ^ gfm2_s_box[st[9]] ^ gfm3_s_box[st[14]] ^ s_box[st[3]]; + dt[ 6] = s_box[st[4]] ^ s_box[st[9]] ^ gfm2_s_box[st[14]] ^ gfm3_s_box[st[3]]; + dt[ 7] = gfm3_s_box[st[4]] ^ s_box[st[9]] ^ s_box[st[14]] ^ gfm2_s_box[st[3]]; + + dt[ 8] = gfm2_s_box[st[8]] ^ gfm3_s_box[st[13]] ^ s_box[st[2]] ^ s_box[st[7]]; + dt[ 9] = s_box[st[8]] ^ gfm2_s_box[st[13]] ^ gfm3_s_box[st[2]] ^ s_box[st[7]]; + dt[10] = s_box[st[8]] ^ s_box[st[13]] ^ gfm2_s_box[st[2]] ^ gfm3_s_box[st[7]]; + dt[11] = gfm3_s_box[st[8]] ^ s_box[st[13]] ^ s_box[st[2]] ^ gfm2_s_box[st[7]]; + + dt[12] = gfm2_s_box[st[12]] ^ gfm3_s_box[st[1]] ^ s_box[st[6]] ^ s_box[st[11]]; + dt[13] = s_box[st[12]] ^ gfm2_s_box[st[1]] ^ gfm3_s_box[st[6]] ^ s_box[st[11]]; + dt[14] = s_box[st[12]] ^ s_box[st[1]] ^ gfm2_s_box[st[6]] ^ gfm3_s_box[st[11]]; + dt[15] = gfm3_s_box[st[12]] ^ s_box[st[1]] ^ s_box[st[6]] ^ gfm2_s_box[st[11]]; + } + +#if defined( VERSION_1 ) + static void inv_mix_sub_columns( uint_8t dt[N_BLOCK] ) + { uint_8t st[N_BLOCK]; + block16_copy(st, dt); +#else + static void inv_mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] ) + { +#endif + dt[ 0] = inv_s_box[gfmul_e[st[ 0]] ^ gfmul_b[st[ 1]] ^ gfmul_d[st[ 2]] ^ gfmul_9[st[ 3]]]; + dt[ 5] = inv_s_box[gfmul_9[st[ 0]] ^ gfmul_e[st[ 1]] ^ gfmul_b[st[ 2]] ^ gfmul_d[st[ 3]]]; + dt[10] = inv_s_box[gfmul_d[st[ 0]] ^ gfmul_9[st[ 1]] ^ gfmul_e[st[ 2]] ^ gfmul_b[st[ 3]]]; + dt[15] = inv_s_box[gfmul_b[st[ 0]] ^ gfmul_d[st[ 1]] ^ gfmul_9[st[ 2]] ^ gfmul_e[st[ 3]]]; + + dt[ 4] = inv_s_box[gfmul_e[st[ 4]] ^ gfmul_b[st[ 5]] ^ gfmul_d[st[ 6]] ^ gfmul_9[st[ 7]]]; + dt[ 9] = inv_s_box[gfmul_9[st[ 4]] ^ gfmul_e[st[ 5]] ^ gfmul_b[st[ 6]] ^ gfmul_d[st[ 7]]]; + dt[14] = inv_s_box[gfmul_d[st[ 4]] ^ gfmul_9[st[ 5]] ^ gfmul_e[st[ 6]] ^ gfmul_b[st[ 7]]]; + dt[ 3] = inv_s_box[gfmul_b[st[ 4]] ^ gfmul_d[st[ 5]] ^ gfmul_9[st[ 6]] ^ gfmul_e[st[ 7]]]; + + dt[ 8] = inv_s_box[gfmul_e[st[ 8]] ^ gfmul_b[st[ 9]] ^ gfmul_d[st[10]] ^ gfmul_9[st[11]]]; + dt[13] = inv_s_box[gfmul_9[st[ 8]] ^ gfmul_e[st[ 9]] ^ gfmul_b[st[10]] ^ gfmul_d[st[11]]]; + dt[ 2] = inv_s_box[gfmul_d[st[ 8]] ^ gfmul_9[st[ 9]] ^ gfmul_e[st[10]] ^ gfmul_b[st[11]]]; + dt[ 7] = inv_s_box[gfmul_b[st[ 8]] ^ gfmul_d[st[ 9]] ^ gfmul_9[st[10]] ^ gfmul_e[st[11]]]; + + dt[12] = inv_s_box[gfmul_e[st[12]] ^ gfmul_b[st[13]] ^ gfmul_d[st[14]] ^ gfmul_9[st[15]]]; + dt[ 1] = inv_s_box[gfmul_9[st[12]] ^ gfmul_e[st[13]] ^ gfmul_b[st[14]] ^ gfmul_d[st[15]]]; + dt[ 6] = inv_s_box[gfmul_d[st[12]] ^ gfmul_9[st[13]] ^ gfmul_e[st[14]] ^ gfmul_b[st[15]]]; + dt[11] = inv_s_box[gfmul_b[st[12]] ^ gfmul_d[st[13]] ^ gfmul_9[st[14]] ^ gfmul_e[st[15]]]; + } + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +/* Set the cipher key for the pre-keyed version */ + +return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] ) +{ + uint_8t cc, rc, hi; + + switch( keylen ) + { + case 16: + case 128: + keylen = 16; + break; + case 24: + case 192: + keylen = 24; + break; + case 32: + case 256: + keylen = 32; + break; + default: + ctx->rnd = 0; + return (return_type) -1; + } + block_copy(ctx->ksch, key, keylen); + hi = (keylen + 28) << 2; + ctx->rnd = (hi >> 4) - 1; + for( cc = keylen, rc = 1; cc < hi; cc += 4 ) + { uint_8t tt, t0, t1, t2, t3; + + t0 = ctx->ksch[cc - 4]; + t1 = ctx->ksch[cc - 3]; + t2 = ctx->ksch[cc - 2]; + t3 = ctx->ksch[cc - 1]; + if( cc % keylen == 0 ) + { + tt = t0; + t0 = s_box[t1] ^ rc; + t1 = s_box[t2]; + t2 = s_box[t3]; + t3 = s_box[tt]; + rc = f2(rc); + } + else if( keylen > 24 && cc % keylen == 16 ) + { + t0 = s_box[t0]; + t1 = s_box[t1]; + t2 = s_box[t2]; + t3 = s_box[t3]; + } + tt = cc - keylen; + ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; + ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; + ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; + ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; + } + return 0; +} + +#endif + +#if defined( AES_ENC_PREKEYED ) + +/* Encrypt a single block of 16 bytes */ + +return_type aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint_8t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch ); + + for( r = 1 ; r < ctx->rnd ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + add_round_key( s1, ctx->ksch + r * N_BLOCK); + } +#else + { uint_8t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK); + } +#endif + shift_sub_rows( s1 ); + copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); + } + else + return (return_type) -1; + return 0; +} + +#endif + +#if defined( AES_DEC_PREKEYED ) + +/* Decrypt a single block of 16 bytes */ + +return_type aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint_8t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); + inv_shift_sub_rows( s1 ); + + for( r = ctx->rnd ; --r ; ) +#if defined( VERSION_1 ) + { + add_round_key( s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1 ); + } +#else + { uint_8t s2[N_BLOCK]; + copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, ctx->ksch ); + } + else + return (return_type) -1; + return 0; +} + +#endif + +#if defined( AES_ENC_128_OTFK ) + +/* The 'on the fly' encryption key update for for 128 bit keys */ + +static void update_encrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + k[0] ^= s_box[k[13]] ^ *rc; + k[1] ^= s_box[k[14]]; + k[2] ^= s_box[k[15]]; + k[3] ^= s_box[k[12]]; + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) +{ uint_8t s1[N_BLOCK], r, rc = 1; + + if(o_key != key) + block16_copy( o_key, key ); + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 10 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + update_encrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + } +#else + { uint_8t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_128_OTFK ) + +/* The 'on the fly' decryption key update for for 128 bit keys */ + +static void update_decrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + for( cc = 12; cc > 0; cc -= 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + *rc = d2(*rc); + k[0] ^= s_box[k[13]] ^ *rc; + k[1] ^= s_box[k[14]]; + k[2] ^= s_box[k[15]]; + k[3] ^= s_box[k[12]]; +} + +/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) +{ + uint_8t s1[N_BLOCK], r, rc = 0x6c; + if(o_key != key) + block16_copy( o_key, key ); + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 10 ; --r ; ) +#if defined( VERSION_1 ) + { + update_decrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint_8t s2[N_BLOCK]; + update_decrypt_key_128( o_key, &rc ); + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + update_decrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_ENC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_encrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + k[0] ^= s_box[k[29]] ^ *rc; + k[1] ^= s_box[k[30]]; + k[2] ^= s_box[k[31]]; + k[3] ^= s_box[k[28]]; + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box[k[12]]; + k[17] ^= s_box[k[13]]; + k[18] ^= s_box[k[14]]; + k[19] ^= s_box[k[15]]; + + for( cc = 20; cc < 32; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ + +void aes_encrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] ) +{ + uint_8t s1[N_BLOCK], r, rc = 1; + if(o_key != key) + { + block16_copy( o_key, key ); + block16_copy( o_key + 16, key + 16 ); + } + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 14 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns(s1); + if( r & 1 ) + add_round_key( s1, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key ); + } + } +#else + { uint_8t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + if( r & 1 ) + copy_and_key( s1, s2, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_256( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_decrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + for(cc = 28; cc > 16; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box[k[12]]; + k[17] ^= s_box[k[13]]; + k[18] ^= s_box[k[14]]; + k[19] ^= s_box[k[15]]; + + for(cc = 12; cc > 0; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + *rc = d2(*rc); + k[0] ^= s_box[k[29]] ^ *rc; + k[1] ^= s_box[k[30]]; + k[2] ^= s_box[k[31]]; + k[3] ^= s_box[k[28]]; +} + +/* Decrypt a single block of 16 bytes with 'on the fly' + 256 bit keying +*/ +void aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] ) +{ + uint_8t s1[N_BLOCK], r, rc = 0x80; + + if(o_key != key) + { + block16_copy( o_key, key ); + block16_copy( o_key + 16, key + 16 ); + } + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 14 ; --r ; ) +#if defined( VERSION_1 ) + { + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key + 16 ); + } + else + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint_8t s2[N_BLOCK]; + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + copy_and_key( s2, s1, o_key + 16 ); + } + else + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, o_key ); +} + +#endif diff --git a/Crypto/AesSmall.h b/Crypto/AesSmall.h index ebeb24e..516c696 100644 --- a/Crypto/AesSmall.h +++ b/Crypto/AesSmall.h @@ -1,169 +1,169 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - ALTERNATIVELY, provided that this notice is retained in full, this product - may be distributed under the terms of the GNU General Public License (GPL), - in which case the provisions of the GPL apply INSTEAD OF those given above. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue 09/09/2006 - - This is an AES implementation that uses only 8-bit byte operations on the - cipher state. - */ - -#ifndef AES_H -#define AES_H - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* This provides speed optimisation opportunities if 32-bit word - operations are available -*/ -#if 1 -# define HAVE_UINT_32T -#endif - -#if 1 -# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ -#endif -#if 1 -# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ -#endif -#if 0 -# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ -#endif -#if 0 -# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ -#endif -#if 0 -# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ -#endif -#if 0 -# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ -#endif - -#define N_ROW 4 -#define N_COL 4 -#define N_BLOCK (N_ROW * N_COL) -#define N_MAX_ROUNDS 14 - -typedef unsigned char uint_8t; - -typedef uint_8t return_type; -typedef uint_8t length_type; -typedef uint_8t uint_type; - -typedef unsigned char uint_8t; - -typedef struct -{ uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; - uint_8t rnd; -} aes_context; - -/* The following calls are for a precomputed key schedule - - NOTE: If the length_type used for the key length is an - unsigned 8-bit character, a key length of 256 bits must - be entered as a length in bytes (valid inputs are hence - 128, 192, 16, 24 and 32). -*/ - -#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) - -return_type aes_set_key( const unsigned char key[], - length_type keylen, - aes_context ctx[1] ); -#endif - -#if defined( AES_ENC_PREKEYED ) - -return_type aes_encrypt( const unsigned char in[N_BLOCK], - unsigned char out[N_BLOCK], - const aes_context ctx[1] ); -#endif - -#if defined( AES_DEC_PREKEYED ) - -return_type aes_decrypt( const unsigned char in[N_BLOCK], - unsigned char out[N_BLOCK], - const aes_context ctx[1] ); -#endif - -/* The following calls are for 'on the fly' keying. In this case the - encryption and decryption keys are different. - - The encryption subroutines take a key in an array of bytes in - key[L] where L is 16, 24 or 32 bytes for key lengths of 128, - 192, and 256 bits respectively. They then encrypts the input - data, in[] with this key and put the reult in the output array - out[]. In addition, the second key array, o_key[L], is used - to output the key that is needed by the decryption subroutine - to reverse the encryption operation. The two key arrays can - be the same array but in this case the original key will be - overwritten. - - In the same way, the decryption subroutines output keys that - can be used to reverse their effect when used for encryption. - - Only 128 and 256 bit keys are supported in these 'on the fly' - modes. -*/ - -#if defined( AES_ENC_128_OTFK ) -void aes_encrypt_128( const unsigned char in[N_BLOCK], - unsigned char out[N_BLOCK], - const unsigned char key[N_BLOCK], - uint_8t o_key[N_BLOCK] ); -#endif - -#if defined( AES_DEC_128_OTFK ) -void aes_decrypt_128( const unsigned char in[N_BLOCK], - unsigned char out[N_BLOCK], - const unsigned char key[N_BLOCK], - unsigned char o_key[N_BLOCK] ); -#endif - -#if defined( AES_ENC_256_OTFK ) -void aes_encrypt_256( const unsigned char in[N_BLOCK], - unsigned char out[N_BLOCK], - const unsigned char key[2 * N_BLOCK], - unsigned char o_key[2 * N_BLOCK] ); -#endif - -#if defined( AES_DEC_256_OTFK ) -void aes_decrypt_256( const unsigned char in[N_BLOCK], - unsigned char out[N_BLOCK], - const unsigned char key[2 * N_BLOCK], - unsigned char o_key[2 * N_BLOCK] ); -#endif - -#if defined(__cplusplus) -} -#endif - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state. + */ + +#ifndef AES_H +#define AES_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* This provides speed optimisation opportunities if 32-bit word + operations are available +*/ +#if 1 +# define HAVE_UINT_32T +#endif + +#if 1 +# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ +#endif +#if 1 +# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ +#endif +#if 0 +# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ +#endif +#if 0 +# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ +#endif + +#define N_ROW 4 +#define N_COL 4 +#define N_BLOCK (N_ROW * N_COL) +#define N_MAX_ROUNDS 14 + +typedef unsigned char uint_8t; + +typedef uint_8t return_type; +typedef uint_8t length_type; +typedef uint_8t uint_type; + +typedef unsigned char uint_8t; + +typedef struct +{ uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; + uint_8t rnd; +} aes_context; + +/* The following calls are for a precomputed key schedule + + NOTE: If the length_type used for the key length is an + unsigned 8-bit character, a key length of 256 bits must + be entered as a length in bytes (valid inputs are hence + 128, 192, 16, 24 and 32). +*/ + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +return_type aes_set_key( const unsigned char key[], + length_type keylen, + aes_context ctx[1] ); +#endif + +#if defined( AES_ENC_PREKEYED ) + +return_type aes_encrypt( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const aes_context ctx[1] ); +#endif + +#if defined( AES_DEC_PREKEYED ) + +return_type aes_decrypt( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const aes_context ctx[1] ); +#endif + +/* The following calls are for 'on the fly' keying. In this case the + encryption and decryption keys are different. + + The encryption subroutines take a key in an array of bytes in + key[L] where L is 16, 24 or 32 bytes for key lengths of 128, + 192, and 256 bits respectively. They then encrypts the input + data, in[] with this key and put the reult in the output array + out[]. In addition, the second key array, o_key[L], is used + to output the key that is needed by the decryption subroutine + to reverse the encryption operation. The two key arrays can + be the same array but in this case the original key will be + overwritten. + + In the same way, the decryption subroutines output keys that + can be used to reverse their effect when used for encryption. + + Only 128 and 256 bit keys are supported in these 'on the fly' + modes. +*/ + +#if defined( AES_ENC_128_OTFK ) +void aes_encrypt_128( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], + uint_8t o_key[N_BLOCK] ); +#endif + +#if defined( AES_DEC_128_OTFK ) +void aes_decrypt_128( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], + unsigned char o_key[N_BLOCK] ); +#endif + +#if defined( AES_ENC_256_OTFK ) +void aes_encrypt_256( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], + unsigned char o_key[2 * N_BLOCK] ); +#endif + +#if defined( AES_DEC_256_OTFK ) +void aes_decrypt_256( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], + unsigned char o_key[2 * N_BLOCK] ); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Crypto/Aes_x64.asm b/Crypto/Aes_x64.asm index 1ccf73c..70a2ecf 100644 --- a/Crypto/Aes_x64.asm +++ b/Crypto/Aes_x64.asm @@ -29,6 +29,11 @@ ; Some of the techniques used in this implementation are the result of ; suggestions made by him for which I am most grateful. +; +; Adapted for TrueCrypt by the TrueCrypt Foundation: +; - Adapted for NASM +; + ; An AES implementation for AMD64 processors using the YASM assembler. This ; implemetation provides only encryption, decryption and hence requires key ; scheduling support in C. It uses 8k bytes of tables but its encryption and @@ -716,7 +721,7 @@ end_prologue %endif movzx esi, byte [kptr+4*KS_LENGTH] - lea tptr,[enc_tab wrt rip] + lea tptr, [rel enc_tab] sub kptr, fofs mov eax, [rdi+0*4] @@ -830,7 +835,7 @@ end_prologue %endif movzx esi,byte[kptr+4*KS_LENGTH] - lea tptr,[dec_tab wrt rip] + lea tptr, [rel dec_tab] sub kptr, rofs mov eax, [rdi+0*4] @@ -900,5 +905,3 @@ end_prologue %endif %endif - - end diff --git a/Crypto/Aes_x86.asm b/Crypto/Aes_x86.asm index 4a3dea3..0087199 100644 --- a/Crypto/Aes_x86.asm +++ b/Crypto/Aes_x86.asm @@ -27,6 +27,11 @@ ; This code requires ASM_X86_V1C to be set in aesopt.h. It requires the C files ; aeskey.c and aestab.c for support. +; +; Adapted for TrueCrypt by the TrueCrypt Foundation: +; - Adapted for NASM +; + ; An AES implementation for x86 processors using the YASM (or NASM) assembler. ; This is an assembler implementation that covers encryption and decryption ; only and is intended as a replacement of the C file aescrypt.c. It hence @@ -639,6 +644,3 @@ stk_spc equ 20 ; stack space do_exit %endif - - end - diff --git a/Crypto/Aescrypt.c b/Crypto/Aescrypt.c index 4617598..c77ec67 100644 --- a/Crypto/Aescrypt.c +++ b/Crypto/Aescrypt.c @@ -1,311 +1,311 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 20/12/2007 -*/ - -#include "Aesopt.h" -#include "Aestab.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) -#define so(y,x,c) word_out(y, c, s(x,c)) - -#if defined(ARRAYS) -#define locals(y,x) x[4],y[4] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 -#endif - -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) - -#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) - -/* Visual C++ .Net v7.1 provides the fastest encryption code when using - Pentium optimiation with small code but this is poor for decryption - so we need to control this with the following VC++ pragmas -*/ - -#if defined( _MSC_VER ) && !defined( _WIN64 ) -#pragma optimize( "s", on ) -#endif - -/* Given the column (c) of the output state variable, the following - macros give the input state variables which are needed in its - computation for each row (r) of the state. All the alternative - macros give the same end values but expand into different ways - of calculating these values. In particular the complex macro - used for dynamically variable block sizes is designed to expand - to a compile time constant whenever possible but will expand to - conditional clauses on some branches (I am grateful to Frank - Yellin for this construction) -*/ - -#define fwd_var(x,r,c)\ - ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ - : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ - : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ - : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) - -#if defined(FT4_SET) -#undef dec_fmvars -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) -#elif defined(FT1_SET) -#undef dec_fmvars -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) -#else -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) -#endif - -#if defined(FL4_SET) -#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) -#elif defined(FL1_SET) -#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) -#else -#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) -#endif - -AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) -{ uint_32t locals(b0, b1); - const uint_32t *kp; -#if defined( dec_fmvars ) - dec_fmvars; /* declare variables for fwd_mcol() if needed */ -#endif - -#if defined( AES_ERR_CHK ) - if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) - return EXIT_FAILURE; -#endif - - kp = cx->ks; - state_in(b0, in, kp); - -#if (ENC_UNROLL == FULL) - - switch(cx->inf.b[0]) - { - case 14 * 16: - round(fwd_rnd, b1, b0, kp + 1 * N_COLS); - round(fwd_rnd, b0, b1, kp + 2 * N_COLS); - kp += 2 * N_COLS; - case 12 * 16: - round(fwd_rnd, b1, b0, kp + 1 * N_COLS); - round(fwd_rnd, b0, b1, kp + 2 * N_COLS); - kp += 2 * N_COLS; - case 10 * 16: - round(fwd_rnd, b1, b0, kp + 1 * N_COLS); - round(fwd_rnd, b0, b1, kp + 2 * N_COLS); - round(fwd_rnd, b1, b0, kp + 3 * N_COLS); - round(fwd_rnd, b0, b1, kp + 4 * N_COLS); - round(fwd_rnd, b1, b0, kp + 5 * N_COLS); - round(fwd_rnd, b0, b1, kp + 6 * N_COLS); - round(fwd_rnd, b1, b0, kp + 7 * N_COLS); - round(fwd_rnd, b0, b1, kp + 8 * N_COLS); - round(fwd_rnd, b1, b0, kp + 9 * N_COLS); - round(fwd_lrnd, b0, b1, kp +10 * N_COLS); - } - -#else - -#if (ENC_UNROLL == PARTIAL) - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) - { - kp += N_COLS; - round(fwd_rnd, b1, b0, kp); - kp += N_COLS; - round(fwd_rnd, b0, b1, kp); - } - kp += N_COLS; - round(fwd_rnd, b1, b0, kp); -#else - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) - { - kp += N_COLS; - round(fwd_rnd, b1, b0, kp); - l_copy(b0, b1); - } -#endif - kp += N_COLS; - round(fwd_lrnd, b0, b1, kp); - } -#endif - - state_out(out, b0); - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if ( FUNCS_IN_C & DECRYPTION_IN_C) - -/* Visual C++ .Net v7.1 provides the fastest encryption code when using - Pentium optimiation with small code but this is poor for decryption - so we need to control this with the following VC++ pragmas -*/ - -#if defined( _MSC_VER ) && !defined( _WIN64 ) -#pragma optimize( "t", on ) -#endif - -/* Given the column (c) of the output state variable, the following - macros give the input state variables which are needed in its - computation for each row (r) of the state. All the alternative - macros give the same end values but expand into different ways - of calculating these values. In particular the complex macro - used for dynamically variable block sizes is designed to expand - to a compile time constant whenever possible but will expand to - conditional clauses on some branches (I am grateful to Frank - Yellin for this construction) -*/ - -#define inv_var(x,r,c)\ - ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ - : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ - : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ - : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) - -#if defined(IT4_SET) -#undef dec_imvars -#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) -#elif defined(IT1_SET) -#undef dec_imvars -#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) -#else -#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) -#endif - -#if defined(IL4_SET) -#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) -#elif defined(IL1_SET) -#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) -#else -#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) -#endif - -/* This code can work with the decryption key schedule in the */ -/* order that is used for encrytpion (where the 1st decryption */ -/* round key is at the high end ot the schedule) or with a key */ -/* schedule that has been reversed to put the 1st decryption */ -/* round key at the low end of the schedule in memory (when */ -/* AES_REV_DKS is defined) */ - -#ifdef AES_REV_DKS -#define key_ofs 0 -#define rnd_key(n) (kp + n * N_COLS) -#else -#define key_ofs 1 -#define rnd_key(n) (kp - n * N_COLS) -#endif - -AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) -{ uint_32t locals(b0, b1); -#if defined( dec_imvars ) - dec_imvars; /* declare variables for inv_mcol() if needed */ -#endif - const uint_32t *kp; - -#if defined( AES_ERR_CHK ) - if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) - return EXIT_FAILURE; -#endif - - kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0); - state_in(b0, in, kp); - -#if (DEC_UNROLL == FULL) - - kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2)); - switch(cx->inf.b[0]) - { - case 14 * 16: - round(inv_rnd, b1, b0, rnd_key(-13)); - round(inv_rnd, b0, b1, rnd_key(-12)); - case 12 * 16: - round(inv_rnd, b1, b0, rnd_key(-11)); - round(inv_rnd, b0, b1, rnd_key(-10)); - case 10 * 16: - round(inv_rnd, b1, b0, rnd_key(-9)); - round(inv_rnd, b0, b1, rnd_key(-8)); - round(inv_rnd, b1, b0, rnd_key(-7)); - round(inv_rnd, b0, b1, rnd_key(-6)); - round(inv_rnd, b1, b0, rnd_key(-5)); - round(inv_rnd, b0, b1, rnd_key(-4)); - round(inv_rnd, b1, b0, rnd_key(-3)); - round(inv_rnd, b0, b1, rnd_key(-2)); - round(inv_rnd, b1, b0, rnd_key(-1)); - round(inv_lrnd, b0, b1, rnd_key( 0)); - } - -#else - -#if (DEC_UNROLL == PARTIAL) - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) - { - kp = rnd_key(1); - round(inv_rnd, b1, b0, kp); - kp = rnd_key(1); - round(inv_rnd, b0, b1, kp); - } - kp = rnd_key(1); - round(inv_rnd, b1, b0, kp); -#else - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) - { - kp = rnd_key(1); - round(inv_rnd, b1, b0, kp); - l_copy(b0, b1); - } -#endif - kp = rnd_key(1); - round(inv_lrnd, b0, b1, kp); - } -#endif - - state_out(out, b0); - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if defined(__cplusplus) -} -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 +*/ + +#include "Aesopt.h" +#include "Aestab.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) +#define so(y,x,c) word_out(y, c, s(x,c)) + +#if defined(ARRAYS) +#define locals(y,x) x[4],y[4] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 +#endif + +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimiation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) +#pragma optimize( "s", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define fwd_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) +#elif defined(FT1_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) +#else +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) +#elif defined(FL1_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) +#else +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) +#endif + +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) +{ uint_32t locals(b0, b1); + const uint_32t *kp; +#if defined( dec_fmvars ) + dec_fmvars; /* declare variables for fwd_mcol() if needed */ +#endif + +#if defined( AES_ERR_CHK ) + if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) + return EXIT_FAILURE; +#endif + + kp = cx->ks; + state_in(b0, in, kp); + +#if (ENC_UNROLL == FULL) + + switch(cx->inf.b[0]) + { + case 14 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 12 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 10 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + round(fwd_rnd, b1, b0, kp + 3 * N_COLS); + round(fwd_rnd, b0, b1, kp + 4 * N_COLS); + round(fwd_rnd, b1, b0, kp + 5 * N_COLS); + round(fwd_rnd, b0, b1, kp + 6 * N_COLS); + round(fwd_rnd, b1, b0, kp + 7 * N_COLS); + round(fwd_rnd, b0, b1, kp + 8 * N_COLS); + round(fwd_rnd, b1, b0, kp + 9 * N_COLS); + round(fwd_lrnd, b0, b1, kp +10 * N_COLS); + } + +#else + +#if (ENC_UNROLL == PARTIAL) + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + kp += N_COLS; + round(fwd_rnd, b0, b1, kp); + } + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); +#else + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp += N_COLS; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimiation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) +#pragma optimize( "t", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define inv_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) + +#if defined(IT4_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) +#elif defined(IT1_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) +#else +#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) +#elif defined(IL1_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) +#else +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) +#endif + +/* This code can work with the decryption key schedule in the */ +/* order that is used for encrytpion (where the 1st decryption */ +/* round key is at the high end ot the schedule) or with a key */ +/* schedule that has been reversed to put the 1st decryption */ +/* round key at the low end of the schedule in memory (when */ +/* AES_REV_DKS is defined) */ + +#ifdef AES_REV_DKS +#define key_ofs 0 +#define rnd_key(n) (kp + n * N_COLS) +#else +#define key_ofs 1 +#define rnd_key(n) (kp - n * N_COLS) +#endif + +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) +{ uint_32t locals(b0, b1); +#if defined( dec_imvars ) + dec_imvars; /* declare variables for inv_mcol() if needed */ +#endif + const uint_32t *kp; + +#if defined( AES_ERR_CHK ) + if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) + return EXIT_FAILURE; +#endif + + kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0); + state_in(b0, in, kp); + +#if (DEC_UNROLL == FULL) + + kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2)); + switch(cx->inf.b[0]) + { + case 14 * 16: + round(inv_rnd, b1, b0, rnd_key(-13)); + round(inv_rnd, b0, b1, rnd_key(-12)); + case 12 * 16: + round(inv_rnd, b1, b0, rnd_key(-11)); + round(inv_rnd, b0, b1, rnd_key(-10)); + case 10 * 16: + round(inv_rnd, b1, b0, rnd_key(-9)); + round(inv_rnd, b0, b1, rnd_key(-8)); + round(inv_rnd, b1, b0, rnd_key(-7)); + round(inv_rnd, b0, b1, rnd_key(-6)); + round(inv_rnd, b1, b0, rnd_key(-5)); + round(inv_rnd, b0, b1, rnd_key(-4)); + round(inv_rnd, b1, b0, rnd_key(-3)); + round(inv_rnd, b0, b1, rnd_key(-2)); + round(inv_rnd, b1, b0, rnd_key(-1)); + round(inv_lrnd, b0, b1, rnd_key( 0)); + } + +#else + +#if (DEC_UNROLL == PARTIAL) + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + kp = rnd_key(1); + round(inv_rnd, b0, b1, kp); + } + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); +#else + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp = rnd_key(1); + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/Crypto/Aeskey.c b/Crypto/Aeskey.c index 96933e2..55b6a3c 100644 --- a/Crypto/Aeskey.c +++ b/Crypto/Aeskey.c @@ -1,573 +1,573 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 20/12/2007 -*/ - -#include "Aesopt.h" -#include "Aestab.h" - -#ifdef USE_VIA_ACE_IF_PRESENT -# include "aes_via_ace.h" -#endif - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* Initialise the key schedule from the user supplied key. The key - length can be specified in bytes, with legal values of 16, 24 - and 32, or in bits, with legal values of 128, 192 and 256. These - values correspond with Nk values of 4, 6 and 8 respectively. - - The following macros implement a single cycle in the key - schedule generation process. The number of cycles needed - for each cx->n_col and nk value is: - - nk = 4 5 6 7 8 - ------------------------------ - cx->n_col = 4 10 9 8 7 7 - cx->n_col = 5 14 11 10 9 9 - cx->n_col = 6 19 15 12 11 11 - cx->n_col = 7 21 19 16 13 14 - cx->n_col = 8 29 23 19 17 14 -*/ - -#if (FUNCS_IN_C & ENC_KEYING_IN_C) - -#if defined(AES_128) || defined(AES_VAR) - -#define ke4(k,i) \ -{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ - k[4*(i)+5] = ss[1] ^= ss[0]; \ - k[4*(i)+6] = ss[2] ^= ss[1]; \ - k[4*(i)+7] = ss[3] ^= ss[2]; \ -} - -AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) -{ uint_32t ss[4]; - - cx->ks[0] = ss[0] = word_in(key, 0); - cx->ks[1] = ss[1] = word_in(key, 1); - cx->ks[2] = ss[2] = word_in(key, 2); - cx->ks[3] = ss[3] = word_in(key, 3); - -#if ENC_UNROLL == NONE - { uint_32t i; - for(i = 0; i < 9; ++i) - ke4(cx->ks, i); - } -#else - ke4(cx->ks, 0); ke4(cx->ks, 1); - ke4(cx->ks, 2); ke4(cx->ks, 3); - ke4(cx->ks, 4); ke4(cx->ks, 5); - ke4(cx->ks, 6); ke4(cx->ks, 7); - ke4(cx->ks, 8); -#endif - ke4(cx->ks, 9); - cx->inf.l = 0; - cx->inf.b[0] = 10 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if defined(AES_192) || defined(AES_VAR) - -#define kef6(k,i) \ -{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ - k[6*(i)+ 7] = ss[1] ^= ss[0]; \ - k[6*(i)+ 8] = ss[2] ^= ss[1]; \ - k[6*(i)+ 9] = ss[3] ^= ss[2]; \ -} - -#define ke6(k,i) \ -{ kef6(k,i); \ - k[6*(i)+10] = ss[4] ^= ss[3]; \ - k[6*(i)+11] = ss[5] ^= ss[4]; \ -} - -AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) -{ uint_32t ss[6]; - - cx->ks[0] = ss[0] = word_in(key, 0); - cx->ks[1] = ss[1] = word_in(key, 1); - cx->ks[2] = ss[2] = word_in(key, 2); - cx->ks[3] = ss[3] = word_in(key, 3); - cx->ks[4] = ss[4] = word_in(key, 4); - cx->ks[5] = ss[5] = word_in(key, 5); - -#if ENC_UNROLL == NONE - { uint_32t i; - for(i = 0; i < 7; ++i) - ke6(cx->ks, i); - } -#else - ke6(cx->ks, 0); ke6(cx->ks, 1); - ke6(cx->ks, 2); ke6(cx->ks, 3); - ke6(cx->ks, 4); ke6(cx->ks, 5); - ke6(cx->ks, 6); -#endif - kef6(cx->ks, 7); - cx->inf.l = 0; - cx->inf.b[0] = 12 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if defined(AES_256) || defined(AES_VAR) - -#define kef8(k,i) \ -{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ - k[8*(i)+ 9] = ss[1] ^= ss[0]; \ - k[8*(i)+10] = ss[2] ^= ss[1]; \ - k[8*(i)+11] = ss[3] ^= ss[2]; \ -} - -#define ke8(k,i) \ -{ kef8(k,i); \ - k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ - k[8*(i)+13] = ss[5] ^= ss[4]; \ - k[8*(i)+14] = ss[6] ^= ss[5]; \ - k[8*(i)+15] = ss[7] ^= ss[6]; \ -} - -AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) -{ uint_32t ss[8]; - - cx->ks[0] = ss[0] = word_in(key, 0); - cx->ks[1] = ss[1] = word_in(key, 1); - cx->ks[2] = ss[2] = word_in(key, 2); - cx->ks[3] = ss[3] = word_in(key, 3); - cx->ks[4] = ss[4] = word_in(key, 4); - cx->ks[5] = ss[5] = word_in(key, 5); - cx->ks[6] = ss[6] = word_in(key, 6); - cx->ks[7] = ss[7] = word_in(key, 7); - -#if ENC_UNROLL == NONE - { uint_32t i; - for(i = 0; i < 6; ++i) - ke8(cx->ks, i); - } -#else - ke8(cx->ks, 0); ke8(cx->ks, 1); - ke8(cx->ks, 2); ke8(cx->ks, 3); - ke8(cx->ks, 4); ke8(cx->ks, 5); -#endif - kef8(cx->ks, 6); - cx->inf.l = 0; - cx->inf.b[0] = 14 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if defined(AES_VAR) - -AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) -{ - switch(key_len) - { -#if defined( AES_ERR_CHK ) - case 16: case 128: return aes_encrypt_key128(key, cx); - case 24: case 192: return aes_encrypt_key192(key, cx); - case 32: case 256: return aes_encrypt_key256(key, cx); - default: return EXIT_FAILURE; -#else - case 16: case 128: aes_encrypt_key128(key, cx); return; - case 24: case 192: aes_encrypt_key192(key, cx); return; - case 32: case 256: aes_encrypt_key256(key, cx); return; -#endif - } -} - -#endif - -#endif - -#if (FUNCS_IN_C & DEC_KEYING_IN_C) - -/* this is used to store the decryption round keys */ -/* in forward or reverse order */ - -#ifdef AES_REV_DKS -#define v(n,i) ((n) - (i) + 2 * ((i) & 3)) -#else -#define v(n,i) (i) -#endif - -#if DEC_ROUND == NO_TABLES -#define ff(x) (x) -#else -#define ff(x) inv_mcol(x) -#if defined( dec_imvars ) -#define d_vars dec_imvars -#endif -#endif - -#if defined(AES_128) || defined(AES_VAR) - -#define k4e(k,i) \ -{ k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ - k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \ - k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \ - k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \ -} - -#if 1 - -#define kdf4(k,i) \ -{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ - ss[1] = ss[1] ^ ss[3]; \ - ss[2] = ss[2] ^ ss[3]; \ - ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ - ss[i % 4] ^= ss[4]; \ - ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \ - ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \ - ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \ - ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \ -} - -#define kd4(k,i) \ -{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ - ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ - k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \ - k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \ - k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \ - k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \ -} - -#define kdl4(k,i) \ -{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ - k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ - k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \ - k[v(40,(4*(i))+6)] = ss[0]; \ - k[v(40,(4*(i))+7)] = ss[1]; \ -} - -#else - -#define kdf4(k,i) \ -{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \ - ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \ - ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \ -} - -#define kd4(k,i) \ -{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ - ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \ - ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \ - ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \ - ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \ -} - -#define kdl4(k,i) \ -{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \ - ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \ - ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \ - ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \ -} - -#endif - -AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) -{ uint_32t ss[5]; -#if defined( d_vars ) - d_vars; -#endif - cx->ks[v(40,(0))] = ss[0] = word_in(key, 0); - cx->ks[v(40,(1))] = ss[1] = word_in(key, 1); - cx->ks[v(40,(2))] = ss[2] = word_in(key, 2); - cx->ks[v(40,(3))] = ss[3] = word_in(key, 3); - -#if DEC_UNROLL == NONE - { uint_32t i; - for(i = 0; i < 10; ++i) - k4e(cx->ks, i); -#if !(DEC_ROUND == NO_TABLES) - for(i = N_COLS; i < 10 * N_COLS; ++i) - cx->ks[i] = inv_mcol(cx->ks[i]); -#endif - } -#else - kdf4(cx->ks, 0); kd4(cx->ks, 1); - kd4(cx->ks, 2); kd4(cx->ks, 3); - kd4(cx->ks, 4); kd4(cx->ks, 5); - kd4(cx->ks, 6); kd4(cx->ks, 7); - kd4(cx->ks, 8); kdl4(cx->ks, 9); -#endif - cx->inf.l = 0; - cx->inf.b[0] = 10 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if defined(AES_192) || defined(AES_VAR) - -#define k6ef(k,i) \ -{ k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ - k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \ - k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \ - k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \ -} - -#define k6e(k,i) \ -{ k6ef(k,i); \ - k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \ - k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \ -} - -#define kdf6(k,i) \ -{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \ - ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \ - ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \ - ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \ - ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \ -} - -#define kd6(k,i) \ -{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ - ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \ - ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \ - ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \ - ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \ - ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \ - ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \ -} - -#define kdl6(k,i) \ -{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \ - ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \ - ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \ - ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \ -} - -AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) -{ uint_32t ss[7]; -#if defined( d_vars ) - d_vars; -#endif - cx->ks[v(48,(0))] = ss[0] = word_in(key, 0); - cx->ks[v(48,(1))] = ss[1] = word_in(key, 1); - cx->ks[v(48,(2))] = ss[2] = word_in(key, 2); - cx->ks[v(48,(3))] = ss[3] = word_in(key, 3); - -#if DEC_UNROLL == NONE - cx->ks[v(48,(4))] = ss[4] = word_in(key, 4); - cx->ks[v(48,(5))] = ss[5] = word_in(key, 5); - { uint_32t i; - - for(i = 0; i < 7; ++i) - k6e(cx->ks, i); - k6ef(cx->ks, 7); -#if !(DEC_ROUND == NO_TABLES) - for(i = N_COLS; i < 12 * N_COLS; ++i) - cx->ks[i] = inv_mcol(cx->ks[i]); -#endif - } -#else - cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4)); - cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5)); - kdf6(cx->ks, 0); kd6(cx->ks, 1); - kd6(cx->ks, 2); kd6(cx->ks, 3); - kd6(cx->ks, 4); kd6(cx->ks, 5); - kd6(cx->ks, 6); kdl6(cx->ks, 7); -#endif - cx->inf.l = 0; - cx->inf.b[0] = 12 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if defined(AES_256) || defined(AES_VAR) - -#define k8ef(k,i) \ -{ k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ - k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \ - k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \ - k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \ -} - -#define k8e(k,i) \ -{ k8ef(k,i); \ - k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \ - k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \ - k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \ - k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \ -} - -#define kdf8(k,i) \ -{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \ - ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \ - ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \ - ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \ - ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \ - ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \ - ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \ -} - -#define kd8(k,i) \ -{ ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ - ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \ - ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \ - ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \ - ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \ - ss[8] = ls_box(ss[3],0); \ - ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \ - ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \ - ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \ - ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \ -} - -#define kdl8(k,i) \ -{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \ - ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \ - ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \ - ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \ -} - -AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) -{ uint_32t ss[9]; -#if defined( d_vars ) - d_vars; -#endif - cx->ks[v(56,(0))] = ss[0] = word_in(key, 0); - cx->ks[v(56,(1))] = ss[1] = word_in(key, 1); - cx->ks[v(56,(2))] = ss[2] = word_in(key, 2); - cx->ks[v(56,(3))] = ss[3] = word_in(key, 3); - -#if DEC_UNROLL == NONE - cx->ks[v(56,(4))] = ss[4] = word_in(key, 4); - cx->ks[v(56,(5))] = ss[5] = word_in(key, 5); - cx->ks[v(56,(6))] = ss[6] = word_in(key, 6); - cx->ks[v(56,(7))] = ss[7] = word_in(key, 7); - { uint_32t i; - - for(i = 0; i < 6; ++i) - k8e(cx->ks, i); - k8ef(cx->ks, 6); -#if !(DEC_ROUND == NO_TABLES) - for(i = N_COLS; i < 14 * N_COLS; ++i) - cx->ks[i] = inv_mcol(cx->ks[i]); - -#endif - } -#else - cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4)); - cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5)); - cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6)); - cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7)); - kdf8(cx->ks, 0); kd8(cx->ks, 1); - kd8(cx->ks, 2); kd8(cx->ks, 3); - kd8(cx->ks, 4); kd8(cx->ks, 5); - kdl8(cx->ks, 6); -#endif - cx->inf.l = 0; - cx->inf.b[0] = 14 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - -#if defined( AES_ERR_CHK ) - return EXIT_SUCCESS; -#endif -} - -#endif - -#if defined(AES_VAR) - -AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) -{ - switch(key_len) - { -#if defined( AES_ERR_CHK ) - case 16: case 128: return aes_decrypt_key128(key, cx); - case 24: case 192: return aes_decrypt_key192(key, cx); - case 32: case 256: return aes_decrypt_key256(key, cx); - default: return EXIT_FAILURE; -#else - case 16: case 128: aes_decrypt_key128(key, cx); return; - case 24: case 192: aes_decrypt_key192(key, cx); return; - case 32: case 256: aes_decrypt_key256(key, cx); return; -#endif - } -} - -#endif - -#endif - -#if defined(__cplusplus) -} -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 +*/ + +#include "Aesopt.h" +#include "Aestab.h" + +#ifdef USE_VIA_ACE_IF_PRESENT +# include "aes_via_ace.h" +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Initialise the key schedule from the user supplied key. The key + length can be specified in bytes, with legal values of 16, 24 + and 32, or in bits, with legal values of 128, 192 and 256. These + values correspond with Nk values of 4, 6 and 8 respectively. + + The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_col and nk value is: + + nk = 4 5 6 7 8 + ------------------------------ + cx->n_col = 4 10 9 8 7 7 + cx->n_col = 5 14 11 10 9 9 + cx->n_col = 6 19 15 12 11 11 + cx->n_col = 7 21 19 16 13 14 + cx->n_col = 8 29 23 19 17 14 +*/ + +#if (FUNCS_IN_C & ENC_KEYING_IN_C) + +#if defined(AES_128) || defined(AES_VAR) + +#define ke4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; \ + k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[4]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + +#if ENC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 9; ++i) + ke4(cx->ks, i); + } +#else + ke4(cx->ks, 0); ke4(cx->ks, 1); + ke4(cx->ks, 2); ke4(cx->ks, 3); + ke4(cx->ks, 4); ke4(cx->ks, 5); + ke4(cx->ks, 6); ke4(cx->ks, 7); + ke4(cx->ks, 8); +#endif + ke4(cx->ks, 9); + cx->inf.l = 0; + cx->inf.b[0] = 10 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_192) || defined(AES_VAR) + +#define kef6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; \ + k[6*(i)+ 9] = ss[3] ^= ss[2]; \ +} + +#define ke6(k,i) \ +{ kef6(k,i); \ + k[6*(i)+10] = ss[4] ^= ss[3]; \ + k[6*(i)+11] = ss[5] ^= ss[4]; \ +} + +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[6]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + +#if ENC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 7; ++i) + ke6(cx->ks, i); + } +#else + ke6(cx->ks, 0); ke6(cx->ks, 1); + ke6(cx->ks, 2); ke6(cx->ks, 3); + ke6(cx->ks, 4); ke6(cx->ks, 5); + ke6(cx->ks, 6); +#endif + kef6(cx->ks, 7); + cx->inf.l = 0; + cx->inf.b[0] = 12 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_256) || defined(AES_VAR) + +#define kef8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; \ + k[8*(i)+11] = ss[3] ^= ss[2]; \ +} + +#define ke8(k,i) \ +{ kef8(k,i); \ + k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ + k[8*(i)+13] = ss[5] ^= ss[4]; \ + k[8*(i)+14] = ss[6] ^= ss[5]; \ + k[8*(i)+15] = ss[7] ^= ss[6]; \ +} + +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[8]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + cx->ks[6] = ss[6] = word_in(key, 6); + cx->ks[7] = ss[7] = word_in(key, 7); + +#if ENC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 6; ++i) + ke8(cx->ks, i); + } +#else + ke8(cx->ks, 0); ke8(cx->ks, 1); + ke8(cx->ks, 2); ke8(cx->ks, 3); + ke8(cx->ks, 4); ke8(cx->ks, 5); +#endif + kef8(cx->ks, 6); + cx->inf.l = 0; + cx->inf.b[0] = 14 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_VAR) + +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) +{ + switch(key_len) + { +#if defined( AES_ERR_CHK ) + case 16: case 128: return aes_encrypt_key128(key, cx); + case 24: case 192: return aes_encrypt_key192(key, cx); + case 32: case 256: return aes_encrypt_key256(key, cx); + default: return EXIT_FAILURE; +#else + case 16: case 128: aes_encrypt_key128(key, cx); return; + case 24: case 192: aes_encrypt_key192(key, cx); return; + case 32: case 256: aes_encrypt_key256(key, cx); return; +#endif + } +} + +#endif + +#endif + +#if (FUNCS_IN_C & DEC_KEYING_IN_C) + +/* this is used to store the decryption round keys */ +/* in forward or reverse order */ + +#ifdef AES_REV_DKS +#define v(n,i) ((n) - (i) + 2 * ((i) & 3)) +#else +#define v(n,i) (i) +#endif + +#if DEC_ROUND == NO_TABLES +#define ff(x) (x) +#else +#define ff(x) inv_mcol(x) +#if defined( dec_imvars ) +#define d_vars dec_imvars +#endif +#endif + +#if defined(AES_128) || defined(AES_VAR) + +#define k4e(k,i) \ +{ k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \ + k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \ + k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \ +} + +#if 1 + +#define kdf4(k,i) \ +{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ + ss[1] = ss[1] ^ ss[3]; \ + ss[2] = ss[2] ^ ss[3]; \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ + k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \ + k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \ + k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \ +} + +#define kdl4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ + k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ + k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \ + k[v(40,(4*(i))+6)] = ss[0]; \ + k[v(40,(4*(i))+7)] = ss[1]; \ +} + +#else + +#define kdf4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \ +} + +#define kdl4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \ +} + +#endif + +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[5]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(40,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(40,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(40,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(40,(3))] = ss[3] = word_in(key, 3); + +#if DEC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 10; ++i) + k4e(cx->ks, i); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 10 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#else + kdf4(cx->ks, 0); kd4(cx->ks, 1); + kd4(cx->ks, 2); kd4(cx->ks, 3); + kd4(cx->ks, 4); kd4(cx->ks, 5); + kd4(cx->ks, 6); kd4(cx->ks, 7); + kd4(cx->ks, 8); kdl4(cx->ks, 9); +#endif + cx->inf.l = 0; + cx->inf.b[0] = 10 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_192) || defined(AES_VAR) + +#define k6ef(k,i) \ +{ k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \ + k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \ + k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \ +} + +#define k6e(k,i) \ +{ k6ef(k,i); \ + k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \ + k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \ +} + +#define kdf6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \ +} + +#define kd6(k,i) \ +{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \ +} + +#define kdl6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \ +} + +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[7]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(48,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(48,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(48,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(48,(3))] = ss[3] = word_in(key, 3); + +#if DEC_UNROLL == NONE + cx->ks[v(48,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(48,(5))] = ss[5] = word_in(key, 5); + { uint_32t i; + + for(i = 0; i < 7; ++i) + k6e(cx->ks, i); + k6ef(cx->ks, 7); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 12 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#else + cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4)); + cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5)); + kdf6(cx->ks, 0); kd6(cx->ks, 1); + kd6(cx->ks, 2); kd6(cx->ks, 3); + kd6(cx->ks, 4); kd6(cx->ks, 5); + kd6(cx->ks, 6); kdl6(cx->ks, 7); +#endif + cx->inf.l = 0; + cx->inf.b[0] = 12 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_256) || defined(AES_VAR) + +#define k8ef(k,i) \ +{ k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \ + k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \ + k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \ +} + +#define k8e(k,i) \ +{ k8ef(k,i); \ + k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \ + k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \ + k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \ + k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \ +} + +#define kdf8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \ +} + +#define kd8(k,i) \ +{ ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \ + ss[8] = ls_box(ss[3],0); \ + ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \ +} + +#define kdl8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \ +} + +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[9]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(56,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(56,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(56,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(56,(3))] = ss[3] = word_in(key, 3); + +#if DEC_UNROLL == NONE + cx->ks[v(56,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(56,(5))] = ss[5] = word_in(key, 5); + cx->ks[v(56,(6))] = ss[6] = word_in(key, 6); + cx->ks[v(56,(7))] = ss[7] = word_in(key, 7); + { uint_32t i; + + for(i = 0; i < 6; ++i) + k8e(cx->ks, i); + k8ef(cx->ks, 6); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 14 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); + +#endif + } +#else + cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4)); + cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5)); + cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6)); + cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7)); + kdf8(cx->ks, 0); kd8(cx->ks, 1); + kd8(cx->ks, 2); kd8(cx->ks, 3); + kd8(cx->ks, 4); kd8(cx->ks, 5); + kdl8(cx->ks, 6); +#endif + cx->inf.l = 0; + cx->inf.b[0] = 14 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_VAR) + +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) +{ + switch(key_len) + { +#if defined( AES_ERR_CHK ) + case 16: case 128: return aes_decrypt_key128(key, cx); + case 24: case 192: return aes_decrypt_key192(key, cx); + case 32: case 256: return aes_decrypt_key256(key, cx); + default: return EXIT_FAILURE; +#else + case 16: case 128: aes_decrypt_key128(key, cx); return; + case 24: case 192: aes_decrypt_key192(key, cx); return; + case 32: case 256: aes_decrypt_key256(key, cx); return; +#endif + } +} + +#endif + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/Crypto/Aesopt.h b/Crypto/Aesopt.h index 0761a2e..1589404 100644 --- a/Crypto/Aesopt.h +++ b/Crypto/Aesopt.h @@ -1,734 +1,734 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 20/12/2007 - - This file contains the compilation options for AES (Rijndael) and code - that is common across encryption, key scheduling and table generation. - - OPERATION - - These source code files implement the AES algorithm Rijndael designed by - Joan Daemen and Vincent Rijmen. This version is designed for the standard - block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 - and 32 bytes). - - This version is designed for flexibility and speed using operations on - 32-bit words rather than operations on bytes. It can be compiled with - either big or little endian internal byte order but is faster when the - native byte order for the processor is used. - - THE CIPHER INTERFACE - - The cipher interface is implemented as an array of bytes in which lower - AES bit sequence indexes map to higher numeric significance within bytes. - - uint_8t (an unsigned 8-bit type) - uint_32t (an unsigned 32-bit type) - struct aes_encrypt_ctx (structure for the cipher encryption context) - struct aes_decrypt_ctx (structure for the cipher decryption context) - AES_RETURN the function return type - - C subroutine calls: - - AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); - AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); - AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); - AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, - const aes_encrypt_ctx cx[1]); - - AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); - AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); - AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); - AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, - const aes_decrypt_ctx cx[1]); - - IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that - you call aes_init() before AES is used so that the tables are initialised. - - C++ aes class subroutines: - - Class AESencrypt for encryption - - Construtors: - AESencrypt(void) - AESencrypt(const unsigned char *key) - 128 bit key - Members: - AES_RETURN key128(const unsigned char *key) - AES_RETURN key192(const unsigned char *key) - AES_RETURN key256(const unsigned char *key) - AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const - - Class AESdecrypt for encryption - Construtors: - AESdecrypt(void) - AESdecrypt(const unsigned char *key) - 128 bit key - Members: - AES_RETURN key128(const unsigned char *key) - AES_RETURN key192(const unsigned char *key) - AES_RETURN key256(const unsigned char *key) - AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const -*/ - -/* Adapted for TrueCrypt by the TrueCrypt Foundation */ - -#if !defined( _AESOPT_H ) -#define _AESOPT_H - -#ifdef TC_WINDOWS_BOOT -#define ASM_X86_V2 -#endif - -#if defined( __cplusplus ) -#include "Aescpp.h" -#else -#include "Aes.h" -#endif - - -#include "Common/Endian.h" -#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ -#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ - -#if BYTE_ORDER == LITTLE_ENDIAN -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#endif - -#if BYTE_ORDER == BIG_ENDIAN -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -#endif - - -/* CONFIGURATION - THE USE OF DEFINES - - Later in this section there are a number of defines that control the - operation of the code. In each section, the purpose of each define is - explained so that the relevant form can be included or excluded by - setting either 1's or 0's respectively on the branches of the related - #if clauses. The following local defines should not be changed. -*/ - -#define ENCRYPTION_IN_C 1 -#define DECRYPTION_IN_C 2 -#define ENC_KEYING_IN_C 4 -#define DEC_KEYING_IN_C 8 - -#define NO_TABLES 0 -#define ONE_TABLE 1 -#define FOUR_TABLES 4 -#define NONE 0 -#define PARTIAL 1 -#define FULL 2 - -/* --- START OF USER CONFIGURED OPTIONS --- */ - -/* 1. BYTE ORDER WITHIN 32 BIT WORDS - - The fundamental data processing units in Rijndael are 8-bit bytes. The - input, output and key input are all enumerated arrays of bytes in which - bytes are numbered starting at zero and increasing to one less than the - number of bytes in the array in question. This enumeration is only used - for naming bytes and does not imply any adjacency or order relationship - from one byte to another. When these inputs and outputs are considered - as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to - byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. - In this implementation bits are numbered from 0 to 7 starting at the - numerically least significant end of each byte (bit n represents 2^n). - - However, Rijndael can be implemented more efficiently using 32-bit - words by packing bytes into words so that bytes 4*n to 4*n+3 are placed - into word[n]. While in principle these bytes can be assembled into words - in any positions, this implementation only supports the two formats in - which bytes in adjacent positions within words also have adjacent byte - numbers. This order is called big-endian if the lowest numbered bytes - in words have the highest numeric significance and little-endian if the - opposite applies. - - This code can work in either order irrespective of the order used by the - machine on which it runs. Normally the internal byte order will be set - to the order of the processor on which the code is to be run but this - define can be used to reverse this in special situations - - WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. - This define will hence be redefined later (in section 4) if necessary -*/ - -#if 1 -#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER -#elif 0 -#define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN -#elif 0 -#define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN -#else -#error The algorithm byte order is not defined -#endif - -/* 2. VIA ACE SUPPORT - - Define this option if support for the VIA ACE is required. This uses - inline assembler instructions and is only implemented for the Microsoft, - Intel and GCC compilers. If VIA ACE is known to be present, then defining - ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption - code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if - it is detected (both present and enabled) but the normal AES code will - also be present. - - When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte - aligned; other input/output buffers do not need to be 16 byte aligned - but there are very large performance gains if this can be arranged. - VIA ACE also requires the decryption key schedule to be in reverse - order (which later checks below ensure). -*/ - -#if 0 && !defined( USE_VIA_ACE_IF_PRESENT ) -# define USE_VIA_ACE_IF_PRESENT -#endif - -#if 0 && !defined( ASSUME_VIA_ACE_PRESENT ) -# define ASSUME_VIA_ACE_PRESENT -# endif - -#if defined ( _WIN64 ) || defined( _WIN32_WCE ) || \ - defined( _MSC_VER ) && ( _MSC_VER <= 800 ) -# if defined( USE_VIA_ACE_IF_PRESENT ) -# undef USE_VIA_ACE_IF_PRESENT -# endif -# if defined( ASSUME_VIA_ACE_PRESENT ) -# undef ASSUME_VIA_ACE_PRESENT -# endif -#endif - -/* 3. ASSEMBLER SUPPORT - - This define (which can be on the command line) enables the use of the - assembler code routines for encryption, decryption and key scheduling - as follows: - - ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for - encryption and decryption and but with key scheduling in C - ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for - encryption, decryption and key scheduling - ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for - encryption and decryption and but with key scheduling in C - ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for - encryption and decryption and but with key scheduling in C - - Change one 'if 0' below to 'if 1' to select the version or define - as a compilation option. -*/ - -#if 0 && !defined( ASM_X86_V1C ) -# define ASM_X86_V1C -#elif 0 && !defined( ASM_X86_V2 ) -# define ASM_X86_V2 -#elif 0 && !defined( ASM_X86_V2C ) -# define ASM_X86_V2C -#elif 0 && !defined( ASM_AMD64_C ) -# define ASM_AMD64_C -#endif - -#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \ - && !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 ) -//# error Assembler code is only available for x86 and AMD64 systems -#endif - -/* 4. FAST INPUT/OUTPUT OPERATIONS. - - On some machines it is possible to improve speed by transferring the - bytes in the input and output arrays to and from the internal 32-bit - variables by addressing these arrays as if they are arrays of 32-bit - words. On some machines this will always be possible but there may - be a large performance penalty if the byte arrays are not aligned on - the normal word boundaries. On other machines this technique will - lead to memory access errors when such 32-bit word accesses are not - properly aligned. The option SAFE_IO avoids such problems but will - often be slower on those machines that support misaligned access - (especially so if care is taken to align the input and output byte - arrays on 32-bit word boundaries). If SAFE_IO is not defined it is - assumed that access to byte arrays as if they are arrays of 32-bit - words will not cause problems when such accesses are misaligned. -*/ -#if 1 && !defined( _MSC_VER ) -#define SAFE_IO -#endif - -/* 5. LOOP UNROLLING - - The code for encryption and decrytpion cycles through a number of rounds - that can be implemented either in a loop or by expanding the code into a - long sequence of instructions, the latter producing a larger program but - one that will often be much faster. The latter is called loop unrolling. - There are also potential speed advantages in expanding two iterations in - a loop with half the number of iterations, which is called partial loop - unrolling. The following options allow partial or full loop unrolling - to be set independently for encryption and decryption -*/ -#if 1 -#define ENC_UNROLL FULL -#elif 0 -#define ENC_UNROLL PARTIAL -#else -#define ENC_UNROLL NONE -#endif - -#if 1 -#define DEC_UNROLL FULL -#elif 0 -#define DEC_UNROLL PARTIAL -#else -#define DEC_UNROLL NONE -#endif - -/* 6. FAST FINITE FIELD OPERATIONS - - If this section is included, tables are used to provide faster finite - field arithmetic (this has no effect if FIXED_TABLES is defined). -*/ -#if !defined (TC_WINDOWS_BOOT) -#define FF_TABLES -#endif - -/* 7. INTERNAL STATE VARIABLE FORMAT - - The internal state of Rijndael is stored in a number of local 32-bit - word varaibles which can be defined either as an array or as individual - names variables. Include this section if you want to store these local - varaibles in arrays. Otherwise individual local variables will be used. -*/ -#if 1 -#define ARRAYS -#endif - -/* 8. FIXED OR DYNAMIC TABLES - - When this section is included the tables used by the code are compiled - statically into the binary file. Otherwise the subroutine aes_init() - must be called to compute them before the code is first used. -*/ -#if !defined (TC_WINDOWS_BOOT) && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 )) -#define FIXED_TABLES -#endif - -/* 9. TABLE ALIGNMENT - - On some sytsems speed will be improved by aligning the AES large lookup - tables on particular boundaries. This define should be set to a power of - two giving the desired alignment. It can be left undefined if alignment - is not needed. This option is specific to the Microsft VC++ compiler - - it seems to sometimes cause trouble for the VC++ version 6 compiler. -*/ - -#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) -#define TABLE_ALIGN 32 -#endif - -/* 10. TABLE OPTIONS - - This cipher proceeds by repeating in a number of cycles known as 'rounds' - which are implemented by a round function which can optionally be speeded - up using tables. The basic tables are each 256 32-bit words, with either - one or four tables being required for each round function depending on - how much speed is required. The encryption and decryption round functions - are different and the last encryption and decrytpion round functions are - different again making four different round functions in all. - - This means that: - 1. Normal encryption and decryption rounds can each use either 0, 1 - or 4 tables and table spaces of 0, 1024 or 4096 bytes each. - 2. The last encryption and decryption rounds can also use either 0, 1 - or 4 tables and table spaces of 0, 1024 or 4096 bytes each. - - Include or exclude the appropriate definitions below to set the number - of tables used by this implementation. -*/ - -#if 1 /* set tables for the normal encryption round */ -#define ENC_ROUND FOUR_TABLES -#elif 0 -#define ENC_ROUND ONE_TABLE -#else -#define ENC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the last encryption round */ -#define LAST_ENC_ROUND FOUR_TABLES -#elif 0 -#define LAST_ENC_ROUND ONE_TABLE -#else -#define LAST_ENC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the normal decryption round */ -#define DEC_ROUND FOUR_TABLES -#elif 0 -#define DEC_ROUND ONE_TABLE -#else -#define DEC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the last decryption round */ -#define LAST_DEC_ROUND FOUR_TABLES -#elif 0 -#define LAST_DEC_ROUND ONE_TABLE -#else -#define LAST_DEC_ROUND NO_TABLES -#endif - -/* The decryption key schedule can be speeded up with tables in the same - way that the round functions can. Include or exclude the following - defines to set this requirement. -*/ -#if 1 -#define KEY_SCHED FOUR_TABLES -#elif 0 -#define KEY_SCHED ONE_TABLE -#else -#define KEY_SCHED NO_TABLES -#endif - -/* ---- END OF USER CONFIGURED OPTIONS ---- */ - -/* VIA ACE support is only available for VC++ and GCC */ - -#if !defined( _MSC_VER ) && !defined( __GNUC__ ) -# if defined( ASSUME_VIA_ACE_PRESENT ) -# undef ASSUME_VIA_ACE_PRESENT -# endif -# if defined( USE_VIA_ACE_IF_PRESENT ) -# undef USE_VIA_ACE_IF_PRESENT -# endif -#endif - -#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT ) -#define USE_VIA_ACE_IF_PRESENT -#endif - -#if defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS ) -#define AES_REV_DKS -#endif - -/* Assembler support requires the use of platform byte order */ - -#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \ - && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) -#undef ALGORITHM_BYTE_ORDER -#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER -#endif - -/* In this implementation the columns of the state array are each held in - 32-bit words. The state array can be held in various ways: in an array - of words, in a number of individual word variables or in a number of - processor registers. The following define maps a variable name x and - a column number c to the way the state array variable is to be held. - The first define below maps the state into an array x[c] whereas the - second form maps the state into a number of individual variables x0, - x1, etc. Another form could map individual state colums to machine - register names. -*/ - -#if defined( ARRAYS ) -#define s(x,c) x[c] -#else -#define s(x,c) x##c -#endif - -/* This implementation provides subroutines for encryption, decryption - and for setting the three key lengths (separately) for encryption - and decryption. Since not all functions are needed, masks are set - up here to determine which will be implemented in C -*/ - -#if !defined( AES_ENCRYPT ) -# define EFUNCS_IN_C 0 -#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ - || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) -# define EFUNCS_IN_C ENC_KEYING_IN_C -#elif !defined( ASM_X86_V2 ) -# define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C ) -#else -# define EFUNCS_IN_C 0 -#endif - -#if !defined( AES_DECRYPT ) -# define DFUNCS_IN_C 0 -#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ - || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) -# define DFUNCS_IN_C DEC_KEYING_IN_C -#elif !defined( ASM_X86_V2 ) -# define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C ) -#else -# define DFUNCS_IN_C 0 -#endif - -#define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C ) - -/* END OF CONFIGURATION OPTIONS */ - -#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) - -/* Disable or report errors on some combinations of options */ - -#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES -#undef LAST_ENC_ROUND -#define LAST_ENC_ROUND NO_TABLES -#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES -#undef LAST_ENC_ROUND -#define LAST_ENC_ROUND ONE_TABLE -#endif - -#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE -#undef ENC_UNROLL -#define ENC_UNROLL NONE -#endif - -#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES -#undef LAST_DEC_ROUND -#define LAST_DEC_ROUND NO_TABLES -#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES -#undef LAST_DEC_ROUND -#define LAST_DEC_ROUND ONE_TABLE -#endif - -#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE -#undef DEC_UNROLL -#define DEC_UNROLL NONE -#endif - -#if defined( bswap32 ) -#define aes_sw32 bswap32 -#elif defined( bswap_32 ) -#define aes_sw32 bswap_32 -#else -#define brot(x,n) (((uint_32t)(x) << n) | ((uint_32t)(x) >> (32 - n))) -#define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) -#endif - -/* upr(x,n): rotates bytes within words by n positions, moving bytes to - higher index positions with wrap around into low positions - ups(x,n): moves bytes by n positions to higher index positions in - words but without wrap around - bval(x,n): extracts a byte from a word - - WARNING: The definitions given here are intended only for use with - unsigned variables and with shift counts that are compile - time constants -*/ - -#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN ) -#define upr(x,n) (((uint_32t)(x) << (8 * (n))) | ((uint_32t)(x) >> (32 - 8 * (n)))) -#define ups(x,n) ((uint_32t) (x) << (8 * (n))) -#define bval(x,n) ((uint_8t)((x) >> (8 * (n)))) -#define bytes2word(b0, b1, b2, b3) \ - (((uint_32t)(b3) << 24) | ((uint_32t)(b2) << 16) | ((uint_32t)(b1) << 8) | (b0)) -#endif - -#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN ) -#define upr(x,n) (((uint_32t)(x) >> (8 * (n))) | ((uint_32t)(x) << (32 - 8 * (n)))) -#define ups(x,n) ((uint_32t) (x) >> (8 * (n))) -#define bval(x,n) ((uint_8t)((x) >> (24 - 8 * (n)))) -#define bytes2word(b0, b1, b2, b3) \ - (((uint_32t)(b0) << 24) | ((uint_32t)(b1) << 16) | ((uint_32t)(b2) << 8) | (b3)) -#endif - -#if defined( SAFE_IO ) - -#define word_in(x,c) bytes2word(((const uint_8t*)(x)+4*c)[0], ((const uint_8t*)(x)+4*c)[1], \ - ((const uint_8t*)(x)+4*c)[2], ((const uint_8t*)(x)+4*c)[3]) -#define word_out(x,c,v) { ((uint_8t*)(x)+4*c)[0] = bval(v,0); ((uint_8t*)(x)+4*c)[1] = bval(v,1); \ - ((uint_8t*)(x)+4*c)[2] = bval(v,2); ((uint_8t*)(x)+4*c)[3] = bval(v,3); } - -#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER ) - -#define word_in(x,c) (*((uint_32t*)(x)+(c))) -#define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = (v)) - -#else - -#define word_in(x,c) aes_sw32(*((uint_32t*)(x)+(c))) -#define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = aes_sw32(v)) - -#endif - -/* the finite field modular polynomial and elements */ - -#define WPOLY 0x011b -#define BPOLY 0x1b - -/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ - -#define m1 0x80808080 -#define m2 0x7f7f7f7f -#define gf_mulx(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) - -/* The following defines provide alternative definitions of gf_mulx that might - give improved performance if a fast 32-bit multiply is not available. Note - that a temporary variable u needs to be defined where gf_mulx is used. - -#define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) -#define m4 (0x01010101 * BPOLY) -#define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) -*/ - -/* Work out which tables are needed for the different options */ - -#if defined( ASM_X86_V1C ) -#if defined( ENC_ROUND ) -#undef ENC_ROUND -#endif -#define ENC_ROUND FOUR_TABLES -#if defined( LAST_ENC_ROUND ) -#undef LAST_ENC_ROUND -#endif -#define LAST_ENC_ROUND FOUR_TABLES -#if defined( DEC_ROUND ) -#undef DEC_ROUND -#endif -#define DEC_ROUND FOUR_TABLES -#if defined( LAST_DEC_ROUND ) -#undef LAST_DEC_ROUND -#endif -#define LAST_DEC_ROUND FOUR_TABLES -#if defined( KEY_SCHED ) -#undef KEY_SCHED -#define KEY_SCHED FOUR_TABLES -#endif -#endif - -#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C ) -#if ENC_ROUND == ONE_TABLE -#define FT1_SET -#elif ENC_ROUND == FOUR_TABLES -#define FT4_SET -#else -#define SBX_SET -#endif -#if LAST_ENC_ROUND == ONE_TABLE -#define FL1_SET -#elif LAST_ENC_ROUND == FOUR_TABLES -#define FL4_SET -#elif !defined( SBX_SET ) -#define SBX_SET -#endif -#endif - -#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C ) -#if DEC_ROUND == ONE_TABLE -#define IT1_SET -#elif DEC_ROUND == FOUR_TABLES -#define IT4_SET -#else -#define ISB_SET -#endif -#if LAST_DEC_ROUND == ONE_TABLE -#define IL1_SET -#elif LAST_DEC_ROUND == FOUR_TABLES -#define IL4_SET -#elif !defined(ISB_SET) -#define ISB_SET -#endif -#endif - -#if (FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C) -#if KEY_SCHED == ONE_TABLE -#define LS1_SET -#elif KEY_SCHED == FOUR_TABLES -#define LS4_SET -#elif !defined( SBX_SET ) -#define SBX_SET -#endif -#endif - -#if (FUNCS_IN_C & DEC_KEYING_IN_C) -#if KEY_SCHED == ONE_TABLE -#define IM1_SET -#elif KEY_SCHED == FOUR_TABLES -#define IM4_SET -#elif !defined( SBX_SET ) -#define SBX_SET -#endif -#endif - -/* generic definitions of Rijndael macros that use tables */ - -#define no_table(x,box,vf,rf,c) bytes2word( \ - box[bval(vf(x,0,c),rf(0,c))], \ - box[bval(vf(x,1,c),rf(1,c))], \ - box[bval(vf(x,2,c),rf(2,c))], \ - box[bval(vf(x,3,c),rf(3,c))]) - -#define one_table(x,op,tab,vf,rf,c) \ - ( tab[bval(vf(x,0,c),rf(0,c))] \ - ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ - ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ - ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) - -#define four_tables(x,tab,vf,rf,c) \ - ( tab[0][bval(vf(x,0,c),rf(0,c))] \ - ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ - ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ - ^ tab[3][bval(vf(x,3,c),rf(3,c))]) - -#define vf1(x,r,c) (x) -#define rf1(r,c) (r) -#define rf2(r,c) ((8+r-c)&3) - -/* perform forward and inverse column mix operation on four bytes in long word x in */ -/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ - -#if defined( FM4_SET ) /* not currently used */ -#define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) -#elif defined( FM1_SET ) /* not currently used */ -#define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) -#else -#define dec_fmvars uint_32t g2 -#define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) -#endif - -#if defined( IM4_SET ) -#define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) -#elif defined( IM1_SET ) -#define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) -#else -#define dec_imvars uint_32t g2, g4, g9 -#define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ - (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) -#endif - -#if defined( FL4_SET ) -#define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) -#elif defined( LS4_SET ) -#define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) -#elif defined( FL1_SET ) -#define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) -#elif defined( LS1_SET ) -#define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) -#else -#define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) -#endif - -#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET ) -#define ISB_SET -#endif - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + + This file contains the compilation options for AES (Rijndael) and code + that is common across encryption, key scheduling and table generation. + + OPERATION + + These source code files implement the AES algorithm Rijndael designed by + Joan Daemen and Vincent Rijmen. This version is designed for the standard + block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 + and 32 bytes). + + This version is designed for flexibility and speed using operations on + 32-bit words rather than operations on bytes. It can be compiled with + either big or little endian internal byte order but is faster when the + native byte order for the processor is used. + + THE CIPHER INTERFACE + + The cipher interface is implemented as an array of bytes in which lower + AES bit sequence indexes map to higher numeric significance within bytes. + + uint_8t (an unsigned 8-bit type) + uint_32t (an unsigned 32-bit type) + struct aes_encrypt_ctx (structure for the cipher encryption context) + struct aes_decrypt_ctx (structure for the cipher decryption context) + AES_RETURN the function return type + + C subroutine calls: + + AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, + const aes_encrypt_ctx cx[1]); + + AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, + const aes_decrypt_ctx cx[1]); + + IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that + you call aes_init() before AES is used so that the tables are initialised. + + C++ aes class subroutines: + + Class AESencrypt for encryption + + Construtors: + AESencrypt(void) + AESencrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const + + Class AESdecrypt for encryption + Construtors: + AESdecrypt(void) + AESdecrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#if !defined( _AESOPT_H ) +#define _AESOPT_H + +#ifdef TC_WINDOWS_BOOT +#define ASM_X86_V2 +#endif + +#if defined( __cplusplus ) +#include "Aescpp.h" +#else +#include "Aes.h" +#endif + + +#include "Common/Endian.h" +#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#endif + + +/* CONFIGURATION - THE USE OF DEFINES + + Later in this section there are a number of defines that control the + operation of the code. In each section, the purpose of each define is + explained so that the relevant form can be included or excluded by + setting either 1's or 0's respectively on the branches of the related + #if clauses. The following local defines should not be changed. +*/ + +#define ENCRYPTION_IN_C 1 +#define DECRYPTION_IN_C 2 +#define ENC_KEYING_IN_C 4 +#define DEC_KEYING_IN_C 8 + +#define NO_TABLES 0 +#define ONE_TABLE 1 +#define FOUR_TABLES 4 +#define NONE 0 +#define PARTIAL 1 +#define FULL 2 + +/* --- START OF USER CONFIGURED OPTIONS --- */ + +/* 1. BYTE ORDER WITHIN 32 BIT WORDS + + The fundamental data processing units in Rijndael are 8-bit bytes. The + input, output and key input are all enumerated arrays of bytes in which + bytes are numbered starting at zero and increasing to one less than the + number of bytes in the array in question. This enumeration is only used + for naming bytes and does not imply any adjacency or order relationship + from one byte to another. When these inputs and outputs are considered + as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to + byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. + In this implementation bits are numbered from 0 to 7 starting at the + numerically least significant end of each byte (bit n represents 2^n). + + However, Rijndael can be implemented more efficiently using 32-bit + words by packing bytes into words so that bytes 4*n to 4*n+3 are placed + into word[n]. While in principle these bytes can be assembled into words + in any positions, this implementation only supports the two formats in + which bytes in adjacent positions within words also have adjacent byte + numbers. This order is called big-endian if the lowest numbered bytes + in words have the highest numeric significance and little-endian if the + opposite applies. + + This code can work in either order irrespective of the order used by the + machine on which it runs. Normally the internal byte order will be set + to the order of the processor on which the code is to be run but this + define can be used to reverse this in special situations + + WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. + This define will hence be redefined later (in section 4) if necessary +*/ + +#if 1 +#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#elif 0 +#define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 +#define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN +#else +#error The algorithm byte order is not defined +#endif + +/* 2. VIA ACE SUPPORT + + Define this option if support for the VIA ACE is required. This uses + inline assembler instructions and is only implemented for the Microsoft, + Intel and GCC compilers. If VIA ACE is known to be present, then defining + ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption + code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if + it is detected (both present and enabled) but the normal AES code will + also be present. + + When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte + aligned; other input/output buffers do not need to be 16 byte aligned + but there are very large performance gains if this can be arranged. + VIA ACE also requires the decryption key schedule to be in reverse + order (which later checks below ensure). +*/ + +#if 0 && !defined( USE_VIA_ACE_IF_PRESENT ) +# define USE_VIA_ACE_IF_PRESENT +#endif + +#if 0 && !defined( ASSUME_VIA_ACE_PRESENT ) +# define ASSUME_VIA_ACE_PRESENT +# endif + +#if defined ( _WIN64 ) || defined( _WIN32_WCE ) || \ + defined( _MSC_VER ) && ( _MSC_VER <= 800 ) +# if defined( USE_VIA_ACE_IF_PRESENT ) +# undef USE_VIA_ACE_IF_PRESENT +# endif +# if defined( ASSUME_VIA_ACE_PRESENT ) +# undef ASSUME_VIA_ACE_PRESENT +# endif +#endif + +/* 3. ASSEMBLER SUPPORT + + This define (which can be on the command line) enables the use of the + assembler code routines for encryption, decryption and key scheduling + as follows: + + ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for + encryption and decryption and but with key scheduling in C + ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for + encryption, decryption and key scheduling + ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + + Change one 'if 0' below to 'if 1' to select the version or define + as a compilation option. +*/ + +#if 0 && !defined( ASM_X86_V1C ) +# define ASM_X86_V1C +#elif 0 && !defined( ASM_X86_V2 ) +# define ASM_X86_V2 +#elif 0 && !defined( ASM_X86_V2C ) +# define ASM_X86_V2C +#elif 0 && !defined( ASM_AMD64_C ) +# define ASM_AMD64_C +#endif + +#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \ + && !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 ) +//# error Assembler code is only available for x86 and AMD64 systems +#endif + +/* 4. FAST INPUT/OUTPUT OPERATIONS. + + On some machines it is possible to improve speed by transferring the + bytes in the input and output arrays to and from the internal 32-bit + variables by addressing these arrays as if they are arrays of 32-bit + words. On some machines this will always be possible but there may + be a large performance penalty if the byte arrays are not aligned on + the normal word boundaries. On other machines this technique will + lead to memory access errors when such 32-bit word accesses are not + properly aligned. The option SAFE_IO avoids such problems but will + often be slower on those machines that support misaligned access + (especially so if care is taken to align the input and output byte + arrays on 32-bit word boundaries). If SAFE_IO is not defined it is + assumed that access to byte arrays as if they are arrays of 32-bit + words will not cause problems when such accesses are misaligned. +*/ +#if 1 && !defined( _MSC_VER ) +#define SAFE_IO +#endif + +/* 5. LOOP UNROLLING + + The code for encryption and decrytpion cycles through a number of rounds + that can be implemented either in a loop or by expanding the code into a + long sequence of instructions, the latter producing a larger program but + one that will often be much faster. The latter is called loop unrolling. + There are also potential speed advantages in expanding two iterations in + a loop with half the number of iterations, which is called partial loop + unrolling. The following options allow partial or full loop unrolling + to be set independently for encryption and decryption +*/ +#if 1 +#define ENC_UNROLL FULL +#elif 0 +#define ENC_UNROLL PARTIAL +#else +#define ENC_UNROLL NONE +#endif + +#if 1 +#define DEC_UNROLL FULL +#elif 0 +#define DEC_UNROLL PARTIAL +#else +#define DEC_UNROLL NONE +#endif + +/* 6. FAST FINITE FIELD OPERATIONS + + If this section is included, tables are used to provide faster finite + field arithmetic (this has no effect if FIXED_TABLES is defined). +*/ +#if !defined (TC_WINDOWS_BOOT) +#define FF_TABLES +#endif + +/* 7. INTERNAL STATE VARIABLE FORMAT + + The internal state of Rijndael is stored in a number of local 32-bit + word varaibles which can be defined either as an array or as individual + names variables. Include this section if you want to store these local + varaibles in arrays. Otherwise individual local variables will be used. +*/ +#if 1 +#define ARRAYS +#endif + +/* 8. FIXED OR DYNAMIC TABLES + + When this section is included the tables used by the code are compiled + statically into the binary file. Otherwise the subroutine aes_init() + must be called to compute them before the code is first used. +*/ +#if !defined (TC_WINDOWS_BOOT) && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 )) +#define FIXED_TABLES +#endif + +/* 9. TABLE ALIGNMENT + + On some sytsems speed will be improved by aligning the AES large lookup + tables on particular boundaries. This define should be set to a power of + two giving the desired alignment. It can be left undefined if alignment + is not needed. This option is specific to the Microsft VC++ compiler - + it seems to sometimes cause trouble for the VC++ version 6 compiler. +*/ + +#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) +#define TABLE_ALIGN 32 +#endif + +/* 10. TABLE OPTIONS + + This cipher proceeds by repeating in a number of cycles known as 'rounds' + which are implemented by a round function which can optionally be speeded + up using tables. The basic tables are each 256 32-bit words, with either + one or four tables being required for each round function depending on + how much speed is required. The encryption and decryption round functions + are different and the last encryption and decrytpion round functions are + different again making four different round functions in all. + + This means that: + 1. Normal encryption and decryption rounds can each use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + 2. The last encryption and decryption rounds can also use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + + Include or exclude the appropriate definitions below to set the number + of tables used by this implementation. +*/ + +#if 1 /* set tables for the normal encryption round */ +#define ENC_ROUND FOUR_TABLES +#elif 0 +#define ENC_ROUND ONE_TABLE +#else +#define ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last encryption round */ +#define LAST_ENC_ROUND FOUR_TABLES +#elif 0 +#define LAST_ENC_ROUND ONE_TABLE +#else +#define LAST_ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the normal decryption round */ +#define DEC_ROUND FOUR_TABLES +#elif 0 +#define DEC_ROUND ONE_TABLE +#else +#define DEC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last decryption round */ +#define LAST_DEC_ROUND FOUR_TABLES +#elif 0 +#define LAST_DEC_ROUND ONE_TABLE +#else +#define LAST_DEC_ROUND NO_TABLES +#endif + +/* The decryption key schedule can be speeded up with tables in the same + way that the round functions can. Include or exclude the following + defines to set this requirement. +*/ +#if 1 +#define KEY_SCHED FOUR_TABLES +#elif 0 +#define KEY_SCHED ONE_TABLE +#else +#define KEY_SCHED NO_TABLES +#endif + +/* ---- END OF USER CONFIGURED OPTIONS ---- */ + +/* VIA ACE support is only available for VC++ and GCC */ + +#if !defined( _MSC_VER ) && !defined( __GNUC__ ) +# if defined( ASSUME_VIA_ACE_PRESENT ) +# undef ASSUME_VIA_ACE_PRESENT +# endif +# if defined( USE_VIA_ACE_IF_PRESENT ) +# undef USE_VIA_ACE_IF_PRESENT +# endif +#endif + +#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT ) +#define USE_VIA_ACE_IF_PRESENT +#endif + +#if defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS ) +#define AES_REV_DKS +#endif + +/* Assembler support requires the use of platform byte order */ + +#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \ + && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) +#undef ALGORITHM_BYTE_ORDER +#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#endif + +/* In this implementation the columns of the state array are each held in + 32-bit words. The state array can be held in various ways: in an array + of words, in a number of individual word variables or in a number of + processor registers. The following define maps a variable name x and + a column number c to the way the state array variable is to be held. + The first define below maps the state into an array x[c] whereas the + second form maps the state into a number of individual variables x0, + x1, etc. Another form could map individual state colums to machine + register names. +*/ + +#if defined( ARRAYS ) +#define s(x,c) x[c] +#else +#define s(x,c) x##c +#endif + +/* This implementation provides subroutines for encryption, decryption + and for setting the three key lengths (separately) for encryption + and decryption. Since not all functions are needed, masks are set + up here to determine which will be implemented in C +*/ + +#if !defined( AES_ENCRYPT ) +# define EFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define EFUNCS_IN_C ENC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C ) +#else +# define EFUNCS_IN_C 0 +#endif + +#if !defined( AES_DECRYPT ) +# define DFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define DFUNCS_IN_C DEC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C ) +#else +# define DFUNCS_IN_C 0 +#endif + +#define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C ) + +/* END OF CONFIGURATION OPTIONS */ + +#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) + +/* Disable or report errors on some combinations of options */ + +#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND NO_TABLES +#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND ONE_TABLE +#endif + +#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE +#undef ENC_UNROLL +#define ENC_UNROLL NONE +#endif + +#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND NO_TABLES +#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND ONE_TABLE +#endif + +#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE +#undef DEC_UNROLL +#define DEC_UNROLL NONE +#endif + +#if defined( bswap32 ) +#define aes_sw32 bswap32 +#elif defined( bswap_32 ) +#define aes_sw32 bswap_32 +#else +#define brot(x,n) (((uint_32t)(x) << n) | ((uint_32t)(x) >> (32 - n))) +#define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) +#endif + +/* upr(x,n): rotates bytes within words by n positions, moving bytes to + higher index positions with wrap around into low positions + ups(x,n): moves bytes by n positions to higher index positions in + words but without wrap around + bval(x,n): extracts a byte from a word + + WARNING: The definitions given here are intended only for use with + unsigned variables and with shift counts that are compile + time constants +*/ + +#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN ) +#define upr(x,n) (((uint_32t)(x) << (8 * (n))) | ((uint_32t)(x) >> (32 - 8 * (n)))) +#define ups(x,n) ((uint_32t) (x) << (8 * (n))) +#define bval(x,n) ((uint_8t)((x) >> (8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((uint_32t)(b3) << 24) | ((uint_32t)(b2) << 16) | ((uint_32t)(b1) << 8) | (b0)) +#endif + +#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN ) +#define upr(x,n) (((uint_32t)(x) >> (8 * (n))) | ((uint_32t)(x) << (32 - 8 * (n)))) +#define ups(x,n) ((uint_32t) (x) >> (8 * (n))) +#define bval(x,n) ((uint_8t)((x) >> (24 - 8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((uint_32t)(b0) << 24) | ((uint_32t)(b1) << 16) | ((uint_32t)(b2) << 8) | (b3)) +#endif + +#if defined( SAFE_IO ) + +#define word_in(x,c) bytes2word(((const uint_8t*)(x)+4*c)[0], ((const uint_8t*)(x)+4*c)[1], \ + ((const uint_8t*)(x)+4*c)[2], ((const uint_8t*)(x)+4*c)[3]) +#define word_out(x,c,v) { ((uint_8t*)(x)+4*c)[0] = bval(v,0); ((uint_8t*)(x)+4*c)[1] = bval(v,1); \ + ((uint_8t*)(x)+4*c)[2] = bval(v,2); ((uint_8t*)(x)+4*c)[3] = bval(v,3); } + +#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER ) + +#define word_in(x,c) (*((uint_32t*)(x)+(c))) +#define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = (v)) + +#else + +#define word_in(x,c) aes_sw32(*((uint_32t*)(x)+(c))) +#define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = aes_sw32(v)) + +#endif + +/* the finite field modular polynomial and elements */ + +#define WPOLY 0x011b +#define BPOLY 0x1b + +/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + +#define m1 0x80808080 +#define m2 0x7f7f7f7f +#define gf_mulx(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) + +/* The following defines provide alternative definitions of gf_mulx that might + give improved performance if a fast 32-bit multiply is not available. Note + that a temporary variable u needs to be defined where gf_mulx is used. + +#define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) +#define m4 (0x01010101 * BPOLY) +#define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) +*/ + +/* Work out which tables are needed for the different options */ + +#if defined( ASM_X86_V1C ) +#if defined( ENC_ROUND ) +#undef ENC_ROUND +#endif +#define ENC_ROUND FOUR_TABLES +#if defined( LAST_ENC_ROUND ) +#undef LAST_ENC_ROUND +#endif +#define LAST_ENC_ROUND FOUR_TABLES +#if defined( DEC_ROUND ) +#undef DEC_ROUND +#endif +#define DEC_ROUND FOUR_TABLES +#if defined( LAST_DEC_ROUND ) +#undef LAST_DEC_ROUND +#endif +#define LAST_DEC_ROUND FOUR_TABLES +#if defined( KEY_SCHED ) +#undef KEY_SCHED +#define KEY_SCHED FOUR_TABLES +#endif +#endif + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C ) +#if ENC_ROUND == ONE_TABLE +#define FT1_SET +#elif ENC_ROUND == FOUR_TABLES +#define FT4_SET +#else +#define SBX_SET +#endif +#if LAST_ENC_ROUND == ONE_TABLE +#define FL1_SET +#elif LAST_ENC_ROUND == FOUR_TABLES +#define FL4_SET +#elif !defined( SBX_SET ) +#define SBX_SET +#endif +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C ) +#if DEC_ROUND == ONE_TABLE +#define IT1_SET +#elif DEC_ROUND == FOUR_TABLES +#define IT4_SET +#else +#define ISB_SET +#endif +#if LAST_DEC_ROUND == ONE_TABLE +#define IL1_SET +#elif LAST_DEC_ROUND == FOUR_TABLES +#define IL4_SET +#elif !defined(ISB_SET) +#define ISB_SET +#endif +#endif + +#if (FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C) +#if KEY_SCHED == ONE_TABLE +#define LS1_SET +#elif KEY_SCHED == FOUR_TABLES +#define LS4_SET +#elif !defined( SBX_SET ) +#define SBX_SET +#endif +#endif + +#if (FUNCS_IN_C & DEC_KEYING_IN_C) +#if KEY_SCHED == ONE_TABLE +#define IM1_SET +#elif KEY_SCHED == FOUR_TABLES +#define IM4_SET +#elif !defined( SBX_SET ) +#define SBX_SET +#endif +#endif + +/* generic definitions of Rijndael macros that use tables */ + +#define no_table(x,box,vf,rf,c) bytes2word( \ + box[bval(vf(x,0,c),rf(0,c))], \ + box[bval(vf(x,1,c),rf(1,c))], \ + box[bval(vf(x,2,c),rf(2,c))], \ + box[bval(vf(x,3,c),rf(3,c))]) + +#define one_table(x,op,tab,vf,rf,c) \ + ( tab[bval(vf(x,0,c),rf(0,c))] \ + ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ + ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ + ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) + +#define four_tables(x,tab,vf,rf,c) \ + ( tab[0][bval(vf(x,0,c),rf(0,c))] \ + ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ + ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ + ^ tab[3][bval(vf(x,3,c),rf(3,c))]) + +#define vf1(x,r,c) (x) +#define rf1(r,c) (r) +#define rf2(r,c) ((8+r-c)&3) + +/* perform forward and inverse column mix operation on four bytes in long word x in */ +/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ + +#if defined( FM4_SET ) /* not currently used */ +#define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) +#elif defined( FM1_SET ) /* not currently used */ +#define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) +#else +#define dec_fmvars uint_32t g2 +#define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) +#endif + +#if defined( IM4_SET ) +#define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) +#elif defined( IM1_SET ) +#define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) +#else +#define dec_imvars uint_32t g2, g4, g9 +#define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ + (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) +#endif + +#if defined( FL4_SET ) +#define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) +#elif defined( LS4_SET ) +#define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) +#elif defined( FL1_SET ) +#define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) +#elif defined( LS1_SET ) +#define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) +#else +#define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) +#endif + +#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET ) +#define ISB_SET +#endif + +#endif diff --git a/Crypto/Aestab.c b/Crypto/Aestab.c index cd7d018..10da30c 100644 --- a/Crypto/Aestab.c +++ b/Crypto/Aestab.c @@ -1,428 +1,428 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 20/12/2007 -*/ - -/* Adapted for TrueCrypt by the TrueCrypt Foundation: - - Added run-time table generator for Aes_x86_v2.asm -*/ - -#define DO_TABLES - -#include "Aes.h" -#include "Aesopt.h" - -#if defined(FIXED_TABLES) - -#define sb_data(w) {\ - w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ - w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ - w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ - w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ - w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ - w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ - w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ - w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ - w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ - w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ - w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ - w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ - w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ - w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ - w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ - w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ - w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ - w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ - w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ - w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ - w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ - w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ - w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ - w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ - w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ - w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ - w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ - w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ - w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ - w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ - w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ - w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } - -#define isb_data(w) {\ - w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ - w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ - w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ - w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ - w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ - w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ - w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ - w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ - w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ - w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ - w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ - w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ - w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ - w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ - w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ - w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ - w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ - w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ - w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ - w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ - w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ - w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ - w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ - w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ - w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ - w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ - w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ - w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ - w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ - w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ - w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ - w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } - -#define mm_data(w) {\ - w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ - w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ - w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ - w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ - w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ - w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ - w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ - w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ - w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ - w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ - w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ - w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ - w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ - w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ - w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ - w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ - w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ - w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ - w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ - w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ - w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ - w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ - w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ - w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ - w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ - w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ - w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ - w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ - w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ - w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ - w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ - w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } - -#define rc_data(w) {\ - w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ - w(0x1b), w(0x36) } - -#define h0(x) (x) - -#define w0(p) bytes2word(p, 0, 0, 0) -#define w1(p) bytes2word(0, p, 0, 0) -#define w2(p) bytes2word(0, 0, p, 0) -#define w3(p) bytes2word(0, 0, 0, p) - -#define u0(p) bytes2word(f2(p), p, p, f3(p)) -#define u1(p) bytes2word(f3(p), f2(p), p, p) -#define u2(p) bytes2word(p, f3(p), f2(p), p) -#define u3(p) bytes2word(p, p, f3(p), f2(p)) - -#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) -#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) -#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) -#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) - -#endif - -#if defined(FIXED_TABLES) || !defined(FF_TABLES) - -#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) -#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) -#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ - ^ (((x>>5) & 4) * WPOLY)) -#define f3(x) (f2(x) ^ x) -#define f9(x) (f8(x) ^ x) -#define fb(x) (f8(x) ^ f2(x) ^ x) -#define fd(x) (f8(x) ^ f4(x) ^ x) -#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) - -#else - -#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) -#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) -#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) -#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) -#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) -#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) -#define fi(x) ((x) ? pow[ 255 - log[x]] : 0) - -#endif - -#include "Aestab.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#if defined(FIXED_TABLES) - -/* implemented in case of wrong call for fixed tables */ - -AES_RETURN aes_init(void) -{ - return EXIT_SUCCESS; -} - -#else /* dynamic table generation */ - -#if !defined(FF_TABLES) - -/* Generate the tables for the dynamic table option - - It will generally be sensible to use tables to compute finite - field multiplies and inverses but where memory is scarse this - code might sometimes be better. But it only has effect during - initialisation so its pretty unimportant in overall terms. -*/ - -/* return 2 ^ (n - 1) where n is the bit number of the highest bit - set in x with x in the range 1 < x < 0x00000200. This form is - used so that locals within fi can be bytes rather than words -*/ - -static uint_8t hibit(const uint_32t x) -{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2)); - - r |= (r >> 2); - r |= (r >> 4); - return (r + 1) >> 1; -} - -/* return the inverse of the finite field element x */ - -static uint_8t fi(const uint_8t x) -{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; - - if(x < 2) return x; - - for(;;) - { - if(!n1) return v1; - - while(n2 >= n1) - { - n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); - } - - if(!n2) return v2; - - while(n1 >= n2) - { - n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); - } - } -} - -#endif - -/* The forward and inverse affine transformations used in the S-box */ - -#define fwd_affine(x) \ - (w = (uint_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(uint_8t)(w^(w>>8))) - -#define inv_affine(x) \ - (w = (uint_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(uint_8t)(w^(w>>8))) - -static int init = 0; - -#ifdef TC_WINDOWS_BOOT - -#pragma optimize ("l", on) -uint_8t aes_enc_tab[256][8]; -uint_8t aes_dec_tab[256][8]; - -#endif - -AES_RETURN aes_init(void) -{ uint_32t i, w; - -#ifdef TC_WINDOWS_BOOT - - if (init) - return EXIT_SUCCESS; - - for (i = 0; i < 256; ++i) - { - uint_8t x = fwd_affine(fi((uint_8t)i)); - aes_enc_tab[i][0] = 0; - aes_enc_tab[i][1] = x; - aes_enc_tab[i][2] = x; - aes_enc_tab[i][3] = f3(x); - aes_enc_tab[i][4] = f2(x); - aes_enc_tab[i][5] = x; - aes_enc_tab[i][6] = x; - aes_enc_tab[i][7] = f3(x); - - x = fi((uint_8t)inv_affine((uint_8t)i)); - aes_dec_tab[i][0] = fe(x); - aes_dec_tab[i][1] = f9(x); - aes_dec_tab[i][2] = fd(x); - aes_dec_tab[i][3] = fb(x); - aes_dec_tab[i][4] = fe(x); - aes_dec_tab[i][5] = f9(x); - aes_dec_tab[i][6] = fd(x); - aes_dec_tab[i][7] = x; - } - -#else // TC_WINDOWS_BOOT - -#if defined(FF_TABLES) - - uint_8t pow[512], log[256]; - - if(init) - return EXIT_SUCCESS; - /* log and power tables for GF(2^8) finite field with - WPOLY as modular polynomial - the simplest primitive - root is 0x03, used here to generate the tables - */ - - i = 0; w = 1; - do - { - pow[i] = (uint_8t)w; - pow[i + 255] = (uint_8t)w; - log[w] = (uint_8t)i++; - w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); - } - while (w != 1); - -#else - if(init) - return EXIT_SUCCESS; -#endif - - for(i = 0, w = 1; i < RC_LENGTH; ++i) - { - t_set(r,c)[i] = bytes2word(w, 0, 0, 0); - w = f2(w); - } - - for(i = 0; i < 256; ++i) - { uint_8t b; - - b = fwd_affine(fi((uint_8t)i)); - w = bytes2word(f2(b), b, b, f3(b)); - -#if defined( SBX_SET ) - t_set(s,box)[i] = b; -#endif - -#if defined( FT1_SET ) /* tables for a normal encryption round */ - t_set(f,n)[i] = w; -#endif -#if defined( FT4_SET ) - t_set(f,n)[0][i] = w; - t_set(f,n)[1][i] = upr(w,1); - t_set(f,n)[2][i] = upr(w,2); - t_set(f,n)[3][i] = upr(w,3); -#endif - w = bytes2word(b, 0, 0, 0); - -#if defined( FL1_SET ) /* tables for last encryption round (may also */ - t_set(f,l)[i] = w; /* be used in the key schedule) */ -#endif -#if defined( FL4_SET ) - t_set(f,l)[0][i] = w; - t_set(f,l)[1][i] = upr(w,1); - t_set(f,l)[2][i] = upr(w,2); - t_set(f,l)[3][i] = upr(w,3); -#endif - -#if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/ - t_set(l,s)[i] = w; /* not of the required form */ -#endif -#if defined( LS4_SET ) - t_set(l,s)[0][i] = w; - t_set(l,s)[1][i] = upr(w,1); - t_set(l,s)[2][i] = upr(w,2); - t_set(l,s)[3][i] = upr(w,3); -#endif - - b = fi(inv_affine((uint_8t)i)); - w = bytes2word(fe(b), f9(b), fd(b), fb(b)); - -#if defined( IM1_SET ) /* tables for the inverse mix column operation */ - t_set(i,m)[b] = w; -#endif -#if defined( IM4_SET ) - t_set(i,m)[0][b] = w; - t_set(i,m)[1][b] = upr(w,1); - t_set(i,m)[2][b] = upr(w,2); - t_set(i,m)[3][b] = upr(w,3); -#endif - -#if defined( ISB_SET ) - t_set(i,box)[i] = b; -#endif -#if defined( IT1_SET ) /* tables for a normal decryption round */ - t_set(i,n)[i] = w; -#endif -#if defined( IT4_SET ) - t_set(i,n)[0][i] = w; - t_set(i,n)[1][i] = upr(w,1); - t_set(i,n)[2][i] = upr(w,2); - t_set(i,n)[3][i] = upr(w,3); -#endif - w = bytes2word(b, 0, 0, 0); -#if defined( IL1_SET ) /* tables for last decryption round */ - t_set(i,l)[i] = w; -#endif -#if defined( IL4_SET ) - t_set(i,l)[0][i] = w; - t_set(i,l)[1][i] = upr(w,1); - t_set(i,l)[2][i] = upr(w,2); - t_set(i,l)[3][i] = upr(w,3); -#endif - } - -#endif // TC_WINDOWS_BOOT - - init = 1; - return EXIT_SUCCESS; -} - -#endif - -#if defined(__cplusplus) -} -#endif - +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation: + - Added run-time table generator for Aes_x86_v2.asm +*/ + +#define DO_TABLES + +#include "Aes.h" +#include "Aesopt.h" + +#if defined(FIXED_TABLES) + +#define sb_data(w) {\ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + +#define isb_data(w) {\ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } + +#define mm_data(w) {\ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } + +#define rc_data(w) {\ + w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ + w(0x1b), w(0x36) } + +#define h0(x) (x) + +#define w0(p) bytes2word(p, 0, 0, 0) +#define w1(p) bytes2word(0, p, 0, 0) +#define w2(p) bytes2word(0, 0, p, 0) +#define w3(p) bytes2word(0, 0, 0, p) + +#define u0(p) bytes2word(f2(p), p, p, f3(p)) +#define u1(p) bytes2word(f3(p), f2(p), p, p) +#define u2(p) bytes2word(p, f3(p), f2(p), p) +#define u3(p) bytes2word(p, p, f3(p), f2(p)) + +#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) +#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) +#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) +#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) + +#endif + +#if defined(FIXED_TABLES) || !defined(FF_TABLES) + +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#else + +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) +#define fi(x) ((x) ? pow[ 255 - log[x]] : 0) + +#endif + +#include "Aestab.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined(FIXED_TABLES) + +/* implemented in case of wrong call for fixed tables */ + +AES_RETURN aes_init(void) +{ + return EXIT_SUCCESS; +} + +#else /* dynamic table generation */ + +#if !defined(FF_TABLES) + +/* Generate the tables for the dynamic table option + + It will generally be sensible to use tables to compute finite + field multiplies and inverses but where memory is scarse this + code might sometimes be better. But it only has effect during + initialisation so its pretty unimportant in overall terms. +*/ + +/* return 2 ^ (n - 1) where n is the bit number of the highest bit + set in x with x in the range 1 < x < 0x00000200. This form is + used so that locals within fi can be bytes rather than words +*/ + +static uint_8t hibit(const uint_32t x) +{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint_8t fi(const uint_8t x) +{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) return x; + + for(;;) + { + if(!n1) return v1; + + while(n2 >= n1) + { + n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); + } + + if(!n2) return v2; + + while(n1 >= n2) + { + n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); + } + } +} + +#endif + +/* The forward and inverse affine transformations used in the S-box */ + +#define fwd_affine(x) \ + (w = (uint_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(uint_8t)(w^(w>>8))) + +#define inv_affine(x) \ + (w = (uint_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(uint_8t)(w^(w>>8))) + +static int init = 0; + +#ifdef TC_WINDOWS_BOOT + +#pragma optimize ("l", on) +uint_8t aes_enc_tab[256][8]; +uint_8t aes_dec_tab[256][8]; + +#endif + +AES_RETURN aes_init(void) +{ uint_32t i, w; + +#ifdef TC_WINDOWS_BOOT + + if (init) + return EXIT_SUCCESS; + + for (i = 0; i < 256; ++i) + { + uint_8t x = fwd_affine(fi((uint_8t)i)); + aes_enc_tab[i][0] = 0; + aes_enc_tab[i][1] = x; + aes_enc_tab[i][2] = x; + aes_enc_tab[i][3] = f3(x); + aes_enc_tab[i][4] = f2(x); + aes_enc_tab[i][5] = x; + aes_enc_tab[i][6] = x; + aes_enc_tab[i][7] = f3(x); + + x = fi((uint_8t)inv_affine((uint_8t)i)); + aes_dec_tab[i][0] = fe(x); + aes_dec_tab[i][1] = f9(x); + aes_dec_tab[i][2] = fd(x); + aes_dec_tab[i][3] = fb(x); + aes_dec_tab[i][4] = fe(x); + aes_dec_tab[i][5] = f9(x); + aes_dec_tab[i][6] = fd(x); + aes_dec_tab[i][7] = x; + } + +#else // TC_WINDOWS_BOOT + +#if defined(FF_TABLES) + + uint_8t pow[512], log[256]; + + if(init) + return EXIT_SUCCESS; + /* log and power tables for GF(2^8) finite field with + WPOLY as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables + */ + + i = 0; w = 1; + do + { + pow[i] = (uint_8t)w; + pow[i + 255] = (uint_8t)w; + log[w] = (uint_8t)i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } + while (w != 1); + +#else + if(init) + return EXIT_SUCCESS; +#endif + + for(i = 0, w = 1; i < RC_LENGTH; ++i) + { + t_set(r,c)[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for(i = 0; i < 256; ++i) + { uint_8t b; + + b = fwd_affine(fi((uint_8t)i)); + w = bytes2word(f2(b), b, b, f3(b)); + +#if defined( SBX_SET ) + t_set(s,box)[i] = b; +#endif + +#if defined( FT1_SET ) /* tables for a normal encryption round */ + t_set(f,n)[i] = w; +#endif +#if defined( FT4_SET ) + t_set(f,n)[0][i] = w; + t_set(f,n)[1][i] = upr(w,1); + t_set(f,n)[2][i] = upr(w,2); + t_set(f,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); + +#if defined( FL1_SET ) /* tables for last encryption round (may also */ + t_set(f,l)[i] = w; /* be used in the key schedule) */ +#endif +#if defined( FL4_SET ) + t_set(f,l)[0][i] = w; + t_set(f,l)[1][i] = upr(w,1); + t_set(f,l)[2][i] = upr(w,2); + t_set(f,l)[3][i] = upr(w,3); +#endif + +#if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/ + t_set(l,s)[i] = w; /* not of the required form */ +#endif +#if defined( LS4_SET ) + t_set(l,s)[0][i] = w; + t_set(l,s)[1][i] = upr(w,1); + t_set(l,s)[2][i] = upr(w,2); + t_set(l,s)[3][i] = upr(w,3); +#endif + + b = fi(inv_affine((uint_8t)i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + +#if defined( IM1_SET ) /* tables for the inverse mix column operation */ + t_set(i,m)[b] = w; +#endif +#if defined( IM4_SET ) + t_set(i,m)[0][b] = w; + t_set(i,m)[1][b] = upr(w,1); + t_set(i,m)[2][b] = upr(w,2); + t_set(i,m)[3][b] = upr(w,3); +#endif + +#if defined( ISB_SET ) + t_set(i,box)[i] = b; +#endif +#if defined( IT1_SET ) /* tables for a normal decryption round */ + t_set(i,n)[i] = w; +#endif +#if defined( IT4_SET ) + t_set(i,n)[0][i] = w; + t_set(i,n)[1][i] = upr(w,1); + t_set(i,n)[2][i] = upr(w,2); + t_set(i,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); +#if defined( IL1_SET ) /* tables for last decryption round */ + t_set(i,l)[i] = w; +#endif +#if defined( IL4_SET ) + t_set(i,l)[0][i] = w; + t_set(i,l)[1][i] = upr(w,1); + t_set(i,l)[2][i] = upr(w,2); + t_set(i,l)[3][i] = upr(w,3); +#endif + } + +#endif // TC_WINDOWS_BOOT + + init = 1; + return EXIT_SUCCESS; +} + +#endif + +#if defined(__cplusplus) +} +#endif + diff --git a/Crypto/Aestab.h b/Crypto/Aestab.h index e52e005..2ad1b03 100644 --- a/Crypto/Aestab.h +++ b/Crypto/Aestab.h @@ -1,174 +1,174 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 20/12/2007 - - This file contains the code for declaring the tables needed to implement - AES. The file aesopt.h is assumed to be included before this header file. - If there are no global variables, the definitions here can be used to put - the AES tables in a structure so that a pointer can then be added to the - AES context to pass them to the AES routines that need them. If this - facility is used, the calling program has to ensure that this pointer is - managed appropriately. In particular, the value of the t_dec(in,it) item - in the table structure must be set to zero in order to ensure that the - tables are initialised. In practice the three code sequences in aeskey.c - that control the calls to aes_init() and the aes_init() routine itself will - have to be changed for a specific implementation. If global variables are - available it will generally be preferable to use them with the precomputed - FIXED_TABLES option that uses static global tables. - - The following defines can be used to control the way the tables - are defined, initialised and used in embedded environments that - require special features for these purposes - - the 't_dec' construction is used to declare fixed table arrays - the 't_set' construction is used to set fixed table values - the 't_use' construction is used to access fixed table values - - 256 byte tables: - - t_xxx(s,box) => forward S box - t_xxx(i,box) => inverse S box - - 256 32-bit word OR 4 x 256 32-bit word tables: - - t_xxx(f,n) => forward normal round - t_xxx(f,l) => forward last round - t_xxx(i,n) => inverse normal round - t_xxx(i,l) => inverse last round - t_xxx(l,s) => key schedule table - t_xxx(i,m) => key schedule table - - Other variables and tables: - - t_xxx(r,c) => the rcon table -*/ - -#if !defined( _AESTAB_H ) -#define _AESTAB_H - -#define t_dec(m,n) t_##m##n -#define t_set(m,n) t_##m##n -#define t_use(m,n) t_##m##n - -#if defined(FIXED_TABLES) -# if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ )) -/* make tables far data to avoid using too much DGROUP space (PG) */ -# define CONST const far -# else -# define CONST const -# endif -#else -# define CONST -#endif - -#if defined(__cplusplus) -# define EXTERN extern "C" -#elif defined(DO_TABLES) -# define EXTERN -#else -# define EXTERN extern -#endif - -#if defined(_MSC_VER) && defined(TABLE_ALIGN) -#define ALIGN __declspec(align(TABLE_ALIGN)) -#else -#define ALIGN -#endif - -#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) -# define XP_DIR __cdecl -#else -# define XP_DIR -#endif - -#if defined(DO_TABLES) && defined(FIXED_TABLES) -#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e) -#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) } -EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0); -#else -#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] -#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] -EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH]; -#endif - -#if defined( SBX_SET ) - d_1(uint_8t, t_dec(s,box), sb_data, h0); -#endif -#if defined( ISB_SET ) - d_1(uint_8t, t_dec(i,box), isb_data, h0); -#endif - -#if defined( FT1_SET ) - d_1(uint_32t, t_dec(f,n), sb_data, u0); -#endif -#if defined( FT4_SET ) - d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3); -#endif - -#if defined( FL1_SET ) - d_1(uint_32t, t_dec(f,l), sb_data, w0); -#endif -#if defined( FL4_SET ) - d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3); -#endif - -#if defined( IT1_SET ) - d_1(uint_32t, t_dec(i,n), isb_data, v0); -#endif -#if defined( IT4_SET ) - d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3); -#endif - -#if defined( IL1_SET ) - d_1(uint_32t, t_dec(i,l), isb_data, w0); -#endif -#if defined( IL4_SET ) - d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3); -#endif - -#if defined( LS1_SET ) -#if defined( FL1_SET ) -#undef LS1_SET -#else - d_1(uint_32t, t_dec(l,s), sb_data, w0); -#endif -#endif - -#if defined( LS4_SET ) -#if defined( FL4_SET ) -#undef LS4_SET -#else - d_4(uint_32t, t_dec(l,s), sb_data, w0, w1, w2, w3); -#endif -#endif - -#if defined( IM1_SET ) - d_1(uint_32t, t_dec(i,m), mm_data, v0); -#endif -#if defined( IM4_SET ) - d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3); -#endif - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + + This file contains the code for declaring the tables needed to implement + AES. The file aesopt.h is assumed to be included before this header file. + If there are no global variables, the definitions here can be used to put + the AES tables in a structure so that a pointer can then be added to the + AES context to pass them to the AES routines that need them. If this + facility is used, the calling program has to ensure that this pointer is + managed appropriately. In particular, the value of the t_dec(in,it) item + in the table structure must be set to zero in order to ensure that the + tables are initialised. In practice the three code sequences in aeskey.c + that control the calls to aes_init() and the aes_init() routine itself will + have to be changed for a specific implementation. If global variables are + available it will generally be preferable to use them with the precomputed + FIXED_TABLES option that uses static global tables. + + The following defines can be used to control the way the tables + are defined, initialised and used in embedded environments that + require special features for these purposes + + the 't_dec' construction is used to declare fixed table arrays + the 't_set' construction is used to set fixed table values + the 't_use' construction is used to access fixed table values + + 256 byte tables: + + t_xxx(s,box) => forward S box + t_xxx(i,box) => inverse S box + + 256 32-bit word OR 4 x 256 32-bit word tables: + + t_xxx(f,n) => forward normal round + t_xxx(f,l) => forward last round + t_xxx(i,n) => inverse normal round + t_xxx(i,l) => inverse last round + t_xxx(l,s) => key schedule table + t_xxx(i,m) => key schedule table + + Other variables and tables: + + t_xxx(r,c) => the rcon table +*/ + +#if !defined( _AESTAB_H ) +#define _AESTAB_H + +#define t_dec(m,n) t_##m##n +#define t_set(m,n) t_##m##n +#define t_use(m,n) t_##m##n + +#if defined(FIXED_TABLES) +# if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ )) +/* make tables far data to avoid using too much DGROUP space (PG) */ +# define CONST const far +# else +# define CONST const +# endif +#else +# define CONST +#endif + +#if defined(__cplusplus) +# define EXTERN extern "C" +#elif defined(DO_TABLES) +# define EXTERN +#else +# define EXTERN extern +#endif + +#if defined(_MSC_VER) && defined(TABLE_ALIGN) +#define ALIGN __declspec(align(TABLE_ALIGN)) +#else +#define ALIGN +#endif + +#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) +# define XP_DIR __cdecl +#else +# define XP_DIR +#endif + +#if defined(DO_TABLES) && defined(FIXED_TABLES) +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e) +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) } +EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0); +#else +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] +EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH]; +#endif + +#if defined( SBX_SET ) + d_1(uint_8t, t_dec(s,box), sb_data, h0); +#endif +#if defined( ISB_SET ) + d_1(uint_8t, t_dec(i,box), isb_data, h0); +#endif + +#if defined( FT1_SET ) + d_1(uint_32t, t_dec(f,n), sb_data, u0); +#endif +#if defined( FT4_SET ) + d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3); +#endif + +#if defined( FL1_SET ) + d_1(uint_32t, t_dec(f,l), sb_data, w0); +#endif +#if defined( FL4_SET ) + d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3); +#endif + +#if defined( IT1_SET ) + d_1(uint_32t, t_dec(i,n), isb_data, v0); +#endif +#if defined( IT4_SET ) + d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3); +#endif + +#if defined( IL1_SET ) + d_1(uint_32t, t_dec(i,l), isb_data, w0); +#endif +#if defined( IL4_SET ) + d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3); +#endif + +#if defined( LS1_SET ) +#if defined( FL1_SET ) +#undef LS1_SET +#else + d_1(uint_32t, t_dec(l,s), sb_data, w0); +#endif +#endif + +#if defined( LS4_SET ) +#if defined( FL4_SET ) +#undef LS4_SET +#else + d_4(uint_32t, t_dec(l,s), sb_data, w0, w1, w2, w3); +#endif +#endif + +#if defined( IM1_SET ) + d_1(uint_32t, t_dec(i,m), mm_data, v0); +#endif +#if defined( IM4_SET ) + d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3); +#endif + +#endif diff --git a/Crypto/BLOWFISH.H b/Crypto/BLOWFISH.H index 142313e..f5f9169 100644 --- a/Crypto/BLOWFISH.H +++ b/Crypto/BLOWFISH.H @@ -1,22 +1,22 @@ -#ifndef TC_HEADER_Crypto_Blowfish -#define TC_HEADER_Crypto_Blowfish - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BF_KEY_STRUCT -{ - unsigned __int32 pbox[18]; - unsigned __int32 pbox_dec[18]; - unsigned __int32 sbox[4*256]; -} BF_KEY; - -void BlowfishSetKey (BF_KEY *key, int keylength, unsigned char *key_string); -void BlowfishEncryptLE (unsigned char *in, unsigned char *out, BF_KEY *ks, int encrypt); - -#ifdef __cplusplus -} -#endif - -#endif // TC_HEADER_Crypto_Blowfish +#ifndef TC_HEADER_Crypto_Blowfish +#define TC_HEADER_Crypto_Blowfish + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct BF_KEY_STRUCT +{ + unsigned __int32 pbox[18]; + unsigned __int32 pbox_dec[18]; + unsigned __int32 sbox[4*256]; +} BF_KEY; + +void BlowfishSetKey (BF_KEY *key, int keylength, unsigned char *key_string); +void BlowfishEncryptLE (unsigned char *in, unsigned char *out, BF_KEY *ks, int encrypt); + +#ifdef __cplusplus +} +#endif + +#endif // TC_HEADER_Crypto_Blowfish diff --git a/Crypto/Blowfish.c b/Crypto/Blowfish.c index 894bf2e..3a570f1 100644 --- a/Crypto/Blowfish.c +++ b/Crypto/Blowfish.c @@ -1,379 +1,379 @@ -// blowfish.cpp - written and placed in the public domain by Wei Dai - -/* Adapted for TrueCrypt by the TrueCrypt Foundation */ - -#include -#include "Common/Tcdefs.h" -#include "Common/Endian.h" -#include "Blowfish.h" - -#define word32 unsigned __int32 -#define byte unsigned __int8 -#define GETBYTE(x, y) (unsigned int)(byte)((x)>>(8*(y))) -#define ROUNDS 16 - -static const unsigned __int32 p_init[16+2] = -{ - 608135816U, 2242054355U, 320440878U, 57701188U, - 2752067618U, 698298832U, 137296536U, 3964562569U, - 1160258022U, 953160567U, 3193202383U, 887688300U, - 3232508343U, 3380367581U, 1065670069U, 3041331479U, - 2450970073U, 2306472731U -} ; - -static const unsigned __int32 s_init[4*256] = { - 3509652390U, 2564797868U, 805139163U, 3491422135U, - 3101798381U, 1780907670U, 3128725573U, 4046225305U, - 614570311U, 3012652279U, 134345442U, 2240740374U, - 1667834072U, 1901547113U, 2757295779U, 4103290238U, - 227898511U, 1921955416U, 1904987480U, 2182433518U, - 2069144605U, 3260701109U, 2620446009U, 720527379U, - 3318853667U, 677414384U, 3393288472U, 3101374703U, - 2390351024U, 1614419982U, 1822297739U, 2954791486U, - 3608508353U, 3174124327U, 2024746970U, 1432378464U, - 3864339955U, 2857741204U, 1464375394U, 1676153920U, - 1439316330U, 715854006U, 3033291828U, 289532110U, - 2706671279U, 2087905683U, 3018724369U, 1668267050U, - 732546397U, 1947742710U, 3462151702U, 2609353502U, - 2950085171U, 1814351708U, 2050118529U, 680887927U, - 999245976U, 1800124847U, 3300911131U, 1713906067U, - 1641548236U, 4213287313U, 1216130144U, 1575780402U, - 4018429277U, 3917837745U, 3693486850U, 3949271944U, - 596196993U, 3549867205U, 258830323U, 2213823033U, - 772490370U, 2760122372U, 1774776394U, 2652871518U, - 566650946U, 4142492826U, 1728879713U, 2882767088U, - 1783734482U, 3629395816U, 2517608232U, 2874225571U, - 1861159788U, 326777828U, 3124490320U, 2130389656U, - 2716951837U, 967770486U, 1724537150U, 2185432712U, - 2364442137U, 1164943284U, 2105845187U, 998989502U, - 3765401048U, 2244026483U, 1075463327U, 1455516326U, - 1322494562U, 910128902U, 469688178U, 1117454909U, - 936433444U, 3490320968U, 3675253459U, 1240580251U, - 122909385U, 2157517691U, 634681816U, 4142456567U, - 3825094682U, 3061402683U, 2540495037U, 79693498U, - 3249098678U, 1084186820U, 1583128258U, 426386531U, - 1761308591U, 1047286709U, 322548459U, 995290223U, - 1845252383U, 2603652396U, 3431023940U, 2942221577U, - 3202600964U, 3727903485U, 1712269319U, 422464435U, - 3234572375U, 1170764815U, 3523960633U, 3117677531U, - 1434042557U, 442511882U, 3600875718U, 1076654713U, - 1738483198U, 4213154764U, 2393238008U, 3677496056U, - 1014306527U, 4251020053U, 793779912U, 2902807211U, - 842905082U, 4246964064U, 1395751752U, 1040244610U, - 2656851899U, 3396308128U, 445077038U, 3742853595U, - 3577915638U, 679411651U, 2892444358U, 2354009459U, - 1767581616U, 3150600392U, 3791627101U, 3102740896U, - 284835224U, 4246832056U, 1258075500U, 768725851U, - 2589189241U, 3069724005U, 3532540348U, 1274779536U, - 3789419226U, 2764799539U, 1660621633U, 3471099624U, - 4011903706U, 913787905U, 3497959166U, 737222580U, - 2514213453U, 2928710040U, 3937242737U, 1804850592U, - 3499020752U, 2949064160U, 2386320175U, 2390070455U, - 2415321851U, 4061277028U, 2290661394U, 2416832540U, - 1336762016U, 1754252060U, 3520065937U, 3014181293U, - 791618072U, 3188594551U, 3933548030U, 2332172193U, - 3852520463U, 3043980520U, 413987798U, 3465142937U, - 3030929376U, 4245938359U, 2093235073U, 3534596313U, - 375366246U, 2157278981U, 2479649556U, 555357303U, - 3870105701U, 2008414854U, 3344188149U, 4221384143U, - 3956125452U, 2067696032U, 3594591187U, 2921233993U, - 2428461U, 544322398U, 577241275U, 1471733935U, - 610547355U, 4027169054U, 1432588573U, 1507829418U, - 2025931657U, 3646575487U, 545086370U, 48609733U, - 2200306550U, 1653985193U, 298326376U, 1316178497U, - 3007786442U, 2064951626U, 458293330U, 2589141269U, - 3591329599U, 3164325604U, 727753846U, 2179363840U, - 146436021U, 1461446943U, 4069977195U, 705550613U, - 3059967265U, 3887724982U, 4281599278U, 3313849956U, - 1404054877U, 2845806497U, 146425753U, 1854211946U, - - 1266315497U, 3048417604U, 3681880366U, 3289982499U, - 2909710000U, 1235738493U, 2632868024U, 2414719590U, - 3970600049U, 1771706367U, 1449415276U, 3266420449U, - 422970021U, 1963543593U, 2690192192U, 3826793022U, - 1062508698U, 1531092325U, 1804592342U, 2583117782U, - 2714934279U, 4024971509U, 1294809318U, 4028980673U, - 1289560198U, 2221992742U, 1669523910U, 35572830U, - 157838143U, 1052438473U, 1016535060U, 1802137761U, - 1753167236U, 1386275462U, 3080475397U, 2857371447U, - 1040679964U, 2145300060U, 2390574316U, 1461121720U, - 2956646967U, 4031777805U, 4028374788U, 33600511U, - 2920084762U, 1018524850U, 629373528U, 3691585981U, - 3515945977U, 2091462646U, 2486323059U, 586499841U, - 988145025U, 935516892U, 3367335476U, 2599673255U, - 2839830854U, 265290510U, 3972581182U, 2759138881U, - 3795373465U, 1005194799U, 847297441U, 406762289U, - 1314163512U, 1332590856U, 1866599683U, 4127851711U, - 750260880U, 613907577U, 1450815602U, 3165620655U, - 3734664991U, 3650291728U, 3012275730U, 3704569646U, - 1427272223U, 778793252U, 1343938022U, 2676280711U, - 2052605720U, 1946737175U, 3164576444U, 3914038668U, - 3967478842U, 3682934266U, 1661551462U, 3294938066U, - 4011595847U, 840292616U, 3712170807U, 616741398U, - 312560963U, 711312465U, 1351876610U, 322626781U, - 1910503582U, 271666773U, 2175563734U, 1594956187U, - 70604529U, 3617834859U, 1007753275U, 1495573769U, - 4069517037U, 2549218298U, 2663038764U, 504708206U, - 2263041392U, 3941167025U, 2249088522U, 1514023603U, - 1998579484U, 1312622330U, 694541497U, 2582060303U, - 2151582166U, 1382467621U, 776784248U, 2618340202U, - 3323268794U, 2497899128U, 2784771155U, 503983604U, - 4076293799U, 907881277U, 423175695U, 432175456U, - 1378068232U, 4145222326U, 3954048622U, 3938656102U, - 3820766613U, 2793130115U, 2977904593U, 26017576U, - 3274890735U, 3194772133U, 1700274565U, 1756076034U, - 4006520079U, 3677328699U, 720338349U, 1533947780U, - 354530856U, 688349552U, 3973924725U, 1637815568U, - 332179504U, 3949051286U, 53804574U, 2852348879U, - 3044236432U, 1282449977U, 3583942155U, 3416972820U, - 4006381244U, 1617046695U, 2628476075U, 3002303598U, - 1686838959U, 431878346U, 2686675385U, 1700445008U, - 1080580658U, 1009431731U, 832498133U, 3223435511U, - 2605976345U, 2271191193U, 2516031870U, 1648197032U, - 4164389018U, 2548247927U, 300782431U, 375919233U, - 238389289U, 3353747414U, 2531188641U, 2019080857U, - 1475708069U, 455242339U, 2609103871U, 448939670U, - 3451063019U, 1395535956U, 2413381860U, 1841049896U, - 1491858159U, 885456874U, 4264095073U, 4001119347U, - 1565136089U, 3898914787U, 1108368660U, 540939232U, - 1173283510U, 2745871338U, 3681308437U, 4207628240U, - 3343053890U, 4016749493U, 1699691293U, 1103962373U, - 3625875870U, 2256883143U, 3830138730U, 1031889488U, - 3479347698U, 1535977030U, 4236805024U, 3251091107U, - 2132092099U, 1774941330U, 1199868427U, 1452454533U, - 157007616U, 2904115357U, 342012276U, 595725824U, - 1480756522U, 206960106U, 497939518U, 591360097U, - 863170706U, 2375253569U, 3596610801U, 1814182875U, - 2094937945U, 3421402208U, 1082520231U, 3463918190U, - 2785509508U, 435703966U, 3908032597U, 1641649973U, - 2842273706U, 3305899714U, 1510255612U, 2148256476U, - 2655287854U, 3276092548U, 4258621189U, 236887753U, - 3681803219U, 274041037U, 1734335097U, 3815195456U, - 3317970021U, 1899903192U, 1026095262U, 4050517792U, - 356393447U, 2410691914U, 3873677099U, 3682840055U, - - 3913112168U, 2491498743U, 4132185628U, 2489919796U, - 1091903735U, 1979897079U, 3170134830U, 3567386728U, - 3557303409U, 857797738U, 1136121015U, 1342202287U, - 507115054U, 2535736646U, 337727348U, 3213592640U, - 1301675037U, 2528481711U, 1895095763U, 1721773893U, - 3216771564U, 62756741U, 2142006736U, 835421444U, - 2531993523U, 1442658625U, 3659876326U, 2882144922U, - 676362277U, 1392781812U, 170690266U, 3921047035U, - 1759253602U, 3611846912U, 1745797284U, 664899054U, - 1329594018U, 3901205900U, 3045908486U, 2062866102U, - 2865634940U, 3543621612U, 3464012697U, 1080764994U, - 553557557U, 3656615353U, 3996768171U, 991055499U, - 499776247U, 1265440854U, 648242737U, 3940784050U, - 980351604U, 3713745714U, 1749149687U, 3396870395U, - 4211799374U, 3640570775U, 1161844396U, 3125318951U, - 1431517754U, 545492359U, 4268468663U, 3499529547U, - 1437099964U, 2702547544U, 3433638243U, 2581715763U, - 2787789398U, 1060185593U, 1593081372U, 2418618748U, - 4260947970U, 69676912U, 2159744348U, 86519011U, - 2512459080U, 3838209314U, 1220612927U, 3339683548U, - 133810670U, 1090789135U, 1078426020U, 1569222167U, - 845107691U, 3583754449U, 4072456591U, 1091646820U, - 628848692U, 1613405280U, 3757631651U, 526609435U, - 236106946U, 48312990U, 2942717905U, 3402727701U, - 1797494240U, 859738849U, 992217954U, 4005476642U, - 2243076622U, 3870952857U, 3732016268U, 765654824U, - 3490871365U, 2511836413U, 1685915746U, 3888969200U, - 1414112111U, 2273134842U, 3281911079U, 4080962846U, - 172450625U, 2569994100U, 980381355U, 4109958455U, - 2819808352U, 2716589560U, 2568741196U, 3681446669U, - 3329971472U, 1835478071U, 660984891U, 3704678404U, - 4045999559U, 3422617507U, 3040415634U, 1762651403U, - 1719377915U, 3470491036U, 2693910283U, 3642056355U, - 3138596744U, 1364962596U, 2073328063U, 1983633131U, - 926494387U, 3423689081U, 2150032023U, 4096667949U, - 1749200295U, 3328846651U, 309677260U, 2016342300U, - 1779581495U, 3079819751U, 111262694U, 1274766160U, - 443224088U, 298511866U, 1025883608U, 3806446537U, - 1145181785U, 168956806U, 3641502830U, 3584813610U, - 1689216846U, 3666258015U, 3200248200U, 1692713982U, - 2646376535U, 4042768518U, 1618508792U, 1610833997U, - 3523052358U, 4130873264U, 2001055236U, 3610705100U, - 2202168115U, 4028541809U, 2961195399U, 1006657119U, - 2006996926U, 3186142756U, 1430667929U, 3210227297U, - 1314452623U, 4074634658U, 4101304120U, 2273951170U, - 1399257539U, 3367210612U, 3027628629U, 1190975929U, - 2062231137U, 2333990788U, 2221543033U, 2438960610U, - 1181637006U, 548689776U, 2362791313U, 3372408396U, - 3104550113U, 3145860560U, 296247880U, 1970579870U, - 3078560182U, 3769228297U, 1714227617U, 3291629107U, - 3898220290U, 166772364U, 1251581989U, 493813264U, - 448347421U, 195405023U, 2709975567U, 677966185U, - 3703036547U, 1463355134U, 2715995803U, 1338867538U, - 1343315457U, 2802222074U, 2684532164U, 233230375U, - 2599980071U, 2000651841U, 3277868038U, 1638401717U, - 4028070440U, 3237316320U, 6314154U, 819756386U, - 300326615U, 590932579U, 1405279636U, 3267499572U, - 3150704214U, 2428286686U, 3959192993U, 3461946742U, - 1862657033U, 1266418056U, 963775037U, 2089974820U, - 2263052895U, 1917689273U, 448879540U, 3550394620U, - 3981727096U, 150775221U, 3627908307U, 1303187396U, - 508620638U, 2975983352U, 2726630617U, 1817252668U, - 1876281319U, 1457606340U, 908771278U, 3720792119U, - 3617206836U, 2455994898U, 1729034894U, 1080033504U, - - 976866871U, 3556439503U, 2881648439U, 1522871579U, - 1555064734U, 1336096578U, 3548522304U, 2579274686U, - 3574697629U, 3205460757U, 3593280638U, 3338716283U, - 3079412587U, 564236357U, 2993598910U, 1781952180U, - 1464380207U, 3163844217U, 3332601554U, 1699332808U, - 1393555694U, 1183702653U, 3581086237U, 1288719814U, - 691649499U, 2847557200U, 2895455976U, 3193889540U, - 2717570544U, 1781354906U, 1676643554U, 2592534050U, - 3230253752U, 1126444790U, 2770207658U, 2633158820U, - 2210423226U, 2615765581U, 2414155088U, 3127139286U, - 673620729U, 2805611233U, 1269405062U, 4015350505U, - 3341807571U, 4149409754U, 1057255273U, 2012875353U, - 2162469141U, 2276492801U, 2601117357U, 993977747U, - 3918593370U, 2654263191U, 753973209U, 36408145U, - 2530585658U, 25011837U, 3520020182U, 2088578344U, - 530523599U, 2918365339U, 1524020338U, 1518925132U, - 3760827505U, 3759777254U, 1202760957U, 3985898139U, - 3906192525U, 674977740U, 4174734889U, 2031300136U, - 2019492241U, 3983892565U, 4153806404U, 3822280332U, - 352677332U, 2297720250U, 60907813U, 90501309U, - 3286998549U, 1016092578U, 2535922412U, 2839152426U, - 457141659U, 509813237U, 4120667899U, 652014361U, - 1966332200U, 2975202805U, 55981186U, 2327461051U, - 676427537U, 3255491064U, 2882294119U, 3433927263U, - 1307055953U, 942726286U, 933058658U, 2468411793U, - 3933900994U, 4215176142U, 1361170020U, 2001714738U, - 2830558078U, 3274259782U, 1222529897U, 1679025792U, - 2729314320U, 3714953764U, 1770335741U, 151462246U, - 3013232138U, 1682292957U, 1483529935U, 471910574U, - 1539241949U, 458788160U, 3436315007U, 1807016891U, - 3718408830U, 978976581U, 1043663428U, 3165965781U, - 1927990952U, 4200891579U, 2372276910U, 3208408903U, - 3533431907U, 1412390302U, 2931980059U, 4132332400U, - 1947078029U, 3881505623U, 4168226417U, 2941484381U, - 1077988104U, 1320477388U, 886195818U, 18198404U, - 3786409000U, 2509781533U, 112762804U, 3463356488U, - 1866414978U, 891333506U, 18488651U, 661792760U, - 1628790961U, 3885187036U, 3141171499U, 876946877U, - 2693282273U, 1372485963U, 791857591U, 2686433993U, - 3759982718U, 3167212022U, 3472953795U, 2716379847U, - 445679433U, 3561995674U, 3504004811U, 3574258232U, - 54117162U, 3331405415U, 2381918588U, 3769707343U, - 4154350007U, 1140177722U, 4074052095U, 668550556U, - 3214352940U, 367459370U, 261225585U, 2610173221U, - 4209349473U, 3468074219U, 3265815641U, 314222801U, - 3066103646U, 3808782860U, 282218597U, 3406013506U, - 3773591054U, 379116347U, 1285071038U, 846784868U, - 2669647154U, 3771962079U, 3550491691U, 2305946142U, - 453669953U, 1268987020U, 3317592352U, 3279303384U, - 3744833421U, 2610507566U, 3859509063U, 266596637U, - 3847019092U, 517658769U, 3462560207U, 3443424879U, - 370717030U, 4247526661U, 2224018117U, 4143653529U, - 4112773975U, 2788324899U, 2477274417U, 1456262402U, - 2901442914U, 1517677493U, 1846949527U, 2295493580U, - 3734397586U, 2176403920U, 1280348187U, 1908823572U, - 3871786941U, 846861322U, 1172426758U, 3287448474U, - 3383383037U, 1655181056U, 3139813346U, 901632758U, - 1897031941U, 2986607138U, 3066810236U, 3447102507U, - 1393639104U, 373351379U, 950779232U, 625454576U, - 3124240540U, 4148612726U, 2007998917U, 544563296U, - 2244738638U, 2330496472U, 2058025392U, 1291430526U, - 424198748U, 50039436U, 29584100U, 3605783033U, - 2429876329U, 2791104160U, 1057563949U, 3255363231U, - 3075367218U, 3463963227U, 1469046755U, 985887462U -}; - - -// this version is only used to make pbox and sbox -static void crypt_block(BF_KEY *key, const word32 in[2], word32 out[2]) -{ - word32 left = in[0]; - word32 right = in[1]; - - const word32 *const s=key->sbox; - const word32 *p=key->pbox; - - unsigned i; - - left ^= p[0]; - - for (i=0; isbox; - word32 *pbox = key->pbox; - - memcpy(pbox, p_init, sizeof(p_init)); - memcpy(sbox, s_init, sizeof(s_init)); - - // Xor key string into encryption key vector - for (i=0 ; ipbox_dec[ROUNDS+1-i] = pbox[i]; -} - - -void BlowfishEncryptLE (unsigned char *inBlock, unsigned char *outBlock, BF_KEY *key, int encrypt) -{ - word32 left = LE32 (((word32 *) inBlock)[0]); - word32 right = LE32 (((word32 *) inBlock)[1]); - - const word32 *const s = key->sbox; - const word32 * p = encrypt ? key->pbox : key->pbox_dec; - - unsigned i; - - left ^= p[0]; - - for (i=0; i +#include "Common/Tcdefs.h" +#include "Common/Endian.h" +#include "Blowfish.h" + +#define word32 unsigned __int32 +#define byte unsigned __int8 +#define GETBYTE(x, y) (unsigned int)(byte)((x)>>(8*(y))) +#define ROUNDS 16 + +static const unsigned __int32 p_init[16+2] = +{ + 608135816U, 2242054355U, 320440878U, 57701188U, + 2752067618U, 698298832U, 137296536U, 3964562569U, + 1160258022U, 953160567U, 3193202383U, 887688300U, + 3232508343U, 3380367581U, 1065670069U, 3041331479U, + 2450970073U, 2306472731U +} ; + +static const unsigned __int32 s_init[4*256] = { + 3509652390U, 2564797868U, 805139163U, 3491422135U, + 3101798381U, 1780907670U, 3128725573U, 4046225305U, + 614570311U, 3012652279U, 134345442U, 2240740374U, + 1667834072U, 1901547113U, 2757295779U, 4103290238U, + 227898511U, 1921955416U, 1904987480U, 2182433518U, + 2069144605U, 3260701109U, 2620446009U, 720527379U, + 3318853667U, 677414384U, 3393288472U, 3101374703U, + 2390351024U, 1614419982U, 1822297739U, 2954791486U, + 3608508353U, 3174124327U, 2024746970U, 1432378464U, + 3864339955U, 2857741204U, 1464375394U, 1676153920U, + 1439316330U, 715854006U, 3033291828U, 289532110U, + 2706671279U, 2087905683U, 3018724369U, 1668267050U, + 732546397U, 1947742710U, 3462151702U, 2609353502U, + 2950085171U, 1814351708U, 2050118529U, 680887927U, + 999245976U, 1800124847U, 3300911131U, 1713906067U, + 1641548236U, 4213287313U, 1216130144U, 1575780402U, + 4018429277U, 3917837745U, 3693486850U, 3949271944U, + 596196993U, 3549867205U, 258830323U, 2213823033U, + 772490370U, 2760122372U, 1774776394U, 2652871518U, + 566650946U, 4142492826U, 1728879713U, 2882767088U, + 1783734482U, 3629395816U, 2517608232U, 2874225571U, + 1861159788U, 326777828U, 3124490320U, 2130389656U, + 2716951837U, 967770486U, 1724537150U, 2185432712U, + 2364442137U, 1164943284U, 2105845187U, 998989502U, + 3765401048U, 2244026483U, 1075463327U, 1455516326U, + 1322494562U, 910128902U, 469688178U, 1117454909U, + 936433444U, 3490320968U, 3675253459U, 1240580251U, + 122909385U, 2157517691U, 634681816U, 4142456567U, + 3825094682U, 3061402683U, 2540495037U, 79693498U, + 3249098678U, 1084186820U, 1583128258U, 426386531U, + 1761308591U, 1047286709U, 322548459U, 995290223U, + 1845252383U, 2603652396U, 3431023940U, 2942221577U, + 3202600964U, 3727903485U, 1712269319U, 422464435U, + 3234572375U, 1170764815U, 3523960633U, 3117677531U, + 1434042557U, 442511882U, 3600875718U, 1076654713U, + 1738483198U, 4213154764U, 2393238008U, 3677496056U, + 1014306527U, 4251020053U, 793779912U, 2902807211U, + 842905082U, 4246964064U, 1395751752U, 1040244610U, + 2656851899U, 3396308128U, 445077038U, 3742853595U, + 3577915638U, 679411651U, 2892444358U, 2354009459U, + 1767581616U, 3150600392U, 3791627101U, 3102740896U, + 284835224U, 4246832056U, 1258075500U, 768725851U, + 2589189241U, 3069724005U, 3532540348U, 1274779536U, + 3789419226U, 2764799539U, 1660621633U, 3471099624U, + 4011903706U, 913787905U, 3497959166U, 737222580U, + 2514213453U, 2928710040U, 3937242737U, 1804850592U, + 3499020752U, 2949064160U, 2386320175U, 2390070455U, + 2415321851U, 4061277028U, 2290661394U, 2416832540U, + 1336762016U, 1754252060U, 3520065937U, 3014181293U, + 791618072U, 3188594551U, 3933548030U, 2332172193U, + 3852520463U, 3043980520U, 413987798U, 3465142937U, + 3030929376U, 4245938359U, 2093235073U, 3534596313U, + 375366246U, 2157278981U, 2479649556U, 555357303U, + 3870105701U, 2008414854U, 3344188149U, 4221384143U, + 3956125452U, 2067696032U, 3594591187U, 2921233993U, + 2428461U, 544322398U, 577241275U, 1471733935U, + 610547355U, 4027169054U, 1432588573U, 1507829418U, + 2025931657U, 3646575487U, 545086370U, 48609733U, + 2200306550U, 1653985193U, 298326376U, 1316178497U, + 3007786442U, 2064951626U, 458293330U, 2589141269U, + 3591329599U, 3164325604U, 727753846U, 2179363840U, + 146436021U, 1461446943U, 4069977195U, 705550613U, + 3059967265U, 3887724982U, 4281599278U, 3313849956U, + 1404054877U, 2845806497U, 146425753U, 1854211946U, + + 1266315497U, 3048417604U, 3681880366U, 3289982499U, + 2909710000U, 1235738493U, 2632868024U, 2414719590U, + 3970600049U, 1771706367U, 1449415276U, 3266420449U, + 422970021U, 1963543593U, 2690192192U, 3826793022U, + 1062508698U, 1531092325U, 1804592342U, 2583117782U, + 2714934279U, 4024971509U, 1294809318U, 4028980673U, + 1289560198U, 2221992742U, 1669523910U, 35572830U, + 157838143U, 1052438473U, 1016535060U, 1802137761U, + 1753167236U, 1386275462U, 3080475397U, 2857371447U, + 1040679964U, 2145300060U, 2390574316U, 1461121720U, + 2956646967U, 4031777805U, 4028374788U, 33600511U, + 2920084762U, 1018524850U, 629373528U, 3691585981U, + 3515945977U, 2091462646U, 2486323059U, 586499841U, + 988145025U, 935516892U, 3367335476U, 2599673255U, + 2839830854U, 265290510U, 3972581182U, 2759138881U, + 3795373465U, 1005194799U, 847297441U, 406762289U, + 1314163512U, 1332590856U, 1866599683U, 4127851711U, + 750260880U, 613907577U, 1450815602U, 3165620655U, + 3734664991U, 3650291728U, 3012275730U, 3704569646U, + 1427272223U, 778793252U, 1343938022U, 2676280711U, + 2052605720U, 1946737175U, 3164576444U, 3914038668U, + 3967478842U, 3682934266U, 1661551462U, 3294938066U, + 4011595847U, 840292616U, 3712170807U, 616741398U, + 312560963U, 711312465U, 1351876610U, 322626781U, + 1910503582U, 271666773U, 2175563734U, 1594956187U, + 70604529U, 3617834859U, 1007753275U, 1495573769U, + 4069517037U, 2549218298U, 2663038764U, 504708206U, + 2263041392U, 3941167025U, 2249088522U, 1514023603U, + 1998579484U, 1312622330U, 694541497U, 2582060303U, + 2151582166U, 1382467621U, 776784248U, 2618340202U, + 3323268794U, 2497899128U, 2784771155U, 503983604U, + 4076293799U, 907881277U, 423175695U, 432175456U, + 1378068232U, 4145222326U, 3954048622U, 3938656102U, + 3820766613U, 2793130115U, 2977904593U, 26017576U, + 3274890735U, 3194772133U, 1700274565U, 1756076034U, + 4006520079U, 3677328699U, 720338349U, 1533947780U, + 354530856U, 688349552U, 3973924725U, 1637815568U, + 332179504U, 3949051286U, 53804574U, 2852348879U, + 3044236432U, 1282449977U, 3583942155U, 3416972820U, + 4006381244U, 1617046695U, 2628476075U, 3002303598U, + 1686838959U, 431878346U, 2686675385U, 1700445008U, + 1080580658U, 1009431731U, 832498133U, 3223435511U, + 2605976345U, 2271191193U, 2516031870U, 1648197032U, + 4164389018U, 2548247927U, 300782431U, 375919233U, + 238389289U, 3353747414U, 2531188641U, 2019080857U, + 1475708069U, 455242339U, 2609103871U, 448939670U, + 3451063019U, 1395535956U, 2413381860U, 1841049896U, + 1491858159U, 885456874U, 4264095073U, 4001119347U, + 1565136089U, 3898914787U, 1108368660U, 540939232U, + 1173283510U, 2745871338U, 3681308437U, 4207628240U, + 3343053890U, 4016749493U, 1699691293U, 1103962373U, + 3625875870U, 2256883143U, 3830138730U, 1031889488U, + 3479347698U, 1535977030U, 4236805024U, 3251091107U, + 2132092099U, 1774941330U, 1199868427U, 1452454533U, + 157007616U, 2904115357U, 342012276U, 595725824U, + 1480756522U, 206960106U, 497939518U, 591360097U, + 863170706U, 2375253569U, 3596610801U, 1814182875U, + 2094937945U, 3421402208U, 1082520231U, 3463918190U, + 2785509508U, 435703966U, 3908032597U, 1641649973U, + 2842273706U, 3305899714U, 1510255612U, 2148256476U, + 2655287854U, 3276092548U, 4258621189U, 236887753U, + 3681803219U, 274041037U, 1734335097U, 3815195456U, + 3317970021U, 1899903192U, 1026095262U, 4050517792U, + 356393447U, 2410691914U, 3873677099U, 3682840055U, + + 3913112168U, 2491498743U, 4132185628U, 2489919796U, + 1091903735U, 1979897079U, 3170134830U, 3567386728U, + 3557303409U, 857797738U, 1136121015U, 1342202287U, + 507115054U, 2535736646U, 337727348U, 3213592640U, + 1301675037U, 2528481711U, 1895095763U, 1721773893U, + 3216771564U, 62756741U, 2142006736U, 835421444U, + 2531993523U, 1442658625U, 3659876326U, 2882144922U, + 676362277U, 1392781812U, 170690266U, 3921047035U, + 1759253602U, 3611846912U, 1745797284U, 664899054U, + 1329594018U, 3901205900U, 3045908486U, 2062866102U, + 2865634940U, 3543621612U, 3464012697U, 1080764994U, + 553557557U, 3656615353U, 3996768171U, 991055499U, + 499776247U, 1265440854U, 648242737U, 3940784050U, + 980351604U, 3713745714U, 1749149687U, 3396870395U, + 4211799374U, 3640570775U, 1161844396U, 3125318951U, + 1431517754U, 545492359U, 4268468663U, 3499529547U, + 1437099964U, 2702547544U, 3433638243U, 2581715763U, + 2787789398U, 1060185593U, 1593081372U, 2418618748U, + 4260947970U, 69676912U, 2159744348U, 86519011U, + 2512459080U, 3838209314U, 1220612927U, 3339683548U, + 133810670U, 1090789135U, 1078426020U, 1569222167U, + 845107691U, 3583754449U, 4072456591U, 1091646820U, + 628848692U, 1613405280U, 3757631651U, 526609435U, + 236106946U, 48312990U, 2942717905U, 3402727701U, + 1797494240U, 859738849U, 992217954U, 4005476642U, + 2243076622U, 3870952857U, 3732016268U, 765654824U, + 3490871365U, 2511836413U, 1685915746U, 3888969200U, + 1414112111U, 2273134842U, 3281911079U, 4080962846U, + 172450625U, 2569994100U, 980381355U, 4109958455U, + 2819808352U, 2716589560U, 2568741196U, 3681446669U, + 3329971472U, 1835478071U, 660984891U, 3704678404U, + 4045999559U, 3422617507U, 3040415634U, 1762651403U, + 1719377915U, 3470491036U, 2693910283U, 3642056355U, + 3138596744U, 1364962596U, 2073328063U, 1983633131U, + 926494387U, 3423689081U, 2150032023U, 4096667949U, + 1749200295U, 3328846651U, 309677260U, 2016342300U, + 1779581495U, 3079819751U, 111262694U, 1274766160U, + 443224088U, 298511866U, 1025883608U, 3806446537U, + 1145181785U, 168956806U, 3641502830U, 3584813610U, + 1689216846U, 3666258015U, 3200248200U, 1692713982U, + 2646376535U, 4042768518U, 1618508792U, 1610833997U, + 3523052358U, 4130873264U, 2001055236U, 3610705100U, + 2202168115U, 4028541809U, 2961195399U, 1006657119U, + 2006996926U, 3186142756U, 1430667929U, 3210227297U, + 1314452623U, 4074634658U, 4101304120U, 2273951170U, + 1399257539U, 3367210612U, 3027628629U, 1190975929U, + 2062231137U, 2333990788U, 2221543033U, 2438960610U, + 1181637006U, 548689776U, 2362791313U, 3372408396U, + 3104550113U, 3145860560U, 296247880U, 1970579870U, + 3078560182U, 3769228297U, 1714227617U, 3291629107U, + 3898220290U, 166772364U, 1251581989U, 493813264U, + 448347421U, 195405023U, 2709975567U, 677966185U, + 3703036547U, 1463355134U, 2715995803U, 1338867538U, + 1343315457U, 2802222074U, 2684532164U, 233230375U, + 2599980071U, 2000651841U, 3277868038U, 1638401717U, + 4028070440U, 3237316320U, 6314154U, 819756386U, + 300326615U, 590932579U, 1405279636U, 3267499572U, + 3150704214U, 2428286686U, 3959192993U, 3461946742U, + 1862657033U, 1266418056U, 963775037U, 2089974820U, + 2263052895U, 1917689273U, 448879540U, 3550394620U, + 3981727096U, 150775221U, 3627908307U, 1303187396U, + 508620638U, 2975983352U, 2726630617U, 1817252668U, + 1876281319U, 1457606340U, 908771278U, 3720792119U, + 3617206836U, 2455994898U, 1729034894U, 1080033504U, + + 976866871U, 3556439503U, 2881648439U, 1522871579U, + 1555064734U, 1336096578U, 3548522304U, 2579274686U, + 3574697629U, 3205460757U, 3593280638U, 3338716283U, + 3079412587U, 564236357U, 2993598910U, 1781952180U, + 1464380207U, 3163844217U, 3332601554U, 1699332808U, + 1393555694U, 1183702653U, 3581086237U, 1288719814U, + 691649499U, 2847557200U, 2895455976U, 3193889540U, + 2717570544U, 1781354906U, 1676643554U, 2592534050U, + 3230253752U, 1126444790U, 2770207658U, 2633158820U, + 2210423226U, 2615765581U, 2414155088U, 3127139286U, + 673620729U, 2805611233U, 1269405062U, 4015350505U, + 3341807571U, 4149409754U, 1057255273U, 2012875353U, + 2162469141U, 2276492801U, 2601117357U, 993977747U, + 3918593370U, 2654263191U, 753973209U, 36408145U, + 2530585658U, 25011837U, 3520020182U, 2088578344U, + 530523599U, 2918365339U, 1524020338U, 1518925132U, + 3760827505U, 3759777254U, 1202760957U, 3985898139U, + 3906192525U, 674977740U, 4174734889U, 2031300136U, + 2019492241U, 3983892565U, 4153806404U, 3822280332U, + 352677332U, 2297720250U, 60907813U, 90501309U, + 3286998549U, 1016092578U, 2535922412U, 2839152426U, + 457141659U, 509813237U, 4120667899U, 652014361U, + 1966332200U, 2975202805U, 55981186U, 2327461051U, + 676427537U, 3255491064U, 2882294119U, 3433927263U, + 1307055953U, 942726286U, 933058658U, 2468411793U, + 3933900994U, 4215176142U, 1361170020U, 2001714738U, + 2830558078U, 3274259782U, 1222529897U, 1679025792U, + 2729314320U, 3714953764U, 1770335741U, 151462246U, + 3013232138U, 1682292957U, 1483529935U, 471910574U, + 1539241949U, 458788160U, 3436315007U, 1807016891U, + 3718408830U, 978976581U, 1043663428U, 3165965781U, + 1927990952U, 4200891579U, 2372276910U, 3208408903U, + 3533431907U, 1412390302U, 2931980059U, 4132332400U, + 1947078029U, 3881505623U, 4168226417U, 2941484381U, + 1077988104U, 1320477388U, 886195818U, 18198404U, + 3786409000U, 2509781533U, 112762804U, 3463356488U, + 1866414978U, 891333506U, 18488651U, 661792760U, + 1628790961U, 3885187036U, 3141171499U, 876946877U, + 2693282273U, 1372485963U, 791857591U, 2686433993U, + 3759982718U, 3167212022U, 3472953795U, 2716379847U, + 445679433U, 3561995674U, 3504004811U, 3574258232U, + 54117162U, 3331405415U, 2381918588U, 3769707343U, + 4154350007U, 1140177722U, 4074052095U, 668550556U, + 3214352940U, 367459370U, 261225585U, 2610173221U, + 4209349473U, 3468074219U, 3265815641U, 314222801U, + 3066103646U, 3808782860U, 282218597U, 3406013506U, + 3773591054U, 379116347U, 1285071038U, 846784868U, + 2669647154U, 3771962079U, 3550491691U, 2305946142U, + 453669953U, 1268987020U, 3317592352U, 3279303384U, + 3744833421U, 2610507566U, 3859509063U, 266596637U, + 3847019092U, 517658769U, 3462560207U, 3443424879U, + 370717030U, 4247526661U, 2224018117U, 4143653529U, + 4112773975U, 2788324899U, 2477274417U, 1456262402U, + 2901442914U, 1517677493U, 1846949527U, 2295493580U, + 3734397586U, 2176403920U, 1280348187U, 1908823572U, + 3871786941U, 846861322U, 1172426758U, 3287448474U, + 3383383037U, 1655181056U, 3139813346U, 901632758U, + 1897031941U, 2986607138U, 3066810236U, 3447102507U, + 1393639104U, 373351379U, 950779232U, 625454576U, + 3124240540U, 4148612726U, 2007998917U, 544563296U, + 2244738638U, 2330496472U, 2058025392U, 1291430526U, + 424198748U, 50039436U, 29584100U, 3605783033U, + 2429876329U, 2791104160U, 1057563949U, 3255363231U, + 3075367218U, 3463963227U, 1469046755U, 985887462U +}; + + +// this version is only used to make pbox and sbox +static void crypt_block(BF_KEY *key, const word32 in[2], word32 out[2]) +{ + word32 left = in[0]; + word32 right = in[1]; + + const word32 *const s=key->sbox; + const word32 *p=key->pbox; + + unsigned i; + + left ^= p[0]; + + for (i=0; isbox; + word32 *pbox = key->pbox; + + memcpy(pbox, p_init, sizeof(p_init)); + memcpy(sbox, s_init, sizeof(s_init)); + + // Xor key string into encryption key vector + for (i=0 ; ipbox_dec[ROUNDS+1-i] = pbox[i]; +} + + +void BlowfishEncryptLE (unsigned char *inBlock, unsigned char *outBlock, BF_KEY *key, int encrypt) +{ + word32 left = LE32 (((word32 *) inBlock)[0]); + word32 right = LE32 (((word32 *) inBlock)[1]); + + const word32 *const s = key->sbox; + const word32 * p = encrypt ? key->pbox : key->pbox_dec; + + unsigned i; + + left ^= p[0]; + + for (i=0; i -#include "Common/Tcdefs.h" -#include "Common/Endian.h" -#include "Cast.h" - -#define word32 unsigned __int32 -#define byte unsigned __int8 -#define GETBYTE(x, y) (unsigned int)(byte)((x)>>(8*(y))) - -/* Macros to access 8-bit bytes out of a 32-bit word */ -#define U8a(x) GETBYTE(x,3) -#define U8b(x) GETBYTE(x,2) -#define U8c(x) GETBYTE(x,1) -#define U8d(x) GETBYTE(x,0) - -static word32 rotlVariable (word32 x, unsigned int y) -{ - return (word32)((x<>(sizeof(word32)*8-y))); -} - - -// CAST S-boxes - -static const word32 S[8][256] = { -{ - 0x30FB40D4UL, 0x9FA0FF0BUL, 0x6BECCD2FUL, 0x3F258C7AUL, - 0x1E213F2FUL, 0x9C004DD3UL, 0x6003E540UL, 0xCF9FC949UL, - 0xBFD4AF27UL, 0x88BBBDB5UL, 0xE2034090UL, 0x98D09675UL, - 0x6E63A0E0UL, 0x15C361D2UL, 0xC2E7661DUL, 0x22D4FF8EUL, - 0x28683B6FUL, 0xC07FD059UL, 0xFF2379C8UL, 0x775F50E2UL, - 0x43C340D3UL, 0xDF2F8656UL, 0x887CA41AUL, 0xA2D2BD2DUL, - 0xA1C9E0D6UL, 0x346C4819UL, 0x61B76D87UL, 0x22540F2FUL, - 0x2ABE32E1UL, 0xAA54166BUL, 0x22568E3AUL, 0xA2D341D0UL, - 0x66DB40C8UL, 0xA784392FUL, 0x004DFF2FUL, 0x2DB9D2DEUL, - 0x97943FACUL, 0x4A97C1D8UL, 0x527644B7UL, 0xB5F437A7UL, - 0xB82CBAEFUL, 0xD751D159UL, 0x6FF7F0EDUL, 0x5A097A1FUL, - 0x827B68D0UL, 0x90ECF52EUL, 0x22B0C054UL, 0xBC8E5935UL, - 0x4B6D2F7FUL, 0x50BB64A2UL, 0xD2664910UL, 0xBEE5812DUL, - 0xB7332290UL, 0xE93B159FUL, 0xB48EE411UL, 0x4BFF345DUL, - 0xFD45C240UL, 0xAD31973FUL, 0xC4F6D02EUL, 0x55FC8165UL, - 0xD5B1CAADUL, 0xA1AC2DAEUL, 0xA2D4B76DUL, 0xC19B0C50UL, - 0x882240F2UL, 0x0C6E4F38UL, 0xA4E4BFD7UL, 0x4F5BA272UL, - 0x564C1D2FUL, 0xC59C5319UL, 0xB949E354UL, 0xB04669FEUL, - 0xB1B6AB8AUL, 0xC71358DDUL, 0x6385C545UL, 0x110F935DUL, - 0x57538AD5UL, 0x6A390493UL, 0xE63D37E0UL, 0x2A54F6B3UL, - 0x3A787D5FUL, 0x6276A0B5UL, 0x19A6FCDFUL, 0x7A42206AUL, - 0x29F9D4D5UL, 0xF61B1891UL, 0xBB72275EUL, 0xAA508167UL, - 0x38901091UL, 0xC6B505EBUL, 0x84C7CB8CUL, 0x2AD75A0FUL, - 0x874A1427UL, 0xA2D1936BUL, 0x2AD286AFUL, 0xAA56D291UL, - 0xD7894360UL, 0x425C750DUL, 0x93B39E26UL, 0x187184C9UL, - 0x6C00B32DUL, 0x73E2BB14UL, 0xA0BEBC3CUL, 0x54623779UL, - 0x64459EABUL, 0x3F328B82UL, 0x7718CF82UL, 0x59A2CEA6UL, - 0x04EE002EUL, 0x89FE78E6UL, 0x3FAB0950UL, 0x325FF6C2UL, - 0x81383F05UL, 0x6963C5C8UL, 0x76CB5AD6UL, 0xD49974C9UL, - 0xCA180DCFUL, 0x380782D5UL, 0xC7FA5CF6UL, 0x8AC31511UL, - 0x35E79E13UL, 0x47DA91D0UL, 0xF40F9086UL, 0xA7E2419EUL, - 0x31366241UL, 0x051EF495UL, 0xAA573B04UL, 0x4A805D8DUL, - 0x548300D0UL, 0x00322A3CUL, 0xBF64CDDFUL, 0xBA57A68EUL, - 0x75C6372BUL, 0x50AFD341UL, 0xA7C13275UL, 0x915A0BF5UL, - 0x6B54BFABUL, 0x2B0B1426UL, 0xAB4CC9D7UL, 0x449CCD82UL, - 0xF7FBF265UL, 0xAB85C5F3UL, 0x1B55DB94UL, 0xAAD4E324UL, - 0xCFA4BD3FUL, 0x2DEAA3E2UL, 0x9E204D02UL, 0xC8BD25ACUL, - 0xEADF55B3UL, 0xD5BD9E98UL, 0xE31231B2UL, 0x2AD5AD6CUL, - 0x954329DEUL, 0xADBE4528UL, 0xD8710F69UL, 0xAA51C90FUL, - 0xAA786BF6UL, 0x22513F1EUL, 0xAA51A79BUL, 0x2AD344CCUL, - 0x7B5A41F0UL, 0xD37CFBADUL, 0x1B069505UL, 0x41ECE491UL, - 0xB4C332E6UL, 0x032268D4UL, 0xC9600ACCUL, 0xCE387E6DUL, - 0xBF6BB16CUL, 0x6A70FB78UL, 0x0D03D9C9UL, 0xD4DF39DEUL, - 0xE01063DAUL, 0x4736F464UL, 0x5AD328D8UL, 0xB347CC96UL, - 0x75BB0FC3UL, 0x98511BFBUL, 0x4FFBCC35UL, 0xB58BCF6AUL, - 0xE11F0ABCUL, 0xBFC5FE4AUL, 0xA70AEC10UL, 0xAC39570AUL, - 0x3F04442FUL, 0x6188B153UL, 0xE0397A2EUL, 0x5727CB79UL, - 0x9CEB418FUL, 0x1CACD68DUL, 0x2AD37C96UL, 0x0175CB9DUL, - 0xC69DFF09UL, 0xC75B65F0UL, 0xD9DB40D8UL, 0xEC0E7779UL, - 0x4744EAD4UL, 0xB11C3274UL, 0xDD24CB9EUL, 0x7E1C54BDUL, - 0xF01144F9UL, 0xD2240EB1UL, 0x9675B3FDUL, 0xA3AC3755UL, - 0xD47C27AFUL, 0x51C85F4DUL, 0x56907596UL, 0xA5BB15E6UL, - 0x580304F0UL, 0xCA042CF1UL, 0x011A37EAUL, 0x8DBFAADBUL, - 0x35BA3E4AUL, 0x3526FFA0UL, 0xC37B4D09UL, 0xBC306ED9UL, - 0x98A52666UL, 0x5648F725UL, 0xFF5E569DUL, 0x0CED63D0UL, - 0x7C63B2CFUL, 0x700B45E1UL, 0xD5EA50F1UL, 0x85A92872UL, - 0xAF1FBDA7UL, 0xD4234870UL, 0xA7870BF3UL, 0x2D3B4D79UL, - 0x42E04198UL, 0x0CD0EDE7UL, 0x26470DB8UL, 0xF881814CUL, - 0x474D6AD7UL, 0x7C0C5E5CUL, 0xD1231959UL, 0x381B7298UL, - 0xF5D2F4DBUL, 0xAB838653UL, 0x6E2F1E23UL, 0x83719C9EUL, - 0xBD91E046UL, 0x9A56456EUL, 0xDC39200CUL, 0x20C8C571UL, - 0x962BDA1CUL, 0xE1E696FFUL, 0xB141AB08UL, 0x7CCA89B9UL, - 0x1A69E783UL, 0x02CC4843UL, 0xA2F7C579UL, 0x429EF47DUL, - 0x427B169CUL, 0x5AC9F049UL, 0xDD8F0F00UL, 0x5C8165BFUL -}, - -{ - 0x1F201094UL, 0xEF0BA75BUL, 0x69E3CF7EUL, 0x393F4380UL, - 0xFE61CF7AUL, 0xEEC5207AUL, 0x55889C94UL, 0x72FC0651UL, - 0xADA7EF79UL, 0x4E1D7235UL, 0xD55A63CEUL, 0xDE0436BAUL, - 0x99C430EFUL, 0x5F0C0794UL, 0x18DCDB7DUL, 0xA1D6EFF3UL, - 0xA0B52F7BUL, 0x59E83605UL, 0xEE15B094UL, 0xE9FFD909UL, - 0xDC440086UL, 0xEF944459UL, 0xBA83CCB3UL, 0xE0C3CDFBUL, - 0xD1DA4181UL, 0x3B092AB1UL, 0xF997F1C1UL, 0xA5E6CF7BUL, - 0x01420DDBUL, 0xE4E7EF5BUL, 0x25A1FF41UL, 0xE180F806UL, - 0x1FC41080UL, 0x179BEE7AUL, 0xD37AC6A9UL, 0xFE5830A4UL, - 0x98DE8B7FUL, 0x77E83F4EUL, 0x79929269UL, 0x24FA9F7BUL, - 0xE113C85BUL, 0xACC40083UL, 0xD7503525UL, 0xF7EA615FUL, - 0x62143154UL, 0x0D554B63UL, 0x5D681121UL, 0xC866C359UL, - 0x3D63CF73UL, 0xCEE234C0UL, 0xD4D87E87UL, 0x5C672B21UL, - 0x071F6181UL, 0x39F7627FUL, 0x361E3084UL, 0xE4EB573BUL, - 0x602F64A4UL, 0xD63ACD9CUL, 0x1BBC4635UL, 0x9E81032DUL, - 0x2701F50CUL, 0x99847AB4UL, 0xA0E3DF79UL, 0xBA6CF38CUL, - 0x10843094UL, 0x2537A95EUL, 0xF46F6FFEUL, 0xA1FF3B1FUL, - 0x208CFB6AUL, 0x8F458C74UL, 0xD9E0A227UL, 0x4EC73A34UL, - 0xFC884F69UL, 0x3E4DE8DFUL, 0xEF0E0088UL, 0x3559648DUL, - 0x8A45388CUL, 0x1D804366UL, 0x721D9BFDUL, 0xA58684BBUL, - 0xE8256333UL, 0x844E8212UL, 0x128D8098UL, 0xFED33FB4UL, - 0xCE280AE1UL, 0x27E19BA5UL, 0xD5A6C252UL, 0xE49754BDUL, - 0xC5D655DDUL, 0xEB667064UL, 0x77840B4DUL, 0xA1B6A801UL, - 0x84DB26A9UL, 0xE0B56714UL, 0x21F043B7UL, 0xE5D05860UL, - 0x54F03084UL, 0x066FF472UL, 0xA31AA153UL, 0xDADC4755UL, - 0xB5625DBFUL, 0x68561BE6UL, 0x83CA6B94UL, 0x2D6ED23BUL, - 0xECCF01DBUL, 0xA6D3D0BAUL, 0xB6803D5CUL, 0xAF77A709UL, - 0x33B4A34CUL, 0x397BC8D6UL, 0x5EE22B95UL, 0x5F0E5304UL, - 0x81ED6F61UL, 0x20E74364UL, 0xB45E1378UL, 0xDE18639BUL, - 0x881CA122UL, 0xB96726D1UL, 0x8049A7E8UL, 0x22B7DA7BUL, - 0x5E552D25UL, 0x5272D237UL, 0x79D2951CUL, 0xC60D894CUL, - 0x488CB402UL, 0x1BA4FE5BUL, 0xA4B09F6BUL, 0x1CA815CFUL, - 0xA20C3005UL, 0x8871DF63UL, 0xB9DE2FCBUL, 0x0CC6C9E9UL, - 0x0BEEFF53UL, 0xE3214517UL, 0xB4542835UL, 0x9F63293CUL, - 0xEE41E729UL, 0x6E1D2D7CUL, 0x50045286UL, 0x1E6685F3UL, - 0xF33401C6UL, 0x30A22C95UL, 0x31A70850UL, 0x60930F13UL, - 0x73F98417UL, 0xA1269859UL, 0xEC645C44UL, 0x52C877A9UL, - 0xCDFF33A6UL, 0xA02B1741UL, 0x7CBAD9A2UL, 0x2180036FUL, - 0x50D99C08UL, 0xCB3F4861UL, 0xC26BD765UL, 0x64A3F6ABUL, - 0x80342676UL, 0x25A75E7BUL, 0xE4E6D1FCUL, 0x20C710E6UL, - 0xCDF0B680UL, 0x17844D3BUL, 0x31EEF84DUL, 0x7E0824E4UL, - 0x2CCB49EBUL, 0x846A3BAEUL, 0x8FF77888UL, 0xEE5D60F6UL, - 0x7AF75673UL, 0x2FDD5CDBUL, 0xA11631C1UL, 0x30F66F43UL, - 0xB3FAEC54UL, 0x157FD7FAUL, 0xEF8579CCUL, 0xD152DE58UL, - 0xDB2FFD5EUL, 0x8F32CE19UL, 0x306AF97AUL, 0x02F03EF8UL, - 0x99319AD5UL, 0xC242FA0FUL, 0xA7E3EBB0UL, 0xC68E4906UL, - 0xB8DA230CUL, 0x80823028UL, 0xDCDEF3C8UL, 0xD35FB171UL, - 0x088A1BC8UL, 0xBEC0C560UL, 0x61A3C9E8UL, 0xBCA8F54DUL, - 0xC72FEFFAUL, 0x22822E99UL, 0x82C570B4UL, 0xD8D94E89UL, - 0x8B1C34BCUL, 0x301E16E6UL, 0x273BE979UL, 0xB0FFEAA6UL, - 0x61D9B8C6UL, 0x00B24869UL, 0xB7FFCE3FUL, 0x08DC283BUL, - 0x43DAF65AUL, 0xF7E19798UL, 0x7619B72FUL, 0x8F1C9BA4UL, - 0xDC8637A0UL, 0x16A7D3B1UL, 0x9FC393B7UL, 0xA7136EEBUL, - 0xC6BCC63EUL, 0x1A513742UL, 0xEF6828BCUL, 0x520365D6UL, - 0x2D6A77ABUL, 0x3527ED4BUL, 0x821FD216UL, 0x095C6E2EUL, - 0xDB92F2FBUL, 0x5EEA29CBUL, 0x145892F5UL, 0x91584F7FUL, - 0x5483697BUL, 0x2667A8CCUL, 0x85196048UL, 0x8C4BACEAUL, - 0x833860D4UL, 0x0D23E0F9UL, 0x6C387E8AUL, 0x0AE6D249UL, - 0xB284600CUL, 0xD835731DUL, 0xDCB1C647UL, 0xAC4C56EAUL, - 0x3EBD81B3UL, 0x230EABB0UL, 0x6438BC87UL, 0xF0B5B1FAUL, - 0x8F5EA2B3UL, 0xFC184642UL, 0x0A036B7AUL, 0x4FB089BDUL, - 0x649DA589UL, 0xA345415EUL, 0x5C038323UL, 0x3E5D3BB9UL, - 0x43D79572UL, 0x7E6DD07CUL, 0x06DFDF1EUL, 0x6C6CC4EFUL, - 0x7160A539UL, 0x73BFBE70UL, 0x83877605UL, 0x4523ECF1UL -}, - -{ - 0x8DEFC240UL, 0x25FA5D9FUL, 0xEB903DBFUL, 0xE810C907UL, - 0x47607FFFUL, 0x369FE44BUL, 0x8C1FC644UL, 0xAECECA90UL, - 0xBEB1F9BFUL, 0xEEFBCAEAUL, 0xE8CF1950UL, 0x51DF07AEUL, - 0x920E8806UL, 0xF0AD0548UL, 0xE13C8D83UL, 0x927010D5UL, - 0x11107D9FUL, 0x07647DB9UL, 0xB2E3E4D4UL, 0x3D4F285EUL, - 0xB9AFA820UL, 0xFADE82E0UL, 0xA067268BUL, 0x8272792EUL, - 0x553FB2C0UL, 0x489AE22BUL, 0xD4EF9794UL, 0x125E3FBCUL, - 0x21FFFCEEUL, 0x825B1BFDUL, 0x9255C5EDUL, 0x1257A240UL, - 0x4E1A8302UL, 0xBAE07FFFUL, 0x528246E7UL, 0x8E57140EUL, - 0x3373F7BFUL, 0x8C9F8188UL, 0xA6FC4EE8UL, 0xC982B5A5UL, - 0xA8C01DB7UL, 0x579FC264UL, 0x67094F31UL, 0xF2BD3F5FUL, - 0x40FFF7C1UL, 0x1FB78DFCUL, 0x8E6BD2C1UL, 0x437BE59BUL, - 0x99B03DBFUL, 0xB5DBC64BUL, 0x638DC0E6UL, 0x55819D99UL, - 0xA197C81CUL, 0x4A012D6EUL, 0xC5884A28UL, 0xCCC36F71UL, - 0xB843C213UL, 0x6C0743F1UL, 0x8309893CUL, 0x0FEDDD5FUL, - 0x2F7FE850UL, 0xD7C07F7EUL, 0x02507FBFUL, 0x5AFB9A04UL, - 0xA747D2D0UL, 0x1651192EUL, 0xAF70BF3EUL, 0x58C31380UL, - 0x5F98302EUL, 0x727CC3C4UL, 0x0A0FB402UL, 0x0F7FEF82UL, - 0x8C96FDADUL, 0x5D2C2AAEUL, 0x8EE99A49UL, 0x50DA88B8UL, - 0x8427F4A0UL, 0x1EAC5790UL, 0x796FB449UL, 0x8252DC15UL, - 0xEFBD7D9BUL, 0xA672597DUL, 0xADA840D8UL, 0x45F54504UL, - 0xFA5D7403UL, 0xE83EC305UL, 0x4F91751AUL, 0x925669C2UL, - 0x23EFE941UL, 0xA903F12EUL, 0x60270DF2UL, 0x0276E4B6UL, - 0x94FD6574UL, 0x927985B2UL, 0x8276DBCBUL, 0x02778176UL, - 0xF8AF918DUL, 0x4E48F79EUL, 0x8F616DDFUL, 0xE29D840EUL, - 0x842F7D83UL, 0x340CE5C8UL, 0x96BBB682UL, 0x93B4B148UL, - 0xEF303CABUL, 0x984FAF28UL, 0x779FAF9BUL, 0x92DC560DUL, - 0x224D1E20UL, 0x8437AA88UL, 0x7D29DC96UL, 0x2756D3DCUL, - 0x8B907CEEUL, 0xB51FD240UL, 0xE7C07CE3UL, 0xE566B4A1UL, - 0xC3E9615EUL, 0x3CF8209DUL, 0x6094D1E3UL, 0xCD9CA341UL, - 0x5C76460EUL, 0x00EA983BUL, 0xD4D67881UL, 0xFD47572CUL, - 0xF76CEDD9UL, 0xBDA8229CUL, 0x127DADAAUL, 0x438A074EUL, - 0x1F97C090UL, 0x081BDB8AUL, 0x93A07EBEUL, 0xB938CA15UL, - 0x97B03CFFUL, 0x3DC2C0F8UL, 0x8D1AB2ECUL, 0x64380E51UL, - 0x68CC7BFBUL, 0xD90F2788UL, 0x12490181UL, 0x5DE5FFD4UL, - 0xDD7EF86AUL, 0x76A2E214UL, 0xB9A40368UL, 0x925D958FUL, - 0x4B39FFFAUL, 0xBA39AEE9UL, 0xA4FFD30BUL, 0xFAF7933BUL, - 0x6D498623UL, 0x193CBCFAUL, 0x27627545UL, 0x825CF47AUL, - 0x61BD8BA0UL, 0xD11E42D1UL, 0xCEAD04F4UL, 0x127EA392UL, - 0x10428DB7UL, 0x8272A972UL, 0x9270C4A8UL, 0x127DE50BUL, - 0x285BA1C8UL, 0x3C62F44FUL, 0x35C0EAA5UL, 0xE805D231UL, - 0x428929FBUL, 0xB4FCDF82UL, 0x4FB66A53UL, 0x0E7DC15BUL, - 0x1F081FABUL, 0x108618AEUL, 0xFCFD086DUL, 0xF9FF2889UL, - 0x694BCC11UL, 0x236A5CAEUL, 0x12DECA4DUL, 0x2C3F8CC5UL, - 0xD2D02DFEUL, 0xF8EF5896UL, 0xE4CF52DAUL, 0x95155B67UL, - 0x494A488CUL, 0xB9B6A80CUL, 0x5C8F82BCUL, 0x89D36B45UL, - 0x3A609437UL, 0xEC00C9A9UL, 0x44715253UL, 0x0A874B49UL, - 0xD773BC40UL, 0x7C34671CUL, 0x02717EF6UL, 0x4FEB5536UL, - 0xA2D02FFFUL, 0xD2BF60C4UL, 0xD43F03C0UL, 0x50B4EF6DUL, - 0x07478CD1UL, 0x006E1888UL, 0xA2E53F55UL, 0xB9E6D4BCUL, - 0xA2048016UL, 0x97573833UL, 0xD7207D67UL, 0xDE0F8F3DUL, - 0x72F87B33UL, 0xABCC4F33UL, 0x7688C55DUL, 0x7B00A6B0UL, - 0x947B0001UL, 0x570075D2UL, 0xF9BB88F8UL, 0x8942019EUL, - 0x4264A5FFUL, 0x856302E0UL, 0x72DBD92BUL, 0xEE971B69UL, - 0x6EA22FDEUL, 0x5F08AE2BUL, 0xAF7A616DUL, 0xE5C98767UL, - 0xCF1FEBD2UL, 0x61EFC8C2UL, 0xF1AC2571UL, 0xCC8239C2UL, - 0x67214CB8UL, 0xB1E583D1UL, 0xB7DC3E62UL, 0x7F10BDCEUL, - 0xF90A5C38UL, 0x0FF0443DUL, 0x606E6DC6UL, 0x60543A49UL, - 0x5727C148UL, 0x2BE98A1DUL, 0x8AB41738UL, 0x20E1BE24UL, - 0xAF96DA0FUL, 0x68458425UL, 0x99833BE5UL, 0x600D457DUL, - 0x282F9350UL, 0x8334B362UL, 0xD91D1120UL, 0x2B6D8DA0UL, - 0x642B1E31UL, 0x9C305A00UL, 0x52BCE688UL, 0x1B03588AUL, - 0xF7BAEFD5UL, 0x4142ED9CUL, 0xA4315C11UL, 0x83323EC5UL, - 0xDFEF4636UL, 0xA133C501UL, 0xE9D3531CUL, 0xEE353783UL -}, - -{ - 0x9DB30420UL, 0x1FB6E9DEUL, 0xA7BE7BEFUL, 0xD273A298UL, - 0x4A4F7BDBUL, 0x64AD8C57UL, 0x85510443UL, 0xFA020ED1UL, - 0x7E287AFFUL, 0xE60FB663UL, 0x095F35A1UL, 0x79EBF120UL, - 0xFD059D43UL, 0x6497B7B1UL, 0xF3641F63UL, 0x241E4ADFUL, - 0x28147F5FUL, 0x4FA2B8CDUL, 0xC9430040UL, 0x0CC32220UL, - 0xFDD30B30UL, 0xC0A5374FUL, 0x1D2D00D9UL, 0x24147B15UL, - 0xEE4D111AUL, 0x0FCA5167UL, 0x71FF904CUL, 0x2D195FFEUL, - 0x1A05645FUL, 0x0C13FEFEUL, 0x081B08CAUL, 0x05170121UL, - 0x80530100UL, 0xE83E5EFEUL, 0xAC9AF4F8UL, 0x7FE72701UL, - 0xD2B8EE5FUL, 0x06DF4261UL, 0xBB9E9B8AUL, 0x7293EA25UL, - 0xCE84FFDFUL, 0xF5718801UL, 0x3DD64B04UL, 0xA26F263BUL, - 0x7ED48400UL, 0x547EEBE6UL, 0x446D4CA0UL, 0x6CF3D6F5UL, - 0x2649ABDFUL, 0xAEA0C7F5UL, 0x36338CC1UL, 0x503F7E93UL, - 0xD3772061UL, 0x11B638E1UL, 0x72500E03UL, 0xF80EB2BBUL, - 0xABE0502EUL, 0xEC8D77DEUL, 0x57971E81UL, 0xE14F6746UL, - 0xC9335400UL, 0x6920318FUL, 0x081DBB99UL, 0xFFC304A5UL, - 0x4D351805UL, 0x7F3D5CE3UL, 0xA6C866C6UL, 0x5D5BCCA9UL, - 0xDAEC6FEAUL, 0x9F926F91UL, 0x9F46222FUL, 0x3991467DUL, - 0xA5BF6D8EUL, 0x1143C44FUL, 0x43958302UL, 0xD0214EEBUL, - 0x022083B8UL, 0x3FB6180CUL, 0x18F8931EUL, 0x281658E6UL, - 0x26486E3EUL, 0x8BD78A70UL, 0x7477E4C1UL, 0xB506E07CUL, - 0xF32D0A25UL, 0x79098B02UL, 0xE4EABB81UL, 0x28123B23UL, - 0x69DEAD38UL, 0x1574CA16UL, 0xDF871B62UL, 0x211C40B7UL, - 0xA51A9EF9UL, 0x0014377BUL, 0x041E8AC8UL, 0x09114003UL, - 0xBD59E4D2UL, 0xE3D156D5UL, 0x4FE876D5UL, 0x2F91A340UL, - 0x557BE8DEUL, 0x00EAE4A7UL, 0x0CE5C2ECUL, 0x4DB4BBA6UL, - 0xE756BDFFUL, 0xDD3369ACUL, 0xEC17B035UL, 0x06572327UL, - 0x99AFC8B0UL, 0x56C8C391UL, 0x6B65811CUL, 0x5E146119UL, - 0x6E85CB75UL, 0xBE07C002UL, 0xC2325577UL, 0x893FF4ECUL, - 0x5BBFC92DUL, 0xD0EC3B25UL, 0xB7801AB7UL, 0x8D6D3B24UL, - 0x20C763EFUL, 0xC366A5FCUL, 0x9C382880UL, 0x0ACE3205UL, - 0xAAC9548AUL, 0xECA1D7C7UL, 0x041AFA32UL, 0x1D16625AUL, - 0x6701902CUL, 0x9B757A54UL, 0x31D477F7UL, 0x9126B031UL, - 0x36CC6FDBUL, 0xC70B8B46UL, 0xD9E66A48UL, 0x56E55A79UL, - 0x026A4CEBUL, 0x52437EFFUL, 0x2F8F76B4UL, 0x0DF980A5UL, - 0x8674CDE3UL, 0xEDDA04EBUL, 0x17A9BE04UL, 0x2C18F4DFUL, - 0xB7747F9DUL, 0xAB2AF7B4UL, 0xEFC34D20UL, 0x2E096B7CUL, - 0x1741A254UL, 0xE5B6A035UL, 0x213D42F6UL, 0x2C1C7C26UL, - 0x61C2F50FUL, 0x6552DAF9UL, 0xD2C231F8UL, 0x25130F69UL, - 0xD8167FA2UL, 0x0418F2C8UL, 0x001A96A6UL, 0x0D1526ABUL, - 0x63315C21UL, 0x5E0A72ECUL, 0x49BAFEFDUL, 0x187908D9UL, - 0x8D0DBD86UL, 0x311170A7UL, 0x3E9B640CUL, 0xCC3E10D7UL, - 0xD5CAD3B6UL, 0x0CAEC388UL, 0xF73001E1UL, 0x6C728AFFUL, - 0x71EAE2A1UL, 0x1F9AF36EUL, 0xCFCBD12FUL, 0xC1DE8417UL, - 0xAC07BE6BUL, 0xCB44A1D8UL, 0x8B9B0F56UL, 0x013988C3UL, - 0xB1C52FCAUL, 0xB4BE31CDUL, 0xD8782806UL, 0x12A3A4E2UL, - 0x6F7DE532UL, 0x58FD7EB6UL, 0xD01EE900UL, 0x24ADFFC2UL, - 0xF4990FC5UL, 0x9711AAC5UL, 0x001D7B95UL, 0x82E5E7D2UL, - 0x109873F6UL, 0x00613096UL, 0xC32D9521UL, 0xADA121FFUL, - 0x29908415UL, 0x7FBB977FUL, 0xAF9EB3DBUL, 0x29C9ED2AUL, - 0x5CE2A465UL, 0xA730F32CUL, 0xD0AA3FE8UL, 0x8A5CC091UL, - 0xD49E2CE7UL, 0x0CE454A9UL, 0xD60ACD86UL, 0x015F1919UL, - 0x77079103UL, 0xDEA03AF6UL, 0x78A8565EUL, 0xDEE356DFUL, - 0x21F05CBEUL, 0x8B75E387UL, 0xB3C50651UL, 0xB8A5C3EFUL, - 0xD8EEB6D2UL, 0xE523BE77UL, 0xC2154529UL, 0x2F69EFDFUL, - 0xAFE67AFBUL, 0xF470C4B2UL, 0xF3E0EB5BUL, 0xD6CC9876UL, - 0x39E4460CUL, 0x1FDA8538UL, 0x1987832FUL, 0xCA007367UL, - 0xA99144F8UL, 0x296B299EUL, 0x492FC295UL, 0x9266BEABUL, - 0xB5676E69UL, 0x9BD3DDDAUL, 0xDF7E052FUL, 0xDB25701CUL, - 0x1B5E51EEUL, 0xF65324E6UL, 0x6AFCE36CUL, 0x0316CC04UL, - 0x8644213EUL, 0xB7DC59D0UL, 0x7965291FUL, 0xCCD6FD43UL, - 0x41823979UL, 0x932BCDF6UL, 0xB657C34DUL, 0x4EDFD282UL, - 0x7AE5290CUL, 0x3CB9536BUL, 0x851E20FEUL, 0x9833557EUL, - 0x13ECF0B0UL, 0xD3FFB372UL, 0x3F85C5C1UL, 0x0AEF7ED2UL -}, - -{ - 0x7EC90C04UL, 0x2C6E74B9UL, 0x9B0E66DFUL, 0xA6337911UL, - 0xB86A7FFFUL, 0x1DD358F5UL, 0x44DD9D44UL, 0x1731167FUL, - 0x08FBF1FAUL, 0xE7F511CCUL, 0xD2051B00UL, 0x735ABA00UL, - 0x2AB722D8UL, 0x386381CBUL, 0xACF6243AUL, 0x69BEFD7AUL, - 0xE6A2E77FUL, 0xF0C720CDUL, 0xC4494816UL, 0xCCF5C180UL, - 0x38851640UL, 0x15B0A848UL, 0xE68B18CBUL, 0x4CAADEFFUL, - 0x5F480A01UL, 0x0412B2AAUL, 0x259814FCUL, 0x41D0EFE2UL, - 0x4E40B48DUL, 0x248EB6FBUL, 0x8DBA1CFEUL, 0x41A99B02UL, - 0x1A550A04UL, 0xBA8F65CBUL, 0x7251F4E7UL, 0x95A51725UL, - 0xC106ECD7UL, 0x97A5980AUL, 0xC539B9AAUL, 0x4D79FE6AUL, - 0xF2F3F763UL, 0x68AF8040UL, 0xED0C9E56UL, 0x11B4958BUL, - 0xE1EB5A88UL, 0x8709E6B0UL, 0xD7E07156UL, 0x4E29FEA7UL, - 0x6366E52DUL, 0x02D1C000UL, 0xC4AC8E05UL, 0x9377F571UL, - 0x0C05372AUL, 0x578535F2UL, 0x2261BE02UL, 0xD642A0C9UL, - 0xDF13A280UL, 0x74B55BD2UL, 0x682199C0UL, 0xD421E5ECUL, - 0x53FB3CE8UL, 0xC8ADEDB3UL, 0x28A87FC9UL, 0x3D959981UL, - 0x5C1FF900UL, 0xFE38D399UL, 0x0C4EFF0BUL, 0x062407EAUL, - 0xAA2F4FB1UL, 0x4FB96976UL, 0x90C79505UL, 0xB0A8A774UL, - 0xEF55A1FFUL, 0xE59CA2C2UL, 0xA6B62D27UL, 0xE66A4263UL, - 0xDF65001FUL, 0x0EC50966UL, 0xDFDD55BCUL, 0x29DE0655UL, - 0x911E739AUL, 0x17AF8975UL, 0x32C7911CUL, 0x89F89468UL, - 0x0D01E980UL, 0x524755F4UL, 0x03B63CC9UL, 0x0CC844B2UL, - 0xBCF3F0AAUL, 0x87AC36E9UL, 0xE53A7426UL, 0x01B3D82BUL, - 0x1A9E7449UL, 0x64EE2D7EUL, 0xCDDBB1DAUL, 0x01C94910UL, - 0xB868BF80UL, 0x0D26F3FDUL, 0x9342EDE7UL, 0x04A5C284UL, - 0x636737B6UL, 0x50F5B616UL, 0xF24766E3UL, 0x8ECA36C1UL, - 0x136E05DBUL, 0xFEF18391UL, 0xFB887A37UL, 0xD6E7F7D4UL, - 0xC7FB7DC9UL, 0x3063FCDFUL, 0xB6F589DEUL, 0xEC2941DAUL, - 0x26E46695UL, 0xB7566419UL, 0xF654EFC5UL, 0xD08D58B7UL, - 0x48925401UL, 0xC1BACB7FUL, 0xE5FF550FUL, 0xB6083049UL, - 0x5BB5D0E8UL, 0x87D72E5AUL, 0xAB6A6EE1UL, 0x223A66CEUL, - 0xC62BF3CDUL, 0x9E0885F9UL, 0x68CB3E47UL, 0x086C010FUL, - 0xA21DE820UL, 0xD18B69DEUL, 0xF3F65777UL, 0xFA02C3F6UL, - 0x407EDAC3UL, 0xCBB3D550UL, 0x1793084DUL, 0xB0D70EBAUL, - 0x0AB378D5UL, 0xD951FB0CUL, 0xDED7DA56UL, 0x4124BBE4UL, - 0x94CA0B56UL, 0x0F5755D1UL, 0xE0E1E56EUL, 0x6184B5BEUL, - 0x580A249FUL, 0x94F74BC0UL, 0xE327888EUL, 0x9F7B5561UL, - 0xC3DC0280UL, 0x05687715UL, 0x646C6BD7UL, 0x44904DB3UL, - 0x66B4F0A3UL, 0xC0F1648AUL, 0x697ED5AFUL, 0x49E92FF6UL, - 0x309E374FUL, 0x2CB6356AUL, 0x85808573UL, 0x4991F840UL, - 0x76F0AE02UL, 0x083BE84DUL, 0x28421C9AUL, 0x44489406UL, - 0x736E4CB8UL, 0xC1092910UL, 0x8BC95FC6UL, 0x7D869CF4UL, - 0x134F616FUL, 0x2E77118DUL, 0xB31B2BE1UL, 0xAA90B472UL, - 0x3CA5D717UL, 0x7D161BBAUL, 0x9CAD9010UL, 0xAF462BA2UL, - 0x9FE459D2UL, 0x45D34559UL, 0xD9F2DA13UL, 0xDBC65487UL, - 0xF3E4F94EUL, 0x176D486FUL, 0x097C13EAUL, 0x631DA5C7UL, - 0x445F7382UL, 0x175683F4UL, 0xCDC66A97UL, 0x70BE0288UL, - 0xB3CDCF72UL, 0x6E5DD2F3UL, 0x20936079UL, 0x459B80A5UL, - 0xBE60E2DBUL, 0xA9C23101UL, 0xEBA5315CUL, 0x224E42F2UL, - 0x1C5C1572UL, 0xF6721B2CUL, 0x1AD2FFF3UL, 0x8C25404EUL, - 0x324ED72FUL, 0x4067B7FDUL, 0x0523138EUL, 0x5CA3BC78UL, - 0xDC0FD66EUL, 0x75922283UL, 0x784D6B17UL, 0x58EBB16EUL, - 0x44094F85UL, 0x3F481D87UL, 0xFCFEAE7BUL, 0x77B5FF76UL, - 0x8C2302BFUL, 0xAAF47556UL, 0x5F46B02AUL, 0x2B092801UL, - 0x3D38F5F7UL, 0x0CA81F36UL, 0x52AF4A8AUL, 0x66D5E7C0UL, - 0xDF3B0874UL, 0x95055110UL, 0x1B5AD7A8UL, 0xF61ED5ADUL, - 0x6CF6E479UL, 0x20758184UL, 0xD0CEFA65UL, 0x88F7BE58UL, - 0x4A046826UL, 0x0FF6F8F3UL, 0xA09C7F70UL, 0x5346ABA0UL, - 0x5CE96C28UL, 0xE176EDA3UL, 0x6BAC307FUL, 0x376829D2UL, - 0x85360FA9UL, 0x17E3FE2AUL, 0x24B79767UL, 0xF5A96B20UL, - 0xD6CD2595UL, 0x68FF1EBFUL, 0x7555442CUL, 0xF19F06BEUL, - 0xF9E0659AUL, 0xEEB9491DUL, 0x34010718UL, 0xBB30CAB8UL, - 0xE822FE15UL, 0x88570983UL, 0x750E6249UL, 0xDA627E55UL, - 0x5E76FFA8UL, 0xB1534546UL, 0x6D47DE08UL, 0xEFE9E7D4UL -}, - -{ - 0xF6FA8F9DUL, 0x2CAC6CE1UL, 0x4CA34867UL, 0xE2337F7CUL, - 0x95DB08E7UL, 0x016843B4UL, 0xECED5CBCUL, 0x325553ACUL, - 0xBF9F0960UL, 0xDFA1E2EDUL, 0x83F0579DUL, 0x63ED86B9UL, - 0x1AB6A6B8UL, 0xDE5EBE39UL, 0xF38FF732UL, 0x8989B138UL, - 0x33F14961UL, 0xC01937BDUL, 0xF506C6DAUL, 0xE4625E7EUL, - 0xA308EA99UL, 0x4E23E33CUL, 0x79CBD7CCUL, 0x48A14367UL, - 0xA3149619UL, 0xFEC94BD5UL, 0xA114174AUL, 0xEAA01866UL, - 0xA084DB2DUL, 0x09A8486FUL, 0xA888614AUL, 0x2900AF98UL, - 0x01665991UL, 0xE1992863UL, 0xC8F30C60UL, 0x2E78EF3CUL, - 0xD0D51932UL, 0xCF0FEC14UL, 0xF7CA07D2UL, 0xD0A82072UL, - 0xFD41197EUL, 0x9305A6B0UL, 0xE86BE3DAUL, 0x74BED3CDUL, - 0x372DA53CUL, 0x4C7F4448UL, 0xDAB5D440UL, 0x6DBA0EC3UL, - 0x083919A7UL, 0x9FBAEED9UL, 0x49DBCFB0UL, 0x4E670C53UL, - 0x5C3D9C01UL, 0x64BDB941UL, 0x2C0E636AUL, 0xBA7DD9CDUL, - 0xEA6F7388UL, 0xE70BC762UL, 0x35F29ADBUL, 0x5C4CDD8DUL, - 0xF0D48D8CUL, 0xB88153E2UL, 0x08A19866UL, 0x1AE2EAC8UL, - 0x284CAF89UL, 0xAA928223UL, 0x9334BE53UL, 0x3B3A21BFUL, - 0x16434BE3UL, 0x9AEA3906UL, 0xEFE8C36EUL, 0xF890CDD9UL, - 0x80226DAEUL, 0xC340A4A3UL, 0xDF7E9C09UL, 0xA694A807UL, - 0x5B7C5ECCUL, 0x221DB3A6UL, 0x9A69A02FUL, 0x68818A54UL, - 0xCEB2296FUL, 0x53C0843AUL, 0xFE893655UL, 0x25BFE68AUL, - 0xB4628ABCUL, 0xCF222EBFUL, 0x25AC6F48UL, 0xA9A99387UL, - 0x53BDDB65UL, 0xE76FFBE7UL, 0xE967FD78UL, 0x0BA93563UL, - 0x8E342BC1UL, 0xE8A11BE9UL, 0x4980740DUL, 0xC8087DFCUL, - 0x8DE4BF99UL, 0xA11101A0UL, 0x7FD37975UL, 0xDA5A26C0UL, - 0xE81F994FUL, 0x9528CD89UL, 0xFD339FEDUL, 0xB87834BFUL, - 0x5F04456DUL, 0x22258698UL, 0xC9C4C83BUL, 0x2DC156BEUL, - 0x4F628DAAUL, 0x57F55EC5UL, 0xE2220ABEUL, 0xD2916EBFUL, - 0x4EC75B95UL, 0x24F2C3C0UL, 0x42D15D99UL, 0xCD0D7FA0UL, - 0x7B6E27FFUL, 0xA8DC8AF0UL, 0x7345C106UL, 0xF41E232FUL, - 0x35162386UL, 0xE6EA8926UL, 0x3333B094UL, 0x157EC6F2UL, - 0x372B74AFUL, 0x692573E4UL, 0xE9A9D848UL, 0xF3160289UL, - 0x3A62EF1DUL, 0xA787E238UL, 0xF3A5F676UL, 0x74364853UL, - 0x20951063UL, 0x4576698DUL, 0xB6FAD407UL, 0x592AF950UL, - 0x36F73523UL, 0x4CFB6E87UL, 0x7DA4CEC0UL, 0x6C152DAAUL, - 0xCB0396A8UL, 0xC50DFE5DUL, 0xFCD707ABUL, 0x0921C42FUL, - 0x89DFF0BBUL, 0x5FE2BE78UL, 0x448F4F33UL, 0x754613C9UL, - 0x2B05D08DUL, 0x48B9D585UL, 0xDC049441UL, 0xC8098F9BUL, - 0x7DEDE786UL, 0xC39A3373UL, 0x42410005UL, 0x6A091751UL, - 0x0EF3C8A6UL, 0x890072D6UL, 0x28207682UL, 0xA9A9F7BEUL, - 0xBF32679DUL, 0xD45B5B75UL, 0xB353FD00UL, 0xCBB0E358UL, - 0x830F220AUL, 0x1F8FB214UL, 0xD372CF08UL, 0xCC3C4A13UL, - 0x8CF63166UL, 0x061C87BEUL, 0x88C98F88UL, 0x6062E397UL, - 0x47CF8E7AUL, 0xB6C85283UL, 0x3CC2ACFBUL, 0x3FC06976UL, - 0x4E8F0252UL, 0x64D8314DUL, 0xDA3870E3UL, 0x1E665459UL, - 0xC10908F0UL, 0x513021A5UL, 0x6C5B68B7UL, 0x822F8AA0UL, - 0x3007CD3EUL, 0x74719EEFUL, 0xDC872681UL, 0x073340D4UL, - 0x7E432FD9UL, 0x0C5EC241UL, 0x8809286CUL, 0xF592D891UL, - 0x08A930F6UL, 0x957EF305UL, 0xB7FBFFBDUL, 0xC266E96FUL, - 0x6FE4AC98UL, 0xB173ECC0UL, 0xBC60B42AUL, 0x953498DAUL, - 0xFBA1AE12UL, 0x2D4BD736UL, 0x0F25FAABUL, 0xA4F3FCEBUL, - 0xE2969123UL, 0x257F0C3DUL, 0x9348AF49UL, 0x361400BCUL, - 0xE8816F4AUL, 0x3814F200UL, 0xA3F94043UL, 0x9C7A54C2UL, - 0xBC704F57UL, 0xDA41E7F9UL, 0xC25AD33AUL, 0x54F4A084UL, - 0xB17F5505UL, 0x59357CBEUL, 0xEDBD15C8UL, 0x7F97C5ABUL, - 0xBA5AC7B5UL, 0xB6F6DEAFUL, 0x3A479C3AUL, 0x5302DA25UL, - 0x653D7E6AUL, 0x54268D49UL, 0x51A477EAUL, 0x5017D55BUL, - 0xD7D25D88UL, 0x44136C76UL, 0x0404A8C8UL, 0xB8E5A121UL, - 0xB81A928AUL, 0x60ED5869UL, 0x97C55B96UL, 0xEAEC991BUL, - 0x29935913UL, 0x01FDB7F1UL, 0x088E8DFAUL, 0x9AB6F6F5UL, - 0x3B4CBF9FUL, 0x4A5DE3ABUL, 0xE6051D35UL, 0xA0E1D855UL, - 0xD36B4CF1UL, 0xF544EDEBUL, 0xB0E93524UL, 0xBEBB8FBDUL, - 0xA2D762CFUL, 0x49C92F54UL, 0x38B5F331UL, 0x7128A454UL, - 0x48392905UL, 0xA65B1DB8UL, 0x851C97BDUL, 0xD675CF2FUL -}, - -{ - 0x85E04019UL, 0x332BF567UL, 0x662DBFFFUL, 0xCFC65693UL, - 0x2A8D7F6FUL, 0xAB9BC912UL, 0xDE6008A1UL, 0x2028DA1FUL, - 0x0227BCE7UL, 0x4D642916UL, 0x18FAC300UL, 0x50F18B82UL, - 0x2CB2CB11UL, 0xB232E75CUL, 0x4B3695F2UL, 0xB28707DEUL, - 0xA05FBCF6UL, 0xCD4181E9UL, 0xE150210CUL, 0xE24EF1BDUL, - 0xB168C381UL, 0xFDE4E789UL, 0x5C79B0D8UL, 0x1E8BFD43UL, - 0x4D495001UL, 0x38BE4341UL, 0x913CEE1DUL, 0x92A79C3FUL, - 0x089766BEUL, 0xBAEEADF4UL, 0x1286BECFUL, 0xB6EACB19UL, - 0x2660C200UL, 0x7565BDE4UL, 0x64241F7AUL, 0x8248DCA9UL, - 0xC3B3AD66UL, 0x28136086UL, 0x0BD8DFA8UL, 0x356D1CF2UL, - 0x107789BEUL, 0xB3B2E9CEUL, 0x0502AA8FUL, 0x0BC0351EUL, - 0x166BF52AUL, 0xEB12FF82UL, 0xE3486911UL, 0xD34D7516UL, - 0x4E7B3AFFUL, 0x5F43671BUL, 0x9CF6E037UL, 0x4981AC83UL, - 0x334266CEUL, 0x8C9341B7UL, 0xD0D854C0UL, 0xCB3A6C88UL, - 0x47BC2829UL, 0x4725BA37UL, 0xA66AD22BUL, 0x7AD61F1EUL, - 0x0C5CBAFAUL, 0x4437F107UL, 0xB6E79962UL, 0x42D2D816UL, - 0x0A961288UL, 0xE1A5C06EUL, 0x13749E67UL, 0x72FC081AUL, - 0xB1D139F7UL, 0xF9583745UL, 0xCF19DF58UL, 0xBEC3F756UL, - 0xC06EBA30UL, 0x07211B24UL, 0x45C28829UL, 0xC95E317FUL, - 0xBC8EC511UL, 0x38BC46E9UL, 0xC6E6FA14UL, 0xBAE8584AUL, - 0xAD4EBC46UL, 0x468F508BUL, 0x7829435FUL, 0xF124183BUL, - 0x821DBA9FUL, 0xAFF60FF4UL, 0xEA2C4E6DUL, 0x16E39264UL, - 0x92544A8BUL, 0x009B4FC3UL, 0xABA68CEDUL, 0x9AC96F78UL, - 0x06A5B79AUL, 0xB2856E6EUL, 0x1AEC3CA9UL, 0xBE838688UL, - 0x0E0804E9UL, 0x55F1BE56UL, 0xE7E5363BUL, 0xB3A1F25DUL, - 0xF7DEBB85UL, 0x61FE033CUL, 0x16746233UL, 0x3C034C28UL, - 0xDA6D0C74UL, 0x79AAC56CUL, 0x3CE4E1ADUL, 0x51F0C802UL, - 0x98F8F35AUL, 0x1626A49FUL, 0xEED82B29UL, 0x1D382FE3UL, - 0x0C4FB99AUL, 0xBB325778UL, 0x3EC6D97BUL, 0x6E77A6A9UL, - 0xCB658B5CUL, 0xD45230C7UL, 0x2BD1408BUL, 0x60C03EB7UL, - 0xB9068D78UL, 0xA33754F4UL, 0xF430C87DUL, 0xC8A71302UL, - 0xB96D8C32UL, 0xEBD4E7BEUL, 0xBE8B9D2DUL, 0x7979FB06UL, - 0xE7225308UL, 0x8B75CF77UL, 0x11EF8DA4UL, 0xE083C858UL, - 0x8D6B786FUL, 0x5A6317A6UL, 0xFA5CF7A0UL, 0x5DDA0033UL, - 0xF28EBFB0UL, 0xF5B9C310UL, 0xA0EAC280UL, 0x08B9767AUL, - 0xA3D9D2B0UL, 0x79D34217UL, 0x021A718DUL, 0x9AC6336AUL, - 0x2711FD60UL, 0x438050E3UL, 0x069908A8UL, 0x3D7FEDC4UL, - 0x826D2BEFUL, 0x4EEB8476UL, 0x488DCF25UL, 0x36C9D566UL, - 0x28E74E41UL, 0xC2610ACAUL, 0x3D49A9CFUL, 0xBAE3B9DFUL, - 0xB65F8DE6UL, 0x92AEAF64UL, 0x3AC7D5E6UL, 0x9EA80509UL, - 0xF22B017DUL, 0xA4173F70UL, 0xDD1E16C3UL, 0x15E0D7F9UL, - 0x50B1B887UL, 0x2B9F4FD5UL, 0x625ABA82UL, 0x6A017962UL, - 0x2EC01B9CUL, 0x15488AA9UL, 0xD716E740UL, 0x40055A2CUL, - 0x93D29A22UL, 0xE32DBF9AUL, 0x058745B9UL, 0x3453DC1EUL, - 0xD699296EUL, 0x496CFF6FUL, 0x1C9F4986UL, 0xDFE2ED07UL, - 0xB87242D1UL, 0x19DE7EAEUL, 0x053E561AUL, 0x15AD6F8CUL, - 0x66626C1CUL, 0x7154C24CUL, 0xEA082B2AUL, 0x93EB2939UL, - 0x17DCB0F0UL, 0x58D4F2AEUL, 0x9EA294FBUL, 0x52CF564CUL, - 0x9883FE66UL, 0x2EC40581UL, 0x763953C3UL, 0x01D6692EUL, - 0xD3A0C108UL, 0xA1E7160EUL, 0xE4F2DFA6UL, 0x693ED285UL, - 0x74904698UL, 0x4C2B0EDDUL, 0x4F757656UL, 0x5D393378UL, - 0xA132234FUL, 0x3D321C5DUL, 0xC3F5E194UL, 0x4B269301UL, - 0xC79F022FUL, 0x3C997E7EUL, 0x5E4F9504UL, 0x3FFAFBBDUL, - 0x76F7AD0EUL, 0x296693F4UL, 0x3D1FCE6FUL, 0xC61E45BEUL, - 0xD3B5AB34UL, 0xF72BF9B7UL, 0x1B0434C0UL, 0x4E72B567UL, - 0x5592A33DUL, 0xB5229301UL, 0xCFD2A87FUL, 0x60AEB767UL, - 0x1814386BUL, 0x30BCC33DUL, 0x38A0C07DUL, 0xFD1606F2UL, - 0xC363519BUL, 0x589DD390UL, 0x5479F8E6UL, 0x1CB8D647UL, - 0x97FD61A9UL, 0xEA7759F4UL, 0x2D57539DUL, 0x569A58CFUL, - 0xE84E63ADUL, 0x462E1B78UL, 0x6580F87EUL, 0xF3817914UL, - 0x91DA55F4UL, 0x40A230F3UL, 0xD1988F35UL, 0xB6E318D2UL, - 0x3FFA50BCUL, 0x3D40F021UL, 0xC3C0BDAEUL, 0x4958C24CUL, - 0x518F36B2UL, 0x84B1D370UL, 0x0FEDCE83UL, 0x878DDADAUL, - 0xF2A279C7UL, 0x94E01BE8UL, 0x90716F4BUL, 0x954B8AA3UL -}, - -{ - 0xE216300DUL, 0xBBDDFFFCUL, 0xA7EBDABDUL, 0x35648095UL, - 0x7789F8B7UL, 0xE6C1121BUL, 0x0E241600UL, 0x052CE8B5UL, - 0x11A9CFB0UL, 0xE5952F11UL, 0xECE7990AUL, 0x9386D174UL, - 0x2A42931CUL, 0x76E38111UL, 0xB12DEF3AUL, 0x37DDDDFCUL, - 0xDE9ADEB1UL, 0x0A0CC32CUL, 0xBE197029UL, 0x84A00940UL, - 0xBB243A0FUL, 0xB4D137CFUL, 0xB44E79F0UL, 0x049EEDFDUL, - 0x0B15A15DUL, 0x480D3168UL, 0x8BBBDE5AUL, 0x669DED42UL, - 0xC7ECE831UL, 0x3F8F95E7UL, 0x72DF191BUL, 0x7580330DUL, - 0x94074251UL, 0x5C7DCDFAUL, 0xABBE6D63UL, 0xAA402164UL, - 0xB301D40AUL, 0x02E7D1CAUL, 0x53571DAEUL, 0x7A3182A2UL, - 0x12A8DDECUL, 0xFDAA335DUL, 0x176F43E8UL, 0x71FB46D4UL, - 0x38129022UL, 0xCE949AD4UL, 0xB84769ADUL, 0x965BD862UL, - 0x82F3D055UL, 0x66FB9767UL, 0x15B80B4EUL, 0x1D5B47A0UL, - 0x4CFDE06FUL, 0xC28EC4B8UL, 0x57E8726EUL, 0x647A78FCUL, - 0x99865D44UL, 0x608BD593UL, 0x6C200E03UL, 0x39DC5FF6UL, - 0x5D0B00A3UL, 0xAE63AFF2UL, 0x7E8BD632UL, 0x70108C0CUL, - 0xBBD35049UL, 0x2998DF04UL, 0x980CF42AUL, 0x9B6DF491UL, - 0x9E7EDD53UL, 0x06918548UL, 0x58CB7E07UL, 0x3B74EF2EUL, - 0x522FFFB1UL, 0xD24708CCUL, 0x1C7E27CDUL, 0xA4EB215BUL, - 0x3CF1D2E2UL, 0x19B47A38UL, 0x424F7618UL, 0x35856039UL, - 0x9D17DEE7UL, 0x27EB35E6UL, 0xC9AFF67BUL, 0x36BAF5B8UL, - 0x09C467CDUL, 0xC18910B1UL, 0xE11DBF7BUL, 0x06CD1AF8UL, - 0x7170C608UL, 0x2D5E3354UL, 0xD4DE495AUL, 0x64C6D006UL, - 0xBCC0C62CUL, 0x3DD00DB3UL, 0x708F8F34UL, 0x77D51B42UL, - 0x264F620FUL, 0x24B8D2BFUL, 0x15C1B79EUL, 0x46A52564UL, - 0xF8D7E54EUL, 0x3E378160UL, 0x7895CDA5UL, 0x859C15A5UL, - 0xE6459788UL, 0xC37BC75FUL, 0xDB07BA0CUL, 0x0676A3ABUL, - 0x7F229B1EUL, 0x31842E7BUL, 0x24259FD7UL, 0xF8BEF472UL, - 0x835FFCB8UL, 0x6DF4C1F2UL, 0x96F5B195UL, 0xFD0AF0FCUL, - 0xB0FE134CUL, 0xE2506D3DUL, 0x4F9B12EAUL, 0xF215F225UL, - 0xA223736FUL, 0x9FB4C428UL, 0x25D04979UL, 0x34C713F8UL, - 0xC4618187UL, 0xEA7A6E98UL, 0x7CD16EFCUL, 0x1436876CUL, - 0xF1544107UL, 0xBEDEEE14UL, 0x56E9AF27UL, 0xA04AA441UL, - 0x3CF7C899UL, 0x92ECBAE6UL, 0xDD67016DUL, 0x151682EBUL, - 0xA842EEDFUL, 0xFDBA60B4UL, 0xF1907B75UL, 0x20E3030FUL, - 0x24D8C29EUL, 0xE139673BUL, 0xEFA63FB8UL, 0x71873054UL, - 0xB6F2CF3BUL, 0x9F326442UL, 0xCB15A4CCUL, 0xB01A4504UL, - 0xF1E47D8DUL, 0x844A1BE5UL, 0xBAE7DFDCUL, 0x42CBDA70UL, - 0xCD7DAE0AUL, 0x57E85B7AUL, 0xD53F5AF6UL, 0x20CF4D8CUL, - 0xCEA4D428UL, 0x79D130A4UL, 0x3486EBFBUL, 0x33D3CDDCUL, - 0x77853B53UL, 0x37EFFCB5UL, 0xC5068778UL, 0xE580B3E6UL, - 0x4E68B8F4UL, 0xC5C8B37EUL, 0x0D809EA2UL, 0x398FEB7CUL, - 0x132A4F94UL, 0x43B7950EUL, 0x2FEE7D1CUL, 0x223613BDUL, - 0xDD06CAA2UL, 0x37DF932BUL, 0xC4248289UL, 0xACF3EBC3UL, - 0x5715F6B7UL, 0xEF3478DDUL, 0xF267616FUL, 0xC148CBE4UL, - 0x9052815EUL, 0x5E410FABUL, 0xB48A2465UL, 0x2EDA7FA4UL, - 0xE87B40E4UL, 0xE98EA084UL, 0x5889E9E1UL, 0xEFD390FCUL, - 0xDD07D35BUL, 0xDB485694UL, 0x38D7E5B2UL, 0x57720101UL, - 0x730EDEBCUL, 0x5B643113UL, 0x94917E4FUL, 0x503C2FBAUL, - 0x646F1282UL, 0x7523D24AUL, 0xE0779695UL, 0xF9C17A8FUL, - 0x7A5B2121UL, 0xD187B896UL, 0x29263A4DUL, 0xBA510CDFUL, - 0x81F47C9FUL, 0xAD1163EDUL, 0xEA7B5965UL, 0x1A00726EUL, - 0x11403092UL, 0x00DA6D77UL, 0x4A0CDD61UL, 0xAD1F4603UL, - 0x605BDFB0UL, 0x9EEDC364UL, 0x22EBE6A8UL, 0xCEE7D28AUL, - 0xA0E736A0UL, 0x5564A6B9UL, 0x10853209UL, 0xC7EB8F37UL, - 0x2DE705CAUL, 0x8951570FUL, 0xDF09822BUL, 0xBD691A6CUL, - 0xAA12E4F2UL, 0x87451C0FUL, 0xE0F6A27AUL, 0x3ADA4819UL, - 0x4CF1764FUL, 0x0D771C2BUL, 0x67CDB156UL, 0x350D8384UL, - 0x5938FA0FUL, 0x42399EF3UL, 0x36997B07UL, 0x0E84093DUL, - 0x4AA93E61UL, 0x8360D87BUL, 0x1FA98B0CUL, 0x1149382CUL, - 0xE97625A5UL, 0x0614D1B7UL, 0x0E25244BUL, 0x0C768347UL, - 0x589E8D82UL, 0x0D2059D1UL, 0xA466BB1EUL, 0xF8DA0A82UL, - 0x04F19130UL, 0xBA6E4EC0UL, 0x99265164UL, 0x1EE7230DUL, - 0x50B2AD80UL, 0xEAEE6801UL, 0x8DB2A283UL, 0xEA8BF59EUL -}}; - -/* CAST uses three different round functions */ -#define f1(l, r, km, kr) \ - t = rotlVariable(km + r, kr); \ - l ^= ((S[0][U8a(t)] ^ S[1][U8b(t)]) - \ - S[2][U8c(t)]) + S[3][U8d(t)]; -#define f2(l, r, km, kr) \ - t = rotlVariable(km ^ r, kr); \ - l ^= ((S[0][U8a(t)] - S[1][U8b(t)]) + \ - S[2][U8c(t)]) ^ S[3][U8d(t)]; -#define f3(l, r, km, kr) \ - t = rotlVariable(km - r, kr); \ - l ^= ((S[0][U8a(t)] + S[1][U8b(t)]) ^ \ - S[2][U8c(t)]) - S[3][U8d(t)]; - -#define F1(l, r, i, j) f1(l, r, K[i], K[i+j]) -#define F2(l, r, i, j) f2(l, r, K[i], K[i+j]) -#define F3(l, r, i, j) f3(l, r, K[i], K[i+j]) - - -void Cast5Encrypt (const byte *inBlock, byte *outBlock, CAST_KEY *key) -{ - word32 l = BE32 (((word32 *)inBlock)[0]); - word32 r = BE32 (((word32 *)inBlock)[1]); - word32 *K = key->K; - word32 t; - - /* Do the work */ - F1(l, r, 0, 16); - F2(r, l, 1, 16); - F3(l, r, 2, 16); - F1(r, l, 3, 16); - F2(l, r, 4, 16); - F3(r, l, 5, 16); - F1(l, r, 6, 16); - F2(r, l, 7, 16); - F3(l, r, 8, 16); - F1(r, l, 9, 16); - F2(l, r, 10, 16); - F3(r, l, 11, 16); - F1(l, r, 12, 16); - F2(r, l, 13, 16); - F3(l, r, 14, 16); - F1(r, l, 15, 16); - - /* Put l,r into outblock */ - ((word32 *)outBlock)[0] = BE32 (r); - ((word32 *)outBlock)[1] = BE32 (l); -} - - -void Cast5Decrypt (const byte *inBlock, byte *outBlock, CAST_KEY *key) -{ - word32 r = BE32 (((word32 *)inBlock)[0]); - word32 l = BE32 (((word32 *)inBlock)[1]); - word32 *K = key->K; - word32 t; - - /* Only do full 16 rounds if key length > 80 bits */ - F1(r, l, 15, 16); - F3(l, r, 14, 16); - F2(r, l, 13, 16); - F1(l, r, 12, 16); - F3(r, l, 11, 16); - F2(l, r, 10, 16); - F1(r, l, 9, 16); - F3(l, r, 8, 16); - F2(r, l, 7, 16); - F1(l, r, 6, 16); - F3(r, l, 5, 16); - F2(l, r, 4, 16); - F1(r, l, 3, 16); - F3(l, r, 2, 16); - F2(r, l, 1, 16); - F1(l, r, 0, 16); - /* Put l,r into outblock */ - ((word32 *)outBlock)[0] = BE32 (l); - ((word32 *)outBlock)[1] = BE32 (r); - /* Wipe clean */ - t = l = r = 0; -} - -void Cast5SetKey (CAST_KEY *key, unsigned int keylength, const byte *userKey) -{ - unsigned int i; - word32 *K = key->K; - word32 X[4], Z[4]; - - X[0] = BE32 (((word32 *)userKey)[0]); - X[1] = BE32 (((word32 *)userKey)[1]); - X[2] = BE32 (((word32 *)userKey)[2]); - X[3] = BE32 (((word32 *)userKey)[3]); - -#define x(i) GETBYTE(X[i/4], 3-i%4) -#define z(i) GETBYTE(Z[i/4], 3-i%4) - - for (i=0; i<=16; i+=16) - { - // this part is copied directly from RFC 2144 (with some search and replace) by Wei Dai - Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)]; - Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)]; - Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)]; - Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)]; - K[i+0] = S[4][z(0x8)] ^ S[5][z(0x9)] ^ S[6][z(0x7)] ^ S[7][z(0x6)] ^ S[4][z(0x2)]; - K[i+1] = S[4][z(0xA)] ^ S[5][z(0xB)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[5][z(0x6)]; - K[i+2] = S[4][z(0xC)] ^ S[5][z(0xD)] ^ S[6][z(0x3)] ^ S[7][z(0x2)] ^ S[6][z(0x9)]; - K[i+3] = S[4][z(0xE)] ^ S[5][z(0xF)] ^ S[6][z(0x1)] ^ S[7][z(0x0)] ^ S[7][z(0xC)]; - X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)]; - X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)]; - X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)]; - X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)]; - K[i+4] = S[4][x(0x3)] ^ S[5][x(0x2)] ^ S[6][x(0xC)] ^ S[7][x(0xD)] ^ S[4][x(0x8)]; - K[i+5] = S[4][x(0x1)] ^ S[5][x(0x0)] ^ S[6][x(0xE)] ^ S[7][x(0xF)] ^ S[5][x(0xD)]; - K[i+6] = S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x8)] ^ S[7][x(0x9)] ^ S[6][x(0x3)]; - K[i+7] = S[4][x(0x5)] ^ S[5][x(0x4)] ^ S[6][x(0xA)] ^ S[7][x(0xB)] ^ S[7][x(0x7)]; - Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)]; - Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)]; - Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)]; - Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)]; - K[i+8] = S[4][z(0x3)] ^ S[5][z(0x2)] ^ S[6][z(0xC)] ^ S[7][z(0xD)] ^ S[4][z(0x9)]; - K[i+9] = S[4][z(0x1)] ^ S[5][z(0x0)] ^ S[6][z(0xE)] ^ S[7][z(0xF)] ^ S[5][z(0xC)]; - K[i+10] = S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x8)] ^ S[7][z(0x9)] ^ S[6][z(0x2)]; - K[i+11] = S[4][z(0x5)] ^ S[5][z(0x4)] ^ S[6][z(0xA)] ^ S[7][z(0xB)] ^ S[7][z(0x6)]; - X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)]; - X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)]; - X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)]; - X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)]; - K[i+12] = S[4][x(0x8)] ^ S[5][x(0x9)] ^ S[6][x(0x7)] ^ S[7][x(0x6)] ^ S[4][x(0x3)]; - K[i+13] = S[4][x(0xA)] ^ S[5][x(0xB)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[5][x(0x7)]; - K[i+14] = S[4][x(0xC)] ^ S[5][x(0xD)] ^ S[6][x(0x3)] ^ S[7][x(0x2)] ^ S[6][x(0x8)]; - K[i+15] = S[4][x(0xE)] ^ S[5][x(0xF)] ^ S[6][x(0x1)] ^ S[7][x(0x0)] ^ S[7][x(0xD)]; - } - - for (i=16; i<32; i++) - K[i] &= 0x1f; -} +// cast.cpp - written and placed in the public domain by Wei Dai and Leonard Janke +// based on Steve Reid's public domain cast.c + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#include +#include "Common/Tcdefs.h" +#include "Common/Endian.h" +#include "Cast.h" + +#define word32 unsigned __int32 +#define byte unsigned __int8 +#define GETBYTE(x, y) (unsigned int)(byte)((x)>>(8*(y))) + +/* Macros to access 8-bit bytes out of a 32-bit word */ +#define U8a(x) GETBYTE(x,3) +#define U8b(x) GETBYTE(x,2) +#define U8c(x) GETBYTE(x,1) +#define U8d(x) GETBYTE(x,0) + +static word32 rotlVariable (word32 x, unsigned int y) +{ + return (word32)((x<>(sizeof(word32)*8-y))); +} + + +// CAST S-boxes + +static const word32 S[8][256] = { +{ + 0x30FB40D4UL, 0x9FA0FF0BUL, 0x6BECCD2FUL, 0x3F258C7AUL, + 0x1E213F2FUL, 0x9C004DD3UL, 0x6003E540UL, 0xCF9FC949UL, + 0xBFD4AF27UL, 0x88BBBDB5UL, 0xE2034090UL, 0x98D09675UL, + 0x6E63A0E0UL, 0x15C361D2UL, 0xC2E7661DUL, 0x22D4FF8EUL, + 0x28683B6FUL, 0xC07FD059UL, 0xFF2379C8UL, 0x775F50E2UL, + 0x43C340D3UL, 0xDF2F8656UL, 0x887CA41AUL, 0xA2D2BD2DUL, + 0xA1C9E0D6UL, 0x346C4819UL, 0x61B76D87UL, 0x22540F2FUL, + 0x2ABE32E1UL, 0xAA54166BUL, 0x22568E3AUL, 0xA2D341D0UL, + 0x66DB40C8UL, 0xA784392FUL, 0x004DFF2FUL, 0x2DB9D2DEUL, + 0x97943FACUL, 0x4A97C1D8UL, 0x527644B7UL, 0xB5F437A7UL, + 0xB82CBAEFUL, 0xD751D159UL, 0x6FF7F0EDUL, 0x5A097A1FUL, + 0x827B68D0UL, 0x90ECF52EUL, 0x22B0C054UL, 0xBC8E5935UL, + 0x4B6D2F7FUL, 0x50BB64A2UL, 0xD2664910UL, 0xBEE5812DUL, + 0xB7332290UL, 0xE93B159FUL, 0xB48EE411UL, 0x4BFF345DUL, + 0xFD45C240UL, 0xAD31973FUL, 0xC4F6D02EUL, 0x55FC8165UL, + 0xD5B1CAADUL, 0xA1AC2DAEUL, 0xA2D4B76DUL, 0xC19B0C50UL, + 0x882240F2UL, 0x0C6E4F38UL, 0xA4E4BFD7UL, 0x4F5BA272UL, + 0x564C1D2FUL, 0xC59C5319UL, 0xB949E354UL, 0xB04669FEUL, + 0xB1B6AB8AUL, 0xC71358DDUL, 0x6385C545UL, 0x110F935DUL, + 0x57538AD5UL, 0x6A390493UL, 0xE63D37E0UL, 0x2A54F6B3UL, + 0x3A787D5FUL, 0x6276A0B5UL, 0x19A6FCDFUL, 0x7A42206AUL, + 0x29F9D4D5UL, 0xF61B1891UL, 0xBB72275EUL, 0xAA508167UL, + 0x38901091UL, 0xC6B505EBUL, 0x84C7CB8CUL, 0x2AD75A0FUL, + 0x874A1427UL, 0xA2D1936BUL, 0x2AD286AFUL, 0xAA56D291UL, + 0xD7894360UL, 0x425C750DUL, 0x93B39E26UL, 0x187184C9UL, + 0x6C00B32DUL, 0x73E2BB14UL, 0xA0BEBC3CUL, 0x54623779UL, + 0x64459EABUL, 0x3F328B82UL, 0x7718CF82UL, 0x59A2CEA6UL, + 0x04EE002EUL, 0x89FE78E6UL, 0x3FAB0950UL, 0x325FF6C2UL, + 0x81383F05UL, 0x6963C5C8UL, 0x76CB5AD6UL, 0xD49974C9UL, + 0xCA180DCFUL, 0x380782D5UL, 0xC7FA5CF6UL, 0x8AC31511UL, + 0x35E79E13UL, 0x47DA91D0UL, 0xF40F9086UL, 0xA7E2419EUL, + 0x31366241UL, 0x051EF495UL, 0xAA573B04UL, 0x4A805D8DUL, + 0x548300D0UL, 0x00322A3CUL, 0xBF64CDDFUL, 0xBA57A68EUL, + 0x75C6372BUL, 0x50AFD341UL, 0xA7C13275UL, 0x915A0BF5UL, + 0x6B54BFABUL, 0x2B0B1426UL, 0xAB4CC9D7UL, 0x449CCD82UL, + 0xF7FBF265UL, 0xAB85C5F3UL, 0x1B55DB94UL, 0xAAD4E324UL, + 0xCFA4BD3FUL, 0x2DEAA3E2UL, 0x9E204D02UL, 0xC8BD25ACUL, + 0xEADF55B3UL, 0xD5BD9E98UL, 0xE31231B2UL, 0x2AD5AD6CUL, + 0x954329DEUL, 0xADBE4528UL, 0xD8710F69UL, 0xAA51C90FUL, + 0xAA786BF6UL, 0x22513F1EUL, 0xAA51A79BUL, 0x2AD344CCUL, + 0x7B5A41F0UL, 0xD37CFBADUL, 0x1B069505UL, 0x41ECE491UL, + 0xB4C332E6UL, 0x032268D4UL, 0xC9600ACCUL, 0xCE387E6DUL, + 0xBF6BB16CUL, 0x6A70FB78UL, 0x0D03D9C9UL, 0xD4DF39DEUL, + 0xE01063DAUL, 0x4736F464UL, 0x5AD328D8UL, 0xB347CC96UL, + 0x75BB0FC3UL, 0x98511BFBUL, 0x4FFBCC35UL, 0xB58BCF6AUL, + 0xE11F0ABCUL, 0xBFC5FE4AUL, 0xA70AEC10UL, 0xAC39570AUL, + 0x3F04442FUL, 0x6188B153UL, 0xE0397A2EUL, 0x5727CB79UL, + 0x9CEB418FUL, 0x1CACD68DUL, 0x2AD37C96UL, 0x0175CB9DUL, + 0xC69DFF09UL, 0xC75B65F0UL, 0xD9DB40D8UL, 0xEC0E7779UL, + 0x4744EAD4UL, 0xB11C3274UL, 0xDD24CB9EUL, 0x7E1C54BDUL, + 0xF01144F9UL, 0xD2240EB1UL, 0x9675B3FDUL, 0xA3AC3755UL, + 0xD47C27AFUL, 0x51C85F4DUL, 0x56907596UL, 0xA5BB15E6UL, + 0x580304F0UL, 0xCA042CF1UL, 0x011A37EAUL, 0x8DBFAADBUL, + 0x35BA3E4AUL, 0x3526FFA0UL, 0xC37B4D09UL, 0xBC306ED9UL, + 0x98A52666UL, 0x5648F725UL, 0xFF5E569DUL, 0x0CED63D0UL, + 0x7C63B2CFUL, 0x700B45E1UL, 0xD5EA50F1UL, 0x85A92872UL, + 0xAF1FBDA7UL, 0xD4234870UL, 0xA7870BF3UL, 0x2D3B4D79UL, + 0x42E04198UL, 0x0CD0EDE7UL, 0x26470DB8UL, 0xF881814CUL, + 0x474D6AD7UL, 0x7C0C5E5CUL, 0xD1231959UL, 0x381B7298UL, + 0xF5D2F4DBUL, 0xAB838653UL, 0x6E2F1E23UL, 0x83719C9EUL, + 0xBD91E046UL, 0x9A56456EUL, 0xDC39200CUL, 0x20C8C571UL, + 0x962BDA1CUL, 0xE1E696FFUL, 0xB141AB08UL, 0x7CCA89B9UL, + 0x1A69E783UL, 0x02CC4843UL, 0xA2F7C579UL, 0x429EF47DUL, + 0x427B169CUL, 0x5AC9F049UL, 0xDD8F0F00UL, 0x5C8165BFUL +}, + +{ + 0x1F201094UL, 0xEF0BA75BUL, 0x69E3CF7EUL, 0x393F4380UL, + 0xFE61CF7AUL, 0xEEC5207AUL, 0x55889C94UL, 0x72FC0651UL, + 0xADA7EF79UL, 0x4E1D7235UL, 0xD55A63CEUL, 0xDE0436BAUL, + 0x99C430EFUL, 0x5F0C0794UL, 0x18DCDB7DUL, 0xA1D6EFF3UL, + 0xA0B52F7BUL, 0x59E83605UL, 0xEE15B094UL, 0xE9FFD909UL, + 0xDC440086UL, 0xEF944459UL, 0xBA83CCB3UL, 0xE0C3CDFBUL, + 0xD1DA4181UL, 0x3B092AB1UL, 0xF997F1C1UL, 0xA5E6CF7BUL, + 0x01420DDBUL, 0xE4E7EF5BUL, 0x25A1FF41UL, 0xE180F806UL, + 0x1FC41080UL, 0x179BEE7AUL, 0xD37AC6A9UL, 0xFE5830A4UL, + 0x98DE8B7FUL, 0x77E83F4EUL, 0x79929269UL, 0x24FA9F7BUL, + 0xE113C85BUL, 0xACC40083UL, 0xD7503525UL, 0xF7EA615FUL, + 0x62143154UL, 0x0D554B63UL, 0x5D681121UL, 0xC866C359UL, + 0x3D63CF73UL, 0xCEE234C0UL, 0xD4D87E87UL, 0x5C672B21UL, + 0x071F6181UL, 0x39F7627FUL, 0x361E3084UL, 0xE4EB573BUL, + 0x602F64A4UL, 0xD63ACD9CUL, 0x1BBC4635UL, 0x9E81032DUL, + 0x2701F50CUL, 0x99847AB4UL, 0xA0E3DF79UL, 0xBA6CF38CUL, + 0x10843094UL, 0x2537A95EUL, 0xF46F6FFEUL, 0xA1FF3B1FUL, + 0x208CFB6AUL, 0x8F458C74UL, 0xD9E0A227UL, 0x4EC73A34UL, + 0xFC884F69UL, 0x3E4DE8DFUL, 0xEF0E0088UL, 0x3559648DUL, + 0x8A45388CUL, 0x1D804366UL, 0x721D9BFDUL, 0xA58684BBUL, + 0xE8256333UL, 0x844E8212UL, 0x128D8098UL, 0xFED33FB4UL, + 0xCE280AE1UL, 0x27E19BA5UL, 0xD5A6C252UL, 0xE49754BDUL, + 0xC5D655DDUL, 0xEB667064UL, 0x77840B4DUL, 0xA1B6A801UL, + 0x84DB26A9UL, 0xE0B56714UL, 0x21F043B7UL, 0xE5D05860UL, + 0x54F03084UL, 0x066FF472UL, 0xA31AA153UL, 0xDADC4755UL, + 0xB5625DBFUL, 0x68561BE6UL, 0x83CA6B94UL, 0x2D6ED23BUL, + 0xECCF01DBUL, 0xA6D3D0BAUL, 0xB6803D5CUL, 0xAF77A709UL, + 0x33B4A34CUL, 0x397BC8D6UL, 0x5EE22B95UL, 0x5F0E5304UL, + 0x81ED6F61UL, 0x20E74364UL, 0xB45E1378UL, 0xDE18639BUL, + 0x881CA122UL, 0xB96726D1UL, 0x8049A7E8UL, 0x22B7DA7BUL, + 0x5E552D25UL, 0x5272D237UL, 0x79D2951CUL, 0xC60D894CUL, + 0x488CB402UL, 0x1BA4FE5BUL, 0xA4B09F6BUL, 0x1CA815CFUL, + 0xA20C3005UL, 0x8871DF63UL, 0xB9DE2FCBUL, 0x0CC6C9E9UL, + 0x0BEEFF53UL, 0xE3214517UL, 0xB4542835UL, 0x9F63293CUL, + 0xEE41E729UL, 0x6E1D2D7CUL, 0x50045286UL, 0x1E6685F3UL, + 0xF33401C6UL, 0x30A22C95UL, 0x31A70850UL, 0x60930F13UL, + 0x73F98417UL, 0xA1269859UL, 0xEC645C44UL, 0x52C877A9UL, + 0xCDFF33A6UL, 0xA02B1741UL, 0x7CBAD9A2UL, 0x2180036FUL, + 0x50D99C08UL, 0xCB3F4861UL, 0xC26BD765UL, 0x64A3F6ABUL, + 0x80342676UL, 0x25A75E7BUL, 0xE4E6D1FCUL, 0x20C710E6UL, + 0xCDF0B680UL, 0x17844D3BUL, 0x31EEF84DUL, 0x7E0824E4UL, + 0x2CCB49EBUL, 0x846A3BAEUL, 0x8FF77888UL, 0xEE5D60F6UL, + 0x7AF75673UL, 0x2FDD5CDBUL, 0xA11631C1UL, 0x30F66F43UL, + 0xB3FAEC54UL, 0x157FD7FAUL, 0xEF8579CCUL, 0xD152DE58UL, + 0xDB2FFD5EUL, 0x8F32CE19UL, 0x306AF97AUL, 0x02F03EF8UL, + 0x99319AD5UL, 0xC242FA0FUL, 0xA7E3EBB0UL, 0xC68E4906UL, + 0xB8DA230CUL, 0x80823028UL, 0xDCDEF3C8UL, 0xD35FB171UL, + 0x088A1BC8UL, 0xBEC0C560UL, 0x61A3C9E8UL, 0xBCA8F54DUL, + 0xC72FEFFAUL, 0x22822E99UL, 0x82C570B4UL, 0xD8D94E89UL, + 0x8B1C34BCUL, 0x301E16E6UL, 0x273BE979UL, 0xB0FFEAA6UL, + 0x61D9B8C6UL, 0x00B24869UL, 0xB7FFCE3FUL, 0x08DC283BUL, + 0x43DAF65AUL, 0xF7E19798UL, 0x7619B72FUL, 0x8F1C9BA4UL, + 0xDC8637A0UL, 0x16A7D3B1UL, 0x9FC393B7UL, 0xA7136EEBUL, + 0xC6BCC63EUL, 0x1A513742UL, 0xEF6828BCUL, 0x520365D6UL, + 0x2D6A77ABUL, 0x3527ED4BUL, 0x821FD216UL, 0x095C6E2EUL, + 0xDB92F2FBUL, 0x5EEA29CBUL, 0x145892F5UL, 0x91584F7FUL, + 0x5483697BUL, 0x2667A8CCUL, 0x85196048UL, 0x8C4BACEAUL, + 0x833860D4UL, 0x0D23E0F9UL, 0x6C387E8AUL, 0x0AE6D249UL, + 0xB284600CUL, 0xD835731DUL, 0xDCB1C647UL, 0xAC4C56EAUL, + 0x3EBD81B3UL, 0x230EABB0UL, 0x6438BC87UL, 0xF0B5B1FAUL, + 0x8F5EA2B3UL, 0xFC184642UL, 0x0A036B7AUL, 0x4FB089BDUL, + 0x649DA589UL, 0xA345415EUL, 0x5C038323UL, 0x3E5D3BB9UL, + 0x43D79572UL, 0x7E6DD07CUL, 0x06DFDF1EUL, 0x6C6CC4EFUL, + 0x7160A539UL, 0x73BFBE70UL, 0x83877605UL, 0x4523ECF1UL +}, + +{ + 0x8DEFC240UL, 0x25FA5D9FUL, 0xEB903DBFUL, 0xE810C907UL, + 0x47607FFFUL, 0x369FE44BUL, 0x8C1FC644UL, 0xAECECA90UL, + 0xBEB1F9BFUL, 0xEEFBCAEAUL, 0xE8CF1950UL, 0x51DF07AEUL, + 0x920E8806UL, 0xF0AD0548UL, 0xE13C8D83UL, 0x927010D5UL, + 0x11107D9FUL, 0x07647DB9UL, 0xB2E3E4D4UL, 0x3D4F285EUL, + 0xB9AFA820UL, 0xFADE82E0UL, 0xA067268BUL, 0x8272792EUL, + 0x553FB2C0UL, 0x489AE22BUL, 0xD4EF9794UL, 0x125E3FBCUL, + 0x21FFFCEEUL, 0x825B1BFDUL, 0x9255C5EDUL, 0x1257A240UL, + 0x4E1A8302UL, 0xBAE07FFFUL, 0x528246E7UL, 0x8E57140EUL, + 0x3373F7BFUL, 0x8C9F8188UL, 0xA6FC4EE8UL, 0xC982B5A5UL, + 0xA8C01DB7UL, 0x579FC264UL, 0x67094F31UL, 0xF2BD3F5FUL, + 0x40FFF7C1UL, 0x1FB78DFCUL, 0x8E6BD2C1UL, 0x437BE59BUL, + 0x99B03DBFUL, 0xB5DBC64BUL, 0x638DC0E6UL, 0x55819D99UL, + 0xA197C81CUL, 0x4A012D6EUL, 0xC5884A28UL, 0xCCC36F71UL, + 0xB843C213UL, 0x6C0743F1UL, 0x8309893CUL, 0x0FEDDD5FUL, + 0x2F7FE850UL, 0xD7C07F7EUL, 0x02507FBFUL, 0x5AFB9A04UL, + 0xA747D2D0UL, 0x1651192EUL, 0xAF70BF3EUL, 0x58C31380UL, + 0x5F98302EUL, 0x727CC3C4UL, 0x0A0FB402UL, 0x0F7FEF82UL, + 0x8C96FDADUL, 0x5D2C2AAEUL, 0x8EE99A49UL, 0x50DA88B8UL, + 0x8427F4A0UL, 0x1EAC5790UL, 0x796FB449UL, 0x8252DC15UL, + 0xEFBD7D9BUL, 0xA672597DUL, 0xADA840D8UL, 0x45F54504UL, + 0xFA5D7403UL, 0xE83EC305UL, 0x4F91751AUL, 0x925669C2UL, + 0x23EFE941UL, 0xA903F12EUL, 0x60270DF2UL, 0x0276E4B6UL, + 0x94FD6574UL, 0x927985B2UL, 0x8276DBCBUL, 0x02778176UL, + 0xF8AF918DUL, 0x4E48F79EUL, 0x8F616DDFUL, 0xE29D840EUL, + 0x842F7D83UL, 0x340CE5C8UL, 0x96BBB682UL, 0x93B4B148UL, + 0xEF303CABUL, 0x984FAF28UL, 0x779FAF9BUL, 0x92DC560DUL, + 0x224D1E20UL, 0x8437AA88UL, 0x7D29DC96UL, 0x2756D3DCUL, + 0x8B907CEEUL, 0xB51FD240UL, 0xE7C07CE3UL, 0xE566B4A1UL, + 0xC3E9615EUL, 0x3CF8209DUL, 0x6094D1E3UL, 0xCD9CA341UL, + 0x5C76460EUL, 0x00EA983BUL, 0xD4D67881UL, 0xFD47572CUL, + 0xF76CEDD9UL, 0xBDA8229CUL, 0x127DADAAUL, 0x438A074EUL, + 0x1F97C090UL, 0x081BDB8AUL, 0x93A07EBEUL, 0xB938CA15UL, + 0x97B03CFFUL, 0x3DC2C0F8UL, 0x8D1AB2ECUL, 0x64380E51UL, + 0x68CC7BFBUL, 0xD90F2788UL, 0x12490181UL, 0x5DE5FFD4UL, + 0xDD7EF86AUL, 0x76A2E214UL, 0xB9A40368UL, 0x925D958FUL, + 0x4B39FFFAUL, 0xBA39AEE9UL, 0xA4FFD30BUL, 0xFAF7933BUL, + 0x6D498623UL, 0x193CBCFAUL, 0x27627545UL, 0x825CF47AUL, + 0x61BD8BA0UL, 0xD11E42D1UL, 0xCEAD04F4UL, 0x127EA392UL, + 0x10428DB7UL, 0x8272A972UL, 0x9270C4A8UL, 0x127DE50BUL, + 0x285BA1C8UL, 0x3C62F44FUL, 0x35C0EAA5UL, 0xE805D231UL, + 0x428929FBUL, 0xB4FCDF82UL, 0x4FB66A53UL, 0x0E7DC15BUL, + 0x1F081FABUL, 0x108618AEUL, 0xFCFD086DUL, 0xF9FF2889UL, + 0x694BCC11UL, 0x236A5CAEUL, 0x12DECA4DUL, 0x2C3F8CC5UL, + 0xD2D02DFEUL, 0xF8EF5896UL, 0xE4CF52DAUL, 0x95155B67UL, + 0x494A488CUL, 0xB9B6A80CUL, 0x5C8F82BCUL, 0x89D36B45UL, + 0x3A609437UL, 0xEC00C9A9UL, 0x44715253UL, 0x0A874B49UL, + 0xD773BC40UL, 0x7C34671CUL, 0x02717EF6UL, 0x4FEB5536UL, + 0xA2D02FFFUL, 0xD2BF60C4UL, 0xD43F03C0UL, 0x50B4EF6DUL, + 0x07478CD1UL, 0x006E1888UL, 0xA2E53F55UL, 0xB9E6D4BCUL, + 0xA2048016UL, 0x97573833UL, 0xD7207D67UL, 0xDE0F8F3DUL, + 0x72F87B33UL, 0xABCC4F33UL, 0x7688C55DUL, 0x7B00A6B0UL, + 0x947B0001UL, 0x570075D2UL, 0xF9BB88F8UL, 0x8942019EUL, + 0x4264A5FFUL, 0x856302E0UL, 0x72DBD92BUL, 0xEE971B69UL, + 0x6EA22FDEUL, 0x5F08AE2BUL, 0xAF7A616DUL, 0xE5C98767UL, + 0xCF1FEBD2UL, 0x61EFC8C2UL, 0xF1AC2571UL, 0xCC8239C2UL, + 0x67214CB8UL, 0xB1E583D1UL, 0xB7DC3E62UL, 0x7F10BDCEUL, + 0xF90A5C38UL, 0x0FF0443DUL, 0x606E6DC6UL, 0x60543A49UL, + 0x5727C148UL, 0x2BE98A1DUL, 0x8AB41738UL, 0x20E1BE24UL, + 0xAF96DA0FUL, 0x68458425UL, 0x99833BE5UL, 0x600D457DUL, + 0x282F9350UL, 0x8334B362UL, 0xD91D1120UL, 0x2B6D8DA0UL, + 0x642B1E31UL, 0x9C305A00UL, 0x52BCE688UL, 0x1B03588AUL, + 0xF7BAEFD5UL, 0x4142ED9CUL, 0xA4315C11UL, 0x83323EC5UL, + 0xDFEF4636UL, 0xA133C501UL, 0xE9D3531CUL, 0xEE353783UL +}, + +{ + 0x9DB30420UL, 0x1FB6E9DEUL, 0xA7BE7BEFUL, 0xD273A298UL, + 0x4A4F7BDBUL, 0x64AD8C57UL, 0x85510443UL, 0xFA020ED1UL, + 0x7E287AFFUL, 0xE60FB663UL, 0x095F35A1UL, 0x79EBF120UL, + 0xFD059D43UL, 0x6497B7B1UL, 0xF3641F63UL, 0x241E4ADFUL, + 0x28147F5FUL, 0x4FA2B8CDUL, 0xC9430040UL, 0x0CC32220UL, + 0xFDD30B30UL, 0xC0A5374FUL, 0x1D2D00D9UL, 0x24147B15UL, + 0xEE4D111AUL, 0x0FCA5167UL, 0x71FF904CUL, 0x2D195FFEUL, + 0x1A05645FUL, 0x0C13FEFEUL, 0x081B08CAUL, 0x05170121UL, + 0x80530100UL, 0xE83E5EFEUL, 0xAC9AF4F8UL, 0x7FE72701UL, + 0xD2B8EE5FUL, 0x06DF4261UL, 0xBB9E9B8AUL, 0x7293EA25UL, + 0xCE84FFDFUL, 0xF5718801UL, 0x3DD64B04UL, 0xA26F263BUL, + 0x7ED48400UL, 0x547EEBE6UL, 0x446D4CA0UL, 0x6CF3D6F5UL, + 0x2649ABDFUL, 0xAEA0C7F5UL, 0x36338CC1UL, 0x503F7E93UL, + 0xD3772061UL, 0x11B638E1UL, 0x72500E03UL, 0xF80EB2BBUL, + 0xABE0502EUL, 0xEC8D77DEUL, 0x57971E81UL, 0xE14F6746UL, + 0xC9335400UL, 0x6920318FUL, 0x081DBB99UL, 0xFFC304A5UL, + 0x4D351805UL, 0x7F3D5CE3UL, 0xA6C866C6UL, 0x5D5BCCA9UL, + 0xDAEC6FEAUL, 0x9F926F91UL, 0x9F46222FUL, 0x3991467DUL, + 0xA5BF6D8EUL, 0x1143C44FUL, 0x43958302UL, 0xD0214EEBUL, + 0x022083B8UL, 0x3FB6180CUL, 0x18F8931EUL, 0x281658E6UL, + 0x26486E3EUL, 0x8BD78A70UL, 0x7477E4C1UL, 0xB506E07CUL, + 0xF32D0A25UL, 0x79098B02UL, 0xE4EABB81UL, 0x28123B23UL, + 0x69DEAD38UL, 0x1574CA16UL, 0xDF871B62UL, 0x211C40B7UL, + 0xA51A9EF9UL, 0x0014377BUL, 0x041E8AC8UL, 0x09114003UL, + 0xBD59E4D2UL, 0xE3D156D5UL, 0x4FE876D5UL, 0x2F91A340UL, + 0x557BE8DEUL, 0x00EAE4A7UL, 0x0CE5C2ECUL, 0x4DB4BBA6UL, + 0xE756BDFFUL, 0xDD3369ACUL, 0xEC17B035UL, 0x06572327UL, + 0x99AFC8B0UL, 0x56C8C391UL, 0x6B65811CUL, 0x5E146119UL, + 0x6E85CB75UL, 0xBE07C002UL, 0xC2325577UL, 0x893FF4ECUL, + 0x5BBFC92DUL, 0xD0EC3B25UL, 0xB7801AB7UL, 0x8D6D3B24UL, + 0x20C763EFUL, 0xC366A5FCUL, 0x9C382880UL, 0x0ACE3205UL, + 0xAAC9548AUL, 0xECA1D7C7UL, 0x041AFA32UL, 0x1D16625AUL, + 0x6701902CUL, 0x9B757A54UL, 0x31D477F7UL, 0x9126B031UL, + 0x36CC6FDBUL, 0xC70B8B46UL, 0xD9E66A48UL, 0x56E55A79UL, + 0x026A4CEBUL, 0x52437EFFUL, 0x2F8F76B4UL, 0x0DF980A5UL, + 0x8674CDE3UL, 0xEDDA04EBUL, 0x17A9BE04UL, 0x2C18F4DFUL, + 0xB7747F9DUL, 0xAB2AF7B4UL, 0xEFC34D20UL, 0x2E096B7CUL, + 0x1741A254UL, 0xE5B6A035UL, 0x213D42F6UL, 0x2C1C7C26UL, + 0x61C2F50FUL, 0x6552DAF9UL, 0xD2C231F8UL, 0x25130F69UL, + 0xD8167FA2UL, 0x0418F2C8UL, 0x001A96A6UL, 0x0D1526ABUL, + 0x63315C21UL, 0x5E0A72ECUL, 0x49BAFEFDUL, 0x187908D9UL, + 0x8D0DBD86UL, 0x311170A7UL, 0x3E9B640CUL, 0xCC3E10D7UL, + 0xD5CAD3B6UL, 0x0CAEC388UL, 0xF73001E1UL, 0x6C728AFFUL, + 0x71EAE2A1UL, 0x1F9AF36EUL, 0xCFCBD12FUL, 0xC1DE8417UL, + 0xAC07BE6BUL, 0xCB44A1D8UL, 0x8B9B0F56UL, 0x013988C3UL, + 0xB1C52FCAUL, 0xB4BE31CDUL, 0xD8782806UL, 0x12A3A4E2UL, + 0x6F7DE532UL, 0x58FD7EB6UL, 0xD01EE900UL, 0x24ADFFC2UL, + 0xF4990FC5UL, 0x9711AAC5UL, 0x001D7B95UL, 0x82E5E7D2UL, + 0x109873F6UL, 0x00613096UL, 0xC32D9521UL, 0xADA121FFUL, + 0x29908415UL, 0x7FBB977FUL, 0xAF9EB3DBUL, 0x29C9ED2AUL, + 0x5CE2A465UL, 0xA730F32CUL, 0xD0AA3FE8UL, 0x8A5CC091UL, + 0xD49E2CE7UL, 0x0CE454A9UL, 0xD60ACD86UL, 0x015F1919UL, + 0x77079103UL, 0xDEA03AF6UL, 0x78A8565EUL, 0xDEE356DFUL, + 0x21F05CBEUL, 0x8B75E387UL, 0xB3C50651UL, 0xB8A5C3EFUL, + 0xD8EEB6D2UL, 0xE523BE77UL, 0xC2154529UL, 0x2F69EFDFUL, + 0xAFE67AFBUL, 0xF470C4B2UL, 0xF3E0EB5BUL, 0xD6CC9876UL, + 0x39E4460CUL, 0x1FDA8538UL, 0x1987832FUL, 0xCA007367UL, + 0xA99144F8UL, 0x296B299EUL, 0x492FC295UL, 0x9266BEABUL, + 0xB5676E69UL, 0x9BD3DDDAUL, 0xDF7E052FUL, 0xDB25701CUL, + 0x1B5E51EEUL, 0xF65324E6UL, 0x6AFCE36CUL, 0x0316CC04UL, + 0x8644213EUL, 0xB7DC59D0UL, 0x7965291FUL, 0xCCD6FD43UL, + 0x41823979UL, 0x932BCDF6UL, 0xB657C34DUL, 0x4EDFD282UL, + 0x7AE5290CUL, 0x3CB9536BUL, 0x851E20FEUL, 0x9833557EUL, + 0x13ECF0B0UL, 0xD3FFB372UL, 0x3F85C5C1UL, 0x0AEF7ED2UL +}, + +{ + 0x7EC90C04UL, 0x2C6E74B9UL, 0x9B0E66DFUL, 0xA6337911UL, + 0xB86A7FFFUL, 0x1DD358F5UL, 0x44DD9D44UL, 0x1731167FUL, + 0x08FBF1FAUL, 0xE7F511CCUL, 0xD2051B00UL, 0x735ABA00UL, + 0x2AB722D8UL, 0x386381CBUL, 0xACF6243AUL, 0x69BEFD7AUL, + 0xE6A2E77FUL, 0xF0C720CDUL, 0xC4494816UL, 0xCCF5C180UL, + 0x38851640UL, 0x15B0A848UL, 0xE68B18CBUL, 0x4CAADEFFUL, + 0x5F480A01UL, 0x0412B2AAUL, 0x259814FCUL, 0x41D0EFE2UL, + 0x4E40B48DUL, 0x248EB6FBUL, 0x8DBA1CFEUL, 0x41A99B02UL, + 0x1A550A04UL, 0xBA8F65CBUL, 0x7251F4E7UL, 0x95A51725UL, + 0xC106ECD7UL, 0x97A5980AUL, 0xC539B9AAUL, 0x4D79FE6AUL, + 0xF2F3F763UL, 0x68AF8040UL, 0xED0C9E56UL, 0x11B4958BUL, + 0xE1EB5A88UL, 0x8709E6B0UL, 0xD7E07156UL, 0x4E29FEA7UL, + 0x6366E52DUL, 0x02D1C000UL, 0xC4AC8E05UL, 0x9377F571UL, + 0x0C05372AUL, 0x578535F2UL, 0x2261BE02UL, 0xD642A0C9UL, + 0xDF13A280UL, 0x74B55BD2UL, 0x682199C0UL, 0xD421E5ECUL, + 0x53FB3CE8UL, 0xC8ADEDB3UL, 0x28A87FC9UL, 0x3D959981UL, + 0x5C1FF900UL, 0xFE38D399UL, 0x0C4EFF0BUL, 0x062407EAUL, + 0xAA2F4FB1UL, 0x4FB96976UL, 0x90C79505UL, 0xB0A8A774UL, + 0xEF55A1FFUL, 0xE59CA2C2UL, 0xA6B62D27UL, 0xE66A4263UL, + 0xDF65001FUL, 0x0EC50966UL, 0xDFDD55BCUL, 0x29DE0655UL, + 0x911E739AUL, 0x17AF8975UL, 0x32C7911CUL, 0x89F89468UL, + 0x0D01E980UL, 0x524755F4UL, 0x03B63CC9UL, 0x0CC844B2UL, + 0xBCF3F0AAUL, 0x87AC36E9UL, 0xE53A7426UL, 0x01B3D82BUL, + 0x1A9E7449UL, 0x64EE2D7EUL, 0xCDDBB1DAUL, 0x01C94910UL, + 0xB868BF80UL, 0x0D26F3FDUL, 0x9342EDE7UL, 0x04A5C284UL, + 0x636737B6UL, 0x50F5B616UL, 0xF24766E3UL, 0x8ECA36C1UL, + 0x136E05DBUL, 0xFEF18391UL, 0xFB887A37UL, 0xD6E7F7D4UL, + 0xC7FB7DC9UL, 0x3063FCDFUL, 0xB6F589DEUL, 0xEC2941DAUL, + 0x26E46695UL, 0xB7566419UL, 0xF654EFC5UL, 0xD08D58B7UL, + 0x48925401UL, 0xC1BACB7FUL, 0xE5FF550FUL, 0xB6083049UL, + 0x5BB5D0E8UL, 0x87D72E5AUL, 0xAB6A6EE1UL, 0x223A66CEUL, + 0xC62BF3CDUL, 0x9E0885F9UL, 0x68CB3E47UL, 0x086C010FUL, + 0xA21DE820UL, 0xD18B69DEUL, 0xF3F65777UL, 0xFA02C3F6UL, + 0x407EDAC3UL, 0xCBB3D550UL, 0x1793084DUL, 0xB0D70EBAUL, + 0x0AB378D5UL, 0xD951FB0CUL, 0xDED7DA56UL, 0x4124BBE4UL, + 0x94CA0B56UL, 0x0F5755D1UL, 0xE0E1E56EUL, 0x6184B5BEUL, + 0x580A249FUL, 0x94F74BC0UL, 0xE327888EUL, 0x9F7B5561UL, + 0xC3DC0280UL, 0x05687715UL, 0x646C6BD7UL, 0x44904DB3UL, + 0x66B4F0A3UL, 0xC0F1648AUL, 0x697ED5AFUL, 0x49E92FF6UL, + 0x309E374FUL, 0x2CB6356AUL, 0x85808573UL, 0x4991F840UL, + 0x76F0AE02UL, 0x083BE84DUL, 0x28421C9AUL, 0x44489406UL, + 0x736E4CB8UL, 0xC1092910UL, 0x8BC95FC6UL, 0x7D869CF4UL, + 0x134F616FUL, 0x2E77118DUL, 0xB31B2BE1UL, 0xAA90B472UL, + 0x3CA5D717UL, 0x7D161BBAUL, 0x9CAD9010UL, 0xAF462BA2UL, + 0x9FE459D2UL, 0x45D34559UL, 0xD9F2DA13UL, 0xDBC65487UL, + 0xF3E4F94EUL, 0x176D486FUL, 0x097C13EAUL, 0x631DA5C7UL, + 0x445F7382UL, 0x175683F4UL, 0xCDC66A97UL, 0x70BE0288UL, + 0xB3CDCF72UL, 0x6E5DD2F3UL, 0x20936079UL, 0x459B80A5UL, + 0xBE60E2DBUL, 0xA9C23101UL, 0xEBA5315CUL, 0x224E42F2UL, + 0x1C5C1572UL, 0xF6721B2CUL, 0x1AD2FFF3UL, 0x8C25404EUL, + 0x324ED72FUL, 0x4067B7FDUL, 0x0523138EUL, 0x5CA3BC78UL, + 0xDC0FD66EUL, 0x75922283UL, 0x784D6B17UL, 0x58EBB16EUL, + 0x44094F85UL, 0x3F481D87UL, 0xFCFEAE7BUL, 0x77B5FF76UL, + 0x8C2302BFUL, 0xAAF47556UL, 0x5F46B02AUL, 0x2B092801UL, + 0x3D38F5F7UL, 0x0CA81F36UL, 0x52AF4A8AUL, 0x66D5E7C0UL, + 0xDF3B0874UL, 0x95055110UL, 0x1B5AD7A8UL, 0xF61ED5ADUL, + 0x6CF6E479UL, 0x20758184UL, 0xD0CEFA65UL, 0x88F7BE58UL, + 0x4A046826UL, 0x0FF6F8F3UL, 0xA09C7F70UL, 0x5346ABA0UL, + 0x5CE96C28UL, 0xE176EDA3UL, 0x6BAC307FUL, 0x376829D2UL, + 0x85360FA9UL, 0x17E3FE2AUL, 0x24B79767UL, 0xF5A96B20UL, + 0xD6CD2595UL, 0x68FF1EBFUL, 0x7555442CUL, 0xF19F06BEUL, + 0xF9E0659AUL, 0xEEB9491DUL, 0x34010718UL, 0xBB30CAB8UL, + 0xE822FE15UL, 0x88570983UL, 0x750E6249UL, 0xDA627E55UL, + 0x5E76FFA8UL, 0xB1534546UL, 0x6D47DE08UL, 0xEFE9E7D4UL +}, + +{ + 0xF6FA8F9DUL, 0x2CAC6CE1UL, 0x4CA34867UL, 0xE2337F7CUL, + 0x95DB08E7UL, 0x016843B4UL, 0xECED5CBCUL, 0x325553ACUL, + 0xBF9F0960UL, 0xDFA1E2EDUL, 0x83F0579DUL, 0x63ED86B9UL, + 0x1AB6A6B8UL, 0xDE5EBE39UL, 0xF38FF732UL, 0x8989B138UL, + 0x33F14961UL, 0xC01937BDUL, 0xF506C6DAUL, 0xE4625E7EUL, + 0xA308EA99UL, 0x4E23E33CUL, 0x79CBD7CCUL, 0x48A14367UL, + 0xA3149619UL, 0xFEC94BD5UL, 0xA114174AUL, 0xEAA01866UL, + 0xA084DB2DUL, 0x09A8486FUL, 0xA888614AUL, 0x2900AF98UL, + 0x01665991UL, 0xE1992863UL, 0xC8F30C60UL, 0x2E78EF3CUL, + 0xD0D51932UL, 0xCF0FEC14UL, 0xF7CA07D2UL, 0xD0A82072UL, + 0xFD41197EUL, 0x9305A6B0UL, 0xE86BE3DAUL, 0x74BED3CDUL, + 0x372DA53CUL, 0x4C7F4448UL, 0xDAB5D440UL, 0x6DBA0EC3UL, + 0x083919A7UL, 0x9FBAEED9UL, 0x49DBCFB0UL, 0x4E670C53UL, + 0x5C3D9C01UL, 0x64BDB941UL, 0x2C0E636AUL, 0xBA7DD9CDUL, + 0xEA6F7388UL, 0xE70BC762UL, 0x35F29ADBUL, 0x5C4CDD8DUL, + 0xF0D48D8CUL, 0xB88153E2UL, 0x08A19866UL, 0x1AE2EAC8UL, + 0x284CAF89UL, 0xAA928223UL, 0x9334BE53UL, 0x3B3A21BFUL, + 0x16434BE3UL, 0x9AEA3906UL, 0xEFE8C36EUL, 0xF890CDD9UL, + 0x80226DAEUL, 0xC340A4A3UL, 0xDF7E9C09UL, 0xA694A807UL, + 0x5B7C5ECCUL, 0x221DB3A6UL, 0x9A69A02FUL, 0x68818A54UL, + 0xCEB2296FUL, 0x53C0843AUL, 0xFE893655UL, 0x25BFE68AUL, + 0xB4628ABCUL, 0xCF222EBFUL, 0x25AC6F48UL, 0xA9A99387UL, + 0x53BDDB65UL, 0xE76FFBE7UL, 0xE967FD78UL, 0x0BA93563UL, + 0x8E342BC1UL, 0xE8A11BE9UL, 0x4980740DUL, 0xC8087DFCUL, + 0x8DE4BF99UL, 0xA11101A0UL, 0x7FD37975UL, 0xDA5A26C0UL, + 0xE81F994FUL, 0x9528CD89UL, 0xFD339FEDUL, 0xB87834BFUL, + 0x5F04456DUL, 0x22258698UL, 0xC9C4C83BUL, 0x2DC156BEUL, + 0x4F628DAAUL, 0x57F55EC5UL, 0xE2220ABEUL, 0xD2916EBFUL, + 0x4EC75B95UL, 0x24F2C3C0UL, 0x42D15D99UL, 0xCD0D7FA0UL, + 0x7B6E27FFUL, 0xA8DC8AF0UL, 0x7345C106UL, 0xF41E232FUL, + 0x35162386UL, 0xE6EA8926UL, 0x3333B094UL, 0x157EC6F2UL, + 0x372B74AFUL, 0x692573E4UL, 0xE9A9D848UL, 0xF3160289UL, + 0x3A62EF1DUL, 0xA787E238UL, 0xF3A5F676UL, 0x74364853UL, + 0x20951063UL, 0x4576698DUL, 0xB6FAD407UL, 0x592AF950UL, + 0x36F73523UL, 0x4CFB6E87UL, 0x7DA4CEC0UL, 0x6C152DAAUL, + 0xCB0396A8UL, 0xC50DFE5DUL, 0xFCD707ABUL, 0x0921C42FUL, + 0x89DFF0BBUL, 0x5FE2BE78UL, 0x448F4F33UL, 0x754613C9UL, + 0x2B05D08DUL, 0x48B9D585UL, 0xDC049441UL, 0xC8098F9BUL, + 0x7DEDE786UL, 0xC39A3373UL, 0x42410005UL, 0x6A091751UL, + 0x0EF3C8A6UL, 0x890072D6UL, 0x28207682UL, 0xA9A9F7BEUL, + 0xBF32679DUL, 0xD45B5B75UL, 0xB353FD00UL, 0xCBB0E358UL, + 0x830F220AUL, 0x1F8FB214UL, 0xD372CF08UL, 0xCC3C4A13UL, + 0x8CF63166UL, 0x061C87BEUL, 0x88C98F88UL, 0x6062E397UL, + 0x47CF8E7AUL, 0xB6C85283UL, 0x3CC2ACFBUL, 0x3FC06976UL, + 0x4E8F0252UL, 0x64D8314DUL, 0xDA3870E3UL, 0x1E665459UL, + 0xC10908F0UL, 0x513021A5UL, 0x6C5B68B7UL, 0x822F8AA0UL, + 0x3007CD3EUL, 0x74719EEFUL, 0xDC872681UL, 0x073340D4UL, + 0x7E432FD9UL, 0x0C5EC241UL, 0x8809286CUL, 0xF592D891UL, + 0x08A930F6UL, 0x957EF305UL, 0xB7FBFFBDUL, 0xC266E96FUL, + 0x6FE4AC98UL, 0xB173ECC0UL, 0xBC60B42AUL, 0x953498DAUL, + 0xFBA1AE12UL, 0x2D4BD736UL, 0x0F25FAABUL, 0xA4F3FCEBUL, + 0xE2969123UL, 0x257F0C3DUL, 0x9348AF49UL, 0x361400BCUL, + 0xE8816F4AUL, 0x3814F200UL, 0xA3F94043UL, 0x9C7A54C2UL, + 0xBC704F57UL, 0xDA41E7F9UL, 0xC25AD33AUL, 0x54F4A084UL, + 0xB17F5505UL, 0x59357CBEUL, 0xEDBD15C8UL, 0x7F97C5ABUL, + 0xBA5AC7B5UL, 0xB6F6DEAFUL, 0x3A479C3AUL, 0x5302DA25UL, + 0x653D7E6AUL, 0x54268D49UL, 0x51A477EAUL, 0x5017D55BUL, + 0xD7D25D88UL, 0x44136C76UL, 0x0404A8C8UL, 0xB8E5A121UL, + 0xB81A928AUL, 0x60ED5869UL, 0x97C55B96UL, 0xEAEC991BUL, + 0x29935913UL, 0x01FDB7F1UL, 0x088E8DFAUL, 0x9AB6F6F5UL, + 0x3B4CBF9FUL, 0x4A5DE3ABUL, 0xE6051D35UL, 0xA0E1D855UL, + 0xD36B4CF1UL, 0xF544EDEBUL, 0xB0E93524UL, 0xBEBB8FBDUL, + 0xA2D762CFUL, 0x49C92F54UL, 0x38B5F331UL, 0x7128A454UL, + 0x48392905UL, 0xA65B1DB8UL, 0x851C97BDUL, 0xD675CF2FUL +}, + +{ + 0x85E04019UL, 0x332BF567UL, 0x662DBFFFUL, 0xCFC65693UL, + 0x2A8D7F6FUL, 0xAB9BC912UL, 0xDE6008A1UL, 0x2028DA1FUL, + 0x0227BCE7UL, 0x4D642916UL, 0x18FAC300UL, 0x50F18B82UL, + 0x2CB2CB11UL, 0xB232E75CUL, 0x4B3695F2UL, 0xB28707DEUL, + 0xA05FBCF6UL, 0xCD4181E9UL, 0xE150210CUL, 0xE24EF1BDUL, + 0xB168C381UL, 0xFDE4E789UL, 0x5C79B0D8UL, 0x1E8BFD43UL, + 0x4D495001UL, 0x38BE4341UL, 0x913CEE1DUL, 0x92A79C3FUL, + 0x089766BEUL, 0xBAEEADF4UL, 0x1286BECFUL, 0xB6EACB19UL, + 0x2660C200UL, 0x7565BDE4UL, 0x64241F7AUL, 0x8248DCA9UL, + 0xC3B3AD66UL, 0x28136086UL, 0x0BD8DFA8UL, 0x356D1CF2UL, + 0x107789BEUL, 0xB3B2E9CEUL, 0x0502AA8FUL, 0x0BC0351EUL, + 0x166BF52AUL, 0xEB12FF82UL, 0xE3486911UL, 0xD34D7516UL, + 0x4E7B3AFFUL, 0x5F43671BUL, 0x9CF6E037UL, 0x4981AC83UL, + 0x334266CEUL, 0x8C9341B7UL, 0xD0D854C0UL, 0xCB3A6C88UL, + 0x47BC2829UL, 0x4725BA37UL, 0xA66AD22BUL, 0x7AD61F1EUL, + 0x0C5CBAFAUL, 0x4437F107UL, 0xB6E79962UL, 0x42D2D816UL, + 0x0A961288UL, 0xE1A5C06EUL, 0x13749E67UL, 0x72FC081AUL, + 0xB1D139F7UL, 0xF9583745UL, 0xCF19DF58UL, 0xBEC3F756UL, + 0xC06EBA30UL, 0x07211B24UL, 0x45C28829UL, 0xC95E317FUL, + 0xBC8EC511UL, 0x38BC46E9UL, 0xC6E6FA14UL, 0xBAE8584AUL, + 0xAD4EBC46UL, 0x468F508BUL, 0x7829435FUL, 0xF124183BUL, + 0x821DBA9FUL, 0xAFF60FF4UL, 0xEA2C4E6DUL, 0x16E39264UL, + 0x92544A8BUL, 0x009B4FC3UL, 0xABA68CEDUL, 0x9AC96F78UL, + 0x06A5B79AUL, 0xB2856E6EUL, 0x1AEC3CA9UL, 0xBE838688UL, + 0x0E0804E9UL, 0x55F1BE56UL, 0xE7E5363BUL, 0xB3A1F25DUL, + 0xF7DEBB85UL, 0x61FE033CUL, 0x16746233UL, 0x3C034C28UL, + 0xDA6D0C74UL, 0x79AAC56CUL, 0x3CE4E1ADUL, 0x51F0C802UL, + 0x98F8F35AUL, 0x1626A49FUL, 0xEED82B29UL, 0x1D382FE3UL, + 0x0C4FB99AUL, 0xBB325778UL, 0x3EC6D97BUL, 0x6E77A6A9UL, + 0xCB658B5CUL, 0xD45230C7UL, 0x2BD1408BUL, 0x60C03EB7UL, + 0xB9068D78UL, 0xA33754F4UL, 0xF430C87DUL, 0xC8A71302UL, + 0xB96D8C32UL, 0xEBD4E7BEUL, 0xBE8B9D2DUL, 0x7979FB06UL, + 0xE7225308UL, 0x8B75CF77UL, 0x11EF8DA4UL, 0xE083C858UL, + 0x8D6B786FUL, 0x5A6317A6UL, 0xFA5CF7A0UL, 0x5DDA0033UL, + 0xF28EBFB0UL, 0xF5B9C310UL, 0xA0EAC280UL, 0x08B9767AUL, + 0xA3D9D2B0UL, 0x79D34217UL, 0x021A718DUL, 0x9AC6336AUL, + 0x2711FD60UL, 0x438050E3UL, 0x069908A8UL, 0x3D7FEDC4UL, + 0x826D2BEFUL, 0x4EEB8476UL, 0x488DCF25UL, 0x36C9D566UL, + 0x28E74E41UL, 0xC2610ACAUL, 0x3D49A9CFUL, 0xBAE3B9DFUL, + 0xB65F8DE6UL, 0x92AEAF64UL, 0x3AC7D5E6UL, 0x9EA80509UL, + 0xF22B017DUL, 0xA4173F70UL, 0xDD1E16C3UL, 0x15E0D7F9UL, + 0x50B1B887UL, 0x2B9F4FD5UL, 0x625ABA82UL, 0x6A017962UL, + 0x2EC01B9CUL, 0x15488AA9UL, 0xD716E740UL, 0x40055A2CUL, + 0x93D29A22UL, 0xE32DBF9AUL, 0x058745B9UL, 0x3453DC1EUL, + 0xD699296EUL, 0x496CFF6FUL, 0x1C9F4986UL, 0xDFE2ED07UL, + 0xB87242D1UL, 0x19DE7EAEUL, 0x053E561AUL, 0x15AD6F8CUL, + 0x66626C1CUL, 0x7154C24CUL, 0xEA082B2AUL, 0x93EB2939UL, + 0x17DCB0F0UL, 0x58D4F2AEUL, 0x9EA294FBUL, 0x52CF564CUL, + 0x9883FE66UL, 0x2EC40581UL, 0x763953C3UL, 0x01D6692EUL, + 0xD3A0C108UL, 0xA1E7160EUL, 0xE4F2DFA6UL, 0x693ED285UL, + 0x74904698UL, 0x4C2B0EDDUL, 0x4F757656UL, 0x5D393378UL, + 0xA132234FUL, 0x3D321C5DUL, 0xC3F5E194UL, 0x4B269301UL, + 0xC79F022FUL, 0x3C997E7EUL, 0x5E4F9504UL, 0x3FFAFBBDUL, + 0x76F7AD0EUL, 0x296693F4UL, 0x3D1FCE6FUL, 0xC61E45BEUL, + 0xD3B5AB34UL, 0xF72BF9B7UL, 0x1B0434C0UL, 0x4E72B567UL, + 0x5592A33DUL, 0xB5229301UL, 0xCFD2A87FUL, 0x60AEB767UL, + 0x1814386BUL, 0x30BCC33DUL, 0x38A0C07DUL, 0xFD1606F2UL, + 0xC363519BUL, 0x589DD390UL, 0x5479F8E6UL, 0x1CB8D647UL, + 0x97FD61A9UL, 0xEA7759F4UL, 0x2D57539DUL, 0x569A58CFUL, + 0xE84E63ADUL, 0x462E1B78UL, 0x6580F87EUL, 0xF3817914UL, + 0x91DA55F4UL, 0x40A230F3UL, 0xD1988F35UL, 0xB6E318D2UL, + 0x3FFA50BCUL, 0x3D40F021UL, 0xC3C0BDAEUL, 0x4958C24CUL, + 0x518F36B2UL, 0x84B1D370UL, 0x0FEDCE83UL, 0x878DDADAUL, + 0xF2A279C7UL, 0x94E01BE8UL, 0x90716F4BUL, 0x954B8AA3UL +}, + +{ + 0xE216300DUL, 0xBBDDFFFCUL, 0xA7EBDABDUL, 0x35648095UL, + 0x7789F8B7UL, 0xE6C1121BUL, 0x0E241600UL, 0x052CE8B5UL, + 0x11A9CFB0UL, 0xE5952F11UL, 0xECE7990AUL, 0x9386D174UL, + 0x2A42931CUL, 0x76E38111UL, 0xB12DEF3AUL, 0x37DDDDFCUL, + 0xDE9ADEB1UL, 0x0A0CC32CUL, 0xBE197029UL, 0x84A00940UL, + 0xBB243A0FUL, 0xB4D137CFUL, 0xB44E79F0UL, 0x049EEDFDUL, + 0x0B15A15DUL, 0x480D3168UL, 0x8BBBDE5AUL, 0x669DED42UL, + 0xC7ECE831UL, 0x3F8F95E7UL, 0x72DF191BUL, 0x7580330DUL, + 0x94074251UL, 0x5C7DCDFAUL, 0xABBE6D63UL, 0xAA402164UL, + 0xB301D40AUL, 0x02E7D1CAUL, 0x53571DAEUL, 0x7A3182A2UL, + 0x12A8DDECUL, 0xFDAA335DUL, 0x176F43E8UL, 0x71FB46D4UL, + 0x38129022UL, 0xCE949AD4UL, 0xB84769ADUL, 0x965BD862UL, + 0x82F3D055UL, 0x66FB9767UL, 0x15B80B4EUL, 0x1D5B47A0UL, + 0x4CFDE06FUL, 0xC28EC4B8UL, 0x57E8726EUL, 0x647A78FCUL, + 0x99865D44UL, 0x608BD593UL, 0x6C200E03UL, 0x39DC5FF6UL, + 0x5D0B00A3UL, 0xAE63AFF2UL, 0x7E8BD632UL, 0x70108C0CUL, + 0xBBD35049UL, 0x2998DF04UL, 0x980CF42AUL, 0x9B6DF491UL, + 0x9E7EDD53UL, 0x06918548UL, 0x58CB7E07UL, 0x3B74EF2EUL, + 0x522FFFB1UL, 0xD24708CCUL, 0x1C7E27CDUL, 0xA4EB215BUL, + 0x3CF1D2E2UL, 0x19B47A38UL, 0x424F7618UL, 0x35856039UL, + 0x9D17DEE7UL, 0x27EB35E6UL, 0xC9AFF67BUL, 0x36BAF5B8UL, + 0x09C467CDUL, 0xC18910B1UL, 0xE11DBF7BUL, 0x06CD1AF8UL, + 0x7170C608UL, 0x2D5E3354UL, 0xD4DE495AUL, 0x64C6D006UL, + 0xBCC0C62CUL, 0x3DD00DB3UL, 0x708F8F34UL, 0x77D51B42UL, + 0x264F620FUL, 0x24B8D2BFUL, 0x15C1B79EUL, 0x46A52564UL, + 0xF8D7E54EUL, 0x3E378160UL, 0x7895CDA5UL, 0x859C15A5UL, + 0xE6459788UL, 0xC37BC75FUL, 0xDB07BA0CUL, 0x0676A3ABUL, + 0x7F229B1EUL, 0x31842E7BUL, 0x24259FD7UL, 0xF8BEF472UL, + 0x835FFCB8UL, 0x6DF4C1F2UL, 0x96F5B195UL, 0xFD0AF0FCUL, + 0xB0FE134CUL, 0xE2506D3DUL, 0x4F9B12EAUL, 0xF215F225UL, + 0xA223736FUL, 0x9FB4C428UL, 0x25D04979UL, 0x34C713F8UL, + 0xC4618187UL, 0xEA7A6E98UL, 0x7CD16EFCUL, 0x1436876CUL, + 0xF1544107UL, 0xBEDEEE14UL, 0x56E9AF27UL, 0xA04AA441UL, + 0x3CF7C899UL, 0x92ECBAE6UL, 0xDD67016DUL, 0x151682EBUL, + 0xA842EEDFUL, 0xFDBA60B4UL, 0xF1907B75UL, 0x20E3030FUL, + 0x24D8C29EUL, 0xE139673BUL, 0xEFA63FB8UL, 0x71873054UL, + 0xB6F2CF3BUL, 0x9F326442UL, 0xCB15A4CCUL, 0xB01A4504UL, + 0xF1E47D8DUL, 0x844A1BE5UL, 0xBAE7DFDCUL, 0x42CBDA70UL, + 0xCD7DAE0AUL, 0x57E85B7AUL, 0xD53F5AF6UL, 0x20CF4D8CUL, + 0xCEA4D428UL, 0x79D130A4UL, 0x3486EBFBUL, 0x33D3CDDCUL, + 0x77853B53UL, 0x37EFFCB5UL, 0xC5068778UL, 0xE580B3E6UL, + 0x4E68B8F4UL, 0xC5C8B37EUL, 0x0D809EA2UL, 0x398FEB7CUL, + 0x132A4F94UL, 0x43B7950EUL, 0x2FEE7D1CUL, 0x223613BDUL, + 0xDD06CAA2UL, 0x37DF932BUL, 0xC4248289UL, 0xACF3EBC3UL, + 0x5715F6B7UL, 0xEF3478DDUL, 0xF267616FUL, 0xC148CBE4UL, + 0x9052815EUL, 0x5E410FABUL, 0xB48A2465UL, 0x2EDA7FA4UL, + 0xE87B40E4UL, 0xE98EA084UL, 0x5889E9E1UL, 0xEFD390FCUL, + 0xDD07D35BUL, 0xDB485694UL, 0x38D7E5B2UL, 0x57720101UL, + 0x730EDEBCUL, 0x5B643113UL, 0x94917E4FUL, 0x503C2FBAUL, + 0x646F1282UL, 0x7523D24AUL, 0xE0779695UL, 0xF9C17A8FUL, + 0x7A5B2121UL, 0xD187B896UL, 0x29263A4DUL, 0xBA510CDFUL, + 0x81F47C9FUL, 0xAD1163EDUL, 0xEA7B5965UL, 0x1A00726EUL, + 0x11403092UL, 0x00DA6D77UL, 0x4A0CDD61UL, 0xAD1F4603UL, + 0x605BDFB0UL, 0x9EEDC364UL, 0x22EBE6A8UL, 0xCEE7D28AUL, + 0xA0E736A0UL, 0x5564A6B9UL, 0x10853209UL, 0xC7EB8F37UL, + 0x2DE705CAUL, 0x8951570FUL, 0xDF09822BUL, 0xBD691A6CUL, + 0xAA12E4F2UL, 0x87451C0FUL, 0xE0F6A27AUL, 0x3ADA4819UL, + 0x4CF1764FUL, 0x0D771C2BUL, 0x67CDB156UL, 0x350D8384UL, + 0x5938FA0FUL, 0x42399EF3UL, 0x36997B07UL, 0x0E84093DUL, + 0x4AA93E61UL, 0x8360D87BUL, 0x1FA98B0CUL, 0x1149382CUL, + 0xE97625A5UL, 0x0614D1B7UL, 0x0E25244BUL, 0x0C768347UL, + 0x589E8D82UL, 0x0D2059D1UL, 0xA466BB1EUL, 0xF8DA0A82UL, + 0x04F19130UL, 0xBA6E4EC0UL, 0x99265164UL, 0x1EE7230DUL, + 0x50B2AD80UL, 0xEAEE6801UL, 0x8DB2A283UL, 0xEA8BF59EUL +}}; + +/* CAST uses three different round functions */ +#define f1(l, r, km, kr) \ + t = rotlVariable(km + r, kr); \ + l ^= ((S[0][U8a(t)] ^ S[1][U8b(t)]) - \ + S[2][U8c(t)]) + S[3][U8d(t)]; +#define f2(l, r, km, kr) \ + t = rotlVariable(km ^ r, kr); \ + l ^= ((S[0][U8a(t)] - S[1][U8b(t)]) + \ + S[2][U8c(t)]) ^ S[3][U8d(t)]; +#define f3(l, r, km, kr) \ + t = rotlVariable(km - r, kr); \ + l ^= ((S[0][U8a(t)] + S[1][U8b(t)]) ^ \ + S[2][U8c(t)]) - S[3][U8d(t)]; + +#define F1(l, r, i, j) f1(l, r, K[i], K[i+j]) +#define F2(l, r, i, j) f2(l, r, K[i], K[i+j]) +#define F3(l, r, i, j) f3(l, r, K[i], K[i+j]) + + +void Cast5Encrypt (const byte *inBlock, byte *outBlock, CAST_KEY *key) +{ + word32 l = BE32 (((word32 *)inBlock)[0]); + word32 r = BE32 (((word32 *)inBlock)[1]); + word32 *K = key->K; + word32 t; + + /* Do the work */ + F1(l, r, 0, 16); + F2(r, l, 1, 16); + F3(l, r, 2, 16); + F1(r, l, 3, 16); + F2(l, r, 4, 16); + F3(r, l, 5, 16); + F1(l, r, 6, 16); + F2(r, l, 7, 16); + F3(l, r, 8, 16); + F1(r, l, 9, 16); + F2(l, r, 10, 16); + F3(r, l, 11, 16); + F1(l, r, 12, 16); + F2(r, l, 13, 16); + F3(l, r, 14, 16); + F1(r, l, 15, 16); + + /* Put l,r into outblock */ + ((word32 *)outBlock)[0] = BE32 (r); + ((word32 *)outBlock)[1] = BE32 (l); +} + + +void Cast5Decrypt (const byte *inBlock, byte *outBlock, CAST_KEY *key) +{ + word32 r = BE32 (((word32 *)inBlock)[0]); + word32 l = BE32 (((word32 *)inBlock)[1]); + word32 *K = key->K; + word32 t; + + /* Only do full 16 rounds if key length > 80 bits */ + F1(r, l, 15, 16); + F3(l, r, 14, 16); + F2(r, l, 13, 16); + F1(l, r, 12, 16); + F3(r, l, 11, 16); + F2(l, r, 10, 16); + F1(r, l, 9, 16); + F3(l, r, 8, 16); + F2(r, l, 7, 16); + F1(l, r, 6, 16); + F3(r, l, 5, 16); + F2(l, r, 4, 16); + F1(r, l, 3, 16); + F3(l, r, 2, 16); + F2(r, l, 1, 16); + F1(l, r, 0, 16); + /* Put l,r into outblock */ + ((word32 *)outBlock)[0] = BE32 (l); + ((word32 *)outBlock)[1] = BE32 (r); + /* Wipe clean */ + t = l = r = 0; +} + +void Cast5SetKey (CAST_KEY *key, unsigned int keylength, const byte *userKey) +{ + unsigned int i; + word32 *K = key->K; + word32 X[4], Z[4]; + + X[0] = BE32 (((word32 *)userKey)[0]); + X[1] = BE32 (((word32 *)userKey)[1]); + X[2] = BE32 (((word32 *)userKey)[2]); + X[3] = BE32 (((word32 *)userKey)[3]); + +#define x(i) GETBYTE(X[i/4], 3-i%4) +#define z(i) GETBYTE(Z[i/4], 3-i%4) + + for (i=0; i<=16; i+=16) + { + // this part is copied directly from RFC 2144 (with some search and replace) by Wei Dai + Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)]; + Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)]; + Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)]; + Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)]; + K[i+0] = S[4][z(0x8)] ^ S[5][z(0x9)] ^ S[6][z(0x7)] ^ S[7][z(0x6)] ^ S[4][z(0x2)]; + K[i+1] = S[4][z(0xA)] ^ S[5][z(0xB)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[5][z(0x6)]; + K[i+2] = S[4][z(0xC)] ^ S[5][z(0xD)] ^ S[6][z(0x3)] ^ S[7][z(0x2)] ^ S[6][z(0x9)]; + K[i+3] = S[4][z(0xE)] ^ S[5][z(0xF)] ^ S[6][z(0x1)] ^ S[7][z(0x0)] ^ S[7][z(0xC)]; + X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)]; + X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)]; + X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)]; + X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)]; + K[i+4] = S[4][x(0x3)] ^ S[5][x(0x2)] ^ S[6][x(0xC)] ^ S[7][x(0xD)] ^ S[4][x(0x8)]; + K[i+5] = S[4][x(0x1)] ^ S[5][x(0x0)] ^ S[6][x(0xE)] ^ S[7][x(0xF)] ^ S[5][x(0xD)]; + K[i+6] = S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x8)] ^ S[7][x(0x9)] ^ S[6][x(0x3)]; + K[i+7] = S[4][x(0x5)] ^ S[5][x(0x4)] ^ S[6][x(0xA)] ^ S[7][x(0xB)] ^ S[7][x(0x7)]; + Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)]; + Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)]; + Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)]; + Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)]; + K[i+8] = S[4][z(0x3)] ^ S[5][z(0x2)] ^ S[6][z(0xC)] ^ S[7][z(0xD)] ^ S[4][z(0x9)]; + K[i+9] = S[4][z(0x1)] ^ S[5][z(0x0)] ^ S[6][z(0xE)] ^ S[7][z(0xF)] ^ S[5][z(0xC)]; + K[i+10] = S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x8)] ^ S[7][z(0x9)] ^ S[6][z(0x2)]; + K[i+11] = S[4][z(0x5)] ^ S[5][z(0x4)] ^ S[6][z(0xA)] ^ S[7][z(0xB)] ^ S[7][z(0x6)]; + X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)]; + X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)]; + X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)]; + X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)]; + K[i+12] = S[4][x(0x8)] ^ S[5][x(0x9)] ^ S[6][x(0x7)] ^ S[7][x(0x6)] ^ S[4][x(0x3)]; + K[i+13] = S[4][x(0xA)] ^ S[5][x(0xB)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[5][x(0x7)]; + K[i+14] = S[4][x(0xC)] ^ S[5][x(0xD)] ^ S[6][x(0x3)] ^ S[7][x(0x2)] ^ S[6][x(0x8)]; + K[i+15] = S[4][x(0xE)] ^ S[5][x(0xF)] ^ S[6][x(0x1)] ^ S[7][x(0x0)] ^ S[7][x(0xD)]; + } + + for (i=16; i<32; i++) + K[i] &= 0x1f; +} diff --git a/Crypto/Crypto.vcproj b/Crypto/Crypto.vcproj index acb2a49..0fb8532 100644 --- a/Crypto/Crypto.vcproj +++ b/Crypto/Crypto.vcproj @@ -49,8 +49,9 @@ RuntimeLibrary="1" BufferSecurityCheck="false" UsePrecompiledHeader="0" - WarningLevel="3" + WarningLevel="4" DebugInformationFormat="3" + DisableSpecificWarnings="4100;4127;4201" /> @@ -174,7 +176,7 @@ > diff --git a/Crypto/DES.C b/Crypto/DES.C index 09c1001..f225e6c 100644 --- a/Crypto/DES.C +++ b/Crypto/DES.C @@ -1,404 +1,404 @@ -/* Deprecated/legacy */ -// des.cpp - modified by Wei Dai from Phil Karn's des.c -// The original code and all modifications are in the public domain. - -/* - * This is a major rewrite of my old public domain DES code written - * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977 - * public domain code. I pretty much kept my key scheduling code, but - * the actual encrypt/decrypt routines are taken from from Richard - * Outerbridge's DES code as printed in Schneier's "Applied Cryptography." - * - * This code is in the public domain. I would appreciate bug reports and - * enhancements. - * - * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994. - */ - -/* Adapted for TrueCrypt by the TrueCrypt Foundation */ - -#include -#include "Common/Tcdefs.h" -#include "Common/Endian.h" -#include "Des.h" - -#define word32 unsigned __int32 -#define byte unsigned __int8 - -static word32 rotlFixed (word32 x, unsigned int y) -{ - return (word32)((x<>(sizeof(word32)*8-y))); -} - -static word32 rotrFixed (word32 x, unsigned int y) -{ - return (word32)((x>>y) | (x<<(sizeof(word32)*8-y))); -} - - -/* Tables defined in the Data Encryption Standard documents - * Three of these tables, the initial permutation, the final - * permutation and the expansion operator, are regular enough that - * for speed, we hard-code them. They're here for reference only. - * Also, the S and P boxes are used by a separate program, gensp.c, - * to build the combined SP box, Spbox[]. They're also here just - * for reference. - */ -#ifdef notdef -/* initial permutation IP */ -static byte ip[] = { - 58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7 -}; - -/* final permutation IP^-1 */ -static byte fp[] = { - 40, 8, 48, 16, 56, 24, 64, 32, - 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, - 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, - 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, - 33, 1, 41, 9, 49, 17, 57, 25 -}; -/* expansion operation matrix */ -static byte ei[] = { - 32, 1, 2, 3, 4, 5, - 4, 5, 6, 7, 8, 9, - 8, 9, 10, 11, 12, 13, - 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, - 20, 21, 22, 23, 24, 25, - 24, 25, 26, 27, 28, 29, - 28, 29, 30, 31, 32, 1 -}; -/* The (in)famous S-boxes */ -static byte sbox[8][64] = { - /* S1 */ - 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, - 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, - 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, - 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, - - /* S2 */ - 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, - 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, - 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, - 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, - - /* S3 */ - 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, - 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, - 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, - 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, - - /* S4 */ - 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, - 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, - 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, - 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, - - /* S5 */ - 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, - 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, - 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, - 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, - - /* S6 */ - 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, - 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, - 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, - 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, - - /* S7 */ - 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, - 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, - 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, - 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, - - /* S8 */ - 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, - 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, - 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, - 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 -}; - -/* 32-bit permutation function P used on the output of the S-boxes */ -static byte p32i[] = { - 16, 7, 20, 21, - 29, 12, 28, 17, - 1, 15, 23, 26, - 5, 18, 31, 10, - 2, 8, 24, 14, - 32, 27, 3, 9, - 19, 13, 30, 6, - 22, 11, 4, 25 -}; -#endif - -/* permuted choice table (key) */ -static const byte pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static const byte totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static const byte pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* End of DES-defined tables */ - -/* bit 0 is left-most in byte */ -static const int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - -static const word32 Spbox[8][64] = { -{ -0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, -0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004, -0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404, -0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000, -0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400, -0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404, -0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400, -0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004}, -{ -0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020, -0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020, -0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000, -0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020, -0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000, -0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000, -0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020, -0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000}, -{ -0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200, -0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208, -0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208, -0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000, -0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000, -0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008, -0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008, -0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200}, -{ -0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001, -0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001, -0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080, -0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081, -0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000, -0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080, -0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081, -0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080}, -{ -0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000, -0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000, -0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100, -0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100, -0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100, -0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000, -0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000, -0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100}, -{ -0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000, -0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010, -0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010, -0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000, -0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010, -0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000, -0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010, -0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010}, -{ -0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800, -0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802, -0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002, -0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800, -0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002, -0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800, -0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802, -0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002}, -{ -0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000, -0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040, -0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000, -0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000, -0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040, -0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040, -0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000, -0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000} -}; - -/* Set key (initialize key schedule array) */ -static void RawSetKey (int encryption, const byte *key, word32 *scheduledKey) -{ - byte buffer[56+56+8]; - byte *const pc1m=buffer; /* place to modify pc1 into */ - byte *const pcr=pc1m+56; /* place to rotate pc1 into */ - byte *const ks=pcr+56; - register int i,j,l; - int m; - - for (j=0; j<56; j++) { /* convert pc1 to bits of key */ - l=pc1[j]-1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j]=(key[l>>3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } - for (i=0; i<16; i++) { /* key chunk for each iteration */ - memset(ks,0,8); /* Clear key schedule */ - for (j=0; j<56; j++) /* rotate pc1 the right amount */ - pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; - /* rotate left and right halves independently */ - for (j=0; j<48; j++){ /* select bits individually */ - /* check bit that goes to ks[j] */ - if (pcr[pc2[j]-1]){ - /* mask it in if it's there */ - l= j % 6; - ks[j/6] |= bytebit[l] >> 2; - } - } - /* Now convert to odd/even interleaved form for use in F */ - scheduledKey[2*i] = ((word32)ks[0] << 24) - | ((word32)ks[2] << 16) - | ((word32)ks[4] << 8) - | ((word32)ks[6]); - scheduledKey[2*i+1] = ((word32)ks[1] << 24) - | ((word32)ks[3] << 16) - | ((word32)ks[5] << 8) - | ((word32)ks[7]); - } - - if (!encryption) // reverse key schedule order - for (i=0; i<16; i+=2) - { - word32 b = scheduledKey[i]; - scheduledKey[i] = scheduledKey[32-2-i]; - scheduledKey[32-2-i] = b; - - b = scheduledKey[i+1]; - scheduledKey[i+1] = scheduledKey[32-1-i]; - scheduledKey[32-1-i] = b; - } - - burn (buffer, sizeof (buffer)); -} - -static void RawProcessBlock(word32 *l_, word32 *r_, const word32 *k) -{ - word32 l = *l_, r = *r_; - const word32 *kptr=k; - unsigned i; - - for (i=0; i<8; i++) - { - word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; - l ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = r ^ kptr[4*i+1]; - l ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; - - work = rotrFixed(l, 4U) ^ kptr[4*i+2]; - r ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = l ^ kptr[4*i+3]; - r ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; - } - - *l_ = l; *r_ = r; -} - -void TripleDesSetKey (const byte *userKey, unsigned int length, TDES_KEY *ks) -{ - RawSetKey (1, userKey + 0, ks->k1); - RawSetKey (1, userKey + 8, ks->k2); - RawSetKey (1, userKey + 16, ks->k3); - RawSetKey (0, userKey + 16, ks->k1d); - RawSetKey (0, userKey + 8, ks->k2d); - RawSetKey (0, userKey + 0, ks->k3d); -} - -void TripleDesEncrypt (byte *inBlock, byte *outBlock, TDES_KEY *key, int encrypt) -{ - word32 left = BE32 (((word32 *)inBlock)[0]); - word32 right = BE32 (((word32 *)inBlock)[1]); - word32 work; - - right = rotlFixed(right, 4U); - work = (left ^ right) & 0xf0f0f0f0; - left ^= work; - right = rotrFixed(right^work, 20U); - work = (left ^ right) & 0xffff0000; - left ^= work; - right = rotrFixed(right^work, 18U); - work = (left ^ right) & 0x33333333; - left ^= work; - right = rotrFixed(right^work, 6U); - work = (left ^ right) & 0x00ff00ff; - left ^= work; - right = rotlFixed(right^work, 9U); - work = (left ^ right) & 0xaaaaaaaa; - left = rotlFixed(left^work, 1U); - right ^= work; - - RawProcessBlock (&left, &right, encrypt ? key->k1 : key->k1d); - RawProcessBlock (&right, &left, !encrypt ? key->k2 : key->k2d); - RawProcessBlock (&left, &right, encrypt ? key->k3 : key->k3d); - - right = rotrFixed(right, 1U); - work = (left ^ right) & 0xaaaaaaaa; - right ^= work; - left = rotrFixed(left^work, 9U); - work = (left ^ right) & 0x00ff00ff; - right ^= work; - left = rotlFixed(left^work, 6U); - work = (left ^ right) & 0x33333333; - right ^= work; - left = rotlFixed(left^work, 18U); - work = (left ^ right) & 0xffff0000; - right ^= work; - left = rotlFixed(left^work, 20U); - work = (left ^ right) & 0xf0f0f0f0; - right ^= work; - left = rotrFixed(left^work, 4U); - - ((word32 *)outBlock)[0] = BE32 (right); - ((word32 *)outBlock)[1] = BE32 (left); -} +/* Deprecated/legacy */ +// des.cpp - modified by Wei Dai from Phil Karn's des.c +// The original code and all modifications are in the public domain. + +/* + * This is a major rewrite of my old public domain DES code written + * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977 + * public domain code. I pretty much kept my key scheduling code, but + * the actual encrypt/decrypt routines are taken from from Richard + * Outerbridge's DES code as printed in Schneier's "Applied Cryptography." + * + * This code is in the public domain. I would appreciate bug reports and + * enhancements. + * + * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994. + */ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#include +#include "Common/Tcdefs.h" +#include "Common/Endian.h" +#include "Des.h" + +#define word32 unsigned __int32 +#define byte unsigned __int8 + +static word32 rotlFixed (word32 x, unsigned int y) +{ + return (word32)((x<>(sizeof(word32)*8-y))); +} + +static word32 rotrFixed (word32 x, unsigned int y) +{ + return (word32)((x>>y) | (x<<(sizeof(word32)*8-y))); +} + + +/* Tables defined in the Data Encryption Standard documents + * Three of these tables, the initial permutation, the final + * permutation and the expansion operator, are regular enough that + * for speed, we hard-code them. They're here for reference only. + * Also, the S and P boxes are used by a separate program, gensp.c, + * to build the combined SP box, Spbox[]. They're also here just + * for reference. + */ +#ifdef notdef +/* initial permutation IP */ +static byte ip[] = { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; + +/* final permutation IP^-1 */ +static byte fp[] = { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; +/* expansion operation matrix */ +static byte ei[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 +}; +/* The (in)famous S-boxes */ +static byte sbox[8][64] = { + /* S1 */ + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, + + /* S2 */ + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, + + /* S3 */ + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, + + /* S4 */ + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, + + /* S5 */ + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, + + /* S6 */ + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, + + /* S7 */ + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, + + /* S8 */ + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 +}; + +/* 32-bit permutation function P used on the output of the S-boxes */ +static byte p32i[] = { + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 +}; +#endif + +/* permuted choice table (key) */ +static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 +}; + +/* permuted choice key (table) */ +static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* End of DES-defined tables */ + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 +}; + +static const word32 Spbox[8][64] = { +{ +0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, +0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004, +0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404, +0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000, +0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400, +0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404, +0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400, +0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004}, +{ +0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020, +0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020, +0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000, +0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020, +0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000, +0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000, +0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020, +0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000}, +{ +0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200, +0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208, +0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208, +0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000, +0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000, +0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008, +0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008, +0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200}, +{ +0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001, +0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001, +0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080, +0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081, +0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000, +0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080, +0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081, +0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080}, +{ +0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000, +0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000, +0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100, +0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100, +0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100, +0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000, +0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000, +0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100}, +{ +0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000, +0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010, +0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010, +0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000, +0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010, +0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000, +0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010, +0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010}, +{ +0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800, +0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802, +0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002, +0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800, +0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002, +0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800, +0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802, +0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002}, +{ +0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000, +0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040, +0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000, +0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000, +0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040, +0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040, +0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000, +0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000} +}; + +/* Set key (initialize key schedule array) */ +static void RawSetKey (int encryption, const byte *key, word32 *scheduledKey) +{ + byte buffer[56+56+8]; + byte *const pc1m=buffer; /* place to modify pc1 into */ + byte *const pcr=pc1m+56; /* place to rotate pc1 into */ + byte *const ks=pcr+56; + register int i,j,l; + int m; + + for (j=0; j<56; j++) { /* convert pc1 to bits of key */ + l=pc1[j]-1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j]=(key[l>>3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i=0; i<16; i++) { /* key chunk for each iteration */ + memset(ks,0,8); /* Clear key schedule */ + for (j=0; j<56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j=0; j<48; j++){ /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j]-1]){ + /* mask it in if it's there */ + l= j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to odd/even interleaved form for use in F */ + scheduledKey[2*i] = ((word32)ks[0] << 24) + | ((word32)ks[2] << 16) + | ((word32)ks[4] << 8) + | ((word32)ks[6]); + scheduledKey[2*i+1] = ((word32)ks[1] << 24) + | ((word32)ks[3] << 16) + | ((word32)ks[5] << 8) + | ((word32)ks[7]); + } + + if (!encryption) // reverse key schedule order + for (i=0; i<16; i+=2) + { + word32 b = scheduledKey[i]; + scheduledKey[i] = scheduledKey[32-2-i]; + scheduledKey[32-2-i] = b; + + b = scheduledKey[i+1]; + scheduledKey[i+1] = scheduledKey[32-1-i]; + scheduledKey[32-1-i] = b; + } + + burn (buffer, sizeof (buffer)); +} + +static void RawProcessBlock(word32 *l_, word32 *r_, const word32 *k) +{ + word32 l = *l_, r = *r_; + const word32 *kptr=k; + unsigned i; + + for (i=0; i<8; i++) + { + word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrFixed(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } + + *l_ = l; *r_ = r; +} + +void TripleDesSetKey (const byte *userKey, unsigned int length, TDES_KEY *ks) +{ + RawSetKey (1, userKey + 0, ks->k1); + RawSetKey (1, userKey + 8, ks->k2); + RawSetKey (1, userKey + 16, ks->k3); + RawSetKey (0, userKey + 16, ks->k1d); + RawSetKey (0, userKey + 8, ks->k2d); + RawSetKey (0, userKey + 0, ks->k3d); +} + +void TripleDesEncrypt (byte *inBlock, byte *outBlock, TDES_KEY *key, int encrypt) +{ + word32 left = BE32 (((word32 *)inBlock)[0]); + word32 right = BE32 (((word32 *)inBlock)[1]); + word32 work; + + right = rotlFixed(right, 4U); + work = (left ^ right) & 0xf0f0f0f0; + left ^= work; + right = rotrFixed(right^work, 20U); + work = (left ^ right) & 0xffff0000; + left ^= work; + right = rotrFixed(right^work, 18U); + work = (left ^ right) & 0x33333333; + left ^= work; + right = rotrFixed(right^work, 6U); + work = (left ^ right) & 0x00ff00ff; + left ^= work; + right = rotlFixed(right^work, 9U); + work = (left ^ right) & 0xaaaaaaaa; + left = rotlFixed(left^work, 1U); + right ^= work; + + RawProcessBlock (&left, &right, encrypt ? key->k1 : key->k1d); + RawProcessBlock (&right, &left, !encrypt ? key->k2 : key->k2d); + RawProcessBlock (&left, &right, encrypt ? key->k3 : key->k3d); + + right = rotrFixed(right, 1U); + work = (left ^ right) & 0xaaaaaaaa; + right ^= work; + left = rotrFixed(left^work, 9U); + work = (left ^ right) & 0x00ff00ff; + right ^= work; + left = rotlFixed(left^work, 6U); + work = (left ^ right) & 0x33333333; + right ^= work; + left = rotlFixed(left^work, 18U); + work = (left ^ right) & 0xffff0000; + right ^= work; + left = rotlFixed(left^work, 20U); + work = (left ^ right) & 0xf0f0f0f0; + right ^= work; + left = rotrFixed(left^work, 4U); + + ((word32 *)outBlock)[0] = BE32 (right); + ((word32 *)outBlock)[1] = BE32 (left); +} diff --git a/Crypto/DES.H b/Crypto/DES.H index 54c3ed8..1bfe174 100644 --- a/Crypto/DES.H +++ b/Crypto/DES.H @@ -1,27 +1,27 @@ -/* Deprecated/legacy */ - -#ifndef HEADER_Crypto_DES -#define HEADER_Crypto_DES - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct TRIPLE_DES_KEY_STRUCT -{ - unsigned __int32 k1[32]; - unsigned __int32 k2[32]; - unsigned __int32 k3[32]; - unsigned __int32 k1d[32]; - unsigned __int32 k2d[32]; - unsigned __int32 k3d[32]; -} TDES_KEY; - -void TripleDesEncrypt (byte *inBlock, byte *outBlock, TDES_KEY *key, int encrypt); -void TripleDesSetKey (const byte *userKey, unsigned int length, TDES_KEY *ks); - -#ifdef __cplusplus -} -#endif - -#endif // HEADER_Crypto_DES +/* Deprecated/legacy */ + +#ifndef HEADER_Crypto_DES +#define HEADER_Crypto_DES + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct TRIPLE_DES_KEY_STRUCT +{ + unsigned __int32 k1[32]; + unsigned __int32 k2[32]; + unsigned __int32 k3[32]; + unsigned __int32 k1d[32]; + unsigned __int32 k2d[32]; + unsigned __int32 k3d[32]; +} TDES_KEY; + +void TripleDesEncrypt (byte *inBlock, byte *outBlock, TDES_KEY *key, int encrypt); +void TripleDesSetKey (const byte *userKey, unsigned int length, TDES_KEY *ks); + +#ifdef __cplusplus +} +#endif + +#endif // HEADER_Crypto_DES diff --git a/Crypto/Makefile b/Crypto/Makefile index 5acbbd2..53b9a3d 100644 --- a/Crypto/Makefile +++ b/Crypto/Makefile @@ -1 +1 @@ -!INCLUDE $(NTMAKEENV)\makefile.def +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/Crypto/Makefile.inc b/Crypto/Makefile.inc index 48a68fa..3b5c807 100644 --- a/Crypto/Makefile.inc +++ b/Crypto/Makefile.inc @@ -1,9 +1,9 @@ - -!if "$(TC_ARCH)" == "x86" -TC_OBJ_FORMAT = win32 -!else -TC_OBJ_FORMAT = win64 -!endif - -"$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).obj": Aes_$(TC_ARCH).asm - yasm.exe -Xvc -f $(TC_OBJ_FORMAT) -D DLL_EXPORT -o "$@" Aes_$(TC_ARCH).asm + +!if "$(TC_ARCH)" == "x86" +TC_OBJ_FORMAT = win32 +!else +TC_OBJ_FORMAT = win64 +!endif + +"$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).obj": Aes_$(TC_ARCH).asm + nasm.exe -Xvc -f $(TC_OBJ_FORMAT) -Ox -D DLL_EXPORT -o "$@" -l "$(OBJ_PATH)\$(O)\Aes_$(TC_ARCH).lst" Aes_$(TC_ARCH).asm \ No newline at end of file diff --git a/Crypto/Rmd160.c b/Crypto/Rmd160.c index adc9bf1..5abe316 100644 --- a/Crypto/Rmd160.c +++ b/Crypto/Rmd160.c @@ -1,489 +1,490 @@ -// RIPEMD-160 written and placed in the public domain by Wei Dai - -/* - * This code implements the MD4 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - */ - -/* Adapted by TrueCrypt Foundation */ - -#include -#include "Common/Tcdefs.h" -#include "Common/Endian.h" -#include "Rmd160.h" - -#define F(x, y, z) (x ^ y ^ z) -#define G(x, y, z) (z ^ (x & (y^z))) -#define H(x, y, z) (z ^ (x | ~y)) -#define I(x, y, z) (y ^ (z & (x^y))) -#define J(x, y, z) (x ^ (y | ~z)) - -#define PUT_64BIT_LE(cp, value) do { \ - (cp)[7] = (byte) ((value) >> 56); \ - (cp)[6] = (byte) ((value) >> 48); \ - (cp)[5] = (byte) ((value) >> 40); \ - (cp)[4] = (byte) ((value) >> 32); \ - (cp)[3] = (byte) ((value) >> 24); \ - (cp)[2] = (byte) ((value) >> 16); \ - (cp)[1] = (byte) ((value) >> 8); \ - (cp)[0] = (byte) (value); } while (0) - -#define PUT_32BIT_LE(cp, value) do { \ - (cp)[3] = (byte) ((value) >> 24); \ - (cp)[2] = (byte) ((value) >> 16); \ - (cp)[1] = (byte) ((value) >> 8); \ - (cp)[0] = (byte) (value); } while (0) - -#ifndef TC_MINIMIZE_CODE_SIZE - -static byte PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#else - -static byte PADDING[64]; - -#endif - -void RMD160Init (RMD160_CTX *ctx) -{ - ctx->count = 0; - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xefcdab89; - ctx->state[2] = 0x98badcfe; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xc3d2e1f0; - PADDING[0] = 0x80; -} - -/* -* Update context to reflect the concatenation of another buffer full -* of bytes. -*/ -void RMD160Update (RMD160_CTX *ctx, const unsigned char *input, unsigned __int32 len) -{ - size_t have, need; - - /* Check how many bytes we already have and how many more we need. */ - have = (size_t)((ctx->count >> 3) & (RIPEMD160_BLOCK_LENGTH - 1)); - need = RIPEMD160_BLOCK_LENGTH - have; - - /* Update bitcount */ - ctx->count += -#ifndef TC_NO_COMPILER_INT64 - (uint64) -#endif - len << 3; - - if (len >= need) { - if (have != 0) { - memcpy (ctx->buffer + have, input, need); - RMD160Transform ((uint32 *) ctx->state, (const uint32 *) ctx->buffer); - input += need; - len -= need; - have = 0; - } - - /* Process data in RIPEMD160_BLOCK_LENGTH-byte chunks. */ - while (len >= RIPEMD160_BLOCK_LENGTH) { - RMD160Transform ((uint32 *) ctx->state, (const uint32 *) input); - input += RIPEMD160_BLOCK_LENGTH; - len -= RIPEMD160_BLOCK_LENGTH; - } - } - - /* Handle any remaining bytes of data. */ - if (len != 0) - memcpy (ctx->buffer + have, input, (size_t) len); -} - -/* -* Pad pad to 64-byte boundary with the bit pattern -* 1 0* (64-bit count of bits processed, MSB-first) -*/ -static void RMD160Pad(RMD160_CTX *ctx) -{ - byte count[8]; - size_t padlen; - - /* Convert count to 8 bytes in little endian order. */ - -#ifndef TC_NO_COMPILER_INT64 - PUT_64BIT_LE(count, ctx->count); -#else - *(unsigned __int32 *) (count + 4) = 0; - PUT_32BIT_LE(count, ctx->count); -#endif - - /* Pad out to 56 mod 64. */ - padlen = RIPEMD160_BLOCK_LENGTH - - (size_t)((ctx->count >> 3) & (RIPEMD160_BLOCK_LENGTH - 1)); - if (padlen < 1 + 8) - padlen += RIPEMD160_BLOCK_LENGTH; - RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ - RMD160Update(ctx, count, 8); -} - -/* -* Final wrapup--call RMD160Pad, fill in digest and zero out ctx. -*/ -void RMD160Final(unsigned char *digest, RMD160_CTX *ctx) -{ - int i; - - RMD160Pad(ctx); - if (digest) { - for (i = 0; i < 5; i++) - PUT_32BIT_LE(digest + i * 4, ctx->state[i]); - memset (ctx, 0, sizeof(*ctx)); - } -} - - -#ifndef TC_MINIMIZE_CODE_SIZE - -#define word32 unsigned __int32 - -#define k0 0 -#define k1 0x5a827999UL -#define k2 0x6ed9eba1UL -#define k3 0x8f1bbcdcUL -#define k4 0xa953fd4eUL -#define k5 0x50a28be6UL -#define k6 0x5c4dd124UL -#define k7 0x6d703ef3UL -#define k8 0x7a6d76e9UL -#define k9 0 - -static word32 rotlFixed (word32 x, unsigned int y) -{ - return (word32)((x<>(sizeof(word32)*8-y))); -} - -#define Subround(f, a, b, c, d, e, x, s, k) \ - a += f(b, c, d) + x + k;\ - a = rotlFixed((word32)a, s) + e;\ - c = rotlFixed((word32)c, 10U) - -void RMD160Transform (unsigned __int32 *digest, const unsigned __int32 *data) -{ -#if BYTE_ORDER == LITTLE_ENDIAN - const word32 *X = data; -#else - word32 X[16]; - int i; -#endif - - word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; - a1 = a2 = digest[0]; - b1 = b2 = digest[1]; - c1 = c2 = digest[2]; - d1 = d2 = digest[3]; - e1 = e2 = digest[4]; - -#if BYTE_ORDER == BIG_ENDIAN - for (i = 0; i < 16; i++) - { - X[i] = LE32 (data[i]); - } -#endif - - Subround(F, a1, b1, c1, d1, e1, X[ 0], 11, k0); - Subround(F, e1, a1, b1, c1, d1, X[ 1], 14, k0); - Subround(F, d1, e1, a1, b1, c1, X[ 2], 15, k0); - Subround(F, c1, d1, e1, a1, b1, X[ 3], 12, k0); - Subround(F, b1, c1, d1, e1, a1, X[ 4], 5, k0); - Subround(F, a1, b1, c1, d1, e1, X[ 5], 8, k0); - Subround(F, e1, a1, b1, c1, d1, X[ 6], 7, k0); - Subround(F, d1, e1, a1, b1, c1, X[ 7], 9, k0); - Subround(F, c1, d1, e1, a1, b1, X[ 8], 11, k0); - Subround(F, b1, c1, d1, e1, a1, X[ 9], 13, k0); - Subround(F, a1, b1, c1, d1, e1, X[10], 14, k0); - Subround(F, e1, a1, b1, c1, d1, X[11], 15, k0); - Subround(F, d1, e1, a1, b1, c1, X[12], 6, k0); - Subround(F, c1, d1, e1, a1, b1, X[13], 7, k0); - Subround(F, b1, c1, d1, e1, a1, X[14], 9, k0); - Subround(F, a1, b1, c1, d1, e1, X[15], 8, k0); - - Subround(G, e1, a1, b1, c1, d1, X[ 7], 7, k1); - Subround(G, d1, e1, a1, b1, c1, X[ 4], 6, k1); - Subround(G, c1, d1, e1, a1, b1, X[13], 8, k1); - Subround(G, b1, c1, d1, e1, a1, X[ 1], 13, k1); - Subround(G, a1, b1, c1, d1, e1, X[10], 11, k1); - Subround(G, e1, a1, b1, c1, d1, X[ 6], 9, k1); - Subround(G, d1, e1, a1, b1, c1, X[15], 7, k1); - Subround(G, c1, d1, e1, a1, b1, X[ 3], 15, k1); - Subround(G, b1, c1, d1, e1, a1, X[12], 7, k1); - Subround(G, a1, b1, c1, d1, e1, X[ 0], 12, k1); - Subround(G, e1, a1, b1, c1, d1, X[ 9], 15, k1); - Subround(G, d1, e1, a1, b1, c1, X[ 5], 9, k1); - Subround(G, c1, d1, e1, a1, b1, X[ 2], 11, k1); - Subround(G, b1, c1, d1, e1, a1, X[14], 7, k1); - Subround(G, a1, b1, c1, d1, e1, X[11], 13, k1); - Subround(G, e1, a1, b1, c1, d1, X[ 8], 12, k1); - - Subround(H, d1, e1, a1, b1, c1, X[ 3], 11, k2); - Subround(H, c1, d1, e1, a1, b1, X[10], 13, k2); - Subround(H, b1, c1, d1, e1, a1, X[14], 6, k2); - Subround(H, a1, b1, c1, d1, e1, X[ 4], 7, k2); - Subround(H, e1, a1, b1, c1, d1, X[ 9], 14, k2); - Subround(H, d1, e1, a1, b1, c1, X[15], 9, k2); - Subround(H, c1, d1, e1, a1, b1, X[ 8], 13, k2); - Subround(H, b1, c1, d1, e1, a1, X[ 1], 15, k2); - Subround(H, a1, b1, c1, d1, e1, X[ 2], 14, k2); - Subround(H, e1, a1, b1, c1, d1, X[ 7], 8, k2); - Subround(H, d1, e1, a1, b1, c1, X[ 0], 13, k2); - Subround(H, c1, d1, e1, a1, b1, X[ 6], 6, k2); - Subround(H, b1, c1, d1, e1, a1, X[13], 5, k2); - Subround(H, a1, b1, c1, d1, e1, X[11], 12, k2); - Subround(H, e1, a1, b1, c1, d1, X[ 5], 7, k2); - Subround(H, d1, e1, a1, b1, c1, X[12], 5, k2); - - Subround(I, c1, d1, e1, a1, b1, X[ 1], 11, k3); - Subround(I, b1, c1, d1, e1, a1, X[ 9], 12, k3); - Subround(I, a1, b1, c1, d1, e1, X[11], 14, k3); - Subround(I, e1, a1, b1, c1, d1, X[10], 15, k3); - Subround(I, d1, e1, a1, b1, c1, X[ 0], 14, k3); - Subround(I, c1, d1, e1, a1, b1, X[ 8], 15, k3); - Subround(I, b1, c1, d1, e1, a1, X[12], 9, k3); - Subround(I, a1, b1, c1, d1, e1, X[ 4], 8, k3); - Subround(I, e1, a1, b1, c1, d1, X[13], 9, k3); - Subround(I, d1, e1, a1, b1, c1, X[ 3], 14, k3); - Subround(I, c1, d1, e1, a1, b1, X[ 7], 5, k3); - Subround(I, b1, c1, d1, e1, a1, X[15], 6, k3); - Subround(I, a1, b1, c1, d1, e1, X[14], 8, k3); - Subround(I, e1, a1, b1, c1, d1, X[ 5], 6, k3); - Subround(I, d1, e1, a1, b1, c1, X[ 6], 5, k3); - Subround(I, c1, d1, e1, a1, b1, X[ 2], 12, k3); - - Subround(J, b1, c1, d1, e1, a1, X[ 4], 9, k4); - Subround(J, a1, b1, c1, d1, e1, X[ 0], 15, k4); - Subround(J, e1, a1, b1, c1, d1, X[ 5], 5, k4); - Subround(J, d1, e1, a1, b1, c1, X[ 9], 11, k4); - Subround(J, c1, d1, e1, a1, b1, X[ 7], 6, k4); - Subround(J, b1, c1, d1, e1, a1, X[12], 8, k4); - Subround(J, a1, b1, c1, d1, e1, X[ 2], 13, k4); - Subround(J, e1, a1, b1, c1, d1, X[10], 12, k4); - Subround(J, d1, e1, a1, b1, c1, X[14], 5, k4); - Subround(J, c1, d1, e1, a1, b1, X[ 1], 12, k4); - Subround(J, b1, c1, d1, e1, a1, X[ 3], 13, k4); - Subround(J, a1, b1, c1, d1, e1, X[ 8], 14, k4); - Subround(J, e1, a1, b1, c1, d1, X[11], 11, k4); - Subround(J, d1, e1, a1, b1, c1, X[ 6], 8, k4); - Subround(J, c1, d1, e1, a1, b1, X[15], 5, k4); - Subround(J, b1, c1, d1, e1, a1, X[13], 6, k4); - - Subround(J, a2, b2, c2, d2, e2, X[ 5], 8, k5); - Subround(J, e2, a2, b2, c2, d2, X[14], 9, k5); - Subround(J, d2, e2, a2, b2, c2, X[ 7], 9, k5); - Subround(J, c2, d2, e2, a2, b2, X[ 0], 11, k5); - Subround(J, b2, c2, d2, e2, a2, X[ 9], 13, k5); - Subround(J, a2, b2, c2, d2, e2, X[ 2], 15, k5); - Subround(J, e2, a2, b2, c2, d2, X[11], 15, k5); - Subround(J, d2, e2, a2, b2, c2, X[ 4], 5, k5); - Subround(J, c2, d2, e2, a2, b2, X[13], 7, k5); - Subround(J, b2, c2, d2, e2, a2, X[ 6], 7, k5); - Subround(J, a2, b2, c2, d2, e2, X[15], 8, k5); - Subround(J, e2, a2, b2, c2, d2, X[ 8], 11, k5); - Subround(J, d2, e2, a2, b2, c2, X[ 1], 14, k5); - Subround(J, c2, d2, e2, a2, b2, X[10], 14, k5); - Subround(J, b2, c2, d2, e2, a2, X[ 3], 12, k5); - Subround(J, a2, b2, c2, d2, e2, X[12], 6, k5); - - Subround(I, e2, a2, b2, c2, d2, X[ 6], 9, k6); - Subround(I, d2, e2, a2, b2, c2, X[11], 13, k6); - Subround(I, c2, d2, e2, a2, b2, X[ 3], 15, k6); - Subround(I, b2, c2, d2, e2, a2, X[ 7], 7, k6); - Subround(I, a2, b2, c2, d2, e2, X[ 0], 12, k6); - Subround(I, e2, a2, b2, c2, d2, X[13], 8, k6); - Subround(I, d2, e2, a2, b2, c2, X[ 5], 9, k6); - Subround(I, c2, d2, e2, a2, b2, X[10], 11, k6); - Subround(I, b2, c2, d2, e2, a2, X[14], 7, k6); - Subround(I, a2, b2, c2, d2, e2, X[15], 7, k6); - Subround(I, e2, a2, b2, c2, d2, X[ 8], 12, k6); - Subround(I, d2, e2, a2, b2, c2, X[12], 7, k6); - Subround(I, c2, d2, e2, a2, b2, X[ 4], 6, k6); - Subround(I, b2, c2, d2, e2, a2, X[ 9], 15, k6); - Subround(I, a2, b2, c2, d2, e2, X[ 1], 13, k6); - Subround(I, e2, a2, b2, c2, d2, X[ 2], 11, k6); - - Subround(H, d2, e2, a2, b2, c2, X[15], 9, k7); - Subround(H, c2, d2, e2, a2, b2, X[ 5], 7, k7); - Subround(H, b2, c2, d2, e2, a2, X[ 1], 15, k7); - Subround(H, a2, b2, c2, d2, e2, X[ 3], 11, k7); - Subround(H, e2, a2, b2, c2, d2, X[ 7], 8, k7); - Subround(H, d2, e2, a2, b2, c2, X[14], 6, k7); - Subround(H, c2, d2, e2, a2, b2, X[ 6], 6, k7); - Subround(H, b2, c2, d2, e2, a2, X[ 9], 14, k7); - Subround(H, a2, b2, c2, d2, e2, X[11], 12, k7); - Subround(H, e2, a2, b2, c2, d2, X[ 8], 13, k7); - Subround(H, d2, e2, a2, b2, c2, X[12], 5, k7); - Subround(H, c2, d2, e2, a2, b2, X[ 2], 14, k7); - Subround(H, b2, c2, d2, e2, a2, X[10], 13, k7); - Subround(H, a2, b2, c2, d2, e2, X[ 0], 13, k7); - Subround(H, e2, a2, b2, c2, d2, X[ 4], 7, k7); - Subround(H, d2, e2, a2, b2, c2, X[13], 5, k7); - - Subround(G, c2, d2, e2, a2, b2, X[ 8], 15, k8); - Subround(G, b2, c2, d2, e2, a2, X[ 6], 5, k8); - Subround(G, a2, b2, c2, d2, e2, X[ 4], 8, k8); - Subround(G, e2, a2, b2, c2, d2, X[ 1], 11, k8); - Subround(G, d2, e2, a2, b2, c2, X[ 3], 14, k8); - Subround(G, c2, d2, e2, a2, b2, X[11], 14, k8); - Subround(G, b2, c2, d2, e2, a2, X[15], 6, k8); - Subround(G, a2, b2, c2, d2, e2, X[ 0], 14, k8); - Subround(G, e2, a2, b2, c2, d2, X[ 5], 6, k8); - Subround(G, d2, e2, a2, b2, c2, X[12], 9, k8); - Subround(G, c2, d2, e2, a2, b2, X[ 2], 12, k8); - Subround(G, b2, c2, d2, e2, a2, X[13], 9, k8); - Subround(G, a2, b2, c2, d2, e2, X[ 9], 12, k8); - Subround(G, e2, a2, b2, c2, d2, X[ 7], 5, k8); - Subround(G, d2, e2, a2, b2, c2, X[10], 15, k8); - Subround(G, c2, d2, e2, a2, b2, X[14], 8, k8); - - Subround(F, b2, c2, d2, e2, a2, X[12], 8, k9); - Subround(F, a2, b2, c2, d2, e2, X[15], 5, k9); - Subround(F, e2, a2, b2, c2, d2, X[10], 12, k9); - Subround(F, d2, e2, a2, b2, c2, X[ 4], 9, k9); - Subround(F, c2, d2, e2, a2, b2, X[ 1], 12, k9); - Subround(F, b2, c2, d2, e2, a2, X[ 5], 5, k9); - Subround(F, a2, b2, c2, d2, e2, X[ 8], 14, k9); - Subround(F, e2, a2, b2, c2, d2, X[ 7], 6, k9); - Subround(F, d2, e2, a2, b2, c2, X[ 6], 8, k9); - Subround(F, c2, d2, e2, a2, b2, X[ 2], 13, k9); - Subround(F, b2, c2, d2, e2, a2, X[13], 6, k9); - Subround(F, a2, b2, c2, d2, e2, X[14], 5, k9); - Subround(F, e2, a2, b2, c2, d2, X[ 0], 15, k9); - Subround(F, d2, e2, a2, b2, c2, X[ 3], 13, k9); - Subround(F, c2, d2, e2, a2, b2, X[ 9], 11, k9); - Subround(F, b2, c2, d2, e2, a2, X[11], 11, k9); - - c1 = digest[1] + c1 + d2; - digest[1] = digest[2] + d1 + e2; - digest[2] = digest[3] + e1 + a2; - digest[3] = digest[4] + a1 + b2; - digest[4] = digest[0] + b1 + c2; - digest[0] = c1; -} - -#else // TC_MINIMIZE_CODE_SIZE - -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#pragma optimize ("tl", on) - -typedef unsigned __int32 uint32; -typedef unsigned __int8 byte; - -#include -#pragma intrinsic (_lrotl) - -static const byte OrderTab[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 -}; - -static const byte RolTab[] = { - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 -}; - -static const uint32 KTab[] = { - 0x00000000UL, - 0x5A827999UL, - 0x6ED9EBA1UL, - 0x8F1BBCDCUL, - 0xA953FD4EUL, - 0x50A28BE6UL, - 0x5C4DD124UL, - 0x6D703EF3UL, - 0x7A6D76E9UL, - 0x00000000UL -}; - - -void RMD160Transform (unsigned __int32 *state, const unsigned __int32 *data) -{ - uint32 a, b, c, d, e; - uint32 a2, b2, c2, d2, e2; - byte pos; - uint32 tmp; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - - for (pos = 0; pos < 160; ++pos) - { - tmp = a + data[OrderTab[pos]] + KTab[pos >> 4]; - - switch (pos >> 4) - { - case 0: case 9: tmp += F (b, c, d); break; - case 1: case 8: tmp += G (b, c, d); break; - case 2: case 7: tmp += H (b, c, d); break; - case 3: case 6: tmp += I (b, c, d); break; - case 4: case 5: tmp += J (b, c, d); break; - } - - tmp = _lrotl (tmp, RolTab[pos]) + e; - a = e; - e = d; - d = _lrotl (c, 10); - c = b; - b = tmp; - - if (pos == 79) - { - a2 = a; - b2 = b; - c2 = c; - d2 = d; - e2 = e; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - } - } - - tmp = state[1] + c2 + d; - state[1] = state[2] + d2 + e; - state[2] = state[3] + e2 + a; - state[3] = state[4] + a2 + b; - state[4] = state[0] + b2 + c; - state[0] = tmp; -} - -#endif // TC_MINIMIZE_CODE_SIZE +// RIPEMD-160 written and placed in the public domain by Wei Dai + +/* + * This code implements the MD4 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + */ + +/* Adapted by TrueCrypt Foundation */ + +#include +#include "Common/Tcdefs.h" +#include "Common/Endian.h" +#include "Rmd160.h" + +#define F(x, y, z) (x ^ y ^ z) +#define G(x, y, z) (z ^ (x & (y^z))) +#define H(x, y, z) (z ^ (x | ~y)) +#define I(x, y, z) (y ^ (z & (x^y))) +#define J(x, y, z) (x ^ (y | ~z)) + +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (byte) ((value) >> 56); \ + (cp)[6] = (byte) ((value) >> 48); \ + (cp)[5] = (byte) ((value) >> 40); \ + (cp)[4] = (byte) ((value) >> 32); \ + (cp)[3] = (byte) ((value) >> 24); \ + (cp)[2] = (byte) ((value) >> 16); \ + (cp)[1] = (byte) ((value) >> 8); \ + (cp)[0] = (byte) (value); } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (byte) ((value) >> 24); \ + (cp)[2] = (byte) ((value) >> 16); \ + (cp)[1] = (byte) ((value) >> 8); \ + (cp)[0] = (byte) (value); } while (0) + +#ifndef TC_MINIMIZE_CODE_SIZE + +static byte PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#else + +static byte PADDING[64]; + +#endif + +void RMD160Init (RMD160_CTX *ctx) +{ + ctx->count = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xefcdab89; + ctx->state[2] = 0x98badcfe; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xc3d2e1f0; + PADDING[0] = 0x80; +} + +/* +* Update context to reflect the concatenation of another buffer full +* of bytes. +*/ +void RMD160Update (RMD160_CTX *ctx, const unsigned char *input, unsigned __int32 lenArg) +{ +#ifndef TC_WINDOWS_BOOT + uint64 len = lenArg, have, need; +#else + uint16 len = (uint16) lenArg, have, need; +#endif + + /* Check how many bytes we already have and how many more we need. */ + have = ((ctx->count >> 3) & (RIPEMD160_BLOCK_LENGTH - 1)); + need = RIPEMD160_BLOCK_LENGTH - have; + + /* Update bitcount */ + ctx->count += len << 3; + + if (len >= need) { + if (have != 0) { + memcpy (ctx->buffer + have, input, (size_t) need); + RMD160Transform ((uint32 *) ctx->state, (const uint32 *) ctx->buffer); + input += need; + len -= need; + have = 0; + } + + /* Process data in RIPEMD160_BLOCK_LENGTH-byte chunks. */ + while (len >= RIPEMD160_BLOCK_LENGTH) { + RMD160Transform ((uint32 *) ctx->state, (const uint32 *) input); + input += RIPEMD160_BLOCK_LENGTH; + len -= RIPEMD160_BLOCK_LENGTH; + } + } + + /* Handle any remaining bytes of data. */ + if (len != 0) + memcpy (ctx->buffer + have, input, (size_t) len); +} + +/* +* Pad pad to 64-byte boundary with the bit pattern +* 1 0* (64-bit count of bits processed, MSB-first) +*/ +static void RMD160Pad(RMD160_CTX *ctx) +{ + byte count[8]; + uint32 padlen; + + /* Convert count to 8 bytes in little endian order. */ + +#ifndef TC_WINDOWS_BOOT + PUT_64BIT_LE(count, ctx->count); +#else + *(uint32 *) (count + 4) = 0; + *(uint16 *) (count + 2) = 0; + *(uint16 *) (count + 0) = ctx->count; +#endif + + /* Pad out to 56 mod 64. */ + padlen = RIPEMD160_BLOCK_LENGTH - + (uint32)((ctx->count >> 3) & (RIPEMD160_BLOCK_LENGTH - 1)); + if (padlen < 1 + 8) + padlen += RIPEMD160_BLOCK_LENGTH; + RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + RMD160Update(ctx, count, 8); +} + +/* +* Final wrapup--call RMD160Pad, fill in digest and zero out ctx. +*/ +void RMD160Final(unsigned char *digest, RMD160_CTX *ctx) +{ + int i; + + RMD160Pad(ctx); + if (digest) { + for (i = 0; i < 5; i++) + PUT_32BIT_LE(digest + i * 4, ctx->state[i]); + memset (ctx, 0, sizeof(*ctx)); + } +} + + +#ifndef TC_MINIMIZE_CODE_SIZE + +#define word32 unsigned __int32 + +#define k0 0 +#define k1 0x5a827999UL +#define k2 0x6ed9eba1UL +#define k3 0x8f1bbcdcUL +#define k4 0xa953fd4eUL +#define k5 0x50a28be6UL +#define k6 0x5c4dd124UL +#define k7 0x6d703ef3UL +#define k8 0x7a6d76e9UL +#define k9 0 + +static word32 rotlFixed (word32 x, unsigned int y) +{ + return (word32)((x<>(sizeof(word32)*8-y))); +} + +#define Subround(f, a, b, c, d, e, x, s, k) \ + a += f(b, c, d) + x + k;\ + a = rotlFixed((word32)a, s) + e;\ + c = rotlFixed((word32)c, 10U) + +void RMD160Transform (unsigned __int32 *digest, const unsigned __int32 *data) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + const word32 *X = data; +#else + word32 X[16]; + int i; +#endif + + word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; + a1 = a2 = digest[0]; + b1 = b2 = digest[1]; + c1 = c2 = digest[2]; + d1 = d2 = digest[3]; + e1 = e2 = digest[4]; + +#if BYTE_ORDER == BIG_ENDIAN + for (i = 0; i < 16; i++) + { + X[i] = LE32 (data[i]); + } +#endif + + Subround(F, a1, b1, c1, d1, e1, X[ 0], 11, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 1], 14, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 2], 15, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 3], 12, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 4], 5, k0); + Subround(F, a1, b1, c1, d1, e1, X[ 5], 8, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 6], 7, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 7], 9, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 8], 11, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 9], 13, k0); + Subround(F, a1, b1, c1, d1, e1, X[10], 14, k0); + Subround(F, e1, a1, b1, c1, d1, X[11], 15, k0); + Subround(F, d1, e1, a1, b1, c1, X[12], 6, k0); + Subround(F, c1, d1, e1, a1, b1, X[13], 7, k0); + Subround(F, b1, c1, d1, e1, a1, X[14], 9, k0); + Subround(F, a1, b1, c1, d1, e1, X[15], 8, k0); + + Subround(G, e1, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, e1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, e1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, e1, X[10], 11, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 6], 9, k1); + Subround(G, d1, e1, a1, b1, c1, X[15], 7, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 3], 15, k1); + Subround(G, b1, c1, d1, e1, a1, X[12], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[ 0], 12, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 9], 15, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 5], 9, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 2], 11, k1); + Subround(G, b1, c1, d1, e1, a1, X[14], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[11], 13, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 8], 12, k1); + + Subround(H, d1, e1, a1, b1, c1, X[ 3], 11, k2); + Subround(H, c1, d1, e1, a1, b1, X[10], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[14], 6, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 4], 7, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, e1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 2], 14, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 7], 8, k2); + Subround(H, d1, e1, a1, b1, c1, X[ 0], 13, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 6], 6, k2); + Subround(H, b1, c1, d1, e1, a1, X[13], 5, k2); + Subround(H, a1, b1, c1, d1, e1, X[11], 12, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 5], 7, k2); + Subround(H, d1, e1, a1, b1, c1, X[12], 5, k2); + + Subround(I, c1, d1, e1, a1, b1, X[ 1], 11, k3); + Subround(I, b1, c1, d1, e1, a1, X[ 9], 12, k3); + Subround(I, a1, b1, c1, d1, e1, X[11], 14, k3); + Subround(I, e1, a1, b1, c1, d1, X[10], 15, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 0], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 8], 15, k3); + Subround(I, b1, c1, d1, e1, a1, X[12], 9, k3); + Subround(I, a1, b1, c1, d1, e1, X[ 4], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, e1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, e1, X[14], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[ 5], 6, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 6], 5, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 2], 12, k3); + + Subround(J, b1, c1, d1, e1, a1, X[ 4], 9, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 0], 15, k4); + Subround(J, e1, a1, b1, c1, d1, X[ 5], 5, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 9], 11, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 7], 6, k4); + Subround(J, b1, c1, d1, e1, a1, X[12], 8, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 2], 13, k4); + Subround(J, e1, a1, b1, c1, d1, X[10], 12, k4); + Subround(J, d1, e1, a1, b1, c1, X[14], 5, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 1], 12, k4); + Subround(J, b1, c1, d1, e1, a1, X[ 3], 13, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 8], 14, k4); + Subround(J, e1, a1, b1, c1, d1, X[11], 11, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 6], 8, k4); + Subround(J, c1, d1, e1, a1, b1, X[15], 5, k4); + Subround(J, b1, c1, d1, e1, a1, X[13], 6, k4); + + Subround(J, a2, b2, c2, d2, e2, X[ 5], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[14], 9, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 7], 9, k5); + Subround(J, c2, d2, e2, a2, b2, X[ 0], 11, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 9], 13, k5); + Subround(J, a2, b2, c2, d2, e2, X[ 2], 15, k5); + Subround(J, e2, a2, b2, c2, d2, X[11], 15, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 4], 5, k5); + Subround(J, c2, d2, e2, a2, b2, X[13], 7, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 6], 7, k5); + Subround(J, a2, b2, c2, d2, e2, X[15], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[ 8], 11, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 1], 14, k5); + Subround(J, c2, d2, e2, a2, b2, X[10], 14, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 3], 12, k5); + Subround(J, a2, b2, c2, d2, e2, X[12], 6, k5); + + Subround(I, e2, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(I, d2, e2, a2, b2, c2, X[11], 13, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 3], 15, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 7], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 0], 12, k6); + Subround(I, e2, a2, b2, c2, d2, X[13], 8, k6); + Subround(I, d2, e2, a2, b2, c2, X[ 5], 9, k6); + Subround(I, c2, d2, e2, a2, b2, X[10], 11, k6); + Subround(I, b2, c2, d2, e2, a2, X[14], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[15], 7, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 8], 12, k6); + Subround(I, d2, e2, a2, b2, c2, X[12], 7, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 4], 6, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 9], 15, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 1], 13, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 2], 11, k6); + + Subround(H, d2, e2, a2, b2, c2, X[15], 9, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 5], 7, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 1], 15, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 3], 11, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(H, d2, e2, a2, b2, c2, X[14], 6, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 6], 6, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 9], 14, k7); + Subround(H, a2, b2, c2, d2, e2, X[11], 12, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 8], 13, k7); + Subround(H, d2, e2, a2, b2, c2, X[12], 5, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 2], 14, k7); + Subround(H, b2, c2, d2, e2, a2, X[10], 13, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 0], 13, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 4], 7, k7); + Subround(H, d2, e2, a2, b2, c2, X[13], 5, k7); + + Subround(G, c2, d2, e2, a2, b2, X[ 8], 15, k8); + Subround(G, b2, c2, d2, e2, a2, X[ 6], 5, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 4], 8, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 1], 11, k8); + Subround(G, d2, e2, a2, b2, c2, X[ 3], 14, k8); + Subround(G, c2, d2, e2, a2, b2, X[11], 14, k8); + Subround(G, b2, c2, d2, e2, a2, X[15], 6, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 0], 14, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 5], 6, k8); + Subround(G, d2, e2, a2, b2, c2, X[12], 9, k8); + Subround(G, c2, d2, e2, a2, b2, X[ 2], 12, k8); + Subround(G, b2, c2, d2, e2, a2, X[13], 9, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 9], 12, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 7], 5, k8); + Subround(G, d2, e2, a2, b2, c2, X[10], 15, k8); + Subround(G, c2, d2, e2, a2, b2, X[14], 8, k8); + + Subround(F, b2, c2, d2, e2, a2, X[12], 8, k9); + Subround(F, a2, b2, c2, d2, e2, X[15], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[10], 12, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 4], 9, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 1], 12, k9); + Subround(F, b2, c2, d2, e2, a2, X[ 5], 5, k9); + Subround(F, a2, b2, c2, d2, e2, X[ 8], 14, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 7], 6, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 6], 8, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 2], 13, k9); + Subround(F, b2, c2, d2, e2, a2, X[13], 6, k9); + Subround(F, a2, b2, c2, d2, e2, X[14], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 0], 15, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 3], 13, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 9], 11, k9); + Subround(F, b2, c2, d2, e2, a2, X[11], 11, k9); + + c1 = digest[1] + c1 + d2; + digest[1] = digest[2] + d1 + e2; + digest[2] = digest[3] + e1 + a2; + digest[3] = digest[4] + a1 + b2; + digest[4] = digest[0] + b1 + c2; + digest[0] = c1; +} + +#else // TC_MINIMIZE_CODE_SIZE + +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#pragma optimize ("tl", on) + +typedef unsigned __int32 uint32; +typedef unsigned __int8 byte; + +#include +#pragma intrinsic (_lrotl) + +static const byte OrderTab[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +}; + +static const byte RolTab[] = { + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +}; + +static const uint32 KTab[] = { + 0x00000000UL, + 0x5A827999UL, + 0x6ED9EBA1UL, + 0x8F1BBCDCUL, + 0xA953FD4EUL, + 0x50A28BE6UL, + 0x5C4DD124UL, + 0x6D703EF3UL, + 0x7A6D76E9UL, + 0x00000000UL +}; + + +void RMD160Transform (unsigned __int32 *state, const unsigned __int32 *data) +{ + uint32 a, b, c, d, e; + uint32 a2, b2, c2, d2, e2; + byte pos; + uint32 tmp; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + for (pos = 0; pos < 160; ++pos) + { + tmp = a + data[OrderTab[pos]] + KTab[pos >> 4]; + + switch (pos >> 4) + { + case 0: case 9: tmp += F (b, c, d); break; + case 1: case 8: tmp += G (b, c, d); break; + case 2: case 7: tmp += H (b, c, d); break; + case 3: case 6: tmp += I (b, c, d); break; + case 4: case 5: tmp += J (b, c, d); break; + } + + tmp = _lrotl (tmp, RolTab[pos]) + e; + a = e; + e = d; + d = _lrotl (c, 10); + c = b; + b = tmp; + + if (pos == 79) + { + a2 = a; + b2 = b; + c2 = c; + d2 = d; + e2 = e; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + } + } + + tmp = state[1] + c2 + d; + state[1] = state[2] + d2 + e; + state[2] = state[3] + e2 + a; + state[3] = state[4] + a2 + b; + state[4] = state[0] + b2 + c; + state[0] = tmp; +} + +#endif // TC_MINIMIZE_CODE_SIZE diff --git a/Crypto/Rmd160.h b/Crypto/Rmd160.h index 6793864..4bdd794 100644 --- a/Crypto/Rmd160.h +++ b/Crypto/Rmd160.h @@ -1,33 +1,33 @@ -#ifndef TC_HEADER_Crypto_Ripemd160 -#define TC_HEADER_Crypto_Ripemd160 - -#include "Common/Tcdefs.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define RIPEMD160_BLOCK_LENGTH 64 - -typedef struct RMD160Context -{ - unsigned __int32 state[5]; -#ifndef TC_NO_COMPILER_INT64 - uint64 count; -#else - unsigned __int32 count; -#endif - unsigned char buffer[RIPEMD160_BLOCK_LENGTH]; -} RMD160_CTX; - -void RMD160Init (RMD160_CTX *ctx); -void RMD160Transform (unsigned __int32 *state, const unsigned __int32 *data); -void RMD160Update (RMD160_CTX *ctx, const unsigned char *input, unsigned __int32 len); -void RMD160Final (unsigned char *digest, RMD160_CTX *ctx); - -#if defined(__cplusplus) -} -#endif - -#endif // TC_HEADER_Crypto_Ripemd160 +#ifndef TC_HEADER_Crypto_Ripemd160 +#define TC_HEADER_Crypto_Ripemd160 + +#include "Common/Tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define RIPEMD160_BLOCK_LENGTH 64 + +typedef struct RMD160Context +{ + unsigned __int32 state[5]; +#ifndef TC_WINDOWS_BOOT + uint64 count; +#else + uint16 count; +#endif + unsigned char buffer[RIPEMD160_BLOCK_LENGTH]; +} RMD160_CTX; + +void RMD160Init (RMD160_CTX *ctx); +void RMD160Transform (unsigned __int32 *state, const unsigned __int32 *data); +void RMD160Update (RMD160_CTX *ctx, const unsigned char *input, unsigned __int32 len); +void RMD160Final (unsigned char *digest, RMD160_CTX *ctx); + +#if defined(__cplusplus) +} +#endif + +#endif // TC_HEADER_Crypto_Ripemd160 diff --git a/Crypto/SHA1.C b/Crypto/SHA1.C index 5901473..7579439 100644 --- a/Crypto/SHA1.C +++ b/Crypto/SHA1.C @@ -1,282 +1,282 @@ -/* Deprecated/legacy */ - -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 18/06/2004 - - This is a byte oriented version of SHA1 that operates on arrays of bytes - stored in memory. -*/ - -/* Adapted for TrueCrypt by the TrueCrypt Foundation */ - -#include /* for memcpy() etc. */ -#include /* for _lrotl with VC++ */ - -#include "Sha1.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* - To obtain the highest speed on processors with 32-bit words, this code - needs to determine the order in which bytes are packed into such words. - The following block of code is an attempt to capture the most obvious - ways in which various environemnts specify their endian definitions. - It may well fail, in which case the definitions will need to be set by - editing at the points marked **** EDIT HERE IF NECESSARY **** below. -*/ - -/* PLATFORM SPECIFIC INCLUDES */ - -/* Original byte order detection removed */ -#include "../Common/Endian.h" - -#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ -#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ - -#if BYTE_ORDER == LITTLE_ENDIAN -# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN -#endif - -#if BYTE_ORDER == BIG_ENDIAN -# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN -#endif - -#ifdef _MSC_VER -#pragma intrinsic(memcpy) -#endif - -#if 1 && defined(_MSC_VER) && !defined(_DEBUG) -#define rotl32 _rotl -#define rotr32 _rotr -#else -#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) -#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) -#endif - -#if !defined(bswap_32) -#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) -#endif - -#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) -#define SWAP_BYTES -#else -#undef SWAP_BYTES -#endif - -#if defined(SWAP_BYTES) -#define bsw_32(p,n) \ - { int _i = (n); while(_i--) ((sha1_32t*)p)[_i] = bswap_32(((sha1_32t*)p)[_i]); } -#else -#define bsw_32(p,n) -#endif - -#define SHA1_MASK (SHA1_BLOCK_SIZE - 1) - -#if 0 - -#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define parity(x,y,z) ((x) ^ (y) ^ (z)) -#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -#else /* Discovered by Rich Schroeppel and Colin Plumb */ - -#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define parity(x,y,z) ((x) ^ (y) ^ (z)) -#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) - -#endif - -/* Compile 64 bytes of hash data into SHA1 context. Note */ -/* that this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is in such an order that low */ -/* address bytes in the ORIGINAL byte stream will go in */ -/* this buffer to the high end of 32-bit words on BOTH big */ -/* and little endian systems */ - -#ifdef ARRAY -#define q(v,n) v[n] -#else -#define q(v,n) v##n -#endif - -#define one_cycle(v,a,b,c,d,e,f,k,h) \ - q(v,e) += rotr32(q(v,a),27) + \ - f(q(v,b),q(v,c),q(v,d)) + k + h; \ - q(v,b) = rotr32(q(v,b), 2) - -#define five_cycle(v,f,k,i) \ - one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \ - one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \ - one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \ - one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \ - one_cycle(v, 1,2,3,4,0, f,k,hf(i+4)) - -void sha1_compile(sha1_ctx ctx[1]) -{ sha1_32t *w = ctx->wbuf; - -#ifdef ARRAY - sha1_32t v[5]; - memcpy(v, ctx->hash, 5 * sizeof(sha1_32t)); -#else - sha1_32t v0, v1, v2, v3, v4; - v0 = ctx->hash[0]; v1 = ctx->hash[1]; - v2 = ctx->hash[2]; v3 = ctx->hash[3]; - v4 = ctx->hash[4]; -#endif - -#define hf(i) w[i] - - five_cycle(v, ch, 0x5a827999, 0); - five_cycle(v, ch, 0x5a827999, 5); - five_cycle(v, ch, 0x5a827999, 10); - one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \ - -#undef hf -#define hf(i) (w[(i) & 15] = rotl32( \ - w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \ - ^ w[((i) + 2) & 15] ^ w[(i) & 15], 1)) - - one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16)); - one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17)); - one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18)); - one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19)); - - five_cycle(v, parity, 0x6ed9eba1, 20); - five_cycle(v, parity, 0x6ed9eba1, 25); - five_cycle(v, parity, 0x6ed9eba1, 30); - five_cycle(v, parity, 0x6ed9eba1, 35); - - five_cycle(v, maj, 0x8f1bbcdc, 40); - five_cycle(v, maj, 0x8f1bbcdc, 45); - five_cycle(v, maj, 0x8f1bbcdc, 50); - five_cycle(v, maj, 0x8f1bbcdc, 55); - - five_cycle(v, parity, 0xca62c1d6, 60); - five_cycle(v, parity, 0xca62c1d6, 65); - five_cycle(v, parity, 0xca62c1d6, 70); - five_cycle(v, parity, 0xca62c1d6, 75); - -#ifdef ARRAY - ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; - ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; - ctx->hash[4] += v[4]; -#else - ctx->hash[0] += v0; ctx->hash[1] += v1; - ctx->hash[2] += v2; ctx->hash[3] += v3; - ctx->hash[4] += v4; -#endif -} - -void sha1_begin(sha1_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - ctx->hash[0] = 0x67452301; - ctx->hash[1] = 0xefcdab89; - ctx->hash[2] = 0x98badcfe; - ctx->hash[3] = 0x10325476; - ctx->hash[4] = 0xc3d2e1f0; -} - -/* SHA1 hash data in an array of bytes into hash buffer and */ -/* call the hash_compile function as required. */ - -void sha1_hash(const unsigned char data[], unsigned __int32 len, sha1_ctx ctx[1]) -{ sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK), - space = SHA1_BLOCK_SIZE - pos; - const unsigned char *sp = data; - - if((ctx->count[0] += len) < len) - ++(ctx->count[1]); - - while(len >= space) /* tranfer whole blocks if possible */ - { - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); - sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0; - bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2); - sha1_compile(ctx); - } - - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); -} - -/* SHA1 final padding and digest calculation */ - -void sha1_end(unsigned char hval[], sha1_ctx ctx[1]) -{ sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK); - - /* put bytes in the buffer in an order in which references to */ - /* 32-bit words will put bytes with lower addresses into the */ - /* top of 32 bit words on BOTH big and little endian machines */ - bsw_32(ctx->wbuf, (i + 3) >> 2); - - /* we now need to mask valid bytes and add the padding which is */ - /* a single 1 bit and as many zero bits as necessary. Note that */ - /* we can always add the first padding byte here because the */ - /* buffer always has at least one empty slot */ - ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); - ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); - - /* we need 9 or more empty positions, one for the padding byte */ - /* (above) and eight for the length count. If there is not */ - /* enough space, pad and empty the buffer */ - if(i > SHA1_BLOCK_SIZE - 9) - { - if(i < 60) ctx->wbuf[15] = 0; - sha1_compile(ctx); - i = 0; - } - else /* compute a word index for the empty buffer positions */ - i = (i >> 2) + 1; - - while(i < 14) /* and zero pad all but last two positions */ - ctx->wbuf[i++] = 0; - - /* the following 32-bit length fields are assembled in the */ - /* wrong byte order on little endian machines but this is */ - /* corrected later since they are only ever used as 32-bit */ - /* word values. */ - ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); - ctx->wbuf[15] = ctx->count[0] << 3; - sha1_compile(ctx); - - /* extract the hash value as bytes in case the hash buffer is */ - /* misaligned for 32-bit words */ - for(i = 0; i < SHA1_DIGEST_SIZE; ++i) - hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); -} - -void sha1(unsigned char hval[], const unsigned char data[], unsigned __int32 len) -{ sha1_ctx cx[1]; - - sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); -} - -#if defined(__cplusplus) -} -#endif +/* Deprecated/legacy */ + +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 18/06/2004 + + This is a byte oriented version of SHA1 that operates on arrays of bytes + stored in memory. +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#include /* for memcpy() etc. */ +#include /* for _lrotl with VC++ */ + +#include "Sha1.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* + To obtain the highest speed on processors with 32-bit words, this code + needs to determine the order in which bytes are packed into such words. + The following block of code is an attempt to capture the most obvious + ways in which various environemnts specify their endian definitions. + It may well fail, in which case the definitions will need to be set by + editing at the points marked **** EDIT HERE IF NECESSARY **** below. +*/ + +/* PLATFORM SPECIFIC INCLUDES */ + +/* Original byte order detection removed */ +#include "../Common/Endian.h" + +#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN +#endif + +#if BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN +#endif + +#ifdef _MSC_VER +#pragma intrinsic(memcpy) +#endif + +#if 1 && defined(_MSC_VER) && !defined(_DEBUG) +#define rotl32 _rotl +#define rotr32 _rotr +#else +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) +#endif + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#if defined(SWAP_BYTES) +#define bsw_32(p,n) \ + { int _i = (n); while(_i--) ((sha1_32t*)p)[_i] = bswap_32(((sha1_32t*)p)[_i]); } +#else +#define bsw_32(p,n) +#endif + +#define SHA1_MASK (SHA1_BLOCK_SIZE - 1) + +#if 0 + +#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#else /* Discovered by Rich Schroeppel and Colin Plumb */ + +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) + +#endif + +/* Compile 64 bytes of hash data into SHA1 context. Note */ +/* that this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is in such an order that low */ +/* address bytes in the ORIGINAL byte stream will go in */ +/* this buffer to the high end of 32-bit words on BOTH big */ +/* and little endian systems */ + +#ifdef ARRAY +#define q(v,n) v[n] +#else +#define q(v,n) v##n +#endif + +#define one_cycle(v,a,b,c,d,e,f,k,h) \ + q(v,e) += rotr32(q(v,a),27) + \ + f(q(v,b),q(v,c),q(v,d)) + k + h; \ + q(v,b) = rotr32(q(v,b), 2) + +#define five_cycle(v,f,k,i) \ + one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \ + one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \ + one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \ + one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \ + one_cycle(v, 1,2,3,4,0, f,k,hf(i+4)) + +void sha1_compile(sha1_ctx ctx[1]) +{ sha1_32t *w = ctx->wbuf; + +#ifdef ARRAY + sha1_32t v[5]; + memcpy(v, ctx->hash, 5 * sizeof(sha1_32t)); +#else + sha1_32t v0, v1, v2, v3, v4; + v0 = ctx->hash[0]; v1 = ctx->hash[1]; + v2 = ctx->hash[2]; v3 = ctx->hash[3]; + v4 = ctx->hash[4]; +#endif + +#define hf(i) w[i] + + five_cycle(v, ch, 0x5a827999, 0); + five_cycle(v, ch, 0x5a827999, 5); + five_cycle(v, ch, 0x5a827999, 10); + one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \ + +#undef hf +#define hf(i) (w[(i) & 15] = rotl32( \ + w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \ + ^ w[((i) + 2) & 15] ^ w[(i) & 15], 1)) + + one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16)); + one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17)); + one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18)); + one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19)); + + five_cycle(v, parity, 0x6ed9eba1, 20); + five_cycle(v, parity, 0x6ed9eba1, 25); + five_cycle(v, parity, 0x6ed9eba1, 30); + five_cycle(v, parity, 0x6ed9eba1, 35); + + five_cycle(v, maj, 0x8f1bbcdc, 40); + five_cycle(v, maj, 0x8f1bbcdc, 45); + five_cycle(v, maj, 0x8f1bbcdc, 50); + five_cycle(v, maj, 0x8f1bbcdc, 55); + + five_cycle(v, parity, 0xca62c1d6, 60); + five_cycle(v, parity, 0xca62c1d6, 65); + five_cycle(v, parity, 0xca62c1d6, 70); + five_cycle(v, parity, 0xca62c1d6, 75); + +#ifdef ARRAY + ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; + ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; + ctx->hash[4] += v[4]; +#else + ctx->hash[0] += v0; ctx->hash[1] += v1; + ctx->hash[2] += v2; ctx->hash[3] += v3; + ctx->hash[4] += v4; +#endif +} + +void sha1_begin(sha1_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; + ctx->hash[4] = 0xc3d2e1f0; +} + +/* SHA1 hash data in an array of bytes into hash buffer and */ +/* call the hash_compile function as required. */ + +void sha1_hash(const unsigned char data[], unsigned __int32 len, sha1_ctx ctx[1]) +{ sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK), + space = SHA1_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks if possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0; + bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2); + sha1_compile(ctx); + } + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA1 final padding and digest calculation */ + +void sha1_end(unsigned char hval[], sha1_ctx ctx[1]) +{ sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK); + + /* put bytes in the buffer in an order in which references to */ + /* 32-bit words will put bytes with lower addresses into the */ + /* top of 32 bit words on BOTH big and little endian machines */ + bsw_32(ctx->wbuf, (i + 3) >> 2); + + /* we now need to mask valid bytes and add the padding which is */ + /* a single 1 bit and as many zero bits as necessary. Note that */ + /* we can always add the first padding byte here because the */ + /* buffer always has at least one empty slot */ + ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); + ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); + + /* we need 9 or more empty positions, one for the padding byte */ + /* (above) and eight for the length count. If there is not */ + /* enough space, pad and empty the buffer */ + if(i > SHA1_BLOCK_SIZE - 9) + { + if(i < 60) ctx->wbuf[15] = 0; + sha1_compile(ctx); + i = 0; + } + else /* compute a word index for the empty buffer positions */ + i = (i >> 2) + 1; + + while(i < 14) /* and zero pad all but last two positions */ + ctx->wbuf[i++] = 0; + + /* the following 32-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 32-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); + ctx->wbuf[15] = ctx->count[0] << 3; + sha1_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* misaligned for 32-bit words */ + for(i = 0; i < SHA1_DIGEST_SIZE; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); +} + +void sha1(unsigned char hval[], const unsigned char data[], unsigned __int32 len) +{ sha1_ctx cx[1]; + + sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); +} + +#if defined(__cplusplus) +} +#endif diff --git a/Crypto/SHA1.H b/Crypto/SHA1.H index 34a839c..130a1a4 100644 --- a/Crypto/SHA1.H +++ b/Crypto/SHA1.H @@ -1,80 +1,80 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 26/08/2003 -*/ - -#ifndef _SHA1_H -#define _SHA1_H - -#include -#include "Common/Tcdefs.h" - -#define SHA1_BLOCK_SIZE 64 -#define SHA1_DIGEST_SIZE 20 - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* define an unsigned 32-bit type */ - -#if defined(_MSC_VER) - typedef unsigned __int32 sha1_32t; -#elif defined(ULONG_MAX) && ULONG_MAX == 0xfffffffful - typedef unsigned __int32 sha1_32t; -#elif defined(UINT_MAX) && UINT_MAX == 0xffffffff - typedef unsigned int sha1_32t; -#else -# error Please define sha1_32t as an unsigned 32 bit type in sha1.h -#endif - -/* type to hold the SHA256 context */ - -typedef struct -{ sha1_32t count[2]; - sha1_32t hash[5]; - sha1_32t wbuf[16]; -} sha1_ctx; - -/* Note that these prototypes are the same for both bit and */ -/* byte oriented implementations. However the length fields */ -/* are in bytes or bits as appropriate for the version used */ -/* and bit sequences are input as arrays of bytes in which */ -/* bit sequences run from the most to the least significant */ -/* end of each byte */ - -void sha1_compile(sha1_ctx ctx[1]); - -void sha1_begin(sha1_ctx ctx[1]); -void sha1_hash(const unsigned char data[], unsigned __int32 len, sha1_ctx ctx[1]); -void sha1_end(unsigned char hval[], sha1_ctx ctx[1]); -void sha1(unsigned char hval[], const unsigned char data[], unsigned __int32 len); - -#if defined(__cplusplus) -} -#endif - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 26/08/2003 +*/ + +#ifndef _SHA1_H +#define _SHA1_H + +#include +#include "Common/Tcdefs.h" + +#define SHA1_BLOCK_SIZE 64 +#define SHA1_DIGEST_SIZE 20 + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* define an unsigned 32-bit type */ + +#if defined(_MSC_VER) + typedef unsigned __int32 sha1_32t; +#elif defined(ULONG_MAX) && ULONG_MAX == 0xfffffffful + typedef unsigned __int32 sha1_32t; +#elif defined(UINT_MAX) && UINT_MAX == 0xffffffff + typedef unsigned int sha1_32t; +#else +# error Please define sha1_32t as an unsigned 32 bit type in sha1.h +#endif + +/* type to hold the SHA256 context */ + +typedef struct +{ sha1_32t count[2]; + sha1_32t hash[5]; + sha1_32t wbuf[16]; +} sha1_ctx; + +/* Note that these prototypes are the same for both bit and */ +/* byte oriented implementations. However the length fields */ +/* are in bytes or bits as appropriate for the version used */ +/* and bit sequences are input as arrays of bytes in which */ +/* bit sequences run from the most to the least significant */ +/* end of each byte */ + +void sha1_compile(sha1_ctx ctx[1]); + +void sha1_begin(sha1_ctx ctx[1]); +void sha1_hash(const unsigned char data[], unsigned __int32 len, sha1_ctx ctx[1]); +void sha1_end(unsigned char hval[], sha1_ctx ctx[1]); +void sha1(unsigned char hval[], const unsigned char data[], unsigned __int32 len); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Crypto/Serpent.c b/Crypto/Serpent.c index 7d1d0ad..dae3841 100644 --- a/Crypto/Serpent.c +++ b/Crypto/Serpent.c @@ -1,943 +1,943 @@ -// serpent.cpp - written and placed in the public domain by Wei Dai - -/* Adapted for TrueCrypt by the TrueCrypt Foundation */ - -#ifdef TC_WINDOWS_BOOT -#pragma optimize ("t", on) -#endif - -#include "Serpent.h" -#include "Common/Endian.h" - -#include - -#if defined(_WIN32) && !defined(_DEBUG) -#include -#define rotlFixed _rotl -#define rotrFixed _rotr -#else -#define rotlFixed(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) -#define rotrFixed(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) -#endif - -// linear transformation -#define LT(i,a,b,c,d,e) {\ - a = rotlFixed(a, 13); \ - c = rotlFixed(c, 3); \ - d = rotlFixed(d ^ c ^ (a << 3), 7); \ - b = rotlFixed(b ^ a ^ c, 1); \ - a = rotlFixed(a ^ b ^ d, 5); \ - c = rotlFixed(c ^ d ^ (b << 7), 22);} - -// inverse linear transformation -#define ILT(i,a,b,c,d,e) {\ - c = rotrFixed(c, 22); \ - a = rotrFixed(a, 5); \ - c ^= d ^ (b << 7); \ - a ^= b ^ d; \ - b = rotrFixed(b, 1); \ - d = rotrFixed(d, 7) ^ c ^ (a << 3); \ - b ^= a ^ c; \ - c = rotrFixed(c, 3); \ - a = rotrFixed(a, 13);} - -// order of output from S-box functions -#define beforeS0(f) f(0,a,b,c,d,e) -#define afterS0(f) f(1,b,e,c,a,d) -#define afterS1(f) f(2,c,b,a,e,d) -#define afterS2(f) f(3,a,e,b,d,c) -#define afterS3(f) f(4,e,b,d,c,a) -#define afterS4(f) f(5,b,a,e,c,d) -#define afterS5(f) f(6,a,c,b,e,d) -#define afterS6(f) f(7,a,c,d,b,e) -#define afterS7(f) f(8,d,e,b,a,c) - -// order of output from inverse S-box functions -#define beforeI7(f) f(8,a,b,c,d,e) -#define afterI7(f) f(7,d,a,b,e,c) -#define afterI6(f) f(6,a,b,c,e,d) -#define afterI5(f) f(5,b,d,e,c,a) -#define afterI4(f) f(4,b,c,e,a,d) -#define afterI3(f) f(3,a,b,e,c,d) -#define afterI2(f) f(2,b,d,e,c,a) -#define afterI1(f) f(1,a,b,c,e,d) -#define afterI0(f) f(0,a,d,b,e,c) - -// The instruction sequences for the S-box functions -// come from Dag Arne Osvik's paper "Speeding up Serpent". - -#define S0(i, r0, r1, r2, r3, r4) \ - { \ - r3 ^= r0; \ - r4 = r1; \ - r1 &= r3; \ - r4 ^= r2; \ - r1 ^= r0; \ - r0 |= r3; \ - r0 ^= r4; \ - r4 ^= r3; \ - r3 ^= r2; \ - r2 |= r1; \ - r2 ^= r4; \ - r4 = ~r4; \ - r4 |= r1; \ - r1 ^= r3; \ - r1 ^= r4; \ - r3 |= r0; \ - r1 ^= r3; \ - r4 ^= r3; \ - } - -#define I0(i, r0, r1, r2, r3, r4) \ - { \ - r2 = ~r2; \ - r4 = r1; \ - r1 |= r0; \ - r4 = ~r4; \ - r1 ^= r2; \ - r2 |= r4; \ - r1 ^= r3; \ - r0 ^= r4; \ - r2 ^= r0; \ - r0 &= r3; \ - r4 ^= r0; \ - r0 |= r1; \ - r0 ^= r2; \ - r3 ^= r4; \ - r2 ^= r1; \ - r3 ^= r0; \ - r3 ^= r1; \ - r2 &= r3; \ - r4 ^= r2; \ - } - -#define S1(i, r0, r1, r2, r3, r4) \ - { \ - r0 = ~r0; \ - r2 = ~r2; \ - r4 = r0; \ - r0 &= r1; \ - r2 ^= r0; \ - r0 |= r3; \ - r3 ^= r2; \ - r1 ^= r0; \ - r0 ^= r4; \ - r4 |= r1; \ - r1 ^= r3; \ - r2 |= r0; \ - r2 &= r4; \ - r0 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; \ - r0 &= r2; \ - r0 ^= r4; \ - } - -#define I1(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r1; \ - r1 ^= r3; \ - r3 &= r1; \ - r4 ^= r2; \ - r3 ^= r0; \ - r0 |= r1; \ - r2 ^= r3; \ - r0 ^= r4; \ - r0 |= r2; \ - r1 ^= r3; \ - r0 ^= r1; \ - r1 |= r3; \ - r1 ^= r0; \ - r4 = ~r4; \ - r4 ^= r1; \ - r1 |= r0; \ - r1 ^= r0; \ - r1 |= r4; \ - r3 ^= r1; \ - } - -#define S2(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r0; \ - r0 &= r2; \ - r0 ^= r3; \ - r2 ^= r1; \ - r2 ^= r0; \ - r3 |= r4; \ - r3 ^= r1; \ - r4 ^= r2; \ - r1 = r3; \ - r3 |= r4; \ - r3 ^= r0; \ - r0 &= r1; \ - r4 ^= r0; \ - r1 ^= r3; \ - r1 ^= r4; \ - r4 = ~r4; \ - } - -#define I2(i, r0, r1, r2, r3, r4) \ - { \ - r2 ^= r3; \ - r3 ^= r0; \ - r4 = r3; \ - r3 &= r2; \ - r3 ^= r1; \ - r1 |= r2; \ - r1 ^= r4; \ - r4 &= r3; \ - r2 ^= r3; \ - r4 &= r0; \ - r4 ^= r2; \ - r2 &= r1; \ - r2 |= r0; \ - r3 = ~r3; \ - r2 ^= r3; \ - r0 ^= r3; \ - r0 &= r1; \ - r3 ^= r4; \ - r3 ^= r0; \ - } - -#define S3(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r0; \ - r0 |= r3; \ - r3 ^= r1; \ - r1 &= r4; \ - r4 ^= r2; \ - r2 ^= r3; \ - r3 &= r0; \ - r4 |= r1; \ - r3 ^= r4; \ - r0 ^= r1; \ - r4 &= r0; \ - r1 ^= r3; \ - r4 ^= r2; \ - r1 |= r0; \ - r1 ^= r2; \ - r0 ^= r3; \ - r2 = r1; \ - r1 |= r3; \ - r1 ^= r0; \ - } - -#define I3(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; \ - r0 &= r4; \ - r4 ^= r3; \ - r3 |= r1; \ - r3 ^= r2; \ - r0 ^= r4; \ - r2 ^= r0; \ - r0 |= r3; \ - r0 ^= r1; \ - r4 ^= r2; \ - r2 &= r3; \ - r1 |= r3; \ - r1 ^= r2; \ - r4 ^= r0; \ - r2 ^= r4; \ - } - -#define S4(i, r0, r1, r2, r3, r4) \ - { \ - r1 ^= r3; \ - r3 = ~r3; \ - r2 ^= r3; \ - r3 ^= r0; \ - r4 = r1; \ - r1 &= r3; \ - r1 ^= r2; \ - r4 ^= r3; \ - r0 ^= r4; \ - r2 &= r4; \ - r2 ^= r0; \ - r0 &= r1; \ - r3 ^= r0; \ - r4 |= r1; \ - r4 ^= r0; \ - r0 |= r3; \ - r0 ^= r2; \ - r2 &= r3; \ - r0 = ~r0; \ - r4 ^= r2; \ - } - -#define I4(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 &= r3; \ - r2 ^= r1; \ - r1 |= r3; \ - r1 &= r0; \ - r4 ^= r2; \ - r4 ^= r1; \ - r1 &= r2; \ - r0 = ~r0; \ - r3 ^= r4; \ - r1 ^= r3; \ - r3 &= r0; \ - r3 ^= r2; \ - r0 ^= r1; \ - r2 &= r0; \ - r3 ^= r0; \ - r2 ^= r4; \ - r2 |= r3; \ - r3 ^= r0; \ - r2 ^= r1; \ - } - -#define S5(i, r0, r1, r2, r3, r4) \ - { \ - r0 ^= r1; \ - r1 ^= r3; \ - r3 = ~r3; \ - r4 = r1; \ - r1 &= r0; \ - r2 ^= r3; \ - r1 ^= r2; \ - r2 |= r4; \ - r4 ^= r3; \ - r3 &= r1; \ - r3 ^= r0; \ - r4 ^= r1; \ - r4 ^= r2; \ - r2 ^= r0; \ - r0 &= r3; \ - r2 = ~r2; \ - r0 ^= r4; \ - r4 |= r3; \ - r2 ^= r4; \ - } - -#define I5(i, r0, r1, r2, r3, r4) \ - { \ - r1 = ~r1; \ - r4 = r3; \ - r2 ^= r1; \ - r3 |= r0; \ - r3 ^= r2; \ - r2 |= r1; \ - r2 &= r0; \ - r4 ^= r3; \ - r2 ^= r4; \ - r4 |= r0; \ - r4 ^= r1; \ - r1 &= r2; \ - r1 ^= r3; \ - r4 ^= r2; \ - r3 &= r4; \ - r4 ^= r1; \ - r3 ^= r0; \ - r3 ^= r4; \ - r4 = ~r4; \ - } - -#define S6(i, r0, r1, r2, r3, r4) \ - { \ - r2 = ~r2; \ - r4 = r3; \ - r3 &= r0; \ - r0 ^= r4; \ - r3 ^= r2; \ - r2 |= r4; \ - r1 ^= r3; \ - r2 ^= r0; \ - r0 |= r1; \ - r2 ^= r1; \ - r4 ^= r0; \ - r0 |= r3; \ - r0 ^= r2; \ - r4 ^= r3; \ - r4 ^= r0; \ - r3 = ~r3; \ - r2 &= r4; \ - r2 ^= r3; \ - } - -#define I6(i, r0, r1, r2, r3, r4) \ - { \ - r0 ^= r2; \ - r4 = r2; \ - r2 &= r0; \ - r4 ^= r3; \ - r2 = ~r2; \ - r3 ^= r1; \ - r2 ^= r3; \ - r4 |= r0; \ - r0 ^= r2; \ - r3 ^= r4; \ - r4 ^= r1; \ - r1 &= r3; \ - r1 ^= r0; \ - r0 ^= r3; \ - r0 |= r2; \ - r3 ^= r1; \ - r4 ^= r0; \ - } - -#define S7(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 &= r1; \ - r2 ^= r3; \ - r3 &= r1; \ - r4 ^= r2; \ - r2 ^= r1; \ - r1 ^= r0; \ - r0 |= r4; \ - r0 ^= r2; \ - r3 ^= r1; \ - r2 ^= r3; \ - r3 &= r0; \ - r3 ^= r4; \ - r4 ^= r2; \ - r2 &= r0; \ - r4 = ~r4; \ - r2 ^= r4; \ - r4 &= r0; \ - r1 ^= r3; \ - r4 ^= r1; \ - } - -#define I7(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 ^= r0; \ - r0 &= r3; \ - r2 = ~r2; \ - r4 |= r3; \ - r3 ^= r1; \ - r1 |= r0; \ - r0 ^= r2; \ - r2 &= r4; \ - r1 ^= r2; \ - r2 ^= r0; \ - r0 |= r2; \ - r3 &= r4; \ - r0 ^= r3; \ - r4 ^= r1; \ - r3 ^= r4; \ - r4 |= r0; \ - r3 ^= r2; \ - r4 ^= r2; \ - } - -// key xor -#define KX(r, a, b, c, d, e) {\ - a ^= k[4 * r + 0]; \ - b ^= k[4 * r + 1]; \ - c ^= k[4 * r + 2]; \ - d ^= k[4 * r + 3];} - - -#ifdef TC_MINIMIZE_CODE_SIZE - -static void S0f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r3 ^= *r0; - *r4 = *r1; - *r1 &= *r3; - *r4 ^= *r2; - *r1 ^= *r0; - *r0 |= *r3; - *r0 ^= *r4; - *r4 ^= *r3; - *r3 ^= *r2; - *r2 |= *r1; - *r2 ^= *r4; - *r4 = ~*r4; - *r4 |= *r1; - *r1 ^= *r3; - *r1 ^= *r4; - *r3 |= *r0; - *r1 ^= *r3; - *r4 ^= *r3; -} - -static void S1f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r0 = ~*r0; - *r2 = ~*r2; - *r4 = *r0; - *r0 &= *r1; - *r2 ^= *r0; - *r0 |= *r3; - *r3 ^= *r2; - *r1 ^= *r0; - *r0 ^= *r4; - *r4 |= *r1; - *r1 ^= *r3; - *r2 |= *r0; - *r2 &= *r4; - *r0 ^= *r1; - *r1 &= *r2; - *r1 ^= *r0; - *r0 &= *r2; - *r0 ^= *r4; -} - -static void S2f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r4 = *r0; - *r0 &= *r2; - *r0 ^= *r3; - *r2 ^= *r1; - *r2 ^= *r0; - *r3 |= *r4; - *r3 ^= *r1; - *r4 ^= *r2; - *r1 = *r3; - *r3 |= *r4; - *r3 ^= *r0; - *r0 &= *r1; - *r4 ^= *r0; - *r1 ^= *r3; - *r1 ^= *r4; - *r4 = ~*r4; -} - -static void S3f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r4 = *r0; - *r0 |= *r3; - *r3 ^= *r1; - *r1 &= *r4; - *r4 ^= *r2; - *r2 ^= *r3; - *r3 &= *r0; - *r4 |= *r1; - *r3 ^= *r4; - *r0 ^= *r1; - *r4 &= *r0; - *r1 ^= *r3; - *r4 ^= *r2; - *r1 |= *r0; - *r1 ^= *r2; - *r0 ^= *r3; - *r2 = *r1; - *r1 |= *r3; - *r1 ^= *r0; -} - -static void S4f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r1 ^= *r3; - *r3 = ~*r3; - *r2 ^= *r3; - *r3 ^= *r0; - *r4 = *r1; - *r1 &= *r3; - *r1 ^= *r2; - *r4 ^= *r3; - *r0 ^= *r4; - *r2 &= *r4; - *r2 ^= *r0; - *r0 &= *r1; - *r3 ^= *r0; - *r4 |= *r1; - *r4 ^= *r0; - *r0 |= *r3; - *r0 ^= *r2; - *r2 &= *r3; - *r0 = ~*r0; - *r4 ^= *r2; -} - -static void S5f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r0 ^= *r1; - *r1 ^= *r3; - *r3 = ~*r3; - *r4 = *r1; - *r1 &= *r0; - *r2 ^= *r3; - *r1 ^= *r2; - *r2 |= *r4; - *r4 ^= *r3; - *r3 &= *r1; - *r3 ^= *r0; - *r4 ^= *r1; - *r4 ^= *r2; - *r2 ^= *r0; - *r0 &= *r3; - *r2 = ~*r2; - *r0 ^= *r4; - *r4 |= *r3; - *r2 ^= *r4; -} - -static void S6f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r2 = ~*r2; - *r4 = *r3; - *r3 &= *r0; - *r0 ^= *r4; - *r3 ^= *r2; - *r2 |= *r4; - *r1 ^= *r3; - *r2 ^= *r0; - *r0 |= *r1; - *r2 ^= *r1; - *r4 ^= *r0; - *r0 |= *r3; - *r0 ^= *r2; - *r4 ^= *r3; - *r4 ^= *r0; - *r3 = ~*r3; - *r2 &= *r4; - *r2 ^= *r3; -} - -static void S7f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) -{ - *r4 = *r2; - *r2 &= *r1; - *r2 ^= *r3; - *r3 &= *r1; - *r4 ^= *r2; - *r2 ^= *r1; - *r1 ^= *r0; - *r0 |= *r4; - *r0 ^= *r2; - *r3 ^= *r1; - *r2 ^= *r3; - *r3 &= *r0; - *r3 ^= *r4; - *r4 ^= *r2; - *r2 &= *r0; - *r4 = ~*r4; - *r2 ^= *r4; - *r4 &= *r0; - *r1 ^= *r3; - *r4 ^= *r1; -} - -static void KXf (const unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) -{ - *a ^= k[r]; - *b ^= k[r + 1]; - *c ^= k[r + 2]; - *d ^= k[r + 3]; -} - -#endif // TC_MINIMIZE_CODE_SIZE - -#ifndef TC_MINIMIZE_CODE_SIZE - -void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks) -{ - unsigned __int32 a,b,c,d,e; - unsigned __int32 *k = (unsigned __int32 *)ks; - unsigned __int32 t; - int i; - - for (i = 0; i < keylen / (int)sizeof(__int32); i++) - k[i] = LE32(((unsigned __int32*)userKey)[i]); - - if (keylen < 32) - k[keylen/4] |= (unsigned __int32)1 << ((keylen%4)*8); - - k += 8; - t = k[-1]; - for (i = 0; i < 132; ++i) - k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); - k -= 20; - -#define LK(r, a, b, c, d, e) {\ - a = k[(8-r)*4 + 0]; \ - b = k[(8-r)*4 + 1]; \ - c = k[(8-r)*4 + 2]; \ - d = k[(8-r)*4 + 3];} - -#define SK(r, a, b, c, d, e) {\ - k[(8-r)*4 + 4] = a; \ - k[(8-r)*4 + 5] = b; \ - k[(8-r)*4 + 6] = c; \ - k[(8-r)*4 + 7] = d;} \ - - for (i=0; i<4; i++) - { - afterS2(LK); afterS2(S3); afterS3(SK); - afterS1(LK); afterS1(S2); afterS2(SK); - afterS0(LK); afterS0(S1); afterS1(SK); - beforeS0(LK); beforeS0(S0); afterS0(SK); - k += 8*4; - afterS6(LK); afterS6(S7); afterS7(SK); - afterS5(LK); afterS5(S6); afterS6(SK); - afterS4(LK); afterS4(S5); afterS5(SK); - afterS3(LK); afterS3(S4); afterS4(SK); - } - afterS2(LK); afterS2(S3); afterS3(SK); -} - -#else // TC_MINIMIZE_CODE_SIZE - -static void LKf (unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) -{ - *a = k[r]; - *b = k[r + 1]; - *c = k[r + 2]; - *d = k[r + 3]; -} - -static void SKf (unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) -{ - k[r + 4] = *a; - k[r + 5] = *b; - k[r + 6] = *c; - k[r + 7] = *d; -} - -void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks) -{ - unsigned __int32 a,b,c,d,e; - unsigned __int32 *k = (unsigned __int32 *)ks; - unsigned __int32 t; - int i; - - for (i = 0; i < keylen / (int)sizeof(__int32); i++) - k[i] = LE32(((unsigned __int32*)userKey)[i]); - - if (keylen < 32) - k[keylen/4] |= (unsigned __int32)1 << ((keylen%4)*8); - - k += 8; - t = k[-1]; - for (i = 0; i < 132; ++i) - k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); - k -= 20; - - for (i=0; i<4; i++) - { - LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); - LKf (k, 24, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); SKf (k, 20, &a, &e, &b, &d); - LKf (k, 28, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); SKf (k, 24, &c, &b, &a, &e); - LKf (k, 32, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); SKf (k, 28, &b, &e, &c, &a); - k += 8*4; - LKf (k, 4, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); SKf (k, 0, &d, &e, &b, &a); - LKf (k, 8, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); SKf (k, 4, &a, &c, &d, &b); - LKf (k, 12, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); SKf (k, 8, &a, &c, &b, &e); - LKf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); SKf (k, 12, &b, &a, &e, &c); - } - LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); -} - -#endif // TC_MINIMIZE_CODE_SIZE - - -#ifndef TC_MINIMIZE_CODE_SIZE - -void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) -{ - unsigned __int32 a, b, c, d, e; - unsigned int i=1; - const unsigned __int32 *k = (unsigned __int32 *)ks + 8; - unsigned __int32 *in = (unsigned __int32 *) inBlock; - unsigned __int32 *out = (unsigned __int32 *) outBlock; - - a = LE32(in[0]); - b = LE32(in[1]); - c = LE32(in[2]); - d = LE32(in[3]); - - do - { - beforeS0(KX); beforeS0(S0); afterS0(LT); - afterS0(KX); afterS0(S1); afterS1(LT); - afterS1(KX); afterS1(S2); afterS2(LT); - afterS2(KX); afterS2(S3); afterS3(LT); - afterS3(KX); afterS3(S4); afterS4(LT); - afterS4(KX); afterS4(S5); afterS5(LT); - afterS5(KX); afterS5(S6); afterS6(LT); - afterS6(KX); afterS6(S7); - - if (i == 4) - break; - - ++i; - c = b; - b = e; - e = d; - d = a; - a = e; - k += 32; - beforeS0(LT); - } - while (1); - - afterS7(KX); - - out[0] = LE32(d); - out[1] = LE32(e); - out[2] = LE32(b); - out[3] = LE32(a); -} - -#else // TC_MINIMIZE_CODE_SIZE - -typedef unsigned __int32 uint32; - -static void LTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) -{ - *a = rotlFixed(*a, 13); - *c = rotlFixed(*c, 3); - *d = rotlFixed(*d ^ *c ^ (*a << 3), 7); - *b = rotlFixed(*b ^ *a ^ *c, 1); - *a = rotlFixed(*a ^ *b ^ *d, 5); - *c = rotlFixed(*c ^ *d ^ (*b << 7), 22); -} - -void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) -{ - unsigned __int32 a, b, c, d, e; - unsigned int i=1; - const unsigned __int32 *k = (unsigned __int32 *)ks + 8; - unsigned __int32 *in = (unsigned __int32 *) inBlock; - unsigned __int32 *out = (unsigned __int32 *) outBlock; - - a = LE32(in[0]); - b = LE32(in[1]); - c = LE32(in[2]); - d = LE32(in[3]); - - do - { - KXf (k, 0, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); LTf (&b, &e, &c, &a); - KXf (k, 4, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); LTf (&c, &b, &a, &e); - KXf (k, 8, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); LTf (&a, &e, &b, &d); - KXf (k, 12, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); LTf (&e, &b, &d, &c); - KXf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); LTf (&b, &a, &e, &c); - KXf (k, 20, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); LTf (&a, &c, &b, &e); - KXf (k, 24, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); LTf (&a, &c, &d, &b); - KXf (k, 28, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); - - if (i == 4) - break; - - ++i; - c = b; - b = e; - e = d; - d = a; - a = e; - k += 32; - LTf (&a,&b,&c,&d); - } - while (1); - - KXf (k, 32, &d, &e, &b, &a); - - out[0] = LE32(d); - out[1] = LE32(e); - out[2] = LE32(b); - out[3] = LE32(a); -} - -#endif // TC_MINIMIZE_CODE_SIZE - -#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_SERPENT) - -void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) -{ - unsigned __int32 a, b, c, d, e; - const unsigned __int32 *k = (unsigned __int32 *)ks + 104; - unsigned int i=4; - unsigned __int32 *in = (unsigned __int32 *) inBlock; - unsigned __int32 *out = (unsigned __int32 *) outBlock; - - a = LE32(in[0]); - b = LE32(in[1]); - c = LE32(in[2]); - d = LE32(in[3]); - - beforeI7(KX); - goto start; - - do - { - c = b; - b = d; - d = e; - k -= 32; - beforeI7(ILT); -start: - beforeI7(I7); afterI7(KX); - afterI7(ILT); afterI7(I6); afterI6(KX); - afterI6(ILT); afterI6(I5); afterI5(KX); - afterI5(ILT); afterI5(I4); afterI4(KX); - afterI4(ILT); afterI4(I3); afterI3(KX); - afterI3(ILT); afterI3(I2); afterI2(KX); - afterI2(ILT); afterI2(I1); afterI1(KX); - afterI1(ILT); afterI1(I0); afterI0(KX); - } - while (--i != 0); - - out[0] = LE32(a); - out[1] = LE32(d); - out[2] = LE32(b); - out[3] = LE32(e); -} - -#else // TC_MINIMIZE_CODE_SIZE && !TC_WINDOWS_BOOT_SERPENT - -static void ILTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) -{ - *c = rotrFixed(*c, 22); - *a = rotrFixed(*a, 5); - *c ^= *d ^ (*b << 7); - *a ^= *b ^ *d; - *b = rotrFixed(*b, 1); - *d = rotrFixed(*d, 7) ^ *c ^ (*a << 3); - *b ^= *a ^ *c; - *c = rotrFixed(*c, 3); - *a = rotrFixed(*a, 13); -} - -void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) -{ - unsigned __int32 a, b, c, d, e; - const unsigned __int32 *k = (unsigned __int32 *)ks + 104; - unsigned int i=4; - unsigned __int32 *in = (unsigned __int32 *) inBlock; - unsigned __int32 *out = (unsigned __int32 *) outBlock; - - a = LE32(in[0]); - b = LE32(in[1]); - c = LE32(in[2]); - d = LE32(in[3]); - - KXf (k, 32, &a, &b, &c, &d); - goto start; - - do - { - c = b; - b = d; - d = e; - k -= 32; - beforeI7(ILT); -start: - beforeI7(I7); KXf (k, 28, &d, &a, &b, &e); - ILTf (&d, &a, &b, &e); afterI7(I6); KXf (k, 24, &a, &b, &c, &e); - ILTf (&a, &b, &c, &e); afterI6(I5); KXf (k, 20, &b, &d, &e, &c); - ILTf (&b, &d, &e, &c); afterI5(I4); KXf (k, 16, &b, &c, &e, &a); - ILTf (&b, &c, &e, &a); afterI4(I3); KXf (k, 12, &a, &b, &e, &c); - ILTf (&a, &b, &e, &c); afterI3(I2); KXf (k, 8, &b, &d, &e, &c); - ILTf (&b, &d, &e, &c); afterI2(I1); KXf (k, 4, &a, &b, &c, &e); - ILTf (&a, &b, &c, &e); afterI1(I0); KXf (k, 0, &a, &d, &b, &e); - } - while (--i != 0); - - out[0] = LE32(a); - out[1] = LE32(d); - out[2] = LE32(b); - out[3] = LE32(e); -} - -#endif // TC_MINIMIZE_CODE_SIZE && !TC_WINDOWS_BOOT_SERPENT +// serpent.cpp - written and placed in the public domain by Wei Dai + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#ifdef TC_WINDOWS_BOOT +#pragma optimize ("t", on) +#endif + +#include "Serpent.h" +#include "Common/Endian.h" + +#include + +#if defined(_WIN32) && !defined(_DEBUG) +#include +#define rotlFixed _rotl +#define rotrFixed _rotr +#else +#define rotlFixed(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) +#endif + +// linear transformation +#define LT(i,a,b,c,d,e) {\ + a = rotlFixed(a, 13); \ + c = rotlFixed(c, 3); \ + d = rotlFixed(d ^ c ^ (a << 3), 7); \ + b = rotlFixed(b ^ a ^ c, 1); \ + a = rotlFixed(a ^ b ^ d, 5); \ + c = rotlFixed(c ^ d ^ (b << 7), 22);} + +// inverse linear transformation +#define ILT(i,a,b,c,d,e) {\ + c = rotrFixed(c, 22); \ + a = rotrFixed(a, 5); \ + c ^= d ^ (b << 7); \ + a ^= b ^ d; \ + b = rotrFixed(b, 1); \ + d = rotrFixed(d, 7) ^ c ^ (a << 3); \ + b ^= a ^ c; \ + c = rotrFixed(c, 3); \ + a = rotrFixed(a, 13);} + +// order of output from S-box functions +#define beforeS0(f) f(0,a,b,c,d,e) +#define afterS0(f) f(1,b,e,c,a,d) +#define afterS1(f) f(2,c,b,a,e,d) +#define afterS2(f) f(3,a,e,b,d,c) +#define afterS3(f) f(4,e,b,d,c,a) +#define afterS4(f) f(5,b,a,e,c,d) +#define afterS5(f) f(6,a,c,b,e,d) +#define afterS6(f) f(7,a,c,d,b,e) +#define afterS7(f) f(8,d,e,b,a,c) + +// order of output from inverse S-box functions +#define beforeI7(f) f(8,a,b,c,d,e) +#define afterI7(f) f(7,d,a,b,e,c) +#define afterI6(f) f(6,a,b,c,e,d) +#define afterI5(f) f(5,b,d,e,c,a) +#define afterI4(f) f(4,b,c,e,a,d) +#define afterI3(f) f(3,a,b,e,c,d) +#define afterI2(f) f(2,b,d,e,c,a) +#define afterI1(f) f(1,a,b,c,e,d) +#define afterI0(f) f(0,a,d,b,e,c) + +// The instruction sequences for the S-box functions +// come from Dag Arne Osvik's paper "Speeding up Serpent". + +#define S0(i, r0, r1, r2, r3, r4) \ + { \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r4 ^= r2; \ + r1 ^= r0; \ + r0 |= r3; \ + r0 ^= r4; \ + r4 ^= r3; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 ^= r4; \ + r4 = ~r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r1 ^= r4; \ + r3 |= r0; \ + r1 ^= r3; \ + r4 ^= r3; \ + } + +#define I0(i, r0, r1, r2, r3, r4) \ + { \ + r2 = ~r2; \ + r4 = r1; \ + r1 |= r0; \ + r4 = ~r4; \ + r1 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 &= r3; \ + r4 ^= r0; \ + r0 |= r1; \ + r0 ^= r2; \ + r3 ^= r4; \ + r2 ^= r1; \ + r3 ^= r0; \ + r3 ^= r1; \ + r2 &= r3; \ + r4 ^= r2; \ + } + +#define S1(i, r0, r1, r2, r3, r4) \ + { \ + r0 = ~r0; \ + r2 = ~r2; \ + r4 = r0; \ + r0 &= r1; \ + r2 ^= r0; \ + r0 |= r3; \ + r3 ^= r2; \ + r1 ^= r0; \ + r0 ^= r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r2 |= r0; \ + r2 &= r4; \ + r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r2; \ + r0 ^= r4; \ + } + +#define I1(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r1; \ + r1 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r3 ^= r0; \ + r0 |= r1; \ + r2 ^= r3; \ + r0 ^= r4; \ + r0 |= r2; \ + r1 ^= r3; \ + r0 ^= r1; \ + r1 |= r3; \ + r1 ^= r0; \ + r4 = ~r4; \ + r4 ^= r1; \ + r1 |= r0; \ + r1 ^= r0; \ + r1 |= r4; \ + r3 ^= r1; \ + } + +#define S2(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r0; \ + r0 &= r2; \ + r0 ^= r3; \ + r2 ^= r1; \ + r2 ^= r0; \ + r3 |= r4; \ + r3 ^= r1; \ + r4 ^= r2; \ + r1 = r3; \ + r3 |= r4; \ + r3 ^= r0; \ + r0 &= r1; \ + r4 ^= r0; \ + r1 ^= r3; \ + r1 ^= r4; \ + r4 = ~r4; \ + } + +#define I2(i, r0, r1, r2, r3, r4) \ + { \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r3; \ + r3 &= r2; \ + r3 ^= r1; \ + r1 |= r2; \ + r1 ^= r4; \ + r4 &= r3; \ + r2 ^= r3; \ + r4 &= r0; \ + r4 ^= r2; \ + r2 &= r1; \ + r2 |= r0; \ + r3 = ~r3; \ + r2 ^= r3; \ + r0 ^= r3; \ + r0 &= r1; \ + r3 ^= r4; \ + r3 ^= r0; \ + } + +#define S3(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r0; \ + r0 |= r3; \ + r3 ^= r1; \ + r1 &= r4; \ + r4 ^= r2; \ + r2 ^= r3; \ + r3 &= r0; \ + r4 |= r1; \ + r3 ^= r4; \ + r0 ^= r1; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r2; \ + r1 |= r0; \ + r1 ^= r2; \ + r0 ^= r3; \ + r2 = r1; \ + r1 |= r3; \ + r1 ^= r0; \ + } + +#define I3(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r4; \ + r4 ^= r3; \ + r3 |= r1; \ + r3 ^= r2; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 |= r3; \ + r0 ^= r1; \ + r4 ^= r2; \ + r2 &= r3; \ + r1 |= r3; \ + r1 ^= r2; \ + r4 ^= r0; \ + r2 ^= r4; \ + } + +#define S4(i, r0, r1, r2, r3, r4) \ + { \ + r1 ^= r3; \ + r3 = ~r3; \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r1 ^= r2; \ + r4 ^= r3; \ + r0 ^= r4; \ + r2 &= r4; \ + r2 ^= r0; \ + r0 &= r1; \ + r3 ^= r0; \ + r4 |= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r2 &= r3; \ + r0 = ~r0; \ + r4 ^= r2; \ + } + +#define I4(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 &= r3; \ + r2 ^= r1; \ + r1 |= r3; \ + r1 &= r0; \ + r4 ^= r2; \ + r4 ^= r1; \ + r1 &= r2; \ + r0 = ~r0; \ + r3 ^= r4; \ + r1 ^= r3; \ + r3 &= r0; \ + r3 ^= r2; \ + r0 ^= r1; \ + r2 &= r0; \ + r3 ^= r0; \ + r2 ^= r4; \ + r2 |= r3; \ + r3 ^= r0; \ + r2 ^= r1; \ + } + +#define S5(i, r0, r1, r2, r3, r4) \ + { \ + r0 ^= r1; \ + r1 ^= r3; \ + r3 = ~r3; \ + r4 = r1; \ + r1 &= r0; \ + r2 ^= r3; \ + r1 ^= r2; \ + r2 |= r4; \ + r4 ^= r3; \ + r3 &= r1; \ + r3 ^= r0; \ + r4 ^= r1; \ + r4 ^= r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r0 ^= r4; \ + r4 |= r3; \ + r2 ^= r4; \ + } + +#define I5(i, r0, r1, r2, r3, r4) \ + { \ + r1 = ~r1; \ + r4 = r3; \ + r2 ^= r1; \ + r3 |= r0; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 ^= r4; \ + r4 |= r0; \ + r4 ^= r1; \ + r1 &= r2; \ + r1 ^= r3; \ + r4 ^= r2; \ + r3 &= r4; \ + r4 ^= r1; \ + r3 ^= r0; \ + r3 ^= r4; \ + r4 = ~r4; \ + } + +#define S6(i, r0, r1, r2, r3, r4) \ + { \ + r2 = ~r2; \ + r4 = r3; \ + r3 &= r0; \ + r0 ^= r4; \ + r3 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r2 ^= r0; \ + r0 |= r1; \ + r2 ^= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r4 ^= r3; \ + r4 ^= r0; \ + r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ + } + +#define I6(i, r0, r1, r2, r3, r4) \ + { \ + r0 ^= r2; \ + r4 = r2; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 = ~r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r4 |= r0; \ + r0 ^= r2; \ + r3 ^= r4; \ + r4 ^= r1; \ + r1 &= r3; \ + r1 ^= r0; \ + r0 ^= r3; \ + r0 |= r2; \ + r3 ^= r1; \ + r4 ^= r0; \ + } + +#define S7(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 &= r1; \ + r2 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r2 ^= r1; \ + r1 ^= r0; \ + r0 |= r4; \ + r0 ^= r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r3 &= r0; \ + r3 ^= r4; \ + r4 ^= r2; \ + r2 &= r0; \ + r4 = ~r4; \ + r2 ^= r4; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r1; \ + } + +#define I7(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r4 |= r3; \ + r3 ^= r1; \ + r1 |= r0; \ + r0 ^= r2; \ + r2 &= r4; \ + r1 ^= r2; \ + r2 ^= r0; \ + r0 |= r2; \ + r3 &= r4; \ + r0 ^= r3; \ + r4 ^= r1; \ + r3 ^= r4; \ + r4 |= r0; \ + r3 ^= r2; \ + r4 ^= r2; \ + } + +// key xor +#define KX(r, a, b, c, d, e) {\ + a ^= k[4 * r + 0]; \ + b ^= k[4 * r + 1]; \ + c ^= k[4 * r + 2]; \ + d ^= k[4 * r + 3];} + + +#ifdef TC_MINIMIZE_CODE_SIZE + +static void S0f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r3 ^= *r0; + *r4 = *r1; + *r1 &= *r3; + *r4 ^= *r2; + *r1 ^= *r0; + *r0 |= *r3; + *r0 ^= *r4; + *r4 ^= *r3; + *r3 ^= *r2; + *r2 |= *r1; + *r2 ^= *r4; + *r4 = ~*r4; + *r4 |= *r1; + *r1 ^= *r3; + *r1 ^= *r4; + *r3 |= *r0; + *r1 ^= *r3; + *r4 ^= *r3; +} + +static void S1f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r0 = ~*r0; + *r2 = ~*r2; + *r4 = *r0; + *r0 &= *r1; + *r2 ^= *r0; + *r0 |= *r3; + *r3 ^= *r2; + *r1 ^= *r0; + *r0 ^= *r4; + *r4 |= *r1; + *r1 ^= *r3; + *r2 |= *r0; + *r2 &= *r4; + *r0 ^= *r1; + *r1 &= *r2; + *r1 ^= *r0; + *r0 &= *r2; + *r0 ^= *r4; +} + +static void S2f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r4 = *r0; + *r0 &= *r2; + *r0 ^= *r3; + *r2 ^= *r1; + *r2 ^= *r0; + *r3 |= *r4; + *r3 ^= *r1; + *r4 ^= *r2; + *r1 = *r3; + *r3 |= *r4; + *r3 ^= *r0; + *r0 &= *r1; + *r4 ^= *r0; + *r1 ^= *r3; + *r1 ^= *r4; + *r4 = ~*r4; +} + +static void S3f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r4 = *r0; + *r0 |= *r3; + *r3 ^= *r1; + *r1 &= *r4; + *r4 ^= *r2; + *r2 ^= *r3; + *r3 &= *r0; + *r4 |= *r1; + *r3 ^= *r4; + *r0 ^= *r1; + *r4 &= *r0; + *r1 ^= *r3; + *r4 ^= *r2; + *r1 |= *r0; + *r1 ^= *r2; + *r0 ^= *r3; + *r2 = *r1; + *r1 |= *r3; + *r1 ^= *r0; +} + +static void S4f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r1 ^= *r3; + *r3 = ~*r3; + *r2 ^= *r3; + *r3 ^= *r0; + *r4 = *r1; + *r1 &= *r3; + *r1 ^= *r2; + *r4 ^= *r3; + *r0 ^= *r4; + *r2 &= *r4; + *r2 ^= *r0; + *r0 &= *r1; + *r3 ^= *r0; + *r4 |= *r1; + *r4 ^= *r0; + *r0 |= *r3; + *r0 ^= *r2; + *r2 &= *r3; + *r0 = ~*r0; + *r4 ^= *r2; +} + +static void S5f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r0 ^= *r1; + *r1 ^= *r3; + *r3 = ~*r3; + *r4 = *r1; + *r1 &= *r0; + *r2 ^= *r3; + *r1 ^= *r2; + *r2 |= *r4; + *r4 ^= *r3; + *r3 &= *r1; + *r3 ^= *r0; + *r4 ^= *r1; + *r4 ^= *r2; + *r2 ^= *r0; + *r0 &= *r3; + *r2 = ~*r2; + *r0 ^= *r4; + *r4 |= *r3; + *r2 ^= *r4; +} + +static void S6f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r2 = ~*r2; + *r4 = *r3; + *r3 &= *r0; + *r0 ^= *r4; + *r3 ^= *r2; + *r2 |= *r4; + *r1 ^= *r3; + *r2 ^= *r0; + *r0 |= *r1; + *r2 ^= *r1; + *r4 ^= *r0; + *r0 |= *r3; + *r0 ^= *r2; + *r4 ^= *r3; + *r4 ^= *r0; + *r3 = ~*r3; + *r2 &= *r4; + *r2 ^= *r3; +} + +static void S7f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) +{ + *r4 = *r2; + *r2 &= *r1; + *r2 ^= *r3; + *r3 &= *r1; + *r4 ^= *r2; + *r2 ^= *r1; + *r1 ^= *r0; + *r0 |= *r4; + *r0 ^= *r2; + *r3 ^= *r1; + *r2 ^= *r3; + *r3 &= *r0; + *r3 ^= *r4; + *r4 ^= *r2; + *r2 &= *r0; + *r4 = ~*r4; + *r2 ^= *r4; + *r4 &= *r0; + *r1 ^= *r3; + *r4 ^= *r1; +} + +static void KXf (const unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) +{ + *a ^= k[r]; + *b ^= k[r + 1]; + *c ^= k[r + 2]; + *d ^= k[r + 3]; +} + +#endif // TC_MINIMIZE_CODE_SIZE + +#ifndef TC_MINIMIZE_CODE_SIZE + +void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks) +{ + unsigned __int32 a,b,c,d,e; + unsigned __int32 *k = (unsigned __int32 *)ks; + unsigned __int32 t; + int i; + + for (i = 0; i < keylen / (int)sizeof(__int32); i++) + k[i] = LE32(((unsigned __int32*)userKey)[i]); + + if (keylen < 32) + k[keylen/4] |= (unsigned __int32)1 << ((keylen%4)*8); + + k += 8; + t = k[-1]; + for (i = 0; i < 132; ++i) + k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); + k -= 20; + +#define LK(r, a, b, c, d, e) {\ + a = k[(8-r)*4 + 0]; \ + b = k[(8-r)*4 + 1]; \ + c = k[(8-r)*4 + 2]; \ + d = k[(8-r)*4 + 3];} + +#define SK(r, a, b, c, d, e) {\ + k[(8-r)*4 + 4] = a; \ + k[(8-r)*4 + 5] = b; \ + k[(8-r)*4 + 6] = c; \ + k[(8-r)*4 + 7] = d;} \ + + for (i=0; i<4; i++) + { + afterS2(LK); afterS2(S3); afterS3(SK); + afterS1(LK); afterS1(S2); afterS2(SK); + afterS0(LK); afterS0(S1); afterS1(SK); + beforeS0(LK); beforeS0(S0); afterS0(SK); + k += 8*4; + afterS6(LK); afterS6(S7); afterS7(SK); + afterS5(LK); afterS5(S6); afterS6(SK); + afterS4(LK); afterS4(S5); afterS5(SK); + afterS3(LK); afterS3(S4); afterS4(SK); + } + afterS2(LK); afterS2(S3); afterS3(SK); +} + +#else // TC_MINIMIZE_CODE_SIZE + +static void LKf (unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) +{ + *a = k[r]; + *b = k[r + 1]; + *c = k[r + 2]; + *d = k[r + 3]; +} + +static void SKf (unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) +{ + k[r + 4] = *a; + k[r + 5] = *b; + k[r + 6] = *c; + k[r + 7] = *d; +} + +void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks) +{ + unsigned __int32 a,b,c,d,e; + unsigned __int32 *k = (unsigned __int32 *)ks; + unsigned __int32 t; + int i; + + for (i = 0; i < keylen / (int)sizeof(__int32); i++) + k[i] = LE32(((unsigned __int32*)userKey)[i]); + + if (keylen < 32) + k[keylen/4] |= (unsigned __int32)1 << ((keylen%4)*8); + + k += 8; + t = k[-1]; + for (i = 0; i < 132; ++i) + k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); + k -= 20; + + for (i=0; i<4; i++) + { + LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); + LKf (k, 24, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); SKf (k, 20, &a, &e, &b, &d); + LKf (k, 28, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); SKf (k, 24, &c, &b, &a, &e); + LKf (k, 32, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); SKf (k, 28, &b, &e, &c, &a); + k += 8*4; + LKf (k, 4, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); SKf (k, 0, &d, &e, &b, &a); + LKf (k, 8, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); SKf (k, 4, &a, &c, &d, &b); + LKf (k, 12, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); SKf (k, 8, &a, &c, &b, &e); + LKf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); SKf (k, 12, &b, &a, &e, &c); + } + LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); +} + +#endif // TC_MINIMIZE_CODE_SIZE + + +#ifndef TC_MINIMIZE_CODE_SIZE + +void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) +{ + unsigned __int32 a, b, c, d, e; + unsigned int i=1; + const unsigned __int32 *k = (unsigned __int32 *)ks + 8; + unsigned __int32 *in = (unsigned __int32 *) inBlock; + unsigned __int32 *out = (unsigned __int32 *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + do + { + beforeS0(KX); beforeS0(S0); afterS0(LT); + afterS0(KX); afterS0(S1); afterS1(LT); + afterS1(KX); afterS1(S2); afterS2(LT); + afterS2(KX); afterS2(S3); afterS3(LT); + afterS3(KX); afterS3(S4); afterS4(LT); + afterS4(KX); afterS4(S5); afterS5(LT); + afterS5(KX); afterS5(S6); afterS6(LT); + afterS6(KX); afterS6(S7); + + if (i == 4) + break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + beforeS0(LT); + } + while (1); + + afterS7(KX); + + out[0] = LE32(d); + out[1] = LE32(e); + out[2] = LE32(b); + out[3] = LE32(a); +} + +#else // TC_MINIMIZE_CODE_SIZE + +typedef unsigned __int32 uint32; + +static void LTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) +{ + *a = rotlFixed(*a, 13); + *c = rotlFixed(*c, 3); + *d = rotlFixed(*d ^ *c ^ (*a << 3), 7); + *b = rotlFixed(*b ^ *a ^ *c, 1); + *a = rotlFixed(*a ^ *b ^ *d, 5); + *c = rotlFixed(*c ^ *d ^ (*b << 7), 22); +} + +void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) +{ + unsigned __int32 a, b, c, d, e; + unsigned int i=1; + const unsigned __int32 *k = (unsigned __int32 *)ks + 8; + unsigned __int32 *in = (unsigned __int32 *) inBlock; + unsigned __int32 *out = (unsigned __int32 *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + do + { + KXf (k, 0, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); LTf (&b, &e, &c, &a); + KXf (k, 4, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); LTf (&c, &b, &a, &e); + KXf (k, 8, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); LTf (&a, &e, &b, &d); + KXf (k, 12, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); LTf (&e, &b, &d, &c); + KXf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); LTf (&b, &a, &e, &c); + KXf (k, 20, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); LTf (&a, &c, &b, &e); + KXf (k, 24, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); LTf (&a, &c, &d, &b); + KXf (k, 28, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); + + if (i == 4) + break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + LTf (&a,&b,&c,&d); + } + while (1); + + KXf (k, 32, &d, &e, &b, &a); + + out[0] = LE32(d); + out[1] = LE32(e); + out[2] = LE32(b); + out[3] = LE32(a); +} + +#endif // TC_MINIMIZE_CODE_SIZE + +#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_SERPENT) + +void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) +{ + unsigned __int32 a, b, c, d, e; + const unsigned __int32 *k = (unsigned __int32 *)ks + 104; + unsigned int i=4; + unsigned __int32 *in = (unsigned __int32 *) inBlock; + unsigned __int32 *out = (unsigned __int32 *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + beforeI7(KX); + goto start; + + do + { + c = b; + b = d; + d = e; + k -= 32; + beforeI7(ILT); +start: + beforeI7(I7); afterI7(KX); + afterI7(ILT); afterI7(I6); afterI6(KX); + afterI6(ILT); afterI6(I5); afterI5(KX); + afterI5(ILT); afterI5(I4); afterI4(KX); + afterI4(ILT); afterI4(I3); afterI3(KX); + afterI3(ILT); afterI3(I2); afterI2(KX); + afterI2(ILT); afterI2(I1); afterI1(KX); + afterI1(ILT); afterI1(I0); afterI0(KX); + } + while (--i != 0); + + out[0] = LE32(a); + out[1] = LE32(d); + out[2] = LE32(b); + out[3] = LE32(e); +} + +#else // TC_MINIMIZE_CODE_SIZE && !TC_WINDOWS_BOOT_SERPENT + +static void ILTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) +{ + *c = rotrFixed(*c, 22); + *a = rotrFixed(*a, 5); + *c ^= *d ^ (*b << 7); + *a ^= *b ^ *d; + *b = rotrFixed(*b, 1); + *d = rotrFixed(*d, 7) ^ *c ^ (*a << 3); + *b ^= *a ^ *c; + *c = rotrFixed(*c, 3); + *a = rotrFixed(*a, 13); +} + +void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) +{ + unsigned __int32 a, b, c, d, e; + const unsigned __int32 *k = (unsigned __int32 *)ks + 104; + unsigned int i=4; + unsigned __int32 *in = (unsigned __int32 *) inBlock; + unsigned __int32 *out = (unsigned __int32 *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + KXf (k, 32, &a, &b, &c, &d); + goto start; + + do + { + c = b; + b = d; + d = e; + k -= 32; + beforeI7(ILT); +start: + beforeI7(I7); KXf (k, 28, &d, &a, &b, &e); + ILTf (&d, &a, &b, &e); afterI7(I6); KXf (k, 24, &a, &b, &c, &e); + ILTf (&a, &b, &c, &e); afterI6(I5); KXf (k, 20, &b, &d, &e, &c); + ILTf (&b, &d, &e, &c); afterI5(I4); KXf (k, 16, &b, &c, &e, &a); + ILTf (&b, &c, &e, &a); afterI4(I3); KXf (k, 12, &a, &b, &e, &c); + ILTf (&a, &b, &e, &c); afterI3(I2); KXf (k, 8, &b, &d, &e, &c); + ILTf (&b, &d, &e, &c); afterI2(I1); KXf (k, 4, &a, &b, &c, &e); + ILTf (&a, &b, &c, &e); afterI1(I0); KXf (k, 0, &a, &d, &b, &e); + } + while (--i != 0); + + out[0] = LE32(a); + out[1] = LE32(d); + out[2] = LE32(b); + out[3] = LE32(e); +} + +#endif // TC_MINIMIZE_CODE_SIZE && !TC_WINDOWS_BOOT_SERPENT diff --git a/Crypto/Serpent.h b/Crypto/Serpent.h index 47d35f8..7c64d19 100644 --- a/Crypto/Serpent.h +++ b/Crypto/Serpent.h @@ -1,19 +1,19 @@ -#ifndef HEADER_Crypto_Serpent -#define HEADER_Crypto_Serpent - -#include "Common/Tcdefs.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks); -void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks); -void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks); - -#ifdef __cplusplus -} -#endif - -#endif // HEADER_Crypto_Serpent +#ifndef HEADER_Crypto_Serpent +#define HEADER_Crypto_Serpent + +#include "Common/Tcdefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks); +void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks); +void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks); + +#ifdef __cplusplus +} +#endif + +#endif // HEADER_Crypto_Serpent diff --git a/Crypto/Sha2.c b/Crypto/Sha2.c index 9ae8c1c..98a9c01 100644 --- a/Crypto/Sha2.c +++ b/Crypto/Sha2.c @@ -1,770 +1,770 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 01/08/2005 - - This is a byte oriented version of SHA2 that operates on arrays of bytes - stored in memory. This code implements sha256, sha384 and sha512 but the - latter two functions rely on efficient 64-bit integer operations that - may not be very efficient on 32-bit machines - - The sha256 functions use a type 'sha256_ctx' to hold details of the - current hash state and uses the following three calls: - - void sha256_begin(sha256_ctx ctx[1]) - void sha256_hash(const unsigned char data[], - unsigned long len, sha256_ctx ctx[1]) - void sha_end1(unsigned char hval[], sha256_ctx ctx[1]) - - The first subroutine initialises a hash computation by setting up the - context in the sha256_ctx context. The second subroutine hashes 8-bit - bytes from array data[] into the hash state withinh sha256_ctx context, - the number of bytes to be hashed being given by the the unsigned long - integer len. The third subroutine completes the hash calculation and - places the resulting digest value in the array of 8-bit bytes hval[]. - - The sha384 and sha512 functions are similar and use the interfaces: - - void sha384_begin(sha384_ctx ctx[1]); - void sha384_hash(const unsigned char data[], - unsigned long len, sha384_ctx ctx[1]); - void sha384_end(unsigned char hval[], sha384_ctx ctx[1]); - - void sha512_begin(sha512_ctx ctx[1]); - void sha512_hash(const unsigned char data[], - unsigned long len, sha512_ctx ctx[1]); - void sha512_end(unsigned char hval[], sha512_ctx ctx[1]); - - In addition there is a function sha2 that can be used to call all these - functions using a call with a hash length parameter as follows: - - int sha2_begin(unsigned long len, sha2_ctx ctx[1]); - void sha2_hash(const unsigned char data[], - unsigned long len, sha2_ctx ctx[1]); - void sha2_end(unsigned char hval[], sha2_ctx ctx[1]); - - My thanks to Erik Andersen for testing this code - on big-endian systems and for his assistance with corrections -*/ - -#include "Common/Endian.h" -#define PLATFORM_BYTE_ORDER BYTE_ORDER -#define IS_LITTLE_ENDIAN LITTLE_ENDIAN - -#if 0 -#define UNROLL_SHA2 /* for SHA2 loop unroll */ -#endif - -#include /* for memcpy() etc. */ - -#include "Sha2.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) -#pragma intrinsic(memcpy) -#endif - -#if 0 && defined(_MSC_VER) -#define rotl32 _lrotl -#define rotr32 _lrotr -#else -#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) -#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) -#endif - -#if !defined(bswap_32) -#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) -#endif - -#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) -#define SWAP_BYTES -#else -#undef SWAP_BYTES -#endif - -#if 0 - -#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -#else /* Thanks to Rich Schroeppel and Colin Plumb for the following */ - -#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) - -#endif - -/* round transforms for SHA256 and SHA512 compression functions */ - -#define vf(n,i) v[(n - i) & 7] - -#define hf(i) (p[i & 15] += \ - g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15])) - -#define v_cycle(i,j) \ - vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \ - + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \ - vf(3,i) += vf(7,i); \ - vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i)) - -#if defined(SHA_224) || defined(SHA_256) - -#define SHA256_MASK (SHA256_BLOCK_SIZE - 1) - -#if defined(SWAP_BYTES) -#define bsw_32(p,n) \ - { int _i = (n); while(_i--) ((uint_32t*)p)[_i] = bswap_32(((uint_32t*)p)[_i]); } -#else -#define bsw_32(p,n) -#endif - -#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) -#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) -#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) -#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) -#define k_0 k256 - -/* rotated SHA256 round definition. Rather than swapping variables as in */ -/* FIPS-180, different variables are 'rotated' on each round, returning */ -/* to their starting positions every eight rounds */ - -#define q(n) v##n - -#define one_cycle(a,b,c,d,e,f,g,h,k,w) \ - q(h) += s_1(q(e)) + ch(q(e), q(f), q(g)) + k + w; \ - q(d) += q(h); q(h) += s_0(q(a)) + maj(q(a), q(b), q(c)) - -/* SHA256 mixing data */ - -const uint_32t k256[64] = -{ 0x428a2f98ul, 0x71374491ul, 0xb5c0fbcful, 0xe9b5dba5ul, - 0x3956c25bul, 0x59f111f1ul, 0x923f82a4ul, 0xab1c5ed5ul, - 0xd807aa98ul, 0x12835b01ul, 0x243185beul, 0x550c7dc3ul, - 0x72be5d74ul, 0x80deb1feul, 0x9bdc06a7ul, 0xc19bf174ul, - 0xe49b69c1ul, 0xefbe4786ul, 0x0fc19dc6ul, 0x240ca1ccul, - 0x2de92c6ful, 0x4a7484aaul, 0x5cb0a9dcul, 0x76f988daul, - 0x983e5152ul, 0xa831c66dul, 0xb00327c8ul, 0xbf597fc7ul, - 0xc6e00bf3ul, 0xd5a79147ul, 0x06ca6351ul, 0x14292967ul, - 0x27b70a85ul, 0x2e1b2138ul, 0x4d2c6dfcul, 0x53380d13ul, - 0x650a7354ul, 0x766a0abbul, 0x81c2c92eul, 0x92722c85ul, - 0xa2bfe8a1ul, 0xa81a664bul, 0xc24b8b70ul, 0xc76c51a3ul, - 0xd192e819ul, 0xd6990624ul, 0xf40e3585ul, 0x106aa070ul, - 0x19a4c116ul, 0x1e376c08ul, 0x2748774cul, 0x34b0bcb5ul, - 0x391c0cb3ul, 0x4ed8aa4aul, 0x5b9cca4ful, 0x682e6ff3ul, - 0x748f82eeul, 0x78a5636ful, 0x84c87814ul, 0x8cc70208ul, - 0x90befffaul, 0xa4506cebul, 0xbef9a3f7ul, 0xc67178f2ul, -}; - -/* Compile 64 bytes of hash data into SHA256 digest value */ -/* NOTE: this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is such that low address bytes */ -/* in the ORIGINAL byte stream will go into the high end of */ -/* words on BOTH big and little endian systems */ - -VOID_RETURN sha256_compile(sha256_ctx ctx[1]) -{ -#if !defined(UNROLL_SHA2) - - uint_32t j, *p = ctx->wbuf, v[8]; - - memcpy(v, ctx->hash, 8 * sizeof(uint_32t)); - - for(j = 0; j < 64; j += 16) - { - v_cycle( 0, j); v_cycle( 1, j); - v_cycle( 2, j); v_cycle( 3, j); - v_cycle( 4, j); v_cycle( 5, j); - v_cycle( 6, j); v_cycle( 7, j); - v_cycle( 8, j); v_cycle( 9, j); - v_cycle(10, j); v_cycle(11, j); - v_cycle(12, j); v_cycle(13, j); - v_cycle(14, j); v_cycle(15, j); - } - - ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; - ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; - ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; - ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; - -#else - - uint_32t *p = ctx->wbuf,v0,v1,v2,v3,v4,v5,v6,v7; - - v0 = ctx->hash[0]; v1 = ctx->hash[1]; - v2 = ctx->hash[2]; v3 = ctx->hash[3]; - v4 = ctx->hash[4]; v5 = ctx->hash[5]; - v6 = ctx->hash[6]; v7 = ctx->hash[7]; - - one_cycle(0,1,2,3,4,5,6,7,k256[ 0],p[ 0]); - one_cycle(7,0,1,2,3,4,5,6,k256[ 1],p[ 1]); - one_cycle(6,7,0,1,2,3,4,5,k256[ 2],p[ 2]); - one_cycle(5,6,7,0,1,2,3,4,k256[ 3],p[ 3]); - one_cycle(4,5,6,7,0,1,2,3,k256[ 4],p[ 4]); - one_cycle(3,4,5,6,7,0,1,2,k256[ 5],p[ 5]); - one_cycle(2,3,4,5,6,7,0,1,k256[ 6],p[ 6]); - one_cycle(1,2,3,4,5,6,7,0,k256[ 7],p[ 7]); - one_cycle(0,1,2,3,4,5,6,7,k256[ 8],p[ 8]); - one_cycle(7,0,1,2,3,4,5,6,k256[ 9],p[ 9]); - one_cycle(6,7,0,1,2,3,4,5,k256[10],p[10]); - one_cycle(5,6,7,0,1,2,3,4,k256[11],p[11]); - one_cycle(4,5,6,7,0,1,2,3,k256[12],p[12]); - one_cycle(3,4,5,6,7,0,1,2,k256[13],p[13]); - one_cycle(2,3,4,5,6,7,0,1,k256[14],p[14]); - one_cycle(1,2,3,4,5,6,7,0,k256[15],p[15]); - - one_cycle(0,1,2,3,4,5,6,7,k256[16],hf( 0)); - one_cycle(7,0,1,2,3,4,5,6,k256[17],hf( 1)); - one_cycle(6,7,0,1,2,3,4,5,k256[18],hf( 2)); - one_cycle(5,6,7,0,1,2,3,4,k256[19],hf( 3)); - one_cycle(4,5,6,7,0,1,2,3,k256[20],hf( 4)); - one_cycle(3,4,5,6,7,0,1,2,k256[21],hf( 5)); - one_cycle(2,3,4,5,6,7,0,1,k256[22],hf( 6)); - one_cycle(1,2,3,4,5,6,7,0,k256[23],hf( 7)); - one_cycle(0,1,2,3,4,5,6,7,k256[24],hf( 8)); - one_cycle(7,0,1,2,3,4,5,6,k256[25],hf( 9)); - one_cycle(6,7,0,1,2,3,4,5,k256[26],hf(10)); - one_cycle(5,6,7,0,1,2,3,4,k256[27],hf(11)); - one_cycle(4,5,6,7,0,1,2,3,k256[28],hf(12)); - one_cycle(3,4,5,6,7,0,1,2,k256[29],hf(13)); - one_cycle(2,3,4,5,6,7,0,1,k256[30],hf(14)); - one_cycle(1,2,3,4,5,6,7,0,k256[31],hf(15)); - - one_cycle(0,1,2,3,4,5,6,7,k256[32],hf( 0)); - one_cycle(7,0,1,2,3,4,5,6,k256[33],hf( 1)); - one_cycle(6,7,0,1,2,3,4,5,k256[34],hf( 2)); - one_cycle(5,6,7,0,1,2,3,4,k256[35],hf( 3)); - one_cycle(4,5,6,7,0,1,2,3,k256[36],hf( 4)); - one_cycle(3,4,5,6,7,0,1,2,k256[37],hf( 5)); - one_cycle(2,3,4,5,6,7,0,1,k256[38],hf( 6)); - one_cycle(1,2,3,4,5,6,7,0,k256[39],hf( 7)); - one_cycle(0,1,2,3,4,5,6,7,k256[40],hf( 8)); - one_cycle(7,0,1,2,3,4,5,6,k256[41],hf( 9)); - one_cycle(6,7,0,1,2,3,4,5,k256[42],hf(10)); - one_cycle(5,6,7,0,1,2,3,4,k256[43],hf(11)); - one_cycle(4,5,6,7,0,1,2,3,k256[44],hf(12)); - one_cycle(3,4,5,6,7,0,1,2,k256[45],hf(13)); - one_cycle(2,3,4,5,6,7,0,1,k256[46],hf(14)); - one_cycle(1,2,3,4,5,6,7,0,k256[47],hf(15)); - - one_cycle(0,1,2,3,4,5,6,7,k256[48],hf( 0)); - one_cycle(7,0,1,2,3,4,5,6,k256[49],hf( 1)); - one_cycle(6,7,0,1,2,3,4,5,k256[50],hf( 2)); - one_cycle(5,6,7,0,1,2,3,4,k256[51],hf( 3)); - one_cycle(4,5,6,7,0,1,2,3,k256[52],hf( 4)); - one_cycle(3,4,5,6,7,0,1,2,k256[53],hf( 5)); - one_cycle(2,3,4,5,6,7,0,1,k256[54],hf( 6)); - one_cycle(1,2,3,4,5,6,7,0,k256[55],hf( 7)); - one_cycle(0,1,2,3,4,5,6,7,k256[56],hf( 8)); - one_cycle(7,0,1,2,3,4,5,6,k256[57],hf( 9)); - one_cycle(6,7,0,1,2,3,4,5,k256[58],hf(10)); - one_cycle(5,6,7,0,1,2,3,4,k256[59],hf(11)); - one_cycle(4,5,6,7,0,1,2,3,k256[60],hf(12)); - one_cycle(3,4,5,6,7,0,1,2,k256[61],hf(13)); - one_cycle(2,3,4,5,6,7,0,1,k256[62],hf(14)); - one_cycle(1,2,3,4,5,6,7,0,k256[63],hf(15)); - - ctx->hash[0] += v0; ctx->hash[1] += v1; - ctx->hash[2] += v2; ctx->hash[3] += v3; - ctx->hash[4] += v4; ctx->hash[5] += v5; - ctx->hash[6] += v6; ctx->hash[7] += v7; -#endif -} - -/* SHA256 hash data in an array of bytes into hash buffer */ -/* and call the hash_compile function as required. */ - -VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]) -{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA256_MASK), - space = SHA256_BLOCK_SIZE - pos; - const unsigned char *sp = data; - - if((ctx->count[0] += len) < len) - ++(ctx->count[1]); - - while(len >= space) /* tranfer whole blocks while possible */ - { - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); - sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0; - bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2) - sha256_compile(ctx); - } - - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); -} - -/* SHA256 Final padding and digest calculation */ - -static void sha_end1(unsigned char hval[], sha256_ctx ctx[1], const unsigned int hlen) -{ uint_32t i = (uint_32t)(ctx->count[0] & SHA256_MASK); - - /* put bytes in the buffer in an order in which references to */ - /* 32-bit words will put bytes with lower addresses into the */ - /* top of 32 bit words on BOTH big and little endian machines */ - bsw_32(ctx->wbuf, (i + 3) >> 2) - - /* we now need to mask valid bytes and add the padding which is */ - /* a single 1 bit and as many zero bits as necessary. Note that */ - /* we can always add the first padding byte here because the */ - /* buffer always has at least one empty slot */ - ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); - ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); - - /* we need 9 or more empty positions, one for the padding byte */ - /* (above) and eight for the length count. If there is not */ - /* enough space pad and empty the buffer */ - if(i > SHA256_BLOCK_SIZE - 9) - { - if(i < 60) ctx->wbuf[15] = 0; - sha256_compile(ctx); - i = 0; - } - else /* compute a word index for the empty buffer positions */ - i = (i >> 2) + 1; - - while(i < 14) /* and zero pad all but last two positions */ - ctx->wbuf[i++] = 0; - - /* the following 32-bit length fields are assembled in the */ - /* wrong byte order on little endian machines but this is */ - /* corrected later since they are only ever used as 32-bit */ - /* word values. */ - ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); - ctx->wbuf[15] = ctx->count[0] << 3; - sha256_compile(ctx); - - /* extract the hash value as bytes in case the hash buffer is */ - /* mislaigned for 32-bit words */ - for(i = 0; i < hlen; ++i) - hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); -} - -#endif - -#if defined(SHA_224) - -const uint_32t i224[8] = -{ - 0xc1059ed8ul, 0x367cd507ul, 0x3070dd17ul, 0xf70e5939ul, - 0xffc00b31ul, 0x68581511ul, 0x64f98fa7ul, 0xbefa4fa4ul -}; - -VOID_RETURN sha224_begin(sha224_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i224, 8 * sizeof(uint_32t)); -} - -VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]) -{ - sha_end1(hval, ctx, SHA224_DIGEST_SIZE); -} - -VOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha224_ctx cx[1]; - - sha224_begin(cx); - sha224_hash(data, len, cx); - sha_end1(hval, cx, SHA224_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_256) - -const uint_32t i256[8] = -{ - 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, - 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul -}; - -VOID_RETURN sha256_begin(sha256_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i256, 8 * sizeof(uint_32t)); -} - -VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]) -{ - sha_end1(hval, ctx, SHA256_DIGEST_SIZE); -} - -VOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha256_ctx cx[1]; - - sha256_begin(cx); - sha256_hash(data, len, cx); - sha_end1(hval, cx, SHA256_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_384) || defined(SHA_512) - -#define SHA512_MASK (SHA512_BLOCK_SIZE - 1) - -#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n))) - -#if !defined(bswap_64) -#define bswap_64(x) (((uint_64t)(bswap_32((uint_32t)(x)))) << 32 | bswap_32((uint_32t)((x) >> 32))) -#endif - -#if defined(SWAP_BYTES) -#define bsw_64(p,n) \ - { int _i = (n); while(_i--) ((uint_64t*)p)[_i] = bswap_64(((uint_64t*)p)[_i]); } -#else -#define bsw_64(p,n) -#endif - -/* SHA512 mixing function definitions */ - -#ifdef s_0 -# undef s_0 -# undef s_1 -# undef g_0 -# undef g_1 -# undef k_0 -#endif - -#define s_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39)) -#define s_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41)) -#define g_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7)) -#define g_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6)) -#define k_0 k512 - -/* SHA384/SHA512 mixing data */ - -const uint_64t k512[80] = -{ - li_64(428a2f98d728ae22), li_64(7137449123ef65cd), - li_64(b5c0fbcfec4d3b2f), li_64(e9b5dba58189dbbc), - li_64(3956c25bf348b538), li_64(59f111f1b605d019), - li_64(923f82a4af194f9b), li_64(ab1c5ed5da6d8118), - li_64(d807aa98a3030242), li_64(12835b0145706fbe), - li_64(243185be4ee4b28c), li_64(550c7dc3d5ffb4e2), - li_64(72be5d74f27b896f), li_64(80deb1fe3b1696b1), - li_64(9bdc06a725c71235), li_64(c19bf174cf692694), - li_64(e49b69c19ef14ad2), li_64(efbe4786384f25e3), - li_64(0fc19dc68b8cd5b5), li_64(240ca1cc77ac9c65), - li_64(2de92c6f592b0275), li_64(4a7484aa6ea6e483), - li_64(5cb0a9dcbd41fbd4), li_64(76f988da831153b5), - li_64(983e5152ee66dfab), li_64(a831c66d2db43210), - li_64(b00327c898fb213f), li_64(bf597fc7beef0ee4), - li_64(c6e00bf33da88fc2), li_64(d5a79147930aa725), - li_64(06ca6351e003826f), li_64(142929670a0e6e70), - li_64(27b70a8546d22ffc), li_64(2e1b21385c26c926), - li_64(4d2c6dfc5ac42aed), li_64(53380d139d95b3df), - li_64(650a73548baf63de), li_64(766a0abb3c77b2a8), - li_64(81c2c92e47edaee6), li_64(92722c851482353b), - li_64(a2bfe8a14cf10364), li_64(a81a664bbc423001), - li_64(c24b8b70d0f89791), li_64(c76c51a30654be30), - li_64(d192e819d6ef5218), li_64(d69906245565a910), - li_64(f40e35855771202a), li_64(106aa07032bbd1b8), - li_64(19a4c116b8d2d0c8), li_64(1e376c085141ab53), - li_64(2748774cdf8eeb99), li_64(34b0bcb5e19b48a8), - li_64(391c0cb3c5c95a63), li_64(4ed8aa4ae3418acb), - li_64(5b9cca4f7763e373), li_64(682e6ff3d6b2b8a3), - li_64(748f82ee5defb2fc), li_64(78a5636f43172f60), - li_64(84c87814a1f0ab72), li_64(8cc702081a6439ec), - li_64(90befffa23631e28), li_64(a4506cebde82bde9), - li_64(bef9a3f7b2c67915), li_64(c67178f2e372532b), - li_64(ca273eceea26619c), li_64(d186b8c721c0c207), - li_64(eada7dd6cde0eb1e), li_64(f57d4f7fee6ed178), - li_64(06f067aa72176fba), li_64(0a637dc5a2c898a6), - li_64(113f9804bef90dae), li_64(1b710b35131c471b), - li_64(28db77f523047d84), li_64(32caab7b40c72493), - li_64(3c9ebe0a15c9bebc), li_64(431d67c49c100d4c), - li_64(4cc5d4becb3e42b6), li_64(597f299cfc657e2a), - li_64(5fcb6fab3ad6faec), li_64(6c44198c4a475817) -}; - -/* Compile 128 bytes of hash data into SHA384/512 digest */ -/* NOTE: this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is such that low address bytes */ -/* in the ORIGINAL byte stream will go into the high end of */ -/* words on BOTH big and little endian systems */ - -VOID_RETURN sha512_compile(sha512_ctx ctx[1]) -{ uint_64t v[8], *p = ctx->wbuf; - uint_32t j; - - memcpy(v, ctx->hash, 8 * sizeof(uint_64t)); - - for(j = 0; j < 80; j += 16) - { - v_cycle( 0, j); v_cycle( 1, j); - v_cycle( 2, j); v_cycle( 3, j); - v_cycle( 4, j); v_cycle( 5, j); - v_cycle( 6, j); v_cycle( 7, j); - v_cycle( 8, j); v_cycle( 9, j); - v_cycle(10, j); v_cycle(11, j); - v_cycle(12, j); v_cycle(13, j); - v_cycle(14, j); v_cycle(15, j); - } - - ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; - ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; - ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; - ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; -} - -/* Compile 128 bytes of hash data into SHA256 digest value */ -/* NOTE: this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is in such an order that low */ -/* address bytes in the ORIGINAL byte stream placed in this */ -/* buffer will now go to the high end of words on BOTH big */ -/* and little endian systems */ - -VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]) -{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA512_MASK), - space = SHA512_BLOCK_SIZE - pos; - const unsigned char *sp = data; - - if((ctx->count[0] += len) < len) - ++(ctx->count[1]); - - while(len >= space) /* tranfer whole blocks while possible */ - { - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); - sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0; - bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3); - sha512_compile(ctx); - } - - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); -} - -/* SHA384/512 Final padding and digest calculation */ - -static void sha_end2(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen) -{ uint_32t i = (uint_32t)(ctx->count[0] & SHA512_MASK); - - /* put bytes in the buffer in an order in which references to */ - /* 32-bit words will put bytes with lower addresses into the */ - /* top of 32 bit words on BOTH big and little endian machines */ - bsw_64(ctx->wbuf, (i + 7) >> 3); - - /* we now need to mask valid bytes and add the padding which is */ - /* a single 1 bit and as many zero bits as necessary. Note that */ - /* we can always add the first padding byte here because the */ - /* buffer always has at least one empty slot */ - ctx->wbuf[i >> 3] &= li_64(ffffffffffffff00) << 8 * (~i & 7); - ctx->wbuf[i >> 3] |= li_64(0000000000000080) << 8 * (~i & 7); - - /* we need 17 or more empty byte positions, one for the padding */ - /* byte (above) and sixteen for the length count. If there is */ - /* not enough space pad and empty the buffer */ - if(i > SHA512_BLOCK_SIZE - 17) - { - if(i < 120) ctx->wbuf[15] = 0; - sha512_compile(ctx); - i = 0; - } - else - i = (i >> 3) + 1; - - while(i < 14) - ctx->wbuf[i++] = 0; - - /* the following 64-bit length fields are assembled in the */ - /* wrong byte order on little endian machines but this is */ - /* corrected later since they are only ever used as 64-bit */ - /* word values. */ - ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61); - ctx->wbuf[15] = ctx->count[0] << 3; - sha512_compile(ctx); - - /* extract the hash value as bytes in case the hash buffer is */ - /* misaligned for 32-bit words */ - for(i = 0; i < hlen; ++i) - hval[i] = (unsigned char)(ctx->hash[i >> 3] >> (8 * (~i & 7))); -} - -#endif - -#if defined(SHA_384) - -/* SHA384 initialisation data */ - -const uint_64t i384[80] = -{ - li_64(cbbb9d5dc1059ed8), li_64(629a292a367cd507), - li_64(9159015a3070dd17), li_64(152fecd8f70e5939), - li_64(67332667ffc00b31), li_64(8eb44a8768581511), - li_64(db0c2e0d64f98fa7), li_64(47b5481dbefa4fa4) -}; - -VOID_RETURN sha384_begin(sha384_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i384, 8 * sizeof(uint_64t)); -} - -VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]) -{ - sha_end2(hval, ctx, SHA384_DIGEST_SIZE); -} - -VOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha384_ctx cx[1]; - - sha384_begin(cx); - sha384_hash(data, len, cx); - sha_end2(hval, cx, SHA384_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_512) - -/* SHA512 initialisation data */ - -const uint_64t i512[80] = -{ - li_64(6a09e667f3bcc908), li_64(bb67ae8584caa73b), - li_64(3c6ef372fe94f82b), li_64(a54ff53a5f1d36f1), - li_64(510e527fade682d1), li_64(9b05688c2b3e6c1f), - li_64(1f83d9abfb41bd6b), li_64(5be0cd19137e2179) -}; - -VOID_RETURN sha512_begin(sha512_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i512, 8 * sizeof(uint_64t)); -} - -VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]) -{ - sha_end2(hval, ctx, SHA512_DIGEST_SIZE); -} - -VOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha512_ctx cx[1]; - - sha512_begin(cx); - sha512_hash(data, len, cx); - sha_end2(hval, cx, SHA512_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_2) - -#define CTX_224(x) ((x)->uu->ctx256) -#define CTX_256(x) ((x)->uu->ctx256) -#define CTX_384(x) ((x)->uu->ctx512) -#define CTX_512(x) ((x)->uu->ctx512) - -/* SHA2 initialisation */ - -INT_RETURN sha2_begin(unsigned long len, sha2_ctx ctx[1]) -{ - switch(len) - { -#if defined(SHA_224) - case 224: - case 28: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; - memcpy(CTX_256(ctx)->hash, i224, 32); - ctx->sha2_len = 28; return EXIT_SUCCESS; -#endif -#if defined(SHA_256) - case 256: - case 32: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; - memcpy(CTX_256(ctx)->hash, i256, 32); - ctx->sha2_len = 32; return EXIT_SUCCESS; -#endif -#if defined(SHA_384) - case 384: - case 48: CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0; - memcpy(CTX_384(ctx)->hash, i384, 64); - ctx->sha2_len = 48; return EXIT_SUCCESS; -#endif -#if defined(SHA_512) - case 512: - case 64: CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0; - memcpy(CTX_512(ctx)->hash, i512, 64); - ctx->sha2_len = 64; return EXIT_SUCCESS; -#endif - default: return EXIT_FAILURE; - } -} - -VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]) -{ - switch(ctx->sha2_len) - { -#if defined(SHA_224) - case 28: sha224_hash(data, len, CTX_224(ctx)); return; -#endif -#if defined(SHA_256) - case 32: sha256_hash(data, len, CTX_256(ctx)); return; -#endif -#if defined(SHA_384) - case 48: sha384_hash(data, len, CTX_384(ctx)); return; -#endif -#if defined(SHA_512) - case 64: sha512_hash(data, len, CTX_512(ctx)); return; -#endif - } -} - -VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]) -{ - switch(ctx->sha2_len) - { -#if defined(SHA_224) - case 28: sha_end1(hval, CTX_224(ctx), SHA224_DIGEST_SIZE); return; -#endif -#if defined(SHA_256) - case 32: sha_end1(hval, CTX_256(ctx), SHA256_DIGEST_SIZE); return; -#endif -#if defined(SHA_384) - case 48: sha_end2(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return; -#endif -#if defined(SHA_512) - case 64: sha_end2(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return; -#endif - } -} - -INT_RETURN sha2(unsigned char hval[], unsigned long size, - const unsigned char data[], unsigned long len) -{ sha2_ctx cx[1]; - - if(sha2_begin(size, cx) == EXIT_SUCCESS) - { - sha2_hash(data, len, cx); sha2_end(hval, cx); return EXIT_SUCCESS; - } - else - return EXIT_FAILURE; -} - -#endif - -#if defined(__cplusplus) -} -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 01/08/2005 + + This is a byte oriented version of SHA2 that operates on arrays of bytes + stored in memory. This code implements sha256, sha384 and sha512 but the + latter two functions rely on efficient 64-bit integer operations that + may not be very efficient on 32-bit machines + + The sha256 functions use a type 'sha256_ctx' to hold details of the + current hash state and uses the following three calls: + + void sha256_begin(sha256_ctx ctx[1]) + void sha256_hash(const unsigned char data[], + unsigned long len, sha256_ctx ctx[1]) + void sha_end1(unsigned char hval[], sha256_ctx ctx[1]) + + The first subroutine initialises a hash computation by setting up the + context in the sha256_ctx context. The second subroutine hashes 8-bit + bytes from array data[] into the hash state withinh sha256_ctx context, + the number of bytes to be hashed being given by the the unsigned long + integer len. The third subroutine completes the hash calculation and + places the resulting digest value in the array of 8-bit bytes hval[]. + + The sha384 and sha512 functions are similar and use the interfaces: + + void sha384_begin(sha384_ctx ctx[1]); + void sha384_hash(const unsigned char data[], + unsigned long len, sha384_ctx ctx[1]); + void sha384_end(unsigned char hval[], sha384_ctx ctx[1]); + + void sha512_begin(sha512_ctx ctx[1]); + void sha512_hash(const unsigned char data[], + unsigned long len, sha512_ctx ctx[1]); + void sha512_end(unsigned char hval[], sha512_ctx ctx[1]); + + In addition there is a function sha2 that can be used to call all these + functions using a call with a hash length parameter as follows: + + int sha2_begin(unsigned long len, sha2_ctx ctx[1]); + void sha2_hash(const unsigned char data[], + unsigned long len, sha2_ctx ctx[1]); + void sha2_end(unsigned char hval[], sha2_ctx ctx[1]); + + My thanks to Erik Andersen for testing this code + on big-endian systems and for his assistance with corrections +*/ + +#include "Common/Endian.h" +#define PLATFORM_BYTE_ORDER BYTE_ORDER +#define IS_LITTLE_ENDIAN LITTLE_ENDIAN + +#if 0 +#define UNROLL_SHA2 /* for SHA2 loop unroll */ +#endif + +#include /* for memcpy() etc. */ + +#include "Sha2.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) +#pragma intrinsic(memcpy) +#endif + +#if 0 && defined(_MSC_VER) +#define rotl32 _lrotl +#define rotr32 _lrotr +#else +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) +#endif + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#if 0 + +#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#else /* Thanks to Rich Schroeppel and Colin Plumb for the following */ + +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) + +#endif + +/* round transforms for SHA256 and SHA512 compression functions */ + +#define vf(n,i) v[(n - i) & 7] + +#define hf(i) (p[i & 15] += \ + g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15])) + +#define v_cycle(i,j) \ + vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \ + + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \ + vf(3,i) += vf(7,i); \ + vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i)) + +#if defined(SHA_224) || defined(SHA_256) + +#define SHA256_MASK (SHA256_BLOCK_SIZE - 1) + +#if defined(SWAP_BYTES) +#define bsw_32(p,n) \ + { int _i = (n); while(_i--) ((uint_32t*)p)[_i] = bswap_32(((uint_32t*)p)[_i]); } +#else +#define bsw_32(p,n) +#endif + +#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) +#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) +#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) +#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) +#define k_0 k256 + +/* rotated SHA256 round definition. Rather than swapping variables as in */ +/* FIPS-180, different variables are 'rotated' on each round, returning */ +/* to their starting positions every eight rounds */ + +#define q(n) v##n + +#define one_cycle(a,b,c,d,e,f,g,h,k,w) \ + q(h) += s_1(q(e)) + ch(q(e), q(f), q(g)) + k + w; \ + q(d) += q(h); q(h) += s_0(q(a)) + maj(q(a), q(b), q(c)) + +/* SHA256 mixing data */ + +const uint_32t k256[64] = +{ 0x428a2f98ul, 0x71374491ul, 0xb5c0fbcful, 0xe9b5dba5ul, + 0x3956c25bul, 0x59f111f1ul, 0x923f82a4ul, 0xab1c5ed5ul, + 0xd807aa98ul, 0x12835b01ul, 0x243185beul, 0x550c7dc3ul, + 0x72be5d74ul, 0x80deb1feul, 0x9bdc06a7ul, 0xc19bf174ul, + 0xe49b69c1ul, 0xefbe4786ul, 0x0fc19dc6ul, 0x240ca1ccul, + 0x2de92c6ful, 0x4a7484aaul, 0x5cb0a9dcul, 0x76f988daul, + 0x983e5152ul, 0xa831c66dul, 0xb00327c8ul, 0xbf597fc7ul, + 0xc6e00bf3ul, 0xd5a79147ul, 0x06ca6351ul, 0x14292967ul, + 0x27b70a85ul, 0x2e1b2138ul, 0x4d2c6dfcul, 0x53380d13ul, + 0x650a7354ul, 0x766a0abbul, 0x81c2c92eul, 0x92722c85ul, + 0xa2bfe8a1ul, 0xa81a664bul, 0xc24b8b70ul, 0xc76c51a3ul, + 0xd192e819ul, 0xd6990624ul, 0xf40e3585ul, 0x106aa070ul, + 0x19a4c116ul, 0x1e376c08ul, 0x2748774cul, 0x34b0bcb5ul, + 0x391c0cb3ul, 0x4ed8aa4aul, 0x5b9cca4ful, 0x682e6ff3ul, + 0x748f82eeul, 0x78a5636ful, 0x84c87814ul, 0x8cc70208ul, + 0x90befffaul, 0xa4506cebul, 0xbef9a3f7ul, 0xc67178f2ul, +}; + +/* Compile 64 bytes of hash data into SHA256 digest value */ +/* NOTE: this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is such that low address bytes */ +/* in the ORIGINAL byte stream will go into the high end of */ +/* words on BOTH big and little endian systems */ + +VOID_RETURN sha256_compile(sha256_ctx ctx[1]) +{ +#if !defined(UNROLL_SHA2) + + uint_32t j, *p = ctx->wbuf, v[8]; + + memcpy(v, ctx->hash, 8 * sizeof(uint_32t)); + + for(j = 0; j < 64; j += 16) + { + v_cycle( 0, j); v_cycle( 1, j); + v_cycle( 2, j); v_cycle( 3, j); + v_cycle( 4, j); v_cycle( 5, j); + v_cycle( 6, j); v_cycle( 7, j); + v_cycle( 8, j); v_cycle( 9, j); + v_cycle(10, j); v_cycle(11, j); + v_cycle(12, j); v_cycle(13, j); + v_cycle(14, j); v_cycle(15, j); + } + + ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; + ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; + ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; + ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; + +#else + + uint_32t *p = ctx->wbuf,v0,v1,v2,v3,v4,v5,v6,v7; + + v0 = ctx->hash[0]; v1 = ctx->hash[1]; + v2 = ctx->hash[2]; v3 = ctx->hash[3]; + v4 = ctx->hash[4]; v5 = ctx->hash[5]; + v6 = ctx->hash[6]; v7 = ctx->hash[7]; + + one_cycle(0,1,2,3,4,5,6,7,k256[ 0],p[ 0]); + one_cycle(7,0,1,2,3,4,5,6,k256[ 1],p[ 1]); + one_cycle(6,7,0,1,2,3,4,5,k256[ 2],p[ 2]); + one_cycle(5,6,7,0,1,2,3,4,k256[ 3],p[ 3]); + one_cycle(4,5,6,7,0,1,2,3,k256[ 4],p[ 4]); + one_cycle(3,4,5,6,7,0,1,2,k256[ 5],p[ 5]); + one_cycle(2,3,4,5,6,7,0,1,k256[ 6],p[ 6]); + one_cycle(1,2,3,4,5,6,7,0,k256[ 7],p[ 7]); + one_cycle(0,1,2,3,4,5,6,7,k256[ 8],p[ 8]); + one_cycle(7,0,1,2,3,4,5,6,k256[ 9],p[ 9]); + one_cycle(6,7,0,1,2,3,4,5,k256[10],p[10]); + one_cycle(5,6,7,0,1,2,3,4,k256[11],p[11]); + one_cycle(4,5,6,7,0,1,2,3,k256[12],p[12]); + one_cycle(3,4,5,6,7,0,1,2,k256[13],p[13]); + one_cycle(2,3,4,5,6,7,0,1,k256[14],p[14]); + one_cycle(1,2,3,4,5,6,7,0,k256[15],p[15]); + + one_cycle(0,1,2,3,4,5,6,7,k256[16],hf( 0)); + one_cycle(7,0,1,2,3,4,5,6,k256[17],hf( 1)); + one_cycle(6,7,0,1,2,3,4,5,k256[18],hf( 2)); + one_cycle(5,6,7,0,1,2,3,4,k256[19],hf( 3)); + one_cycle(4,5,6,7,0,1,2,3,k256[20],hf( 4)); + one_cycle(3,4,5,6,7,0,1,2,k256[21],hf( 5)); + one_cycle(2,3,4,5,6,7,0,1,k256[22],hf( 6)); + one_cycle(1,2,3,4,5,6,7,0,k256[23],hf( 7)); + one_cycle(0,1,2,3,4,5,6,7,k256[24],hf( 8)); + one_cycle(7,0,1,2,3,4,5,6,k256[25],hf( 9)); + one_cycle(6,7,0,1,2,3,4,5,k256[26],hf(10)); + one_cycle(5,6,7,0,1,2,3,4,k256[27],hf(11)); + one_cycle(4,5,6,7,0,1,2,3,k256[28],hf(12)); + one_cycle(3,4,5,6,7,0,1,2,k256[29],hf(13)); + one_cycle(2,3,4,5,6,7,0,1,k256[30],hf(14)); + one_cycle(1,2,3,4,5,6,7,0,k256[31],hf(15)); + + one_cycle(0,1,2,3,4,5,6,7,k256[32],hf( 0)); + one_cycle(7,0,1,2,3,4,5,6,k256[33],hf( 1)); + one_cycle(6,7,0,1,2,3,4,5,k256[34],hf( 2)); + one_cycle(5,6,7,0,1,2,3,4,k256[35],hf( 3)); + one_cycle(4,5,6,7,0,1,2,3,k256[36],hf( 4)); + one_cycle(3,4,5,6,7,0,1,2,k256[37],hf( 5)); + one_cycle(2,3,4,5,6,7,0,1,k256[38],hf( 6)); + one_cycle(1,2,3,4,5,6,7,0,k256[39],hf( 7)); + one_cycle(0,1,2,3,4,5,6,7,k256[40],hf( 8)); + one_cycle(7,0,1,2,3,4,5,6,k256[41],hf( 9)); + one_cycle(6,7,0,1,2,3,4,5,k256[42],hf(10)); + one_cycle(5,6,7,0,1,2,3,4,k256[43],hf(11)); + one_cycle(4,5,6,7,0,1,2,3,k256[44],hf(12)); + one_cycle(3,4,5,6,7,0,1,2,k256[45],hf(13)); + one_cycle(2,3,4,5,6,7,0,1,k256[46],hf(14)); + one_cycle(1,2,3,4,5,6,7,0,k256[47],hf(15)); + + one_cycle(0,1,2,3,4,5,6,7,k256[48],hf( 0)); + one_cycle(7,0,1,2,3,4,5,6,k256[49],hf( 1)); + one_cycle(6,7,0,1,2,3,4,5,k256[50],hf( 2)); + one_cycle(5,6,7,0,1,2,3,4,k256[51],hf( 3)); + one_cycle(4,5,6,7,0,1,2,3,k256[52],hf( 4)); + one_cycle(3,4,5,6,7,0,1,2,k256[53],hf( 5)); + one_cycle(2,3,4,5,6,7,0,1,k256[54],hf( 6)); + one_cycle(1,2,3,4,5,6,7,0,k256[55],hf( 7)); + one_cycle(0,1,2,3,4,5,6,7,k256[56],hf( 8)); + one_cycle(7,0,1,2,3,4,5,6,k256[57],hf( 9)); + one_cycle(6,7,0,1,2,3,4,5,k256[58],hf(10)); + one_cycle(5,6,7,0,1,2,3,4,k256[59],hf(11)); + one_cycle(4,5,6,7,0,1,2,3,k256[60],hf(12)); + one_cycle(3,4,5,6,7,0,1,2,k256[61],hf(13)); + one_cycle(2,3,4,5,6,7,0,1,k256[62],hf(14)); + one_cycle(1,2,3,4,5,6,7,0,k256[63],hf(15)); + + ctx->hash[0] += v0; ctx->hash[1] += v1; + ctx->hash[2] += v2; ctx->hash[3] += v3; + ctx->hash[4] += v4; ctx->hash[5] += v5; + ctx->hash[6] += v6; ctx->hash[7] += v7; +#endif +} + +/* SHA256 hash data in an array of bytes into hash buffer */ +/* and call the hash_compile function as required. */ + +VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]) +{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA256_MASK), + space = SHA256_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks while possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0; + bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2) + sha256_compile(ctx); + } + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA256 Final padding and digest calculation */ + +static void sha_end1(unsigned char hval[], sha256_ctx ctx[1], const unsigned int hlen) +{ uint_32t i = (uint_32t)(ctx->count[0] & SHA256_MASK); + + /* put bytes in the buffer in an order in which references to */ + /* 32-bit words will put bytes with lower addresses into the */ + /* top of 32 bit words on BOTH big and little endian machines */ + bsw_32(ctx->wbuf, (i + 3) >> 2) + + /* we now need to mask valid bytes and add the padding which is */ + /* a single 1 bit and as many zero bits as necessary. Note that */ + /* we can always add the first padding byte here because the */ + /* buffer always has at least one empty slot */ + ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); + ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); + + /* we need 9 or more empty positions, one for the padding byte */ + /* (above) and eight for the length count. If there is not */ + /* enough space pad and empty the buffer */ + if(i > SHA256_BLOCK_SIZE - 9) + { + if(i < 60) ctx->wbuf[15] = 0; + sha256_compile(ctx); + i = 0; + } + else /* compute a word index for the empty buffer positions */ + i = (i >> 2) + 1; + + while(i < 14) /* and zero pad all but last two positions */ + ctx->wbuf[i++] = 0; + + /* the following 32-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 32-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); + ctx->wbuf[15] = ctx->count[0] << 3; + sha256_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* mislaigned for 32-bit words */ + for(i = 0; i < hlen; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); +} + +#endif + +#if defined(SHA_224) + +const uint_32t i224[8] = +{ + 0xc1059ed8ul, 0x367cd507ul, 0x3070dd17ul, 0xf70e5939ul, + 0xffc00b31ul, 0x68581511ul, 0x64f98fa7ul, 0xbefa4fa4ul +}; + +VOID_RETURN sha224_begin(sha224_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i224, 8 * sizeof(uint_32t)); +} + +VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]) +{ + sha_end1(hval, ctx, SHA224_DIGEST_SIZE); +} + +VOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha224_ctx cx[1]; + + sha224_begin(cx); + sha224_hash(data, len, cx); + sha_end1(hval, cx, SHA224_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_256) + +const uint_32t i256[8] = +{ + 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul +}; + +VOID_RETURN sha256_begin(sha256_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i256, 8 * sizeof(uint_32t)); +} + +VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]) +{ + sha_end1(hval, ctx, SHA256_DIGEST_SIZE); +} + +VOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha256_ctx cx[1]; + + sha256_begin(cx); + sha256_hash(data, len, cx); + sha_end1(hval, cx, SHA256_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_384) || defined(SHA_512) + +#define SHA512_MASK (SHA512_BLOCK_SIZE - 1) + +#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n))) + +#if !defined(bswap_64) +#define bswap_64(x) (((uint_64t)(bswap_32((uint_32t)(x)))) << 32 | bswap_32((uint_32t)((x) >> 32))) +#endif + +#if defined(SWAP_BYTES) +#define bsw_64(p,n) \ + { int _i = (n); while(_i--) ((uint_64t*)p)[_i] = bswap_64(((uint_64t*)p)[_i]); } +#else +#define bsw_64(p,n) +#endif + +/* SHA512 mixing function definitions */ + +#ifdef s_0 +# undef s_0 +# undef s_1 +# undef g_0 +# undef g_1 +# undef k_0 +#endif + +#define s_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39)) +#define s_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41)) +#define g_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7)) +#define g_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6)) +#define k_0 k512 + +/* SHA384/SHA512 mixing data */ + +const uint_64t k512[80] = +{ + li_64(428a2f98d728ae22), li_64(7137449123ef65cd), + li_64(b5c0fbcfec4d3b2f), li_64(e9b5dba58189dbbc), + li_64(3956c25bf348b538), li_64(59f111f1b605d019), + li_64(923f82a4af194f9b), li_64(ab1c5ed5da6d8118), + li_64(d807aa98a3030242), li_64(12835b0145706fbe), + li_64(243185be4ee4b28c), li_64(550c7dc3d5ffb4e2), + li_64(72be5d74f27b896f), li_64(80deb1fe3b1696b1), + li_64(9bdc06a725c71235), li_64(c19bf174cf692694), + li_64(e49b69c19ef14ad2), li_64(efbe4786384f25e3), + li_64(0fc19dc68b8cd5b5), li_64(240ca1cc77ac9c65), + li_64(2de92c6f592b0275), li_64(4a7484aa6ea6e483), + li_64(5cb0a9dcbd41fbd4), li_64(76f988da831153b5), + li_64(983e5152ee66dfab), li_64(a831c66d2db43210), + li_64(b00327c898fb213f), li_64(bf597fc7beef0ee4), + li_64(c6e00bf33da88fc2), li_64(d5a79147930aa725), + li_64(06ca6351e003826f), li_64(142929670a0e6e70), + li_64(27b70a8546d22ffc), li_64(2e1b21385c26c926), + li_64(4d2c6dfc5ac42aed), li_64(53380d139d95b3df), + li_64(650a73548baf63de), li_64(766a0abb3c77b2a8), + li_64(81c2c92e47edaee6), li_64(92722c851482353b), + li_64(a2bfe8a14cf10364), li_64(a81a664bbc423001), + li_64(c24b8b70d0f89791), li_64(c76c51a30654be30), + li_64(d192e819d6ef5218), li_64(d69906245565a910), + li_64(f40e35855771202a), li_64(106aa07032bbd1b8), + li_64(19a4c116b8d2d0c8), li_64(1e376c085141ab53), + li_64(2748774cdf8eeb99), li_64(34b0bcb5e19b48a8), + li_64(391c0cb3c5c95a63), li_64(4ed8aa4ae3418acb), + li_64(5b9cca4f7763e373), li_64(682e6ff3d6b2b8a3), + li_64(748f82ee5defb2fc), li_64(78a5636f43172f60), + li_64(84c87814a1f0ab72), li_64(8cc702081a6439ec), + li_64(90befffa23631e28), li_64(a4506cebde82bde9), + li_64(bef9a3f7b2c67915), li_64(c67178f2e372532b), + li_64(ca273eceea26619c), li_64(d186b8c721c0c207), + li_64(eada7dd6cde0eb1e), li_64(f57d4f7fee6ed178), + li_64(06f067aa72176fba), li_64(0a637dc5a2c898a6), + li_64(113f9804bef90dae), li_64(1b710b35131c471b), + li_64(28db77f523047d84), li_64(32caab7b40c72493), + li_64(3c9ebe0a15c9bebc), li_64(431d67c49c100d4c), + li_64(4cc5d4becb3e42b6), li_64(597f299cfc657e2a), + li_64(5fcb6fab3ad6faec), li_64(6c44198c4a475817) +}; + +/* Compile 128 bytes of hash data into SHA384/512 digest */ +/* NOTE: this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is such that low address bytes */ +/* in the ORIGINAL byte stream will go into the high end of */ +/* words on BOTH big and little endian systems */ + +VOID_RETURN sha512_compile(sha512_ctx ctx[1]) +{ uint_64t v[8], *p = ctx->wbuf; + uint_32t j; + + memcpy(v, ctx->hash, 8 * sizeof(uint_64t)); + + for(j = 0; j < 80; j += 16) + { + v_cycle( 0, j); v_cycle( 1, j); + v_cycle( 2, j); v_cycle( 3, j); + v_cycle( 4, j); v_cycle( 5, j); + v_cycle( 6, j); v_cycle( 7, j); + v_cycle( 8, j); v_cycle( 9, j); + v_cycle(10, j); v_cycle(11, j); + v_cycle(12, j); v_cycle(13, j); + v_cycle(14, j); v_cycle(15, j); + } + + ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; + ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; + ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; + ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; +} + +/* Compile 128 bytes of hash data into SHA256 digest value */ +/* NOTE: this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is in such an order that low */ +/* address bytes in the ORIGINAL byte stream placed in this */ +/* buffer will now go to the high end of words on BOTH big */ +/* and little endian systems */ + +VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]) +{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA512_MASK), + space = SHA512_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks while possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0; + bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3); + sha512_compile(ctx); + } + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA384/512 Final padding and digest calculation */ + +static void sha_end2(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen) +{ uint_32t i = (uint_32t)(ctx->count[0] & SHA512_MASK); + + /* put bytes in the buffer in an order in which references to */ + /* 32-bit words will put bytes with lower addresses into the */ + /* top of 32 bit words on BOTH big and little endian machines */ + bsw_64(ctx->wbuf, (i + 7) >> 3); + + /* we now need to mask valid bytes and add the padding which is */ + /* a single 1 bit and as many zero bits as necessary. Note that */ + /* we can always add the first padding byte here because the */ + /* buffer always has at least one empty slot */ + ctx->wbuf[i >> 3] &= li_64(ffffffffffffff00) << 8 * (~i & 7); + ctx->wbuf[i >> 3] |= li_64(0000000000000080) << 8 * (~i & 7); + + /* we need 17 or more empty byte positions, one for the padding */ + /* byte (above) and sixteen for the length count. If there is */ + /* not enough space pad and empty the buffer */ + if(i > SHA512_BLOCK_SIZE - 17) + { + if(i < 120) ctx->wbuf[15] = 0; + sha512_compile(ctx); + i = 0; + } + else + i = (i >> 3) + 1; + + while(i < 14) + ctx->wbuf[i++] = 0; + + /* the following 64-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 64-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61); + ctx->wbuf[15] = ctx->count[0] << 3; + sha512_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* misaligned for 32-bit words */ + for(i = 0; i < hlen; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 3] >> (8 * (~i & 7))); +} + +#endif + +#if defined(SHA_384) + +/* SHA384 initialisation data */ + +const uint_64t i384[80] = +{ + li_64(cbbb9d5dc1059ed8), li_64(629a292a367cd507), + li_64(9159015a3070dd17), li_64(152fecd8f70e5939), + li_64(67332667ffc00b31), li_64(8eb44a8768581511), + li_64(db0c2e0d64f98fa7), li_64(47b5481dbefa4fa4) +}; + +VOID_RETURN sha384_begin(sha384_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i384, 8 * sizeof(uint_64t)); +} + +VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]) +{ + sha_end2(hval, ctx, SHA384_DIGEST_SIZE); +} + +VOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha384_ctx cx[1]; + + sha384_begin(cx); + sha384_hash(data, len, cx); + sha_end2(hval, cx, SHA384_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_512) + +/* SHA512 initialisation data */ + +const uint_64t i512[80] = +{ + li_64(6a09e667f3bcc908), li_64(bb67ae8584caa73b), + li_64(3c6ef372fe94f82b), li_64(a54ff53a5f1d36f1), + li_64(510e527fade682d1), li_64(9b05688c2b3e6c1f), + li_64(1f83d9abfb41bd6b), li_64(5be0cd19137e2179) +}; + +VOID_RETURN sha512_begin(sha512_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i512, 8 * sizeof(uint_64t)); +} + +VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]) +{ + sha_end2(hval, ctx, SHA512_DIGEST_SIZE); +} + +VOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha512_ctx cx[1]; + + sha512_begin(cx); + sha512_hash(data, len, cx); + sha_end2(hval, cx, SHA512_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_2) + +#define CTX_224(x) ((x)->uu->ctx256) +#define CTX_256(x) ((x)->uu->ctx256) +#define CTX_384(x) ((x)->uu->ctx512) +#define CTX_512(x) ((x)->uu->ctx512) + +/* SHA2 initialisation */ + +INT_RETURN sha2_begin(unsigned long len, sha2_ctx ctx[1]) +{ + switch(len) + { +#if defined(SHA_224) + case 224: + case 28: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; + memcpy(CTX_256(ctx)->hash, i224, 32); + ctx->sha2_len = 28; return EXIT_SUCCESS; +#endif +#if defined(SHA_256) + case 256: + case 32: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; + memcpy(CTX_256(ctx)->hash, i256, 32); + ctx->sha2_len = 32; return EXIT_SUCCESS; +#endif +#if defined(SHA_384) + case 384: + case 48: CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0; + memcpy(CTX_384(ctx)->hash, i384, 64); + ctx->sha2_len = 48; return EXIT_SUCCESS; +#endif +#if defined(SHA_512) + case 512: + case 64: CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0; + memcpy(CTX_512(ctx)->hash, i512, 64); + ctx->sha2_len = 64; return EXIT_SUCCESS; +#endif + default: return EXIT_FAILURE; + } +} + +VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]) +{ + switch(ctx->sha2_len) + { +#if defined(SHA_224) + case 28: sha224_hash(data, len, CTX_224(ctx)); return; +#endif +#if defined(SHA_256) + case 32: sha256_hash(data, len, CTX_256(ctx)); return; +#endif +#if defined(SHA_384) + case 48: sha384_hash(data, len, CTX_384(ctx)); return; +#endif +#if defined(SHA_512) + case 64: sha512_hash(data, len, CTX_512(ctx)); return; +#endif + } +} + +VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]) +{ + switch(ctx->sha2_len) + { +#if defined(SHA_224) + case 28: sha_end1(hval, CTX_224(ctx), SHA224_DIGEST_SIZE); return; +#endif +#if defined(SHA_256) + case 32: sha_end1(hval, CTX_256(ctx), SHA256_DIGEST_SIZE); return; +#endif +#if defined(SHA_384) + case 48: sha_end2(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return; +#endif +#if defined(SHA_512) + case 64: sha_end2(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return; +#endif + } +} + +INT_RETURN sha2(unsigned char hval[], unsigned long size, + const unsigned char data[], unsigned long len) +{ sha2_ctx cx[1]; + + if(sha2_begin(size, cx) == EXIT_SUCCESS) + { + sha2_hash(data, len, cx); sha2_end(hval, cx); return EXIT_SUCCESS; + } + else + return EXIT_FAILURE; +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/Crypto/Sha2.h b/Crypto/Sha2.h index 6d0aeb0..64379d1 100644 --- a/Crypto/Sha2.h +++ b/Crypto/Sha2.h @@ -1,155 +1,155 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 01/08/2005 -*/ - -#ifndef _SHA2_H -#define _SHA2_H - -#include "Common/Tcdefs.h" -#include "Common/Endian.h" - -#define SHA_64BIT - -/* define the hash functions that you need */ -#define SHA_2 /* for dynamic hash length */ -#define SHA_224 -#define SHA_256 -#ifdef SHA_64BIT -# define SHA_384 -# define SHA_512 -# define NEED_UINT_64T -#endif - -#ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 -#define EXIT_FAILURE 1 -#endif - -#define li_64(h) 0x##h##ull - -#define VOID_RETURN void -#define INT_RETURN int - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* Note that the following function prototypes are the same */ -/* for both the bit and byte oriented implementations. But */ -/* the length fields are in bytes or bits as is appropriate */ -/* for the version used. Bit sequences are arrays of bytes */ -/* in which bit sequence indexes increase from the most to */ -/* the least significant end of each byte */ - -#define SHA224_DIGEST_SIZE 28 -#define SHA224_BLOCK_SIZE 64 -#define SHA256_DIGEST_SIZE 32 -#define SHA256_BLOCK_SIZE 64 - -/* type to hold the SHA256 (and SHA224) context */ - -typedef struct -{ uint_32t count[2]; - uint_32t hash[8]; - uint_32t wbuf[16]; -} sha256_ctx; - -typedef sha256_ctx sha224_ctx; - -VOID_RETURN sha256_compile(sha256_ctx ctx[1]); - -VOID_RETURN sha224_begin(sha224_ctx ctx[1]); -#define sha224_hash sha256_hash -VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]); -VOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len); - -VOID_RETURN sha256_begin(sha256_ctx ctx[1]); -VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]); -VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]); -VOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len); - -#ifndef SHA_64BIT - -typedef struct -{ union - { sha256_ctx ctx256[1]; - } uu[1]; - uint_32t sha2_len; -} sha2_ctx; - -#define SHA2_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE - -#else - -#define SHA384_DIGEST_SIZE 48 -#define SHA384_BLOCK_SIZE 128 -#define SHA512_DIGEST_SIZE 64 -#define SHA512_BLOCK_SIZE 128 -#define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE - -/* type to hold the SHA384 (and SHA512) context */ - -typedef struct -{ uint_64t count[2]; - uint_64t hash[8]; - uint_64t wbuf[16]; -} sha512_ctx; - -typedef sha512_ctx sha384_ctx; - -typedef struct -{ union - { sha256_ctx ctx256[1]; - sha512_ctx ctx512[1]; - } uu[1]; - uint_32t sha2_len; -} sha2_ctx; - -VOID_RETURN sha512_compile(sha512_ctx ctx[1]); - -VOID_RETURN sha384_begin(sha384_ctx ctx[1]); -#define sha384_hash sha512_hash -VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]); -VOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len); - -VOID_RETURN sha512_begin(sha512_ctx ctx[1]); -VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]); -VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]); -VOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len); - -INT_RETURN sha2_begin(unsigned long size, sha2_ctx ctx[1]); -VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]); -VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]); -INT_RETURN sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len); - -#endif - -#if defined(__cplusplus) -} -#endif - -#endif +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 01/08/2005 +*/ + +#ifndef _SHA2_H +#define _SHA2_H + +#include "Common/Tcdefs.h" +#include "Common/Endian.h" + +#define SHA_64BIT + +/* define the hash functions that you need */ +#define SHA_2 /* for dynamic hash length */ +#define SHA_224 +#define SHA_256 +#ifdef SHA_64BIT +# define SHA_384 +# define SHA_512 +# define NEED_UINT_64T +#endif + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#endif + +#define li_64(h) 0x##h##ull + +#define VOID_RETURN void +#define INT_RETURN int + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Note that the following function prototypes are the same */ +/* for both the bit and byte oriented implementations. But */ +/* the length fields are in bytes or bits as is appropriate */ +/* for the version used. Bit sequences are arrays of bytes */ +/* in which bit sequence indexes increase from the most to */ +/* the least significant end of each byte */ + +#define SHA224_DIGEST_SIZE 28 +#define SHA224_BLOCK_SIZE 64 +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +/* type to hold the SHA256 (and SHA224) context */ + +typedef struct +{ uint_32t count[2]; + uint_32t hash[8]; + uint_32t wbuf[16]; +} sha256_ctx; + +typedef sha256_ctx sha224_ctx; + +VOID_RETURN sha256_compile(sha256_ctx ctx[1]); + +VOID_RETURN sha224_begin(sha224_ctx ctx[1]); +#define sha224_hash sha256_hash +VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]); +VOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len); + +VOID_RETURN sha256_begin(sha256_ctx ctx[1]); +VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]); +VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]); +VOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len); + +#ifndef SHA_64BIT + +typedef struct +{ union + { sha256_ctx ctx256[1]; + } uu[1]; + uint_32t sha2_len; +} sha2_ctx; + +#define SHA2_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE + +#else + +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 +#define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE + +/* type to hold the SHA384 (and SHA512) context */ + +typedef struct +{ uint_64t count[2]; + uint_64t hash[8]; + uint_64t wbuf[16]; +} sha512_ctx; + +typedef sha512_ctx sha384_ctx; + +typedef struct +{ union + { sha256_ctx ctx256[1]; + sha512_ctx ctx512[1]; + } uu[1]; + uint_32t sha2_len; +} sha2_ctx; + +VOID_RETURN sha512_compile(sha512_ctx ctx[1]); + +VOID_RETURN sha384_begin(sha384_ctx ctx[1]); +#define sha384_hash sha512_hash +VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]); +VOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len); + +VOID_RETURN sha512_begin(sha512_ctx ctx[1]); +VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]); +VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]); +VOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len); + +INT_RETURN sha2_begin(unsigned long size, sha2_ctx ctx[1]); +VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]); +VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]); +INT_RETURN sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Crypto/Twofish.c b/Crypto/Twofish.c index 7ba10c6..3472eb4 100644 --- a/Crypto/Twofish.c +++ b/Crypto/Twofish.c @@ -1,548 +1,548 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 1999, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software is allowed (with or without - changes) provided that: - - 1. source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - 2. binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation; - - 3. the name of the copyright holder is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - - My thanks to Doug Whiting and Niels Ferguson for comments that led - to improvements in this implementation. - - Issue Date: 14th January 1999 -*/ - -/* Adapted for TrueCrypt by the TrueCrypt Foundation */ - - -#ifdef TC_WINDOWS_BOOT -#pragma optimize ("tl", on) -#endif - -#include "Twofish.h" -#include "Common/Endian.h" - -#define Q_TABLES -#define M_TABLE - -#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_TWOFISH) -# define MK_TABLE -# define ONE_STEP -#endif - -/* finite field arithmetic for GF(2**8) with the modular */ -/* polynomial x^8 + x^6 + x^5 + x^3 + 1 (0x169) */ - -#define G_M 0x0169 - -static u1byte tab_5b[4] = { 0, G_M >> 2, G_M >> 1, (G_M >> 1) ^ (G_M >> 2) }; -static u1byte tab_ef[4] = { 0, (G_M >> 1) ^ (G_M >> 2), G_M >> 1, G_M >> 2 }; - -#define ffm_01(x) (x) -#define ffm_5b(x) ((x) ^ ((x) >> 2) ^ tab_5b[(x) & 3]) -#define ffm_ef(x) ((x) ^ ((x) >> 1) ^ ((x) >> 2) ^ tab_ef[(x) & 3]) - -static u1byte ror4[16] = { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; -static u1byte ashx[16] = { 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7 }; - -static u1byte qt0[2][16] = -{ { 8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4 }, - { 2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5 } -}; - -static u1byte qt1[2][16] = -{ { 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 }, - { 1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8 } -}; - -static u1byte qt2[2][16] = -{ { 11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1 }, - { 4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15 } -}; - -static u1byte qt3[2][16] = -{ { 13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10 }, - { 11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10 } -}; - -static u1byte qp(const u4byte n, const u1byte x) -{ u1byte a0, a1, a2, a3, a4, b0, b1, b2, b3, b4; - - a0 = x >> 4; b0 = x & 15; - a1 = a0 ^ b0; b1 = ror4[b0] ^ ashx[a0]; - a2 = qt0[n][a1]; b2 = qt1[n][b1]; - a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2]; - a4 = qt2[n][a3]; b4 = qt3[n][b3]; - return (b4 << 4) | a4; -}; - -#ifdef Q_TABLES - -static u4byte qt_gen = 0; -static u1byte q_tab[2][256]; - -#define q(n,x) q_tab[n][x] - -static void gen_qtab(void) -{ u4byte i; - - for(i = 0; i < 256; ++i) - { - q(0,i) = qp(0, (u1byte)i); - q(1,i) = qp(1, (u1byte)i); - } -}; - -#else - -#define q(n,x) qp(n, x) - -#endif - -#ifdef M_TABLE - -static u4byte mt_gen = 0; -static u4byte m_tab[4][256]; - -static void gen_mtab(void) -{ u4byte i, f01, f5b, fef; - - for(i = 0; i < 256; ++i) - { - f01 = q(1,i); f5b = ffm_5b(f01); fef = ffm_ef(f01); - m_tab[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); - m_tab[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); - - f01 = q(0,i); f5b = ffm_5b(f01); fef = ffm_ef(f01); - m_tab[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); - m_tab[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); - } -}; - -#define mds(n,x) m_tab[n][x] - -#else - -#define fm_00 ffm_01 -#define fm_10 ffm_5b -#define fm_20 ffm_ef -#define fm_30 ffm_ef -#define q_0(x) q(1,x) - -#define fm_01 ffm_ef -#define fm_11 ffm_ef -#define fm_21 ffm_5b -#define fm_31 ffm_01 -#define q_1(x) q(0,x) - -#define fm_02 ffm_5b -#define fm_12 ffm_ef -#define fm_22 ffm_01 -#define fm_32 ffm_ef -#define q_2(x) q(1,x) - -#define fm_03 ffm_5b -#define fm_13 ffm_01 -#define fm_23 ffm_ef -#define fm_33 ffm_5b -#define q_3(x) q(0,x) - -#define f_0(n,x) ((u4byte)fm_0##n(x)) -#define f_1(n,x) ((u4byte)fm_1##n(x) << 8) -#define f_2(n,x) ((u4byte)fm_2##n(x) << 16) -#define f_3(n,x) ((u4byte)fm_3##n(x) << 24) - -#define mds(n,x) f_0(n,q_##n(x)) ^ f_1(n,q_##n(x)) ^ f_2(n,q_##n(x)) ^ f_3(n,q_##n(x)) - -#endif - -static u4byte h_fun(TwofishInstance *instance, const u4byte x, const u4byte key[]) -{ u4byte b0, b1, b2, b3; - -#ifndef M_TABLE - u4byte m5b_b0, m5b_b1, m5b_b2, m5b_b3; - u4byte mef_b0, mef_b1, mef_b2, mef_b3; -#endif - - b0 = extract_byte(x, 0); b1 = extract_byte(x, 1); b2 = extract_byte(x, 2); b3 = extract_byte(x, 3); - - switch(instance->k_len) - { - case 4: b0 = q(1, (u1byte) b0) ^ extract_byte(key[3],0); - b1 = q(0, (u1byte) b1) ^ extract_byte(key[3],1); - b2 = q(0, (u1byte) b2) ^ extract_byte(key[3],2); - b3 = q(1, (u1byte) b3) ^ extract_byte(key[3],3); - case 3: b0 = q(1, (u1byte) b0) ^ extract_byte(key[2],0); - b1 = q(1, (u1byte) b1) ^ extract_byte(key[2],1); - b2 = q(0, (u1byte) b2) ^ extract_byte(key[2],2); - b3 = q(0, (u1byte) b3) ^ extract_byte(key[2],3); - case 2: b0 = q(0, (u1byte) (q(0, (u1byte) b0) ^ extract_byte(key[1],0))) ^ extract_byte(key[0],0); - b1 = q(0, (u1byte) (q(1, (u1byte) b1) ^ extract_byte(key[1],1))) ^ extract_byte(key[0],1); - b2 = q(1, (u1byte) (q(0, (u1byte) b2) ^ extract_byte(key[1],2))) ^ extract_byte(key[0],2); - b3 = q(1, (u1byte) (q(1, (u1byte) b3) ^ extract_byte(key[1],3))) ^ extract_byte(key[0],3); - } -#ifdef M_TABLE - - return mds(0, b0) ^ mds(1, b1) ^ mds(2, b2) ^ mds(3, b3); - -#else - - b0 = q(1, (u1byte) b0); b1 = q(0, (u1byte) b1); b2 = q(1, (u1byte) b2); b3 = q(0, (u1byte) b3); - m5b_b0 = ffm_5b(b0); m5b_b1 = ffm_5b(b1); m5b_b2 = ffm_5b(b2); m5b_b3 = ffm_5b(b3); - mef_b0 = ffm_ef(b0); mef_b1 = ffm_ef(b1); mef_b2 = ffm_ef(b2); mef_b3 = ffm_ef(b3); - b0 ^= mef_b1 ^ m5b_b2 ^ m5b_b3; b3 ^= m5b_b0 ^ mef_b1 ^ mef_b2; - b2 ^= mef_b0 ^ m5b_b1 ^ mef_b3; b1 ^= mef_b0 ^ mef_b2 ^ m5b_b3; - - return b0 | (b3 << 8) | (b2 << 16) | (b1 << 24); - -#endif -}; - -#ifdef MK_TABLE - -#ifdef ONE_STEP -//u4byte mk_tab[4][256]; -#else -static u1byte sb[4][256]; -#endif - -#define q20(x) q(0,q(0,x) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) -#define q21(x) q(0,q(1,x) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) -#define q22(x) q(1,q(0,x) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) -#define q23(x) q(1,q(1,x) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) - -#define q30(x) q(0,q(0,q(1, x) ^ extract_byte(key[2],0)) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) -#define q31(x) q(0,q(1,q(1, x) ^ extract_byte(key[2],1)) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) -#define q32(x) q(1,q(0,q(0, x) ^ extract_byte(key[2],2)) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) -#define q33(x) q(1,q(1,q(0, x) ^ extract_byte(key[2],3)) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) - -#define q40(x) q(0,q(0,q(1, q(1, x) ^ extract_byte(key[3],0)) ^ extract_byte(key[2],0)) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) -#define q41(x) q(0,q(1,q(1, q(0, x) ^ extract_byte(key[3],1)) ^ extract_byte(key[2],1)) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) -#define q42(x) q(1,q(0,q(0, q(0, x) ^ extract_byte(key[3],2)) ^ extract_byte(key[2],2)) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) -#define q43(x) q(1,q(1,q(0, q(1, x) ^ extract_byte(key[3],3)) ^ extract_byte(key[2],3)) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) - -static void gen_mk_tab(TwofishInstance *instance, u4byte key[]) -{ u4byte i; - u1byte by; - - u4byte *mk_tab = instance->mk_tab; - - switch(instance->k_len) - { - case 2: for(i = 0; i < 256; ++i) - { - by = (u1byte)i; -#ifdef ONE_STEP - mk_tab[0 + 4*i] = mds(0, q20(by)); mk_tab[1 + 4*i] = mds(1, q21(by)); - mk_tab[2 + 4*i] = mds(2, q22(by)); mk_tab[3 + 4*i] = mds(3, q23(by)); -#else - sb[0][i] = q20(by); sb[1][i] = q21(by); - sb[2][i] = q22(by); sb[3][i] = q23(by); -#endif - } - break; - - case 3: for(i = 0; i < 256; ++i) - { - by = (u1byte)i; -#ifdef ONE_STEP - mk_tab[0 + 4*i] = mds(0, q30(by)); mk_tab[1 + 4*i] = mds(1, q31(by)); - mk_tab[2 + 4*i] = mds(2, q32(by)); mk_tab[3 + 4*i] = mds(3, q33(by)); -#else - sb[0][i] = q30(by); sb[1][i] = q31(by); - sb[2][i] = q32(by); sb[3][i] = q33(by); -#endif - } - break; - - case 4: for(i = 0; i < 256; ++i) - { - by = (u1byte)i; -#ifdef ONE_STEP - mk_tab[0 + 4*i] = mds(0, q40(by)); mk_tab[1 + 4*i] = mds(1, q41(by)); - mk_tab[2 + 4*i] = mds(2, q42(by)); mk_tab[3 + 4*i] = mds(3, q43(by)); -#else - sb[0][i] = q40(by); sb[1][i] = q41(by); - sb[2][i] = q42(by); sb[3][i] = q43(by); -#endif - } - } -}; - -# ifdef ONE_STEP -# define g0_fun(x) ( mk_tab[0 + 4*extract_byte(x,0)] ^ mk_tab[1 + 4*extract_byte(x,1)] \ - ^ mk_tab[2 + 4*extract_byte(x,2)] ^ mk_tab[3 + 4*extract_byte(x,3)] ) -# define g1_fun(x) ( mk_tab[0 + 4*extract_byte(x,3)] ^ mk_tab[1 + 4*extract_byte(x,0)] \ - ^ mk_tab[2 + 4*extract_byte(x,1)] ^ mk_tab[3 + 4*extract_byte(x,2)] ) - - -# else -# define g0_fun(x) ( mds(0, sb[0][extract_byte(x,0)]) ^ mds(1, sb[1][extract_byte(x,1)]) \ - ^ mds(2, sb[2][extract_byte(x,2)]) ^ mds(3, sb[3][extract_byte(x,3)]) ) -# define g1_fun(x) ( mds(0, sb[0][extract_byte(x,3)]) ^ mds(1, sb[1][extract_byte(x,0)]) \ - ^ mds(2, sb[2][extract_byte(x,1)]) ^ mds(3, sb[3][extract_byte(x,2)]) ) -# endif - -#else - -#define g0_fun(x) h_fun(instance, x, instance->s_key) -#define g1_fun(x) h_fun(instance, rotl(x,8), instance->s_key) - -#endif - -/* The (12,8) Reed Soloman code has the generator polynomial - - g(x) = x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1 - -where the coefficients are in the finite field GF(2^8) with a -modular polynomial a^8 + a^6 + a^3 + a^2 + 1. To generate the -remainder we have to start with a 12th order polynomial with our -eight input bytes as the coefficients of the 4th to 11th terms. -That is: - - m[7] * x^11 + m[6] * x^10 ... + m[0] * x^4 + 0 * x^3 +... + 0 - -We then multiply the generator polynomial by m[7] * x^7 and subtract -it - xor in GF(2^8) - from the above to eliminate the x^7 term (the -artihmetic on the coefficients is done in GF(2^8). We then multiply -the generator polynomial by x^6 * coeff(x^10) and use this to remove -the x^10 term. We carry on in this way until the x^4 term is removed -so that we are left with: - - r[3] * x^3 + r[2] * x^2 + r[1] 8 x^1 + r[0] - -which give the resulting 4 bytes of the remainder. This is equivalent -to the matrix multiplication in the Twofish description but much faster -to implement. - -*/ - -#define G_MOD 0x0000014d - -static u4byte mds_rem(u4byte p0, u4byte p1) -{ u4byte i, t, u; - - for(i = 0; i < 8; ++i) - { - t = p1 >> 24; // get most significant coefficient - - p1 = (p1 << 8) | (p0 >> 24); p0 <<= 8; // shift others up - - // multiply t by a (the primitive element - i.e. left shift) - - u = (t << 1); - - if(t & 0x80) // subtract modular polynomial on overflow - - u ^= G_MOD; - - p1 ^= t ^ (u << 16); // remove t * (a * x^2 + 1) - - u ^= (t >> 1); // form u = a * t + t / a = t * (a + 1 / a); - - if(t & 0x01) // add the modular polynomial on underflow - - u ^= G_MOD >> 1; - - p1 ^= (u << 24) | (u << 8); // remove t * (a + 1/a) * (x^3 + x) - } - - return p1; -}; - -/* initialise the key schedule from the user supplied key */ - -u4byte *twofish_set_key(TwofishInstance *instance, const u4byte in_key[], const u4byte key_len) -{ u4byte i, a, b, me_key[4], mo_key[4]; - u4byte *l_key, *s_key; - - l_key = instance->l_key; - s_key = instance->s_key; - -#ifdef Q_TABLES - if(!qt_gen) - { - gen_qtab(); qt_gen = 1; - } -#endif - -#ifdef M_TABLE - if(!mt_gen) - { - gen_mtab(); mt_gen = 1; - } -#endif - - instance->k_len = key_len / 64; /* 2, 3 or 4 */ - - for(i = 0; i < instance->k_len; ++i) - { - a = LE32(in_key[i + i]); me_key[i] = a; - b = LE32(in_key[i + i + 1]); mo_key[i] = b; - s_key[instance->k_len - i - 1] = mds_rem(a, b); - } - - for(i = 0; i < 40; i += 2) - { - a = 0x01010101 * i; b = a + 0x01010101; - a = h_fun(instance, a, me_key); - b = rotl(h_fun(instance, b, mo_key), 8); - l_key[i] = a + b; - l_key[i + 1] = rotl(a + 2 * b, 9); - } - -#ifdef MK_TABLE - gen_mk_tab(instance, s_key); -#endif - - return l_key; -}; - -/* encrypt a block of text */ - -#ifndef TC_MINIMIZE_CODE_SIZE - -#define f_rnd(i) \ - t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); \ - blk[2] = rotr(blk[2] ^ (t0 + t1 + l_key[4 * (i) + 8]), 1); \ - blk[3] = rotl(blk[3], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]); \ - t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); \ - blk[0] = rotr(blk[0] ^ (t0 + t1 + l_key[4 * (i) + 10]), 1); \ - blk[1] = rotl(blk[1], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]) - -void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]) -{ u4byte t0, t1, blk[4]; - - u4byte *l_key = instance->l_key; - u4byte *mk_tab = instance->mk_tab; - - blk[0] = LE32(in_blk[0]) ^ l_key[0]; - blk[1] = LE32(in_blk[1]) ^ l_key[1]; - blk[2] = LE32(in_blk[2]) ^ l_key[2]; - blk[3] = LE32(in_blk[3]) ^ l_key[3]; - - f_rnd(0); f_rnd(1); f_rnd(2); f_rnd(3); - f_rnd(4); f_rnd(5); f_rnd(6); f_rnd(7); - - out_blk[0] = LE32(blk[2] ^ l_key[4]); - out_blk[1] = LE32(blk[3] ^ l_key[5]); - out_blk[2] = LE32(blk[0] ^ l_key[6]); - out_blk[3] = LE32(blk[1] ^ l_key[7]); -}; - -#else // TC_MINIMIZE_CODE_SIZE - -void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]) -{ u4byte t0, t1, blk[4]; - - u4byte *l_key = instance->l_key; -#ifdef TC_WINDOWS_BOOT_TWOFISH - u4byte *mk_tab = instance->mk_tab; -#endif - int i; - - blk[0] = LE32(in_blk[0]) ^ l_key[0]; - blk[1] = LE32(in_blk[1]) ^ l_key[1]; - blk[2] = LE32(in_blk[2]) ^ l_key[2]; - blk[3] = LE32(in_blk[3]) ^ l_key[3]; - - for (i = 0; i <= 7; ++i) - { - t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); - blk[2] = rotr(blk[2] ^ (t0 + t1 + l_key[4 * (i) + 8]), 1); - blk[3] = rotl(blk[3], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]); - t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); - blk[0] = rotr(blk[0] ^ (t0 + t1 + l_key[4 * (i) + 10]), 1); - blk[1] = rotl(blk[1], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]); - } - - out_blk[0] = LE32(blk[2] ^ l_key[4]); - out_blk[1] = LE32(blk[3] ^ l_key[5]); - out_blk[2] = LE32(blk[0] ^ l_key[6]); - out_blk[3] = LE32(blk[1] ^ l_key[7]); -}; - -#endif // TC_MINIMIZE_CODE_SIZE - -/* decrypt a block of text */ - -#ifndef TC_MINIMIZE_CODE_SIZE - -#define i_rnd(i) \ - t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); \ - blk[2] = rotl(blk[2], 1) ^ (t0 + t1 + l_key[4 * (i) + 10]); \ - blk[3] = rotr(blk[3] ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]), 1); \ - t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); \ - blk[0] = rotl(blk[0], 1) ^ (t0 + t1 + l_key[4 * (i) + 8]); \ - blk[1] = rotr(blk[1] ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]), 1) - -void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]) -{ u4byte t0, t1, blk[4]; - - u4byte *l_key = instance->l_key; - u4byte *mk_tab = instance->mk_tab; - - blk[0] = LE32(in_blk[0]) ^ l_key[4]; - blk[1] = LE32(in_blk[1]) ^ l_key[5]; - blk[2] = LE32(in_blk[2]) ^ l_key[6]; - blk[3] = LE32(in_blk[3]) ^ l_key[7]; - - i_rnd(7); i_rnd(6); i_rnd(5); i_rnd(4); - i_rnd(3); i_rnd(2); i_rnd(1); i_rnd(0); - - out_blk[0] = LE32(blk[2] ^ l_key[0]); - out_blk[1] = LE32(blk[3] ^ l_key[1]); - out_blk[2] = LE32(blk[0] ^ l_key[2]); - out_blk[3] = LE32(blk[1] ^ l_key[3]); -}; - -#else // TC_MINIMIZE_CODE_SIZE - -void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]) -{ u4byte t0, t1, blk[4]; - - u4byte *l_key = instance->l_key; -#ifdef TC_WINDOWS_BOOT_TWOFISH - u4byte *mk_tab = instance->mk_tab; -#endif - int i; - - blk[0] = LE32(in_blk[0]) ^ l_key[4]; - blk[1] = LE32(in_blk[1]) ^ l_key[5]; - blk[2] = LE32(in_blk[2]) ^ l_key[6]; - blk[3] = LE32(in_blk[3]) ^ l_key[7]; - - for (i = 7; i >= 0; --i) - { - t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); - blk[2] = rotl(blk[2], 1) ^ (t0 + t1 + l_key[4 * (i) + 10]); - blk[3] = rotr(blk[3] ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]), 1); - t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); - blk[0] = rotl(blk[0], 1) ^ (t0 + t1 + l_key[4 * (i) + 8]); - blk[1] = rotr(blk[1] ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]), 1); - } - - out_blk[0] = LE32(blk[2] ^ l_key[0]); - out_blk[1] = LE32(blk[3] ^ l_key[1]); - out_blk[2] = LE32(blk[0] ^ l_key[2]); - out_blk[3] = LE32(blk[1] ^ l_key[3]); -}; - -#endif // TC_MINIMIZE_CODE_SIZE +/* + --------------------------------------------------------------------------- + Copyright (c) 1999, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + + My thanks to Doug Whiting and Niels Ferguson for comments that led + to improvements in this implementation. + + Issue Date: 14th January 1999 +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + + +#ifdef TC_WINDOWS_BOOT +#pragma optimize ("tl", on) +#endif + +#include "Twofish.h" +#include "Common/Endian.h" + +#define Q_TABLES +#define M_TABLE + +#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_TWOFISH) +# define MK_TABLE +# define ONE_STEP +#endif + +/* finite field arithmetic for GF(2**8) with the modular */ +/* polynomial x^8 + x^6 + x^5 + x^3 + 1 (0x169) */ + +#define G_M 0x0169 + +static u1byte tab_5b[4] = { 0, G_M >> 2, G_M >> 1, (G_M >> 1) ^ (G_M >> 2) }; +static u1byte tab_ef[4] = { 0, (G_M >> 1) ^ (G_M >> 2), G_M >> 1, G_M >> 2 }; + +#define ffm_01(x) (x) +#define ffm_5b(x) ((x) ^ ((x) >> 2) ^ tab_5b[(x) & 3]) +#define ffm_ef(x) ((x) ^ ((x) >> 1) ^ ((x) >> 2) ^ tab_ef[(x) & 3]) + +static u1byte ror4[16] = { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; +static u1byte ashx[16] = { 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7 }; + +static u1byte qt0[2][16] = +{ { 8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4 }, + { 2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5 } +}; + +static u1byte qt1[2][16] = +{ { 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 }, + { 1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8 } +}; + +static u1byte qt2[2][16] = +{ { 11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1 }, + { 4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15 } +}; + +static u1byte qt3[2][16] = +{ { 13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10 }, + { 11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10 } +}; + +static u1byte qp(const u4byte n, const u1byte x) +{ u1byte a0, a1, a2, a3, a4, b0, b1, b2, b3, b4; + + a0 = x >> 4; b0 = x & 15; + a1 = a0 ^ b0; b1 = ror4[b0] ^ ashx[a0]; + a2 = qt0[n][a1]; b2 = qt1[n][b1]; + a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2]; + a4 = qt2[n][a3]; b4 = qt3[n][b3]; + return (b4 << 4) | a4; +}; + +#ifdef Q_TABLES + +static u4byte qt_gen = 0; +static u1byte q_tab[2][256]; + +#define q(n,x) q_tab[n][x] + +static void gen_qtab(void) +{ u4byte i; + + for(i = 0; i < 256; ++i) + { + q(0,i) = qp(0, (u1byte)i); + q(1,i) = qp(1, (u1byte)i); + } +}; + +#else + +#define q(n,x) qp(n, x) + +#endif + +#ifdef M_TABLE + +static u4byte mt_gen = 0; +static u4byte m_tab[4][256]; + +static void gen_mtab(void) +{ u4byte i, f01, f5b, fef; + + for(i = 0; i < 256; ++i) + { + f01 = q(1,i); f5b = ffm_5b(f01); fef = ffm_ef(f01); + m_tab[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); + m_tab[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); + + f01 = q(0,i); f5b = ffm_5b(f01); fef = ffm_ef(f01); + m_tab[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); + m_tab[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); + } +}; + +#define mds(n,x) m_tab[n][x] + +#else + +#define fm_00 ffm_01 +#define fm_10 ffm_5b +#define fm_20 ffm_ef +#define fm_30 ffm_ef +#define q_0(x) q(1,x) + +#define fm_01 ffm_ef +#define fm_11 ffm_ef +#define fm_21 ffm_5b +#define fm_31 ffm_01 +#define q_1(x) q(0,x) + +#define fm_02 ffm_5b +#define fm_12 ffm_ef +#define fm_22 ffm_01 +#define fm_32 ffm_ef +#define q_2(x) q(1,x) + +#define fm_03 ffm_5b +#define fm_13 ffm_01 +#define fm_23 ffm_ef +#define fm_33 ffm_5b +#define q_3(x) q(0,x) + +#define f_0(n,x) ((u4byte)fm_0##n(x)) +#define f_1(n,x) ((u4byte)fm_1##n(x) << 8) +#define f_2(n,x) ((u4byte)fm_2##n(x) << 16) +#define f_3(n,x) ((u4byte)fm_3##n(x) << 24) + +#define mds(n,x) f_0(n,q_##n(x)) ^ f_1(n,q_##n(x)) ^ f_2(n,q_##n(x)) ^ f_3(n,q_##n(x)) + +#endif + +static u4byte h_fun(TwofishInstance *instance, const u4byte x, const u4byte key[]) +{ u4byte b0, b1, b2, b3; + +#ifndef M_TABLE + u4byte m5b_b0, m5b_b1, m5b_b2, m5b_b3; + u4byte mef_b0, mef_b1, mef_b2, mef_b3; +#endif + + b0 = extract_byte(x, 0); b1 = extract_byte(x, 1); b2 = extract_byte(x, 2); b3 = extract_byte(x, 3); + + switch(instance->k_len) + { + case 4: b0 = q(1, (u1byte) b0) ^ extract_byte(key[3],0); + b1 = q(0, (u1byte) b1) ^ extract_byte(key[3],1); + b2 = q(0, (u1byte) b2) ^ extract_byte(key[3],2); + b3 = q(1, (u1byte) b3) ^ extract_byte(key[3],3); + case 3: b0 = q(1, (u1byte) b0) ^ extract_byte(key[2],0); + b1 = q(1, (u1byte) b1) ^ extract_byte(key[2],1); + b2 = q(0, (u1byte) b2) ^ extract_byte(key[2],2); + b3 = q(0, (u1byte) b3) ^ extract_byte(key[2],3); + case 2: b0 = q(0, (u1byte) (q(0, (u1byte) b0) ^ extract_byte(key[1],0))) ^ extract_byte(key[0],0); + b1 = q(0, (u1byte) (q(1, (u1byte) b1) ^ extract_byte(key[1],1))) ^ extract_byte(key[0],1); + b2 = q(1, (u1byte) (q(0, (u1byte) b2) ^ extract_byte(key[1],2))) ^ extract_byte(key[0],2); + b3 = q(1, (u1byte) (q(1, (u1byte) b3) ^ extract_byte(key[1],3))) ^ extract_byte(key[0],3); + } +#ifdef M_TABLE + + return mds(0, b0) ^ mds(1, b1) ^ mds(2, b2) ^ mds(3, b3); + +#else + + b0 = q(1, (u1byte) b0); b1 = q(0, (u1byte) b1); b2 = q(1, (u1byte) b2); b3 = q(0, (u1byte) b3); + m5b_b0 = ffm_5b(b0); m5b_b1 = ffm_5b(b1); m5b_b2 = ffm_5b(b2); m5b_b3 = ffm_5b(b3); + mef_b0 = ffm_ef(b0); mef_b1 = ffm_ef(b1); mef_b2 = ffm_ef(b2); mef_b3 = ffm_ef(b3); + b0 ^= mef_b1 ^ m5b_b2 ^ m5b_b3; b3 ^= m5b_b0 ^ mef_b1 ^ mef_b2; + b2 ^= mef_b0 ^ m5b_b1 ^ mef_b3; b1 ^= mef_b0 ^ mef_b2 ^ m5b_b3; + + return b0 | (b3 << 8) | (b2 << 16) | (b1 << 24); + +#endif +}; + +#ifdef MK_TABLE + +#ifdef ONE_STEP +//u4byte mk_tab[4][256]; +#else +static u1byte sb[4][256]; +#endif + +#define q20(x) q(0,q(0,x) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) +#define q21(x) q(0,q(1,x) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) +#define q22(x) q(1,q(0,x) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) +#define q23(x) q(1,q(1,x) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) + +#define q30(x) q(0,q(0,q(1, x) ^ extract_byte(key[2],0)) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) +#define q31(x) q(0,q(1,q(1, x) ^ extract_byte(key[2],1)) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) +#define q32(x) q(1,q(0,q(0, x) ^ extract_byte(key[2],2)) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) +#define q33(x) q(1,q(1,q(0, x) ^ extract_byte(key[2],3)) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) + +#define q40(x) q(0,q(0,q(1, q(1, x) ^ extract_byte(key[3],0)) ^ extract_byte(key[2],0)) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) +#define q41(x) q(0,q(1,q(1, q(0, x) ^ extract_byte(key[3],1)) ^ extract_byte(key[2],1)) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) +#define q42(x) q(1,q(0,q(0, q(0, x) ^ extract_byte(key[3],2)) ^ extract_byte(key[2],2)) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) +#define q43(x) q(1,q(1,q(0, q(1, x) ^ extract_byte(key[3],3)) ^ extract_byte(key[2],3)) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) + +static void gen_mk_tab(TwofishInstance *instance, u4byte key[]) +{ u4byte i; + u1byte by; + + u4byte *mk_tab = instance->mk_tab; + + switch(instance->k_len) + { + case 2: for(i = 0; i < 256; ++i) + { + by = (u1byte)i; +#ifdef ONE_STEP + mk_tab[0 + 4*i] = mds(0, q20(by)); mk_tab[1 + 4*i] = mds(1, q21(by)); + mk_tab[2 + 4*i] = mds(2, q22(by)); mk_tab[3 + 4*i] = mds(3, q23(by)); +#else + sb[0][i] = q20(by); sb[1][i] = q21(by); + sb[2][i] = q22(by); sb[3][i] = q23(by); +#endif + } + break; + + case 3: for(i = 0; i < 256; ++i) + { + by = (u1byte)i; +#ifdef ONE_STEP + mk_tab[0 + 4*i] = mds(0, q30(by)); mk_tab[1 + 4*i] = mds(1, q31(by)); + mk_tab[2 + 4*i] = mds(2, q32(by)); mk_tab[3 + 4*i] = mds(3, q33(by)); +#else + sb[0][i] = q30(by); sb[1][i] = q31(by); + sb[2][i] = q32(by); sb[3][i] = q33(by); +#endif + } + break; + + case 4: for(i = 0; i < 256; ++i) + { + by = (u1byte)i; +#ifdef ONE_STEP + mk_tab[0 + 4*i] = mds(0, q40(by)); mk_tab[1 + 4*i] = mds(1, q41(by)); + mk_tab[2 + 4*i] = mds(2, q42(by)); mk_tab[3 + 4*i] = mds(3, q43(by)); +#else + sb[0][i] = q40(by); sb[1][i] = q41(by); + sb[2][i] = q42(by); sb[3][i] = q43(by); +#endif + } + } +}; + +# ifdef ONE_STEP +# define g0_fun(x) ( mk_tab[0 + 4*extract_byte(x,0)] ^ mk_tab[1 + 4*extract_byte(x,1)] \ + ^ mk_tab[2 + 4*extract_byte(x,2)] ^ mk_tab[3 + 4*extract_byte(x,3)] ) +# define g1_fun(x) ( mk_tab[0 + 4*extract_byte(x,3)] ^ mk_tab[1 + 4*extract_byte(x,0)] \ + ^ mk_tab[2 + 4*extract_byte(x,1)] ^ mk_tab[3 + 4*extract_byte(x,2)] ) + + +# else +# define g0_fun(x) ( mds(0, sb[0][extract_byte(x,0)]) ^ mds(1, sb[1][extract_byte(x,1)]) \ + ^ mds(2, sb[2][extract_byte(x,2)]) ^ mds(3, sb[3][extract_byte(x,3)]) ) +# define g1_fun(x) ( mds(0, sb[0][extract_byte(x,3)]) ^ mds(1, sb[1][extract_byte(x,0)]) \ + ^ mds(2, sb[2][extract_byte(x,1)]) ^ mds(3, sb[3][extract_byte(x,2)]) ) +# endif + +#else + +#define g0_fun(x) h_fun(instance, x, instance->s_key) +#define g1_fun(x) h_fun(instance, rotl(x,8), instance->s_key) + +#endif + +/* The (12,8) Reed Soloman code has the generator polynomial + + g(x) = x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1 + +where the coefficients are in the finite field GF(2^8) with a +modular polynomial a^8 + a^6 + a^3 + a^2 + 1. To generate the +remainder we have to start with a 12th order polynomial with our +eight input bytes as the coefficients of the 4th to 11th terms. +That is: + + m[7] * x^11 + m[6] * x^10 ... + m[0] * x^4 + 0 * x^3 +... + 0 + +We then multiply the generator polynomial by m[7] * x^7 and subtract +it - xor in GF(2^8) - from the above to eliminate the x^7 term (the +artihmetic on the coefficients is done in GF(2^8). We then multiply +the generator polynomial by x^6 * coeff(x^10) and use this to remove +the x^10 term. We carry on in this way until the x^4 term is removed +so that we are left with: + + r[3] * x^3 + r[2] * x^2 + r[1] 8 x^1 + r[0] + +which give the resulting 4 bytes of the remainder. This is equivalent +to the matrix multiplication in the Twofish description but much faster +to implement. + +*/ + +#define G_MOD 0x0000014d + +static u4byte mds_rem(u4byte p0, u4byte p1) +{ u4byte i, t, u; + + for(i = 0; i < 8; ++i) + { + t = p1 >> 24; // get most significant coefficient + + p1 = (p1 << 8) | (p0 >> 24); p0 <<= 8; // shift others up + + // multiply t by a (the primitive element - i.e. left shift) + + u = (t << 1); + + if(t & 0x80) // subtract modular polynomial on overflow + + u ^= G_MOD; + + p1 ^= t ^ (u << 16); // remove t * (a * x^2 + 1) + + u ^= (t >> 1); // form u = a * t + t / a = t * (a + 1 / a); + + if(t & 0x01) // add the modular polynomial on underflow + + u ^= G_MOD >> 1; + + p1 ^= (u << 24) | (u << 8); // remove t * (a + 1/a) * (x^3 + x) + } + + return p1; +}; + +/* initialise the key schedule from the user supplied key */ + +u4byte *twofish_set_key(TwofishInstance *instance, const u4byte in_key[], const u4byte key_len) +{ u4byte i, a, b, me_key[4], mo_key[4]; + u4byte *l_key, *s_key; + + l_key = instance->l_key; + s_key = instance->s_key; + +#ifdef Q_TABLES + if(!qt_gen) + { + gen_qtab(); qt_gen = 1; + } +#endif + +#ifdef M_TABLE + if(!mt_gen) + { + gen_mtab(); mt_gen = 1; + } +#endif + + instance->k_len = key_len / 64; /* 2, 3 or 4 */ + + for(i = 0; i < instance->k_len; ++i) + { + a = LE32(in_key[i + i]); me_key[i] = a; + b = LE32(in_key[i + i + 1]); mo_key[i] = b; + s_key[instance->k_len - i - 1] = mds_rem(a, b); + } + + for(i = 0; i < 40; i += 2) + { + a = 0x01010101 * i; b = a + 0x01010101; + a = h_fun(instance, a, me_key); + b = rotl(h_fun(instance, b, mo_key), 8); + l_key[i] = a + b; + l_key[i + 1] = rotl(a + 2 * b, 9); + } + +#ifdef MK_TABLE + gen_mk_tab(instance, s_key); +#endif + + return l_key; +}; + +/* encrypt a block of text */ + +#ifndef TC_MINIMIZE_CODE_SIZE + +#define f_rnd(i) \ + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); \ + blk[2] = rotr(blk[2] ^ (t0 + t1 + l_key[4 * (i) + 8]), 1); \ + blk[3] = rotl(blk[3], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]); \ + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); \ + blk[0] = rotr(blk[0] ^ (t0 + t1 + l_key[4 * (i) + 10]), 1); \ + blk[1] = rotl(blk[1], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]) + +void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; + u4byte *mk_tab = instance->mk_tab; + + blk[0] = LE32(in_blk[0]) ^ l_key[0]; + blk[1] = LE32(in_blk[1]) ^ l_key[1]; + blk[2] = LE32(in_blk[2]) ^ l_key[2]; + blk[3] = LE32(in_blk[3]) ^ l_key[3]; + + f_rnd(0); f_rnd(1); f_rnd(2); f_rnd(3); + f_rnd(4); f_rnd(5); f_rnd(6); f_rnd(7); + + out_blk[0] = LE32(blk[2] ^ l_key[4]); + out_blk[1] = LE32(blk[3] ^ l_key[5]); + out_blk[2] = LE32(blk[0] ^ l_key[6]); + out_blk[3] = LE32(blk[1] ^ l_key[7]); +}; + +#else // TC_MINIMIZE_CODE_SIZE + +void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; +#ifdef TC_WINDOWS_BOOT_TWOFISH + u4byte *mk_tab = instance->mk_tab; +#endif + int i; + + blk[0] = LE32(in_blk[0]) ^ l_key[0]; + blk[1] = LE32(in_blk[1]) ^ l_key[1]; + blk[2] = LE32(in_blk[2]) ^ l_key[2]; + blk[3] = LE32(in_blk[3]) ^ l_key[3]; + + for (i = 0; i <= 7; ++i) + { + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); + blk[2] = rotr(blk[2] ^ (t0 + t1 + l_key[4 * (i) + 8]), 1); + blk[3] = rotl(blk[3], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]); + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); + blk[0] = rotr(blk[0] ^ (t0 + t1 + l_key[4 * (i) + 10]), 1); + blk[1] = rotl(blk[1], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]); + } + + out_blk[0] = LE32(blk[2] ^ l_key[4]); + out_blk[1] = LE32(blk[3] ^ l_key[5]); + out_blk[2] = LE32(blk[0] ^ l_key[6]); + out_blk[3] = LE32(blk[1] ^ l_key[7]); +}; + +#endif // TC_MINIMIZE_CODE_SIZE + +/* decrypt a block of text */ + +#ifndef TC_MINIMIZE_CODE_SIZE + +#define i_rnd(i) \ + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); \ + blk[2] = rotl(blk[2], 1) ^ (t0 + t1 + l_key[4 * (i) + 10]); \ + blk[3] = rotr(blk[3] ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]), 1); \ + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); \ + blk[0] = rotl(blk[0], 1) ^ (t0 + t1 + l_key[4 * (i) + 8]); \ + blk[1] = rotr(blk[1] ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]), 1) + +void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; + u4byte *mk_tab = instance->mk_tab; + + blk[0] = LE32(in_blk[0]) ^ l_key[4]; + blk[1] = LE32(in_blk[1]) ^ l_key[5]; + blk[2] = LE32(in_blk[2]) ^ l_key[6]; + blk[3] = LE32(in_blk[3]) ^ l_key[7]; + + i_rnd(7); i_rnd(6); i_rnd(5); i_rnd(4); + i_rnd(3); i_rnd(2); i_rnd(1); i_rnd(0); + + out_blk[0] = LE32(blk[2] ^ l_key[0]); + out_blk[1] = LE32(blk[3] ^ l_key[1]); + out_blk[2] = LE32(blk[0] ^ l_key[2]); + out_blk[3] = LE32(blk[1] ^ l_key[3]); +}; + +#else // TC_MINIMIZE_CODE_SIZE + +void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; +#ifdef TC_WINDOWS_BOOT_TWOFISH + u4byte *mk_tab = instance->mk_tab; +#endif + int i; + + blk[0] = LE32(in_blk[0]) ^ l_key[4]; + blk[1] = LE32(in_blk[1]) ^ l_key[5]; + blk[2] = LE32(in_blk[2]) ^ l_key[6]; + blk[3] = LE32(in_blk[3]) ^ l_key[7]; + + for (i = 7; i >= 0; --i) + { + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); + blk[2] = rotl(blk[2], 1) ^ (t0 + t1 + l_key[4 * (i) + 10]); + blk[3] = rotr(blk[3] ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]), 1); + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); + blk[0] = rotl(blk[0], 1) ^ (t0 + t1 + l_key[4 * (i) + 8]); + blk[1] = rotr(blk[1] ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]), 1); + } + + out_blk[0] = LE32(blk[2] ^ l_key[0]); + out_blk[1] = LE32(blk[3] ^ l_key[1]); + out_blk[2] = LE32(blk[0] ^ l_key[2]); + out_blk[3] = LE32(blk[1] ^ l_key[3]); +}; + +#endif // TC_MINIMIZE_CODE_SIZE diff --git a/Crypto/Twofish.h b/Crypto/Twofish.h index 90cdd7d..b4d6cfc 100644 --- a/Crypto/Twofish.h +++ b/Crypto/Twofish.h @@ -1,55 +1,55 @@ -#ifndef TWOFISH_H -#define TWOFISH_H - -#include "Common/Tcdefs.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#ifndef u4byte -#define u4byte unsigned __int32 -#endif -#ifndef u1byte -#define u1byte unsigned char -#endif - -#ifndef extract_byte -#define extract_byte(x,n) ((u1byte)((x) >> (8 * n))) -#endif - -#ifndef rotl - -#ifdef _WIN32 -#include -#pragma intrinsic(_lrotr,_lrotl) -#define rotr(x,n) _lrotr(x,n) -#define rotl(x,n) _lrotl(x,n) -#else -#define rotr(x,n) (((x)>>(n))|((x)<<(32-(n)))) -#define rotl(x,n) (((x)<<(n))|((x)>>(32-(n)))) -#endif - -#endif -typedef struct -{ - u4byte l_key[40]; - u4byte s_key[4]; -#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_TWOFISH) - u4byte mk_tab[4 * 256]; -#endif - u4byte k_len; -} TwofishInstance; - -#define TWOFISH_KS sizeof(TwofishInstance) - -u4byte * twofish_set_key(TwofishInstance *instance, const u4byte in_key[], const u4byte key_len); -void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]); -void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]); - -#if defined(__cplusplus) -} -#endif - -#endif // TWOFISH_H +#ifndef TWOFISH_H +#define TWOFISH_H + +#include "Common/Tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifndef u4byte +#define u4byte unsigned __int32 +#endif +#ifndef u1byte +#define u1byte unsigned char +#endif + +#ifndef extract_byte +#define extract_byte(x,n) ((u1byte)((x) >> (8 * n))) +#endif + +#ifndef rotl + +#ifdef _WIN32 +#include +#pragma intrinsic(_lrotr,_lrotl) +#define rotr(x,n) _lrotr(x,n) +#define rotl(x,n) _lrotl(x,n) +#else +#define rotr(x,n) (((x)>>(n))|((x)<<(32-(n)))) +#define rotl(x,n) (((x)<<(n))|((x)>>(32-(n)))) +#endif + +#endif +typedef struct +{ + u4byte l_key[40]; + u4byte s_key[4]; +#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_TWOFISH) + u4byte mk_tab[4 * 256]; +#endif + u4byte k_len; +} TwofishInstance; + +#define TWOFISH_KS sizeof(TwofishInstance) + +u4byte * twofish_set_key(TwofishInstance *instance, const u4byte in_key[], const u4byte key_len); +void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]); +void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]); + +#if defined(__cplusplus) +} +#endif + +#endif // TWOFISH_H diff --git a/Crypto/Whirlpool.c b/Crypto/Whirlpool.c index adbf515..caf1bc2 100644 --- a/Crypto/Whirlpool.c +++ b/Crypto/Whirlpool.c @@ -1,1058 +1,1058 @@ -/** - * The Whirlpool hashing function. - * - *

- * References - * - *

- * The Whirlpool algorithm was developed by - * Paulo S. L. M. Barreto and - * Vincent Rijmen. - * - * See - * P.S.L.M. Barreto, V. Rijmen, - * ``The Whirlpool hashing function,'' - * NESSIE submission, 2000 (tweaked version, 2001), - * - * - * @author Paulo S.L.M. Barreto - * @author Vincent Rijmen. - * Minor modifications by TrueCrypt Foundation. - * - * @version 3.0 (2003.03.12) - * - * ============================================================================= - * - * Differences from version 2.1: - * - * - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, 9). - * - * ============================================================================= - * - * Differences from version 2.0: - * - * - Generation of ISO/IEC 10118-3 test vectors. - * - Bug fix: nonzero carry was ignored when tallying the data length - * (this bug apparently only manifested itself when feeding data - * in pieces rather than in a single chunk at once). - * - Support for MS Visual C++ 64-bit integer arithmetic. - * - * Differences from version 1.0: - * - * - Original S-box replaced by the tweaked, hardware-efficient version. - * - * ============================================================================= - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - /* The code contained in this file (Whirlpool.c) is in the public domain. */ - -#include -#include -#include -#include - -#include "Whirlpool.h" - -/* #define TRACE_INTERMEDIATE_VALUES */ - -/* - * The number of rounds of the internal dedicated block cipher. - */ -#define R 10 - -/* - * Though Whirlpool is endianness-neutral, the encryption tables are listed - * in BIG-ENDIAN format, which is adopted throughout this implementation - * (but little-endian notation would be equally suitable if consistently - * employed). - */ - -static const u64 C0[256] = { - LL(0x18186018c07830d8), LL(0x23238c2305af4626), LL(0xc6c63fc67ef991b8), LL(0xe8e887e8136fcdfb), - LL(0x878726874ca113cb), LL(0xb8b8dab8a9626d11), LL(0x0101040108050209), LL(0x4f4f214f426e9e0d), - LL(0x3636d836adee6c9b), LL(0xa6a6a2a6590451ff), LL(0xd2d26fd2debdb90c), LL(0xf5f5f3f5fb06f70e), - LL(0x7979f979ef80f296), LL(0x6f6fa16f5fcede30), LL(0x91917e91fcef3f6d), LL(0x52525552aa07a4f8), - LL(0x60609d6027fdc047), LL(0xbcbccabc89766535), LL(0x9b9b569baccd2b37), LL(0x8e8e028e048c018a), - LL(0xa3a3b6a371155bd2), LL(0x0c0c300c603c186c), LL(0x7b7bf17bff8af684), LL(0x3535d435b5e16a80), - LL(0x1d1d741de8693af5), LL(0xe0e0a7e05347ddb3), LL(0xd7d77bd7f6acb321), LL(0xc2c22fc25eed999c), - LL(0x2e2eb82e6d965c43), LL(0x4b4b314b627a9629), LL(0xfefedffea321e15d), LL(0x575741578216aed5), - LL(0x15155415a8412abd), LL(0x7777c1779fb6eee8), LL(0x3737dc37a5eb6e92), LL(0xe5e5b3e57b56d79e), - LL(0x9f9f469f8cd92313), LL(0xf0f0e7f0d317fd23), LL(0x4a4a354a6a7f9420), LL(0xdada4fda9e95a944), - LL(0x58587d58fa25b0a2), LL(0xc9c903c906ca8fcf), LL(0x2929a429558d527c), LL(0x0a0a280a5022145a), - LL(0xb1b1feb1e14f7f50), LL(0xa0a0baa0691a5dc9), LL(0x6b6bb16b7fdad614), LL(0x85852e855cab17d9), - LL(0xbdbdcebd8173673c), LL(0x5d5d695dd234ba8f), LL(0x1010401080502090), LL(0xf4f4f7f4f303f507), - LL(0xcbcb0bcb16c08bdd), LL(0x3e3ef83eedc67cd3), LL(0x0505140528110a2d), LL(0x676781671fe6ce78), - LL(0xe4e4b7e47353d597), LL(0x27279c2725bb4e02), LL(0x4141194132588273), LL(0x8b8b168b2c9d0ba7), - LL(0xa7a7a6a7510153f6), LL(0x7d7de97dcf94fab2), LL(0x95956e95dcfb3749), LL(0xd8d847d88e9fad56), - LL(0xfbfbcbfb8b30eb70), LL(0xeeee9fee2371c1cd), LL(0x7c7ced7cc791f8bb), LL(0x6666856617e3cc71), - LL(0xdddd53dda68ea77b), LL(0x17175c17b84b2eaf), LL(0x4747014702468e45), LL(0x9e9e429e84dc211a), - LL(0xcaca0fca1ec589d4), LL(0x2d2db42d75995a58), LL(0xbfbfc6bf9179632e), LL(0x07071c07381b0e3f), - LL(0xadad8ead012347ac), LL(0x5a5a755aea2fb4b0), LL(0x838336836cb51bef), LL(0x3333cc3385ff66b6), - LL(0x636391633ff2c65c), LL(0x02020802100a0412), LL(0xaaaa92aa39384993), LL(0x7171d971afa8e2de), - LL(0xc8c807c80ecf8dc6), LL(0x19196419c87d32d1), LL(0x494939497270923b), LL(0xd9d943d9869aaf5f), - LL(0xf2f2eff2c31df931), LL(0xe3e3abe34b48dba8), LL(0x5b5b715be22ab6b9), LL(0x88881a8834920dbc), - LL(0x9a9a529aa4c8293e), LL(0x262698262dbe4c0b), LL(0x3232c8328dfa64bf), LL(0xb0b0fab0e94a7d59), - LL(0xe9e983e91b6acff2), LL(0x0f0f3c0f78331e77), LL(0xd5d573d5e6a6b733), LL(0x80803a8074ba1df4), - LL(0xbebec2be997c6127), LL(0xcdcd13cd26de87eb), LL(0x3434d034bde46889), LL(0x48483d487a759032), - LL(0xffffdbffab24e354), LL(0x7a7af57af78ff48d), LL(0x90907a90f4ea3d64), LL(0x5f5f615fc23ebe9d), - LL(0x202080201da0403d), LL(0x6868bd6867d5d00f), LL(0x1a1a681ad07234ca), LL(0xaeae82ae192c41b7), - LL(0xb4b4eab4c95e757d), LL(0x54544d549a19a8ce), LL(0x93937693ece53b7f), LL(0x222288220daa442f), - LL(0x64648d6407e9c863), LL(0xf1f1e3f1db12ff2a), LL(0x7373d173bfa2e6cc), LL(0x12124812905a2482), - LL(0x40401d403a5d807a), LL(0x0808200840281048), LL(0xc3c32bc356e89b95), LL(0xecec97ec337bc5df), - LL(0xdbdb4bdb9690ab4d), LL(0xa1a1bea1611f5fc0), LL(0x8d8d0e8d1c830791), LL(0x3d3df43df5c97ac8), - LL(0x97976697ccf1335b), LL(0x0000000000000000), LL(0xcfcf1bcf36d483f9), LL(0x2b2bac2b4587566e), - LL(0x7676c57697b3ece1), LL(0x8282328264b019e6), LL(0xd6d67fd6fea9b128), LL(0x1b1b6c1bd87736c3), - LL(0xb5b5eeb5c15b7774), LL(0xafaf86af112943be), LL(0x6a6ab56a77dfd41d), LL(0x50505d50ba0da0ea), - LL(0x45450945124c8a57), LL(0xf3f3ebf3cb18fb38), LL(0x3030c0309df060ad), LL(0xefef9bef2b74c3c4), - LL(0x3f3ffc3fe5c37eda), LL(0x55554955921caac7), LL(0xa2a2b2a2791059db), LL(0xeaea8fea0365c9e9), - LL(0x656589650fecca6a), LL(0xbabad2bab9686903), LL(0x2f2fbc2f65935e4a), LL(0xc0c027c04ee79d8e), - LL(0xdede5fdebe81a160), LL(0x1c1c701ce06c38fc), LL(0xfdfdd3fdbb2ee746), LL(0x4d4d294d52649a1f), - LL(0x92927292e4e03976), LL(0x7575c9758fbceafa), LL(0x06061806301e0c36), LL(0x8a8a128a249809ae), - LL(0xb2b2f2b2f940794b), LL(0xe6e6bfe66359d185), LL(0x0e0e380e70361c7e), LL(0x1f1f7c1ff8633ee7), - LL(0x6262956237f7c455), LL(0xd4d477d4eea3b53a), LL(0xa8a89aa829324d81), LL(0x96966296c4f43152), - LL(0xf9f9c3f99b3aef62), LL(0xc5c533c566f697a3), LL(0x2525942535b14a10), LL(0x59597959f220b2ab), - LL(0x84842a8454ae15d0), LL(0x7272d572b7a7e4c5), LL(0x3939e439d5dd72ec), LL(0x4c4c2d4c5a619816), - LL(0x5e5e655eca3bbc94), LL(0x7878fd78e785f09f), LL(0x3838e038ddd870e5), LL(0x8c8c0a8c14860598), - LL(0xd1d163d1c6b2bf17), LL(0xa5a5aea5410b57e4), LL(0xe2e2afe2434dd9a1), LL(0x616199612ff8c24e), - LL(0xb3b3f6b3f1457b42), LL(0x2121842115a54234), LL(0x9c9c4a9c94d62508), LL(0x1e1e781ef0663cee), - LL(0x4343114322528661), LL(0xc7c73bc776fc93b1), LL(0xfcfcd7fcb32be54f), LL(0x0404100420140824), - LL(0x51515951b208a2e3), LL(0x99995e99bcc72f25), LL(0x6d6da96d4fc4da22), LL(0x0d0d340d68391a65), - LL(0xfafacffa8335e979), LL(0xdfdf5bdfb684a369), LL(0x7e7ee57ed79bfca9), LL(0x242490243db44819), - LL(0x3b3bec3bc5d776fe), LL(0xabab96ab313d4b9a), LL(0xcece1fce3ed181f0), LL(0x1111441188552299), - LL(0x8f8f068f0c890383), LL(0x4e4e254e4a6b9c04), LL(0xb7b7e6b7d1517366), LL(0xebeb8beb0b60cbe0), - LL(0x3c3cf03cfdcc78c1), LL(0x81813e817cbf1ffd), LL(0x94946a94d4fe3540), LL(0xf7f7fbf7eb0cf31c), - LL(0xb9b9deb9a1676f18), LL(0x13134c13985f268b), LL(0x2c2cb02c7d9c5851), LL(0xd3d36bd3d6b8bb05), - LL(0xe7e7bbe76b5cd38c), LL(0x6e6ea56e57cbdc39), LL(0xc4c437c46ef395aa), LL(0x03030c03180f061b), - LL(0x565645568a13acdc), LL(0x44440d441a49885e), LL(0x7f7fe17fdf9efea0), LL(0xa9a99ea921374f88), - LL(0x2a2aa82a4d825467), LL(0xbbbbd6bbb16d6b0a), LL(0xc1c123c146e29f87), LL(0x53535153a202a6f1), - LL(0xdcdc57dcae8ba572), LL(0x0b0b2c0b58271653), LL(0x9d9d4e9d9cd32701), LL(0x6c6cad6c47c1d82b), - LL(0x3131c43195f562a4), LL(0x7474cd7487b9e8f3), LL(0xf6f6fff6e309f115), LL(0x464605460a438c4c), - LL(0xacac8aac092645a5), LL(0x89891e893c970fb5), LL(0x14145014a04428b4), LL(0xe1e1a3e15b42dfba), - LL(0x16165816b04e2ca6), LL(0x3a3ae83acdd274f7), LL(0x6969b9696fd0d206), LL(0x09092409482d1241), - LL(0x7070dd70a7ade0d7), LL(0xb6b6e2b6d954716f), LL(0xd0d067d0ceb7bd1e), LL(0xeded93ed3b7ec7d6), - LL(0xcccc17cc2edb85e2), LL(0x424215422a578468), LL(0x98985a98b4c22d2c), LL(0xa4a4aaa4490e55ed), - LL(0x2828a0285d885075), LL(0x5c5c6d5cda31b886), LL(0xf8f8c7f8933fed6b), LL(0x8686228644a411c2), -}; - -static const u64 C1[256] = { - LL(0xd818186018c07830), LL(0x2623238c2305af46), LL(0xb8c6c63fc67ef991), LL(0xfbe8e887e8136fcd), - LL(0xcb878726874ca113), LL(0x11b8b8dab8a9626d), LL(0x0901010401080502), LL(0x0d4f4f214f426e9e), - LL(0x9b3636d836adee6c), LL(0xffa6a6a2a6590451), LL(0x0cd2d26fd2debdb9), LL(0x0ef5f5f3f5fb06f7), - LL(0x967979f979ef80f2), LL(0x306f6fa16f5fcede), LL(0x6d91917e91fcef3f), LL(0xf852525552aa07a4), - LL(0x4760609d6027fdc0), LL(0x35bcbccabc897665), LL(0x379b9b569baccd2b), LL(0x8a8e8e028e048c01), - LL(0xd2a3a3b6a371155b), LL(0x6c0c0c300c603c18), LL(0x847b7bf17bff8af6), LL(0x803535d435b5e16a), - LL(0xf51d1d741de8693a), LL(0xb3e0e0a7e05347dd), LL(0x21d7d77bd7f6acb3), LL(0x9cc2c22fc25eed99), - LL(0x432e2eb82e6d965c), LL(0x294b4b314b627a96), LL(0x5dfefedffea321e1), LL(0xd5575741578216ae), - LL(0xbd15155415a8412a), LL(0xe87777c1779fb6ee), LL(0x923737dc37a5eb6e), LL(0x9ee5e5b3e57b56d7), - LL(0x139f9f469f8cd923), LL(0x23f0f0e7f0d317fd), LL(0x204a4a354a6a7f94), LL(0x44dada4fda9e95a9), - LL(0xa258587d58fa25b0), LL(0xcfc9c903c906ca8f), LL(0x7c2929a429558d52), LL(0x5a0a0a280a502214), - LL(0x50b1b1feb1e14f7f), LL(0xc9a0a0baa0691a5d), LL(0x146b6bb16b7fdad6), LL(0xd985852e855cab17), - LL(0x3cbdbdcebd817367), LL(0x8f5d5d695dd234ba), LL(0x9010104010805020), LL(0x07f4f4f7f4f303f5), - LL(0xddcbcb0bcb16c08b), LL(0xd33e3ef83eedc67c), LL(0x2d0505140528110a), LL(0x78676781671fe6ce), - LL(0x97e4e4b7e47353d5), LL(0x0227279c2725bb4e), LL(0x7341411941325882), LL(0xa78b8b168b2c9d0b), - LL(0xf6a7a7a6a7510153), LL(0xb27d7de97dcf94fa), LL(0x4995956e95dcfb37), LL(0x56d8d847d88e9fad), - LL(0x70fbfbcbfb8b30eb), LL(0xcdeeee9fee2371c1), LL(0xbb7c7ced7cc791f8), LL(0x716666856617e3cc), - LL(0x7bdddd53dda68ea7), LL(0xaf17175c17b84b2e), LL(0x454747014702468e), LL(0x1a9e9e429e84dc21), - LL(0xd4caca0fca1ec589), LL(0x582d2db42d75995a), LL(0x2ebfbfc6bf917963), LL(0x3f07071c07381b0e), - LL(0xacadad8ead012347), LL(0xb05a5a755aea2fb4), LL(0xef838336836cb51b), LL(0xb63333cc3385ff66), - LL(0x5c636391633ff2c6), LL(0x1202020802100a04), LL(0x93aaaa92aa393849), LL(0xde7171d971afa8e2), - LL(0xc6c8c807c80ecf8d), LL(0xd119196419c87d32), LL(0x3b49493949727092), LL(0x5fd9d943d9869aaf), - LL(0x31f2f2eff2c31df9), LL(0xa8e3e3abe34b48db), LL(0xb95b5b715be22ab6), LL(0xbc88881a8834920d), - LL(0x3e9a9a529aa4c829), LL(0x0b262698262dbe4c), LL(0xbf3232c8328dfa64), LL(0x59b0b0fab0e94a7d), - LL(0xf2e9e983e91b6acf), LL(0x770f0f3c0f78331e), LL(0x33d5d573d5e6a6b7), LL(0xf480803a8074ba1d), - LL(0x27bebec2be997c61), LL(0xebcdcd13cd26de87), LL(0x893434d034bde468), LL(0x3248483d487a7590), - LL(0x54ffffdbffab24e3), LL(0x8d7a7af57af78ff4), LL(0x6490907a90f4ea3d), LL(0x9d5f5f615fc23ebe), - LL(0x3d202080201da040), LL(0x0f6868bd6867d5d0), LL(0xca1a1a681ad07234), LL(0xb7aeae82ae192c41), - LL(0x7db4b4eab4c95e75), LL(0xce54544d549a19a8), LL(0x7f93937693ece53b), LL(0x2f222288220daa44), - LL(0x6364648d6407e9c8), LL(0x2af1f1e3f1db12ff), LL(0xcc7373d173bfa2e6), LL(0x8212124812905a24), - LL(0x7a40401d403a5d80), LL(0x4808082008402810), LL(0x95c3c32bc356e89b), LL(0xdfecec97ec337bc5), - LL(0x4ddbdb4bdb9690ab), LL(0xc0a1a1bea1611f5f), LL(0x918d8d0e8d1c8307), LL(0xc83d3df43df5c97a), - LL(0x5b97976697ccf133), LL(0x0000000000000000), LL(0xf9cfcf1bcf36d483), LL(0x6e2b2bac2b458756), - LL(0xe17676c57697b3ec), LL(0xe68282328264b019), LL(0x28d6d67fd6fea9b1), LL(0xc31b1b6c1bd87736), - LL(0x74b5b5eeb5c15b77), LL(0xbeafaf86af112943), LL(0x1d6a6ab56a77dfd4), LL(0xea50505d50ba0da0), - LL(0x5745450945124c8a), LL(0x38f3f3ebf3cb18fb), LL(0xad3030c0309df060), LL(0xc4efef9bef2b74c3), - LL(0xda3f3ffc3fe5c37e), LL(0xc755554955921caa), LL(0xdba2a2b2a2791059), LL(0xe9eaea8fea0365c9), - LL(0x6a656589650fecca), LL(0x03babad2bab96869), LL(0x4a2f2fbc2f65935e), LL(0x8ec0c027c04ee79d), - LL(0x60dede5fdebe81a1), LL(0xfc1c1c701ce06c38), LL(0x46fdfdd3fdbb2ee7), LL(0x1f4d4d294d52649a), - LL(0x7692927292e4e039), LL(0xfa7575c9758fbcea), LL(0x3606061806301e0c), LL(0xae8a8a128a249809), - LL(0x4bb2b2f2b2f94079), LL(0x85e6e6bfe66359d1), LL(0x7e0e0e380e70361c), LL(0xe71f1f7c1ff8633e), - LL(0x556262956237f7c4), LL(0x3ad4d477d4eea3b5), LL(0x81a8a89aa829324d), LL(0x5296966296c4f431), - LL(0x62f9f9c3f99b3aef), LL(0xa3c5c533c566f697), LL(0x102525942535b14a), LL(0xab59597959f220b2), - LL(0xd084842a8454ae15), LL(0xc57272d572b7a7e4), LL(0xec3939e439d5dd72), LL(0x164c4c2d4c5a6198), - LL(0x945e5e655eca3bbc), LL(0x9f7878fd78e785f0), LL(0xe53838e038ddd870), LL(0x988c8c0a8c148605), - LL(0x17d1d163d1c6b2bf), LL(0xe4a5a5aea5410b57), LL(0xa1e2e2afe2434dd9), LL(0x4e616199612ff8c2), - LL(0x42b3b3f6b3f1457b), LL(0x342121842115a542), LL(0x089c9c4a9c94d625), LL(0xee1e1e781ef0663c), - LL(0x6143431143225286), LL(0xb1c7c73bc776fc93), LL(0x4ffcfcd7fcb32be5), LL(0x2404041004201408), - LL(0xe351515951b208a2), LL(0x2599995e99bcc72f), LL(0x226d6da96d4fc4da), LL(0x650d0d340d68391a), - LL(0x79fafacffa8335e9), LL(0x69dfdf5bdfb684a3), LL(0xa97e7ee57ed79bfc), LL(0x19242490243db448), - LL(0xfe3b3bec3bc5d776), LL(0x9aabab96ab313d4b), LL(0xf0cece1fce3ed181), LL(0x9911114411885522), - LL(0x838f8f068f0c8903), LL(0x044e4e254e4a6b9c), LL(0x66b7b7e6b7d15173), LL(0xe0ebeb8beb0b60cb), - LL(0xc13c3cf03cfdcc78), LL(0xfd81813e817cbf1f), LL(0x4094946a94d4fe35), LL(0x1cf7f7fbf7eb0cf3), - LL(0x18b9b9deb9a1676f), LL(0x8b13134c13985f26), LL(0x512c2cb02c7d9c58), LL(0x05d3d36bd3d6b8bb), - LL(0x8ce7e7bbe76b5cd3), LL(0x396e6ea56e57cbdc), LL(0xaac4c437c46ef395), LL(0x1b03030c03180f06), - LL(0xdc565645568a13ac), LL(0x5e44440d441a4988), LL(0xa07f7fe17fdf9efe), LL(0x88a9a99ea921374f), - LL(0x672a2aa82a4d8254), LL(0x0abbbbd6bbb16d6b), LL(0x87c1c123c146e29f), LL(0xf153535153a202a6), - LL(0x72dcdc57dcae8ba5), LL(0x530b0b2c0b582716), LL(0x019d9d4e9d9cd327), LL(0x2b6c6cad6c47c1d8), - LL(0xa43131c43195f562), LL(0xf37474cd7487b9e8), LL(0x15f6f6fff6e309f1), LL(0x4c464605460a438c), - LL(0xa5acac8aac092645), LL(0xb589891e893c970f), LL(0xb414145014a04428), LL(0xbae1e1a3e15b42df), - LL(0xa616165816b04e2c), LL(0xf73a3ae83acdd274), LL(0x066969b9696fd0d2), LL(0x4109092409482d12), - LL(0xd77070dd70a7ade0), LL(0x6fb6b6e2b6d95471), LL(0x1ed0d067d0ceb7bd), LL(0xd6eded93ed3b7ec7), - LL(0xe2cccc17cc2edb85), LL(0x68424215422a5784), LL(0x2c98985a98b4c22d), LL(0xeda4a4aaa4490e55), - LL(0x752828a0285d8850), LL(0x865c5c6d5cda31b8), LL(0x6bf8f8c7f8933fed), LL(0xc28686228644a411), -}; - -static const u64 C2[256] = { - LL(0x30d818186018c078), LL(0x462623238c2305af), LL(0x91b8c6c63fc67ef9), LL(0xcdfbe8e887e8136f), - LL(0x13cb878726874ca1), LL(0x6d11b8b8dab8a962), LL(0x0209010104010805), LL(0x9e0d4f4f214f426e), - LL(0x6c9b3636d836adee), LL(0x51ffa6a6a2a65904), LL(0xb90cd2d26fd2debd), LL(0xf70ef5f5f3f5fb06), - LL(0xf2967979f979ef80), LL(0xde306f6fa16f5fce), LL(0x3f6d91917e91fcef), LL(0xa4f852525552aa07), - LL(0xc04760609d6027fd), LL(0x6535bcbccabc8976), LL(0x2b379b9b569baccd), LL(0x018a8e8e028e048c), - LL(0x5bd2a3a3b6a37115), LL(0x186c0c0c300c603c), LL(0xf6847b7bf17bff8a), LL(0x6a803535d435b5e1), - LL(0x3af51d1d741de869), LL(0xddb3e0e0a7e05347), LL(0xb321d7d77bd7f6ac), LL(0x999cc2c22fc25eed), - LL(0x5c432e2eb82e6d96), LL(0x96294b4b314b627a), LL(0xe15dfefedffea321), LL(0xaed5575741578216), - LL(0x2abd15155415a841), LL(0xeee87777c1779fb6), LL(0x6e923737dc37a5eb), LL(0xd79ee5e5b3e57b56), - LL(0x23139f9f469f8cd9), LL(0xfd23f0f0e7f0d317), LL(0x94204a4a354a6a7f), LL(0xa944dada4fda9e95), - LL(0xb0a258587d58fa25), LL(0x8fcfc9c903c906ca), LL(0x527c2929a429558d), LL(0x145a0a0a280a5022), - LL(0x7f50b1b1feb1e14f), LL(0x5dc9a0a0baa0691a), LL(0xd6146b6bb16b7fda), LL(0x17d985852e855cab), - LL(0x673cbdbdcebd8173), LL(0xba8f5d5d695dd234), LL(0x2090101040108050), LL(0xf507f4f4f7f4f303), - LL(0x8bddcbcb0bcb16c0), LL(0x7cd33e3ef83eedc6), LL(0x0a2d050514052811), LL(0xce78676781671fe6), - LL(0xd597e4e4b7e47353), LL(0x4e0227279c2725bb), LL(0x8273414119413258), LL(0x0ba78b8b168b2c9d), - LL(0x53f6a7a7a6a75101), LL(0xfab27d7de97dcf94), LL(0x374995956e95dcfb), LL(0xad56d8d847d88e9f), - LL(0xeb70fbfbcbfb8b30), LL(0xc1cdeeee9fee2371), LL(0xf8bb7c7ced7cc791), LL(0xcc716666856617e3), - LL(0xa77bdddd53dda68e), LL(0x2eaf17175c17b84b), LL(0x8e45474701470246), LL(0x211a9e9e429e84dc), - LL(0x89d4caca0fca1ec5), LL(0x5a582d2db42d7599), LL(0x632ebfbfc6bf9179), LL(0x0e3f07071c07381b), - LL(0x47acadad8ead0123), LL(0xb4b05a5a755aea2f), LL(0x1bef838336836cb5), LL(0x66b63333cc3385ff), - LL(0xc65c636391633ff2), LL(0x041202020802100a), LL(0x4993aaaa92aa3938), LL(0xe2de7171d971afa8), - LL(0x8dc6c8c807c80ecf), LL(0x32d119196419c87d), LL(0x923b494939497270), LL(0xaf5fd9d943d9869a), - LL(0xf931f2f2eff2c31d), LL(0xdba8e3e3abe34b48), LL(0xb6b95b5b715be22a), LL(0x0dbc88881a883492), - LL(0x293e9a9a529aa4c8), LL(0x4c0b262698262dbe), LL(0x64bf3232c8328dfa), LL(0x7d59b0b0fab0e94a), - LL(0xcff2e9e983e91b6a), LL(0x1e770f0f3c0f7833), LL(0xb733d5d573d5e6a6), LL(0x1df480803a8074ba), - LL(0x6127bebec2be997c), LL(0x87ebcdcd13cd26de), LL(0x68893434d034bde4), LL(0x903248483d487a75), - LL(0xe354ffffdbffab24), LL(0xf48d7a7af57af78f), LL(0x3d6490907a90f4ea), LL(0xbe9d5f5f615fc23e), - LL(0x403d202080201da0), LL(0xd00f6868bd6867d5), LL(0x34ca1a1a681ad072), LL(0x41b7aeae82ae192c), - LL(0x757db4b4eab4c95e), LL(0xa8ce54544d549a19), LL(0x3b7f93937693ece5), LL(0x442f222288220daa), - LL(0xc86364648d6407e9), LL(0xff2af1f1e3f1db12), LL(0xe6cc7373d173bfa2), LL(0x248212124812905a), - LL(0x807a40401d403a5d), LL(0x1048080820084028), LL(0x9b95c3c32bc356e8), LL(0xc5dfecec97ec337b), - LL(0xab4ddbdb4bdb9690), LL(0x5fc0a1a1bea1611f), LL(0x07918d8d0e8d1c83), LL(0x7ac83d3df43df5c9), - LL(0x335b97976697ccf1), LL(0x0000000000000000), LL(0x83f9cfcf1bcf36d4), LL(0x566e2b2bac2b4587), - LL(0xece17676c57697b3), LL(0x19e68282328264b0), LL(0xb128d6d67fd6fea9), LL(0x36c31b1b6c1bd877), - LL(0x7774b5b5eeb5c15b), LL(0x43beafaf86af1129), LL(0xd41d6a6ab56a77df), LL(0xa0ea50505d50ba0d), - LL(0x8a5745450945124c), LL(0xfb38f3f3ebf3cb18), LL(0x60ad3030c0309df0), LL(0xc3c4efef9bef2b74), - LL(0x7eda3f3ffc3fe5c3), LL(0xaac755554955921c), LL(0x59dba2a2b2a27910), LL(0xc9e9eaea8fea0365), - LL(0xca6a656589650fec), LL(0x6903babad2bab968), LL(0x5e4a2f2fbc2f6593), LL(0x9d8ec0c027c04ee7), - LL(0xa160dede5fdebe81), LL(0x38fc1c1c701ce06c), LL(0xe746fdfdd3fdbb2e), LL(0x9a1f4d4d294d5264), - LL(0x397692927292e4e0), LL(0xeafa7575c9758fbc), LL(0x0c3606061806301e), LL(0x09ae8a8a128a2498), - LL(0x794bb2b2f2b2f940), LL(0xd185e6e6bfe66359), LL(0x1c7e0e0e380e7036), LL(0x3ee71f1f7c1ff863), - LL(0xc4556262956237f7), LL(0xb53ad4d477d4eea3), LL(0x4d81a8a89aa82932), LL(0x315296966296c4f4), - LL(0xef62f9f9c3f99b3a), LL(0x97a3c5c533c566f6), LL(0x4a102525942535b1), LL(0xb2ab59597959f220), - LL(0x15d084842a8454ae), LL(0xe4c57272d572b7a7), LL(0x72ec3939e439d5dd), LL(0x98164c4c2d4c5a61), - LL(0xbc945e5e655eca3b), LL(0xf09f7878fd78e785), LL(0x70e53838e038ddd8), LL(0x05988c8c0a8c1486), - LL(0xbf17d1d163d1c6b2), LL(0x57e4a5a5aea5410b), LL(0xd9a1e2e2afe2434d), LL(0xc24e616199612ff8), - LL(0x7b42b3b3f6b3f145), LL(0x42342121842115a5), LL(0x25089c9c4a9c94d6), LL(0x3cee1e1e781ef066), - LL(0x8661434311432252), LL(0x93b1c7c73bc776fc), LL(0xe54ffcfcd7fcb32b), LL(0x0824040410042014), - LL(0xa2e351515951b208), LL(0x2f2599995e99bcc7), LL(0xda226d6da96d4fc4), LL(0x1a650d0d340d6839), - LL(0xe979fafacffa8335), LL(0xa369dfdf5bdfb684), LL(0xfca97e7ee57ed79b), LL(0x4819242490243db4), - LL(0x76fe3b3bec3bc5d7), LL(0x4b9aabab96ab313d), LL(0x81f0cece1fce3ed1), LL(0x2299111144118855), - LL(0x03838f8f068f0c89), LL(0x9c044e4e254e4a6b), LL(0x7366b7b7e6b7d151), LL(0xcbe0ebeb8beb0b60), - LL(0x78c13c3cf03cfdcc), LL(0x1ffd81813e817cbf), LL(0x354094946a94d4fe), LL(0xf31cf7f7fbf7eb0c), - LL(0x6f18b9b9deb9a167), LL(0x268b13134c13985f), LL(0x58512c2cb02c7d9c), LL(0xbb05d3d36bd3d6b8), - LL(0xd38ce7e7bbe76b5c), LL(0xdc396e6ea56e57cb), LL(0x95aac4c437c46ef3), LL(0x061b03030c03180f), - LL(0xacdc565645568a13), LL(0x885e44440d441a49), LL(0xfea07f7fe17fdf9e), LL(0x4f88a9a99ea92137), - LL(0x54672a2aa82a4d82), LL(0x6b0abbbbd6bbb16d), LL(0x9f87c1c123c146e2), LL(0xa6f153535153a202), - LL(0xa572dcdc57dcae8b), LL(0x16530b0b2c0b5827), LL(0x27019d9d4e9d9cd3), LL(0xd82b6c6cad6c47c1), - LL(0x62a43131c43195f5), LL(0xe8f37474cd7487b9), LL(0xf115f6f6fff6e309), LL(0x8c4c464605460a43), - LL(0x45a5acac8aac0926), LL(0x0fb589891e893c97), LL(0x28b414145014a044), LL(0xdfbae1e1a3e15b42), - LL(0x2ca616165816b04e), LL(0x74f73a3ae83acdd2), LL(0xd2066969b9696fd0), LL(0x124109092409482d), - LL(0xe0d77070dd70a7ad), LL(0x716fb6b6e2b6d954), LL(0xbd1ed0d067d0ceb7), LL(0xc7d6eded93ed3b7e), - LL(0x85e2cccc17cc2edb), LL(0x8468424215422a57), LL(0x2d2c98985a98b4c2), LL(0x55eda4a4aaa4490e), - LL(0x50752828a0285d88), LL(0xb8865c5c6d5cda31), LL(0xed6bf8f8c7f8933f), LL(0x11c28686228644a4), -}; - -static const u64 C3[256] = { - LL(0x7830d818186018c0), LL(0xaf462623238c2305), LL(0xf991b8c6c63fc67e), LL(0x6fcdfbe8e887e813), - LL(0xa113cb878726874c), LL(0x626d11b8b8dab8a9), LL(0x0502090101040108), LL(0x6e9e0d4f4f214f42), - LL(0xee6c9b3636d836ad), LL(0x0451ffa6a6a2a659), LL(0xbdb90cd2d26fd2de), LL(0x06f70ef5f5f3f5fb), - LL(0x80f2967979f979ef), LL(0xcede306f6fa16f5f), LL(0xef3f6d91917e91fc), LL(0x07a4f852525552aa), - LL(0xfdc04760609d6027), LL(0x766535bcbccabc89), LL(0xcd2b379b9b569bac), LL(0x8c018a8e8e028e04), - LL(0x155bd2a3a3b6a371), LL(0x3c186c0c0c300c60), LL(0x8af6847b7bf17bff), LL(0xe16a803535d435b5), - LL(0x693af51d1d741de8), LL(0x47ddb3e0e0a7e053), LL(0xacb321d7d77bd7f6), LL(0xed999cc2c22fc25e), - LL(0x965c432e2eb82e6d), LL(0x7a96294b4b314b62), LL(0x21e15dfefedffea3), LL(0x16aed55757415782), - LL(0x412abd15155415a8), LL(0xb6eee87777c1779f), LL(0xeb6e923737dc37a5), LL(0x56d79ee5e5b3e57b), - LL(0xd923139f9f469f8c), LL(0x17fd23f0f0e7f0d3), LL(0x7f94204a4a354a6a), LL(0x95a944dada4fda9e), - LL(0x25b0a258587d58fa), LL(0xca8fcfc9c903c906), LL(0x8d527c2929a42955), LL(0x22145a0a0a280a50), - LL(0x4f7f50b1b1feb1e1), LL(0x1a5dc9a0a0baa069), LL(0xdad6146b6bb16b7f), LL(0xab17d985852e855c), - LL(0x73673cbdbdcebd81), LL(0x34ba8f5d5d695dd2), LL(0x5020901010401080), LL(0x03f507f4f4f7f4f3), - LL(0xc08bddcbcb0bcb16), LL(0xc67cd33e3ef83eed), LL(0x110a2d0505140528), LL(0xe6ce78676781671f), - LL(0x53d597e4e4b7e473), LL(0xbb4e0227279c2725), LL(0x5882734141194132), LL(0x9d0ba78b8b168b2c), - LL(0x0153f6a7a7a6a751), LL(0x94fab27d7de97dcf), LL(0xfb374995956e95dc), LL(0x9fad56d8d847d88e), - LL(0x30eb70fbfbcbfb8b), LL(0x71c1cdeeee9fee23), LL(0x91f8bb7c7ced7cc7), LL(0xe3cc716666856617), - LL(0x8ea77bdddd53dda6), LL(0x4b2eaf17175c17b8), LL(0x468e454747014702), LL(0xdc211a9e9e429e84), - LL(0xc589d4caca0fca1e), LL(0x995a582d2db42d75), LL(0x79632ebfbfc6bf91), LL(0x1b0e3f07071c0738), - LL(0x2347acadad8ead01), LL(0x2fb4b05a5a755aea), LL(0xb51bef838336836c), LL(0xff66b63333cc3385), - LL(0xf2c65c636391633f), LL(0x0a04120202080210), LL(0x384993aaaa92aa39), LL(0xa8e2de7171d971af), - LL(0xcf8dc6c8c807c80e), LL(0x7d32d119196419c8), LL(0x70923b4949394972), LL(0x9aaf5fd9d943d986), - LL(0x1df931f2f2eff2c3), LL(0x48dba8e3e3abe34b), LL(0x2ab6b95b5b715be2), LL(0x920dbc88881a8834), - LL(0xc8293e9a9a529aa4), LL(0xbe4c0b262698262d), LL(0xfa64bf3232c8328d), LL(0x4a7d59b0b0fab0e9), - LL(0x6acff2e9e983e91b), LL(0x331e770f0f3c0f78), LL(0xa6b733d5d573d5e6), LL(0xba1df480803a8074), - LL(0x7c6127bebec2be99), LL(0xde87ebcdcd13cd26), LL(0xe468893434d034bd), LL(0x75903248483d487a), - LL(0x24e354ffffdbffab), LL(0x8ff48d7a7af57af7), LL(0xea3d6490907a90f4), LL(0x3ebe9d5f5f615fc2), - LL(0xa0403d202080201d), LL(0xd5d00f6868bd6867), LL(0x7234ca1a1a681ad0), LL(0x2c41b7aeae82ae19), - LL(0x5e757db4b4eab4c9), LL(0x19a8ce54544d549a), LL(0xe53b7f93937693ec), LL(0xaa442f222288220d), - LL(0xe9c86364648d6407), LL(0x12ff2af1f1e3f1db), LL(0xa2e6cc7373d173bf), LL(0x5a24821212481290), - LL(0x5d807a40401d403a), LL(0x2810480808200840), LL(0xe89b95c3c32bc356), LL(0x7bc5dfecec97ec33), - LL(0x90ab4ddbdb4bdb96), LL(0x1f5fc0a1a1bea161), LL(0x8307918d8d0e8d1c), LL(0xc97ac83d3df43df5), - LL(0xf1335b97976697cc), LL(0x0000000000000000), LL(0xd483f9cfcf1bcf36), LL(0x87566e2b2bac2b45), - LL(0xb3ece17676c57697), LL(0xb019e68282328264), LL(0xa9b128d6d67fd6fe), LL(0x7736c31b1b6c1bd8), - LL(0x5b7774b5b5eeb5c1), LL(0x2943beafaf86af11), LL(0xdfd41d6a6ab56a77), LL(0x0da0ea50505d50ba), - LL(0x4c8a574545094512), LL(0x18fb38f3f3ebf3cb), LL(0xf060ad3030c0309d), LL(0x74c3c4efef9bef2b), - LL(0xc37eda3f3ffc3fe5), LL(0x1caac75555495592), LL(0x1059dba2a2b2a279), LL(0x65c9e9eaea8fea03), - LL(0xecca6a656589650f), LL(0x686903babad2bab9), LL(0x935e4a2f2fbc2f65), LL(0xe79d8ec0c027c04e), - LL(0x81a160dede5fdebe), LL(0x6c38fc1c1c701ce0), LL(0x2ee746fdfdd3fdbb), LL(0x649a1f4d4d294d52), - LL(0xe0397692927292e4), LL(0xbceafa7575c9758f), LL(0x1e0c360606180630), LL(0x9809ae8a8a128a24), - LL(0x40794bb2b2f2b2f9), LL(0x59d185e6e6bfe663), LL(0x361c7e0e0e380e70), LL(0x633ee71f1f7c1ff8), - LL(0xf7c4556262956237), LL(0xa3b53ad4d477d4ee), LL(0x324d81a8a89aa829), LL(0xf4315296966296c4), - LL(0x3aef62f9f9c3f99b), LL(0xf697a3c5c533c566), LL(0xb14a102525942535), LL(0x20b2ab59597959f2), - LL(0xae15d084842a8454), LL(0xa7e4c57272d572b7), LL(0xdd72ec3939e439d5), LL(0x6198164c4c2d4c5a), - LL(0x3bbc945e5e655eca), LL(0x85f09f7878fd78e7), LL(0xd870e53838e038dd), LL(0x8605988c8c0a8c14), - LL(0xb2bf17d1d163d1c6), LL(0x0b57e4a5a5aea541), LL(0x4dd9a1e2e2afe243), LL(0xf8c24e616199612f), - LL(0x457b42b3b3f6b3f1), LL(0xa542342121842115), LL(0xd625089c9c4a9c94), LL(0x663cee1e1e781ef0), - LL(0x5286614343114322), LL(0xfc93b1c7c73bc776), LL(0x2be54ffcfcd7fcb3), LL(0x1408240404100420), - LL(0x08a2e351515951b2), LL(0xc72f2599995e99bc), LL(0xc4da226d6da96d4f), LL(0x391a650d0d340d68), - LL(0x35e979fafacffa83), LL(0x84a369dfdf5bdfb6), LL(0x9bfca97e7ee57ed7), LL(0xb44819242490243d), - LL(0xd776fe3b3bec3bc5), LL(0x3d4b9aabab96ab31), LL(0xd181f0cece1fce3e), LL(0x5522991111441188), - LL(0x8903838f8f068f0c), LL(0x6b9c044e4e254e4a), LL(0x517366b7b7e6b7d1), LL(0x60cbe0ebeb8beb0b), - LL(0xcc78c13c3cf03cfd), LL(0xbf1ffd81813e817c), LL(0xfe354094946a94d4), LL(0x0cf31cf7f7fbf7eb), - LL(0x676f18b9b9deb9a1), LL(0x5f268b13134c1398), LL(0x9c58512c2cb02c7d), LL(0xb8bb05d3d36bd3d6), - LL(0x5cd38ce7e7bbe76b), LL(0xcbdc396e6ea56e57), LL(0xf395aac4c437c46e), LL(0x0f061b03030c0318), - LL(0x13acdc565645568a), LL(0x49885e44440d441a), LL(0x9efea07f7fe17fdf), LL(0x374f88a9a99ea921), - LL(0x8254672a2aa82a4d), LL(0x6d6b0abbbbd6bbb1), LL(0xe29f87c1c123c146), LL(0x02a6f153535153a2), - LL(0x8ba572dcdc57dcae), LL(0x2716530b0b2c0b58), LL(0xd327019d9d4e9d9c), LL(0xc1d82b6c6cad6c47), - LL(0xf562a43131c43195), LL(0xb9e8f37474cd7487), LL(0x09f115f6f6fff6e3), LL(0x438c4c464605460a), - LL(0x2645a5acac8aac09), LL(0x970fb589891e893c), LL(0x4428b414145014a0), LL(0x42dfbae1e1a3e15b), - LL(0x4e2ca616165816b0), LL(0xd274f73a3ae83acd), LL(0xd0d2066969b9696f), LL(0x2d12410909240948), - LL(0xade0d77070dd70a7), LL(0x54716fb6b6e2b6d9), LL(0xb7bd1ed0d067d0ce), LL(0x7ec7d6eded93ed3b), - LL(0xdb85e2cccc17cc2e), LL(0x578468424215422a), LL(0xc22d2c98985a98b4), LL(0x0e55eda4a4aaa449), - LL(0x8850752828a0285d), LL(0x31b8865c5c6d5cda), LL(0x3fed6bf8f8c7f893), LL(0xa411c28686228644), -}; - -static const u64 C4[256] = { - LL(0xc07830d818186018), LL(0x05af462623238c23), LL(0x7ef991b8c6c63fc6), LL(0x136fcdfbe8e887e8), - LL(0x4ca113cb87872687), LL(0xa9626d11b8b8dab8), LL(0x0805020901010401), LL(0x426e9e0d4f4f214f), - LL(0xadee6c9b3636d836), LL(0x590451ffa6a6a2a6), LL(0xdebdb90cd2d26fd2), LL(0xfb06f70ef5f5f3f5), - LL(0xef80f2967979f979), LL(0x5fcede306f6fa16f), LL(0xfcef3f6d91917e91), LL(0xaa07a4f852525552), - LL(0x27fdc04760609d60), LL(0x89766535bcbccabc), LL(0xaccd2b379b9b569b), LL(0x048c018a8e8e028e), - LL(0x71155bd2a3a3b6a3), LL(0x603c186c0c0c300c), LL(0xff8af6847b7bf17b), LL(0xb5e16a803535d435), - LL(0xe8693af51d1d741d), LL(0x5347ddb3e0e0a7e0), LL(0xf6acb321d7d77bd7), LL(0x5eed999cc2c22fc2), - LL(0x6d965c432e2eb82e), LL(0x627a96294b4b314b), LL(0xa321e15dfefedffe), LL(0x8216aed557574157), - LL(0xa8412abd15155415), LL(0x9fb6eee87777c177), LL(0xa5eb6e923737dc37), LL(0x7b56d79ee5e5b3e5), - LL(0x8cd923139f9f469f), LL(0xd317fd23f0f0e7f0), LL(0x6a7f94204a4a354a), LL(0x9e95a944dada4fda), - LL(0xfa25b0a258587d58), LL(0x06ca8fcfc9c903c9), LL(0x558d527c2929a429), LL(0x5022145a0a0a280a), - LL(0xe14f7f50b1b1feb1), LL(0x691a5dc9a0a0baa0), LL(0x7fdad6146b6bb16b), LL(0x5cab17d985852e85), - LL(0x8173673cbdbdcebd), LL(0xd234ba8f5d5d695d), LL(0x8050209010104010), LL(0xf303f507f4f4f7f4), - LL(0x16c08bddcbcb0bcb), LL(0xedc67cd33e3ef83e), LL(0x28110a2d05051405), LL(0x1fe6ce7867678167), - LL(0x7353d597e4e4b7e4), LL(0x25bb4e0227279c27), LL(0x3258827341411941), LL(0x2c9d0ba78b8b168b), - LL(0x510153f6a7a7a6a7), LL(0xcf94fab27d7de97d), LL(0xdcfb374995956e95), LL(0x8e9fad56d8d847d8), - LL(0x8b30eb70fbfbcbfb), LL(0x2371c1cdeeee9fee), LL(0xc791f8bb7c7ced7c), LL(0x17e3cc7166668566), - LL(0xa68ea77bdddd53dd), LL(0xb84b2eaf17175c17), LL(0x02468e4547470147), LL(0x84dc211a9e9e429e), - LL(0x1ec589d4caca0fca), LL(0x75995a582d2db42d), LL(0x9179632ebfbfc6bf), LL(0x381b0e3f07071c07), - LL(0x012347acadad8ead), LL(0xea2fb4b05a5a755a), LL(0x6cb51bef83833683), LL(0x85ff66b63333cc33), - LL(0x3ff2c65c63639163), LL(0x100a041202020802), LL(0x39384993aaaa92aa), LL(0xafa8e2de7171d971), - LL(0x0ecf8dc6c8c807c8), LL(0xc87d32d119196419), LL(0x7270923b49493949), LL(0x869aaf5fd9d943d9), - LL(0xc31df931f2f2eff2), LL(0x4b48dba8e3e3abe3), LL(0xe22ab6b95b5b715b), LL(0x34920dbc88881a88), - LL(0xa4c8293e9a9a529a), LL(0x2dbe4c0b26269826), LL(0x8dfa64bf3232c832), LL(0xe94a7d59b0b0fab0), - LL(0x1b6acff2e9e983e9), LL(0x78331e770f0f3c0f), LL(0xe6a6b733d5d573d5), LL(0x74ba1df480803a80), - LL(0x997c6127bebec2be), LL(0x26de87ebcdcd13cd), LL(0xbde468893434d034), LL(0x7a75903248483d48), - LL(0xab24e354ffffdbff), LL(0xf78ff48d7a7af57a), LL(0xf4ea3d6490907a90), LL(0xc23ebe9d5f5f615f), - LL(0x1da0403d20208020), LL(0x67d5d00f6868bd68), LL(0xd07234ca1a1a681a), LL(0x192c41b7aeae82ae), - LL(0xc95e757db4b4eab4), LL(0x9a19a8ce54544d54), LL(0xece53b7f93937693), LL(0x0daa442f22228822), - LL(0x07e9c86364648d64), LL(0xdb12ff2af1f1e3f1), LL(0xbfa2e6cc7373d173), LL(0x905a248212124812), - LL(0x3a5d807a40401d40), LL(0x4028104808082008), LL(0x56e89b95c3c32bc3), LL(0x337bc5dfecec97ec), - LL(0x9690ab4ddbdb4bdb), LL(0x611f5fc0a1a1bea1), LL(0x1c8307918d8d0e8d), LL(0xf5c97ac83d3df43d), - LL(0xccf1335b97976697), LL(0x0000000000000000), LL(0x36d483f9cfcf1bcf), LL(0x4587566e2b2bac2b), - LL(0x97b3ece17676c576), LL(0x64b019e682823282), LL(0xfea9b128d6d67fd6), LL(0xd87736c31b1b6c1b), - LL(0xc15b7774b5b5eeb5), LL(0x112943beafaf86af), LL(0x77dfd41d6a6ab56a), LL(0xba0da0ea50505d50), - LL(0x124c8a5745450945), LL(0xcb18fb38f3f3ebf3), LL(0x9df060ad3030c030), LL(0x2b74c3c4efef9bef), - LL(0xe5c37eda3f3ffc3f), LL(0x921caac755554955), LL(0x791059dba2a2b2a2), LL(0x0365c9e9eaea8fea), - LL(0x0fecca6a65658965), LL(0xb9686903babad2ba), LL(0x65935e4a2f2fbc2f), LL(0x4ee79d8ec0c027c0), - LL(0xbe81a160dede5fde), LL(0xe06c38fc1c1c701c), LL(0xbb2ee746fdfdd3fd), LL(0x52649a1f4d4d294d), - LL(0xe4e0397692927292), LL(0x8fbceafa7575c975), LL(0x301e0c3606061806), LL(0x249809ae8a8a128a), - LL(0xf940794bb2b2f2b2), LL(0x6359d185e6e6bfe6), LL(0x70361c7e0e0e380e), LL(0xf8633ee71f1f7c1f), - LL(0x37f7c45562629562), LL(0xeea3b53ad4d477d4), LL(0x29324d81a8a89aa8), LL(0xc4f4315296966296), - LL(0x9b3aef62f9f9c3f9), LL(0x66f697a3c5c533c5), LL(0x35b14a1025259425), LL(0xf220b2ab59597959), - LL(0x54ae15d084842a84), LL(0xb7a7e4c57272d572), LL(0xd5dd72ec3939e439), LL(0x5a6198164c4c2d4c), - LL(0xca3bbc945e5e655e), LL(0xe785f09f7878fd78), LL(0xddd870e53838e038), LL(0x148605988c8c0a8c), - LL(0xc6b2bf17d1d163d1), LL(0x410b57e4a5a5aea5), LL(0x434dd9a1e2e2afe2), LL(0x2ff8c24e61619961), - LL(0xf1457b42b3b3f6b3), LL(0x15a5423421218421), LL(0x94d625089c9c4a9c), LL(0xf0663cee1e1e781e), - LL(0x2252866143431143), LL(0x76fc93b1c7c73bc7), LL(0xb32be54ffcfcd7fc), LL(0x2014082404041004), - LL(0xb208a2e351515951), LL(0xbcc72f2599995e99), LL(0x4fc4da226d6da96d), LL(0x68391a650d0d340d), - LL(0x8335e979fafacffa), LL(0xb684a369dfdf5bdf), LL(0xd79bfca97e7ee57e), LL(0x3db4481924249024), - LL(0xc5d776fe3b3bec3b), LL(0x313d4b9aabab96ab), LL(0x3ed181f0cece1fce), LL(0x8855229911114411), - LL(0x0c8903838f8f068f), LL(0x4a6b9c044e4e254e), LL(0xd1517366b7b7e6b7), LL(0x0b60cbe0ebeb8beb), - LL(0xfdcc78c13c3cf03c), LL(0x7cbf1ffd81813e81), LL(0xd4fe354094946a94), LL(0xeb0cf31cf7f7fbf7), - LL(0xa1676f18b9b9deb9), LL(0x985f268b13134c13), LL(0x7d9c58512c2cb02c), LL(0xd6b8bb05d3d36bd3), - LL(0x6b5cd38ce7e7bbe7), LL(0x57cbdc396e6ea56e), LL(0x6ef395aac4c437c4), LL(0x180f061b03030c03), - LL(0x8a13acdc56564556), LL(0x1a49885e44440d44), LL(0xdf9efea07f7fe17f), LL(0x21374f88a9a99ea9), - LL(0x4d8254672a2aa82a), LL(0xb16d6b0abbbbd6bb), LL(0x46e29f87c1c123c1), LL(0xa202a6f153535153), - LL(0xae8ba572dcdc57dc), LL(0x582716530b0b2c0b), LL(0x9cd327019d9d4e9d), LL(0x47c1d82b6c6cad6c), - LL(0x95f562a43131c431), LL(0x87b9e8f37474cd74), LL(0xe309f115f6f6fff6), LL(0x0a438c4c46460546), - LL(0x092645a5acac8aac), LL(0x3c970fb589891e89), LL(0xa04428b414145014), LL(0x5b42dfbae1e1a3e1), - LL(0xb04e2ca616165816), LL(0xcdd274f73a3ae83a), LL(0x6fd0d2066969b969), LL(0x482d124109092409), - LL(0xa7ade0d77070dd70), LL(0xd954716fb6b6e2b6), LL(0xceb7bd1ed0d067d0), LL(0x3b7ec7d6eded93ed), - LL(0x2edb85e2cccc17cc), LL(0x2a57846842421542), LL(0xb4c22d2c98985a98), LL(0x490e55eda4a4aaa4), - LL(0x5d8850752828a028), LL(0xda31b8865c5c6d5c), LL(0x933fed6bf8f8c7f8), LL(0x44a411c286862286), -}; - -static const u64 C5[256] = { - LL(0x18c07830d8181860), LL(0x2305af462623238c), LL(0xc67ef991b8c6c63f), LL(0xe8136fcdfbe8e887), - LL(0x874ca113cb878726), LL(0xb8a9626d11b8b8da), LL(0x0108050209010104), LL(0x4f426e9e0d4f4f21), - LL(0x36adee6c9b3636d8), LL(0xa6590451ffa6a6a2), LL(0xd2debdb90cd2d26f), LL(0xf5fb06f70ef5f5f3), - LL(0x79ef80f2967979f9), LL(0x6f5fcede306f6fa1), LL(0x91fcef3f6d91917e), LL(0x52aa07a4f8525255), - LL(0x6027fdc04760609d), LL(0xbc89766535bcbcca), LL(0x9baccd2b379b9b56), LL(0x8e048c018a8e8e02), - LL(0xa371155bd2a3a3b6), LL(0x0c603c186c0c0c30), LL(0x7bff8af6847b7bf1), LL(0x35b5e16a803535d4), - LL(0x1de8693af51d1d74), LL(0xe05347ddb3e0e0a7), LL(0xd7f6acb321d7d77b), LL(0xc25eed999cc2c22f), - LL(0x2e6d965c432e2eb8), LL(0x4b627a96294b4b31), LL(0xfea321e15dfefedf), LL(0x578216aed5575741), - LL(0x15a8412abd151554), LL(0x779fb6eee87777c1), LL(0x37a5eb6e923737dc), LL(0xe57b56d79ee5e5b3), - LL(0x9f8cd923139f9f46), LL(0xf0d317fd23f0f0e7), LL(0x4a6a7f94204a4a35), LL(0xda9e95a944dada4f), - LL(0x58fa25b0a258587d), LL(0xc906ca8fcfc9c903), LL(0x29558d527c2929a4), LL(0x0a5022145a0a0a28), - LL(0xb1e14f7f50b1b1fe), LL(0xa0691a5dc9a0a0ba), LL(0x6b7fdad6146b6bb1), LL(0x855cab17d985852e), - LL(0xbd8173673cbdbdce), LL(0x5dd234ba8f5d5d69), LL(0x1080502090101040), LL(0xf4f303f507f4f4f7), - LL(0xcb16c08bddcbcb0b), LL(0x3eedc67cd33e3ef8), LL(0x0528110a2d050514), LL(0x671fe6ce78676781), - LL(0xe47353d597e4e4b7), LL(0x2725bb4e0227279c), LL(0x4132588273414119), LL(0x8b2c9d0ba78b8b16), - LL(0xa7510153f6a7a7a6), LL(0x7dcf94fab27d7de9), LL(0x95dcfb374995956e), LL(0xd88e9fad56d8d847), - LL(0xfb8b30eb70fbfbcb), LL(0xee2371c1cdeeee9f), LL(0x7cc791f8bb7c7ced), LL(0x6617e3cc71666685), - LL(0xdda68ea77bdddd53), LL(0x17b84b2eaf17175c), LL(0x4702468e45474701), LL(0x9e84dc211a9e9e42), - LL(0xca1ec589d4caca0f), LL(0x2d75995a582d2db4), LL(0xbf9179632ebfbfc6), LL(0x07381b0e3f07071c), - LL(0xad012347acadad8e), LL(0x5aea2fb4b05a5a75), LL(0x836cb51bef838336), LL(0x3385ff66b63333cc), - LL(0x633ff2c65c636391), LL(0x02100a0412020208), LL(0xaa39384993aaaa92), LL(0x71afa8e2de7171d9), - LL(0xc80ecf8dc6c8c807), LL(0x19c87d32d1191964), LL(0x497270923b494939), LL(0xd9869aaf5fd9d943), - LL(0xf2c31df931f2f2ef), LL(0xe34b48dba8e3e3ab), LL(0x5be22ab6b95b5b71), LL(0x8834920dbc88881a), - LL(0x9aa4c8293e9a9a52), LL(0x262dbe4c0b262698), LL(0x328dfa64bf3232c8), LL(0xb0e94a7d59b0b0fa), - LL(0xe91b6acff2e9e983), LL(0x0f78331e770f0f3c), LL(0xd5e6a6b733d5d573), LL(0x8074ba1df480803a), - LL(0xbe997c6127bebec2), LL(0xcd26de87ebcdcd13), LL(0x34bde468893434d0), LL(0x487a75903248483d), - LL(0xffab24e354ffffdb), LL(0x7af78ff48d7a7af5), LL(0x90f4ea3d6490907a), LL(0x5fc23ebe9d5f5f61), - LL(0x201da0403d202080), LL(0x6867d5d00f6868bd), LL(0x1ad07234ca1a1a68), LL(0xae192c41b7aeae82), - LL(0xb4c95e757db4b4ea), LL(0x549a19a8ce54544d), LL(0x93ece53b7f939376), LL(0x220daa442f222288), - LL(0x6407e9c86364648d), LL(0xf1db12ff2af1f1e3), LL(0x73bfa2e6cc7373d1), LL(0x12905a2482121248), - LL(0x403a5d807a40401d), LL(0x0840281048080820), LL(0xc356e89b95c3c32b), LL(0xec337bc5dfecec97), - LL(0xdb9690ab4ddbdb4b), LL(0xa1611f5fc0a1a1be), LL(0x8d1c8307918d8d0e), LL(0x3df5c97ac83d3df4), - LL(0x97ccf1335b979766), LL(0x0000000000000000), LL(0xcf36d483f9cfcf1b), LL(0x2b4587566e2b2bac), - LL(0x7697b3ece17676c5), LL(0x8264b019e6828232), LL(0xd6fea9b128d6d67f), LL(0x1bd87736c31b1b6c), - LL(0xb5c15b7774b5b5ee), LL(0xaf112943beafaf86), LL(0x6a77dfd41d6a6ab5), LL(0x50ba0da0ea50505d), - LL(0x45124c8a57454509), LL(0xf3cb18fb38f3f3eb), LL(0x309df060ad3030c0), LL(0xef2b74c3c4efef9b), - LL(0x3fe5c37eda3f3ffc), LL(0x55921caac7555549), LL(0xa2791059dba2a2b2), LL(0xea0365c9e9eaea8f), - LL(0x650fecca6a656589), LL(0xbab9686903babad2), LL(0x2f65935e4a2f2fbc), LL(0xc04ee79d8ec0c027), - LL(0xdebe81a160dede5f), LL(0x1ce06c38fc1c1c70), LL(0xfdbb2ee746fdfdd3), LL(0x4d52649a1f4d4d29), - LL(0x92e4e03976929272), LL(0x758fbceafa7575c9), LL(0x06301e0c36060618), LL(0x8a249809ae8a8a12), - LL(0xb2f940794bb2b2f2), LL(0xe66359d185e6e6bf), LL(0x0e70361c7e0e0e38), LL(0x1ff8633ee71f1f7c), - LL(0x6237f7c455626295), LL(0xd4eea3b53ad4d477), LL(0xa829324d81a8a89a), LL(0x96c4f43152969662), - LL(0xf99b3aef62f9f9c3), LL(0xc566f697a3c5c533), LL(0x2535b14a10252594), LL(0x59f220b2ab595979), - LL(0x8454ae15d084842a), LL(0x72b7a7e4c57272d5), LL(0x39d5dd72ec3939e4), LL(0x4c5a6198164c4c2d), - LL(0x5eca3bbc945e5e65), LL(0x78e785f09f7878fd), LL(0x38ddd870e53838e0), LL(0x8c148605988c8c0a), - LL(0xd1c6b2bf17d1d163), LL(0xa5410b57e4a5a5ae), LL(0xe2434dd9a1e2e2af), LL(0x612ff8c24e616199), - LL(0xb3f1457b42b3b3f6), LL(0x2115a54234212184), LL(0x9c94d625089c9c4a), LL(0x1ef0663cee1e1e78), - LL(0x4322528661434311), LL(0xc776fc93b1c7c73b), LL(0xfcb32be54ffcfcd7), LL(0x0420140824040410), - LL(0x51b208a2e3515159), LL(0x99bcc72f2599995e), LL(0x6d4fc4da226d6da9), LL(0x0d68391a650d0d34), - LL(0xfa8335e979fafacf), LL(0xdfb684a369dfdf5b), LL(0x7ed79bfca97e7ee5), LL(0x243db44819242490), - LL(0x3bc5d776fe3b3bec), LL(0xab313d4b9aabab96), LL(0xce3ed181f0cece1f), LL(0x1188552299111144), - LL(0x8f0c8903838f8f06), LL(0x4e4a6b9c044e4e25), LL(0xb7d1517366b7b7e6), LL(0xeb0b60cbe0ebeb8b), - LL(0x3cfdcc78c13c3cf0), LL(0x817cbf1ffd81813e), LL(0x94d4fe354094946a), LL(0xf7eb0cf31cf7f7fb), - LL(0xb9a1676f18b9b9de), LL(0x13985f268b13134c), LL(0x2c7d9c58512c2cb0), LL(0xd3d6b8bb05d3d36b), - LL(0xe76b5cd38ce7e7bb), LL(0x6e57cbdc396e6ea5), LL(0xc46ef395aac4c437), LL(0x03180f061b03030c), - LL(0x568a13acdc565645), LL(0x441a49885e44440d), LL(0x7fdf9efea07f7fe1), LL(0xa921374f88a9a99e), - LL(0x2a4d8254672a2aa8), LL(0xbbb16d6b0abbbbd6), LL(0xc146e29f87c1c123), LL(0x53a202a6f1535351), - LL(0xdcae8ba572dcdc57), LL(0x0b582716530b0b2c), LL(0x9d9cd327019d9d4e), LL(0x6c47c1d82b6c6cad), - LL(0x3195f562a43131c4), LL(0x7487b9e8f37474cd), LL(0xf6e309f115f6f6ff), LL(0x460a438c4c464605), - LL(0xac092645a5acac8a), LL(0x893c970fb589891e), LL(0x14a04428b4141450), LL(0xe15b42dfbae1e1a3), - LL(0x16b04e2ca6161658), LL(0x3acdd274f73a3ae8), LL(0x696fd0d2066969b9), LL(0x09482d1241090924), - LL(0x70a7ade0d77070dd), LL(0xb6d954716fb6b6e2), LL(0xd0ceb7bd1ed0d067), LL(0xed3b7ec7d6eded93), - LL(0xcc2edb85e2cccc17), LL(0x422a578468424215), LL(0x98b4c22d2c98985a), LL(0xa4490e55eda4a4aa), - LL(0x285d8850752828a0), LL(0x5cda31b8865c5c6d), LL(0xf8933fed6bf8f8c7), LL(0x8644a411c2868622), -}; - -static const u64 C6[256] = { - LL(0x6018c07830d81818), LL(0x8c2305af46262323), LL(0x3fc67ef991b8c6c6), LL(0x87e8136fcdfbe8e8), - LL(0x26874ca113cb8787), LL(0xdab8a9626d11b8b8), LL(0x0401080502090101), LL(0x214f426e9e0d4f4f), - LL(0xd836adee6c9b3636), LL(0xa2a6590451ffa6a6), LL(0x6fd2debdb90cd2d2), LL(0xf3f5fb06f70ef5f5), - LL(0xf979ef80f2967979), LL(0xa16f5fcede306f6f), LL(0x7e91fcef3f6d9191), LL(0x5552aa07a4f85252), - LL(0x9d6027fdc0476060), LL(0xcabc89766535bcbc), LL(0x569baccd2b379b9b), LL(0x028e048c018a8e8e), - LL(0xb6a371155bd2a3a3), LL(0x300c603c186c0c0c), LL(0xf17bff8af6847b7b), LL(0xd435b5e16a803535), - LL(0x741de8693af51d1d), LL(0xa7e05347ddb3e0e0), LL(0x7bd7f6acb321d7d7), LL(0x2fc25eed999cc2c2), - LL(0xb82e6d965c432e2e), LL(0x314b627a96294b4b), LL(0xdffea321e15dfefe), LL(0x41578216aed55757), - LL(0x5415a8412abd1515), LL(0xc1779fb6eee87777), LL(0xdc37a5eb6e923737), LL(0xb3e57b56d79ee5e5), - LL(0x469f8cd923139f9f), LL(0xe7f0d317fd23f0f0), LL(0x354a6a7f94204a4a), LL(0x4fda9e95a944dada), - LL(0x7d58fa25b0a25858), LL(0x03c906ca8fcfc9c9), LL(0xa429558d527c2929), LL(0x280a5022145a0a0a), - LL(0xfeb1e14f7f50b1b1), LL(0xbaa0691a5dc9a0a0), LL(0xb16b7fdad6146b6b), LL(0x2e855cab17d98585), - LL(0xcebd8173673cbdbd), LL(0x695dd234ba8f5d5d), LL(0x4010805020901010), LL(0xf7f4f303f507f4f4), - LL(0x0bcb16c08bddcbcb), LL(0xf83eedc67cd33e3e), LL(0x140528110a2d0505), LL(0x81671fe6ce786767), - LL(0xb7e47353d597e4e4), LL(0x9c2725bb4e022727), LL(0x1941325882734141), LL(0x168b2c9d0ba78b8b), - LL(0xa6a7510153f6a7a7), LL(0xe97dcf94fab27d7d), LL(0x6e95dcfb37499595), LL(0x47d88e9fad56d8d8), - LL(0xcbfb8b30eb70fbfb), LL(0x9fee2371c1cdeeee), LL(0xed7cc791f8bb7c7c), LL(0x856617e3cc716666), - LL(0x53dda68ea77bdddd), LL(0x5c17b84b2eaf1717), LL(0x014702468e454747), LL(0x429e84dc211a9e9e), - LL(0x0fca1ec589d4caca), LL(0xb42d75995a582d2d), LL(0xc6bf9179632ebfbf), LL(0x1c07381b0e3f0707), - LL(0x8ead012347acadad), LL(0x755aea2fb4b05a5a), LL(0x36836cb51bef8383), LL(0xcc3385ff66b63333), - LL(0x91633ff2c65c6363), LL(0x0802100a04120202), LL(0x92aa39384993aaaa), LL(0xd971afa8e2de7171), - LL(0x07c80ecf8dc6c8c8), LL(0x6419c87d32d11919), LL(0x39497270923b4949), LL(0x43d9869aaf5fd9d9), - LL(0xeff2c31df931f2f2), LL(0xabe34b48dba8e3e3), LL(0x715be22ab6b95b5b), LL(0x1a8834920dbc8888), - LL(0x529aa4c8293e9a9a), LL(0x98262dbe4c0b2626), LL(0xc8328dfa64bf3232), LL(0xfab0e94a7d59b0b0), - LL(0x83e91b6acff2e9e9), LL(0x3c0f78331e770f0f), LL(0x73d5e6a6b733d5d5), LL(0x3a8074ba1df48080), - LL(0xc2be997c6127bebe), LL(0x13cd26de87ebcdcd), LL(0xd034bde468893434), LL(0x3d487a7590324848), - LL(0xdbffab24e354ffff), LL(0xf57af78ff48d7a7a), LL(0x7a90f4ea3d649090), LL(0x615fc23ebe9d5f5f), - LL(0x80201da0403d2020), LL(0xbd6867d5d00f6868), LL(0x681ad07234ca1a1a), LL(0x82ae192c41b7aeae), - LL(0xeab4c95e757db4b4), LL(0x4d549a19a8ce5454), LL(0x7693ece53b7f9393), LL(0x88220daa442f2222), - LL(0x8d6407e9c8636464), LL(0xe3f1db12ff2af1f1), LL(0xd173bfa2e6cc7373), LL(0x4812905a24821212), - LL(0x1d403a5d807a4040), LL(0x2008402810480808), LL(0x2bc356e89b95c3c3), LL(0x97ec337bc5dfecec), - LL(0x4bdb9690ab4ddbdb), LL(0xbea1611f5fc0a1a1), LL(0x0e8d1c8307918d8d), LL(0xf43df5c97ac83d3d), - LL(0x6697ccf1335b9797), LL(0x0000000000000000), LL(0x1bcf36d483f9cfcf), LL(0xac2b4587566e2b2b), - LL(0xc57697b3ece17676), LL(0x328264b019e68282), LL(0x7fd6fea9b128d6d6), LL(0x6c1bd87736c31b1b), - LL(0xeeb5c15b7774b5b5), LL(0x86af112943beafaf), LL(0xb56a77dfd41d6a6a), LL(0x5d50ba0da0ea5050), - LL(0x0945124c8a574545), LL(0xebf3cb18fb38f3f3), LL(0xc0309df060ad3030), LL(0x9bef2b74c3c4efef), - LL(0xfc3fe5c37eda3f3f), LL(0x4955921caac75555), LL(0xb2a2791059dba2a2), LL(0x8fea0365c9e9eaea), - LL(0x89650fecca6a6565), LL(0xd2bab9686903baba), LL(0xbc2f65935e4a2f2f), LL(0x27c04ee79d8ec0c0), - LL(0x5fdebe81a160dede), LL(0x701ce06c38fc1c1c), LL(0xd3fdbb2ee746fdfd), LL(0x294d52649a1f4d4d), - LL(0x7292e4e039769292), LL(0xc9758fbceafa7575), LL(0x1806301e0c360606), LL(0x128a249809ae8a8a), - LL(0xf2b2f940794bb2b2), LL(0xbfe66359d185e6e6), LL(0x380e70361c7e0e0e), LL(0x7c1ff8633ee71f1f), - LL(0x956237f7c4556262), LL(0x77d4eea3b53ad4d4), LL(0x9aa829324d81a8a8), LL(0x6296c4f431529696), - LL(0xc3f99b3aef62f9f9), LL(0x33c566f697a3c5c5), LL(0x942535b14a102525), LL(0x7959f220b2ab5959), - LL(0x2a8454ae15d08484), LL(0xd572b7a7e4c57272), LL(0xe439d5dd72ec3939), LL(0x2d4c5a6198164c4c), - LL(0x655eca3bbc945e5e), LL(0xfd78e785f09f7878), LL(0xe038ddd870e53838), LL(0x0a8c148605988c8c), - LL(0x63d1c6b2bf17d1d1), LL(0xaea5410b57e4a5a5), LL(0xafe2434dd9a1e2e2), LL(0x99612ff8c24e6161), - LL(0xf6b3f1457b42b3b3), LL(0x842115a542342121), LL(0x4a9c94d625089c9c), LL(0x781ef0663cee1e1e), - LL(0x1143225286614343), LL(0x3bc776fc93b1c7c7), LL(0xd7fcb32be54ffcfc), LL(0x1004201408240404), - LL(0x5951b208a2e35151), LL(0x5e99bcc72f259999), LL(0xa96d4fc4da226d6d), LL(0x340d68391a650d0d), - LL(0xcffa8335e979fafa), LL(0x5bdfb684a369dfdf), LL(0xe57ed79bfca97e7e), LL(0x90243db448192424), - LL(0xec3bc5d776fe3b3b), LL(0x96ab313d4b9aabab), LL(0x1fce3ed181f0cece), LL(0x4411885522991111), - LL(0x068f0c8903838f8f), LL(0x254e4a6b9c044e4e), LL(0xe6b7d1517366b7b7), LL(0x8beb0b60cbe0ebeb), - LL(0xf03cfdcc78c13c3c), LL(0x3e817cbf1ffd8181), LL(0x6a94d4fe35409494), LL(0xfbf7eb0cf31cf7f7), - LL(0xdeb9a1676f18b9b9), LL(0x4c13985f268b1313), LL(0xb02c7d9c58512c2c), LL(0x6bd3d6b8bb05d3d3), - LL(0xbbe76b5cd38ce7e7), LL(0xa56e57cbdc396e6e), LL(0x37c46ef395aac4c4), LL(0x0c03180f061b0303), - LL(0x45568a13acdc5656), LL(0x0d441a49885e4444), LL(0xe17fdf9efea07f7f), LL(0x9ea921374f88a9a9), - LL(0xa82a4d8254672a2a), LL(0xd6bbb16d6b0abbbb), LL(0x23c146e29f87c1c1), LL(0x5153a202a6f15353), - LL(0x57dcae8ba572dcdc), LL(0x2c0b582716530b0b), LL(0x4e9d9cd327019d9d), LL(0xad6c47c1d82b6c6c), - LL(0xc43195f562a43131), LL(0xcd7487b9e8f37474), LL(0xfff6e309f115f6f6), LL(0x05460a438c4c4646), - LL(0x8aac092645a5acac), LL(0x1e893c970fb58989), LL(0x5014a04428b41414), LL(0xa3e15b42dfbae1e1), - LL(0x5816b04e2ca61616), LL(0xe83acdd274f73a3a), LL(0xb9696fd0d2066969), LL(0x2409482d12410909), - LL(0xdd70a7ade0d77070), LL(0xe2b6d954716fb6b6), LL(0x67d0ceb7bd1ed0d0), LL(0x93ed3b7ec7d6eded), - LL(0x17cc2edb85e2cccc), LL(0x15422a5784684242), LL(0x5a98b4c22d2c9898), LL(0xaaa4490e55eda4a4), - LL(0xa0285d8850752828), LL(0x6d5cda31b8865c5c), LL(0xc7f8933fed6bf8f8), LL(0x228644a411c28686), -}; - -static const u64 C7[256] = { - LL(0x186018c07830d818), LL(0x238c2305af462623), LL(0xc63fc67ef991b8c6), LL(0xe887e8136fcdfbe8), - LL(0x8726874ca113cb87), LL(0xb8dab8a9626d11b8), LL(0x0104010805020901), LL(0x4f214f426e9e0d4f), - LL(0x36d836adee6c9b36), LL(0xa6a2a6590451ffa6), LL(0xd26fd2debdb90cd2), LL(0xf5f3f5fb06f70ef5), - LL(0x79f979ef80f29679), LL(0x6fa16f5fcede306f), LL(0x917e91fcef3f6d91), LL(0x525552aa07a4f852), - LL(0x609d6027fdc04760), LL(0xbccabc89766535bc), LL(0x9b569baccd2b379b), LL(0x8e028e048c018a8e), - LL(0xa3b6a371155bd2a3), LL(0x0c300c603c186c0c), LL(0x7bf17bff8af6847b), LL(0x35d435b5e16a8035), - LL(0x1d741de8693af51d), LL(0xe0a7e05347ddb3e0), LL(0xd77bd7f6acb321d7), LL(0xc22fc25eed999cc2), - LL(0x2eb82e6d965c432e), LL(0x4b314b627a96294b), LL(0xfedffea321e15dfe), LL(0x5741578216aed557), - LL(0x155415a8412abd15), LL(0x77c1779fb6eee877), LL(0x37dc37a5eb6e9237), LL(0xe5b3e57b56d79ee5), - LL(0x9f469f8cd923139f), LL(0xf0e7f0d317fd23f0), LL(0x4a354a6a7f94204a), LL(0xda4fda9e95a944da), - LL(0x587d58fa25b0a258), LL(0xc903c906ca8fcfc9), LL(0x29a429558d527c29), LL(0x0a280a5022145a0a), - LL(0xb1feb1e14f7f50b1), LL(0xa0baa0691a5dc9a0), LL(0x6bb16b7fdad6146b), LL(0x852e855cab17d985), - LL(0xbdcebd8173673cbd), LL(0x5d695dd234ba8f5d), LL(0x1040108050209010), LL(0xf4f7f4f303f507f4), - LL(0xcb0bcb16c08bddcb), LL(0x3ef83eedc67cd33e), LL(0x05140528110a2d05), LL(0x6781671fe6ce7867), - LL(0xe4b7e47353d597e4), LL(0x279c2725bb4e0227), LL(0x4119413258827341), LL(0x8b168b2c9d0ba78b), - LL(0xa7a6a7510153f6a7), LL(0x7de97dcf94fab27d), LL(0x956e95dcfb374995), LL(0xd847d88e9fad56d8), - LL(0xfbcbfb8b30eb70fb), LL(0xee9fee2371c1cdee), LL(0x7ced7cc791f8bb7c), LL(0x66856617e3cc7166), - LL(0xdd53dda68ea77bdd), LL(0x175c17b84b2eaf17), LL(0x47014702468e4547), LL(0x9e429e84dc211a9e), - LL(0xca0fca1ec589d4ca), LL(0x2db42d75995a582d), LL(0xbfc6bf9179632ebf), LL(0x071c07381b0e3f07), - LL(0xad8ead012347acad), LL(0x5a755aea2fb4b05a), LL(0x8336836cb51bef83), LL(0x33cc3385ff66b633), - LL(0x6391633ff2c65c63), LL(0x020802100a041202), LL(0xaa92aa39384993aa), LL(0x71d971afa8e2de71), - LL(0xc807c80ecf8dc6c8), LL(0x196419c87d32d119), LL(0x4939497270923b49), LL(0xd943d9869aaf5fd9), - LL(0xf2eff2c31df931f2), LL(0xe3abe34b48dba8e3), LL(0x5b715be22ab6b95b), LL(0x881a8834920dbc88), - LL(0x9a529aa4c8293e9a), LL(0x2698262dbe4c0b26), LL(0x32c8328dfa64bf32), LL(0xb0fab0e94a7d59b0), - LL(0xe983e91b6acff2e9), LL(0x0f3c0f78331e770f), LL(0xd573d5e6a6b733d5), LL(0x803a8074ba1df480), - LL(0xbec2be997c6127be), LL(0xcd13cd26de87ebcd), LL(0x34d034bde4688934), LL(0x483d487a75903248), - LL(0xffdbffab24e354ff), LL(0x7af57af78ff48d7a), LL(0x907a90f4ea3d6490), LL(0x5f615fc23ebe9d5f), - LL(0x2080201da0403d20), LL(0x68bd6867d5d00f68), LL(0x1a681ad07234ca1a), LL(0xae82ae192c41b7ae), - LL(0xb4eab4c95e757db4), LL(0x544d549a19a8ce54), LL(0x937693ece53b7f93), LL(0x2288220daa442f22), - LL(0x648d6407e9c86364), LL(0xf1e3f1db12ff2af1), LL(0x73d173bfa2e6cc73), LL(0x124812905a248212), - LL(0x401d403a5d807a40), LL(0x0820084028104808), LL(0xc32bc356e89b95c3), LL(0xec97ec337bc5dfec), - LL(0xdb4bdb9690ab4ddb), LL(0xa1bea1611f5fc0a1), LL(0x8d0e8d1c8307918d), LL(0x3df43df5c97ac83d), - LL(0x976697ccf1335b97), LL(0x0000000000000000), LL(0xcf1bcf36d483f9cf), LL(0x2bac2b4587566e2b), - LL(0x76c57697b3ece176), LL(0x82328264b019e682), LL(0xd67fd6fea9b128d6), LL(0x1b6c1bd87736c31b), - LL(0xb5eeb5c15b7774b5), LL(0xaf86af112943beaf), LL(0x6ab56a77dfd41d6a), LL(0x505d50ba0da0ea50), - LL(0x450945124c8a5745), LL(0xf3ebf3cb18fb38f3), LL(0x30c0309df060ad30), LL(0xef9bef2b74c3c4ef), - LL(0x3ffc3fe5c37eda3f), LL(0x554955921caac755), LL(0xa2b2a2791059dba2), LL(0xea8fea0365c9e9ea), - LL(0x6589650fecca6a65), LL(0xbad2bab9686903ba), LL(0x2fbc2f65935e4a2f), LL(0xc027c04ee79d8ec0), - LL(0xde5fdebe81a160de), LL(0x1c701ce06c38fc1c), LL(0xfdd3fdbb2ee746fd), LL(0x4d294d52649a1f4d), - LL(0x927292e4e0397692), LL(0x75c9758fbceafa75), LL(0x061806301e0c3606), LL(0x8a128a249809ae8a), - LL(0xb2f2b2f940794bb2), LL(0xe6bfe66359d185e6), LL(0x0e380e70361c7e0e), LL(0x1f7c1ff8633ee71f), - LL(0x62956237f7c45562), LL(0xd477d4eea3b53ad4), LL(0xa89aa829324d81a8), LL(0x966296c4f4315296), - LL(0xf9c3f99b3aef62f9), LL(0xc533c566f697a3c5), LL(0x25942535b14a1025), LL(0x597959f220b2ab59), - LL(0x842a8454ae15d084), LL(0x72d572b7a7e4c572), LL(0x39e439d5dd72ec39), LL(0x4c2d4c5a6198164c), - LL(0x5e655eca3bbc945e), LL(0x78fd78e785f09f78), LL(0x38e038ddd870e538), LL(0x8c0a8c148605988c), - LL(0xd163d1c6b2bf17d1), LL(0xa5aea5410b57e4a5), LL(0xe2afe2434dd9a1e2), LL(0x6199612ff8c24e61), - LL(0xb3f6b3f1457b42b3), LL(0x21842115a5423421), LL(0x9c4a9c94d625089c), LL(0x1e781ef0663cee1e), - LL(0x4311432252866143), LL(0xc73bc776fc93b1c7), LL(0xfcd7fcb32be54ffc), LL(0x0410042014082404), - LL(0x515951b208a2e351), LL(0x995e99bcc72f2599), LL(0x6da96d4fc4da226d), LL(0x0d340d68391a650d), - LL(0xfacffa8335e979fa), LL(0xdf5bdfb684a369df), LL(0x7ee57ed79bfca97e), LL(0x2490243db4481924), - LL(0x3bec3bc5d776fe3b), LL(0xab96ab313d4b9aab), LL(0xce1fce3ed181f0ce), LL(0x1144118855229911), - LL(0x8f068f0c8903838f), LL(0x4e254e4a6b9c044e), LL(0xb7e6b7d1517366b7), LL(0xeb8beb0b60cbe0eb), - LL(0x3cf03cfdcc78c13c), LL(0x813e817cbf1ffd81), LL(0x946a94d4fe354094), LL(0xf7fbf7eb0cf31cf7), - LL(0xb9deb9a1676f18b9), LL(0x134c13985f268b13), LL(0x2cb02c7d9c58512c), LL(0xd36bd3d6b8bb05d3), - LL(0xe7bbe76b5cd38ce7), LL(0x6ea56e57cbdc396e), LL(0xc437c46ef395aac4), LL(0x030c03180f061b03), - LL(0x5645568a13acdc56), LL(0x440d441a49885e44), LL(0x7fe17fdf9efea07f), LL(0xa99ea921374f88a9), - LL(0x2aa82a4d8254672a), LL(0xbbd6bbb16d6b0abb), LL(0xc123c146e29f87c1), LL(0x535153a202a6f153), - LL(0xdc57dcae8ba572dc), LL(0x0b2c0b582716530b), LL(0x9d4e9d9cd327019d), LL(0x6cad6c47c1d82b6c), - LL(0x31c43195f562a431), LL(0x74cd7487b9e8f374), LL(0xf6fff6e309f115f6), LL(0x4605460a438c4c46), - LL(0xac8aac092645a5ac), LL(0x891e893c970fb589), LL(0x145014a04428b414), LL(0xe1a3e15b42dfbae1), - LL(0x165816b04e2ca616), LL(0x3ae83acdd274f73a), LL(0x69b9696fd0d20669), LL(0x092409482d124109), - LL(0x70dd70a7ade0d770), LL(0xb6e2b6d954716fb6), LL(0xd067d0ceb7bd1ed0), LL(0xed93ed3b7ec7d6ed), - LL(0xcc17cc2edb85e2cc), LL(0x4215422a57846842), LL(0x985a98b4c22d2c98), LL(0xa4aaa4490e55eda4), - LL(0x28a0285d88507528), LL(0x5c6d5cda31b8865c), LL(0xf8c7f8933fed6bf8), LL(0x86228644a411c286), -}; - -static const u64 rc[R + 1] = { - LL(0x0000000000000000), - LL(0x1823c6e887b8014f), - LL(0x36a6d2f5796f9152), - LL(0x60bc9b8ea30c7b35), - LL(0x1de0d7c22e4bfe57), - LL(0x157737e59ff04ada), - LL(0x58c9290ab1a06b85), - LL(0xbd5d10f4cb3e0567), - LL(0xe427418ba77d95d8), - LL(0xfbee7c66dd17479e), - LL(0xca2dbf07ad5a8333), -}; - -/** - * The core Whirlpool transform. - */ -static void processBuffer(struct NESSIEstruct * const structpointer) { - int i, r; - u64 K[8]; /* the round key */ - u64 block[8]; /* mu(buffer) */ - u64 state[8]; /* the cipher state */ - u64 L[8]; - u8 *buffer = structpointer->buffer; - /* - * map the buffer to a block: - */ - for (i = 0; i < 8; i++, buffer += 8) { - block[i] = - (((u64)buffer[0] ) << 56) ^ - (((u64)buffer[1] & 0xffL) << 48) ^ - (((u64)buffer[2] & 0xffL) << 40) ^ - (((u64)buffer[3] & 0xffL) << 32) ^ - (((u64)buffer[4] & 0xffL) << 24) ^ - (((u64)buffer[5] & 0xffL) << 16) ^ - (((u64)buffer[6] & 0xffL) << 8) ^ - (((u64)buffer[7] & 0xffL) ); - } - /* - * compute and apply K^0 to the cipher state: - */ - state[0] = block[0] ^ (K[0] = structpointer->hash[0]); - state[1] = block[1] ^ (K[1] = structpointer->hash[1]); - state[2] = block[2] ^ (K[2] = structpointer->hash[2]); - state[3] = block[3] ^ (K[3] = structpointer->hash[3]); - state[4] = block[4] ^ (K[4] = structpointer->hash[4]); - state[5] = block[5] ^ (K[5] = structpointer->hash[5]); - state[6] = block[6] ^ (K[6] = structpointer->hash[6]); - state[7] = block[7] ^ (K[7] = structpointer->hash[7]); - /* - * iterate over all rounds: - */ - for (r = 1; r <= R; r++) { - /* - * compute K^r from K^{r-1}: - */ - L[0] = - C0[(int)(K[0] >> 56) ] ^ - C1[(int)(K[7] >> 48) & 0xff] ^ - C2[(int)(K[6] >> 40) & 0xff] ^ - C3[(int)(K[5] >> 32) & 0xff] ^ - C4[(int)(K[4] >> 24) & 0xff] ^ - C5[(int)(K[3] >> 16) & 0xff] ^ - C6[(int)(K[2] >> 8) & 0xff] ^ - C7[(int)(K[1] ) & 0xff] ^ - rc[r]; - L[1] = - C0[(int)(K[1] >> 56) ] ^ - C1[(int)(K[0] >> 48) & 0xff] ^ - C2[(int)(K[7] >> 40) & 0xff] ^ - C3[(int)(K[6] >> 32) & 0xff] ^ - C4[(int)(K[5] >> 24) & 0xff] ^ - C5[(int)(K[4] >> 16) & 0xff] ^ - C6[(int)(K[3] >> 8) & 0xff] ^ - C7[(int)(K[2] ) & 0xff]; - L[2] = - C0[(int)(K[2] >> 56) ] ^ - C1[(int)(K[1] >> 48) & 0xff] ^ - C2[(int)(K[0] >> 40) & 0xff] ^ - C3[(int)(K[7] >> 32) & 0xff] ^ - C4[(int)(K[6] >> 24) & 0xff] ^ - C5[(int)(K[5] >> 16) & 0xff] ^ - C6[(int)(K[4] >> 8) & 0xff] ^ - C7[(int)(K[3] ) & 0xff]; - L[3] = - C0[(int)(K[3] >> 56) ] ^ - C1[(int)(K[2] >> 48) & 0xff] ^ - C2[(int)(K[1] >> 40) & 0xff] ^ - C3[(int)(K[0] >> 32) & 0xff] ^ - C4[(int)(K[7] >> 24) & 0xff] ^ - C5[(int)(K[6] >> 16) & 0xff] ^ - C6[(int)(K[5] >> 8) & 0xff] ^ - C7[(int)(K[4] ) & 0xff]; - L[4] = - C0[(int)(K[4] >> 56) ] ^ - C1[(int)(K[3] >> 48) & 0xff] ^ - C2[(int)(K[2] >> 40) & 0xff] ^ - C3[(int)(K[1] >> 32) & 0xff] ^ - C4[(int)(K[0] >> 24) & 0xff] ^ - C5[(int)(K[7] >> 16) & 0xff] ^ - C6[(int)(K[6] >> 8) & 0xff] ^ - C7[(int)(K[5] ) & 0xff]; - L[5] = - C0[(int)(K[5] >> 56) ] ^ - C1[(int)(K[4] >> 48) & 0xff] ^ - C2[(int)(K[3] >> 40) & 0xff] ^ - C3[(int)(K[2] >> 32) & 0xff] ^ - C4[(int)(K[1] >> 24) & 0xff] ^ - C5[(int)(K[0] >> 16) & 0xff] ^ - C6[(int)(K[7] >> 8) & 0xff] ^ - C7[(int)(K[6] ) & 0xff]; - L[6] = - C0[(int)(K[6] >> 56) ] ^ - C1[(int)(K[5] >> 48) & 0xff] ^ - C2[(int)(K[4] >> 40) & 0xff] ^ - C3[(int)(K[3] >> 32) & 0xff] ^ - C4[(int)(K[2] >> 24) & 0xff] ^ - C5[(int)(K[1] >> 16) & 0xff] ^ - C6[(int)(K[0] >> 8) & 0xff] ^ - C7[(int)(K[7] ) & 0xff]; - L[7] = - C0[(int)(K[7] >> 56) ] ^ - C1[(int)(K[6] >> 48) & 0xff] ^ - C2[(int)(K[5] >> 40) & 0xff] ^ - C3[(int)(K[4] >> 32) & 0xff] ^ - C4[(int)(K[3] >> 24) & 0xff] ^ - C5[(int)(K[2] >> 16) & 0xff] ^ - C6[(int)(K[1] >> 8) & 0xff] ^ - C7[(int)(K[0] ) & 0xff]; - K[0] = L[0]; - K[1] = L[1]; - K[2] = L[2]; - K[3] = L[3]; - K[4] = L[4]; - K[5] = L[5]; - K[6] = L[6]; - K[7] = L[7]; - /* - * apply the r-th round transformation: - */ - L[0] = - C0[(int)(state[0] >> 56) ] ^ - C1[(int)(state[7] >> 48) & 0xff] ^ - C2[(int)(state[6] >> 40) & 0xff] ^ - C3[(int)(state[5] >> 32) & 0xff] ^ - C4[(int)(state[4] >> 24) & 0xff] ^ - C5[(int)(state[3] >> 16) & 0xff] ^ - C6[(int)(state[2] >> 8) & 0xff] ^ - C7[(int)(state[1] ) & 0xff] ^ - K[0]; - L[1] = - C0[(int)(state[1] >> 56) ] ^ - C1[(int)(state[0] >> 48) & 0xff] ^ - C2[(int)(state[7] >> 40) & 0xff] ^ - C3[(int)(state[6] >> 32) & 0xff] ^ - C4[(int)(state[5] >> 24) & 0xff] ^ - C5[(int)(state[4] >> 16) & 0xff] ^ - C6[(int)(state[3] >> 8) & 0xff] ^ - C7[(int)(state[2] ) & 0xff] ^ - K[1]; - L[2] = - C0[(int)(state[2] >> 56) ] ^ - C1[(int)(state[1] >> 48) & 0xff] ^ - C2[(int)(state[0] >> 40) & 0xff] ^ - C3[(int)(state[7] >> 32) & 0xff] ^ - C4[(int)(state[6] >> 24) & 0xff] ^ - C5[(int)(state[5] >> 16) & 0xff] ^ - C6[(int)(state[4] >> 8) & 0xff] ^ - C7[(int)(state[3] ) & 0xff] ^ - K[2]; - L[3] = - C0[(int)(state[3] >> 56) ] ^ - C1[(int)(state[2] >> 48) & 0xff] ^ - C2[(int)(state[1] >> 40) & 0xff] ^ - C3[(int)(state[0] >> 32) & 0xff] ^ - C4[(int)(state[7] >> 24) & 0xff] ^ - C5[(int)(state[6] >> 16) & 0xff] ^ - C6[(int)(state[5] >> 8) & 0xff] ^ - C7[(int)(state[4] ) & 0xff] ^ - K[3]; - L[4] = - C0[(int)(state[4] >> 56) ] ^ - C1[(int)(state[3] >> 48) & 0xff] ^ - C2[(int)(state[2] >> 40) & 0xff] ^ - C3[(int)(state[1] >> 32) & 0xff] ^ - C4[(int)(state[0] >> 24) & 0xff] ^ - C5[(int)(state[7] >> 16) & 0xff] ^ - C6[(int)(state[6] >> 8) & 0xff] ^ - C7[(int)(state[5] ) & 0xff] ^ - K[4]; - L[5] = - C0[(int)(state[5] >> 56) ] ^ - C1[(int)(state[4] >> 48) & 0xff] ^ - C2[(int)(state[3] >> 40) & 0xff] ^ - C3[(int)(state[2] >> 32) & 0xff] ^ - C4[(int)(state[1] >> 24) & 0xff] ^ - C5[(int)(state[0] >> 16) & 0xff] ^ - C6[(int)(state[7] >> 8) & 0xff] ^ - C7[(int)(state[6] ) & 0xff] ^ - K[5]; - L[6] = - C0[(int)(state[6] >> 56) ] ^ - C1[(int)(state[5] >> 48) & 0xff] ^ - C2[(int)(state[4] >> 40) & 0xff] ^ - C3[(int)(state[3] >> 32) & 0xff] ^ - C4[(int)(state[2] >> 24) & 0xff] ^ - C5[(int)(state[1] >> 16) & 0xff] ^ - C6[(int)(state[0] >> 8) & 0xff] ^ - C7[(int)(state[7] ) & 0xff] ^ - K[6]; - L[7] = - C0[(int)(state[7] >> 56) ] ^ - C1[(int)(state[6] >> 48) & 0xff] ^ - C2[(int)(state[5] >> 40) & 0xff] ^ - C3[(int)(state[4] >> 32) & 0xff] ^ - C4[(int)(state[3] >> 24) & 0xff] ^ - C5[(int)(state[2] >> 16) & 0xff] ^ - C6[(int)(state[1] >> 8) & 0xff] ^ - C7[(int)(state[0] ) & 0xff] ^ - K[7]; - state[0] = L[0]; - state[1] = L[1]; - state[2] = L[2]; - state[3] = L[3]; - state[4] = L[4]; - state[5] = L[5]; - state[6] = L[6]; - state[7] = L[7]; - } - /* - * apply the Miyaguchi-Preneel compression function: - */ - structpointer->hash[0] ^= state[0] ^ block[0]; - structpointer->hash[1] ^= state[1] ^ block[1]; - structpointer->hash[2] ^= state[2] ^ block[2]; - structpointer->hash[3] ^= state[3] ^ block[3]; - structpointer->hash[4] ^= state[4] ^ block[4]; - structpointer->hash[5] ^= state[5] ^ block[5]; - structpointer->hash[6] ^= state[6] ^ block[6]; - structpointer->hash[7] ^= state[7] ^ block[7]; -} - -/** - * Initialize the hashing state. - */ -void WHIRLPOOL_init(struct NESSIEstruct * const structpointer) { - int i; - - memset(structpointer->bitLength, 0, 32); - structpointer->bufferBits = structpointer->bufferPos = 0; - structpointer->buffer[0] = 0; /* it's only necessary to cleanup buffer[bufferPos] */ - for (i = 0; i < 8; i++) { - structpointer->hash[i] = 0L; /* initial value */ - } -} - -/** - * Delivers input data to the hashing algorithm. - * - * @param source plaintext data to hash. - * @param sourceBits how many bits of plaintext to process. - * - * This method maintains the invariant: bufferBits < DIGESTBITS - */ -void WHIRLPOOL_add(const unsigned char * const source, - unsigned __int32 sourceBits, - struct NESSIEstruct * const structpointer) { - /* - sourcePos - | - +-------+-------+------- - ||||||||||||||||||||| source - +-------+-------+------- - +-------+-------+-------+-------+-------+------- - |||||||||||||||||||||| buffer - +-------+-------+-------+-------+-------+------- - | - bufferPos - */ - int sourcePos = 0; /* index of leftmost source u8 containing data (1 to 8 bits). */ - int sourceGap = (8 - ((int)sourceBits & 7)) & 7; /* space on source[sourcePos]. */ - int bufferRem = structpointer->bufferBits & 7; /* occupied bits on buffer[bufferPos]. */ - int i; - u32 b, carry; - u8 *buffer = structpointer->buffer; - u8 *bitLength = structpointer->bitLength; - int bufferBits = structpointer->bufferBits; - int bufferPos = structpointer->bufferPos; - - /* - * tally the length of the added data: - */ - u64 value = sourceBits; - for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != LL(0)); i--) { - carry += bitLength[i] + ((u32)value & 0xff); - bitLength[i] = (u8)carry; - carry >>= 8; - value >>= 8; - } - /* - * process data in chunks of 8 bits (a more efficient approach would be to take whole-word chunks): - */ - while (sourceBits > 8) { - /* N.B. at least source[sourcePos] and source[sourcePos+1] contain data. */ - /* - * take a byte from the source: - */ - b = ((source[sourcePos] << sourceGap) & 0xff) | - ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); - /* - * process this byte: - */ - buffer[bufferPos++] |= (u8)(b >> bufferRem); - bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ - if (bufferBits == DIGESTBITS) { - /* - * process data block: - */ - processBuffer(structpointer); - /* - * reset buffer: - */ - bufferBits = bufferPos = 0; - } - buffer[bufferPos] = (u8) (b << (8 - bufferRem)); - bufferBits += bufferRem; - /* - * proceed to remaining data: - */ - sourceBits -= 8; - sourcePos++; - } - /* now 0 <= sourceBits <= 8; - * furthermore, all data (if any is left) is in source[sourcePos]. - */ - if (sourceBits > 0) { - b = (source[sourcePos] << sourceGap) & 0xff; /* bits are left-justified on b. */ - /* - * process the remaining bits: - */ - buffer[bufferPos] |= b >> bufferRem; - } else { - b = 0; - } - if (bufferRem + sourceBits < 8) { - /* - * all remaining data fits on buffer[bufferPos], - * and there still remains some space. - */ - bufferBits += sourceBits; - } else { - /* - * buffer[bufferPos] is full: - */ - bufferPos++; - bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ - sourceBits -= 8 - bufferRem; - /* now 0 <= sourceBits < 8; - * furthermore, all data (if any is left) is in source[sourcePos]. - */ - if (bufferBits == DIGESTBITS) { - /* - * process data block: - */ - processBuffer(structpointer); - /* - * reset buffer: - */ - bufferBits = bufferPos = 0; - } - buffer[bufferPos] = (u8) (b << (8 - bufferRem)); - bufferBits += (int)sourceBits; - } - structpointer->bufferBits = bufferBits; - structpointer->bufferPos = bufferPos; -} - -/** - * Get the hash value from the hashing state. - * - * This method uses the invariant: bufferBits < DIGESTBITS - */ -void WHIRLPOOL_finalize(struct NESSIEstruct * const structpointer, - unsigned char * const result) { - int i; - u8 *buffer = structpointer->buffer; - u8 *bitLength = structpointer->bitLength; - int bufferBits = structpointer->bufferBits; - int bufferPos = structpointer->bufferPos; - u8 *digest = result; - - /* - * append a '1'-bit: - */ - buffer[bufferPos] |= 0x80U >> (bufferBits & 7); - bufferPos++; /* all remaining bits on the current u8 are set to zero. */ - /* - * pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits: - */ - if (bufferPos > WBLOCKBYTES - LENGTHBYTES) { - if (bufferPos < WBLOCKBYTES) { - memset(&buffer[bufferPos], 0, WBLOCKBYTES - bufferPos); - } - /* - * process data block: - */ - processBuffer(structpointer); - /* - * reset buffer: - */ - bufferPos = 0; - } - if (bufferPos < WBLOCKBYTES - LENGTHBYTES) { - memset(&buffer[bufferPos], 0, (WBLOCKBYTES - LENGTHBYTES) - bufferPos); - } - bufferPos = WBLOCKBYTES - LENGTHBYTES; - /* - * append bit length of hashed data: - */ - memcpy(&buffer[WBLOCKBYTES - LENGTHBYTES], bitLength, LENGTHBYTES); - /* - * process data block: - */ - processBuffer(structpointer); - /* - * return the completed message digest: - */ - for (i = 0; i < DIGESTBYTES/8; i++) { - digest[0] = (u8)(structpointer->hash[i] >> 56); - digest[1] = (u8)(structpointer->hash[i] >> 48); - digest[2] = (u8)(structpointer->hash[i] >> 40); - digest[3] = (u8)(structpointer->hash[i] >> 32); - digest[4] = (u8)(structpointer->hash[i] >> 24); - digest[5] = (u8)(structpointer->hash[i] >> 16); - digest[6] = (u8)(structpointer->hash[i] >> 8); - digest[7] = (u8)(structpointer->hash[i] ); - digest += 8; - } - structpointer->bufferBits = bufferBits; - structpointer->bufferPos = bufferPos; -} +/** + * The Whirlpool hashing function. + * + *

+ * References + * + *

+ * The Whirlpool algorithm was developed by + * Paulo S. L. M. Barreto and + * Vincent Rijmen. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * @author Paulo S.L.M. Barreto + * @author Vincent Rijmen. + * Minor modifications by TrueCrypt Foundation. + * + * @version 3.0 (2003.03.12) + * + * ============================================================================= + * + * Differences from version 2.1: + * + * - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, 9). + * + * ============================================================================= + * + * Differences from version 2.0: + * + * - Generation of ISO/IEC 10118-3 test vectors. + * - Bug fix: nonzero carry was ignored when tallying the data length + * (this bug apparently only manifested itself when feeding data + * in pieces rather than in a single chunk at once). + * - Support for MS Visual C++ 64-bit integer arithmetic. + * + * Differences from version 1.0: + * + * - Original S-box replaced by the tweaked, hardware-efficient version. + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + /* The code contained in this file (Whirlpool.c) is in the public domain. */ + +#include +#include +#include +#include + +#include "Whirlpool.h" + +/* #define TRACE_INTERMEDIATE_VALUES */ + +/* + * The number of rounds of the internal dedicated block cipher. + */ +#define R 10 + +/* + * Though Whirlpool is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ + +static const u64 C0[256] = { + LL(0x18186018c07830d8), LL(0x23238c2305af4626), LL(0xc6c63fc67ef991b8), LL(0xe8e887e8136fcdfb), + LL(0x878726874ca113cb), LL(0xb8b8dab8a9626d11), LL(0x0101040108050209), LL(0x4f4f214f426e9e0d), + LL(0x3636d836adee6c9b), LL(0xa6a6a2a6590451ff), LL(0xd2d26fd2debdb90c), LL(0xf5f5f3f5fb06f70e), + LL(0x7979f979ef80f296), LL(0x6f6fa16f5fcede30), LL(0x91917e91fcef3f6d), LL(0x52525552aa07a4f8), + LL(0x60609d6027fdc047), LL(0xbcbccabc89766535), LL(0x9b9b569baccd2b37), LL(0x8e8e028e048c018a), + LL(0xa3a3b6a371155bd2), LL(0x0c0c300c603c186c), LL(0x7b7bf17bff8af684), LL(0x3535d435b5e16a80), + LL(0x1d1d741de8693af5), LL(0xe0e0a7e05347ddb3), LL(0xd7d77bd7f6acb321), LL(0xc2c22fc25eed999c), + LL(0x2e2eb82e6d965c43), LL(0x4b4b314b627a9629), LL(0xfefedffea321e15d), LL(0x575741578216aed5), + LL(0x15155415a8412abd), LL(0x7777c1779fb6eee8), LL(0x3737dc37a5eb6e92), LL(0xe5e5b3e57b56d79e), + LL(0x9f9f469f8cd92313), LL(0xf0f0e7f0d317fd23), LL(0x4a4a354a6a7f9420), LL(0xdada4fda9e95a944), + LL(0x58587d58fa25b0a2), LL(0xc9c903c906ca8fcf), LL(0x2929a429558d527c), LL(0x0a0a280a5022145a), + LL(0xb1b1feb1e14f7f50), LL(0xa0a0baa0691a5dc9), LL(0x6b6bb16b7fdad614), LL(0x85852e855cab17d9), + LL(0xbdbdcebd8173673c), LL(0x5d5d695dd234ba8f), LL(0x1010401080502090), LL(0xf4f4f7f4f303f507), + LL(0xcbcb0bcb16c08bdd), LL(0x3e3ef83eedc67cd3), LL(0x0505140528110a2d), LL(0x676781671fe6ce78), + LL(0xe4e4b7e47353d597), LL(0x27279c2725bb4e02), LL(0x4141194132588273), LL(0x8b8b168b2c9d0ba7), + LL(0xa7a7a6a7510153f6), LL(0x7d7de97dcf94fab2), LL(0x95956e95dcfb3749), LL(0xd8d847d88e9fad56), + LL(0xfbfbcbfb8b30eb70), LL(0xeeee9fee2371c1cd), LL(0x7c7ced7cc791f8bb), LL(0x6666856617e3cc71), + LL(0xdddd53dda68ea77b), LL(0x17175c17b84b2eaf), LL(0x4747014702468e45), LL(0x9e9e429e84dc211a), + LL(0xcaca0fca1ec589d4), LL(0x2d2db42d75995a58), LL(0xbfbfc6bf9179632e), LL(0x07071c07381b0e3f), + LL(0xadad8ead012347ac), LL(0x5a5a755aea2fb4b0), LL(0x838336836cb51bef), LL(0x3333cc3385ff66b6), + LL(0x636391633ff2c65c), LL(0x02020802100a0412), LL(0xaaaa92aa39384993), LL(0x7171d971afa8e2de), + LL(0xc8c807c80ecf8dc6), LL(0x19196419c87d32d1), LL(0x494939497270923b), LL(0xd9d943d9869aaf5f), + LL(0xf2f2eff2c31df931), LL(0xe3e3abe34b48dba8), LL(0x5b5b715be22ab6b9), LL(0x88881a8834920dbc), + LL(0x9a9a529aa4c8293e), LL(0x262698262dbe4c0b), LL(0x3232c8328dfa64bf), LL(0xb0b0fab0e94a7d59), + LL(0xe9e983e91b6acff2), LL(0x0f0f3c0f78331e77), LL(0xd5d573d5e6a6b733), LL(0x80803a8074ba1df4), + LL(0xbebec2be997c6127), LL(0xcdcd13cd26de87eb), LL(0x3434d034bde46889), LL(0x48483d487a759032), + LL(0xffffdbffab24e354), LL(0x7a7af57af78ff48d), LL(0x90907a90f4ea3d64), LL(0x5f5f615fc23ebe9d), + LL(0x202080201da0403d), LL(0x6868bd6867d5d00f), LL(0x1a1a681ad07234ca), LL(0xaeae82ae192c41b7), + LL(0xb4b4eab4c95e757d), LL(0x54544d549a19a8ce), LL(0x93937693ece53b7f), LL(0x222288220daa442f), + LL(0x64648d6407e9c863), LL(0xf1f1e3f1db12ff2a), LL(0x7373d173bfa2e6cc), LL(0x12124812905a2482), + LL(0x40401d403a5d807a), LL(0x0808200840281048), LL(0xc3c32bc356e89b95), LL(0xecec97ec337bc5df), + LL(0xdbdb4bdb9690ab4d), LL(0xa1a1bea1611f5fc0), LL(0x8d8d0e8d1c830791), LL(0x3d3df43df5c97ac8), + LL(0x97976697ccf1335b), LL(0x0000000000000000), LL(0xcfcf1bcf36d483f9), LL(0x2b2bac2b4587566e), + LL(0x7676c57697b3ece1), LL(0x8282328264b019e6), LL(0xd6d67fd6fea9b128), LL(0x1b1b6c1bd87736c3), + LL(0xb5b5eeb5c15b7774), LL(0xafaf86af112943be), LL(0x6a6ab56a77dfd41d), LL(0x50505d50ba0da0ea), + LL(0x45450945124c8a57), LL(0xf3f3ebf3cb18fb38), LL(0x3030c0309df060ad), LL(0xefef9bef2b74c3c4), + LL(0x3f3ffc3fe5c37eda), LL(0x55554955921caac7), LL(0xa2a2b2a2791059db), LL(0xeaea8fea0365c9e9), + LL(0x656589650fecca6a), LL(0xbabad2bab9686903), LL(0x2f2fbc2f65935e4a), LL(0xc0c027c04ee79d8e), + LL(0xdede5fdebe81a160), LL(0x1c1c701ce06c38fc), LL(0xfdfdd3fdbb2ee746), LL(0x4d4d294d52649a1f), + LL(0x92927292e4e03976), LL(0x7575c9758fbceafa), LL(0x06061806301e0c36), LL(0x8a8a128a249809ae), + LL(0xb2b2f2b2f940794b), LL(0xe6e6bfe66359d185), LL(0x0e0e380e70361c7e), LL(0x1f1f7c1ff8633ee7), + LL(0x6262956237f7c455), LL(0xd4d477d4eea3b53a), LL(0xa8a89aa829324d81), LL(0x96966296c4f43152), + LL(0xf9f9c3f99b3aef62), LL(0xc5c533c566f697a3), LL(0x2525942535b14a10), LL(0x59597959f220b2ab), + LL(0x84842a8454ae15d0), LL(0x7272d572b7a7e4c5), LL(0x3939e439d5dd72ec), LL(0x4c4c2d4c5a619816), + LL(0x5e5e655eca3bbc94), LL(0x7878fd78e785f09f), LL(0x3838e038ddd870e5), LL(0x8c8c0a8c14860598), + LL(0xd1d163d1c6b2bf17), LL(0xa5a5aea5410b57e4), LL(0xe2e2afe2434dd9a1), LL(0x616199612ff8c24e), + LL(0xb3b3f6b3f1457b42), LL(0x2121842115a54234), LL(0x9c9c4a9c94d62508), LL(0x1e1e781ef0663cee), + LL(0x4343114322528661), LL(0xc7c73bc776fc93b1), LL(0xfcfcd7fcb32be54f), LL(0x0404100420140824), + LL(0x51515951b208a2e3), LL(0x99995e99bcc72f25), LL(0x6d6da96d4fc4da22), LL(0x0d0d340d68391a65), + LL(0xfafacffa8335e979), LL(0xdfdf5bdfb684a369), LL(0x7e7ee57ed79bfca9), LL(0x242490243db44819), + LL(0x3b3bec3bc5d776fe), LL(0xabab96ab313d4b9a), LL(0xcece1fce3ed181f0), LL(0x1111441188552299), + LL(0x8f8f068f0c890383), LL(0x4e4e254e4a6b9c04), LL(0xb7b7e6b7d1517366), LL(0xebeb8beb0b60cbe0), + LL(0x3c3cf03cfdcc78c1), LL(0x81813e817cbf1ffd), LL(0x94946a94d4fe3540), LL(0xf7f7fbf7eb0cf31c), + LL(0xb9b9deb9a1676f18), LL(0x13134c13985f268b), LL(0x2c2cb02c7d9c5851), LL(0xd3d36bd3d6b8bb05), + LL(0xe7e7bbe76b5cd38c), LL(0x6e6ea56e57cbdc39), LL(0xc4c437c46ef395aa), LL(0x03030c03180f061b), + LL(0x565645568a13acdc), LL(0x44440d441a49885e), LL(0x7f7fe17fdf9efea0), LL(0xa9a99ea921374f88), + LL(0x2a2aa82a4d825467), LL(0xbbbbd6bbb16d6b0a), LL(0xc1c123c146e29f87), LL(0x53535153a202a6f1), + LL(0xdcdc57dcae8ba572), LL(0x0b0b2c0b58271653), LL(0x9d9d4e9d9cd32701), LL(0x6c6cad6c47c1d82b), + LL(0x3131c43195f562a4), LL(0x7474cd7487b9e8f3), LL(0xf6f6fff6e309f115), LL(0x464605460a438c4c), + LL(0xacac8aac092645a5), LL(0x89891e893c970fb5), LL(0x14145014a04428b4), LL(0xe1e1a3e15b42dfba), + LL(0x16165816b04e2ca6), LL(0x3a3ae83acdd274f7), LL(0x6969b9696fd0d206), LL(0x09092409482d1241), + LL(0x7070dd70a7ade0d7), LL(0xb6b6e2b6d954716f), LL(0xd0d067d0ceb7bd1e), LL(0xeded93ed3b7ec7d6), + LL(0xcccc17cc2edb85e2), LL(0x424215422a578468), LL(0x98985a98b4c22d2c), LL(0xa4a4aaa4490e55ed), + LL(0x2828a0285d885075), LL(0x5c5c6d5cda31b886), LL(0xf8f8c7f8933fed6b), LL(0x8686228644a411c2), +}; + +static const u64 C1[256] = { + LL(0xd818186018c07830), LL(0x2623238c2305af46), LL(0xb8c6c63fc67ef991), LL(0xfbe8e887e8136fcd), + LL(0xcb878726874ca113), LL(0x11b8b8dab8a9626d), LL(0x0901010401080502), LL(0x0d4f4f214f426e9e), + LL(0x9b3636d836adee6c), LL(0xffa6a6a2a6590451), LL(0x0cd2d26fd2debdb9), LL(0x0ef5f5f3f5fb06f7), + LL(0x967979f979ef80f2), LL(0x306f6fa16f5fcede), LL(0x6d91917e91fcef3f), LL(0xf852525552aa07a4), + LL(0x4760609d6027fdc0), LL(0x35bcbccabc897665), LL(0x379b9b569baccd2b), LL(0x8a8e8e028e048c01), + LL(0xd2a3a3b6a371155b), LL(0x6c0c0c300c603c18), LL(0x847b7bf17bff8af6), LL(0x803535d435b5e16a), + LL(0xf51d1d741de8693a), LL(0xb3e0e0a7e05347dd), LL(0x21d7d77bd7f6acb3), LL(0x9cc2c22fc25eed99), + LL(0x432e2eb82e6d965c), LL(0x294b4b314b627a96), LL(0x5dfefedffea321e1), LL(0xd5575741578216ae), + LL(0xbd15155415a8412a), LL(0xe87777c1779fb6ee), LL(0x923737dc37a5eb6e), LL(0x9ee5e5b3e57b56d7), + LL(0x139f9f469f8cd923), LL(0x23f0f0e7f0d317fd), LL(0x204a4a354a6a7f94), LL(0x44dada4fda9e95a9), + LL(0xa258587d58fa25b0), LL(0xcfc9c903c906ca8f), LL(0x7c2929a429558d52), LL(0x5a0a0a280a502214), + LL(0x50b1b1feb1e14f7f), LL(0xc9a0a0baa0691a5d), LL(0x146b6bb16b7fdad6), LL(0xd985852e855cab17), + LL(0x3cbdbdcebd817367), LL(0x8f5d5d695dd234ba), LL(0x9010104010805020), LL(0x07f4f4f7f4f303f5), + LL(0xddcbcb0bcb16c08b), LL(0xd33e3ef83eedc67c), LL(0x2d0505140528110a), LL(0x78676781671fe6ce), + LL(0x97e4e4b7e47353d5), LL(0x0227279c2725bb4e), LL(0x7341411941325882), LL(0xa78b8b168b2c9d0b), + LL(0xf6a7a7a6a7510153), LL(0xb27d7de97dcf94fa), LL(0x4995956e95dcfb37), LL(0x56d8d847d88e9fad), + LL(0x70fbfbcbfb8b30eb), LL(0xcdeeee9fee2371c1), LL(0xbb7c7ced7cc791f8), LL(0x716666856617e3cc), + LL(0x7bdddd53dda68ea7), LL(0xaf17175c17b84b2e), LL(0x454747014702468e), LL(0x1a9e9e429e84dc21), + LL(0xd4caca0fca1ec589), LL(0x582d2db42d75995a), LL(0x2ebfbfc6bf917963), LL(0x3f07071c07381b0e), + LL(0xacadad8ead012347), LL(0xb05a5a755aea2fb4), LL(0xef838336836cb51b), LL(0xb63333cc3385ff66), + LL(0x5c636391633ff2c6), LL(0x1202020802100a04), LL(0x93aaaa92aa393849), LL(0xde7171d971afa8e2), + LL(0xc6c8c807c80ecf8d), LL(0xd119196419c87d32), LL(0x3b49493949727092), LL(0x5fd9d943d9869aaf), + LL(0x31f2f2eff2c31df9), LL(0xa8e3e3abe34b48db), LL(0xb95b5b715be22ab6), LL(0xbc88881a8834920d), + LL(0x3e9a9a529aa4c829), LL(0x0b262698262dbe4c), LL(0xbf3232c8328dfa64), LL(0x59b0b0fab0e94a7d), + LL(0xf2e9e983e91b6acf), LL(0x770f0f3c0f78331e), LL(0x33d5d573d5e6a6b7), LL(0xf480803a8074ba1d), + LL(0x27bebec2be997c61), LL(0xebcdcd13cd26de87), LL(0x893434d034bde468), LL(0x3248483d487a7590), + LL(0x54ffffdbffab24e3), LL(0x8d7a7af57af78ff4), LL(0x6490907a90f4ea3d), LL(0x9d5f5f615fc23ebe), + LL(0x3d202080201da040), LL(0x0f6868bd6867d5d0), LL(0xca1a1a681ad07234), LL(0xb7aeae82ae192c41), + LL(0x7db4b4eab4c95e75), LL(0xce54544d549a19a8), LL(0x7f93937693ece53b), LL(0x2f222288220daa44), + LL(0x6364648d6407e9c8), LL(0x2af1f1e3f1db12ff), LL(0xcc7373d173bfa2e6), LL(0x8212124812905a24), + LL(0x7a40401d403a5d80), LL(0x4808082008402810), LL(0x95c3c32bc356e89b), LL(0xdfecec97ec337bc5), + LL(0x4ddbdb4bdb9690ab), LL(0xc0a1a1bea1611f5f), LL(0x918d8d0e8d1c8307), LL(0xc83d3df43df5c97a), + LL(0x5b97976697ccf133), LL(0x0000000000000000), LL(0xf9cfcf1bcf36d483), LL(0x6e2b2bac2b458756), + LL(0xe17676c57697b3ec), LL(0xe68282328264b019), LL(0x28d6d67fd6fea9b1), LL(0xc31b1b6c1bd87736), + LL(0x74b5b5eeb5c15b77), LL(0xbeafaf86af112943), LL(0x1d6a6ab56a77dfd4), LL(0xea50505d50ba0da0), + LL(0x5745450945124c8a), LL(0x38f3f3ebf3cb18fb), LL(0xad3030c0309df060), LL(0xc4efef9bef2b74c3), + LL(0xda3f3ffc3fe5c37e), LL(0xc755554955921caa), LL(0xdba2a2b2a2791059), LL(0xe9eaea8fea0365c9), + LL(0x6a656589650fecca), LL(0x03babad2bab96869), LL(0x4a2f2fbc2f65935e), LL(0x8ec0c027c04ee79d), + LL(0x60dede5fdebe81a1), LL(0xfc1c1c701ce06c38), LL(0x46fdfdd3fdbb2ee7), LL(0x1f4d4d294d52649a), + LL(0x7692927292e4e039), LL(0xfa7575c9758fbcea), LL(0x3606061806301e0c), LL(0xae8a8a128a249809), + LL(0x4bb2b2f2b2f94079), LL(0x85e6e6bfe66359d1), LL(0x7e0e0e380e70361c), LL(0xe71f1f7c1ff8633e), + LL(0x556262956237f7c4), LL(0x3ad4d477d4eea3b5), LL(0x81a8a89aa829324d), LL(0x5296966296c4f431), + LL(0x62f9f9c3f99b3aef), LL(0xa3c5c533c566f697), LL(0x102525942535b14a), LL(0xab59597959f220b2), + LL(0xd084842a8454ae15), LL(0xc57272d572b7a7e4), LL(0xec3939e439d5dd72), LL(0x164c4c2d4c5a6198), + LL(0x945e5e655eca3bbc), LL(0x9f7878fd78e785f0), LL(0xe53838e038ddd870), LL(0x988c8c0a8c148605), + LL(0x17d1d163d1c6b2bf), LL(0xe4a5a5aea5410b57), LL(0xa1e2e2afe2434dd9), LL(0x4e616199612ff8c2), + LL(0x42b3b3f6b3f1457b), LL(0x342121842115a542), LL(0x089c9c4a9c94d625), LL(0xee1e1e781ef0663c), + LL(0x6143431143225286), LL(0xb1c7c73bc776fc93), LL(0x4ffcfcd7fcb32be5), LL(0x2404041004201408), + LL(0xe351515951b208a2), LL(0x2599995e99bcc72f), LL(0x226d6da96d4fc4da), LL(0x650d0d340d68391a), + LL(0x79fafacffa8335e9), LL(0x69dfdf5bdfb684a3), LL(0xa97e7ee57ed79bfc), LL(0x19242490243db448), + LL(0xfe3b3bec3bc5d776), LL(0x9aabab96ab313d4b), LL(0xf0cece1fce3ed181), LL(0x9911114411885522), + LL(0x838f8f068f0c8903), LL(0x044e4e254e4a6b9c), LL(0x66b7b7e6b7d15173), LL(0xe0ebeb8beb0b60cb), + LL(0xc13c3cf03cfdcc78), LL(0xfd81813e817cbf1f), LL(0x4094946a94d4fe35), LL(0x1cf7f7fbf7eb0cf3), + LL(0x18b9b9deb9a1676f), LL(0x8b13134c13985f26), LL(0x512c2cb02c7d9c58), LL(0x05d3d36bd3d6b8bb), + LL(0x8ce7e7bbe76b5cd3), LL(0x396e6ea56e57cbdc), LL(0xaac4c437c46ef395), LL(0x1b03030c03180f06), + LL(0xdc565645568a13ac), LL(0x5e44440d441a4988), LL(0xa07f7fe17fdf9efe), LL(0x88a9a99ea921374f), + LL(0x672a2aa82a4d8254), LL(0x0abbbbd6bbb16d6b), LL(0x87c1c123c146e29f), LL(0xf153535153a202a6), + LL(0x72dcdc57dcae8ba5), LL(0x530b0b2c0b582716), LL(0x019d9d4e9d9cd327), LL(0x2b6c6cad6c47c1d8), + LL(0xa43131c43195f562), LL(0xf37474cd7487b9e8), LL(0x15f6f6fff6e309f1), LL(0x4c464605460a438c), + LL(0xa5acac8aac092645), LL(0xb589891e893c970f), LL(0xb414145014a04428), LL(0xbae1e1a3e15b42df), + LL(0xa616165816b04e2c), LL(0xf73a3ae83acdd274), LL(0x066969b9696fd0d2), LL(0x4109092409482d12), + LL(0xd77070dd70a7ade0), LL(0x6fb6b6e2b6d95471), LL(0x1ed0d067d0ceb7bd), LL(0xd6eded93ed3b7ec7), + LL(0xe2cccc17cc2edb85), LL(0x68424215422a5784), LL(0x2c98985a98b4c22d), LL(0xeda4a4aaa4490e55), + LL(0x752828a0285d8850), LL(0x865c5c6d5cda31b8), LL(0x6bf8f8c7f8933fed), LL(0xc28686228644a411), +}; + +static const u64 C2[256] = { + LL(0x30d818186018c078), LL(0x462623238c2305af), LL(0x91b8c6c63fc67ef9), LL(0xcdfbe8e887e8136f), + LL(0x13cb878726874ca1), LL(0x6d11b8b8dab8a962), LL(0x0209010104010805), LL(0x9e0d4f4f214f426e), + LL(0x6c9b3636d836adee), LL(0x51ffa6a6a2a65904), LL(0xb90cd2d26fd2debd), LL(0xf70ef5f5f3f5fb06), + LL(0xf2967979f979ef80), LL(0xde306f6fa16f5fce), LL(0x3f6d91917e91fcef), LL(0xa4f852525552aa07), + LL(0xc04760609d6027fd), LL(0x6535bcbccabc8976), LL(0x2b379b9b569baccd), LL(0x018a8e8e028e048c), + LL(0x5bd2a3a3b6a37115), LL(0x186c0c0c300c603c), LL(0xf6847b7bf17bff8a), LL(0x6a803535d435b5e1), + LL(0x3af51d1d741de869), LL(0xddb3e0e0a7e05347), LL(0xb321d7d77bd7f6ac), LL(0x999cc2c22fc25eed), + LL(0x5c432e2eb82e6d96), LL(0x96294b4b314b627a), LL(0xe15dfefedffea321), LL(0xaed5575741578216), + LL(0x2abd15155415a841), LL(0xeee87777c1779fb6), LL(0x6e923737dc37a5eb), LL(0xd79ee5e5b3e57b56), + LL(0x23139f9f469f8cd9), LL(0xfd23f0f0e7f0d317), LL(0x94204a4a354a6a7f), LL(0xa944dada4fda9e95), + LL(0xb0a258587d58fa25), LL(0x8fcfc9c903c906ca), LL(0x527c2929a429558d), LL(0x145a0a0a280a5022), + LL(0x7f50b1b1feb1e14f), LL(0x5dc9a0a0baa0691a), LL(0xd6146b6bb16b7fda), LL(0x17d985852e855cab), + LL(0x673cbdbdcebd8173), LL(0xba8f5d5d695dd234), LL(0x2090101040108050), LL(0xf507f4f4f7f4f303), + LL(0x8bddcbcb0bcb16c0), LL(0x7cd33e3ef83eedc6), LL(0x0a2d050514052811), LL(0xce78676781671fe6), + LL(0xd597e4e4b7e47353), LL(0x4e0227279c2725bb), LL(0x8273414119413258), LL(0x0ba78b8b168b2c9d), + LL(0x53f6a7a7a6a75101), LL(0xfab27d7de97dcf94), LL(0x374995956e95dcfb), LL(0xad56d8d847d88e9f), + LL(0xeb70fbfbcbfb8b30), LL(0xc1cdeeee9fee2371), LL(0xf8bb7c7ced7cc791), LL(0xcc716666856617e3), + LL(0xa77bdddd53dda68e), LL(0x2eaf17175c17b84b), LL(0x8e45474701470246), LL(0x211a9e9e429e84dc), + LL(0x89d4caca0fca1ec5), LL(0x5a582d2db42d7599), LL(0x632ebfbfc6bf9179), LL(0x0e3f07071c07381b), + LL(0x47acadad8ead0123), LL(0xb4b05a5a755aea2f), LL(0x1bef838336836cb5), LL(0x66b63333cc3385ff), + LL(0xc65c636391633ff2), LL(0x041202020802100a), LL(0x4993aaaa92aa3938), LL(0xe2de7171d971afa8), + LL(0x8dc6c8c807c80ecf), LL(0x32d119196419c87d), LL(0x923b494939497270), LL(0xaf5fd9d943d9869a), + LL(0xf931f2f2eff2c31d), LL(0xdba8e3e3abe34b48), LL(0xb6b95b5b715be22a), LL(0x0dbc88881a883492), + LL(0x293e9a9a529aa4c8), LL(0x4c0b262698262dbe), LL(0x64bf3232c8328dfa), LL(0x7d59b0b0fab0e94a), + LL(0xcff2e9e983e91b6a), LL(0x1e770f0f3c0f7833), LL(0xb733d5d573d5e6a6), LL(0x1df480803a8074ba), + LL(0x6127bebec2be997c), LL(0x87ebcdcd13cd26de), LL(0x68893434d034bde4), LL(0x903248483d487a75), + LL(0xe354ffffdbffab24), LL(0xf48d7a7af57af78f), LL(0x3d6490907a90f4ea), LL(0xbe9d5f5f615fc23e), + LL(0x403d202080201da0), LL(0xd00f6868bd6867d5), LL(0x34ca1a1a681ad072), LL(0x41b7aeae82ae192c), + LL(0x757db4b4eab4c95e), LL(0xa8ce54544d549a19), LL(0x3b7f93937693ece5), LL(0x442f222288220daa), + LL(0xc86364648d6407e9), LL(0xff2af1f1e3f1db12), LL(0xe6cc7373d173bfa2), LL(0x248212124812905a), + LL(0x807a40401d403a5d), LL(0x1048080820084028), LL(0x9b95c3c32bc356e8), LL(0xc5dfecec97ec337b), + LL(0xab4ddbdb4bdb9690), LL(0x5fc0a1a1bea1611f), LL(0x07918d8d0e8d1c83), LL(0x7ac83d3df43df5c9), + LL(0x335b97976697ccf1), LL(0x0000000000000000), LL(0x83f9cfcf1bcf36d4), LL(0x566e2b2bac2b4587), + LL(0xece17676c57697b3), LL(0x19e68282328264b0), LL(0xb128d6d67fd6fea9), LL(0x36c31b1b6c1bd877), + LL(0x7774b5b5eeb5c15b), LL(0x43beafaf86af1129), LL(0xd41d6a6ab56a77df), LL(0xa0ea50505d50ba0d), + LL(0x8a5745450945124c), LL(0xfb38f3f3ebf3cb18), LL(0x60ad3030c0309df0), LL(0xc3c4efef9bef2b74), + LL(0x7eda3f3ffc3fe5c3), LL(0xaac755554955921c), LL(0x59dba2a2b2a27910), LL(0xc9e9eaea8fea0365), + LL(0xca6a656589650fec), LL(0x6903babad2bab968), LL(0x5e4a2f2fbc2f6593), LL(0x9d8ec0c027c04ee7), + LL(0xa160dede5fdebe81), LL(0x38fc1c1c701ce06c), LL(0xe746fdfdd3fdbb2e), LL(0x9a1f4d4d294d5264), + LL(0x397692927292e4e0), LL(0xeafa7575c9758fbc), LL(0x0c3606061806301e), LL(0x09ae8a8a128a2498), + LL(0x794bb2b2f2b2f940), LL(0xd185e6e6bfe66359), LL(0x1c7e0e0e380e7036), LL(0x3ee71f1f7c1ff863), + LL(0xc4556262956237f7), LL(0xb53ad4d477d4eea3), LL(0x4d81a8a89aa82932), LL(0x315296966296c4f4), + LL(0xef62f9f9c3f99b3a), LL(0x97a3c5c533c566f6), LL(0x4a102525942535b1), LL(0xb2ab59597959f220), + LL(0x15d084842a8454ae), LL(0xe4c57272d572b7a7), LL(0x72ec3939e439d5dd), LL(0x98164c4c2d4c5a61), + LL(0xbc945e5e655eca3b), LL(0xf09f7878fd78e785), LL(0x70e53838e038ddd8), LL(0x05988c8c0a8c1486), + LL(0xbf17d1d163d1c6b2), LL(0x57e4a5a5aea5410b), LL(0xd9a1e2e2afe2434d), LL(0xc24e616199612ff8), + LL(0x7b42b3b3f6b3f145), LL(0x42342121842115a5), LL(0x25089c9c4a9c94d6), LL(0x3cee1e1e781ef066), + LL(0x8661434311432252), LL(0x93b1c7c73bc776fc), LL(0xe54ffcfcd7fcb32b), LL(0x0824040410042014), + LL(0xa2e351515951b208), LL(0x2f2599995e99bcc7), LL(0xda226d6da96d4fc4), LL(0x1a650d0d340d6839), + LL(0xe979fafacffa8335), LL(0xa369dfdf5bdfb684), LL(0xfca97e7ee57ed79b), LL(0x4819242490243db4), + LL(0x76fe3b3bec3bc5d7), LL(0x4b9aabab96ab313d), LL(0x81f0cece1fce3ed1), LL(0x2299111144118855), + LL(0x03838f8f068f0c89), LL(0x9c044e4e254e4a6b), LL(0x7366b7b7e6b7d151), LL(0xcbe0ebeb8beb0b60), + LL(0x78c13c3cf03cfdcc), LL(0x1ffd81813e817cbf), LL(0x354094946a94d4fe), LL(0xf31cf7f7fbf7eb0c), + LL(0x6f18b9b9deb9a167), LL(0x268b13134c13985f), LL(0x58512c2cb02c7d9c), LL(0xbb05d3d36bd3d6b8), + LL(0xd38ce7e7bbe76b5c), LL(0xdc396e6ea56e57cb), LL(0x95aac4c437c46ef3), LL(0x061b03030c03180f), + LL(0xacdc565645568a13), LL(0x885e44440d441a49), LL(0xfea07f7fe17fdf9e), LL(0x4f88a9a99ea92137), + LL(0x54672a2aa82a4d82), LL(0x6b0abbbbd6bbb16d), LL(0x9f87c1c123c146e2), LL(0xa6f153535153a202), + LL(0xa572dcdc57dcae8b), LL(0x16530b0b2c0b5827), LL(0x27019d9d4e9d9cd3), LL(0xd82b6c6cad6c47c1), + LL(0x62a43131c43195f5), LL(0xe8f37474cd7487b9), LL(0xf115f6f6fff6e309), LL(0x8c4c464605460a43), + LL(0x45a5acac8aac0926), LL(0x0fb589891e893c97), LL(0x28b414145014a044), LL(0xdfbae1e1a3e15b42), + LL(0x2ca616165816b04e), LL(0x74f73a3ae83acdd2), LL(0xd2066969b9696fd0), LL(0x124109092409482d), + LL(0xe0d77070dd70a7ad), LL(0x716fb6b6e2b6d954), LL(0xbd1ed0d067d0ceb7), LL(0xc7d6eded93ed3b7e), + LL(0x85e2cccc17cc2edb), LL(0x8468424215422a57), LL(0x2d2c98985a98b4c2), LL(0x55eda4a4aaa4490e), + LL(0x50752828a0285d88), LL(0xb8865c5c6d5cda31), LL(0xed6bf8f8c7f8933f), LL(0x11c28686228644a4), +}; + +static const u64 C3[256] = { + LL(0x7830d818186018c0), LL(0xaf462623238c2305), LL(0xf991b8c6c63fc67e), LL(0x6fcdfbe8e887e813), + LL(0xa113cb878726874c), LL(0x626d11b8b8dab8a9), LL(0x0502090101040108), LL(0x6e9e0d4f4f214f42), + LL(0xee6c9b3636d836ad), LL(0x0451ffa6a6a2a659), LL(0xbdb90cd2d26fd2de), LL(0x06f70ef5f5f3f5fb), + LL(0x80f2967979f979ef), LL(0xcede306f6fa16f5f), LL(0xef3f6d91917e91fc), LL(0x07a4f852525552aa), + LL(0xfdc04760609d6027), LL(0x766535bcbccabc89), LL(0xcd2b379b9b569bac), LL(0x8c018a8e8e028e04), + LL(0x155bd2a3a3b6a371), LL(0x3c186c0c0c300c60), LL(0x8af6847b7bf17bff), LL(0xe16a803535d435b5), + LL(0x693af51d1d741de8), LL(0x47ddb3e0e0a7e053), LL(0xacb321d7d77bd7f6), LL(0xed999cc2c22fc25e), + LL(0x965c432e2eb82e6d), LL(0x7a96294b4b314b62), LL(0x21e15dfefedffea3), LL(0x16aed55757415782), + LL(0x412abd15155415a8), LL(0xb6eee87777c1779f), LL(0xeb6e923737dc37a5), LL(0x56d79ee5e5b3e57b), + LL(0xd923139f9f469f8c), LL(0x17fd23f0f0e7f0d3), LL(0x7f94204a4a354a6a), LL(0x95a944dada4fda9e), + LL(0x25b0a258587d58fa), LL(0xca8fcfc9c903c906), LL(0x8d527c2929a42955), LL(0x22145a0a0a280a50), + LL(0x4f7f50b1b1feb1e1), LL(0x1a5dc9a0a0baa069), LL(0xdad6146b6bb16b7f), LL(0xab17d985852e855c), + LL(0x73673cbdbdcebd81), LL(0x34ba8f5d5d695dd2), LL(0x5020901010401080), LL(0x03f507f4f4f7f4f3), + LL(0xc08bddcbcb0bcb16), LL(0xc67cd33e3ef83eed), LL(0x110a2d0505140528), LL(0xe6ce78676781671f), + LL(0x53d597e4e4b7e473), LL(0xbb4e0227279c2725), LL(0x5882734141194132), LL(0x9d0ba78b8b168b2c), + LL(0x0153f6a7a7a6a751), LL(0x94fab27d7de97dcf), LL(0xfb374995956e95dc), LL(0x9fad56d8d847d88e), + LL(0x30eb70fbfbcbfb8b), LL(0x71c1cdeeee9fee23), LL(0x91f8bb7c7ced7cc7), LL(0xe3cc716666856617), + LL(0x8ea77bdddd53dda6), LL(0x4b2eaf17175c17b8), LL(0x468e454747014702), LL(0xdc211a9e9e429e84), + LL(0xc589d4caca0fca1e), LL(0x995a582d2db42d75), LL(0x79632ebfbfc6bf91), LL(0x1b0e3f07071c0738), + LL(0x2347acadad8ead01), LL(0x2fb4b05a5a755aea), LL(0xb51bef838336836c), LL(0xff66b63333cc3385), + LL(0xf2c65c636391633f), LL(0x0a04120202080210), LL(0x384993aaaa92aa39), LL(0xa8e2de7171d971af), + LL(0xcf8dc6c8c807c80e), LL(0x7d32d119196419c8), LL(0x70923b4949394972), LL(0x9aaf5fd9d943d986), + LL(0x1df931f2f2eff2c3), LL(0x48dba8e3e3abe34b), LL(0x2ab6b95b5b715be2), LL(0x920dbc88881a8834), + LL(0xc8293e9a9a529aa4), LL(0xbe4c0b262698262d), LL(0xfa64bf3232c8328d), LL(0x4a7d59b0b0fab0e9), + LL(0x6acff2e9e983e91b), LL(0x331e770f0f3c0f78), LL(0xa6b733d5d573d5e6), LL(0xba1df480803a8074), + LL(0x7c6127bebec2be99), LL(0xde87ebcdcd13cd26), LL(0xe468893434d034bd), LL(0x75903248483d487a), + LL(0x24e354ffffdbffab), LL(0x8ff48d7a7af57af7), LL(0xea3d6490907a90f4), LL(0x3ebe9d5f5f615fc2), + LL(0xa0403d202080201d), LL(0xd5d00f6868bd6867), LL(0x7234ca1a1a681ad0), LL(0x2c41b7aeae82ae19), + LL(0x5e757db4b4eab4c9), LL(0x19a8ce54544d549a), LL(0xe53b7f93937693ec), LL(0xaa442f222288220d), + LL(0xe9c86364648d6407), LL(0x12ff2af1f1e3f1db), LL(0xa2e6cc7373d173bf), LL(0x5a24821212481290), + LL(0x5d807a40401d403a), LL(0x2810480808200840), LL(0xe89b95c3c32bc356), LL(0x7bc5dfecec97ec33), + LL(0x90ab4ddbdb4bdb96), LL(0x1f5fc0a1a1bea161), LL(0x8307918d8d0e8d1c), LL(0xc97ac83d3df43df5), + LL(0xf1335b97976697cc), LL(0x0000000000000000), LL(0xd483f9cfcf1bcf36), LL(0x87566e2b2bac2b45), + LL(0xb3ece17676c57697), LL(0xb019e68282328264), LL(0xa9b128d6d67fd6fe), LL(0x7736c31b1b6c1bd8), + LL(0x5b7774b5b5eeb5c1), LL(0x2943beafaf86af11), LL(0xdfd41d6a6ab56a77), LL(0x0da0ea50505d50ba), + LL(0x4c8a574545094512), LL(0x18fb38f3f3ebf3cb), LL(0xf060ad3030c0309d), LL(0x74c3c4efef9bef2b), + LL(0xc37eda3f3ffc3fe5), LL(0x1caac75555495592), LL(0x1059dba2a2b2a279), LL(0x65c9e9eaea8fea03), + LL(0xecca6a656589650f), LL(0x686903babad2bab9), LL(0x935e4a2f2fbc2f65), LL(0xe79d8ec0c027c04e), + LL(0x81a160dede5fdebe), LL(0x6c38fc1c1c701ce0), LL(0x2ee746fdfdd3fdbb), LL(0x649a1f4d4d294d52), + LL(0xe0397692927292e4), LL(0xbceafa7575c9758f), LL(0x1e0c360606180630), LL(0x9809ae8a8a128a24), + LL(0x40794bb2b2f2b2f9), LL(0x59d185e6e6bfe663), LL(0x361c7e0e0e380e70), LL(0x633ee71f1f7c1ff8), + LL(0xf7c4556262956237), LL(0xa3b53ad4d477d4ee), LL(0x324d81a8a89aa829), LL(0xf4315296966296c4), + LL(0x3aef62f9f9c3f99b), LL(0xf697a3c5c533c566), LL(0xb14a102525942535), LL(0x20b2ab59597959f2), + LL(0xae15d084842a8454), LL(0xa7e4c57272d572b7), LL(0xdd72ec3939e439d5), LL(0x6198164c4c2d4c5a), + LL(0x3bbc945e5e655eca), LL(0x85f09f7878fd78e7), LL(0xd870e53838e038dd), LL(0x8605988c8c0a8c14), + LL(0xb2bf17d1d163d1c6), LL(0x0b57e4a5a5aea541), LL(0x4dd9a1e2e2afe243), LL(0xf8c24e616199612f), + LL(0x457b42b3b3f6b3f1), LL(0xa542342121842115), LL(0xd625089c9c4a9c94), LL(0x663cee1e1e781ef0), + LL(0x5286614343114322), LL(0xfc93b1c7c73bc776), LL(0x2be54ffcfcd7fcb3), LL(0x1408240404100420), + LL(0x08a2e351515951b2), LL(0xc72f2599995e99bc), LL(0xc4da226d6da96d4f), LL(0x391a650d0d340d68), + LL(0x35e979fafacffa83), LL(0x84a369dfdf5bdfb6), LL(0x9bfca97e7ee57ed7), LL(0xb44819242490243d), + LL(0xd776fe3b3bec3bc5), LL(0x3d4b9aabab96ab31), LL(0xd181f0cece1fce3e), LL(0x5522991111441188), + LL(0x8903838f8f068f0c), LL(0x6b9c044e4e254e4a), LL(0x517366b7b7e6b7d1), LL(0x60cbe0ebeb8beb0b), + LL(0xcc78c13c3cf03cfd), LL(0xbf1ffd81813e817c), LL(0xfe354094946a94d4), LL(0x0cf31cf7f7fbf7eb), + LL(0x676f18b9b9deb9a1), LL(0x5f268b13134c1398), LL(0x9c58512c2cb02c7d), LL(0xb8bb05d3d36bd3d6), + LL(0x5cd38ce7e7bbe76b), LL(0xcbdc396e6ea56e57), LL(0xf395aac4c437c46e), LL(0x0f061b03030c0318), + LL(0x13acdc565645568a), LL(0x49885e44440d441a), LL(0x9efea07f7fe17fdf), LL(0x374f88a9a99ea921), + LL(0x8254672a2aa82a4d), LL(0x6d6b0abbbbd6bbb1), LL(0xe29f87c1c123c146), LL(0x02a6f153535153a2), + LL(0x8ba572dcdc57dcae), LL(0x2716530b0b2c0b58), LL(0xd327019d9d4e9d9c), LL(0xc1d82b6c6cad6c47), + LL(0xf562a43131c43195), LL(0xb9e8f37474cd7487), LL(0x09f115f6f6fff6e3), LL(0x438c4c464605460a), + LL(0x2645a5acac8aac09), LL(0x970fb589891e893c), LL(0x4428b414145014a0), LL(0x42dfbae1e1a3e15b), + LL(0x4e2ca616165816b0), LL(0xd274f73a3ae83acd), LL(0xd0d2066969b9696f), LL(0x2d12410909240948), + LL(0xade0d77070dd70a7), LL(0x54716fb6b6e2b6d9), LL(0xb7bd1ed0d067d0ce), LL(0x7ec7d6eded93ed3b), + LL(0xdb85e2cccc17cc2e), LL(0x578468424215422a), LL(0xc22d2c98985a98b4), LL(0x0e55eda4a4aaa449), + LL(0x8850752828a0285d), LL(0x31b8865c5c6d5cda), LL(0x3fed6bf8f8c7f893), LL(0xa411c28686228644), +}; + +static const u64 C4[256] = { + LL(0xc07830d818186018), LL(0x05af462623238c23), LL(0x7ef991b8c6c63fc6), LL(0x136fcdfbe8e887e8), + LL(0x4ca113cb87872687), LL(0xa9626d11b8b8dab8), LL(0x0805020901010401), LL(0x426e9e0d4f4f214f), + LL(0xadee6c9b3636d836), LL(0x590451ffa6a6a2a6), LL(0xdebdb90cd2d26fd2), LL(0xfb06f70ef5f5f3f5), + LL(0xef80f2967979f979), LL(0x5fcede306f6fa16f), LL(0xfcef3f6d91917e91), LL(0xaa07a4f852525552), + LL(0x27fdc04760609d60), LL(0x89766535bcbccabc), LL(0xaccd2b379b9b569b), LL(0x048c018a8e8e028e), + LL(0x71155bd2a3a3b6a3), LL(0x603c186c0c0c300c), LL(0xff8af6847b7bf17b), LL(0xb5e16a803535d435), + LL(0xe8693af51d1d741d), LL(0x5347ddb3e0e0a7e0), LL(0xf6acb321d7d77bd7), LL(0x5eed999cc2c22fc2), + LL(0x6d965c432e2eb82e), LL(0x627a96294b4b314b), LL(0xa321e15dfefedffe), LL(0x8216aed557574157), + LL(0xa8412abd15155415), LL(0x9fb6eee87777c177), LL(0xa5eb6e923737dc37), LL(0x7b56d79ee5e5b3e5), + LL(0x8cd923139f9f469f), LL(0xd317fd23f0f0e7f0), LL(0x6a7f94204a4a354a), LL(0x9e95a944dada4fda), + LL(0xfa25b0a258587d58), LL(0x06ca8fcfc9c903c9), LL(0x558d527c2929a429), LL(0x5022145a0a0a280a), + LL(0xe14f7f50b1b1feb1), LL(0x691a5dc9a0a0baa0), LL(0x7fdad6146b6bb16b), LL(0x5cab17d985852e85), + LL(0x8173673cbdbdcebd), LL(0xd234ba8f5d5d695d), LL(0x8050209010104010), LL(0xf303f507f4f4f7f4), + LL(0x16c08bddcbcb0bcb), LL(0xedc67cd33e3ef83e), LL(0x28110a2d05051405), LL(0x1fe6ce7867678167), + LL(0x7353d597e4e4b7e4), LL(0x25bb4e0227279c27), LL(0x3258827341411941), LL(0x2c9d0ba78b8b168b), + LL(0x510153f6a7a7a6a7), LL(0xcf94fab27d7de97d), LL(0xdcfb374995956e95), LL(0x8e9fad56d8d847d8), + LL(0x8b30eb70fbfbcbfb), LL(0x2371c1cdeeee9fee), LL(0xc791f8bb7c7ced7c), LL(0x17e3cc7166668566), + LL(0xa68ea77bdddd53dd), LL(0xb84b2eaf17175c17), LL(0x02468e4547470147), LL(0x84dc211a9e9e429e), + LL(0x1ec589d4caca0fca), LL(0x75995a582d2db42d), LL(0x9179632ebfbfc6bf), LL(0x381b0e3f07071c07), + LL(0x012347acadad8ead), LL(0xea2fb4b05a5a755a), LL(0x6cb51bef83833683), LL(0x85ff66b63333cc33), + LL(0x3ff2c65c63639163), LL(0x100a041202020802), LL(0x39384993aaaa92aa), LL(0xafa8e2de7171d971), + LL(0x0ecf8dc6c8c807c8), LL(0xc87d32d119196419), LL(0x7270923b49493949), LL(0x869aaf5fd9d943d9), + LL(0xc31df931f2f2eff2), LL(0x4b48dba8e3e3abe3), LL(0xe22ab6b95b5b715b), LL(0x34920dbc88881a88), + LL(0xa4c8293e9a9a529a), LL(0x2dbe4c0b26269826), LL(0x8dfa64bf3232c832), LL(0xe94a7d59b0b0fab0), + LL(0x1b6acff2e9e983e9), LL(0x78331e770f0f3c0f), LL(0xe6a6b733d5d573d5), LL(0x74ba1df480803a80), + LL(0x997c6127bebec2be), LL(0x26de87ebcdcd13cd), LL(0xbde468893434d034), LL(0x7a75903248483d48), + LL(0xab24e354ffffdbff), LL(0xf78ff48d7a7af57a), LL(0xf4ea3d6490907a90), LL(0xc23ebe9d5f5f615f), + LL(0x1da0403d20208020), LL(0x67d5d00f6868bd68), LL(0xd07234ca1a1a681a), LL(0x192c41b7aeae82ae), + LL(0xc95e757db4b4eab4), LL(0x9a19a8ce54544d54), LL(0xece53b7f93937693), LL(0x0daa442f22228822), + LL(0x07e9c86364648d64), LL(0xdb12ff2af1f1e3f1), LL(0xbfa2e6cc7373d173), LL(0x905a248212124812), + LL(0x3a5d807a40401d40), LL(0x4028104808082008), LL(0x56e89b95c3c32bc3), LL(0x337bc5dfecec97ec), + LL(0x9690ab4ddbdb4bdb), LL(0x611f5fc0a1a1bea1), LL(0x1c8307918d8d0e8d), LL(0xf5c97ac83d3df43d), + LL(0xccf1335b97976697), LL(0x0000000000000000), LL(0x36d483f9cfcf1bcf), LL(0x4587566e2b2bac2b), + LL(0x97b3ece17676c576), LL(0x64b019e682823282), LL(0xfea9b128d6d67fd6), LL(0xd87736c31b1b6c1b), + LL(0xc15b7774b5b5eeb5), LL(0x112943beafaf86af), LL(0x77dfd41d6a6ab56a), LL(0xba0da0ea50505d50), + LL(0x124c8a5745450945), LL(0xcb18fb38f3f3ebf3), LL(0x9df060ad3030c030), LL(0x2b74c3c4efef9bef), + LL(0xe5c37eda3f3ffc3f), LL(0x921caac755554955), LL(0x791059dba2a2b2a2), LL(0x0365c9e9eaea8fea), + LL(0x0fecca6a65658965), LL(0xb9686903babad2ba), LL(0x65935e4a2f2fbc2f), LL(0x4ee79d8ec0c027c0), + LL(0xbe81a160dede5fde), LL(0xe06c38fc1c1c701c), LL(0xbb2ee746fdfdd3fd), LL(0x52649a1f4d4d294d), + LL(0xe4e0397692927292), LL(0x8fbceafa7575c975), LL(0x301e0c3606061806), LL(0x249809ae8a8a128a), + LL(0xf940794bb2b2f2b2), LL(0x6359d185e6e6bfe6), LL(0x70361c7e0e0e380e), LL(0xf8633ee71f1f7c1f), + LL(0x37f7c45562629562), LL(0xeea3b53ad4d477d4), LL(0x29324d81a8a89aa8), LL(0xc4f4315296966296), + LL(0x9b3aef62f9f9c3f9), LL(0x66f697a3c5c533c5), LL(0x35b14a1025259425), LL(0xf220b2ab59597959), + LL(0x54ae15d084842a84), LL(0xb7a7e4c57272d572), LL(0xd5dd72ec3939e439), LL(0x5a6198164c4c2d4c), + LL(0xca3bbc945e5e655e), LL(0xe785f09f7878fd78), LL(0xddd870e53838e038), LL(0x148605988c8c0a8c), + LL(0xc6b2bf17d1d163d1), LL(0x410b57e4a5a5aea5), LL(0x434dd9a1e2e2afe2), LL(0x2ff8c24e61619961), + LL(0xf1457b42b3b3f6b3), LL(0x15a5423421218421), LL(0x94d625089c9c4a9c), LL(0xf0663cee1e1e781e), + LL(0x2252866143431143), LL(0x76fc93b1c7c73bc7), LL(0xb32be54ffcfcd7fc), LL(0x2014082404041004), + LL(0xb208a2e351515951), LL(0xbcc72f2599995e99), LL(0x4fc4da226d6da96d), LL(0x68391a650d0d340d), + LL(0x8335e979fafacffa), LL(0xb684a369dfdf5bdf), LL(0xd79bfca97e7ee57e), LL(0x3db4481924249024), + LL(0xc5d776fe3b3bec3b), LL(0x313d4b9aabab96ab), LL(0x3ed181f0cece1fce), LL(0x8855229911114411), + LL(0x0c8903838f8f068f), LL(0x4a6b9c044e4e254e), LL(0xd1517366b7b7e6b7), LL(0x0b60cbe0ebeb8beb), + LL(0xfdcc78c13c3cf03c), LL(0x7cbf1ffd81813e81), LL(0xd4fe354094946a94), LL(0xeb0cf31cf7f7fbf7), + LL(0xa1676f18b9b9deb9), LL(0x985f268b13134c13), LL(0x7d9c58512c2cb02c), LL(0xd6b8bb05d3d36bd3), + LL(0x6b5cd38ce7e7bbe7), LL(0x57cbdc396e6ea56e), LL(0x6ef395aac4c437c4), LL(0x180f061b03030c03), + LL(0x8a13acdc56564556), LL(0x1a49885e44440d44), LL(0xdf9efea07f7fe17f), LL(0x21374f88a9a99ea9), + LL(0x4d8254672a2aa82a), LL(0xb16d6b0abbbbd6bb), LL(0x46e29f87c1c123c1), LL(0xa202a6f153535153), + LL(0xae8ba572dcdc57dc), LL(0x582716530b0b2c0b), LL(0x9cd327019d9d4e9d), LL(0x47c1d82b6c6cad6c), + LL(0x95f562a43131c431), LL(0x87b9e8f37474cd74), LL(0xe309f115f6f6fff6), LL(0x0a438c4c46460546), + LL(0x092645a5acac8aac), LL(0x3c970fb589891e89), LL(0xa04428b414145014), LL(0x5b42dfbae1e1a3e1), + LL(0xb04e2ca616165816), LL(0xcdd274f73a3ae83a), LL(0x6fd0d2066969b969), LL(0x482d124109092409), + LL(0xa7ade0d77070dd70), LL(0xd954716fb6b6e2b6), LL(0xceb7bd1ed0d067d0), LL(0x3b7ec7d6eded93ed), + LL(0x2edb85e2cccc17cc), LL(0x2a57846842421542), LL(0xb4c22d2c98985a98), LL(0x490e55eda4a4aaa4), + LL(0x5d8850752828a028), LL(0xda31b8865c5c6d5c), LL(0x933fed6bf8f8c7f8), LL(0x44a411c286862286), +}; + +static const u64 C5[256] = { + LL(0x18c07830d8181860), LL(0x2305af462623238c), LL(0xc67ef991b8c6c63f), LL(0xe8136fcdfbe8e887), + LL(0x874ca113cb878726), LL(0xb8a9626d11b8b8da), LL(0x0108050209010104), LL(0x4f426e9e0d4f4f21), + LL(0x36adee6c9b3636d8), LL(0xa6590451ffa6a6a2), LL(0xd2debdb90cd2d26f), LL(0xf5fb06f70ef5f5f3), + LL(0x79ef80f2967979f9), LL(0x6f5fcede306f6fa1), LL(0x91fcef3f6d91917e), LL(0x52aa07a4f8525255), + LL(0x6027fdc04760609d), LL(0xbc89766535bcbcca), LL(0x9baccd2b379b9b56), LL(0x8e048c018a8e8e02), + LL(0xa371155bd2a3a3b6), LL(0x0c603c186c0c0c30), LL(0x7bff8af6847b7bf1), LL(0x35b5e16a803535d4), + LL(0x1de8693af51d1d74), LL(0xe05347ddb3e0e0a7), LL(0xd7f6acb321d7d77b), LL(0xc25eed999cc2c22f), + LL(0x2e6d965c432e2eb8), LL(0x4b627a96294b4b31), LL(0xfea321e15dfefedf), LL(0x578216aed5575741), + LL(0x15a8412abd151554), LL(0x779fb6eee87777c1), LL(0x37a5eb6e923737dc), LL(0xe57b56d79ee5e5b3), + LL(0x9f8cd923139f9f46), LL(0xf0d317fd23f0f0e7), LL(0x4a6a7f94204a4a35), LL(0xda9e95a944dada4f), + LL(0x58fa25b0a258587d), LL(0xc906ca8fcfc9c903), LL(0x29558d527c2929a4), LL(0x0a5022145a0a0a28), + LL(0xb1e14f7f50b1b1fe), LL(0xa0691a5dc9a0a0ba), LL(0x6b7fdad6146b6bb1), LL(0x855cab17d985852e), + LL(0xbd8173673cbdbdce), LL(0x5dd234ba8f5d5d69), LL(0x1080502090101040), LL(0xf4f303f507f4f4f7), + LL(0xcb16c08bddcbcb0b), LL(0x3eedc67cd33e3ef8), LL(0x0528110a2d050514), LL(0x671fe6ce78676781), + LL(0xe47353d597e4e4b7), LL(0x2725bb4e0227279c), LL(0x4132588273414119), LL(0x8b2c9d0ba78b8b16), + LL(0xa7510153f6a7a7a6), LL(0x7dcf94fab27d7de9), LL(0x95dcfb374995956e), LL(0xd88e9fad56d8d847), + LL(0xfb8b30eb70fbfbcb), LL(0xee2371c1cdeeee9f), LL(0x7cc791f8bb7c7ced), LL(0x6617e3cc71666685), + LL(0xdda68ea77bdddd53), LL(0x17b84b2eaf17175c), LL(0x4702468e45474701), LL(0x9e84dc211a9e9e42), + LL(0xca1ec589d4caca0f), LL(0x2d75995a582d2db4), LL(0xbf9179632ebfbfc6), LL(0x07381b0e3f07071c), + LL(0xad012347acadad8e), LL(0x5aea2fb4b05a5a75), LL(0x836cb51bef838336), LL(0x3385ff66b63333cc), + LL(0x633ff2c65c636391), LL(0x02100a0412020208), LL(0xaa39384993aaaa92), LL(0x71afa8e2de7171d9), + LL(0xc80ecf8dc6c8c807), LL(0x19c87d32d1191964), LL(0x497270923b494939), LL(0xd9869aaf5fd9d943), + LL(0xf2c31df931f2f2ef), LL(0xe34b48dba8e3e3ab), LL(0x5be22ab6b95b5b71), LL(0x8834920dbc88881a), + LL(0x9aa4c8293e9a9a52), LL(0x262dbe4c0b262698), LL(0x328dfa64bf3232c8), LL(0xb0e94a7d59b0b0fa), + LL(0xe91b6acff2e9e983), LL(0x0f78331e770f0f3c), LL(0xd5e6a6b733d5d573), LL(0x8074ba1df480803a), + LL(0xbe997c6127bebec2), LL(0xcd26de87ebcdcd13), LL(0x34bde468893434d0), LL(0x487a75903248483d), + LL(0xffab24e354ffffdb), LL(0x7af78ff48d7a7af5), LL(0x90f4ea3d6490907a), LL(0x5fc23ebe9d5f5f61), + LL(0x201da0403d202080), LL(0x6867d5d00f6868bd), LL(0x1ad07234ca1a1a68), LL(0xae192c41b7aeae82), + LL(0xb4c95e757db4b4ea), LL(0x549a19a8ce54544d), LL(0x93ece53b7f939376), LL(0x220daa442f222288), + LL(0x6407e9c86364648d), LL(0xf1db12ff2af1f1e3), LL(0x73bfa2e6cc7373d1), LL(0x12905a2482121248), + LL(0x403a5d807a40401d), LL(0x0840281048080820), LL(0xc356e89b95c3c32b), LL(0xec337bc5dfecec97), + LL(0xdb9690ab4ddbdb4b), LL(0xa1611f5fc0a1a1be), LL(0x8d1c8307918d8d0e), LL(0x3df5c97ac83d3df4), + LL(0x97ccf1335b979766), LL(0x0000000000000000), LL(0xcf36d483f9cfcf1b), LL(0x2b4587566e2b2bac), + LL(0x7697b3ece17676c5), LL(0x8264b019e6828232), LL(0xd6fea9b128d6d67f), LL(0x1bd87736c31b1b6c), + LL(0xb5c15b7774b5b5ee), LL(0xaf112943beafaf86), LL(0x6a77dfd41d6a6ab5), LL(0x50ba0da0ea50505d), + LL(0x45124c8a57454509), LL(0xf3cb18fb38f3f3eb), LL(0x309df060ad3030c0), LL(0xef2b74c3c4efef9b), + LL(0x3fe5c37eda3f3ffc), LL(0x55921caac7555549), LL(0xa2791059dba2a2b2), LL(0xea0365c9e9eaea8f), + LL(0x650fecca6a656589), LL(0xbab9686903babad2), LL(0x2f65935e4a2f2fbc), LL(0xc04ee79d8ec0c027), + LL(0xdebe81a160dede5f), LL(0x1ce06c38fc1c1c70), LL(0xfdbb2ee746fdfdd3), LL(0x4d52649a1f4d4d29), + LL(0x92e4e03976929272), LL(0x758fbceafa7575c9), LL(0x06301e0c36060618), LL(0x8a249809ae8a8a12), + LL(0xb2f940794bb2b2f2), LL(0xe66359d185e6e6bf), LL(0x0e70361c7e0e0e38), LL(0x1ff8633ee71f1f7c), + LL(0x6237f7c455626295), LL(0xd4eea3b53ad4d477), LL(0xa829324d81a8a89a), LL(0x96c4f43152969662), + LL(0xf99b3aef62f9f9c3), LL(0xc566f697a3c5c533), LL(0x2535b14a10252594), LL(0x59f220b2ab595979), + LL(0x8454ae15d084842a), LL(0x72b7a7e4c57272d5), LL(0x39d5dd72ec3939e4), LL(0x4c5a6198164c4c2d), + LL(0x5eca3bbc945e5e65), LL(0x78e785f09f7878fd), LL(0x38ddd870e53838e0), LL(0x8c148605988c8c0a), + LL(0xd1c6b2bf17d1d163), LL(0xa5410b57e4a5a5ae), LL(0xe2434dd9a1e2e2af), LL(0x612ff8c24e616199), + LL(0xb3f1457b42b3b3f6), LL(0x2115a54234212184), LL(0x9c94d625089c9c4a), LL(0x1ef0663cee1e1e78), + LL(0x4322528661434311), LL(0xc776fc93b1c7c73b), LL(0xfcb32be54ffcfcd7), LL(0x0420140824040410), + LL(0x51b208a2e3515159), LL(0x99bcc72f2599995e), LL(0x6d4fc4da226d6da9), LL(0x0d68391a650d0d34), + LL(0xfa8335e979fafacf), LL(0xdfb684a369dfdf5b), LL(0x7ed79bfca97e7ee5), LL(0x243db44819242490), + LL(0x3bc5d776fe3b3bec), LL(0xab313d4b9aabab96), LL(0xce3ed181f0cece1f), LL(0x1188552299111144), + LL(0x8f0c8903838f8f06), LL(0x4e4a6b9c044e4e25), LL(0xb7d1517366b7b7e6), LL(0xeb0b60cbe0ebeb8b), + LL(0x3cfdcc78c13c3cf0), LL(0x817cbf1ffd81813e), LL(0x94d4fe354094946a), LL(0xf7eb0cf31cf7f7fb), + LL(0xb9a1676f18b9b9de), LL(0x13985f268b13134c), LL(0x2c7d9c58512c2cb0), LL(0xd3d6b8bb05d3d36b), + LL(0xe76b5cd38ce7e7bb), LL(0x6e57cbdc396e6ea5), LL(0xc46ef395aac4c437), LL(0x03180f061b03030c), + LL(0x568a13acdc565645), LL(0x441a49885e44440d), LL(0x7fdf9efea07f7fe1), LL(0xa921374f88a9a99e), + LL(0x2a4d8254672a2aa8), LL(0xbbb16d6b0abbbbd6), LL(0xc146e29f87c1c123), LL(0x53a202a6f1535351), + LL(0xdcae8ba572dcdc57), LL(0x0b582716530b0b2c), LL(0x9d9cd327019d9d4e), LL(0x6c47c1d82b6c6cad), + LL(0x3195f562a43131c4), LL(0x7487b9e8f37474cd), LL(0xf6e309f115f6f6ff), LL(0x460a438c4c464605), + LL(0xac092645a5acac8a), LL(0x893c970fb589891e), LL(0x14a04428b4141450), LL(0xe15b42dfbae1e1a3), + LL(0x16b04e2ca6161658), LL(0x3acdd274f73a3ae8), LL(0x696fd0d2066969b9), LL(0x09482d1241090924), + LL(0x70a7ade0d77070dd), LL(0xb6d954716fb6b6e2), LL(0xd0ceb7bd1ed0d067), LL(0xed3b7ec7d6eded93), + LL(0xcc2edb85e2cccc17), LL(0x422a578468424215), LL(0x98b4c22d2c98985a), LL(0xa4490e55eda4a4aa), + LL(0x285d8850752828a0), LL(0x5cda31b8865c5c6d), LL(0xf8933fed6bf8f8c7), LL(0x8644a411c2868622), +}; + +static const u64 C6[256] = { + LL(0x6018c07830d81818), LL(0x8c2305af46262323), LL(0x3fc67ef991b8c6c6), LL(0x87e8136fcdfbe8e8), + LL(0x26874ca113cb8787), LL(0xdab8a9626d11b8b8), LL(0x0401080502090101), LL(0x214f426e9e0d4f4f), + LL(0xd836adee6c9b3636), LL(0xa2a6590451ffa6a6), LL(0x6fd2debdb90cd2d2), LL(0xf3f5fb06f70ef5f5), + LL(0xf979ef80f2967979), LL(0xa16f5fcede306f6f), LL(0x7e91fcef3f6d9191), LL(0x5552aa07a4f85252), + LL(0x9d6027fdc0476060), LL(0xcabc89766535bcbc), LL(0x569baccd2b379b9b), LL(0x028e048c018a8e8e), + LL(0xb6a371155bd2a3a3), LL(0x300c603c186c0c0c), LL(0xf17bff8af6847b7b), LL(0xd435b5e16a803535), + LL(0x741de8693af51d1d), LL(0xa7e05347ddb3e0e0), LL(0x7bd7f6acb321d7d7), LL(0x2fc25eed999cc2c2), + LL(0xb82e6d965c432e2e), LL(0x314b627a96294b4b), LL(0xdffea321e15dfefe), LL(0x41578216aed55757), + LL(0x5415a8412abd1515), LL(0xc1779fb6eee87777), LL(0xdc37a5eb6e923737), LL(0xb3e57b56d79ee5e5), + LL(0x469f8cd923139f9f), LL(0xe7f0d317fd23f0f0), LL(0x354a6a7f94204a4a), LL(0x4fda9e95a944dada), + LL(0x7d58fa25b0a25858), LL(0x03c906ca8fcfc9c9), LL(0xa429558d527c2929), LL(0x280a5022145a0a0a), + LL(0xfeb1e14f7f50b1b1), LL(0xbaa0691a5dc9a0a0), LL(0xb16b7fdad6146b6b), LL(0x2e855cab17d98585), + LL(0xcebd8173673cbdbd), LL(0x695dd234ba8f5d5d), LL(0x4010805020901010), LL(0xf7f4f303f507f4f4), + LL(0x0bcb16c08bddcbcb), LL(0xf83eedc67cd33e3e), LL(0x140528110a2d0505), LL(0x81671fe6ce786767), + LL(0xb7e47353d597e4e4), LL(0x9c2725bb4e022727), LL(0x1941325882734141), LL(0x168b2c9d0ba78b8b), + LL(0xa6a7510153f6a7a7), LL(0xe97dcf94fab27d7d), LL(0x6e95dcfb37499595), LL(0x47d88e9fad56d8d8), + LL(0xcbfb8b30eb70fbfb), LL(0x9fee2371c1cdeeee), LL(0xed7cc791f8bb7c7c), LL(0x856617e3cc716666), + LL(0x53dda68ea77bdddd), LL(0x5c17b84b2eaf1717), LL(0x014702468e454747), LL(0x429e84dc211a9e9e), + LL(0x0fca1ec589d4caca), LL(0xb42d75995a582d2d), LL(0xc6bf9179632ebfbf), LL(0x1c07381b0e3f0707), + LL(0x8ead012347acadad), LL(0x755aea2fb4b05a5a), LL(0x36836cb51bef8383), LL(0xcc3385ff66b63333), + LL(0x91633ff2c65c6363), LL(0x0802100a04120202), LL(0x92aa39384993aaaa), LL(0xd971afa8e2de7171), + LL(0x07c80ecf8dc6c8c8), LL(0x6419c87d32d11919), LL(0x39497270923b4949), LL(0x43d9869aaf5fd9d9), + LL(0xeff2c31df931f2f2), LL(0xabe34b48dba8e3e3), LL(0x715be22ab6b95b5b), LL(0x1a8834920dbc8888), + LL(0x529aa4c8293e9a9a), LL(0x98262dbe4c0b2626), LL(0xc8328dfa64bf3232), LL(0xfab0e94a7d59b0b0), + LL(0x83e91b6acff2e9e9), LL(0x3c0f78331e770f0f), LL(0x73d5e6a6b733d5d5), LL(0x3a8074ba1df48080), + LL(0xc2be997c6127bebe), LL(0x13cd26de87ebcdcd), LL(0xd034bde468893434), LL(0x3d487a7590324848), + LL(0xdbffab24e354ffff), LL(0xf57af78ff48d7a7a), LL(0x7a90f4ea3d649090), LL(0x615fc23ebe9d5f5f), + LL(0x80201da0403d2020), LL(0xbd6867d5d00f6868), LL(0x681ad07234ca1a1a), LL(0x82ae192c41b7aeae), + LL(0xeab4c95e757db4b4), LL(0x4d549a19a8ce5454), LL(0x7693ece53b7f9393), LL(0x88220daa442f2222), + LL(0x8d6407e9c8636464), LL(0xe3f1db12ff2af1f1), LL(0xd173bfa2e6cc7373), LL(0x4812905a24821212), + LL(0x1d403a5d807a4040), LL(0x2008402810480808), LL(0x2bc356e89b95c3c3), LL(0x97ec337bc5dfecec), + LL(0x4bdb9690ab4ddbdb), LL(0xbea1611f5fc0a1a1), LL(0x0e8d1c8307918d8d), LL(0xf43df5c97ac83d3d), + LL(0x6697ccf1335b9797), LL(0x0000000000000000), LL(0x1bcf36d483f9cfcf), LL(0xac2b4587566e2b2b), + LL(0xc57697b3ece17676), LL(0x328264b019e68282), LL(0x7fd6fea9b128d6d6), LL(0x6c1bd87736c31b1b), + LL(0xeeb5c15b7774b5b5), LL(0x86af112943beafaf), LL(0xb56a77dfd41d6a6a), LL(0x5d50ba0da0ea5050), + LL(0x0945124c8a574545), LL(0xebf3cb18fb38f3f3), LL(0xc0309df060ad3030), LL(0x9bef2b74c3c4efef), + LL(0xfc3fe5c37eda3f3f), LL(0x4955921caac75555), LL(0xb2a2791059dba2a2), LL(0x8fea0365c9e9eaea), + LL(0x89650fecca6a6565), LL(0xd2bab9686903baba), LL(0xbc2f65935e4a2f2f), LL(0x27c04ee79d8ec0c0), + LL(0x5fdebe81a160dede), LL(0x701ce06c38fc1c1c), LL(0xd3fdbb2ee746fdfd), LL(0x294d52649a1f4d4d), + LL(0x7292e4e039769292), LL(0xc9758fbceafa7575), LL(0x1806301e0c360606), LL(0x128a249809ae8a8a), + LL(0xf2b2f940794bb2b2), LL(0xbfe66359d185e6e6), LL(0x380e70361c7e0e0e), LL(0x7c1ff8633ee71f1f), + LL(0x956237f7c4556262), LL(0x77d4eea3b53ad4d4), LL(0x9aa829324d81a8a8), LL(0x6296c4f431529696), + LL(0xc3f99b3aef62f9f9), LL(0x33c566f697a3c5c5), LL(0x942535b14a102525), LL(0x7959f220b2ab5959), + LL(0x2a8454ae15d08484), LL(0xd572b7a7e4c57272), LL(0xe439d5dd72ec3939), LL(0x2d4c5a6198164c4c), + LL(0x655eca3bbc945e5e), LL(0xfd78e785f09f7878), LL(0xe038ddd870e53838), LL(0x0a8c148605988c8c), + LL(0x63d1c6b2bf17d1d1), LL(0xaea5410b57e4a5a5), LL(0xafe2434dd9a1e2e2), LL(0x99612ff8c24e6161), + LL(0xf6b3f1457b42b3b3), LL(0x842115a542342121), LL(0x4a9c94d625089c9c), LL(0x781ef0663cee1e1e), + LL(0x1143225286614343), LL(0x3bc776fc93b1c7c7), LL(0xd7fcb32be54ffcfc), LL(0x1004201408240404), + LL(0x5951b208a2e35151), LL(0x5e99bcc72f259999), LL(0xa96d4fc4da226d6d), LL(0x340d68391a650d0d), + LL(0xcffa8335e979fafa), LL(0x5bdfb684a369dfdf), LL(0xe57ed79bfca97e7e), LL(0x90243db448192424), + LL(0xec3bc5d776fe3b3b), LL(0x96ab313d4b9aabab), LL(0x1fce3ed181f0cece), LL(0x4411885522991111), + LL(0x068f0c8903838f8f), LL(0x254e4a6b9c044e4e), LL(0xe6b7d1517366b7b7), LL(0x8beb0b60cbe0ebeb), + LL(0xf03cfdcc78c13c3c), LL(0x3e817cbf1ffd8181), LL(0x6a94d4fe35409494), LL(0xfbf7eb0cf31cf7f7), + LL(0xdeb9a1676f18b9b9), LL(0x4c13985f268b1313), LL(0xb02c7d9c58512c2c), LL(0x6bd3d6b8bb05d3d3), + LL(0xbbe76b5cd38ce7e7), LL(0xa56e57cbdc396e6e), LL(0x37c46ef395aac4c4), LL(0x0c03180f061b0303), + LL(0x45568a13acdc5656), LL(0x0d441a49885e4444), LL(0xe17fdf9efea07f7f), LL(0x9ea921374f88a9a9), + LL(0xa82a4d8254672a2a), LL(0xd6bbb16d6b0abbbb), LL(0x23c146e29f87c1c1), LL(0x5153a202a6f15353), + LL(0x57dcae8ba572dcdc), LL(0x2c0b582716530b0b), LL(0x4e9d9cd327019d9d), LL(0xad6c47c1d82b6c6c), + LL(0xc43195f562a43131), LL(0xcd7487b9e8f37474), LL(0xfff6e309f115f6f6), LL(0x05460a438c4c4646), + LL(0x8aac092645a5acac), LL(0x1e893c970fb58989), LL(0x5014a04428b41414), LL(0xa3e15b42dfbae1e1), + LL(0x5816b04e2ca61616), LL(0xe83acdd274f73a3a), LL(0xb9696fd0d2066969), LL(0x2409482d12410909), + LL(0xdd70a7ade0d77070), LL(0xe2b6d954716fb6b6), LL(0x67d0ceb7bd1ed0d0), LL(0x93ed3b7ec7d6eded), + LL(0x17cc2edb85e2cccc), LL(0x15422a5784684242), LL(0x5a98b4c22d2c9898), LL(0xaaa4490e55eda4a4), + LL(0xa0285d8850752828), LL(0x6d5cda31b8865c5c), LL(0xc7f8933fed6bf8f8), LL(0x228644a411c28686), +}; + +static const u64 C7[256] = { + LL(0x186018c07830d818), LL(0x238c2305af462623), LL(0xc63fc67ef991b8c6), LL(0xe887e8136fcdfbe8), + LL(0x8726874ca113cb87), LL(0xb8dab8a9626d11b8), LL(0x0104010805020901), LL(0x4f214f426e9e0d4f), + LL(0x36d836adee6c9b36), LL(0xa6a2a6590451ffa6), LL(0xd26fd2debdb90cd2), LL(0xf5f3f5fb06f70ef5), + LL(0x79f979ef80f29679), LL(0x6fa16f5fcede306f), LL(0x917e91fcef3f6d91), LL(0x525552aa07a4f852), + LL(0x609d6027fdc04760), LL(0xbccabc89766535bc), LL(0x9b569baccd2b379b), LL(0x8e028e048c018a8e), + LL(0xa3b6a371155bd2a3), LL(0x0c300c603c186c0c), LL(0x7bf17bff8af6847b), LL(0x35d435b5e16a8035), + LL(0x1d741de8693af51d), LL(0xe0a7e05347ddb3e0), LL(0xd77bd7f6acb321d7), LL(0xc22fc25eed999cc2), + LL(0x2eb82e6d965c432e), LL(0x4b314b627a96294b), LL(0xfedffea321e15dfe), LL(0x5741578216aed557), + LL(0x155415a8412abd15), LL(0x77c1779fb6eee877), LL(0x37dc37a5eb6e9237), LL(0xe5b3e57b56d79ee5), + LL(0x9f469f8cd923139f), LL(0xf0e7f0d317fd23f0), LL(0x4a354a6a7f94204a), LL(0xda4fda9e95a944da), + LL(0x587d58fa25b0a258), LL(0xc903c906ca8fcfc9), LL(0x29a429558d527c29), LL(0x0a280a5022145a0a), + LL(0xb1feb1e14f7f50b1), LL(0xa0baa0691a5dc9a0), LL(0x6bb16b7fdad6146b), LL(0x852e855cab17d985), + LL(0xbdcebd8173673cbd), LL(0x5d695dd234ba8f5d), LL(0x1040108050209010), LL(0xf4f7f4f303f507f4), + LL(0xcb0bcb16c08bddcb), LL(0x3ef83eedc67cd33e), LL(0x05140528110a2d05), LL(0x6781671fe6ce7867), + LL(0xe4b7e47353d597e4), LL(0x279c2725bb4e0227), LL(0x4119413258827341), LL(0x8b168b2c9d0ba78b), + LL(0xa7a6a7510153f6a7), LL(0x7de97dcf94fab27d), LL(0x956e95dcfb374995), LL(0xd847d88e9fad56d8), + LL(0xfbcbfb8b30eb70fb), LL(0xee9fee2371c1cdee), LL(0x7ced7cc791f8bb7c), LL(0x66856617e3cc7166), + LL(0xdd53dda68ea77bdd), LL(0x175c17b84b2eaf17), LL(0x47014702468e4547), LL(0x9e429e84dc211a9e), + LL(0xca0fca1ec589d4ca), LL(0x2db42d75995a582d), LL(0xbfc6bf9179632ebf), LL(0x071c07381b0e3f07), + LL(0xad8ead012347acad), LL(0x5a755aea2fb4b05a), LL(0x8336836cb51bef83), LL(0x33cc3385ff66b633), + LL(0x6391633ff2c65c63), LL(0x020802100a041202), LL(0xaa92aa39384993aa), LL(0x71d971afa8e2de71), + LL(0xc807c80ecf8dc6c8), LL(0x196419c87d32d119), LL(0x4939497270923b49), LL(0xd943d9869aaf5fd9), + LL(0xf2eff2c31df931f2), LL(0xe3abe34b48dba8e3), LL(0x5b715be22ab6b95b), LL(0x881a8834920dbc88), + LL(0x9a529aa4c8293e9a), LL(0x2698262dbe4c0b26), LL(0x32c8328dfa64bf32), LL(0xb0fab0e94a7d59b0), + LL(0xe983e91b6acff2e9), LL(0x0f3c0f78331e770f), LL(0xd573d5e6a6b733d5), LL(0x803a8074ba1df480), + LL(0xbec2be997c6127be), LL(0xcd13cd26de87ebcd), LL(0x34d034bde4688934), LL(0x483d487a75903248), + LL(0xffdbffab24e354ff), LL(0x7af57af78ff48d7a), LL(0x907a90f4ea3d6490), LL(0x5f615fc23ebe9d5f), + LL(0x2080201da0403d20), LL(0x68bd6867d5d00f68), LL(0x1a681ad07234ca1a), LL(0xae82ae192c41b7ae), + LL(0xb4eab4c95e757db4), LL(0x544d549a19a8ce54), LL(0x937693ece53b7f93), LL(0x2288220daa442f22), + LL(0x648d6407e9c86364), LL(0xf1e3f1db12ff2af1), LL(0x73d173bfa2e6cc73), LL(0x124812905a248212), + LL(0x401d403a5d807a40), LL(0x0820084028104808), LL(0xc32bc356e89b95c3), LL(0xec97ec337bc5dfec), + LL(0xdb4bdb9690ab4ddb), LL(0xa1bea1611f5fc0a1), LL(0x8d0e8d1c8307918d), LL(0x3df43df5c97ac83d), + LL(0x976697ccf1335b97), LL(0x0000000000000000), LL(0xcf1bcf36d483f9cf), LL(0x2bac2b4587566e2b), + LL(0x76c57697b3ece176), LL(0x82328264b019e682), LL(0xd67fd6fea9b128d6), LL(0x1b6c1bd87736c31b), + LL(0xb5eeb5c15b7774b5), LL(0xaf86af112943beaf), LL(0x6ab56a77dfd41d6a), LL(0x505d50ba0da0ea50), + LL(0x450945124c8a5745), LL(0xf3ebf3cb18fb38f3), LL(0x30c0309df060ad30), LL(0xef9bef2b74c3c4ef), + LL(0x3ffc3fe5c37eda3f), LL(0x554955921caac755), LL(0xa2b2a2791059dba2), LL(0xea8fea0365c9e9ea), + LL(0x6589650fecca6a65), LL(0xbad2bab9686903ba), LL(0x2fbc2f65935e4a2f), LL(0xc027c04ee79d8ec0), + LL(0xde5fdebe81a160de), LL(0x1c701ce06c38fc1c), LL(0xfdd3fdbb2ee746fd), LL(0x4d294d52649a1f4d), + LL(0x927292e4e0397692), LL(0x75c9758fbceafa75), LL(0x061806301e0c3606), LL(0x8a128a249809ae8a), + LL(0xb2f2b2f940794bb2), LL(0xe6bfe66359d185e6), LL(0x0e380e70361c7e0e), LL(0x1f7c1ff8633ee71f), + LL(0x62956237f7c45562), LL(0xd477d4eea3b53ad4), LL(0xa89aa829324d81a8), LL(0x966296c4f4315296), + LL(0xf9c3f99b3aef62f9), LL(0xc533c566f697a3c5), LL(0x25942535b14a1025), LL(0x597959f220b2ab59), + LL(0x842a8454ae15d084), LL(0x72d572b7a7e4c572), LL(0x39e439d5dd72ec39), LL(0x4c2d4c5a6198164c), + LL(0x5e655eca3bbc945e), LL(0x78fd78e785f09f78), LL(0x38e038ddd870e538), LL(0x8c0a8c148605988c), + LL(0xd163d1c6b2bf17d1), LL(0xa5aea5410b57e4a5), LL(0xe2afe2434dd9a1e2), LL(0x6199612ff8c24e61), + LL(0xb3f6b3f1457b42b3), LL(0x21842115a5423421), LL(0x9c4a9c94d625089c), LL(0x1e781ef0663cee1e), + LL(0x4311432252866143), LL(0xc73bc776fc93b1c7), LL(0xfcd7fcb32be54ffc), LL(0x0410042014082404), + LL(0x515951b208a2e351), LL(0x995e99bcc72f2599), LL(0x6da96d4fc4da226d), LL(0x0d340d68391a650d), + LL(0xfacffa8335e979fa), LL(0xdf5bdfb684a369df), LL(0x7ee57ed79bfca97e), LL(0x2490243db4481924), + LL(0x3bec3bc5d776fe3b), LL(0xab96ab313d4b9aab), LL(0xce1fce3ed181f0ce), LL(0x1144118855229911), + LL(0x8f068f0c8903838f), LL(0x4e254e4a6b9c044e), LL(0xb7e6b7d1517366b7), LL(0xeb8beb0b60cbe0eb), + LL(0x3cf03cfdcc78c13c), LL(0x813e817cbf1ffd81), LL(0x946a94d4fe354094), LL(0xf7fbf7eb0cf31cf7), + LL(0xb9deb9a1676f18b9), LL(0x134c13985f268b13), LL(0x2cb02c7d9c58512c), LL(0xd36bd3d6b8bb05d3), + LL(0xe7bbe76b5cd38ce7), LL(0x6ea56e57cbdc396e), LL(0xc437c46ef395aac4), LL(0x030c03180f061b03), + LL(0x5645568a13acdc56), LL(0x440d441a49885e44), LL(0x7fe17fdf9efea07f), LL(0xa99ea921374f88a9), + LL(0x2aa82a4d8254672a), LL(0xbbd6bbb16d6b0abb), LL(0xc123c146e29f87c1), LL(0x535153a202a6f153), + LL(0xdc57dcae8ba572dc), LL(0x0b2c0b582716530b), LL(0x9d4e9d9cd327019d), LL(0x6cad6c47c1d82b6c), + LL(0x31c43195f562a431), LL(0x74cd7487b9e8f374), LL(0xf6fff6e309f115f6), LL(0x4605460a438c4c46), + LL(0xac8aac092645a5ac), LL(0x891e893c970fb589), LL(0x145014a04428b414), LL(0xe1a3e15b42dfbae1), + LL(0x165816b04e2ca616), LL(0x3ae83acdd274f73a), LL(0x69b9696fd0d20669), LL(0x092409482d124109), + LL(0x70dd70a7ade0d770), LL(0xb6e2b6d954716fb6), LL(0xd067d0ceb7bd1ed0), LL(0xed93ed3b7ec7d6ed), + LL(0xcc17cc2edb85e2cc), LL(0x4215422a57846842), LL(0x985a98b4c22d2c98), LL(0xa4aaa4490e55eda4), + LL(0x28a0285d88507528), LL(0x5c6d5cda31b8865c), LL(0xf8c7f8933fed6bf8), LL(0x86228644a411c286), +}; + +static const u64 rc[R + 1] = { + LL(0x0000000000000000), + LL(0x1823c6e887b8014f), + LL(0x36a6d2f5796f9152), + LL(0x60bc9b8ea30c7b35), + LL(0x1de0d7c22e4bfe57), + LL(0x157737e59ff04ada), + LL(0x58c9290ab1a06b85), + LL(0xbd5d10f4cb3e0567), + LL(0xe427418ba77d95d8), + LL(0xfbee7c66dd17479e), + LL(0xca2dbf07ad5a8333), +}; + +/** + * The core Whirlpool transform. + */ +static void processBuffer(struct NESSIEstruct * const structpointer) { + int i, r; + u64 K[8]; /* the round key */ + u64 block[8]; /* mu(buffer) */ + u64 state[8]; /* the cipher state */ + u64 L[8]; + u8 *buffer = structpointer->buffer; + /* + * map the buffer to a block: + */ + for (i = 0; i < 8; i++, buffer += 8) { + block[i] = + (((u64)buffer[0] ) << 56) ^ + (((u64)buffer[1] & 0xffL) << 48) ^ + (((u64)buffer[2] & 0xffL) << 40) ^ + (((u64)buffer[3] & 0xffL) << 32) ^ + (((u64)buffer[4] & 0xffL) << 24) ^ + (((u64)buffer[5] & 0xffL) << 16) ^ + (((u64)buffer[6] & 0xffL) << 8) ^ + (((u64)buffer[7] & 0xffL) ); + } + /* + * compute and apply K^0 to the cipher state: + */ + state[0] = block[0] ^ (K[0] = structpointer->hash[0]); + state[1] = block[1] ^ (K[1] = structpointer->hash[1]); + state[2] = block[2] ^ (K[2] = structpointer->hash[2]); + state[3] = block[3] ^ (K[3] = structpointer->hash[3]); + state[4] = block[4] ^ (K[4] = structpointer->hash[4]); + state[5] = block[5] ^ (K[5] = structpointer->hash[5]); + state[6] = block[6] ^ (K[6] = structpointer->hash[6]); + state[7] = block[7] ^ (K[7] = structpointer->hash[7]); + /* + * iterate over all rounds: + */ + for (r = 1; r <= R; r++) { + /* + * compute K^r from K^{r-1}: + */ + L[0] = + C0[(int)(K[0] >> 56) ] ^ + C1[(int)(K[7] >> 48) & 0xff] ^ + C2[(int)(K[6] >> 40) & 0xff] ^ + C3[(int)(K[5] >> 32) & 0xff] ^ + C4[(int)(K[4] >> 24) & 0xff] ^ + C5[(int)(K[3] >> 16) & 0xff] ^ + C6[(int)(K[2] >> 8) & 0xff] ^ + C7[(int)(K[1] ) & 0xff] ^ + rc[r]; + L[1] = + C0[(int)(K[1] >> 56) ] ^ + C1[(int)(K[0] >> 48) & 0xff] ^ + C2[(int)(K[7] >> 40) & 0xff] ^ + C3[(int)(K[6] >> 32) & 0xff] ^ + C4[(int)(K[5] >> 24) & 0xff] ^ + C5[(int)(K[4] >> 16) & 0xff] ^ + C6[(int)(K[3] >> 8) & 0xff] ^ + C7[(int)(K[2] ) & 0xff]; + L[2] = + C0[(int)(K[2] >> 56) ] ^ + C1[(int)(K[1] >> 48) & 0xff] ^ + C2[(int)(K[0] >> 40) & 0xff] ^ + C3[(int)(K[7] >> 32) & 0xff] ^ + C4[(int)(K[6] >> 24) & 0xff] ^ + C5[(int)(K[5] >> 16) & 0xff] ^ + C6[(int)(K[4] >> 8) & 0xff] ^ + C7[(int)(K[3] ) & 0xff]; + L[3] = + C0[(int)(K[3] >> 56) ] ^ + C1[(int)(K[2] >> 48) & 0xff] ^ + C2[(int)(K[1] >> 40) & 0xff] ^ + C3[(int)(K[0] >> 32) & 0xff] ^ + C4[(int)(K[7] >> 24) & 0xff] ^ + C5[(int)(K[6] >> 16) & 0xff] ^ + C6[(int)(K[5] >> 8) & 0xff] ^ + C7[(int)(K[4] ) & 0xff]; + L[4] = + C0[(int)(K[4] >> 56) ] ^ + C1[(int)(K[3] >> 48) & 0xff] ^ + C2[(int)(K[2] >> 40) & 0xff] ^ + C3[(int)(K[1] >> 32) & 0xff] ^ + C4[(int)(K[0] >> 24) & 0xff] ^ + C5[(int)(K[7] >> 16) & 0xff] ^ + C6[(int)(K[6] >> 8) & 0xff] ^ + C7[(int)(K[5] ) & 0xff]; + L[5] = + C0[(int)(K[5] >> 56) ] ^ + C1[(int)(K[4] >> 48) & 0xff] ^ + C2[(int)(K[3] >> 40) & 0xff] ^ + C3[(int)(K[2] >> 32) & 0xff] ^ + C4[(int)(K[1] >> 24) & 0xff] ^ + C5[(int)(K[0] >> 16) & 0xff] ^ + C6[(int)(K[7] >> 8) & 0xff] ^ + C7[(int)(K[6] ) & 0xff]; + L[6] = + C0[(int)(K[6] >> 56) ] ^ + C1[(int)(K[5] >> 48) & 0xff] ^ + C2[(int)(K[4] >> 40) & 0xff] ^ + C3[(int)(K[3] >> 32) & 0xff] ^ + C4[(int)(K[2] >> 24) & 0xff] ^ + C5[(int)(K[1] >> 16) & 0xff] ^ + C6[(int)(K[0] >> 8) & 0xff] ^ + C7[(int)(K[7] ) & 0xff]; + L[7] = + C0[(int)(K[7] >> 56) ] ^ + C1[(int)(K[6] >> 48) & 0xff] ^ + C2[(int)(K[5] >> 40) & 0xff] ^ + C3[(int)(K[4] >> 32) & 0xff] ^ + C4[(int)(K[3] >> 24) & 0xff] ^ + C5[(int)(K[2] >> 16) & 0xff] ^ + C6[(int)(K[1] >> 8) & 0xff] ^ + C7[(int)(K[0] ) & 0xff]; + K[0] = L[0]; + K[1] = L[1]; + K[2] = L[2]; + K[3] = L[3]; + K[4] = L[4]; + K[5] = L[5]; + K[6] = L[6]; + K[7] = L[7]; + /* + * apply the r-th round transformation: + */ + L[0] = + C0[(int)(state[0] >> 56) ] ^ + C1[(int)(state[7] >> 48) & 0xff] ^ + C2[(int)(state[6] >> 40) & 0xff] ^ + C3[(int)(state[5] >> 32) & 0xff] ^ + C4[(int)(state[4] >> 24) & 0xff] ^ + C5[(int)(state[3] >> 16) & 0xff] ^ + C6[(int)(state[2] >> 8) & 0xff] ^ + C7[(int)(state[1] ) & 0xff] ^ + K[0]; + L[1] = + C0[(int)(state[1] >> 56) ] ^ + C1[(int)(state[0] >> 48) & 0xff] ^ + C2[(int)(state[7] >> 40) & 0xff] ^ + C3[(int)(state[6] >> 32) & 0xff] ^ + C4[(int)(state[5] >> 24) & 0xff] ^ + C5[(int)(state[4] >> 16) & 0xff] ^ + C6[(int)(state[3] >> 8) & 0xff] ^ + C7[(int)(state[2] ) & 0xff] ^ + K[1]; + L[2] = + C0[(int)(state[2] >> 56) ] ^ + C1[(int)(state[1] >> 48) & 0xff] ^ + C2[(int)(state[0] >> 40) & 0xff] ^ + C3[(int)(state[7] >> 32) & 0xff] ^ + C4[(int)(state[6] >> 24) & 0xff] ^ + C5[(int)(state[5] >> 16) & 0xff] ^ + C6[(int)(state[4] >> 8) & 0xff] ^ + C7[(int)(state[3] ) & 0xff] ^ + K[2]; + L[3] = + C0[(int)(state[3] >> 56) ] ^ + C1[(int)(state[2] >> 48) & 0xff] ^ + C2[(int)(state[1] >> 40) & 0xff] ^ + C3[(int)(state[0] >> 32) & 0xff] ^ + C4[(int)(state[7] >> 24) & 0xff] ^ + C5[(int)(state[6] >> 16) & 0xff] ^ + C6[(int)(state[5] >> 8) & 0xff] ^ + C7[(int)(state[4] ) & 0xff] ^ + K[3]; + L[4] = + C0[(int)(state[4] >> 56) ] ^ + C1[(int)(state[3] >> 48) & 0xff] ^ + C2[(int)(state[2] >> 40) & 0xff] ^ + C3[(int)(state[1] >> 32) & 0xff] ^ + C4[(int)(state[0] >> 24) & 0xff] ^ + C5[(int)(state[7] >> 16) & 0xff] ^ + C6[(int)(state[6] >> 8) & 0xff] ^ + C7[(int)(state[5] ) & 0xff] ^ + K[4]; + L[5] = + C0[(int)(state[5] >> 56) ] ^ + C1[(int)(state[4] >> 48) & 0xff] ^ + C2[(int)(state[3] >> 40) & 0xff] ^ + C3[(int)(state[2] >> 32) & 0xff] ^ + C4[(int)(state[1] >> 24) & 0xff] ^ + C5[(int)(state[0] >> 16) & 0xff] ^ + C6[(int)(state[7] >> 8) & 0xff] ^ + C7[(int)(state[6] ) & 0xff] ^ + K[5]; + L[6] = + C0[(int)(state[6] >> 56) ] ^ + C1[(int)(state[5] >> 48) & 0xff] ^ + C2[(int)(state[4] >> 40) & 0xff] ^ + C3[(int)(state[3] >> 32) & 0xff] ^ + C4[(int)(state[2] >> 24) & 0xff] ^ + C5[(int)(state[1] >> 16) & 0xff] ^ + C6[(int)(state[0] >> 8) & 0xff] ^ + C7[(int)(state[7] ) & 0xff] ^ + K[6]; + L[7] = + C0[(int)(state[7] >> 56) ] ^ + C1[(int)(state[6] >> 48) & 0xff] ^ + C2[(int)(state[5] >> 40) & 0xff] ^ + C3[(int)(state[4] >> 32) & 0xff] ^ + C4[(int)(state[3] >> 24) & 0xff] ^ + C5[(int)(state[2] >> 16) & 0xff] ^ + C6[(int)(state[1] >> 8) & 0xff] ^ + C7[(int)(state[0] ) & 0xff] ^ + K[7]; + state[0] = L[0]; + state[1] = L[1]; + state[2] = L[2]; + state[3] = L[3]; + state[4] = L[4]; + state[5] = L[5]; + state[6] = L[6]; + state[7] = L[7]; + } + /* + * apply the Miyaguchi-Preneel compression function: + */ + structpointer->hash[0] ^= state[0] ^ block[0]; + structpointer->hash[1] ^= state[1] ^ block[1]; + structpointer->hash[2] ^= state[2] ^ block[2]; + structpointer->hash[3] ^= state[3] ^ block[3]; + structpointer->hash[4] ^= state[4] ^ block[4]; + structpointer->hash[5] ^= state[5] ^ block[5]; + structpointer->hash[6] ^= state[6] ^ block[6]; + structpointer->hash[7] ^= state[7] ^ block[7]; +} + +/** + * Initialize the hashing state. + */ +void WHIRLPOOL_init(struct NESSIEstruct * const structpointer) { + int i; + + memset(structpointer->bitLength, 0, 32); + structpointer->bufferBits = structpointer->bufferPos = 0; + structpointer->buffer[0] = 0; /* it's only necessary to cleanup buffer[bufferPos] */ + for (i = 0; i < 8; i++) { + structpointer->hash[i] = 0L; /* initial value */ + } +} + +/** + * Delivers input data to the hashing algorithm. + * + * @param source plaintext data to hash. + * @param sourceBits how many bits of plaintext to process. + * + * This method maintains the invariant: bufferBits < DIGESTBITS + */ +void WHIRLPOOL_add(const unsigned char * const source, + unsigned __int32 sourceBits, + struct NESSIEstruct * const structpointer) { + /* + sourcePos + | + +-------+-------+------- + ||||||||||||||||||||| source + +-------+-------+------- + +-------+-------+-------+-------+-------+------- + |||||||||||||||||||||| buffer + +-------+-------+-------+-------+-------+------- + | + bufferPos + */ + int sourcePos = 0; /* index of leftmost source u8 containing data (1 to 8 bits). */ + int sourceGap = (8 - ((int)sourceBits & 7)) & 7; /* space on source[sourcePos]. */ + int bufferRem = structpointer->bufferBits & 7; /* occupied bits on buffer[bufferPos]. */ + int i; + u32 b, carry; + u8 *buffer = structpointer->buffer; + u8 *bitLength = structpointer->bitLength; + int bufferBits = structpointer->bufferBits; + int bufferPos = structpointer->bufferPos; + + /* + * tally the length of the added data: + */ + u64 value = sourceBits; + for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != LL(0)); i--) { + carry += bitLength[i] + ((u32)value & 0xff); + bitLength[i] = (u8)carry; + carry >>= 8; + value >>= 8; + } + /* + * process data in chunks of 8 bits (a more efficient approach would be to take whole-word chunks): + */ + while (sourceBits > 8) { + /* N.B. at least source[sourcePos] and source[sourcePos+1] contain data. */ + /* + * take a byte from the source: + */ + b = ((source[sourcePos] << sourceGap) & 0xff) | + ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); + /* + * process this byte: + */ + buffer[bufferPos++] |= (u8)(b >> bufferRem); + bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ + if (bufferBits == DIGESTBITS) { + /* + * process data block: + */ + processBuffer(structpointer); + /* + * reset buffer: + */ + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = (u8) (b << (8 - bufferRem)); + bufferBits += bufferRem; + /* + * proceed to remaining data: + */ + sourceBits -= 8; + sourcePos++; + } + /* now 0 <= sourceBits <= 8; + * furthermore, all data (if any is left) is in source[sourcePos]. + */ + if (sourceBits > 0) { + b = (source[sourcePos] << sourceGap) & 0xff; /* bits are left-justified on b. */ + /* + * process the remaining bits: + */ + buffer[bufferPos] |= b >> bufferRem; + } else { + b = 0; + } + if (bufferRem + sourceBits < 8) { + /* + * all remaining data fits on buffer[bufferPos], + * and there still remains some space. + */ + bufferBits += sourceBits; + } else { + /* + * buffer[bufferPos] is full: + */ + bufferPos++; + bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ + sourceBits -= 8 - bufferRem; + /* now 0 <= sourceBits < 8; + * furthermore, all data (if any is left) is in source[sourcePos]. + */ + if (bufferBits == DIGESTBITS) { + /* + * process data block: + */ + processBuffer(structpointer); + /* + * reset buffer: + */ + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = (u8) (b << (8 - bufferRem)); + bufferBits += (int)sourceBits; + } + structpointer->bufferBits = bufferBits; + structpointer->bufferPos = bufferPos; +} + +/** + * Get the hash value from the hashing state. + * + * This method uses the invariant: bufferBits < DIGESTBITS + */ +void WHIRLPOOL_finalize(struct NESSIEstruct * const structpointer, + unsigned char * const result) { + int i; + u8 *buffer = structpointer->buffer; + u8 *bitLength = structpointer->bitLength; + int bufferBits = structpointer->bufferBits; + int bufferPos = structpointer->bufferPos; + u8 *digest = result; + + /* + * append a '1'-bit: + */ + buffer[bufferPos] |= 0x80U >> (bufferBits & 7); + bufferPos++; /* all remaining bits on the current u8 are set to zero. */ + /* + * pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits: + */ + if (bufferPos > WBLOCKBYTES - LENGTHBYTES) { + if (bufferPos < WBLOCKBYTES) { + memset(&buffer[bufferPos], 0, WBLOCKBYTES - bufferPos); + } + /* + * process data block: + */ + processBuffer(structpointer); + /* + * reset buffer: + */ + bufferPos = 0; + } + if (bufferPos < WBLOCKBYTES - LENGTHBYTES) { + memset(&buffer[bufferPos], 0, (WBLOCKBYTES - LENGTHBYTES) - bufferPos); + } + bufferPos = WBLOCKBYTES - LENGTHBYTES; + /* + * append bit length of hashed data: + */ + memcpy(&buffer[WBLOCKBYTES - LENGTHBYTES], bitLength, LENGTHBYTES); + /* + * process data block: + */ + processBuffer(structpointer); + /* + * return the completed message digest: + */ + for (i = 0; i < DIGESTBYTES/8; i++) { + digest[0] = (u8)(structpointer->hash[i] >> 56); + digest[1] = (u8)(structpointer->hash[i] >> 48); + digest[2] = (u8)(structpointer->hash[i] >> 40); + digest[3] = (u8)(structpointer->hash[i] >> 32); + digest[4] = (u8)(structpointer->hash[i] >> 24); + digest[5] = (u8)(structpointer->hash[i] >> 16); + digest[6] = (u8)(structpointer->hash[i] >> 8); + digest[7] = (u8)(structpointer->hash[i] ); + digest += 8; + } + structpointer->bufferBits = bufferBits; + structpointer->bufferPos = bufferPos; +} diff --git a/Crypto/Whirlpool.h b/Crypto/Whirlpool.h index ed0f642..be04c05 100644 --- a/Crypto/Whirlpool.h +++ b/Crypto/Whirlpool.h @@ -1,151 +1,151 @@ -#ifndef WHIRLPOOL_H -#define WHIRLPOOL_H 1 - -#include "Common/Tcdefs.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#ifndef PORTABLE_C__ -#define PORTABLE_C__ - -#include - -/* Definition of minimum-width integer types - * - * u8 -> unsigned integer type, at least 8 bits, equivalent to unsigned char - * u16 -> unsigned integer type, at least 16 bits - * u32 -> unsigned integer type, at least 32 bits - * - * s8, s16, s32 -> signed counterparts of u8, u16, u32 - * - * Always use macro's T8(), T16() or T32() to obtain exact-width results, - * i.e., to specify the size of the result of each expression. - */ - -typedef signed char s8; -typedef unsigned char u8; - -#if UINT_MAX >= 4294967295UL - -typedef signed short s16; -typedef signed int s32; -typedef unsigned short u16; -typedef unsigned int u32; - -#define ONE32 0xffffffffU - -#else - -typedef signed int s16; -typedef signed long s32; -typedef unsigned int u16; -typedef unsigned __int32 u32; - -#define ONE32 0xffffffffUL - -#endif - -#define ONE8 0xffU -#define ONE16 0xffffU - -#define T8(x) ((x) & ONE8) -#define T16(x) ((x) & ONE16) -#define T32(x) ((x) & ONE32) - -#ifdef _MSC_VER -typedef unsigned __int64 u64; -typedef signed __int64 s64; -#define LL(v) (v##i64) -#define ONE64 LL(0xffffffffffffffff) -#else /* !_MSC_VER */ -typedef unsigned long long u64; -typedef signed long long s64; -#define LL(v) (v##ULL) -#define ONE64 LL(0xffffffffffffffff) -#endif /* ?_MSC_VER */ -#define T64(x) ((x) & ONE64) -#define ROTR64(v, n) (((v) >> (n)) | T64((v) << (64 - (n)))) -/* - * Note: the test is used to detect native 64-bit architectures; - * if the unsigned long is strictly greater than 32-bit, it is - * assumed to be at least 64-bit. This will not work correctly - * on (old) 36-bit architectures (PDP-11 for instance). - * - * On non-64-bit architectures, "long long" is used. - */ - -/* - * U8TO32_BIG(c) returns the 32-bit value stored in big-endian convention - * in the unsigned char array pointed to by c. - */ -#define U8TO32_BIG(c) (((u32)T8(*(c)) << 24) | ((u32)T8(*((c) + 1)) << 16) | ((u32)T8(*((c) + 2)) << 8) | ((u32)T8(*((c) + 3)))) - -/* - * U8TO32_LITTLE(c) returns the 32-bit value stored in little-endian convention - * in the unsigned char array pointed to by c. - */ -#define U8TO32_LITTLE(c) (((u32)T8(*(c))) | ((u32)T8(*((c) + 1)) << 8) | (u32)T8(*((c) + 2)) << 16) | ((u32)T8(*((c) + 3)) << 24)) - -/* - * U8TO32_BIG(c, v) stores the 32-bit-value v in big-endian convention - * into the unsigned char array pointed to by c. - */ -#define U32TO8_BIG(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x >> 24); d[1] = T8(x >> 16); d[2] = T8(x >> 8); d[3] = T8(x); } while (0) - -/* - * U8TO32_LITTLE(c, v) stores the 32-bit-value v in little-endian convention - * into the unsigned char array pointed to by c. - */ -#define U32TO8_LITTLE(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x); d[1] = T8(x >> 8); d[2] = T8(x >> 16); d[3] = T8(x >> 24); } while (0) - -/* - * ROTL32(v, n) returns the value of the 32-bit unsigned value v after - * a rotation of n bits to the left. It might be replaced by the appropriate - * architecture-specific macro. - * - * It evaluates v and n twice. - * - * The compiler might emit a warning if n is the constant 0. The result - * is undefined if n is greater than 31. - */ -#define ROTL32(v, n) (T32((v) << (n)) | ((v) >> (32 - (n)))) - -/* - * Whirlpool-specific definitions. - */ - -#define DIGESTBYTES 64 -#define DIGESTBITS (8*DIGESTBYTES) /* 512 */ - -#define WBLOCKBYTES 64 -#define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */ - -#define LENGTHBYTES 32 -#define LENGTHBITS (8*LENGTHBYTES) /* 256 */ - -typedef struct NESSIEstruct { - u8 bitLength[LENGTHBYTES]; /* global number of hashed bits (256-bit counter) */ - u8 buffer[WBLOCKBYTES]; /* buffer of data to hash */ - int bufferBits; /* current number of bits on the buffer */ - int bufferPos; /* current (possibly incomplete) byte slot on the buffer */ - u64 hash[DIGESTBYTES/8]; /* the hashing state */ -} NESSIEstruct; - -#endif /* PORTABLE_C__ */ - -// ------------- - -typedef NESSIEstruct WHIRLPOOL_CTX; - -void WHIRLPOOL_add(const unsigned char * const source, unsigned __int32 sourceBits, struct NESSIEstruct * const structpointer); -void WHIRLPOOL_finalize(struct NESSIEstruct * const structpointer, unsigned char * const result); -void WHIRLPOOL_init(struct NESSIEstruct * const structpointer); - -#if defined(__cplusplus) -} -#endif - -#endif /* WHIRLPOOL_H */ +#ifndef WHIRLPOOL_H +#define WHIRLPOOL_H 1 + +#include "Common/Tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifndef PORTABLE_C__ +#define PORTABLE_C__ + +#include + +/* Definition of minimum-width integer types + * + * u8 -> unsigned integer type, at least 8 bits, equivalent to unsigned char + * u16 -> unsigned integer type, at least 16 bits + * u32 -> unsigned integer type, at least 32 bits + * + * s8, s16, s32 -> signed counterparts of u8, u16, u32 + * + * Always use macro's T8(), T16() or T32() to obtain exact-width results, + * i.e., to specify the size of the result of each expression. + */ + +typedef signed char s8; +typedef unsigned char u8; + +#if UINT_MAX >= 4294967295UL + +typedef signed short s16; +typedef signed int s32; +typedef unsigned short u16; +typedef unsigned int u32; + +#define ONE32 0xffffffffU + +#else + +typedef signed int s16; +typedef signed long s32; +typedef unsigned int u16; +typedef unsigned __int32 u32; + +#define ONE32 0xffffffffUL + +#endif + +#define ONE8 0xffU +#define ONE16 0xffffU + +#define T8(x) ((x) & ONE8) +#define T16(x) ((x) & ONE16) +#define T32(x) ((x) & ONE32) + +#ifdef _MSC_VER +typedef unsigned __int64 u64; +typedef signed __int64 s64; +#define LL(v) (v##ui64) +#define ONE64 LL(0xffffffffffffffff) +#else /* !_MSC_VER */ +typedef unsigned long long u64; +typedef signed long long s64; +#define LL(v) (v##ULL) +#define ONE64 LL(0xffffffffffffffff) +#endif /* ?_MSC_VER */ +#define T64(x) ((x) & ONE64) +#define ROTR64(v, n) (((v) >> (n)) | T64((v) << (64 - (n)))) +/* + * Note: the test is used to detect native 64-bit architectures; + * if the unsigned long is strictly greater than 32-bit, it is + * assumed to be at least 64-bit. This will not work correctly + * on (old) 36-bit architectures (PDP-11 for instance). + * + * On non-64-bit architectures, "long long" is used. + */ + +/* + * U8TO32_BIG(c) returns the 32-bit value stored in big-endian convention + * in the unsigned char array pointed to by c. + */ +#define U8TO32_BIG(c) (((u32)T8(*(c)) << 24) | ((u32)T8(*((c) + 1)) << 16) | ((u32)T8(*((c) + 2)) << 8) | ((u32)T8(*((c) + 3)))) + +/* + * U8TO32_LITTLE(c) returns the 32-bit value stored in little-endian convention + * in the unsigned char array pointed to by c. + */ +#define U8TO32_LITTLE(c) (((u32)T8(*(c))) | ((u32)T8(*((c) + 1)) << 8) | (u32)T8(*((c) + 2)) << 16) | ((u32)T8(*((c) + 3)) << 24)) + +/* + * U8TO32_BIG(c, v) stores the 32-bit-value v in big-endian convention + * into the unsigned char array pointed to by c. + */ +#define U32TO8_BIG(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x >> 24); d[1] = T8(x >> 16); d[2] = T8(x >> 8); d[3] = T8(x); } while (0) + +/* + * U8TO32_LITTLE(c, v) stores the 32-bit-value v in little-endian convention + * into the unsigned char array pointed to by c. + */ +#define U32TO8_LITTLE(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x); d[1] = T8(x >> 8); d[2] = T8(x >> 16); d[3] = T8(x >> 24); } while (0) + +/* + * ROTL32(v, n) returns the value of the 32-bit unsigned value v after + * a rotation of n bits to the left. It might be replaced by the appropriate + * architecture-specific macro. + * + * It evaluates v and n twice. + * + * The compiler might emit a warning if n is the constant 0. The result + * is undefined if n is greater than 31. + */ +#define ROTL32(v, n) (T32((v) << (n)) | ((v) >> (32 - (n)))) + +/* + * Whirlpool-specific definitions. + */ + +#define DIGESTBYTES 64 +#define DIGESTBITS (8*DIGESTBYTES) /* 512 */ + +#define WBLOCKBYTES 64 +#define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */ + +#define LENGTHBYTES 32 +#define LENGTHBITS (8*LENGTHBYTES) /* 256 */ + +typedef struct NESSIEstruct { + u8 bitLength[LENGTHBYTES]; /* global number of hashed bits (256-bit counter) */ + u8 buffer[WBLOCKBYTES]; /* buffer of data to hash */ + int bufferBits; /* current number of bits on the buffer */ + int bufferPos; /* current (possibly incomplete) byte slot on the buffer */ + u64 hash[DIGESTBYTES/8]; /* the hashing state */ +} NESSIEstruct; + +#endif /* PORTABLE_C__ */ + +// ------------- + +typedef NESSIEstruct WHIRLPOOL_CTX; + +void WHIRLPOOL_add(const unsigned char * const source, unsigned __int32 sourceBits, struct NESSIEstruct * const structpointer); +void WHIRLPOOL_finalize(struct NESSIEstruct * const structpointer, unsigned char * const result); +void WHIRLPOOL_init(struct NESSIEstruct * const structpointer); + +#if defined(__cplusplus) +} +#endif + +#endif /* WHIRLPOOL_H */ diff --git a/Driver/BuildDriver.cmd b/Driver/BuildDriver.cmd index 7f65a85..f34a0bb 100644 --- a/Driver/BuildDriver.cmd +++ b/Driver/BuildDriver.cmd @@ -1,7 +1,7 @@ :: :: Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. :: -:: Governed by the TrueCrypt License 2.7 the full text of which is contained +:: Governed by the TrueCrypt License 2.8 the full text of which is contained :: in the file License.txt included in TrueCrypt binary and source code :: distribution packages. :: @@ -19,7 +19,7 @@ shift :: Windows Driver Kit build number -set TC_WINDDK_BUILD=6001.18002 +set TC_WINDDK_BUILD=7600.16385.0 :: Check for spaces in the current directory path @@ -36,9 +36,10 @@ if %ERRORLEVEL% == 0 ( set TC_C_DEFINES=-D_WIN32 -DNT4_DRIVER set TC_C_FLAGS=-nologo -I.. +set TC_C_WARNING_LEVEL=-W4 +set TC_C_DISABLED_WARNINGS=-wd4057 -wd4100 -wd4127 -wd4152 -wd4201 -wd4701 -wd4702 -wd4706 set TC_LIBRARIAN_FLAGS=-nologo set TC_LINKER_FLAGS=-nologo -set NO_SAFESEH=1 :: Windows Driver Kit root @@ -65,6 +66,7 @@ if "%TC_ARG_ARCH%"=="-x64" ( set TC_BUILD_ARCH_DIR=amd64 set TC_ARCH=x64 set TC_ARCH_SUFFIX=-x64 + set TC_C_DISABLED_WARNINGS=%TC_C_DISABLED_WARNINGS% -wd4328 -wd4366 ) else ( set TC_BUILD_ARCH=WXP set TC_BUILD_ARCH_DIR=i386 @@ -83,7 +85,6 @@ if "%TC_ARG_TYPE%"=="-debug" ( ) else ( set TC_BUILD_TYPE=fre set TC_BUILD_ALT_DIR=_driver_release - set TC_C_FLAGS=%TC_C_FLAGS% -w34189 set TC_COPY_DIR="..\Release" ) @@ -91,7 +92,7 @@ if "%TC_ARG_TYPE%"=="-debug" ( :: WDK environment pushd . -call %TC_WINDDK_ROOT%\bin\setenv %TC_WINDDK_ROOT% %TC_BUILD_TYPE% %TC_BUILD_ARCH% || exit /B %errorlevel% +call %TC_WINDDK_ROOT%\bin\setenv %TC_WINDDK_ROOT% %TC_BUILD_TYPE% %TC_BUILD_ARCH% no_oacr || exit /B %errorlevel% popd @@ -110,7 +111,8 @@ pushd . rd /q obj%TC_BUILD_ALT_DIR% 2>NUL: ) else ( - set USER_C_FLAGS=%TC_C_FLAGS% -FAcs -Fa%~1\obj%TC_BUILD_ALT_DIR%\%TC_BUILD_ARCH_DIR%\ + set USER_C_FLAGS=%TC_C_FLAGS% %TC_C_DISABLED_WARNINGS% -FAcs -Fa%~1\obj%TC_BUILD_ALT_DIR%\%TC_BUILD_ARCH_DIR%\ + set MSC_WARNING_LEVEL=%TC_C_WARNING_LEVEL% set C_DEFINES=%TC_C_DEFINES% set RCOPTIONS=/I %MFC_INC_PATH% set LIBRARIAN_FLAGS=%TC_LIBRARIAN_FLAGS% diff --git a/Driver/DriveFilter.c b/Driver/DriveFilter.c index 4f548ac..a398b71 100644 --- a/Driver/DriveFilter.c +++ b/Driver/DriveFilter.c @@ -1,1855 +1,1891 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "TCdefs.h" -#include -#include -#include "Cache.h" -#include "Crc.h" -#include "Crypto.h" -#include "Apidrvr.h" -#include "EncryptedIoQueue.h" -#include "Common/Endian.h" -#include "Ntdriver.h" -#include "Ntvol.h" -#include "Volumes.h" -#include "VolumeFilter.h" -#include "Wipe.h" -#include "DriveFilter.h" -#include "Boot/Windows/BootCommon.h" - -static BOOL DeviceFilterActive = FALSE; - -BOOL BootArgsValid = FALSE; -BootArguments BootArgs; -static uint16 BootLoaderSegment; - -static BOOL BootDriveFound = FALSE; -static DriveFilterExtension *BootDriveFilterExtension = NULL; -static LARGE_INTEGER BootDriveLength; - -static BOOL HibernationDriverFilterActive = FALSE; -static byte *HibernationWriteBuffer = NULL; -static MDL *HibernationWriteBufferMdl = NULL; -static uint32 HibernationPreventionCount = 0; - -static BootEncryptionSetupRequest SetupRequest; -static volatile BOOL SetupInProgress = FALSE; -static PKTHREAD EncryptionSetupThread; -static volatile BOOL EncryptionSetupThreadAbortRequested; -static KSPIN_LOCK SetupStatusSpinLock; -static int64 SetupStatusEncryptedAreaEnd; -static BOOL TransformWaitingForIdle; -static NTSTATUS SetupResult; - -static WipeDecoySystemRequest WipeDecoyRequest; -static volatile BOOL DecoySystemWipeInProgress = FALSE; -static volatile BOOL DecoySystemWipeThreadAbortRequested; -static KSPIN_LOCK DecoySystemWipeStatusSpinLock; -static int64 DecoySystemWipedAreaEnd; -static PKTHREAD DecoySystemWipeThread; -static NTSTATUS DecoySystemWipeResult; - - -NTSTATUS LoadBootArguments () -{ - NTSTATUS status = STATUS_UNSUCCESSFUL; - PHYSICAL_ADDRESS bootArgsAddr; - byte *mappedBootArgs; - uint16 bootLoaderSegment; - - for (bootLoaderSegment = TC_BOOT_LOADER_SEGMENT; - bootLoaderSegment >= TC_BOOT_LOADER_SEGMENT - 64 * 1024 / 16 && status != STATUS_SUCCESS; - bootLoaderSegment -= 32 * 1024 / 16) - { - bootArgsAddr.QuadPart = (bootLoaderSegment << 4) + TC_BOOT_LOADER_ARGS_OFFSET; - Dump ("Checking BootArguments at 0x%x\n", bootArgsAddr.LowPart); - - mappedBootArgs = MmMapIoSpace (bootArgsAddr, sizeof (BootArguments), MmCached); - if (!mappedBootArgs) - return STATUS_INSUFFICIENT_RESOURCES; - - if (TC_IS_BOOT_ARGUMENTS_SIGNATURE (mappedBootArgs)) - { - BootArguments *bootArguments = (BootArguments *) mappedBootArgs; - Dump ("BootArguments found at 0x%x\n", bootArgsAddr.LowPart); - - DumpMem (mappedBootArgs, sizeof (BootArguments)); - - if (bootArguments->BootLoaderVersion == VERSION_NUM - && bootArguments->BootArgumentsCrc32 != GetCrc32 ((byte *) bootArguments, (int) ((byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments))) - { - Dump ("BootArguments CRC incorrect\n"); - TC_BUG_CHECK (STATUS_CRC_ERROR); - } - - BootLoaderSegment = bootLoaderSegment; - - BootArgs = *bootArguments; - BootArgsValid = TRUE; - memset (bootArguments, 0, sizeof (*bootArguments)); - - if (BootArgs.BootLoaderVersion < 0x600) - { - BootArgs.HiddenSystemPartitionStart = 0; - BootArgs.DecoySystemPartitionStart = 0; - } - - Dump ("BootLoaderVersion = %x\n", (int) BootArgs.BootLoaderVersion); - Dump ("HeaderSaltCrc32 = %x\n", (int) BootArgs.HeaderSaltCrc32); - Dump ("CryptoInfoOffset = %x\n", (int) BootArgs.CryptoInfoOffset); - Dump ("CryptoInfoLength = %d\n", (int) BootArgs.CryptoInfoLength); - Dump ("HiddenSystemPartitionStart = %I64u\n", BootArgs.HiddenSystemPartitionStart); - Dump ("DecoySystemPartitionStart = %I64u\n", BootArgs.DecoySystemPartitionStart); - Dump ("BootArgumentsCrc32 = %x\n", BootArgs.BootArgumentsCrc32); - - if (CacheBootPassword && BootArgs.BootPassword.Length > 0) - AddPasswordToCache (&BootArgs.BootPassword); - - status = STATUS_SUCCESS; - } - - MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments)); - } - - return status; -} - - -NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) -{ - DriveFilterExtension *Extension; - NTSTATUS status; - PDEVICE_OBJECT filterDeviceObject = NULL; - PDEVICE_OBJECT attachedDeviceObject; - - Dump ("DriveFilterAddDevice pdo=%p\n", pdo); - - attachedDeviceObject = IoGetAttachedDeviceReference (pdo); - - DriverMutexWait(); - status = IoCreateDevice (driverObject, sizeof (DriveFilterExtension), NULL, attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject); - DriverMutexRelease(); - - ObDereferenceObject (attachedDeviceObject); - - if (!NT_SUCCESS (status)) - { - filterDeviceObject = NULL; - goto err; - } - - Extension = (DriveFilterExtension *) filterDeviceObject->DeviceExtension; - memset (Extension, 0, sizeof (DriveFilterExtension)); - - Extension->LowerDeviceObject = IoAttachDeviceToDeviceStack (filterDeviceObject, pdo); // IoAttachDeviceToDeviceStackSafe() is not required in AddDevice routine and is also unavailable on Windows 2000 SP4 - if (!Extension->LowerDeviceObject) - { - status = STATUS_DEVICE_REMOVED; - goto err; - } - - Extension->IsDriveFilterDevice = Extension->Queue.IsFilterDevice = TRUE; - Extension->DeviceObject = Extension->Queue.DeviceObject = filterDeviceObject; - Extension->Pdo = pdo; - - Extension->Queue.LowerDeviceObject = Extension->LowerDeviceObject; - IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0); - - Extension->ConfiguredEncryptedAreaStart = -1; - Extension->ConfiguredEncryptedAreaEnd = -1; - Extension->Queue.EncryptedAreaStart = -1; - Extension->Queue.EncryptedAreaEnd = -1; - - filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE); - filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - DeviceFilterActive = TRUE; - return status; - -err: - if (filterDeviceObject) - { - if (Extension->LowerDeviceObject) - IoDetachDevice (Extension->LowerDeviceObject); - - DriverMutexWait(); - IoDeleteDevice (filterDeviceObject); - DriverMutexRelease(); - } - - return status; -} - - -static void DismountDrive (DriveFilterExtension *Extension, BOOL stopIoQueue) -{ - Dump ("Dismounting drive\n"); - ASSERT (Extension->DriveMounted); - - if (stopIoQueue && EncryptedIoQueueIsRunning (&Extension->Queue)) - EncryptedIoQueueStop (&Extension->Queue); - - crypto_close (Extension->Queue.CryptoInfo); - Extension->Queue.CryptoInfo = NULL; - - crypto_close (Extension->HeaderCryptoInfo); - Extension->HeaderCryptoInfo = NULL; - - Extension->DriveMounted = FALSE; -} - - -static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, uint32 *headerSaltCrc32) -{ - BOOL hiddenVolume = (BootArgs.HiddenSystemPartitionStart != 0); - int64 hiddenHeaderOffset = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; - NTSTATUS status; - LARGE_INTEGER offset; - char *header; - - Dump ("MountDrive pdo=%p\n", Extension->Pdo); - ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); - - header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - if (!header) - return STATUS_INSUFFICIENT_RESOURCES; - - offset.QuadPart = hiddenVolume ? hiddenHeaderOffset : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; - Dump ("Reading volume header at %I64u\n", offset.QuadPart); - - status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - if (!NT_SUCCESS (status)) - { - Dump ("TCReadDevice error %x\n", status); - goto ret; - } - - if (headerSaltCrc32) - { - uint32 saltCrc = GetCrc32 (header, PKCS5_SALT_SIZE); - - if (saltCrc != *headerSaltCrc32) - { - status = STATUS_UNSUCCESSFUL; - goto ret; - } - - Extension->VolumeHeaderSaltCrc32 = saltCrc; - } - - Extension->HeaderCryptoInfo = crypto_open(); - if (!Extension->HeaderCryptoInfo) - { - status = STATUS_INSUFFICIENT_RESOURCES; - goto ret; - } - - if (ReadVolumeHeader (!hiddenVolume, header, password, &Extension->Queue.CryptoInfo, Extension->HeaderCryptoInfo) == 0) - { - // Header decrypted - status = STATUS_SUCCESS; - Dump ("Header decrypted\n"); - - if (Extension->Queue.CryptoInfo->hiddenVolume) - { - int64 hiddenPartitionOffset = BootArgs.HiddenSystemPartitionStart; - Dump ("Hidden volume start offset = %I64d\n", Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + hiddenPartitionOffset); - - Extension->HiddenSystem = TRUE; - - Extension->Queue.RemapEncryptedArea = TRUE; - Extension->Queue.RemappedAreaOffset = hiddenPartitionOffset + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value - BootArgs.DecoySystemPartitionStart; - Extension->Queue.RemappedAreaDataUnitOffset = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value / ENCRYPTION_DATA_UNIT_SIZE - BootArgs.DecoySystemPartitionStart / ENCRYPTION_DATA_UNIT_SIZE; - - Extension->Queue.CryptoInfo->EncryptedAreaStart.Value = BootArgs.DecoySystemPartitionStart; - - if (Extension->Queue.CryptoInfo->VolumeSize.Value > hiddenPartitionOffset - BootArgs.DecoySystemPartitionStart) - TC_THROW_FATAL_EXCEPTION; - - Dump ("RemappedAreaOffset = %I64d\n", Extension->Queue.RemappedAreaOffset); - Dump ("RemappedAreaDataUnitOffset = %I64d\n", Extension->Queue.RemappedAreaDataUnitOffset); - } - else - { - Extension->HiddenSystem = FALSE; - Extension->Queue.RemapEncryptedArea = FALSE; - } - - Extension->ConfiguredEncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value; - Extension->ConfiguredEncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->VolumeSize.Value - 1; - - Extension->Queue.EncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value; - Extension->Queue.EncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->EncryptedAreaLength.Value - 1; - - if (Extension->Queue.CryptoInfo->EncryptedAreaLength.Value == 0) - { - Extension->Queue.EncryptedAreaStart = -1; - Extension->Queue.EncryptedAreaEnd = -1; - } - - Dump ("Loaded: ConfiguredEncryptedAreaStart=%I64d (%I64d) ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd); - Dump ("Loaded: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd); - - // Erase boot loader scheduled keys - if (BootArgs.CryptoInfoLength > 0) - { - PHYSICAL_ADDRESS cryptoInfoAddress; - byte *mappedCryptoInfo; - - cryptoInfoAddress.QuadPart = (BootLoaderSegment << 4) + BootArgs.CryptoInfoOffset; - mappedCryptoInfo = MmMapIoSpace (cryptoInfoAddress, BootArgs.CryptoInfoLength, MmCached); - - if (mappedCryptoInfo) - { - Dump ("Wiping memory %x %d\n", cryptoInfoAddress.LowPart, BootArgs.CryptoInfoLength); - memset (mappedCryptoInfo, 0, BootArgs.CryptoInfoLength); - MmUnmapIoSpace (mappedCryptoInfo, BootArgs.CryptoInfoLength); - } - } - - BootDriveFilterExtension = Extension; - BootDriveFound = Extension->BootDrive = Extension->DriveMounted = Extension->VolumeHeaderPresent = TRUE; - - burn (&BootArgs.BootPassword, sizeof (BootArgs.BootPassword)); - - // Get drive length - status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &BootDriveLength, sizeof (BootDriveLength)); - - if (!NT_SUCCESS (status)) - { - Dump ("Failed to get drive length - error %x\n", status); - BootDriveLength.QuadPart = 0; - Extension->Queue.MaxReadAheadOffset.QuadPart = _I64_MAX; - } - else - Extension->Queue.MaxReadAheadOffset = BootDriveLength; - - status = EncryptedIoQueueStart (&Extension->Queue); - if (!NT_SUCCESS (status)) - TC_BUG_CHECK (status); - - if (!HibernationDriverFilterActive) - StartHibernationDriverFilter(); - } - else - { - Dump ("Header not decrypted\n"); - crypto_close (Extension->HeaderCryptoInfo); - Extension->HeaderCryptoInfo = NULL; - - status = STATUS_UNSUCCESSFUL; - } - -ret: - TCfree (header); - return status; -} - - -static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension) -{ - NTSTATUS status = STATUS_SUCCESS; - LARGE_INTEGER offset; - byte *header; - - header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - if (!header) - return STATUS_INSUFFICIENT_RESOURCES; - - offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; - - status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - if (!NT_SUCCESS (status)) - { - Dump ("TCReadDevice error %x", status); - goto ret; - } - - Dump ("Saving: ConfiguredEncryptedAreaStart=%I64d (%I64d) ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd); - Dump ("Saving: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd); - - if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1 - || Extension->Queue.EncryptedAreaEnd <= Extension->Queue.EncryptedAreaStart) - { - if (SetupRequest.SetupMode == SetupDecryption) - { - memset (header, 0, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - Extension->VolumeHeaderPresent = FALSE; - } - } - else - { - uint32 headerCrc32; - uint64 encryptedAreaLength = Extension->Queue.EncryptedAreaEnd + 1 - Extension->Queue.EncryptedAreaStart; - byte *fieldPos = header + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH; - - DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo); - - if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545) - { - Dump ("Header not decrypted"); - status = STATUS_UNSUCCESSFUL; - goto ret; - } - - mputInt64 (fieldPos, encryptedAreaLength); - - headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); - fieldPos = header + TC_HEADER_OFFSET_HEADER_CRC; - mputLong (fieldPos, headerCrc32); - - EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo); - } - - status = TCWriteDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - if (!NT_SUCCESS (status)) - { - Dump ("TCWriteDevice error %x", status); - goto ret; - } - -ret: - TCfree (header); - return status; -} - - -static NTSTATUS PassIrp (PDEVICE_OBJECT deviceObject, PIRP irp) -{ - IoSkipCurrentIrpStackLocation (irp); - return IoCallDriver (deviceObject, irp); -} - - -static NTSTATUS PassFilteredIrp (PDEVICE_OBJECT deviceObject, PIRP irp, PIO_COMPLETION_ROUTINE completionRoutine, PVOID completionRoutineArg) -{ - IoCopyCurrentIrpStackLocationToNext (irp); - - if (completionRoutine) - IoSetCompletionRoutine (irp, completionRoutine, completionRoutineArg, TRUE, TRUE, TRUE); - - return IoCallDriver (deviceObject, irp); -} - - -static NTSTATUS OnDeviceUsageNotificationCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, DriveFilterExtension *Extension) -{ - if (Irp->PendingReturned) - IoMarkIrpPending (Irp); - - if (!(Extension->LowerDeviceObject->Flags & DO_POWER_PAGABLE)) - filterDeviceObject->Flags &= ~DO_POWER_PAGABLE; - - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - return STATUS_CONTINUE_COMPLETION; -} - - -static BOOL IsVolumeDevice (PDEVICE_OBJECT deviceObject) -{ - VOLUME_NUMBER volNumber; - VOLUME_DISK_EXTENTS extents[2]; - NTSTATUS extentStatus = SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, extents, sizeof (extents)); - - return NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_SUPPORTS_ONLINE_OFFLINE, NULL, 0, NULL, 0)) - || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_OFFLINE, NULL, 0, NULL, 0)) - || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_IO_CAPABLE, NULL, 0, NULL, 0)) - || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_PARTITION, NULL, 0, NULL, 0)) - || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_QUERY_VOLUME_NUMBER, NULL, 0, &volNumber, sizeof (volNumber))) - || NT_SUCCESS (extentStatus) || extentStatus == STATUS_BUFFER_OVERFLOW || extentStatus == STATUS_BUFFER_TOO_SMALL; -} - - -static void CheckDeviceTypeAndMount (DriveFilterExtension *filterExtension) -{ - if (BootArgsValid) - { - // Windows sometimes merges a removable drive PDO and its volume PDO to a single PDO having no volume interface (GUID_DEVINTERFACE_VOLUME). - // Therefore, we need to test whether the device supports volume IOCTLs. - if (VolumeClassFilterRegistered - && BootArgs.HiddenSystemPartitionStart != 0 - && IsVolumeDevice (filterExtension->LowerDeviceObject)) - { - Dump ("Drive and volume merged pdo=%p", filterExtension->Pdo); - - filterExtension->IsVolumeFilterDevice = TRUE; - filterExtension->IsDriveFilterDevice = FALSE; - } - else if (!BootDriveFound) - { - MountDrive (filterExtension, &BootArgs.BootPassword, &BootArgs.HeaderSaltCrc32); - } - } -} - - -static VOID MountDriveWorkItemRoutine (PDEVICE_OBJECT deviceObject, DriveFilterExtension *filterExtension) -{ - CheckDeviceTypeAndMount (filterExtension); - KeSetEvent (&filterExtension->MountWorkItemCompletedEvent, IO_NO_INCREMENT, FALSE); -} - - -static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, DriveFilterExtension *Extension) -{ - if (Irp->PendingReturned) - IoMarkIrpPending (Irp); - - if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) - filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; - - if (KeGetCurrentIrql() == PASSIVE_LEVEL) - { - CheckDeviceTypeAndMount (Extension); - } - else - { - PIO_WORKITEM workItem = IoAllocateWorkItem (filterDeviceObject); - if (!workItem) - { - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - return STATUS_INSUFFICIENT_RESOURCES; - } - - KeInitializeEvent (&Extension->MountWorkItemCompletedEvent, SynchronizationEvent, FALSE); - IoQueueWorkItem (workItem, MountDriveWorkItemRoutine, DelayedWorkQueue, Extension); - - KeWaitForSingleObject (&Extension->MountWorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL); - IoFreeWorkItem (workItem); - } - - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - return STATUS_CONTINUE_COMPLETION; -} - - -static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp) -{ - NTSTATUS status; - - status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); - if (!NT_SUCCESS (status)) - return TCCompleteIrp (Irp, status, Irp->IoStatus.Information); - - switch (irpSp->MinorFunction) - { - case IRP_MN_START_DEVICE: - Dump ("IRP_MN_START_DEVICE pdo=%p\n", Extension->Pdo); - return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension); - - - case IRP_MN_DEVICE_USAGE_NOTIFICATION: - Dump ("IRP_MN_DEVICE_USAGE_NOTIFICATION type=%d\n", (int) irpSp->Parameters.UsageNotification.Type); - - { - PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject); - - if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE)) - DeviceObject->Flags |= DO_POWER_PAGABLE; - - ObDereferenceObject (attachedDevice); - } - - // Prevent creation of hibernation and crash dump files - if (irpSp->Parameters.UsageNotification.InPath - && (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile - || (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation && !HibernationDriverFilterActive))) - { - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - - if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) - ++HibernationPreventionCount; - - return TCCompleteIrp (Irp, STATUS_UNSUCCESSFUL, Irp->IoStatus.Information); - } - - return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension); - - - case IRP_MN_REMOVE_DEVICE: - Dump ("IRP_MN_REMOVE_DEVICE pdo=%p\n", Extension->Pdo); - - IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp); - status = PassIrp (Extension->LowerDeviceObject, Irp); - - IoDetachDevice (Extension->LowerDeviceObject); - - if (Extension->DriveMounted) - DismountDrive (Extension, TRUE); - - if (Extension->BootDrive) - { - BootDriveFound = FALSE; - BootDriveFilterExtension = NULL; - } - - DriverMutexWait(); - IoDeleteDevice (DeviceObject); - DriverMutexRelease(); - - return status; - - - default: - status = PassIrp (Extension->LowerDeviceObject, Irp); - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - } - return status; -} - - -static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp) -{ - NTSTATUS status; - Dump ("IRP_MJ_POWER minor=%d type=%d shutdown=%d\n", (int) irpSp->MinorFunction, (int) irpSp->Parameters.Power.Type, (int) irpSp->Parameters.Power.ShutdownType); - - if (SetupInProgress - && irpSp->MinorFunction == IRP_MN_SET_POWER - && irpSp->Parameters.Power.Type == DevicePowerState - && irpSp->Parameters.Power.ShutdownType == PowerActionHibernate) - { - EncryptionSetupThreadAbortRequested = TRUE; - ObDereferenceObject (EncryptionSetupThread); - - while (SetupInProgress) - TCSleep (200); - } - -#if 0 // Dismount of the system drive is disabled until there is a way to do it without causing system errors (see the documentation for more info) - if (DriverShuttingDown - && Extension->DriveMounted - && irpSp->MinorFunction == IRP_MN_SET_POWER - && irpSp->Parameters.Power.Type == DevicePowerState) - { - DismountDrive (Extension, TRUE); - } -#endif // 0 - - PoStartNextPowerIrp (Irp); - - status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); - if (!NT_SUCCESS (status)) - return TCCompleteIrp (Irp, status, Irp->IoStatus.Information); - - IoSkipCurrentIrpStackLocation (Irp); - status = PoCallDriver (Extension->LowerDeviceObject, Irp); - - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - return status; -} - - -NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - DriveFilterExtension *Extension = (DriveFilterExtension *) DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); - - ASSERT (!Extension->bRootDevice && Extension->IsDriveFilterDevice); - - switch (irpSp->MajorFunction) - { - case IRP_MJ_READ: - case IRP_MJ_WRITE: - if (!Extension->BootDrive) - { - return PassIrp (Extension->LowerDeviceObject, Irp); - } - else - { - NTSTATUS status = EncryptedIoQueueAddIrp (&Extension->Queue, Irp); - - if (status != STATUS_PENDING) - TCCompleteDiskIrp (Irp, status, 0); - - return status; - } - - case IRP_MJ_PNP: - return DispatchPnp (DeviceObject, Irp, Extension, irpSp); - - case IRP_MJ_POWER: - return DispatchPower (DeviceObject, Irp, Extension, irpSp); - - default: - return PassIrp (Extension->LowerDeviceObject, Irp); - } -} - - -void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp) -{ - LARGE_INTEGER offset; - char *header; - ReopenBootVolumeHeaderRequest *request = (ReopenBootVolumeHeaderRequest *) irp->AssociatedIrp.SystemBuffer; - - irp->IoStatus.Information = 0; - - if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice()) - { - irp->IoStatus.Status = STATUS_ACCESS_DENIED; - return; - } - - if (!ValidateIOBufferSize (irp, sizeof (ReopenBootVolumeHeaderRequest), ValidateInput)) - return; - - if (!BootDriveFound || !BootDriveFilterExtension || !BootDriveFilterExtension->DriveMounted || !BootDriveFilterExtension->HeaderCryptoInfo - || request->VolumePassword.Length > MAX_PASSWORD) - { - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto wipe; - } - - header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - if (!header) - { - irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - goto wipe; - } - - if (BootDriveFilterExtension->HiddenSystem) - offset.QuadPart = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; - else - offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; - - irp->IoStatus.Status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); - if (!NT_SUCCESS (irp->IoStatus.Status)) - { - Dump ("TCReadDevice error %x\n", irp->IoStatus.Status); - goto ret; - } - - if (ReadVolumeHeader (!BootDriveFilterExtension->HiddenSystem, header, &request->VolumePassword, NULL, BootDriveFilterExtension->HeaderCryptoInfo) == 0) - { - Dump ("Header reopened\n"); - - BootDriveFilterExtension->Queue.CryptoInfo->header_creation_time = BootDriveFilterExtension->HeaderCryptoInfo->header_creation_time; - BootDriveFilterExtension->Queue.CryptoInfo->pkcs5 = BootDriveFilterExtension->HeaderCryptoInfo->pkcs5; - BootDriveFilterExtension->Queue.CryptoInfo->noIterations = BootDriveFilterExtension->HeaderCryptoInfo->noIterations; - - irp->IoStatus.Status = STATUS_SUCCESS; - } - else - { - crypto_close (BootDriveFilterExtension->HeaderCryptoInfo); - BootDriveFilterExtension->HeaderCryptoInfo = NULL; - - Dump ("Header not reopened\n"); - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - } - -ret: - TCfree (header); -wipe: - burn (request, sizeof (*request)); -} - - -typedef NTSTATUS (*HiberDriverWriteFunctionA) (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3); -typedef NTSTATUS (*HiberDriverWriteFunctionB) (PLARGE_INTEGER writeOffset, PMDL dataMdl); - -typedef struct -{ - // Until MS releases an API for filtering hibernation drivers, we have to resort to this. -#ifdef _WIN64 - byte FieldPad1[64]; - HiberDriverWriteFunctionB WriteFunctionB; - byte FieldPad2[56]; -#else - byte FieldPad1[48]; - HiberDriverWriteFunctionB WriteFunctionB; - byte FieldPad2[32]; -#endif - HiberDriverWriteFunctionA WriteFunctionA; - byte FieldPad3[24]; - LARGE_INTEGER PartitionStartOffset; -} HiberDriverContext; - -typedef NTSTATUS (*HiberDriverEntry) (PVOID arg0, HiberDriverContext *hiberDriverContext); - -typedef struct -{ - LIST_ENTRY ModuleList; -#ifdef _WIN64 - byte FieldPad1[32]; -#else - byte FieldPad1[16]; -#endif - PVOID ModuleBaseAddress; - HiberDriverEntry ModuleEntryAddress; -#ifdef _WIN64 - byte FieldPad2[24]; -#else - byte FieldPad2[12]; -#endif - UNICODE_STRING ModuleName; -} ModuleTableItem; - - -#define TC_MAX_HIBER_FILTER_COUNT 3 -static int LastHiberFilterNumber = 0; - -static HiberDriverEntry OriginalHiberDriverEntries[TC_MAX_HIBER_FILTER_COUNT]; -static HiberDriverWriteFunctionA OriginalHiberDriverWriteFunctionsA[TC_MAX_HIBER_FILTER_COUNT]; -static HiberDriverWriteFunctionB OriginalHiberDriverWriteFunctionsB[TC_MAX_HIBER_FILTER_COUNT]; - -static LARGE_INTEGER HiberPartitionOffset; - - -static NTSTATUS HiberDriverWriteFunctionFilter (int filterNumber, PLARGE_INTEGER writeOffset, PMDL dataMdl, BOOL writeB, ULONG arg0WriteA, PVOID arg3WriteA) -{ - MDL *encryptedDataMdl = dataMdl; - - if (writeOffset && dataMdl && BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted) - { - ULONG dataLength = MmGetMdlByteCount (dataMdl); - - if (dataMdl->MappedSystemVa && dataLength > 0) - { - uint64 offset = HiberPartitionOffset.QuadPart + writeOffset->QuadPart; - uint64 intersectStart; - uint32 intersectLength; - - if (dataLength > TC_HIBERNATION_WRITE_BUFFER_SIZE) - TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW); - - if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) - TC_BUG_CHECK (STATUS_INVALID_PARAMETER); - - if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) - TC_BUG_CHECK (STATUS_INVALID_PARAMETER); - - GetIntersection (offset, - dataLength, - BootDriveFilterExtension->Queue.EncryptedAreaStart, - BootDriveFilterExtension->Queue.EncryptedAreaEnd, - &intersectStart, - &intersectLength); - - if (intersectLength > 0) - { - UINT64_STRUCT dataUnit; - dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE; - - memcpy (HibernationWriteBuffer, dataMdl->MappedSystemVa, dataLength); - - if (BootDriveFilterExtension->Queue.RemapEncryptedArea) - dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset; - - EncryptDataUnitsCurrentThread (HibernationWriteBuffer + (intersectStart - offset), - &dataUnit, - intersectLength / ENCRYPTION_DATA_UNIT_SIZE, - BootDriveFilterExtension->Queue.CryptoInfo); - - encryptedDataMdl = HibernationWriteBufferMdl; - MmInitializeMdl (encryptedDataMdl, HibernationWriteBuffer, dataLength); - encryptedDataMdl->MdlFlags = dataMdl->MdlFlags; - } - } - } - - if (writeB) - return (*OriginalHiberDriverWriteFunctionsB[filterNumber]) (writeOffset, encryptedDataMdl); - - return (*OriginalHiberDriverWriteFunctionsA[filterNumber]) (arg0WriteA, writeOffset, encryptedDataMdl, arg3WriteA); -} - - -static NTSTATUS HiberDriverWriteFunctionAFilter0 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3) -{ - return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, FALSE, arg0, arg3); -} - -static NTSTATUS HiberDriverWriteFunctionAFilter1 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3) -{ - return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, FALSE, arg0, arg3); -} - -static NTSTATUS HiberDriverWriteFunctionAFilter2 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3) -{ - return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, FALSE, arg0, arg3); -} - - -static NTSTATUS HiberDriverWriteFunctionBFilter0 (PLARGE_INTEGER writeOffset, PMDL dataMdl) -{ - return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, TRUE, 0, NULL); -} - -static NTSTATUS HiberDriverWriteFunctionBFilter1 (PLARGE_INTEGER writeOffset, PMDL dataMdl) -{ - return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, TRUE, 0, NULL); -} - -static NTSTATUS HiberDriverWriteFunctionBFilter2 (PLARGE_INTEGER writeOffset, PMDL dataMdl) -{ - return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, TRUE, 0, NULL); -} - - -static NTSTATUS HiberDriverEntryFilter (int filterNumber, PVOID arg0, HiberDriverContext *hiberDriverContext) -{ - BOOL filterInstalled = FALSE; - NTSTATUS status; - - if (!OriginalHiberDriverEntries[filterNumber]) - return STATUS_UNSUCCESSFUL; - - status = (*OriginalHiberDriverEntries[filterNumber]) (arg0, hiberDriverContext); - - if (!NT_SUCCESS (status) || !hiberDriverContext) - return status; - - if (SetupInProgress) - TC_BUG_CHECK (STATUS_INVALID_PARAMETER); - - if (hiberDriverContext->WriteFunctionA) - { - Dump ("Filtering WriteFunctionA %d\n", filterNumber); - OriginalHiberDriverWriteFunctionsA[filterNumber] = hiberDriverContext->WriteFunctionA; - - switch (filterNumber) - { - case 0: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter0; break; - case 1: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter1; break; - case 2: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter2; break; - default: TC_THROW_FATAL_EXCEPTION; - } - - filterInstalled = TRUE; - } - - if (hiberDriverContext->WriteFunctionB) - { - Dump ("Filtering WriteFunctionB %d\n", filterNumber); - OriginalHiberDriverWriteFunctionsB[filterNumber] = hiberDriverContext->WriteFunctionB; - - switch (filterNumber) - { - case 0: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter0; break; - case 1: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter1; break; - case 2: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter2; break; - default: TC_THROW_FATAL_EXCEPTION; - } - - filterInstalled = TRUE; - } - - if (filterInstalled && hiberDriverContext->PartitionStartOffset.QuadPart != 0) - { - HiberPartitionOffset = hiberDriverContext->PartitionStartOffset; - - if (BootDriveFilterExtension->Queue.RemapEncryptedArea) - hiberDriverContext->PartitionStartOffset.QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset; - } - - return STATUS_SUCCESS; -} - - -static NTSTATUS HiberDriverEntryFilter0 (PVOID arg0, HiberDriverContext *hiberDriverContext) -{ - return HiberDriverEntryFilter (0, arg0, hiberDriverContext); -} - - -static NTSTATUS HiberDriverEntryFilter1 (PVOID arg0, HiberDriverContext *hiberDriverContext) -{ - return HiberDriverEntryFilter (1, arg0, hiberDriverContext); -} - - -static NTSTATUS HiberDriverEntryFilter2 (PVOID arg0, HiberDriverContext *hiberDriverContext) -{ - return HiberDriverEntryFilter (2, arg0, hiberDriverContext); -} - - -static VOID LoadImageNotifyRoutine (PUNICODE_STRING fullImageName, HANDLE processId, PIMAGE_INFO imageInfo) -{ - ModuleTableItem *moduleItem; - LIST_ENTRY *listEntry; - KIRQL origIrql; - - if (!imageInfo || !imageInfo->SystemModeImage || !imageInfo->ImageBase || !TCDriverObject->DriverSection) - return; - - moduleItem = *(ModuleTableItem **) TCDriverObject->DriverSection; - if (!moduleItem || !moduleItem->ModuleList.Flink) - return; - - // Search loaded system modules for hibernation driver - origIrql = KeRaiseIrqlToDpcLevel(); - - for (listEntry = moduleItem->ModuleList.Flink->Blink; - listEntry && listEntry != TCDriverObject->DriverSection; - listEntry = listEntry->Flink) - { - moduleItem = CONTAINING_RECORD (listEntry, ModuleTableItem, ModuleList); - - if (moduleItem && imageInfo->ImageBase == moduleItem->ModuleBaseAddress) - { - if (moduleItem->ModuleName.Buffer && moduleItem->ModuleName.Length >= 5 * sizeof (wchar_t)) - { - // Skip MS BitLocker filter - if (moduleItem->ModuleName.Length >= 13 * sizeof (wchar_t) - && memcmp (moduleItem->ModuleName.Buffer, L"hiber_dumpfve", 13 * sizeof (wchar_t)) == 0) - break; - - if (memcmp (moduleItem->ModuleName.Buffer, L"hiber", 5 * sizeof (wchar_t)) == 0 - || memcmp (moduleItem->ModuleName.Buffer, L"Hiber", 5 * sizeof (wchar_t)) == 0 - || memcmp (moduleItem->ModuleName.Buffer, L"HIBER", 5 * sizeof (wchar_t)) == 0) - { - HiberDriverEntry filterEntry; - - switch (LastHiberFilterNumber) - { - case 0: filterEntry = HiberDriverEntryFilter0; break; - case 1: filterEntry = HiberDriverEntryFilter1; break; - case 2: filterEntry = HiberDriverEntryFilter2; break; - default: TC_THROW_FATAL_EXCEPTION; - } - - if (moduleItem->ModuleEntryAddress != filterEntry) - { - // Install filter - OriginalHiberDriverEntries[LastHiberFilterNumber] = moduleItem->ModuleEntryAddress; - moduleItem->ModuleEntryAddress = filterEntry; - - if (++LastHiberFilterNumber > TC_MAX_HIBER_FILTER_COUNT - 1) - LastHiberFilterNumber = 0; - } - } - } - break; - } - } - - KeLowerIrql (origIrql); -} - - -void StartHibernationDriverFilter () -{ - PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr; - NTSTATUS status; - - ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); - - if (!TCDriverObject->DriverSection || !*(ModuleTableItem **) TCDriverObject->DriverSection) - goto err; - - // All buffers required for hibernation must be allocated here -#ifdef _WIN64 - highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFULL; -#else - highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFULL; -#endif - - HibernationWriteBuffer = MmAllocateContiguousMemory (TC_HIBERNATION_WRITE_BUFFER_SIZE, highestAcceptableWriteBufferAddr); - if (!HibernationWriteBuffer) - goto err; - - HibernationWriteBufferMdl = IoAllocateMdl (HibernationWriteBuffer, TC_HIBERNATION_WRITE_BUFFER_SIZE, FALSE, FALSE, NULL); - if (!HibernationWriteBufferMdl) - goto err; - - MmBuildMdlForNonPagedPool (HibernationWriteBufferMdl); - - status = PsSetLoadImageNotifyRoutine (LoadImageNotifyRoutine); - if (!NT_SUCCESS (status)) - goto err; - - HibernationDriverFilterActive = TRUE; - return; - -err: - HibernationDriverFilterActive = FALSE; - - if (HibernationWriteBufferMdl) - { - IoFreeMdl (HibernationWriteBufferMdl); - HibernationWriteBufferMdl = NULL; - } - - if (HibernationWriteBuffer) - { - MmFreeContiguousMemory (HibernationWriteBuffer); - HibernationWriteBuffer = NULL; - } -} - - -static VOID SetupThreadProc (PVOID threadArg) -{ - DriveFilterExtension *Extension = BootDriveFilterExtension; - - LARGE_INTEGER offset; - UINT64_STRUCT dataUnit; - ULONG setupBlockSize = TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE; - BOOL headerUpdateRequired = FALSE; - int64 bytesWrittenSinceHeaderUpdate = 0; - - byte *buffer = NULL; - byte *wipeBuffer = NULL; - byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT]; - byte wipeRandCharsUpdate[TC_WIPE_RAND_CHAR_COUNT]; - - KIRQL irql; - NTSTATUS status; - - SetupResult = STATUS_UNSUCCESSFUL; - - // Make sure volume header can be updated - if (Extension->HeaderCryptoInfo == NULL) - { - SetupResult = STATUS_INVALID_PARAMETER; - goto ret; - } - - buffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); - if (!buffer) - { - SetupResult = STATUS_INSUFFICIENT_RESOURCES; - goto ret; - } - - if (SetupRequest.SetupMode == SetupEncryption && SetupRequest.WipeAlgorithm != TC_WIPE_NONE) - { - wipeBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); - if (!wipeBuffer) - { - SetupResult = STATUS_INSUFFICIENT_RESOURCES; - goto ret; - } - } - - while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 1000))) - { - if (EncryptionSetupThreadAbortRequested) - goto abort; - - TransformWaitingForIdle = TRUE; - } - TransformWaitingForIdle = FALSE; - - switch (SetupRequest.SetupMode) - { - case SetupEncryption: - Dump ("Encrypting...\n"); - if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1) - { - // Start encryption - Extension->Queue.EncryptedAreaStart = Extension->ConfiguredEncryptedAreaStart; - Extension->Queue.EncryptedAreaEnd = -1; - offset.QuadPart = Extension->ConfiguredEncryptedAreaStart; - } - else - { - // Resume aborted encryption - if (Extension->Queue.EncryptedAreaEnd == Extension->ConfiguredEncryptedAreaEnd) - goto err; - - offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1; - } - - break; - - case SetupDecryption: - Dump ("Decrypting...\n"); - if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1) - { - SetupResult = STATUS_SUCCESS; - goto abort; - } - - offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1; - break; - - default: - goto err; - } - - EncryptedIoQueueResumeFromHold (&Extension->Queue); - - Dump ("EncryptedAreaStart=%I64d\n", Extension->Queue.EncryptedAreaStart); - Dump ("EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaEnd); - Dump ("ConfiguredEncryptedAreaStart=%I64d\n", Extension->ConfiguredEncryptedAreaStart); - Dump ("ConfiguredEncryptedAreaEnd=%I64d\n", Extension->ConfiguredEncryptedAreaEnd); - Dump ("offset=%I64d\n", offset.QuadPart); - Dump ("EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024); - - while (!EncryptionSetupThreadAbortRequested) - { - if (SetupRequest.SetupMode == SetupEncryption) - { - if (offset.QuadPart + setupBlockSize > Extension->ConfiguredEncryptedAreaEnd + 1) - setupBlockSize = (ULONG) (Extension->ConfiguredEncryptedAreaEnd + 1 - offset.QuadPart); - - if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd) - break; - } - else - { - if (offset.QuadPart - setupBlockSize < Extension->Queue.EncryptedAreaStart) - setupBlockSize = (ULONG) (offset.QuadPart - Extension->Queue.EncryptedAreaStart); - - offset.QuadPart -= setupBlockSize; - - if (setupBlockSize == 0 || offset.QuadPart < Extension->Queue.EncryptedAreaStart) - break; - } - - while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 500))) - { - if (EncryptionSetupThreadAbortRequested) - goto abort; - - TransformWaitingForIdle = TRUE; - } - TransformWaitingForIdle = FALSE; - - status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); - if (!NT_SUCCESS (status)) - { - Dump ("TCReadDevice error %x offset=%I64d\n", status, offset.QuadPart); - - if (SetupRequest.ZeroUnreadableSectors && SetupRequest.SetupMode == SetupEncryption) - { - // Zero unreadable sectors - uint64 zeroedSectorCount; - - status = ZeroUnreadableSectors (BootDriveFilterExtension->LowerDeviceObject, offset, setupBlockSize, &zeroedSectorCount); - if (!NT_SUCCESS (status)) - { - SetupResult = status; - goto err; - } - - // Retry read - status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); - if (!NT_SUCCESS (status)) - { - SetupResult = status; - goto err; - } - } - else if (SetupRequest.DiscardUnreadableEncryptedSectors && SetupRequest.SetupMode == SetupDecryption) - { - // Discard unreadable encrypted sectors - uint64 badSectorCount; - - status = ReadDeviceSkipUnreadableSectors (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize, &badSectorCount); - if (!NT_SUCCESS (status)) - { - SetupResult = status; - goto err; - } - } - else - { - SetupResult = status; - goto err; - } - } - - dataUnit.Value = offset.QuadPart / ENCRYPTION_DATA_UNIT_SIZE; - - if (SetupRequest.SetupMode == SetupEncryption) - { - EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); - - if (SetupRequest.WipeAlgorithm != TC_WIPE_NONE) - { - byte wipePass; - for (wipePass = 1; wipePass <= GetWipePassCount (SetupRequest.WipeAlgorithm); ++wipePass) - { - if (!WipeBuffer (SetupRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, setupBlockSize)) - { - ULONG i; - for (i = 0; i < setupBlockSize; ++i) - { - wipeBuffer[i] = buffer[i] + wipePass; - } - - EncryptDataUnits (wipeBuffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); - memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); - } - - status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, setupBlockSize); - if (!NT_SUCCESS (status)) - { - // Undo failed write operation - DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); - TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); - - SetupResult = status; - goto err; - } - } - - memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate)); - } - } - else - { - DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); - } - - status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); - if (!NT_SUCCESS (status)) - { - Dump ("TCWriteDevice error %x\n", status); - - // Undo failed write operation - if (SetupRequest.SetupMode == SetupEncryption) - DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); - else - EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); - - TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); - - SetupResult = status; - goto err; - } - - if (SetupRequest.SetupMode == SetupEncryption) - offset.QuadPart += setupBlockSize; - - Extension->Queue.EncryptedAreaEnd = offset.QuadPart - 1; - headerUpdateRequired = TRUE; - - EncryptedIoQueueResumeFromHold (&Extension->Queue); - - KeAcquireSpinLock (&SetupStatusSpinLock, &irql); - SetupStatusEncryptedAreaEnd = Extension->Queue.EncryptedAreaEnd; - KeReleaseSpinLock (&SetupStatusSpinLock, irql); - - // Update volume header - bytesWrittenSinceHeaderUpdate += setupBlockSize; - if (bytesWrittenSinceHeaderUpdate >= TC_ENCRYPTION_SETUP_HEADER_UPDATE_THRESHOLD) - { - status = SaveDriveVolumeHeader (Extension); - - if (!NT_SUCCESS (status)) - { - SetupResult = status; - goto err; - } - - headerUpdateRequired = FALSE; - bytesWrittenSinceHeaderUpdate = 0; - } - } - -abort: - SetupResult = STATUS_SUCCESS; -err: - - if (Extension->Queue.EncryptedAreaEnd == -1) - Extension->Queue.EncryptedAreaStart = -1; - - if (EncryptedIoQueueIsSuspended (&Extension->Queue)) - EncryptedIoQueueResumeFromHold (&Extension->Queue); - - if (SetupRequest.SetupMode == SetupDecryption && Extension->Queue.EncryptedAreaStart >= Extension->Queue.EncryptedAreaEnd) - { - while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 0))); - - Extension->ConfiguredEncryptedAreaStart = Extension->ConfiguredEncryptedAreaEnd = -1; - Extension->Queue.EncryptedAreaStart = Extension->Queue.EncryptedAreaEnd = -1; - - EncryptedIoQueueResumeFromHold (&Extension->Queue); - - headerUpdateRequired = TRUE; - } - - Dump ("Setup completed: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd); - - if (headerUpdateRequired) - { - status = SaveDriveVolumeHeader (Extension); - - if (!NT_SUCCESS (status) && NT_SUCCESS (SetupResult)) - SetupResult = status; - } - - if (SetupRequest.SetupMode == SetupDecryption && Extension->ConfiguredEncryptedAreaEnd == -1 && Extension->DriveMounted) - { - DismountDrive (Extension, FALSE); - } - -ret: - if (buffer) - TCfree (buffer); - if (wipeBuffer) - TCfree (wipeBuffer); - - SetupInProgress = FALSE; - PsTerminateSystemThread (SetupResult); -} - - -NTSTATUS StartBootEncryptionSetup (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp) -{ - NTSTATUS status; - - if (!UserCanAccessDriveDevice()) - return STATUS_ACCESS_DENIED; - - if (SetupInProgress || !BootDriveFound || !BootDriveFilterExtension - || BootDriveFilterExtension->HiddenSystem - || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (BootEncryptionSetupRequest)) - return STATUS_INVALID_PARAMETER; - - SetupRequest = *(BootEncryptionSetupRequest *) irp->AssociatedIrp.SystemBuffer; - - EncryptionSetupThreadAbortRequested = FALSE; - KeInitializeSpinLock (&SetupStatusSpinLock); - SetupStatusEncryptedAreaEnd = BootDriveFilterExtension ? BootDriveFilterExtension->Queue.EncryptedAreaEnd : -1; - - SetupInProgress = TRUE; - status = TCStartThread (SetupThreadProc, DeviceObject, &EncryptionSetupThread); - - if (!NT_SUCCESS (status)) - SetupInProgress = FALSE; - - return status; -} - - -void GetBootDriveVolumeProperties (PIRP irp, PIO_STACK_LOCATION irpSp) -{ - if (ValidateIOBufferSize (irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateOutput)) - { - DriveFilterExtension *Extension = BootDriveFilterExtension; - VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) irp->AssociatedIrp.SystemBuffer; - memset (prop, 0, sizeof (*prop)); - - if (!BootDriveFound || !Extension) - { - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - irp->IoStatus.Information = 0; - } - else - { - prop->hiddenVolume = Extension->Queue.CryptoInfo->hiddenVolume; - prop->diskLength = Extension->ConfiguredEncryptedAreaEnd + 1 - Extension->ConfiguredEncryptedAreaStart; - prop->ea = Extension->Queue.CryptoInfo->ea; - prop->mode = Extension->Queue.CryptoInfo->mode; - prop->pkcs5 = Extension->Queue.CryptoInfo->pkcs5; - prop->pkcs5Iterations = Extension->Queue.CryptoInfo->noIterations; -#if 0 - prop->volumeCreationTime = Extension->Queue.CryptoInfo->volume_creation_time; - prop->headerCreationTime = Extension->Queue.CryptoInfo->header_creation_time; -#endif - prop->volFormatVersion = Extension->Queue.CryptoInfo->LegacyVolume ? TC_VOLUME_FORMAT_VERSION_PRE_6_0 : TC_VOLUME_FORMAT_VERSION; - - prop->totalBytesRead = Extension->Queue.TotalBytesRead; - prop->totalBytesWritten = Extension->Queue.TotalBytesWritten; - - irp->IoStatus.Information = sizeof (VOLUME_PROPERTIES_STRUCT); - irp->IoStatus.Status = STATUS_SUCCESS; - } - } -} - - -void GetBootEncryptionStatus (PIRP irp, PIO_STACK_LOCATION irpSp) -{ - /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */ - - if (ValidateIOBufferSize (irp, sizeof (BootEncryptionStatus), ValidateOutput)) - { - DriveFilterExtension *Extension = BootDriveFilterExtension; - BootEncryptionStatus *bootEncStatus = (BootEncryptionStatus *) irp->AssociatedIrp.SystemBuffer; - memset (bootEncStatus, 0, sizeof (*bootEncStatus)); - - if (BootArgsValid) - bootEncStatus->BootLoaderVersion = BootArgs.BootLoaderVersion; - - bootEncStatus->DeviceFilterActive = DeviceFilterActive; - bootEncStatus->SetupInProgress = SetupInProgress; - bootEncStatus->SetupMode = SetupRequest.SetupMode; - bootEncStatus->TransformWaitingForIdle = TransformWaitingForIdle; - - if (!BootDriveFound || !Extension) - { - bootEncStatus->DriveEncrypted = FALSE; - bootEncStatus->DriveMounted = FALSE; - bootEncStatus->VolumeHeaderPresent = FALSE; - } - else - { - bootEncStatus->DriveMounted = Extension->DriveMounted; - bootEncStatus->VolumeHeaderPresent = Extension->VolumeHeaderPresent; - bootEncStatus->DriveEncrypted = Extension->Queue.EncryptedAreaStart != -1; - bootEncStatus->BootDriveLength = BootDriveLength; - - bootEncStatus->ConfiguredEncryptedAreaStart = Extension->ConfiguredEncryptedAreaStart; - bootEncStatus->ConfiguredEncryptedAreaEnd = Extension->ConfiguredEncryptedAreaEnd; - bootEncStatus->EncryptedAreaStart = Extension->Queue.EncryptedAreaStart; - - if (SetupInProgress) - { - KIRQL irql; - KeAcquireSpinLock (&SetupStatusSpinLock, &irql); - bootEncStatus->EncryptedAreaEnd = SetupStatusEncryptedAreaEnd; - KeReleaseSpinLock (&SetupStatusSpinLock, irql); - } - else - bootEncStatus->EncryptedAreaEnd = Extension->Queue.EncryptedAreaEnd; - - bootEncStatus->VolumeHeaderSaltCrc32 = Extension->VolumeHeaderSaltCrc32; - bootEncStatus->HibernationPreventionCount = HibernationPreventionCount; - bootEncStatus->HiddenSysLeakProtectionCount = HiddenSysLeakProtectionCount; - - bootEncStatus->HiddenSystem = Extension->HiddenSystem; - - if (Extension->HiddenSystem) - bootEncStatus->HiddenSystemPartitionStart = BootArgs.HiddenSystemPartitionStart; - } - - irp->IoStatus.Information = sizeof (BootEncryptionStatus); - irp->IoStatus.Status = STATUS_SUCCESS; - } -} - - -void GetBootLoaderVersion (PIRP irp, PIO_STACK_LOCATION irpSp) -{ - if (ValidateIOBufferSize (irp, sizeof (uint16), ValidateOutput)) - { - if (BootArgsValid) - { - *(uint16 *) irp->AssociatedIrp.SystemBuffer = BootArgs.BootLoaderVersion; - irp->IoStatus.Information = sizeof (uint16); - irp->IoStatus.Status = STATUS_SUCCESS; - } - else - { - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - irp->IoStatus.Information = 0; - } - } -} - - -void GetBootEncryptionAlgorithmName (PIRP irp, PIO_STACK_LOCATION irpSp) -{ - if (ValidateIOBufferSize (irp, sizeof (GetBootEncryptionAlgorithmNameRequest), ValidateOutput)) - { - if (BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted) - { - GetBootEncryptionAlgorithmNameRequest *request = (GetBootEncryptionAlgorithmNameRequest *) irp->AssociatedIrp.SystemBuffer; - EAGetName (request->BootEncryptionAlgorithmName, BootDriveFilterExtension->Queue.CryptoInfo->ea); - - irp->IoStatus.Information = sizeof (GetBootEncryptionAlgorithmNameRequest); - irp->IoStatus.Status = STATUS_SUCCESS; - } - else - { - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - irp->IoStatus.Information = 0; - } - } -} - - -NTSTATUS GetSetupResult() -{ - return SetupResult; -} - - -BOOL IsBootDriveMounted () -{ - return BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted; -} - - -BOOL IsBootEncryptionSetupInProgress () -{ - return SetupInProgress; -} - - -BOOL IsHiddenSystemRunning () -{ - return BootDriveFilterExtension && BootDriveFilterExtension->HiddenSystem; -} - - -CRYPTO_INFO *GetSystemDriveCryptoInfo () -{ - return BootDriveFilterExtension->Queue.CryptoInfo; -} - - -NTSTATUS AbortBootEncryptionSetup () -{ - if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice()) - return STATUS_ACCESS_DENIED; - - if (!SetupInProgress) - return STATUS_SUCCESS; - - EncryptionSetupThreadAbortRequested = TRUE; - TCStopThread (EncryptionSetupThread, NULL); - - return STATUS_SUCCESS; -} - - -static VOID DecoySystemWipeThreadProc (PVOID threadArg) -{ - DriveFilterExtension *Extension = BootDriveFilterExtension; - - LARGE_INTEGER offset; - UINT64_STRUCT dataUnit; - ULONG wipeBlockSize = TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE; - - CRYPTO_INFO *wipeCryptoInfo = NULL; - byte *wipeBuffer = NULL; - byte *wipeRandBuffer = NULL; - byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT]; - size_t wipePass; - int ea = Extension->Queue.CryptoInfo->ea; - - KIRQL irql; - NTSTATUS status; - - DecoySystemWipeResult = STATUS_UNSUCCESSFUL; - - wipeBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); - if (!wipeBuffer) - { - DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES; - goto ret; - } - - wipeRandBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); - if (!wipeRandBuffer) - { - DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES; - goto ret; - } - - wipeCryptoInfo = crypto_open(); - if (!wipeCryptoInfo) - { - DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES; - goto ret; - } - - wipeCryptoInfo->ea = ea; - wipeCryptoInfo->mode = Extension->Queue.CryptoInfo->mode; - - if (EAInit (ea, WipeDecoyRequest.WipeKey, wipeCryptoInfo->ks) != ERR_SUCCESS) - { - DecoySystemWipeResult = STATUS_INVALID_PARAMETER; - goto ret; - } - - memcpy (wipeCryptoInfo->k2, WipeDecoyRequest.WipeKey + EAGetKeySize (ea), EAGetKeySize (ea)); - - if (!EAInitMode (wipeCryptoInfo)) - { - DecoySystemWipeResult = STATUS_INVALID_PARAMETER; - goto err; - } - - EncryptDataUnits (wipeRandBuffer, &dataUnit, wipeBlockSize / ENCRYPTION_DATA_UNIT_SIZE, wipeCryptoInfo); - memcpy (wipeRandChars, wipeRandBuffer, sizeof (wipeRandChars)); - - burn (WipeDecoyRequest.WipeKey, sizeof (WipeDecoyRequest.WipeKey)); - - offset.QuadPart = Extension->ConfiguredEncryptedAreaStart; - - Dump ("Wiping decoy system: start offset = %I64d\n", offset.QuadPart); - - while (!DecoySystemWipeThreadAbortRequested) - { - if (offset.QuadPart + wipeBlockSize > Extension->ConfiguredEncryptedAreaEnd + 1) - wipeBlockSize = (ULONG) (Extension->ConfiguredEncryptedAreaEnd + 1 - offset.QuadPart); - - if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd) - break; - - for (wipePass = 1; wipePass <= GetWipePassCount (WipeDecoyRequest.WipeAlgorithm); ++wipePass) - { - if (!WipeBuffer (WipeDecoyRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, wipeBlockSize)) - { - dataUnit.Value = offset.QuadPart / ENCRYPTION_DATA_UNIT_SIZE; - EncryptDataUnits (wipeRandBuffer, &dataUnit, wipeBlockSize / ENCRYPTION_DATA_UNIT_SIZE, wipeCryptoInfo); - memcpy (wipeBuffer, wipeRandBuffer, wipeBlockSize); - } - - while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 500))) - { - if (DecoySystemWipeThreadAbortRequested) - goto abort; - } - - status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, wipeBlockSize); - - if (!NT_SUCCESS (status)) - { - DecoySystemWipeResult = status; - goto err; - } - - EncryptedIoQueueResumeFromHold (&Extension->Queue); - } - - offset.QuadPart += wipeBlockSize; - - KeAcquireSpinLock (&DecoySystemWipeStatusSpinLock, &irql); - DecoySystemWipedAreaEnd = offset.QuadPart - 1; - KeReleaseSpinLock (&DecoySystemWipeStatusSpinLock, irql); - } - -abort: - DecoySystemWipeResult = STATUS_SUCCESS; -err: - - if (EncryptedIoQueueIsSuspended (&Extension->Queue)) - EncryptedIoQueueResumeFromHold (&Extension->Queue); - - Dump ("Wipe end: DecoySystemWipedAreaEnd=%I64d (%I64d)\n", DecoySystemWipedAreaEnd, DecoySystemWipedAreaEnd / 1024 / 1024); - -ret: - if (wipeCryptoInfo) - crypto_close (wipeCryptoInfo); - - if (wipeRandBuffer) - TCfree (wipeRandBuffer); - - if (wipeBuffer) - TCfree (wipeBuffer); - - DecoySystemWipeInProgress = FALSE; - PsTerminateSystemThread (DecoySystemWipeResult); -} - - -NTSTATUS StartDecoySystemWipe (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp) -{ - NTSTATUS status; - WipeDecoySystemRequest *request; - - if (!UserCanAccessDriveDevice()) - return STATUS_ACCESS_DENIED; - - if (!IsHiddenSystemRunning() - || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (WipeDecoySystemRequest)) - return STATUS_INVALID_PARAMETER; - - if (DecoySystemWipeInProgress) - return STATUS_SUCCESS; - - request = (WipeDecoySystemRequest *) irp->AssociatedIrp.SystemBuffer; - WipeDecoyRequest = *request; - - burn (request->WipeKey, sizeof (request->WipeKey)); - - DecoySystemWipeThreadAbortRequested = FALSE; - KeInitializeSpinLock (&DecoySystemWipeStatusSpinLock); - DecoySystemWipedAreaEnd = BootDriveFilterExtension->ConfiguredEncryptedAreaStart; - - DecoySystemWipeInProgress = TRUE; - status = TCStartThread (DecoySystemWipeThreadProc, DeviceObject, &DecoySystemWipeThread); - - if (!NT_SUCCESS (status)) - DecoySystemWipeInProgress = FALSE; - - return status; -} - - -BOOL IsDecoySystemWipeInProgress() -{ - return DecoySystemWipeInProgress; -} - - -void GetDecoySystemWipeStatus (PIRP irp, PIO_STACK_LOCATION irpSp) -{ - if (ValidateIOBufferSize (irp, sizeof (DecoySystemWipeStatus), ValidateOutput)) - { - DecoySystemWipeStatus *wipeStatus = (DecoySystemWipeStatus *) irp->AssociatedIrp.SystemBuffer; - - if (!IsHiddenSystemRunning()) - { - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - irp->IoStatus.Information = 0; - } - else - { - wipeStatus->WipeInProgress = DecoySystemWipeInProgress; - wipeStatus->WipeAlgorithm = WipeDecoyRequest.WipeAlgorithm; - - if (DecoySystemWipeInProgress) - { - KIRQL irql; - KeAcquireSpinLock (&DecoySystemWipeStatusSpinLock, &irql); - wipeStatus->WipedAreaEnd = DecoySystemWipedAreaEnd; - KeReleaseSpinLock (&DecoySystemWipeStatusSpinLock, irql); - } - else - wipeStatus->WipedAreaEnd = DecoySystemWipedAreaEnd; - - irp->IoStatus.Information = sizeof (DecoySystemWipeStatus); - irp->IoStatus.Status = STATUS_SUCCESS; - } - } -} - - -NTSTATUS GetDecoySystemWipeResult() -{ - return DecoySystemWipeResult; -} - - -NTSTATUS AbortDecoySystemWipe () -{ - if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice()) - return STATUS_ACCESS_DENIED; - - if (DecoySystemWipeInProgress) - { - DecoySystemWipeThreadAbortRequested = TRUE; - TCStopThread (DecoySystemWipeThread, NULL); - } - - return STATUS_SUCCESS; -} - - -uint64 GetBootDriveLength () -{ - return BootDriveLength.QuadPart; -} - - -NTSTATUS WriteBootDriveSector (PIRP irp, PIO_STACK_LOCATION irpSp) -{ - WriteBootDriveSectorRequest *request; - - if (!UserCanAccessDriveDevice()) - return STATUS_ACCESS_DENIED; - - if (!BootDriveFilterExtension - || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (WriteBootDriveSectorRequest)) - return STATUS_INVALID_PARAMETER; - - request = (WriteBootDriveSectorRequest *) irp->AssociatedIrp.SystemBuffer; - return TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, request->Data, request->Offset, sizeof (request->Data)); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "TCdefs.h" +#include +#include +#include "Cache.h" +#include "Crc.h" +#include "Crypto.h" +#include "Apidrvr.h" +#include "EncryptedIoQueue.h" +#include "Common/Endian.h" +#include "Ntdriver.h" +#include "Ntvol.h" +#include "Volumes.h" +#include "VolumeFilter.h" +#include "Wipe.h" +#include "DriveFilter.h" +#include "Boot/Windows/BootCommon.h" + +static BOOL DeviceFilterActive = FALSE; + +BOOL BootArgsValid = FALSE; +BootArguments BootArgs; +static uint16 BootLoaderSegment; + +static BOOL BootDriveFound = FALSE; +static DriveFilterExtension *BootDriveFilterExtension = NULL; +static LARGE_INTEGER BootDriveLength; + +static BOOL HibernationDriverFilterActive = FALSE; +static byte *HibernationWriteBuffer = NULL; +static MDL *HibernationWriteBufferMdl = NULL; +static uint32 HibernationPreventionCount = 0; + +static BootEncryptionSetupRequest SetupRequest; +static volatile BOOL SetupInProgress = FALSE; +PKTHREAD EncryptionSetupThread = NULL; +static volatile BOOL EncryptionSetupThreadAbortRequested; +static KSPIN_LOCK SetupStatusSpinLock; +static int64 SetupStatusEncryptedAreaEnd; +static BOOL TransformWaitingForIdle; +static NTSTATUS SetupResult; + +static WipeDecoySystemRequest WipeDecoyRequest; +static volatile BOOL DecoySystemWipeInProgress = FALSE; +static volatile BOOL DecoySystemWipeThreadAbortRequested; +static KSPIN_LOCK DecoySystemWipeStatusSpinLock; +static int64 DecoySystemWipedAreaEnd; +PKTHREAD DecoySystemWipeThread = NULL; +static NTSTATUS DecoySystemWipeResult; + + +NTSTATUS LoadBootArguments () +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + PHYSICAL_ADDRESS bootArgsAddr; + byte *mappedBootArgs; + uint16 bootLoaderSegment; + + for (bootLoaderSegment = TC_BOOT_LOADER_SEGMENT; + bootLoaderSegment >= TC_BOOT_LOADER_SEGMENT - 64 * 1024 / 16 && status != STATUS_SUCCESS; + bootLoaderSegment -= 32 * 1024 / 16) + { + bootArgsAddr.QuadPart = (bootLoaderSegment << 4) + TC_BOOT_LOADER_ARGS_OFFSET; + Dump ("Checking BootArguments at 0x%x\n", bootArgsAddr.LowPart); + + mappedBootArgs = MmMapIoSpace (bootArgsAddr, sizeof (BootArguments), MmCached); + if (!mappedBootArgs) + return STATUS_INSUFFICIENT_RESOURCES; + + if (TC_IS_BOOT_ARGUMENTS_SIGNATURE (mappedBootArgs)) + { + BootArguments *bootArguments = (BootArguments *) mappedBootArgs; + Dump ("BootArguments found at 0x%x\n", bootArgsAddr.LowPart); + + DumpMem (mappedBootArgs, sizeof (BootArguments)); + + if (bootArguments->BootLoaderVersion == VERSION_NUM + && bootArguments->BootArgumentsCrc32 != GetCrc32 ((byte *) bootArguments, (int) ((byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments))) + { + Dump ("BootArguments CRC incorrect\n"); + TC_BUG_CHECK (STATUS_CRC_ERROR); + } + + BootLoaderSegment = bootLoaderSegment; + + BootArgs = *bootArguments; + BootArgsValid = TRUE; + memset (bootArguments, 0, sizeof (*bootArguments)); + + if (BootArgs.BootLoaderVersion < 0x600) + { + BootArgs.HiddenSystemPartitionStart = 0; + BootArgs.DecoySystemPartitionStart = 0; + } + + if (BootArgs.BootLoaderVersion < 0x630) + BootArgs.Flags = 0; + + Dump ("BootLoaderVersion = %x\n", (int) BootArgs.BootLoaderVersion); + Dump ("HeaderSaltCrc32 = %x\n", (int) BootArgs.HeaderSaltCrc32); + Dump ("CryptoInfoOffset = %x\n", (int) BootArgs.CryptoInfoOffset); + Dump ("CryptoInfoLength = %d\n", (int) BootArgs.CryptoInfoLength); + Dump ("HiddenSystemPartitionStart = %I64u\n", BootArgs.HiddenSystemPartitionStart); + Dump ("DecoySystemPartitionStart = %I64u\n", BootArgs.DecoySystemPartitionStart); + Dump ("Flags = %x\n", BootArgs.Flags); + Dump ("BootArgumentsCrc32 = %x\n", BootArgs.BootArgumentsCrc32); + + if (CacheBootPassword && BootArgs.BootPassword.Length > 0) + AddPasswordToCache (&BootArgs.BootPassword); + + status = STATUS_SUCCESS; + } + + MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments)); + } + + return status; +} + + +NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) +{ + DriveFilterExtension *Extension; + NTSTATUS status; + PDEVICE_OBJECT filterDeviceObject = NULL; + PDEVICE_OBJECT attachedDeviceObject; + + Dump ("DriveFilterAddDevice pdo=%p\n", pdo); + + attachedDeviceObject = IoGetAttachedDeviceReference (pdo); + + DriverMutexWait(); + status = IoCreateDevice (driverObject, sizeof (DriveFilterExtension), NULL, attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject); + DriverMutexRelease(); + + ObDereferenceObject (attachedDeviceObject); + + if (!NT_SUCCESS (status)) + { + filterDeviceObject = NULL; + goto err; + } + + Extension = (DriveFilterExtension *) filterDeviceObject->DeviceExtension; + memset (Extension, 0, sizeof (DriveFilterExtension)); + + Extension->LowerDeviceObject = IoAttachDeviceToDeviceStack (filterDeviceObject, pdo); // IoAttachDeviceToDeviceStackSafe() is not required in AddDevice routine and is also unavailable on Windows 2000 SP4 + if (!Extension->LowerDeviceObject) + { + status = STATUS_DEVICE_REMOVED; + goto err; + } + + Extension->IsDriveFilterDevice = Extension->Queue.IsFilterDevice = TRUE; + Extension->DeviceObject = Extension->Queue.DeviceObject = filterDeviceObject; + Extension->Pdo = pdo; + + Extension->Queue.LowerDeviceObject = Extension->LowerDeviceObject; + IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0); + + Extension->ConfiguredEncryptedAreaStart = -1; + Extension->ConfiguredEncryptedAreaEnd = -1; + Extension->Queue.EncryptedAreaStart = -1; + Extension->Queue.EncryptedAreaEnd = -1; + + filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE); + filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + DeviceFilterActive = TRUE; + return status; + +err: + if (filterDeviceObject) + { + if (Extension->LowerDeviceObject) + IoDetachDevice (Extension->LowerDeviceObject); + + DriverMutexWait(); + IoDeleteDevice (filterDeviceObject); + DriverMutexRelease(); + } + + return status; +} + + +static void DismountDrive (DriveFilterExtension *Extension, BOOL stopIoQueue) +{ + Dump ("Dismounting drive\n"); + ASSERT (Extension->DriveMounted); + + if (stopIoQueue && EncryptedIoQueueIsRunning (&Extension->Queue)) + EncryptedIoQueueStop (&Extension->Queue); + + crypto_close (Extension->Queue.CryptoInfo); + Extension->Queue.CryptoInfo = NULL; + + crypto_close (Extension->HeaderCryptoInfo); + Extension->HeaderCryptoInfo = NULL; + + Extension->DriveMounted = FALSE; +} + + +static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, uint32 *headerSaltCrc32) +{ + BOOL hiddenVolume = (BootArgs.HiddenSystemPartitionStart != 0); + int64 hiddenHeaderOffset = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; + NTSTATUS status; + LARGE_INTEGER offset; + char *header; + + Dump ("MountDrive pdo=%p\n", Extension->Pdo); + ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); + + header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + if (!header) + return STATUS_INSUFFICIENT_RESOURCES; + + offset.QuadPart = hiddenVolume ? hiddenHeaderOffset : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + Dump ("Reading volume header at %I64u\n", offset.QuadPart); + + status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + if (!NT_SUCCESS (status)) + { + Dump ("TCReadDevice error %x\n", status); + goto ret; + } + + if (headerSaltCrc32) + { + uint32 saltCrc = GetCrc32 (header, PKCS5_SALT_SIZE); + + if (saltCrc != *headerSaltCrc32) + { + status = STATUS_UNSUCCESSFUL; + goto ret; + } + + Extension->VolumeHeaderSaltCrc32 = saltCrc; + } + + Extension->HeaderCryptoInfo = crypto_open(); + if (!Extension->HeaderCryptoInfo) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto ret; + } + + if (ReadVolumeHeader (!hiddenVolume, header, password, &Extension->Queue.CryptoInfo, Extension->HeaderCryptoInfo) == 0) + { + // Header decrypted + status = STATUS_SUCCESS; + Dump ("Header decrypted\n"); + + if (Extension->Queue.CryptoInfo->hiddenVolume) + { + int64 hiddenPartitionOffset = BootArgs.HiddenSystemPartitionStart; + Dump ("Hidden volume start offset = %I64d\n", Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + hiddenPartitionOffset); + + Extension->HiddenSystem = TRUE; + + Extension->Queue.RemapEncryptedArea = TRUE; + Extension->Queue.RemappedAreaOffset = hiddenPartitionOffset + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value - BootArgs.DecoySystemPartitionStart; + Extension->Queue.RemappedAreaDataUnitOffset = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value / ENCRYPTION_DATA_UNIT_SIZE - BootArgs.DecoySystemPartitionStart / ENCRYPTION_DATA_UNIT_SIZE; + + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value = BootArgs.DecoySystemPartitionStart; + + if (Extension->Queue.CryptoInfo->VolumeSize.Value > hiddenPartitionOffset - BootArgs.DecoySystemPartitionStart) + TC_THROW_FATAL_EXCEPTION; + + Dump ("RemappedAreaOffset = %I64d\n", Extension->Queue.RemappedAreaOffset); + Dump ("RemappedAreaDataUnitOffset = %I64d\n", Extension->Queue.RemappedAreaDataUnitOffset); + } + else + { + Extension->HiddenSystem = FALSE; + Extension->Queue.RemapEncryptedArea = FALSE; + } + + Extension->ConfiguredEncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value; + Extension->ConfiguredEncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->VolumeSize.Value - 1; + + Extension->Queue.EncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value; + Extension->Queue.EncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->EncryptedAreaLength.Value - 1; + + if (Extension->Queue.CryptoInfo->EncryptedAreaLength.Value == 0) + { + Extension->Queue.EncryptedAreaStart = -1; + Extension->Queue.EncryptedAreaEnd = -1; + } + + Dump ("Loaded: ConfiguredEncryptedAreaStart=%I64d (%I64d) ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd); + Dump ("Loaded: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd); + + // Erase boot loader scheduled keys + if (BootArgs.CryptoInfoLength > 0) + { + PHYSICAL_ADDRESS cryptoInfoAddress; + byte *mappedCryptoInfo; + + cryptoInfoAddress.QuadPart = (BootLoaderSegment << 4) + BootArgs.CryptoInfoOffset; + mappedCryptoInfo = MmMapIoSpace (cryptoInfoAddress, BootArgs.CryptoInfoLength, MmCached); + + if (mappedCryptoInfo) + { + Dump ("Wiping memory %x %d\n", cryptoInfoAddress.LowPart, BootArgs.CryptoInfoLength); + memset (mappedCryptoInfo, 0, BootArgs.CryptoInfoLength); + MmUnmapIoSpace (mappedCryptoInfo, BootArgs.CryptoInfoLength); + } + } + + BootDriveFilterExtension = Extension; + BootDriveFound = Extension->BootDrive = Extension->DriveMounted = Extension->VolumeHeaderPresent = TRUE; + + burn (&BootArgs.BootPassword, sizeof (BootArgs.BootPassword)); + + // Get drive length + status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &BootDriveLength, sizeof (BootDriveLength)); + + if (!NT_SUCCESS (status)) + { + Dump ("Failed to get drive length - error %x\n", status); + BootDriveLength.QuadPart = 0; + Extension->Queue.MaxReadAheadOffset.QuadPart = _I64_MAX; + } + else + Extension->Queue.MaxReadAheadOffset = BootDriveLength; + + status = EncryptedIoQueueStart (&Extension->Queue); + if (!NT_SUCCESS (status)) + TC_BUG_CHECK (status); + + if (!HibernationDriverFilterActive) + StartHibernationDriverFilter(); + } + else + { + Dump ("Header not decrypted\n"); + crypto_close (Extension->HeaderCryptoInfo); + Extension->HeaderCryptoInfo = NULL; + + status = STATUS_UNSUCCESSFUL; + } + +ret: + TCfree (header); + return status; +} + + +static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension) +{ + NTSTATUS status = STATUS_SUCCESS; + LARGE_INTEGER offset; + byte *header; + + header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + if (!header) + return STATUS_INSUFFICIENT_RESOURCES; + + offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + + status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + if (!NT_SUCCESS (status)) + { + Dump ("TCReadDevice error %x", status); + goto ret; + } + + Dump ("Saving: ConfiguredEncryptedAreaStart=%I64d (%I64d) ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd); + Dump ("Saving: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd); + + if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1 + || Extension->Queue.EncryptedAreaEnd <= Extension->Queue.EncryptedAreaStart) + { + if (SetupRequest.SetupMode == SetupDecryption) + { + memset (header, 0, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + Extension->VolumeHeaderPresent = FALSE; + } + } + else + { + uint32 headerCrc32; + uint64 encryptedAreaLength = Extension->Queue.EncryptedAreaEnd + 1 - Extension->Queue.EncryptedAreaStart; + byte *fieldPos = header + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH; + + DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo); + + if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545) + { + Dump ("Header not decrypted"); + status = STATUS_UNKNOWN_REVISION; + goto ret; + } + + mputInt64 (fieldPos, encryptedAreaLength); + + headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); + fieldPos = header + TC_HEADER_OFFSET_HEADER_CRC; + mputLong (fieldPos, headerCrc32); + + EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo); + } + + status = TCWriteDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + if (!NT_SUCCESS (status)) + { + Dump ("TCWriteDevice error %x", status); + goto ret; + } + +ret: + TCfree (header); + return status; +} + + +static NTSTATUS PassIrp (PDEVICE_OBJECT deviceObject, PIRP irp) +{ + IoSkipCurrentIrpStackLocation (irp); + return IoCallDriver (deviceObject, irp); +} + + +static NTSTATUS PassFilteredIrp (PDEVICE_OBJECT deviceObject, PIRP irp, PIO_COMPLETION_ROUTINE completionRoutine, PVOID completionRoutineArg) +{ + IoCopyCurrentIrpStackLocationToNext (irp); + + if (completionRoutine) + IoSetCompletionRoutine (irp, completionRoutine, completionRoutineArg, TRUE, TRUE, TRUE); + + return IoCallDriver (deviceObject, irp); +} + + +static NTSTATUS OnDeviceUsageNotificationCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, DriveFilterExtension *Extension) +{ + if (Irp->PendingReturned) + IoMarkIrpPending (Irp); + + if (!(Extension->LowerDeviceObject->Flags & DO_POWER_PAGABLE)) + filterDeviceObject->Flags &= ~DO_POWER_PAGABLE; + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return STATUS_CONTINUE_COMPLETION; +} + + +static BOOL IsVolumeDevice (PDEVICE_OBJECT deviceObject) +{ + VOLUME_NUMBER volNumber; + VOLUME_DISK_EXTENTS extents[2]; + NTSTATUS extentStatus = SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, extents, sizeof (extents)); + + return NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_SUPPORTS_ONLINE_OFFLINE, NULL, 0, NULL, 0)) + || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_OFFLINE, NULL, 0, NULL, 0)) + || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_IO_CAPABLE, NULL, 0, NULL, 0)) + || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_PARTITION, NULL, 0, NULL, 0)) + || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_QUERY_VOLUME_NUMBER, NULL, 0, &volNumber, sizeof (volNumber))) + || NT_SUCCESS (extentStatus) || extentStatus == STATUS_BUFFER_OVERFLOW || extentStatus == STATUS_BUFFER_TOO_SMALL; +} + + +static void CheckDeviceTypeAndMount (DriveFilterExtension *filterExtension) +{ + if (BootArgsValid) + { + // Windows sometimes merges a removable drive PDO and its volume PDO to a single PDO having no volume interface (GUID_DEVINTERFACE_VOLUME). + // Therefore, we need to test whether the device supports volume IOCTLs. + if (VolumeClassFilterRegistered + && BootArgs.HiddenSystemPartitionStart != 0 + && IsVolumeDevice (filterExtension->LowerDeviceObject)) + { + Dump ("Drive and volume merged pdo=%p", filterExtension->Pdo); + + filterExtension->IsVolumeFilterDevice = TRUE; + filterExtension->IsDriveFilterDevice = FALSE; + } + else if (!BootDriveFound) + { + DriverMutexWait(); + MountDrive (filterExtension, &BootArgs.BootPassword, &BootArgs.HeaderSaltCrc32); + DriverMutexRelease(); + } + } +} + + +static VOID MountDriveWorkItemRoutine (PDEVICE_OBJECT deviceObject, DriveFilterExtension *filterExtension) +{ + CheckDeviceTypeAndMount (filterExtension); + KeSetEvent (&filterExtension->MountWorkItemCompletedEvent, IO_NO_INCREMENT, FALSE); +} + + +static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, DriveFilterExtension *Extension) +{ + if (Irp->PendingReturned) + IoMarkIrpPending (Irp); + + if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; + + if (KeGetCurrentIrql() == PASSIVE_LEVEL) + { + CheckDeviceTypeAndMount (Extension); + } + else + { + PIO_WORKITEM workItem = IoAllocateWorkItem (filterDeviceObject); + if (!workItem) + { + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return STATUS_INSUFFICIENT_RESOURCES; + } + + KeInitializeEvent (&Extension->MountWorkItemCompletedEvent, SynchronizationEvent, FALSE); + IoQueueWorkItem (workItem, MountDriveWorkItemRoutine, DelayedWorkQueue, Extension); + + KeWaitForSingleObject (&Extension->MountWorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL); + IoFreeWorkItem (workItem); + } + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return STATUS_CONTINUE_COMPLETION; +} + + +static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp) +{ + NTSTATUS status; + + status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (status)) + return TCCompleteIrp (Irp, status, 0); + + switch (irpSp->MinorFunction) + { + case IRP_MN_START_DEVICE: + Dump ("IRP_MN_START_DEVICE pdo=%p\n", Extension->Pdo); + return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension); + + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + Dump ("IRP_MN_DEVICE_USAGE_NOTIFICATION type=%d\n", (int) irpSp->Parameters.UsageNotification.Type); + + { + PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject); + + if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE)) + DeviceObject->Flags |= DO_POWER_PAGABLE; + + ObDereferenceObject (attachedDevice); + } + + // Prevent creation of hibernation and crash dump files + if (irpSp->Parameters.UsageNotification.InPath + && (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile + || (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation && !HibernationDriverFilterActive))) + { + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + + if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) + ++HibernationPreventionCount; + + return TCCompleteIrp (Irp, STATUS_UNSUCCESSFUL, 0); + } + + return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension); + + + case IRP_MN_REMOVE_DEVICE: + Dump ("IRP_MN_REMOVE_DEVICE pdo=%p\n", Extension->Pdo); + + IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp); + status = PassIrp (Extension->LowerDeviceObject, Irp); + + IoDetachDevice (Extension->LowerDeviceObject); + + DriverMutexWait(); + + if (Extension->DriveMounted) + DismountDrive (Extension, TRUE); + + if (Extension->BootDrive) + { + BootDriveFound = FALSE; + BootDriveFilterExtension = NULL; + } + + IoDeleteDevice (DeviceObject); + + DriverMutexRelease(); + + return status; + + + default: + status = PassIrp (Extension->LowerDeviceObject, Irp); + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + } + return status; +} + + +static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp) +{ + NTSTATUS status; + Dump ("IRP_MJ_POWER minor=%d type=%d shutdown=%d\n", (int) irpSp->MinorFunction, (int) irpSp->Parameters.Power.Type, (int) irpSp->Parameters.Power.ShutdownType); + + if (SetupInProgress + && irpSp->MinorFunction == IRP_MN_SET_POWER + && irpSp->Parameters.Power.ShutdownType == PowerActionHibernate) + { + AbortBootEncryptionSetup(); + } + +#if 0 // Dismount of the system drive is disabled until there is a way to do it without causing system errors (see the documentation for more info) + if (DriverShuttingDown + && Extension->BootDrive + && Extension->DriveMounted + && irpSp->MinorFunction == IRP_MN_SET_POWER + && irpSp->Parameters.Power.Type == DevicePowerState) + { + DriverMutexWait(); + DismountDrive (Extension, TRUE); + DriverMutexRelease(); + } +#endif // 0 + + PoStartNextPowerIrp (Irp); + + status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (status)) + return TCCompleteIrp (Irp, status, 0); + + IoSkipCurrentIrpStackLocation (Irp); + status = PoCallDriver (Extension->LowerDeviceObject, Irp); + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return status; +} + + +NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DriveFilterExtension *Extension = (DriveFilterExtension *) DeviceObject->DeviceExtension; + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + NTSTATUS status; + + ASSERT (!Extension->bRootDevice && Extension->IsDriveFilterDevice); + + switch (irpSp->MajorFunction) + { + case IRP_MJ_READ: + case IRP_MJ_WRITE: + if (Extension->BootDrive) + { + status = EncryptedIoQueueAddIrp (&Extension->Queue, Irp); + + if (status != STATUS_PENDING) + TCCompleteDiskIrp (Irp, status, 0); + + return status; + } + break; + + case IRP_MJ_PNP: + return DispatchPnp (DeviceObject, Irp, Extension, irpSp); + + case IRP_MJ_POWER: + return DispatchPower (DeviceObject, Irp, Extension, irpSp); + } + + status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (status)) + return TCCompleteIrp (Irp, status, 0); + + status = PassIrp (Extension->LowerDeviceObject, Irp); + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return status; +} + + +void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp) +{ + LARGE_INTEGER offset; + char *header; + ReopenBootVolumeHeaderRequest *request = (ReopenBootVolumeHeaderRequest *) irp->AssociatedIrp.SystemBuffer; + + irp->IoStatus.Information = 0; + + if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice()) + { + irp->IoStatus.Status = STATUS_ACCESS_DENIED; + return; + } + + if (!ValidateIOBufferSize (irp, sizeof (ReopenBootVolumeHeaderRequest), ValidateInput)) + return; + + if (!BootDriveFound || !BootDriveFilterExtension || !BootDriveFilterExtension->DriveMounted || !BootDriveFilterExtension->HeaderCryptoInfo + || request->VolumePassword.Length > MAX_PASSWORD) + { + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + goto wipe; + } + + header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + if (!header) + { + irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + goto wipe; + } + + if (BootDriveFilterExtension->HiddenSystem) + offset.QuadPart = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; + else + offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + + irp->IoStatus.Status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); + if (!NT_SUCCESS (irp->IoStatus.Status)) + { + Dump ("TCReadDevice error %x\n", irp->IoStatus.Status); + goto ret; + } + + if (ReadVolumeHeader (!BootDriveFilterExtension->HiddenSystem, header, &request->VolumePassword, NULL, BootDriveFilterExtension->HeaderCryptoInfo) == 0) + { + Dump ("Header reopened\n"); + + BootDriveFilterExtension->Queue.CryptoInfo->header_creation_time = BootDriveFilterExtension->HeaderCryptoInfo->header_creation_time; + BootDriveFilterExtension->Queue.CryptoInfo->pkcs5 = BootDriveFilterExtension->HeaderCryptoInfo->pkcs5; + BootDriveFilterExtension->Queue.CryptoInfo->noIterations = BootDriveFilterExtension->HeaderCryptoInfo->noIterations; + + irp->IoStatus.Status = STATUS_SUCCESS; + } + else + { + crypto_close (BootDriveFilterExtension->HeaderCryptoInfo); + BootDriveFilterExtension->HeaderCryptoInfo = NULL; + + Dump ("Header not reopened\n"); + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + } + +ret: + TCfree (header); +wipe: + burn (request, sizeof (*request)); +} + + +typedef NTSTATUS (*HiberDriverWriteFunctionA) (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3); +typedef NTSTATUS (*HiberDriverWriteFunctionB) (PLARGE_INTEGER writeOffset, PMDL dataMdl); + +typedef struct +{ + // Until MS releases an API for filtering hibernation drivers, we have to resort to this. +#ifdef _WIN64 + byte FieldPad1[64]; + HiberDriverWriteFunctionB WriteFunctionB; + byte FieldPad2[56]; +#else + byte FieldPad1[48]; + HiberDriverWriteFunctionB WriteFunctionB; + byte FieldPad2[32]; +#endif + HiberDriverWriteFunctionA WriteFunctionA; + byte FieldPad3[24]; + LARGE_INTEGER PartitionStartOffset; +} HiberDriverContext; + +typedef NTSTATUS (*HiberDriverEntry) (PVOID arg0, HiberDriverContext *hiberDriverContext); + +typedef struct +{ + LIST_ENTRY ModuleList; +#ifdef _WIN64 + byte FieldPad1[32]; +#else + byte FieldPad1[16]; +#endif + PVOID ModuleBaseAddress; + HiberDriverEntry ModuleEntryAddress; +#ifdef _WIN64 + byte FieldPad2[24]; +#else + byte FieldPad2[12]; +#endif + UNICODE_STRING ModuleName; +} ModuleTableItem; + + +#define TC_MAX_HIBER_FILTER_COUNT 3 +static int LastHiberFilterNumber = 0; + +static HiberDriverEntry OriginalHiberDriverEntries[TC_MAX_HIBER_FILTER_COUNT]; +static HiberDriverWriteFunctionA OriginalHiberDriverWriteFunctionsA[TC_MAX_HIBER_FILTER_COUNT]; +static HiberDriverWriteFunctionB OriginalHiberDriverWriteFunctionsB[TC_MAX_HIBER_FILTER_COUNT]; + +static LARGE_INTEGER HiberPartitionOffset; + + +static NTSTATUS HiberDriverWriteFunctionFilter (int filterNumber, PLARGE_INTEGER writeOffset, PMDL dataMdl, BOOL writeB, ULONG arg0WriteA, PVOID arg3WriteA) +{ + MDL *encryptedDataMdl = dataMdl; + + if (writeOffset && dataMdl && BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted) + { + ULONG dataLength = MmGetMdlByteCount (dataMdl); + + if (dataMdl->MappedSystemVa && dataLength > 0) + { + uint64 offset = HiberPartitionOffset.QuadPart + writeOffset->QuadPart; + uint64 intersectStart; + uint32 intersectLength; + + if (dataLength > TC_HIBERNATION_WRITE_BUFFER_SIZE) + TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW); + + if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + + if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + + GetIntersection (offset, + dataLength, + BootDriveFilterExtension->Queue.EncryptedAreaStart, + BootDriveFilterExtension->Queue.EncryptedAreaEnd, + &intersectStart, + &intersectLength); + + if (intersectLength > 0) + { + UINT64_STRUCT dataUnit; + dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE; + + memcpy (HibernationWriteBuffer, dataMdl->MappedSystemVa, dataLength); + + if (BootDriveFilterExtension->Queue.RemapEncryptedArea) + dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset; + + EncryptDataUnitsCurrentThread (HibernationWriteBuffer + (intersectStart - offset), + &dataUnit, + intersectLength / ENCRYPTION_DATA_UNIT_SIZE, + BootDriveFilterExtension->Queue.CryptoInfo); + + encryptedDataMdl = HibernationWriteBufferMdl; + MmInitializeMdl (encryptedDataMdl, HibernationWriteBuffer, dataLength); + encryptedDataMdl->MdlFlags = dataMdl->MdlFlags; + } + } + } + + if (writeB) + return (*OriginalHiberDriverWriteFunctionsB[filterNumber]) (writeOffset, encryptedDataMdl); + + return (*OriginalHiberDriverWriteFunctionsA[filterNumber]) (arg0WriteA, writeOffset, encryptedDataMdl, arg3WriteA); +} + + +static NTSTATUS HiberDriverWriteFunctionAFilter0 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3) +{ + return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, FALSE, arg0, arg3); +} + +static NTSTATUS HiberDriverWriteFunctionAFilter1 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3) +{ + return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, FALSE, arg0, arg3); +} + +static NTSTATUS HiberDriverWriteFunctionAFilter2 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3) +{ + return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, FALSE, arg0, arg3); +} + + +static NTSTATUS HiberDriverWriteFunctionBFilter0 (PLARGE_INTEGER writeOffset, PMDL dataMdl) +{ + return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, TRUE, 0, NULL); +} + +static NTSTATUS HiberDriverWriteFunctionBFilter1 (PLARGE_INTEGER writeOffset, PMDL dataMdl) +{ + return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, TRUE, 0, NULL); +} + +static NTSTATUS HiberDriverWriteFunctionBFilter2 (PLARGE_INTEGER writeOffset, PMDL dataMdl) +{ + return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, TRUE, 0, NULL); +} + + +static NTSTATUS HiberDriverEntryFilter (int filterNumber, PVOID arg0, HiberDriverContext *hiberDriverContext) +{ + BOOL filterInstalled = FALSE; + NTSTATUS status; + + if (!OriginalHiberDriverEntries[filterNumber]) + return STATUS_UNSUCCESSFUL; + + status = (*OriginalHiberDriverEntries[filterNumber]) (arg0, hiberDriverContext); + + if (!NT_SUCCESS (status) || !hiberDriverContext) + return status; + + if (SetupInProgress) + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + + if (hiberDriverContext->WriteFunctionA) + { + Dump ("Filtering WriteFunctionA %d\n", filterNumber); + OriginalHiberDriverWriteFunctionsA[filterNumber] = hiberDriverContext->WriteFunctionA; + + switch (filterNumber) + { + case 0: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter0; break; + case 1: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter1; break; + case 2: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter2; break; + default: TC_THROW_FATAL_EXCEPTION; + } + + filterInstalled = TRUE; + } + + if (hiberDriverContext->WriteFunctionB) + { + Dump ("Filtering WriteFunctionB %d\n", filterNumber); + OriginalHiberDriverWriteFunctionsB[filterNumber] = hiberDriverContext->WriteFunctionB; + + switch (filterNumber) + { + case 0: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter0; break; + case 1: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter1; break; + case 2: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter2; break; + default: TC_THROW_FATAL_EXCEPTION; + } + + filterInstalled = TRUE; + } + + if (filterInstalled && hiberDriverContext->PartitionStartOffset.QuadPart != 0) + { + HiberPartitionOffset = hiberDriverContext->PartitionStartOffset; + + if (BootDriveFilterExtension->Queue.RemapEncryptedArea) + hiberDriverContext->PartitionStartOffset.QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset; + } + + return STATUS_SUCCESS; +} + + +static NTSTATUS HiberDriverEntryFilter0 (PVOID arg0, HiberDriverContext *hiberDriverContext) +{ + return HiberDriverEntryFilter (0, arg0, hiberDriverContext); +} + + +static NTSTATUS HiberDriverEntryFilter1 (PVOID arg0, HiberDriverContext *hiberDriverContext) +{ + return HiberDriverEntryFilter (1, arg0, hiberDriverContext); +} + + +static NTSTATUS HiberDriverEntryFilter2 (PVOID arg0, HiberDriverContext *hiberDriverContext) +{ + return HiberDriverEntryFilter (2, arg0, hiberDriverContext); +} + + +static VOID LoadImageNotifyRoutine (PUNICODE_STRING fullImageName, HANDLE processId, PIMAGE_INFO imageInfo) +{ + ModuleTableItem *moduleItem; + LIST_ENTRY *listEntry; + KIRQL origIrql; + + if (!imageInfo || !imageInfo->SystemModeImage || !imageInfo->ImageBase || !TCDriverObject->DriverSection) + return; + + moduleItem = *(ModuleTableItem **) TCDriverObject->DriverSection; + if (!moduleItem || !moduleItem->ModuleList.Flink) + return; + + // Search loaded system modules for hibernation driver + origIrql = KeRaiseIrqlToDpcLevel(); + + for (listEntry = moduleItem->ModuleList.Flink->Blink; + listEntry && listEntry != TCDriverObject->DriverSection; + listEntry = listEntry->Flink) + { + moduleItem = CONTAINING_RECORD (listEntry, ModuleTableItem, ModuleList); + + if (moduleItem && imageInfo->ImageBase == moduleItem->ModuleBaseAddress) + { + if (moduleItem->ModuleName.Buffer && moduleItem->ModuleName.Length >= 5 * sizeof (wchar_t)) + { + // Skip MS BitLocker filter + if (moduleItem->ModuleName.Length >= 13 * sizeof (wchar_t) + && memcmp (moduleItem->ModuleName.Buffer, L"hiber_dumpfve", 13 * sizeof (wchar_t)) == 0) + break; + + if (memcmp (moduleItem->ModuleName.Buffer, L"hiber", 5 * sizeof (wchar_t)) == 0 + || memcmp (moduleItem->ModuleName.Buffer, L"Hiber", 5 * sizeof (wchar_t)) == 0 + || memcmp (moduleItem->ModuleName.Buffer, L"HIBER", 5 * sizeof (wchar_t)) == 0) + { + HiberDriverEntry filterEntry; + + switch (LastHiberFilterNumber) + { + case 0: filterEntry = HiberDriverEntryFilter0; break; + case 1: filterEntry = HiberDriverEntryFilter1; break; + case 2: filterEntry = HiberDriverEntryFilter2; break; + default: TC_THROW_FATAL_EXCEPTION; + } + + if (moduleItem->ModuleEntryAddress != filterEntry) + { + // Install filter + OriginalHiberDriverEntries[LastHiberFilterNumber] = moduleItem->ModuleEntryAddress; + moduleItem->ModuleEntryAddress = filterEntry; + + if (++LastHiberFilterNumber > TC_MAX_HIBER_FILTER_COUNT - 1) + LastHiberFilterNumber = 0; + } + } + } + break; + } + } + + KeLowerIrql (origIrql); +} + + +void StartHibernationDriverFilter () +{ + PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr; + NTSTATUS status; + + ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); + + // Hidden system hibernation is not supported if an extra boot partition is present as the system is not allowed to update the boot partition + if (IsHiddenSystemRunning() && (BootArgs.Flags & TC_BOOT_ARGS_FLAG_EXTRA_BOOT_PARTITION)) + return; + + if (!TCDriverObject->DriverSection || !*(ModuleTableItem **) TCDriverObject->DriverSection) + goto err; + + // All buffers required for hibernation must be allocated here +#ifdef _WIN64 + highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFULL; +#else + highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFULL; +#endif + + HibernationWriteBuffer = MmAllocateContiguousMemory (TC_HIBERNATION_WRITE_BUFFER_SIZE, highestAcceptableWriteBufferAddr); + if (!HibernationWriteBuffer) + goto err; + + HibernationWriteBufferMdl = IoAllocateMdl (HibernationWriteBuffer, TC_HIBERNATION_WRITE_BUFFER_SIZE, FALSE, FALSE, NULL); + if (!HibernationWriteBufferMdl) + goto err; + + MmBuildMdlForNonPagedPool (HibernationWriteBufferMdl); + + status = PsSetLoadImageNotifyRoutine (LoadImageNotifyRoutine); + if (!NT_SUCCESS (status)) + goto err; + + HibernationDriverFilterActive = TRUE; + return; + +err: + HibernationDriverFilterActive = FALSE; + + if (HibernationWriteBufferMdl) + { + IoFreeMdl (HibernationWriteBufferMdl); + HibernationWriteBufferMdl = NULL; + } + + if (HibernationWriteBuffer) + { + MmFreeContiguousMemory (HibernationWriteBuffer); + HibernationWriteBuffer = NULL; + } +} + + +static VOID SetupThreadProc (PVOID threadArg) +{ + DriveFilterExtension *Extension = BootDriveFilterExtension; + + LARGE_INTEGER offset; + UINT64_STRUCT dataUnit; + ULONG setupBlockSize = TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE; + BOOL headerUpdateRequired = FALSE; + int64 bytesWrittenSinceHeaderUpdate = 0; + + byte *buffer = NULL; + byte *wipeBuffer = NULL; + byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT]; + byte wipeRandCharsUpdate[TC_WIPE_RAND_CHAR_COUNT]; + + KIRQL irql; + NTSTATUS status; + + SetupResult = STATUS_UNSUCCESSFUL; + + // Make sure volume header can be updated + if (Extension->HeaderCryptoInfo == NULL) + { + SetupResult = STATUS_INVALID_PARAMETER; + goto ret; + } + + buffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); + if (!buffer) + { + SetupResult = STATUS_INSUFFICIENT_RESOURCES; + goto ret; + } + + if (SetupRequest.SetupMode == SetupEncryption && SetupRequest.WipeAlgorithm != TC_WIPE_NONE) + { + wipeBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); + if (!wipeBuffer) + { + SetupResult = STATUS_INSUFFICIENT_RESOURCES; + goto ret; + } + } + + while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 1000))) + { + if (EncryptionSetupThreadAbortRequested) + goto abort; + + TransformWaitingForIdle = TRUE; + } + TransformWaitingForIdle = FALSE; + + switch (SetupRequest.SetupMode) + { + case SetupEncryption: + Dump ("Encrypting...\n"); + if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1) + { + // Start encryption + Extension->Queue.EncryptedAreaStart = Extension->ConfiguredEncryptedAreaStart; + Extension->Queue.EncryptedAreaEnd = -1; + offset.QuadPart = Extension->ConfiguredEncryptedAreaStart; + } + else + { + // Resume aborted encryption + if (Extension->Queue.EncryptedAreaEnd == Extension->ConfiguredEncryptedAreaEnd) + goto err; + + offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1; + } + + break; + + case SetupDecryption: + Dump ("Decrypting...\n"); + if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1) + { + SetupResult = STATUS_SUCCESS; + goto abort; + } + + offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1; + break; + + default: + goto err; + } + + EncryptedIoQueueResumeFromHold (&Extension->Queue); + + Dump ("EncryptedAreaStart=%I64d\n", Extension->Queue.EncryptedAreaStart); + Dump ("EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaEnd); + Dump ("ConfiguredEncryptedAreaStart=%I64d\n", Extension->ConfiguredEncryptedAreaStart); + Dump ("ConfiguredEncryptedAreaEnd=%I64d\n", Extension->ConfiguredEncryptedAreaEnd); + Dump ("offset=%I64d\n", offset.QuadPart); + Dump ("EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024); + + while (!EncryptionSetupThreadAbortRequested) + { + if (SetupRequest.SetupMode == SetupEncryption) + { + if (offset.QuadPart + setupBlockSize > Extension->ConfiguredEncryptedAreaEnd + 1) + setupBlockSize = (ULONG) (Extension->ConfiguredEncryptedAreaEnd + 1 - offset.QuadPart); + + if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd) + break; + } + else + { + if (offset.QuadPart - setupBlockSize < Extension->Queue.EncryptedAreaStart) + setupBlockSize = (ULONG) (offset.QuadPart - Extension->Queue.EncryptedAreaStart); + + offset.QuadPart -= setupBlockSize; + + if (setupBlockSize == 0 || offset.QuadPart < Extension->Queue.EncryptedAreaStart) + break; + } + + while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 500))) + { + if (EncryptionSetupThreadAbortRequested) + goto abort; + + TransformWaitingForIdle = TRUE; + } + TransformWaitingForIdle = FALSE; + + status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); + if (!NT_SUCCESS (status)) + { + Dump ("TCReadDevice error %x offset=%I64d\n", status, offset.QuadPart); + + if (SetupRequest.ZeroUnreadableSectors && SetupRequest.SetupMode == SetupEncryption) + { + // Zero unreadable sectors + uint64 zeroedSectorCount; + + status = ZeroUnreadableSectors (BootDriveFilterExtension->LowerDeviceObject, offset, setupBlockSize, &zeroedSectorCount); + if (!NT_SUCCESS (status)) + { + SetupResult = status; + goto err; + } + + // Retry read + status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); + if (!NT_SUCCESS (status)) + { + SetupResult = status; + goto err; + } + } + else if (SetupRequest.DiscardUnreadableEncryptedSectors && SetupRequest.SetupMode == SetupDecryption) + { + // Discard unreadable encrypted sectors + uint64 badSectorCount; + + status = ReadDeviceSkipUnreadableSectors (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize, &badSectorCount); + if (!NT_SUCCESS (status)) + { + SetupResult = status; + goto err; + } + } + else + { + SetupResult = status; + goto err; + } + } + + dataUnit.Value = offset.QuadPart / ENCRYPTION_DATA_UNIT_SIZE; + + if (SetupRequest.SetupMode == SetupEncryption) + { + EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); + + if (SetupRequest.WipeAlgorithm != TC_WIPE_NONE) + { + byte wipePass; + for (wipePass = 1; wipePass <= GetWipePassCount (SetupRequest.WipeAlgorithm); ++wipePass) + { + if (!WipeBuffer (SetupRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, setupBlockSize)) + { + ULONG i; + for (i = 0; i < setupBlockSize; ++i) + { + wipeBuffer[i] = buffer[i] + wipePass; + } + + EncryptDataUnits (wipeBuffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); + memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); + } + + status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, setupBlockSize); + if (!NT_SUCCESS (status)) + { + // Undo failed write operation + DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); + TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); + + SetupResult = status; + goto err; + } + } + + memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate)); + } + } + else + { + DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); + } + + status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); + if (!NT_SUCCESS (status)) + { + Dump ("TCWriteDevice error %x\n", status); + + // Undo failed write operation + if (SetupRequest.SetupMode == SetupEncryption) + DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); + else + EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); + + TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize); + + SetupResult = status; + goto err; + } + + if (SetupRequest.SetupMode == SetupEncryption) + offset.QuadPart += setupBlockSize; + + Extension->Queue.EncryptedAreaEnd = offset.QuadPart - 1; + headerUpdateRequired = TRUE; + + EncryptedIoQueueResumeFromHold (&Extension->Queue); + + KeAcquireSpinLock (&SetupStatusSpinLock, &irql); + SetupStatusEncryptedAreaEnd = Extension->Queue.EncryptedAreaEnd; + KeReleaseSpinLock (&SetupStatusSpinLock, irql); + + // Update volume header + bytesWrittenSinceHeaderUpdate += setupBlockSize; + if (bytesWrittenSinceHeaderUpdate >= TC_ENCRYPTION_SETUP_HEADER_UPDATE_THRESHOLD) + { + status = SaveDriveVolumeHeader (Extension); + ASSERT (NT_SUCCESS (status)); + + headerUpdateRequired = FALSE; + bytesWrittenSinceHeaderUpdate = 0; + } + } + +abort: + SetupResult = STATUS_SUCCESS; +err: + + if (Extension->Queue.EncryptedAreaEnd == -1) + Extension->Queue.EncryptedAreaStart = -1; + + if (EncryptedIoQueueIsSuspended (&Extension->Queue)) + EncryptedIoQueueResumeFromHold (&Extension->Queue); + + if (SetupRequest.SetupMode == SetupDecryption && Extension->Queue.EncryptedAreaStart >= Extension->Queue.EncryptedAreaEnd) + { + while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 0))); + + Extension->ConfiguredEncryptedAreaStart = Extension->ConfiguredEncryptedAreaEnd = -1; + Extension->Queue.EncryptedAreaStart = Extension->Queue.EncryptedAreaEnd = -1; + + EncryptedIoQueueResumeFromHold (&Extension->Queue); + + headerUpdateRequired = TRUE; + } + + Dump ("Setup completed: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd); + + if (headerUpdateRequired) + { + status = SaveDriveVolumeHeader (Extension); + + if (!NT_SUCCESS (status) && NT_SUCCESS (SetupResult)) + SetupResult = status; + } + + if (SetupRequest.SetupMode == SetupDecryption && Extension->ConfiguredEncryptedAreaEnd == -1 && Extension->DriveMounted) + { + while (!DriverMutexAcquireNoWait() && !EncryptionSetupThreadAbortRequested) + { + TCSleep (100); + } + + DismountDrive (Extension, FALSE); + + if (!EncryptionSetupThreadAbortRequested) + DriverMutexRelease(); + } + +ret: + if (buffer) + TCfree (buffer); + if (wipeBuffer) + TCfree (wipeBuffer); + + SetupInProgress = FALSE; + PsTerminateSystemThread (SetupResult); +} + + +NTSTATUS StartBootEncryptionSetup (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp) +{ + NTSTATUS status; + + if (!UserCanAccessDriveDevice()) + return STATUS_ACCESS_DENIED; + + if (SetupInProgress || !BootDriveFound || !BootDriveFilterExtension + || !BootDriveFilterExtension->DriveMounted + || BootDriveFilterExtension->HiddenSystem + || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (BootEncryptionSetupRequest)) + return STATUS_INVALID_PARAMETER; + + if (EncryptionSetupThread) + AbortBootEncryptionSetup(); + + SetupRequest = *(BootEncryptionSetupRequest *) irp->AssociatedIrp.SystemBuffer; + + EncryptionSetupThreadAbortRequested = FALSE; + KeInitializeSpinLock (&SetupStatusSpinLock); + SetupStatusEncryptedAreaEnd = BootDriveFilterExtension ? BootDriveFilterExtension->Queue.EncryptedAreaEnd : -1; + + SetupInProgress = TRUE; + status = TCStartThread (SetupThreadProc, DeviceObject, &EncryptionSetupThread); + + if (!NT_SUCCESS (status)) + SetupInProgress = FALSE; + + return status; +} + + +void GetBootDriveVolumeProperties (PIRP irp, PIO_STACK_LOCATION irpSp) +{ + if (ValidateIOBufferSize (irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateOutput)) + { + DriveFilterExtension *Extension = BootDriveFilterExtension; + VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) irp->AssociatedIrp.SystemBuffer; + memset (prop, 0, sizeof (*prop)); + + if (!BootDriveFound || !Extension || !Extension->DriveMounted) + { + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + irp->IoStatus.Information = 0; + } + else + { + prop->hiddenVolume = Extension->Queue.CryptoInfo->hiddenVolume; + prop->diskLength = Extension->ConfiguredEncryptedAreaEnd + 1 - Extension->ConfiguredEncryptedAreaStart; + prop->ea = Extension->Queue.CryptoInfo->ea; + prop->mode = Extension->Queue.CryptoInfo->mode; + prop->pkcs5 = Extension->Queue.CryptoInfo->pkcs5; + prop->pkcs5Iterations = Extension->Queue.CryptoInfo->noIterations; +#if 0 + prop->volumeCreationTime = Extension->Queue.CryptoInfo->volume_creation_time; + prop->headerCreationTime = Extension->Queue.CryptoInfo->header_creation_time; +#endif + prop->volFormatVersion = Extension->Queue.CryptoInfo->LegacyVolume ? TC_VOLUME_FORMAT_VERSION_PRE_6_0 : TC_VOLUME_FORMAT_VERSION; + + prop->totalBytesRead = Extension->Queue.TotalBytesRead; + prop->totalBytesWritten = Extension->Queue.TotalBytesWritten; + + irp->IoStatus.Information = sizeof (VOLUME_PROPERTIES_STRUCT); + irp->IoStatus.Status = STATUS_SUCCESS; + } + } +} + + +void GetBootEncryptionStatus (PIRP irp, PIO_STACK_LOCATION irpSp) +{ + /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */ + + if (ValidateIOBufferSize (irp, sizeof (BootEncryptionStatus), ValidateOutput)) + { + DriveFilterExtension *Extension = BootDriveFilterExtension; + BootEncryptionStatus *bootEncStatus = (BootEncryptionStatus *) irp->AssociatedIrp.SystemBuffer; + memset (bootEncStatus, 0, sizeof (*bootEncStatus)); + + if (BootArgsValid) + bootEncStatus->BootLoaderVersion = BootArgs.BootLoaderVersion; + + bootEncStatus->DeviceFilterActive = DeviceFilterActive; + bootEncStatus->SetupInProgress = SetupInProgress; + bootEncStatus->SetupMode = SetupRequest.SetupMode; + bootEncStatus->TransformWaitingForIdle = TransformWaitingForIdle; + + if (!BootDriveFound || !Extension || !Extension->DriveMounted) + { + bootEncStatus->DriveEncrypted = FALSE; + bootEncStatus->DriveMounted = FALSE; + bootEncStatus->VolumeHeaderPresent = FALSE; + } + else + { + bootEncStatus->DriveMounted = Extension->DriveMounted; + bootEncStatus->VolumeHeaderPresent = Extension->VolumeHeaderPresent; + bootEncStatus->DriveEncrypted = Extension->Queue.EncryptedAreaStart != -1; + bootEncStatus->BootDriveLength = BootDriveLength; + + bootEncStatus->ConfiguredEncryptedAreaStart = Extension->ConfiguredEncryptedAreaStart; + bootEncStatus->ConfiguredEncryptedAreaEnd = Extension->ConfiguredEncryptedAreaEnd; + bootEncStatus->EncryptedAreaStart = Extension->Queue.EncryptedAreaStart; + + if (SetupInProgress) + { + KIRQL irql; + KeAcquireSpinLock (&SetupStatusSpinLock, &irql); + bootEncStatus->EncryptedAreaEnd = SetupStatusEncryptedAreaEnd; + KeReleaseSpinLock (&SetupStatusSpinLock, irql); + } + else + bootEncStatus->EncryptedAreaEnd = Extension->Queue.EncryptedAreaEnd; + + bootEncStatus->VolumeHeaderSaltCrc32 = Extension->VolumeHeaderSaltCrc32; + bootEncStatus->HibernationPreventionCount = HibernationPreventionCount; + bootEncStatus->HiddenSysLeakProtectionCount = HiddenSysLeakProtectionCount; + + bootEncStatus->HiddenSystem = Extension->HiddenSystem; + + if (Extension->HiddenSystem) + bootEncStatus->HiddenSystemPartitionStart = BootArgs.HiddenSystemPartitionStart; + } + + irp->IoStatus.Information = sizeof (BootEncryptionStatus); + irp->IoStatus.Status = STATUS_SUCCESS; + } +} + + +void GetBootLoaderVersion (PIRP irp, PIO_STACK_LOCATION irpSp) +{ + if (ValidateIOBufferSize (irp, sizeof (uint16), ValidateOutput)) + { + if (BootArgsValid) + { + *(uint16 *) irp->AssociatedIrp.SystemBuffer = BootArgs.BootLoaderVersion; + irp->IoStatus.Information = sizeof (uint16); + irp->IoStatus.Status = STATUS_SUCCESS; + } + else + { + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + irp->IoStatus.Information = 0; + } + } +} + + +void GetBootEncryptionAlgorithmName (PIRP irp, PIO_STACK_LOCATION irpSp) +{ + if (ValidateIOBufferSize (irp, sizeof (GetBootEncryptionAlgorithmNameRequest), ValidateOutput)) + { + if (BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted) + { + GetBootEncryptionAlgorithmNameRequest *request = (GetBootEncryptionAlgorithmNameRequest *) irp->AssociatedIrp.SystemBuffer; + EAGetName (request->BootEncryptionAlgorithmName, BootDriveFilterExtension->Queue.CryptoInfo->ea); + + irp->IoStatus.Information = sizeof (GetBootEncryptionAlgorithmNameRequest); + irp->IoStatus.Status = STATUS_SUCCESS; + } + else + { + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + irp->IoStatus.Information = 0; + } + } +} + + +NTSTATUS GetSetupResult() +{ + return SetupResult; +} + + +BOOL IsBootDriveMounted () +{ + return BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted; +} + + +BOOL IsBootEncryptionSetupInProgress () +{ + return SetupInProgress; +} + + +BOOL IsHiddenSystemRunning () +{ + return BootDriveFilterExtension && BootDriveFilterExtension->HiddenSystem; +} + + +CRYPTO_INFO *GetSystemDriveCryptoInfo () +{ + return BootDriveFilterExtension->Queue.CryptoInfo; +} + + +NTSTATUS AbortBootEncryptionSetup () +{ + if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice()) + return STATUS_ACCESS_DENIED; + + DriverMutexWait(); + + if (EncryptionSetupThread) + { + EncryptionSetupThreadAbortRequested = TRUE; + + TCStopThread (EncryptionSetupThread, NULL); + EncryptionSetupThread = NULL; + } + + DriverMutexRelease(); + + return STATUS_SUCCESS; +} + + +static VOID DecoySystemWipeThreadProc (PVOID threadArg) +{ + DriveFilterExtension *Extension = BootDriveFilterExtension; + + LARGE_INTEGER offset; + UINT64_STRUCT dataUnit; + ULONG wipeBlockSize = TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE; + + CRYPTO_INFO *wipeCryptoInfo = NULL; + byte *wipeBuffer = NULL; + byte *wipeRandBuffer = NULL; + byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT]; + int wipePass; + int ea = Extension->Queue.CryptoInfo->ea; + + KIRQL irql; + NTSTATUS status; + + DecoySystemWipeResult = STATUS_UNSUCCESSFUL; + + wipeBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); + if (!wipeBuffer) + { + DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES; + goto ret; + } + + wipeRandBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); + if (!wipeRandBuffer) + { + DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES; + goto ret; + } + + wipeCryptoInfo = crypto_open(); + if (!wipeCryptoInfo) + { + DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES; + goto ret; + } + + wipeCryptoInfo->ea = ea; + wipeCryptoInfo->mode = Extension->Queue.CryptoInfo->mode; + + if (EAInit (ea, WipeDecoyRequest.WipeKey, wipeCryptoInfo->ks) != ERR_SUCCESS) + { + DecoySystemWipeResult = STATUS_INVALID_PARAMETER; + goto ret; + } + + memcpy (wipeCryptoInfo->k2, WipeDecoyRequest.WipeKey + EAGetKeySize (ea), EAGetKeySize (ea)); + + if (!EAInitMode (wipeCryptoInfo)) + { + DecoySystemWipeResult = STATUS_INVALID_PARAMETER; + goto err; + } + + EncryptDataUnits (wipeRandBuffer, &dataUnit, wipeBlockSize / ENCRYPTION_DATA_UNIT_SIZE, wipeCryptoInfo); + memcpy (wipeRandChars, wipeRandBuffer, sizeof (wipeRandChars)); + + burn (WipeDecoyRequest.WipeKey, sizeof (WipeDecoyRequest.WipeKey)); + + offset.QuadPart = Extension->ConfiguredEncryptedAreaStart; + + Dump ("Wiping decoy system: start offset = %I64d\n", offset.QuadPart); + + while (!DecoySystemWipeThreadAbortRequested) + { + if (offset.QuadPart + wipeBlockSize > Extension->ConfiguredEncryptedAreaEnd + 1) + wipeBlockSize = (ULONG) (Extension->ConfiguredEncryptedAreaEnd + 1 - offset.QuadPart); + + if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd) + break; + + for (wipePass = 1; wipePass <= GetWipePassCount (WipeDecoyRequest.WipeAlgorithm); ++wipePass) + { + if (!WipeBuffer (WipeDecoyRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, wipeBlockSize)) + { + dataUnit.Value = offset.QuadPart / ENCRYPTION_DATA_UNIT_SIZE; + EncryptDataUnits (wipeRandBuffer, &dataUnit, wipeBlockSize / ENCRYPTION_DATA_UNIT_SIZE, wipeCryptoInfo); + memcpy (wipeBuffer, wipeRandBuffer, wipeBlockSize); + } + + while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 500))) + { + if (DecoySystemWipeThreadAbortRequested) + goto abort; + } + + status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, wipeBlockSize); + + if (!NT_SUCCESS (status)) + { + DecoySystemWipeResult = status; + goto err; + } + + EncryptedIoQueueResumeFromHold (&Extension->Queue); + } + + offset.QuadPart += wipeBlockSize; + + KeAcquireSpinLock (&DecoySystemWipeStatusSpinLock, &irql); + DecoySystemWipedAreaEnd = offset.QuadPart - 1; + KeReleaseSpinLock (&DecoySystemWipeStatusSpinLock, irql); + } + +abort: + DecoySystemWipeResult = STATUS_SUCCESS; +err: + + if (EncryptedIoQueueIsSuspended (&Extension->Queue)) + EncryptedIoQueueResumeFromHold (&Extension->Queue); + + Dump ("Wipe end: DecoySystemWipedAreaEnd=%I64d (%I64d)\n", DecoySystemWipedAreaEnd, DecoySystemWipedAreaEnd / 1024 / 1024); + +ret: + if (wipeCryptoInfo) + crypto_close (wipeCryptoInfo); + + if (wipeRandBuffer) + TCfree (wipeRandBuffer); + + if (wipeBuffer) + TCfree (wipeBuffer); + + DecoySystemWipeInProgress = FALSE; + PsTerminateSystemThread (DecoySystemWipeResult); +} + + +NTSTATUS StartDecoySystemWipe (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp) +{ + NTSTATUS status; + WipeDecoySystemRequest *request; + + if (!UserCanAccessDriveDevice()) + return STATUS_ACCESS_DENIED; + + if (!IsHiddenSystemRunning() + || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (WipeDecoySystemRequest)) + return STATUS_INVALID_PARAMETER; + + if (DecoySystemWipeInProgress) + return STATUS_SUCCESS; + + if (DecoySystemWipeThread) + AbortDecoySystemWipe(); + + request = (WipeDecoySystemRequest *) irp->AssociatedIrp.SystemBuffer; + WipeDecoyRequest = *request; + + burn (request->WipeKey, sizeof (request->WipeKey)); + + DecoySystemWipeThreadAbortRequested = FALSE; + KeInitializeSpinLock (&DecoySystemWipeStatusSpinLock); + DecoySystemWipedAreaEnd = BootDriveFilterExtension->ConfiguredEncryptedAreaStart; + + DecoySystemWipeInProgress = TRUE; + status = TCStartThread (DecoySystemWipeThreadProc, DeviceObject, &DecoySystemWipeThread); + + if (!NT_SUCCESS (status)) + DecoySystemWipeInProgress = FALSE; + + return status; +} + + +BOOL IsDecoySystemWipeInProgress() +{ + return DecoySystemWipeInProgress; +} + + +void GetDecoySystemWipeStatus (PIRP irp, PIO_STACK_LOCATION irpSp) +{ + if (ValidateIOBufferSize (irp, sizeof (DecoySystemWipeStatus), ValidateOutput)) + { + DecoySystemWipeStatus *wipeStatus = (DecoySystemWipeStatus *) irp->AssociatedIrp.SystemBuffer; + + if (!IsHiddenSystemRunning()) + { + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + irp->IoStatus.Information = 0; + } + else + { + wipeStatus->WipeInProgress = DecoySystemWipeInProgress; + wipeStatus->WipeAlgorithm = WipeDecoyRequest.WipeAlgorithm; + + if (DecoySystemWipeInProgress) + { + KIRQL irql; + KeAcquireSpinLock (&DecoySystemWipeStatusSpinLock, &irql); + wipeStatus->WipedAreaEnd = DecoySystemWipedAreaEnd; + KeReleaseSpinLock (&DecoySystemWipeStatusSpinLock, irql); + } + else + wipeStatus->WipedAreaEnd = DecoySystemWipedAreaEnd; + + irp->IoStatus.Information = sizeof (DecoySystemWipeStatus); + irp->IoStatus.Status = STATUS_SUCCESS; + } + } +} + + +NTSTATUS GetDecoySystemWipeResult() +{ + return DecoySystemWipeResult; +} + + +NTSTATUS AbortDecoySystemWipe () +{ + if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice()) + return STATUS_ACCESS_DENIED; + + DriverMutexWait(); + + if (DecoySystemWipeThread) + { + DecoySystemWipeThreadAbortRequested = TRUE; + + TCStopThread (DecoySystemWipeThread, NULL); + DecoySystemWipeThread = NULL; + } + + DriverMutexRelease(); + + return STATUS_SUCCESS; +} + + +uint64 GetBootDriveLength () +{ + return BootDriveLength.QuadPart; +} + + +NTSTATUS WriteBootDriveSector (PIRP irp, PIO_STACK_LOCATION irpSp) +{ + WriteBootDriveSectorRequest *request; + + if (!UserCanAccessDriveDevice()) + return STATUS_ACCESS_DENIED; + + if (!BootDriveFilterExtension + || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (WriteBootDriveSectorRequest)) + return STATUS_INVALID_PARAMETER; + + request = (WriteBootDriveSectorRequest *) irp->AssociatedIrp.SystemBuffer; + return TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, request->Data, request->Offset, sizeof (request->Data)); +} diff --git a/Driver/DriveFilter.h b/Driver/DriveFilter.h index e3c20ef..5660e54 100644 --- a/Driver/DriveFilter.h +++ b/Driver/DriveFilter.h @@ -1,76 +1,78 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_DRIVER_DRIVE_FILTER -#define TC_HEADER_DRIVER_DRIVE_FILTER - -#include "TCdefs.h" -#include "Boot/Windows/BootCommon.h" -#include "EncryptedIoQueue.h" - -typedef struct -{ - BOOL bRootDevice; - BOOL IsVolumeDevice; - BOOL IsDriveFilterDevice; - BOOL IsVolumeFilterDevice; - - PDEVICE_OBJECT DeviceObject; - PDEVICE_OBJECT LowerDeviceObject; - PDEVICE_OBJECT Pdo; - - int64 ConfiguredEncryptedAreaStart; - int64 ConfiguredEncryptedAreaEnd; - - uint32 VolumeHeaderSaltCrc32; - EncryptedIoQueue Queue; - - BOOL BootDrive; - BOOL VolumeHeaderPresent; - BOOL DriveMounted; - - KEVENT MountWorkItemCompletedEvent; - - CRYPTO_INFO *HeaderCryptoInfo; - BOOL HiddenSystem; - -} DriveFilterExtension; - -extern BOOL BootArgsValid; -extern BootArguments BootArgs; - -NTSTATUS AbortBootEncryptionSetup (); -NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo); -NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp); -void GetBootDriveVolumeProperties (PIRP irp, PIO_STACK_LOCATION irpSp); -void GetBootEncryptionAlgorithmName (PIRP irp, PIO_STACK_LOCATION irpSp); -void GetBootEncryptionStatus (PIRP irp, PIO_STACK_LOCATION irpSp); -void GetBootLoaderVersion (PIRP irp, PIO_STACK_LOCATION irpSp); -NTSTATUS GetSetupResult (); -CRYPTO_INFO *GetSystemDriveCryptoInfo (); -BOOL IsBootDriveMounted (); -BOOL IsBootEncryptionSetupInProgress (); -BOOL IsHiddenSystemRunning (); -NTSTATUS LoadBootArguments (); -static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension); -NTSTATUS StartBootEncryptionSetup (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp); -void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp); -NTSTATUS StartDecoySystemWipe (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp); -void StartHibernationDriverFilter (); -NTSTATUS AbortDecoySystemWipe (); -BOOL IsDecoySystemWipeInProgress(); -NTSTATUS GetDecoySystemWipeResult(); -void GetDecoySystemWipeStatus (PIRP irp, PIO_STACK_LOCATION irpSp); -uint64 GetBootDriveLength (); -NTSTATUS WriteBootDriveSector (PIRP irp, PIO_STACK_LOCATION irpSp); - -#define TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE (1536 * 1024) -#define TC_ENCRYPTION_SETUP_HEADER_UPDATE_THRESHOLD (64 * 1024 * 1024) -#define TC_HIBERNATION_WRITE_BUFFER_SIZE (128 * 1024) - -#endif // TC_HEADER_DRIVER_DRIVE_FILTER +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_DRIVER_DRIVE_FILTER +#define TC_HEADER_DRIVER_DRIVE_FILTER + +#include "TCdefs.h" +#include "Boot/Windows/BootCommon.h" +#include "EncryptedIoQueue.h" + +typedef struct +{ + BOOL bRootDevice; + BOOL IsVolumeDevice; + BOOL IsDriveFilterDevice; + BOOL IsVolumeFilterDevice; + + PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT LowerDeviceObject; + PDEVICE_OBJECT Pdo; + + int64 ConfiguredEncryptedAreaStart; + int64 ConfiguredEncryptedAreaEnd; + + uint32 VolumeHeaderSaltCrc32; + EncryptedIoQueue Queue; + + BOOL BootDrive; + BOOL VolumeHeaderPresent; + BOOL DriveMounted; + + KEVENT MountWorkItemCompletedEvent; + + CRYPTO_INFO *HeaderCryptoInfo; + BOOL HiddenSystem; + +} DriveFilterExtension; + +extern BOOL BootArgsValid; +extern BootArguments BootArgs; +extern PKTHREAD EncryptionSetupThread; +extern PKTHREAD DecoySystemWipeThread; + +NTSTATUS AbortBootEncryptionSetup (); +NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo); +NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp); +void GetBootDriveVolumeProperties (PIRP irp, PIO_STACK_LOCATION irpSp); +void GetBootEncryptionAlgorithmName (PIRP irp, PIO_STACK_LOCATION irpSp); +void GetBootEncryptionStatus (PIRP irp, PIO_STACK_LOCATION irpSp); +void GetBootLoaderVersion (PIRP irp, PIO_STACK_LOCATION irpSp); +NTSTATUS GetSetupResult (); +CRYPTO_INFO *GetSystemDriveCryptoInfo (); +BOOL IsBootDriveMounted (); +BOOL IsBootEncryptionSetupInProgress (); +BOOL IsHiddenSystemRunning (); +NTSTATUS LoadBootArguments (); +static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension); +NTSTATUS StartBootEncryptionSetup (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp); +void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp); +NTSTATUS StartDecoySystemWipe (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp); +void StartHibernationDriverFilter (); +NTSTATUS AbortDecoySystemWipe (); +BOOL IsDecoySystemWipeInProgress(); +NTSTATUS GetDecoySystemWipeResult(); +void GetDecoySystemWipeStatus (PIRP irp, PIO_STACK_LOCATION irpSp); +uint64 GetBootDriveLength (); +NTSTATUS WriteBootDriveSector (PIRP irp, PIO_STACK_LOCATION irpSp); + +#define TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE (1536 * 1024) +#define TC_ENCRYPTION_SETUP_HEADER_UPDATE_THRESHOLD (64 * 1024 * 1024) +#define TC_HIBERNATION_WRITE_BUFFER_SIZE (128 * 1024) + +#endif // TC_HEADER_DRIVER_DRIVE_FILTER diff --git a/Driver/Driver.rc b/Driver/Driver.rc index 609d6ec..f8dd0b1 100644 --- a/Driver/Driver.rc +++ b/Driver/Driver.rc @@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,2,1,0 - PRODUCTVERSION 6,2,1,0 + FILEVERSION 6,3,0,0 + PRODUCTVERSION 6,3,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -45,12 +45,11 @@ BEGIN BEGIN VALUE "CompanyName", "TrueCrypt Foundation" VALUE "FileDescription", "TrueCrypt Driver" - VALUE "FileVersion", "6.2a" - VALUE "LegalCopyright", "TrueCrypt Foundation" + VALUE "FileVersion", "6.3" VALUE "LegalTrademarks", "TrueCrypt" VALUE "OriginalFilename", "truecrypt.sys" VALUE "ProductName", "TrueCrypt" - VALUE "ProductVersion", "6.2a" + VALUE "ProductVersion", "6.3" END END BLOCK "VarFileInfo" diff --git a/Driver/EncryptedIoQueue.c b/Driver/EncryptedIoQueue.c index bae252f..88c272e 100644 --- a/Driver/EncryptedIoQueue.c +++ b/Driver/EncryptedIoQueue.c @@ -1,1057 +1,1007 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "TCdefs.h" -#include "Apidrvr.h" -#include "Ntdriver.h" -#include "DriveFilter.h" -#include "EncryptedIoQueue.h" -#include "EncryptionThreadPool.h" -#include "Volumes.h" - - -static void AcquireBufferPoolMutex (EncryptedIoQueue *queue) -{ - NTSTATUS status; - - status = KeWaitForMutexObject (&queue->BufferPoolMutex, Executive, KernelMode, FALSE, NULL); - if (!NT_SUCCESS (status)) - TC_BUG_CHECK (status); -} - - -static void ReleaseBufferPoolMutex (EncryptedIoQueue *queue) -{ - KeReleaseMutex (&queue->BufferPoolMutex, FALSE); -} - - -static void *GetPoolBuffer (EncryptedIoQueue *queue, ULONG requestedSize) -{ - EncryptedIoQueueBuffer *buffer; - void *bufferAddress = NULL; - BOOL requestedSizePresentInPool = FALSE; - - while (TRUE) - { - AcquireBufferPoolMutex (queue); - - for (buffer = queue->FirstPoolBuffer; ; buffer = buffer->NextBuffer) - { - if (buffer && buffer->Size == requestedSize) - { - requestedSizePresentInPool = TRUE; - - if (!buffer->InUse) - { - // Reuse a free buffer - buffer->InUse = TRUE; - bufferAddress = buffer->Address; - break; - } - } - - if (!buffer || !buffer->NextBuffer) - { - EncryptedIoQueueBuffer *newBuffer; - - if (requestedSizePresentInPool && !queue->StartPending) - break; - - // Allocate a new buffer - newBuffer = TCalloc (sizeof (EncryptedIoQueueBuffer)); - if (!newBuffer) - { - bufferAddress = NULL; - break; - } - - bufferAddress = TCalloc (requestedSize); - if (bufferAddress) - { - newBuffer->NextBuffer = NULL; - newBuffer->Address = bufferAddress; - newBuffer->Size = requestedSize; - newBuffer->InUse = TRUE; - - if (!buffer) - queue->FirstPoolBuffer = newBuffer; - else - buffer->NextBuffer = newBuffer; - } - else - TCfree (newBuffer); - - break; - } - } - - ReleaseBufferPoolMutex (queue); - - if (bufferAddress || !requestedSizePresentInPool || queue->StartPending) - break; - - KeWaitForSingleObject (&queue->PoolBufferFreeEvent, Executive, KernelMode, FALSE, NULL); - } - - return bufferAddress; -} - - -static void ReleasePoolBuffer (EncryptedIoQueue *queue, void *address) -{ - EncryptedIoQueueBuffer *buffer; - AcquireBufferPoolMutex (queue); - - for (buffer = queue->FirstPoolBuffer; buffer != NULL; buffer = buffer->NextBuffer) - { - if (buffer->Address == address) - { - ASSERT (buffer->InUse); - - buffer->InUse = FALSE; - break; - } - } - - ReleaseBufferPoolMutex (queue); - KeSetEvent (&queue->PoolBufferFreeEvent, IO_DISK_INCREMENT, FALSE); -} - - -static void FreePoolBuffers (EncryptedIoQueue *queue) -{ - EncryptedIoQueueBuffer *buffer; - AcquireBufferPoolMutex (queue); - - for (buffer = queue->FirstPoolBuffer; buffer != NULL; ) - { - EncryptedIoQueueBuffer *nextBuffer = buffer->NextBuffer; - - ASSERT (!buffer->InUse); - - TCfree (buffer->Address); - TCfree (buffer); - - buffer = nextBuffer; - } - - queue->FirstPoolBuffer = NULL; - ReleaseBufferPoolMutex (queue); -} - - -static void DecrementOutstandingIoCount (EncryptedIoQueue *queue) -{ - if (InterlockedDecrement (&queue->OutstandingIoCount) == 0 && (queue->SuspendPending || queue->StopPending)) - KeSetEvent (&queue->NoOutstandingIoEvent, IO_DISK_INCREMENT, FALSE); -} - - -static void OnItemCompleted (EncryptedIoQueueItem *item, BOOL freeItem) -{ - DecrementOutstandingIoCount (item->Queue); - - if (item->Queue->IsFilterDevice) - IoReleaseRemoveLock (&item->Queue->RemoveLock, item->OriginalIrp); - - if (NT_SUCCESS (item->Status)) - { - if (item->Write) - item->Queue->TotalBytesWritten += item->OriginalLength; - else - item->Queue->TotalBytesRead += item->OriginalLength; - } - - if (freeItem) - ReleasePoolBuffer (item->Queue, item); -} - - -static NTSTATUS CompleteOriginalIrp (EncryptedIoQueueItem *item, NTSTATUS status, ULONG_PTR information) -{ -#ifdef TC_TRACE_IO_QUEUE - Dump ("< %I64d [%I64d] %c status=%x info=%I64d\n", item->OriginalIrpOffset, GetElapsedTime (&item->Queue->LastPerformanceCounter), item->Write ? 'W' : 'R', status, (int64) information); -#endif - - TCCompleteDiskIrp (item->OriginalIrp, status, information); - - item->Status = status; - OnItemCompleted (item, TRUE); - - return status; -} - - -static void AcquireFragmentBuffer (EncryptedIoQueue *queue, byte *buffer) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - - if (buffer == queue->FragmentBufferA) - { - status = KeWaitForSingleObject (&queue->FragmentBufferAFreeEvent, Executive, KernelMode, FALSE, NULL); - } - else if (buffer == queue->FragmentBufferB) - { - status = KeWaitForSingleObject (&queue->FragmentBufferBFreeEvent, Executive, KernelMode, FALSE, NULL); - } - - if (!NT_SUCCESS (status)) - TC_BUG_CHECK (status); -} - - -static void ReleaseFragmentBuffer (EncryptedIoQueue *queue, byte *buffer) -{ - if (buffer == queue->FragmentBufferA) - { - KeSetEvent (&queue->FragmentBufferAFreeEvent, IO_DISK_INCREMENT, FALSE); - } - else if (buffer == queue->FragmentBufferB) - { - KeSetEvent (&queue->FragmentBufferBFreeEvent, IO_DISK_INCREMENT, FALSE); - } - else - { - TC_BUG_CHECK (STATUS_INVALID_PARAMETER); - } -} - - -static VOID CompletionThreadProc (PVOID threadArg) -{ - EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg; - PLIST_ENTRY listEntry; - EncryptedIoRequest *request; - UINT64_STRUCT dataUnit; - - if (IsEncryptionThreadPoolRunning()) - KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); - - while (!queue->ThreadExitRequested) - { - if (!NT_SUCCESS (KeWaitForSingleObject (&queue->CompletionThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL))) - continue; - - if (queue->ThreadExitRequested) - break; - - while ((listEntry = ExInterlockedRemoveHeadList (&queue->CompletionThreadQueue, &queue->CompletionThreadQueueLock))) - { - request = CONTAINING_RECORD (listEntry, EncryptedIoRequest, CompletionListEntry); - - if (request->EncryptedLength > 0 && NT_SUCCESS (request->Item->Status)) - { - ASSERT (request->EncryptedOffset + request->EncryptedLength <= request->Offset.QuadPart + request->Length); - dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) / ENCRYPTION_DATA_UNIT_SIZE; - - if (queue->CryptoInfo->bPartitionInInactiveSysEncScope) - dataUnit.Value += queue->CryptoInfo->FirstDataUnitNo.Value; - else if (queue->RemapEncryptedArea) - dataUnit.Value += queue->RemappedAreaDataUnitOffset; - - DecryptDataUnits (request->Data + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); - } - - if (request->CompleteOriginalIrp) - { - CompleteOriginalIrp (request->Item, request->Item->Status, - NT_SUCCESS (request->Item->Status) ? request->Item->OriginalLength : 0); - } - else - { - InterlockedDecrement (&request->Item->OutstandingRequestCount); - KeSetEvent (&queue->RequestCompletedEvent, IO_DISK_INCREMENT, FALSE); - } - - ReleasePoolBuffer (queue, request); - } - } - - PsTerminateSystemThread (STATUS_SUCCESS); -} - - -static NTSTATUS TCCachedRead (EncryptedIoQueue *queue, IO_STATUS_BLOCK *ioStatus, PVOID buffer, LARGE_INTEGER offset, ULONG length) -{ - queue->LastReadOffset = offset; - queue->LastReadLength = length; - - if (queue->ReadAheadBufferValid && queue->ReadAheadOffset.QuadPart == offset.QuadPart && queue->ReadAheadLength >= length) - { - memcpy (buffer, queue->ReadAheadBuffer, length); - - if (!queue->IsFilterDevice) - { - ioStatus->Information = length; - ioStatus->Status = STATUS_SUCCESS; - } - - return STATUS_SUCCESS; - } - - if (queue->IsFilterDevice) - return TCReadDevice (queue->LowerDeviceObject, buffer, offset, length); - - return ZwReadFile (queue->HostFileHandle, NULL, NULL, NULL, ioStatus, buffer, length, &offset, NULL); -} - - -static VOID IoThreadProc (PVOID threadArg) -{ - EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg; - PLIST_ENTRY listEntry; - EncryptedIoRequest *request; - - KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); - - if (!queue->IsFilterDevice && queue->SecurityClientContext) - { -#ifdef DEBUG - NTSTATUS status = -#endif - SeImpersonateClientEx (queue->SecurityClientContext, NULL); - ASSERT (NT_SUCCESS (status)); - } - - while (!queue->ThreadExitRequested) - { - if (!NT_SUCCESS (KeWaitForSingleObject (&queue->IoThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL))) - continue; - - if (queue->ThreadExitRequested) - break; - - while ((listEntry = ExInterlockedRemoveHeadList (&queue->IoThreadQueue, &queue->IoThreadQueueLock))) - { - InterlockedDecrement (&queue->IoThreadPendingRequestCount); - request = CONTAINING_RECORD (listEntry, EncryptedIoRequest, ListEntry); - -#ifdef TC_TRACE_IO_QUEUE - Dump ("%c %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->Write ? 'W' : 'R', request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), request->Offset.QuadPart, request->Length); -#endif - - // Perform IO request if no preceding request of the item failed - if (NT_SUCCESS (request->Item->Status)) - { - if (queue->IsFilterDevice) - { - if (queue->RemapEncryptedArea && request->EncryptedLength > 0) - { - if (request->EncryptedLength != request->Length) - { - // Up to three subfragments may be required to handle a partially remapped fragment - int subFragment; - byte *subFragmentData = request->Data; - - for (subFragment = 0 ; subFragment < 3; ++subFragment) - { - LARGE_INTEGER subFragmentOffset; - ULONG subFragmentLength; - subFragmentOffset.QuadPart = request->Offset.QuadPart; - - switch (subFragment) - { - case 0: - subFragmentLength = (ULONG) request->EncryptedOffset; - break; - - case 1: - subFragmentOffset.QuadPart += request->EncryptedOffset + queue->RemappedAreaOffset; - subFragmentLength = request->EncryptedLength; - break; - - case 2: - subFragmentOffset.QuadPart += request->EncryptedOffset + request->EncryptedLength; - subFragmentLength = (ULONG) (request->Length - (request->EncryptedOffset + request->EncryptedLength)); - break; - } - - if (subFragmentLength > 0) - { - if (request->Item->Write) - request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, subFragmentData, subFragmentOffset, subFragmentLength); - else - request->Item->Status = TCCachedRead (queue, NULL, subFragmentData, subFragmentOffset, subFragmentLength); - - subFragmentData += subFragmentLength; - } - } - } - else - { - // Remap the fragment - LARGE_INTEGER remappedOffset; - remappedOffset.QuadPart = request->Offset.QuadPart + queue->RemappedAreaOffset; - - if (request->Item->Write) - request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, remappedOffset, request->Length); - else - request->Item->Status = TCCachedRead (queue, NULL, request->Data, remappedOffset, request->Length); - } - } - else - { - if (request->Item->Write) - request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, request->Offset, request->Length); - else - request->Item->Status = TCCachedRead (queue, NULL, request->Data, request->Offset, request->Length); - } - } - else - { - IO_STATUS_BLOCK ioStatus; - - if (request->Item->Write) - request->Item->Status = ZwWriteFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, request->Data, request->Length, &request->Offset, NULL); - else - request->Item->Status = TCCachedRead (queue, &ioStatus, request->Data, request->Offset, request->Length); - - if (NT_SUCCESS (request->Item->Status) && ioStatus.Information != request->Length) - request->Item->Status = STATUS_END_OF_FILE; - } - } - - if (request->Item->Write) - { - queue->ReadAheadBufferValid = FALSE; - - ReleaseFragmentBuffer (queue, request->Data); - - if (request->CompleteOriginalIrp) - { - CompleteOriginalIrp (request->Item, request->Item->Status, - NT_SUCCESS (request->Item->Status) ? request->Item->OriginalLength : 0); - } - else - { - InterlockedDecrement (&request->Item->OutstandingRequestCount); - KeSetEvent (&queue->RequestCompletedEvent, IO_DISK_INCREMENT, FALSE); - } - - ReleasePoolBuffer (queue, request); - } - else - { - BOOL readAhead = FALSE; - - if (NT_SUCCESS (request->Item->Status)) - memcpy (request->OrigDataBufferFragment, request->Data, request->Length); - - ReleaseFragmentBuffer (queue, request->Data); - request->Data = request->OrigDataBufferFragment; - - if (request->CompleteOriginalIrp - && queue->LastReadLength > 0 - && NT_SUCCESS (request->Item->Status) - && InterlockedExchangeAdd (&queue->IoThreadPendingRequestCount, 0) == 0) - { - readAhead = TRUE; - InterlockedIncrement (&queue->OutstandingIoCount); - } - - ExInterlockedInsertTailList (&queue->CompletionThreadQueue, &request->CompletionListEntry, &queue->CompletionThreadQueueLock); - KeSetEvent (&queue->CompletionThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE); - - if (readAhead) - { - queue->ReadAheadBufferValid = FALSE; - queue->ReadAheadOffset.QuadPart = queue->LastReadOffset.QuadPart + queue->LastReadLength; - queue->ReadAheadLength = queue->LastReadLength; - -#ifdef TC_TRACE_IO_QUEUE - Dump ("A %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), queue->ReadAheadOffset, queue->ReadAheadLength); -#endif - - if (queue->ReadAheadOffset.QuadPart + queue->ReadAheadLength <= queue->MaxReadAheadOffset.QuadPart) - { - if (queue->IsFilterDevice) - { - queue->ReadAheadBufferValid = NT_SUCCESS (TCReadDevice (queue->LowerDeviceObject, queue->ReadAheadBuffer, queue->ReadAheadOffset, queue->ReadAheadLength)); - } - else - { - IO_STATUS_BLOCK ioStatus; - queue->ReadAheadBufferValid = NT_SUCCESS (ZwReadFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, queue->ReadAheadBuffer, queue->ReadAheadLength, &queue->ReadAheadOffset, NULL)); - queue->ReadAheadLength = (ULONG) ioStatus.Information; - } - } - - DecrementOutstandingIoCount (queue); - } - } - } - } - - PsTerminateSystemThread (STATUS_SUCCESS); -} - - -static VOID MainThreadProc (PVOID threadArg) -{ - EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg; - PLIST_ENTRY listEntry; - EncryptedIoQueueItem *item; - - LARGE_INTEGER fragmentOffset; - ULONG dataRemaining; - PUCHAR activeFragmentBuffer = queue->FragmentBufferA; - PUCHAR dataBuffer; - EncryptedIoRequest *request; - uint64 intersectStart; - uint32 intersectLength; - - int64 mdlWaitTime; - LARGE_INTEGER mdlWaitPerfCounter; - - if (IsEncryptionThreadPoolRunning()) - KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); - - while (!queue->ThreadExitRequested) - { - if (!NT_SUCCESS (KeWaitForSingleObject (&queue->MainThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL))) - continue; - - while ((listEntry = ExInterlockedRemoveHeadList (&queue->MainThreadQueue, &queue->MainThreadQueueLock))) - { - PIRP irp = CONTAINING_RECORD (listEntry, IRP, Tail.Overlay.ListEntry); - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp); - - if (queue->Suspended) - KeWaitForSingleObject (&queue->QueueResumedEvent, Executive, KernelMode, FALSE, NULL); - - item = GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem)); - if (!item) - { - EncryptedIoQueueItem stackItem; - stackItem.Queue = queue; - stackItem.OriginalIrp = irp; - stackItem.Status = STATUS_INSUFFICIENT_RESOURCES; - - TCCompleteDiskIrp (irp, STATUS_INSUFFICIENT_RESOURCES, 0); - OnItemCompleted (&stackItem, FALSE); - continue; - } - - item->Queue = queue; - item->OriginalIrp = irp; - item->OutstandingRequestCount = 0; - item->Status = STATUS_SUCCESS; - - IoSetCancelRoutine (irp, NULL); - if (irp->Cancel) - { - CompleteOriginalIrp (item, STATUS_CANCELLED, 0); - continue; - } - - switch (irpSp->MajorFunction) - { - case IRP_MJ_READ: - item->Write = FALSE; - item->OriginalOffset = irpSp->Parameters.Read.ByteOffset; - item->OriginalLength = irpSp->Parameters.Read.Length; - break; - - case IRP_MJ_WRITE: - item->Write = TRUE; - item->OriginalOffset = irpSp->Parameters.Write.ByteOffset; - item->OriginalLength = irpSp->Parameters.Write.Length; - break; - - default: - CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); - continue; - } - -#ifdef TC_TRACE_IO_QUEUE - item->OriginalIrpOffset = item->OriginalOffset; -#endif - - // Handle misaligned read operations to work around a bug in Windows System Assessment Tool which does not follow FILE_FLAG_NO_BUFFERING requirements when benchmarking disk devices - if (queue->IsFilterDevice - && !item->Write - && item->OriginalLength > 0 - && (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) == 0 - && (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) - { - byte *buffer; - ULONG alignedLength = item->OriginalLength + ENCRYPTION_DATA_UNIT_SIZE; - LARGE_INTEGER alignedOffset; - alignedOffset.QuadPart = item->OriginalOffset.QuadPart & ~((LONGLONG) ENCRYPTION_DATA_UNIT_SIZE - 1); - - buffer = TCalloc (alignedLength); - if (!buffer) - { - CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); - continue; - } - - item->Status = TCReadDevice (queue->LowerDeviceObject, buffer, alignedOffset, alignedLength); - - if (NT_SUCCESS (item->Status)) - { - UINT64_STRUCT dataUnit; - - dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); - if (!dataBuffer) - { - TCfree (buffer); - CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); - continue; - } - - if (queue->EncryptedAreaStart != -1 && queue->EncryptedAreaEnd != -1) - { - GetIntersection (alignedOffset.QuadPart, alignedLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength); - if (intersectLength > 0) - { - dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE; - DecryptDataUnits (buffer + (intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); - } - } - - memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength); - } - - TCfree (buffer); - CompleteOriginalIrp (item, item->Status, NT_SUCCESS (item->Status) ? item->OriginalLength : 0); - continue; - } - - // Validate offset and length - if (item->OriginalLength == 0 - || (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 - || (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 - || (!queue->IsFilterDevice && item->OriginalOffset.QuadPart + item->OriginalLength > queue->VirtualDeviceLength)) - { - CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); - continue; - } - -#ifdef TC_TRACE_IO_QUEUE - Dump ("Q %I64d [%I64d] %c len=%d\n", item->OriginalOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), item->Write ? 'W' : 'R', item->OriginalLength); -#endif - - if (!queue->IsFilterDevice) - { - // Adjust the offset for host file or device - if (queue->CryptoInfo->hiddenVolume) - item->OriginalOffset.QuadPart += queue->CryptoInfo->hiddenVolumeOffset; - else - item->OriginalOffset.QuadPart += queue->CryptoInfo->volDataAreaOffset; - - // Hidden volume protection - if (item->Write && queue->CryptoInfo->bProtectHiddenVolume) - { - // If there has already been a write operation denied in order to protect the - // hidden volume (since the volume mount time) - if (queue->CryptoInfo->bHiddenVolProtectionAction) - { - // Do not allow writing to this volume anymore. This is to fake a complete volume - // or system failure (otherwise certain kinds of inconsistency within the file - // system could indicate that this volume has used hidden volume protection). - CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); - continue; - } - - // Verify that no byte is going to be written to the hidden volume area - if (RegionsOverlap ((unsigned __int64) item->OriginalOffset.QuadPart, - (unsigned __int64) item->OriginalOffset.QuadPart + item->OriginalLength - 1, - queue->CryptoInfo->hiddenVolumeOffset, - (unsigned __int64) queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1)) - { - Dump ("Hidden volume protection triggered: write %I64d-%I64d (protected %I64d-%I64d)\n", item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, queue->CryptoInfo->hiddenVolumeOffset, queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1); - queue->CryptoInfo->bHiddenVolProtectionAction = TRUE; - - // Deny this write operation to prevent the hidden volume from being overwritten - CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); - continue; - } - } - } - else if (item->Write && IsHiddenSystemRunning() - && (RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, SECTOR_SIZE, TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE - 1) - || RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, GetBootDriveLength(), _I64_MAX))) - { - Dump ("Preventing write to boot loader or host protected area\n"); - CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); - continue; - } - - // Original IRP data buffer - mdlWaitTime = 0; - mdlWaitPerfCounter.QuadPart = 0; - while (TRUE) - { - dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); - - if (dataBuffer || mdlWaitTime >= TC_ENC_IO_QUEUE_MEM_ALLOC_TIMEOUT) - break; - - if (mdlWaitPerfCounter.QuadPart == 0) - GetElapsedTimeInit (&mdlWaitPerfCounter); - - TCSleep (TC_ENC_IO_QUEUE_MEM_ALLOC_RETRY_DELAY); - mdlWaitTime += GetElapsedTime (&mdlWaitPerfCounter) / 1000; - } - - if (dataBuffer == NULL) - { - CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); - continue; - } - - // Divide data block to fragments to enable efficient overlapping of encryption and IO operations - - dataRemaining = item->OriginalLength; - fragmentOffset = item->OriginalOffset; - - while (dataRemaining > 0) - { - BOOL isLastFragment = dataRemaining <= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; - - ULONG dataFragmentLength = isLastFragment ? dataRemaining : TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; - activeFragmentBuffer = (activeFragmentBuffer == queue->FragmentBufferA ? queue->FragmentBufferB : queue->FragmentBufferA); - - // Create IO request - request = GetPoolBuffer (queue, sizeof (EncryptedIoRequest)); - if (!request) - { - while (InterlockedExchangeAdd (&item->OutstandingRequestCount, 0) > 0) - KeWaitForSingleObject (&queue->RequestCompletedEvent, Executive, KernelMode, FALSE, NULL); - - CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); - break; - } - - InterlockedIncrement (&queue->IoThreadPendingRequestCount); - - request->Item = item; - request->CompleteOriginalIrp = isLastFragment; - request->Offset = fragmentOffset; - request->Data = activeFragmentBuffer; - request->OrigDataBufferFragment = dataBuffer; - request->Length = dataFragmentLength; - - if (queue->IsFilterDevice) - { - if (queue->EncryptedAreaStart == -1 || queue->EncryptedAreaEnd == -1) - { - request->EncryptedLength = 0; - } - else - { - // Get intersection of data fragment with encrypted area - GetIntersection (fragmentOffset.QuadPart, dataFragmentLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength); - - request->EncryptedOffset = intersectStart - fragmentOffset.QuadPart; - request->EncryptedLength = intersectLength; - } - } - else - { - request->EncryptedOffset = 0; - request->EncryptedLength = dataFragmentLength; - } - - AcquireFragmentBuffer (queue, activeFragmentBuffer); - - if (item->Write) - { - // Encrypt data - memcpy (activeFragmentBuffer, dataBuffer, dataFragmentLength); - - if (request->EncryptedLength > 0) - { - UINT64_STRUCT dataUnit; - ASSERT (request->EncryptedOffset + request->EncryptedLength <= request->Offset.QuadPart + request->Length); - - dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) / ENCRYPTION_DATA_UNIT_SIZE; - - if (queue->CryptoInfo->bPartitionInInactiveSysEncScope) - dataUnit.Value += queue->CryptoInfo->FirstDataUnitNo.Value; - else if (queue->RemapEncryptedArea) - dataUnit.Value += queue->RemappedAreaDataUnitOffset; - - EncryptDataUnits (activeFragmentBuffer + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); - } - } - - // Queue IO request - InterlockedIncrement (&item->OutstandingRequestCount); - - ExInterlockedInsertTailList (&queue->IoThreadQueue, &request->ListEntry, &queue->IoThreadQueueLock); - KeSetEvent (&queue->IoThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE); - - if (isLastFragment) - break; - - dataRemaining -= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; - dataBuffer += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; - fragmentOffset.QuadPart += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; - } - } - } - - PsTerminateSystemThread (STATUS_SUCCESS); -} - - -NTSTATUS EncryptedIoQueueAddIrp (EncryptedIoQueue *queue, PIRP irp) -{ - NTSTATUS status; - - InterlockedIncrement (&queue->OutstandingIoCount); - if (queue->StopPending) - { - Dump ("STATUS_DEVICE_NOT_READY out=%d\n", queue->OutstandingIoCount); - status = STATUS_DEVICE_NOT_READY; - goto err; - } - - if (queue->IsFilterDevice) - { - status = IoAcquireRemoveLock (&queue->RemoveLock, irp); - if (!NT_SUCCESS (status)) - goto err; - } - -#ifdef TC_TRACE_IO_QUEUE - { - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp); - Dump ("* %I64d [%I64d] %c len=%d out=%d\n", irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.ByteOffset : irpSp->Parameters.Read.ByteOffset, GetElapsedTime (&queue->LastPerformanceCounter), irpSp->MajorFunction == IRP_MJ_WRITE ? 'W' : 'R', irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.Length : irpSp->Parameters.Read.Length, queue->OutstandingIoCount); - } -#endif - - IoMarkIrpPending (irp); - - ExInterlockedInsertTailList (&queue->MainThreadQueue, &irp->Tail.Overlay.ListEntry, &queue->MainThreadQueueLock); - KeSetEvent (&queue->MainThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE); - - return STATUS_PENDING; - -err: - DecrementOutstandingIoCount (queue); - return status; -} - - -NTSTATUS EncryptedIoQueueHoldWhenIdle (EncryptedIoQueue *queue, int64 timeout) -{ - NTSTATUS status; - ASSERT (!queue->Suspended); - - queue->SuspendPending = TRUE; - - while (TRUE) - { - while (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0) - { - LARGE_INTEGER waitTimeout; - - waitTimeout.QuadPart = timeout * -10000; - status = KeWaitForSingleObject (&queue->NoOutstandingIoEvent, Executive, KernelMode, FALSE, timeout != 0 ? &waitTimeout : NULL); - - if (status == STATUS_TIMEOUT) - status = STATUS_UNSUCCESSFUL; - - if (!NT_SUCCESS (status)) - { - queue->SuspendPending = FALSE; - return status; - } - - TCSleep (1); - if (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0) - { - queue->SuspendPending = FALSE; - return STATUS_UNSUCCESSFUL; - } - } - - KeClearEvent (&queue->QueueResumedEvent); - queue->Suspended = TRUE; - - if (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) == 0) - break; - - queue->Suspended = FALSE; - KeSetEvent (&queue->QueueResumedEvent, IO_DISK_INCREMENT, FALSE); - } - - queue->ReadAheadBufferValid = FALSE; - - queue->SuspendPending = FALSE; - return STATUS_SUCCESS; -} - - -BOOL EncryptedIoQueueIsSuspended (EncryptedIoQueue *queue) -{ - return queue->Suspended; -} - - -BOOL EncryptedIoQueueIsRunning (EncryptedIoQueue *queue) -{ - return !queue->StopPending; -} - - -NTSTATUS EncryptedIoQueueResumeFromHold (EncryptedIoQueue *queue) -{ - ASSERT (queue->Suspended); - - queue->Suspended = FALSE; - KeSetEvent (&queue->QueueResumedEvent, IO_DISK_INCREMENT, FALSE); - - return STATUS_SUCCESS; -} - - -NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue) -{ - NTSTATUS status; - EncryptedIoQueueBuffer *buffer; - int i; - - queue->StartPending = TRUE; - queue->ThreadExitRequested = FALSE; - - queue->OutstandingIoCount = 0; - queue->IoThreadPendingRequestCount = 0; - - queue->FirstPoolBuffer = NULL; - KeInitializeMutex (&queue->BufferPoolMutex, 0); - - KeInitializeEvent (&queue->NoOutstandingIoEvent, SynchronizationEvent, FALSE); - KeInitializeEvent (&queue->RequestCompletedEvent, SynchronizationEvent, FALSE); - KeInitializeEvent (&queue->PoolBufferFreeEvent, SynchronizationEvent, FALSE); - KeInitializeEvent (&queue->QueueResumedEvent, SynchronizationEvent, FALSE); - - queue->FragmentBufferA = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); - if (!queue->FragmentBufferA) - goto noMemory; - - queue->FragmentBufferB = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); - if (!queue->FragmentBufferB) - goto noMemory; - - KeInitializeEvent (&queue->FragmentBufferAFreeEvent, SynchronizationEvent, TRUE); - KeInitializeEvent (&queue->FragmentBufferBFreeEvent, SynchronizationEvent, TRUE); - - queue->ReadAheadBufferValid = FALSE; - queue->ReadAheadBuffer = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); - if (!queue->ReadAheadBuffer) - goto noMemory; - - // Preallocate buffers - for (i = 0; i < TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; ++i) - { - if (i < TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT && !GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem))) - goto noMemory; - - if (!GetPoolBuffer (queue, sizeof (EncryptedIoRequest))) - goto noMemory; - } - - for (buffer = queue->FirstPoolBuffer; buffer != NULL; buffer = buffer->NextBuffer) - { - buffer->InUse = FALSE; - } - - // Main thread - InitializeListHead (&queue->MainThreadQueue); - KeInitializeSpinLock (&queue->MainThreadQueueLock); - KeInitializeEvent (&queue->MainThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE); - - status = TCStartThread (MainThreadProc, queue, &queue->MainThread); - if (!NT_SUCCESS (status)) - goto err; - - // IO thread - InitializeListHead (&queue->IoThreadQueue); - KeInitializeSpinLock (&queue->IoThreadQueueLock); - KeInitializeEvent (&queue->IoThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE); - - status = TCStartThread (IoThreadProc, queue, &queue->IoThread); - if (!NT_SUCCESS (status)) - { - queue->ThreadExitRequested = TRUE; - TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent); - goto err; - } - - // Completion thread - InitializeListHead (&queue->CompletionThreadQueue); - KeInitializeSpinLock (&queue->CompletionThreadQueueLock); - KeInitializeEvent (&queue->CompletionThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE); - - status = TCStartThread (CompletionThreadProc, queue, &queue->CompletionThread); - if (!NT_SUCCESS (status)) - { - queue->ThreadExitRequested = TRUE; - TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent); - TCStopThread (queue->IoThread, &queue->IoThreadQueueNotEmptyEvent); - goto err; - } - -#ifdef TC_TRACE_IO_QUEUE - GetElapsedTimeInit (&queue->LastPerformanceCounter); -#endif - - queue->StopPending = FALSE; - queue->StartPending = FALSE; - - Dump ("Queue started\n"); - return STATUS_SUCCESS; - -noMemory: - status = STATUS_INSUFFICIENT_RESOURCES; - -err: - if (queue->FragmentBufferA) - TCfree (queue->FragmentBufferA); - if (queue->FragmentBufferB) - TCfree (queue->FragmentBufferB); - - FreePoolBuffers (queue); - - queue->StartPending = FALSE; - return status; -} - - -NTSTATUS EncryptedIoQueueStop (EncryptedIoQueue *queue) -{ - ASSERT (!queue->StopPending); - queue->StopPending = TRUE; - - while (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0) - { - KeWaitForSingleObject (&queue->NoOutstandingIoEvent, Executive, KernelMode, FALSE, NULL); - } - - Dump ("Queue stopping out=%d\n", queue->OutstandingIoCount); - - queue->ThreadExitRequested = TRUE; - - TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent); - TCStopThread (queue->IoThread, &queue->IoThreadQueueNotEmptyEvent); - TCStopThread (queue->CompletionThread, &queue->CompletionThreadQueueNotEmptyEvent); - - TCfree (queue->FragmentBufferA); - TCfree (queue->FragmentBufferB); - TCfree (queue->ReadAheadBuffer); - - FreePoolBuffers (queue); - - Dump ("Queue stopped out=%d\n", queue->OutstandingIoCount); - return STATUS_SUCCESS; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "TCdefs.h" +#include "Apidrvr.h" +#include "Ntdriver.h" +#include "DriveFilter.h" +#include "EncryptedIoQueue.h" +#include "EncryptionThreadPool.h" +#include "Volumes.h" + + +static void AcquireBufferPoolMutex (EncryptedIoQueue *queue) +{ + NTSTATUS status; + + status = KeWaitForMutexObject (&queue->BufferPoolMutex, Executive, KernelMode, FALSE, NULL); + if (!NT_SUCCESS (status)) + TC_BUG_CHECK (status); +} + + +static void ReleaseBufferPoolMutex (EncryptedIoQueue *queue) +{ + KeReleaseMutex (&queue->BufferPoolMutex, FALSE); +} + + +static void *GetPoolBuffer (EncryptedIoQueue *queue, ULONG requestedSize) +{ + EncryptedIoQueueBuffer *buffer; + void *bufferAddress = NULL; + BOOL requestedSizePresentInPool = FALSE; + + while (TRUE) + { + AcquireBufferPoolMutex (queue); + + for (buffer = queue->FirstPoolBuffer; ; buffer = buffer->NextBuffer) + { + if (buffer && buffer->Size == requestedSize) + { + requestedSizePresentInPool = TRUE; + + if (!buffer->InUse) + { + // Reuse a free buffer + buffer->InUse = TRUE; + bufferAddress = buffer->Address; + break; + } + } + + if (!buffer || !buffer->NextBuffer) + { + EncryptedIoQueueBuffer *newBuffer; + + if (requestedSizePresentInPool && !queue->StartPending) + break; + + // Allocate a new buffer + newBuffer = TCalloc (sizeof (EncryptedIoQueueBuffer)); + if (!newBuffer) + { + bufferAddress = NULL; + break; + } + + bufferAddress = TCalloc (requestedSize); + if (bufferAddress) + { + newBuffer->NextBuffer = NULL; + newBuffer->Address = bufferAddress; + newBuffer->Size = requestedSize; + newBuffer->InUse = TRUE; + + if (!buffer) + queue->FirstPoolBuffer = newBuffer; + else + buffer->NextBuffer = newBuffer; + } + else + TCfree (newBuffer); + + break; + } + } + + ReleaseBufferPoolMutex (queue); + + if (bufferAddress || !requestedSizePresentInPool || queue->StartPending) + break; + + KeWaitForSingleObject (&queue->PoolBufferFreeEvent, Executive, KernelMode, FALSE, NULL); + } + + return bufferAddress; +} + + +static void ReleasePoolBuffer (EncryptedIoQueue *queue, void *address) +{ + EncryptedIoQueueBuffer *buffer; + AcquireBufferPoolMutex (queue); + + for (buffer = queue->FirstPoolBuffer; buffer != NULL; buffer = buffer->NextBuffer) + { + if (buffer->Address == address) + { + ASSERT (buffer->InUse); + + buffer->InUse = FALSE; + break; + } + } + + ReleaseBufferPoolMutex (queue); + KeSetEvent (&queue->PoolBufferFreeEvent, IO_DISK_INCREMENT, FALSE); +} + + +static void FreePoolBuffers (EncryptedIoQueue *queue) +{ + EncryptedIoQueueBuffer *buffer; + AcquireBufferPoolMutex (queue); + + for (buffer = queue->FirstPoolBuffer; buffer != NULL; ) + { + EncryptedIoQueueBuffer *nextBuffer = buffer->NextBuffer; + + ASSERT (!buffer->InUse); + + TCfree (buffer->Address); + TCfree (buffer); + + buffer = nextBuffer; + } + + queue->FirstPoolBuffer = NULL; + ReleaseBufferPoolMutex (queue); +} + + +static void DecrementOutstandingIoCount (EncryptedIoQueue *queue) +{ + if (InterlockedDecrement (&queue->OutstandingIoCount) == 0 && (queue->SuspendPending || queue->StopPending)) + KeSetEvent (&queue->NoOutstandingIoEvent, IO_DISK_INCREMENT, FALSE); +} + + +static void OnItemCompleted (EncryptedIoQueueItem *item, BOOL freeItem) +{ + DecrementOutstandingIoCount (item->Queue); + IoReleaseRemoveLock (&item->Queue->RemoveLock, item->OriginalIrp); + + if (NT_SUCCESS (item->Status)) + { + if (item->Write) + item->Queue->TotalBytesWritten += item->OriginalLength; + else + item->Queue->TotalBytesRead += item->OriginalLength; + } + + if (freeItem) + ReleasePoolBuffer (item->Queue, item); +} + + +static NTSTATUS CompleteOriginalIrp (EncryptedIoQueueItem *item, NTSTATUS status, ULONG_PTR information) +{ +#ifdef TC_TRACE_IO_QUEUE + Dump ("< %I64d [%I64d] %c status=%x info=%I64d\n", item->OriginalIrpOffset, GetElapsedTime (&item->Queue->LastPerformanceCounter), item->Write ? 'W' : 'R', status, (int64) information); +#endif + + TCCompleteDiskIrp (item->OriginalIrp, status, information); + + item->Status = status; + OnItemCompleted (item, TRUE); + + return status; +} + + +static void AcquireFragmentBuffer (EncryptedIoQueue *queue, byte *buffer) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + + if (buffer == queue->FragmentBufferA) + { + status = KeWaitForSingleObject (&queue->FragmentBufferAFreeEvent, Executive, KernelMode, FALSE, NULL); + } + else if (buffer == queue->FragmentBufferB) + { + status = KeWaitForSingleObject (&queue->FragmentBufferBFreeEvent, Executive, KernelMode, FALSE, NULL); + } + + if (!NT_SUCCESS (status)) + TC_BUG_CHECK (status); +} + + +static void ReleaseFragmentBuffer (EncryptedIoQueue *queue, byte *buffer) +{ + if (buffer == queue->FragmentBufferA) + { + KeSetEvent (&queue->FragmentBufferAFreeEvent, IO_DISK_INCREMENT, FALSE); + } + else if (buffer == queue->FragmentBufferB) + { + KeSetEvent (&queue->FragmentBufferBFreeEvent, IO_DISK_INCREMENT, FALSE); + } + else + { + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + } +} + + +static VOID CompletionThreadProc (PVOID threadArg) +{ + EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg; + PLIST_ENTRY listEntry; + EncryptedIoRequest *request; + UINT64_STRUCT dataUnit; + + if (IsEncryptionThreadPoolRunning()) + KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); + + while (!queue->ThreadExitRequested) + { + if (!NT_SUCCESS (KeWaitForSingleObject (&queue->CompletionThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL))) + continue; + + if (queue->ThreadExitRequested) + break; + + while ((listEntry = ExInterlockedRemoveHeadList (&queue->CompletionThreadQueue, &queue->CompletionThreadQueueLock))) + { + request = CONTAINING_RECORD (listEntry, EncryptedIoRequest, CompletionListEntry); + + if (request->EncryptedLength > 0 && NT_SUCCESS (request->Item->Status)) + { + ASSERT (request->EncryptedOffset + request->EncryptedLength <= request->Offset.QuadPart + request->Length); + dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) / ENCRYPTION_DATA_UNIT_SIZE; + + if (queue->CryptoInfo->bPartitionInInactiveSysEncScope) + dataUnit.Value += queue->CryptoInfo->FirstDataUnitNo.Value; + else if (queue->RemapEncryptedArea) + dataUnit.Value += queue->RemappedAreaDataUnitOffset; + + DecryptDataUnits (request->Data + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); + } + + if (request->CompleteOriginalIrp) + { + CompleteOriginalIrp (request->Item, request->Item->Status, + NT_SUCCESS (request->Item->Status) ? request->Item->OriginalLength : 0); + } + + ReleasePoolBuffer (queue, request); + } + } + + PsTerminateSystemThread (STATUS_SUCCESS); +} + + +static NTSTATUS TCCachedRead (EncryptedIoQueue *queue, IO_STATUS_BLOCK *ioStatus, PVOID buffer, LARGE_INTEGER offset, ULONG length) +{ + queue->LastReadOffset = offset; + queue->LastReadLength = length; + + if (queue->ReadAheadBufferValid && queue->ReadAheadOffset.QuadPart == offset.QuadPart && queue->ReadAheadLength >= length) + { + memcpy (buffer, queue->ReadAheadBuffer, length); + + if (!queue->IsFilterDevice) + { + ioStatus->Information = length; + ioStatus->Status = STATUS_SUCCESS; + } + + return STATUS_SUCCESS; + } + + if (queue->IsFilterDevice) + return TCReadDevice (queue->LowerDeviceObject, buffer, offset, length); + + return ZwReadFile (queue->HostFileHandle, NULL, NULL, NULL, ioStatus, buffer, length, &offset, NULL); +} + + +static VOID IoThreadProc (PVOID threadArg) +{ + EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg; + PLIST_ENTRY listEntry; + EncryptedIoRequest *request; + + KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); + + if (!queue->IsFilterDevice && queue->SecurityClientContext) + { +#ifdef DEBUG + NTSTATUS status = +#endif + SeImpersonateClientEx (queue->SecurityClientContext, NULL); + ASSERT (NT_SUCCESS (status)); + } + + while (!queue->ThreadExitRequested) + { + if (!NT_SUCCESS (KeWaitForSingleObject (&queue->IoThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL))) + continue; + + if (queue->ThreadExitRequested) + break; + + while ((listEntry = ExInterlockedRemoveHeadList (&queue->IoThreadQueue, &queue->IoThreadQueueLock))) + { + InterlockedDecrement (&queue->IoThreadPendingRequestCount); + request = CONTAINING_RECORD (listEntry, EncryptedIoRequest, ListEntry); + +#ifdef TC_TRACE_IO_QUEUE + Dump ("%c %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->Write ? 'W' : 'R', request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), request->Offset.QuadPart, request->Length); +#endif + + // Perform IO request if no preceding request of the item failed + if (NT_SUCCESS (request->Item->Status)) + { + if (queue->IsFilterDevice) + { + if (queue->RemapEncryptedArea && request->EncryptedLength > 0) + { + if (request->EncryptedLength != request->Length) + { + // Up to three subfragments may be required to handle a partially remapped fragment + int subFragment; + byte *subFragmentData = request->Data; + + for (subFragment = 0 ; subFragment < 3; ++subFragment) + { + LARGE_INTEGER subFragmentOffset; + ULONG subFragmentLength; + subFragmentOffset.QuadPart = request->Offset.QuadPart; + + switch (subFragment) + { + case 0: + subFragmentLength = (ULONG) request->EncryptedOffset; + break; + + case 1: + subFragmentOffset.QuadPart += request->EncryptedOffset + queue->RemappedAreaOffset; + subFragmentLength = request->EncryptedLength; + break; + + case 2: + subFragmentOffset.QuadPart += request->EncryptedOffset + request->EncryptedLength; + subFragmentLength = (ULONG) (request->Length - (request->EncryptedOffset + request->EncryptedLength)); + break; + } + + if (subFragmentLength > 0) + { + if (request->Item->Write) + request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, subFragmentData, subFragmentOffset, subFragmentLength); + else + request->Item->Status = TCCachedRead (queue, NULL, subFragmentData, subFragmentOffset, subFragmentLength); + + subFragmentData += subFragmentLength; + } + } + } + else + { + // Remap the fragment + LARGE_INTEGER remappedOffset; + remappedOffset.QuadPart = request->Offset.QuadPart + queue->RemappedAreaOffset; + + if (request->Item->Write) + request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, remappedOffset, request->Length); + else + request->Item->Status = TCCachedRead (queue, NULL, request->Data, remappedOffset, request->Length); + } + } + else + { + if (request->Item->Write) + request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, request->Offset, request->Length); + else + request->Item->Status = TCCachedRead (queue, NULL, request->Data, request->Offset, request->Length); + } + } + else + { + IO_STATUS_BLOCK ioStatus; + + if (request->Item->Write) + request->Item->Status = ZwWriteFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, request->Data, request->Length, &request->Offset, NULL); + else + request->Item->Status = TCCachedRead (queue, &ioStatus, request->Data, request->Offset, request->Length); + + if (NT_SUCCESS (request->Item->Status) && ioStatus.Information != request->Length) + request->Item->Status = STATUS_END_OF_FILE; + } + } + + if (request->Item->Write) + { + queue->ReadAheadBufferValid = FALSE; + + ReleaseFragmentBuffer (queue, request->Data); + + if (request->CompleteOriginalIrp) + { + CompleteOriginalIrp (request->Item, request->Item->Status, + NT_SUCCESS (request->Item->Status) ? request->Item->OriginalLength : 0); + } + + ReleasePoolBuffer (queue, request); + } + else + { + BOOL readAhead = FALSE; + + if (NT_SUCCESS (request->Item->Status)) + memcpy (request->OrigDataBufferFragment, request->Data, request->Length); + + ReleaseFragmentBuffer (queue, request->Data); + request->Data = request->OrigDataBufferFragment; + + if (request->CompleteOriginalIrp + && queue->LastReadLength > 0 + && NT_SUCCESS (request->Item->Status) + && InterlockedExchangeAdd (&queue->IoThreadPendingRequestCount, 0) == 0) + { + readAhead = TRUE; + InterlockedIncrement (&queue->OutstandingIoCount); + } + + ExInterlockedInsertTailList (&queue->CompletionThreadQueue, &request->CompletionListEntry, &queue->CompletionThreadQueueLock); + KeSetEvent (&queue->CompletionThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE); + + if (readAhead) + { + queue->ReadAheadBufferValid = FALSE; + queue->ReadAheadOffset.QuadPart = queue->LastReadOffset.QuadPart + queue->LastReadLength; + queue->ReadAheadLength = queue->LastReadLength; + +#ifdef TC_TRACE_IO_QUEUE + Dump ("A %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), queue->ReadAheadOffset, queue->ReadAheadLength); +#endif + + if (queue->ReadAheadOffset.QuadPart + queue->ReadAheadLength <= queue->MaxReadAheadOffset.QuadPart) + { + if (queue->IsFilterDevice) + { + queue->ReadAheadBufferValid = NT_SUCCESS (TCReadDevice (queue->LowerDeviceObject, queue->ReadAheadBuffer, queue->ReadAheadOffset, queue->ReadAheadLength)); + } + else + { + IO_STATUS_BLOCK ioStatus; + queue->ReadAheadBufferValid = NT_SUCCESS (ZwReadFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, queue->ReadAheadBuffer, queue->ReadAheadLength, &queue->ReadAheadOffset, NULL)); + queue->ReadAheadLength = (ULONG) ioStatus.Information; + } + } + + DecrementOutstandingIoCount (queue); + } + } + } + } + + PsTerminateSystemThread (STATUS_SUCCESS); +} + + +static VOID MainThreadProc (PVOID threadArg) +{ + EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg; + PLIST_ENTRY listEntry; + EncryptedIoQueueItem *item; + + LARGE_INTEGER fragmentOffset; + ULONG dataRemaining; + PUCHAR activeFragmentBuffer = queue->FragmentBufferA; + PUCHAR dataBuffer; + EncryptedIoRequest *request; + uint64 intersectStart; + uint32 intersectLength; + + if (IsEncryptionThreadPoolRunning()) + KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); + + while (!queue->ThreadExitRequested) + { + if (!NT_SUCCESS (KeWaitForSingleObject (&queue->MainThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL))) + continue; + + while ((listEntry = ExInterlockedRemoveHeadList (&queue->MainThreadQueue, &queue->MainThreadQueueLock))) + { + PIRP irp = CONTAINING_RECORD (listEntry, IRP, Tail.Overlay.ListEntry); + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp); + + if (queue->Suspended) + KeWaitForSingleObject (&queue->QueueResumedEvent, Executive, KernelMode, FALSE, NULL); + + item = GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem)); + item->Queue = queue; + item->OriginalIrp = irp; + item->Status = STATUS_SUCCESS; + + IoSetCancelRoutine (irp, NULL); + if (irp->Cancel) + { + CompleteOriginalIrp (item, STATUS_CANCELLED, 0); + continue; + } + + switch (irpSp->MajorFunction) + { + case IRP_MJ_READ: + item->Write = FALSE; + item->OriginalOffset = irpSp->Parameters.Read.ByteOffset; + item->OriginalLength = irpSp->Parameters.Read.Length; + break; + + case IRP_MJ_WRITE: + item->Write = TRUE; + item->OriginalOffset = irpSp->Parameters.Write.ByteOffset; + item->OriginalLength = irpSp->Parameters.Write.Length; + break; + + default: + CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); + continue; + } + +#ifdef TC_TRACE_IO_QUEUE + item->OriginalIrpOffset = item->OriginalOffset; +#endif + + // Handle misaligned read operations to work around a bug in Windows System Assessment Tool which does not follow FILE_FLAG_NO_BUFFERING requirements when benchmarking disk devices + if (queue->IsFilterDevice + && !item->Write + && item->OriginalLength > 0 + && (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) == 0 + && (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) + { + byte *buffer; + ULONG alignedLength = item->OriginalLength + ENCRYPTION_DATA_UNIT_SIZE; + LARGE_INTEGER alignedOffset; + alignedOffset.QuadPart = item->OriginalOffset.QuadPart & ~((LONGLONG) ENCRYPTION_DATA_UNIT_SIZE - 1); + + buffer = TCalloc (alignedLength); + if (!buffer) + { + CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); + continue; + } + + item->Status = TCReadDevice (queue->LowerDeviceObject, buffer, alignedOffset, alignedLength); + + if (NT_SUCCESS (item->Status)) + { + UINT64_STRUCT dataUnit; + + dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); + if (!dataBuffer) + { + TCfree (buffer); + CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); + continue; + } + + if (queue->EncryptedAreaStart != -1 && queue->EncryptedAreaEnd != -1) + { + GetIntersection (alignedOffset.QuadPart, alignedLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength); + if (intersectLength > 0) + { + dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE; + DecryptDataUnits (buffer + (intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); + } + } + + memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength); + } + + TCfree (buffer); + CompleteOriginalIrp (item, item->Status, NT_SUCCESS (item->Status) ? item->OriginalLength : 0); + continue; + } + + // Validate offset and length + if (item->OriginalLength == 0 + || (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 + || (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 + || (!queue->IsFilterDevice && item->OriginalOffset.QuadPart + item->OriginalLength > queue->VirtualDeviceLength)) + { + CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); + continue; + } + +#ifdef TC_TRACE_IO_QUEUE + Dump ("Q %I64d [%I64d] %c len=%d\n", item->OriginalOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), item->Write ? 'W' : 'R', item->OriginalLength); +#endif + + if (!queue->IsFilterDevice) + { + // Adjust the offset for host file or device + if (queue->CryptoInfo->hiddenVolume) + item->OriginalOffset.QuadPart += queue->CryptoInfo->hiddenVolumeOffset; + else + item->OriginalOffset.QuadPart += queue->CryptoInfo->volDataAreaOffset; + + // Hidden volume protection + if (item->Write && queue->CryptoInfo->bProtectHiddenVolume) + { + // If there has already been a write operation denied in order to protect the + // hidden volume (since the volume mount time) + if (queue->CryptoInfo->bHiddenVolProtectionAction) + { + // Do not allow writing to this volume anymore. This is to fake a complete volume + // or system failure (otherwise certain kinds of inconsistency within the file + // system could indicate that this volume has used hidden volume protection). + CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); + continue; + } + + // Verify that no byte is going to be written to the hidden volume area + if (RegionsOverlap ((unsigned __int64) item->OriginalOffset.QuadPart, + (unsigned __int64) item->OriginalOffset.QuadPart + item->OriginalLength - 1, + queue->CryptoInfo->hiddenVolumeOffset, + (unsigned __int64) queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1)) + { + Dump ("Hidden volume protection triggered: write %I64d-%I64d (protected %I64d-%I64d)\n", item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, queue->CryptoInfo->hiddenVolumeOffset, queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1); + queue->CryptoInfo->bHiddenVolProtectionAction = TRUE; + + // Deny this write operation to prevent the hidden volume from being overwritten + CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); + continue; + } + } + } + else if (item->Write + && RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET + TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE - 1)) + { + // Prevent inappropriately designed software from damaging important data that may be out of sync with the backup on the Rescue Disk (such as the end of the encrypted area). + Dump ("Preventing write to the system encryption key data area\n"); + CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); + continue; + } + else if (item->Write && IsHiddenSystemRunning() + && (RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, SECTOR_SIZE, TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE - 1) + || RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, GetBootDriveLength(), _I64_MAX))) + { + Dump ("Preventing write to boot loader or host protected area\n"); + CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); + continue; + } + + dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); + + if (dataBuffer == NULL) + { + CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); + continue; + } + + // Divide data block to fragments to enable efficient overlapping of encryption and IO operations + + dataRemaining = item->OriginalLength; + fragmentOffset = item->OriginalOffset; + + while (dataRemaining > 0) + { + BOOL isLastFragment = dataRemaining <= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + + ULONG dataFragmentLength = isLastFragment ? dataRemaining : TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + activeFragmentBuffer = (activeFragmentBuffer == queue->FragmentBufferA ? queue->FragmentBufferB : queue->FragmentBufferA); + + InterlockedIncrement (&queue->IoThreadPendingRequestCount); + + // Create IO request + request = GetPoolBuffer (queue, sizeof (EncryptedIoRequest)); + request->Item = item; + request->CompleteOriginalIrp = isLastFragment; + request->Offset = fragmentOffset; + request->Data = activeFragmentBuffer; + request->OrigDataBufferFragment = dataBuffer; + request->Length = dataFragmentLength; + + if (queue->IsFilterDevice) + { + if (queue->EncryptedAreaStart == -1 || queue->EncryptedAreaEnd == -1) + { + request->EncryptedLength = 0; + } + else + { + // Get intersection of data fragment with encrypted area + GetIntersection (fragmentOffset.QuadPart, dataFragmentLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength); + + request->EncryptedOffset = intersectStart - fragmentOffset.QuadPart; + request->EncryptedLength = intersectLength; + } + } + else + { + request->EncryptedOffset = 0; + request->EncryptedLength = dataFragmentLength; + } + + AcquireFragmentBuffer (queue, activeFragmentBuffer); + + if (item->Write) + { + // Encrypt data + memcpy (activeFragmentBuffer, dataBuffer, dataFragmentLength); + + if (request->EncryptedLength > 0) + { + UINT64_STRUCT dataUnit; + ASSERT (request->EncryptedOffset + request->EncryptedLength <= request->Offset.QuadPart + request->Length); + + dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) / ENCRYPTION_DATA_UNIT_SIZE; + + if (queue->CryptoInfo->bPartitionInInactiveSysEncScope) + dataUnit.Value += queue->CryptoInfo->FirstDataUnitNo.Value; + else if (queue->RemapEncryptedArea) + dataUnit.Value += queue->RemappedAreaDataUnitOffset; + + EncryptDataUnits (activeFragmentBuffer + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); + } + } + + // Queue IO request + ExInterlockedInsertTailList (&queue->IoThreadQueue, &request->ListEntry, &queue->IoThreadQueueLock); + KeSetEvent (&queue->IoThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE); + + if (isLastFragment) + break; + + dataRemaining -= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + dataBuffer += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + fragmentOffset.QuadPart += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + } + } + } + + PsTerminateSystemThread (STATUS_SUCCESS); +} + + +NTSTATUS EncryptedIoQueueAddIrp (EncryptedIoQueue *queue, PIRP irp) +{ + NTSTATUS status; + + InterlockedIncrement (&queue->OutstandingIoCount); + if (queue->StopPending) + { + Dump ("STATUS_DEVICE_NOT_READY out=%d\n", queue->OutstandingIoCount); + status = STATUS_DEVICE_NOT_READY; + goto err; + } + + status = IoAcquireRemoveLock (&queue->RemoveLock, irp); + if (!NT_SUCCESS (status)) + goto err; + +#ifdef TC_TRACE_IO_QUEUE + { + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp); + Dump ("* %I64d [%I64d] %c len=%d out=%d\n", irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.ByteOffset : irpSp->Parameters.Read.ByteOffset, GetElapsedTime (&queue->LastPerformanceCounter), irpSp->MajorFunction == IRP_MJ_WRITE ? 'W' : 'R', irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.Length : irpSp->Parameters.Read.Length, queue->OutstandingIoCount); + } +#endif + + IoMarkIrpPending (irp); + + ExInterlockedInsertTailList (&queue->MainThreadQueue, &irp->Tail.Overlay.ListEntry, &queue->MainThreadQueueLock); + KeSetEvent (&queue->MainThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE); + + return STATUS_PENDING; + +err: + DecrementOutstandingIoCount (queue); + return status; +} + + +NTSTATUS EncryptedIoQueueHoldWhenIdle (EncryptedIoQueue *queue, int64 timeout) +{ + NTSTATUS status; + ASSERT (!queue->Suspended); + + queue->SuspendPending = TRUE; + + while (TRUE) + { + while (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0) + { + LARGE_INTEGER waitTimeout; + + waitTimeout.QuadPart = timeout * -10000; + status = KeWaitForSingleObject (&queue->NoOutstandingIoEvent, Executive, KernelMode, FALSE, timeout != 0 ? &waitTimeout : NULL); + + if (status == STATUS_TIMEOUT) + status = STATUS_UNSUCCESSFUL; + + if (!NT_SUCCESS (status)) + { + queue->SuspendPending = FALSE; + return status; + } + + TCSleep (1); + if (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0) + { + queue->SuspendPending = FALSE; + return STATUS_UNSUCCESSFUL; + } + } + + KeClearEvent (&queue->QueueResumedEvent); + queue->Suspended = TRUE; + + if (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) == 0) + break; + + queue->Suspended = FALSE; + KeSetEvent (&queue->QueueResumedEvent, IO_DISK_INCREMENT, FALSE); + } + + queue->ReadAheadBufferValid = FALSE; + + queue->SuspendPending = FALSE; + return STATUS_SUCCESS; +} + + +BOOL EncryptedIoQueueIsSuspended (EncryptedIoQueue *queue) +{ + return queue->Suspended; +} + + +BOOL EncryptedIoQueueIsRunning (EncryptedIoQueue *queue) +{ + return !queue->StopPending; +} + + +NTSTATUS EncryptedIoQueueResumeFromHold (EncryptedIoQueue *queue) +{ + ASSERT (queue->Suspended); + + queue->Suspended = FALSE; + KeSetEvent (&queue->QueueResumedEvent, IO_DISK_INCREMENT, FALSE); + + return STATUS_SUCCESS; +} + + +NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue) +{ + NTSTATUS status; + EncryptedIoQueueBuffer *buffer; + int i; + + queue->StartPending = TRUE; + queue->ThreadExitRequested = FALSE; + + queue->OutstandingIoCount = 0; + queue->IoThreadPendingRequestCount = 0; + + queue->FirstPoolBuffer = NULL; + KeInitializeMutex (&queue->BufferPoolMutex, 0); + + KeInitializeEvent (&queue->NoOutstandingIoEvent, SynchronizationEvent, FALSE); + KeInitializeEvent (&queue->PoolBufferFreeEvent, SynchronizationEvent, FALSE); + KeInitializeEvent (&queue->QueueResumedEvent, SynchronizationEvent, FALSE); + + queue->FragmentBufferA = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); + if (!queue->FragmentBufferA) + goto noMemory; + + queue->FragmentBufferB = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); + if (!queue->FragmentBufferB) + goto noMemory; + + KeInitializeEvent (&queue->FragmentBufferAFreeEvent, SynchronizationEvent, TRUE); + KeInitializeEvent (&queue->FragmentBufferBFreeEvent, SynchronizationEvent, TRUE); + + queue->ReadAheadBufferValid = FALSE; + queue->ReadAheadBuffer = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); + if (!queue->ReadAheadBuffer) + goto noMemory; + + // Preallocate buffers + for (i = 0; i < TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; ++i) + { + if (i < TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT && !GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem))) + goto noMemory; + + if (!GetPoolBuffer (queue, sizeof (EncryptedIoRequest))) + goto noMemory; + } + + for (buffer = queue->FirstPoolBuffer; buffer != NULL; buffer = buffer->NextBuffer) + { + buffer->InUse = FALSE; + } + + // Main thread + InitializeListHead (&queue->MainThreadQueue); + KeInitializeSpinLock (&queue->MainThreadQueueLock); + KeInitializeEvent (&queue->MainThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE); + + status = TCStartThread (MainThreadProc, queue, &queue->MainThread); + if (!NT_SUCCESS (status)) + goto err; + + // IO thread + InitializeListHead (&queue->IoThreadQueue); + KeInitializeSpinLock (&queue->IoThreadQueueLock); + KeInitializeEvent (&queue->IoThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE); + + status = TCStartThread (IoThreadProc, queue, &queue->IoThread); + if (!NT_SUCCESS (status)) + { + queue->ThreadExitRequested = TRUE; + TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent); + goto err; + } + + // Completion thread + InitializeListHead (&queue->CompletionThreadQueue); + KeInitializeSpinLock (&queue->CompletionThreadQueueLock); + KeInitializeEvent (&queue->CompletionThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE); + + status = TCStartThread (CompletionThreadProc, queue, &queue->CompletionThread); + if (!NT_SUCCESS (status)) + { + queue->ThreadExitRequested = TRUE; + TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent); + TCStopThread (queue->IoThread, &queue->IoThreadQueueNotEmptyEvent); + goto err; + } + +#ifdef TC_TRACE_IO_QUEUE + GetElapsedTimeInit (&queue->LastPerformanceCounter); +#endif + + queue->StopPending = FALSE; + queue->StartPending = FALSE; + + Dump ("Queue started\n"); + return STATUS_SUCCESS; + +noMemory: + status = STATUS_INSUFFICIENT_RESOURCES; + +err: + if (queue->FragmentBufferA) + TCfree (queue->FragmentBufferA); + if (queue->FragmentBufferB) + TCfree (queue->FragmentBufferB); + + FreePoolBuffers (queue); + + queue->StartPending = FALSE; + return status; +} + + +NTSTATUS EncryptedIoQueueStop (EncryptedIoQueue *queue) +{ + ASSERT (!queue->StopPending); + queue->StopPending = TRUE; + + while (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0) + { + KeWaitForSingleObject (&queue->NoOutstandingIoEvent, Executive, KernelMode, FALSE, NULL); + } + + Dump ("Queue stopping out=%d\n", queue->OutstandingIoCount); + + queue->ThreadExitRequested = TRUE; + + TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent); + TCStopThread (queue->IoThread, &queue->IoThreadQueueNotEmptyEvent); + TCStopThread (queue->CompletionThread, &queue->CompletionThreadQueueNotEmptyEvent); + + TCfree (queue->FragmentBufferA); + TCfree (queue->FragmentBufferB); + TCfree (queue->ReadAheadBuffer); + + FreePoolBuffers (queue); + + Dump ("Queue stopped out=%d\n", queue->OutstandingIoCount); + return STATUS_SUCCESS; +} diff --git a/Driver/EncryptedIoQueue.h b/Driver/EncryptedIoQueue.h index f7b4168..acbd40f 100644 --- a/Driver/EncryptedIoQueue.h +++ b/Driver/EncryptedIoQueue.h @@ -1,165 +1,160 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE -#define TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE - -#include "TCdefs.h" -#include "Apidrvr.h" - -#if 0 -# define TC_TRACE_IO_QUEUE -#endif - -#define TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE (256 * 1024) - -#define TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT 8 -#define TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT 16 - -#define TC_ENC_IO_QUEUE_MEM_ALLOC_RETRY_DELAY 1 -#define TC_ENC_IO_QUEUE_MEM_ALLOC_TIMEOUT 1000 - - -typedef struct EncryptedIoQueueBufferStruct -{ - struct EncryptedIoQueueBufferStruct *NextBuffer; - - void *Address; - ULONG Size; - BOOL InUse; - -} EncryptedIoQueueBuffer; - - -typedef struct -{ - PDEVICE_OBJECT DeviceObject; - - KMUTEX BufferPoolMutex; - EncryptedIoQueueBuffer *FirstPoolBuffer; - - CRYPTO_INFO *CryptoInfo; - - // File-handle-based IO - HANDLE HostFileHandle; - int64 VirtualDeviceLength; - SECURITY_CLIENT_CONTEXT *SecurityClientContext; - - // Filter device - BOOL IsFilterDevice; - PDEVICE_OBJECT LowerDeviceObject; - int64 EncryptedAreaStart; - int64 EncryptedAreaEnd; - BOOL RemapEncryptedArea; - int64 RemappedAreaOffset; - int64 RemappedAreaDataUnitOffset; - IO_REMOVE_LOCK RemoveLock; - - // Main tread - PKTHREAD MainThread; - LIST_ENTRY MainThreadQueue; - KSPIN_LOCK MainThreadQueueLock; - KEVENT MainThreadQueueNotEmptyEvent; - - // IO thread - PKTHREAD IoThread; - LIST_ENTRY IoThreadQueue; - KSPIN_LOCK IoThreadQueueLock; - KEVENT IoThreadQueueNotEmptyEvent; - - // Completion thread - PKTHREAD CompletionThread; - LIST_ENTRY CompletionThreadQueue; - KSPIN_LOCK CompletionThreadQueueLock; - KEVENT CompletionThreadQueueNotEmptyEvent; - - // Fragment buffers - byte *FragmentBufferA; - byte *FragmentBufferB; - KEVENT FragmentBufferAFreeEvent; - KEVENT FragmentBufferBFreeEvent; - - // Read-ahead buffer - BOOL ReadAheadBufferValid; - LARGE_INTEGER LastReadOffset; - ULONG LastReadLength; - LARGE_INTEGER ReadAheadOffset; - ULONG ReadAheadLength; - byte *ReadAheadBuffer; - LARGE_INTEGER MaxReadAheadOffset; - - LONG OutstandingIoCount; - KEVENT NoOutstandingIoEvent; - LONG IoThreadPendingRequestCount; - - KEVENT RequestCompletedEvent; - KEVENT PoolBufferFreeEvent; - - __int64 TotalBytesRead; - __int64 TotalBytesWritten; - - volatile BOOL StartPending; - volatile BOOL ThreadExitRequested; - - volatile BOOL Suspended; - volatile BOOL SuspendPending; - volatile BOOL StopPending; - - KEVENT QueueResumedEvent; - -#ifdef TC_TRACE_IO_QUEUE - LARGE_INTEGER LastPerformanceCounter; -#endif - -} EncryptedIoQueue; - - -typedef struct -{ - EncryptedIoQueue *Queue; - PIRP OriginalIrp; - BOOL Write; - ULONG OriginalLength; - LARGE_INTEGER OriginalOffset; - LONG OutstandingRequestCount; - NTSTATUS Status; - -#ifdef TC_TRACE_IO_QUEUE - LARGE_INTEGER OriginalIrpOffset; -#endif - -} EncryptedIoQueueItem; - - -typedef struct -{ - EncryptedIoQueueItem *Item; - - BOOL CompleteOriginalIrp; - LARGE_INTEGER Offset; - ULONG Length; - int64 EncryptedOffset; - ULONG EncryptedLength; - byte *Data; - byte *OrigDataBufferFragment; - - LIST_ENTRY ListEntry; - LIST_ENTRY CompletionListEntry; -} EncryptedIoRequest; - - -NTSTATUS EncryptedIoQueueAddIrp (EncryptedIoQueue *queue, PIRP irp); -BOOL EncryptedIoQueueIsRunning (EncryptedIoQueue *queue); -BOOL EncryptedIoQueueIsSuspended (EncryptedIoQueue *queue); -NTSTATUS EncryptedIoQueueResumeFromHold (EncryptedIoQueue *queue); -NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue); -NTSTATUS EncryptedIoQueueStop (EncryptedIoQueue *queue); -NTSTATUS EncryptedIoQueueHoldWhenIdle (EncryptedIoQueue *queue, int64 timeout); - - -#endif // TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE +#define TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE + +#include "TCdefs.h" +#include "Apidrvr.h" + +#if 0 +# define TC_TRACE_IO_QUEUE +#endif + +#define TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE (256 * 1024) + +#define TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT 8 +#define TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT 16 + + +typedef struct EncryptedIoQueueBufferStruct +{ + struct EncryptedIoQueueBufferStruct *NextBuffer; + + void *Address; + ULONG Size; + BOOL InUse; + +} EncryptedIoQueueBuffer; + + +typedef struct +{ + PDEVICE_OBJECT DeviceObject; + + KMUTEX BufferPoolMutex; + EncryptedIoQueueBuffer *FirstPoolBuffer; + + CRYPTO_INFO *CryptoInfo; + + // File-handle-based IO + HANDLE HostFileHandle; + int64 VirtualDeviceLength; + SECURITY_CLIENT_CONTEXT *SecurityClientContext; + + // Filter device + BOOL IsFilterDevice; + PDEVICE_OBJECT LowerDeviceObject; + int64 EncryptedAreaStart; + int64 EncryptedAreaEnd; + BOOL RemapEncryptedArea; + int64 RemappedAreaOffset; + int64 RemappedAreaDataUnitOffset; + IO_REMOVE_LOCK RemoveLock; + + // Main tread + PKTHREAD MainThread; + LIST_ENTRY MainThreadQueue; + KSPIN_LOCK MainThreadQueueLock; + KEVENT MainThreadQueueNotEmptyEvent; + + // IO thread + PKTHREAD IoThread; + LIST_ENTRY IoThreadQueue; + KSPIN_LOCK IoThreadQueueLock; + KEVENT IoThreadQueueNotEmptyEvent; + + // Completion thread + PKTHREAD CompletionThread; + LIST_ENTRY CompletionThreadQueue; + KSPIN_LOCK CompletionThreadQueueLock; + KEVENT CompletionThreadQueueNotEmptyEvent; + + // Fragment buffers + byte *FragmentBufferA; + byte *FragmentBufferB; + KEVENT FragmentBufferAFreeEvent; + KEVENT FragmentBufferBFreeEvent; + + // Read-ahead buffer + BOOL ReadAheadBufferValid; + LARGE_INTEGER LastReadOffset; + ULONG LastReadLength; + LARGE_INTEGER ReadAheadOffset; + ULONG ReadAheadLength; + byte *ReadAheadBuffer; + LARGE_INTEGER MaxReadAheadOffset; + + LONG OutstandingIoCount; + KEVENT NoOutstandingIoEvent; + LONG IoThreadPendingRequestCount; + + KEVENT PoolBufferFreeEvent; + + __int64 TotalBytesRead; + __int64 TotalBytesWritten; + + volatile BOOL StartPending; + volatile BOOL ThreadExitRequested; + + volatile BOOL Suspended; + volatile BOOL SuspendPending; + volatile BOOL StopPending; + + KEVENT QueueResumedEvent; + +#ifdef TC_TRACE_IO_QUEUE + LARGE_INTEGER LastPerformanceCounter; +#endif + +} EncryptedIoQueue; + + +typedef struct +{ + EncryptedIoQueue *Queue; + PIRP OriginalIrp; + BOOL Write; + ULONG OriginalLength; + LARGE_INTEGER OriginalOffset; + NTSTATUS Status; + +#ifdef TC_TRACE_IO_QUEUE + LARGE_INTEGER OriginalIrpOffset; +#endif + +} EncryptedIoQueueItem; + + +typedef struct +{ + EncryptedIoQueueItem *Item; + + BOOL CompleteOriginalIrp; + LARGE_INTEGER Offset; + ULONG Length; + int64 EncryptedOffset; + ULONG EncryptedLength; + byte *Data; + byte *OrigDataBufferFragment; + + LIST_ENTRY ListEntry; + LIST_ENTRY CompletionListEntry; +} EncryptedIoRequest; + + +NTSTATUS EncryptedIoQueueAddIrp (EncryptedIoQueue *queue, PIRP irp); +BOOL EncryptedIoQueueIsRunning (EncryptedIoQueue *queue); +BOOL EncryptedIoQueueIsSuspended (EncryptedIoQueue *queue); +NTSTATUS EncryptedIoQueueResumeFromHold (EncryptedIoQueue *queue); +NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue); +NTSTATUS EncryptedIoQueueStop (EncryptedIoQueue *queue); +NTSTATUS EncryptedIoQueueHoldWhenIdle (EncryptedIoQueue *queue, int64 timeout); + + +#endif // TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE diff --git a/Driver/Fuse/Driver.make b/Driver/Fuse/Driver.make index 320e1eb..15bb9d9 100644 --- a/Driver/Fuse/Driver.make +++ b/Driver/Fuse/Driver.make @@ -1,16 +1,16 @@ -# -# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -NAME := Driver - -OBJS := -OBJS += FuseService.o - -CXXFLAGS += $(shell pkg-config fuse --cflags) - -include $(BUILD_INC)/Makefile.inc +# +# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +NAME := Driver + +OBJS := +OBJS += FuseService.o + +CXXFLAGS += $(shell pkg-config fuse --cflags) + +include $(BUILD_INC)/Makefile.inc diff --git a/Driver/Fuse/FuseService.cpp b/Driver/Fuse/FuseService.cpp index 8a8edba..30e0abd 100644 --- a/Driver/Fuse/FuseService.cpp +++ b/Driver/Fuse/FuseService.cpp @@ -1,592 +1,592 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#define FUSE_USE_VERSION 25 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "FuseService.h" -#include "Platform/FileStream.h" -#include "Platform/MemoryStream.h" -#include "Platform/Serializable.h" -#include "Platform/SystemLog.h" -#include "Platform/Unix/Pipe.h" -#include "Platform/Unix/Poller.h" -#include "Volume/EncryptionThreadPool.h" -#include "Core/Core.h" - -namespace TrueCrypt -{ - static int fuse_service_access (const char *path, int mask) - { - try - { - if (!FuseService::CheckAccessRights()) - return -EACCES; - } - catch (...) - { - return FuseService::ExceptionToErrorCode(); - } - - return 0; - } - - static void *fuse_service_init () - { - try - { - // Termination signals are handled by a separate process to allow clean dismount on shutdown - struct sigaction action; - Memory::Zero (&action, sizeof (action)); - action.sa_handler = SIG_IGN; - - sigaction (SIGINT, &action, nullptr); - sigaction (SIGQUIT, &action, nullptr); - sigaction (SIGTERM, &action, nullptr); - - if (!EncryptionThreadPool::IsRunning()) - EncryptionThreadPool::Start(); - } - catch (exception &e) - { - SystemLog::WriteException (e); - } - catch (...) - { - SystemLog::WriteException (UnknownException (SRC_POS)); - } - - return nullptr; - } - - static void fuse_service_destroy (void *userdata) - { - try - { - FuseService::Dismount(); - } - catch (exception &e) - { - SystemLog::WriteException (e); - } - catch (...) - { - SystemLog::WriteException (UnknownException (SRC_POS)); - } - } - - static int fuse_service_getattr (const char *path, struct stat *statData) - { - try - { - Memory::Zero (statData, sizeof(*statData)); - - statData->st_uid = FuseService::GetUserId(); - statData->st_gid = FuseService::GetGroupId(); - statData->st_atime = time (NULL); - statData->st_ctime = time (NULL); - statData->st_mtime = time (NULL); - - if (strcmp (path, "/") == 0) - { - statData->st_mode = S_IFDIR | 0500; - statData->st_nlink = 2; - } - else - { - if (!FuseService::CheckAccessRights()) - return -EACCES; - - if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) - { - statData->st_mode = S_IFREG | 0600; - statData->st_nlink = 1; - statData->st_size = FuseService::GetVolumeSize(); - } - else if (strcmp (path, FuseService::GetControlPath()) == 0) - { - statData->st_mode = S_IFREG | 0600; - statData->st_nlink = 1; - statData->st_size = FuseService::GetVolumeInfo()->Size(); - } - else - { - return -ENOENT; - } - } - } - catch (...) - { - return FuseService::ExceptionToErrorCode(); - } - - return 0; - } - - static int fuse_service_opendir (const char *path, struct fuse_file_info *fi) - { - try - { - if (!FuseService::CheckAccessRights()) - return -EACCES; - - if (strcmp (path, "/") != 0) - return -ENOENT; - } - catch (...) - { - return FuseService::ExceptionToErrorCode(); - } - - return 0; - } - - static int fuse_service_open (const char *path, struct fuse_file_info *fi) - { - try - { - if (!FuseService::CheckAccessRights()) - return -EACCES; - - if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) - return 0; - - if (strcmp (path, FuseService::GetControlPath()) == 0) - { - fi->direct_io = 1; - return 0; - } - } - catch (...) - { - return FuseService::ExceptionToErrorCode(); - } - return -ENOENT; - } - - static int fuse_service_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) - { - try - { - if (!FuseService::CheckAccessRights()) - return -EACCES; - - if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) - { - try - { - // Test for read beyond the end of the volume - if (offset + size > FuseService::GetVolumeSize()) - size = FuseService::GetVolumeSize() - offset; - - size_t sectorSize = FuseService::GetVolumeSectorSize(); - if (size % sectorSize != 0 || offset % sectorSize != 0) - { - // Support for non-sector-aligned read operations is required by some loop device tools - // which may analyze the volume image before attaching it as a device - - uint64 alignedOffset = offset - (offset % sectorSize); - uint64 alignedSize = size + (offset % sectorSize); - - if (alignedSize % sectorSize != 0) - alignedSize += sectorSize - (alignedSize % sectorSize); - - SecureBuffer alignedBuffer (alignedSize); - - FuseService::ReadVolumeSectors (alignedBuffer, alignedOffset); - BufferPtr ((byte *) buf, size).CopyFrom (alignedBuffer.GetRange (offset % sectorSize, size)); - } - else - { - FuseService::ReadVolumeSectors (BufferPtr ((byte *) buf, size), offset); - } - } - catch (MissingVolumeData) - { - return 0; - } - - return size; - } - - if (strcmp (path, FuseService::GetControlPath()) == 0) - { - shared_ptr infoBuf = FuseService::GetVolumeInfo(); - BufferPtr outBuf ((byte *)buf, size); - - if (offset >= infoBuf->Size()) - return 0; - - if (offset + size > infoBuf->Size()) - size = infoBuf->Size () - offset; - - outBuf.CopyFrom (infoBuf->GetRange (offset, size)); - return size; - } - } - catch (...) - { - return FuseService::ExceptionToErrorCode(); - } - - return -ENOENT; - } - - static int fuse_service_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) - { - try - { - if (!FuseService::CheckAccessRights()) - return -EACCES; - - if (strcmp (path, "/") != 0) - return -ENOENT; - - filler (buf, ".", NULL, 0); - filler (buf, "..", NULL, 0); - filler (buf, FuseService::GetVolumeImagePath() + 1, NULL, 0); - filler (buf, FuseService::GetControlPath() + 1, NULL, 0); - } - catch (...) - { - return FuseService::ExceptionToErrorCode(); - } - - return 0; - } - - static int fuse_service_write (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) - { - try - { - if (!FuseService::CheckAccessRights()) - return -EACCES; - - if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) - { - FuseService::WriteVolumeSectors (BufferPtr ((byte *) buf, size), offset); - return size; - } - - if (strcmp (path, FuseService::GetControlPath()) == 0) - { - if (FuseService::AuxDeviceInfoReceived()) - return -EACCES; - - FuseService::ReceiveAuxDeviceInfo (ConstBufferPtr ((const byte *)buf, size)); - return size; - } - } -#ifdef TC_FREEBSD - // FreeBSD apparently retries failed write operations forever, which may lead to a system crash. - catch (VolumeReadOnly&) - { - return size; - } - catch (VolumeProtected&) - { - return size; - } -#endif - catch (...) - { - return FuseService::ExceptionToErrorCode(); - } - - return -ENOENT; - } - - bool FuseService::CheckAccessRights () - { - return fuse_get_context()->uid == 0 || fuse_get_context()->uid == UserId; - } - - void FuseService::CloseMountedVolume () - { - if (MountedVolume) - { - // This process will exit before the use count of MountedVolume reaches zero - if (MountedVolume->GetFile().use_count() > 1) - MountedVolume->GetFile()->Close(); - - if (MountedVolume.use_count() > 1) - delete MountedVolume.get(); - - MountedVolume.reset(); - } - } - - void FuseService::Dismount () - { - CloseMountedVolume(); - - if (EncryptionThreadPool::IsRunning()) - EncryptionThreadPool::Stop(); - } - - int FuseService::ExceptionToErrorCode () - { - try - { - throw; - } - catch (std::bad_alloc) - { - return -ENOMEM; - } - catch (ParameterIncorrect &e) - { - SystemLog::WriteException (e); - return -EINVAL; - } - catch (VolumeProtected&) - { - return -EIO; - } - catch (VolumeReadOnly&) - { - return -EPERM; - } - catch (SystemException &e) - { - SystemLog::WriteException (e); - return -static_cast (e.GetErrorCode()); - } - catch (std::exception &e) - { - SystemLog::WriteException (e); - return -EINTR; - } - catch (...) - { - SystemLog::WriteException (UnknownException (SRC_POS)); - return -EINTR; - } - } - - shared_ptr FuseService::GetVolumeInfo () - { - shared_ptr stream (new MemoryStream); - - { - ScopeLock lock (OpenVolumeInfoMutex); - - OpenVolumeInfo.Set (*MountedVolume); - OpenVolumeInfo.SlotNumber = SlotNumber; - - OpenVolumeInfo.Serialize (stream); - } - - ConstBufferPtr infoBuf = dynamic_cast (*stream); - shared_ptr outBuf (new Buffer (infoBuf.Size())); - outBuf->CopyFrom (infoBuf); - - return outBuf; - } - - const char *FuseService::GetVolumeImagePath () - { -#ifdef TC_MACOSX - return "/volume.dmg"; -#else - return "/volume"; -#endif - } - - uint64 FuseService::GetVolumeSize () - { - if (!MountedVolume) - throw NotInitialized (SRC_POS); - - return MountedVolume->GetSize(); - } - - void FuseService::Mount (shared_ptr openVolume, VolumeSlotNumber slotNumber, const string &fuseMountPoint) - { - list args; - args.push_back (FuseService::GetDeviceType()); - args.push_back (fuseMountPoint); - -#ifdef TC_MACOSX - args.push_back ("-o"); - args.push_back ("noping_diskarb"); - args.push_back ("-o"); - args.push_back ("nobrowse"); - - if (getuid() == 0 || geteuid() == 0) -#endif - { - args.push_back ("-o"); - args.push_back ("allow_other"); - } - - ExecFunctor execFunctor (openVolume, slotNumber); - Process::Execute ("fuse", args, -1, &execFunctor); - - for (int t = 0; true; t++) - { - try - { - if (FilesystemPath (fuseMountPoint + FuseService::GetControlPath()).GetType() == FilesystemPathType::File) - break; - } - catch (...) - { - if (t > 50) - throw; - - Thread::Sleep (100); - } - } - } - - void FuseService::ReadVolumeSectors (const BufferPtr &buffer, uint64 byteOffset) - { - if (!MountedVolume) - throw NotInitialized (SRC_POS); - - MountedVolume->ReadSectors (buffer, byteOffset); - } - - void FuseService::ReceiveAuxDeviceInfo (const ConstBufferPtr &buffer) - { - shared_ptr stream (new MemoryStream (buffer)); - Serializer sr (stream); - - ScopeLock lock (OpenVolumeInfoMutex); - OpenVolumeInfo.VirtualDevice = sr.DeserializeString ("VirtualDevice"); - OpenVolumeInfo.LoopDevice = sr.DeserializeString ("LoopDevice"); - } - - void FuseService::SendAuxDeviceInfo (const DirectoryPath &fuseMountPoint, const DevicePath &virtualDevice, const DevicePath &loopDevice) - { - File fuseServiceControl; - fuseServiceControl.Open (string (fuseMountPoint) + GetControlPath(), File::OpenWrite); - - shared_ptr stream (new MemoryStream); - Serializer sr (stream); - - sr.Serialize ("VirtualDevice", string (virtualDevice)); - sr.Serialize ("LoopDevice", string (loopDevice)); - fuseServiceControl.Write (dynamic_cast (*stream)); - } - - void FuseService::WriteVolumeSectors (const ConstBufferPtr &buffer, uint64 byteOffset) - { - if (!MountedVolume) - throw NotInitialized (SRC_POS); - - MountedVolume->WriteSectors (buffer, byteOffset); - } - - void FuseService::OnSignal (int signal) - { - try - { - shared_ptr volume = Core->GetMountedVolume (SlotNumber); - - if (volume) - Core->DismountVolume (volume, true); - } - catch (...) { } - - _exit (0); - } - - void FuseService::ExecFunctor::operator() (int argc, char *argv[]) - { - struct timeval tv; - gettimeofday (&tv, NULL); - FuseService::OpenVolumeInfo.SerialInstanceNumber = (uint64)tv.tv_sec * 1000000ULL + tv.tv_usec; - - FuseService::MountedVolume = MountedVolume; - FuseService::SlotNumber = SlotNumber; - - FuseService::UserId = getuid(); - FuseService::GroupId = getgid(); - - if (getenv ("SUDO_UID")) - { - try - { - string s (getenv ("SUDO_UID")); - FuseService::UserId = static_cast (StringConverter::ToUInt64 (s)); - - if (getenv ("SUDO_GID")) - { - s = getenv ("SUDO_GID"); - FuseService::GroupId = static_cast (StringConverter::ToUInt64 (s)); - } - } - catch (...) { } - } - - static fuse_operations fuse_service_oper; - - fuse_service_oper.access = fuse_service_access; - fuse_service_oper.destroy = fuse_service_destroy; - fuse_service_oper.getattr = fuse_service_getattr; - fuse_service_oper.init = fuse_service_init; - fuse_service_oper.open = fuse_service_open; - fuse_service_oper.opendir = fuse_service_opendir; - fuse_service_oper.read = fuse_service_read; - fuse_service_oper.readdir = fuse_service_readdir; - fuse_service_oper.write = fuse_service_write; - - // Create a new session - setsid (); - - // Fork handler of termination signals - SignalHandlerPipe.reset (new Pipe); - - int forkedPid = fork(); - throw_sys_if (forkedPid == -1); - - if (forkedPid == 0) - { - CloseMountedVolume(); - - struct sigaction action; - Memory::Zero (&action, sizeof (action)); - action.sa_handler = OnSignal; - - sigaction (SIGINT, &action, nullptr); - sigaction (SIGQUIT, &action, nullptr); - sigaction (SIGTERM, &action, nullptr); - - // Wait for the exit of the main service - byte buf[1]; - if (read (SignalHandlerPipe->GetReadFD(), buf, sizeof (buf))) { } // Errors ignored - - _exit (0); - } - - SignalHandlerPipe->GetWriteFD(); - - _exit (fuse_main (argc, argv, &fuse_service_oper)); - } - - VolumeInfo FuseService::OpenVolumeInfo; - Mutex FuseService::OpenVolumeInfoMutex; - shared_ptr FuseService::MountedVolume; - VolumeSlotNumber FuseService::SlotNumber; - uid_t FuseService::UserId; - gid_t FuseService::GroupId; - auto_ptr FuseService::SignalHandlerPipe; -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#define FUSE_USE_VERSION 25 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FuseService.h" +#include "Platform/FileStream.h" +#include "Platform/MemoryStream.h" +#include "Platform/Serializable.h" +#include "Platform/SystemLog.h" +#include "Platform/Unix/Pipe.h" +#include "Platform/Unix/Poller.h" +#include "Volume/EncryptionThreadPool.h" +#include "Core/Core.h" + +namespace TrueCrypt +{ + static int fuse_service_access (const char *path, int mask) + { + try + { + if (!FuseService::CheckAccessRights()) + return -EACCES; + } + catch (...) + { + return FuseService::ExceptionToErrorCode(); + } + + return 0; + } + + static void *fuse_service_init () + { + try + { + // Termination signals are handled by a separate process to allow clean dismount on shutdown + struct sigaction action; + Memory::Zero (&action, sizeof (action)); + action.sa_handler = SIG_IGN; + + sigaction (SIGINT, &action, nullptr); + sigaction (SIGQUIT, &action, nullptr); + sigaction (SIGTERM, &action, nullptr); + + if (!EncryptionThreadPool::IsRunning()) + EncryptionThreadPool::Start(); + } + catch (exception &e) + { + SystemLog::WriteException (e); + } + catch (...) + { + SystemLog::WriteException (UnknownException (SRC_POS)); + } + + return nullptr; + } + + static void fuse_service_destroy (void *userdata) + { + try + { + FuseService::Dismount(); + } + catch (exception &e) + { + SystemLog::WriteException (e); + } + catch (...) + { + SystemLog::WriteException (UnknownException (SRC_POS)); + } + } + + static int fuse_service_getattr (const char *path, struct stat *statData) + { + try + { + Memory::Zero (statData, sizeof(*statData)); + + statData->st_uid = FuseService::GetUserId(); + statData->st_gid = FuseService::GetGroupId(); + statData->st_atime = time (NULL); + statData->st_ctime = time (NULL); + statData->st_mtime = time (NULL); + + if (strcmp (path, "/") == 0) + { + statData->st_mode = S_IFDIR | 0500; + statData->st_nlink = 2; + } + else + { + if (!FuseService::CheckAccessRights()) + return -EACCES; + + if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) + { + statData->st_mode = S_IFREG | 0600; + statData->st_nlink = 1; + statData->st_size = FuseService::GetVolumeSize(); + } + else if (strcmp (path, FuseService::GetControlPath()) == 0) + { + statData->st_mode = S_IFREG | 0600; + statData->st_nlink = 1; + statData->st_size = FuseService::GetVolumeInfo()->Size(); + } + else + { + return -ENOENT; + } + } + } + catch (...) + { + return FuseService::ExceptionToErrorCode(); + } + + return 0; + } + + static int fuse_service_opendir (const char *path, struct fuse_file_info *fi) + { + try + { + if (!FuseService::CheckAccessRights()) + return -EACCES; + + if (strcmp (path, "/") != 0) + return -ENOENT; + } + catch (...) + { + return FuseService::ExceptionToErrorCode(); + } + + return 0; + } + + static int fuse_service_open (const char *path, struct fuse_file_info *fi) + { + try + { + if (!FuseService::CheckAccessRights()) + return -EACCES; + + if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) + return 0; + + if (strcmp (path, FuseService::GetControlPath()) == 0) + { + fi->direct_io = 1; + return 0; + } + } + catch (...) + { + return FuseService::ExceptionToErrorCode(); + } + return -ENOENT; + } + + static int fuse_service_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) + { + try + { + if (!FuseService::CheckAccessRights()) + return -EACCES; + + if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) + { + try + { + // Test for read beyond the end of the volume + if ((uint64) offset + size > FuseService::GetVolumeSize()) + size = FuseService::GetVolumeSize() - offset; + + size_t sectorSize = FuseService::GetVolumeSectorSize(); + if (size % sectorSize != 0 || offset % sectorSize != 0) + { + // Support for non-sector-aligned read operations is required by some loop device tools + // which may analyze the volume image before attaching it as a device + + uint64 alignedOffset = offset - (offset % sectorSize); + uint64 alignedSize = size + (offset % sectorSize); + + if (alignedSize % sectorSize != 0) + alignedSize += sectorSize - (alignedSize % sectorSize); + + SecureBuffer alignedBuffer (alignedSize); + + FuseService::ReadVolumeSectors (alignedBuffer, alignedOffset); + BufferPtr ((byte *) buf, size).CopyFrom (alignedBuffer.GetRange (offset % sectorSize, size)); + } + else + { + FuseService::ReadVolumeSectors (BufferPtr ((byte *) buf, size), offset); + } + } + catch (MissingVolumeData) + { + return 0; + } + + return size; + } + + if (strcmp (path, FuseService::GetControlPath()) == 0) + { + shared_ptr infoBuf = FuseService::GetVolumeInfo(); + BufferPtr outBuf ((byte *)buf, size); + + if (offset >= (off_t) infoBuf->Size()) + return 0; + + if (offset + size > infoBuf->Size()) + size = infoBuf->Size () - offset; + + outBuf.CopyFrom (infoBuf->GetRange (offset, size)); + return size; + } + } + catch (...) + { + return FuseService::ExceptionToErrorCode(); + } + + return -ENOENT; + } + + static int fuse_service_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) + { + try + { + if (!FuseService::CheckAccessRights()) + return -EACCES; + + if (strcmp (path, "/") != 0) + return -ENOENT; + + filler (buf, ".", NULL, 0); + filler (buf, "..", NULL, 0); + filler (buf, FuseService::GetVolumeImagePath() + 1, NULL, 0); + filler (buf, FuseService::GetControlPath() + 1, NULL, 0); + } + catch (...) + { + return FuseService::ExceptionToErrorCode(); + } + + return 0; + } + + static int fuse_service_write (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) + { + try + { + if (!FuseService::CheckAccessRights()) + return -EACCES; + + if (strcmp (path, FuseService::GetVolumeImagePath()) == 0) + { + FuseService::WriteVolumeSectors (BufferPtr ((byte *) buf, size), offset); + return size; + } + + if (strcmp (path, FuseService::GetControlPath()) == 0) + { + if (FuseService::AuxDeviceInfoReceived()) + return -EACCES; + + FuseService::ReceiveAuxDeviceInfo (ConstBufferPtr ((const byte *)buf, size)); + return size; + } + } +#ifdef TC_FREEBSD + // FreeBSD apparently retries failed write operations forever, which may lead to a system crash. + catch (VolumeReadOnly&) + { + return size; + } + catch (VolumeProtected&) + { + return size; + } +#endif + catch (...) + { + return FuseService::ExceptionToErrorCode(); + } + + return -ENOENT; + } + + bool FuseService::CheckAccessRights () + { + return fuse_get_context()->uid == 0 || fuse_get_context()->uid == UserId; + } + + void FuseService::CloseMountedVolume () + { + if (MountedVolume) + { + // This process will exit before the use count of MountedVolume reaches zero + if (MountedVolume->GetFile().use_count() > 1) + MountedVolume->GetFile()->Close(); + + if (MountedVolume.use_count() > 1) + delete MountedVolume.get(); + + MountedVolume.reset(); + } + } + + void FuseService::Dismount () + { + CloseMountedVolume(); + + if (EncryptionThreadPool::IsRunning()) + EncryptionThreadPool::Stop(); + } + + int FuseService::ExceptionToErrorCode () + { + try + { + throw; + } + catch (std::bad_alloc) + { + return -ENOMEM; + } + catch (ParameterIncorrect &e) + { + SystemLog::WriteException (e); + return -EINVAL; + } + catch (VolumeProtected&) + { + return -EPERM; + } + catch (VolumeReadOnly&) + { + return -EPERM; + } + catch (SystemException &e) + { + SystemLog::WriteException (e); + return -static_cast (e.GetErrorCode()); + } + catch (std::exception &e) + { + SystemLog::WriteException (e); + return -EINTR; + } + catch (...) + { + SystemLog::WriteException (UnknownException (SRC_POS)); + return -EINTR; + } + } + + shared_ptr FuseService::GetVolumeInfo () + { + shared_ptr stream (new MemoryStream); + + { + ScopeLock lock (OpenVolumeInfoMutex); + + OpenVolumeInfo.Set (*MountedVolume); + OpenVolumeInfo.SlotNumber = SlotNumber; + + OpenVolumeInfo.Serialize (stream); + } + + ConstBufferPtr infoBuf = dynamic_cast (*stream); + shared_ptr outBuf (new Buffer (infoBuf.Size())); + outBuf->CopyFrom (infoBuf); + + return outBuf; + } + + const char *FuseService::GetVolumeImagePath () + { +#ifdef TC_MACOSX + return "/volume.dmg"; +#else + return "/volume"; +#endif + } + + uint64 FuseService::GetVolumeSize () + { + if (!MountedVolume) + throw NotInitialized (SRC_POS); + + return MountedVolume->GetSize(); + } + + void FuseService::Mount (shared_ptr openVolume, VolumeSlotNumber slotNumber, const string &fuseMountPoint) + { + list args; + args.push_back (FuseService::GetDeviceType()); + args.push_back (fuseMountPoint); + +#ifdef TC_MACOSX + args.push_back ("-o"); + args.push_back ("noping_diskarb"); + args.push_back ("-o"); + args.push_back ("nobrowse"); + + if (getuid() == 0 || geteuid() == 0) +#endif + { + args.push_back ("-o"); + args.push_back ("allow_other"); + } + + ExecFunctor execFunctor (openVolume, slotNumber); + Process::Execute ("fuse", args, -1, &execFunctor); + + for (int t = 0; true; t++) + { + try + { + if (FilesystemPath (fuseMountPoint + FuseService::GetControlPath()).GetType() == FilesystemPathType::File) + break; + } + catch (...) + { + if (t > 50) + throw; + + Thread::Sleep (100); + } + } + } + + void FuseService::ReadVolumeSectors (const BufferPtr &buffer, uint64 byteOffset) + { + if (!MountedVolume) + throw NotInitialized (SRC_POS); + + MountedVolume->ReadSectors (buffer, byteOffset); + } + + void FuseService::ReceiveAuxDeviceInfo (const ConstBufferPtr &buffer) + { + shared_ptr stream (new MemoryStream (buffer)); + Serializer sr (stream); + + ScopeLock lock (OpenVolumeInfoMutex); + OpenVolumeInfo.VirtualDevice = sr.DeserializeString ("VirtualDevice"); + OpenVolumeInfo.LoopDevice = sr.DeserializeString ("LoopDevice"); + } + + void FuseService::SendAuxDeviceInfo (const DirectoryPath &fuseMountPoint, const DevicePath &virtualDevice, const DevicePath &loopDevice) + { + File fuseServiceControl; + fuseServiceControl.Open (string (fuseMountPoint) + GetControlPath(), File::OpenWrite); + + shared_ptr stream (new MemoryStream); + Serializer sr (stream); + + sr.Serialize ("VirtualDevice", string (virtualDevice)); + sr.Serialize ("LoopDevice", string (loopDevice)); + fuseServiceControl.Write (dynamic_cast (*stream)); + } + + void FuseService::WriteVolumeSectors (const ConstBufferPtr &buffer, uint64 byteOffset) + { + if (!MountedVolume) + throw NotInitialized (SRC_POS); + + MountedVolume->WriteSectors (buffer, byteOffset); + } + + void FuseService::OnSignal (int signal) + { + try + { + shared_ptr volume = Core->GetMountedVolume (SlotNumber); + + if (volume) + Core->DismountVolume (volume, true); + } + catch (...) { } + + _exit (0); + } + + void FuseService::ExecFunctor::operator() (int argc, char *argv[]) + { + struct timeval tv; + gettimeofday (&tv, NULL); + FuseService::OpenVolumeInfo.SerialInstanceNumber = (uint64)tv.tv_sec * 1000000ULL + tv.tv_usec; + + FuseService::MountedVolume = MountedVolume; + FuseService::SlotNumber = SlotNumber; + + FuseService::UserId = getuid(); + FuseService::GroupId = getgid(); + + if (getenv ("SUDO_UID")) + { + try + { + string s (getenv ("SUDO_UID")); + FuseService::UserId = static_cast (StringConverter::ToUInt64 (s)); + + if (getenv ("SUDO_GID")) + { + s = getenv ("SUDO_GID"); + FuseService::GroupId = static_cast (StringConverter::ToUInt64 (s)); + } + } + catch (...) { } + } + + static fuse_operations fuse_service_oper; + + fuse_service_oper.access = fuse_service_access; + fuse_service_oper.destroy = fuse_service_destroy; + fuse_service_oper.getattr = fuse_service_getattr; + fuse_service_oper.init = fuse_service_init; + fuse_service_oper.open = fuse_service_open; + fuse_service_oper.opendir = fuse_service_opendir; + fuse_service_oper.read = fuse_service_read; + fuse_service_oper.readdir = fuse_service_readdir; + fuse_service_oper.write = fuse_service_write; + + // Create a new session + setsid (); + + // Fork handler of termination signals + SignalHandlerPipe.reset (new Pipe); + + int forkedPid = fork(); + throw_sys_if (forkedPid == -1); + + if (forkedPid == 0) + { + CloseMountedVolume(); + + struct sigaction action; + Memory::Zero (&action, sizeof (action)); + action.sa_handler = OnSignal; + + sigaction (SIGINT, &action, nullptr); + sigaction (SIGQUIT, &action, nullptr); + sigaction (SIGTERM, &action, nullptr); + + // Wait for the exit of the main service + byte buf[1]; + if (read (SignalHandlerPipe->GetReadFD(), buf, sizeof (buf))) { } // Errors ignored + + _exit (0); + } + + SignalHandlerPipe->GetWriteFD(); + + _exit (fuse_main (argc, argv, &fuse_service_oper)); + } + + VolumeInfo FuseService::OpenVolumeInfo; + Mutex FuseService::OpenVolumeInfoMutex; + shared_ptr FuseService::MountedVolume; + VolumeSlotNumber FuseService::SlotNumber; + uid_t FuseService::UserId; + gid_t FuseService::GroupId; + auto_ptr FuseService::SignalHandlerPipe; +} diff --git a/Driver/Fuse/FuseService.h b/Driver/Fuse/FuseService.h index 535db09..1224fc6 100644 --- a/Driver/Fuse/FuseService.h +++ b/Driver/Fuse/FuseService.h @@ -1,73 +1,73 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Driver_Fuse_FuseService -#define TC_HEADER_Driver_Fuse_FuseService - -#include "Platform/Platform.h" -#include "Platform/Unix/Pipe.h" -#include "Platform/Unix/Process.h" -#include "Volume/VolumeInfo.h" -#include "Volume/Volume.h" - -namespace TrueCrypt -{ - - class FuseService - { - protected: - struct ExecFunctor : public ProcessExecFunctor - { - ExecFunctor (shared_ptr openVolume, VolumeSlotNumber slotNumber) - : MountedVolume (openVolume), SlotNumber (slotNumber) - { - } - virtual void operator() (int argc, char *argv[]); - - protected: - shared_ptr MountedVolume; - VolumeSlotNumber SlotNumber; - }; - - friend class ExecFunctor; - - public: - static bool AuxDeviceInfoReceived () { return !OpenVolumeInfo.VirtualDevice.IsEmpty(); } - static bool CheckAccessRights (); - static void Dismount (); - static int ExceptionToErrorCode (); - static const char *GetControlPath () { return "/control"; } - static const char *GetVolumeImagePath (); - static string GetDeviceType () { return "truecrypt"; } - static uid_t GetGroupId () { return GroupId; } - static uid_t GetUserId () { return UserId; } - static shared_ptr GetVolumeInfo (); - static uint64 GetVolumeSize (); - static uint64 GetVolumeSectorSize () { return MountedVolume->GetSectorSize(); } - static void Mount (shared_ptr openVolume, VolumeSlotNumber slotNumber, const string &fuseMountPoint); - static void ReadVolumeSectors (const BufferPtr &buffer, uint64 byteOffset); - static void ReceiveAuxDeviceInfo (const ConstBufferPtr &buffer); - static void SendAuxDeviceInfo (const DirectoryPath &fuseMountPoint, const DevicePath &virtualDevice, const DevicePath &loopDevice = DevicePath()); - static void WriteVolumeSectors (const ConstBufferPtr &buffer, uint64 byteOffset); - - protected: - FuseService (); - static void CloseMountedVolume (); - static void OnSignal (int signal); - - static VolumeInfo OpenVolumeInfo; - static Mutex OpenVolumeInfoMutex; - static shared_ptr MountedVolume; - static VolumeSlotNumber SlotNumber; - static uid_t UserId; - static gid_t GroupId; - static auto_ptr SignalHandlerPipe; - }; -} - -#endif // TC_HEADER_Driver_Fuse_FuseService +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Driver_Fuse_FuseService +#define TC_HEADER_Driver_Fuse_FuseService + +#include "Platform/Platform.h" +#include "Platform/Unix/Pipe.h" +#include "Platform/Unix/Process.h" +#include "Volume/VolumeInfo.h" +#include "Volume/Volume.h" + +namespace TrueCrypt +{ + + class FuseService + { + protected: + struct ExecFunctor : public ProcessExecFunctor + { + ExecFunctor (shared_ptr openVolume, VolumeSlotNumber slotNumber) + : MountedVolume (openVolume), SlotNumber (slotNumber) + { + } + virtual void operator() (int argc, char *argv[]); + + protected: + shared_ptr MountedVolume; + VolumeSlotNumber SlotNumber; + }; + + friend class ExecFunctor; + + public: + static bool AuxDeviceInfoReceived () { return !OpenVolumeInfo.VirtualDevice.IsEmpty(); } + static bool CheckAccessRights (); + static void Dismount (); + static int ExceptionToErrorCode (); + static const char *GetControlPath () { return "/control"; } + static const char *GetVolumeImagePath (); + static string GetDeviceType () { return "truecrypt"; } + static uid_t GetGroupId () { return GroupId; } + static uid_t GetUserId () { return UserId; } + static shared_ptr GetVolumeInfo (); + static uint64 GetVolumeSize (); + static uint64 GetVolumeSectorSize () { return MountedVolume->GetSectorSize(); } + static void Mount (shared_ptr openVolume, VolumeSlotNumber slotNumber, const string &fuseMountPoint); + static void ReadVolumeSectors (const BufferPtr &buffer, uint64 byteOffset); + static void ReceiveAuxDeviceInfo (const ConstBufferPtr &buffer); + static void SendAuxDeviceInfo (const DirectoryPath &fuseMountPoint, const DevicePath &virtualDevice, const DevicePath &loopDevice = DevicePath()); + static void WriteVolumeSectors (const ConstBufferPtr &buffer, uint64 byteOffset); + + protected: + FuseService (); + static void CloseMountedVolume (); + static void OnSignal (int signal); + + static VolumeInfo OpenVolumeInfo; + static Mutex OpenVolumeInfoMutex; + static shared_ptr MountedVolume; + static VolumeSlotNumber SlotNumber; + static uid_t UserId; + static gid_t GroupId; + static auto_ptr SignalHandlerPipe; + }; +} + +#endif // TC_HEADER_Driver_Fuse_FuseService diff --git a/Driver/MAKEFILE b/Driver/MAKEFILE index 5acbbd2..53b9a3d 100644 --- a/Driver/MAKEFILE +++ b/Driver/MAKEFILE @@ -1 +1 @@ -!INCLUDE $(NTMAKEENV)\makefile.def +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/Driver/NTDRIVER.C b/Driver/NTDRIVER.C index 5d285d5..3504c64 100644 --- a/Driver/NTDRIVER.C +++ b/Driver/NTDRIVER.C @@ -1,3111 +1,3208 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "TCdefs.h" -#include -#include "Crypto.h" -#include "Fat.h" -#include "Tests.h" - -#include "Apidrvr.h" -#include "Boot/Windows/BootDefs.h" -#include "EncryptedIoQueue.h" -#include "EncryptionThreadPool.h" -#include "Ntdriver.h" -#include "Ntvol.h" -#include "DriveFilter.h" -#include "Cache.h" -#include "Volumes.h" -#include "VolumeFilter.h" - -#include -#include -#include -#include -#include - -/* Init section, which is thrown away as soon as DriverEntry returns */ -#pragma alloc_text(INIT,DriverEntry) -#pragma alloc_text(INIT,TCCreateRootDeviceObject) - -PDRIVER_OBJECT TCDriverObject; -KMUTEX driverMutex; /* Sync mutex for the entire driver */ -BOOL DriverShuttingDown = FALSE; -BOOL SelfTestsPassed; -int LastUniqueVolumeId; -ULONG OsMajorVersion; -ULONG OsMinorVersion; -BOOL ReferencedDeviceDeleted = FALSE; -BOOL TravelerMode = FALSE; -BOOL VolumeClassFilterRegistered = FALSE; -BOOL CacheBootPassword = FALSE; - - -NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) -{ - PKEY_VALUE_PARTIAL_INFORMATION startKeyValue; - int i; - - Dump ("DriverEntry " TC_APP_NAME " " VERSION_STRING "\n"); - - TCDriverObject = DriverObject; - KeInitializeMutex (&driverMutex, 0); - - EncryptionThreadPoolStart(); - SelfTestsPassed = AutoTestAlgorithms (); - PsGetVersion (&OsMajorVersion, &OsMinorVersion, NULL, NULL); - - ReadRegistryConfigFlags(); - - // Enable device class filters and load boot arguments if the driver is set to start at system boot - - if (NT_SUCCESS (TCReadRegistryKey (RegistryPath, L"Start", &startKeyValue))) - { - if (startKeyValue->Type == REG_DWORD && *((uint32 *) startKeyValue->Data) == SERVICE_BOOT_START) - { - if (!SelfTestsPassed) - TC_BUG_CHECK (STATUS_INVALID_PARAMETER); - - LoadBootArguments(); - VolumeClassFilterRegistered = IsVolumeClassFilterRegistered(); - - DriverObject->DriverExtension->AddDevice = DriverAddDevice; - } - - TCfree (startKeyValue); - } - - for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i) - { - DriverObject->MajorFunction[i] = TCDispatchQueueIRP; - } - - DriverObject->DriverUnload = TCUnloadDriver; - return TCCreateRootDeviceObject (DriverObject); -} - - -NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) -{ -#ifdef DEBUG - char nameInfoBuffer[128]; - POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION) nameInfoBuffer; - ULONG nameInfoSize; - Dump ("AddDevice pdo=%p type=%x name=%ws\n", pdo, pdo->DeviceType, NT_SUCCESS (ObQueryNameString (pdo, nameInfo, sizeof (nameInfoBuffer), &nameInfoSize)) ? nameInfo->Name.Buffer : L"?"); -#endif - - if (VolumeClassFilterRegistered && BootArgsValid && BootArgs.HiddenSystemPartitionStart != 0) - { - PWSTR interfaceLinks; - if (NT_SUCCESS (IoGetDeviceInterfaces (&GUID_DEVINTERFACE_VOLUME, pdo, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &interfaceLinks))) - { - if (interfaceLinks[0] != UNICODE_NULL) - { - Dump ("Volume pdo=%p interface=%ws\n", pdo, interfaceLinks); - ExFreePool (interfaceLinks); - - return VolumeFilterAddDevice (driverObject, pdo); - } - - ExFreePool (interfaceLinks); - } - } - - return DriveFilterAddDevice (driverObject, pdo); -} - - -// Dumps a memory region to debug output -void DumpMemory (void *mem, int size) -{ - unsigned char str[20]; - unsigned char *m = mem; - int i,j; - - for (j = 0; j < size / 8; j++) - { - memset (str,0,sizeof str); - for (i = 0; i < 8; i++) - { - if (m[i] > ' ' && m[i] <= '~') - str[i]=m[i]; - else - str[i]='.'; - } - - Dump ("0x%08p %02x %02x %02x %02x %02x %02x %02x %02x %s\n", - m, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], str); - - m+=8; - } -} - - -BOOL ValidateIOBufferSize (PIRP irp, size_t requiredBufferSize, ValidateIOBufferSizeType type) -{ - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp); - BOOL input = (type == ValidateInput || type == ValidateInputOutput); - BOOL output = (type == ValidateOutput || type == ValidateInputOutput); - - if ((input && irpSp->Parameters.DeviceIoControl.InputBufferLength < requiredBufferSize) - || (output && irpSp->Parameters.DeviceIoControl.OutputBufferLength < requiredBufferSize)) - { - Dump ("STATUS_BUFFER_TOO_SMALL ioctl=0x%x,%d in=%d out=%d reqsize=%d insize=%d outsize=%d\n", (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16), (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2), input, output, requiredBufferSize, irpSp->Parameters.DeviceIoControl.InputBufferLength, irpSp->Parameters.DeviceIoControl.OutputBufferLength); - - irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - irp->IoStatus.Information = 0; - return FALSE; - } - - if (!input && output) - memset (irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength); - - return TRUE; -} - - -/* TCDispatchQueueIRP queues any IRP's so that they can be processed later - by the thread -- or in some cases handles them immediately! */ -NTSTATUS TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - PEXTENSION Extension = (PEXTENSION) DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); - NTSTATUS ntStatus; - -#ifdef _DEBUG - if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && (Extension->bRootDevice || Extension->IsVolumeDevice)) - { - switch (irpSp->Parameters.DeviceIoControl.IoControlCode) - { - case TC_IOCTL_GET_MOUNTED_VOLUMES: - case TC_IOCTL_GET_PASSWORD_CACHE_STATUS: - case TC_IOCTL_GET_TRAVELER_MODE_STATUS: - case TC_IOCTL_SET_TRAVELER_MODE_STATUS: - case TC_IOCTL_OPEN_TEST: - case TC_IOCTL_GET_RESOLVED_SYMLINK: - case TC_IOCTL_GET_DRIVE_PARTITION_INFO: - case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES: - case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS: - case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING: - case IOCTL_DISK_CHECK_VERIFY: - break; - - default: - Dump ("%ls (0x%x %d)\n", - TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode), - (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16), - (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2)); - } - } -#endif - - if (!Extension->bRootDevice) - { - // Drive filter IRP - if (Extension->IsDriveFilterDevice) - return DriveFilterDispatchIrp (DeviceObject, Irp); - - // Volume filter IRP - if (Extension->IsVolumeFilterDevice) - return VolumeFilterDispatchIrp (DeviceObject, Irp); - } - - switch (irpSp->MajorFunction) - { - case IRP_MJ_CLOSE: - case IRP_MJ_CREATE: - case IRP_MJ_CLEANUP: - return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0); - - case IRP_MJ_SHUTDOWN: - if (Extension->bRootDevice) - { - DriverShuttingDown = TRUE; - - if (IsBootEncryptionSetupInProgress()) - AbortBootEncryptionSetup(); - - if (IsDecoySystemWipeInProgress()) - AbortDecoySystemWipe(); - - UnmountAllDevices (NULL, DeviceObject, TRUE); - - // Boot drive will be dismounted when IRP_MJ_POWER is received after IRP_MJ_SHUTDOWN - } - - return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0); - - case IRP_MJ_FLUSH_BUFFERS: - case IRP_MJ_READ: - case IRP_MJ_WRITE: - case IRP_MJ_DEVICE_CONTROL: - - if (Extension->bRootDevice) - { - if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) - return ProcessMainDeviceControlIrp (DeviceObject, Extension, Irp); - break; - } - - if (Extension->bShuttingDown) - { - Dump ("Device %d shutting down: STATUS_DEVICE_NOT_READY\n", Extension->nDosDriveNo); - return TCCompleteDiskIrp (Irp, STATUS_DEVICE_NOT_READY, 0); - } - - if (Extension->bRemovable - && (DeviceObject->Flags & DO_VERIFY_VOLUME) - && !(irpSp->Flags & SL_OVERRIDE_VERIFY_VOLUME) - && irpSp->MajorFunction != IRP_MJ_FLUSH_BUFFERS) - { - Dump ("Removable device %d has DO_VERIFY_VOLUME flag: STATUS_DEVICE_NOT_READY\n", Extension->nDosDriveNo); - return TCCompleteDiskIrp (Irp, STATUS_DEVICE_NOT_READY, 0); - } - - switch (irpSp->MajorFunction) - { - case IRP_MJ_READ: - case IRP_MJ_WRITE: - ntStatus = EncryptedIoQueueAddIrp (&Extension->Queue, Irp); - - if (ntStatus != STATUS_PENDING) - TCCompleteDiskIrp (Irp, ntStatus, 0); - - return ntStatus; - - case IRP_MJ_DEVICE_CONTROL: - IoMarkIrpPending (Irp); - - ExInterlockedInsertTailList (&Extension->ListEntry, &Irp->Tail.Overlay.ListEntry, &Extension->ListSpinLock); - KeReleaseSemaphore (&Extension->RequestSemaphore, IO_DISK_INCREMENT, 1, FALSE); - - return STATUS_PENDING; - - case IRP_MJ_FLUSH_BUFFERS: - return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0); - } - } - - return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0); -} - -NTSTATUS TCCreateRootDeviceObject (PDRIVER_OBJECT DriverObject) -{ - UNICODE_STRING Win32NameString, ntUnicodeString; - WCHAR dosname[32], ntname[32]; - PDEVICE_OBJECT DeviceObject; - NTSTATUS ntStatus; - BOOL *bRootExtension; - - Dump ("TCCreateRootDeviceObject BEGIN\n"); - ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); - - wcscpy (dosname, (LPWSTR) DOS_ROOT_PREFIX); - wcscpy (ntname, (LPWSTR) NT_ROOT_PREFIX); - RtlInitUnicodeString (&ntUnicodeString, ntname); - RtlInitUnicodeString (&Win32NameString, dosname); - - Dump ("Creating root device nt=%ls dos=%ls\n", ntname, dosname); - - ntStatus = IoCreateDevice ( - DriverObject, - sizeof (BOOL), - &ntUnicodeString, - FILE_DEVICE_UNKNOWN, - FILE_DEVICE_SECURE_OPEN, - FALSE, - &DeviceObject); - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus); - return ntStatus;/* Failed to create DeviceObject */ - } - - DeviceObject->Flags |= DO_DIRECT_IO; - DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; - - /* Setup the device extension */ - bRootExtension = (BOOL *) DeviceObject->DeviceExtension; - *bRootExtension = TRUE; - - ntStatus = IoCreateSymbolicLink (&Win32NameString, &ntUnicodeString); - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus); - IoDeleteDevice (DeviceObject); - return ntStatus; - } - - IoRegisterShutdownNotification (DeviceObject); - - Dump ("TCCreateRootDeviceObject STATUS_SUCCESS END\n"); - return STATUS_SUCCESS; -} - -NTSTATUS TCCreateDeviceObject (PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT * ppDeviceObject, - MOUNT_STRUCT * mount) -{ - UNICODE_STRING Win32NameString, ntUnicodeString; - WCHAR dosname[32], ntname[32]; - PEXTENSION Extension; - NTSTATUS ntStatus; - ULONG devChars = 0; - - Dump ("TCCreateDeviceObject BEGIN\n"); - ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); - - TCGetDosNameFromNumber (dosname, mount->nDosDriveNo); - TCGetNTNameFromNumber (ntname, mount->nDosDriveNo); - RtlInitUnicodeString (&ntUnicodeString, ntname); - RtlInitUnicodeString (&Win32NameString, dosname); - - devChars = FILE_DEVICE_SECURE_OPEN; - devChars |= mount->bMountReadOnly ? FILE_READ_ONLY_DEVICE : 0; - devChars |= mount->bMountRemovable ? FILE_REMOVABLE_MEDIA : 0; - - Dump ("Creating device nt=%ls dos=%ls\n", ntname, dosname); - - ntStatus = IoCreateDevice ( - DriverObject, /* Our Driver Object */ - sizeof (EXTENSION), /* Size of state information */ - &ntUnicodeString, /* Device name "\Device\Name" */ - FILE_DEVICE_DISK, /* Device type */ - devChars, /* Device characteristics */ - FALSE, /* Exclusive device */ - ppDeviceObject); /* Returned ptr to Device Object */ - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("TCCreateDeviceObject NTSTATUS = 0x%08x END\n", ntStatus); - return ntStatus;/* Failed to create DeviceObject */ - } - /* Initialize device object and extension. */ - - (*ppDeviceObject)->Flags |= DO_DIRECT_IO; - (*ppDeviceObject)->StackSize += 2; // Reduce occurrence of NO_MORE_IRP_STACK_LOCATIONS bug check caused by buggy drivers - - /* Setup the device extension */ - Extension = (PEXTENSION) (*ppDeviceObject)->DeviceExtension; - memset (Extension, 0, sizeof (EXTENSION)); - - Extension->IsVolumeDevice = TRUE; - Extension->lMagicNumber = 0xabfeacde; - Extension->nDosDriveNo = mount->nDosDriveNo; - Extension->bRemovable = mount->bMountRemovable; - - KeInitializeEvent (&Extension->keCreateEvent, SynchronizationEvent, FALSE); - KeInitializeSemaphore (&Extension->RequestSemaphore, 0L, MAXLONG); - KeInitializeSpinLock (&Extension->ListSpinLock); - InitializeListHead (&Extension->ListEntry); - - Dump ("TCCreateDeviceObject STATUS_SUCCESS END\n"); - - return STATUS_SUCCESS; -} - - -void DriverMutexWait () -{ - KeWaitForMutexObject (&driverMutex, Executive, KernelMode, FALSE, NULL); -} - - -void DriverMutexRelease () -{ - KeReleaseMutex (&driverMutex, FALSE); -} - - -NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp) -{ - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); - - switch (irpSp->Parameters.DeviceIoControl.IoControlCode) - { - - case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: - if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_NAME), ValidateOutput)) - { - Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME); - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - } - else - { - ULONG outLength; - UNICODE_STRING ntUnicodeString; - WCHAR ntName[256]; - PMOUNTDEV_NAME outputBuffer = (PMOUNTDEV_NAME) Irp->AssociatedIrp.SystemBuffer; - - TCGetNTNameFromNumber (ntName, Extension->nDosDriveNo); - RtlInitUnicodeString (&ntUnicodeString, ntName); - - outputBuffer->NameLength = ntUnicodeString.Length; - outLength = ntUnicodeString.Length + sizeof(USHORT); - - if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength) - { - Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME); - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - - break; - } - - RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = outLength; - - Dump ("name = %ls\n",ntName); - } - break; - - case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: - if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_UNIQUE_ID), ValidateOutput)) - { - Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID); - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - } - else - { - ULONG outLength; - UCHAR volId[128], tmp[] = { 0,0 }; - PMOUNTDEV_UNIQUE_ID outputBuffer = (PMOUNTDEV_UNIQUE_ID) Irp->AssociatedIrp.SystemBuffer; - - strcpy (volId, TC_UNIQUE_ID_PREFIX); - tmp[0] = 'A' + Extension->nDosDriveNo; - strcat (volId, tmp); - - outputBuffer->UniqueIdLength = (USHORT) strlen (volId); - outLength = strlen (volId) + sizeof(USHORT); - - if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength) - { - Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID); - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - break; - } - - RtlCopyMemory ((PCHAR)outputBuffer->UniqueId, volId, strlen (volId)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = outLength; - - Dump ("id = %s\n",volId); - } - break; - - case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: - { - ULONG outLength; - UNICODE_STRING ntUnicodeString; - WCHAR ntName[256]; - PMOUNTDEV_SUGGESTED_LINK_NAME outputBuffer = (PMOUNTDEV_SUGGESTED_LINK_NAME) Irp->AssociatedIrp.SystemBuffer; - - if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_SUGGESTED_LINK_NAME), ValidateOutput)) - { - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - Irp->IoStatus.Information = 0; - break; - } - - TCGetDosNameFromNumber (ntName, Extension->nDosDriveNo); - RtlInitUnicodeString (&ntUnicodeString, ntName); - - outLength = FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME,Name) + ntUnicodeString.Length; - - outputBuffer->UseOnlyIfThereAreNoOtherLinks = FALSE; - outputBuffer->NameLength = ntUnicodeString.Length; - - if(irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength) - { - Irp->IoStatus.Information = sizeof (MOUNTDEV_SUGGESTED_LINK_NAME); - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - break; - } - - RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = outLength; - - Dump ("link = %ls\n",ntName); - } - break; - - case IOCTL_DISK_GET_MEDIA_TYPES: - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - /* Return the drive geometry for the disk. Note that we - return values which were made up to suit the disk size. */ - if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY), ValidateOutput)) - { - PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY) - Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->MediaType = Extension->bRemovable ? RemovableMedia : FixedMedia; - outputBuffer->Cylinders.QuadPart = Extension->NumberOfCylinders; - outputBuffer->TracksPerCylinder = Extension->TracksPerCylinder; - outputBuffer->SectorsPerTrack = Extension->SectorsPerTrack; - outputBuffer->BytesPerSector = Extension->BytesPerSector; - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (DISK_GEOMETRY); - } - break; - - case IOCTL_DISK_GET_PARTITION_INFO: - if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION), ValidateOutput)) - { - PPARTITION_INFORMATION outputBuffer = (PPARTITION_INFORMATION) - Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->PartitionType = Extension->PartitionType; - outputBuffer->BootIndicator = FALSE; - outputBuffer->RecognizedPartition = TRUE; - outputBuffer->RewritePartition = FALSE; - outputBuffer->StartingOffset.QuadPart = SECTOR_SIZE; - outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; - outputBuffer->HiddenSectors = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION); - } - break; - - case IOCTL_DISK_GET_PARTITION_INFO_EX: - if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION_EX), ValidateOutput)) - { - PPARTITION_INFORMATION_EX outputBuffer = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->PartitionStyle = PARTITION_STYLE_MBR; - outputBuffer->RewritePartition = FALSE; - outputBuffer->StartingOffset.QuadPart = SECTOR_SIZE; - outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; - outputBuffer->Mbr.PartitionType = Extension->PartitionType; - outputBuffer->Mbr.BootIndicator = FALSE; - outputBuffer->Mbr.RecognizedPartition = TRUE; - outputBuffer->Mbr.HiddenSectors = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION_EX); - } - break; - - case IOCTL_DISK_GET_DRIVE_LAYOUT: - if (ValidateIOBufferSize (Irp, sizeof (DRIVE_LAYOUT_INFORMATION), ValidateOutput)) - { - PDRIVE_LAYOUT_INFORMATION outputBuffer = (PDRIVE_LAYOUT_INFORMATION) - Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->PartitionCount = 1; - outputBuffer->Signature = 0; - - outputBuffer->PartitionEntry->PartitionType = Extension->PartitionType; - outputBuffer->PartitionEntry->BootIndicator = FALSE; - outputBuffer->PartitionEntry->RecognizedPartition = TRUE; - outputBuffer->PartitionEntry->RewritePartition = FALSE; - outputBuffer->PartitionEntry->StartingOffset.QuadPart = SECTOR_SIZE; - outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength; - outputBuffer->PartitionEntry->HiddenSectors = 0; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION); - } - break; - - case IOCTL_DISK_GET_LENGTH_INFO: - if (!ValidateIOBufferSize (Irp, sizeof (GET_LENGTH_INFORMATION), ValidateOutput)) - { - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION); - } - else - { - PGET_LENGTH_INFORMATION outputBuffer = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->Length.QuadPart = Extension->DiskLength; - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION); - } - break; - - case IOCTL_DISK_VERIFY: - if (ValidateIOBufferSize (Irp, sizeof (VERIFY_INFORMATION), ValidateInput)) - { - PVERIFY_INFORMATION pVerifyInformation; - pVerifyInformation = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer; - - if (pVerifyInformation->StartingOffset.QuadPart + pVerifyInformation->Length > Extension->DiskLength) - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - else - { - IO_STATUS_BLOCK ioStatus; - PVOID buffer = TCalloc (max (pVerifyInformation->Length, PAGE_SIZE)); - - if (!buffer) - { - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - LARGE_INTEGER offset = pVerifyInformation->StartingOffset; - offset.QuadPart += Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset; - - Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, pVerifyInformation->Length, &offset, NULL); - TCfree (buffer); - - if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != pVerifyInformation->Length) - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - } - } - - Irp->IoStatus.Information = 0; - } - break; - - case IOCTL_DISK_CHECK_VERIFY: - case IOCTL_STORAGE_CHECK_VERIFY: - { - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - if (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof (ULONG)) - { - *((ULONG *) Irp->AssociatedIrp.SystemBuffer) = 0; - Irp->IoStatus.Information = sizeof (ULONG); - } - } - break; - - case IOCTL_DISK_IS_WRITABLE: - { - if (Extension->bReadOnly) - Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED; - else - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - } - break; - - case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: - - // Vista's filesystem defragmenter fails if IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS does not succeed. - if (OsMajorVersion < 6) - { - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - Irp->IoStatus.Information = 0; - } - else if (ValidateIOBufferSize (Irp, sizeof (VOLUME_DISK_EXTENTS), ValidateOutput)) - { - VOLUME_DISK_EXTENTS *extents = (VOLUME_DISK_EXTENTS *) Irp->AssociatedIrp.SystemBuffer; - - // No extent data can be returned as this is not a physical drive. - memset (extents, 0, sizeof (*extents)); - extents->NumberOfDiskExtents = 0; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (*extents); - } - break; - - default: - return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0); - } - -#ifdef DEBUG - if (!NT_SUCCESS (Irp->IoStatus.Status)) - { - Dump ("IOCTL error 0x%08x (0x%x %d)\n", - Irp->IoStatus.Status, - (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16), - (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2)); - } -#endif - - return TCCompleteDiskIrp (Irp, Irp->IoStatus.Status, Irp->IoStatus.Information); -} - - -NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp) -{ - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); - NTSTATUS ntStatus; - - switch (irpSp->Parameters.DeviceIoControl.IoControlCode) - { - case TC_IOCTL_GET_DRIVER_VERSION: - case TC_IOCTL_LEGACY_GET_DRIVER_VERSION: - if (ValidateIOBufferSize (Irp, sizeof (LONG), ValidateOutput)) - { - LONG tmp = VERSION_NUM; - memcpy (Irp->AssociatedIrp.SystemBuffer, &tmp, 4); - Irp->IoStatus.Information = sizeof (LONG); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - break; - - case TC_IOCTL_GET_DEVICE_REFCOUNT: - if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) - { - *(int *) Irp->AssociatedIrp.SystemBuffer = DeviceObject->ReferenceCount; - Irp->IoStatus.Information = sizeof (int); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - break; - - case TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED: - if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) - { - *(int *) Irp->AssociatedIrp.SystemBuffer = ReferencedDeviceDeleted; - Irp->IoStatus.Information = sizeof (int); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - break; - - case TC_IOCTL_IS_ANY_VOLUME_MOUNTED: - if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) - { - PDEVICE_OBJECT ListDevice; - *(int *) Irp->AssociatedIrp.SystemBuffer = 0; - - DriverMutexWait (); - - for (ListDevice = DeviceObject->DriverObject->DeviceObject; - ListDevice != (PDEVICE_OBJECT) NULL; ListDevice = ListDevice->NextDevice) - { - PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; - if (!ListExtension->bRootDevice - && ListExtension->IsVolumeDevice - && ListExtension->lMagicNumber == 0xabfeacde) - { - *(int *) Irp->AssociatedIrp.SystemBuffer = 1; - break; - } - } - - DriverMutexRelease (); - - if (IsBootDriveMounted()) - *(int *) Irp->AssociatedIrp.SystemBuffer = 1; - - Irp->IoStatus.Information = sizeof (int); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - break; - - case TC_IOCTL_OPEN_TEST: - { - OPEN_TEST_STRUCT *opentest = (OPEN_TEST_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE NtFileHandle; - UNICODE_STRING FullFileName; - IO_STATUS_BLOCK IoStatus; - LARGE_INTEGER offset; - unsigned char readBuffer [SECTOR_SIZE]; - - if (!ValidateIOBufferSize (Irp, sizeof (OPEN_TEST_STRUCT), ValidateInputOutput)) - break; - - EnsureNullTerminatedString (opentest->wszFileName, sizeof (opentest->wszFileName)); - RtlInitUnicodeString (&FullFileName, opentest->wszFileName); - - InitializeObjectAttributes (&ObjectAttributes, &FullFileName, OBJ_CASE_INSENSITIVE, - NULL, NULL); - - ntStatus = ZwCreateFile (&NtFileHandle, - SYNCHRONIZE | GENERIC_READ, &ObjectAttributes, &IoStatus, NULL /* alloc size = none */ , - FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_RANDOM_ACCESS, NULL, 0); - - if (NT_SUCCESS (ntStatus)) - { - opentest->TCBootLoaderDetected = FALSE; - opentest->FilesystemDetected = FALSE; - - if (opentest->bDetectTCBootLoader || opentest->DetectFilesystem) - { - // Determine if the first sector contains a portion of the TrueCrypt Boot Loader - - offset.QuadPart = 0; // MBR - - ntStatus = ZwReadFile (NtFileHandle, - NULL, - NULL, - NULL, - &IoStatus, - readBuffer, - sizeof(readBuffer), - &offset, - NULL); - - if (NT_SUCCESS (ntStatus)) - { - size_t i; - - if (opentest->bDetectTCBootLoader) - { - // Search for the string "TrueCrypt" - for (i = 0; i < sizeof (readBuffer) - strlen (TC_APP_NAME); ++i) - { - if (memcmp (readBuffer + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0) - { - opentest->TCBootLoaderDetected = TRUE; - break; - } - } - } - - if (opentest->DetectFilesystem) - { - switch (BE64 (*(uint64 *) readBuffer)) - { - case 0xEB52904E54465320: // NTFS - case 0xEB3C904D53444F53: // FAT16 - case 0xEB58904D53444F53: // FAT32 - case 0xEB76904558464154: // exFAT - - opentest->FilesystemDetected = TRUE; - break; - } - } - } - } - - ZwClose (NtFileHandle); - Dump ("Open test on file %ls success.\n", opentest->wszFileName); - } - else - { -#if 0 - Dump ("Open test on file %ls failed NTSTATUS 0x%08x\n", opentest->wszFileName, ntStatus); -#endif - } - - Irp->IoStatus.Information = NT_SUCCESS (ntStatus) ? sizeof (OPEN_TEST_STRUCT) : 0; - Irp->IoStatus.Status = ntStatus; - } - break; - - case TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG: - { - GetSystemDriveConfigurationRequest *request = (GetSystemDriveConfigurationRequest *) Irp->AssociatedIrp.SystemBuffer; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE NtFileHandle; - UNICODE_STRING FullFileName; - IO_STATUS_BLOCK IoStatus; - LARGE_INTEGER offset; - byte readBuffer [SECTOR_SIZE]; - - if (!ValidateIOBufferSize (Irp, sizeof (GetSystemDriveConfigurationRequest), ValidateInputOutput)) - break; - - EnsureNullTerminatedString (request->DevicePath, sizeof (request->DevicePath)); - RtlInitUnicodeString (&FullFileName, request->DevicePath); - - InitializeObjectAttributes (&ObjectAttributes, &FullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); - - ntStatus = ZwCreateFile (&NtFileHandle, - SYNCHRONIZE | GENERIC_READ, &ObjectAttributes, &IoStatus, NULL, - FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_RANDOM_ACCESS, NULL, 0); - - if (NT_SUCCESS (ntStatus)) - { - // Determine if the first sector contains a portion of the TrueCrypt Boot Loader - offset.QuadPart = 0; // MBR - - ntStatus = ZwReadFile (NtFileHandle, - NULL, - NULL, - NULL, - &IoStatus, - readBuffer, - sizeof(readBuffer), - &offset, - NULL); - - if (NT_SUCCESS (ntStatus)) - { - size_t i; - - // Check for dynamic drive - request->DriveIsDynamic = FALSE; - - if (readBuffer[510] == 0x55 && readBuffer[511] == 0xaa) - { - int i; - for (i = 0; i < 4; ++i) - { - if (readBuffer[446 + i * 16 + 4] == PARTITION_LDM) - { - request->DriveIsDynamic = TRUE; - break; - } - } - } - - request->BootLoaderVersion = 0; - request->Configuration = 0; - request->UserConfiguration = 0; - request->CustomUserMessage[0] = 0; - - // Search for the string "TrueCrypt" - for (i = 0; i < sizeof (readBuffer) - strlen (TC_APP_NAME); ++i) - { - if (memcmp (readBuffer + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0) - { - request->BootLoaderVersion = BE16 (*(uint16 *) (readBuffer + TC_BOOT_SECTOR_VERSION_OFFSET)); - request->Configuration = readBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET]; - - if (request->BootLoaderVersion != 0 && request->BootLoaderVersion <= VERSION_NUM) - { - request->UserConfiguration = readBuffer[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; - memcpy (request->CustomUserMessage, readBuffer + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); - } - break; - } - } - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (*request); - } - else - { - Irp->IoStatus.Status = ntStatus; - Irp->IoStatus.Information = 0; - } - - ZwClose (NtFileHandle); - - } - else - { - Irp->IoStatus.Status = ntStatus; - Irp->IoStatus.Information = 0; - } - } - break; - - case TC_IOCTL_WIPE_PASSWORD_CACHE: - DriverMutexWait (); - WipeCache (); - DriverMutexRelease (); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - break; - - case TC_IOCTL_GET_PASSWORD_CACHE_STATUS: - Irp->IoStatus.Status = cacheEmpty ? STATUS_PIPE_EMPTY : STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - break; - - case TC_IOCTL_SET_TRAVELER_MODE_STATUS: - if (!UserCanAccessDriveDevice()) - { - Irp->IoStatus.Status = STATUS_ACCESS_DENIED; - Irp->IoStatus.Information = 0; - } - else - { - TravelerMode = TRUE; - Dump ("Setting traveler mode\n"); - } - break; - - case TC_IOCTL_GET_TRAVELER_MODE_STATUS: - Irp->IoStatus.Status = TravelerMode ? STATUS_SUCCESS : STATUS_PIPE_EMPTY; - Irp->IoStatus.Information = 0; - break; - - case TC_IOCTL_GET_MOUNTED_VOLUMES: - - if (ValidateIOBufferSize (Irp, sizeof (MOUNT_LIST_STRUCT), ValidateOutput)) - { - MOUNT_LIST_STRUCT *list = (MOUNT_LIST_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - PDEVICE_OBJECT ListDevice; - - DriverMutexWait (); - - list->ulMountedDrives = 0; - - for (ListDevice = DeviceObject->DriverObject->DeviceObject; - ListDevice != (PDEVICE_OBJECT) NULL; ListDevice = ListDevice->NextDevice) - { - PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; - if (!ListExtension->bRootDevice - && ListExtension->IsVolumeDevice - && !ListExtension->bShuttingDown - && ListExtension->lMagicNumber == 0xabfeacde - && IsVolumeAccessibleByCurrentUser (ListExtension)) - { - list->ulMountedDrives |= (1 << ListExtension->nDosDriveNo); - wcscpy (list->wszVolume[ListExtension->nDosDriveNo], ListExtension->wszVolume); - list->diskLength[ListExtension->nDosDriveNo] = ListExtension->DiskLength; - list->ea[ListExtension->nDosDriveNo] = ListExtension->cryptoInfo->ea; - if (ListExtension->cryptoInfo->hiddenVolume) - list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_HIDDEN; // Hidden volume - else if (ListExtension->cryptoInfo->bHiddenVolProtectionAction) - list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED; // Normal/outer volume (hidden volume protected AND write already prevented) - else if (ListExtension->cryptoInfo->bProtectHiddenVolume) - list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER; // Normal/outer volume (hidden volume protected) - else - list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_NORMAL; // Normal volume - } - } - - DriverMutexRelease (); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (MOUNT_LIST_STRUCT); - } - break; - - case TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES: - if (ValidateIOBufferSize (Irp, sizeof (uint32), ValidateOutput)) - { - // Prevent the user from downgrading to versions lower than 5.0 by faking mounted volumes. - // The user could render the system unbootable by downgrading when boot encryption - // is active or being set up. - - memset (Irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength); - *(uint32 *) Irp->AssociatedIrp.SystemBuffer = 0xffffFFFF; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = irpSp->Parameters.DeviceIoControl.OutputBufferLength; - } - break; - - case TC_IOCTL_GET_VOLUME_PROPERTIES: - if (ValidateIOBufferSize (Irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateInputOutput)) - { - VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - PDEVICE_OBJECT ListDevice; - - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - Irp->IoStatus.Information = 0; - - DriverMutexWait (); - - for (ListDevice = DeviceObject->DriverObject->DeviceObject; - ListDevice != (PDEVICE_OBJECT) NULL; ListDevice = ListDevice->NextDevice) - { - - PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; - if (!ListExtension->bRootDevice - && ListExtension->IsVolumeDevice - && !ListExtension->bShuttingDown - && ListExtension->nDosDriveNo == prop->driveNo - && IsVolumeAccessibleByCurrentUser (ListExtension)) - { - prop->uniqueId = ListExtension->UniqueVolumeId; - wcscpy (prop->wszVolume, ListExtension->wszVolume); - prop->diskLength = ListExtension->DiskLength; - prop->ea = ListExtension->cryptoInfo->ea; - prop->mode = ListExtension->cryptoInfo->mode; - prop->pkcs5 = ListExtension->cryptoInfo->pkcs5; - prop->pkcs5Iterations = ListExtension->cryptoInfo->noIterations; -#if 0 - prop->volumeCreationTime = ListExtension->cryptoInfo->volume_creation_time; - prop->headerCreationTime = ListExtension->cryptoInfo->header_creation_time; -#endif - prop->volumeHeaderFlags = ListExtension->cryptoInfo->HeaderFlags; - prop->readOnly = ListExtension->bReadOnly; - prop->removable = ListExtension->bRemovable; - prop->hiddenVolume = ListExtension->cryptoInfo->hiddenVolume; - - if (ListExtension->cryptoInfo->bProtectHiddenVolume) - prop->hiddenVolProtection = ListExtension->cryptoInfo->bHiddenVolProtectionAction ? HIDVOL_PROT_STATUS_ACTION_TAKEN : HIDVOL_PROT_STATUS_ACTIVE; - else - prop->hiddenVolProtection = HIDVOL_PROT_STATUS_NONE; - - prop->totalBytesRead = ListExtension->Queue.TotalBytesRead; - prop->totalBytesWritten = ListExtension->Queue.TotalBytesWritten; - - prop->volFormatVersion = ListExtension->cryptoInfo->LegacyVolume ? TC_VOLUME_FORMAT_VERSION_PRE_6_0 : TC_VOLUME_FORMAT_VERSION; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (VOLUME_PROPERTIES_STRUCT); - break; - } - } - - DriverMutexRelease (); - } - break; - - case TC_IOCTL_GET_RESOLVED_SYMLINK: - if (ValidateIOBufferSize (Irp, sizeof (RESOLVE_SYMLINK_STRUCT), ValidateInputOutput)) - { - RESOLVE_SYMLINK_STRUCT *resolve = (RESOLVE_SYMLINK_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - { - NTSTATUS ntStatus; - - EnsureNullTerminatedString (resolve->symLinkName, sizeof (resolve->symLinkName)); - - ntStatus = SymbolicLinkToTarget (resolve->symLinkName, - resolve->targetName, - sizeof (resolve->targetName)); - - Irp->IoStatus.Information = sizeof (RESOLVE_SYMLINK_STRUCT); - Irp->IoStatus.Status = ntStatus; - } - } - break; - - case TC_IOCTL_GET_DRIVE_PARTITION_INFO: - if (ValidateIOBufferSize (Irp, sizeof (DISK_PARTITION_INFO_STRUCT), ValidateInputOutput)) - { - DISK_PARTITION_INFO_STRUCT *info = (DISK_PARTITION_INFO_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - { - PARTITION_INFORMATION_EX pi; - NTSTATUS ntStatus; - - EnsureNullTerminatedString (info->deviceName, sizeof (info->deviceName)); - - ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &pi, sizeof (pi)); - if (NT_SUCCESS(ntStatus)) - { - memset (&info->partInfo, 0, sizeof (info->partInfo)); - - info->partInfo.PartitionLength = pi.PartitionLength; - info->partInfo.PartitionNumber = pi.PartitionNumber; - info->partInfo.StartingOffset = pi.StartingOffset; - - if (pi.PartitionStyle == PARTITION_STYLE_MBR) - { - info->partInfo.PartitionType = pi.Mbr.PartitionType; - info->partInfo.BootIndicator = pi.Mbr.BootIndicator; - } - - info->IsGPT = pi.PartitionStyle == PARTITION_STYLE_GPT; - } - else - { - // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX - ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &info->partInfo, sizeof (info->partInfo)); - info->IsGPT = FALSE; - } - - if (!NT_SUCCESS (ntStatus)) - { - GET_LENGTH_INFORMATION lengthInfo; - ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &lengthInfo, sizeof (lengthInfo)); - - if (NT_SUCCESS (ntStatus)) - { - memset (&info->partInfo, 0, sizeof (info->partInfo)); - info->partInfo.PartitionLength = lengthInfo.Length; - } - } - - info->IsDynamic = FALSE; - - if (NT_SUCCESS (ntStatus) && OsMajorVersion >= 6) - { -# define IOCTL_VOLUME_IS_DYNAMIC CTL_CODE(IOCTL_VOLUME_BASE, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) - if (!NT_SUCCESS (TCDeviceIoControl (info->deviceName, IOCTL_VOLUME_IS_DYNAMIC, NULL, 0, &info->IsDynamic, sizeof (info->IsDynamic)))) - info->IsDynamic = FALSE; - } - - Irp->IoStatus.Information = sizeof (DISK_PARTITION_INFO_STRUCT); - Irp->IoStatus.Status = ntStatus; - } - } - break; - - case TC_IOCTL_GET_DRIVE_GEOMETRY: - if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY_STRUCT), ValidateInputOutput)) - { - DISK_GEOMETRY_STRUCT *g = (DISK_GEOMETRY_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - { - NTSTATUS ntStatus; - - EnsureNullTerminatedString (g->deviceName, sizeof (g->deviceName)); - - ntStatus = TCDeviceIoControl (g->deviceName, - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, 0, &g->diskGeometry, sizeof (g->diskGeometry)); - - Irp->IoStatus.Information = sizeof (DISK_GEOMETRY_STRUCT); - Irp->IoStatus.Status = ntStatus; - } - } - break; - - case TC_IOCTL_PROBE_REAL_DRIVE_SIZE: - if (ValidateIOBufferSize (Irp, sizeof (ProbeRealDriveSizeRequest), ValidateInputOutput)) - { - ProbeRealDriveSizeRequest *request = (ProbeRealDriveSizeRequest *) Irp->AssociatedIrp.SystemBuffer; - NTSTATUS status; - UNICODE_STRING name; - PFILE_OBJECT fileObject; - PDEVICE_OBJECT deviceObject; - - EnsureNullTerminatedString (request->DeviceName, sizeof (request->DeviceName)); - - RtlInitUnicodeString (&name, request->DeviceName); - status = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject); - if (!NT_SUCCESS (status)) - { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = status; - break; - } - - status = ProbeRealDriveSize (deviceObject, &request->RealDriveSize); - ObDereferenceObject (fileObject); - - if (status == STATUS_TIMEOUT) - { - request->TimeOut = TRUE; - Irp->IoStatus.Information = sizeof (ProbeRealDriveSizeRequest); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - else if (!NT_SUCCESS (status)) - { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = status; - } - else - { - request->TimeOut = FALSE; - Irp->IoStatus.Information = sizeof (ProbeRealDriveSizeRequest); - Irp->IoStatus.Status = status; - } - } - break; - - case TC_IOCTL_MOUNT_VOLUME: - if (ValidateIOBufferSize (Irp, sizeof (MOUNT_STRUCT), ValidateInputOutput)) - { - MOUNT_STRUCT *mount = (MOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - - if (mount->VolumePassword.Length > MAX_PASSWORD || mount->ProtectedHidVolPassword.Length > MAX_PASSWORD) - { - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - Irp->IoStatus.Information = 0; - break; - } - - EnsureNullTerminatedString (mount->wszVolume, sizeof (mount->wszVolume)); - - DriverMutexWait (); - - Irp->IoStatus.Information = sizeof (MOUNT_STRUCT); - Irp->IoStatus.Status = MountDevice (DeviceObject, mount); - - DriverMutexRelease (); - - burn (&mount->VolumePassword, sizeof (mount->VolumePassword)); - burn (&mount->ProtectedHidVolPassword, sizeof (mount->ProtectedHidVolPassword)); - } - break; - - case TC_IOCTL_DISMOUNT_VOLUME: - if (ValidateIOBufferSize (Irp, sizeof (UNMOUNT_STRUCT), ValidateInputOutput)) - { - UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - PDEVICE_OBJECT ListDevice; - - unmount->nReturnCode = ERR_DRIVE_NOT_FOUND; - - for (ListDevice = DeviceObject->DriverObject->DeviceObject; - ListDevice != (PDEVICE_OBJECT) NULL; - ListDevice = ListDevice->NextDevice) - { - PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; - - if (!ListExtension->bRootDevice - && ListExtension->IsVolumeDevice - && !ListExtension->bShuttingDown - && unmount->nDosDriveNo == ListExtension->nDosDriveNo - && IsVolumeAccessibleByCurrentUser (ListExtension)) - { - DriverMutexWait (); - unmount->nReturnCode = UnmountDevice (unmount, ListDevice, unmount->ignoreOpenFiles); - DriverMutexRelease (); - break; - } - } - - Irp->IoStatus.Information = sizeof (UNMOUNT_STRUCT); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - break; - - case TC_IOCTL_DISMOUNT_ALL_VOLUMES: - if (ValidateIOBufferSize (Irp, sizeof (UNMOUNT_STRUCT), ValidateInputOutput)) - { - UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer; - - unmount->nReturnCode = UnmountAllDevices (unmount, DeviceObject, unmount->ignoreOpenFiles); - - Irp->IoStatus.Information = sizeof (UNMOUNT_STRUCT); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - break; - - case TC_IOCTL_BOOT_ENCRYPTION_SETUP: - DriverMutexWait (); - - Irp->IoStatus.Status = StartBootEncryptionSetup (DeviceObject, Irp, irpSp); - Irp->IoStatus.Information = 0; - - DriverMutexRelease (); - break; - - case TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP: - DriverMutexWait (); - - Irp->IoStatus.Status = AbortBootEncryptionSetup(); - Irp->IoStatus.Information = 0; - - DriverMutexRelease (); - break; - - case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS: - DriverMutexWait (); - GetBootEncryptionStatus (Irp, irpSp); - DriverMutexRelease (); - break; - - case TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT: - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = GetSetupResult(); - break; - - case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES: - DriverMutexWait (); - GetBootDriveVolumeProperties (Irp, irpSp); - DriverMutexRelease (); - break; - - case TC_IOCTL_GET_BOOT_LOADER_VERSION: - DriverMutexWait (); - GetBootLoaderVersion (Irp, irpSp); - DriverMutexRelease (); - break; - - case TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER: - DriverMutexWait (); - ReopenBootVolumeHeader (Irp, irpSp); - DriverMutexRelease (); - break; - - case TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME: - DriverMutexWait (); - GetBootEncryptionAlgorithmName (Irp, irpSp); - DriverMutexRelease (); - break; - - case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING: - if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) - { - *(int *) Irp->AssociatedIrp.SystemBuffer = IsHiddenSystemRunning() ? 1 : 0; - Irp->IoStatus.Information = sizeof (int); - Irp->IoStatus.Status = STATUS_SUCCESS; - } - break; - - case TC_IOCTL_START_DECOY_SYSTEM_WIPE: - DriverMutexWait (); - - Irp->IoStatus.Status = StartDecoySystemWipe (DeviceObject, Irp, irpSp); - Irp->IoStatus.Information = 0; - - DriverMutexRelease (); - break; - - case TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE: - DriverMutexWait (); - - Irp->IoStatus.Status = AbortDecoySystemWipe(); - Irp->IoStatus.Information = 0; - - DriverMutexRelease (); - break; - - case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT: - Irp->IoStatus.Status = GetDecoySystemWipeResult(); - Irp->IoStatus.Information = 0; - break; - - case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS: - DriverMutexWait (); - GetDecoySystemWipeStatus (Irp, irpSp); - DriverMutexRelease (); - break; - - case TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR: - Irp->IoStatus.Status = WriteBootDriveSector (Irp, irpSp); - Irp->IoStatus.Information = 0; - break; - - default: - return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0); - } - - -#ifdef DEBUG - if (!NT_SUCCESS (Irp->IoStatus.Status)) - { - switch (irpSp->Parameters.DeviceIoControl.IoControlCode) - { - case TC_IOCTL_GET_MOUNTED_VOLUMES: - case TC_IOCTL_GET_PASSWORD_CACHE_STATUS: - case TC_IOCTL_GET_TRAVELER_MODE_STATUS: - case TC_IOCTL_SET_TRAVELER_MODE_STATUS: - case TC_IOCTL_OPEN_TEST: - case TC_IOCTL_GET_RESOLVED_SYMLINK: - case TC_IOCTL_GET_DRIVE_PARTITION_INFO: - case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES: - case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS: - case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING: - break; - - default: - Dump ("IOCTL error 0x%08x\n", Irp->IoStatus.Status); - } - } -#endif - - return TCCompleteIrp (Irp, Irp->IoStatus.Status, Irp->IoStatus.Information); -} - - -NTSTATUS TCStartThread (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread) -{ - return TCStartThreadInProcess (threadProc, threadArg, kThread, NULL); -} - - -NTSTATUS TCStartThreadInProcess (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread, PEPROCESS process) -{ - NTSTATUS status; - HANDLE threadHandle; - HANDLE processHandle = NULL; - OBJECT_ATTRIBUTES threadObjAttributes; - - if (process) - { - status = ObOpenObjectByPointer (process, OBJ_KERNEL_HANDLE, NULL, 0, NULL, KernelMode, &processHandle); - if (!NT_SUCCESS (status)) - return status; - } - - InitializeObjectAttributes (&threadObjAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); - - status = PsCreateSystemThread (&threadHandle, THREAD_ALL_ACCESS, &threadObjAttributes, processHandle, NULL, threadProc, threadArg); - if (!NT_SUCCESS (status)) - return status; - - status = ObReferenceObjectByHandle (threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *) kThread, NULL); - if (!NT_SUCCESS (status)) - { - ZwClose (threadHandle); - *kThread = NULL; - return status; - } - - if (processHandle) - ZwClose (processHandle); - - ZwClose (threadHandle); - return STATUS_SUCCESS; -} - - -void TCStopThread (PKTHREAD kThread, PKEVENT wakeUpEvent) -{ - if (wakeUpEvent) - KeSetEvent (wakeUpEvent, 0, FALSE); - - KeWaitForSingleObject (kThread, Executive, KernelMode, FALSE, NULL); - ObDereferenceObject (kThread); -} - - -NTSTATUS TCStartVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, MOUNT_STRUCT * mount) -{ - PTHREAD_BLOCK pThreadBlock = TCalloc (sizeof (THREAD_BLOCK)); - HANDLE hThread; - NTSTATUS ntStatus; - OBJECT_ATTRIBUTES threadObjAttributes; - SECURITY_QUALITY_OF_SERVICE qos; - - Dump ("Starting thread...\n"); - - if (pThreadBlock == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - else - { - pThreadBlock->DeviceObject = DeviceObject; - pThreadBlock->mount = mount; - } - - qos.Length = sizeof (qos); - qos.ContextTrackingMode = SECURITY_STATIC_TRACKING; - qos.EffectiveOnly = TRUE; - qos.ImpersonationLevel = SecurityImpersonation; - - ntStatus = SeCreateClientSecurity (PsGetCurrentThread(), &qos, FALSE, &Extension->SecurityClientContext); - if (!NT_SUCCESS (ntStatus)) - goto ret; - - Extension->SecurityClientContextValid = TRUE; - - Extension->bThreadShouldQuit = FALSE; - - InitializeObjectAttributes (&threadObjAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); - - ntStatus = PsCreateSystemThread (&hThread, - THREAD_ALL_ACCESS, - &threadObjAttributes, - NULL, - NULL, - VolumeThreadProc, - pThreadBlock); - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("PsCreateSystemThread Failed END\n"); - goto ret; - } - - ntStatus = ObReferenceObjectByHandle (hThread, - THREAD_ALL_ACCESS, - NULL, - KernelMode, - &Extension->peThread, - NULL); - - ZwClose (hThread); - - if (!NT_SUCCESS (ntStatus)) - goto ret; - - Dump ("Waiting for thread to initialize...\n"); - - KeWaitForSingleObject (&Extension->keCreateEvent, - Executive, - KernelMode, - FALSE, - NULL); - - Dump ("Waiting completed! Thread returns 0x%08x\n", pThreadBlock->ntCreateStatus); - ntStatus = pThreadBlock->ntCreateStatus; - -ret: - TCfree (pThreadBlock); - return ntStatus; -} - -void TCStopVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) -{ - NTSTATUS ntStatus; - - if (DeviceObject); /* Remove compiler warning */ - - Dump ("Signalling thread to quit...\n"); - - Extension->bThreadShouldQuit = TRUE; - - KeReleaseSemaphore (&Extension->RequestSemaphore, - 0, - 1, - TRUE); - - ntStatus = KeWaitForSingleObject (Extension->peThread, - Executive, - KernelMode, - FALSE, - NULL); - if (ntStatus != STATUS_SUCCESS) - Dump ("Failed waiting for crypto thread to quit: 0x%08x...\n", - ntStatus); - - ObDereferenceObject (Extension->peThread); - Extension->peThread = NULL; - - Dump ("Thread exited\n"); -} - - -// Suspend current thread for a number of milliseconds -void TCSleep (int milliSeconds) -{ - PKTIMER timer = (PKTIMER) TCalloc (sizeof (KTIMER)); - LARGE_INTEGER duetime; - - if (!timer) - return; - - duetime.QuadPart = (__int64) milliSeconds * -10000; - KeInitializeTimerEx(timer, NotificationTimer); - KeSetTimerEx(timer, duetime, 0, NULL); - - KeWaitForSingleObject (timer, Executive, KernelMode, FALSE, NULL); - - TCfree (timer); -} - - -/* VolumeThreadProc does all the work of processing IRP's, and dispatching them - to either the ReadWrite function or the DeviceControl function */ -VOID VolumeThreadProc (PVOID Context) -{ - PTHREAD_BLOCK pThreadBlock = (PTHREAD_BLOCK) Context; - PDEVICE_OBJECT DeviceObject = pThreadBlock->DeviceObject; - PEXTENSION Extension = (PEXTENSION) DeviceObject->DeviceExtension; - BOOL bDevice; - - /* Set thread priority to lowest realtime level. */ - KeSetPriorityThread (KeGetCurrentThread (), LOW_REALTIME_PRIORITY); - - Dump ("Mount THREAD OPENING VOLUME BEGIN\n"); - - if (memcmp (pThreadBlock->mount->wszVolume, WIDE ("\\Device"), 14) != 0) - { - wcscpy (pThreadBlock->wszMountVolume, WIDE ("\\??\\")); - wcsncat (pThreadBlock->wszMountVolume, pThreadBlock->mount->wszVolume, - sizeof (pThreadBlock->wszMountVolume) / 2 - 5); - bDevice = FALSE; - } - else - { - pThreadBlock->wszMountVolume[0] = 0; - wcsncat (pThreadBlock->wszMountVolume, pThreadBlock->mount->wszVolume, - sizeof (pThreadBlock->wszMountVolume) / 2 - 1); - bDevice = TRUE; - } - - Dump ("Mount THREAD request for File %ls DriveNumber %d Device = %d\n", - pThreadBlock->wszMountVolume, pThreadBlock->mount->nDosDriveNo, bDevice); - - pThreadBlock->ntCreateStatus = TCOpenVolume (DeviceObject, - Extension, - pThreadBlock->mount, - pThreadBlock->wszMountVolume, - bDevice); - - if (!NT_SUCCESS (pThreadBlock->ntCreateStatus) || pThreadBlock->mount->nReturnCode != 0) - { - KeSetEvent (&Extension->keCreateEvent, 0, FALSE); - PsTerminateSystemThread (STATUS_SUCCESS); - } - - // Start IO queue - Extension->Queue.IsFilterDevice = FALSE; - Extension->Queue.DeviceObject = DeviceObject; - Extension->Queue.CryptoInfo = Extension->cryptoInfo; - Extension->Queue.HostFileHandle = Extension->hDeviceFile; - Extension->Queue.VirtualDeviceLength = Extension->DiskLength; - Extension->Queue.MaxReadAheadOffset.QuadPart = Extension->HostLength; - - if (Extension->SecurityClientContextValid) - Extension->Queue.SecurityClientContext = &Extension->SecurityClientContext; - else - Extension->Queue.SecurityClientContext = NULL; - - pThreadBlock->ntCreateStatus = EncryptedIoQueueStart (&Extension->Queue); - - if (!NT_SUCCESS (pThreadBlock->ntCreateStatus)) - { - TCCloseVolume (DeviceObject, Extension); - - pThreadBlock->mount->nReturnCode = ERR_OS_ERROR; - KeSetEvent (&Extension->keCreateEvent, 0, FALSE); - PsTerminateSystemThread (STATUS_SUCCESS); - } - - KeSetEvent (&Extension->keCreateEvent, 0, FALSE); - /* From this point on pThreadBlock cannot be used as it will have been released! */ - pThreadBlock = NULL; - - for (;;) - { - /* Wait for a request from the dispatch routines. */ - KeWaitForSingleObject ((PVOID) & Extension->RequestSemaphore, Executive, KernelMode, FALSE, NULL); - - for (;;) - { - PIO_STACK_LOCATION irpSp; - PLIST_ENTRY request; - PIRP irp; - - request = ExInterlockedRemoveHeadList (&Extension->ListEntry, &Extension->ListSpinLock); - if (request == NULL) - break; - - irp = CONTAINING_RECORD (request, IRP, Tail.Overlay.ListEntry); - irpSp = IoGetCurrentIrpStackLocation (irp); - - if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) - ProcessVolumeDeviceControlIrp (DeviceObject, Extension, irp); - else - ASSERT (FALSE); - } - - if (Extension->bThreadShouldQuit) - { - Dump ("Closing volume\n"); - EncryptedIoQueueStop (&Extension->Queue); - - TCCloseVolume (DeviceObject, Extension); - PsTerminateSystemThread (STATUS_SUCCESS); - } - } -} - -void TCGetNTNameFromNumber (LPWSTR ntname, int nDriveNo) -{ - WCHAR tmp[3] = - {0, ':', 0}; - int j = nDriveNo + (WCHAR) 'A'; - - tmp[0] = (short) j; - wcscpy (ntname, (LPWSTR) NT_MOUNT_PREFIX); - wcsncat (ntname, tmp, 1); -} - -void TCGetDosNameFromNumber (LPWSTR dosname, int nDriveNo) -{ - WCHAR tmp[3] = - {0, ':', 0}; - int j = nDriveNo + (WCHAR) 'A'; - - tmp[0] = (short) j; - wcscpy (dosname, (LPWSTR) DOS_MOUNT_PREFIX); - wcscat (dosname, tmp); -} - -#ifdef _DEBUG -LPWSTR TCTranslateCode (ULONG ulCode) -{ - switch (ulCode) - { -#define TC_CASE_RET_NAME(CODE) case CODE : return L###CODE - - TC_CASE_RET_NAME (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); - TC_CASE_RET_NAME (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE); - TC_CASE_RET_NAME (TC_IOCTL_BOOT_ENCRYPTION_SETUP); - TC_CASE_RET_NAME (TC_IOCTL_DISMOUNT_ALL_VOLUMES); - TC_CASE_RET_NAME (TC_IOCTL_DISMOUNT_VOLUME); - TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES); - TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME); - TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT); - TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS); - TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_LOADER_VERSION); - TC_CASE_RET_NAME (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT); - TC_CASE_RET_NAME (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS); - TC_CASE_RET_NAME (TC_IOCTL_GET_DEVICE_REFCOUNT); - TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVE_GEOMETRY); - TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVE_PARTITION_INFO); - TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVER_VERSION); - TC_CASE_RET_NAME (TC_IOCTL_GET_MOUNTED_VOLUMES); - TC_CASE_RET_NAME (TC_IOCTL_GET_PASSWORD_CACHE_STATUS); - TC_CASE_RET_NAME (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG); - TC_CASE_RET_NAME (TC_IOCTL_GET_TRAVELER_MODE_STATUS); - TC_CASE_RET_NAME (TC_IOCTL_SET_TRAVELER_MODE_STATUS); - TC_CASE_RET_NAME (TC_IOCTL_GET_RESOLVED_SYMLINK); - TC_CASE_RET_NAME (TC_IOCTL_GET_VOLUME_PROPERTIES); - TC_CASE_RET_NAME (TC_IOCTL_DISK_IS_WRITABLE); - TC_CASE_RET_NAME (TC_IOCTL_IS_ANY_VOLUME_MOUNTED); - TC_CASE_RET_NAME (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING); - TC_CASE_RET_NAME (TC_IOCTL_MOUNT_VOLUME); - TC_CASE_RET_NAME (TC_IOCTL_OPEN_TEST); - TC_CASE_RET_NAME (TC_IOCTL_PROBE_REAL_DRIVE_SIZE); - TC_CASE_RET_NAME (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER); - TC_CASE_RET_NAME (TC_IOCTL_START_DECOY_SYSTEM_WIPE); - TC_CASE_RET_NAME (TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED); - TC_CASE_RET_NAME (TC_IOCTL_WIPE_PASSWORD_CACHE); - TC_CASE_RET_NAME (TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR); - - TC_CASE_RET_NAME (IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS); - -#undef TC_CASE_RET_NAME - } - - if (ulCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) - return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_GEOMETRY"); - else if (ulCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) - return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX"); - else if (ulCode == IOCTL_MOUNTDEV_QUERY_DEVICE_NAME) - return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME"); - else if (ulCode == IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME) - return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME"); - else if (ulCode == IOCTL_MOUNTDEV_QUERY_UNIQUE_ID) - return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_UNIQUE_ID"); - else if (ulCode == IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY) - return (LPWSTR) _T ("IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY"); - else if (ulCode == IOCTL_VOLUME_ONLINE) - return (LPWSTR) _T ("IOCTL_VOLUME_ONLINE"); - else if (ulCode == IOCTL_MOUNTDEV_LINK_CREATED) - return (LPWSTR) _T ("IOCTL_MOUNTDEV_LINK_CREATED"); - else if (ulCode == IOCTL_MOUNTDEV_LINK_DELETED) - return (LPWSTR) _T ("IOCTL_MOUNTDEV_LINK_DELETED"); - else if (ulCode == IOCTL_MOUNTMGR_QUERY_POINTS) - return (LPWSTR) _T ("IOCTL_MOUNTMGR_QUERY_POINTS"); - else if (ulCode == IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED) - return (LPWSTR) _T ("IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED"); - else if (ulCode == IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED) - return (LPWSTR) _T ("IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED"); - else if (ulCode == IOCTL_DISK_GET_LENGTH_INFO) - return (LPWSTR) _T ("IOCTL_DISK_GET_LENGTH_INFO"); - else if (ulCode == IOCTL_STORAGE_GET_DEVICE_NUMBER) - return (LPWSTR) _T ("IOCTL_STORAGE_GET_DEVICE_NUMBER"); - else if (ulCode == IOCTL_DISK_GET_PARTITION_INFO) - return (LPWSTR) _T ("IOCTL_DISK_GET_PARTITION_INFO"); - else if (ulCode == IOCTL_DISK_GET_PARTITION_INFO_EX) - return (LPWSTR) _T ("IOCTL_DISK_GET_PARTITION_INFO_EX"); - else if (ulCode == IOCTL_DISK_SET_PARTITION_INFO) - return (LPWSTR) _T ("IOCTL_DISK_SET_PARTITION_INFO"); - else if (ulCode == IOCTL_DISK_GET_DRIVE_LAYOUT) - return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_LAYOUT"); - else if (ulCode == IOCTL_DISK_SET_DRIVE_LAYOUT_EX) - return (LPWSTR) _T ("IOCTL_DISK_SET_DRIVE_LAYOUT_EX"); - else if (ulCode == IOCTL_DISK_VERIFY) - return (LPWSTR) _T ("IOCTL_DISK_VERIFY"); - else if (ulCode == IOCTL_DISK_FORMAT_TRACKS) - return (LPWSTR) _T ("IOCTL_DISK_FORMAT_TRACKS"); - else if (ulCode == IOCTL_DISK_REASSIGN_BLOCKS) - return (LPWSTR) _T ("IOCTL_DISK_REASSIGN_BLOCKS"); - else if (ulCode == IOCTL_DISK_PERFORMANCE) - return (LPWSTR) _T ("IOCTL_DISK_PERFORMANCE"); - else if (ulCode == IOCTL_DISK_IS_WRITABLE) - return (LPWSTR) _T ("IOCTL_DISK_IS_WRITABLE"); - else if (ulCode == IOCTL_DISK_LOGGING) - return (LPWSTR) _T ("IOCTL_DISK_LOGGING"); - else if (ulCode == IOCTL_DISK_FORMAT_TRACKS_EX) - return (LPWSTR) _T ("IOCTL_DISK_FORMAT_TRACKS_EX"); - else if (ulCode == IOCTL_DISK_HISTOGRAM_STRUCTURE) - return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_STRUCTURE"); - else if (ulCode == IOCTL_DISK_HISTOGRAM_DATA) - return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_DATA"); - else if (ulCode == IOCTL_DISK_HISTOGRAM_RESET) - return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_RESET"); - else if (ulCode == IOCTL_DISK_REQUEST_STRUCTURE) - return (LPWSTR) _T ("IOCTL_DISK_REQUEST_STRUCTURE"); - else if (ulCode == IOCTL_DISK_REQUEST_DATA) - return (LPWSTR) _T ("IOCTL_DISK_REQUEST_DATA"); - else if (ulCode == IOCTL_DISK_CONTROLLER_NUMBER) - return (LPWSTR) _T ("IOCTL_DISK_CONTROLLER_NUMBER"); - else if (ulCode == SMART_GET_VERSION) - return (LPWSTR) _T ("SMART_GET_VERSION"); - else if (ulCode == SMART_SEND_DRIVE_COMMAND) - return (LPWSTR) _T ("SMART_SEND_DRIVE_COMMAND"); - else if (ulCode == SMART_RCV_DRIVE_DATA) - return (LPWSTR) _T ("SMART_RCV_DRIVE_DATA"); - else if (ulCode == IOCTL_DISK_INTERNAL_SET_VERIFY) - return (LPWSTR) _T ("IOCTL_DISK_INTERNAL_SET_VERIFY"); - else if (ulCode == IOCTL_DISK_INTERNAL_CLEAR_VERIFY) - return (LPWSTR) _T ("IOCTL_DISK_INTERNAL_CLEAR_VERIFY"); - else if (ulCode == IOCTL_DISK_CHECK_VERIFY) - return (LPWSTR) _T ("IOCTL_DISK_CHECK_VERIFY"); - else if (ulCode == IOCTL_DISK_MEDIA_REMOVAL) - return (LPWSTR) _T ("IOCTL_DISK_MEDIA_REMOVAL"); - else if (ulCode == IOCTL_DISK_EJECT_MEDIA) - return (LPWSTR) _T ("IOCTL_DISK_EJECT_MEDIA"); - else if (ulCode == IOCTL_DISK_LOAD_MEDIA) - return (LPWSTR) _T ("IOCTL_DISK_LOAD_MEDIA"); - else if (ulCode == IOCTL_DISK_RESERVE) - return (LPWSTR) _T ("IOCTL_DISK_RESERVE"); - else if (ulCode == IOCTL_DISK_RELEASE) - return (LPWSTR) _T ("IOCTL_DISK_RELEASE"); - else if (ulCode == IOCTL_DISK_FIND_NEW_DEVICES) - return (LPWSTR) _T ("IOCTL_DISK_FIND_NEW_DEVICES"); - else if (ulCode == IOCTL_DISK_GET_MEDIA_TYPES) - return (LPWSTR) _T ("IOCTL_DISK_GET_MEDIA_TYPES"); - else if (ulCode == IOCTL_STORAGE_SET_HOTPLUG_INFO) - return (LPWSTR) _T ("IOCTL_STORAGE_SET_HOTPLUG_INFO"); - else if (ulCode == IRP_MJ_READ) - return (LPWSTR) _T ("IRP_MJ_READ"); - else if (ulCode == IRP_MJ_WRITE) - return (LPWSTR) _T ("IRP_MJ_WRITE"); - else if (ulCode == IRP_MJ_CREATE) - return (LPWSTR) _T ("IRP_MJ_CREATE"); - else if (ulCode == IRP_MJ_CLOSE) - return (LPWSTR) _T ("IRP_MJ_CLOSE"); - else if (ulCode == IRP_MJ_CLEANUP) - return (LPWSTR) _T ("IRP_MJ_CLEANUP"); - else if (ulCode == IRP_MJ_FLUSH_BUFFERS) - return (LPWSTR) _T ("IRP_MJ_FLUSH_BUFFERS"); - else if (ulCode == IRP_MJ_SHUTDOWN) - return (LPWSTR) _T ("IRP_MJ_SHUTDOWN"); - else if (ulCode == IRP_MJ_DEVICE_CONTROL) - return (LPWSTR) _T ("IRP_MJ_DEVICE_CONTROL"); - else - { - return (LPWSTR) _T ("IOCTL"); - } -} - -#endif - -PDEVICE_OBJECT TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) -{ - PDEVICE_OBJECT OldDeviceObject = DeviceObject; - UNICODE_STRING Win32NameString; - NTSTATUS ntStatus; - - Dump ("TCDeleteDeviceObject BEGIN\n"); - - if (Extension->bRootDevice) - { - RtlInitUnicodeString (&Win32NameString, (LPWSTR) DOS_ROOT_PREFIX); - ntStatus = IoDeleteSymbolicLink (&Win32NameString); - if (!NT_SUCCESS (ntStatus)) - Dump ("IoDeleteSymbolicLink failed ntStatus = 0x%08x\n", ntStatus); - } - else - { - if (Extension->peThread != NULL) - TCStopVolumeThread (DeviceObject, Extension); - - if (Extension->UserSid) - TCfree (Extension->UserSid); - - if (Extension->SecurityClientContextValid) - { - if (OsMajorVersion == 5 && OsMinorVersion == 0) - { - ObDereferenceObject (Extension->SecurityClientContext.ClientToken); - } - else - { - // Windows 2000 does not support PsDereferenceImpersonationToken() used by SeDeleteClientSecurity(). - // TODO: Use only SeDeleteClientSecurity() once support for Windows 2000 is dropped. - - VOID (*PsDereferenceImpersonationTokenD) (PACCESS_TOKEN ImpersonationToken); - UNICODE_STRING name; - RtlInitUnicodeString (&name, L"PsDereferenceImpersonationToken"); - - PsDereferenceImpersonationTokenD = MmGetSystemRoutineAddress (&name); - if (!PsDereferenceImpersonationTokenD) - TC_BUG_CHECK (STATUS_NOT_IMPLEMENTED); - -# define PsDereferencePrimaryToken -# define PsDereferenceImpersonationToken PsDereferenceImpersonationTokenD - - SeDeleteClientSecurity (&Extension->SecurityClientContext); - -# undef PsDereferencePrimaryToken -# undef PsDereferenceImpersonationToken - } - } - - if (DeviceObject->ReferenceCount > 0) - ReferencedDeviceDeleted = TRUE; - - // Forced dismount does not set reference count to zero even if all open handles are closed - Dump ("Deleting device with ref count %ld\n", DeviceObject->ReferenceCount); - DeviceObject->ReferenceCount = 0; - } - - if (DeviceObject != NULL) - DeviceObject = DeviceObject->NextDevice; - - IoDeleteDevice (OldDeviceObject); - - Dump ("TCDeleteDeviceObject END\n"); - return DeviceObject; -} - - -VOID TCUnloadDriver (PDRIVER_OBJECT DriverObject) -{ - PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject; - - Dump ("TCUnloadDriver BEGIN\n"); - - UnmountAllDevices (NULL, DeviceObject, TRUE); - - /* Now walk the list of driver objects and get rid of them */ - while (DeviceObject != (PDEVICE_OBJECT) NULL) - { - DeviceObject = TCDeleteDeviceObject (DeviceObject, - (PEXTENSION) DeviceObject->DeviceExtension); - } - - WipeCache (); - - if (IsBootDriveMounted()) - TC_BUG_CHECK (STATUS_INVALID_DEVICE_STATE); - - EncryptionThreadPoolStop(); - - Dump ("TCUnloadDriver END\n"); -} - - -NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, - void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize) -{ - IO_STATUS_BLOCK ioStatusBlock; - NTSTATUS ntStatus; - PIRP irp; - PFILE_OBJECT fileObject; - PDEVICE_OBJECT deviceObject; - KEVENT event; - UNICODE_STRING name; - - RtlInitUnicodeString(&name, deviceName); - ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject); - - if (ntStatus != STATUS_SUCCESS) - return ntStatus; - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - irp = IoBuildDeviceIoControlRequest (IoControlCode, - deviceObject, - InputBuffer, InputBufferSize, - OutputBuffer, OutputBufferSize, - FALSE, - &event, - &ioStatusBlock); - - if (irp == NULL) - { - Dump ("IRP allocation failed\n"); - ntStatus = STATUS_INSUFFICIENT_RESOURCES; - goto ret; - } - - ntStatus = IoCallDriver (deviceObject, irp); - if (ntStatus == STATUS_PENDING) - { - KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); - ntStatus = ioStatusBlock.Status; - } - -ret: - ObDereferenceObject (fileObject); - return ntStatus; -} - - -NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize) -{ - IO_STATUS_BLOCK ioStatusBlock; - NTSTATUS status; - PIRP irp; - KEVENT event; - - ASSERT(KeGetCurrentIrql() <= APC_LEVEL); - - KeInitializeEvent (&event, NotificationEvent, FALSE); - - irp = IoBuildDeviceIoControlRequest (ioControlCode, deviceObject, inputBuffer, inputBufferSize, - outputBuffer, outputBufferSize, FALSE, &event, &ioStatusBlock); - - if (!irp) - return STATUS_INSUFFICIENT_RESOURCES; - - ObReferenceObject (deviceObject); - - status = IoCallDriver (deviceObject, irp); - if (status == STATUS_PENDING) - { - KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); - status = ioStatusBlock.Status; - } - - ObDereferenceObject (deviceObject); - return status; -} - - -NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *driveSize) -{ - NTSTATUS status; - LARGE_INTEGER sysLength; - LARGE_INTEGER offset; - byte *sectorBuffer; - ULONGLONG startTime; - - if (!UserCanAccessDriveDevice()) - return STATUS_ACCESS_DENIED; - - sectorBuffer = TCalloc (SECTOR_SIZE); - if (!sectorBuffer) - return STATUS_INSUFFICIENT_RESOURCES; - - status = SendDeviceIoControlRequest (driveDeviceObject, IOCTL_DISK_GET_LENGTH_INFO, - NULL, 0, &sysLength, sizeof (sysLength)); - - if (!NT_SUCCESS (status)) - { - Dump ("Failed to get drive size - error %x\n", status); - TCfree (sectorBuffer); - return status; - } - - startTime = KeQueryInterruptTime (); - for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += SECTOR_SIZE) - { - status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, SECTOR_SIZE); - - if (NT_SUCCESS (status)) - status = TCWriteDevice (driveDeviceObject, sectorBuffer, offset, SECTOR_SIZE); - - if (!NT_SUCCESS (status)) - { - driveSize->QuadPart = offset.QuadPart; - Dump ("Real drive size = %I64d bytes (%I64d hidden)\n", driveSize->QuadPart, driveSize->QuadPart - sysLength.QuadPart); - TCfree (sectorBuffer); - return STATUS_SUCCESS; - } - - if (KeQueryInterruptTime() - startTime > 3ULL * 60 * 1000 * 1000 * 10) - { - // Abort if probing for more than 3 minutes - driveSize->QuadPart = sysLength.QuadPart; - TCfree (sectorBuffer); - return STATUS_TIMEOUT; - } - } -} - - -// Opens a mounted TC volume on filesystem level -NTSTATUS TCOpenFsVolume (PEXTENSION Extension, PHANDLE volumeHandle, PFILE_OBJECT * fileObject) -{ - NTSTATUS ntStatus; - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING fullFileName; - IO_STATUS_BLOCK ioStatus; - WCHAR volumeName[TC_MAX_PATH]; - - TCGetDosNameFromNumber (volumeName, Extension->nDosDriveNo); - RtlInitUnicodeString (&fullFileName, volumeName); - InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); - - ntStatus = ZwCreateFile (volumeHandle, - SYNCHRONIZE | GENERIC_READ, - &objectAttributes, - &ioStatus, - NULL, - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN, - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - - Dump ("Volume %ls open NTSTATUS 0x%08x\n", volumeName, ntStatus); - - if (!NT_SUCCESS (ntStatus)) - return ntStatus; - - ntStatus = ObReferenceObjectByHandle (*volumeHandle, - FILE_READ_DATA, - NULL, - KernelMode, - fileObject, - NULL); - - Dump ("ObReferenceObjectByHandle NTSTATUS 0x%08x\n", ntStatus); - - if (!NT_SUCCESS (ntStatus)) - { - ZwClose(*volumeHandle); - return ntStatus; - } - - return ntStatus; -} - - -void TCCloseFsVolume (HANDLE volumeHandle, PFILE_OBJECT fileObject) -{ - ObDereferenceObject (fileObject); - ZwClose (volumeHandle); -} - - -static NTSTATUS TCReadWriteDevice (BOOL write, PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length) -{ - NTSTATUS status; - IO_STATUS_BLOCK ioStatusBlock; - PIRP irp; - KEVENT completionEvent; - - ASSERT (KeGetCurrentIrql() <= APC_LEVEL); - - KeInitializeEvent (&completionEvent, NotificationEvent, FALSE); - irp = IoBuildSynchronousFsdRequest (write ? IRP_MJ_WRITE : IRP_MJ_READ, deviceObject, buffer, length, &offset, &completionEvent, &ioStatusBlock); - if (!irp) - return STATUS_INSUFFICIENT_RESOURCES; - - ObReferenceObject (deviceObject); - status = IoCallDriver (deviceObject, irp); - - if (status == STATUS_PENDING) - { - status = KeWaitForSingleObject (&completionEvent, Executive, KernelMode, FALSE, NULL); - if (NT_SUCCESS (status)) - status = ioStatusBlock.Status; - } - - ObDereferenceObject (deviceObject); - return status; -} - - -NTSTATUS TCReadDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length) -{ - return TCReadWriteDevice (FALSE, deviceObject, buffer, offset, length); -} - - -NTSTATUS TCWriteDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length) -{ - return TCReadWriteDevice (TRUE, deviceObject, buffer, offset, length); -} - - -NTSTATUS TCFsctlCall (PFILE_OBJECT fileObject, LONG IoControlCode, - void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize) -{ - IO_STATUS_BLOCK ioStatusBlock; - NTSTATUS ntStatus; - PIRP irp; - KEVENT event; - PIO_STACK_LOCATION stack; - PDEVICE_OBJECT deviceObject = IoGetRelatedDeviceObject (fileObject); - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - irp = IoBuildDeviceIoControlRequest (IoControlCode, - deviceObject, - InputBuffer, InputBufferSize, - OutputBuffer, OutputBufferSize, - FALSE, - &event, - &ioStatusBlock); - - if (irp == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - - stack = IoGetNextIrpStackLocation(irp); - - stack->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; - stack->MinorFunction = IRP_MN_USER_FS_REQUEST; - stack->FileObject = fileObject; - - ntStatus = IoCallDriver (deviceObject, irp); - if (ntStatus == STATUS_PENDING) - { - KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); - ntStatus = ioStatusBlock.Status; - } - - return ntStatus; -} - - -NTSTATUS CreateDriveLink (int nDosDriveNo) -{ - WCHAR dev[128], link[128]; - UNICODE_STRING deviceName, symLink; - NTSTATUS ntStatus; - - TCGetNTNameFromNumber (dev, nDosDriveNo); - TCGetDosNameFromNumber (link, nDosDriveNo); - - RtlInitUnicodeString (&deviceName, dev); - RtlInitUnicodeString (&symLink, link); - - ntStatus = IoCreateSymbolicLink (&symLink, &deviceName); - Dump ("IoCreateSymbolicLink returned %X\n", ntStatus); - return ntStatus; -} - - -NTSTATUS RemoveDriveLink (int nDosDriveNo) -{ - WCHAR link[256]; - UNICODE_STRING symLink; - NTSTATUS ntStatus; - - TCGetDosNameFromNumber (link, nDosDriveNo); - RtlInitUnicodeString (&symLink, link); - - ntStatus = IoDeleteSymbolicLink (&symLink); - Dump ("IoDeleteSymbolicLink returned %X\n", ntStatus); - return ntStatus; -} - - -NTSTATUS MountManagerMount (MOUNT_STRUCT *mount) -{ - NTSTATUS ntStatus; - WCHAR arrVolume[256]; - char buf[200]; - PMOUNTMGR_TARGET_NAME in = (PMOUNTMGR_TARGET_NAME) buf; - PMOUNTMGR_CREATE_POINT_INPUT point = (PMOUNTMGR_CREATE_POINT_INPUT) buf; - UNICODE_STRING symName, devName; - - TCGetNTNameFromNumber (arrVolume, mount->nDosDriveNo); - in->DeviceNameLength = (USHORT) wcslen (arrVolume) * 2; - wcscpy(in->DeviceName, arrVolume); - - ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, - in, sizeof (in->DeviceNameLength) + wcslen (arrVolume) * 2, 0, 0); - - memset (buf, 0, sizeof buf); - TCGetDosNameFromNumber ((PWSTR) &point[1], mount->nDosDriveNo); - - point->SymbolicLinkNameOffset = sizeof (MOUNTMGR_CREATE_POINT_INPUT); - point->SymbolicLinkNameLength = (USHORT) wcslen ((PWSTR) &point[1]) * 2; - - RtlInitUnicodeString(&symName, (PWSTR) (buf + point->SymbolicLinkNameOffset)); - - point->DeviceNameOffset = point->SymbolicLinkNameOffset + point->SymbolicLinkNameLength; - TCGetNTNameFromNumber ((PWSTR) (buf + point->DeviceNameOffset), mount->nDosDriveNo); - point->DeviceNameLength = (USHORT) wcslen ((PWSTR) (buf + point->DeviceNameOffset)) * 2; - - RtlInitUnicodeString(&devName, (PWSTR) (buf + point->DeviceNameOffset)); - - ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_CREATE_POINT, point, - point->DeviceNameOffset + point->DeviceNameLength, 0, 0); - - return ntStatus; -} - - -NTSTATUS MountManagerUnmount (int nDosDriveNo) -{ - NTSTATUS ntStatus; - char buf[256], out[300]; - PMOUNTMGR_MOUNT_POINT in = (PMOUNTMGR_MOUNT_POINT) buf; - - memset (buf, 0, sizeof buf); - - TCGetDosNameFromNumber ((PWSTR) &in[1], nDosDriveNo); - - in->SymbolicLinkNameOffset = sizeof (MOUNTMGR_MOUNT_POINT); - in->SymbolicLinkNameLength = (USHORT) wcslen ((PWCHAR) &in[1]) * 2; - - ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_DELETE_POINTS, - in, sizeof(MOUNTMGR_MOUNT_POINT) + in->SymbolicLinkNameLength, out, sizeof out); - - Dump ("IOCTL_MOUNTMGR_DELETE_POINTS returned 0x%08x\n", ntStatus); - - return ntStatus; -} - - -NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount) -{ - PDEVICE_OBJECT NewDeviceObject; - NTSTATUS ntStatus; - - // Make sure the user is asking for a reasonable nDosDriveNo - if (mount->nDosDriveNo >= 0 && mount->nDosDriveNo <= 25 && IsDriveLetterAvailable (mount->nDosDriveNo)) - { - Dump ("Mount request looks valid\n"); - } - else - { - Dump ("WARNING: MOUNT DRIVE LETTER INVALID\n"); - mount->nReturnCode = ERR_DRIVE_NOT_FOUND; - return ERR_DRIVE_NOT_FOUND; - } - - if (!SelfTestsPassed) - { - mount->nReturnCode = ERR_SELF_TESTS_FAILED; - return ERR_SELF_TESTS_FAILED; - } - - ntStatus = TCCreateDeviceObject (DeviceObject->DriverObject, &NewDeviceObject, mount); - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("Mount CREATE DEVICE ERROR, ntStatus = 0x%08x\n", ntStatus); - return ntStatus; - } - else - { - PEXTENSION NewExtension = (PEXTENSION) NewDeviceObject->DeviceExtension; - SECURITY_SUBJECT_CONTEXT subContext; - PACCESS_TOKEN accessToken; - - SeCaptureSubjectContext (&subContext); - accessToken = SeQuerySubjectContextToken (&subContext); - - if (!accessToken) - { - ntStatus = STATUS_INVALID_PARAMETER; - } - else - { - PTOKEN_USER tokenUser; - - ntStatus = SeQueryInformationToken (accessToken, TokenUser, &tokenUser); - if (NT_SUCCESS (ntStatus)) - { - ULONG sidLength = RtlLengthSid (tokenUser->User.Sid); - - NewExtension->UserSid = TCalloc (sidLength); - if (!NewExtension->UserSid) - ntStatus = STATUS_INSUFFICIENT_RESOURCES; - else - ntStatus = RtlCopySid (sidLength, NewExtension->UserSid, tokenUser->User.Sid); - } - } - - SeReleaseSubjectContext (&subContext); - - if (NT_SUCCESS (ntStatus)) - ntStatus = TCStartVolumeThread (NewDeviceObject, NewExtension, mount); - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("Mount FAILURE NT ERROR, ntStatus = 0x%08x\n", ntStatus); - TCDeleteDeviceObject (NewDeviceObject, NewExtension); - return ntStatus; - } - else - { - if (mount->nReturnCode == 0) - { - HANDLE volumeHandle; - PFILE_OBJECT volumeFileObject; - - Dump ("Mount SUCCESS TC code = 0x%08x READ-ONLY = %d\n", mount->nReturnCode, NewExtension->bReadOnly); - - if (NewExtension->bReadOnly) - NewDeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; - - NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - NewExtension->UniqueVolumeId = LastUniqueVolumeId++; - - if (mount->bMountManager) - MountManagerMount (mount); - - NewExtension->bMountManager = mount->bMountManager; - - // We create symbolic link even if mount manager is notified of - // arriving volume as it apparently sometimes fails to create the link - CreateDriveLink (mount->nDosDriveNo); - - mount->FilesystemDirty = FALSE; - - if (NT_SUCCESS (TCOpenFsVolume (NewExtension, &volumeHandle, &volumeFileObject))) - { - __try - { - ULONG fsStatus; - - if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &fsStatus, sizeof (fsStatus))) - && (fsStatus & VOLUME_IS_DIRTY)) - { - mount->FilesystemDirty = TRUE; - } - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - mount->FilesystemDirty = TRUE; - } - - TCCloseFsVolume (volumeHandle, volumeFileObject); - } - } - else - { - Dump ("Mount FAILURE TC code = 0x%08x\n", mount->nReturnCode); - TCDeleteDeviceObject (NewDeviceObject, NewExtension); - } - - return STATUS_SUCCESS; - } - } -} - -NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles) -{ - PEXTENSION extension = deviceObject->DeviceExtension; - NTSTATUS ntStatus; - HANDLE volumeHandle; - PFILE_OBJECT volumeFileObject; - - Dump ("UnmountDevice %d\n", extension->nDosDriveNo); - - ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject); - if (!NT_SUCCESS (ntStatus)) - { - // User may have deleted symbolic link - CreateDriveLink (extension->nDosDriveNo); - - ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject); - } - - if (NT_SUCCESS (ntStatus)) - { - int dismountRetry; - - // Lock volume - ntStatus = TCFsctlCall (volumeFileObject, FSCTL_LOCK_VOLUME, 0, 0, 0, 0); - Dump ("FSCTL_LOCK_VOLUME returned %X\n", ntStatus); - - if (!NT_SUCCESS (ntStatus) && !ignoreOpenFiles) - { - TCCloseFsVolume (volumeHandle, volumeFileObject); - return ERR_FILES_OPEN; - } - - // Dismount volume - for (dismountRetry = 0; dismountRetry < 50; ++dismountRetry) - { - ntStatus = TCFsctlCall (volumeFileObject, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0); - Dump ("FSCTL_DISMOUNT_VOLUME returned %X\n", ntStatus); - - if (NT_SUCCESS (ntStatus) || ntStatus == STATUS_VOLUME_DISMOUNTED) - break; - - TCSleep (100); - } - } - else - { - // Volume cannot be opened => force dismount if allowed - if (!ignoreOpenFiles) - return ERR_FILES_OPEN; - else - volumeHandle = NULL; - } - - if (extension->bMountManager) - MountManagerUnmount (extension->nDosDriveNo); - - // We always remove symbolic link as mount manager might fail to do so - RemoveDriveLink (extension->nDosDriveNo); - - extension->bShuttingDown = TRUE; - - if (volumeHandle != NULL) - TCCloseFsVolume (volumeHandle, volumeFileObject); - - if (unmountRequest) - { - PCRYPTO_INFO cryptoInfo = ((PEXTENSION) deviceObject->DeviceExtension)->cryptoInfo; - unmountRequest->HiddenVolumeProtectionTriggered = (cryptoInfo->bProtectHiddenVolume && cryptoInfo->bHiddenVolProtectionAction); - } - - TCDeleteDeviceObject (deviceObject, (PEXTENSION) deviceObject->DeviceExtension); - return 0; -} - -NTSTATUS UnmountAllDevices (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT DeviceObject, BOOL ignoreOpenFiles) -{ - NTSTATUS status = 0; - PDEVICE_OBJECT ListDevice; - - Dump ("Unmounting all volumes\n"); - - if (unmountRequest) - unmountRequest->HiddenVolumeProtectionTriggered = FALSE; - - if (!DeviceObject || !DeviceObject->DriverObject) - return STATUS_INVALID_PARAMETER; - - DriverMutexWait (); - - ListDevice = DeviceObject->DriverObject->DeviceObject; - while (ListDevice != NULL) - { - PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; - if (!ListExtension->bRootDevice && ListExtension->IsVolumeDevice && !ListExtension->bShuttingDown - && IsVolumeAccessibleByCurrentUser (ListExtension)) - { - PDEVICE_OBJECT nextDevice = ListDevice->NextDevice; - NTSTATUS ntStatus; - - if (unmountRequest) - unmountRequest->nDosDriveNo = ListExtension->nDosDriveNo; - - ntStatus = UnmountDevice (unmountRequest, ListDevice, ignoreOpenFiles); - status = ntStatus == 0 ? status : ntStatus; - - if (unmountRequest && unmountRequest->HiddenVolumeProtectionTriggered) - break; - - ListDevice = nextDevice; - continue; - } - - ListDevice = ListDevice->NextDevice; - } - - DriverMutexRelease (); - return status; -} - -// Resolves symbolic link name to its target name -NTSTATUS SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTargetNameLength) -{ - NTSTATUS ntStatus; - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING fullFileName; - HANDLE handle; - - RtlInitUnicodeString (&fullFileName, symlinkName); - InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - - ntStatus = ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, &objectAttributes); - - if (NT_SUCCESS (ntStatus)) - { - UNICODE_STRING target; - target.Buffer = targetName; - target.Length = 0; - target.MaximumLength = maxTargetNameLength; - memset (targetName, 0, maxTargetNameLength); - - ntStatus = ZwQuerySymbolicLinkObject (handle, &target, NULL); - - ZwClose (handle); - } - - return ntStatus; -} - - -// Checks if two regions overlap (borders are parts of regions) -BOOL RegionsOverlap (unsigned __int64 start1, unsigned __int64 end1, unsigned __int64 start2, unsigned __int64 end2) -{ - return (start1 < start2) ? (end1 >= start2) : (start1 <= end2); -} - - -void GetIntersection (uint64 start1, uint32 length1, uint64 start2, uint64 end2, uint64 *intersectStart, uint32 *intersectLength) -{ - uint64 end1 = start1 + length1 - 1; - uint64 intersectEnd = (end1 <= end2) ? end1 : end2; - - *intersectStart = (start1 >= start2) ? start1 : start2; - *intersectLength = (uint32) ((*intersectStart > intersectEnd) ? 0 : intersectEnd + 1 - *intersectStart); - - if (*intersectLength == 0) - *intersectStart = start1; -} - - -BOOL IsAccessibleByUser (PUNICODE_STRING objectFileName, BOOL readOnly) -{ - OBJECT_ATTRIBUTES fileObjAttributes; - IO_STATUS_BLOCK ioStatusBlock; - HANDLE fileHandle; - NTSTATUS status; - - ASSERT (!IoIsSystemThread (PsGetCurrentThread())); - - InitializeObjectAttributes (&fileObjAttributes, objectFileName, OBJ_CASE_INSENSITIVE | OBJ_FORCE_ACCESS_CHECK, NULL, NULL); - - status = ZwCreateFile (&fileHandle, - readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, - &fileObjAttributes, - &ioStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - - if (NT_SUCCESS (status)) - { - ZwClose (fileHandle); - return TRUE; - } - - return FALSE; -} - - -BOOL UserCanAccessDriveDevice () -{ - UNICODE_STRING name; - RtlInitUnicodeString (&name, L"\\Device\\MountPointManager"); - - return IsAccessibleByUser (&name, FALSE); -} - - -BOOL IsDriveLetterAvailable (int nDosDriveNo) -{ - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING objectName; - WCHAR link[128]; - HANDLE handle; - - TCGetDosNameFromNumber (link, nDosDriveNo); - RtlInitUnicodeString (&objectName, link); - InitializeObjectAttributes (&objectAttributes, &objectName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - - if (NT_SUCCESS (ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, &objectAttributes))) - { - ZwClose (handle); - return FALSE; - } - - return TRUE; -} - - -NTSTATUS TCCompleteIrp (PIRP irp, NTSTATUS status, ULONG_PTR information) -{ - irp->IoStatus.Status = status; - irp->IoStatus.Information = information; - IoCompleteRequest (irp, IO_NO_INCREMENT); - return status; -} - - -NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information) -{ - irp->IoStatus.Status = status; - irp->IoStatus.Information = information; - IoCompleteRequest (irp, NT_SUCCESS (status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); - return status; -} - - -size_t GetCpuCount () -{ - KAFFINITY activeCpuMap = KeQueryActiveProcessors(); - size_t mapSize = sizeof (activeCpuMap) * 8; - size_t cpuCount = 0; - - while (mapSize--) - { - if (activeCpuMap & 1) - ++cpuCount; - - activeCpuMap >>= 1; - } - - if (cpuCount == 0) - return 1; - - return cpuCount; -} - - -void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes) -{ - ASSERT ((maxSizeInBytes & 1) == 0); - str[maxSizeInBytes / sizeof (wchar_t) - 1] = 0; -} - - -void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout) -{ - LARGE_INTEGER waitInterval; - waitInterval.QuadPart = retryDelay * -10000; - - ASSERT (KeGetCurrentIrql() <= APC_LEVEL); - ASSERT (retryDelay > 0 && retryDelay <= timeout); - - while (TRUE) - { - void *memory = TCalloc (size); - if (memory) - return memory; - - timeout -= retryDelay; - if (timeout <= 0) - break; - - KeDelayExecutionThread (KernelMode, FALSE, &waitInterval); - } - - return NULL; -} - - -NTSTATUS TCReadRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, PKEY_VALUE_PARTIAL_INFORMATION *keyData) -{ - OBJECT_ATTRIBUTES regObjAttribs; - HANDLE regKeyHandle; - NTSTATUS status; - UNICODE_STRING valName; - ULONG size = 0; - ULONG resultSize; - - InitializeObjectAttributes (®ObjAttribs, keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - status = ZwOpenKey (®KeyHandle, KEY_READ, ®ObjAttribs); - if (!NT_SUCCESS (status)) - return status; - - RtlInitUnicodeString (&valName, keyValueName); - status = ZwQueryValueKey (regKeyHandle, &valName, KeyValuePartialInformation, NULL, 0, &size); - - if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) - { - ZwClose (regKeyHandle); - return status; - } - - if (size == 0) - { - ZwClose (regKeyHandle); - return STATUS_NO_DATA_DETECTED; - } - - *keyData = (PKEY_VALUE_PARTIAL_INFORMATION) TCalloc (size); - if (!*keyData) - { - ZwClose (regKeyHandle); - return STATUS_INSUFFICIENT_RESOURCES; - } - - status = ZwQueryValueKey (regKeyHandle, &valName, KeyValuePartialInformation, *keyData, size, &resultSize); - - ZwClose (regKeyHandle); - return status; -} - - -NTSTATUS TCWriteRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, ULONG keyValueType, void *valueData, ULONG valueSize) -{ - OBJECT_ATTRIBUTES regObjAttribs; - HANDLE regKeyHandle; - NTSTATUS status; - UNICODE_STRING valName; - - InitializeObjectAttributes (®ObjAttribs, keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - status = ZwOpenKey (®KeyHandle, KEY_READ | KEY_WRITE, ®ObjAttribs); - if (!NT_SUCCESS (status)) - return status; - - RtlInitUnicodeString (&valName, keyValueName); - - status = ZwSetValueKey (regKeyHandle, &valName, keyValueType, keyValueType, valueData, valueSize); - - ZwClose (regKeyHandle); - return status; -} - - -BOOL IsVolumeClassFilterRegistered () -{ - UNICODE_STRING name; - NTSTATUS status; - BOOL registered = FALSE; - - PKEY_VALUE_PARTIAL_INFORMATION data; - - RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{71A27CDD-812A-11D0-BEC7-08002BE2092F}"); - status = TCReadRegistryKey (&name, L"UpperFilters", &data); - - if (NT_SUCCESS (status)) - { - if (data->Type == REG_MULTI_SZ && data->DataLength >= 9 * sizeof (wchar_t)) - { - // Search for the string "truecrypt" - ULONG i; - for (i = 0; i <= data->DataLength - 9 * sizeof (wchar_t); ++i) - { - if (memcmp (data->Data + i, L"truecrypt", 9 * sizeof (wchar_t)) == 0) - { - Dump ("Volume class filter active\n"); - registered = TRUE; - break; - } - } - } - - TCfree (data); - } - - return registered; -} - - -uint32 ReadRegistryConfigFlags () -{ - PKEY_VALUE_PARTIAL_INFORMATION data; - UNICODE_STRING name; - NTSTATUS status; - uint32 flags = 0; - - RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\truecrypt"); - status = TCReadRegistryKey (&name, TC_DRIVER_CONFIG_REG_VALUE_NAME, &data); - - if (NT_SUCCESS (status)) - { - if (data->Type == REG_DWORD) - { - flags = *(uint32 *) data->Data; - Dump ("Configuration flags = 0x%x\n", flags); - - if (flags & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD) - CacheBootPassword = TRUE; - } - - TCfree (data); - } - - return flags; -} - - -NTSTATUS WriteRegistryConfigFlags (uint32 flags) -{ - UNICODE_STRING name; - RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\truecrypt"); - - return TCWriteRegistryKey (&name, TC_DRIVER_CONFIG_REG_VALUE_NAME, REG_DWORD, &flags, sizeof (flags)); -} - - -NTSTATUS GetDeviceSectorSize (PDEVICE_OBJECT deviceObject, ULONG *bytesPerSector) -{ - NTSTATUS status; - DISK_GEOMETRY geometry; - - status = SendDeviceIoControlRequest (deviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geometry, sizeof (geometry)); - - if (!NT_SUCCESS (status)) - return status; - - *bytesPerSector = geometry.BytesPerSector; - return STATUS_SUCCESS; -} - - -NTSTATUS ZeroUnreadableSectors (PDEVICE_OBJECT deviceObject, LARGE_INTEGER startOffset, ULONG size, uint64 *zeroedSectorCount) -{ - NTSTATUS status; - ULONG sectorSize; - ULONG sectorCount; - byte *sectorBuffer = NULL; - - *zeroedSectorCount = 0; - - status = GetDeviceSectorSize (deviceObject, §orSize); - if (!NT_SUCCESS (status)) - return status; - - sectorBuffer = TCalloc (sectorSize); - if (!sectorBuffer) - return STATUS_INSUFFICIENT_RESOURCES; - - for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount, startOffset.QuadPart += sectorSize) - { - status = TCReadDevice (deviceObject, sectorBuffer, startOffset, sectorSize); - if (!NT_SUCCESS (status)) - { - Dump ("Zeroing sector at %I64d\n", startOffset.QuadPart); - memset (sectorBuffer, 0, sectorSize); - - status = TCWriteDevice (deviceObject, sectorBuffer, startOffset, sectorSize); - if (!NT_SUCCESS (status)) - goto err; - - ++(*zeroedSectorCount); - } - } - - status = STATUS_SUCCESS; - -err: - if (sectorBuffer) - TCfree (sectorBuffer); - - return status; -} - - -NTSTATUS ReadDeviceSkipUnreadableSectors (PDEVICE_OBJECT deviceObject, byte *buffer, LARGE_INTEGER startOffset, ULONG size, uint64 *badSectorCount) -{ - NTSTATUS status; - ULONG sectorSize; - ULONG sectorCount; - - *badSectorCount = 0; - - status = GetDeviceSectorSize (deviceObject, §orSize); - if (!NT_SUCCESS (status)) - return status; - - for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount, startOffset.QuadPart += sectorSize, buffer += sectorSize) - { - status = TCReadDevice (deviceObject, buffer, startOffset, sectorSize); - if (!NT_SUCCESS (status)) - { - Dump ("Skipping bad sector at %I64d\n", startOffset.QuadPart); - memset (buffer, 0, sectorSize); - ++(*badSectorCount); - } - } - - return STATUS_SUCCESS; -} - - -BOOL IsVolumeAccessibleByCurrentUser (PEXTENSION volumeDeviceExtension) -{ - SECURITY_SUBJECT_CONTEXT subContext; - PACCESS_TOKEN accessToken; - PTOKEN_USER tokenUser; - BOOL result = FALSE; - - if (IoIsSystemThread (PsGetCurrentThread()) || UserCanAccessDriveDevice() || !volumeDeviceExtension->UserSid) - return TRUE; - - SeCaptureSubjectContext (&subContext); - accessToken = SeQuerySubjectContextToken (&subContext); - - if (!accessToken) - goto ret; - - if (SeTokenIsAdmin (accessToken)) - { - result = TRUE; - goto ret; - } - - if (!NT_SUCCESS (SeQueryInformationToken (accessToken, TokenUser, &tokenUser))) - goto ret; - - result = RtlEqualSid (volumeDeviceExtension->UserSid, tokenUser->User.Sid); - -ret: - SeReleaseSubjectContext (&subContext); - return result; -} - - -void GetElapsedTimeInit (LARGE_INTEGER *lastPerfCounter) -{ - *lastPerfCounter = KeQueryPerformanceCounter (NULL); -} - - -// Returns elapsed time in microseconds since last call -int64 GetElapsedTime (LARGE_INTEGER *lastPerfCounter) -{ - LARGE_INTEGER freq; - LARGE_INTEGER counter = KeQueryPerformanceCounter (&freq); - - int64 elapsed = (counter.QuadPart - lastPerfCounter->QuadPart) * 1000000LL / freq.QuadPart; - *lastPerfCounter = counter; - - return elapsed; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "TCdefs.h" +#include +#include "Crypto.h" +#include "Fat.h" +#include "Tests.h" + +#include "Apidrvr.h" +#include "Boot/Windows/BootDefs.h" +#include "EncryptedIoQueue.h" +#include "EncryptionThreadPool.h" +#include "Ntdriver.h" +#include "Ntvol.h" +#include "DriveFilter.h" +#include "Cache.h" +#include "Volumes.h" +#include "VolumeFilter.h" + +#include +#include +#include +#include +#include + +/* Init section, which is thrown away as soon as DriverEntry returns */ +#pragma alloc_text(INIT,DriverEntry) +#pragma alloc_text(INIT,TCCreateRootDeviceObject) + +PDRIVER_OBJECT TCDriverObject; +KMUTEX driverMutex; /* Sync mutex for the entire driver */ +BOOL DriverShuttingDown = FALSE; +BOOL SelfTestsPassed; +int LastUniqueVolumeId; +ULONG OsMajorVersion = 0; +ULONG OsMinorVersion; +BOOL ReferencedDeviceDeleted = FALSE; +BOOL PortableMode = FALSE; +BOOL VolumeClassFilterRegistered = FALSE; +BOOL CacheBootPassword = FALSE; +BOOL NonAdminSystemFavoritesAccessDisabled = FALSE; +static BOOL SystemFavoriteVolumeDirty = FALSE; + + +NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + PKEY_VALUE_PARTIAL_INFORMATION startKeyValue; + int i; + + Dump ("DriverEntry " TC_APP_NAME " " VERSION_STRING "\n"); + + TCDriverObject = DriverObject; + KeInitializeMutex (&driverMutex, 0); + + EncryptionThreadPoolStart(); + SelfTestsPassed = AutoTestAlgorithms (); + PsGetVersion (&OsMajorVersion, &OsMinorVersion, NULL, NULL); + + ReadRegistryConfigFlags(); + + // Enable device class filters and load boot arguments if the driver is set to start at system boot + + if (NT_SUCCESS (TCReadRegistryKey (RegistryPath, L"Start", &startKeyValue))) + { + if (startKeyValue->Type == REG_DWORD && *((uint32 *) startKeyValue->Data) == SERVICE_BOOT_START) + { + if (!SelfTestsPassed) + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + + LoadBootArguments(); + VolumeClassFilterRegistered = IsVolumeClassFilterRegistered(); + + DriverObject->DriverExtension->AddDevice = DriverAddDevice; + } + + TCfree (startKeyValue); + } + + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i) + { + DriverObject->MajorFunction[i] = TCDispatchQueueIRP; + } + + DriverObject->DriverUnload = TCUnloadDriver; + return TCCreateRootDeviceObject (DriverObject); +} + + +NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) +{ +#ifdef DEBUG + char nameInfoBuffer[128]; + POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION) nameInfoBuffer; + ULONG nameInfoSize; + Dump ("AddDevice pdo=%p type=%x name=%ws\n", pdo, pdo->DeviceType, NT_SUCCESS (ObQueryNameString (pdo, nameInfo, sizeof (nameInfoBuffer), &nameInfoSize)) ? nameInfo->Name.Buffer : L"?"); +#endif + + if (VolumeClassFilterRegistered && BootArgsValid && BootArgs.HiddenSystemPartitionStart != 0) + { + PWSTR interfaceLinks; + if (NT_SUCCESS (IoGetDeviceInterfaces (&GUID_DEVINTERFACE_VOLUME, pdo, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &interfaceLinks))) + { + if (interfaceLinks[0] != UNICODE_NULL) + { + Dump ("Volume pdo=%p interface=%ws\n", pdo, interfaceLinks); + ExFreePool (interfaceLinks); + + return VolumeFilterAddDevice (driverObject, pdo); + } + + ExFreePool (interfaceLinks); + } + } + + return DriveFilterAddDevice (driverObject, pdo); +} + + +// Dumps a memory region to debug output +void DumpMemory (void *mem, int size) +{ + unsigned char str[20]; + unsigned char *m = mem; + int i,j; + + for (j = 0; j < size / 8; j++) + { + memset (str,0,sizeof str); + for (i = 0; i < 8; i++) + { + if (m[i] > ' ' && m[i] <= '~') + str[i]=m[i]; + else + str[i]='.'; + } + + Dump ("0x%08p %02x %02x %02x %02x %02x %02x %02x %02x %s\n", + m, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], str); + + m+=8; + } +} + + +BOOL ValidateIOBufferSize (PIRP irp, size_t requiredBufferSize, ValidateIOBufferSizeType type) +{ + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp); + BOOL input = (type == ValidateInput || type == ValidateInputOutput); + BOOL output = (type == ValidateOutput || type == ValidateInputOutput); + + if ((input && irpSp->Parameters.DeviceIoControl.InputBufferLength < requiredBufferSize) + || (output && irpSp->Parameters.DeviceIoControl.OutputBufferLength < requiredBufferSize)) + { + Dump ("STATUS_BUFFER_TOO_SMALL ioctl=0x%x,%d in=%d out=%d reqsize=%d insize=%d outsize=%d\n", (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16), (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2), input, output, requiredBufferSize, irpSp->Parameters.DeviceIoControl.InputBufferLength, irpSp->Parameters.DeviceIoControl.OutputBufferLength); + + irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + irp->IoStatus.Information = 0; + return FALSE; + } + + if (!input && output) + memset (irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength); + + return TRUE; +} + + +/* TCDispatchQueueIRP queues any IRP's so that they can be processed later + by the thread -- or in some cases handles them immediately! */ +NTSTATUS TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PEXTENSION Extension = (PEXTENSION) DeviceObject->DeviceExtension; + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + NTSTATUS ntStatus; + +#ifdef _DEBUG + if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && (Extension->bRootDevice || Extension->IsVolumeDevice)) + { + switch (irpSp->Parameters.DeviceIoControl.IoControlCode) + { + case TC_IOCTL_GET_MOUNTED_VOLUMES: + case TC_IOCTL_GET_PASSWORD_CACHE_STATUS: + case TC_IOCTL_GET_PORTABLE_MODE_STATUS: + case TC_IOCTL_SET_PORTABLE_MODE_STATUS: + case TC_IOCTL_OPEN_TEST: + case TC_IOCTL_GET_RESOLVED_SYMLINK: + case TC_IOCTL_GET_DRIVE_PARTITION_INFO: + case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES: + case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS: + case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS: + case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING: + case IOCTL_DISK_CHECK_VERIFY: + break; + + default: + Dump ("%ls (0x%x %d)\n", + TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode), + (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16), + (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2)); + } + } +#endif + + if (!Extension->bRootDevice) + { + // Drive filter IRP + if (Extension->IsDriveFilterDevice) + return DriveFilterDispatchIrp (DeviceObject, Irp); + + // Volume filter IRP + if (Extension->IsVolumeFilterDevice) + return VolumeFilterDispatchIrp (DeviceObject, Irp); + } + + switch (irpSp->MajorFunction) + { + case IRP_MJ_CLOSE: + case IRP_MJ_CREATE: + case IRP_MJ_CLEANUP: + return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0); + + case IRP_MJ_SHUTDOWN: + if (Extension->bRootDevice) + { + Dump ("Driver shutting down\n"); + DriverShuttingDown = TRUE; + + if (EncryptionSetupThread) + AbortBootEncryptionSetup(); + + if (DecoySystemWipeThread) + AbortDecoySystemWipe(); + + UnmountAllDevices (NULL, DeviceObject, TRUE); + } + + return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0); + + case IRP_MJ_FLUSH_BUFFERS: + case IRP_MJ_READ: + case IRP_MJ_WRITE: + case IRP_MJ_DEVICE_CONTROL: + + if (Extension->bRootDevice) + { + if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) + return ProcessMainDeviceControlIrp (DeviceObject, Extension, Irp); + break; + } + + if (Extension->bShuttingDown) + { + Dump ("Device %d shutting down: STATUS_DELETE_PENDING\n", Extension->nDosDriveNo); + return TCCompleteDiskIrp (Irp, STATUS_DELETE_PENDING, 0); + } + + if (Extension->bRemovable + && (DeviceObject->Flags & DO_VERIFY_VOLUME) + && !(irpSp->Flags & SL_OVERRIDE_VERIFY_VOLUME) + && irpSp->MajorFunction != IRP_MJ_FLUSH_BUFFERS) + { + Dump ("Removable device %d has DO_VERIFY_VOLUME flag: STATUS_DEVICE_NOT_READY\n", Extension->nDosDriveNo); + return TCCompleteDiskIrp (Irp, STATUS_DEVICE_NOT_READY, 0); + } + + switch (irpSp->MajorFunction) + { + case IRP_MJ_READ: + case IRP_MJ_WRITE: + ntStatus = EncryptedIoQueueAddIrp (&Extension->Queue, Irp); + + if (ntStatus != STATUS_PENDING) + TCCompleteDiskIrp (Irp, ntStatus, 0); + + return ntStatus; + + case IRP_MJ_DEVICE_CONTROL: + ntStatus = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (ntStatus)) + return TCCompleteIrp (Irp, ntStatus, 0); + + IoMarkIrpPending (Irp); + + ExInterlockedInsertTailList (&Extension->ListEntry, &Irp->Tail.Overlay.ListEntry, &Extension->ListSpinLock); + KeReleaseSemaphore (&Extension->RequestSemaphore, IO_DISK_INCREMENT, 1, FALSE); + + return STATUS_PENDING; + + case IRP_MJ_FLUSH_BUFFERS: + return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0); + } + } + + return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0); +} + +NTSTATUS TCCreateRootDeviceObject (PDRIVER_OBJECT DriverObject) +{ + UNICODE_STRING Win32NameString, ntUnicodeString; + WCHAR dosname[32], ntname[32]; + PDEVICE_OBJECT DeviceObject; + NTSTATUS ntStatus; + BOOL *bRootExtension; + + Dump ("TCCreateRootDeviceObject BEGIN\n"); + ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); + + wcscpy (dosname, (LPWSTR) DOS_ROOT_PREFIX); + wcscpy (ntname, (LPWSTR) NT_ROOT_PREFIX); + RtlInitUnicodeString (&ntUnicodeString, ntname); + RtlInitUnicodeString (&Win32NameString, dosname); + + Dump ("Creating root device nt=%ls dos=%ls\n", ntname, dosname); + + ntStatus = IoCreateDevice ( + DriverObject, + sizeof (BOOL), + &ntUnicodeString, + FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &DeviceObject); + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus); + return ntStatus;/* Failed to create DeviceObject */ + } + + DeviceObject->Flags |= DO_DIRECT_IO; + DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; + + /* Setup the device extension */ + bRootExtension = (BOOL *) DeviceObject->DeviceExtension; + *bRootExtension = TRUE; + + ntStatus = IoCreateSymbolicLink (&Win32NameString, &ntUnicodeString); + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus); + IoDeleteDevice (DeviceObject); + return ntStatus; + } + + IoRegisterShutdownNotification (DeviceObject); + + Dump ("TCCreateRootDeviceObject STATUS_SUCCESS END\n"); + return STATUS_SUCCESS; +} + +NTSTATUS TCCreateDeviceObject (PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT * ppDeviceObject, + MOUNT_STRUCT * mount) +{ + UNICODE_STRING Win32NameString, ntUnicodeString; + WCHAR dosname[32], ntname[32]; + PEXTENSION Extension; + NTSTATUS ntStatus; + ULONG devChars = 0; + + Dump ("TCCreateDeviceObject BEGIN\n"); + ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); + + TCGetDosNameFromNumber (dosname, mount->nDosDriveNo); + TCGetNTNameFromNumber (ntname, mount->nDosDriveNo); + RtlInitUnicodeString (&ntUnicodeString, ntname); + RtlInitUnicodeString (&Win32NameString, dosname); + + devChars = FILE_DEVICE_SECURE_OPEN; + devChars |= mount->bMountReadOnly ? FILE_READ_ONLY_DEVICE : 0; + devChars |= mount->bMountRemovable ? FILE_REMOVABLE_MEDIA : 0; + + Dump ("Creating device nt=%ls dos=%ls\n", ntname, dosname); + + ntStatus = IoCreateDevice ( + DriverObject, /* Our Driver Object */ + sizeof (EXTENSION), /* Size of state information */ + &ntUnicodeString, /* Device name "\Device\Name" */ + FILE_DEVICE_DISK, /* Device type */ + devChars, /* Device characteristics */ + FALSE, /* Exclusive device */ + ppDeviceObject); /* Returned ptr to Device Object */ + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("TCCreateDeviceObject NTSTATUS = 0x%08x END\n", ntStatus); + return ntStatus;/* Failed to create DeviceObject */ + } + /* Initialize device object and extension. */ + + (*ppDeviceObject)->Flags |= DO_DIRECT_IO; + (*ppDeviceObject)->StackSize += 2; // Reduce occurrence of NO_MORE_IRP_STACK_LOCATIONS bug check caused by buggy drivers + + /* Setup the device extension */ + Extension = (PEXTENSION) (*ppDeviceObject)->DeviceExtension; + memset (Extension, 0, sizeof (EXTENSION)); + + Extension->IsVolumeDevice = TRUE; + Extension->lMagicNumber = 0xabfeacde; + Extension->nDosDriveNo = mount->nDosDriveNo; + Extension->bRemovable = mount->bMountRemovable; + Extension->PartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope; + Extension->SystemFavorite = mount->SystemFavorite; + + KeInitializeEvent (&Extension->keCreateEvent, SynchronizationEvent, FALSE); + KeInitializeSemaphore (&Extension->RequestSemaphore, 0L, MAXLONG); + KeInitializeSpinLock (&Extension->ListSpinLock); + InitializeListHead (&Extension->ListEntry); + IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0); + + Dump ("TCCreateDeviceObject STATUS_SUCCESS END\n"); + + return STATUS_SUCCESS; +} + + +void DriverMutexWait () +{ + NTSTATUS status = KeWaitForMutexObject (&driverMutex, Executive, KernelMode, FALSE, NULL); + + if (!NT_SUCCESS (status)) + TC_BUG_CHECK (status); +} + + +BOOL DriverMutexAcquireNoWait () +{ + NTSTATUS status; + LARGE_INTEGER timeout; + timeout.QuadPart = 0; + + status = KeWaitForMutexObject (&driverMutex, Executive, KernelMode, FALSE, &timeout); + return NT_SUCCESS (status) && status != STATUS_TIMEOUT; +} + + +void DriverMutexRelease () +{ + KeReleaseMutex (&driverMutex, FALSE); +} + + +NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp) +{ + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + + switch (irpSp->Parameters.DeviceIoControl.IoControlCode) + { + + case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: + if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_NAME), ValidateOutput)) + { + Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME); + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ULONG outLength; + UNICODE_STRING ntUnicodeString; + WCHAR ntName[256]; + PMOUNTDEV_NAME outputBuffer = (PMOUNTDEV_NAME) Irp->AssociatedIrp.SystemBuffer; + + TCGetNTNameFromNumber (ntName, Extension->nDosDriveNo); + RtlInitUnicodeString (&ntUnicodeString, ntName); + + outputBuffer->NameLength = ntUnicodeString.Length; + outLength = ntUnicodeString.Length + sizeof(USHORT); + + if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength) + { + Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME); + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + + break; + } + + RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = outLength; + + Dump ("name = %ls\n",ntName); + } + break; + + case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: + if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_UNIQUE_ID), ValidateOutput)) + { + Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID); + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ULONG outLength; + UCHAR volId[128], tmp[] = { 0,0 }; + PMOUNTDEV_UNIQUE_ID outputBuffer = (PMOUNTDEV_UNIQUE_ID) Irp->AssociatedIrp.SystemBuffer; + + strcpy (volId, TC_UNIQUE_ID_PREFIX); + tmp[0] = 'A' + (UCHAR) Extension->nDosDriveNo; + strcat (volId, tmp); + + outputBuffer->UniqueIdLength = (USHORT) strlen (volId); + outLength = (ULONG) (strlen (volId) + sizeof (USHORT)); + + if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength) + { + Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID); + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + break; + } + + RtlCopyMemory ((PCHAR)outputBuffer->UniqueId, volId, strlen (volId)); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = outLength; + + Dump ("id = %s\n",volId); + } + break; + + case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: + { + ULONG outLength; + UNICODE_STRING ntUnicodeString; + WCHAR ntName[256]; + PMOUNTDEV_SUGGESTED_LINK_NAME outputBuffer = (PMOUNTDEV_SUGGESTED_LINK_NAME) Irp->AssociatedIrp.SystemBuffer; + + if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_SUGGESTED_LINK_NAME), ValidateOutput)) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + break; + } + + TCGetDosNameFromNumber (ntName, Extension->nDosDriveNo); + RtlInitUnicodeString (&ntUnicodeString, ntName); + + outLength = FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME,Name) + ntUnicodeString.Length; + + outputBuffer->UseOnlyIfThereAreNoOtherLinks = FALSE; + outputBuffer->NameLength = ntUnicodeString.Length; + + if(irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength) + { + Irp->IoStatus.Information = sizeof (MOUNTDEV_SUGGESTED_LINK_NAME); + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + break; + } + + RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = outLength; + + Dump ("link = %ls\n",ntName); + } + break; + + case IOCTL_DISK_GET_MEDIA_TYPES: + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + /* Return the drive geometry for the disk. Note that we + return values which were made up to suit the disk size. */ + if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY), ValidateOutput)) + { + PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY) + Irp->AssociatedIrp.SystemBuffer; + + outputBuffer->MediaType = Extension->bRemovable ? RemovableMedia : FixedMedia; + outputBuffer->Cylinders.QuadPart = Extension->NumberOfCylinders; + outputBuffer->TracksPerCylinder = Extension->TracksPerCylinder; + outputBuffer->SectorsPerTrack = Extension->SectorsPerTrack; + outputBuffer->BytesPerSector = Extension->BytesPerSector; + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (DISK_GEOMETRY); + } + break; + + case IOCTL_DISK_GET_PARTITION_INFO: + if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION), ValidateOutput)) + { + PPARTITION_INFORMATION outputBuffer = (PPARTITION_INFORMATION) + Irp->AssociatedIrp.SystemBuffer; + + outputBuffer->PartitionType = Extension->PartitionType; + outputBuffer->BootIndicator = FALSE; + outputBuffer->RecognizedPartition = TRUE; + outputBuffer->RewritePartition = FALSE; + outputBuffer->StartingOffset.QuadPart = SECTOR_SIZE; + outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; + outputBuffer->HiddenSectors = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION); + } + break; + + case IOCTL_DISK_GET_PARTITION_INFO_EX: + if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION_EX), ValidateOutput)) + { + PPARTITION_INFORMATION_EX outputBuffer = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer; + + outputBuffer->PartitionStyle = PARTITION_STYLE_MBR; + outputBuffer->RewritePartition = FALSE; + outputBuffer->StartingOffset.QuadPart = SECTOR_SIZE; + outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; + outputBuffer->Mbr.PartitionType = Extension->PartitionType; + outputBuffer->Mbr.BootIndicator = FALSE; + outputBuffer->Mbr.RecognizedPartition = TRUE; + outputBuffer->Mbr.HiddenSectors = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION_EX); + } + break; + + case IOCTL_DISK_GET_DRIVE_LAYOUT: + if (ValidateIOBufferSize (Irp, sizeof (DRIVE_LAYOUT_INFORMATION), ValidateOutput)) + { + PDRIVE_LAYOUT_INFORMATION outputBuffer = (PDRIVE_LAYOUT_INFORMATION) + Irp->AssociatedIrp.SystemBuffer; + + outputBuffer->PartitionCount = 1; + outputBuffer->Signature = 0; + + outputBuffer->PartitionEntry->PartitionType = Extension->PartitionType; + outputBuffer->PartitionEntry->BootIndicator = FALSE; + outputBuffer->PartitionEntry->RecognizedPartition = TRUE; + outputBuffer->PartitionEntry->RewritePartition = FALSE; + outputBuffer->PartitionEntry->StartingOffset.QuadPart = SECTOR_SIZE; + outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength; + outputBuffer->PartitionEntry->HiddenSectors = 0; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION); + } + break; + + case IOCTL_DISK_GET_LENGTH_INFO: + if (!ValidateIOBufferSize (Irp, sizeof (GET_LENGTH_INFORMATION), ValidateOutput)) + { + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION); + } + else + { + PGET_LENGTH_INFORMATION outputBuffer = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer; + + outputBuffer->Length.QuadPart = Extension->DiskLength; + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION); + } + break; + + case IOCTL_DISK_VERIFY: + if (ValidateIOBufferSize (Irp, sizeof (VERIFY_INFORMATION), ValidateInput)) + { + PVERIFY_INFORMATION pVerifyInformation; + pVerifyInformation = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer; + + if (pVerifyInformation->StartingOffset.QuadPart + pVerifyInformation->Length > Extension->DiskLength) + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + else + { + IO_STATUS_BLOCK ioStatus; + PVOID buffer = TCalloc (max (pVerifyInformation->Length, PAGE_SIZE)); + + if (!buffer) + { + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + LARGE_INTEGER offset = pVerifyInformation->StartingOffset; + offset.QuadPart += Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset; + + Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, pVerifyInformation->Length, &offset, NULL); + TCfree (buffer); + + if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != pVerifyInformation->Length) + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + } + } + + Irp->IoStatus.Information = 0; + } + break; + + case IOCTL_DISK_CHECK_VERIFY: + case IOCTL_STORAGE_CHECK_VERIFY: + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + if (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof (ULONG)) + { + *((ULONG *) Irp->AssociatedIrp.SystemBuffer) = 0; + Irp->IoStatus.Information = sizeof (ULONG); + } + } + break; + + case IOCTL_DISK_IS_WRITABLE: + { + if (Extension->bReadOnly) + Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED; + else + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + } + break; + + case IOCTL_VOLUME_ONLINE: + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + break; + + case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: + + // Vista's filesystem defragmenter fails if IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS does not succeed. + if (!(OsMajorVersion == 6 && OsMinorVersion == 0)) + { + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Information = 0; + } + else if (ValidateIOBufferSize (Irp, sizeof (VOLUME_DISK_EXTENTS), ValidateOutput)) + { + VOLUME_DISK_EXTENTS *extents = (VOLUME_DISK_EXTENTS *) Irp->AssociatedIrp.SystemBuffer; + + // No extent data can be returned as this is not a physical drive. + memset (extents, 0, sizeof (*extents)); + extents->NumberOfDiskExtents = 0; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (*extents); + } + break; + + default: + return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0); + } + +#ifdef DEBUG + if (!NT_SUCCESS (Irp->IoStatus.Status)) + { + Dump ("IOCTL error 0x%08x (0x%x %d)\n", + Irp->IoStatus.Status, + (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16), + (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2)); + } +#endif + + return TCCompleteDiskIrp (Irp, Irp->IoStatus.Status, Irp->IoStatus.Information); +} + + +NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp) +{ + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + NTSTATUS ntStatus; + + switch (irpSp->Parameters.DeviceIoControl.IoControlCode) + { + case TC_IOCTL_GET_DRIVER_VERSION: + case TC_IOCTL_LEGACY_GET_DRIVER_VERSION: + if (ValidateIOBufferSize (Irp, sizeof (LONG), ValidateOutput)) + { + LONG tmp = VERSION_NUM; + memcpy (Irp->AssociatedIrp.SystemBuffer, &tmp, 4); + Irp->IoStatus.Information = sizeof (LONG); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + + case TC_IOCTL_GET_DEVICE_REFCOUNT: + if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) + { + *(int *) Irp->AssociatedIrp.SystemBuffer = DeviceObject->ReferenceCount; + Irp->IoStatus.Information = sizeof (int); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + + case TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED: + if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) + { + *(int *) Irp->AssociatedIrp.SystemBuffer = ReferencedDeviceDeleted; + Irp->IoStatus.Information = sizeof (int); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + + case TC_IOCTL_IS_ANY_VOLUME_MOUNTED: + if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) + { + PDEVICE_OBJECT ListDevice; + *(int *) Irp->AssociatedIrp.SystemBuffer = 0; + + DriverMutexWait (); + + for (ListDevice = DeviceObject->DriverObject->DeviceObject; + ListDevice != (PDEVICE_OBJECT) NULL; ListDevice = ListDevice->NextDevice) + { + PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; + if (!ListExtension->bRootDevice + && ListExtension->IsVolumeDevice + && ListExtension->lMagicNumber == 0xabfeacde) + { + *(int *) Irp->AssociatedIrp.SystemBuffer = 1; + break; + } + } + + DriverMutexRelease (); + + if (IsBootDriveMounted()) + *(int *) Irp->AssociatedIrp.SystemBuffer = 1; + + Irp->IoStatus.Information = sizeof (int); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + + case TC_IOCTL_OPEN_TEST: + { + OPEN_TEST_STRUCT *opentest = (OPEN_TEST_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE NtFileHandle; + UNICODE_STRING FullFileName; + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER offset; + unsigned char readBuffer [SECTOR_SIZE]; + ACCESS_MASK access = FILE_READ_ATTRIBUTES; + + if (!ValidateIOBufferSize (Irp, sizeof (OPEN_TEST_STRUCT), ValidateInputOutput)) + break; + + EnsureNullTerminatedString (opentest->wszFileName, sizeof (opentest->wszFileName)); + RtlInitUnicodeString (&FullFileName, opentest->wszFileName); + + InitializeObjectAttributes (&ObjectAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + + if (opentest->bDetectTCBootLoader || opentest->DetectFilesystem) + access |= FILE_READ_DATA; + + ntStatus = ZwCreateFile (&NtFileHandle, + SYNCHRONIZE | access, &ObjectAttributes, &IoStatus, NULL, + 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); + + if (NT_SUCCESS (ntStatus)) + { + opentest->TCBootLoaderDetected = FALSE; + opentest->FilesystemDetected = FALSE; + + if (opentest->bDetectTCBootLoader || opentest->DetectFilesystem) + { + // Determine if the first sector contains a portion of the TrueCrypt Boot Loader + + offset.QuadPart = 0; // MBR + + ntStatus = ZwReadFile (NtFileHandle, + NULL, + NULL, + NULL, + &IoStatus, + readBuffer, + sizeof(readBuffer), + &offset, + NULL); + + if (NT_SUCCESS (ntStatus)) + { + size_t i; + + if (opentest->bDetectTCBootLoader) + { + // Search for the string "TrueCrypt" + for (i = 0; i < sizeof (readBuffer) - strlen (TC_APP_NAME); ++i) + { + if (memcmp (readBuffer + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0) + { + opentest->TCBootLoaderDetected = TRUE; + break; + } + } + } + + if (opentest->DetectFilesystem) + { + switch (BE64 (*(uint64 *) readBuffer)) + { + case 0xEB52904E54465320: // NTFS + case 0xEB3C904D53444F53: // FAT16 + case 0xEB58904D53444F53: // FAT32 + case 0xEB76904558464154: // exFAT + + opentest->FilesystemDetected = TRUE; + break; + } + } + } + } + + ZwClose (NtFileHandle); + Dump ("Open test on file %ls success.\n", opentest->wszFileName); + } + else + { +#if 0 + Dump ("Open test on file %ls failed NTSTATUS 0x%08x\n", opentest->wszFileName, ntStatus); +#endif + } + + Irp->IoStatus.Information = NT_SUCCESS (ntStatus) ? sizeof (OPEN_TEST_STRUCT) : 0; + Irp->IoStatus.Status = ntStatus; + } + break; + + case TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG: + { + GetSystemDriveConfigurationRequest *request = (GetSystemDriveConfigurationRequest *) Irp->AssociatedIrp.SystemBuffer; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE NtFileHandle; + UNICODE_STRING FullFileName; + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER offset; + byte readBuffer [SECTOR_SIZE]; + + if (!ValidateIOBufferSize (Irp, sizeof (GetSystemDriveConfigurationRequest), ValidateInputOutput)) + break; + + EnsureNullTerminatedString (request->DevicePath, sizeof (request->DevicePath)); + RtlInitUnicodeString (&FullFileName, request->DevicePath); + + InitializeObjectAttributes (&ObjectAttributes, &FullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); + + ntStatus = ZwCreateFile (&NtFileHandle, + SYNCHRONIZE | GENERIC_READ, &ObjectAttributes, &IoStatus, NULL, + FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_RANDOM_ACCESS, NULL, 0); + + if (NT_SUCCESS (ntStatus)) + { + // Determine if the first sector contains a portion of the TrueCrypt Boot Loader + offset.QuadPart = 0; // MBR + + ntStatus = ZwReadFile (NtFileHandle, + NULL, + NULL, + NULL, + &IoStatus, + readBuffer, + sizeof(readBuffer), + &offset, + NULL); + + if (NT_SUCCESS (ntStatus)) + { + size_t i; + + // Check for dynamic drive + request->DriveIsDynamic = FALSE; + + if (readBuffer[510] == 0x55 && readBuffer[511] == 0xaa) + { + int i; + for (i = 0; i < 4; ++i) + { + if (readBuffer[446 + i * 16 + 4] == PARTITION_LDM) + { + request->DriveIsDynamic = TRUE; + break; + } + } + } + + request->BootLoaderVersion = 0; + request->Configuration = 0; + request->UserConfiguration = 0; + request->CustomUserMessage[0] = 0; + + // Search for the string "TrueCrypt" + for (i = 0; i < sizeof (readBuffer) - strlen (TC_APP_NAME); ++i) + { + if (memcmp (readBuffer + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0) + { + request->BootLoaderVersion = BE16 (*(uint16 *) (readBuffer + TC_BOOT_SECTOR_VERSION_OFFSET)); + request->Configuration = readBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET]; + + if (request->BootLoaderVersion != 0 && request->BootLoaderVersion <= VERSION_NUM) + { + request->UserConfiguration = readBuffer[TC_BOOT_SECTOR_USER_CONFIG_OFFSET]; + memcpy (request->CustomUserMessage, readBuffer + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH); + } + break; + } + } + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (*request); + } + else + { + Irp->IoStatus.Status = ntStatus; + Irp->IoStatus.Information = 0; + } + + ZwClose (NtFileHandle); + + } + else + { + Irp->IoStatus.Status = ntStatus; + Irp->IoStatus.Information = 0; + } + } + break; + + case TC_IOCTL_WIPE_PASSWORD_CACHE: + DriverMutexWait (); + WipeCache (); + DriverMutexRelease (); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + break; + + case TC_IOCTL_GET_PASSWORD_CACHE_STATUS: + Irp->IoStatus.Status = cacheEmpty ? STATUS_PIPE_EMPTY : STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + break; + + case TC_IOCTL_SET_PORTABLE_MODE_STATUS: + if (!UserCanAccessDriveDevice()) + { + Irp->IoStatus.Status = STATUS_ACCESS_DENIED; + Irp->IoStatus.Information = 0; + } + else + { + PortableMode = TRUE; + Dump ("Setting portable mode\n"); + } + break; + + case TC_IOCTL_GET_PORTABLE_MODE_STATUS: + Irp->IoStatus.Status = PortableMode ? STATUS_SUCCESS : STATUS_PIPE_EMPTY; + Irp->IoStatus.Information = 0; + break; + + case TC_IOCTL_GET_MOUNTED_VOLUMES: + + if (ValidateIOBufferSize (Irp, sizeof (MOUNT_LIST_STRUCT), ValidateOutput)) + { + MOUNT_LIST_STRUCT *list = (MOUNT_LIST_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + PDEVICE_OBJECT ListDevice; + + DriverMutexWait (); + + list->ulMountedDrives = 0; + + for (ListDevice = DeviceObject->DriverObject->DeviceObject; + ListDevice != (PDEVICE_OBJECT) NULL; ListDevice = ListDevice->NextDevice) + { + PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; + if (!ListExtension->bRootDevice + && ListExtension->IsVolumeDevice + && !ListExtension->bShuttingDown + && ListExtension->lMagicNumber == 0xabfeacde + && IsVolumeAccessibleByCurrentUser (ListExtension)) + { + list->ulMountedDrives |= (1 << ListExtension->nDosDriveNo); + wcscpy (list->wszVolume[ListExtension->nDosDriveNo], ListExtension->wszVolume); + list->diskLength[ListExtension->nDosDriveNo] = ListExtension->DiskLength; + list->ea[ListExtension->nDosDriveNo] = ListExtension->cryptoInfo->ea; + if (ListExtension->cryptoInfo->hiddenVolume) + list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_HIDDEN; // Hidden volume + else if (ListExtension->cryptoInfo->bHiddenVolProtectionAction) + list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED; // Normal/outer volume (hidden volume protected AND write already prevented) + else if (ListExtension->cryptoInfo->bProtectHiddenVolume) + list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER; // Normal/outer volume (hidden volume protected) + else + list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_NORMAL; // Normal volume + } + } + + DriverMutexRelease (); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (MOUNT_LIST_STRUCT); + } + break; + + case TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES: + if (ValidateIOBufferSize (Irp, sizeof (uint32), ValidateOutput)) + { + // Prevent the user from downgrading to versions lower than 5.0 by faking mounted volumes. + // The user could render the system unbootable by downgrading when boot encryption + // is active or being set up. + + memset (Irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength); + *(uint32 *) Irp->AssociatedIrp.SystemBuffer = 0xffffFFFF; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = irpSp->Parameters.DeviceIoControl.OutputBufferLength; + } + break; + + case TC_IOCTL_GET_VOLUME_PROPERTIES: + if (ValidateIOBufferSize (Irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateInputOutput)) + { + VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + PDEVICE_OBJECT ListDevice; + + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + + DriverMutexWait (); + + for (ListDevice = DeviceObject->DriverObject->DeviceObject; + ListDevice != (PDEVICE_OBJECT) NULL; ListDevice = ListDevice->NextDevice) + { + + PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; + if (!ListExtension->bRootDevice + && ListExtension->IsVolumeDevice + && !ListExtension->bShuttingDown + && ListExtension->nDosDriveNo == prop->driveNo + && IsVolumeAccessibleByCurrentUser (ListExtension)) + { + prop->uniqueId = ListExtension->UniqueVolumeId; + wcscpy (prop->wszVolume, ListExtension->wszVolume); + prop->diskLength = ListExtension->DiskLength; + prop->ea = ListExtension->cryptoInfo->ea; + prop->mode = ListExtension->cryptoInfo->mode; + prop->pkcs5 = ListExtension->cryptoInfo->pkcs5; + prop->pkcs5Iterations = ListExtension->cryptoInfo->noIterations; +#if 0 + prop->volumeCreationTime = ListExtension->cryptoInfo->volume_creation_time; + prop->headerCreationTime = ListExtension->cryptoInfo->header_creation_time; +#endif + prop->volumeHeaderFlags = ListExtension->cryptoInfo->HeaderFlags; + prop->readOnly = ListExtension->bReadOnly; + prop->removable = ListExtension->bRemovable; + prop->partitionInInactiveSysEncScope = ListExtension->PartitionInInactiveSysEncScope; + prop->hiddenVolume = ListExtension->cryptoInfo->hiddenVolume; + + if (ListExtension->cryptoInfo->bProtectHiddenVolume) + prop->hiddenVolProtection = ListExtension->cryptoInfo->bHiddenVolProtectionAction ? HIDVOL_PROT_STATUS_ACTION_TAKEN : HIDVOL_PROT_STATUS_ACTIVE; + else + prop->hiddenVolProtection = HIDVOL_PROT_STATUS_NONE; + + prop->totalBytesRead = ListExtension->Queue.TotalBytesRead; + prop->totalBytesWritten = ListExtension->Queue.TotalBytesWritten; + + prop->volFormatVersion = ListExtension->cryptoInfo->LegacyVolume ? TC_VOLUME_FORMAT_VERSION_PRE_6_0 : TC_VOLUME_FORMAT_VERSION; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (VOLUME_PROPERTIES_STRUCT); + break; + } + } + + DriverMutexRelease (); + } + break; + + case TC_IOCTL_GET_RESOLVED_SYMLINK: + if (ValidateIOBufferSize (Irp, sizeof (RESOLVE_SYMLINK_STRUCT), ValidateInputOutput)) + { + RESOLVE_SYMLINK_STRUCT *resolve = (RESOLVE_SYMLINK_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + { + NTSTATUS ntStatus; + + EnsureNullTerminatedString (resolve->symLinkName, sizeof (resolve->symLinkName)); + + ntStatus = SymbolicLinkToTarget (resolve->symLinkName, + resolve->targetName, + sizeof (resolve->targetName)); + + Irp->IoStatus.Information = sizeof (RESOLVE_SYMLINK_STRUCT); + Irp->IoStatus.Status = ntStatus; + } + } + break; + + case TC_IOCTL_GET_DRIVE_PARTITION_INFO: + if (ValidateIOBufferSize (Irp, sizeof (DISK_PARTITION_INFO_STRUCT), ValidateInputOutput)) + { + DISK_PARTITION_INFO_STRUCT *info = (DISK_PARTITION_INFO_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + { + PARTITION_INFORMATION_EX pi; + NTSTATUS ntStatus; + + EnsureNullTerminatedString (info->deviceName, sizeof (info->deviceName)); + + ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &pi, sizeof (pi)); + if (NT_SUCCESS(ntStatus)) + { + memset (&info->partInfo, 0, sizeof (info->partInfo)); + + info->partInfo.PartitionLength = pi.PartitionLength; + info->partInfo.PartitionNumber = pi.PartitionNumber; + info->partInfo.StartingOffset = pi.StartingOffset; + + if (pi.PartitionStyle == PARTITION_STYLE_MBR) + { + info->partInfo.PartitionType = pi.Mbr.PartitionType; + info->partInfo.BootIndicator = pi.Mbr.BootIndicator; + } + + info->IsGPT = pi.PartitionStyle == PARTITION_STYLE_GPT; + } + else + { + // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX + ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &info->partInfo, sizeof (info->partInfo)); + info->IsGPT = FALSE; + } + + if (!NT_SUCCESS (ntStatus)) + { + GET_LENGTH_INFORMATION lengthInfo; + ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &lengthInfo, sizeof (lengthInfo)); + + if (NT_SUCCESS (ntStatus)) + { + memset (&info->partInfo, 0, sizeof (info->partInfo)); + info->partInfo.PartitionLength = lengthInfo.Length; + } + } + + info->IsDynamic = FALSE; + + if (NT_SUCCESS (ntStatus) && OsMajorVersion >= 6) + { +# define IOCTL_VOLUME_IS_DYNAMIC CTL_CODE(IOCTL_VOLUME_BASE, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) + if (!NT_SUCCESS (TCDeviceIoControl (info->deviceName, IOCTL_VOLUME_IS_DYNAMIC, NULL, 0, &info->IsDynamic, sizeof (info->IsDynamic)))) + info->IsDynamic = FALSE; + } + + Irp->IoStatus.Information = sizeof (DISK_PARTITION_INFO_STRUCT); + Irp->IoStatus.Status = ntStatus; + } + } + break; + + case TC_IOCTL_GET_DRIVE_GEOMETRY: + if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY_STRUCT), ValidateInputOutput)) + { + DISK_GEOMETRY_STRUCT *g = (DISK_GEOMETRY_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + { + NTSTATUS ntStatus; + + EnsureNullTerminatedString (g->deviceName, sizeof (g->deviceName)); + + ntStatus = TCDeviceIoControl (g->deviceName, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, 0, &g->diskGeometry, sizeof (g->diskGeometry)); + + Irp->IoStatus.Information = sizeof (DISK_GEOMETRY_STRUCT); + Irp->IoStatus.Status = ntStatus; + } + } + break; + + case TC_IOCTL_PROBE_REAL_DRIVE_SIZE: + if (ValidateIOBufferSize (Irp, sizeof (ProbeRealDriveSizeRequest), ValidateInputOutput)) + { + ProbeRealDriveSizeRequest *request = (ProbeRealDriveSizeRequest *) Irp->AssociatedIrp.SystemBuffer; + NTSTATUS status; + UNICODE_STRING name; + PFILE_OBJECT fileObject; + PDEVICE_OBJECT deviceObject; + + EnsureNullTerminatedString (request->DeviceName, sizeof (request->DeviceName)); + + RtlInitUnicodeString (&name, request->DeviceName); + status = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject); + if (!NT_SUCCESS (status)) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = status; + break; + } + + status = ProbeRealDriveSize (deviceObject, &request->RealDriveSize); + ObDereferenceObject (fileObject); + + if (status == STATUS_TIMEOUT) + { + request->TimeOut = TRUE; + Irp->IoStatus.Information = sizeof (ProbeRealDriveSizeRequest); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + else if (!NT_SUCCESS (status)) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = status; + } + else + { + request->TimeOut = FALSE; + Irp->IoStatus.Information = sizeof (ProbeRealDriveSizeRequest); + Irp->IoStatus.Status = status; + } + } + break; + + case TC_IOCTL_MOUNT_VOLUME: + if (ValidateIOBufferSize (Irp, sizeof (MOUNT_STRUCT), ValidateInputOutput)) + { + MOUNT_STRUCT *mount = (MOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + + if (mount->VolumePassword.Length > MAX_PASSWORD || mount->ProtectedHidVolPassword.Length > MAX_PASSWORD) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + break; + } + + EnsureNullTerminatedString (mount->wszVolume, sizeof (mount->wszVolume)); + + DriverMutexWait (); + + Irp->IoStatus.Information = sizeof (MOUNT_STRUCT); + Irp->IoStatus.Status = MountDevice (DeviceObject, mount); + + DriverMutexRelease (); + + burn (&mount->VolumePassword, sizeof (mount->VolumePassword)); + burn (&mount->ProtectedHidVolPassword, sizeof (mount->ProtectedHidVolPassword)); + } + break; + + case TC_IOCTL_DISMOUNT_VOLUME: + if (ValidateIOBufferSize (Irp, sizeof (UNMOUNT_STRUCT), ValidateInputOutput)) + { + UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + PDEVICE_OBJECT ListDevice; + + unmount->nReturnCode = ERR_DRIVE_NOT_FOUND; + + for (ListDevice = DeviceObject->DriverObject->DeviceObject; + ListDevice != (PDEVICE_OBJECT) NULL; + ListDevice = ListDevice->NextDevice) + { + PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; + + if (!ListExtension->bRootDevice + && ListExtension->IsVolumeDevice + && !ListExtension->bShuttingDown + && unmount->nDosDriveNo == ListExtension->nDosDriveNo + && IsVolumeAccessibleByCurrentUser (ListExtension)) + { + DriverMutexWait (); + unmount->nReturnCode = UnmountDevice (unmount, ListDevice, unmount->ignoreOpenFiles); + DriverMutexRelease (); + break; + } + } + + Irp->IoStatus.Information = sizeof (UNMOUNT_STRUCT); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + + case TC_IOCTL_DISMOUNT_ALL_VOLUMES: + if (ValidateIOBufferSize (Irp, sizeof (UNMOUNT_STRUCT), ValidateInputOutput)) + { + UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer; + + unmount->nReturnCode = UnmountAllDevices (unmount, DeviceObject, unmount->ignoreOpenFiles); + + Irp->IoStatus.Information = sizeof (UNMOUNT_STRUCT); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + + case TC_IOCTL_BOOT_ENCRYPTION_SETUP: + DriverMutexWait (); + + Irp->IoStatus.Status = StartBootEncryptionSetup (DeviceObject, Irp, irpSp); + Irp->IoStatus.Information = 0; + + DriverMutexRelease (); + break; + + case TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP: + DriverMutexWait (); + + Irp->IoStatus.Status = AbortBootEncryptionSetup(); + Irp->IoStatus.Information = 0; + + DriverMutexRelease (); + break; + + case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS: + DriverMutexWait (); + GetBootEncryptionStatus (Irp, irpSp); + DriverMutexRelease (); + break; + + case TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT: + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = GetSetupResult(); + break; + + case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES: + DriverMutexWait (); + GetBootDriveVolumeProperties (Irp, irpSp); + DriverMutexRelease (); + break; + + case TC_IOCTL_GET_BOOT_LOADER_VERSION: + DriverMutexWait (); + GetBootLoaderVersion (Irp, irpSp); + DriverMutexRelease (); + break; + + case TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER: + DriverMutexWait (); + ReopenBootVolumeHeader (Irp, irpSp); + DriverMutexRelease (); + break; + + case TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME: + DriverMutexWait (); + GetBootEncryptionAlgorithmName (Irp, irpSp); + DriverMutexRelease (); + break; + + case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING: + if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) + { + *(int *) Irp->AssociatedIrp.SystemBuffer = IsHiddenSystemRunning() ? 1 : 0; + Irp->IoStatus.Information = sizeof (int); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + + case TC_IOCTL_START_DECOY_SYSTEM_WIPE: + DriverMutexWait (); + + Irp->IoStatus.Status = StartDecoySystemWipe (DeviceObject, Irp, irpSp); + Irp->IoStatus.Information = 0; + + DriverMutexRelease (); + break; + + case TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE: + DriverMutexWait (); + + Irp->IoStatus.Status = AbortDecoySystemWipe(); + Irp->IoStatus.Information = 0; + + DriverMutexRelease (); + break; + + case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT: + Irp->IoStatus.Status = GetDecoySystemWipeResult(); + Irp->IoStatus.Information = 0; + break; + + case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS: + DriverMutexWait (); + GetDecoySystemWipeStatus (Irp, irpSp); + DriverMutexRelease (); + break; + + case TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR: + Irp->IoStatus.Status = WriteBootDriveSector (Irp, irpSp); + Irp->IoStatus.Information = 0; + break; + + case TC_IOCTL_IS_SYSTEM_FAVORITE_VOLUME_DIRTY: + if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput)) + { + *(int *) Irp->AssociatedIrp.SystemBuffer = SystemFavoriteVolumeDirty ? 1 : 0; + Irp->IoStatus.Information = sizeof (int); + Irp->IoStatus.Status = STATUS_SUCCESS; + + SystemFavoriteVolumeDirty = FALSE; + } + break; + + case TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY: + if (UserCanAccessDriveDevice()) + { + SystemFavoriteVolumeDirty = TRUE; + Irp->IoStatus.Status = STATUS_SUCCESS; + } + else + Irp->IoStatus.Status = STATUS_ACCESS_DENIED; + + Irp->IoStatus.Information = 0; + break; + + default: + return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0); + } + + +#ifdef DEBUG + if (!NT_SUCCESS (Irp->IoStatus.Status)) + { + switch (irpSp->Parameters.DeviceIoControl.IoControlCode) + { + case TC_IOCTL_GET_MOUNTED_VOLUMES: + case TC_IOCTL_GET_PASSWORD_CACHE_STATUS: + case TC_IOCTL_GET_PORTABLE_MODE_STATUS: + case TC_IOCTL_SET_PORTABLE_MODE_STATUS: + case TC_IOCTL_OPEN_TEST: + case TC_IOCTL_GET_RESOLVED_SYMLINK: + case TC_IOCTL_GET_DRIVE_PARTITION_INFO: + case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES: + case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS: + case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING: + break; + + default: + Dump ("IOCTL error 0x%08x\n", Irp->IoStatus.Status); + } + } +#endif + + return TCCompleteIrp (Irp, Irp->IoStatus.Status, Irp->IoStatus.Information); +} + + +NTSTATUS TCStartThread (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread) +{ + return TCStartThreadInProcess (threadProc, threadArg, kThread, NULL); +} + + +NTSTATUS TCStartThreadInProcess (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread, PEPROCESS process) +{ + NTSTATUS status; + HANDLE threadHandle; + HANDLE processHandle = NULL; + OBJECT_ATTRIBUTES threadObjAttributes; + + if (process) + { + status = ObOpenObjectByPointer (process, OBJ_KERNEL_HANDLE, NULL, 0, NULL, KernelMode, &processHandle); + if (!NT_SUCCESS (status)) + return status; + } + + InitializeObjectAttributes (&threadObjAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); + + status = PsCreateSystemThread (&threadHandle, THREAD_ALL_ACCESS, &threadObjAttributes, processHandle, NULL, threadProc, threadArg); + if (!NT_SUCCESS (status)) + return status; + + status = ObReferenceObjectByHandle (threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *) kThread, NULL); + if (!NT_SUCCESS (status)) + { + ZwClose (threadHandle); + *kThread = NULL; + return status; + } + + if (processHandle) + ZwClose (processHandle); + + ZwClose (threadHandle); + return STATUS_SUCCESS; +} + + +void TCStopThread (PKTHREAD kThread, PKEVENT wakeUpEvent) +{ + if (wakeUpEvent) + KeSetEvent (wakeUpEvent, 0, FALSE); + + KeWaitForSingleObject (kThread, Executive, KernelMode, FALSE, NULL); + ObDereferenceObject (kThread); +} + + +NTSTATUS TCStartVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, MOUNT_STRUCT * mount) +{ + PTHREAD_BLOCK pThreadBlock = TCalloc (sizeof (THREAD_BLOCK)); + HANDLE hThread; + NTSTATUS ntStatus; + OBJECT_ATTRIBUTES threadObjAttributes; + SECURITY_QUALITY_OF_SERVICE qos; + + Dump ("Starting thread...\n"); + + if (pThreadBlock == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + pThreadBlock->DeviceObject = DeviceObject; + pThreadBlock->mount = mount; + } + + qos.Length = sizeof (qos); + qos.ContextTrackingMode = SECURITY_STATIC_TRACKING; + qos.EffectiveOnly = TRUE; + qos.ImpersonationLevel = SecurityImpersonation; + + ntStatus = SeCreateClientSecurity (PsGetCurrentThread(), &qos, FALSE, &Extension->SecurityClientContext); + if (!NT_SUCCESS (ntStatus)) + goto ret; + + Extension->SecurityClientContextValid = TRUE; + + Extension->bThreadShouldQuit = FALSE; + + InitializeObjectAttributes (&threadObjAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); + + ntStatus = PsCreateSystemThread (&hThread, + THREAD_ALL_ACCESS, + &threadObjAttributes, + NULL, + NULL, + VolumeThreadProc, + pThreadBlock); + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("PsCreateSystemThread Failed END\n"); + goto ret; + } + + ntStatus = ObReferenceObjectByHandle (hThread, + THREAD_ALL_ACCESS, + NULL, + KernelMode, + &Extension->peThread, + NULL); + + ZwClose (hThread); + + if (!NT_SUCCESS (ntStatus)) + goto ret; + + Dump ("Waiting for thread to initialize...\n"); + + KeWaitForSingleObject (&Extension->keCreateEvent, + Executive, + KernelMode, + FALSE, + NULL); + + Dump ("Waiting completed! Thread returns 0x%08x\n", pThreadBlock->ntCreateStatus); + ntStatus = pThreadBlock->ntCreateStatus; + +ret: + TCfree (pThreadBlock); + return ntStatus; +} + +void TCStopVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) +{ + NTSTATUS ntStatus; + + if (DeviceObject); /* Remove compiler warning */ + + Dump ("Signalling thread to quit...\n"); + + Extension->bThreadShouldQuit = TRUE; + + KeReleaseSemaphore (&Extension->RequestSemaphore, + 0, + 1, + TRUE); + + ntStatus = KeWaitForSingleObject (Extension->peThread, + Executive, + KernelMode, + FALSE, + NULL); + + ASSERT (NT_SUCCESS (ntStatus)); + + ObDereferenceObject (Extension->peThread); + Extension->peThread = NULL; + + Dump ("Thread exited\n"); +} + + +// Suspend current thread for a number of milliseconds +void TCSleep (int milliSeconds) +{ + PKTIMER timer = (PKTIMER) TCalloc (sizeof (KTIMER)); + LARGE_INTEGER duetime; + + if (!timer) + return; + + duetime.QuadPart = (__int64) milliSeconds * -10000; + KeInitializeTimerEx(timer, NotificationTimer); + KeSetTimerEx(timer, duetime, 0, NULL); + + KeWaitForSingleObject (timer, Executive, KernelMode, FALSE, NULL); + + TCfree (timer); +} + + +/* VolumeThreadProc does all the work of processing IRP's, and dispatching them + to either the ReadWrite function or the DeviceControl function */ +VOID VolumeThreadProc (PVOID Context) +{ + PTHREAD_BLOCK pThreadBlock = (PTHREAD_BLOCK) Context; + PDEVICE_OBJECT DeviceObject = pThreadBlock->DeviceObject; + PEXTENSION Extension = (PEXTENSION) DeviceObject->DeviceExtension; + BOOL bDevice; + + /* Set thread priority to lowest realtime level. */ + KeSetPriorityThread (KeGetCurrentThread (), LOW_REALTIME_PRIORITY); + + Dump ("Mount THREAD OPENING VOLUME BEGIN\n"); + + if (memcmp (pThreadBlock->mount->wszVolume, WIDE ("\\Device"), 14) != 0) + { + wcscpy (pThreadBlock->wszMountVolume, WIDE ("\\??\\")); + wcsncat (pThreadBlock->wszMountVolume, pThreadBlock->mount->wszVolume, + sizeof (pThreadBlock->wszMountVolume) / 2 - 5); + bDevice = FALSE; + } + else + { + pThreadBlock->wszMountVolume[0] = 0; + wcsncat (pThreadBlock->wszMountVolume, pThreadBlock->mount->wszVolume, + sizeof (pThreadBlock->wszMountVolume) / 2 - 1); + bDevice = TRUE; + } + + Dump ("Mount THREAD request for File %ls DriveNumber %d Device = %d\n", + pThreadBlock->wszMountVolume, pThreadBlock->mount->nDosDriveNo, bDevice); + + pThreadBlock->ntCreateStatus = TCOpenVolume (DeviceObject, + Extension, + pThreadBlock->mount, + pThreadBlock->wszMountVolume, + bDevice); + + if (!NT_SUCCESS (pThreadBlock->ntCreateStatus) || pThreadBlock->mount->nReturnCode != 0) + { + KeSetEvent (&Extension->keCreateEvent, 0, FALSE); + PsTerminateSystemThread (STATUS_SUCCESS); + } + + // Start IO queue + Extension->Queue.IsFilterDevice = FALSE; + Extension->Queue.DeviceObject = DeviceObject; + Extension->Queue.CryptoInfo = Extension->cryptoInfo; + Extension->Queue.HostFileHandle = Extension->hDeviceFile; + Extension->Queue.VirtualDeviceLength = Extension->DiskLength; + Extension->Queue.MaxReadAheadOffset.QuadPart = Extension->HostLength; + + if (Extension->SecurityClientContextValid) + Extension->Queue.SecurityClientContext = &Extension->SecurityClientContext; + else + Extension->Queue.SecurityClientContext = NULL; + + pThreadBlock->ntCreateStatus = EncryptedIoQueueStart (&Extension->Queue); + + if (!NT_SUCCESS (pThreadBlock->ntCreateStatus)) + { + TCCloseVolume (DeviceObject, Extension); + + pThreadBlock->mount->nReturnCode = ERR_OS_ERROR; + KeSetEvent (&Extension->keCreateEvent, 0, FALSE); + PsTerminateSystemThread (STATUS_SUCCESS); + } + + KeSetEvent (&Extension->keCreateEvent, 0, FALSE); + /* From this point on pThreadBlock cannot be used as it will have been released! */ + pThreadBlock = NULL; + + for (;;) + { + /* Wait for a request from the dispatch routines. */ + KeWaitForSingleObject ((PVOID) & Extension->RequestSemaphore, Executive, KernelMode, FALSE, NULL); + + for (;;) + { + PIO_STACK_LOCATION irpSp; + PLIST_ENTRY request; + PIRP irp; + + request = ExInterlockedRemoveHeadList (&Extension->ListEntry, &Extension->ListSpinLock); + if (request == NULL) + break; + + irp = CONTAINING_RECORD (request, IRP, Tail.Overlay.ListEntry); + irpSp = IoGetCurrentIrpStackLocation (irp); + + ASSERT (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL); + + ProcessVolumeDeviceControlIrp (DeviceObject, Extension, irp); + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, irp); + } + + if (Extension->bThreadShouldQuit) + { + Dump ("Closing volume\n"); + EncryptedIoQueueStop (&Extension->Queue); + + TCCloseVolume (DeviceObject, Extension); + PsTerminateSystemThread (STATUS_SUCCESS); + } + } +} + +void TCGetNTNameFromNumber (LPWSTR ntname, int nDriveNo) +{ + WCHAR tmp[3] = + {0, ':', 0}; + int j = nDriveNo + (WCHAR) 'A'; + + tmp[0] = (short) j; + wcscpy (ntname, (LPWSTR) NT_MOUNT_PREFIX); + wcsncat (ntname, tmp, 1); +} + +void TCGetDosNameFromNumber (LPWSTR dosname, int nDriveNo) +{ + WCHAR tmp[3] = + {0, ':', 0}; + int j = nDriveNo + (WCHAR) 'A'; + + tmp[0] = (short) j; + wcscpy (dosname, (LPWSTR) DOS_MOUNT_PREFIX); + wcscat (dosname, tmp); +} + +#ifdef _DEBUG +LPWSTR TCTranslateCode (ULONG ulCode) +{ + switch (ulCode) + { +#define TC_CASE_RET_NAME(CODE) case CODE : return L###CODE + + TC_CASE_RET_NAME (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP); + TC_CASE_RET_NAME (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE); + TC_CASE_RET_NAME (TC_IOCTL_BOOT_ENCRYPTION_SETUP); + TC_CASE_RET_NAME (TC_IOCTL_DISMOUNT_ALL_VOLUMES); + TC_CASE_RET_NAME (TC_IOCTL_DISMOUNT_VOLUME); + TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES); + TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME); + TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT); + TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS); + TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_LOADER_VERSION); + TC_CASE_RET_NAME (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT); + TC_CASE_RET_NAME (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS); + TC_CASE_RET_NAME (TC_IOCTL_GET_DEVICE_REFCOUNT); + TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVE_GEOMETRY); + TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVE_PARTITION_INFO); + TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVER_VERSION); + TC_CASE_RET_NAME (TC_IOCTL_GET_MOUNTED_VOLUMES); + TC_CASE_RET_NAME (TC_IOCTL_GET_PASSWORD_CACHE_STATUS); + TC_CASE_RET_NAME (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG); + TC_CASE_RET_NAME (TC_IOCTL_GET_PORTABLE_MODE_STATUS); + TC_CASE_RET_NAME (TC_IOCTL_SET_PORTABLE_MODE_STATUS); + TC_CASE_RET_NAME (TC_IOCTL_GET_RESOLVED_SYMLINK); + TC_CASE_RET_NAME (TC_IOCTL_GET_VOLUME_PROPERTIES); + TC_CASE_RET_NAME (TC_IOCTL_DISK_IS_WRITABLE); + TC_CASE_RET_NAME (TC_IOCTL_IS_ANY_VOLUME_MOUNTED); + TC_CASE_RET_NAME (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING); + TC_CASE_RET_NAME (TC_IOCTL_IS_SYSTEM_FAVORITE_VOLUME_DIRTY); + TC_CASE_RET_NAME (TC_IOCTL_MOUNT_VOLUME); + TC_CASE_RET_NAME (TC_IOCTL_OPEN_TEST); + TC_CASE_RET_NAME (TC_IOCTL_PROBE_REAL_DRIVE_SIZE); + TC_CASE_RET_NAME (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER); + TC_CASE_RET_NAME (TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY); + TC_CASE_RET_NAME (TC_IOCTL_START_DECOY_SYSTEM_WIPE); + TC_CASE_RET_NAME (TC_IOCTL_WAS_REFERENCED_DEVICE_DELETED); + TC_CASE_RET_NAME (TC_IOCTL_WIPE_PASSWORD_CACHE); + TC_CASE_RET_NAME (TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR); + + TC_CASE_RET_NAME (IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS); + +#undef TC_CASE_RET_NAME + } + + if (ulCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) + return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_GEOMETRY"); + else if (ulCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) + return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX"); + else if (ulCode == IOCTL_MOUNTDEV_QUERY_DEVICE_NAME) + return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME"); + else if (ulCode == IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME) + return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME"); + else if (ulCode == IOCTL_MOUNTDEV_QUERY_UNIQUE_ID) + return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_UNIQUE_ID"); + else if (ulCode == IOCTL_VOLUME_ONLINE) + return (LPWSTR) _T ("IOCTL_VOLUME_ONLINE"); + else if (ulCode == IOCTL_MOUNTDEV_LINK_CREATED) + return (LPWSTR) _T ("IOCTL_MOUNTDEV_LINK_CREATED"); + else if (ulCode == IOCTL_MOUNTDEV_LINK_DELETED) + return (LPWSTR) _T ("IOCTL_MOUNTDEV_LINK_DELETED"); + else if (ulCode == IOCTL_MOUNTMGR_QUERY_POINTS) + return (LPWSTR) _T ("IOCTL_MOUNTMGR_QUERY_POINTS"); + else if (ulCode == IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED) + return (LPWSTR) _T ("IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED"); + else if (ulCode == IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED) + return (LPWSTR) _T ("IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED"); + else if (ulCode == IOCTL_DISK_GET_LENGTH_INFO) + return (LPWSTR) _T ("IOCTL_DISK_GET_LENGTH_INFO"); + else if (ulCode == IOCTL_STORAGE_GET_DEVICE_NUMBER) + return (LPWSTR) _T ("IOCTL_STORAGE_GET_DEVICE_NUMBER"); + else if (ulCode == IOCTL_DISK_GET_PARTITION_INFO) + return (LPWSTR) _T ("IOCTL_DISK_GET_PARTITION_INFO"); + else if (ulCode == IOCTL_DISK_GET_PARTITION_INFO_EX) + return (LPWSTR) _T ("IOCTL_DISK_GET_PARTITION_INFO_EX"); + else if (ulCode == IOCTL_DISK_SET_PARTITION_INFO) + return (LPWSTR) _T ("IOCTL_DISK_SET_PARTITION_INFO"); + else if (ulCode == IOCTL_DISK_GET_DRIVE_LAYOUT) + return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_LAYOUT"); + else if (ulCode == IOCTL_DISK_SET_DRIVE_LAYOUT_EX) + return (LPWSTR) _T ("IOCTL_DISK_SET_DRIVE_LAYOUT_EX"); + else if (ulCode == IOCTL_DISK_VERIFY) + return (LPWSTR) _T ("IOCTL_DISK_VERIFY"); + else if (ulCode == IOCTL_DISK_FORMAT_TRACKS) + return (LPWSTR) _T ("IOCTL_DISK_FORMAT_TRACKS"); + else if (ulCode == IOCTL_DISK_REASSIGN_BLOCKS) + return (LPWSTR) _T ("IOCTL_DISK_REASSIGN_BLOCKS"); + else if (ulCode == IOCTL_DISK_PERFORMANCE) + return (LPWSTR) _T ("IOCTL_DISK_PERFORMANCE"); + else if (ulCode == IOCTL_DISK_IS_WRITABLE) + return (LPWSTR) _T ("IOCTL_DISK_IS_WRITABLE"); + else if (ulCode == IOCTL_DISK_LOGGING) + return (LPWSTR) _T ("IOCTL_DISK_LOGGING"); + else if (ulCode == IOCTL_DISK_FORMAT_TRACKS_EX) + return (LPWSTR) _T ("IOCTL_DISK_FORMAT_TRACKS_EX"); + else if (ulCode == IOCTL_DISK_HISTOGRAM_STRUCTURE) + return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_STRUCTURE"); + else if (ulCode == IOCTL_DISK_HISTOGRAM_DATA) + return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_DATA"); + else if (ulCode == IOCTL_DISK_HISTOGRAM_RESET) + return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_RESET"); + else if (ulCode == IOCTL_DISK_REQUEST_STRUCTURE) + return (LPWSTR) _T ("IOCTL_DISK_REQUEST_STRUCTURE"); + else if (ulCode == IOCTL_DISK_REQUEST_DATA) + return (LPWSTR) _T ("IOCTL_DISK_REQUEST_DATA"); + else if (ulCode == IOCTL_DISK_CONTROLLER_NUMBER) + return (LPWSTR) _T ("IOCTL_DISK_CONTROLLER_NUMBER"); + else if (ulCode == SMART_GET_VERSION) + return (LPWSTR) _T ("SMART_GET_VERSION"); + else if (ulCode == SMART_SEND_DRIVE_COMMAND) + return (LPWSTR) _T ("SMART_SEND_DRIVE_COMMAND"); + else if (ulCode == SMART_RCV_DRIVE_DATA) + return (LPWSTR) _T ("SMART_RCV_DRIVE_DATA"); + else if (ulCode == IOCTL_DISK_INTERNAL_SET_VERIFY) + return (LPWSTR) _T ("IOCTL_DISK_INTERNAL_SET_VERIFY"); + else if (ulCode == IOCTL_DISK_INTERNAL_CLEAR_VERIFY) + return (LPWSTR) _T ("IOCTL_DISK_INTERNAL_CLEAR_VERIFY"); + else if (ulCode == IOCTL_DISK_CHECK_VERIFY) + return (LPWSTR) _T ("IOCTL_DISK_CHECK_VERIFY"); + else if (ulCode == IOCTL_DISK_MEDIA_REMOVAL) + return (LPWSTR) _T ("IOCTL_DISK_MEDIA_REMOVAL"); + else if (ulCode == IOCTL_DISK_EJECT_MEDIA) + return (LPWSTR) _T ("IOCTL_DISK_EJECT_MEDIA"); + else if (ulCode == IOCTL_DISK_LOAD_MEDIA) + return (LPWSTR) _T ("IOCTL_DISK_LOAD_MEDIA"); + else if (ulCode == IOCTL_DISK_RESERVE) + return (LPWSTR) _T ("IOCTL_DISK_RESERVE"); + else if (ulCode == IOCTL_DISK_RELEASE) + return (LPWSTR) _T ("IOCTL_DISK_RELEASE"); + else if (ulCode == IOCTL_DISK_FIND_NEW_DEVICES) + return (LPWSTR) _T ("IOCTL_DISK_FIND_NEW_DEVICES"); + else if (ulCode == IOCTL_DISK_GET_MEDIA_TYPES) + return (LPWSTR) _T ("IOCTL_DISK_GET_MEDIA_TYPES"); + else if (ulCode == IOCTL_STORAGE_SET_HOTPLUG_INFO) + return (LPWSTR) _T ("IOCTL_STORAGE_SET_HOTPLUG_INFO"); + else if (ulCode == IRP_MJ_READ) + return (LPWSTR) _T ("IRP_MJ_READ"); + else if (ulCode == IRP_MJ_WRITE) + return (LPWSTR) _T ("IRP_MJ_WRITE"); + else if (ulCode == IRP_MJ_CREATE) + return (LPWSTR) _T ("IRP_MJ_CREATE"); + else if (ulCode == IRP_MJ_CLOSE) + return (LPWSTR) _T ("IRP_MJ_CLOSE"); + else if (ulCode == IRP_MJ_CLEANUP) + return (LPWSTR) _T ("IRP_MJ_CLEANUP"); + else if (ulCode == IRP_MJ_FLUSH_BUFFERS) + return (LPWSTR) _T ("IRP_MJ_FLUSH_BUFFERS"); + else if (ulCode == IRP_MJ_SHUTDOWN) + return (LPWSTR) _T ("IRP_MJ_SHUTDOWN"); + else if (ulCode == IRP_MJ_DEVICE_CONTROL) + return (LPWSTR) _T ("IRP_MJ_DEVICE_CONTROL"); + else + { + return (LPWSTR) _T ("IOCTL"); + } +} + +#endif + +PDEVICE_OBJECT TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) +{ + PDEVICE_OBJECT OldDeviceObject = DeviceObject; + UNICODE_STRING Win32NameString; + NTSTATUS ntStatus; + + Dump ("TCDeleteDeviceObject BEGIN\n"); + + if (Extension->bRootDevice) + { + RtlInitUnicodeString (&Win32NameString, (LPWSTR) DOS_ROOT_PREFIX); + ntStatus = IoDeleteSymbolicLink (&Win32NameString); + if (!NT_SUCCESS (ntStatus)) + Dump ("IoDeleteSymbolicLink failed ntStatus = 0x%08x\n", ntStatus); + } + else + { + if (Extension->peThread != NULL) + TCStopVolumeThread (DeviceObject, Extension); + + if (Extension->UserSid) + TCfree (Extension->UserSid); + + if (Extension->SecurityClientContextValid) + { + if (OsMajorVersion == 5 && OsMinorVersion == 0) + { + ObDereferenceObject (Extension->SecurityClientContext.ClientToken); + } + else + { + // Windows 2000 does not support PsDereferenceImpersonationToken() used by SeDeleteClientSecurity(). + // TODO: Use only SeDeleteClientSecurity() once support for Windows 2000 is dropped. + + VOID (*PsDereferenceImpersonationTokenD) (PACCESS_TOKEN ImpersonationToken); + UNICODE_STRING name; + RtlInitUnicodeString (&name, L"PsDereferenceImpersonationToken"); + + PsDereferenceImpersonationTokenD = MmGetSystemRoutineAddress (&name); + if (!PsDereferenceImpersonationTokenD) + TC_BUG_CHECK (STATUS_NOT_IMPLEMENTED); + +# define PsDereferencePrimaryToken +# define PsDereferenceImpersonationToken PsDereferenceImpersonationTokenD + + SeDeleteClientSecurity (&Extension->SecurityClientContext); + +# undef PsDereferencePrimaryToken +# undef PsDereferenceImpersonationToken + } + } + + if (DeviceObject->ReferenceCount > 0) + ReferencedDeviceDeleted = TRUE; + + // Forced dismount does not set reference count to zero even if all open handles are closed + Dump ("Deleting device with ref count %ld\n", DeviceObject->ReferenceCount); + DeviceObject->ReferenceCount = 0; + } + + if (DeviceObject != NULL) + DeviceObject = DeviceObject->NextDevice; + + IoDeleteDevice (OldDeviceObject); + + Dump ("TCDeleteDeviceObject END\n"); + return DeviceObject; +} + + +VOID TCUnloadDriver (PDRIVER_OBJECT DriverObject) +{ + PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject; + + Dump ("TCUnloadDriver BEGIN\n"); + + UnmountAllDevices (NULL, DeviceObject, TRUE); + + /* Now walk the list of driver objects and get rid of them */ + while (DeviceObject != (PDEVICE_OBJECT) NULL) + { + DeviceObject = TCDeleteDeviceObject (DeviceObject, + (PEXTENSION) DeviceObject->DeviceExtension); + } + + WipeCache (); + + if (IsBootDriveMounted()) + TC_BUG_CHECK (STATUS_INVALID_DEVICE_STATE); + + EncryptionThreadPoolStop(); + + Dump ("TCUnloadDriver END\n"); +} + + +NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize) +{ + IO_STATUS_BLOCK ioStatusBlock; + NTSTATUS ntStatus; + PIRP irp; + PFILE_OBJECT fileObject; + PDEVICE_OBJECT deviceObject; + KEVENT event; + UNICODE_STRING name; + + RtlInitUnicodeString(&name, deviceName); + ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject); + + if (!NT_SUCCESS (ntStatus)) + return ntStatus; + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + irp = IoBuildDeviceIoControlRequest (IoControlCode, + deviceObject, + InputBuffer, InputBufferSize, + OutputBuffer, OutputBufferSize, + FALSE, + &event, + &ioStatusBlock); + + if (irp == NULL) + { + Dump ("IRP allocation failed\n"); + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto ret; + } + + IoGetNextIrpStackLocation (irp)->FileObject = fileObject; + + ntStatus = IoCallDriver (deviceObject, irp); + if (ntStatus == STATUS_PENDING) + { + KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); + ntStatus = ioStatusBlock.Status; + } + +ret: + ObDereferenceObject (fileObject); + return ntStatus; +} + + +NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize) +{ + IO_STATUS_BLOCK ioStatusBlock; + NTSTATUS status; + PIRP irp; + KEVENT event; + + ASSERT(KeGetCurrentIrql() <= APC_LEVEL); + + KeInitializeEvent (&event, NotificationEvent, FALSE); + + irp = IoBuildDeviceIoControlRequest (ioControlCode, deviceObject, inputBuffer, inputBufferSize, + outputBuffer, outputBufferSize, FALSE, &event, &ioStatusBlock); + + if (!irp) + return STATUS_INSUFFICIENT_RESOURCES; + + ObReferenceObject (deviceObject); + + status = IoCallDriver (deviceObject, irp); + if (status == STATUS_PENDING) + { + KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); + status = ioStatusBlock.Status; + } + + ObDereferenceObject (deviceObject); + return status; +} + + +NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *driveSize) +{ + NTSTATUS status; + LARGE_INTEGER sysLength; + LARGE_INTEGER offset; + byte *sectorBuffer; + ULONGLONG startTime; + + if (!UserCanAccessDriveDevice()) + return STATUS_ACCESS_DENIED; + + sectorBuffer = TCalloc (SECTOR_SIZE); + if (!sectorBuffer) + return STATUS_INSUFFICIENT_RESOURCES; + + status = SendDeviceIoControlRequest (driveDeviceObject, IOCTL_DISK_GET_LENGTH_INFO, + NULL, 0, &sysLength, sizeof (sysLength)); + + if (!NT_SUCCESS (status)) + { + Dump ("Failed to get drive size - error %x\n", status); + TCfree (sectorBuffer); + return status; + } + + startTime = KeQueryInterruptTime (); + for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += SECTOR_SIZE) + { + status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, SECTOR_SIZE); + + if (NT_SUCCESS (status)) + status = TCWriteDevice (driveDeviceObject, sectorBuffer, offset, SECTOR_SIZE); + + if (!NT_SUCCESS (status)) + { + driveSize->QuadPart = offset.QuadPart; + Dump ("Real drive size = %I64d bytes (%I64d hidden)\n", driveSize->QuadPart, driveSize->QuadPart - sysLength.QuadPart); + TCfree (sectorBuffer); + return STATUS_SUCCESS; + } + + if (KeQueryInterruptTime() - startTime > 3ULL * 60 * 1000 * 1000 * 10) + { + // Abort if probing for more than 3 minutes + driveSize->QuadPart = sysLength.QuadPart; + TCfree (sectorBuffer); + return STATUS_TIMEOUT; + } + } +} + + +NTSTATUS TCOpenFsVolume (PEXTENSION Extension, PHANDLE volumeHandle, PFILE_OBJECT * fileObject) +{ + NTSTATUS ntStatus; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fullFileName; + IO_STATUS_BLOCK ioStatus; + WCHAR volumeName[TC_MAX_PATH]; + + TCGetNTNameFromNumber (volumeName, Extension->nDosDriveNo); + RtlInitUnicodeString (&fullFileName, volumeName); + InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); + + ntStatus = ZwCreateFile (volumeHandle, + SYNCHRONIZE | GENERIC_READ, + &objectAttributes, + &ioStatus, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + Dump ("Volume %ls open NTSTATUS 0x%08x\n", volumeName, ntStatus); + + if (!NT_SUCCESS (ntStatus)) + return ntStatus; + + ntStatus = ObReferenceObjectByHandle (*volumeHandle, + FILE_READ_DATA, + NULL, + KernelMode, + fileObject, + NULL); + + if (!NT_SUCCESS (ntStatus)) + ZwClose (*volumeHandle); + + return ntStatus; +} + + +void TCCloseFsVolume (HANDLE volumeHandle, PFILE_OBJECT fileObject) +{ + ObDereferenceObject (fileObject); + ZwClose (volumeHandle); +} + + +static NTSTATUS TCReadWriteDevice (BOOL write, PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length) +{ + NTSTATUS status; + IO_STATUS_BLOCK ioStatusBlock; + PIRP irp; + KEVENT completionEvent; + + ASSERT (KeGetCurrentIrql() <= APC_LEVEL); + + KeInitializeEvent (&completionEvent, NotificationEvent, FALSE); + irp = IoBuildSynchronousFsdRequest (write ? IRP_MJ_WRITE : IRP_MJ_READ, deviceObject, buffer, length, &offset, &completionEvent, &ioStatusBlock); + if (!irp) + return STATUS_INSUFFICIENT_RESOURCES; + + ObReferenceObject (deviceObject); + status = IoCallDriver (deviceObject, irp); + + if (status == STATUS_PENDING) + { + status = KeWaitForSingleObject (&completionEvent, Executive, KernelMode, FALSE, NULL); + if (NT_SUCCESS (status)) + status = ioStatusBlock.Status; + } + + ObDereferenceObject (deviceObject); + return status; +} + + +NTSTATUS TCReadDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length) +{ + return TCReadWriteDevice (FALSE, deviceObject, buffer, offset, length); +} + + +NTSTATUS TCWriteDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length) +{ + return TCReadWriteDevice (TRUE, deviceObject, buffer, offset, length); +} + + +NTSTATUS TCFsctlCall (PFILE_OBJECT fileObject, LONG IoControlCode, + void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize) +{ + IO_STATUS_BLOCK ioStatusBlock; + NTSTATUS ntStatus; + PIRP irp; + KEVENT event; + PIO_STACK_LOCATION stack; + PDEVICE_OBJECT deviceObject = IoGetRelatedDeviceObject (fileObject); + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + irp = IoBuildDeviceIoControlRequest (IoControlCode, + deviceObject, + InputBuffer, InputBufferSize, + OutputBuffer, OutputBufferSize, + FALSE, + &event, + &ioStatusBlock); + + if (irp == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + stack = IoGetNextIrpStackLocation(irp); + + stack->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; + stack->MinorFunction = IRP_MN_USER_FS_REQUEST; + stack->FileObject = fileObject; + + ntStatus = IoCallDriver (deviceObject, irp); + if (ntStatus == STATUS_PENDING) + { + KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); + ntStatus = ioStatusBlock.Status; + } + + return ntStatus; +} + + +NTSTATUS CreateDriveLink (int nDosDriveNo) +{ + WCHAR dev[128], link[128]; + UNICODE_STRING deviceName, symLink; + NTSTATUS ntStatus; + + TCGetNTNameFromNumber (dev, nDosDriveNo); + TCGetDosNameFromNumber (link, nDosDriveNo); + + RtlInitUnicodeString (&deviceName, dev); + RtlInitUnicodeString (&symLink, link); + + ntStatus = IoCreateSymbolicLink (&symLink, &deviceName); + Dump ("IoCreateSymbolicLink returned %X\n", ntStatus); + return ntStatus; +} + + +NTSTATUS RemoveDriveLink (int nDosDriveNo) +{ + WCHAR link[256]; + UNICODE_STRING symLink; + NTSTATUS ntStatus; + + TCGetDosNameFromNumber (link, nDosDriveNo); + RtlInitUnicodeString (&symLink, link); + + ntStatus = IoDeleteSymbolicLink (&symLink); + Dump ("IoDeleteSymbolicLink returned %X\n", ntStatus); + return ntStatus; +} + + +NTSTATUS MountManagerMount (MOUNT_STRUCT *mount) +{ + NTSTATUS ntStatus; + WCHAR arrVolume[256]; + char buf[200]; + PMOUNTMGR_TARGET_NAME in = (PMOUNTMGR_TARGET_NAME) buf; + PMOUNTMGR_CREATE_POINT_INPUT point = (PMOUNTMGR_CREATE_POINT_INPUT) buf; + UNICODE_STRING symName, devName; + + TCGetNTNameFromNumber (arrVolume, mount->nDosDriveNo); + in->DeviceNameLength = (USHORT) wcslen (arrVolume) * 2; + wcscpy(in->DeviceName, arrVolume); + + ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, + in, (ULONG) (sizeof (in->DeviceNameLength) + wcslen (arrVolume) * 2), 0, 0); + + memset (buf, 0, sizeof buf); + TCGetDosNameFromNumber ((PWSTR) &point[1], mount->nDosDriveNo); + + point->SymbolicLinkNameOffset = sizeof (MOUNTMGR_CREATE_POINT_INPUT); + point->SymbolicLinkNameLength = (USHORT) wcslen ((PWSTR) &point[1]) * 2; + + RtlInitUnicodeString(&symName, (PWSTR) (buf + point->SymbolicLinkNameOffset)); + + point->DeviceNameOffset = point->SymbolicLinkNameOffset + point->SymbolicLinkNameLength; + TCGetNTNameFromNumber ((PWSTR) (buf + point->DeviceNameOffset), mount->nDosDriveNo); + point->DeviceNameLength = (USHORT) wcslen ((PWSTR) (buf + point->DeviceNameOffset)) * 2; + + RtlInitUnicodeString(&devName, (PWSTR) (buf + point->DeviceNameOffset)); + + ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_CREATE_POINT, point, + point->DeviceNameOffset + point->DeviceNameLength, 0, 0); + + return ntStatus; +} + + +NTSTATUS MountManagerUnmount (int nDosDriveNo) +{ + NTSTATUS ntStatus; + char buf[256], out[300]; + PMOUNTMGR_MOUNT_POINT in = (PMOUNTMGR_MOUNT_POINT) buf; + + memset (buf, 0, sizeof buf); + + TCGetDosNameFromNumber ((PWSTR) &in[1], nDosDriveNo); + + // Only symbolic link can be deleted with IOCTL_MOUNTMGR_DELETE_POINTS. If any other entry is specified, the mount manager will ignore subsequent IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION for the same volume ID. + in->SymbolicLinkNameOffset = sizeof (MOUNTMGR_MOUNT_POINT); + in->SymbolicLinkNameLength = (USHORT) wcslen ((PWCHAR) &in[1]) * 2; + + ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_DELETE_POINTS, + in, sizeof(MOUNTMGR_MOUNT_POINT) + in->SymbolicLinkNameLength, out, sizeof out); + + Dump ("IOCTL_MOUNTMGR_DELETE_POINTS returned 0x%08x\n", ntStatus); + + return ntStatus; +} + + +NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount) +{ + PDEVICE_OBJECT NewDeviceObject; + NTSTATUS ntStatus; + + // Make sure the user is asking for a reasonable nDosDriveNo + if (mount->nDosDriveNo >= 0 && mount->nDosDriveNo <= 25 && IsDriveLetterAvailable (mount->nDosDriveNo)) + { + Dump ("Mount request looks valid\n"); + } + else + { + Dump ("WARNING: MOUNT DRIVE LETTER INVALID\n"); + mount->nReturnCode = ERR_DRIVE_NOT_FOUND; + return ERR_DRIVE_NOT_FOUND; + } + + if (!SelfTestsPassed) + { + mount->nReturnCode = ERR_SELF_TESTS_FAILED; + return ERR_SELF_TESTS_FAILED; + } + + ntStatus = TCCreateDeviceObject (DeviceObject->DriverObject, &NewDeviceObject, mount); + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("Mount CREATE DEVICE ERROR, ntStatus = 0x%08x\n", ntStatus); + return ntStatus; + } + else + { + PEXTENSION NewExtension = (PEXTENSION) NewDeviceObject->DeviceExtension; + SECURITY_SUBJECT_CONTEXT subContext; + PACCESS_TOKEN accessToken; + + SeCaptureSubjectContext (&subContext); + accessToken = SeQuerySubjectContextToken (&subContext); + + if (!accessToken) + { + ntStatus = STATUS_INVALID_PARAMETER; + } + else + { + PTOKEN_USER tokenUser; + + ntStatus = SeQueryInformationToken (accessToken, TokenUser, &tokenUser); + if (NT_SUCCESS (ntStatus)) + { + ULONG sidLength = RtlLengthSid (tokenUser->User.Sid); + + NewExtension->UserSid = TCalloc (sidLength); + if (!NewExtension->UserSid) + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + else + ntStatus = RtlCopySid (sidLength, NewExtension->UserSid, tokenUser->User.Sid); + } + } + + SeReleaseSubjectContext (&subContext); + + if (NT_SUCCESS (ntStatus)) + ntStatus = TCStartVolumeThread (NewDeviceObject, NewExtension, mount); + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("Mount FAILURE NT ERROR, ntStatus = 0x%08x\n", ntStatus); + TCDeleteDeviceObject (NewDeviceObject, NewExtension); + return ntStatus; + } + else + { + if (mount->nReturnCode == 0) + { + HANDLE volumeHandle; + PFILE_OBJECT volumeFileObject; + + Dump ("Mount SUCCESS TC code = 0x%08x READ-ONLY = %d\n", mount->nReturnCode, NewExtension->bReadOnly); + + if (NewExtension->bReadOnly) + NewDeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; + + NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + NewExtension->UniqueVolumeId = LastUniqueVolumeId++; + + if (mount->bMountManager) + MountManagerMount (mount); + + NewExtension->bMountManager = mount->bMountManager; + + // We create symbolic link even if mount manager is notified of + // arriving volume as it apparently sometimes fails to create the link + CreateDriveLink (mount->nDosDriveNo); + + mount->FilesystemDirty = FALSE; + + if (NT_SUCCESS (TCOpenFsVolume (NewExtension, &volumeHandle, &volumeFileObject))) + { + __try + { + ULONG fsStatus; + + if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &fsStatus, sizeof (fsStatus))) + && (fsStatus & VOLUME_IS_DIRTY)) + { + mount->FilesystemDirty = TRUE; + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + mount->FilesystemDirty = TRUE; + } + + + TCCloseFsVolume (volumeHandle, volumeFileObject); + } + } + else + { + Dump ("Mount FAILURE TC code = 0x%08x\n", mount->nReturnCode); + TCDeleteDeviceObject (NewDeviceObject, NewExtension); + } + + return STATUS_SUCCESS; + } + } +} + +NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles) +{ + PEXTENSION extension = deviceObject->DeviceExtension; + NTSTATUS ntStatus; + HANDLE volumeHandle; + PFILE_OBJECT volumeFileObject; + + Dump ("UnmountDevice %d\n", extension->nDosDriveNo); + + ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject); + + if (NT_SUCCESS (ntStatus)) + { + int dismountRetry; + + // Dismounting a writable NTFS filesystem prevents the driver from being unloaded on Windows 7 + if (IsOSAtLeast (WIN_7) && !extension->bReadOnly) + { + NTFS_VOLUME_DATA_BUFFER ntfsData; + + if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof (ntfsData)))) + ReferencedDeviceDeleted = TRUE; + } + + // Lock volume + ntStatus = TCFsctlCall (volumeFileObject, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); + Dump ("FSCTL_LOCK_VOLUME returned %X\n", ntStatus); + + if (!NT_SUCCESS (ntStatus) && !ignoreOpenFiles) + { + TCCloseFsVolume (volumeHandle, volumeFileObject); + return ERR_FILES_OPEN; + } + + // Dismount volume + for (dismountRetry = 0; dismountRetry < 200; ++dismountRetry) + { + ntStatus = TCFsctlCall (volumeFileObject, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); + Dump ("FSCTL_DISMOUNT_VOLUME returned %X\n", ntStatus); + + if (NT_SUCCESS (ntStatus) || ntStatus == STATUS_VOLUME_DISMOUNTED) + break; + + if (!ignoreOpenFiles) + { + TCCloseFsVolume (volumeHandle, volumeFileObject); + return ERR_FILES_OPEN; + } + + TCSleep (100); + } + } + else + { + // Volume cannot be opened => force dismount if allowed + if (!ignoreOpenFiles) + return ERR_FILES_OPEN; + else + volumeHandle = NULL; + } + + if (extension->bMountManager) + MountManagerUnmount (extension->nDosDriveNo); + + // We always remove symbolic link as mount manager might fail to do so + RemoveDriveLink (extension->nDosDriveNo); + + extension->bShuttingDown = TRUE; + + ntStatus = IoAcquireRemoveLock (&extension->Queue.RemoveLock, NULL); + ASSERT (NT_SUCCESS (ntStatus)); + IoReleaseRemoveLockAndWait (&extension->Queue.RemoveLock, NULL); + + if (volumeHandle != NULL) + TCCloseFsVolume (volumeHandle, volumeFileObject); + + if (unmountRequest) + { + PCRYPTO_INFO cryptoInfo = ((PEXTENSION) deviceObject->DeviceExtension)->cryptoInfo; + unmountRequest->HiddenVolumeProtectionTriggered = (cryptoInfo->bProtectHiddenVolume && cryptoInfo->bHiddenVolProtectionAction); + } + + TCDeleteDeviceObject (deviceObject, (PEXTENSION) deviceObject->DeviceExtension); + return 0; +} + +NTSTATUS UnmountAllDevices (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT DeviceObject, BOOL ignoreOpenFiles) +{ + NTSTATUS status = 0; + PDEVICE_OBJECT ListDevice; + + Dump ("Unmounting all volumes\n"); + + if (unmountRequest) + unmountRequest->HiddenVolumeProtectionTriggered = FALSE; + + if (!DeviceObject || !DeviceObject->DriverObject) + return STATUS_INVALID_PARAMETER; + + DriverMutexWait (); + + ListDevice = DeviceObject->DriverObject->DeviceObject; + while (ListDevice != NULL) + { + PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension; + if (!ListExtension->bRootDevice && ListExtension->IsVolumeDevice && !ListExtension->bShuttingDown + && IsVolumeAccessibleByCurrentUser (ListExtension)) + { + PDEVICE_OBJECT nextDevice = ListDevice->NextDevice; + NTSTATUS ntStatus; + + if (unmountRequest) + unmountRequest->nDosDriveNo = ListExtension->nDosDriveNo; + + ntStatus = UnmountDevice (unmountRequest, ListDevice, ignoreOpenFiles); + status = ntStatus == 0 ? status : ntStatus; + + if (unmountRequest && unmountRequest->HiddenVolumeProtectionTriggered) + break; + + ListDevice = nextDevice; + continue; + } + + ListDevice = ListDevice->NextDevice; + } + + DriverMutexRelease (); + return status; +} + +// Resolves symbolic link name to its target name +NTSTATUS SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTargetNameLength) +{ + NTSTATUS ntStatus; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fullFileName; + HANDLE handle; + + RtlInitUnicodeString (&fullFileName, symlinkName); + InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + ntStatus = ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, &objectAttributes); + + if (NT_SUCCESS (ntStatus)) + { + UNICODE_STRING target; + target.Buffer = targetName; + target.Length = 0; + target.MaximumLength = maxTargetNameLength; + memset (targetName, 0, maxTargetNameLength); + + ntStatus = ZwQuerySymbolicLinkObject (handle, &target, NULL); + + ZwClose (handle); + } + + return ntStatus; +} + + +// Checks if two regions overlap (borders are parts of regions) +BOOL RegionsOverlap (unsigned __int64 start1, unsigned __int64 end1, unsigned __int64 start2, unsigned __int64 end2) +{ + return (start1 < start2) ? (end1 >= start2) : (start1 <= end2); +} + + +void GetIntersection (uint64 start1, uint32 length1, uint64 start2, uint64 end2, uint64 *intersectStart, uint32 *intersectLength) +{ + uint64 end1 = start1 + length1 - 1; + uint64 intersectEnd = (end1 <= end2) ? end1 : end2; + + *intersectStart = (start1 >= start2) ? start1 : start2; + *intersectLength = (uint32) ((*intersectStart > intersectEnd) ? 0 : intersectEnd + 1 - *intersectStart); + + if (*intersectLength == 0) + *intersectStart = start1; +} + + +BOOL IsAccessibleByUser (PUNICODE_STRING objectFileName, BOOL readOnly) +{ + OBJECT_ATTRIBUTES fileObjAttributes; + IO_STATUS_BLOCK ioStatusBlock; + HANDLE fileHandle; + NTSTATUS status; + + ASSERT (!IoIsSystemThread (PsGetCurrentThread())); + + InitializeObjectAttributes (&fileObjAttributes, objectFileName, OBJ_CASE_INSENSITIVE | OBJ_FORCE_ACCESS_CHECK, NULL, NULL); + + status = ZwCreateFile (&fileHandle, + readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + &fileObjAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS (status)) + { + ZwClose (fileHandle); + return TRUE; + } + + return FALSE; +} + + +BOOL UserCanAccessDriveDevice () +{ + UNICODE_STRING name; + RtlInitUnicodeString (&name, L"\\Device\\MountPointManager"); + + return IsAccessibleByUser (&name, FALSE); +} + + +BOOL IsDriveLetterAvailable (int nDosDriveNo) +{ + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING objectName; + WCHAR link[128]; + HANDLE handle; + + TCGetDosNameFromNumber (link, nDosDriveNo); + RtlInitUnicodeString (&objectName, link); + InitializeObjectAttributes (&objectAttributes, &objectName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + if (NT_SUCCESS (ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, &objectAttributes))) + { + ZwClose (handle); + return FALSE; + } + + return TRUE; +} + + +NTSTATUS TCCompleteIrp (PIRP irp, NTSTATUS status, ULONG_PTR information) +{ + irp->IoStatus.Status = status; + irp->IoStatus.Information = information; + IoCompleteRequest (irp, IO_NO_INCREMENT); + return status; +} + + +NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information) +{ + irp->IoStatus.Status = status; + irp->IoStatus.Information = information; + IoCompleteRequest (irp, NT_SUCCESS (status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + return status; +} + + +size_t GetCpuCount () +{ + KAFFINITY activeCpuMap = KeQueryActiveProcessors(); + size_t mapSize = sizeof (activeCpuMap) * 8; + size_t cpuCount = 0; + + while (mapSize--) + { + if (activeCpuMap & 1) + ++cpuCount; + + activeCpuMap >>= 1; + } + + if (cpuCount == 0) + return 1; + + return cpuCount; +} + + +void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes) +{ + ASSERT ((maxSizeInBytes & 1) == 0); + str[maxSizeInBytes / sizeof (wchar_t) - 1] = 0; +} + + +void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout) +{ + LARGE_INTEGER waitInterval; + waitInterval.QuadPart = retryDelay * -10000; + + ASSERT (KeGetCurrentIrql() <= APC_LEVEL); + ASSERT (retryDelay > 0 && retryDelay <= timeout); + + while (TRUE) + { + void *memory = TCalloc (size); + if (memory) + return memory; + + timeout -= retryDelay; + if (timeout <= 0) + break; + + KeDelayExecutionThread (KernelMode, FALSE, &waitInterval); + } + + return NULL; +} + + +NTSTATUS TCReadRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, PKEY_VALUE_PARTIAL_INFORMATION *keyData) +{ + OBJECT_ATTRIBUTES regObjAttribs; + HANDLE regKeyHandle; + NTSTATUS status; + UNICODE_STRING valName; + ULONG size = 0; + ULONG resultSize; + + InitializeObjectAttributes (®ObjAttribs, keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenKey (®KeyHandle, KEY_READ, ®ObjAttribs); + if (!NT_SUCCESS (status)) + return status; + + RtlInitUnicodeString (&valName, keyValueName); + status = ZwQueryValueKey (regKeyHandle, &valName, KeyValuePartialInformation, NULL, 0, &size); + + if (!NT_SUCCESS (status) && status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) + { + ZwClose (regKeyHandle); + return status; + } + + if (size == 0) + { + ZwClose (regKeyHandle); + return STATUS_NO_DATA_DETECTED; + } + + *keyData = (PKEY_VALUE_PARTIAL_INFORMATION) TCalloc (size); + if (!*keyData) + { + ZwClose (regKeyHandle); + return STATUS_INSUFFICIENT_RESOURCES; + } + + status = ZwQueryValueKey (regKeyHandle, &valName, KeyValuePartialInformation, *keyData, size, &resultSize); + + ZwClose (regKeyHandle); + return status; +} + + +NTSTATUS TCWriteRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, ULONG keyValueType, void *valueData, ULONG valueSize) +{ + OBJECT_ATTRIBUTES regObjAttribs; + HANDLE regKeyHandle; + NTSTATUS status; + UNICODE_STRING valName; + + InitializeObjectAttributes (®ObjAttribs, keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenKey (®KeyHandle, KEY_READ | KEY_WRITE, ®ObjAttribs); + if (!NT_SUCCESS (status)) + return status; + + RtlInitUnicodeString (&valName, keyValueName); + + status = ZwSetValueKey (regKeyHandle, &valName, keyValueType, keyValueType, valueData, valueSize); + + ZwClose (regKeyHandle); + return status; +} + + +BOOL IsVolumeClassFilterRegistered () +{ + UNICODE_STRING name; + NTSTATUS status; + BOOL registered = FALSE; + + PKEY_VALUE_PARTIAL_INFORMATION data; + + RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{71A27CDD-812A-11D0-BEC7-08002BE2092F}"); + status = TCReadRegistryKey (&name, L"UpperFilters", &data); + + if (NT_SUCCESS (status)) + { + if (data->Type == REG_MULTI_SZ && data->DataLength >= 9 * sizeof (wchar_t)) + { + // Search for the string "truecrypt" + ULONG i; + for (i = 0; i <= data->DataLength - 9 * sizeof (wchar_t); ++i) + { + if (memcmp (data->Data + i, L"truecrypt", 9 * sizeof (wchar_t)) == 0) + { + Dump ("Volume class filter active\n"); + registered = TRUE; + break; + } + } + } + + TCfree (data); + } + + return registered; +} + + +uint32 ReadRegistryConfigFlags () +{ + PKEY_VALUE_PARTIAL_INFORMATION data; + UNICODE_STRING name; + NTSTATUS status; + uint32 flags = 0; + + RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\truecrypt"); + status = TCReadRegistryKey (&name, TC_DRIVER_CONFIG_REG_VALUE_NAME, &data); + + if (NT_SUCCESS (status)) + { + if (data->Type == REG_DWORD) + { + flags = *(uint32 *) data->Data; + Dump ("Configuration flags = 0x%x\n", flags); + + if (flags & (TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD | TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES)) + CacheBootPassword = TRUE; + + if (flags & TC_DRIVER_CONFIG_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS) + NonAdminSystemFavoritesAccessDisabled = TRUE; + } + + TCfree (data); + } + + return flags; +} + + +NTSTATUS WriteRegistryConfigFlags (uint32 flags) +{ + UNICODE_STRING name; + RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\truecrypt"); + + return TCWriteRegistryKey (&name, TC_DRIVER_CONFIG_REG_VALUE_NAME, REG_DWORD, &flags, sizeof (flags)); +} + + +NTSTATUS GetDeviceSectorSize (PDEVICE_OBJECT deviceObject, ULONG *bytesPerSector) +{ + NTSTATUS status; + DISK_GEOMETRY geometry; + + status = SendDeviceIoControlRequest (deviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geometry, sizeof (geometry)); + + if (!NT_SUCCESS (status)) + return status; + + *bytesPerSector = geometry.BytesPerSector; + return STATUS_SUCCESS; +} + + +NTSTATUS ZeroUnreadableSectors (PDEVICE_OBJECT deviceObject, LARGE_INTEGER startOffset, ULONG size, uint64 *zeroedSectorCount) +{ + NTSTATUS status; + ULONG sectorSize; + ULONG sectorCount; + byte *sectorBuffer = NULL; + + *zeroedSectorCount = 0; + + status = GetDeviceSectorSize (deviceObject, §orSize); + if (!NT_SUCCESS (status)) + return status; + + sectorBuffer = TCalloc (sectorSize); + if (!sectorBuffer) + return STATUS_INSUFFICIENT_RESOURCES; + + for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount, startOffset.QuadPart += sectorSize) + { + status = TCReadDevice (deviceObject, sectorBuffer, startOffset, sectorSize); + if (!NT_SUCCESS (status)) + { + Dump ("Zeroing sector at %I64d\n", startOffset.QuadPart); + memset (sectorBuffer, 0, sectorSize); + + status = TCWriteDevice (deviceObject, sectorBuffer, startOffset, sectorSize); + if (!NT_SUCCESS (status)) + goto err; + + ++(*zeroedSectorCount); + } + } + + status = STATUS_SUCCESS; + +err: + if (sectorBuffer) + TCfree (sectorBuffer); + + return status; +} + + +NTSTATUS ReadDeviceSkipUnreadableSectors (PDEVICE_OBJECT deviceObject, byte *buffer, LARGE_INTEGER startOffset, ULONG size, uint64 *badSectorCount) +{ + NTSTATUS status; + ULONG sectorSize; + ULONG sectorCount; + + *badSectorCount = 0; + + status = GetDeviceSectorSize (deviceObject, §orSize); + if (!NT_SUCCESS (status)) + return status; + + for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount, startOffset.QuadPart += sectorSize, buffer += sectorSize) + { + status = TCReadDevice (deviceObject, buffer, startOffset, sectorSize); + if (!NT_SUCCESS (status)) + { + Dump ("Skipping bad sector at %I64d\n", startOffset.QuadPart); + memset (buffer, 0, sectorSize); + ++(*badSectorCount); + } + } + + return STATUS_SUCCESS; +} + + +BOOL IsVolumeAccessibleByCurrentUser (PEXTENSION volumeDeviceExtension) +{ + SECURITY_SUBJECT_CONTEXT subContext; + PACCESS_TOKEN accessToken; + PTOKEN_USER tokenUser; + BOOL result = FALSE; + + if (IoIsSystemThread (PsGetCurrentThread()) + || UserCanAccessDriveDevice() + || !volumeDeviceExtension->UserSid + || (volumeDeviceExtension->SystemFavorite && !NonAdminSystemFavoritesAccessDisabled)) + { + return TRUE; + } + + SeCaptureSubjectContext (&subContext); + accessToken = SeQuerySubjectContextToken (&subContext); + + if (!accessToken) + goto ret; + + if (SeTokenIsAdmin (accessToken)) + { + result = TRUE; + goto ret; + } + + if (!NT_SUCCESS (SeQueryInformationToken (accessToken, TokenUser, &tokenUser))) + goto ret; + + result = RtlEqualSid (volumeDeviceExtension->UserSid, tokenUser->User.Sid); + +ret: + SeReleaseSubjectContext (&subContext); + return result; +} + + +void GetElapsedTimeInit (LARGE_INTEGER *lastPerfCounter) +{ + *lastPerfCounter = KeQueryPerformanceCounter (NULL); +} + + +// Returns elapsed time in microseconds since last call +int64 GetElapsedTime (LARGE_INTEGER *lastPerfCounter) +{ + LARGE_INTEGER freq; + LARGE_INTEGER counter = KeQueryPerformanceCounter (&freq); + + int64 elapsed = (counter.QuadPart - lastPerfCounter->QuadPart) * 1000000LL / freq.QuadPart; + *lastPerfCounter = counter; + + return elapsed; +} + + +BOOL IsOSAtLeast (OSVersionEnum reqMinOS) +{ + /* When updating this function, update IsOSVersionAtLeast() in Dlgcode.c too. */ + + ULONG major = 0, minor = 0; + + ASSERT (OsMajorVersion != 0); + + switch (reqMinOS) + { + case WIN_2000: major = 5; minor = 0; break; + case WIN_XP: major = 5; minor = 1; break; + case WIN_SERVER_2003: major = 5; minor = 2; break; + case WIN_VISTA: major = 6; minor = 0; break; + case WIN_7: major = 6; minor = 1; break; + + default: + TC_THROW_FATAL_EXCEPTION; + break; + } + + return ((OsMajorVersion << 16 | OsMinorVersion << 8) + >= (major << 16 | minor << 8)); +} diff --git a/Driver/NTDRIVER.H b/Driver/NTDRIVER.H index fa6989a..41551d6 100644 --- a/Driver/NTDRIVER.H +++ b/Driver/NTDRIVER.H @@ -1,171 +1,176 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifndef TC_HEADER_NTDRIVER -#define TC_HEADER_NTDRIVER - -#include "EncryptedIoQueue.h" - -/* This structure is used to start new threads */ -typedef struct _THREAD_BLOCK_ -{ - PDEVICE_OBJECT DeviceObject; - NTSTATUS ntCreateStatus; - WCHAR wszMountVolume[TC_MAX_PATH + 8]; - MOUNT_STRUCT *mount; -} THREAD_BLOCK, *PTHREAD_BLOCK; - - -/* This structure is allocated for non-root devices! WARNING: bRootDevice - must be the first member of the structure! */ -typedef struct EXTENSION -{ - BOOL bRootDevice; /* Is this the root device ? which the user-mode apps talk to */ - BOOL IsVolumeDevice; - BOOL IsDriveFilterDevice; - BOOL IsVolumeFilterDevice; - - ULONG lMagicNumber; /* To ensure the completion routine is not sending us bad IRP's */ - - int UniqueVolumeId; - int nDosDriveNo; /* Drive number this extension is mounted against */ - - BOOL bShuttingDown; /* Is the driver shutting down ? */ - BOOL bThreadShouldQuit; /* Instruct per device worker thread to quit */ - PETHREAD peThread; /* Thread handle */ - KEVENT keCreateEvent; /* Device creation event */ - KSPIN_LOCK ListSpinLock; /* IRP spinlock */ - LIST_ENTRY ListEntry; /* IRP listentry */ - KSEMAPHORE RequestSemaphore; /* IRP list request Semaphore */ - - HANDLE hDeviceFile; /* Device handle for this device */ - PFILE_OBJECT pfoDeviceFile; /* Device fileobject for this device */ - PDEVICE_OBJECT pFsdDevice; /* lower level device handle */ - - CRYPTO_INFO *cryptoInfo; /* Cryptographic and other information for this device */ - - __int64 HostLength; - __int64 DiskLength; /* The length of the disk referred to by this device */ - __int64 NumberOfCylinders; /* Partition info */ - ULONG TracksPerCylinder; /* Partition info */ - ULONG SectorsPerTrack; /* Partition info */ - ULONG BytesPerSector; /* Partition info */ - UCHAR PartitionType; /* Partition info */ - - int HostBytesPerSector; - - KEVENT keVolumeEvent; /* Event structure used when setting up a device */ - - EncryptedIoQueue Queue; - - BOOL bReadOnly; /* Is this device read-only ? */ - BOOL bRemovable; /* Is this device removable media ? */ - BOOL bRawDevice; /* Is this a raw-partition or raw-floppy device ? */ - BOOL bMountManager; /* Mount manager knows about volume */ - - WCHAR wszVolume[TC_MAX_PATH]; /* DONT change this size without also changing MOUNT_LIST_STRUCT! */ - - // Container file date/time (used to reset date and time of file-hosted volumes after dismount or unsuccessful mount attempt, to preserve plausible deniability of hidden volumes). - LARGE_INTEGER fileCreationTime; - LARGE_INTEGER fileLastAccessTime; - LARGE_INTEGER fileLastWriteTime; - LARGE_INTEGER fileLastChangeTime; - BOOL bTimeStampValid; - - PSID UserSid; - BOOL SecurityClientContextValid; - SECURITY_CLIENT_CONTEXT SecurityClientContext; - -} EXTENSION, *PEXTENSION; - - -typedef enum -{ - ValidateInput, - ValidateOutput, - ValidateInputOutput -} ValidateIOBufferSizeType; - - -extern PDRIVER_OBJECT TCDriverObject; -extern BOOL DriverShuttingDown; -extern ULONG OsMajorVersion; -extern ULONG OsMinorVersion; -extern BOOL VolumeClassFilterRegistered; -extern BOOL CacheBootPassword; - -/* Helper macro returning x seconds in units of 100 nanoseconds */ -#define WAIT_SECONDS(x) ((x)*10000000) - -NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); -NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo); -void DumpMemory (void *memory, int size); -BOOL IsAccessibleByUser (PUNICODE_STRING objectFileName, BOOL readOnly); -NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp); -NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp); -NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize); -NTSTATUS TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp); -NTSTATUS TCCreateRootDeviceObject (PDRIVER_OBJECT DriverObject); -NTSTATUS TCCreateDeviceObject (PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * ppDeviceObject, MOUNT_STRUCT * mount); -NTSTATUS TCReadDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length); -NTSTATUS TCWriteDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length); -NTSTATUS TCStartThread (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread); -NTSTATUS TCStartThreadInProcess (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread, PEPROCESS process); -NTSTATUS TCStartVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, MOUNT_STRUCT * mount); -void TCStopThread (PKTHREAD kThread, PKEVENT wakeUpEvent); -void TCStopVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension); -VOID VolumeThreadProc (PVOID Context); -void TCSleep (int milliSeconds); -void TCGetNTNameFromNumber (LPWSTR ntname, int nDriveNo); -void TCGetDosNameFromNumber (LPWSTR dosname, int nDriveNo); -LPWSTR TCTranslateCode (ULONG ulCode); -PDEVICE_OBJECT TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension); -VOID TCUnloadDriver (PDRIVER_OBJECT DriverObject); -NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize); -NTSTATUS TCOpenFsVolume (PEXTENSION Extension, PHANDLE volumeHandle, PFILE_OBJECT * fileObject); -void TCCloseFsVolume (HANDLE volumeHandle, PFILE_OBJECT fileObject); -NTSTATUS TCFsctlCall (PFILE_OBJECT fileObject, LONG IoControlCode, void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize); -NTSTATUS CreateDriveLink (int nDosDriveNo); -NTSTATUS RemoveDriveLink (int nDosDriveNo); -NTSTATUS MountManagerMount (MOUNT_STRUCT *mount); -NTSTATUS MountManagerUnmount (int nDosDriveNo); -NTSTATUS MountDevice (PDEVICE_OBJECT deviceObject, MOUNT_STRUCT *mount); -NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles); -NTSTATUS UnmountAllDevices (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT DeviceObject, BOOL ignoreOpenFiles); -NTSTATUS SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTargetNameLength); -void DriverMutexWait (); -void DriverMutexRelease (); -BOOL RegionsOverlap (unsigned __int64 start1, unsigned __int64 end1, unsigned __int64 start2, unsigned __int64 end2); -void GetIntersection (uint64 start1, uint32 length1, uint64 start2, uint64 end2, uint64 *intersectStart, uint32 *intersectLength); -NTSTATUS TCCompleteIrp (PIRP irp, NTSTATUS status, ULONG_PTR information); -NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information); -NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *driveSize); -BOOL UserCanAccessDriveDevice (); -size_t GetCpuCount (); -void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes); -void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout); -BOOL IsDriveLetterAvailable (int nDosDriveNo); -NTSTATUS TCReadRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, PKEY_VALUE_PARTIAL_INFORMATION *keyData); -NTSTATUS TCWriteRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, ULONG keyValueType, void *valueData, ULONG valueSize); -BOOL IsVolumeClassFilterRegistered (); -uint32 ReadRegistryConfigFlags (); -NTSTATUS WriteRegistryConfigFlags (uint32 flags); -BOOL ValidateIOBufferSize (PIRP irp, size_t requiredBufferSize, ValidateIOBufferSizeType type); -NTSTATUS GetDeviceSectorSize (PDEVICE_OBJECT deviceObject, ULONG *bytesPerSector); -NTSTATUS ZeroUnreadableSectors (PDEVICE_OBJECT deviceObject, LARGE_INTEGER startOffset, ULONG size, uint64 *zeroedSectorCount); -NTSTATUS ReadDeviceSkipUnreadableSectors (PDEVICE_OBJECT deviceObject, byte *buffer, LARGE_INTEGER startOffset, ULONG size, uint64 *badSectorCount); -BOOL IsVolumeAccessibleByCurrentUser (PEXTENSION volumeDeviceExtension); -void GetElapsedTimeInit (LARGE_INTEGER *lastPerfCounter); -int64 GetElapsedTime (LARGE_INTEGER *lastPerfCounter); - -#define TC_BUG_CHECK(status) KeBugCheckEx (SECURITY_SYSTEM, __LINE__, status, 0, 'TC') - -#endif // TC_HEADER_NTDRIVER +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_NTDRIVER +#define TC_HEADER_NTDRIVER + +#include "Common.h" +#include "EncryptedIoQueue.h" + +/* This structure is used to start new threads */ +typedef struct _THREAD_BLOCK_ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS ntCreateStatus; + WCHAR wszMountVolume[TC_MAX_PATH + 8]; + MOUNT_STRUCT *mount; +} THREAD_BLOCK, *PTHREAD_BLOCK; + + +/* This structure is allocated for non-root devices! WARNING: bRootDevice + must be the first member of the structure! */ +typedef struct EXTENSION +{ + BOOL bRootDevice; /* Is this the root device ? which the user-mode apps talk to */ + BOOL IsVolumeDevice; + BOOL IsDriveFilterDevice; + BOOL IsVolumeFilterDevice; + + ULONG lMagicNumber; /* To ensure the completion routine is not sending us bad IRP's */ + + int UniqueVolumeId; + int nDosDriveNo; /* Drive number this extension is mounted against */ + + BOOL bShuttingDown; /* Is the driver shutting down ? */ + BOOL bThreadShouldQuit; /* Instruct per device worker thread to quit */ + PETHREAD peThread; /* Thread handle */ + KEVENT keCreateEvent; /* Device creation event */ + KSPIN_LOCK ListSpinLock; /* IRP spinlock */ + LIST_ENTRY ListEntry; /* IRP listentry */ + KSEMAPHORE RequestSemaphore; /* IRP list request Semaphore */ + + HANDLE hDeviceFile; /* Device handle for this device */ + PFILE_OBJECT pfoDeviceFile; /* Device fileobject for this device */ + PDEVICE_OBJECT pFsdDevice; /* lower level device handle */ + + CRYPTO_INFO *cryptoInfo; /* Cryptographic and other information for this device */ + + __int64 HostLength; + __int64 DiskLength; /* The length of the disk referred to by this device */ + __int64 NumberOfCylinders; /* Partition info */ + ULONG TracksPerCylinder; /* Partition info */ + ULONG SectorsPerTrack; /* Partition info */ + ULONG BytesPerSector; /* Partition info */ + UCHAR PartitionType; /* Partition info */ + + int HostBytesPerSector; + + KEVENT keVolumeEvent; /* Event structure used when setting up a device */ + + EncryptedIoQueue Queue; + + BOOL bReadOnly; /* Is this device read-only ? */ + BOOL bRemovable; /* Is this device removable media ? */ + BOOL PartitionInInactiveSysEncScope; + BOOL bRawDevice; /* Is this a raw-partition or raw-floppy device ? */ + BOOL bMountManager; /* Mount manager knows about volume */ + BOOL SystemFavorite; + + WCHAR wszVolume[TC_MAX_PATH]; /* DONT change this size without also changing MOUNT_LIST_STRUCT! */ + + // Container file date/time (used to reset date and time of file-hosted volumes after dismount or unsuccessful mount attempt, to preserve plausible deniability of hidden volumes). + LARGE_INTEGER fileCreationTime; + LARGE_INTEGER fileLastAccessTime; + LARGE_INTEGER fileLastWriteTime; + LARGE_INTEGER fileLastChangeTime; + BOOL bTimeStampValid; + + PSID UserSid; + BOOL SecurityClientContextValid; + SECURITY_CLIENT_CONTEXT SecurityClientContext; + +} EXTENSION, *PEXTENSION; + + +typedef enum +{ + ValidateInput, + ValidateOutput, + ValidateInputOutput +} ValidateIOBufferSizeType; + + +extern PDRIVER_OBJECT TCDriverObject; +extern BOOL DriverShuttingDown; +extern ULONG OsMajorVersion; +extern ULONG OsMinorVersion; +extern BOOL VolumeClassFilterRegistered; +extern BOOL CacheBootPassword; + +/* Helper macro returning x seconds in units of 100 nanoseconds */ +#define WAIT_SECONDS(x) ((x)*10000000) + +NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); +NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo); +void DumpMemory (void *memory, int size); +BOOL IsAccessibleByUser (PUNICODE_STRING objectFileName, BOOL readOnly); +NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp); +NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp); +NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize); +NTSTATUS TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS TCCreateRootDeviceObject (PDRIVER_OBJECT DriverObject); +NTSTATUS TCCreateDeviceObject (PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * ppDeviceObject, MOUNT_STRUCT * mount); +NTSTATUS TCReadDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length); +NTSTATUS TCWriteDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length); +NTSTATUS TCStartThread (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread); +NTSTATUS TCStartThreadInProcess (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread, PEPROCESS process); +NTSTATUS TCStartVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, MOUNT_STRUCT * mount); +void TCStopThread (PKTHREAD kThread, PKEVENT wakeUpEvent); +void TCStopVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension); +VOID VolumeThreadProc (PVOID Context); +void TCSleep (int milliSeconds); +void TCGetNTNameFromNumber (LPWSTR ntname, int nDriveNo); +void TCGetDosNameFromNumber (LPWSTR dosname, int nDriveNo); +LPWSTR TCTranslateCode (ULONG ulCode); +PDEVICE_OBJECT TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension); +VOID TCUnloadDriver (PDRIVER_OBJECT DriverObject); +NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize); +NTSTATUS TCOpenFsVolume (PEXTENSION Extension, PHANDLE volumeHandle, PFILE_OBJECT * fileObject); +void TCCloseFsVolume (HANDLE volumeHandle, PFILE_OBJECT fileObject); +NTSTATUS TCFsctlCall (PFILE_OBJECT fileObject, LONG IoControlCode, void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize); +NTSTATUS CreateDriveLink (int nDosDriveNo); +NTSTATUS RemoveDriveLink (int nDosDriveNo); +NTSTATUS MountManagerMount (MOUNT_STRUCT *mount); +NTSTATUS MountManagerUnmount (int nDosDriveNo); +NTSTATUS MountDevice (PDEVICE_OBJECT deviceObject, MOUNT_STRUCT *mount); +NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles); +NTSTATUS UnmountAllDevices (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT DeviceObject, BOOL ignoreOpenFiles); +NTSTATUS SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTargetNameLength); +void DriverMutexWait (); +BOOL DriverMutexAcquireNoWait (); +void DriverMutexRelease (); +BOOL RegionsOverlap (unsigned __int64 start1, unsigned __int64 end1, unsigned __int64 start2, unsigned __int64 end2); +void GetIntersection (uint64 start1, uint32 length1, uint64 start2, uint64 end2, uint64 *intersectStart, uint32 *intersectLength); +NTSTATUS TCCompleteIrp (PIRP irp, NTSTATUS status, ULONG_PTR information); +NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information); +NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *driveSize); +BOOL UserCanAccessDriveDevice (); +size_t GetCpuCount (); +void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes); +void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout); +BOOL IsDriveLetterAvailable (int nDosDriveNo); +NTSTATUS TCReadRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, PKEY_VALUE_PARTIAL_INFORMATION *keyData); +NTSTATUS TCWriteRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, ULONG keyValueType, void *valueData, ULONG valueSize); +BOOL IsVolumeClassFilterRegistered (); +uint32 ReadRegistryConfigFlags (); +NTSTATUS WriteRegistryConfigFlags (uint32 flags); +BOOL ValidateIOBufferSize (PIRP irp, size_t requiredBufferSize, ValidateIOBufferSizeType type); +NTSTATUS GetDeviceSectorSize (PDEVICE_OBJECT deviceObject, ULONG *bytesPerSector); +NTSTATUS ZeroUnreadableSectors (PDEVICE_OBJECT deviceObject, LARGE_INTEGER startOffset, ULONG size, uint64 *zeroedSectorCount); +NTSTATUS ReadDeviceSkipUnreadableSectors (PDEVICE_OBJECT deviceObject, byte *buffer, LARGE_INTEGER startOffset, ULONG size, uint64 *badSectorCount); +BOOL IsVolumeAccessibleByCurrentUser (PEXTENSION volumeDeviceExtension); +void GetElapsedTimeInit (LARGE_INTEGER *lastPerfCounter); +int64 GetElapsedTime (LARGE_INTEGER *lastPerfCounter); +BOOL IsOSAtLeast (OSVersionEnum reqMinOS); + +#define TC_BUG_CHECK(status) KeBugCheckEx (SECURITY_SYSTEM, __LINE__, (ULONG_PTR) status, 0, 'TC') + +#endif // TC_HEADER_NTDRIVER diff --git a/Driver/NTVOL.C b/Driver/NTVOL.C index 353bdaf..c6e0935 100644 --- a/Driver/NTVOL.C +++ b/Driver/NTVOL.C @@ -1,839 +1,839 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "TCdefs.h" -#include -#include "Crypto.h" -#include "Volumes.h" - -#include "Apidrvr.h" -#include "DriveFilter.h" -#include "Ntdriver.h" -#include "Ntvol.h" -#include "VolumeFilter.h" - -#include "Boot/Windows/BootCommon.h" - -#include "Cache.h" - -#if 0 && _DEBUG -#define EXTRA_INFO 1 -#endif - -#pragma warning( disable : 4127 ) - -volatile BOOL ProbingHostDeviceForWrite = FALSE; - - -NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, - PEXTENSION Extension, - MOUNT_STRUCT *mount, - PWSTR pwszMountVolume, - BOOL bRawDevice) -{ - FILE_STANDARD_INFORMATION FileStandardInfo; - FILE_BASIC_INFORMATION FileBasicInfo; - OBJECT_ATTRIBUTES oaFileAttributes; - UNICODE_STRING FullFileName; - IO_STATUS_BLOCK IoStatusBlock; - PCRYPTO_INFO cryptoInfoPtr = NULL; - PCRYPTO_INFO tmpCryptoInfo = NULL; - LARGE_INTEGER lDiskLength; - __int64 partitionStartingOffset = 0; - int volumeType; - char *readBuffer = 0; - NTSTATUS ntStatus = 0; - BOOL forceAccessCheck = (!bRawDevice && !(OsMajorVersion == 5 &&OsMinorVersion == 0)); // Windows 2000 does not support OBJ_FORCE_ACCESS_CHECK attribute - - Extension->pfoDeviceFile = NULL; - Extension->hDeviceFile = NULL; - Extension->bTimeStampValid = FALSE; - - RtlInitUnicodeString (&FullFileName, pwszMountVolume); - InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0), NULL, NULL); - KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE); - - if (Extension->SecurityClientContextValid) - { - ntStatus = SeImpersonateClientEx (&Extension->SecurityClientContext, NULL); - if (!NT_SUCCESS (ntStatus)) - goto error; - } - - mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = FALSE; - - // If we are opening a device, query its size first - if (bRawDevice) - { - PARTITION_INFORMATION pi; - PARTITION_INFORMATION_EX pix; - LARGE_INTEGER diskLengthInfo; - DISK_GEOMETRY dg; - - ntStatus = IoGetDeviceObjectPointer (&FullFileName, - FILE_READ_DATA, - &Extension->pfoDeviceFile, - &Extension->pFsdDevice); - - if (!NT_SUCCESS (ntStatus)) - goto error; - - if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg)))) - { - lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector; - mount->BytesPerSector = dg.BytesPerSector; - } - else - lDiskLength.QuadPart = 0; - - // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails - if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix)))) - { - lDiskLength.QuadPart = pix.PartitionLength.QuadPart; - partitionStartingOffset = pix.StartingOffset.QuadPart; - } - // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX - else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi)))) - { - lDiskLength.QuadPart = pi.PartitionLength.QuadPart; - partitionStartingOffset = pi.StartingOffset.QuadPart; - } - else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_LENGTH_INFO, &diskLengthInfo, sizeof (diskLengthInfo)))) - { - lDiskLength = diskLengthInfo; - } - - ProbingHostDeviceForWrite = TRUE; - - if (!mount->bMountReadOnly - && TCSendHostDeviceIoControlRequest (DeviceObject, Extension, - IsHiddenSystemRunning() ? TC_IOCTL_DISK_IS_WRITABLE : IOCTL_DISK_IS_WRITABLE, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED) - { - mount->bMountReadOnly = TRUE; - DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; - mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = TRUE; - } - - ProbingHostDeviceForWrite = FALSE; - } - - if (mount->BytesPerSector == 0) - mount->BytesPerSector = SECTOR_SIZE; - - Extension->HostBytesPerSector = mount->BytesPerSector; - - // Open the volume hosting file/device - if (!mount->bMountReadOnly) - { - ntStatus = ZwCreateFile (&Extension->hDeviceFile, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &oaFileAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL | - FILE_ATTRIBUTE_SYSTEM, - mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN, - FILE_RANDOM_ACCESS | - FILE_WRITE_THROUGH | - (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - } - - /* 26-4-99 NT for some partitions returns this code, it is really a access denied */ - if (ntStatus == 0xc000001b) - ntStatus = STATUS_ACCESS_DENIED; - - mount->VolumeMountedReadOnlyAfterAccessDenied = FALSE; - - if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED) - { - ntStatus = ZwCreateFile (&Extension->hDeviceFile, - GENERIC_READ | SYNCHRONIZE, - &oaFileAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL | - FILE_ATTRIBUTE_SYSTEM, - mount->bExclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN, - FILE_RANDOM_ACCESS | - FILE_WRITE_THROUGH | - (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - - if (NT_SUCCESS (ntStatus) && !mount->bMountReadOnly) - mount->VolumeMountedReadOnlyAfterAccessDenied = TRUE; - - Extension->bReadOnly = TRUE; - DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; - } - else - Extension->bReadOnly = FALSE; - - /* 26-4-99 NT for some partitions returns this code, it is really a - access denied */ - if (ntStatus == 0xc000001b) - { - /* Partitions which return this code can still be opened with - FILE_SHARE_READ but this causes NT problems elsewhere in - particular if you do FILE_SHARE_READ NT will die later if - anyone even tries to open the partition (or file for that - matter...) */ - ntStatus = STATUS_SHARING_VIOLATION; - } - - if (!NT_SUCCESS (ntStatus)) - { - goto error; - } - - // If we have opened a file, query its size now - if (bRawDevice == FALSE) - { - ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, - &IoStatusBlock, - &FileBasicInfo, - sizeof (FileBasicInfo), - FileBasicInformation); - - if (NT_SUCCESS (ntStatus)) - { - if (mount->bPreserveTimestamp) - { - /* Remember the container timestamp. (Used to reset access/modification file date/time - of file-hosted volumes upon dismount or after unsuccessful mount attempt to preserve - plausible deniability of hidden volumes.) */ - Extension->fileCreationTime = FileBasicInfo.CreationTime; - Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime; - Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime; - Extension->fileLastChangeTime = FileBasicInfo.ChangeTime; - Extension->bTimeStampValid = TRUE; - } - - ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, - &IoStatusBlock, - &FileStandardInfo, - sizeof (FileStandardInfo), - FileStandardInformation); - } - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n", - ntStatus); - goto error; - } - - lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart; - - if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED) - { - Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume); - mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED; - ntStatus = STATUS_SUCCESS; - goto error; - } - - ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile, - FILE_ALL_ACCESS, - *IoFileObjectType, - KernelMode, - &Extension->pfoDeviceFile, - 0); - - if (!NT_SUCCESS (ntStatus)) - { - goto error; - } - - /* Get the FSD device for the file (probably either NTFS or FAT) */ - Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile); - } - else - { - // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, - // the NTFS driver guards hidden sectors and prevents mounting using a backup header e.g. after the user - // accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS). - - PFILE_OBJECT pfoTmpDeviceFile = NULL; - - if (NT_SUCCESS (ObReferenceObjectByHandle (Extension->hDeviceFile, FILE_ALL_ACCESS, *IoFileObjectType, KernelMode, &pfoTmpDeviceFile, NULL)) - && pfoTmpDeviceFile != NULL) - { - TCFsctlCall (pfoTmpDeviceFile, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0); - ObDereferenceObject (pfoTmpDeviceFile); - } - } - - // Check volume size - if (lDiskLength.QuadPart < TC_MIN_VOLUME_SIZE_LEGACY || lDiskLength.QuadPart > TC_MAX_VOLUME_SIZE) - { - mount->nReturnCode = ERR_VOL_SIZE_WRONG; - ntStatus = STATUS_SUCCESS; - goto error; - } - - Extension->DiskLength = lDiskLength.QuadPart; - Extension->HostLength = lDiskLength.QuadPart; - - readBuffer = TCalloc (max (TC_VOLUME_HEADER_EFFECTIVE_SIZE, PAGE_SIZE)); - if (readBuffer == NULL) - { - ntStatus = STATUS_INSUFFICIENT_RESOURCES; - goto error; - } - - // Go through all volume types (e.g., normal, hidden) - for (volumeType = TC_VOLUME_TYPE_NORMAL; - volumeType < TC_VOLUME_TYPE_COUNT; - volumeType++) - { - Dump ("Trying to open volume type %d\n", volumeType); - - if (mount->bPartitionInInactiveSysEncScope - && volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) - continue; - - /* Read the volume header */ - - if (!mount->bPartitionInInactiveSysEncScope - || (mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_HIDDEN)) - { - // Header of a volume that is not within the scope of system encryption, or - // header of a system hidden volume (containing a hidden OS) - - LARGE_INTEGER headerOffset; - - if (mount->UseBackupHeader && lDiskLength.QuadPart <= TC_TOTAL_VOLUME_HEADERS_SIZE) - continue; - - switch (volumeType) - { - case TC_VOLUME_TYPE_NORMAL: - headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; - break; - - case TC_VOLUME_TYPE_HIDDEN: - if (lDiskLength.QuadPart <= TC_VOLUME_HEADER_GROUP_SIZE) - continue; - - headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_HIDDEN_VOLUME_HEADER_OFFSET; - break; - - case TC_VOLUME_TYPE_HIDDEN_LEGACY: - if (mount->UseBackupHeader) - continue; - - headerOffset.QuadPart = lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; - break; - } - - Dump ("Reading volume header at %I64d\n", headerOffset.QuadPart); - - ntStatus = ZwReadFile (Extension->hDeviceFile, - NULL, - NULL, - NULL, - &IoStatusBlock, - readBuffer, - TC_VOLUME_HEADER_EFFECTIVE_SIZE, - &headerOffset, - NULL); - } - else - { - // Header of a partition that is within the scope of system encryption - - WCHAR parentDrivePath [47+1] = {0}; - HANDLE hParentDeviceFile = NULL; - UNICODE_STRING FullParentPath; - OBJECT_ATTRIBUTES oaParentFileAttributes; - LARGE_INTEGER parentKeyDataOffset; - - _snwprintf (parentDrivePath, - sizeof (parentDrivePath) / sizeof (WCHAR) - 1, - WIDE ("\\Device\\Harddisk%d\\Partition0"), - mount->nPartitionInInactiveSysEncScopeDriveNo); - - Dump ("Mounting partition within scope of system encryption (reading key data from: %ls)\n", parentDrivePath); - - RtlInitUnicodeString (&FullParentPath, parentDrivePath); - InitializeObjectAttributes (&oaParentFileAttributes, &FullParentPath, OBJ_CASE_INSENSITIVE, NULL, NULL); - - ntStatus = ZwCreateFile (&hParentDeviceFile, - GENERIC_READ | SYNCHRONIZE, - &oaParentFileAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL | - FILE_ATTRIBUTE_SYSTEM, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN, - FILE_RANDOM_ACCESS | - FILE_WRITE_THROUGH | - (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - - if (!NT_SUCCESS (ntStatus)) - { - if (hParentDeviceFile != NULL) - ZwClose (hParentDeviceFile); - - Dump ("Cannot open %ls\n", parentDrivePath); - - goto error; - } - - parentKeyDataOffset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; - - ntStatus = ZwReadFile (hParentDeviceFile, - NULL, - NULL, - NULL, - &IoStatusBlock, - readBuffer, - TC_VOLUME_HEADER_EFFECTIVE_SIZE, - &parentKeyDataOffset, - NULL); - - if (hParentDeviceFile != NULL) - ZwClose (hParentDeviceFile); - } - - if (!NT_SUCCESS (ntStatus) && ntStatus != STATUS_END_OF_FILE) - { - Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus); - goto error; - } - - if (ntStatus == STATUS_END_OF_FILE || IoStatusBlock.Information != TC_VOLUME_HEADER_EFFECTIVE_SIZE) - { - Dump ("Read didn't read enough data\n"); - - // If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the - // filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is - // shorter than the partition). This can happen for example after the user quick-formats a dismounted - // partition-hosted TrueCrypt volume and then tries to mount the volume using the embedded backup header. - memset (readBuffer, 0, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - } - - /* Attempt to recognize the volume (decrypt the header) */ - - ReadVolumeHeaderRecoveryMode = mount->RecoveryMode; - - if ((volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) && mount->bProtectHiddenVolume) - { - mount->nReturnCode = ReadVolumeHeaderWCache ( - FALSE, - mount->bCache, - readBuffer, - &mount->ProtectedHidVolPassword, - &tmpCryptoInfo); - } - else - { - mount->nReturnCode = ReadVolumeHeaderWCache ( - mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_NORMAL, - mount->bCache, - readBuffer, - &mount->VolumePassword, - &Extension->cryptoInfo); - } - - ReadVolumeHeaderRecoveryMode = FALSE; - - if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY) - { - /* Volume header successfully decrypted */ - - Dump ("Volume header decrypted\n"); - Dump ("Required program version = %x\n", (int) Extension->cryptoInfo->RequiredProgramVersion); - Dump ("Legacy volume = %d\n", (int) Extension->cryptoInfo->LegacyVolume); - - if (IsHiddenSystemRunning() && !Extension->cryptoInfo->hiddenVolume) - { - Extension->bReadOnly = mount->bMountReadOnly = TRUE; - HiddenSysLeakProtectionCount++; - } - - Extension->cryptoInfo->bProtectHiddenVolume = FALSE; - Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE; - - Extension->cryptoInfo->bPartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope; - - if (volumeType == TC_VOLUME_TYPE_NORMAL) - { - if (mount->bPartitionInInactiveSysEncScope) - { - if (Extension->cryptoInfo->EncryptedAreaStart.Value > (unsigned __int64) partitionStartingOffset - || Extension->cryptoInfo->EncryptedAreaStart.Value + Extension->cryptoInfo->VolumeSize.Value <= (unsigned __int64) partitionStartingOffset) - { - // The partition is not within the key scope of system encryption - mount->nReturnCode = ERR_PASSWORD_WRONG; - ntStatus = STATUS_SUCCESS; - goto error; - } - - if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) - { - // Partial encryption is not supported for volumes mounted as regular - mount->nReturnCode = ERR_ENCRYPTION_NOT_COMPLETED; - ntStatus = STATUS_SUCCESS; - goto error; - } - } - else if (Extension->cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) - { - if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) - { - // Non-system in-place encryption process has not been completed on this volume - mount->nReturnCode = ERR_NONSYS_INPLACE_ENC_INCOMPLETE; - ntStatus = STATUS_SUCCESS; - goto error; - } - } - } - - Extension->cryptoInfo->FirstDataUnitNo.Value = 0; - - if (Extension->cryptoInfo->hiddenVolume && IsHiddenSystemRunning()) - { - // Prevent mount of a hidden system partition if the system hosted on it is currently running - if (memcmp (Extension->cryptoInfo->master_keydata, GetSystemDriveCryptoInfo()->master_keydata, EAGetKeySize (Extension->cryptoInfo->ea)) == 0) - { - mount->nReturnCode = ERR_VOL_ALREADY_MOUNTED; - ntStatus = STATUS_SUCCESS; - goto error; - } - } - - switch (volumeType) - { - case TC_VOLUME_TYPE_NORMAL: - - Extension->cryptoInfo->hiddenVolume = FALSE; - - if (mount->bPartitionInInactiveSysEncScope) - { - Extension->cryptoInfo->volDataAreaOffset = 0; - Extension->DiskLength = lDiskLength.QuadPart; - Extension->cryptoInfo->FirstDataUnitNo.Value = partitionStartingOffset / ENCRYPTION_DATA_UNIT_SIZE; - } - else if (Extension->cryptoInfo->LegacyVolume) - { - Extension->cryptoInfo->volDataAreaOffset = TC_VOLUME_HEADER_SIZE_LEGACY; - Extension->DiskLength = lDiskLength.QuadPart - TC_VOLUME_HEADER_SIZE_LEGACY; - } - else - { - Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->EncryptedAreaStart.Value; - Extension->DiskLength = Extension->cryptoInfo->VolumeSize.Value; - } - - break; - - case TC_VOLUME_TYPE_HIDDEN: - case TC_VOLUME_TYPE_HIDDEN_LEGACY: - - cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo; - - if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) - Extension->cryptoInfo->hiddenVolumeOffset = lDiskLength.QuadPart - cryptoInfoPtr->hiddenVolumeSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; - else - Extension->cryptoInfo->hiddenVolumeOffset = cryptoInfoPtr->EncryptedAreaStart.Value; - - Dump ("Hidden volume offset = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset); - Dump ("Hidden volume size = %I64d\n", cryptoInfoPtr->hiddenVolumeSize); - Dump ("Hidden volume end = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset + cryptoInfoPtr->hiddenVolumeSize - 1); - - // Validate the offset - if (Extension->cryptoInfo->hiddenVolumeOffset % ENCRYPTION_DATA_UNIT_SIZE != 0) - { - mount->nReturnCode = ERR_VOL_SIZE_WRONG; - ntStatus = STATUS_SUCCESS; - goto error; - } - - // If we are supposed to actually mount the hidden volume (not just to protect it) - if (!mount->bProtectHiddenVolume) - { - Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize; - Extension->cryptoInfo->hiddenVolume = TRUE; - Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->hiddenVolumeOffset; - } - else - { - // Hidden volume protection - Extension->cryptoInfo->hiddenVolume = FALSE; - Extension->cryptoInfo->bProtectHiddenVolume = TRUE; - - Extension->cryptoInfo->hiddenVolumeProtectedSize = tmpCryptoInfo->hiddenVolumeSize; - - if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) - Extension->cryptoInfo->hiddenVolumeProtectedSize += TC_VOLUME_HEADER_SIZE_LEGACY; - - Dump ("Hidden volume protection active: %I64d-%I64d (%I64d)\n", Extension->cryptoInfo->hiddenVolumeOffset, Extension->cryptoInfo->hiddenVolumeProtectedSize + Extension->cryptoInfo->hiddenVolumeOffset - 1, Extension->cryptoInfo->hiddenVolumeProtectedSize); - } - - break; - } - - Dump ("Volume data offset = %I64d\n", Extension->cryptoInfo->volDataAreaOffset); - Dump ("Volume data size = %I64d\n", Extension->DiskLength); - Dump ("Volume data end = %I64d\n", Extension->cryptoInfo->volDataAreaOffset + Extension->DiskLength - 1); - - if (Extension->DiskLength == 0) - { - Dump ("Incorrect volume size\n"); - continue; - } - - // If this is a hidden volume, make sure we are supposed to actually - // mount it (i.e. not just to protect it) - if (volumeType == TC_VOLUME_TYPE_NORMAL || !mount->bProtectHiddenVolume) - { - // Calculate virtual volume geometry - Extension->TracksPerCylinder = 1; - Extension->SectorsPerTrack = 1; - Extension->BytesPerSector = SECTOR_SIZE; - Extension->NumberOfCylinders = Extension->DiskLength / SECTOR_SIZE; - Extension->PartitionType = 0; - - Extension->bRawDevice = bRawDevice; - - memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume)); - if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume) - { - /* UNC path */ - _snwprintf (Extension->wszVolume, - sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1, - WIDE ("\\??\\\\%s"), - pwszMountVolume + 7); - } - else - { - wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1); - } - } - - // If we are to protect a hidden volume we cannot exit yet, for we must also - // decrypt the hidden volume header. - if (!(volumeType == TC_VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume)) - { - TCfree (readBuffer); - - if (tmpCryptoInfo != NULL) - { - crypto_close (tmpCryptoInfo); - tmpCryptoInfo = NULL; - } - - return STATUS_SUCCESS; - } - } - else if ((mount->bProtectHiddenVolume && volumeType == TC_VOLUME_TYPE_NORMAL) - || mount->nReturnCode != ERR_PASSWORD_WRONG) - { - /* If we are not supposed to protect a hidden volume, the only error that is - tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume). - - If we _are_ supposed to protect a hidden volume, we do not tolerate any error - (both volume headers must be successfully decrypted). */ - - break; - } - } - - /* Failed due to some non-OS reason so we drop through and return NT - SUCCESS then nReturnCode is checked later in user-mode */ - - if (mount->nReturnCode == ERR_OUTOFMEMORY) - ntStatus = STATUS_INSUFFICIENT_RESOURCES; - else - ntStatus = STATUS_SUCCESS; - -error: - if (mount->nReturnCode == ERR_SUCCESS) - mount->nReturnCode = ERR_PASSWORD_WRONG; - - if (tmpCryptoInfo != NULL) - { - crypto_close (tmpCryptoInfo); - tmpCryptoInfo = NULL; - } - - if (Extension->cryptoInfo) - { - crypto_close (Extension->cryptoInfo); - Extension->cryptoInfo = NULL; - } - - if (Extension->bTimeStampValid) - { - /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */ - RestoreTimeStamp (Extension); - } - - /* Close the hDeviceFile */ - if (Extension->hDeviceFile != NULL) - ZwClose (Extension->hDeviceFile); - - /* The cryptoInfo pointer is deallocated if the readheader routines - fail so there is no need to deallocate here */ - - /* Dereference the user-mode file object */ - if (Extension->pfoDeviceFile != NULL) - ObDereferenceObject (Extension->pfoDeviceFile); - - /* Free the tmp IO buffers */ - if (readBuffer != NULL) - TCfree (readBuffer); - - return ntStatus; -} - -void TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) -{ - if (DeviceObject); /* Remove compiler warning */ - - if (Extension->hDeviceFile != NULL) - { - if (Extension->bRawDevice == FALSE - && Extension->bTimeStampValid) - { - /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */ - RestoreTimeStamp (Extension); - } - ZwClose (Extension->hDeviceFile); - } - ObDereferenceObject (Extension->pfoDeviceFile); - crypto_close (Extension->cryptoInfo); -} - - -NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, - PEXTENSION Extension, - ULONG IoControlCode, - void *OutputBuffer, - ULONG OutputBufferSize) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS ntStatus; - PIRP Irp; - - if (DeviceObject); /* Remove compiler warning */ - - KeClearEvent (&Extension->keVolumeEvent); - - Irp = IoBuildDeviceIoControlRequest (IoControlCode, - Extension->pFsdDevice, - NULL, 0, - OutputBuffer, OutputBufferSize, - FALSE, - &Extension->keVolumeEvent, - &IoStatusBlock); - - if (Irp == NULL) - { - Dump ("IRP allocation failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // Disk device may be used by filesystem driver which needs file object - IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile; - - ntStatus = IoCallDriver (Extension->pFsdDevice, Irp); - if (ntStatus == STATUS_PENDING) - { - KeWaitForSingleObject (&Extension->keVolumeEvent, Executive, KernelMode, FALSE, NULL); - ntStatus = IoStatusBlock.Status; - } - - return ntStatus; -} - -NTSTATUS COMPLETE_IRP (PDEVICE_OBJECT DeviceObject, - PIRP Irp, - NTSTATUS IrpStatus, - ULONG_PTR IrpInformation) -{ - Irp->IoStatus.Status = IrpStatus; - Irp->IoStatus.Information = IrpInformation; - - if (DeviceObject); /* Remove compiler warning */ - -#if EXTRA_INFO - if (!NT_SUCCESS (IrpStatus)) - { - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); - Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), - (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); - } - else - { - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); - Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), - (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); - } -#endif - IoCompleteRequest (Irp, IO_NO_INCREMENT); - return IrpStatus; -} - -// Restores the container timestamp to preserve plausible deniability of possible hidden volume. -static void RestoreTimeStamp (PEXTENSION Extension) -{ - NTSTATUS ntStatus; - FILE_BASIC_INFORMATION FileBasicInfo; - IO_STATUS_BLOCK IoStatusBlock; - - if (Extension->hDeviceFile != NULL - && Extension->bRawDevice == FALSE - && Extension->bReadOnly == FALSE - && Extension->bTimeStampValid) - { - ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, - &IoStatusBlock, - &FileBasicInfo, - sizeof (FileBasicInfo), - FileBasicInformation); - - if (!NT_SUCCESS (ntStatus)) - { - Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n", - ntStatus); - } - else - { - FileBasicInfo.CreationTime = Extension->fileCreationTime; - FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime; - FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime; - FileBasicInfo.ChangeTime = Extension->fileLastChangeTime; - - ntStatus = ZwSetInformationFile( - Extension->hDeviceFile, - &IoStatusBlock, - &FileBasicInfo, - sizeof (FileBasicInfo), - FileBasicInformation); - - if (!NT_SUCCESS (ntStatus)) - Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus); - } - } -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "TCdefs.h" +#include +#include "Crypto.h" +#include "Volumes.h" + +#include "Apidrvr.h" +#include "DriveFilter.h" +#include "Ntdriver.h" +#include "Ntvol.h" +#include "VolumeFilter.h" + +#include "Boot/Windows/BootCommon.h" + +#include "Cache.h" + +#if 0 && _DEBUG +#define EXTRA_INFO 1 +#endif + +#pragma warning( disable : 4127 ) + +volatile BOOL ProbingHostDeviceForWrite = FALSE; + + +NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, + PEXTENSION Extension, + MOUNT_STRUCT *mount, + PWSTR pwszMountVolume, + BOOL bRawDevice) +{ + FILE_STANDARD_INFORMATION FileStandardInfo; + FILE_BASIC_INFORMATION FileBasicInfo; + OBJECT_ATTRIBUTES oaFileAttributes; + UNICODE_STRING FullFileName; + IO_STATUS_BLOCK IoStatusBlock; + PCRYPTO_INFO cryptoInfoPtr = NULL; + PCRYPTO_INFO tmpCryptoInfo = NULL; + LARGE_INTEGER lDiskLength; + __int64 partitionStartingOffset = 0; + int volumeType; + char *readBuffer = 0; + NTSTATUS ntStatus = 0; + BOOL forceAccessCheck = (!bRawDevice && !(OsMajorVersion == 5 &&OsMinorVersion == 0)); // Windows 2000 does not support OBJ_FORCE_ACCESS_CHECK attribute + + Extension->pfoDeviceFile = NULL; + Extension->hDeviceFile = NULL; + Extension->bTimeStampValid = FALSE; + + RtlInitUnicodeString (&FullFileName, pwszMountVolume); + InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0), NULL, NULL); + KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE); + + if (Extension->SecurityClientContextValid) + { + ntStatus = SeImpersonateClientEx (&Extension->SecurityClientContext, NULL); + if (!NT_SUCCESS (ntStatus)) + goto error; + } + + mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = FALSE; + + // If we are opening a device, query its size first + if (bRawDevice) + { + PARTITION_INFORMATION pi; + PARTITION_INFORMATION_EX pix; + LARGE_INTEGER diskLengthInfo; + DISK_GEOMETRY dg; + + ntStatus = IoGetDeviceObjectPointer (&FullFileName, + FILE_READ_DATA | FILE_READ_ATTRIBUTES, + &Extension->pfoDeviceFile, + &Extension->pFsdDevice); + + if (!NT_SUCCESS (ntStatus)) + goto error; + + if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg)))) + { + lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector; + mount->BytesPerSector = dg.BytesPerSector; + } + else + lDiskLength.QuadPart = 0; + + // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails + if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix)))) + { + lDiskLength.QuadPart = pix.PartitionLength.QuadPart; + partitionStartingOffset = pix.StartingOffset.QuadPart; + } + // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX + else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi)))) + { + lDiskLength.QuadPart = pi.PartitionLength.QuadPart; + partitionStartingOffset = pi.StartingOffset.QuadPart; + } + else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_LENGTH_INFO, &diskLengthInfo, sizeof (diskLengthInfo)))) + { + lDiskLength = diskLengthInfo; + } + + ProbingHostDeviceForWrite = TRUE; + + if (!mount->bMountReadOnly + && TCSendHostDeviceIoControlRequest (DeviceObject, Extension, + IsHiddenSystemRunning() ? TC_IOCTL_DISK_IS_WRITABLE : IOCTL_DISK_IS_WRITABLE, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED) + { + mount->bMountReadOnly = TRUE; + DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; + mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = TRUE; + } + + ProbingHostDeviceForWrite = FALSE; + } + + if (mount->BytesPerSector == 0) + mount->BytesPerSector = SECTOR_SIZE; + + Extension->HostBytesPerSector = mount->BytesPerSector; + + // Open the volume hosting file/device + if (!mount->bMountReadOnly) + { + ntStatus = ZwCreateFile (&Extension->hDeviceFile, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &oaFileAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL | + FILE_ATTRIBUTE_SYSTEM, + mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_RANDOM_ACCESS | + FILE_WRITE_THROUGH | + (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + } + + /* 26-4-99 NT for some partitions returns this code, it is really a access denied */ + if (ntStatus == 0xc000001b) + ntStatus = STATUS_ACCESS_DENIED; + + mount->VolumeMountedReadOnlyAfterAccessDenied = FALSE; + + if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED) + { + ntStatus = ZwCreateFile (&Extension->hDeviceFile, + GENERIC_READ | SYNCHRONIZE, + &oaFileAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL | + FILE_ATTRIBUTE_SYSTEM, + mount->bExclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_RANDOM_ACCESS | + FILE_WRITE_THROUGH | + (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS (ntStatus) && !mount->bMountReadOnly) + mount->VolumeMountedReadOnlyAfterAccessDenied = TRUE; + + Extension->bReadOnly = TRUE; + DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; + } + else + Extension->bReadOnly = FALSE; + + /* 26-4-99 NT for some partitions returns this code, it is really a + access denied */ + if (ntStatus == 0xc000001b) + { + /* Partitions which return this code can still be opened with + FILE_SHARE_READ but this causes NT problems elsewhere in + particular if you do FILE_SHARE_READ NT will die later if + anyone even tries to open the partition (or file for that + matter...) */ + ntStatus = STATUS_SHARING_VIOLATION; + } + + if (!NT_SUCCESS (ntStatus)) + { + goto error; + } + + // If we have opened a file, query its size now + if (bRawDevice == FALSE) + { + ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, + &IoStatusBlock, + &FileBasicInfo, + sizeof (FileBasicInfo), + FileBasicInformation); + + if (NT_SUCCESS (ntStatus)) + { + if (mount->bPreserveTimestamp) + { + /* Remember the container timestamp. (Used to reset access/modification file date/time + of file-hosted volumes upon dismount or after unsuccessful mount attempt to preserve + plausible deniability of hidden volumes.) */ + Extension->fileCreationTime = FileBasicInfo.CreationTime; + Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime; + Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime; + Extension->fileLastChangeTime = FileBasicInfo.ChangeTime; + Extension->bTimeStampValid = TRUE; + } + + ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, + &IoStatusBlock, + &FileStandardInfo, + sizeof (FileStandardInfo), + FileStandardInformation); + } + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n", + ntStatus); + goto error; + } + + lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart; + + if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED) + { + Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume); + mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED; + ntStatus = STATUS_SUCCESS; + goto error; + } + + ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile, + FILE_ALL_ACCESS, + *IoFileObjectType, + KernelMode, + &Extension->pfoDeviceFile, + 0); + + if (!NT_SUCCESS (ntStatus)) + { + goto error; + } + + /* Get the FSD device for the file (probably either NTFS or FAT) */ + Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile); + } + else + { + // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, + // the NTFS driver guards hidden sectors and prevents mounting using a backup header e.g. after the user + // accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS). + + PFILE_OBJECT pfoTmpDeviceFile = NULL; + + if (NT_SUCCESS (ObReferenceObjectByHandle (Extension->hDeviceFile, FILE_ALL_ACCESS, *IoFileObjectType, KernelMode, &pfoTmpDeviceFile, NULL)) + && pfoTmpDeviceFile != NULL) + { + TCFsctlCall (pfoTmpDeviceFile, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0); + ObDereferenceObject (pfoTmpDeviceFile); + } + } + + // Check volume size + if (lDiskLength.QuadPart < TC_MIN_VOLUME_SIZE_LEGACY || lDiskLength.QuadPart > TC_MAX_VOLUME_SIZE) + { + mount->nReturnCode = ERR_VOL_SIZE_WRONG; + ntStatus = STATUS_SUCCESS; + goto error; + } + + Extension->DiskLength = lDiskLength.QuadPart; + Extension->HostLength = lDiskLength.QuadPart; + + readBuffer = TCalloc (max (TC_VOLUME_HEADER_EFFECTIVE_SIZE, PAGE_SIZE)); + if (readBuffer == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto error; + } + + // Go through all volume types (e.g., normal, hidden) + for (volumeType = TC_VOLUME_TYPE_NORMAL; + volumeType < TC_VOLUME_TYPE_COUNT; + volumeType++) + { + Dump ("Trying to open volume type %d\n", volumeType); + + if (mount->bPartitionInInactiveSysEncScope + && volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) + continue; + + /* Read the volume header */ + + if (!mount->bPartitionInInactiveSysEncScope + || (mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_HIDDEN)) + { + // Header of a volume that is not within the scope of system encryption, or + // header of a system hidden volume (containing a hidden OS) + + LARGE_INTEGER headerOffset; + + if (mount->UseBackupHeader && lDiskLength.QuadPart <= TC_TOTAL_VOLUME_HEADERS_SIZE) + continue; + + switch (volumeType) + { + case TC_VOLUME_TYPE_NORMAL: + headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; + break; + + case TC_VOLUME_TYPE_HIDDEN: + if (lDiskLength.QuadPart <= TC_VOLUME_HEADER_GROUP_SIZE) + continue; + + headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_HIDDEN_VOLUME_HEADER_OFFSET; + break; + + case TC_VOLUME_TYPE_HIDDEN_LEGACY: + if (mount->UseBackupHeader) + continue; + + headerOffset.QuadPart = lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; + break; + } + + Dump ("Reading volume header at %I64d\n", headerOffset.QuadPart); + + ntStatus = ZwReadFile (Extension->hDeviceFile, + NULL, + NULL, + NULL, + &IoStatusBlock, + readBuffer, + TC_VOLUME_HEADER_EFFECTIVE_SIZE, + &headerOffset, + NULL); + } + else + { + // Header of a partition that is within the scope of system encryption + + WCHAR parentDrivePath [47+1] = {0}; + HANDLE hParentDeviceFile = NULL; + UNICODE_STRING FullParentPath; + OBJECT_ATTRIBUTES oaParentFileAttributes; + LARGE_INTEGER parentKeyDataOffset; + + _snwprintf (parentDrivePath, + sizeof (parentDrivePath) / sizeof (WCHAR) - 1, + WIDE ("\\Device\\Harddisk%d\\Partition0"), + mount->nPartitionInInactiveSysEncScopeDriveNo); + + Dump ("Mounting partition within scope of system encryption (reading key data from: %ls)\n", parentDrivePath); + + RtlInitUnicodeString (&FullParentPath, parentDrivePath); + InitializeObjectAttributes (&oaParentFileAttributes, &FullParentPath, OBJ_CASE_INSENSITIVE, NULL, NULL); + + ntStatus = ZwCreateFile (&hParentDeviceFile, + GENERIC_READ | SYNCHRONIZE, + &oaParentFileAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL | + FILE_ATTRIBUTE_SYSTEM, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_RANDOM_ACCESS | + FILE_WRITE_THROUGH | + (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (!NT_SUCCESS (ntStatus)) + { + if (hParentDeviceFile != NULL) + ZwClose (hParentDeviceFile); + + Dump ("Cannot open %ls\n", parentDrivePath); + + goto error; + } + + parentKeyDataOffset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + + ntStatus = ZwReadFile (hParentDeviceFile, + NULL, + NULL, + NULL, + &IoStatusBlock, + readBuffer, + TC_VOLUME_HEADER_EFFECTIVE_SIZE, + &parentKeyDataOffset, + NULL); + + if (hParentDeviceFile != NULL) + ZwClose (hParentDeviceFile); + } + + if (!NT_SUCCESS (ntStatus) && ntStatus != STATUS_END_OF_FILE) + { + Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus); + goto error; + } + + if (ntStatus == STATUS_END_OF_FILE || IoStatusBlock.Information != TC_VOLUME_HEADER_EFFECTIVE_SIZE) + { + Dump ("Read didn't read enough data\n"); + + // If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the + // filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is + // shorter than the partition). This can happen for example after the user quick-formats a dismounted + // partition-hosted TrueCrypt volume and then tries to mount the volume using the embedded backup header. + memset (readBuffer, 0, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + } + + /* Attempt to recognize the volume (decrypt the header) */ + + ReadVolumeHeaderRecoveryMode = mount->RecoveryMode; + + if ((volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) && mount->bProtectHiddenVolume) + { + mount->nReturnCode = ReadVolumeHeaderWCache ( + FALSE, + mount->bCache, + readBuffer, + &mount->ProtectedHidVolPassword, + &tmpCryptoInfo); + } + else + { + mount->nReturnCode = ReadVolumeHeaderWCache ( + mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_NORMAL, + mount->bCache, + readBuffer, + &mount->VolumePassword, + &Extension->cryptoInfo); + } + + ReadVolumeHeaderRecoveryMode = FALSE; + + if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY) + { + /* Volume header successfully decrypted */ + + Dump ("Volume header decrypted\n"); + Dump ("Required program version = %x\n", (int) Extension->cryptoInfo->RequiredProgramVersion); + Dump ("Legacy volume = %d\n", (int) Extension->cryptoInfo->LegacyVolume); + + if (IsHiddenSystemRunning() && !Extension->cryptoInfo->hiddenVolume) + { + Extension->bReadOnly = mount->bMountReadOnly = TRUE; + HiddenSysLeakProtectionCount++; + } + + Extension->cryptoInfo->bProtectHiddenVolume = FALSE; + Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE; + + Extension->cryptoInfo->bPartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope; + + if (volumeType == TC_VOLUME_TYPE_NORMAL) + { + if (mount->bPartitionInInactiveSysEncScope) + { + if (Extension->cryptoInfo->EncryptedAreaStart.Value > (unsigned __int64) partitionStartingOffset + || Extension->cryptoInfo->EncryptedAreaStart.Value + Extension->cryptoInfo->VolumeSize.Value <= (unsigned __int64) partitionStartingOffset) + { + // The partition is not within the key scope of system encryption + mount->nReturnCode = ERR_PASSWORD_WRONG; + ntStatus = STATUS_SUCCESS; + goto error; + } + + if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) + { + // Partial encryption is not supported for volumes mounted as regular + mount->nReturnCode = ERR_ENCRYPTION_NOT_COMPLETED; + ntStatus = STATUS_SUCCESS; + goto error; + } + } + else if (Extension->cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) + { + if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) + { + // Non-system in-place encryption process has not been completed on this volume + mount->nReturnCode = ERR_NONSYS_INPLACE_ENC_INCOMPLETE; + ntStatus = STATUS_SUCCESS; + goto error; + } + } + } + + Extension->cryptoInfo->FirstDataUnitNo.Value = 0; + + if (Extension->cryptoInfo->hiddenVolume && IsHiddenSystemRunning()) + { + // Prevent mount of a hidden system partition if the system hosted on it is currently running + if (memcmp (Extension->cryptoInfo->master_keydata, GetSystemDriveCryptoInfo()->master_keydata, EAGetKeySize (Extension->cryptoInfo->ea)) == 0) + { + mount->nReturnCode = ERR_VOL_ALREADY_MOUNTED; + ntStatus = STATUS_SUCCESS; + goto error; + } + } + + switch (volumeType) + { + case TC_VOLUME_TYPE_NORMAL: + + Extension->cryptoInfo->hiddenVolume = FALSE; + + if (mount->bPartitionInInactiveSysEncScope) + { + Extension->cryptoInfo->volDataAreaOffset = 0; + Extension->DiskLength = lDiskLength.QuadPart; + Extension->cryptoInfo->FirstDataUnitNo.Value = partitionStartingOffset / ENCRYPTION_DATA_UNIT_SIZE; + } + else if (Extension->cryptoInfo->LegacyVolume) + { + Extension->cryptoInfo->volDataAreaOffset = TC_VOLUME_HEADER_SIZE_LEGACY; + Extension->DiskLength = lDiskLength.QuadPart - TC_VOLUME_HEADER_SIZE_LEGACY; + } + else + { + Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->EncryptedAreaStart.Value; + Extension->DiskLength = Extension->cryptoInfo->VolumeSize.Value; + } + + break; + + case TC_VOLUME_TYPE_HIDDEN: + case TC_VOLUME_TYPE_HIDDEN_LEGACY: + + cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo; + + if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) + Extension->cryptoInfo->hiddenVolumeOffset = lDiskLength.QuadPart - cryptoInfoPtr->hiddenVolumeSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; + else + Extension->cryptoInfo->hiddenVolumeOffset = cryptoInfoPtr->EncryptedAreaStart.Value; + + Dump ("Hidden volume offset = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset); + Dump ("Hidden volume size = %I64d\n", cryptoInfoPtr->hiddenVolumeSize); + Dump ("Hidden volume end = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset + cryptoInfoPtr->hiddenVolumeSize - 1); + + // Validate the offset + if (Extension->cryptoInfo->hiddenVolumeOffset % ENCRYPTION_DATA_UNIT_SIZE != 0) + { + mount->nReturnCode = ERR_VOL_SIZE_WRONG; + ntStatus = STATUS_SUCCESS; + goto error; + } + + // If we are supposed to actually mount the hidden volume (not just to protect it) + if (!mount->bProtectHiddenVolume) + { + Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize; + Extension->cryptoInfo->hiddenVolume = TRUE; + Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->hiddenVolumeOffset; + } + else + { + // Hidden volume protection + Extension->cryptoInfo->hiddenVolume = FALSE; + Extension->cryptoInfo->bProtectHiddenVolume = TRUE; + + Extension->cryptoInfo->hiddenVolumeProtectedSize = tmpCryptoInfo->hiddenVolumeSize; + + if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) + Extension->cryptoInfo->hiddenVolumeProtectedSize += TC_VOLUME_HEADER_SIZE_LEGACY; + + Dump ("Hidden volume protection active: %I64d-%I64d (%I64d)\n", Extension->cryptoInfo->hiddenVolumeOffset, Extension->cryptoInfo->hiddenVolumeProtectedSize + Extension->cryptoInfo->hiddenVolumeOffset - 1, Extension->cryptoInfo->hiddenVolumeProtectedSize); + } + + break; + } + + Dump ("Volume data offset = %I64d\n", Extension->cryptoInfo->volDataAreaOffset); + Dump ("Volume data size = %I64d\n", Extension->DiskLength); + Dump ("Volume data end = %I64d\n", Extension->cryptoInfo->volDataAreaOffset + Extension->DiskLength - 1); + + if (Extension->DiskLength == 0) + { + Dump ("Incorrect volume size\n"); + continue; + } + + // If this is a hidden volume, make sure we are supposed to actually + // mount it (i.e. not just to protect it) + if (volumeType == TC_VOLUME_TYPE_NORMAL || !mount->bProtectHiddenVolume) + { + // Calculate virtual volume geometry + Extension->TracksPerCylinder = 1; + Extension->SectorsPerTrack = 1; + Extension->BytesPerSector = SECTOR_SIZE; + Extension->NumberOfCylinders = Extension->DiskLength / SECTOR_SIZE; + Extension->PartitionType = 0; + + Extension->bRawDevice = bRawDevice; + + memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume)); + if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume) + { + /* UNC path */ + _snwprintf (Extension->wszVolume, + sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1, + WIDE ("\\??\\\\%s"), + pwszMountVolume + 7); + } + else + { + wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1); + } + } + + // If we are to protect a hidden volume we cannot exit yet, for we must also + // decrypt the hidden volume header. + if (!(volumeType == TC_VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume)) + { + TCfree (readBuffer); + + if (tmpCryptoInfo != NULL) + { + crypto_close (tmpCryptoInfo); + tmpCryptoInfo = NULL; + } + + return STATUS_SUCCESS; + } + } + else if ((mount->bProtectHiddenVolume && volumeType == TC_VOLUME_TYPE_NORMAL) + || mount->nReturnCode != ERR_PASSWORD_WRONG) + { + /* If we are not supposed to protect a hidden volume, the only error that is + tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume). + + If we _are_ supposed to protect a hidden volume, we do not tolerate any error + (both volume headers must be successfully decrypted). */ + + break; + } + } + + /* Failed due to some non-OS reason so we drop through and return NT + SUCCESS then nReturnCode is checked later in user-mode */ + + if (mount->nReturnCode == ERR_OUTOFMEMORY) + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + else + ntStatus = STATUS_SUCCESS; + +error: + if (mount->nReturnCode == ERR_SUCCESS) + mount->nReturnCode = ERR_PASSWORD_WRONG; + + if (tmpCryptoInfo != NULL) + { + crypto_close (tmpCryptoInfo); + tmpCryptoInfo = NULL; + } + + if (Extension->cryptoInfo) + { + crypto_close (Extension->cryptoInfo); + Extension->cryptoInfo = NULL; + } + + if (Extension->bTimeStampValid) + { + /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */ + RestoreTimeStamp (Extension); + } + + /* Close the hDeviceFile */ + if (Extension->hDeviceFile != NULL) + ZwClose (Extension->hDeviceFile); + + /* The cryptoInfo pointer is deallocated if the readheader routines + fail so there is no need to deallocate here */ + + /* Dereference the user-mode file object */ + if (Extension->pfoDeviceFile != NULL) + ObDereferenceObject (Extension->pfoDeviceFile); + + /* Free the tmp IO buffers */ + if (readBuffer != NULL) + TCfree (readBuffer); + + return ntStatus; +} + +void TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) +{ + if (DeviceObject); /* Remove compiler warning */ + + if (Extension->hDeviceFile != NULL) + { + if (Extension->bRawDevice == FALSE + && Extension->bTimeStampValid) + { + /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */ + RestoreTimeStamp (Extension); + } + ZwClose (Extension->hDeviceFile); + } + ObDereferenceObject (Extension->pfoDeviceFile); + crypto_close (Extension->cryptoInfo); +} + + +NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, + PEXTENSION Extension, + ULONG IoControlCode, + void *OutputBuffer, + ULONG OutputBufferSize) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS ntStatus; + PIRP Irp; + + if (DeviceObject); /* Remove compiler warning */ + + KeClearEvent (&Extension->keVolumeEvent); + + Irp = IoBuildDeviceIoControlRequest (IoControlCode, + Extension->pFsdDevice, + NULL, 0, + OutputBuffer, OutputBufferSize, + FALSE, + &Extension->keVolumeEvent, + &IoStatusBlock); + + if (Irp == NULL) + { + Dump ("IRP allocation failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Disk device may be used by filesystem driver which needs file object + IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile; + + ntStatus = IoCallDriver (Extension->pFsdDevice, Irp); + if (ntStatus == STATUS_PENDING) + { + KeWaitForSingleObject (&Extension->keVolumeEvent, Executive, KernelMode, FALSE, NULL); + ntStatus = IoStatusBlock.Status; + } + + return ntStatus; +} + +NTSTATUS COMPLETE_IRP (PDEVICE_OBJECT DeviceObject, + PIRP Irp, + NTSTATUS IrpStatus, + ULONG_PTR IrpInformation) +{ + Irp->IoStatus.Status = IrpStatus; + Irp->IoStatus.Information = IrpInformation; + + if (DeviceObject); /* Remove compiler warning */ + +#if EXTRA_INFO + if (!NT_SUCCESS (IrpStatus)) + { + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), + (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); + } + else + { + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), + (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); + } +#endif + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return IrpStatus; +} + +// Restores the container timestamp to preserve plausible deniability of possible hidden volume. +static void RestoreTimeStamp (PEXTENSION Extension) +{ + NTSTATUS ntStatus; + FILE_BASIC_INFORMATION FileBasicInfo; + IO_STATUS_BLOCK IoStatusBlock; + + if (Extension->hDeviceFile != NULL + && Extension->bRawDevice == FALSE + && Extension->bReadOnly == FALSE + && Extension->bTimeStampValid) + { + ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, + &IoStatusBlock, + &FileBasicInfo, + sizeof (FileBasicInfo), + FileBasicInformation); + + if (!NT_SUCCESS (ntStatus)) + { + Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n", + ntStatus); + } + else + { + FileBasicInfo.CreationTime = Extension->fileCreationTime; + FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime; + FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime; + FileBasicInfo.ChangeTime = Extension->fileLastChangeTime; + + ntStatus = ZwSetInformationFile( + Extension->hDeviceFile, + &IoStatusBlock, + &FileBasicInfo, + sizeof (FileBasicInfo), + FileBasicInformation); + + if (!NT_SUCCESS (ntStatus)) + Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus); + } + } +} diff --git a/Driver/NTVOL.H b/Driver/NTVOL.H index 7396cd7..33f0d0e 100644 --- a/Driver/NTVOL.H +++ b/Driver/NTVOL.H @@ -1,19 +1,19 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -extern volatile BOOL ProbingHostDeviceForWrite; - -NTSTATUS TCOpenVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , MOUNT_STRUCT *mount , PWSTR pwszMountVolume , BOOL bRawDevice ); -void TCCloseVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension ); -NTSTATUS TCCompletion ( PDEVICE_OBJECT DeviceObject , PIRP Irp , PVOID pUserBuffer ); -static NTSTATUS TCSendHostDeviceIoControlRequest ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , ULONG IoControlCode , void *OutputBuffer , ULONG OutputBufferSize ); -NTSTATUS COMPLETE_IRP ( PDEVICE_OBJECT DeviceObject , PIRP Irp , NTSTATUS IrpStatus , ULONG_PTR IrpInformation ); -static void RestoreTimeStamp ( PEXTENSION Extension ); +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +extern volatile BOOL ProbingHostDeviceForWrite; + +NTSTATUS TCOpenVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , MOUNT_STRUCT *mount , PWSTR pwszMountVolume , BOOL bRawDevice ); +void TCCloseVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension ); +NTSTATUS TCCompletion ( PDEVICE_OBJECT DeviceObject , PIRP Irp , PVOID pUserBuffer ); +static NTSTATUS TCSendHostDeviceIoControlRequest ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , ULONG IoControlCode , void *OutputBuffer , ULONG OutputBufferSize ); +NTSTATUS COMPLETE_IRP ( PDEVICE_OBJECT DeviceObject , PIRP Irp , NTSTATUS IrpStatus , ULONG_PTR IrpInformation ); +static void RestoreTimeStamp ( PEXTENSION Extension ); diff --git a/Driver/VolumeFilter.c b/Driver/VolumeFilter.c index ee9cb28..b1e9e99 100644 --- a/Driver/VolumeFilter.c +++ b/Driver/VolumeFilter.c @@ -1,262 +1,281 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "TCdefs.h" -#include "Ntdriver.h" -#include "Ntvol.h" -#include "DriveFilter.h" -#include "VolumeFilter.h" - -typedef DriveFilterExtension VolumeFilterExtension; - -static PDEVICE_OBJECT SystemVolumePdo = NULL; - -// Number of times the filter driver answered that an unencrypted volume -// is read-only (or mounted an outer/normal TrueCrypt volume as read only) -uint32 HiddenSysLeakProtectionCount = 0; - - -NTSTATUS VolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) -{ - VolumeFilterExtension *Extension; - NTSTATUS status; - PDEVICE_OBJECT filterDeviceObject = NULL; - PDEVICE_OBJECT attachedDeviceObject; - - Dump ("VolumeFilterAddDevice pdo=%p\n", pdo); - - attachedDeviceObject = IoGetAttachedDeviceReference (pdo); - - DriverMutexWait(); - status = IoCreateDevice (driverObject, sizeof (VolumeFilterExtension), NULL, attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject); - DriverMutexRelease(); - - ObDereferenceObject (attachedDeviceObject); - - if (!NT_SUCCESS (status)) - { - filterDeviceObject = NULL; - goto err; - } - - Extension = (VolumeFilterExtension *) filterDeviceObject->DeviceExtension; - memset (Extension, 0, sizeof (VolumeFilterExtension)); - - Extension->LowerDeviceObject = IoAttachDeviceToDeviceStack (filterDeviceObject, pdo); // IoAttachDeviceToDeviceStackSafe() is not required in AddDevice routine and is also unavailable on Windows 2000 SP4 - if (!Extension->LowerDeviceObject) - { - status = STATUS_DEVICE_REMOVED; - goto err; - } - - Extension->IsVolumeFilterDevice = TRUE; - Extension->DeviceObject = filterDeviceObject; - Extension->Pdo = pdo; - - IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0); - - filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE); - filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - return status; - -err: - if (filterDeviceObject) - { - if (Extension->LowerDeviceObject) - IoDetachDevice (Extension->LowerDeviceObject); - - DriverMutexWait(); - IoDeleteDevice (filterDeviceObject); - DriverMutexRelease(); - } - - return status; -} - - -static NTSTATUS PassIrp (PDEVICE_OBJECT deviceObject, PIRP irp) -{ - IoSkipCurrentIrpStackLocation (irp); - return IoCallDriver (deviceObject, irp); -} - - -static NTSTATUS PassFilteredIrp (PDEVICE_OBJECT deviceObject, PIRP irp, PIO_COMPLETION_ROUTINE completionRoutine, PVOID completionRoutineArg) -{ - IoCopyCurrentIrpStackLocationToNext (irp); - - if (completionRoutine) - IoSetCompletionRoutine (irp, completionRoutine, completionRoutineArg, TRUE, TRUE, TRUE); - - return IoCallDriver (deviceObject, irp); -} - - -static NTSTATUS OnDeviceUsageNotificationCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension) -{ - if (Irp->PendingReturned) - IoMarkIrpPending (Irp); - - if (!(Extension->LowerDeviceObject->Flags & DO_POWER_PAGABLE)) - filterDeviceObject->Flags &= ~DO_POWER_PAGABLE; - - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - return STATUS_CONTINUE_COMPLETION; -} - - -static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension) -{ - if (Irp->PendingReturned) - IoMarkIrpPending (Irp); - - if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) - filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; - - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - return STATUS_CONTINUE_COMPLETION; -} - - -static NTSTATUS DispatchControl (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp) -{ - NTSTATUS status; - - if (IsHiddenSystemRunning()) - { - switch (irpSp->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_DISK_IS_WRITABLE: - - if (SystemVolumePdo == NULL) - { - // The first volume checked for being writable is the system volume - SystemVolumePdo = Extension->Pdo; - Dump ("System volume pdo=%p\n", SystemVolumePdo); - } - else if (Extension->Pdo != SystemVolumePdo) - { - // Volumes other than the system volume must be presented as read-only - ++HiddenSysLeakProtectionCount; - return TCCompleteDiskIrp (Irp, STATUS_MEDIA_WRITE_PROTECTED, 0); - } - - return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0); - - case TC_IOCTL_DISK_IS_WRITABLE: - Dump ("TC_IOCTL_DISK_IS_WRITABLE pdo=%p\n", Extension->Pdo); - - if (!ProbingHostDeviceForWrite) - break; - - // Probe the real state of the device as the user is mounting a TrueCrypt volume. - - // Volume filter may be attached to a merged drive+volume PDO. First test if TC_IOCTL_DISK_IS_WRITABLE works for the underlying device. - status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, TC_IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0); - if (NT_SUCCESS (status) || status == STATUS_MEDIA_WRITE_PROTECTED) - return TCCompleteDiskIrp (Irp, status, 0); - - status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0); - return TCCompleteDiskIrp (Irp, status, 0); - } - } - - return PassIrp (Extension->LowerDeviceObject, Irp); -} - - -static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp) -{ - NTSTATUS status; - - status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); - if (!NT_SUCCESS (status)) - return TCCompleteIrp (Irp, status, Irp->IoStatus.Information); - - switch (irpSp->MinorFunction) - { - case IRP_MN_START_DEVICE: - Dump ("IRP_MN_START_DEVICE volume pdo=%p\n", Extension->Pdo); - return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension); - - case IRP_MN_DEVICE_USAGE_NOTIFICATION: - { - PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject); - - if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE)) - DeviceObject->Flags |= DO_POWER_PAGABLE; - - ObDereferenceObject (attachedDevice); - } - - return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension); - - - case IRP_MN_REMOVE_DEVICE: - Dump ("IRP_MN_REMOVE_DEVICE volume pdo=%p\n", Extension->Pdo); - - IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp); - status = PassIrp (Extension->LowerDeviceObject, Irp); - - IoDetachDevice (Extension->LowerDeviceObject); - - DriverMutexWait(); - IoDeleteDevice (DeviceObject); - DriverMutexRelease(); - - return status; - - default: - status = PassIrp (Extension->LowerDeviceObject, Irp); - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - } - - return status; -} - - -static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp) -{ - NTSTATUS status; - PoStartNextPowerIrp (Irp); - - status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); - if (!NT_SUCCESS (status)) - return TCCompleteIrp (Irp, status, Irp->IoStatus.Information); - - IoSkipCurrentIrpStackLocation (Irp); - status = PoCallDriver (Extension->LowerDeviceObject, Irp); - - IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); - return status; -} - - -NTSTATUS VolumeFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - VolumeFilterExtension *Extension = (VolumeFilterExtension *) DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); - - ASSERT (!Extension->bRootDevice && Extension->IsVolumeFilterDevice); - - switch (irpSp->MajorFunction) - { - case IRP_MJ_DEVICE_CONTROL: - return DispatchControl (DeviceObject, Irp, Extension, irpSp); - - case IRP_MJ_PNP: - return DispatchPnp (DeviceObject, Irp, Extension, irpSp); - - case IRP_MJ_POWER: - return DispatchPower (DeviceObject, Irp, Extension, irpSp); - - default: - return PassIrp (Extension->LowerDeviceObject, Irp); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "TCdefs.h" +#include "Ntdriver.h" +#include "Ntvol.h" +#include "DriveFilter.h" +#include "VolumeFilter.h" + +typedef DriveFilterExtension VolumeFilterExtension; + +static PDEVICE_OBJECT SystemVolumePdo = NULL; + +// Number of times the filter driver answered that an unencrypted volume +// is read-only (or mounted an outer/normal TrueCrypt volume as read only) +uint32 HiddenSysLeakProtectionCount = 0; + + +NTSTATUS VolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) +{ + VolumeFilterExtension *Extension; + NTSTATUS status; + PDEVICE_OBJECT filterDeviceObject = NULL; + PDEVICE_OBJECT attachedDeviceObject; + + Dump ("VolumeFilterAddDevice pdo=%p\n", pdo); + + attachedDeviceObject = IoGetAttachedDeviceReference (pdo); + + DriverMutexWait(); + status = IoCreateDevice (driverObject, sizeof (VolumeFilterExtension), NULL, attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject); + DriverMutexRelease(); + + ObDereferenceObject (attachedDeviceObject); + + if (!NT_SUCCESS (status)) + { + filterDeviceObject = NULL; + goto err; + } + + Extension = (VolumeFilterExtension *) filterDeviceObject->DeviceExtension; + memset (Extension, 0, sizeof (VolumeFilterExtension)); + + Extension->LowerDeviceObject = IoAttachDeviceToDeviceStack (filterDeviceObject, pdo); // IoAttachDeviceToDeviceStackSafe() is not required in AddDevice routine and is also unavailable on Windows 2000 SP4 + if (!Extension->LowerDeviceObject) + { + status = STATUS_DEVICE_REMOVED; + goto err; + } + + Extension->IsVolumeFilterDevice = TRUE; + Extension->DeviceObject = filterDeviceObject; + Extension->Pdo = pdo; + + IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0); + + filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE); + filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + return status; + +err: + if (filterDeviceObject) + { + if (Extension->LowerDeviceObject) + IoDetachDevice (Extension->LowerDeviceObject); + + DriverMutexWait(); + IoDeleteDevice (filterDeviceObject); + DriverMutexRelease(); + } + + return status; +} + + +static NTSTATUS PassIrp (PDEVICE_OBJECT deviceObject, PIRP irp) +{ + IoSkipCurrentIrpStackLocation (irp); + return IoCallDriver (deviceObject, irp); +} + + +static NTSTATUS PassFilteredIrp (PDEVICE_OBJECT deviceObject, PIRP irp, PIO_COMPLETION_ROUTINE completionRoutine, PVOID completionRoutineArg) +{ + IoCopyCurrentIrpStackLocationToNext (irp); + + if (completionRoutine) + IoSetCompletionRoutine (irp, completionRoutine, completionRoutineArg, TRUE, TRUE, TRUE); + + return IoCallDriver (deviceObject, irp); +} + + +static NTSTATUS OnDeviceUsageNotificationCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension) +{ + if (Irp->PendingReturned) + IoMarkIrpPending (Irp); + + if (!(Extension->LowerDeviceObject->Flags & DO_POWER_PAGABLE)) + filterDeviceObject->Flags &= ~DO_POWER_PAGABLE; + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return STATUS_CONTINUE_COMPLETION; +} + + +static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension) +{ + if (Irp->PendingReturned) + IoMarkIrpPending (Irp); + + if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return STATUS_CONTINUE_COMPLETION; +} + + +static NTSTATUS DispatchControl (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp) +{ + NTSTATUS status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (status)) + return TCCompleteIrp (Irp, status, 0); + + if (IsHiddenSystemRunning()) + { + switch (irpSp->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_DISK_IS_WRITABLE: + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + + if (SystemVolumePdo == NULL) + { + // The first volume checked for being writable is the system volume + SystemVolumePdo = Extension->Pdo; + Dump ("System volume pdo=%p\n", SystemVolumePdo); + } + else if (Extension->Pdo != SystemVolumePdo) + { + // Volumes other than the system volume must be presented as read-only + ++HiddenSysLeakProtectionCount; + return TCCompleteDiskIrp (Irp, STATUS_MEDIA_WRITE_PROTECTED, 0); + } + + return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0); + + case TC_IOCTL_DISK_IS_WRITABLE: + Dump ("TC_IOCTL_DISK_IS_WRITABLE pdo=%p\n", Extension->Pdo); + + if (!ProbingHostDeviceForWrite) + break; + + // Probe the real state of the device as the user is mounting a TrueCrypt volume. + + // Volume filter may be attached to a merged drive+volume PDO. First test if TC_IOCTL_DISK_IS_WRITABLE works for the underlying device. + status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, TC_IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0); + + if (NT_SUCCESS (status) || status == STATUS_MEDIA_WRITE_PROTECTED) + { + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return TCCompleteDiskIrp (Irp, status, 0); + } + + status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0); + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return TCCompleteDiskIrp (Irp, status, 0); + } + } + + status = PassIrp (Extension->LowerDeviceObject, Irp); + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return status; +} + + +static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp) +{ + NTSTATUS status; + + status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (status)) + return TCCompleteIrp (Irp, status, 0); + + switch (irpSp->MinorFunction) + { + case IRP_MN_START_DEVICE: + Dump ("IRP_MN_START_DEVICE volume pdo=%p\n", Extension->Pdo); + return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension); + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + { + PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject); + + if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE)) + DeviceObject->Flags |= DO_POWER_PAGABLE; + + ObDereferenceObject (attachedDevice); + } + + return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension); + + + case IRP_MN_REMOVE_DEVICE: + Dump ("IRP_MN_REMOVE_DEVICE volume pdo=%p\n", Extension->Pdo); + + IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp); + status = PassIrp (Extension->LowerDeviceObject, Irp); + + IoDetachDevice (Extension->LowerDeviceObject); + + DriverMutexWait(); + IoDeleteDevice (DeviceObject); + DriverMutexRelease(); + + return status; + + default: + status = PassIrp (Extension->LowerDeviceObject, Irp); + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + } + + return status; +} + + +static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp) +{ + NTSTATUS status; + PoStartNextPowerIrp (Irp); + + status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (status)) + return TCCompleteIrp (Irp, status, 0); + + IoSkipCurrentIrpStackLocation (Irp); + status = PoCallDriver (Extension->LowerDeviceObject, Irp); + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return status; +} + + +NTSTATUS VolumeFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + VolumeFilterExtension *Extension = (VolumeFilterExtension *) DeviceObject->DeviceExtension; + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + NTSTATUS status; + + ASSERT (!Extension->bRootDevice && Extension->IsVolumeFilterDevice); + + switch (irpSp->MajorFunction) + { + case IRP_MJ_DEVICE_CONTROL: + return DispatchControl (DeviceObject, Irp, Extension, irpSp); + + case IRP_MJ_PNP: + return DispatchPnp (DeviceObject, Irp, Extension, irpSp); + + case IRP_MJ_POWER: + return DispatchPower (DeviceObject, Irp, Extension, irpSp); + + default: + status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp); + if (!NT_SUCCESS (status)) + return TCCompleteIrp (Irp, status, 0); + + status = PassIrp (Extension->LowerDeviceObject, Irp); + + IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp); + return status; + } +} diff --git a/Driver/VolumeFilter.h b/Driver/VolumeFilter.h index 3a36bf4..34d7fdf 100644 --- a/Driver/VolumeFilter.h +++ b/Driver/VolumeFilter.h @@ -1,19 +1,19 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_DRIVER_VOLUME_FILTER -#define TC_HEADER_DRIVER_VOLUME_FILTER - -#include "TCdefs.h" - -extern uint32 HiddenSysLeakProtectionCount; - -NTSTATUS VolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo); -NTSTATUS VolumeFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp); - -#endif // TC_HEADER_DRIVER_VOLUME_FILTER +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_DRIVER_VOLUME_FILTER +#define TC_HEADER_DRIVER_VOLUME_FILTER + +#include "TCdefs.h" + +extern uint32 HiddenSysLeakProtectionCount; + +NTSTATUS VolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo); +NTSTATUS VolumeFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp); + +#endif // TC_HEADER_DRIVER_VOLUME_FILTER diff --git a/Driver/resource.h b/Driver/resource.h index a3e7364..effd804 100644 --- a/Driver/resource.h +++ b/Driver/resource.h @@ -1,16 +1,16 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Driver.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Driver.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Format/Format.manifest b/Format/Format.manifest index 13d7582..48616cf 100644 --- a/Format/Format.manifest +++ b/Format/Format.manifest @@ -1,5 +1,5 @@ - + @@ -7,4 +7,15 @@ + + + true + + + + + + + + \ No newline at end of file diff --git a/Format/Format.rc b/Format/Format.rc index 2657ea3..f3610ae 100644 --- a/Format/Format.rc +++ b/Format/Format.rc @@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,2,1,0 - PRODUCTVERSION 6,2,1,0 + FILEVERSION 6,3,0,0 + PRODUCTVERSION 6,3,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -46,12 +46,11 @@ BEGIN BEGIN VALUE "CompanyName", "TrueCrypt Foundation" VALUE "FileDescription", "TrueCrypt Format" - VALUE "FileVersion", "6.2a" - VALUE "LegalCopyright", "TrueCrypt Foundation" + VALUE "FileVersion", "6.3" VALUE "LegalTrademarks", "TrueCrypt" VALUE "OriginalFilename", "TrueCrypt Format.exe" VALUE "ProductName", "TrueCrypt" - VALUE "ProductVersion", "6.2a" + VALUE "ProductVersion", "6.3" END END BLOCK "VarFileInfo" @@ -249,7 +248,7 @@ BEGIN CONTROL "Encrypt the Windows system partition",IDC_SYS_PARTITION, "Button",BS_AUTORADIOBUTTON,0,7,212,10 CONTROL "Encrypt the whole drive",IDC_WHOLE_SYS_DRIVE,"Button",BS_AUTORADIOBUTTON,0,53,212,10 - LTEXT "Select this option to encrypt the partition where your Windows is installed and from which it boots.",IDT_SYS_PARTITION,16,20,205,32 + LTEXT "Select this option to encrypt the partition where the currently running Windows operating system is installed.",IDT_SYS_PARTITION,16,20,205,32 LTEXT "",IDT_WHOLE_SYS_DRIVE,16,66,205,79 END diff --git a/Format/Format.vcproj b/Format/Format.vcproj index 65ab792..ae164a0 100644 --- a/Format/Format.vcproj +++ b/Format/Format.vcproj @@ -50,9 +50,9 @@ RuntimeLibrary="1" BufferSecurityCheck="true" UsePrecompiledHeader="0" - WarningLevel="3" + WarningLevel="4" DebugInformationFormat="4" - DisableSpecificWarnings="4311" + DisableSpecificWarnings="4057;4100;4127;4201;4204;4701;4706" /> + + + + + + -#include -#include -#include -#include "BaseCom.h" -#include "BootEncryption.h" -#include "Dlgcode.h" -#include "Format.h" -#include "Progress.h" -#include "TcFormat.h" -#include "FormatCom.h" -#include "FormatCom_h.h" -#include "FormatCom_i.c" - -using namespace TrueCrypt; - -static volatile LONG ObjectCount = 0; - -class TrueCryptFormatCom : public ITrueCryptFormatCom -{ - -public: - TrueCryptFormatCom (DWORD messageThreadId) : RefCount (0), - MessageThreadId (messageThreadId), - CallBack (NULL) - { - InterlockedIncrement (&ObjectCount); - } - - ~TrueCryptFormatCom () - { - if (InterlockedDecrement (&ObjectCount) == 0) - PostThreadMessage (MessageThreadId, WM_APP, 0, 0); - } - - virtual ULONG STDMETHODCALLTYPE AddRef () - { - return InterlockedIncrement (&RefCount); - } - - virtual ULONG STDMETHODCALLTYPE Release () - { - if (!InterlockedDecrement (&RefCount)) - { - delete this; - return 0; - } - - return RefCount; - } - - virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) - { - if (riid == IID_IUnknown || riid == IID_ITrueCryptFormatCom) - *ppvObject = this; - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - AddRef (); - return S_OK; - } - - virtual DWORD STDMETHODCALLTYPE CallDriver (DWORD ioctl, BSTR input, BSTR *output) - { - return BaseCom::CallDriver (ioctl, input, output); - } - - virtual BOOL STDMETHODCALLTYPE FormatNtfs (int driveNo, int clusterSize) - { - return ::FormatNtfs (driveNo, clusterSize); - } - - virtual int STDMETHODCALLTYPE AnalyzeHiddenVolumeHost ( - LONG_PTR hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *nbrFreeClusters) - { - return ::AnalyzeHiddenVolumeHost ( - (HWND) hwndDlg, driveNo, hiddenVolHostSize, realClusterSize, nbrFreeClusters); - } - - virtual DWORD STDMETHODCALLTYPE ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone) - { - return BaseCom::ReadWriteFile (write, device, filePath, bufferBstr, offset, size, sizeDone); - } - - virtual DWORD STDMETHODCALLTYPE RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass) - { - return BaseCom::RegisterFilterDriver (registerDriver, volumeClass); - } - - virtual DWORD STDMETHODCALLTYPE SetDriverServiceStartType (DWORD startType) - { - return BaseCom::SetDriverServiceStartType (startType); - } - - virtual BOOL STDMETHODCALLTYPE IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) - { - return BaseCom::IsPagingFileActive (checkNonWindowsPartitionsOnly); - } - - virtual DWORD STDMETHODCALLTYPE WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value) - { - return BaseCom::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value); - } - -protected: - DWORD MessageThreadId; - LONG RefCount; - ITrueCryptFormatCom *CallBack; -}; - - -extern "C" BOOL ComServerFormat () -{ - SetProcessShutdownParameters (0x100, 0); - - TrueCryptFactory factory (GetCurrentThreadId ()); - DWORD cookie; - - if (IsUacSupported ()) - UacElevated = TRUE; - - if (CoRegisterClassObject (CLSID_TrueCryptFormatCom, (LPUNKNOWN) &factory, - CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie) != S_OK) - return FALSE; - - MSG msg; - while (int r = GetMessage (&msg, NULL, 0, 0)) - { - if (r == -1) - return FALSE; - - TranslateMessage (&msg); - DispatchMessage (&msg); - - if (msg.message == WM_APP - && ObjectCount < 1 - && !factory.IsServerLocked ()) - break; - } - CoRevokeClassObject (cookie); - - return TRUE; -} - - -static BOOL ComGetInstance (HWND hWnd, ITrueCryptFormatCom **tcServer) -{ - return ComGetInstanceBase (hWnd, CLSID_TrueCryptFormatCom, IID_ITrueCryptFormatCom, (void **) tcServer); -} - - -ITrueCryptFormatCom *GetElevatedInstance (HWND parent) -{ - ITrueCryptFormatCom *instance; - - if (!ComGetInstance (parent, &instance)) - throw UserAbort (SRC_POS); - - return instance; -} - - -extern "C" int UacFormatNtfs (HWND hWnd, int driveNo, int clusterSize) -{ - CComPtr tc; - int r; - - CoInitialize (NULL); - - if (ComGetInstance (hWnd, &tc)) - r = tc->FormatNtfs (driveNo, clusterSize); - else - r = 0; - - CoUninitialize (); - - return r; -} - - -extern "C" int UacAnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *nbrFreeClusters) -{ - CComPtr tc; - int r; - - CoInitialize (NULL); - - if (ComGetInstance (hwndDlg, &tc)) - r = tc->AnalyzeHiddenVolumeHost ((LONG_PTR) hwndDlg, driveNo, hiddenVolHostSize, realClusterSize, nbrFreeClusters); - else - r = 0; - - CoUninitialize (); - - return r; -} +/* + Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include "BaseCom.h" +#include "BootEncryption.h" +#include "Dlgcode.h" +#include "Format.h" +#include "Progress.h" +#include "TcFormat.h" +#include "FormatCom.h" +#include "FormatCom_h.h" +#include "FormatCom_i.c" + +using namespace TrueCrypt; + +static volatile LONG ObjectCount = 0; + +class TrueCryptFormatCom : public ITrueCryptFormatCom +{ + +public: + TrueCryptFormatCom (DWORD messageThreadId) : RefCount (0), + MessageThreadId (messageThreadId), + CallBack (NULL) + { + InterlockedIncrement (&ObjectCount); + } + + ~TrueCryptFormatCom () + { + if (InterlockedDecrement (&ObjectCount) == 0) + PostThreadMessage (MessageThreadId, WM_APP, 0, 0); + } + + virtual ULONG STDMETHODCALLTYPE AddRef () + { + return InterlockedIncrement (&RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release () + { + if (!InterlockedDecrement (&RefCount)) + { + delete this; + return 0; + } + + return RefCount; + } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) + { + if (riid == IID_IUnknown || riid == IID_ITrueCryptFormatCom) + *ppvObject = this; + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + AddRef (); + return S_OK; + } + + virtual DWORD STDMETHODCALLTYPE CallDriver (DWORD ioctl, BSTR input, BSTR *output) + { + return BaseCom::CallDriver (ioctl, input, output); + } + + virtual DWORD STDMETHODCALLTYPE CopyFile (BSTR sourceFile, BSTR destinationFile) + { + return BaseCom::CopyFile (sourceFile, destinationFile); + } + + virtual DWORD STDMETHODCALLTYPE DeleteFile (BSTR file) + { + return BaseCom::DeleteFile (file); + } + + virtual BOOL STDMETHODCALLTYPE FormatNtfs (int driveNo, int clusterSize) + { + return ::FormatNtfs (driveNo, clusterSize); + } + + virtual int STDMETHODCALLTYPE AnalyzeHiddenVolumeHost ( + LONG_PTR hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *nbrFreeClusters) + { + return ::AnalyzeHiddenVolumeHost ( + (HWND) hwndDlg, driveNo, hiddenVolHostSize, realClusterSize, nbrFreeClusters); + } + + virtual DWORD STDMETHODCALLTYPE ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone) + { + return BaseCom::ReadWriteFile (write, device, filePath, bufferBstr, offset, size, sizeDone); + } + + virtual DWORD STDMETHODCALLTYPE RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass) + { + return BaseCom::RegisterFilterDriver (registerDriver, volumeClass); + } + + virtual DWORD STDMETHODCALLTYPE RegisterSystemFavoritesService (BOOL registerService) + { + return BaseCom::RegisterSystemFavoritesService (registerService); + } + + virtual DWORD STDMETHODCALLTYPE SetDriverServiceStartType (DWORD startType) + { + return BaseCom::SetDriverServiceStartType (startType); + } + + virtual BOOL STDMETHODCALLTYPE IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) + { + return BaseCom::IsPagingFileActive (checkNonWindowsPartitionsOnly); + } + + virtual DWORD STDMETHODCALLTYPE WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value) + { + return BaseCom::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value); + } + +protected: + DWORD MessageThreadId; + LONG RefCount; + ITrueCryptFormatCom *CallBack; +}; + + +extern "C" BOOL ComServerFormat () +{ + SetProcessShutdownParameters (0x100, 0); + + TrueCryptFactory factory (GetCurrentThreadId ()); + DWORD cookie; + + if (IsUacSupported ()) + UacElevated = TRUE; + + if (CoRegisterClassObject (CLSID_TrueCryptFormatCom, (LPUNKNOWN) &factory, + CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie) != S_OK) + return FALSE; + + MSG msg; + while (int r = GetMessage (&msg, NULL, 0, 0)) + { + if (r == -1) + return FALSE; + + TranslateMessage (&msg); + DispatchMessage (&msg); + + if (msg.message == WM_APP + && ObjectCount < 1 + && !factory.IsServerLocked ()) + break; + } + CoRevokeClassObject (cookie); + + return TRUE; +} + + +static BOOL ComGetInstance (HWND hWnd, ITrueCryptFormatCom **tcServer) +{ + return ComGetInstanceBase (hWnd, CLSID_TrueCryptFormatCom, IID_ITrueCryptFormatCom, (void **) tcServer); +} + + +ITrueCryptFormatCom *GetElevatedInstance (HWND parent) +{ + ITrueCryptFormatCom *instance; + + if (!ComGetInstance (parent, &instance)) + throw UserAbort (SRC_POS); + + return instance; +} + + +extern "C" int UacFormatNtfs (HWND hWnd, int driveNo, int clusterSize) +{ + CComPtr tc; + int r; + + CoInitialize (NULL); + + if (ComGetInstance (hWnd, &tc)) + r = tc->FormatNtfs (driveNo, clusterSize); + else + r = 0; + + CoUninitialize (); + + return r; +} + + +extern "C" int UacAnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *nbrFreeClusters) +{ + CComPtr tc; + int r; + + CoInitialize (NULL); + + if (ComGetInstance (hwndDlg, &tc)) + r = tc->AnalyzeHiddenVolumeHost ((LONG_PTR) hwndDlg, driveNo, hiddenVolHostSize, realClusterSize, nbrFreeClusters); + else + r = 0; + + CoUninitialize (); + + return r; +} diff --git a/Format/FormatCom.h b/Format/FormatCom.h index 6d54f43..73fd20b 100644 --- a/Format/FormatCom.h +++ b/Format/FormatCom.h @@ -1,32 +1,32 @@ -/* - Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_FORMAT_COM -#define TC_HEADER_FORMAT_COM - -#include - -#ifdef __cplusplus - -#include "FormatCom_h.h" -ITrueCryptFormatCom *GetElevatedInstance (HWND parent); - -extern "C" { -#endif - -BOOL ComServerFormat (); -int UacFormatNtfs (HWND hWnd, int driveNo, int clusterSize); -int UacAnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *nbrFreeClusters); -int UacFormatVolume (char *cvolumePath , BOOL bDevice , unsigned __int64 size , unsigned __int64 hiddenVolHostSize , Password *password , int cipher , int pkcs5 , BOOL quickFormat, BOOL sparseFileSwitch, int fileSystem , int clusterSize, HWND hwndDlg , BOOL hiddenVol , int *realClusterSize); -BOOL UacUpdateProgressBar (__int64 nSecNo, BOOL *bVolTransformThreadCancel); - -#ifdef __cplusplus -} -#endif - +/* + Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_FORMAT_COM +#define TC_HEADER_FORMAT_COM + +#include + +#ifdef __cplusplus + +#include "FormatCom_h.h" +ITrueCryptFormatCom *GetElevatedInstance (HWND parent); + +extern "C" { +#endif + +BOOL ComServerFormat (); +int UacFormatNtfs (HWND hWnd, int driveNo, int clusterSize); +int UacAnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *nbrFreeClusters); +int UacFormatVolume (char *cvolumePath , BOOL bDevice , unsigned __int64 size , unsigned __int64 hiddenVolHostSize , Password *password , int cipher , int pkcs5 , BOOL quickFormat, BOOL sparseFileSwitch, int fileSystem , int clusterSize, HWND hwndDlg , BOOL hiddenVol , int *realClusterSize); +BOOL UacUpdateProgressBar (__int64 nSecNo, BOOL *bVolTransformThreadCancel); + +#ifdef __cplusplus +} +#endif + #endif // TC_HEADER_FORMAT_COM \ No newline at end of file diff --git a/Format/FormatCom.idl b/Format/FormatCom.idl index 491e516..cde715d 100644 --- a/Format/FormatCom.idl +++ b/Format/FormatCom.idl @@ -1,7 +1,7 @@ /* - Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. + Copyright (c) 2007-2009 TrueCrypt Foundation. All rights reserved. - Governed by the TrueCrypt License 2.7 the full text of which is contained + Governed by the TrueCrypt License 2.8 the full text of which is contained in the file License.txt included in TrueCrypt binary and source code distribution packages. */ @@ -12,7 +12,7 @@ import "..\Common\Password.h"; [ uuid(A7DF958C-0716-49E9-8C3E-53A775797576), helpstring("TrueCrypt Format UAC Support Library"), - version(2.2) + version(2.3) ] library TrueCryptFormatCom { @@ -26,10 +26,13 @@ library TrueCryptFormatCom { int AnalyzeHiddenVolumeHost (LONG_PTR hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *nbrFreeClusters); DWORD CallDriver (DWORD ioctl, BSTR input, BSTR *output); + DWORD CopyFile (BSTR sourceFile, BSTR destinationFile); + DWORD DeleteFile (BSTR file); BOOL FormatNtfs (int driveNo, int clusterSize); BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); DWORD ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone); DWORD RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass); + DWORD RegisterSystemFavoritesService (BOOL registerService); DWORD SetDriverServiceStartType (DWORD startType); DWORD WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value); }; diff --git a/Format/InPlace.c b/Format/InPlace.c index d89e87f..08f162a 100644 --- a/Format/InPlace.c +++ b/Format/InPlace.c @@ -1,1690 +1,1690 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - - -/* In this file, _WIN32_WINNT is defined as 0x0600 to make filesystem shrink available (Vista -or later). _WIN32_WINNT cannot be defined as 0x0600 for the entire user-space projects -because it breaks the main font app when the app is running on XP (likely an MS bug). -IMPORTANT: Due to this issue, functions in this file must not directly interact with GUI. */ -#define TC_LOCAL_WIN32_WINNT_OVERRIDE 1 -#if (_WIN32_WINNT < 0x0600) -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0600 -#endif - - -#include -#include -#include - -#include "Tcdefs.h" -#include "Platform/Finally.h" - -#include "Common.h" -#include "Crc.h" -#include "Dlgcode.h" -#include "Language.h" -#include "Tcformat.h" -#include "Volumes.h" - -#include "InPlace.h" - -using namespace std; -using namespace TrueCrypt; - -#define TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE (2048 * BYTES_PER_KB) -#define TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE (2 * TC_MAX_VOLUME_SECTOR_SIZE) -#define TC_NTFS_CONCEAL_CONSTANT 0xFF -#define TC_NONSYS_INPLACE_ENC_HEADER_UPDATE_INTERVAL (64 * BYTES_PER_MB) -#define TC_NONSYS_INPLACE_ENC_MIN_VOL_SIZE (TC_TOTAL_VOLUME_HEADERS_SIZE + TC_MIN_NTFS_FS_SIZE * 2) - - -// If the returned value is greater than 0, it is the desired volume size in NTFS sectors (not in bytes) -// after shrinking has been performed. If there's any error, returns -1. -static __int64 NewFileSysSizeAfterShrink (HANDLE dev, const char *devicePath, int64 *totalClusterCount, DWORD *bytesPerCluster, BOOL silent) -{ - NTFS_VOLUME_DATA_BUFFER ntfsVolData; - DWORD nBytesReturned; - __int64 fileSysSize, desiredNbrSectors; - - // Filesystem size and sector size - - if (!DeviceIoControl (dev, - FSCTL_GET_NTFS_VOLUME_DATA, - NULL, - 0, - (LPVOID) &ntfsVolData, - sizeof (ntfsVolData), - &nBytesReturned, - NULL)) - { - if (!silent) - handleWin32Error (MainDlg); - - return -1; - } - - fileSysSize = ntfsVolData.NumberSectors.QuadPart * ntfsVolData.BytesPerSector; - - desiredNbrSectors = (fileSysSize - TC_TOTAL_VOLUME_HEADERS_SIZE) / ntfsVolData.BytesPerSector; - - if (desiredNbrSectors <= 0) - return -1; - - if (totalClusterCount) - *totalClusterCount = ntfsVolData.TotalClusters.QuadPart; - if (bytesPerCluster) - *bytesPerCluster = ntfsVolData.BytesPerCluster; - - return desiredNbrSectors; -} - - -BOOL CheckRequirementsForNonSysInPlaceEnc (const char *devicePath, BOOL silent) -{ - NTFS_VOLUME_DATA_BUFFER ntfsVolData; - DWORD nBytesReturned; - HANDLE dev; - char szFileSysName [256]; - WCHAR devPath [MAX_PATH]; - char dosDev [TC_MAX_PATH] = {0}; - char devName [MAX_PATH] = {0}; - int driveLetterNo = -1; - char szRootPath[4] = {0, ':', '\\', 0}; - __int64 deviceSize; - int partitionNumber = -1, driveNumber = -1; - - - /* ---------- Checks that do not require admin rights ----------- */ - - - /* Operating system */ - - if (CurrentOSMajor < 6) - { - if (!silent) - ShowInPlaceEncErrMsgWAltSteps ("OS_NOT_SUPPORTED_FOR_NONSYS_INPLACE_ENC", FALSE); - - return FALSE; - } - - - /* Volume type (must be a partition or a dynamic volume) */ - - if (sscanf (devicePath, "\\Device\\HarddiskVolume%d", &partitionNumber) != 1 - && sscanf (devicePath, "\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2) - { - if (!silent) - Error ("INPLACE_ENC_INVALID_PATH"); - - return FALSE; - } - - if (partitionNumber == 0) - { - if (!silent) - Warning ("RAW_DEV_NOT_SUPPORTED_FOR_INPLACE_ENC"); - - return FALSE; - } - - - /* Admin rights */ - - if (!IsAdmin()) - { - // We rely on the wizard process to call us only when the whole wizard process has been elevated (so UAC - // status can be ignored). In case the IsAdmin() detection somehow fails, we allow the user to continue. - - if (!silent) - Warning ("ADMIN_PRIVILEGES_WARN_DEVICES"); - } - - - /* ---------- Checks that may require admin rights ----------- */ - - - /* Access to the partition */ - - strcpy ((char *) devPath, devicePath); - ToUNICODE ((char *) devPath); - - driveLetterNo = GetDiskDeviceDriveLetter (devPath); - - if (driveLetterNo >= 0) - szRootPath[0] = driveLetterNo + 'A'; - - if (FakeDosNameForDevice (devicePath, dosDev, devName, FALSE) != 0) - { - if (!silent) - { - handleWin32Error (MainDlg); - Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); - } - return FALSE; - } - - dev = OpenPartitionVolume (devName, - FALSE, // Do not require exclusive access - TRUE, // Require shared access (must be TRUE; otherwise, volume properties will not be possible to obtain) - FALSE, // Do not ask the user to confirm shared access (if exclusive fails) - FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages) - silent); // Silent mode - - if (dev == INVALID_HANDLE_VALUE) - return FALSE; - - - /* File system type */ - - GetVolumeInformation (szRootPath, NULL, 0, NULL, NULL, NULL, szFileSysName, sizeof(szFileSysName)); - - if (strncmp (szFileSysName, "NTFS", 4)) - { - // The previous filesystem type detection method failed (or it's not NTFS) -- try an alternative method - - if (!DeviceIoControl (dev, - FSCTL_GET_NTFS_VOLUME_DATA, - NULL, - 0, - (LPVOID) &ntfsVolData, - sizeof (ntfsVolData), - &nBytesReturned, - NULL)) - { - if (!silent) - { - // The filesystem is not NTFS or the filesystem type could not be determined (or the NTFS filesystem - // is dismounted). - - if (IsDeviceMounted (devName)) - ShowInPlaceEncErrMsgWAltSteps ("ONLY_NTFS_SUPPORTED_FOR_NONSYS_INPLACE_ENC", FALSE); - else - Warning ("ONLY_MOUNTED_VOL_SUPPORTED_FOR_NONSYS_INPLACE_ENC"); - } - - CloseHandle (dev); - return FALSE; - } - } - - - /* Attempt to determine whether the filesystem can be safely shrunk */ - - if (NewFileSysSizeAfterShrink (dev, devicePath, NULL, NULL, silent) == -1) - { - // Cannot determine whether shrinking is required - if (!silent) - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); - - CloseHandle (dev); - return FALSE; - } - - - /* Partition size */ - - deviceSize = GetDeviceSize (devicePath); - if (deviceSize < 0) - { - // Cannot determine the size of the partition - if (!silent) - Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); - - CloseHandle (dev); - return FALSE; - } - - if (deviceSize < TC_NONSYS_INPLACE_ENC_MIN_VOL_SIZE) - { - // The partition is too small - if (!silent) - { - ShowInPlaceEncErrMsgWAltSteps ("PARTITION_TOO_SMALL_FOR_NONSYS_INPLACE_ENC", FALSE); - } - - CloseHandle (dev); - return FALSE; - } - - - /* Free space on the filesystem */ - - if (!DeviceIoControl (dev, - FSCTL_GET_NTFS_VOLUME_DATA, - NULL, - 0, - (LPVOID) &ntfsVolData, - sizeof (ntfsVolData), - &nBytesReturned, - NULL)) - { - if (!silent) - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL", TRUE); - - CloseHandle (dev); - return FALSE; - } - - if (ntfsVolData.FreeClusters.QuadPart * ntfsVolData.BytesPerCluster < TC_TOTAL_VOLUME_HEADERS_SIZE) - { - if (!silent) - ShowInPlaceEncErrMsgWAltSteps ("NOT_ENOUGH_FREE_FILESYS_SPACE_FOR_SHRINK", TRUE); - - CloseHandle (dev); - return FALSE; - } - - - /* Filesystem sector size */ - - if (ntfsVolData.BytesPerSector > TC_MAX_VOLUME_SECTOR_SIZE - || ntfsVolData.BytesPerSector % ENCRYPTION_DATA_UNIT_SIZE != 0) - { - if (!silent) - ShowInPlaceEncErrMsgWAltSteps ("ERR_UNSUPPORTED_SECTOR_SIZE_GENERIC", TRUE); - - CloseHandle (dev); - return FALSE; - } - - - CloseHandle (dev); - return TRUE; -} - - -int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, volatile HANDLE *outHandle, WipeAlgorithmId wipeAlgorithm) -{ - SHRINK_VOLUME_INFORMATION shrinkVolInfo; - signed __int64 sizeToShrinkTo; - int nStatus = ERR_SUCCESS; - PCRYPTO_INFO cryptoInfo = NULL; - PCRYPTO_INFO cryptoInfo2 = NULL; - HANDLE dev = INVALID_HANDLE_VALUE; - DWORD dwError; - char *header; - char dosDev[TC_MAX_PATH] = {0}; - char devName[MAX_PATH] = {0}; - int driveLetter = -1; - WCHAR deviceName[MAX_PATH]; - uint64 dataAreaSize; - __int64 deviceSize; - LARGE_INTEGER offset; - DWORD dwResult; - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PREPARING); - - - if (!CheckRequirementsForNonSysInPlaceEnc (volParams->volumePath, FALSE)) - return ERR_DONT_REPORT; - - - header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); - if (!header) - return ERR_OUTOFMEMORY; - - VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - - deviceSize = GetDeviceSize (volParams->volumePath); - if (deviceSize < 0) - { - // Cannot determine the size of the partition - nStatus = ERR_PARAMETER_INCORRECT; - goto closing_seq; - } - - if (deviceSize < TC_NONSYS_INPLACE_ENC_MIN_VOL_SIZE) - { - ShowInPlaceEncErrMsgWAltSteps ("PARTITION_TOO_SMALL_FOR_NONSYS_INPLACE_ENC", TRUE); - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - - dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, deviceSize); - - strcpy ((char *)deviceName, volParams->volumePath); - ToUNICODE ((char *)deviceName); - - driveLetter = GetDiskDeviceDriveLetter (deviceName); - - - if (FakeDosNameForDevice (volParams->volumePath, dosDev, devName, FALSE) != 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - if (IsDeviceMounted (devName)) - { - dev = OpenPartitionVolume (devName, - FALSE, // Do not require exclusive access (must be FALSE; otherwise, it will not be possible to dismount the volume or obtain its properties and FSCTL_ALLOW_EXTENDED_DASD_IO will fail too) - TRUE, // Require shared access (must be TRUE; otherwise, it will not be possible to dismount the volume or obtain its properties and FSCTL_ALLOW_EXTENDED_DASD_IO will fail too) - FALSE, // Do not ask the user to confirm shared access (if exclusive fails) - FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages) - FALSE); // Non-silent mode - - if (dev == INVALID_HANDLE_VALUE) - { - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - } - else - { - // The volume is not mounted so we can't work with the filesystem. - Error ("ONLY_MOUNTED_VOL_SUPPORTED_FOR_NONSYS_INPLACE_ENC"); - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - - - /* Gain "raw" access to the partition (the NTFS driver guards hidden sectors). */ - - if (!DeviceIoControl (dev, - FSCTL_ALLOW_EXTENDED_DASD_IO, - NULL, - 0, - NULL, - 0, - &dwResult, - NULL)) - { - handleWin32Error (MainDlg); - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - - - - /* Shrink the filesystem */ - - int64 totalClusterCount; - DWORD bytesPerCluster; - - sizeToShrinkTo = NewFileSysSizeAfterShrink (dev, volParams->volumePath, &totalClusterCount, &bytesPerCluster, FALSE); - - if (sizeToShrinkTo == -1) - { - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_RESIZING); - - memset (&shrinkVolInfo, 0, sizeof (shrinkVolInfo)); - - shrinkVolInfo.ShrinkRequestType = ShrinkPrepare; - shrinkVolInfo.NewNumberOfSectors = sizeToShrinkTo; - - if (!DeviceIoControl (dev, - FSCTL_SHRINK_VOLUME, - (LPVOID) &shrinkVolInfo, - sizeof (shrinkVolInfo), - NULL, - 0, - &dwResult, - NULL)) - { - handleWin32Error (MainDlg); - ShowInPlaceEncErrMsgWAltSteps ("CANNOT_RESIZE_FILESYS", TRUE); - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - - BOOL clustersMovedBeforeVolumeEnd = FALSE; - - while (true) - { - shrinkVolInfo.ShrinkRequestType = ShrinkCommit; - shrinkVolInfo.NewNumberOfSectors = 0; - - if (!DeviceIoControl (dev, FSCTL_SHRINK_VOLUME, &shrinkVolInfo, sizeof (shrinkVolInfo), NULL, 0, &dwResult, NULL)) - { - // If there are any occupied clusters beyond the new desired end of the volume, the call fails with - // ERROR_ACCESS_DENIED (STATUS_ALREADY_COMMITTED). - if (GetLastError () == ERROR_ACCESS_DENIED) - { - if (!clustersMovedBeforeVolumeEnd) - { - if (MoveClustersBeforeThreshold (dev, deviceName, totalClusterCount - (bytesPerCluster > TC_TOTAL_VOLUME_HEADERS_SIZE ? 1 : TC_TOTAL_VOLUME_HEADERS_SIZE / bytesPerCluster))) - { - clustersMovedBeforeVolumeEnd = TRUE; - continue; - } - - handleWin32Error (MainDlg); - } - } - else - handleWin32Error (MainDlg); - - ShowInPlaceEncErrMsgWAltSteps ("CANNOT_RESIZE_FILESYS", TRUE); - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - - break; - } - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PREPARING); - - - /* Gain exclusive access to the volume */ - - nStatus = DismountFileSystem (dev, - driveLetter, - TRUE, - TRUE, - FALSE); - - if (nStatus != ERR_SUCCESS) - { - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - - - - /* Create header backup on the partition. Until the volume is fully encrypted, the backup header will provide - us with the master key, encrypted range, and other data for pause/resume operations. We cannot create the - primary header until the entire partition is encrypted (because we encrypt backwards and the primary header - area is occuppied by data until the very end of the process). */ - - // Prepare the backup header - for (int wipePass = 0; wipePass < (wipeAlgorithm == TC_WIPE_NONE ? 1 : PRAND_DISK_WIPE_PASSES); wipePass++) - { - nStatus = CreateVolumeHeaderInMemory (FALSE, - header, - volParams->ea, - FIRST_MODE_OF_OPERATION_ID, - volParams->password, - volParams->pkcs5, - wipePass == 0 ? NULL : (char *) cryptoInfo->master_keydata, - &cryptoInfo, - dataAreaSize, - 0, - TC_VOLUME_DATA_OFFSET + dataAreaSize, // Start of the encrypted area = the first byte of the backup heeader (encrypting from the end) - 0, // No data is encrypted yet - 0, - volParams->headerFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC, - wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_DISK_WIPE_PASSES - 1)); - - if (nStatus != 0) - goto closing_seq; - - offset.QuadPart = TC_VOLUME_DATA_OFFSET + dataAreaSize; - - if (!SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - // Write the backup header to the partition - if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - // Fill the reserved sectors of the backup header area with random data - nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, TRUE); - - if (nStatus != ERR_SUCCESS) - goto closing_seq; - } - - - /* Now we will try to decrypt the backup header to verify it has been correctly written. */ - - nStatus = OpenBackupHeader (dev, volParams->volumePath, volParams->password, &cryptoInfo2, NULL, deviceSize); - - if (nStatus != ERR_SUCCESS - || cryptoInfo->EncryptedAreaStart.Value != cryptoInfo2->EncryptedAreaStart.Value - || cryptoInfo2->EncryptedAreaStart.Value == 0) - { - if (nStatus == ERR_SUCCESS) - nStatus = ERR_PARAMETER_INCORRECT; - - goto closing_seq; - } - - // The backup header is valid so we know we should be able to safely resume in-place encryption - // of this partition even if the system/app crashes. - - - - /* Conceal the NTFS filesystem (by performing an easy-to-undo modification). This will prevent Windows - and apps from interfering with the volume until it has been fully encrypted. */ - - nStatus = ConcealNTFS (dev); - - if (nStatus != ERR_SUCCESS) - goto closing_seq; - - - - // /* If a drive letter is assigned to the device, remove it (so that users do not try to open it, which - //would cause Windows to ask them if they want to format the volume and other dangerous things). */ - - //if (driveLetter >= 0) - //{ - // char rootPath[] = { driveLetter + 'A', ':', '\\', 0 }; - - // // Try to remove the assigned drive letter - // if (DeleteVolumeMountPoint (rootPath)) - // driveLetter = -1; - //} - - - - /* Update config files and app data */ - - // In the config file, increase the number of partitions where in-place encryption is in progress - - SaveNonSysInPlaceEncSettings (1, wipeAlgorithm); - - - // Add the wizard to the system startup sequence if appropriate - - if (!IsNonInstallMode ()) - ManageStartupSeqWiz (FALSE, "/prinplace"); - - - nStatus = ERR_SUCCESS; - - -closing_seq: - - dwError = GetLastError(); - - if (cryptoInfo != NULL) - { - crypto_close (cryptoInfo); - cryptoInfo = NULL; - } - - if (cryptoInfo2 != NULL) - { - crypto_close (cryptoInfo2); - cryptoInfo2 = NULL; - } - - burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - TCfree (header); - - if (dosDev[0]) - RemoveFakeDosName (volParams->volumePath, dosDev); - - *outHandle = dev; - - if (nStatus != ERR_SUCCESS) - SetLastError (dwError); - - return nStatus; -} - - -int EncryptPartitionInPlaceResume (HANDLE dev, - volatile FORMAT_VOL_PARAMETERS *volParams, - WipeAlgorithmId wipeAlgorithm, - volatile BOOL *bTryToCorrectReadErrors) -{ - PCRYPTO_INFO masterCryptoInfo = NULL, headerCryptoInfo = NULL, tmpCryptoInfo = NULL; - UINT64_STRUCT unitNo; - char *buf = NULL, *header = NULL; - byte *wipeBuffer = NULL; - byte wipeRandChars [TC_WIPE_RAND_CHAR_COUNT]; - byte wipeRandCharsUpdate [TC_WIPE_RAND_CHAR_COUNT]; - char dosDev[TC_MAX_PATH] = {0}; - char devName[MAX_PATH] = {0}; - WCHAR deviceName[MAX_PATH]; - int nStatus = ERR_SUCCESS; - __int64 deviceSize; - uint64 remainingBytes, lastHeaderUpdateDistance = 0, zeroedSectorCount = 0; - uint32 workChunkSize; - DWORD dwError, dwResult; - BOOL bPause = FALSE, bEncryptedAreaSizeChanged = FALSE; - LARGE_INTEGER offset; - int sectorSize; - int i; - DWORD n; - char *devicePath = volParams->volumePath; - Password *password = volParams->password; - DISK_GEOMETRY driveGeometry; - - - bInPlaceEncNonSysResumed = TRUE; - - buf = (char *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE); - if (!buf) - { - nStatus = ERR_OUTOFMEMORY; - goto closing_seq; - } - - header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); - if (!header) - { - nStatus = ERR_OUTOFMEMORY; - goto closing_seq; - } - - VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - - if (wipeAlgorithm != TC_WIPE_NONE) - { - wipeBuffer = (byte *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE); - if (!wipeBuffer) - { - nStatus = ERR_OUTOFMEMORY; - goto closing_seq; - } - } - - headerCryptoInfo = crypto_open(); - - if (headerCryptoInfo == NULL) - { - nStatus = ERR_OUTOFMEMORY; - goto closing_seq; - } - - deviceSize = GetDeviceSize (devicePath); - if (deviceSize < 0) - { - // Cannot determine the size of the partition - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - if (dev == INVALID_HANDLE_VALUE) - { - strcpy ((char *)deviceName, devicePath); - ToUNICODE ((char *)deviceName); - - if (FakeDosNameForDevice (devicePath, dosDev, devName, FALSE) != 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - dev = OpenPartitionVolume (devName, - FALSE, // Do not require exclusive access - FALSE, // Do not require shared access - TRUE, // Ask the user to confirm shared access (if exclusive fails) - FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages) - FALSE); // Non-silent mode - - if (dev == INVALID_HANDLE_VALUE) - { - nStatus = ERR_DONT_REPORT; - goto closing_seq; - } - } - - // This should never be needed, but is still performed for extra safety (without checking the result) - DeviceIoControl (dev, - FSCTL_ALLOW_EXTENDED_DASD_IO, - NULL, - 0, - NULL, - 0, - &dwResult, - NULL); - - - if (!DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveGeometry, sizeof (driveGeometry), &dwResult, NULL)) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - sectorSize = driveGeometry.BytesPerSector; - - - nStatus = OpenBackupHeader (dev, devicePath, password, &masterCryptoInfo, headerCryptoInfo, deviceSize); - - if (nStatus != ERR_SUCCESS) - goto closing_seq; - - - - remainingBytes = masterCryptoInfo->VolumeSize.Value - masterCryptoInfo->EncryptedAreaLength.Value; - - lastHeaderUpdateDistance = 0; - - - ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value / SECTOR_SIZE); - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_ENCRYPTING); - - bFirstNonSysInPlaceEncResumeDone = TRUE; - - - /* The in-place encryption core */ - - while (remainingBytes > 0) - { - workChunkSize = (uint32) min (remainingBytes, TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE); - - if (workChunkSize % ENCRYPTION_DATA_UNIT_SIZE != 0) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto closing_seq; - } - - unitNo.Value = (remainingBytes - workChunkSize + TC_VOLUME_DATA_OFFSET) / ENCRYPTION_DATA_UNIT_SIZE; - - - // Read the plaintext into RAM - -inplace_enc_read: - - offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize - TC_VOLUME_DATA_OFFSET; - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - if (ReadFile (dev, buf, workChunkSize, &n, NULL) == 0) - { - // Read error - - DWORD dwTmpErr = GetLastError (); - - if (IsDiskReadError (dwTmpErr) && !bVolTransformThreadCancel) - { - // Physical defect or data corruption - - if (!*bTryToCorrectReadErrors) - { - *bTryToCorrectReadErrors = (AskWarnYesNo ("ENABLE_BAD_SECTOR_ZEROING") == IDYES); - } - - if (*bTryToCorrectReadErrors) - { - // Try to correct the read errors physically - - offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize - TC_VOLUME_DATA_OFFSET; - - nStatus = ZeroUnreadableSectors (dev, offset, workChunkSize, sectorSize, &zeroedSectorCount); - - if (nStatus != ERR_SUCCESS) - { - // Due to write errors, we can't correct the read errors - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - goto inplace_enc_read; - } - } - - SetLastError (dwTmpErr); // Preserve the original error code - - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - if (remainingBytes - workChunkSize < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE) - { - // We reached the inital portion of the filesystem, which we had concealed (in order to prevent - // Windows from interfering with the volume). Now we need to undo that modification. - - for (i = 0; i < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE - (remainingBytes - workChunkSize); i++) - buf[i] ^= TC_NTFS_CONCEAL_CONSTANT; - } - - - // Encrypt the plaintext in RAM - - EncryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); - - - // If enabled, wipe the area to which we will write the ciphertext - - if (wipeAlgorithm != TC_WIPE_NONE) - { - byte wipePass; - - offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize; - - for (wipePass = 1; wipePass <= GetWipePassCount (wipeAlgorithm); ++wipePass) - { - if (!WipeBuffer (wipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, workChunkSize)) - { - ULONG i; - for (i = 0; i < workChunkSize; ++i) - { - wipeBuffer[i] = buf[i] + wipePass; - } - - EncryptDataUnits (wipeBuffer, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); - memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); - } - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 - || WriteFile (dev, wipeBuffer, workChunkSize, &n, NULL) == 0) - { - // Write error - dwError = GetLastError(); - - // Undo failed write operation - if (workChunkSize > TC_VOLUME_DATA_OFFSET && SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) - { - DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); - WriteFile (dev, buf + TC_VOLUME_DATA_OFFSET, workChunkSize - TC_VOLUME_DATA_OFFSET, &n, NULL); - } - - SetLastError (dwError); - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - } - - memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate)); - } - - - // Write the ciphertext - - offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize; - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - if (WriteFile (dev, buf, workChunkSize, &n, NULL) == 0) - { - // Write error - dwError = GetLastError(); - - // Undo failed write operation - if (workChunkSize > TC_VOLUME_DATA_OFFSET && SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) - { - DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); - WriteFile (dev, buf + TC_VOLUME_DATA_OFFSET, workChunkSize - TC_VOLUME_DATA_OFFSET, &n, NULL); - } - - SetLastError (dwError); - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - - masterCryptoInfo->EncryptedAreaStart.Value -= workChunkSize; - masterCryptoInfo->EncryptedAreaLength.Value += workChunkSize; - - remainingBytes -= workChunkSize; - lastHeaderUpdateDistance += workChunkSize; - - bEncryptedAreaSizeChanged = TRUE; - - if (lastHeaderUpdateDistance >= TC_NONSYS_INPLACE_ENC_HEADER_UPDATE_INTERVAL) - { - nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize); - - if (nStatus != ERR_SUCCESS) - goto closing_seq; - - lastHeaderUpdateDistance = 0; - } - - ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value / SECTOR_SIZE); - - if (bVolTransformThreadCancel) - { - bPause = TRUE; - break; - } - } - - nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize); - - - if (nStatus != ERR_SUCCESS) - goto closing_seq; - - - if (!bPause) - { - /* The data area has been fully encrypted; create and write the primary volume header */ - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINALIZING); - - for (int wipePass = 0; wipePass < (wipeAlgorithm == TC_WIPE_NONE ? 1 : PRAND_DISK_WIPE_PASSES); wipePass++) - { - nStatus = CreateVolumeHeaderInMemory (FALSE, - header, - headerCryptoInfo->ea, - headerCryptoInfo->mode, - password, - masterCryptoInfo->pkcs5, - (char *) masterCryptoInfo->master_keydata, - &tmpCryptoInfo, - masterCryptoInfo->VolumeSize.Value, - 0, - masterCryptoInfo->EncryptedAreaStart.Value, - masterCryptoInfo->EncryptedAreaLength.Value, - masterCryptoInfo->RequiredProgramVersion, - masterCryptoInfo->HeaderFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC, - wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_DISK_WIPE_PASSES - 1)); - - if (nStatus != ERR_SUCCESS) - goto closing_seq; - - - offset.QuadPart = TC_VOLUME_HEADER_OFFSET; - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 - || WriteFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - // Fill the reserved sectors of the header area with random data - nStatus = WriteRandomDataToReservedHeaderAreas (dev, headerCryptoInfo, masterCryptoInfo->VolumeSize.Value, TRUE, FALSE); - - if (nStatus != ERR_SUCCESS) - goto closing_seq; - } - - // Update the configuration files - - SaveNonSysInPlaceEncSettings (-1, wipeAlgorithm); - - - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINISHED); - - nStatus = ERR_SUCCESS; - } - else - { - // The process has been paused by the user or aborted by the wizard (e.g. on app exit) - - nStatus = ERR_USER_ABORT; - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED); - } - - -closing_seq: - - dwError = GetLastError(); - - if (bEncryptedAreaSizeChanged - && dev != INVALID_HANDLE_VALUE - && masterCryptoInfo != NULL - && headerCryptoInfo != NULL - && deviceSize > 0) - { - // Execution of the core loop may have been interrupted due to an error or user action without updating the header - FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize); - } - - if (masterCryptoInfo != NULL) - { - crypto_close (masterCryptoInfo); - masterCryptoInfo = NULL; - } - - if (headerCryptoInfo != NULL) - { - crypto_close (headerCryptoInfo); - headerCryptoInfo = NULL; - } - - if (tmpCryptoInfo != NULL) - { - crypto_close (tmpCryptoInfo); - tmpCryptoInfo = NULL; - } - - if (dosDev[0]) - RemoveFakeDosName (devicePath, dosDev); - - if (dev != INVALID_HANDLE_VALUE) - { - CloseHandle (dev); - dev = INVALID_HANDLE_VALUE; - } - - if (buf != NULL) - TCfree (buf); - - if (header != NULL) - { - burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - TCfree (header); - } - - if (wipeBuffer != NULL) - TCfree (wipeBuffer); - - if (zeroedSectorCount > 0) - { - wchar_t msg[30000] = {0}; - wchar_t sizeStr[500] = {0}; - - GetSizeString (zeroedSectorCount * sectorSize, sizeStr); - - wsprintfW (msg, - GetString ("ZEROED_BAD_SECTOR_COUNT"), - zeroedSectorCount, - sizeStr); - - WarningDirect (msg); - } - - if (nStatus != ERR_SUCCESS && nStatus != ERR_USER_ABORT) - SetLastError (dwError); - - return nStatus; -} - - -int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_INFO *masterCryptoInfo, __int64 deviceSize) -{ - LARGE_INTEGER offset; - DWORD n; - int nStatus = ERR_SUCCESS; - byte *header; - DWORD dwError; - uint32 headerCrc32; - byte *fieldPos; - - header = (byte *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); - - if (!header) - return ERR_OUTOFMEMORY; - - VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - - - fieldPos = (byte *) header + TC_HEADER_OFFSET_ENCRYPTED_AREA_START; - - offset.QuadPart = deviceSize - TC_VOLUME_HEADER_GROUP_SIZE; - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 - || ReadFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - - DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); - - if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto closing_seq; - } - - mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaStart.Value)); - mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaLength.Value)); - - - headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); - fieldPos = (byte *) header + TC_HEADER_OFFSET_HEADER_CRC; - mputLong (fieldPos, headerCrc32); - - EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); - - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 - || WriteFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - -closing_seq: - - dwError = GetLastError(); - - burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - TCfree (header); - - if (nStatus != ERR_SUCCESS) - SetLastError (dwError); - - return nStatus; -} - - -static HANDLE OpenPartitionVolume (const char *devName, - BOOL bExclusiveRequired, - BOOL bSharedRequired, - BOOL bSharedRequiresConfirmation, - BOOL bShowAlternativeSteps, - BOOL bSilent) -{ - HANDLE dev = INVALID_HANDLE_VALUE; - int retryCount = 0; - - if (bExclusiveRequired) - bSharedRequired = FALSE; - - if (bExclusiveRequired || !bSharedRequired) - { - // Exclusive access - // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries). - while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES) - { - dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); - - if (retryCount > 1) - Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY); - } - } - - if (dev == INVALID_HANDLE_VALUE) - { - if (bExclusiveRequired) - { - if (!bSilent) - { - handleWin32Error (MainDlg); - - if (bShowAlternativeSteps) - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); - else - Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); - } - return INVALID_HANDLE_VALUE; - } - - // Shared mode - dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); - if (dev != INVALID_HANDLE_VALUE) - { - if (bSharedRequiresConfirmation - && !bSilent - && AskWarnNoYes ("DEVICE_IN_USE_INPLACE_ENC") == IDNO) - { - CloseHandle (dev); - return INVALID_HANDLE_VALUE; - } - } - else - { - if (!bSilent) - { - handleWin32Error (MainDlg); - - if (bShowAlternativeSteps) - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); - else - Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); - } - return INVALID_HANDLE_VALUE; - } - } - - return dev; -} - - -static int DismountFileSystem (HANDLE dev, - int driveLetter, - BOOL bForcedAllowed, - BOOL bForcedRequiresConfirmation, - BOOL bSilent) -{ - int attempt; - BOOL bResult; - DWORD dwResult; - - CloseVolumeExplorerWindows (MainDlg, driveLetter); - - attempt = UNMOUNT_MAX_AUTO_RETRIES * 10; - - while (!(bResult = DeviceIoControl (dev, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - if (!bResult) - { - if (!bForcedAllowed) - { - if (!bSilent) - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_LOCK_OR_DISMOUNT_FILESYS", TRUE); - - return ERR_DONT_REPORT; - } - - if (bForcedRequiresConfirmation - && !bSilent - && AskWarnYesNo ("VOL_LOCK_FAILED_OFFER_FORCED_DISMOUNT") == IDNO) - { - return ERR_DONT_REPORT; - } - } - - // Dismount the volume - - attempt = UNMOUNT_MAX_AUTO_RETRIES * 10; - - while (!(bResult = DeviceIoControl (dev, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - if (!bResult) - { - if (!bSilent) - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_LOCK_OR_DISMOUNT_FILESYS", TRUE); - - return ERR_DONT_REPORT; - } - - return ERR_SUCCESS; -} - - -// Easy-to-undo modification applied to conceal the NTFS filesystem (to prevent Windows and apps from -// interfering with it until the volume has been fully encrypted). Note that this function will precisely -// undo any modifications it made to the filesystem automatically if an error occurs when writing (including -// physical drive defects). -static int ConcealNTFS (HANDLE dev) -{ - char buf [TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE]; - DWORD nbrBytesProcessed, nbrBytesProcessed2; - int i; - LARGE_INTEGER offset; - DWORD dwError; - - offset.QuadPart = 0; - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) - return ERR_OS_ERROR; - - if (ReadFile (dev, buf, TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, &nbrBytesProcessed, NULL) == 0) - return ERR_OS_ERROR; - - for (i = 0; i < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE; i++) - buf[i] ^= TC_NTFS_CONCEAL_CONSTANT; - - offset.QuadPart = 0; - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) - return ERR_OS_ERROR; - - if (WriteFile (dev, buf, TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, &nbrBytesProcessed, NULL) == 0) - { - // One or more of the sectors is/are probably damaged and cause write errors. - // We must undo the modifications we made. - - dwError = GetLastError(); - - for (i = 0; i < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE; i++) - buf[i] ^= TC_NTFS_CONCEAL_CONSTANT; - - offset.QuadPart = 0; - - do - { - Sleep (1); - } - while (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 - || WriteFile (dev, buf, TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, &nbrBytesProcessed2, NULL) == 0); - - SetLastError (dwError); - - return ERR_OS_ERROR; - } - - return ERR_SUCCESS; -} - - -void ShowInPlaceEncErrMsgWAltSteps (char *iniStrId, BOOL bErr) -{ - wchar_t msg[30000]; - - wcscpy (msg, GetString (iniStrId)); - - wcscat (msg, L"\n\n\n"); - wcscat (msg, GetString ("INPLACE_ENC_ALTERNATIVE_STEPS")); - - if (bErr) - ErrorDirect (msg); - else - WarningDirect (msg); -} - - -static void ExportProgressStats (__int64 bytesDone, __int64 totalSectors) -{ - NonSysInplaceEncBytesDone = bytesDone; - NonSysInplaceEncTotalSectors = totalSectors; -} - - -void SetNonSysInplaceEncUIStatus (int nonSysInplaceEncStatus) -{ - NonSysInplaceEncStatus = nonSysInplaceEncStatus; -} - - -BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId newWipeAlgorithm) -{ - int count; - char str[32]; - WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; - - if (delta == 0) - return TRUE; - - count = LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) + delta; - - if (count < 1) - { - RemoveNonSysInPlaceEncNotifications(); - return TRUE; - } - else - { - if (newWipeAlgorithm != TC_WIPE_NONE) - { - sprintf (str, "%d", (int) newWipeAlgorithm); - - SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), strlen(str), FALSE); - } - else if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) - { - remove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)); - } - - sprintf (str, "%d", count); - - return SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), strlen(str), FALSE); - } -} - - -// Repairs damaged sectors (i.e. those with read errors) by zeroing them. -// Note that this operating fails if there are any write errors. -int ZeroUnreadableSectors (HANDLE dev, LARGE_INTEGER startOffset, int64 size, int sectorSize, uint64 *zeroedSectorCount) -{ - int nStatus; - DWORD n; - int64 sectorCount; - LARGE_INTEGER workOffset; - byte *sectorBuffer = NULL; - DWORD dwError; - - workOffset.QuadPart = startOffset.QuadPart; - - sectorBuffer = (byte *) TCalloc (sectorSize); - - if (!sectorBuffer) - return ERR_OUTOFMEMORY; - - if (SetFilePointerEx (dev, startOffset, NULL, FILE_BEGIN) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - - for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount) - { - if (ReadFile (dev, sectorBuffer, sectorSize, &n, NULL) == 0) - { - memset (sectorBuffer, 0, sectorSize); - - if (SetFilePointerEx (dev, workOffset, NULL, FILE_BEGIN) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - if (WriteFile (dev, sectorBuffer, sectorSize, &n, NULL) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - ++(*zeroedSectorCount); - } - - workOffset.QuadPart += n; - } - - nStatus = ERR_SUCCESS; - -closing_seq: - - dwError = GetLastError(); - - if (sectorBuffer != NULL) - TCfree (sectorBuffer); - - if (nStatus != ERR_SUCCESS) - SetLastError (dwError); - - return nStatus; -} - - -static int OpenBackupHeader (HANDLE dev, const char *devicePath, Password *password, PCRYPTO_INFO *retMasterCryptoInfo, CRYPTO_INFO *headerCryptoInfo, __int64 deviceSize) -{ - LARGE_INTEGER offset; - DWORD n; - int nStatus = ERR_SUCCESS; - char *header; - DWORD dwError; - - header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); - if (!header) - return ERR_OUTOFMEMORY; - - VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - - - - offset.QuadPart = deviceSize - TC_VOLUME_HEADER_GROUP_SIZE; - - if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 - || ReadFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) - { - nStatus = ERR_OS_ERROR; - goto closing_seq; - } - - - nStatus = ReadVolumeHeader (FALSE, header, password, retMasterCryptoInfo, headerCryptoInfo); - if (nStatus != ERR_SUCCESS) - goto closing_seq; - - -closing_seq: - - dwError = GetLastError(); - - burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); - TCfree (header); - - dwError = GetLastError(); - - if (nStatus != ERR_SUCCESS) - SetLastError (dwError); - - return nStatus; -} - - -static BOOL GetFreeClusterBeforeThreshold (HANDLE volumeHandle, int64 *freeCluster, int64 clusterThreshold) -{ - const int bitmapSize = 65536; - byte bitmapBuffer[bitmapSize + sizeof (VOLUME_BITMAP_BUFFER)]; - VOLUME_BITMAP_BUFFER *bitmap = (VOLUME_BITMAP_BUFFER *) bitmapBuffer; - STARTING_LCN_INPUT_BUFFER startLcn; - startLcn.StartingLcn.QuadPart = 0; - - DWORD bytesReturned; - while (DeviceIoControl (volumeHandle, FSCTL_GET_VOLUME_BITMAP, &startLcn, sizeof (startLcn), &bitmapBuffer, sizeof (bitmapBuffer), &bytesReturned, NULL) - || GetLastError() == ERROR_MORE_DATA) - { - for (int64 bitmapIndex = 0; bitmapIndex < min (bitmapSize, (bitmap->BitmapSize.QuadPart / 8)); ++bitmapIndex) - { - if (bitmap->StartingLcn.QuadPart + bitmapIndex * 8 >= clusterThreshold) - goto err; - - if (bitmap->Buffer[bitmapIndex] != 0xff) - { - for (int bit = 0; bit < 8; ++bit) - { - if ((bitmap->Buffer[bitmapIndex] & (1 << bit)) == 0) - { - *freeCluster = bitmap->StartingLcn.QuadPart + bitmapIndex * 8 + bit; - - if (*freeCluster >= clusterThreshold) - goto err; - - return TRUE; - } - } - } - } - - startLcn.StartingLcn.QuadPart += min (bitmapSize * 8, bitmap->BitmapSize.QuadPart); - } - -err: - SetLastError (ERROR_DISK_FULL); - return FALSE; -} - - -static BOOL MoveClustersBeforeThresholdInDir (HANDLE volumeHandle, const wstring &directory, int64 clusterThreshold) -{ - WIN32_FIND_DATAW findData; - - HANDLE findHandle = FindFirstFileW (((directory.size() <= 3 ? L"" : L"\\\\?\\") + directory + L"\\*").c_str(), &findData); - if (findHandle == INVALID_HANDLE_VALUE) - return TRUE; // Error ignored - - finally_do_arg (HANDLE, findHandle, { FindClose (finally_arg); }); - - // Find all files and directories - do - { - if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - wstring subDir = findData.cFileName; - - if (subDir == L"." || subDir == L"..") - continue; - - if (!MoveClustersBeforeThresholdInDir (volumeHandle, directory + L"\\" + subDir, clusterThreshold)) - return FALSE; - } - - DWORD access = FILE_READ_ATTRIBUTES; - - if (findData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) - access = FILE_READ_DATA; - - HANDLE fsObject = CreateFileW ((directory + L"\\" + findData.cFileName).c_str(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (fsObject == INVALID_HANDLE_VALUE) - continue; - - finally_do_arg (HANDLE, fsObject, { CloseHandle (finally_arg); }); - - STARTING_VCN_INPUT_BUFFER startVcn; - startVcn.StartingVcn.QuadPart = 0; - RETRIEVAL_POINTERS_BUFFER retPointers; - DWORD bytesReturned; - - // Find clusters allocated beyond the threshold - while (DeviceIoControl (fsObject, FSCTL_GET_RETRIEVAL_POINTERS, &startVcn, sizeof (startVcn), &retPointers, sizeof (retPointers), &bytesReturned, NULL) - || GetLastError() == ERROR_MORE_DATA) - { - if (retPointers.ExtentCount == 0) - break; - - if (retPointers.Extents[0].Lcn.QuadPart != -1) - { - int64 extentStartCluster = retPointers.Extents[0].Lcn.QuadPart; - int64 extentLen = retPointers.Extents[0].NextVcn.QuadPart - retPointers.StartingVcn.QuadPart; - int64 extentEndCluster = extentStartCluster + extentLen - 1; - - if (extentEndCluster >= clusterThreshold) - { - // Move clusters before the threshold - for (int64 movedCluster = max (extentStartCluster, clusterThreshold); movedCluster <= extentEndCluster; ++movedCluster) - { - for (int retry = 0; ; ++retry) - { - MOVE_FILE_DATA moveData; - - if (GetFreeClusterBeforeThreshold (volumeHandle, &moveData.StartingLcn.QuadPart, clusterThreshold)) - { - moveData.FileHandle = fsObject; - moveData.StartingVcn.QuadPart = movedCluster - extentStartCluster + retPointers.StartingVcn.QuadPart; - moveData.ClusterCount = 1; - - if (DeviceIoControl (volumeHandle, FSCTL_MOVE_FILE, &moveData, sizeof (moveData), NULL, 0, &bytesReturned, NULL)) - break; - } - - if (retry > 600) - return FALSE; - - // There are possible race conditions as we work on a live filesystem - Sleep (100); - } - } - } - } - - startVcn.StartingVcn = retPointers.Extents[0].NextVcn; - } - - } while (FindNextFileW (findHandle, &findData)); - - return TRUE; -} - - -BOOL MoveClustersBeforeThreshold (HANDLE volumeHandle, PWSTR volumeDevicePath, int64 clusterThreshold) -{ - int drive = GetDiskDeviceDriveLetter (volumeDevicePath); - if (drive == -1) - { - SetLastError (ERROR_INVALID_PARAMETER); - return FALSE; - } - - wstring volumeRoot = L"X:"; - volumeRoot[0] = L'A' + drive; - - return MoveClustersBeforeThresholdInDir (volumeHandle, volumeRoot, clusterThreshold); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + + +/* In this file, _WIN32_WINNT is defined as 0x0600 to make filesystem shrink available (Vista +or later). _WIN32_WINNT cannot be defined as 0x0600 for the entire user-space projects +because it breaks the main font app when the app is running on XP (likely an MS bug). +IMPORTANT: Due to this issue, functions in this file must not directly interact with GUI. */ +#define TC_LOCAL_WIN32_WINNT_OVERRIDE 1 +#if (_WIN32_WINNT < 0x0600) +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +#endif + + +#include +#include +#include + +#include "Tcdefs.h" +#include "Platform/Finally.h" + +#include "Common.h" +#include "Crc.h" +#include "Dlgcode.h" +#include "Language.h" +#include "Tcformat.h" +#include "Volumes.h" + +#include "InPlace.h" + +using namespace std; +using namespace TrueCrypt; + +#define TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE (2048 * BYTES_PER_KB) +#define TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE (2 * TC_MAX_VOLUME_SECTOR_SIZE) +#define TC_NTFS_CONCEAL_CONSTANT 0xFF +#define TC_NONSYS_INPLACE_ENC_HEADER_UPDATE_INTERVAL (64 * BYTES_PER_MB) +#define TC_NONSYS_INPLACE_ENC_MIN_VOL_SIZE (TC_TOTAL_VOLUME_HEADERS_SIZE + TC_MIN_NTFS_FS_SIZE * 2) + + +// If the returned value is greater than 0, it is the desired volume size in NTFS sectors (not in bytes) +// after shrinking has been performed. If there's any error, returns -1. +static __int64 NewFileSysSizeAfterShrink (HANDLE dev, const char *devicePath, int64 *totalClusterCount, DWORD *bytesPerCluster, BOOL silent) +{ + NTFS_VOLUME_DATA_BUFFER ntfsVolData; + DWORD nBytesReturned; + __int64 fileSysSize, desiredNbrSectors; + + // Filesystem size and sector size + + if (!DeviceIoControl (dev, + FSCTL_GET_NTFS_VOLUME_DATA, + NULL, + 0, + (LPVOID) &ntfsVolData, + sizeof (ntfsVolData), + &nBytesReturned, + NULL)) + { + if (!silent) + handleWin32Error (MainDlg); + + return -1; + } + + fileSysSize = ntfsVolData.NumberSectors.QuadPart * ntfsVolData.BytesPerSector; + + desiredNbrSectors = (fileSysSize - TC_TOTAL_VOLUME_HEADERS_SIZE) / ntfsVolData.BytesPerSector; + + if (desiredNbrSectors <= 0) + return -1; + + if (totalClusterCount) + *totalClusterCount = ntfsVolData.TotalClusters.QuadPart; + if (bytesPerCluster) + *bytesPerCluster = ntfsVolData.BytesPerCluster; + + return desiredNbrSectors; +} + + +BOOL CheckRequirementsForNonSysInPlaceEnc (const char *devicePath, BOOL silent) +{ + NTFS_VOLUME_DATA_BUFFER ntfsVolData; + DWORD nBytesReturned; + HANDLE dev; + char szFileSysName [256]; + WCHAR devPath [MAX_PATH]; + char dosDev [TC_MAX_PATH] = {0}; + char devName [MAX_PATH] = {0}; + int driveLetterNo = -1; + char szRootPath[4] = {0, ':', '\\', 0}; + __int64 deviceSize; + int partitionNumber = -1, driveNumber = -1; + + + /* ---------- Checks that do not require admin rights ----------- */ + + + /* Operating system */ + + if (CurrentOSMajor < 6) + { + if (!silent) + ShowInPlaceEncErrMsgWAltSteps ("OS_NOT_SUPPORTED_FOR_NONSYS_INPLACE_ENC", FALSE); + + return FALSE; + } + + + /* Volume type (must be a partition or a dynamic volume) */ + + if (sscanf (devicePath, "\\Device\\HarddiskVolume%d", &partitionNumber) != 1 + && sscanf (devicePath, "\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2) + { + if (!silent) + Error ("INPLACE_ENC_INVALID_PATH"); + + return FALSE; + } + + if (partitionNumber == 0) + { + if (!silent) + Warning ("RAW_DEV_NOT_SUPPORTED_FOR_INPLACE_ENC"); + + return FALSE; + } + + + /* Admin rights */ + + if (!IsAdmin()) + { + // We rely on the wizard process to call us only when the whole wizard process has been elevated (so UAC + // status can be ignored). In case the IsAdmin() detection somehow fails, we allow the user to continue. + + if (!silent) + Warning ("ADMIN_PRIVILEGES_WARN_DEVICES"); + } + + + /* ---------- Checks that may require admin rights ----------- */ + + + /* Access to the partition */ + + strcpy ((char *) devPath, devicePath); + ToUNICODE ((char *) devPath); + + driveLetterNo = GetDiskDeviceDriveLetter (devPath); + + if (driveLetterNo >= 0) + szRootPath[0] = (char) driveLetterNo + 'A'; + + if (FakeDosNameForDevice (devicePath, dosDev, devName, FALSE) != 0) + { + if (!silent) + { + handleWin32Error (MainDlg); + Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); + } + return FALSE; + } + + dev = OpenPartitionVolume (devName, + FALSE, // Do not require exclusive access + TRUE, // Require shared access (must be TRUE; otherwise, volume properties will not be possible to obtain) + FALSE, // Do not ask the user to confirm shared access (if exclusive fails) + FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages) + silent); // Silent mode + + if (dev == INVALID_HANDLE_VALUE) + return FALSE; + + + /* File system type */ + + GetVolumeInformation (szRootPath, NULL, 0, NULL, NULL, NULL, szFileSysName, sizeof(szFileSysName)); + + if (strncmp (szFileSysName, "NTFS", 4)) + { + // The previous filesystem type detection method failed (or it's not NTFS) -- try an alternative method + + if (!DeviceIoControl (dev, + FSCTL_GET_NTFS_VOLUME_DATA, + NULL, + 0, + (LPVOID) &ntfsVolData, + sizeof (ntfsVolData), + &nBytesReturned, + NULL)) + { + if (!silent) + { + // The filesystem is not NTFS or the filesystem type could not be determined (or the NTFS filesystem + // is dismounted). + + if (IsDeviceMounted (devName)) + ShowInPlaceEncErrMsgWAltSteps ("ONLY_NTFS_SUPPORTED_FOR_NONSYS_INPLACE_ENC", FALSE); + else + Warning ("ONLY_MOUNTED_VOL_SUPPORTED_FOR_NONSYS_INPLACE_ENC"); + } + + CloseHandle (dev); + return FALSE; + } + } + + + /* Attempt to determine whether the filesystem can be safely shrunk */ + + if (NewFileSysSizeAfterShrink (dev, devicePath, NULL, NULL, silent) == -1) + { + // Cannot determine whether shrinking is required + if (!silent) + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); + + CloseHandle (dev); + return FALSE; + } + + + /* Partition size */ + + deviceSize = GetDeviceSize (devicePath); + if (deviceSize < 0) + { + // Cannot determine the size of the partition + if (!silent) + Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); + + CloseHandle (dev); + return FALSE; + } + + if (deviceSize < TC_NONSYS_INPLACE_ENC_MIN_VOL_SIZE) + { + // The partition is too small + if (!silent) + { + ShowInPlaceEncErrMsgWAltSteps ("PARTITION_TOO_SMALL_FOR_NONSYS_INPLACE_ENC", FALSE); + } + + CloseHandle (dev); + return FALSE; + } + + + /* Free space on the filesystem */ + + if (!DeviceIoControl (dev, + FSCTL_GET_NTFS_VOLUME_DATA, + NULL, + 0, + (LPVOID) &ntfsVolData, + sizeof (ntfsVolData), + &nBytesReturned, + NULL)) + { + if (!silent) + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL", TRUE); + + CloseHandle (dev); + return FALSE; + } + + if (ntfsVolData.FreeClusters.QuadPart * ntfsVolData.BytesPerCluster < TC_TOTAL_VOLUME_HEADERS_SIZE) + { + if (!silent) + ShowInPlaceEncErrMsgWAltSteps ("NOT_ENOUGH_FREE_FILESYS_SPACE_FOR_SHRINK", TRUE); + + CloseHandle (dev); + return FALSE; + } + + + /* Filesystem sector size */ + + if (ntfsVolData.BytesPerSector > TC_MAX_VOLUME_SECTOR_SIZE + || ntfsVolData.BytesPerSector % ENCRYPTION_DATA_UNIT_SIZE != 0) + { + if (!silent) + ShowInPlaceEncErrMsgWAltSteps ("ERR_UNSUPPORTED_SECTOR_SIZE_GENERIC", TRUE); + + CloseHandle (dev); + return FALSE; + } + + + CloseHandle (dev); + return TRUE; +} + + +int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, volatile HANDLE *outHandle, WipeAlgorithmId wipeAlgorithm) +{ + SHRINK_VOLUME_INFORMATION shrinkVolInfo; + signed __int64 sizeToShrinkTo; + int nStatus = ERR_SUCCESS; + PCRYPTO_INFO cryptoInfo = NULL; + PCRYPTO_INFO cryptoInfo2 = NULL; + HANDLE dev = INVALID_HANDLE_VALUE; + DWORD dwError; + char *header; + char dosDev[TC_MAX_PATH] = {0}; + char devName[MAX_PATH] = {0}; + int driveLetter = -1; + WCHAR deviceName[MAX_PATH]; + uint64 dataAreaSize; + __int64 deviceSize; + LARGE_INTEGER offset; + DWORD dwResult; + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PREPARING); + + + if (!CheckRequirementsForNonSysInPlaceEnc (volParams->volumePath, FALSE)) + return ERR_DONT_REPORT; + + + header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); + if (!header) + return ERR_OUTOFMEMORY; + + VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + + deviceSize = GetDeviceSize (volParams->volumePath); + if (deviceSize < 0) + { + // Cannot determine the size of the partition + nStatus = ERR_PARAMETER_INCORRECT; + goto closing_seq; + } + + if (deviceSize < TC_NONSYS_INPLACE_ENC_MIN_VOL_SIZE) + { + ShowInPlaceEncErrMsgWAltSteps ("PARTITION_TOO_SMALL_FOR_NONSYS_INPLACE_ENC", TRUE); + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + + dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, deviceSize); + + strcpy ((char *)deviceName, volParams->volumePath); + ToUNICODE ((char *)deviceName); + + driveLetter = GetDiskDeviceDriveLetter (deviceName); + + + if (FakeDosNameForDevice (volParams->volumePath, dosDev, devName, FALSE) != 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + if (IsDeviceMounted (devName)) + { + dev = OpenPartitionVolume (devName, + FALSE, // Do not require exclusive access (must be FALSE; otherwise, it will not be possible to dismount the volume or obtain its properties and FSCTL_ALLOW_EXTENDED_DASD_IO will fail too) + TRUE, // Require shared access (must be TRUE; otherwise, it will not be possible to dismount the volume or obtain its properties and FSCTL_ALLOW_EXTENDED_DASD_IO will fail too) + FALSE, // Do not ask the user to confirm shared access (if exclusive fails) + FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages) + FALSE); // Non-silent mode + + if (dev == INVALID_HANDLE_VALUE) + { + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + } + else + { + // The volume is not mounted so we can't work with the filesystem. + Error ("ONLY_MOUNTED_VOL_SUPPORTED_FOR_NONSYS_INPLACE_ENC"); + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + + + /* Gain "raw" access to the partition (the NTFS driver guards hidden sectors). */ + + if (!DeviceIoControl (dev, + FSCTL_ALLOW_EXTENDED_DASD_IO, + NULL, + 0, + NULL, + 0, + &dwResult, + NULL)) + { + handleWin32Error (MainDlg); + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + + + + /* Shrink the filesystem */ + + int64 totalClusterCount; + DWORD bytesPerCluster; + + sizeToShrinkTo = NewFileSysSizeAfterShrink (dev, volParams->volumePath, &totalClusterCount, &bytesPerCluster, FALSE); + + if (sizeToShrinkTo == -1) + { + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_RESIZING); + + memset (&shrinkVolInfo, 0, sizeof (shrinkVolInfo)); + + shrinkVolInfo.ShrinkRequestType = ShrinkPrepare; + shrinkVolInfo.NewNumberOfSectors = sizeToShrinkTo; + + if (!DeviceIoControl (dev, + FSCTL_SHRINK_VOLUME, + (LPVOID) &shrinkVolInfo, + sizeof (shrinkVolInfo), + NULL, + 0, + &dwResult, + NULL)) + { + handleWin32Error (MainDlg); + ShowInPlaceEncErrMsgWAltSteps ("CANNOT_RESIZE_FILESYS", TRUE); + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + + BOOL clustersMovedBeforeVolumeEnd = FALSE; + + while (true) + { + shrinkVolInfo.ShrinkRequestType = ShrinkCommit; + shrinkVolInfo.NewNumberOfSectors = 0; + + if (!DeviceIoControl (dev, FSCTL_SHRINK_VOLUME, &shrinkVolInfo, sizeof (shrinkVolInfo), NULL, 0, &dwResult, NULL)) + { + // If there are any occupied clusters beyond the new desired end of the volume, the call fails with + // ERROR_ACCESS_DENIED (STATUS_ALREADY_COMMITTED). + if (GetLastError () == ERROR_ACCESS_DENIED) + { + if (!clustersMovedBeforeVolumeEnd) + { + if (MoveClustersBeforeThreshold (dev, deviceName, totalClusterCount - (bytesPerCluster > TC_TOTAL_VOLUME_HEADERS_SIZE ? 1 : TC_TOTAL_VOLUME_HEADERS_SIZE / bytesPerCluster))) + { + clustersMovedBeforeVolumeEnd = TRUE; + continue; + } + + handleWin32Error (MainDlg); + } + } + else + handleWin32Error (MainDlg); + + ShowInPlaceEncErrMsgWAltSteps ("CANNOT_RESIZE_FILESYS", TRUE); + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + + break; + } + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PREPARING); + + + /* Gain exclusive access to the volume */ + + nStatus = DismountFileSystem (dev, + driveLetter, + TRUE, + TRUE, + FALSE); + + if (nStatus != ERR_SUCCESS) + { + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + + + + /* Create header backup on the partition. Until the volume is fully encrypted, the backup header will provide + us with the master key, encrypted range, and other data for pause/resume operations. We cannot create the + primary header until the entire partition is encrypted (because we encrypt backwards and the primary header + area is occuppied by data until the very end of the process). */ + + // Prepare the backup header + for (int wipePass = 0; wipePass < (wipeAlgorithm == TC_WIPE_NONE ? 1 : PRAND_DISK_WIPE_PASSES); wipePass++) + { + nStatus = CreateVolumeHeaderInMemory (FALSE, + header, + volParams->ea, + FIRST_MODE_OF_OPERATION_ID, + volParams->password, + volParams->pkcs5, + wipePass == 0 ? NULL : (char *) cryptoInfo->master_keydata, + &cryptoInfo, + dataAreaSize, + 0, + TC_VOLUME_DATA_OFFSET + dataAreaSize, // Start of the encrypted area = the first byte of the backup heeader (encrypting from the end) + 0, // No data is encrypted yet + 0, + volParams->headerFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC, + wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_DISK_WIPE_PASSES - 1)); + + if (nStatus != 0) + goto closing_seq; + + offset.QuadPart = TC_VOLUME_DATA_OFFSET + dataAreaSize; + + if (!SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + // Write the backup header to the partition + if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + // Fill the reserved sectors of the backup header area with random data + nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, TRUE); + + if (nStatus != ERR_SUCCESS) + goto closing_seq; + } + + + /* Now we will try to decrypt the backup header to verify it has been correctly written. */ + + nStatus = OpenBackupHeader (dev, volParams->volumePath, volParams->password, &cryptoInfo2, NULL, deviceSize); + + if (nStatus != ERR_SUCCESS + || cryptoInfo->EncryptedAreaStart.Value != cryptoInfo2->EncryptedAreaStart.Value + || cryptoInfo2->EncryptedAreaStart.Value == 0) + { + if (nStatus == ERR_SUCCESS) + nStatus = ERR_PARAMETER_INCORRECT; + + goto closing_seq; + } + + // The backup header is valid so we know we should be able to safely resume in-place encryption + // of this partition even if the system/app crashes. + + + + /* Conceal the NTFS filesystem (by performing an easy-to-undo modification). This will prevent Windows + and apps from interfering with the volume until it has been fully encrypted. */ + + nStatus = ConcealNTFS (dev); + + if (nStatus != ERR_SUCCESS) + goto closing_seq; + + + + // /* If a drive letter is assigned to the device, remove it (so that users do not try to open it, which + //would cause Windows to ask them if they want to format the volume and other dangerous things). */ + + //if (driveLetter >= 0) + //{ + // char rootPath[] = { driveLetter + 'A', ':', '\\', 0 }; + + // // Try to remove the assigned drive letter + // if (DeleteVolumeMountPoint (rootPath)) + // driveLetter = -1; + //} + + + + /* Update config files and app data */ + + // In the config file, increase the number of partitions where in-place encryption is in progress + + SaveNonSysInPlaceEncSettings (1, wipeAlgorithm); + + + // Add the wizard to the system startup sequence if appropriate + + if (!IsNonInstallMode ()) + ManageStartupSeqWiz (FALSE, "/prinplace"); + + + nStatus = ERR_SUCCESS; + + +closing_seq: + + dwError = GetLastError(); + + if (cryptoInfo != NULL) + { + crypto_close (cryptoInfo); + cryptoInfo = NULL; + } + + if (cryptoInfo2 != NULL) + { + crypto_close (cryptoInfo2); + cryptoInfo2 = NULL; + } + + burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + TCfree (header); + + if (dosDev[0]) + RemoveFakeDosName (volParams->volumePath, dosDev); + + *outHandle = dev; + + if (nStatus != ERR_SUCCESS) + SetLastError (dwError); + + return nStatus; +} + + +int EncryptPartitionInPlaceResume (HANDLE dev, + volatile FORMAT_VOL_PARAMETERS *volParams, + WipeAlgorithmId wipeAlgorithm, + volatile BOOL *bTryToCorrectReadErrors) +{ + PCRYPTO_INFO masterCryptoInfo = NULL, headerCryptoInfo = NULL, tmpCryptoInfo = NULL; + UINT64_STRUCT unitNo; + char *buf = NULL, *header = NULL; + byte *wipeBuffer = NULL; + byte wipeRandChars [TC_WIPE_RAND_CHAR_COUNT]; + byte wipeRandCharsUpdate [TC_WIPE_RAND_CHAR_COUNT]; + char dosDev[TC_MAX_PATH] = {0}; + char devName[MAX_PATH] = {0}; + WCHAR deviceName[MAX_PATH]; + int nStatus = ERR_SUCCESS; + __int64 deviceSize; + uint64 remainingBytes, lastHeaderUpdateDistance = 0, zeroedSectorCount = 0; + uint32 workChunkSize; + DWORD dwError, dwResult; + BOOL bPause = FALSE, bEncryptedAreaSizeChanged = FALSE; + LARGE_INTEGER offset; + int sectorSize; + int i; + DWORD n; + char *devicePath = volParams->volumePath; + Password *password = volParams->password; + DISK_GEOMETRY driveGeometry; + + + bInPlaceEncNonSysResumed = TRUE; + + buf = (char *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE); + if (!buf) + { + nStatus = ERR_OUTOFMEMORY; + goto closing_seq; + } + + header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); + if (!header) + { + nStatus = ERR_OUTOFMEMORY; + goto closing_seq; + } + + VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + + if (wipeAlgorithm != TC_WIPE_NONE) + { + wipeBuffer = (byte *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE); + if (!wipeBuffer) + { + nStatus = ERR_OUTOFMEMORY; + goto closing_seq; + } + } + + headerCryptoInfo = crypto_open(); + + if (headerCryptoInfo == NULL) + { + nStatus = ERR_OUTOFMEMORY; + goto closing_seq; + } + + deviceSize = GetDeviceSize (devicePath); + if (deviceSize < 0) + { + // Cannot determine the size of the partition + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + if (dev == INVALID_HANDLE_VALUE) + { + strcpy ((char *)deviceName, devicePath); + ToUNICODE ((char *)deviceName); + + if (FakeDosNameForDevice (devicePath, dosDev, devName, FALSE) != 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + dev = OpenPartitionVolume (devName, + FALSE, // Do not require exclusive access + FALSE, // Do not require shared access + TRUE, // Ask the user to confirm shared access (if exclusive fails) + FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages) + FALSE); // Non-silent mode + + if (dev == INVALID_HANDLE_VALUE) + { + nStatus = ERR_DONT_REPORT; + goto closing_seq; + } + } + + // This should never be needed, but is still performed for extra safety (without checking the result) + DeviceIoControl (dev, + FSCTL_ALLOW_EXTENDED_DASD_IO, + NULL, + 0, + NULL, + 0, + &dwResult, + NULL); + + + if (!DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveGeometry, sizeof (driveGeometry), &dwResult, NULL)) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + sectorSize = driveGeometry.BytesPerSector; + + + nStatus = OpenBackupHeader (dev, devicePath, password, &masterCryptoInfo, headerCryptoInfo, deviceSize); + + if (nStatus != ERR_SUCCESS) + goto closing_seq; + + + + remainingBytes = masterCryptoInfo->VolumeSize.Value - masterCryptoInfo->EncryptedAreaLength.Value; + + lastHeaderUpdateDistance = 0; + + + ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value / SECTOR_SIZE); + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_ENCRYPTING); + + bFirstNonSysInPlaceEncResumeDone = TRUE; + + + /* The in-place encryption core */ + + while (remainingBytes > 0) + { + workChunkSize = (uint32) min (remainingBytes, TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE); + + if (workChunkSize % ENCRYPTION_DATA_UNIT_SIZE != 0) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto closing_seq; + } + + unitNo.Value = (remainingBytes - workChunkSize + TC_VOLUME_DATA_OFFSET) / ENCRYPTION_DATA_UNIT_SIZE; + + + // Read the plaintext into RAM + +inplace_enc_read: + + offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize - TC_VOLUME_DATA_OFFSET; + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + if (ReadFile (dev, buf, workChunkSize, &n, NULL) == 0) + { + // Read error + + DWORD dwTmpErr = GetLastError (); + + if (IsDiskReadError (dwTmpErr) && !bVolTransformThreadCancel) + { + // Physical defect or data corruption + + if (!*bTryToCorrectReadErrors) + { + *bTryToCorrectReadErrors = (AskWarnYesNo ("ENABLE_BAD_SECTOR_ZEROING") == IDYES); + } + + if (*bTryToCorrectReadErrors) + { + // Try to correct the read errors physically + + offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize - TC_VOLUME_DATA_OFFSET; + + nStatus = ZeroUnreadableSectors (dev, offset, workChunkSize, sectorSize, &zeroedSectorCount); + + if (nStatus != ERR_SUCCESS) + { + // Due to write errors, we can't correct the read errors + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + goto inplace_enc_read; + } + } + + SetLastError (dwTmpErr); // Preserve the original error code + + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + if (remainingBytes - workChunkSize < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE) + { + // We reached the inital portion of the filesystem, which we had concealed (in order to prevent + // Windows from interfering with the volume). Now we need to undo that modification. + + for (i = 0; i < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE - (remainingBytes - workChunkSize); i++) + buf[i] ^= TC_NTFS_CONCEAL_CONSTANT; + } + + + // Encrypt the plaintext in RAM + + EncryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); + + + // If enabled, wipe the area to which we will write the ciphertext + + if (wipeAlgorithm != TC_WIPE_NONE) + { + byte wipePass; + + offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize; + + for (wipePass = 1; wipePass <= GetWipePassCount (wipeAlgorithm); ++wipePass) + { + if (!WipeBuffer (wipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, workChunkSize)) + { + ULONG i; + for (i = 0; i < workChunkSize; ++i) + { + wipeBuffer[i] = buf[i] + wipePass; + } + + EncryptDataUnits (wipeBuffer, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); + memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); + } + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 + || WriteFile (dev, wipeBuffer, workChunkSize, &n, NULL) == 0) + { + // Write error + dwError = GetLastError(); + + // Undo failed write operation + if (workChunkSize > TC_VOLUME_DATA_OFFSET && SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) + { + DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); + WriteFile (dev, buf + TC_VOLUME_DATA_OFFSET, workChunkSize - TC_VOLUME_DATA_OFFSET, &n, NULL); + } + + SetLastError (dwError); + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + } + + memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate)); + } + + + // Write the ciphertext + + offset.QuadPart = masterCryptoInfo->EncryptedAreaStart.Value - workChunkSize; + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + if (WriteFile (dev, buf, workChunkSize, &n, NULL) == 0) + { + // Write error + dwError = GetLastError(); + + // Undo failed write operation + if (workChunkSize > TC_VOLUME_DATA_OFFSET && SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)) + { + DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo); + WriteFile (dev, buf + TC_VOLUME_DATA_OFFSET, workChunkSize - TC_VOLUME_DATA_OFFSET, &n, NULL); + } + + SetLastError (dwError); + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + + masterCryptoInfo->EncryptedAreaStart.Value -= workChunkSize; + masterCryptoInfo->EncryptedAreaLength.Value += workChunkSize; + + remainingBytes -= workChunkSize; + lastHeaderUpdateDistance += workChunkSize; + + bEncryptedAreaSizeChanged = TRUE; + + if (lastHeaderUpdateDistance >= TC_NONSYS_INPLACE_ENC_HEADER_UPDATE_INTERVAL) + { + nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize); + + if (nStatus != ERR_SUCCESS) + goto closing_seq; + + lastHeaderUpdateDistance = 0; + } + + ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value / SECTOR_SIZE); + + if (bVolTransformThreadCancel) + { + bPause = TRUE; + break; + } + } + + nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize); + + + if (nStatus != ERR_SUCCESS) + goto closing_seq; + + + if (!bPause) + { + /* The data area has been fully encrypted; create and write the primary volume header */ + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINALIZING); + + for (int wipePass = 0; wipePass < (wipeAlgorithm == TC_WIPE_NONE ? 1 : PRAND_DISK_WIPE_PASSES); wipePass++) + { + nStatus = CreateVolumeHeaderInMemory (FALSE, + header, + headerCryptoInfo->ea, + headerCryptoInfo->mode, + password, + masterCryptoInfo->pkcs5, + (char *) masterCryptoInfo->master_keydata, + &tmpCryptoInfo, + masterCryptoInfo->VolumeSize.Value, + 0, + masterCryptoInfo->EncryptedAreaStart.Value, + masterCryptoInfo->EncryptedAreaLength.Value, + masterCryptoInfo->RequiredProgramVersion, + masterCryptoInfo->HeaderFlags | TC_HEADER_FLAG_NONSYS_INPLACE_ENC, + wipeAlgorithm == TC_WIPE_NONE ? FALSE : (wipePass < PRAND_DISK_WIPE_PASSES - 1)); + + if (nStatus != ERR_SUCCESS) + goto closing_seq; + + + offset.QuadPart = TC_VOLUME_HEADER_OFFSET; + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 + || WriteFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + // Fill the reserved sectors of the header area with random data + nStatus = WriteRandomDataToReservedHeaderAreas (dev, headerCryptoInfo, masterCryptoInfo->VolumeSize.Value, TRUE, FALSE); + + if (nStatus != ERR_SUCCESS) + goto closing_seq; + } + + // Update the configuration files + + SaveNonSysInPlaceEncSettings (-1, wipeAlgorithm); + + + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINISHED); + + nStatus = ERR_SUCCESS; + } + else + { + // The process has been paused by the user or aborted by the wizard (e.g. on app exit) + + nStatus = ERR_USER_ABORT; + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED); + } + + +closing_seq: + + dwError = GetLastError(); + + if (bEncryptedAreaSizeChanged + && dev != INVALID_HANDLE_VALUE + && masterCryptoInfo != NULL + && headerCryptoInfo != NULL + && deviceSize > 0) + { + // Execution of the core loop may have been interrupted due to an error or user action without updating the header + FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize); + } + + if (masterCryptoInfo != NULL) + { + crypto_close (masterCryptoInfo); + masterCryptoInfo = NULL; + } + + if (headerCryptoInfo != NULL) + { + crypto_close (headerCryptoInfo); + headerCryptoInfo = NULL; + } + + if (tmpCryptoInfo != NULL) + { + crypto_close (tmpCryptoInfo); + tmpCryptoInfo = NULL; + } + + if (dosDev[0]) + RemoveFakeDosName (devicePath, dosDev); + + if (dev != INVALID_HANDLE_VALUE) + { + CloseHandle (dev); + dev = INVALID_HANDLE_VALUE; + } + + if (buf != NULL) + TCfree (buf); + + if (header != NULL) + { + burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + TCfree (header); + } + + if (wipeBuffer != NULL) + TCfree (wipeBuffer); + + if (zeroedSectorCount > 0) + { + wchar_t msg[30000] = {0}; + wchar_t sizeStr[500] = {0}; + + GetSizeString (zeroedSectorCount * sectorSize, sizeStr); + + wsprintfW (msg, + GetString ("ZEROED_BAD_SECTOR_COUNT"), + zeroedSectorCount, + sizeStr); + + WarningDirect (msg); + } + + if (nStatus != ERR_SUCCESS && nStatus != ERR_USER_ABORT) + SetLastError (dwError); + + return nStatus; +} + + +int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_INFO *masterCryptoInfo, __int64 deviceSize) +{ + LARGE_INTEGER offset; + DWORD n; + int nStatus = ERR_SUCCESS; + byte *header; + DWORD dwError; + uint32 headerCrc32; + byte *fieldPos; + + header = (byte *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); + + if (!header) + return ERR_OUTOFMEMORY; + + VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + + + fieldPos = (byte *) header + TC_HEADER_OFFSET_ENCRYPTED_AREA_START; + + offset.QuadPart = deviceSize - TC_VOLUME_HEADER_GROUP_SIZE; + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 + || ReadFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + + DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); + + if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto closing_seq; + } + + mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaStart.Value)); + mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaLength.Value)); + + + headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); + fieldPos = (byte *) header + TC_HEADER_OFFSET_HEADER_CRC; + mputLong (fieldPos, headerCrc32); + + EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo); + + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 + || WriteFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + +closing_seq: + + dwError = GetLastError(); + + burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + TCfree (header); + + if (nStatus != ERR_SUCCESS) + SetLastError (dwError); + + return nStatus; +} + + +static HANDLE OpenPartitionVolume (const char *devName, + BOOL bExclusiveRequired, + BOOL bSharedRequired, + BOOL bSharedRequiresConfirmation, + BOOL bShowAlternativeSteps, + BOOL bSilent) +{ + HANDLE dev = INVALID_HANDLE_VALUE; + int retryCount = 0; + + if (bExclusiveRequired) + bSharedRequired = FALSE; + + if (bExclusiveRequired || !bSharedRequired) + { + // Exclusive access + // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries). + while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES) + { + dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); + + if (retryCount > 1) + Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY); + } + } + + if (dev == INVALID_HANDLE_VALUE) + { + if (bExclusiveRequired) + { + if (!bSilent) + { + handleWin32Error (MainDlg); + + if (bShowAlternativeSteps) + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); + else + Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); + } + return INVALID_HANDLE_VALUE; + } + + // Shared mode + dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); + if (dev != INVALID_HANDLE_VALUE) + { + if (bSharedRequiresConfirmation + && !bSilent + && AskWarnNoYes ("DEVICE_IN_USE_INPLACE_ENC") == IDNO) + { + CloseHandle (dev); + return INVALID_HANDLE_VALUE; + } + } + else + { + if (!bSilent) + { + handleWin32Error (MainDlg); + + if (bShowAlternativeSteps) + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL_ALT", TRUE); + else + Error ("INPLACE_ENC_CANT_ACCESS_OR_GET_INFO_ON_VOL"); + } + return INVALID_HANDLE_VALUE; + } + } + + return dev; +} + + +static int DismountFileSystem (HANDLE dev, + int driveLetter, + BOOL bForcedAllowed, + BOOL bForcedRequiresConfirmation, + BOOL bSilent) +{ + int attempt; + BOOL bResult; + DWORD dwResult; + + CloseVolumeExplorerWindows (MainDlg, driveLetter); + + attempt = UNMOUNT_MAX_AUTO_RETRIES * 10; + + while (!(bResult = DeviceIoControl (dev, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) + { + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; + } + + if (!bResult) + { + if (!bForcedAllowed) + { + if (!bSilent) + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_LOCK_OR_DISMOUNT_FILESYS", TRUE); + + return ERR_DONT_REPORT; + } + + if (bForcedRequiresConfirmation + && !bSilent + && AskWarnYesNo ("VOL_LOCK_FAILED_OFFER_FORCED_DISMOUNT") == IDNO) + { + return ERR_DONT_REPORT; + } + } + + // Dismount the volume + + attempt = UNMOUNT_MAX_AUTO_RETRIES * 10; + + while (!(bResult = DeviceIoControl (dev, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) + { + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; + } + + if (!bResult) + { + if (!bSilent) + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_CANT_LOCK_OR_DISMOUNT_FILESYS", TRUE); + + return ERR_DONT_REPORT; + } + + return ERR_SUCCESS; +} + + +// Easy-to-undo modification applied to conceal the NTFS filesystem (to prevent Windows and apps from +// interfering with it until the volume has been fully encrypted). Note that this function will precisely +// undo any modifications it made to the filesystem automatically if an error occurs when writing (including +// physical drive defects). +static int ConcealNTFS (HANDLE dev) +{ + char buf [TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE]; + DWORD nbrBytesProcessed, nbrBytesProcessed2; + int i; + LARGE_INTEGER offset; + DWORD dwError; + + offset.QuadPart = 0; + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) + return ERR_OS_ERROR; + + if (ReadFile (dev, buf, TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, &nbrBytesProcessed, NULL) == 0) + return ERR_OS_ERROR; + + for (i = 0; i < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE; i++) + buf[i] ^= TC_NTFS_CONCEAL_CONSTANT; + + offset.QuadPart = 0; + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0) + return ERR_OS_ERROR; + + if (WriteFile (dev, buf, TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, &nbrBytesProcessed, NULL) == 0) + { + // One or more of the sectors is/are probably damaged and cause write errors. + // We must undo the modifications we made. + + dwError = GetLastError(); + + for (i = 0; i < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE; i++) + buf[i] ^= TC_NTFS_CONCEAL_CONSTANT; + + offset.QuadPart = 0; + + do + { + Sleep (1); + } + while (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 + || WriteFile (dev, buf, TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, &nbrBytesProcessed2, NULL) == 0); + + SetLastError (dwError); + + return ERR_OS_ERROR; + } + + return ERR_SUCCESS; +} + + +void ShowInPlaceEncErrMsgWAltSteps (char *iniStrId, BOOL bErr) +{ + wchar_t msg[30000]; + + wcscpy (msg, GetString (iniStrId)); + + wcscat (msg, L"\n\n\n"); + wcscat (msg, GetString ("INPLACE_ENC_ALTERNATIVE_STEPS")); + + if (bErr) + ErrorDirect (msg); + else + WarningDirect (msg); +} + + +static void ExportProgressStats (__int64 bytesDone, __int64 totalSectors) +{ + NonSysInplaceEncBytesDone = bytesDone; + NonSysInplaceEncTotalSectors = totalSectors; +} + + +void SetNonSysInplaceEncUIStatus (int nonSysInplaceEncStatus) +{ + NonSysInplaceEncStatus = nonSysInplaceEncStatus; +} + + +BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId newWipeAlgorithm) +{ + int count; + char str[32]; + WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; + + if (delta == 0) + return TRUE; + + count = LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) + delta; + + if (count < 1) + { + RemoveNonSysInPlaceEncNotifications(); + return TRUE; + } + else + { + if (newWipeAlgorithm != TC_WIPE_NONE) + { + sprintf (str, "%d", (int) newWipeAlgorithm); + + SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), strlen(str), FALSE); + } + else if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) + { + remove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)); + } + + sprintf (str, "%d", count); + + return SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), strlen(str), FALSE); + } +} + + +// Repairs damaged sectors (i.e. those with read errors) by zeroing them. +// Note that this operating fails if there are any write errors. +int ZeroUnreadableSectors (HANDLE dev, LARGE_INTEGER startOffset, int64 size, int sectorSize, uint64 *zeroedSectorCount) +{ + int nStatus; + DWORD n; + int64 sectorCount; + LARGE_INTEGER workOffset; + byte *sectorBuffer = NULL; + DWORD dwError; + + workOffset.QuadPart = startOffset.QuadPart; + + sectorBuffer = (byte *) TCalloc (sectorSize); + + if (!sectorBuffer) + return ERR_OUTOFMEMORY; + + if (SetFilePointerEx (dev, startOffset, NULL, FILE_BEGIN) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + + for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount) + { + if (ReadFile (dev, sectorBuffer, sectorSize, &n, NULL) == 0) + { + memset (sectorBuffer, 0, sectorSize); + + if (SetFilePointerEx (dev, workOffset, NULL, FILE_BEGIN) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + if (WriteFile (dev, sectorBuffer, sectorSize, &n, NULL) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + ++(*zeroedSectorCount); + } + + workOffset.QuadPart += n; + } + + nStatus = ERR_SUCCESS; + +closing_seq: + + dwError = GetLastError(); + + if (sectorBuffer != NULL) + TCfree (sectorBuffer); + + if (nStatus != ERR_SUCCESS) + SetLastError (dwError); + + return nStatus; +} + + +static int OpenBackupHeader (HANDLE dev, const char *devicePath, Password *password, PCRYPTO_INFO *retMasterCryptoInfo, CRYPTO_INFO *headerCryptoInfo, __int64 deviceSize) +{ + LARGE_INTEGER offset; + DWORD n; + int nStatus = ERR_SUCCESS; + char *header; + DWORD dwError; + + header = (char *) TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE); + if (!header) + return ERR_OUTOFMEMORY; + + VirtualLock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + + + + offset.QuadPart = deviceSize - TC_VOLUME_HEADER_GROUP_SIZE; + + if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0 + || ReadFile (dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &n, NULL) == 0) + { + nStatus = ERR_OS_ERROR; + goto closing_seq; + } + + + nStatus = ReadVolumeHeader (FALSE, header, password, retMasterCryptoInfo, headerCryptoInfo); + if (nStatus != ERR_SUCCESS) + goto closing_seq; + + +closing_seq: + + dwError = GetLastError(); + + burn (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + VirtualUnlock (header, TC_VOLUME_HEADER_EFFECTIVE_SIZE); + TCfree (header); + + dwError = GetLastError(); + + if (nStatus != ERR_SUCCESS) + SetLastError (dwError); + + return nStatus; +} + + +static BOOL GetFreeClusterBeforeThreshold (HANDLE volumeHandle, int64 *freeCluster, int64 clusterThreshold) +{ + const int bitmapSize = 65536; + byte bitmapBuffer[bitmapSize + sizeof (VOLUME_BITMAP_BUFFER)]; + VOLUME_BITMAP_BUFFER *bitmap = (VOLUME_BITMAP_BUFFER *) bitmapBuffer; + STARTING_LCN_INPUT_BUFFER startLcn; + startLcn.StartingLcn.QuadPart = 0; + + DWORD bytesReturned; + while (DeviceIoControl (volumeHandle, FSCTL_GET_VOLUME_BITMAP, &startLcn, sizeof (startLcn), &bitmapBuffer, sizeof (bitmapBuffer), &bytesReturned, NULL) + || GetLastError() == ERROR_MORE_DATA) + { + for (int64 bitmapIndex = 0; bitmapIndex < min (bitmapSize, (bitmap->BitmapSize.QuadPart / 8)); ++bitmapIndex) + { + if (bitmap->StartingLcn.QuadPart + bitmapIndex * 8 >= clusterThreshold) + goto err; + + if (bitmap->Buffer[bitmapIndex] != 0xff) + { + for (int bit = 0; bit < 8; ++bit) + { + if ((bitmap->Buffer[bitmapIndex] & (1 << bit)) == 0) + { + *freeCluster = bitmap->StartingLcn.QuadPart + bitmapIndex * 8 + bit; + + if (*freeCluster >= clusterThreshold) + goto err; + + return TRUE; + } + } + } + } + + startLcn.StartingLcn.QuadPart += min (bitmapSize * 8, bitmap->BitmapSize.QuadPart); + } + +err: + SetLastError (ERROR_DISK_FULL); + return FALSE; +} + + +static BOOL MoveClustersBeforeThresholdInDir (HANDLE volumeHandle, const wstring &directory, int64 clusterThreshold) +{ + WIN32_FIND_DATAW findData; + + HANDLE findHandle = FindFirstFileW (((directory.size() <= 3 ? L"" : L"\\\\?\\") + directory + L"\\*").c_str(), &findData); + if (findHandle == INVALID_HANDLE_VALUE) + return TRUE; // Error ignored + + finally_do_arg (HANDLE, findHandle, { FindClose (finally_arg); }); + + // Find all files and directories + do + { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + wstring subDir = findData.cFileName; + + if (subDir == L"." || subDir == L"..") + continue; + + if (!MoveClustersBeforeThresholdInDir (volumeHandle, directory + L"\\" + subDir, clusterThreshold)) + return FALSE; + } + + DWORD access = FILE_READ_ATTRIBUTES; + + if (findData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) + access = FILE_READ_DATA; + + HANDLE fsObject = CreateFileW ((directory + L"\\" + findData.cFileName).c_str(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (fsObject == INVALID_HANDLE_VALUE) + continue; + + finally_do_arg (HANDLE, fsObject, { CloseHandle (finally_arg); }); + + STARTING_VCN_INPUT_BUFFER startVcn; + startVcn.StartingVcn.QuadPart = 0; + RETRIEVAL_POINTERS_BUFFER retPointers; + DWORD bytesReturned; + + // Find clusters allocated beyond the threshold + while (DeviceIoControl (fsObject, FSCTL_GET_RETRIEVAL_POINTERS, &startVcn, sizeof (startVcn), &retPointers, sizeof (retPointers), &bytesReturned, NULL) + || GetLastError() == ERROR_MORE_DATA) + { + if (retPointers.ExtentCount == 0) + break; + + if (retPointers.Extents[0].Lcn.QuadPart != -1) + { + int64 extentStartCluster = retPointers.Extents[0].Lcn.QuadPart; + int64 extentLen = retPointers.Extents[0].NextVcn.QuadPart - retPointers.StartingVcn.QuadPart; + int64 extentEndCluster = extentStartCluster + extentLen - 1; + + if (extentEndCluster >= clusterThreshold) + { + // Move clusters before the threshold + for (int64 movedCluster = max (extentStartCluster, clusterThreshold); movedCluster <= extentEndCluster; ++movedCluster) + { + for (int retry = 0; ; ++retry) + { + MOVE_FILE_DATA moveData; + + if (GetFreeClusterBeforeThreshold (volumeHandle, &moveData.StartingLcn.QuadPart, clusterThreshold)) + { + moveData.FileHandle = fsObject; + moveData.StartingVcn.QuadPart = movedCluster - extentStartCluster + retPointers.StartingVcn.QuadPart; + moveData.ClusterCount = 1; + + if (DeviceIoControl (volumeHandle, FSCTL_MOVE_FILE, &moveData, sizeof (moveData), NULL, 0, &bytesReturned, NULL)) + break; + } + + if (retry > 600) + return FALSE; + + // There are possible race conditions as we work on a live filesystem + Sleep (100); + } + } + } + } + + startVcn.StartingVcn = retPointers.Extents[0].NextVcn; + } + + } while (FindNextFileW (findHandle, &findData)); + + return TRUE; +} + + +BOOL MoveClustersBeforeThreshold (HANDLE volumeHandle, PWSTR volumeDevicePath, int64 clusterThreshold) +{ + int drive = GetDiskDeviceDriveLetter (volumeDevicePath); + if (drive == -1) + { + SetLastError (ERROR_INVALID_PARAMETER); + return FALSE; + } + + wstring volumeRoot = L"X:"; + volumeRoot[0] = L'A' + (wchar_t) drive; + + return MoveClustersBeforeThresholdInDir (volumeHandle, volumeRoot, clusterThreshold); +} diff --git a/Format/InPlace.h b/Format/InPlace.h index c5f0bc4..1c886d9 100644 --- a/Format/InPlace.h +++ b/Format/InPlace.h @@ -1,45 +1,45 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "Format.h" - -enum nonsys_inplace_enc_status -{ - NONSYS_INPLACE_ENC_STATUS_NONE = 0, - NONSYS_INPLACE_ENC_STATUS_PREPARING, - NONSYS_INPLACE_ENC_STATUS_RESIZING, - NONSYS_INPLACE_ENC_STATUS_ENCRYPTING, - NONSYS_INPLACE_ENC_STATUS_FINALIZING, - NONSYS_INPLACE_ENC_STATUS_PAUSED, - NONSYS_INPLACE_ENC_STATUS_FINISHED, - NONSYS_INPLACE_ENC_STATUS_ERROR -}; - -BOOL CheckRequirementsForNonSysInPlaceEnc (const char *devicePath, BOOL silent); -int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, volatile HANDLE *outHandle, WipeAlgorithmId wipeAlgorithm); -int EncryptPartitionInPlaceResume (HANDLE dev, volatile FORMAT_VOL_PARAMETERS *volParams, WipeAlgorithmId wipeAlgorithm, volatile BOOL *bTryToCorrectReadErrors); -void ShowInPlaceEncErrMsgWAltSteps (char *iniStrId, BOOL bErr); -void SetNonSysInplaceEncUIStatus (int nonSysInplaceEncStatus); -int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_INFO *masterCryptoInfo, __int64 deviceSize); - -HANDLE OpenPartitionVolume (const char *devName, BOOL bExclusiveRequired, BOOL bSharedRequired, BOOL bSharedRequiresConfirmation, BOOL bShowAlternativeSteps, BOOL bSilent); -int DismountFileSystem (HANDLE dev, int driveLetter, BOOL bForcedAllowed, BOOL bForcedRequiresConfirmation, BOOL bSilent); -int ConcealNTFS (HANDLE dev); -BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId wipeAlgorithm); -void ExportProgressStats (__int64 bytesDone, __int64 totalSectors); -int ZeroUnreadableSectors (HANDLE dev, LARGE_INTEGER startOffset, int64 size, int sectorSize, uint64 *zeroedSectorCount); -int OpenBackupHeader (HANDLE dev, const char *devicePath, Password *password, PCRYPTO_INFO *retCryptoInfo, CRYPTO_INFO *headerCryptoInfo, __int64 deviceSize); -BOOL MoveClustersBeforeThreshold (HANDLE volumeHandle, PWSTR volumeDevicePath, int64 clusterThreshold); - -#ifdef __cplusplus -} -#endif +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Format.h" + +enum nonsys_inplace_enc_status +{ + NONSYS_INPLACE_ENC_STATUS_NONE = 0, + NONSYS_INPLACE_ENC_STATUS_PREPARING, + NONSYS_INPLACE_ENC_STATUS_RESIZING, + NONSYS_INPLACE_ENC_STATUS_ENCRYPTING, + NONSYS_INPLACE_ENC_STATUS_FINALIZING, + NONSYS_INPLACE_ENC_STATUS_PAUSED, + NONSYS_INPLACE_ENC_STATUS_FINISHED, + NONSYS_INPLACE_ENC_STATUS_ERROR +}; + +BOOL CheckRequirementsForNonSysInPlaceEnc (const char *devicePath, BOOL silent); +int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, volatile HANDLE *outHandle, WipeAlgorithmId wipeAlgorithm); +int EncryptPartitionInPlaceResume (HANDLE dev, volatile FORMAT_VOL_PARAMETERS *volParams, WipeAlgorithmId wipeAlgorithm, volatile BOOL *bTryToCorrectReadErrors); +void ShowInPlaceEncErrMsgWAltSteps (char *iniStrId, BOOL bErr); +void SetNonSysInplaceEncUIStatus (int nonSysInplaceEncStatus); +int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_INFO *masterCryptoInfo, __int64 deviceSize); + +static HANDLE OpenPartitionVolume (const char *devName, BOOL bExclusiveRequired, BOOL bSharedRequired, BOOL bSharedRequiresConfirmation, BOOL bShowAlternativeSteps, BOOL bSilent); +static int DismountFileSystem (HANDLE dev, int driveLetter, BOOL bForcedAllowed, BOOL bForcedRequiresConfirmation, BOOL bSilent); +static int ConcealNTFS (HANDLE dev); +BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId wipeAlgorithm); +static void ExportProgressStats (__int64 bytesDone, __int64 totalSectors); +int ZeroUnreadableSectors (HANDLE dev, LARGE_INTEGER startOffset, int64 size, int sectorSize, uint64 *zeroedSectorCount); +static int OpenBackupHeader (HANDLE dev, const char *devicePath, Password *password, PCRYPTO_INFO *retCryptoInfo, CRYPTO_INFO *headerCryptoInfo, __int64 deviceSize); +BOOL MoveClustersBeforeThreshold (HANDLE volumeHandle, PWSTR volumeDevicePath, int64 clusterThreshold); + +#ifdef __cplusplus +} +#endif diff --git a/Format/TCFORMAT.C b/Format/TCFORMAT.C index 1193109..a13350b 100644 --- a/Format/TCFORMAT.C +++ b/Format/TCFORMAT.C @@ -1,8774 +1,8835 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "Crypto.h" -#include "Apidrvr.h" -#include "Dlgcode.h" -#include "Language.h" -#include "Combo.h" -#include "Registry.h" -#include "Boot/Windows/BootDefs.h" -#include "Common/Common.h" -#include "Common/BootEncryption.h" -#include "Common/Dictionary.h" -#include "Common/Endian.h" -#include "Common/resource.h" -#include "Platform/Finally.h" -#include "Platform/ForEach.h" -#include "Random.h" -#include "Fat.h" -#include "InPlace.h" -#include "Resource.h" -#include "TcFormat.h" -#include "Format.h" -#include "FormatCom.h" -#include "Password.h" -#include "Progress.h" -#include "Tests.h" -#include "Cmdline.h" -#include "Volumes.h" -#include "Wipe.h" -#include "Xml.h" - -using namespace TrueCrypt; - -enum wizard_pages -{ - /* IMPORTANT: IF YOU ADD/REMOVE/MOVE ANY PAGES THAT ARE RELATED TO SYSTEM ENCRYPTION, - REVISE THE 'DECOY_OS_INSTRUCTIONS' STRING! */ - - INTRO_PAGE, - SYSENC_TYPE_PAGE, - SYSENC_HIDDEN_OS_REQ_CHECK_PAGE, - SYSENC_SPAN_PAGE, - SYSENC_PRE_DRIVE_ANALYSIS_PAGE, - SYSENC_DRIVE_ANALYSIS_PAGE, - SYSENC_MULTI_BOOT_MODE_PAGE, - SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE, - SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE, - SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE, - SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE, - SYSENC_MULTI_BOOT_OUTCOME_PAGE, - VOLUME_TYPE_PAGE, - HIDDEN_VOL_WIZARD_MODE_PAGE, - VOLUME_LOCATION_PAGE, - DEVICE_TRANSFORM_MODE_PAGE, - HIDDEN_VOL_HOST_PRE_CIPHER_PAGE, - HIDDEN_VOL_PRE_CIPHER_PAGE, - CIPHER_PAGE, - SIZE_PAGE, - HIDDEN_VOL_HOST_PASSWORD_PAGE, - PASSWORD_PAGE, - FILESYS_PAGE, - SYSENC_COLLECTING_RANDOM_DATA_PAGE, - SYSENC_KEYS_GEN_PAGE, - SYSENC_RESCUE_DISK_CREATION_PAGE, - SYSENC_RESCUE_DISK_BURN_PAGE, - SYSENC_RESCUE_DISK_VERIFIED_PAGE, - SYSENC_WIPE_MODE_PAGE, - SYSENC_PRETEST_INFO_PAGE, - SYSENC_PRETEST_RESULT_PAGE, - SYSENC_ENCRYPTION_PAGE, - NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE, - NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE, - NONSYS_INPLACE_ENC_RAND_DATA_PAGE, - NONSYS_INPLACE_ENC_WIPE_MODE_PAGE, - NONSYS_INPLACE_ENC_ENCRYPTION_PAGE, - NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE, - FORMAT_PAGE, - FORMAT_FINISHED_PAGE, - SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE, - SYSENC_HIDDEN_OS_WIPE_INFO_PAGE, - DEVICE_WIPE_MODE_PAGE, - DEVICE_WIPE_PAGE -}; - -#define TIMER_INTERVAL_RANDVIEW 30 -#define TIMER_INTERVAL_SYSENC_PROGRESS 30 -#define TIMER_INTERVAL_NONSYS_INPLACE_ENC_PROGRESS 30 -#define TIMER_INTERVAL_SYSENC_DRIVE_ANALYSIS_PROGRESS 100 -#define TIMER_INTERVAL_WIPE_PROGRESS 30 -#define TIMER_INTERVAL_KEYB_LAYOUT_GUARD 10 - -enum sys_encryption_cmd_line_switches -{ - SYSENC_COMMAND_NONE = 0, - SYSENC_COMMAND_RESUME, - SYSENC_COMMAND_STARTUP_SEQ_RESUME, - SYSENC_COMMAND_ENCRYPT, - SYSENC_COMMAND_DECRYPT, - SYSENC_COMMAND_CREATE_HIDDEN_OS, - SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV -}; - -typedef struct -{ - int NumberOfSysDrives; // Number of drives that contain an operating system. -1: unknown, 1: one, 2: two or more - int MultipleSystemsOnDrive; // Multiple systems are installed on the drive where the currently running system resides. -1: unknown, 0: no, 1: yes - int BootLoaderLocation; // Boot loader (boot manager) installed in: 1: MBR/1st cylinder, 0: partition/bootsector: -1: unknown - int BootLoaderBrand; // -1: unknown, 0: Microsoft Windows, 1: any non-Windows boot manager/loader - int SystemOnBootDrive; // If the currently running operating system is installed on the boot drive. -1: unknown, 0: no, 1: yes -} SYSENC_MULTIBOOT_CFG; - -#define SYSENC_PAUSE_RETRY_INTERVAL 100 -#define SYSENC_PAUSE_RETRIES 200 - -// Expected duration of system drive analysis, in ms -#define SYSENC_DRIVE_ANALYSIS_ETA (4*60000) - -BootEncryption *BootEncObj = NULL; -BootEncryptionStatus BootEncStatus; - -HWND hCurPage = NULL; /* Handle to current wizard page */ -int nCurPageNo = -1; /* The current wizard page */ -int nLastPageNo = -1; -volatile int WizardMode = DEFAULT_VOL_CREATION_WIZARD_MODE; /* IMPORTANT: Never change this value directly -- always use ChangeWizardMode() instead. */ -volatile BOOL bHiddenOS = FALSE; /* If TRUE, we are performing or (or supposed to perform) actions relating to an operating system installed in a hidden volume (i.e., encrypting a decoy OS partition or creating the outer/hidden volume for the hidden OS). To determine or set the phase of the process, call ChangeHiddenOSCreationPhase() and DetermineHiddenOSCreationPhase()) */ -BOOL bDirectSysEncMode = FALSE; -BOOL bDirectSysEncModeCommand = SYSENC_COMMAND_NONE; -BOOL DirectDeviceEncMode = FALSE; -BOOL DirectNonSysInplaceEncResumeMode = FALSE; -BOOL DirectPromptNonSysInplaceEncResumeMode = FALSE; -volatile BOOL bInPlaceEncNonSys = FALSE; /* If TRUE, existing data on a non-system partition/volume are to be encrypted (for system encryption, this flag is ignored) */ -volatile BOOL bInPlaceEncNonSysResumed = FALSE; /* If TRUE, the wizard is supposed to resume (or has resumed) process of non-system in-place encryption. */ -volatile BOOL bFirstNonSysInPlaceEncResumeDone = FALSE; -__int64 NonSysInplaceEncBytesDone = 0; -__int64 NonSysInplaceEncTotalSectors = 0; -BOOL bDeviceTransformModeChoiceMade = FALSE; /* TRUE if the user has at least once manually selected the 'in-place' or 'format' option (on the 'device transform mode' page). */ -int nNeedToStoreFilesOver4GB = 0; /* Whether the user wants to be able to store files larger than 4GB on the volume: -1 = Undecided or error, 0 = No, 1 = Yes */ -int nVolumeEA = 1; /* Default encryption algorithm */ -BOOL bSystemEncryptionInProgress = FALSE; /* TRUE when encrypting/decrypting the system partition/drive (FALSE when paused). */ -BOOL bWholeSysDrive = FALSE; /* Whether to encrypt the entire system drive or just the system partition. */ -static BOOL bSystemEncryptionStatusChanged = FALSE; /* TRUE if this instance changed the value of SystemEncryptionStatus (it's set to FALSE each time the system encryption settings are saved to the config file). This value is to be treated as protected -- only the wizard can change this value (others may only read it). */ -volatile BOOL bSysEncDriveAnalysisInProgress = FALSE; -volatile BOOL bSysEncDriveAnalysisTimeOutOccurred = FALSE; -int SysEncDetectHiddenSectors = -1; /* Whether the user wants us to detect and encrypt the Host Protect Area (if any): -1 = Undecided or error, 0 = No, 1 = Yes */ -int SysEncDriveAnalysisStart; -BOOL bDontVerifyRescueDisk = FALSE; -BOOL bFirstSysEncResumeDone = FALSE; -int nMultiBoot = 0; /* The number of operating systems installed on the computer, according to the user. 0: undetermined, 1: one, 2: two or more */ -volatile BOOL bHiddenVol = FALSE; /* If true, we are (or will be) creating a hidden volume. */ -volatile BOOL bHiddenVolHost = FALSE; /* If true, we are (or will be) creating the host volume (called "outer") for a hidden volume. */ -volatile BOOL bHiddenVolDirect = FALSE; /* If true, the wizard omits creating a host volume in the course of the process of hidden volume creation. */ -volatile BOOL bHiddenVolFinished = FALSE; -int hiddenVolHostDriveNo = -1; /* Drive letter for the volume intended to host a hidden volume. */ -BOOL bRemovableHostDevice = FALSE; /* TRUE when creating a device/partition-hosted volume on a removable device. State undefined when creating file-hosted volumes. */ -int realClusterSize; /* Parameter used when determining the maximum possible size of a hidden volume. */ -int hash_algo = DEFAULT_HASH_ALGORITHM; /* Which PRF to use in header key derivation (PKCS #5) and in the RNG. */ -unsigned __int64 nUIVolumeSize = 0; /* The volume size. Important: This value is not in bytes. It has to be multiplied by nMultiplier. Do not use this value when actually creating the volume (it may chop off 512 bytes, if it is not a multiple of 1024 bytes). */ -unsigned __int64 nVolumeSize = 0; /* The volume size, in bytes. */ -unsigned __int64 nHiddenVolHostSize = 0; /* Size of the hidden volume host, in bytes */ -__int64 nMaximumHiddenVolSize = 0; /* Maximum possible size of the hidden volume, in bytes */ -__int64 nbrFreeClusters = 0; -int nMultiplier = BYTES_PER_MB; /* Size selection multiplier. */ -char szFileName[TC_MAX_PATH+1]; /* The file selected by the user */ -char szDiskFile[TC_MAX_PATH+1]; /* Fully qualified name derived from szFileName */ -char szRescueDiskISO[TC_MAX_PATH+1]; /* The filename and path to the Rescue Disk ISO file to be burned (for boot encryption) */ -BOOL bDeviceWipeInProgress = FALSE; -volatile BOOL bTryToCorrectReadErrors = FALSE; -volatile BOOL DiscardUnreadableEncryptedSectors = FALSE; - -volatile BOOL bVolTransformThreadCancel = FALSE; /* TRUE if the user cancels/pauses volume encryption/format */ -volatile BOOL bVolTransformThreadRunning = FALSE; /* Is the volume encryption/format thread running */ -volatile BOOL bVolTransformThreadToRun = FALSE; /* TRUE if the Format/Encrypt button has been clicked and we are proceeding towards launching the thread. */ - -volatile BOOL bConfirmQuit = FALSE; /* If TRUE, the user is asked to confirm exit when he clicks the X icon, Exit, etc. */ -volatile BOOL bConfirmQuitSysEncPretest = FALSE; - -BOOL bDevice = FALSE; /* Is this a partition volume ? */ - -BOOL showKeys = TRUE; -volatile HWND hMasterKey = NULL; /* Text box showing hex dump of the master key */ -volatile HWND hHeaderKey = NULL; /* Text box showing hex dump of the header key */ -volatile HWND hRandPool = NULL; /* Text box showing hex dump of the random pool */ -volatile HWND hRandPoolSys = NULL; /* Text box showing hex dump of the random pool for system encryption */ -volatile HWND hPasswordInputField = NULL; /* Password input field */ -volatile HWND hVerifyPasswordInputField = NULL; /* Verify-password input field */ - -HBITMAP hbmWizardBitmapRescaled = NULL; - -char OrigKeyboardLayout [8+1] = "00000409"; -BOOL bKeyboardLayoutChanged = FALSE; /* TRUE if the keyboard layout was changed to the standard US keyboard layout (from any other layout). */ -BOOL bKeybLayoutAltKeyWarningShown = FALSE; /* TRUE if the user has been informed that it is not possible to type characters by pressing keys while the right Alt key is held down. */ - -#ifndef _DEBUG - BOOL bWarnDeviceFormatAdvanced = TRUE; -#else - BOOL bWarnDeviceFormatAdvanced = FALSE; -#endif - -BOOL bWarnOuterVolSuitableFileSys = TRUE; - -Password volumePassword; /* User password */ -char szVerify[MAX_PASSWORD + 1]; /* Tmp password buffer */ -char szRawPassword[MAX_PASSWORD + 1]; /* Password before keyfile was applied to it */ - -BOOL bHistoryCmdLine = FALSE; /* History control is always disabled */ -BOOL ComServerMode = FALSE; - -int nPbar = 0; /* Control ID of progress bar:- for format code */ - -char HeaderKeyGUIView [KEY_GUI_VIEW_SIZE]; -char MasterKeyGUIView [KEY_GUI_VIEW_SIZE]; - -#define RANDPOOL_DISPLAY_COLUMNS 15 -#define RANDPOOL_DISPLAY_ROWS 8 -#define RANDPOOL_DISPLAY_BYTE_PORTION (RANDPOOL_DISPLAY_COLUMNS * RANDPOOL_DISPLAY_ROWS) -#define RANDPOOL_DISPLAY_SIZE (RANDPOOL_DISPLAY_BYTE_PORTION * 3 + RANDPOOL_DISPLAY_ROWS + 2) -unsigned char randPool [RANDPOOL_DISPLAY_BYTE_PORTION]; -unsigned char lastRandPool [RANDPOOL_DISPLAY_BYTE_PORTION]; -unsigned char outRandPoolDispBuffer [RANDPOOL_DISPLAY_SIZE]; -BOOL bDisplayPoolContents = TRUE; - -volatile BOOL bSparseFileSwitch = FALSE; -volatile BOOL quickFormat = FALSE; /* WARNING: Meaning of this variable depends on bSparseFileSwitch. If bSparseFileSwitch is TRUE, this variable represents the sparse file flag. */ -volatile int fileSystem = FILESYS_NONE; -volatile int clusterSize = 0; - -SYSENC_MULTIBOOT_CFG SysEncMultiBootCfg; -wchar_t SysEncMultiBootCfgOutcome [4096] = {'N','/','A',0}; -volatile int NonSysInplaceEncStatus = NONSYS_INPLACE_ENC_STATUS_NONE; - -vector DeferredNonSysInPlaceEncDevices; - - -static BOOL ElevateWholeWizardProcess (string arguments) -{ - char modPath[MAX_PATH]; - - if (IsAdmin()) - return TRUE; - - if (!IsUacSupported()) - return IsAdmin(); - - GetModuleFileName (NULL, modPath, sizeof (modPath)); - - if ((int)ShellExecute (MainDlg, "runas", modPath, (string("/q UAC ") + arguments).c_str(), NULL, SW_SHOWNORMAL) > 32) - { - exit (0); - } - else - { - Error ("UAC_INIT_ERROR"); - return FALSE; - } -} - -static void WipePasswordsAndKeyfiles (void) -{ - char tmp[MAX_PASSWORD+1]; - - // Attempt to wipe passwords stored in the input field buffers - memset (tmp, 'X', MAX_PASSWORD); - tmp [MAX_PASSWORD] = 0; - SetWindowText (hPasswordInputField, tmp); - SetWindowText (hVerifyPasswordInputField, tmp); - - burn (&szVerify[0], sizeof (szVerify)); - burn (&volumePassword, sizeof (volumePassword)); - burn (&szRawPassword[0], sizeof (szRawPassword)); - - SetWindowText (hPasswordInputField, ""); - SetWindowText (hVerifyPasswordInputField, ""); - - KeyFileRemoveAll (&FirstKeyFile); - KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); -} - -static void localcleanup (void) -{ - char tmp[RANDPOOL_DISPLAY_SIZE+1]; - - // System encryption - - if (WizardMode == WIZARD_MODE_SYS_DEVICE - && InstanceHasSysEncMutex ()) - { - try - { - BootEncStatus = BootEncObj->GetStatus(); - - if (BootEncStatus.SetupInProgress) - { - BootEncObj->AbortSetup (); - } - } - catch (...) - { - // NOP - } - } - - // Mon-system in-place encryption - - if (bInPlaceEncNonSys && (bVolTransformThreadRunning || bVolTransformThreadToRun)) - { - NonSysInplaceEncPause (); - } - - CloseNonSysInplaceEncMutex (); - - - // Device wipe - - if (bDeviceWipeInProgress) - WipeAbort(); - - - WipePasswordsAndKeyfiles (); - - RandStop (TRUE); - - burn (HeaderKeyGUIView, sizeof(HeaderKeyGUIView)); - burn (MasterKeyGUIView, sizeof(MasterKeyGUIView)); - burn (randPool, sizeof(randPool)); - burn (lastRandPool, sizeof(lastRandPool)); - burn (outRandPoolDispBuffer, sizeof(outRandPoolDispBuffer)); - burn (szFileName, sizeof(szFileName)); - burn (szDiskFile, sizeof(szDiskFile)); - - // Attempt to wipe the GUI fields showing portions of randpool, of the master and header keys - memset (tmp, 'X', sizeof(tmp)); - tmp [sizeof(tmp)-1] = 0; - SetWindowText (hRandPool, tmp); - SetWindowText (hRandPoolSys, tmp); - SetWindowText (hMasterKey, tmp); - SetWindowText (hHeaderKey, tmp); - - UnregisterRedTick (hInst); - - // Delete buffered bitmaps (if any) - if (hbmWizardBitmapRescaled != NULL) - { - DeleteObject ((HGDIOBJ) hbmWizardBitmapRescaled); - hbmWizardBitmapRescaled = NULL; - } - - // Cleanup common code resources - cleanup (); - - if (BootEncObj != NULL) - { - delete BootEncObj; - BootEncObj = NULL; - } -} - -static BOOL CALLBACK BroadcastSysEncCfgUpdateCallb (HWND hwnd, LPARAM lParam) -{ - if (GetWindowLongPtr (hwnd, GWLP_USERDATA) == (LONG_PTR) 'TRUE') - { - char name[1024] = { 0 }; - GetWindowText (hwnd, name, sizeof (name) - 1); - if (hwnd != MainDlg && strstr (name, "TrueCrypt")) - { - PostMessage (hwnd, TC_APPMSG_SYSENC_CONFIG_UPDATE, 0, 0); - } - } - return TRUE; -} - -static BOOL BroadcastSysEncCfgUpdate (void) -{ - BOOL bSuccess = FALSE; - EnumWindows (BroadcastSysEncCfgUpdateCallb, (LPARAM) &bSuccess); - return bSuccess; -} - -// IMPORTANT: This function may be called only by Format (other modules can only _read_ the system encryption config). -// Returns TRUE if successful (otherwise FALSE) -static BOOL SaveSysEncSettings (HWND hwndDlg) -{ - FILE *f; - - if (!bSystemEncryptionStatusChanged) - return TRUE; - - if (hwndDlg == NULL && MainDlg != NULL) - hwndDlg = MainDlg; - - if (!CreateSysEncMutex ()) - return FALSE; // Only one instance that has the mutex can modify the system encryption settings - - if (SystemEncryptionStatus == SYSENC_STATUS_NONE) - { - if (remove (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION)) != 0) - { - Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS"); - return FALSE; - } - - bSystemEncryptionStatusChanged = FALSE; - BroadcastSysEncCfgUpdate (); - return TRUE; - } - - f = fopen (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), "w"); - if (f == NULL) - { - Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS"); - handleWin32Error (hwndDlg); - return FALSE; - } - - if (XmlWriteHeader (f) < 0 - - || fputs ("\n\t", f) < 0 - - || fprintf (f, "\n\t\t%d", SystemEncryptionStatus) < 0 - - || fprintf (f, "\n\t\t%d", (int) nWipeMode) < 0 - - || fputs ("\n\t", f) < 0 - - || XmlWriteFooter (f) < 0) - { - handleWin32Error (hwndDlg); - fclose (f); - Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS"); - return FALSE; - } - - TCFlushFile (f); - - fclose (f); - - bSystemEncryptionStatusChanged = FALSE; - BroadcastSysEncCfgUpdate (); - - return TRUE; -} - -// WARNING: This function may take a long time to finish -static unsigned int DetermineHiddenOSCreationPhase (void) -{ - unsigned int phase = TC_HIDDEN_OS_CREATION_PHASE_NONE; - - try - { - phase = BootEncObj->GetHiddenOSCreationPhase(); - } - catch (Exception &e) - { - e.Show (MainDlg); - AbortProcess("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - } - - return phase; -} - -// IMPORTANT: This function may be called only by Format (other modules can only _read_ the status). -// Returns TRUE if successful (otherwise FALSE) -static BOOL ChangeHiddenOSCreationPhase (int newPhase) -{ - if (!CreateSysEncMutex ()) - { - Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - return FALSE; - } - - try - { - BootEncObj->SetHiddenOSCreationPhase (newPhase); - } - catch (Exception &e) - { - e.Show (MainDlg); - return FALSE; - } - - //// The contents of the following items might be inappropriate after a change of the phase - //szFileName[0] = 0; - //szDiskFile[0] = 0; - //nUIVolumeSize = 0; - //nVolumeSize = 0; - - return TRUE; -} - -// IMPORTANT: This function may be called only by Format (other modules can only _read_ the system encryption status). -// Returns TRUE if successful (otherwise FALSE) -static BOOL ChangeSystemEncryptionStatus (int newStatus) -{ - if (!CreateSysEncMutex ()) - { - Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - return FALSE; // Only one instance that has the mutex can modify the system encryption settings - } - - SystemEncryptionStatus = newStatus; - bSystemEncryptionStatusChanged = TRUE; - - if (newStatus == SYSENC_STATUS_ENCRYPTING) - { - // If the user has created a hidden OS and now is creating a decoy OS, we must wipe the hidden OS - // config area in the MBR. - WipeHiddenOSCreationConfig(); - } - - if (newStatus == SYSENC_STATUS_NONE && !IsHiddenOSRunning()) - { - if (DetermineHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE - && !ChangeHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE)) - return FALSE; - - WipeHiddenOSCreationConfig(); - } - - if (!SaveSysEncSettings (MainDlg)) - { - return FALSE; - } - - return TRUE; -} - -// If the return code of this function is ignored and newWizardMode == WIZARD_MODE_SYS_DEVICE, then this function -// may be called only after CreateSysEncMutex() returns TRUE. It returns TRUE if successful (otherwise FALSE). -static BOOL ChangeWizardMode (int newWizardMode) -{ - if (WizardMode != newWizardMode) - { - if (WizardMode == WIZARD_MODE_SYS_DEVICE || newWizardMode == WIZARD_MODE_SYS_DEVICE) - { - if (newWizardMode == WIZARD_MODE_SYS_DEVICE) - { - if (!CreateSysEncMutex ()) - { - Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - return FALSE; - } - } - - // If the previous mode was different, the password may have been typed using a different - // keyboard layout (which might confuse the user and cause other problems if system encryption - // was or will be involved). - WipePasswordsAndKeyfiles(); - } - - if (newWizardMode != WIZARD_MODE_NONSYS_DEVICE) - bInPlaceEncNonSys = FALSE; - - if (newWizardMode == WIZARD_MODE_NONSYS_DEVICE && !IsAdmin() && IsUacSupported()) - { - if (!ElevateWholeWizardProcess ("/e")) - return FALSE; - } - - // The contents of the following items may be inappropriate after a change of mode - szFileName[0] = 0; - szDiskFile[0] = 0; - nUIVolumeSize = 0; - nVolumeSize = 0; - - WizardMode = newWizardMode; - } - - bDevice = (WizardMode != WIZARD_MODE_FILE_CONTAINER); - - if (newWizardMode != WIZARD_MODE_SYS_DEVICE - && !bHiddenOS) - { - CloseSysEncMutex (); - } - - return TRUE; -} - -// Determines whether the wizard directly affects system encryption in any way. -// Note, for example, that when the user enters a password for a hidden volume that is to host a hidden OS, -// WizardMode is NOT set to WIZARD_MODE_SYS_DEVICE. The keyboard layout, however, has to be US. That's why -// this function has to be called instead of checking the value of WizardMode. -static BOOL SysEncInEffect (void) -{ - return (WizardMode == WIZARD_MODE_SYS_DEVICE - || CreatingHiddenSysVol()); -} - -static BOOL CreatingHiddenSysVol (void) -{ - return (bHiddenOS - && bHiddenVol && !bHiddenVolHost); -} - -static void LoadSettings (HWND hwndDlg) -{ - WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; - - LoadSysEncSettings (hwndDlg); - - if (LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) != 0) - bInPlaceEncNonSysPending = TRUE; - - defaultKeyFilesParam.EnableKeyFiles = FALSE; - - bStartOnLogon = ConfigReadInt ("StartOnLogon", FALSE); - - HiddenSectorDetectionStatus = ConfigReadInt ("HiddenSectorDetectionStatus", 0); - - bHistory = ConfigReadInt ("SaveVolumeHistory", FALSE); - - ConfigReadString ("SecurityTokenLibrary", "", SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath) - 1); - if (SecurityTokenLibraryPath[0]) - InitSecurityTokenLibrary(); - - if (hwndDlg != NULL) - { - LoadCombo (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); - return; - } - - if (bHistoryCmdLine) - return; -} - -static void SaveSettings (HWND hwndDlg) -{ - WaitCursor (); - - if (hwndDlg != NULL) - DumpCombo (GetDlgItem (hwndDlg, IDC_COMBO_BOX), !bHistory); - - ConfigWriteBegin (); - - ConfigWriteInt ("StartOnLogon", bStartOnLogon); - ConfigWriteInt ("HiddenSectorDetectionStatus", HiddenSectorDetectionStatus); - ConfigWriteInt ("SaveVolumeHistory", bHistory); - ConfigWriteString ("SecurityTokenLibrary", SecurityTokenLibraryPath[0] ? SecurityTokenLibraryPath : ""); - - if (GetPreferredLangId () != NULL) - ConfigWriteString ("Language", GetPreferredLangId ()); - - ConfigWriteEnd (); - - NormalCursor (); -} - -// WARNING: This function does NOT cause immediate application exit (use e.g. return 1 after calling it -// from a DialogProc function). -static void EndMainDlg (HWND hwndDlg) -{ - if (nCurPageNo == VOLUME_LOCATION_PAGE) - { - if (IsWindow(GetDlgItem(hCurPage, IDC_NO_HISTORY))) - bHistory = !IsButtonChecked (GetDlgItem (hCurPage, IDC_NO_HISTORY)); - - MoveEditToCombo (GetDlgItem (hCurPage, IDC_COMBO_BOX), bHistory); - SaveSettings (hCurPage); - } - else - { - SaveSettings (NULL); - } - - SaveSysEncSettings (hwndDlg); - - if (!bHistory) - CleanLastVisitedMRU (); - - EndDialog (hwndDlg, 0); -} - -// Returns TRUE if system encryption or decryption had been or is in progress and has not been completed -static BOOL SysEncryptionOrDecryptionRequired (void) -{ - /* If you update this function, revise SysEncryptionOrDecryptionRequired() in Mount.c as well. */ - - static BootEncryptionStatus locBootEncStatus; - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - return (SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING - || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING - || - ( - locBootEncStatus.DriveMounted - && - ( - locBootEncStatus.ConfiguredEncryptedAreaStart != locBootEncStatus.EncryptedAreaStart - || locBootEncStatus.ConfiguredEncryptedAreaEnd != locBootEncStatus.EncryptedAreaEnd - ) - ) - ); -} - -// Returns TRUE if the system partition/drive is completely encrypted -static BOOL SysDriveOrPartitionFullyEncrypted (BOOL bSilent) -{ - /* If you update this function, revise SysDriveOrPartitionFullyEncrypted() in Mount.c as well. */ - - static BootEncryptionStatus locBootEncStatus; - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - if (!bSilent) - e.Show (MainDlg); - } - - return (!locBootEncStatus.SetupInProgress - && locBootEncStatus.ConfiguredEncryptedAreaEnd != 0 - && locBootEncStatus.ConfiguredEncryptedAreaEnd != -1 - && locBootEncStatus.ConfiguredEncryptedAreaStart == locBootEncStatus.EncryptedAreaStart - && locBootEncStatus.ConfiguredEncryptedAreaEnd == locBootEncStatus.EncryptedAreaEnd); -} - -// This functions is to be used when the wizard mode needs to be changed to WIZARD_MODE_SYS_DEVICE. -// If the function fails to switch the mode, it returns FALSE (otherwise TRUE). -BOOL SwitchWizardToSysEncMode (void) -{ - WaitCursor (); - - try - { - BootEncStatus = BootEncObj->GetStatus(); - bWholeSysDrive = BootEncObj->SystemPartitionCoversWholeDrive(); - } - catch (Exception &e) - { - e.Show (MainDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - NormalCursor (); - return FALSE; - } - - // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption - if (!CreateSysEncMutex ()) - { - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - NormalCursor (); - return FALSE; - } - - // User-mode app may have crashed and its mutex may have gotten lost, so we need to check the driver status too - if (BootEncStatus.SetupInProgress) - { - if (AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) - { - if (SystemEncryptionStatus != SYSENC_STATUS_ENCRYPTING - && SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) - { - // The config file with status was lost or not written correctly - if (!ResolveUnknownSysEncDirection ()) - { - CloseSysEncMutex (); - NormalCursor (); - return FALSE; - } - } - - bDirectSysEncMode = TRUE; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - LoadPage (MainDlg, SYSENC_ENCRYPTION_PAGE); - NormalCursor (); - return TRUE; - } - else - { - CloseSysEncMutex (); - Error ("SYS_ENCRYPTION_OR_DECRYPTION_IN_PROGRESS"); - NormalCursor (); - return FALSE; - } - } - - if (BootEncStatus.DriveMounted - || BootEncStatus.DriveEncrypted - || SysEncryptionOrDecryptionRequired ()) - { - - if (!SysDriveOrPartitionFullyEncrypted (FALSE) - && AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) - { - if (SystemEncryptionStatus == SYSENC_STATUS_NONE) - { - // If the config file with status was lost or not written correctly, we - // don't know whether to encrypt or decrypt (but we know that encryption or - // decryption is required). Ask the user to select encryption, decryption, - // or cancel - if (!ResolveUnknownSysEncDirection ()) - { - CloseSysEncMutex (); - NormalCursor (); - return FALSE; - } - } - - bDirectSysEncMode = TRUE; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - LoadPage (MainDlg, SYSENC_ENCRYPTION_PAGE); - NormalCursor (); - return TRUE; - } - else - { - CloseSysEncMutex (); - Error ("SETUP_FAILED_BOOT_DRIVE_ENCRYPTED"); - NormalCursor (); - return FALSE; - } - } - else - { - // Check compliance with requirements for boot encryption - - if (!IsAdmin()) - { - if (!IsUacSupported()) - { - Warning ("ADMIN_PRIVILEGES_WARN_DEVICES"); - } - } - - try - { - BootEncObj->CheckRequirements (); - } - catch (Exception &e) - { - CloseSysEncMutex (); - e.Show (MainDlg); - NormalCursor (); - return FALSE; - } - - if (!ChangeWizardMode (WIZARD_MODE_SYS_DEVICE)) - { - NormalCursor (); - return FALSE; - } - - if (bSysDriveSelected || bSysPartitionSelected) - { - // The user selected the non-sys-device wizard mode but then selected a system device - - bWholeSysDrive = (bSysDriveSelected && !bSysPartitionSelected); - - bSysDriveSelected = FALSE; - bSysPartitionSelected = FALSE; - - try - { - if (!bHiddenVol) - { - if (bWholeSysDrive && !BootEncObj->SystemPartitionCoversWholeDrive()) - { - if (!IsOSAtLeast (WIN_VISTA)) - { - if (BootEncObj->SystemDriveContainsExtendedPartition()) - { - bWholeSysDrive = FALSE; - - Error ("WDE_UNSUPPORTED_FOR_EXTENDED_PARTITIONS"); - - if (AskYesNo ("ASK_ENCRYPT_PARTITION_INSTEAD_OF_DRIVE") == IDNO) - { - ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE); - return FALSE; - } - } - else - Warning ("WDE_EXTENDED_PARTITIONS_WARNING"); - } - } - else if (BootEncObj->SystemPartitionCoversWholeDrive() - && !bWholeSysDrive) - bWholeSysDrive = (AskYesNo ("WHOLE_SYC_DEVICE_RECOM") == IDYES); - } - - } - catch (Exception &e) - { - e.Show (MainDlg); - return FALSE; - } - - if (!bHiddenVol) - { - // Skip SYSENC_SPAN_PAGE and SYSENC_TYPE_PAGE as the user already made the choice - LoadPage (MainDlg, bWholeSysDrive ? SYSENC_PRE_DRIVE_ANALYSIS_PAGE : SYSENC_MULTI_BOOT_MODE_PAGE); - } - else - { - // The user selected the non-sys-device wizard mode but then selected a system device. - // In addition, he selected the hidden volume mode. - - if (bWholeSysDrive) - Warning ("HIDDEN_OS_PRECLUDES_SINGLE_KEY_WDE"); - - bWholeSysDrive = FALSE; - - LoadPage (MainDlg, SYSENC_TYPE_PAGE); - } - } - else - LoadPage (MainDlg, SYSENC_TYPE_PAGE); - - NormalCursor (); - return TRUE; - } - - CloseSysEncMutex (); - NormalCursor (); - return FALSE; -} - -void SwitchWizardToFileContainerMode (void) -{ - ChangeWizardMode (WIZARD_MODE_FILE_CONTAINER); - - LoadPage (MainDlg, VOLUME_LOCATION_PAGE); - - NormalCursor (); -} - -void SwitchWizardToNonSysDeviceMode (void) -{ - ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE); - - LoadPage (MainDlg, VOLUME_TYPE_PAGE); - - NormalCursor (); -} - -BOOL SwitchWizardToHiddenOSMode (void) -{ - if (SwitchWizardToSysEncMode()) - { - if (nCurPageNo != SYSENC_ENCRYPTION_PAGE) // If the user did not manually choose to resume encryption or decryption of the system partition/drive - { - bHiddenOS = TRUE; - bHiddenVol = TRUE; - bHiddenVolHost = TRUE; - bHiddenVolDirect = FALSE; - bWholeSysDrive = FALSE; - bInPlaceEncNonSys = FALSE; - - if (bDirectSysEncModeCommand == SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV) - { - // Some of the requirements for hidden OS should have already been checked by the wizard process - // that launched us (in order to elevate), but we must recheck them. Otherwise, an advanced user - // could bypass the checks by using the undocumented CLI switch. Moreover, some requirements - // can be checked only at this point (when we are elevated). - try - { - BootEncObj->CheckRequirementsHiddenOS (); - - BootEncObj->InitialSecurityChecksForHiddenOS (); - } - catch (Exception &e) - { - e.Show (MainDlg); - return FALSE; - } - - LoadPage (MainDlg, SYSENC_MULTI_BOOT_MODE_PAGE); - } - else - LoadPage (MainDlg, SYSENC_HIDDEN_OS_REQ_CHECK_PAGE); - - NormalCursor (); - } - else - return TRUE; - } - else - return FALSE; - - return TRUE; -} - -void SwitchWizardToNonSysInplaceEncResumeMode (void) -{ - if (!IsAdmin() && IsUacSupported()) - { - if (!ElevateWholeWizardProcess ("/zinplace")) - AbortProcessSilent (); - } - - if (!IsAdmin()) - AbortProcess("ADMIN_PRIVILEGES_WARN_DEVICES"); - - CreateNonSysInplaceEncMutex (); - - bInPlaceEncNonSys = TRUE; - bInPlaceEncNonSysResumed = TRUE; - - ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE); - - LoadPage (MainDlg, NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE); -} - -// Use this function e.g. if the config file with the system encryption settings was lost or not written -// correctly, and we don't know whether to encrypt or decrypt (but we know that encryption or decryption -// is required). Returns FALSE if failed or cancelled. -static BOOL ResolveUnknownSysEncDirection (void) -{ - if (CreateSysEncMutex ()) - { - if (SystemEncryptionStatus != SYSENC_STATUS_ENCRYPTING - && SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) - { - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - return FALSE; - } - - if (BootEncStatus.SetupInProgress) - { - return ChangeSystemEncryptionStatus ( - (BootEncStatus.SetupMode != SetupDecryption) ? SYSENC_STATUS_ENCRYPTING : SYSENC_STATUS_DECRYPTING); - } - else - { - // Ask the user to select encryption, decryption, or cancel - - char *tmpStr[] = {0, - !BootEncStatus.DriveEncrypted ? "CHOOSE_ENCRYPT_OR_DECRYPT_FINALIZE_DECRYPT_NOTE" : "CHOOSE_ENCRYPT_OR_DECRYPT", - "ENCRYPT", - "DECRYPT", - "IDCANCEL", - 0}; - - switch (AskMultiChoice ((void **) tmpStr, FALSE)) - { - case 1: - return ChangeSystemEncryptionStatus (SYSENC_STATUS_ENCRYPTING); - case 2: - return ChangeSystemEncryptionStatus (SYSENC_STATUS_DECRYPTING); - default: - return FALSE; - } - } - } - else - return TRUE; - } - else - { - Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - return FALSE; - } -} - -// This function should be used to resolve inconsistencies that might lead to a deadlock (inability to encrypt or -// decrypt the system partition/drive and to uninstall TrueCrypt). The function removes the system encryption key -// data ("volume header"), the TrueCrypt boot loader, restores the original system loader (if available), -// unregisters the boot driver, etc. Note that if the system partition/drive is encrypted, it will start decrypting -// it in the background (therefore, it should be used when the system partition/drive is not encrypted, ideally). -// Exceptions are handled and errors are reported within the function. Returns TRUE if successful. -static BOOL ForceRemoveSysEnc (void) -{ - if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption - { - BootEncryptionStatus locBootEncStatus; - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - - if (locBootEncStatus.SetupInProgress) - BootEncObj->AbortSetupWait (); - - locBootEncStatus = BootEncObj->GetStatus(); - - if (locBootEncStatus.DriveMounted) - { - // Remove the header - BootEncObj->StartDecryption (DiscardUnreadableEncryptedSectors); - locBootEncStatus = BootEncObj->GetStatus(); - - while (locBootEncStatus.SetupInProgress) - { - Sleep (100); - locBootEncStatus = BootEncObj->GetStatus(); - } - - BootEncObj->CheckEncryptionSetupResult (); - } - - Sleep (50); - } - catch (Exception &e) - { - e.Show (MainDlg); - return FALSE; - } - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - - if (!locBootEncStatus.DriveMounted) - BootEncObj->Deinstall (); - } - catch (Exception &e) - { - e.Show (MainDlg); - return FALSE; - } - - return TRUE; - } - else - return FALSE; -} - -// Returns 0 if there's an error. -__int64 GetSystemPartitionSize (void) -{ - try - { - return BootEncObj->GetSystemDriveConfiguration().SystemPartition.Info.PartitionLength.QuadPart; - } - catch (Exception &e) - { - e.Show (MainDlg); - return 0; - } -} - -void ComboSelChangeEA (HWND hwndDlg) -{ - LPARAM nIndex = SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); - - if (nIndex == CB_ERR) - { - SetWindowText (GetDlgItem (hwndDlg, IDC_BOX_HELP), ""); - } - else - { - char name[100]; - wchar_t auxLine[4096]; - wchar_t hyperLink[256] = { 0 }; - char cipherIDs[5]; - int i, cnt = 0; - - nIndex = SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); - EAGetName (name, nIndex); - - if (strcmp (name, "AES") == 0) - { - swprintf_s (hyperLink, sizeof(hyperLink) / 2, GetString ("MORE_INFO_ABOUT"), name); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("AES_HELP")); - } - else if (strcmp (name, "Serpent") == 0) - { - swprintf_s (hyperLink, sizeof(hyperLink) / 2, GetString ("MORE_INFO_ABOUT"), name); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SERPENT_HELP")); - } - else if (strcmp (name, "Twofish") == 0) - { - swprintf_s (hyperLink, sizeof(hyperLink) / 2, GetString ("MORE_INFO_ABOUT"), name); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("TWOFISH_HELP")); - } - else if (EAGetCipherCount (nIndex) > 1) - { - // Cascade - cipherIDs[cnt++] = i = EAGetLastCipher(nIndex); - while (i = EAGetPreviousCipher(nIndex, i)) - { - cipherIDs[cnt] = i; - cnt++; - } - - switch (cnt) // Number of ciphers in the cascade - { - case 2: - swprintf (auxLine, GetString ("TWO_LAYER_CASCADE_HELP"), - CipherGetName (cipherIDs[1]), - CipherGetKeySize (cipherIDs[1])*8, - CipherGetName (cipherIDs[0]), - CipherGetKeySize (cipherIDs[0])*8); - break; - - case 3: - swprintf (auxLine, GetString ("THREE_LAYER_CASCADE_HELP"), - CipherGetName (cipherIDs[2]), - CipherGetKeySize (cipherIDs[2])*8, - CipherGetName (cipherIDs[1]), - CipherGetKeySize (cipherIDs[1])*8, - CipherGetName (cipherIDs[0]), - CipherGetKeySize (cipherIDs[0])*8); - break; - } - - wcscpy_s (hyperLink, sizeof(hyperLink) / 2, GetString ("IDC_LINK_MORE_INFO_ABOUT_CIPHER")); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), auxLine); - } - else - { - // No info available for this encryption algorithm - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), L""); - } - - - // Update hyperlink - SetWindowTextW (GetDlgItem (hwndDlg, IDC_LINK_MORE_INFO_ABOUT_CIPHER), hyperLink); - AccommodateTextField (hwndDlg, IDC_LINK_MORE_INFO_ABOUT_CIPHER, FALSE); - } -} - -static void VerifySizeAndUpdate (HWND hwndDlg, BOOL bUpdate) -{ - BOOL bEnable = TRUE; - char szTmp[50]; - __int64 lTmp; - size_t i; - static unsigned __int64 nLastVolumeSize = 0; - - GetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTmp, sizeof (szTmp)); - - for (i = 0; i < strlen (szTmp); i++) - { - if (szTmp[i] >= '0' && szTmp[i] <= '9') - continue; - else - { - bEnable = FALSE; - break; - } - } - - if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_KB))) - nMultiplier = BYTES_PER_KB; - else if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_MB))) - nMultiplier = BYTES_PER_MB; - else - nMultiplier = BYTES_PER_GB; - - if (bDevice && !(bHiddenVol && !bHiddenVolHost)) // If raw device but not a hidden volume - { - lTmp = nVolumeSize; - i = 1; - } - else - { - i = nMultiplier; - lTmp = _atoi64 (szTmp); - } - - if (bEnable) - { - if (lTmp * i < (bHiddenVolHost ? TC_MIN_HIDDEN_VOLUME_HOST_SIZE : (bHiddenVol ? TC_MIN_HIDDEN_VOLUME_SIZE : TC_MIN_VOLUME_SIZE))) - bEnable = FALSE; - - if (!bHiddenVolHost && bHiddenVol) - { - if (lTmp * i > nMaximumHiddenVolSize) - bEnable = FALSE; - } - else - { - if (lTmp * i > (bHiddenVolHost ? TC_MAX_HIDDEN_VOLUME_HOST_SIZE : TC_MAX_VOLUME_SIZE)) - bEnable = FALSE; - } - - if (lTmp * i % SECTOR_SIZE != 0) - bEnable = FALSE; - } - - if (bUpdate) - { - nUIVolumeSize = lTmp; - - if (!bDevice || (bHiddenVol && !bHiddenVolHost)) // Update only if it's not a raw device or if it's a hidden volume - nVolumeSize = i * lTmp; - } - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), bEnable); - - if (nVolumeSize != nLastVolumeSize) - { - // Change of volume size may make some file systems allowed or disallowed, so the default filesystem must - // be reselected. - fileSystem = FILESYS_NONE; - nLastVolumeSize = nVolumeSize; - } -} - -static void UpdateWizardModeControls (HWND hwndDlg, int setWizardMode) -{ - SendMessage (GetDlgItem (hwndDlg, IDC_FILE_CONTAINER), - BM_SETCHECK, - setWizardMode == WIZARD_MODE_FILE_CONTAINER ? BST_CHECKED : BST_UNCHECKED, - 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_NONSYS_DEVICE), - BM_SETCHECK, - setWizardMode == WIZARD_MODE_NONSYS_DEVICE ? BST_CHECKED : BST_UNCHECKED, - 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_SYS_DEVICE), - BM_SETCHECK, - setWizardMode == WIZARD_MODE_SYS_DEVICE ? BST_CHECKED : BST_UNCHECKED, - 0); -} - -static int GetSelectedWizardMode (HWND hwndDlg) -{ - if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_FILE_CONTAINER))) - return WIZARD_MODE_FILE_CONTAINER; - - if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_NONSYS_DEVICE))) - return WIZARD_MODE_NONSYS_DEVICE; - - if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_SYS_DEVICE))) - return WIZARD_MODE_SYS_DEVICE; - - return DEFAULT_VOL_CREATION_WIZARD_MODE; -} - -static void RefreshMultiBootControls (HWND hwndDlg) -{ - SendMessage (GetDlgItem (hwndDlg, IDC_SINGLE_BOOT), - BM_SETCHECK, - nMultiBoot == 1 ? BST_CHECKED : BST_UNCHECKED, - 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_BOOT), - BM_SETCHECK, - nMultiBoot > 1 ? BST_CHECKED : BST_UNCHECKED, - 0); -} - -// -1 = Undecided or error, 0 = No, 1 = Yes -static int Get2RadButtonPageAnswer (void) -{ - if (IsButtonChecked (GetDlgItem (hCurPage, IDC_CHOICE1))) - return 1; - - if (IsButtonChecked (GetDlgItem (hCurPage, IDC_CHOICE2))) - return 0; - - return -1; -} - -// 0 = No, 1 = Yes -static void Update2RadButtonPage (int answer) -{ - SendMessage (GetDlgItem (hCurPage, IDC_CHOICE1), - BM_SETCHECK, - answer == 1 ? BST_CHECKED : BST_UNCHECKED, - 0); - - SendMessage (GetDlgItem (hCurPage, IDC_CHOICE2), - BM_SETCHECK, - answer == 0 ? BST_CHECKED : BST_UNCHECKED, - 0); -} - -// -1 = Undecided, 0 = No, 1 = Yes -static void Init2RadButtonPageYesNo (int answer) -{ - SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE1), GetString ("UISTR_YES")); - SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE2), GetString ("UISTR_NO")); - - SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), answer >= 0); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), TRUE); - - Update2RadButtonPage (answer); -} - -static void UpdateSysEncProgressBar (void) -{ - BootEncryptionStatus locBootEncStatus; - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - } - catch (...) - { - return; - } - - if (locBootEncStatus.EncryptedAreaEnd == -1 - || locBootEncStatus.EncryptedAreaStart == -1) - { - UpdateProgressBarProc (0); - } - else - { - UpdateProgressBarProc ((locBootEncStatus.EncryptedAreaEnd - locBootEncStatus.EncryptedAreaStart + 1) / SECTOR_SIZE); - - if (locBootEncStatus.SetupInProgress) - { - wchar_t tmpStr[100]; - - // Status - - if (locBootEncStatus.TransformWaitingForIdle) - wcscpy (tmpStr, GetString ("PROGRESS_STATUS_WAITING")); - else - wcscpy (tmpStr, GetString (SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING ? "PROGRESS_STATUS_DECRYPTING" : "PROGRESS_STATUS_ENCRYPTING")); - - wcscat (tmpStr, L" "); - - SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), tmpStr); - } - } -} - -static void InitSysEncProgressBar (void) -{ - BootEncryptionStatus locBootEncStatus; - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - } - catch (...) - { - return; - } - - if (locBootEncStatus.ConfiguredEncryptedAreaEnd == -1 - || locBootEncStatus.ConfiguredEncryptedAreaStart == -1) - return; - - InitProgressBar ((locBootEncStatus.ConfiguredEncryptedAreaEnd - - locBootEncStatus.ConfiguredEncryptedAreaStart + 1) / SECTOR_SIZE, - (locBootEncStatus.EncryptedAreaEnd == locBootEncStatus.EncryptedAreaStart || locBootEncStatus.EncryptedAreaEnd == -1) ? - 0 : locBootEncStatus.EncryptedAreaEnd - locBootEncStatus.EncryptedAreaStart + 1, - SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING, - TRUE, - TRUE, - TRUE); -} - -static void UpdateSysEncControls (void) -{ - BootEncryptionStatus locBootEncStatus; - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - } - catch (...) - { - return; - } - - EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), - !locBootEncStatus.SetupInProgress - && SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING); - - SetWindowTextW (GetDlgItem (hCurPage, IDC_PAUSE), - GetString (locBootEncStatus.SetupInProgress ? "IDC_PAUSE" : "RESUME")); - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), !locBootEncStatus.SetupInProgress && !bFirstSysEncResumeDone); - - if (!locBootEncStatus.SetupInProgress) - { - wchar_t tmpStr[100]; - - wcscpy (tmpStr, GetString ((SysDriveOrPartitionFullyEncrypted (TRUE) || !locBootEncStatus.DriveMounted) ? - "PROGRESS_STATUS_FINISHED" : "PROGRESS_STATUS_PAUSED")); - wcscat (tmpStr, L" "); - - // Status - SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), tmpStr); - - if (SysDriveOrPartitionFullyEncrypted (TRUE) || SystemEncryptionStatus == SYSENC_STATUS_NONE) - { - wcscpy (tmpStr, GetString ("PROCESSED_PORTION_100_PERCENT")); - wcscat (tmpStr, L" "); - - SetWindowTextW (GetDlgItem (hCurPage, IDC_BYTESWRITTEN), tmpStr); - } - - SetWindowText (GetDlgItem (hCurPage, IDC_TIMEREMAIN), " "); - } -} - -static void SysEncPause (void) -{ - BootEncryptionStatus locBootEncStatus; - - if (CreateSysEncMutex ()) - { - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - return; - } - - if (!locBootEncStatus.SetupInProgress) - { - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - return; - } - - WaitCursor (); - - try - { - int attempts = SYSENC_PAUSE_RETRIES; - - BootEncObj->AbortSetup (); - - locBootEncStatus = BootEncObj->GetStatus(); - - while (locBootEncStatus.SetupInProgress && attempts > 0) - { - Sleep (SYSENC_PAUSE_RETRY_INTERVAL); - attempts--; - locBootEncStatus = BootEncObj->GetStatus(); - } - - if (!locBootEncStatus.SetupInProgress) - BootEncObj->CheckEncryptionSetupResult (); - - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - NormalCursor (); - - if (locBootEncStatus.SetupInProgress) - { - SetTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS, TIMER_INTERVAL_SYSENC_PROGRESS, NULL); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - Error ("FAILED_TO_INTERRUPT_SYSTEM_ENCRYPTION"); - return; - } - - UpdateSysEncControls (); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - } - else - Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); -} - - -static void SysEncResume (void) -{ - BootEncryptionStatus locBootEncStatus; - - if (CreateSysEncMutex ()) - { - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); - - try - { - locBootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - return; - } - - if (locBootEncStatus.SetupInProgress) - { - bSystemEncryptionInProgress = TRUE; - UpdateSysEncControls (); - SetTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS, TIMER_INTERVAL_SYSENC_PROGRESS, NULL); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - return; - } - - bSystemEncryptionInProgress = FALSE; - WaitCursor (); - - try - { - switch (SystemEncryptionStatus) - { - case SYSENC_STATUS_ENCRYPTING: - - BootEncObj->StartEncryption (nWipeMode, bTryToCorrectReadErrors ? true : false); - break; - - case SYSENC_STATUS_DECRYPTING: - - if (locBootEncStatus.DriveMounted) // If the drive is not encrypted we will just deinstall - BootEncObj->StartDecryption (DiscardUnreadableEncryptedSectors); - - break; - } - - bSystemEncryptionInProgress = TRUE; - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - NormalCursor (); - - if (!bSystemEncryptionInProgress) - { - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - Error ("FAILED_TO_RESUME_SYSTEM_ENCRYPTION"); - return; - } - - bFirstSysEncResumeDone = TRUE; - InitSysEncProgressBar (); - UpdateSysEncProgressBar (); - UpdateSysEncControls (); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); - SetTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS, TIMER_INTERVAL_SYSENC_PROGRESS, NULL); - } - else - Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); -} - - -static BOOL GetDevicePathForHiddenOS (void) -{ - BOOL tmpbDevice = FALSE; - - try - { - strncpy (szFileName, BootEncObj->GetPartitionForHiddenOS().DevicePath.c_str(), sizeof(szFileName)); - - CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); - } - catch (Exception &e) - { - e.Show (MainDlg); - return FALSE; - } - - return (szFileName[0] != 0 - && szDiskFile[0] != 0 - && tmpbDevice); -} - - -// Returns TRUE if there is unallocated space greater than 64 MB (max possible slack space size) between the -// boot partition and the first partition behind it. If there's none or if an error occurs, returns FALSE. -static BOOL CheckGapBetweenSysAndHiddenOS (void) -{ - try - { - SystemDriveConfiguration sysDriveCfg = BootEncObj->GetSystemDriveConfiguration(); - - return (sysDriveCfg.SystemPartition.Info.StartingOffset.QuadPart - + sysDriveCfg.SystemPartition.Info.PartitionLength.QuadPart - + 64 * BYTES_PER_MB - + 128 * BYTES_PER_KB - <= BootEncObj->GetPartitionForHiddenOS().Info.StartingOffset.QuadPart); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - return FALSE; -} - - -static void NonSysInplaceEncPause (void) -{ - bVolTransformThreadCancel = TRUE; - - WaitCursor (); - - int waitThreshold = 100; // Do not block GUI events for more than 10 seconds. IMPORTANT: This prevents deadlocks when the thread calls us back e.g. to update GUI! - - while (bVolTransformThreadRunning || bVolTransformThreadToRun) - { - MSG guiMsg; - - bVolTransformThreadCancel = TRUE; - - if (waitThreshold <= 0) - { - while (PeekMessage (&guiMsg, NULL, 0, 0, PM_REMOVE) != 0) - { - DispatchMessage (&guiMsg); - } - } - else - waitThreshold--; - - Sleep (100); - } -} - - -static void NonSysInplaceEncResume (void) -{ - if (bVolTransformThreadRunning || bVolTransformThreadToRun || bVolTransformThreadCancel) - return; - - if (!bInPlaceEncNonSysResumed - && !FinalPreTransformPrompts ()) - { - return; - } - - CreateNonSysInplaceEncMutex (); - - bFirstNonSysInPlaceEncResumeDone = TRUE; - - SetTimer (MainDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS, TIMER_INTERVAL_NONSYS_INPLACE_ENC_PROGRESS, NULL); - - bVolTransformThreadCancel = FALSE; - bVolTransformThreadToRun = TRUE; - - UpdateNonSysInPlaceEncControls (); - - LastDialogId = "NONSYS_INPLACE_ENC_IN_PROGRESS"; - - _beginthread (volTransformThreadFunction, 0, MainDlg); - - return; -} - - -void ShowNonSysInPlaceEncUIStatus (void) -{ - wchar_t nonSysInplaceEncUIStatus [300] = {0}; - - switch (NonSysInplaceEncStatus) - { - case NONSYS_INPLACE_ENC_STATUS_PAUSED: - wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_PAUSED")); - break; - case NONSYS_INPLACE_ENC_STATUS_PREPARING: - wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_PREPARING")); - break; - case NONSYS_INPLACE_ENC_STATUS_RESIZING: - wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_RESIZING")); - break; - case NONSYS_INPLACE_ENC_STATUS_ENCRYPTING: - wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_ENCRYPTING")); - break; - case NONSYS_INPLACE_ENC_STATUS_FINALIZING: - wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_FINALIZING")); - break; - case NONSYS_INPLACE_ENC_STATUS_FINISHED: - wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_FINISHED")); - break; - case NONSYS_INPLACE_ENC_STATUS_ERROR: - wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_ERROR")); - break; - } - - wcscat (nonSysInplaceEncUIStatus, L" "); - - SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), nonSysInplaceEncUIStatus); -} - - -void UpdateNonSysInPlaceEncControls (void) -{ - EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), !(bVolTransformThreadRunning || bVolTransformThreadToRun)); - - SetWindowTextW (GetDlgItem (hCurPage, IDC_PAUSE), - GetString ((bVolTransformThreadRunning || bVolTransformThreadToRun) ? "IDC_PAUSE" : "RESUME")); - - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString (bInPlaceEncNonSysResumed ? "DEFER" : "CANCEL")); - - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), bFirstNonSysInPlaceEncResumeDone - && NonSysInplaceEncStatus != NONSYS_INPLACE_ENC_STATUS_FINALIZING - && NonSysInplaceEncStatus != NONSYS_INPLACE_ENC_STATUS_FINISHED); - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), !(bVolTransformThreadRunning || bVolTransformThreadToRun) && !bFirstNonSysInPlaceEncResumeDone); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), !(bVolTransformThreadRunning || bVolTransformThreadToRun) && !bInPlaceEncNonSysResumed); - EnableWindow (GetDlgItem (MainDlg, IDCANCEL), - !(bVolTransformThreadToRun - || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_PREPARING - || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_RESIZING - || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINALIZING - || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)); - - if (bVolTransformThreadRunning || bVolTransformThreadToRun) - { - switch (NonSysInplaceEncStatus) - { - case NONSYS_INPLACE_ENC_STATUS_PREPARING: - case NONSYS_INPLACE_ENC_STATUS_RESIZING: - case NONSYS_INPLACE_ENC_STATUS_FINALIZING: - ArrowWaitCursor (); - break; - - case NONSYS_INPLACE_ENC_STATUS_ENCRYPTING: - NormalCursor (); - break; - - default: - NormalCursor (); - break; - } - - if (bVolTransformThreadCancel) - WaitCursor (); - } - else - { - NormalCursor (); - - if (bInPlaceEncNonSysResumed) - { - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED); - } - else - SetWindowText (GetDlgItem (hCurPage, IDC_WRITESPEED), " "); - - SetWindowText (GetDlgItem (hCurPage, IDC_TIMEREMAIN), " "); - } - - ShowNonSysInPlaceEncUIStatus (); - - UpdateNonSysInplaceEncProgressBar (); -} - - -static void UpdateNonSysInplaceEncProgressBar (void) -{ - static int lastNonSysInplaceEncStatus = NONSYS_INPLACE_ENC_STATUS_NONE; - int nonSysInplaceEncStatus = NonSysInplaceEncStatus; - __int64 totalSectors; - - totalSectors = NonSysInplaceEncTotalSectors; - - if (bVolTransformThreadRunning - && (nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_ENCRYPTING - || nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINALIZING - || nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)) - { - if (lastNonSysInplaceEncStatus != nonSysInplaceEncStatus - && nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_ENCRYPTING) - { - InitNonSysInplaceEncProgressBar (); - } - else - { - if (totalSectors <= 0 && nVolumeSize > 0) - totalSectors = nVolumeSize / SECTOR_SIZE; - - if (totalSectors > 0) - UpdateProgressBarProc (NonSysInplaceEncBytesDone / SECTOR_SIZE); - } - } - - ShowNonSysInPlaceEncUIStatus (); - - lastNonSysInplaceEncStatus = nonSysInplaceEncStatus; -} - - -static void InitNonSysInplaceEncProgressBar (void) -{ - __int64 totalSectors = NonSysInplaceEncTotalSectors; - - if (totalSectors <= 0) - { - if (nVolumeSize <= 0) - return; - - totalSectors = nVolumeSize / SECTOR_SIZE; - } - - InitProgressBar (totalSectors, - NonSysInplaceEncBytesDone, - FALSE, - TRUE, - TRUE, - TRUE); -} - - -void DisplayRandPool (HWND hPoolDisplay, BOOL bShow) -{ - unsigned char tmp[4]; - unsigned char tmpByte; - int col, row; - static BOOL bRandPoolDispAscii = FALSE; - - if (!bShow) - { - SetWindowText (hPoolDisplay, ""); - return; - } - - RandpeekBytes (randPool, sizeof (randPool)); - - if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) - { - outRandPoolDispBuffer[0] = 0; - - for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) - { - for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) - { - tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; - - sprintf ((char *) tmp, bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != '&') ? " %c " : " . ") : "%02X ", tmpByte); - strcat ((char *) outRandPoolDispBuffer, (char *) tmp); - } - strcat ((char *) outRandPoolDispBuffer, "\n"); - } - SetWindowText (hPoolDisplay, (char *) outRandPoolDispBuffer); - - memcpy (lastRandPool, randPool, sizeof(lastRandPool)); - } -} - - -static void WipeAbort (void) -{ - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); - - if (bHiddenOS && IsHiddenOSRunning()) - { - /* Decoy system partition wipe */ - - DecoySystemWipeStatus decoySysPartitionWipeStatus; - - try - { - decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); - return; - } - - if (!decoySysPartitionWipeStatus.WipeInProgress) - { - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); - return; - } - - WaitCursor (); - - try - { - int attempts = SYSENC_PAUSE_RETRIES; - - BootEncObj->AbortDecoyOSWipe (); - - decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); - - while (decoySysPartitionWipeStatus.WipeInProgress && attempts > 0) - { - Sleep (SYSENC_PAUSE_RETRY_INTERVAL); - attempts--; - decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); - } - - if (!decoySysPartitionWipeStatus.WipeInProgress) - BootEncObj->CheckDecoyOSWipeResult (); - - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - NormalCursor (); - - if (decoySysPartitionWipeStatus.WipeInProgress) - { - SetTimer (MainDlg, TIMER_ID_WIPE_PROGRESS, TIMER_INTERVAL_WIPE_PROGRESS, NULL); - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); - Error ("FAILED_TO_INTERRUPT_WIPING"); - return; - } - } - else - { - /* Regular device wipe (not decoy system partition wipe) */ - } - - UpdateWipeControls (); - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); -} - - -static void WipeStart (void) -{ - if (bHiddenOS && IsHiddenOSRunning()) - { - /* Decoy system partition wipe */ - - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); - - bDeviceWipeInProgress = FALSE; - WaitCursor (); - - try - { - BootEncObj->StartDecoyOSWipe (nWipeMode); - - bDeviceWipeInProgress = TRUE; - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - NormalCursor (); - - if (!bDeviceWipeInProgress) - { - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); - Error ("FAILED_TO_START_WIPING"); - return; - } - } - else - { - /* Regular device wipe (not decoy system partition wipe) */ - } - - InitWipeProgressBar (); - UpdateWipeProgressBar (); - UpdateWipeControls (); - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); - SetTimer (MainDlg, TIMER_ID_WIPE_PROGRESS, TIMER_INTERVAL_WIPE_PROGRESS, NULL); -} - - -static void UpdateWipeProgressBar (void) -{ - if (bHiddenOS && IsHiddenOSRunning()) - { - /* Decoy system partition wipe */ - - DecoySystemWipeStatus decoySysPartitionWipeStatus; - - try - { - decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); - BootEncStatus = BootEncObj->GetStatus(); - } - catch (...) - { - return; - } - - if (decoySysPartitionWipeStatus.WipedAreaEnd == -1) - UpdateProgressBarProc (0); - else - UpdateProgressBarProc ((decoySysPartitionWipeStatus.WipedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1) / SECTOR_SIZE); - } - else - { - /* Regular device wipe (not decoy system partition wipe) */ - } -} - - -static void InitWipeProgressBar (void) -{ - if (bHiddenOS && IsHiddenOSRunning()) - { - /* Decoy system partition wipe */ - - DecoySystemWipeStatus decoySysPartitionWipeStatus; - - try - { - decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); - BootEncStatus = BootEncObj->GetStatus(); - } - catch (...) - { - return; - } - - if (BootEncStatus.ConfiguredEncryptedAreaEnd == -1 - || BootEncStatus.ConfiguredEncryptedAreaStart == -1) - return; - - InitProgressBar ((BootEncStatus.ConfiguredEncryptedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1) / SECTOR_SIZE, - (decoySysPartitionWipeStatus.WipedAreaEnd == BootEncStatus.ConfiguredEncryptedAreaStart || decoySysPartitionWipeStatus.WipedAreaEnd == -1) ? - 0 : decoySysPartitionWipeStatus.WipedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1, - FALSE, - TRUE, - FALSE, - TRUE); - } - else - { - /* Regular device wipe (not decoy system partition wipe) */ - } -} - - -static void UpdateWipeControls (void) -{ - if (bHiddenOS && IsHiddenOSRunning()) - { - /* Decoy system partition wipe */ - - DecoySystemWipeStatus decoySysPartitionWipeStatus; - - try - { - decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); - BootEncStatus = BootEncObj->GetStatus(); - } - catch (...) - { - return; - } - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), !decoySysPartitionWipeStatus.WipeInProgress); - } - else - { - /* Regular device wipe (not decoy system partition wipe) */ - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), bDeviceWipeInProgress); - - if (!bDeviceWipeInProgress) - { - SetWindowText (GetDlgItem (hCurPage, IDC_TIMEREMAIN), " "); - } - } - - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), bDeviceWipeInProgress); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), !bDeviceWipeInProgress); - - bConfirmQuit = bDeviceWipeInProgress; -} - - - -static void __cdecl sysEncDriveAnalysisThread (void *hwndDlgArg) -{ - // Mark the detection process as 'in progress' - HiddenSectorDetectionStatus = 1; - SaveSettings (NULL); - BroadcastSysEncCfgUpdate (); - - try - { - BootEncObj->ProbeRealSystemDriveSize (); - bSysEncDriveAnalysisTimeOutOccurred = FALSE; - } - catch (TimeOut &) - { - bSysEncDriveAnalysisTimeOutOccurred = TRUE; - } - catch (Exception &e) - { - e.Show (NULL); - EndMainDlg (MainDlg); - exit(0); - } - - // Mark the detection process as successful - HiddenSectorDetectionStatus = 0; - SaveSettings (NULL); - BroadcastSysEncCfgUpdate (); - - // This artificial delay prevents user confusion on systems where the analysis ends almost instantly - Sleep (3000); - - bSysEncDriveAnalysisInProgress = FALSE; -} - -static void __cdecl volTransformThreadFunction (void *hwndDlgArg) -{ - int nStatus; - DWORD dwWin32FormatError; - BOOL bHidden; - HWND hwndDlg = (HWND) hwndDlgArg; - volatile FORMAT_VOL_PARAMETERS *volParams = (FORMAT_VOL_PARAMETERS *) malloc (sizeof(FORMAT_VOL_PARAMETERS)); - - if (volParams == NULL) - AbortProcess ("ERR_MEM_ALLOC"); - - VirtualLock ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); - - bVolTransformThreadRunning = TRUE; - bVolTransformThreadToRun = FALSE; - - // Check administrator privileges - if (!IsAdmin () && !IsUacSupported ()) - { - if (fileSystem == FILESYS_NTFS) - { - if (MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_NTFS"), lpszTitle, MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2) == IDCANCEL) - goto cancel; - } - if (bDevice) - { - if (MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_DEVICES"), lpszTitle, MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2) == IDCANCEL) - goto cancel; - } - } - - if (!bInPlaceEncNonSys) - { - if (!bDevice) - { - int x = _access (szDiskFile, 06); - if (x == 0 || errno != ENOENT) - { - wchar_t szTmp[512]; - - if (! ((bHiddenVol && !bHiddenVolHost) && errno != EACCES)) // Only ask ask for permission to overwrite an existing volume if we're not creating a hidden volume - { - _snwprintf (szTmp, sizeof szTmp / 2, - GetString (errno == EACCES ? "READONLYPROMPT" : "OVERWRITEPROMPT"), - szDiskFile); - - x = MessageBoxW (hwndDlg, szTmp, lpszTitle, YES_NO|MB_ICONWARNING|MB_DEFBUTTON2); - - if (x != IDYES) - goto cancel; - } - } - - if (_access (szDiskFile, 06) != 0) - { - if (errno == EACCES) - { - if (_chmod (szDiskFile, _S_IREAD | _S_IWRITE) != 0) - { - MessageBoxW (hwndDlg, GetString ("ACCESSMODEFAIL"), lpszTitle, ICON_HAND); - goto cancel; - } - } - } - - } - else - { - // Partition / device / dynamic volume - - if (!FinalPreTransformPrompts ()) - goto cancel; - } - } - - bHidden = bHiddenVol && !bHiddenVolHost; - - volParams->bDevice = bDevice; - volParams->hiddenVol = bHidden; - volParams->volumePath = szDiskFile; - volParams->size = nVolumeSize; - volParams->hiddenVolHostSize = nHiddenVolHostSize; - volParams->ea = nVolumeEA; - volParams->pkcs5 = hash_algo; - volParams->headerFlags = CreatingHiddenSysVol() ? TC_HEADER_FLAG_ENCRYPTED_SYSTEM : 0; - volParams->fileSystem = fileSystem; - volParams->clusterSize = clusterSize; - volParams->sparseFileSwitch = bSparseFileSwitch; - volParams->quickFormat = quickFormat; - volParams->realClusterSize = &realClusterSize; - volParams->password = &volumePassword; - volParams->hwndDlg = hwndDlg; - - if (bInPlaceEncNonSys) - { - HANDLE hPartition = INVALID_HANDLE_VALUE; - - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PREPARING); - - if (!bInPlaceEncNonSysResumed) - { - bTryToCorrectReadErrors = FALSE; - - nStatus = EncryptPartitionInPlaceBegin (volParams, &hPartition, nWipeMode); - - if (nStatus == ERR_SUCCESS) - { - nStatus = EncryptPartitionInPlaceResume (hPartition, volParams, nWipeMode, &bTryToCorrectReadErrors); - } - else if (hPartition != INVALID_HANDLE_VALUE) - { - CloseHandle (hPartition); - hPartition = INVALID_HANDLE_VALUE; - } - } - else - { - nStatus = EncryptPartitionInPlaceResume (INVALID_HANDLE_VALUE, volParams, nWipeMode, &bTryToCorrectReadErrors); - } - } - else - { - InitProgressBar (GetVolumeDataAreaSize (bHidden, nVolumeSize) / SECTOR_SIZE, 0, FALSE, FALSE, FALSE, TRUE); - - nStatus = TCFormatVolume (volParams); - } - - if (nStatus == ERR_OUTOFMEMORY) - { - AbortProcess ("OUTOFMEMORY"); - } - - if (bInPlaceEncNonSys - && nStatus == ERR_USER_ABORT - && NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED) - { - // Ignore user abort if non-system in-place encryption successfully finished - nStatus = ERR_SUCCESS; - } - - - dwWin32FormatError = GetLastError (); - - if (bHiddenVolHost && !bVolTransformThreadCancel && nStatus == 0) - { - /* Auto mount the newly created hidden volume host */ - switch (MountHiddenVolHost (hwndDlg, szDiskFile, &hiddenVolHostDriveNo, &volumePassword, FALSE)) - { - case ERR_NO_FREE_DRIVES: - MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVE_FOR_OUTER_VOL"), lpszTitle, ICON_HAND); - bVolTransformThreadCancel = TRUE; - break; - case ERR_VOL_MOUNT_FAILED: - case ERR_PASSWORD_WRONG: - MessageBoxW (hwndDlg, GetString ("CANT_MOUNT_OUTER_VOL"), lpszTitle, ICON_HAND); - bVolTransformThreadCancel = TRUE; - break; - } - } - - SetLastError (dwWin32FormatError); - - if ((bVolTransformThreadCancel || nStatus == ERR_USER_ABORT) - && !(bInPlaceEncNonSys && NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)) // Ignore user abort if non-system in-place encryption successfully finished. - { - if (!bDevice && !(bHiddenVol && !bHiddenVolHost)) // If we're not creating a hidden volume and if it's a file container - { - remove (szDiskFile); // Delete the container - } - - goto cancel; - } - - if (nStatus != ERR_USER_ABORT) - { - if (nStatus != 0) - { - /* An error occurred */ - - wchar_t szMsg[8192]; - - handleError (hwndDlg, nStatus); - - if (bInPlaceEncNonSys) - { - if (bInPlaceEncNonSysResumed) - { - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED); - Error ("INPLACE_ENC_GENERIC_ERR_RESUME"); - } - else - { - SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_ERROR); - ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_GENERIC_ERR_ALT_STEPS", TRUE); - } - } - else if (!(bHiddenVolHost && hiddenVolHostDriveNo < 0)) // If the error was not that the hidden volume host could not be mounted (this error has already been reported to the user) - { - swprintf (szMsg, GetString ("CREATE_FAILED"), szDiskFile); - MessageBoxW (hwndDlg, szMsg, lpszTitle, ICON_HAND); - } - - if (!bDevice && !(bHiddenVol && !bHiddenVolHost)) // If we're not creating a hidden volume and if it's a file container - { - remove (szDiskFile); // Delete the container - } - - goto cancel; - } - else - { - /* Volume successfully created */ - - RestoreDefaultKeyFilesParam (); - - if (bDevice && !bInPlaceEncNonSys) - { - // Handle assigned drive letter (if any) - - HandleOldAssignedDriveLetter (); - } - - if (!bHiddenVolHost) - { - if (bHiddenVol) - { - bHiddenVolFinished = TRUE; - - if (!bHiddenOS) - Warning ("HIDVOL_FORMAT_FINISHED_HELP"); - } - else if (bInPlaceEncNonSys) - { - Warning ("NONSYS_INPLACE_ENC_FINISHED_INFO"); - - HandleOldAssignedDriveLetter (); - } - else - { - Info("FORMAT_FINISHED_INFO"); - - if (bSparseFileSwitch && quickFormat) - Warning("SPARSE_FILE_SIZE_NOTE"); - } - } - else - { - /* We've just created an outer volume (to host a hidden volume within) */ - - bHiddenVolHost = FALSE; - bHiddenVolFinished = FALSE; - nHiddenVolHostSize = nVolumeSize; - - // Clear the outer volume password - memset(&szVerify[0], 0, sizeof (szVerify)); - memset(&szRawPassword[0], 0, sizeof (szRawPassword)); - - MessageBeep (MB_OK); - } - - if (!bInPlaceEncNonSys) - SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); - - if (volParams != NULL) - { - burn ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); - VirtualUnlock ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); - free ((LPVOID) volParams); - volParams = NULL; - } - - bVolTransformThreadRunning = FALSE; - bVolTransformThreadCancel = FALSE; - - PostMessage (hwndDlg, bInPlaceEncNonSys ? TC_APPMSG_NONSYS_INPLACE_ENC_FINISHED : TC_APPMSG_FORMAT_FINISHED, 0, 0); - - LastDialogId = "FORMAT_FINISHED"; - _endthread (); - } - } - -cancel: - LastDialogId = (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_CANCELED" : "FORMAT_CANCELED"); - - if (!bInPlaceEncNonSys) - SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); - - if (volParams != NULL) - { - burn ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); - VirtualUnlock ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); - free ((LPVOID) volParams); - volParams = NULL; - } - - bVolTransformThreadRunning = FALSE; - bVolTransformThreadCancel = FALSE; - - PostMessage (hwndDlg, TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED, 0, 0); - - if (bHiddenVolHost && hiddenVolHostDriveNo < -1 && !bVolTransformThreadCancel) // If hidden volume host could not be mounted - AbortProcessSilent (); - - _endthread (); -} - -static void LoadPage (HWND hwndDlg, int nPageNo) -{ - RECT rD, rW; - - nLastPageNo = nCurPageNo; - - if (hCurPage != NULL) - { - // WARNING: nCurPageNo must be set to a non-existent ID here before wiping the password fields below in - // this function, etc. Otherwise, such actions (SetWindowText) would invoke the EN_CHANGE handlers, which - // would, if keyfiles were applied, e.g. use strlen() on a buffer full of random data, in most cases - // not null-terminated. - nCurPageNo = -1; - - - // Place here any actions that need to be performed at the latest possible time when leaving a wizard page - // (i.e. right before "destroying" the page). Also, code that needs to be executed both on IDC_NEXT and - // on IDC_PREV can be placed here so as to avoid code doubling. - - switch (nLastPageNo) - { - case PASSWORD_PAGE: - { - char tmp[MAX_PASSWORD+1]; - - // Attempt to wipe passwords stored in the input field buffers. This is performed here (and - // not in the IDC_PREV or IDC_NEXT sections) in order to prevent certain race conditions - // when keyfiles are used. - memset (tmp, 'X', MAX_PASSWORD); - tmp [MAX_PASSWORD] = 0; - SetWindowText (hPasswordInputField, tmp); - SetWindowText (hVerifyPasswordInputField, tmp); - } - break; - } - - DestroyWindow (hCurPage); - hCurPage = NULL; - } - - // This prevents the mouse pointer from remaining as the "hand" cursor when the user presses Enter - // while hovering over a hyperlink. - bHyperLinkBeingTracked = FALSE; - NormalCursor(); - - GetWindowRect (GetDlgItem (hwndDlg, IDC_POS_BOX), &rW); - - - nCurPageNo = nPageNo; - - - switch (nPageNo) - { - case INTRO_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INTRO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_TYPE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_TYPE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_HIDDEN_OS_REQ_CHECK_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_SPAN_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_SPAN_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_PRE_DRIVE_ANALYSIS_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_DRIVE_ANALYSIS_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_DRIVE_ANALYSIS_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_MULTI_BOOT_MODE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_MULTI_BOOT_MODE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE: - case SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE: - case SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE: - case SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_MULTI_BOOT_OUTCOME_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case VOLUME_TYPE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_VOLUME_TYPE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case HIDDEN_VOL_WIZARD_MODE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_HIDDEN_VOL_WIZARD_MODE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case VOLUME_LOCATION_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_VOLUME_LOCATION_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - - EnableWindow (GetDlgItem(hCurPage, IDC_NO_HISTORY), !bHistoryCmdLine); - - EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), - GetWindowTextLength (GetDlgItem (hCurPage, IDC_COMBO_BOX)) > 0); - - break; - - case DEVICE_TRANSFORM_MODE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_DEVICE_TRANSFORM_MODE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case HIDDEN_VOL_HOST_PRE_CIPHER_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case HIDDEN_VOL_PRE_CIPHER_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case CIPHER_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_CIPHER_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SIZE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SIZE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case HIDDEN_VOL_HOST_PASSWORD_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_PASSWORD_ENTRY_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case PASSWORD_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_PASSWORD_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case FILESYS_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_COLLECTING_RANDOM_DATA_PAGE: - case NONSYS_INPLACE_ENC_RAND_DATA_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_COLLECTING_RANDOM_DATA_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_KEYS_GEN_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_KEYS_GEN_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_RESCUE_DISK_CREATION_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_RESCUE_DISK_CREATION_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_RESCUE_DISK_BURN_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_RESCUE_DISK_BURN_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_RESCUE_DISK_VERIFIED_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_WIPE_MODE_PAGE: - case NONSYS_INPLACE_ENC_WIPE_MODE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_WIPE_MODE_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_PRETEST_INFO_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_PRETEST_RESULT_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case SYSENC_ENCRYPTION_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INPLACE_ENCRYPTION_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_PASSWORD_ENTRY_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_EXPANDED_LIST_SELECT_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INPLACE_ENCRYPTION_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case FORMAT_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_FORMAT_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - case FORMAT_FINISHED_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW ((bHiddenVol && !bHiddenVolHost && !bHiddenVolFinished) ? IDD_HIDVOL_HOST_FILL_PAGE_DLG : IDD_INFO_PAGE_DLG), hwndDlg, - (DLGPROC) PageDialogProc); - break; - - case SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); - break; - - case SYSENC_HIDDEN_OS_WIPE_INFO_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); - break; - - case DEVICE_WIPE_MODE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_DEVICE_WIPE_MODE_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); - break; - - case DEVICE_WIPE_PAGE: - hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_DEVICE_WIPE_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); - break; - } - - rD.left = 162; - rD.top = 25; - rD.right = 0; - rD.bottom = 0; - MapDialogRect (hwndDlg, &rD); - - if (hCurPage != NULL) - { - MoveWindow (hCurPage, rD.left, rD.top, rW.right - rW.left, rW.bottom - rW.top, TRUE); - ShowWindow (hCurPage, SW_SHOWNORMAL); - - // Place here any message boxes that need to be displayed as soon as a new page is displayed. This - // ensures that the page is fully rendered (otherwise it would remain blank, until the message box - // is closed). - switch (nPageNo) - { - case PASSWORD_PAGE: - - CheckCapsLock (hwndDlg, FALSE); - - if (CreatingHiddenSysVol()) - Warning ("PASSWORD_HIDDEN_OS_NOTE"); - - break; - - case CIPHER_PAGE: - - if (CreatingHiddenSysVol()) - Warning ("HIDDEN_OS_PRE_CIPHER_WARNING"); - - break; - } - } -} - - -int PrintFreeSpace (HWND hwndTextBox, char *lpszDrive, PLARGE_INTEGER lDiskFree) -{ - char *nResourceString; - int nMultiplier; - wchar_t szTmp2[256]; - - if (lDiskFree->QuadPart < BYTES_PER_KB) - nMultiplier = 1; - else if (lDiskFree->QuadPart < BYTES_PER_MB) - nMultiplier = BYTES_PER_KB; - else if (lDiskFree->QuadPart < BYTES_PER_GB) - nMultiplier = BYTES_PER_MB; - else - nMultiplier = BYTES_PER_GB; - - if (nMultiplier == 1) - { - if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume - nResourceString = "MAX_HIDVOL_SIZE_BYTES"; - else if (bDevice) - nResourceString = "DEVICE_FREE_BYTES"; - else - nResourceString = "DISK_FREE_BYTES"; - } - else if (nMultiplier == BYTES_PER_KB) - { - if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume - nResourceString = "MAX_HIDVOL_SIZE_KB"; - else if (bDevice) - nResourceString = "DEVICE_FREE_KB"; - else - nResourceString = "DISK_FREE_KB"; - } - else if (nMultiplier == BYTES_PER_MB) - { - if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume - nResourceString = "MAX_HIDVOL_SIZE_MB"; - else if (bDevice) - nResourceString = "DEVICE_FREE_MB"; - else - nResourceString = "DISK_FREE_MB"; - } - else - { - if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume - nResourceString = "MAX_HIDVOL_SIZE_GB"; - else if (bDevice) - nResourceString = "DEVICE_FREE_GB"; - else - nResourceString = "DISK_FREE_GB"; - } - - if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume - { - _snwprintf (szTmp2, sizeof szTmp2 / 2, GetString (nResourceString), ((double) lDiskFree->QuadPart) / nMultiplier); - SetWindowTextW (GetDlgItem (hwndTextBox, IDC_SIZEBOX), szTmp2); - } - else - _snwprintf (szTmp2, sizeof szTmp2 / 2, GetString (nResourceString), lpszDrive, ((double) lDiskFree->QuadPart) / nMultiplier); - - SetWindowTextW (hwndTextBox, szTmp2); - - if (lDiskFree->QuadPart % (__int64) BYTES_PER_MB != 0) - nMultiplier = BYTES_PER_KB; - - return nMultiplier; -} - -void DisplaySizingErrorText (HWND hwndTextBox) -{ - wchar_t szTmp[1024]; - - if (translateWin32Error (szTmp, sizeof (szTmp) / sizeof(szTmp[0]))) - { - wchar_t szTmp2[1024]; - wsprintfW (szTmp2, L"%s\n%s", GetString ("CANNOT_CALC_SPACE"), szTmp); - SetWindowTextW (hwndTextBox, szTmp2); - } - else - { - SetWindowText (hwndTextBox, ""); - } -} - -void EnableDisableFileNext (HWND hComboBox, HWND hMainButton) -{ - LPARAM nIndex = SendMessage (hComboBox, CB_GETCURSEL, 0, 0); - if (bHistory && nIndex == CB_ERR) - { - EnableWindow (hMainButton, FALSE); - SetFocus (hComboBox); - } - else - { - EnableWindow (hMainButton, TRUE); - SetFocus (hMainButton); - } -} - -// Returns TRUE if the file is a sparse file. If it's not a sparse file or in case of any error, returns FALSE. -BOOL IsSparseFile (HWND hwndDlg) -{ - HANDLE hFile; - BY_HANDLE_FILE_INFORMATION bhFileInfo; - - FILETIME ftLastAccessTime; - BOOL bTimeStampValid = FALSE; - - BOOL retCode = FALSE; - - hFile = CreateFile (szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - { - MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_VOL"), lpszTitle, ICON_HAND); - return FALSE; - } - - if (bPreserveTimestamp) - { - /* Remember the container timestamp (used to reset file date and time of file-hosted - containers to preserve plausible deniability of hidden volumes) */ - if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) - { - bTimeStampValid = FALSE; - MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); - } - else - bTimeStampValid = TRUE; - } - - bhFileInfo.dwFileAttributes = 0; - - GetFileInformationByHandle(hFile, &bhFileInfo); - - retCode = bhFileInfo.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE; - - if (bTimeStampValid) - { - // Restore the container timestamp (to preserve plausible deniability). - if (SetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) - MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PREP_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); - } - CloseHandle (hFile); - return retCode; -} - - -// Note: GetFileVolSize is not to be used for devices (only for file-hosted volumes) -BOOL GetFileVolSize (HWND hwndDlg, unsigned __int64 *size) -{ - LARGE_INTEGER fileSize; - HANDLE hFile; - - FILETIME ftLastAccessTime; - BOOL bTimeStampValid = FALSE; - - hFile = CreateFile (szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - { - MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_VOL"), lpszTitle, ICON_HAND); - return FALSE; - } - - if (bPreserveTimestamp) - { - /* Remember the container timestamp (used to reset file date and time of file-hosted - containers to preserve plausible deniability of hidden volumes) */ - if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) - { - bTimeStampValid = FALSE; - MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); - } - else - bTimeStampValid = TRUE; - } - - if (GetFileSizeEx(hFile, &fileSize) == 0) - { - MessageBoxW (hwndDlg, GetString ("CANT_GET_VOLSIZE"), lpszTitle, ICON_HAND); - if (bTimeStampValid) - { - // Restore the container timestamp (to preserve plausible deniability). - if (SetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) - MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PREP_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); - } - CloseHandle (hFile); - return FALSE; - } - - if (bTimeStampValid) - { - // Restore the container timestamp (to preserve plausible deniability). - if (SetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) - MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PREP_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); - } - CloseHandle (hFile); - *size = fileSize.QuadPart; - return TRUE; -} - - -BOOL QueryFreeSpace (HWND hwndDlg, HWND hwndTextBox, BOOL display) -{ - if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume - { - LARGE_INTEGER lDiskFree; - char szTmp[TC_MAX_PATH]; - - lDiskFree.QuadPart = nMaximumHiddenVolSize; - - if (display) - PrintFreeSpace (hwndTextBox, szTmp, &lDiskFree); - - return TRUE; - } - else if (bDevice == FALSE) - { - char root[TC_MAX_PATH]; - ULARGE_INTEGER free; - - if (!GetVolumePathName (szFileName, root, sizeof (root))) - { - handleWin32Error (hwndDlg); - return FALSE; - } - - if (!GetDiskFreeSpaceEx (root, &free, 0, 0)) - { - if (display) - DisplaySizingErrorText (hwndTextBox); - - return FALSE; - } - else - { - LARGE_INTEGER lDiskFree; - lDiskFree.QuadPart = free.QuadPart; - - if (display) - PrintFreeSpace (hwndTextBox, root, &lDiskFree); - - return TRUE; - } - } - else - { - DISK_GEOMETRY driveInfo; - PARTITION_INFORMATION diskInfo; - BOOL piValid = FALSE; - BOOL gValid = FALSE; - - // Query partition size - piValid = GetPartitionInfo (szDiskFile, &diskInfo); - gValid = GetDriveGeometry (szDiskFile, &driveInfo); - - if (!piValid && !gValid) - { - if (display) - DisplaySizingErrorText (hwndTextBox); - - return FALSE; - } - - if (gValid && driveInfo.BytesPerSector != 512) - { - Error ("LARGE_SECTOR_UNSUPPORTED"); - return FALSE; - } - - if (piValid) - { - nVolumeSize = diskInfo.PartitionLength.QuadPart; - - if(display) - nMultiplier = PrintFreeSpace (hwndTextBox, szDiskFile, &diskInfo.PartitionLength); - - nUIVolumeSize = diskInfo.PartitionLength.QuadPart / nMultiplier; - - if (nVolumeSize == 0) - { - if (display) - SetWindowTextW (hwndTextBox, GetString ("EXT_PARTITION")); - - return FALSE; - } - } - else - { - LARGE_INTEGER lDiskFree; - - // Drive geometry info is used only when GetPartitionInfo() fails - lDiskFree.QuadPart = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * - driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; - - nVolumeSize = lDiskFree.QuadPart; - - if (display) - nMultiplier = PrintFreeSpace (hwndTextBox, szDiskFile, &lDiskFree); - - nUIVolumeSize = lDiskFree.QuadPart / nMultiplier; - } - - return TRUE; - } -} - - -static BOOL FinalPreTransformPrompts (void) -{ - int x; - wchar_t szTmp[4096]; - int driveNo; - WCHAR deviceName[MAX_PATH]; - - strcpy ((char *)deviceName, szFileName); - ToUNICODE ((char *)deviceName); - - driveNo = GetDiskDeviceDriveLetter (deviceName); - - if (!(bHiddenVol && !bHiddenVolHost)) // Do not ask for permission to overwrite an existing volume if we're creating a hidden volume within it - { - wchar_t drive[128]; - wchar_t volumeLabel[128]; - wchar_t *type; - BOOL bTmpIsPartition = FALSE; - - type = GetPathType (szFileName, !bInPlaceEncNonSys, &bTmpIsPartition); - - if (driveNo != -1) - { - if (!GetDriveLabel (driveNo, volumeLabel, sizeof (volumeLabel))) - volumeLabel[0] = 0; - - swprintf_s (drive, sizeof (drive)/2, volumeLabel[0] ? L" (%hc: '%s')" : L" (%hc:%s)", 'A' + driveNo, volumeLabel[0] ? volumeLabel : L""); - } - else - { - drive[0] = 0; - volumeLabel[0] = 0; - } - - if (bHiddenOS && bHiddenVolHost) - swprintf (szTmp, GetString ("OVERWRITEPROMPT_DEVICE_HIDDEN_OS_PARTITION"), szFileName, drive); - else - swprintf (szTmp, GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_CONFIRM" : "OVERWRITEPROMPT_DEVICE"), type, szFileName, drive); - - - x = MessageBoxW (MainDlg, szTmp, lpszTitle, YES_NO | MB_ICONWARNING | (bInPlaceEncNonSys ? MB_DEFBUTTON1 : MB_DEFBUTTON2)); - if (x != IDYES) - return FALSE; - - - if (driveNo != -1 && bTmpIsPartition && !bInPlaceEncNonSys) - { - float percentFreeSpace = 100.0; - __int64 occupiedBytes = 0; - - // Do a second check. If we find that the partition contains more than 1GB of data or more than 12% - // of its space is occupied, we will display an extra warning, however, this time it won't be a Yes/No - // dialog box (because users often ignore such dialog boxes). - - if (GetStatsFreeSpaceOnPartition (szFileName, &percentFreeSpace, &occupiedBytes, TRUE) != -1) - { - if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. - || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. - { - wchar_t tmpMcMsg [8000]; - wchar_t tmpMcOption1 [500]; - wchar_t tmpMcOptionCancel [50]; - - wcscpy (tmpMcMsg, GetString("OVERWRITEPROMPT_DEVICE_SECOND_WARNING_LOTS_OF_DATA")); - wcscpy (tmpMcOption1, GetString("ERASE_FILES_BY_CREATING_VOLUME")); - wcscpy (tmpMcOptionCancel, GetString("CANCEL")); - - wcscat (tmpMcMsg, L"\n\n"); - wcscat (tmpMcMsg, GetString("DRIVE_LETTER_ITEM")); - swprintf_s (szTmp, sizeof (szTmp)/2, L"%hc:", 'A' + driveNo); - wcscat (tmpMcMsg, szTmp); - - wcscat (tmpMcMsg, L"\n"); - wcscat (tmpMcMsg, GetString("LABEL_ITEM")); - wcscat (tmpMcMsg, volumeLabel[0] != 0 ? volumeLabel : GetString("NOT_APPLICABLE_OR_NOT_AVAILABLE")); - - wcscat (tmpMcMsg, L"\n"); - wcscat (tmpMcMsg, GetString("SIZE_ITEM")); - GetSizeString (nVolumeSize, szTmp); - wcscat (tmpMcMsg, szTmp); - - wcscat (tmpMcMsg, L"\n"); - wcscat (tmpMcMsg, GetString("PATH_ITEM")); - wcscat (tmpMcMsg, deviceName); - - wchar_t *tmpStr[] = {L"", tmpMcMsg, tmpMcOption1, tmpMcOptionCancel, 0}; - switch (AskMultiChoice ((void **) tmpStr, TRUE)) - { - case 1: - // Proceed - - // NOP - break; - - default: - return FALSE; - } - } - } - } - } - return TRUE; -} - -void HandleOldAssignedDriveLetter (void) -{ - if (bDevice) - { - // Handle assigned drive letter (if any) - - WCHAR deviceName[MAX_PATH]; - int driveLetter = -1; - - strcpy ((char *)deviceName, szDiskFile); - ToUNICODE ((char *)deviceName); - driveLetter = GetDiskDeviceDriveLetter (deviceName); - - if (!bHiddenVolHost - && !bHiddenOS - && driveLetter > 1) // If a drive letter is assigned to the device, but not A: or B: - { - char rootPath[] = { driveLetter + 'A', ':', '\\', 0 }; - wchar_t szTmp[8192]; - - swprintf (szTmp, GetString ("AFTER_FORMAT_DRIVE_LETTER_WARN"), rootPath[0], rootPath[0], rootPath[0], rootPath[0]); - MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING); - } - } -} - - -// Returns TRUE if it makes sense to ask the user whether he wants to store files larger than 4GB in the volume. -static BOOL FileSize4GBLimitQuestionNeeded (void) -{ - uint64 dataAreaSize = GetVolumeDataAreaSize (bHiddenVol && !bHiddenVolHost, nVolumeSize); - - return (dataAreaSize > 4 * BYTES_PER_GB + TC_MIN_FAT_FS_SIZE - && dataAreaSize <= TC_MAX_FAT_FS_SIZE); -} - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static char PageDebugId[128]; - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - - hCurPage = hwndDlg; - - switch (uMsg) - { - case WM_INITDIALOG: - LocalizeDialog (hwndDlg, "IDD_VOL_CREATION_WIZARD_DLG"); - - sprintf (PageDebugId, "FORMAT_PAGE_%d", nCurPageNo); - LastDialogId = PageDebugId; - - switch (nCurPageNo) - { - case INTRO_PAGE: - - SendMessage (GetDlgItem (hwndDlg, IDC_FILE_CONTAINER), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_NONSYS_DEVICE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_SYS_DEVICE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("INTRO_TITLE")); - - ToHyperlink (hwndDlg, IDC_MORE_INFO_ON_CONTAINERS); - ToHyperlink (hwndDlg, IDC_MORE_INFO_ON_SYS_ENCRYPTION); - - EnableWindow (GetDlgItem (hwndDlg, IDC_STD_VOL), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_HIDDEN_VOL), TRUE); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - - UpdateWizardModeControls (hwndDlg, WizardMode); - break; - - case SYSENC_TYPE_PAGE: - - bHiddenVolHost = bHiddenVol = bHiddenOS; - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_TYPE_PAGE_TITLE")); - - SendMessage (GetDlgItem (hwndDlg, IDC_SYSENC_HIDDEN), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_SYSENC_NORMAL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - - CheckButton (GetDlgItem (hwndDlg, bHiddenOS ? IDC_SYSENC_HIDDEN : IDC_SYSENC_NORMAL)); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_TYPE_HELP")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP_SYSENC_NORMAL), GetString ("SYSENC_NORMAL_TYPE_HELP")); - - ToHyperlink (hwndDlg, IDC_HIDDEN_SYSENC_INFO_LINK); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bDirectSysEncMode); - - SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); - break; - - case SYSENC_HIDDEN_OS_REQ_CHECK_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_HELP")); - SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), bDirectSysEncModeCommand != SYSENC_COMMAND_CREATE_HIDDEN_OS && bDirectSysEncModeCommand != SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV); - - ToHyperlink (hwndDlg, IDC_HIDDEN_SYSENC_INFO_LINK); - break; - - case SYSENC_SPAN_PAGE: - - SendMessage (GetDlgItem (hwndDlg, IDC_WHOLE_SYS_DRIVE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_SYS_PARTITION), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_ENCRYPTION_SPAN_TITLE")); - - SetWindowTextW (GetDlgItem (hwndDlg, IDT_WHOLE_SYS_DRIVE), GetString ("SYS_ENCRYPTION_SPAN_WHOLE_SYS_DRIVE_HELP")); - - CheckButton (GetDlgItem (hwndDlg, bWholeSysDrive ? IDC_WHOLE_SYS_DRIVE : IDC_SYS_PARTITION)); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - break; - - - case SYSENC_PRE_DRIVE_ANALYSIS_PAGE: - - Init2RadButtonPageYesNo (SysEncDetectHiddenSectors); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_PRE_DRIVE_ANALYSIS_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_PRE_DRIVE_ANALYSIS_HELP")); - break; - - - case SYSENC_DRIVE_ANALYSIS_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_DRIVE_ANALYSIS_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDT_SYSENC_DRIVE_ANALYSIS_INFO), GetString ("SYSENC_DRIVE_ANALYSIS_INFO")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), FALSE); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), FALSE); - EnableWindow (GetDlgItem (MainDlg, IDCANCEL), FALSE); - - LoadSettings (hwndDlg); - - if (HiddenSectorDetectionStatus == 1) - { - // Detection of hidden sectors was already in progress but it did not finish successfully. - // Ask the user if he wants to try again (to prevent repeated system freezing, etc.) - - char *tmpStr[] = {0, "HIDDEN_SECTOR_DETECTION_FAILED_PREVIOUSLY", "SKIP_HIDDEN_SECTOR_DETECTION", "RETRY_HIDDEN_SECTOR_DETECTION", "IDC_EXIT", 0}; - switch (AskMultiChoice ((void **) tmpStr, FALSE)) - { - case 1: - // Do not try again - LoadPage (MainDlg, SYSENC_DRIVE_ANALYSIS_PAGE + 1); - return 0; - - case 2: - // Try again - break; - - default: - EndMainDlg (MainDlg); - return 0; - } - } - - SetTimer (MainDlg, TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS, TIMER_INTERVAL_SYSENC_DRIVE_ANALYSIS_PROGRESS, NULL); - bSysEncDriveAnalysisInProgress = TRUE; - ArrowWaitCursor (); - SysEncDriveAnalysisStart = GetTickCount (); - InitProgressBar (SYSENC_DRIVE_ANALYSIS_ETA, 0, FALSE, FALSE, FALSE, TRUE); - - _beginthread (sysEncDriveAnalysisThread, 0, hwndDlg); - - break; - - - case SYSENC_MULTI_BOOT_MODE_PAGE: - - SendMessage (GetDlgItem (hwndDlg, IDC_SINGLE_BOOT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_BOOT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_MULTI_BOOT_MODE_TITLE")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); - - RefreshMultiBootControls (hwndDlg); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), nMultiBoot > 0); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); - break; - - - case SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE: - - Init2RadButtonPageYesNo (SysEncMultiBootCfg.SystemOnBootDrive); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_SYS_EQ_BOOT_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_SYS_EQ_BOOT_HELP")); - break; - - - case SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE: - - SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE1), GetString ("DIGIT_ONE")); - SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE2), GetString ("TWO_OR_MORE")); - - SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), SysEncMultiBootCfg.NumberOfSysDrives > 0); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), TRUE); - - if (SysEncMultiBootCfg.NumberOfSysDrives == 2) - Update2RadButtonPage (0); // 2 or more drives contain an OS - else if (SysEncMultiBootCfg.NumberOfSysDrives == 1) - Update2RadButtonPage (1); // Only 1 drive contains an OS - else - Update2RadButtonPage (-1); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_HELP")); - break; - - - case SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE: - - Init2RadButtonPageYesNo (SysEncMultiBootCfg.MultipleSystemsOnDrive); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_ADJACENT_SYS_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_ADJACENT_SYS_HELP")); - break; - - - case SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE: - - Init2RadButtonPageYesNo (SysEncMultiBootCfg.BootLoaderBrand); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_HELP")); - break; - - - case SYSENC_MULTI_BOOT_OUTCOME_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_OUTCOME_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), SysEncMultiBootCfgOutcome); - SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), TRUE); - break; - - - case VOLUME_TYPE_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("VOLUME_TYPE_TITLE")); - - SendMessage (GetDlgItem (hwndDlg, IDC_HIDDEN_VOL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_STD_VOL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - - CheckButton (GetDlgItem (hwndDlg, bHiddenVol ? IDC_HIDDEN_VOL : IDC_STD_VOL)); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_VOLUME_TYPE_HELP")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP_NORMAL_VOL), GetString ("NORMAL_VOLUME_TYPE_HELP")); - - ToHyperlink (hwndDlg, IDC_HIDDEN_VOL_HELP); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); - break; - - case HIDDEN_VOL_WIZARD_MODE_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDDEN_VOL_WIZARD_MODE_TITLE")); - - SendMessage (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_DIRECT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_FULL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - - CheckButton (GetDlgItem (hwndDlg, bHiddenVolDirect ? IDC_HIDVOL_WIZ_MODE_DIRECT : IDC_HIDVOL_WIZ_MODE_FULL)); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_VOL_WIZARD_MODE_NORMAL_HELP")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP2), GetString ("HIDDEN_VOL_WIZARD_MODE_DIRECT_HELP")); - - EnableWindow (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_DIRECT), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_FULL), TRUE); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - break; - - case VOLUME_LOCATION_PAGE: - { - char *nID; - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_SELECT_VOLUME_LOCATION), - GetString (bDevice ? "IDC_SELECT_DEVICE" : "IDC_SELECT_FILE")); - - if (bHiddenVolDirect && bHiddenVolHost) - { - nID = "FILE_HELP_HIDDEN_HOST_VOL_DIRECT"; - } - else - { - if (bDevice) - nID = bHiddenVolHost ? "DEVICE_HELP_HIDDEN_HOST_VOL" : "DEVICE_HELP"; - else - nID = bHiddenVolHost ? "FILE_HELP_HIDDEN_HOST_VOL" : "FILE_HELP"; - } - - SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_RESETCONTENT, 0, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_LIMITTEXT, TC_MAX_PATH, 0); - - LoadCombo (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); - - SendMessage (GetDlgItem (hwndDlg, IDC_NO_HISTORY), BM_SETCHECK, bHistory ? BST_UNCHECKED : BST_CHECKED, 0); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FILE_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (nID)); - - SetFocus (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - AddComboItem (GetDlgItem (hwndDlg, IDC_COMBO_BOX), szFileName, bHistory); - - EnableDisableFileNext (GetDlgItem (hwndDlg, IDC_COMBO_BOX), - GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); - - } - break; - - case DEVICE_TRANSFORM_MODE_PAGE: - - if (!bDeviceTransformModeChoiceMade && !bInPlaceEncNonSys) - { - // The user has not chosen whether to perform in-place encryption or format yet. - // We will preselect in-place encryption if the requirements are met and if the - // filesystem does not appear empty. - - WaitCursor(); - - if (CheckRequirementsForNonSysInPlaceEnc (szDiskFile, TRUE)) - { - bInPlaceEncNonSys = (FileSystemAppearsEmpty (szDiskFile) == 0); - } - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("DEVICE_TRANSFORM_MODE_PAGE_TITLE")); - - SendMessage (GetDlgItem (hwndDlg, IDC_DEVICE_TRANSFORM_MODE_INPLACE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_DEVICE_TRANSFORM_MODE_FORMAT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("DEVICE_TRANSFORM_MODE_PAGE_FORMAT_HELP")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP2), GetString ("DEVICE_TRANSFORM_MODE_PAGE_INPLACE_HELP")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - CheckButton (GetDlgItem (hwndDlg, bInPlaceEncNonSys ? IDC_DEVICE_TRANSFORM_MODE_INPLACE : IDC_DEVICE_TRANSFORM_MODE_FORMAT)); - - NormalCursor(); - - break; - - case HIDDEN_VOL_HOST_PRE_CIPHER_PAGE: - { - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDVOL_HOST_PRE_CIPHER_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bHiddenOS ? "HIDVOL_HOST_PRE_CIPHER_HELP_SYSENC" : "HIDVOL_HOST_PRE_CIPHER_HELP")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - if (bHiddenOS) - { - if (!GetDevicePathForHiddenOS()) - AbortProcess ("INVALID_PATH"); - } - } - break; - - case HIDDEN_VOL_PRE_CIPHER_PAGE: - { - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDVOL_PRE_CIPHER_TITLE")); - - if (bHiddenOS) - { - // Verify whether the clone of the OS fits in the hidden volume (the hidden - // volume is to host a hidden OS). - if (nMaximumHiddenVolSize - TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH < GetSystemPartitionSize()) - { - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_VOLUME_TOO_SMALL_FOR_OS_CLONE")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("EXIT")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - - bConfirmQuit = FALSE; - bConfirmQuitSysEncPretest = FALSE; - } - else - { - // The hidden volume must be as large as the system partition - nVolumeSize = GetSystemPartitionSize() + TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_OS_PRE_CIPHER_HELP")); - } - } - else - { - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDVOL_PRE_CIPHER_HELP")); - } - } - break; - - case CIPHER_PAGE: - { - int ea, hid; - char buf[100]; - - // Encryption algorithms - - SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_RESETCONTENT, 0, 0); - - if (bHiddenVol) - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "CIPHER_HIDVOL_HOST_TITLE" : "CIPHER_HIDVOL_TITLE")); - else - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("CIPHER_TITLE")); - - for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) - { - if (EAIsFormatEnabled (ea)) - AddComboPair (GetDlgItem (hwndDlg, IDC_COMBO_BOX), EAGetName (buf, ea), ea); - } - - SelectAlgo (GetDlgItem (hwndDlg, IDC_COMBO_BOX), &nVolumeEA); - ComboSelChangeEA (hwndDlg); - SetFocus (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); - - ToHyperlink (hwndDlg, IDC_LINK_MORE_INFO_ABOUT_CIPHER); - - // Hash algorithms - - if (SysEncInEffect ()) - { - hash_algo = DEFAULT_HASH_ALGORITHM_BOOT; - RandSetHashFunction (DEFAULT_HASH_ALGORITHM_BOOT); - } - else - hash_algo = RandGetHashFunction(); - - for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) - { - if (!HashIsDeprecated (hid)) - AddComboPair (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), HashGetName(hid), hid); - } - SelectAlgo (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), &hash_algo); - - ToHyperlink (hwndDlg, IDC_LINK_HASH_INFO); - - // Wizard buttons - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - } - break; - - case SIZE_PAGE: - { - wchar_t str[1000]; - - if (bHiddenVolHost) - { - wcsncpy (str, GetString ("SIZE_HELP_HIDDEN_HOST_VOL"), sizeof (str) / 2); - } - else - { - wcsncpy (str, GetString (bHiddenVol ? "SIZE_HELP_HIDDEN_VOL" : "SIZE_HELP"), sizeof (str) / 2); - } - - if (bDevice && !(bHiddenVol && !bHiddenVolHost)) // If raw device but not a hidden volume - { - _snwprintf (str, sizeof str / 2, L"%s%s", - GetString ((bHiddenOS && bHiddenVol) ? "SIZE_PARTITION_HIDDEN_SYSENC_HELP" : "SIZE_PARTITION_HELP"), - (bHiddenVolHost && !bHiddenOS) ? GetString ("SIZE_PARTITION_HIDDEN_VOL_HELP") : L""); - } - - SendMessage (GetDlgItem (hwndDlg, IDC_SPACE_LEFT), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_SIZEBOX), EM_LIMITTEXT, 12, 0); - - if(!QueryFreeSpace (hwndDlg, GetDlgItem (hwndDlg, IDC_SPACE_LEFT), TRUE)) - { - nUIVolumeSize=0; - nVolumeSize=0; - SetWindowTextW (GetDlgItem (hwndDlg, IDC_SIZEBOX), GetString ("UNKNOWN")); - EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_KB), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_MB), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_GB), FALSE); - - } - else if (bDevice && !(bHiddenVol && !bHiddenVolHost)) // If raw device but not a hidden volume - { - EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_KB), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_MB), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_GB), FALSE); - } - else - { - EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_KB), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_MB), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_GB), TRUE); - } - - SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_UNCHECKED, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_UNCHECKED, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_UNCHECKED, 0); - - switch (nMultiplier) - { - case BYTES_PER_KB: - SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_CHECKED, 0); - break; - case BYTES_PER_MB: - SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_CHECKED, 0); - break; - case BYTES_PER_GB: - SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_CHECKED, 0); - break; - } - - if (nUIVolumeSize != 0) - { - char szTmp[32]; - sprintf (szTmp, "%I64u", nUIVolumeSize); - SetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTmp); - } - - SetFocus (GetDlgItem (hwndDlg, IDC_SIZEBOX)); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), str); - - if (bHiddenVol) - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "SIZE_HIDVOL_HOST_TITLE" : "SIZE_HIDVOL_TITLE")); - else - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SIZE_TITLE")); - - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - VerifySizeAndUpdate (hwndDlg, FALSE); - } - break; - - case HIDDEN_VOL_HOST_PASSWORD_PAGE: - case NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE: - - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), EM_LIMITTEXT, MAX_PASSWORD, 0); - - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), szRawPassword); - - SetFocus (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT)); - - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE_HELP" : "PASSWORD_HIDDENVOL_HOST_DIRECT_HELP")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bInPlaceEncNonSys ? "PASSWORD" : "PASSWORD_HIDVOL_HOST_TITLE")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bInPlaceEncNonSys); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - - break; - - case PASSWORD_PAGE: - { - wchar_t str[1000]; - - hPasswordInputField = GetDlgItem (hwndDlg, IDC_PASSWORD); - hVerifyPasswordInputField = GetDlgItem (hwndDlg, IDC_VERIFY); - - if (SysEncInEffect ()) - { - ToBootPwdField (hwndDlg, IDC_PASSWORD); - ToBootPwdField (hwndDlg, IDC_VERIFY); - - sprintf (OrigKeyboardLayout, "%08X", (DWORD) GetKeyboardLayout (NULL) & 0xFFFF); - - if ((DWORD) GetKeyboardLayout (NULL) != 0x00000409 && (DWORD) GetKeyboardLayout (NULL) != 0x04090409) - { - DWORD keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); - EndMainDlg (MainDlg); - return 1; - } - bKeyboardLayoutChanged = TRUE; - } - - ShowWindow(GetDlgItem(hwndDlg, IDC_SHOW_PASSWORD), SW_HIDE); - - if (SetTimer (MainDlg, TIMER_ID_KEYB_LAYOUT_GUARD, TIMER_INTERVAL_KEYB_LAYOUT_GUARD, NULL) == 0) - { - Error ("CANNOT_SET_TIMER"); - EndMainDlg (MainDlg); - return 1; - } - } - - if (bHiddenVolHost) - { - wcsncpy (str, GetString (bHiddenOS ? "PASSWORD_SYSENC_OUTERVOL_HELP" : "PASSWORD_HIDDENVOL_HOST_HELP"), sizeof (str) / 2); - } - else if (bHiddenVol) - { - _snwprintf (str, sizeof str / 2, L"%s%s", - GetString (bHiddenOS ? "PASSWORD_HIDDEN_OS_HELP" : "PASSWORD_HIDDENVOL_HELP"), - GetString ("PASSWORD_HELP")); - } - else - { - wcsncpy (str, GetString ("PASSWORD_HELP"), sizeof (str) / 2); - } - - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), EM_LIMITTEXT, MAX_PASSWORD, 0); - - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), szRawPassword); - SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), szVerify); - - SetFocus (GetDlgItem (hwndDlg, IDC_PASSWORD)); - - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable && !SysEncInEffect()); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEY_FILES), KeyFilesEnable); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), str); - - if (CreatingHiddenSysVol()) - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("PASSWORD_HIDDEN_OS_TITLE")); - else if (bHiddenVol) - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "PASSWORD_HIDVOL_HOST_TITLE" : "PASSWORD_HIDVOL_TITLE")); - else if (WizardMode == WIZARD_MODE_SYS_DEVICE) - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("PASSWORD")); - else - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("PASSWORD_TITLE")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), - GetDlgItem (hwndDlg, IDC_PASSWORD), - GetDlgItem (hwndDlg, IDC_VERIFY), - NULL, - NULL, - KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect()); - volumePassword.Length = strlen ((char *) volumePassword.Text); - } - break; - - case FILESYS_PAGE: - { - wchar_t szTmp[8192]; - - Init2RadButtonPageYesNo (nNeedToStoreFilesOver4GB); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FILESYS_PAGE_TITLE")); - - wcscpy (szTmp, GetString ("FILESYS_PAGE_HELP_QUESTION")); - - if (bHiddenVolHost) - wcscat (szTmp, L"\n\n"); - else - { - wcscat (szTmp, L"\n\n\n"); - wcscat (szTmp, GetString ("NOTE_BEGINNING")); - } - - wcscat (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION")); - - if (bHiddenVolHost) - { - wcscat (szTmp, L" "); - wcscat (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION_HIDVOL")); - } - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), szTmp); - } - break; - - case SYSENC_COLLECTING_RANDOM_DATA_PAGE: - case NONSYS_INPLACE_ENC_RAND_DATA_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("COLLECTING_RANDOM_DATA_TITLE")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - SetTimer (GetParent (hwndDlg), TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); - - hRandPoolSys = GetDlgItem (hwndDlg, IDC_SYS_POOL_CONTENTS); - - SendMessage (GetDlgItem (hwndDlg, IDC_SYS_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - - SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), BM_SETCHECK, showKeys ? BST_CHECKED : BST_UNCHECKED, 0); - - DisplayRandPool (hRandPoolSys, showKeys); - - break; - - case SYSENC_KEYS_GEN_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("KEYS_GEN_TITLE")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - hMasterKey = GetDlgItem (hwndDlg, IDC_DISK_KEY); - hHeaderKey = GetDlgItem (hwndDlg, IDC_HEADER_KEY); - - SendMessage (GetDlgItem (hwndDlg, IDC_DISK_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_HEADER_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - - SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_KEYS), BM_SETCHECK, showKeys ? BST_CHECKED : BST_UNCHECKED, 0); - - SetWindowText (GetDlgItem (hwndDlg, IDC_HEADER_KEY), showKeys ? HeaderKeyGUIView : "******************************** "); - SetWindowText (GetDlgItem (hwndDlg, IDC_DISK_KEY), showKeys ? MasterKeyGUIView : "******************************** "); - - break; - - case SYSENC_RESCUE_DISK_CREATION_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("RESCUE_DISK")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (hwndDlg, IDT_RESCUE_DISK_INFO), GetString ("RESCUE_DISK_INFO")); - SetDlgItemText (hwndDlg, IDC_RESCUE_DISK_ISO_PATH, szRescueDiskISO); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_RESCUE_DISK_ISO_PATH)) > 1)); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - break; - - case SYSENC_RESCUE_DISK_BURN_PAGE: - { - wchar_t szTmp[8192]; - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bDontVerifyRescueDisk ? "RESCUE_DISK_CREATED_TITLE" : "RESCUE_DISK_RECORDING_TITLE")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - _snwprintf (szTmp, sizeof szTmp / 2, - GetString (bDontVerifyRescueDisk ? "RESCUE_DISK_BURN_INFO_NO_CHECK" : "RESCUE_DISK_BURN_INFO"), - szRescueDiskISO); - - SetWindowTextW (GetDlgItem (hwndDlg, IDT_RESCUE_DISK_BURN_INFO), szTmp); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - - /* The 'Back' button must be disabled now because the user could burn a Rescue Disk, then go back, and - generate a different master key, which would cause the Rescue Disk verification to fail (the result - would be confusion and bug reports). */ - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - - ToHyperlink (hwndDlg, IDC_DOWNLOAD_CD_BURN_SOFTWARE); - } - break; - - case SYSENC_RESCUE_DISK_VERIFIED_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("RESCUE_DISK_DISK_VERIFIED_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("RESCUE_DISK_VERIFIED_INFO")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - - // Rescue Disk has been verified, no need to go back - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - - // Prevent losing the burned rescue disk by inadvertent exit - bConfirmQuit = TRUE; - - break; - - case SYSENC_WIPE_MODE_PAGE: - case NONSYS_INPLACE_ENC_WIPE_MODE_PAGE: - { - if (nWipeMode == TC_WIPE_1_RAND) - nWipeMode = TC_WIPE_NONE; - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("WIPE_MODE_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDT_WIPE_MODE_INFO), GetString ("INPLACE_ENC_WIPE_MODE_INFO")); - - PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), - SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING && !bInPlaceEncNonSys, - TRUE); - - SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - } - break; - - case SYSENC_PRETEST_INFO_PAGE: - - if (bHiddenOS) - { - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDDEN_OS_CREATION_PREINFO_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_OS_CREATION_PREINFO_HELP")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("START")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - } - else - { - wchar_t finalMsg[8024] = {0}; - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_ENCRYPTION_PRETEST_TITLE")); - - try - { - wsprintfW (finalMsg, - GetString ("SYS_ENCRYPTION_PRETEST_INFO"), - BootEncObj->GetSystemDriveConfiguration().DriveNumber); - } - catch (Exception &e) - { - e.Show (hwndDlg); - EndMainDlg (MainDlg); - return 0; - } - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), finalMsg); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("TEST")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - - break; - - case SYSENC_PRETEST_RESULT_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_ENCRYPTION_PRETEST_RESULT_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYS_ENCRYPTION_PRETEST_RESULT_INFO")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("ENCRYPT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("DEFER")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); - - break; - - case SYSENC_ENCRYPTION_PAGE: - - if (CreateSysEncMutex ()) - { - try - { - BootEncStatus = BootEncObj->GetStatus(); - bSystemEncryptionInProgress = BootEncStatus.SetupInProgress; - } - catch (Exception &e) - { - e.Show (hwndDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - EndMainDlg (MainDlg); - return 0; - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), - GetString (SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING ? "ENCRYPTION" : "DECRYPTION")); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_ENCRYPTION_PAGE_INFO")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("DEFER")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), - GetString (SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING ? "ENCRYPT" : "DECRYPT")); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_PAUSE), - GetString (bSystemEncryptionInProgress ? "IDC_PAUSE" : "RESUME")); - - EnableWindow (GetDlgItem (hwndDlg, IDC_PAUSE), BootEncStatus.DriveEncrypted); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), !BootEncStatus.SetupInProgress); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDHELP), TRUE); - - ToHyperlink (hwndDlg, IDC_MORE_INFO_SYS_ENCRYPTION); - - if (SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING) - { - nWipeMode = TC_WIPE_NONE; - EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_WIPE_MODE), FALSE); - PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), TRUE, TRUE); - SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); - } - else - { - EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), !bSystemEncryptionInProgress); - PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, TRUE); - SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); - } - - PostMessage (hwndDlg, TC_APPMSG_PERFORM_POST_SYSENC_WMINIT_TASKS, 0, 0); - } - else - { - Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - EndMainDlg (MainDlg); - return 0; - } - return 0; - - case NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE: - - { - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FILE_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_RESUME_VOL_SELECT_HELP")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); - - foreach (const HostDevice &device, DeferredNonSysInPlaceEncDevices) - { - SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_ADDSTRING, 0, (LPARAM) device.Path.c_str()); - } - - // Deselect all - SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_SETCURSEL, -1, 0); - } - - break; - - case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE: - - if (bInPlaceEncNonSysResumed) - { - WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; - - if (LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) != 0) - nWipeMode = savedWipeAlgorithm; - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("ENCRYPTION")); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_ENCRYPTION_PAGE_INFO")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString (bInPlaceEncNonSysResumed ? "DEFER" : "CANCEL")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString (bInPlaceEncNonSysResumed ? "RESUME" : "ENCRYPT")); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_PAUSE), GetString ("IDC_PAUSE")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bInPlaceEncNonSysResumed); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDHELP), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_PAUSE), FALSE); - - ShowWindow (GetDlgItem (hwndDlg, IDC_MORE_INFO_SYS_ENCRYPTION), SW_HIDE); - - EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), TRUE); - PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, TRUE); - SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); - - break; - - case NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE: - - bConfirmQuit = FALSE; - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("NONSYS_INPLACE_ENC_FINISHED_TITLE")); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_FINISHED_INFO")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("FINALIZE")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("EXIT")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), FALSE); - - break; - - case FORMAT_PAGE: - { - BOOL bNTFSallowed = FALSE; - BOOL bFATallowed = FALSE; - BOOL bNoFSallowed = FALSE; - - SetTimer (GetParent (hwndDlg), TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); - - hMasterKey = GetDlgItem (hwndDlg, IDC_DISK_KEY); - hHeaderKey = GetDlgItem (hwndDlg, IDC_HEADER_KEY); - hRandPool = GetDlgItem (hwndDlg, IDC_RANDOM_BYTES); - - SendMessage (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_DISK_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - SendMessage (GetDlgItem (hwndDlg, IDC_HEADER_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), - GetString (bHiddenVolHost ? "FORMAT_HIDVOL_HOST_HELP" : "FORMAT_HELP")); - - if (bHiddenVol) - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "FORMAT_HIDVOL_HOST_TITLE" : "FORMAT_HIDVOL_TITLE")); - else - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FORMAT_TITLE")); - - /* Quick/Dynamic */ - - if (bHiddenVol) - { - quickFormat = !bHiddenVolHost; - bSparseFileSwitch = FALSE; - - SetCheckBox (hwndDlg, IDC_QUICKFORMAT, quickFormat); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), GetString ((bDevice || !bHiddenVolHost) ? "IDC_QUICKFORMAT" : "SPARSE_FILE")); - EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), bDevice && bHiddenVolHost); - } - else - { - if (bDevice) - { - bSparseFileSwitch = FALSE; - SetWindowTextW (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), GetString("IDC_QUICKFORMAT")); - EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), TRUE); - } - else - { - char root[TC_MAX_PATH]; - DWORD fileSystemFlags = 0; - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), GetString("SPARSE_FILE")); - - /* Check if the host file system supports sparse files */ - - if (GetVolumePathName (szFileName, root, sizeof (root))) - { - GetVolumeInformation (root, NULL, 0, NULL, NULL, &fileSystemFlags, NULL, 0); - bSparseFileSwitch = fileSystemFlags & FILE_SUPPORTS_SPARSE_FILES; - } - else - bSparseFileSwitch = FALSE; - - EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), bSparseFileSwitch); - } - } - - SendMessage (GetDlgItem (hwndDlg, IDC_SHOW_KEYS), BM_SETCHECK, showKeys ? BST_CHECKED : BST_UNCHECKED, 0); - SetWindowText (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), showKeys ? "" : "******************************** "); - SetWindowText (GetDlgItem (hwndDlg, IDC_HEADER_KEY), showKeys ? "" : "******************************** "); - SetWindowText (GetDlgItem (hwndDlg, IDC_DISK_KEY), showKeys ? "" : "******************************** "); - - SendMessage (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), CB_RESETCONTENT, 0, 0); - AddComboPairW (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), GetString ("DEFAULT"), 0); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "0.5 KB", 1); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "1 KB", 2); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "2 KB", 4); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "4 KB", 8); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "8 KB", 16); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "16 KB", 32); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "32 KB", 64); - AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "64 KB", 128); - SendMessage (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), CB_SETCURSEL, 0, 0); - - EnableWindow (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), TRUE); - - /* Filesystems */ - - bNTFSallowed = FALSE; - bFATallowed = FALSE; - bNoFSallowed = FALSE; - - SendMessage (GetDlgItem (hwndDlg, IDC_FILESYS), CB_RESETCONTENT, 0, 0); - - EnableWindow (GetDlgItem (hwndDlg, IDC_FILESYS), TRUE); - - uint64 dataAreaSize = GetVolumeDataAreaSize (bHiddenVol && !bHiddenVolHost, nVolumeSize); - - if (!CreatingHiddenSysVol()) - { - if (dataAreaSize >= TC_MIN_NTFS_FS_SIZE && dataAreaSize <= TC_MAX_NTFS_FS_SIZE) - { - AddComboPair (GetDlgItem (hwndDlg, IDC_FILESYS), "NTFS", FILESYS_NTFS); - bNTFSallowed = TRUE; - } - - if (dataAreaSize >= TC_MIN_FAT_FS_SIZE && dataAreaSize <= TC_MAX_FAT_FS_SIZE) - { - AddComboPair (GetDlgItem (hwndDlg, IDC_FILESYS), "FAT", FILESYS_FAT); - bFATallowed = TRUE; - } - } - else - { - // We're creating a hidden volume for a hidden OS, so we don't need to format it with - // any filesystem (the entire OS will be copied to the hidden volume sector by sector). - EnableWindow (GetDlgItem (hwndDlg, IDC_FILESYS), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), FALSE); - } - - if (!bHiddenVolHost) - { - AddComboPairW (GetDlgItem (hwndDlg, IDC_FILESYS), GetString ("NONE"), FILESYS_NONE); - bNoFSallowed = TRUE; - } - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - - if (fileSystem == FILESYS_NONE) // If no file system has been previously selected - { - // Set default file system - - if (bFATallowed && !(nNeedToStoreFilesOver4GB == 1 && bNTFSallowed)) - fileSystem = FILESYS_FAT; - else if (bNTFSallowed) - fileSystem = FILESYS_NTFS; - else if (bNoFSallowed) - fileSystem = FILESYS_NONE; - else - { - AddComboPair (GetDlgItem (hwndDlg, IDC_FILESYS), "---", 0); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); - } - } - - SendMessage (GetDlgItem (hwndDlg, IDC_FILESYS), CB_SETCURSEL, 0, 0); - SelectAlgo (GetDlgItem (hwndDlg, IDC_FILESYS), (int *) &fileSystem); - - EnableWindow (GetDlgItem (hwndDlg, IDC_ABORT_BUTTON), FALSE); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("FORMAT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - SetFocus (GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); - } - break; - - case FORMAT_FINISHED_PAGE: - { - if (!bHiddenVolHost && bHiddenVol && !bHiddenVolFinished) - { - wchar_t msg[4096]; - - nNeedToStoreFilesOver4GB = -1; - - if (bHiddenOS) - { - wchar_t szMaxRecomOuterVolFillSize[100]; - - __int64 maxRecomOuterVolFillSize = 0; - - // Determine the maximum recommended total size of files that can be copied to the outer volume - // while leaving enough space for the hidden volume, which must contain a clone of the OS - - maxRecomOuterVolFillSize = nVolumeSize - GetSystemPartitionSize(); - - // -50% reserve for filesystem "peculiarities" - maxRecomOuterVolFillSize /= 2; - - swprintf (szMaxRecomOuterVolFillSize, L"%I64d %s", maxRecomOuterVolFillSize / BYTES_PER_MB, GetString ("MB")); - - swprintf (msg, GetString ("HIDVOL_HOST_FILLING_HELP_SYSENC"), hiddenVolHostDriveNo + 'A', szMaxRecomOuterVolFillSize); - } - else - swprintf (msg, GetString ("HIDVOL_HOST_FILLING_HELP"), hiddenVolHostDriveNo + 'A'); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), msg); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDVOL_HOST_FILLING_TITLE")); - } - else - { - if (bHiddenOS) - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_VOL_FORMAT_FINISHED_HELP")); - else - { - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_FINISHED_INFO" : "FORMAT_FINISHED_HELP")); - bConfirmQuit = FALSE; - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVol ? "HIDVOL_FORMAT_FINISHED_TITLE" : "FORMAT_FINISHED_TITLE")); - } - - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), (!bHiddenVol || bHiddenVolFinished) && !bHiddenOS && !bInPlaceEncNonSys); - - if ((!bHiddenVol || bHiddenVolFinished) && !bHiddenOS) - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("EXIT")); - } - break; - - case SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE: - - if (!IsHiddenOSRunning() || !bHiddenOS) - { - ReportUnexpectedState (SRC_POS); - EndMainDlg (MainDlg); - return 0; - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_HIDDEN_OS_INITIAL_INFO_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("FIRST_HIDDEN_OS_BOOT_INFO")); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("DEFER")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); - break; - - case SYSENC_HIDDEN_OS_WIPE_INFO_PAGE: - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_HIDDEN_OS_WIPE_INFO_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_OS_WIPE_INFO")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - break; - - case DEVICE_WIPE_MODE_PAGE: - - if (nWipeMode == TC_WIPE_NONE) - nWipeMode = TC_WIPE_1_RAND; - - if (bHiddenOS && IsHiddenOSRunning()) - { - // Decoy system partition wipe - - WipeAbort(); // In case the GUI previously crashed and the driver is still wiping - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); - } - else - { - // Regular device wipe (not decoy system partition wipe) - - // Title bar - SetWindowText (MainDlg, TC_APP_NAME); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("WIPE_MODE_TITLE")); - SetWindowTextW (GetDlgItem (hwndDlg, IDT_WIPE_MODE_INFO), GetString ("WIPE_MODE_INFO")); - - PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, FALSE); - - SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); - - break; - - case DEVICE_WIPE_PAGE: - - if (bHiddenOS && IsHiddenOSRunning()) - { - // Decoy system partition wipe - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("DEVICE_WIPE_PAGE_INFO_HIDDEN_OS")); - } - else - { - // Regular device wipe (not decoy system partition wipe) - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("DEVICE_WIPE_PAGE_INFO")); - } - - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("DEVICE_WIPE_PAGE_TITLE")); - SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("WIPE")); - SetWindowTextW (GetDlgItem (hCurPage, IDC_WIPE_MODE), (wstring (L" ") + GetWipeModeName (nWipeMode)).c_str()); - - EnableWindow (GetDlgItem (hwndDlg, IDC_ABORT_BUTTON), FALSE); - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); - - break; - } - return 0; - - case WM_HELP: - OpenPageHelp (GetParent (hwndDlg), nCurPageNo); - return 1; - - case TC_APPMSG_PERFORM_POST_SYSENC_WMINIT_TASKS: - AfterSysEncProgressWMInitTasks (hwndDlg); - return 1; - - case WM_COMMAND: - - if (nCurPageNo == INTRO_PAGE) - { - switch (lw) - { - case IDC_FILE_CONTAINER: - UpdateWizardModeControls (hwndDlg, WIZARD_MODE_FILE_CONTAINER); - return 1; - - case IDC_NONSYS_DEVICE: - UpdateWizardModeControls (hwndDlg, WIZARD_MODE_NONSYS_DEVICE); - return 1; - - case IDC_SYS_DEVICE: - UpdateWizardModeControls (hwndDlg, WIZARD_MODE_SYS_DEVICE); - return 1; - - case IDC_MORE_INFO_ON_CONTAINERS: - Applink ("introcontainer", TRUE, ""); - return 1; - - case IDC_MORE_INFO_ON_SYS_ENCRYPTION: - Applink ("introsysenc", TRUE, ""); - return 1; - } - } - - if (nCurPageNo == SYSENC_TYPE_PAGE) - { - switch (lw) - { - case IDC_SYSENC_HIDDEN: - bHiddenOS = TRUE; - bHiddenVol = TRUE; - bHiddenVolHost = TRUE; - return 1; - - case IDC_SYSENC_NORMAL: - bHiddenOS = FALSE; - bHiddenVol = FALSE; - bHiddenVolHost = FALSE; - return 1; - - case IDC_HIDDEN_SYSENC_INFO_LINK: - Applink ("hiddensysenc", TRUE, ""); - return 1; - } - } - - if (nCurPageNo == SYSENC_HIDDEN_OS_REQ_CHECK_PAGE && lw == IDC_HIDDEN_SYSENC_INFO_LINK) - { - Applink ("hiddensysenc", TRUE, ""); - return 1; - } - - if (nCurPageNo == SYSENC_SPAN_PAGE) - { - switch (lw) - { - case IDC_WHOLE_SYS_DRIVE: - bWholeSysDrive = TRUE; - return 1; - case IDC_SYS_PARTITION: - bWholeSysDrive = FALSE; - return 1; - } - - } - - if (nCurPageNo == SYSENC_MULTI_BOOT_MODE_PAGE) - { - switch (lw) - { - case IDC_SINGLE_BOOT: - nMultiBoot = 1; - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - return 1; - case IDC_MULTI_BOOT: - nMultiBoot = 2; - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - return 1; - } - } - - // Dual choice pages - switch (nCurPageNo) - { - case SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE: - case SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE: - case SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE: - case SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE: - case SYSENC_PRE_DRIVE_ANALYSIS_PAGE: - - if (lw == IDC_CHOICE1 || lw == IDC_CHOICE2) - { - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - return 1; - } - break; - } - - if (nCurPageNo == FILESYS_PAGE && (lw == IDC_CHOICE1 || lw == IDC_CHOICE2)) - { - if (bWarnOuterVolSuitableFileSys && lw == IDC_CHOICE1 && bHiddenVolHost) - { - wchar_t szTmp [4096]; - - bWarnOuterVolSuitableFileSys = FALSE; // Do not show this warning anymore (this also prevents potential endless repetition due to some race conditions) - - wcscpy (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION_HIDVOL")); - wcscat (szTmp, L"\n\n"); - wcscat (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION_HIDVOL_CONFIRM")); - - if (MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2) == IDNO) - { - nNeedToStoreFilesOver4GB = 0; - Init2RadButtonPageYesNo (nNeedToStoreFilesOver4GB); - } - } - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - return 1; - } - - if (lw == IDC_HIDDEN_VOL && nCurPageNo == VOLUME_TYPE_PAGE) - { - bHiddenVol = TRUE; - bHiddenVolHost = TRUE; - bInPlaceEncNonSys = FALSE; - return 1; - } - - if (lw == IDC_STD_VOL && nCurPageNo == VOLUME_TYPE_PAGE) - { - bHiddenVol = FALSE; - bHiddenVolHost = FALSE; - return 1; - } - - if (nCurPageNo == SYSENC_ENCRYPTION_PAGE) - { - BootEncryptionStatus locBootEncStatus; - - switch (lw) - { - case IDC_PAUSE: - try - { - locBootEncStatus = BootEncObj->GetStatus(); - - if (locBootEncStatus.SetupInProgress) - SysEncPause (); - else - SysEncResume (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - return 1; - - case IDC_WIPE_MODE: - if (hw == CBN_SELCHANGE) - { - nWipeMode = (WipeAlgorithmId) SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), - CB_GETITEMDATA, - SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), CB_GETCURSEL, 0, 0), - 0); - - return 1; - } - break; - - case IDC_MORE_INFO_SYS_ENCRYPTION: - Applink ("sysencprogressinfo", TRUE, ""); - return 1; - } - } - - if (bInPlaceEncNonSys) - { - switch (nCurPageNo) - { - case NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE: - - if (lw == IDC_LIST_BOX - && (hw == LBN_SELCHANGE || hw == LBN_DBLCLK)) - { - BOOL tmpbDevice = FALSE; - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); - - int selPartitionItemId = (int) SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_GETCURSEL, 0, 0); - - if (selPartitionItemId == LB_ERR) - { - // Deselect all - SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_SETCURSEL, -1, 0); - - SetFocus (GetDlgItem (MainDlg, IDC_NEXT)); - return 1; - } - - SetFocus (GetDlgItem (MainDlg, IDC_NEXT)); - - strcpy (szFileName, DeferredNonSysInPlaceEncDevices [selPartitionItemId].Path.c_str()); - CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); - - nVolumeSize = GetDeviceSize (szDiskFile); - if (nVolumeSize == -1) - { - handleWin32Error (MainDlg); - return 1; - } - - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - - return 1; - } - break; - - case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE: - { - switch (lw) - { - case IDC_PAUSE: - - // Pause/resume non-system in-place encryption - - if (bVolTransformThreadRunning || bVolTransformThreadToRun) - { - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); - NonSysInplaceEncPause (); - } - else - NonSysInplaceEncResume (); - - return 1; - - case IDC_WIPE_MODE: - if (hw == CBN_SELCHANGE) - { - nWipeMode = (WipeAlgorithmId) SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), - CB_GETITEMDATA, - SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), CB_GETCURSEL, 0, 0), - 0); - - return 1; - } - break; - } - } - break; - } - } - - - if (lw == IDC_OPEN_OUTER_VOLUME && nCurPageNo == FORMAT_FINISHED_PAGE) - { - OpenVolumeExplorerWindow (hiddenVolHostDriveNo); - return 1; - } - - if (lw == IDC_HIDDEN_VOL_HELP && nCurPageNo == VOLUME_TYPE_PAGE) - { - Applink ("hiddenvolume", TRUE, ""); - return 1; - } - - if (lw == IDC_ABORT_BUTTON && nCurPageNo == FORMAT_PAGE) - { - if (MessageBoxW (hwndDlg, GetString ("FORMAT_ABORT"), lpszTitle, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 ) == IDYES) - bVolTransformThreadCancel = TRUE; - return 1; - } - - if (lw == IDC_CIPHER_TEST && nCurPageNo == CIPHER_PAGE) - { - LPARAM nIndex; - int c; - - nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); - nVolumeEA = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); - - for (c = EAGetLastCipher (nVolumeEA); c != 0; c = EAGetPreviousCipher (nVolumeEA, c)) - { - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_CIPHER_TEST_DLG), - GetParent (hwndDlg), (DLGPROC) CipherTestDialogProc, (LPARAM) c); - } - return 1; - } - - if (lw == IDC_WIZ_BENCHMARK && nCurPageNo == CIPHER_PAGE) - { - // Reduce CPU load - bFastPollEnabled = FALSE; - bRandmixEnabled = FALSE; - - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_BENCHMARK_DLG), hwndDlg, - (DLGPROC) BenchmarkDlgProc, (LPARAM) NULL); - - bFastPollEnabled = TRUE; - bRandmixEnabled = TRUE; - - return 1; - } - - if (lw == IDC_LINK_MORE_INFO_ABOUT_CIPHER && nCurPageNo == CIPHER_PAGE) - { - char name[100]; - - int nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); - nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); - EAGetName (name, nIndex); - - if (strcmp (name, "AES") == 0) - Applink ("aes", FALSE, ""); - else if (strcmp (name, "Serpent") == 0) - Applink ("serpent", FALSE, ""); - else if (strcmp (name, "Twofish") == 0) - Applink ("twofish", FALSE, ""); - else if (EAGetCipherCount (nIndex) > 1) - Applink ("cascades", TRUE, ""); - - return 1; - } - - if (lw == IDC_LINK_HASH_INFO && nCurPageNo == CIPHER_PAGE) - { - Applink ("hashalgorithms", TRUE, ""); - return 1; - } - - if (hw == CBN_EDITCHANGE && nCurPageNo == VOLUME_LOCATION_PAGE) - { - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), - GetWindowTextLength (GetDlgItem (hCurPage, IDC_COMBO_BOX)) > 0); - - bDeviceTransformModeChoiceMade = FALSE; - bInPlaceEncNonSys = FALSE; - - return 1; - } - - if (hw == CBN_SELCHANGE && nCurPageNo == VOLUME_LOCATION_PAGE) - { - LPARAM nIndex; - - nIndex = MoveEditToCombo ((HWND) lParam, bHistory); - nIndex = UpdateComboOrder (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); - - if (nIndex != CB_ERR) - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); - else - EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); - - bDeviceTransformModeChoiceMade = FALSE; - bInPlaceEncNonSys = FALSE; - - return 1; - } - - if (hw == EN_CHANGE && nCurPageNo == SIZE_PAGE) - { - VerifySizeAndUpdate (hwndDlg, FALSE); - return 1; - } - - if (hw == EN_CHANGE && nCurPageNo == PASSWORD_PAGE) - { - VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), - GetDlgItem (hwndDlg, IDC_PASSWORD), - GetDlgItem (hwndDlg, IDC_VERIFY), - NULL, - NULL, - KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect()); - volumePassword.Length = strlen ((char *) volumePassword.Text); - - return 1; - } - - if (lw == IDC_SHOW_PASSWORD && nCurPageNo == PASSWORD_PAGE) - { - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD) ? 0 : '*', - 0); - SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD) ? 0 : '*', - 0); - InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); - InvalidateRect (GetDlgItem (hwndDlg, IDC_VERIFY), NULL, TRUE); - return 1; - } - - if (nCurPageNo == PASSWORD_PAGE - || nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) - { - if (lw == IDC_KEY_FILES) - { - if (SysEncInEffect()) - { - Warning ("KEYFILES_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); - return 1; - } - - KeyFilesDlgParam param; - param.EnableKeyFiles = KeyFilesEnable; - param.FirstKeyFile = FirstKeyFile; - - if (IDOK == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, - (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m)) - { - KeyFilesEnable = param.EnableKeyFiles; - FirstKeyFile = param.FirstKeyFile; - - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); - - if (nCurPageNo != HIDDEN_VOL_HOST_PASSWORD_PAGE && nCurPageNo != NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) - EnableWindow (GetDlgItem (hwndDlg, IDC_KEY_FILES), KeyFilesEnable); - - if (nCurPageNo != HIDDEN_VOL_HOST_PASSWORD_PAGE && nCurPageNo != NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) - { - VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), - GetDlgItem (hCurPage, IDC_PASSWORD), - GetDlgItem (hCurPage, IDC_VERIFY), - volumePassword.Text, szVerify, KeyFilesEnable && FirstKeyFile!=NULL); - } - } - - return 1; - } - - if (lw == IDC_KEYFILES_ENABLE) - { - KeyFilesEnable = GetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE); - - if (nCurPageNo != HIDDEN_VOL_HOST_PASSWORD_PAGE && nCurPageNo != NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) - { - EnableWindow (GetDlgItem (hwndDlg, IDC_KEY_FILES), KeyFilesEnable); - - VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), - GetDlgItem (hCurPage, IDC_PASSWORD), - GetDlgItem (hCurPage, IDC_VERIFY), - volumePassword.Text, szVerify, KeyFilesEnable && FirstKeyFile!=NULL); - } - - return 1; - } - } - - if (nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) - { - if (hw == EN_CHANGE) - { - GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), (char *) volumePassword.Text, sizeof (volumePassword.Text)); - volumePassword.Length = strlen ((char *) volumePassword.Text); - return 1; - } - - if (lw == IDC_SHOW_PASSWORD_SINGLE) - { - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_SINGLE) ? 0 : '*', - 0); - InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), NULL, TRUE); - return 1; - } - } - - if ((lw == IDC_KB || lw == IDC_MB || lw == IDC_GB) && nCurPageNo == SIZE_PAGE) - { - SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_UNCHECKED, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_UNCHECKED, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_UNCHECKED, 0); - - switch (lw) - { - case IDC_KB: - SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_CHECKED, 0); - break; - case IDC_MB: - SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_CHECKED, 0); - break; - case IDC_GB: - SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_CHECKED, 0); - break; - } - - VerifySizeAndUpdate (hwndDlg, FALSE); - return 1; - } - - if (lw == IDC_HIDVOL_WIZ_MODE_DIRECT && nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) - { - bHiddenVolDirect = TRUE; - return 1; - } - - if (lw == IDC_HIDVOL_WIZ_MODE_FULL && nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) - { - bHiddenVolDirect = FALSE; - return 1; - } - - if (lw == IDC_SELECT_VOLUME_LOCATION && nCurPageNo == VOLUME_LOCATION_PAGE) - { - if (!bDevice) - { - // Select file - - if (BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, !bHiddenVolDirect, NULL) == FALSE) - return 1; - - AddComboItem (GetDlgItem (hwndDlg, IDC_COMBO_BOX), szFileName, bHistory); - - EnableDisableFileNext (GetDlgItem (hwndDlg, IDC_COMBO_BOX), - GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); - - return 1; - } - else - { - // Select device - - int nResult = DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_RAWDEVICES_DLG), GetParent (hwndDlg), - (DLGPROC) RawDevicesDlgProc, (LPARAM) & szFileName[0]); - - // Check administrator privileges - if (!strstr (szFileName, "Floppy") && !IsAdmin() && !IsUacSupported ()) - MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_DEVICES"), lpszTitle, MB_OK|MB_ICONWARNING); - - if (nResult == IDOK && strlen (szFileName) > 0) - { - AddComboItem (GetDlgItem (hwndDlg, IDC_COMBO_BOX), szFileName, bHistory); - - EnableDisableFileNext (GetDlgItem (hwndDlg, IDC_COMBO_BOX), - GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); - - bDeviceTransformModeChoiceMade = FALSE; - bInPlaceEncNonSys = FALSE; - } - return 1; - } - } - - if (nCurPageNo == DEVICE_TRANSFORM_MODE_PAGE) - { - switch (lw) - { - case IDC_DEVICE_TRANSFORM_MODE_FORMAT: - - bInPlaceEncNonSys = FALSE; - bDeviceTransformModeChoiceMade = TRUE; - - return 1; - - case IDC_DEVICE_TRANSFORM_MODE_INPLACE: - - bInPlaceEncNonSys = TRUE; - bDeviceTransformModeChoiceMade = TRUE; - - bHiddenVol = FALSE; - bHiddenVolDirect = FALSE; - bHiddenVolHost = FALSE; - bSparseFileSwitch = FALSE; - quickFormat = FALSE; - - return 1; - } - } - - if (lw == IDC_HIDVOL_WIZ_MODE_FULL && nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) - { - bHiddenVolDirect = FALSE; - return 1; - } - - if (hw == CBN_SELCHANGE && nCurPageNo == CIPHER_PAGE) - { - switch (lw) - { - case IDC_COMBO_BOX: - ComboSelChangeEA (hwndDlg); - break; - - case IDC_COMBO_BOX_HASH_ALGO: - if (SysEncInEffect () - && SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), CB_GETITEMDATA, - SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), CB_GETCURSEL, 0, 0), 0) - != DEFAULT_HASH_ALGORITHM_BOOT) - { - hash_algo = DEFAULT_HASH_ALGORITHM_BOOT; - RandSetHashFunction (DEFAULT_HASH_ALGORITHM_BOOT); - Info ("ALGO_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); - SelectAlgo (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), &hash_algo); - } - break; - } - return 1; - - } - - if (lw == IDC_QUICKFORMAT && IsButtonChecked (GetDlgItem (hCurPage, IDC_QUICKFORMAT))) - { - if (bSparseFileSwitch) - { - if (AskWarnYesNo("CONFIRM_SPARSE_FILE") == IDNO) - SetCheckBox (hwndDlg, IDC_QUICKFORMAT, FALSE); - } - else - { - if (AskWarnYesNo("WARN_QUICK_FORMAT") == IDNO) - SetCheckBox (hwndDlg, IDC_QUICKFORMAT, FALSE); - } - return 1; - } - - if (lw == IDC_FILESYS && hw == CBN_SELCHANGE) - { - fileSystem = SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETITEMDATA, - SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETCURSEL, 0, 0) , 0); - - return 1; - } - - if (lw == IDC_SHOW_KEYS && nCurPageNo == FORMAT_PAGE) - { - showKeys = IsButtonChecked (GetDlgItem (hCurPage, IDC_SHOW_KEYS)); - - SetWindowText (GetDlgItem (hCurPage, IDC_RANDOM_BYTES), showKeys ? " " : "******************************** "); - SetWindowText (GetDlgItem (hCurPage, IDC_HEADER_KEY), showKeys ? "" : "******************************** "); - SetWindowText (GetDlgItem (hCurPage, IDC_DISK_KEY), showKeys ? "" : "******************************** "); - return 1; - } - - if (lw == IDC_DISPLAY_POOL_CONTENTS - && (nCurPageNo == SYSENC_COLLECTING_RANDOM_DATA_PAGE || nCurPageNo == NONSYS_INPLACE_ENC_RAND_DATA_PAGE)) - { - showKeys = IsButtonChecked (GetDlgItem (hCurPage, IDC_DISPLAY_POOL_CONTENTS)); - DisplayRandPool (hRandPoolSys, showKeys); - - return 1; - } - - if (lw == IDC_DISPLAY_KEYS && nCurPageNo == SYSENC_KEYS_GEN_PAGE) - { - showKeys = IsButtonChecked (GetDlgItem (hCurPage, IDC_DISPLAY_KEYS)); - - SetWindowText (GetDlgItem (hwndDlg, IDC_HEADER_KEY), showKeys ? HeaderKeyGUIView : "******************************** "); - SetWindowText (GetDlgItem (hwndDlg, IDC_DISK_KEY), showKeys ? MasterKeyGUIView : "******************************** "); - return 1; - } - - if (nCurPageNo == SYSENC_RESCUE_DISK_CREATION_PAGE) - { - if (lw == IDC_BROWSE) - { - char tmpszRescueDiskISO [TC_MAX_PATH+1]; - - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", tmpszRescueDiskISO, FALSE, TRUE, NULL)) - return 1; - - strcpy (szRescueDiskISO, tmpszRescueDiskISO); - - SetDlgItemText (hwndDlg, IDC_RESCUE_DISK_ISO_PATH, szRescueDiskISO); - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_RESCUE_DISK_ISO_PATH)) > 1)); - return 1; - } - - if ( hw == EN_CHANGE ) - { - GetDlgItemText (hwndDlg, IDC_RESCUE_DISK_ISO_PATH, szRescueDiskISO, sizeof(szRescueDiskISO)); - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_RESCUE_DISK_ISO_PATH)) > 1)); - return 1; - } - } - - if (nCurPageNo == SYSENC_RESCUE_DISK_BURN_PAGE && lw == IDC_DOWNLOAD_CD_BURN_SOFTWARE) - { - Applink ("isoburning", TRUE, ""); - return 1; - } - - if ((nCurPageNo == SYSENC_WIPE_MODE_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_WIPE_MODE_PAGE - || nCurPageNo == DEVICE_WIPE_MODE_PAGE) - && hw == CBN_SELCHANGE) - { - nWipeMode = (WipeAlgorithmId) SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), - CB_GETITEMDATA, - SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), CB_GETCURSEL, 0, 0), - 0); - - return 1; - } - - if (nCurPageNo == DEVICE_WIPE_PAGE) - { - switch (lw) - { - case IDC_ABORT_BUTTON: - - if (AskWarnNoYes ("CONFIRM_WIPE_ABORT") == IDYES) - WipeAbort(); - - return 1; - } - } - - if (lw == IDC_NO_HISTORY) - { - if (!(bHistory = !IsButtonChecked (GetDlgItem (hCurPage, IDC_NO_HISTORY)))) - ClearHistory (GetDlgItem (hCurPage, IDC_COMBO_BOX)); - - return 1; - } - - return 0; - } - - return 0; -} - -/* Except in response to the WM_INITDIALOG and WM_ENDSESSION messages, the dialog box procedure - should return nonzero if it processes the message, and zero if it does not. - see DialogProc */ -BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - - int nNewPageNo = nCurPageNo; - - switch (uMsg) - { - case WM_INITDIALOG: - { - MainDlg = hwndDlg; - InitDialog (hwndDlg); - LocalizeDialog (hwndDlg, "IDD_VOL_CREATION_WIZARD_DLG"); - - if (IsTrueCryptInstallerRunning()) - AbortProcess ("TC_INSTALLER_IS_RUNNING"); - - // Resize the bitmap if the user has a non-default DPI - if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) - { - hbmWizardBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_WIZARD), - GetDlgItem (hwndDlg, IDC_BITMAP_WIZARD), - 0, 0, 0, 0, FALSE, FALSE); - } - - LoadSettings (hwndDlg); - - LoadDefaultKeyFilesParam (); - RestoreDefaultKeyFilesParam (); - - SysEncMultiBootCfg.NumberOfSysDrives = -1; - SysEncMultiBootCfg.MultipleSystemsOnDrive = -1; - SysEncMultiBootCfg.BootLoaderLocation = -1; - SysEncMultiBootCfg.BootLoaderBrand = -1; - SysEncMultiBootCfg.SystemOnBootDrive = -1; - - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (hwndDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - EndMainDlg (MainDlg); - return 0; - } - - SendMessage (GetDlgItem (hwndDlg, IDC_BOX_TITLE), WM_SETFONT, (WPARAM) hTitleFont, (LPARAM) TRUE); - SetWindowTextW (hwndDlg, lpszTitle); - - ExtractCommandLine (hwndDlg, (char *) lParam); - - if (ComServerMode) - { - InitDialog (hwndDlg); - - if (!ComServerFormat ()) - { - handleWin32Error (hwndDlg); - exit (1); - } - exit (0); - } - - SHGetFolderPath (NULL, CSIDL_MYDOCUMENTS, NULL, 0, szRescueDiskISO); - strcat (szRescueDiskISO, "\\TrueCrypt Rescue Disk.iso"); - -#ifdef _DEBUG - // For faster testing - sprintf (szVerify, "%s", "q"); - sprintf (szRawPassword, "%s", "q"); -#endif - - PostMessage (hwndDlg, TC_APPMSG_PERFORM_POST_WMINIT_TASKS, 0, 0); - } - return 0; - - case WM_SYSCOMMAND: - if (lw == IDC_ABOUT) - { - DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc); - return 1; - } - return 0; - - case WM_TIMER: - - switch (wParam) - { - case TIMER_ID_RANDVIEW: - - if (WizardMode == WIZARD_MODE_SYS_DEVICE - || bInPlaceEncNonSys) - { - DisplayRandPool (hRandPoolSys, showKeys); - } - else - { - unsigned char tmp[17]; - char tmp2[43]; - int i; - - if (!showKeys) - return 1; - - RandpeekBytes (tmp, sizeof (tmp)); - - tmp2[0] = 0; - - for (i = 0; i < sizeof (tmp); i++) - { - char tmp3[8]; - sprintf (tmp3, "%02X", (int) (unsigned char) tmp[i]); - strcat (tmp2, tmp3); - } - - tmp2[32] = 0; - - SetWindowText (GetDlgItem (hCurPage, IDC_RANDOM_BYTES), tmp2); - - burn (tmp, sizeof(tmp)); - burn (tmp2, sizeof(tmp2)); - } - return 1; - - case TIMER_ID_SYSENC_PROGRESS: - { - // Manage system encryption/decryption and update related GUI - - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - KillTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS); - - try - { - BootEncObj->AbortSetup (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - e.Show (hwndDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - EndMainDlg (MainDlg); - return 1; - } - - if (BootEncStatus.SetupInProgress) - UpdateSysEncProgressBar (); - - if (bSystemEncryptionInProgress != BootEncStatus.SetupInProgress) - { - bSystemEncryptionInProgress = BootEncStatus.SetupInProgress; - - UpdateSysEncProgressBar (); - UpdateSysEncControls (); - - if (!bSystemEncryptionInProgress) - { - // The driver stopped encrypting/decrypting - - KillTimer (hwndDlg, TIMER_ID_SYSENC_PROGRESS); - - try - { - if (BootEncStatus.DriveMounted) // If we had been really encrypting/decrypting (not just proceeding to deinstall) - BootEncObj->CheckEncryptionSetupResult(); - } - catch (SystemException &e) - { - if (!bTryToCorrectReadErrors - && SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING - && (IsDiskReadError (e.ErrorCode))) - { - bTryToCorrectReadErrors = (AskWarnYesNo ("ENABLE_BAD_SECTOR_ZEROING") == IDYES); - - if (bTryToCorrectReadErrors) - { - SysEncResume(); - return 1; - } - } - else if (!DiscardUnreadableEncryptedSectors - && SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING - && (IsDiskReadError (e.ErrorCode))) - { - DiscardUnreadableEncryptedSectors = (AskWarnYesNo ("DISCARD_UNREADABLE_ENCRYPTED_SECTORS") == IDYES); - - if (DiscardUnreadableEncryptedSectors) - { - SysEncResume(); - return 1; - } - } - - e.Show (hwndDlg); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - switch (SystemEncryptionStatus) - { - case SYSENC_STATUS_ENCRYPTING: - - if (BootEncStatus.ConfiguredEncryptedAreaStart == BootEncStatus.EncryptedAreaStart - && BootEncStatus.ConfiguredEncryptedAreaEnd == BootEncStatus.EncryptedAreaEnd) - { - // The partition/drive has been fully encrypted - - ManageStartupSeqWiz (TRUE, ""); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_NEXT), GetString ("FINALIZE")); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); - - WipeHiddenOSCreationConfig(); // For extra conservative security - - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - - Info ("SYSTEM_ENCRYPTION_FINISHED"); - return 1; - } - break; - - case SYSENC_STATUS_DECRYPTING: - - if (!BootEncStatus.DriveEncrypted) - { - // The partition/drive has been fully decrypted - - try - { - // Finalize the process - BootEncObj->Deinstall (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - ManageStartupSeqWiz (TRUE, ""); - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_NEXT), GetString ("FINALIZE")); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); - - Info ("SYSTEM_DECRYPTION_FINISHED"); - - return 1; - } - break; - } - } - } - } - return 1; - - case TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS: - - if (bInPlaceEncNonSys) - { - // Non-system in-place encryption - - if (!bVolTransformThreadRunning && !bVolTransformThreadToRun) - { - KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS); - } - - UpdateNonSysInPlaceEncControls (); - } - return 1; - - case TIMER_ID_KEYB_LAYOUT_GUARD: - if (SysEncInEffect ()) - { - DWORD keybLayout = (DWORD) GetKeyboardLayout (NULL); - - /* Watch the keyboard layout */ - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - // Keyboard layout is not standard US - - WipePasswordsAndKeyfiles (); - - SetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD), szRawPassword); - SetWindowText (GetDlgItem (hCurPage, IDC_VERIFY), szVerify); - - keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); - Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); - EndMainDlg (MainDlg); - return 1; - } - - bKeyboardLayoutChanged = TRUE; - - wchar_t szTmp [4096]; - wcscpy (szTmp, GetString ("KEYB_LAYOUT_CHANGE_PREVENTED")); - wcscat (szTmp, L"\n\n"); - wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); - MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - } - - /* Watch the right Alt key (which is used to enter various characters on non-US keyboards) */ - - if (bKeyboardLayoutChanged && !bKeybLayoutAltKeyWarningShown) - { - if (GetAsyncKeyState (VK_RMENU) < 0) - { - bKeybLayoutAltKeyWarningShown = TRUE; - - wchar_t szTmp [4096]; - wcscpy (szTmp, GetString ("ALT_KEY_CHARS_NOT_FOR_SYS_ENCRYPTION")); - wcscat (szTmp, L"\n\n"); - wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); - MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); - } - } - } - return 1; - - case TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS: - - if (bSysEncDriveAnalysisInProgress) - { - UpdateProgressBarProc (GetTickCount() - SysEncDriveAnalysisStart); - - if (GetTickCount() - SysEncDriveAnalysisStart > SYSENC_DRIVE_ANALYSIS_ETA) - { - // It's taking longer than expected -- reinit the progress bar - SysEncDriveAnalysisStart = GetTickCount (); - InitProgressBar (SYSENC_DRIVE_ANALYSIS_ETA, 0, FALSE, FALSE, FALSE, TRUE); - } - - ArrowWaitCursor (); - } - else - { - KillTimer (hwndDlg, TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS); - UpdateProgressBarProc (SYSENC_DRIVE_ANALYSIS_ETA); - Sleep (1500); // User-friendly GUI - - if (bSysEncDriveAnalysisTimeOutOccurred) - Warning ("SYS_DRIVE_SIZE_PROBE_TIMEOUT"); - - LoadPage (hwndDlg, SYSENC_DRIVE_ANALYSIS_PAGE + 1); - } - return 1; - - case TIMER_ID_WIPE_PROGRESS: - - // Manage device wipe and update related GUI - - if (bHiddenOS && IsHiddenOSRunning()) - { - // Decoy system partition wipe - - DecoySystemWipeStatus decoySysPartitionWipeStatus; - - try - { - decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - KillTimer (MainDlg, TIMER_ID_WIPE_PROGRESS); - - try - { - BootEncObj->AbortDecoyOSWipe (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - e.Show (hwndDlg); - EndMainDlg (MainDlg); - return 1; - } - - if (decoySysPartitionWipeStatus.WipeInProgress) - { - ArrowWaitCursor (); - - UpdateWipeProgressBar (); - } - - if (bDeviceWipeInProgress != decoySysPartitionWipeStatus.WipeInProgress) - { - bDeviceWipeInProgress = decoySysPartitionWipeStatus.WipeInProgress; - - UpdateWipeProgressBar (); - UpdateWipeControls (); - - if (!bDeviceWipeInProgress) - { - // The driver stopped wiping - - KillTimer (hwndDlg, TIMER_ID_WIPE_PROGRESS); - - try - { - BootEncObj->CheckDecoyOSWipeResult(); - } - catch (Exception &e) - { - e.Show (hwndDlg); - AbortProcessSilent(); - } - - if (BootEncStatus.ConfiguredEncryptedAreaEnd == decoySysPartitionWipeStatus.WipedAreaEnd) - { - // Decoy system partition has been fully wiped - - ChangeHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED); - - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("EXIT")); - EnableWindow (GetDlgItem (MainDlg, IDCANCEL), TRUE); - EnableWindow (GetDlgItem (MainDlg, IDC_PREV), FALSE); - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); - - Info ("WIPE_FINISHED_DECOY_SYSTEM_PARTITION"); - - TextInfoDialogBox (TC_TBXID_DECOY_OS_INSTRUCTIONS); - - return 1; - } - } - } - } - else - { - // Regular device wipe (not decoy system partition wipe) - - //Info ("WIPE_FINISHED"); - } - return 1; - } - - return 0; - - - case TC_APPMSG_PERFORM_POST_WMINIT_TASKS: - - AfterWMInitTasks (hwndDlg); - return 1; - - case TC_APPMSG_FORMAT_FINISHED: - { - char tmp[RNG_POOL_SIZE*2+1]; - - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREV), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDHELP), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); - SetFocus (GetDlgItem (hwndDlg, IDC_NEXT)); - - if (nCurPageNo == FORMAT_PAGE) - KillTimer (hwndDlg, TIMER_ID_RANDVIEW); - - // Attempt to wipe the GUI fields showing portions of randpool, of the master and header keys - memset (tmp, 'X', sizeof(tmp)); - tmp [sizeof(tmp)-1] = 0; - SetWindowText (hRandPool, tmp); - SetWindowText (hMasterKey, tmp); - SetWindowText (hHeaderKey, tmp); - - LoadPage (hwndDlg, FORMAT_FINISHED_PAGE); - } - return 1; - - case TC_APPMSG_NONSYS_INPLACE_ENC_FINISHED: - - // A partition has just been fully encrypted in place - - KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS); - - LoadPage (hwndDlg, NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE); - - return 1; - - case TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED: - - if (bInPlaceEncNonSys) - { - // In-place encryption was interrupted/paused (did not finish) - - KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS); - - UpdateNonSysInPlaceEncControls (); - } - else - { - // Format has been aborted (did not finish) - - EnableWindow (GetDlgItem (hCurPage, IDC_QUICKFORMAT), (bDevice || bSparseFileSwitch) && !(bHiddenVol && !bHiddenVolHost)); - EnableWindow (GetDlgItem (hCurPage, IDC_FILESYS), TRUE); - EnableWindow (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREV), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDHELP), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), TRUE); - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); - SendMessage (GetDlgItem (hCurPage, IDC_PROGRESS_BAR), PBM_SETPOS, 0, 0L); - SetFocus (GetDlgItem (hwndDlg, IDC_NEXT)); - } - - NormalCursor (); - return 1; - - case WM_HELP: - - OpenPageHelp (hwndDlg, nCurPageNo); - return 1; - - case TC_APPMSG_FORMAT_USER_QUIT: - - if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_PAGE - && (bVolTransformThreadRunning || bVolTransformThreadToRun || bInPlaceEncNonSysResumed)) - { - // Non-system encryption in progress - if (AskNoYes ("NONSYS_INPLACE_ENC_DEFER_CONFIRM") == IDYES) - { - NonSysInplaceEncPause (); - - EndMainDlg (hwndDlg); - return 1; - } - else - return 1; // Disallow close - } - else if (bVolTransformThreadRunning || bVolTransformThreadToRun) - { - // Format (non-in-place encryption) in progress - if (AskNoYes ("FORMAT_ABORT") == IDYES) - { - bVolTransformThreadCancel = TRUE; - - EndMainDlg (hwndDlg); - return 1; - } - else - return 1; // Disallow close - } - else if ((nCurPageNo == SYSENC_ENCRYPTION_PAGE || nCurPageNo == SYSENC_PRETEST_RESULT_PAGE) - && SystemEncryptionStatus != SYSENC_STATUS_NONE - && InstanceHasSysEncMutex ()) - { - // System encryption/decryption in progress - - if (AskYesNo (SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING ? - "SYSTEM_DECRYPTION_DEFER_CONFIRM" : "SYSTEM_ENCRYPTION_DEFER_CONFIRM") == IDYES) - { - if (nCurPageNo == SYSENC_PRETEST_RESULT_PAGE) - TextInfoDialogBox (TC_TBXID_SYS_ENC_RESCUE_DISK); - - try - { - BootEncStatus = BootEncObj->GetStatus(); - - if (BootEncStatus.SetupInProgress) - { - BootEncObj->AbortSetupWait (); - Sleep (200); - BootEncStatus = BootEncObj->GetStatus(); - } - - if (!BootEncStatus.SetupInProgress) - { - EndMainDlg (MainDlg); - return 1; - } - else - { - Error ("FAILED_TO_INTERRUPT_SYSTEM_ENCRYPTION"); - return 1; // Disallow close - } - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - return 1; // Disallow close - } - else - return 1; // Disallow close - } - else if (bConfirmQuitSysEncPretest) - { - if (AskWarnNoYes (bHiddenOS ? "CONFIRM_CANCEL_HIDDEN_OS_CREATION" : "CONFIRM_CANCEL_SYS_ENC_PRETEST") == IDNO) - return 1; // Disallow close - } - else if (bConfirmQuit) - { - if (AskWarnNoYes ("CONFIRM_EXIT_UNIVERSAL") == IDNO) - return 1; // Disallow close - } - - if (hiddenVolHostDriveNo > -1) - { - CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); - UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE); - } - - EndMainDlg (hwndDlg); - return 1; - - - case WM_COMMAND: - - if (lw == IDHELP) - { - OpenPageHelp (hwndDlg, nCurPageNo); - return 1; - } - else if (lw == IDCANCEL) - { - PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); - return 1; - } - else if (lw == IDC_NEXT) - { - if (nCurPageNo == INTRO_PAGE) - { - switch (GetSelectedWizardMode (hCurPage)) - { - case WIZARD_MODE_FILE_CONTAINER: - - if (CurrentOSMajor >= 6 && IsUacSupported() && IsAdmin() && !IsNonInstallMode()) - { - static bool warningConfirmed = false; - if (!warningConfirmed) - { - if (AskWarnYesNo ("CONTAINER_ADMIN_WARNING") == IDYES) - exit (0); - - warningConfirmed = true; - } - } - - WaitCursor (); - CloseSysEncMutex (); - ChangeWizardMode (WIZARD_MODE_FILE_CONTAINER); - bHiddenOS = FALSE; - bInPlaceEncNonSys = FALSE; - nNewPageNo = VOLUME_TYPE_PAGE - 1; // Skip irrelevant pages - break; - - case WIZARD_MODE_NONSYS_DEVICE: - - WaitCursor (); - CloseSysEncMutex (); - - if (!ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE)) - { - NormalCursor (); - return 1; - } - - bHiddenOS = FALSE; - nNewPageNo = VOLUME_TYPE_PAGE - 1; // Skip irrelevant pages - break; - - case WIZARD_MODE_SYS_DEVICE: - - WaitCursor (); - bHiddenVol = FALSE; - bInPlaceEncNonSys = FALSE; - SwitchWizardToSysEncMode (); - return 1; - } - } - else if (nCurPageNo == SYSENC_TYPE_PAGE) - { - if (bHiddenOS) - { - bWholeSysDrive = FALSE; - bHiddenVolDirect = FALSE; - } - - if (!bHiddenOS) - nNewPageNo = SYSENC_SPAN_PAGE - 1; // Skip irrelevant pages - } - else if (nCurPageNo == SYSENC_HIDDEN_OS_REQ_CHECK_PAGE) - { - WaitCursor (); - try - { - BootEncObj->CheckRequirementsHiddenOS (); - - if (CheckGapBetweenSysAndHiddenOS ()) - Warning ("GAP_BETWEEN_SYS_AND_HIDDEN_OS_PARTITION"); - } - catch (Exception &e) - { - e.Show (hwndDlg); - NormalCursor (); - return 1; - } - - if (AskWarnYesNo ("DECOY_OS_REINSTALL_WARNING") == IDNO) - { - NormalCursor (); - return 1; - } - - if (AskWarnYesNo ("DECOY_OS_REQUIREMENTS") == IDNO) - { - NormalCursor (); - return 1; - } - - if (!IsAdmin() && IsUacSupported()) - { - // If UAC elevation is needed, we need to elevate the complete wizard process here, because - // we will need to switch to the non-sys-device mode, which requires the whole wizard process - // to have admin rights. - - CloseSysEncMutex (); - - if (!ElevateWholeWizardProcess ("/r")) - { - // Failed to obtain admin rights - - NormalCursor (); - - if (!CreateSysEncMutex ()) - AbortProcess ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - - return 1; - } - } - - // This check requires admin rights - try - { - BootEncObj->InitialSecurityChecksForHiddenOS (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - EndMainDlg (MainDlg); // Some of the checks need the wizard to be restarted (results are cached until exit and the checks would fail even if the issues were rectified). - return 1; - } - - nNewPageNo = SYSENC_MULTI_BOOT_MODE_PAGE - 1; // Skip irrelevant pages - } - else if (nCurPageNo == SYSENC_SPAN_PAGE) - { - try - { - if (bWholeSysDrive && !BootEncObj->SystemPartitionCoversWholeDrive()) - { - if (!IsOSAtLeast (WIN_VISTA)) - { - if (BootEncObj->SystemDriveContainsExtendedPartition()) - { - Error ("WDE_UNSUPPORTED_FOR_EXTENDED_PARTITIONS"); - - if (AskYesNo ("ASK_ENCRYPT_PARTITION_INSTEAD_OF_DRIVE") == IDNO) - return 1; - - bWholeSysDrive = FALSE; - } - else - Warning ("WDE_EXTENDED_PARTITIONS_WARNING"); - } - } - - if (!bWholeSysDrive && BootEncObj->SystemPartitionCoversWholeDrive()) - bWholeSysDrive = (AskYesNo ("WHOLE_SYC_DEVICE_RECOM") == IDYES); - } - catch (Exception &e) - { - e.Show (hwndDlg); - NormalCursor (); - return 1; - } - - if (!bWholeSysDrive) - nNewPageNo = SYSENC_MULTI_BOOT_MODE_PAGE - 1; // Skip irrelevant pages - } - else if (nCurPageNo == SYSENC_PRE_DRIVE_ANALYSIS_PAGE) - { - if ((SysEncDetectHiddenSectors = Get2RadButtonPageAnswer()) != 1) - { - // Skip drive analysis - nNewPageNo = SYSENC_DRIVE_ANALYSIS_PAGE; - - // If the user had already searched for hidden sectors, we must clear (invalidate) the - // result because now he changed his mind and no longer wishes to encrypt the hidden sectors. - try - { - BootEncObj->InvalidateCachedSysDriveProperties (); - } - catch (Exception &e) - { - e.Show (MainDlg); - EndMainDlg (MainDlg); - exit(0); - } - } - } - else if (nCurPageNo == SYSENC_MULTI_BOOT_MODE_PAGE) - { - if (nMultiBoot <= 1) - { - if (bHiddenOS) - { - if (!ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE)) - { - NormalCursor (); - return 1; - } - - nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE - 1; // Skip irrelevant pages - } - else - nNewPageNo = CIPHER_PAGE - 1; // Skip irrelevant pages - } - else if (AskWarnNoYes ("MULTI_BOOT_FOR_ADVANCED_ONLY") == IDNO) - return 1; - } - else if (nCurPageNo == SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE) - { - SysEncMultiBootCfg.SystemOnBootDrive = Get2RadButtonPageAnswer (); - - if (!SysEncMultiBootCfg.SystemOnBootDrive) - { - Error ("SYS_PARTITION_MUST_BE_ON_BOOT_DRIVE"); - EndMainDlg (MainDlg); - return 1; - } - } - else if (nCurPageNo == SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE) - { - if (Get2RadButtonPageAnswer () == 0) - { - // 2 or more drives contain an OS - - SysEncMultiBootCfg.NumberOfSysDrives = 2; - } - else if (Get2RadButtonPageAnswer () == 1) - { - // Only 1 drive contains an OS - - SysEncMultiBootCfg.NumberOfSysDrives = 1; - - if (bWholeSysDrive) - { - // Whole-system-drive encryption is currently not supported if the drive contains - // more than one system - Error ("WDE_UNSUPPORTED_FOR_MULTIPLE_SYSTEMS_ON_ONE_DRIVE"); - return 1; - } - - // Ask whether there is a non-Windows boot loader in the MBR - nNewPageNo = SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE - 1; - } - } - else if (nCurPageNo == SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE) - { - SysEncMultiBootCfg.MultipleSystemsOnDrive = Get2RadButtonPageAnswer (); - - if (SysEncMultiBootCfg.MultipleSystemsOnDrive && bWholeSysDrive) - { - // Whole-system-drive encryption is currently not supported if the drive contains - // more than one system - Error ("WDE_UNSUPPORTED_FOR_MULTIPLE_SYSTEMS_ON_ONE_DRIVE"); - return 1; - } - } - - else if (nCurPageNo == SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE) - { - SysEncMultiBootCfg.BootLoaderBrand = Get2RadButtonPageAnswer (); - - if (SysEncMultiBootCfg.BootLoaderBrand) - { - // A non-Windows boot manager in the MBR - Error ("CUSTOM_BOOT_MANAGERS_IN_MBR_UNSUPPORTED"); - EndMainDlg (MainDlg); - return 1; - } - else - { - // Either a standard Windows boot manager or no boot manager - wcscpy_s (SysEncMultiBootCfgOutcome, sizeof(SysEncMultiBootCfgOutcome) / 2, GetString ("WINDOWS_BOOT_LOADER_HINTS")); - } - } - - else if (nCurPageNo == SYSENC_MULTI_BOOT_OUTCOME_PAGE) - { - SYSTEMTIME sysTime; - GetLocalTime (&sysTime); - - if (sysTime.wYear <= 2010) - Warning ("MULTI_BOOT_VISTA_SP1"); - - if (bHiddenOS) - { - if (!ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE)) - { - NormalCursor (); - return 1; - } - - nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE - 1; // Skip irrelevant pages - } - else - nNewPageNo = CIPHER_PAGE - 1; // Skip irrelevant pages - } - - else if (nCurPageNo == VOLUME_TYPE_PAGE) - { - if (IsButtonChecked (GetDlgItem (hCurPage, IDC_HIDDEN_VOL))) - { - if (!IsAdmin() && !IsUacSupported () - && IDNO == MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_HIDVOL"), - lpszTitle, MB_ICONWARNING|MB_YESNO|MB_DEFBUTTON2)) - { - return 1; - } - else - { - bHiddenVol = TRUE; - bHiddenVolHost = TRUE; - bInPlaceEncNonSys = FALSE; - } - } - else - { - if (IsHiddenOSRunning()) - { - WarningDirect ((wstring (GetString ("CAN_CREATE_ONLY_HIDDEN_VOLUMES_UNDER_HIDDEN_OS")) - + L"\n\n" - + GetString ("NOTE_BEGINNING") - + GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO") - + L" " - + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION")).c_str()); - - NormalCursor (); - return 1; - } - - bHiddenVol = FALSE; - bHiddenVolHost = FALSE; - bHiddenVolDirect = FALSE; - nNewPageNo = VOLUME_LOCATION_PAGE - 1; // Skip the hidden volume creation wizard mode selection - } - } - - else if (nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) - { - if (IsButtonChecked (GetDlgItem (hCurPage, IDC_HIDVOL_WIZ_MODE_DIRECT))) - bHiddenVolDirect = TRUE; - else - { - if (IsHiddenOSRunning()) - { - WarningDirect ((wstring (GetString ("HIDDEN_VOL_CREATION_UNDER_HIDDEN_OS_HOWTO")) - + L"\n\n\n" - + GetString ("NOTE_BEGINNING") - + GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO") - + L" " - + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION")).c_str()); - NormalCursor (); - return 1; - } - - bHiddenVolDirect = FALSE; - } - } - - else if (nCurPageNo == VOLUME_LOCATION_PAGE) - { - BOOL tmpbDevice; - - WaitCursor(); - - GetWindowText (GetDlgItem (hCurPage, IDC_COMBO_BOX), szFileName, sizeof (szFileName)); - CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); - - if (tmpbDevice != bDevice) - { - if (bDevice) - { - // Not a valid device path - Error ("CANNOT_CALC_SPACE"); - NormalCursor (); - return 1; - } - else - { - if (AskWarnYesNo ("DEVICE_SELECTED_IN_NON_DEVICE_MODE") == IDNO) - { - NormalCursor (); - return 1; - } - - SwitchWizardToNonSysDeviceMode (); - NormalCursor (); - return 1; - } - } - - MoveEditToCombo (GetDlgItem (hCurPage, IDC_COMBO_BOX), bHistory); - - if (IsMountedVolume (szDiskFile)) - { - Error ("ALREADY_MOUNTED"); - NormalCursor (); - return 1; - } - - if (bDevice) - { - switch (IsSystemDevicePath (szDiskFile, hCurPage, TRUE)) - { - case 1: - case 2: - if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE") == IDNO) - { - NormalCursor (); - return 1; - } - szFileName[0] = 0; - szDiskFile[0] = 0; - SwitchWizardToSysEncMode (); - NormalCursor (); - return 1; - - case -1: - // In some environments (such as PE), the system volume is not located on a hard drive. - // Therefore, we must interpret this return code as "Not a system device path" (otherwise, - // non-system devices could not be TC-formatted in such environments). Note that this is - // rather safe, because bReliableRequired is set to TRUE. - - // NOP - break; - } - } - else - { - if (CheckFileExtension(szFileName) - && AskWarnNoYes ("EXE_FILE_EXTENSION_CONFIRM") == IDNO) - { - NormalCursor (); - return 1; - } - } - - bHistory = !IsButtonChecked (GetDlgItem (hCurPage, IDC_NO_HISTORY)); - - SaveSettings (hCurPage); - - if (bHiddenVolDirect && bHiddenVolHost) - { - nNewPageNo = HIDDEN_VOL_HOST_PASSWORD_PAGE - 1; - - if (bDevice) - { - if(!QueryFreeSpace (hwndDlg, GetDlgItem (hwndDlg, IDC_SPACE_LEFT), FALSE)) - { - MessageBoxW (hwndDlg, GetString ("CANT_GET_VOLSIZE"), lpszTitle, ICON_HAND); - NormalCursor (); - return 1; - } - else - nHiddenVolHostSize = nVolumeSize; - } - else - { - if (!GetFileVolSize (hwndDlg, &nHiddenVolHostSize)) - { - NormalCursor (); - return 1; - } - else if (IsSparseFile (hwndDlg)) - { - // Hidden volumes must not be created within sparse file containers - Warning ("HIDDEN_VOL_HOST_SPARSE"); - NormalCursor (); - return 1; - } - } - } - else - { - if (!bHiddenVol && !bDevice) - nNewPageNo = CIPHER_PAGE - 1; - else if (bHiddenVol) - nNewPageNo = (bHiddenVolHost ? HIDDEN_VOL_HOST_PRE_CIPHER_PAGE : HIDDEN_VOL_PRE_CIPHER_PAGE) - 1; - } - } - - else if (nCurPageNo == DEVICE_TRANSFORM_MODE_PAGE) - { - if (bInPlaceEncNonSys) - { - // Check requirements for non-system in-place encryption - - if (!CheckRequirementsForNonSysInPlaceEnc (szDiskFile, FALSE)) - { - return 1; - } - - // We are going to skip the Size page so we must get the size here - nVolumeSize = GetDeviceSize (szDiskFile); - - if (nVolumeSize == -1) - { - handleWin32Error (MainDlg); - return 1; - } - - if (AskWarnYesNo ("NONSYS_INPLACE_ENC_CONFIRM_BACKUP") == IDNO) - return 1; - } - nNewPageNo = CIPHER_PAGE - 1; - } - - else if (nCurPageNo == HIDDEN_VOL_HOST_PRE_CIPHER_PAGE) - { - if (bHiddenVolHost) - nNewPageNo = CIPHER_PAGE - 1; // Skip the info on the hiddem volume - } - - else if (nCurPageNo == CIPHER_PAGE) - { - LPARAM nIndex; - nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); - nVolumeEA = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); - - if (SysEncInEffect () - && EAGetCipherCount (nVolumeEA) > 1) // Cascade? - { - if (AskWarnNoYes ("CONFIRM_CASCADE_FOR_SYS_ENCRYPTION") == IDNO) - return 1; - - Info ("NOTE_CASCADE_FOR_SYS_ENCRYPTION"); - } - - nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETCURSEL, 0, 0); - hash_algo = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETITEMDATA, nIndex, 0); - - RandSetHashFunction (hash_algo); - - if (SysEncInEffect () || bInPlaceEncNonSys) - nNewPageNo = PASSWORD_PAGE - 1; // Skip irrelevant pages - } - - else if (nCurPageNo == SIZE_PAGE) - { - char szFileSystemNameBuffer[256]; - - VerifySizeAndUpdate (hCurPage, TRUE); - - if (!bDevice) - { - /* Verify that the volume would not be too large for the host file system */ - - char root[TC_MAX_PATH]; - - if (GetVolumePathName (szDiskFile, root, sizeof (root)) - && GetVolumeInformation (root, NULL, 0, NULL, NULL, NULL, szFileSystemNameBuffer, sizeof(szFileSystemNameBuffer)) - && !strncmp (szFileSystemNameBuffer, "FAT32", 5)) - { - // The host file system is FAT32 - if (nUIVolumeSize * nMultiplier >= 4 * BYTES_PER_GB) - { - Error ("VOLUME_TOO_LARGE_FOR_FAT32"); - return 1; - } - } - } - - if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume - { - /* Ask for confirmation if the hidden volume is too large for the user to be - able to write much more data to the outer volume. */ - - if (((double) nUIVolumeSize / (nMaximumHiddenVolSize / nMultiplier)) > 0.85) // 85% - { - if (AskWarnNoYes ("FREE_SPACE_FOR_WRITING_TO_OUTER_VOLUME") == IDNO) - return 1; - } - } - - if (!(bHiddenVolDirect && bHiddenVolHost)) - nNewPageNo = PASSWORD_PAGE - 1; - } - - else if (nCurPageNo == PASSWORD_PAGE) - { - VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (MainDlg, IDC_NEXT), - GetDlgItem (hCurPage, IDC_PASSWORD), - GetDlgItem (hCurPage, IDC_VERIFY), - volumePassword.Text, - szVerify, - KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect()); - - volumePassword.Length = strlen ((char *) volumePassword.Text); - - if (volumePassword.Length > 0) - { - // Password character encoding - if (!CheckPasswordCharEncoding (GetDlgItem (hCurPage, IDC_PASSWORD), NULL)) - { - Error ("UNSUPPORTED_CHARS_IN_PWD"); - return 1; - } - // Check password length (do not check if it's for an outer volume). - else if (!bHiddenVolHost - && !CheckPasswordLength (hwndDlg, GetDlgItem (hCurPage, IDC_PASSWORD))) - { - return 1; - } - } - - // Store the password in case we need to restore it after keyfile is applied to it - GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD), szRawPassword, sizeof (szRawPassword)); - - if (!SysEncInEffect ()) - { - if (KeyFilesEnable) - { - WaitCursor (); - KeyFilesApply (&volumePassword, FirstKeyFile); - NormalCursor (); - } - - } - else - { - KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); - - if (bKeyboardLayoutChanged) - { - // Restore the original keyboard layout - if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) - Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); - else - bKeyboardLayoutChanged = FALSE; - } - - nNewPageNo = SYSENC_COLLECTING_RANDOM_DATA_PAGE - 1; // Skip irrelevant pages - } - - if (bInPlaceEncNonSys) - { - nNewPageNo = NONSYS_INPLACE_ENC_RAND_DATA_PAGE - 1; // Skip irrelevant pages - } - else if (WizardMode != WIZARD_MODE_SYS_DEVICE - && !FileSize4GBLimitQuestionNeeded () - || CreatingHiddenSysVol()) // If we're creating a hidden volume for a hidden OS, we don't need to format it with any filesystem (the entire OS will be copied to the hidden volume sector by sector). - { - nNewPageNo = FORMAT_PAGE - 1; // Skip irrelevant pages - } - } - - else if (nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) - { - WaitCursor (); - - GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), (char *) volumePassword.Text, sizeof (volumePassword.Text)); - volumePassword.Length = strlen ((char *) volumePassword.Text); - - // Store the password in case we need to restore it after keyfile is applied to it - GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), szRawPassword, sizeof (szRawPassword)); - - if (KeyFilesEnable) - { - KeyFilesApply (&volumePassword, FirstKeyFile); - } - - if (!bInPlaceEncNonSys) - { - - /* Mount the volume which is to host the new hidden volume as read only */ - - if (hiddenVolHostDriveNo >= 0) // If the hidden volume host is currently mounted (e.g. after previous unsuccessful dismount attempt) - { - BOOL tmp_result; - - // Dismount the hidden volume host (in order to remount it as read-only subsequently) - while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) - { - if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL) != IDRETRY) - { - // Cancel - NormalCursor(); - return 1; - } - } - if (tmp_result) // If dismounted - hiddenVolHostDriveNo = -1; - } - - if (hiddenVolHostDriveNo < 0) // If the hidden volume host is not mounted - { - int retCode; - - // Mount the hidden volume host as read-only (to ensure consistent and secure - // results of the volume bitmap scanning) - switch (MountHiddenVolHost (hwndDlg, szDiskFile, &hiddenVolHostDriveNo, &volumePassword, TRUE)) - { - case ERR_NO_FREE_DRIVES: - NormalCursor (); - MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVE_FOR_OUTER_VOL"), lpszTitle, ICON_HAND); - return 1; - case ERR_VOL_MOUNT_FAILED: - case ERR_PASSWORD_WRONG: - NormalCursor (); - return 1; - case 0: - - /* Hidden volume host successfully mounted as read-only */ - - WaitCursor (); - - // Verify that the outer volume contains a suitable file system, retrieve cluster size, and - // scan the volume bitmap - if (!IsAdmin () && IsUacSupported ()) - retCode = UacAnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); - else - retCode = AnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); - - switch (retCode) - { - case -1: // Fatal error - CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); - - if (UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE)) - hiddenVolHostDriveNo = -1; - - AbortProcessSilent (); - break; - - case 0: // Unsupported file system (or other non-fatal error which has already been reported) - if (bHiddenVolDirect) - { - CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); - - if (UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE)) - hiddenVolHostDriveNo = -1; - } - NormalCursor (); - return 1; - - case 1: - - // Determine the maximum possible size of the hidden volume - if (DetermineMaxHiddenVolSize (hwndDlg) < 1) - { - // Non-fatal error while determining maximum possible size of the hidden volume - NormalCursor(); - return 1; - } - else - { - BOOL tmp_result; - - /* Maximum possible size of the hidden volume successfully determined */ - - // Dismount the hidden volume host - while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) - { - if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL) != IDRETRY) - { - // Cancel - NormalCursor(); - return 1; - } - } - - if (tmp_result) // If dismounted - { - hiddenVolHostDriveNo = -1; - - bHiddenVolHost = FALSE; - bHiddenVolFinished = FALSE; - - // Clear the outer volume password - WipePasswordsAndKeyfiles (); - - RestoreDefaultKeyFilesParam (); - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); - NormalCursor (); - - nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE; - } - } - break; - } - break; - } - } - } - else - { - /* Scan all available partitions to discover all partitions where non-system in-place - encryption has been interrupted. */ - - BOOL tmpbDevice; - DeferredNonSysInPlaceEncDevices.clear(); - - foreach (const HostDevice &device, GetAvailableHostDevices (true, true)) - { - if (device.IsPartition || device.DynamicVolume) - { - OpenVolumeContext volume; - - if (OpenVolume (&volume, device.Path.c_str(), &volumePassword, FALSE, FALSE, TRUE) == ERR_SUCCESS) - { - if ((volume.CryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0 - && volume.CryptoInfo->EncryptedAreaLength.Value != volume.CryptoInfo->VolumeSize.Value) - { - DeferredNonSysInPlaceEncDevices.push_back (device); - } - - CloseVolume (&volume); - } - } - } - - if (DeferredNonSysInPlaceEncDevices.empty()) - { - Warning ("FOUND_NO_PARTITION_W_DEFERRED_INPLACE_ENC"); - - NormalCursor(); - return 1; - } - else if (DeferredNonSysInPlaceEncDevices.size() == 1) - { - CreateFullVolumePath (szDiskFile, DeferredNonSysInPlaceEncDevices.front().Path.c_str(), &tmpbDevice); - - nVolumeSize = GetDeviceSize (szDiskFile); - if (nVolumeSize == -1) - { - handleWin32Error (MainDlg); - NormalCursor(); - return 1; - } - - nNewPageNo = NONSYS_INPLACE_ENC_ENCRYPTION_PAGE - 1; // Skip irrelevant pages - } - - NormalCursor(); - } - - } - - else if (nCurPageNo == FILESYS_PAGE) - { - if (nNeedToStoreFilesOver4GB != Get2RadButtonPageAnswer()) - fileSystem = FILESYS_NONE; // The user may have gone back and changed the answer, so default file system must be reselected - - nNeedToStoreFilesOver4GB = Get2RadButtonPageAnswer(); - - nNewPageNo = FORMAT_PAGE - 1; // Skip irrelevant pages - } - - else if (nCurPageNo == SYSENC_COLLECTING_RANDOM_DATA_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_RAND_DATA_PAGE) - { - char tmp[RANDPOOL_DISPLAY_SIZE+1]; - - if (!bInPlaceEncNonSys) - { - /* Generate master key and other related data (except the rescue disk) for system encryption. */ - - try - { - WaitCursor(); - BootEncObj->PrepareInstallation (!bWholeSysDrive, volumePassword, nVolumeEA, FIRST_MODE_OF_OPERATION_ID, hash_algo, ""); - } - catch (Exception &e) - { - e.Show (hwndDlg); - NormalCursor (); - return 1; - } - } - - KillTimer (hwndDlg, TIMER_ID_RANDVIEW); - - // Attempt to wipe the GUI field showing portions of randpool - memset (tmp, 'X', sizeof(tmp)); - tmp [sizeof(tmp)-1] = 0; - SetWindowText (hRandPoolSys, tmp); - - NormalCursor (); - } - - else if (nCurPageNo == SYSENC_KEYS_GEN_PAGE) - { - char tmp[KEY_GUI_VIEW_SIZE+1]; - - // Attempt to wipe the GUI fields showing portions of the master and header keys - memset (tmp, 'X', sizeof(tmp)); - tmp [sizeof(tmp)-1] = 0; - SetWindowText (hMasterKey, tmp); - SetWindowText (hHeaderKey, tmp); - } - - else if (nCurPageNo == SYSENC_RESCUE_DISK_CREATION_PAGE) - { - /* Generate rescue disk for boot encryption */ - - GetWindowText (GetDlgItem (hCurPage, IDC_RESCUE_DISK_ISO_PATH), szRescueDiskISO, sizeof (szRescueDiskISO)); - - try - { - WaitCursor(); - BootEncObj->CreateRescueIsoImage (true, szRescueDiskISO); - - } - catch (Exception &e) - { - e.Show (hwndDlg); - NormalCursor (); - return 1; - } - NormalCursor (); - } - - else if (nCurPageNo == SYSENC_RESCUE_DISK_BURN_PAGE) - { - if (!bDontVerifyRescueDisk) - { - /* Verify that the rescue disk has been written correctly */ - - try - { - WaitCursor(); - if (!BootEncObj->VerifyRescueDisk ()) - { - Error ("RESCUE_DISK_CHECK_FAILED"); - NormalCursor (); -#ifndef _DEBUG - return 1; -#endif - } - } - catch (Exception &e) - { - e.Show (hwndDlg); - NormalCursor (); - return 1; - } - NormalCursor (); - } - else - { - Warning ("RESCUE_DISK_BURN_NO_CHECK_WARN"); - nNewPageNo = SYSENC_RESCUE_DISK_VERIFIED_PAGE; // Skip irrelevant pages - } - } - - else if (nCurPageNo == SYSENC_WIPE_MODE_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_WIPE_MODE_PAGE) - { - if (nWipeMode > 0 - && AskWarnYesNo ("WIPE_MODE_WARN") == IDNO) - return 1; - } - - else if (nCurPageNo == SYSENC_PRETEST_INFO_PAGE) - { - if (LocalizationActive - && AskWarnYesNo ("PREBOOT_NOT_LOCALIZED") == IDNO) - return 1; - - bConfirmQuitSysEncPretest = TRUE; - - if (!bHiddenOS) // This text is not tailored to hidden OS - TextInfoDialogBox (TC_TBXID_SYS_ENCRYPTION_PRETEST); - - if (AskWarnYesNo ("CONFIRM_RESTART") == IDNO) - return 1; - - /* Install the pre-boot authentication component and initiate the system encryption pretest. - If we are creating a hidden OS, pretest is omitted and OS cloning will follow. */ - - try - { - WaitCursor(); - -#if 0 - // Make sure the Rescue Disk is not in the drive - while (BootEncObj->VerifyRescueDisk ()) - { - Error ("REMOVE_RESCUE_DISK_FROM_DRIVE"); - } -#endif - - BootEncObj->Install (bHiddenOS ? true : false); - } - catch (Exception &e) - { - e.Show (hwndDlg); - Error (bHiddenOS ? "CANNOT_INITIATE_HIDDEN_OS_CREATION" : "CANNOT_INITIATE_SYS_ENCRYPTION_PRETEST"); - NormalCursor (); - return 1; - } - - - /* Add the main TrueCrypt app to the system startup sequence (the TrueCrypt Background Task), which - we need e.g. for notifications about prevented hibernation, about hidden OS leak protection, about - inconsistent hidden OS installs (TrueCrypt upgraded in the decoy system but not in the hidden one), etc. - Note that this must be done before calling ChangeSystemEncryptionStatus(), which broadcasts the change, - so that the main app (if it's running with different cached settings) will not overwrite our new - settings when it exits. */ - bStartOnLogon = TRUE; - SaveSettings (NULL); - ManageStartupSeq (); - - - if (bHiddenOS) - { - /* When we are going to create a hidden OS, the system encryption status is set - to SYSENC_STATUS_PRETEST (not to any special hidden-OS status), in case the XML - configuration file and its properties somehow leaks somewhere outside the system - partition (which will be wiped later on) indicating that a hidden OS has been created - on the computer. Instead, we update our raw config flags in the master boot record - (which is also altered when our boot loader is installed). */ - - if (!ChangeSystemEncryptionStatus (SYSENC_STATUS_PRETEST) - || !ChangeHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING)) - { - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - Error ("CANNOT_INITIATE_HIDDEN_OS_CREATION"); - NormalCursor (); - return 1; - } - } - else if (!ChangeSystemEncryptionStatus (SYSENC_STATUS_PRETEST)) - { - Error ("CANNOT_INITIATE_SYS_ENCRYPTION_PRETEST"); - NormalCursor (); - return 1; - } - - // Add the wizard to the system startup sequence - ManageStartupSeqWiz (FALSE, "/acsysenc"); - - EndMainDlg (MainDlg); - - try - { - BootEncObj->RestartComputer (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - return 1; - } - - else if (nCurPageNo == SYSENC_PRETEST_RESULT_PAGE) - { - TextInfoDialogBox (TC_TBXID_SYS_ENC_RESCUE_DISK); - - // Begin the actual encryption process - - ChangeSystemEncryptionStatus (SYSENC_STATUS_ENCRYPTING); - } - - else if (nCurPageNo == SYSENC_ENCRYPTION_PAGE - && CreateSysEncMutex ()) - { - // The 'Next' button functions as Finish or Resume - - if (SystemEncryptionStatus != SYSENC_STATUS_NONE) - { - try - { - // Resume - SysEncResume (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - } - else - { - // Finish - PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); - } - - return 1; - } - else if (nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE) - { - nNewPageNo = NONSYS_INPLACE_ENC_ENCRYPTION_PAGE - 1; // Skip irrelevant pages - } - else if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_PAGE) - { - /* In-place encryption start (the 'Next' button has been clicked) */ - - NonSysInplaceEncResume (); - return 1; - } - else if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE) - { - PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); - return 1; - } - else if (nCurPageNo == FORMAT_PAGE) - { - /* Format start (the 'Next' button has been clicked on the Format page) */ - - if (bVolTransformThreadRunning || bVolTransformThreadToRun) - return 1; - - bVolTransformThreadCancel = FALSE; - - bVolTransformThreadToRun = TRUE; - - fileSystem = SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETITEMDATA, - SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETCURSEL, 0, 0) , 0); - - clusterSize = SendMessage (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), CB_GETITEMDATA, - SendMessage (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), CB_GETCURSEL, 0, 0) , 0); - - quickFormat = IsButtonChecked (GetDlgItem (hCurPage, IDC_QUICKFORMAT)); - - if (bHiddenVolHost) - { - hiddenVolHostDriveNo = -1; - nMaximumHiddenVolSize = 0; - - if (fileSystem == FILESYS_NTFS) - { - if (bHiddenOS - && (double) nVolumeSize / GetSystemPartitionSize() < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS) - { - Error("OUTER_VOLUME_TOO_SMALL_FOR_HIDDEN_OS_NTFS"); - - if (GetVolumeDataAreaSize (FALSE, nVolumeSize) <= TC_MAX_FAT_FS_SIZE - && AskYesNo("OFFER_FAT_FORMAT_ALTERNATIVE") == IDYES) - { - fileSystem = FILESYS_FAT; - SelectAlgo (GetDlgItem (hCurPage, IDC_FILESYS), (int *) &fileSystem); - } - else - { - bVolTransformThreadToRun = FALSE; - return 1; - } - } - - if (fileSystem == FILESYS_NTFS) // The file system may have been changed in the previous block - { - if (nCurrentOS == WIN_2000) - { - Error("HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS_WIN2000"); - bVolTransformThreadToRun = FALSE; - return 1; - } - else if (GetVolumeDataAreaSize (FALSE, nVolumeSize) <= TC_MAX_FAT_FS_SIZE - && AskYesNo("HIDDEN_VOL_HOST_NTFS_ASK") == IDNO) - { - bVolTransformThreadToRun = FALSE; - return 1; - } - } - } - } - else if (bHiddenVol) - { - // Hidden volume is always quick-formatted (if, however, the meaning of quickFormat is - // whether to create a sparse file, it must be set to FALSE). - quickFormat = !bSparseFileSwitch; - } - - - if (fileSystem == FILESYS_FAT - && nNeedToStoreFilesOver4GB == 1 - && AskWarnNoYes("CONFIRM_FAT_FOR_FILES_OVER_4GB") == IDNO) - { - bVolTransformThreadToRun = FALSE; - return 1; - } - - EnableWindow (GetDlgItem (hwndDlg, IDC_PREV), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDHELP), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_QUICKFORMAT), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_FILESYS), FALSE); - EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); - SetFocus (GetDlgItem (hCurPage, IDC_ABORT_BUTTON)); - - // Increase cluster size if it's too small for this volume size - if (fileSystem == FILESYS_FAT && clusterSize > 0) - { - BOOL fixed = FALSE; - while (clusterSize < 128 - && nVolumeSize / clusterSize > 17179869184I64) - { - clusterSize *= 2; - fixed = TRUE; - } - if (fixed) - MessageBoxW (hwndDlg, GetString ("CLUSTER_TOO_SMALL"), lpszTitle, MB_ICONWARNING); - } - - LastDialogId = "FORMAT_IN_PROGRESS"; - ArrowWaitCursor (); - _beginthread (volTransformThreadFunction, 0, MainDlg); - - return 1; - } - - else if (nCurPageNo == FORMAT_FINISHED_PAGE) - { - if (!bHiddenVol || bHiddenVolFinished) - { - /* Wizard loop restart */ - - if (bHiddenOS) - { - if (!ChangeWizardMode (WIZARD_MODE_SYS_DEVICE)) - return 1; - - // Hidden volume for hidden OS has been created. Now we will prepare our boot loader - // that will handle the OS cloning. - try - { - WaitCursor(); - - BootEncObj->PrepareHiddenOSCreation (nVolumeEA, FIRST_MODE_OF_OPERATION_ID, hash_algo); - } - catch (Exception &e) - { - e.Show (MainDlg); - NormalCursor(); - return 1; - } - - bHiddenVol = FALSE; - - LoadPage (hwndDlg, SYSENC_PRETEST_INFO_PAGE); - } - else - LoadPage (hwndDlg, INTRO_PAGE); - - SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); - bHiddenVolFinished = FALSE; - WipePasswordsAndKeyfiles (); - - return 1; - } - else - { - /* We're going to scan the bitmap of the hidden volume host (in the non-Direct hidden volume wizard mode) */ - int retCode; - WaitCursor (); - - if (hiddenVolHostDriveNo != -1) // If the hidden volume host is mounted - { - BOOL tmp_result; - - // Dismount the hidden volume host (in order to remount it as read-only subsequently) - CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); - while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) - { - if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL | MB_ICONERROR | MB_SETFOREGROUND) != IDRETRY) - { - // Cancel - NormalCursor(); - return 1; - } - } - if (tmp_result) // If dismounted - hiddenVolHostDriveNo = -1; - } - - if (hiddenVolHostDriveNo < 0) // If the hidden volume host is not mounted - { - // Remount the hidden volume host as read-only (to ensure consistent and secure - // results of the volume bitmap scanning) - switch (MountHiddenVolHost (hwndDlg, szDiskFile, &hiddenVolHostDriveNo, &volumePassword, TRUE)) - { - case ERR_NO_FREE_DRIVES: - MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVE_FOR_OUTER_VOL"), lpszTitle, ICON_HAND); - NormalCursor (); - return 1; - - case ERR_VOL_MOUNT_FAILED: - case ERR_PASSWORD_WRONG: - NormalCursor (); - return 1; - - case 0: - - /* Hidden volume host successfully mounted as read-only */ - - // Verify that the outer volume contains a suitable file system, retrieve cluster size, and - // scan the volume bitmap - if (!IsAdmin () && IsUacSupported ()) - retCode = UacAnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); - else - retCode = AnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); - - switch (retCode) - { - case -1: // Fatal error - CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); - - if (UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE)) - hiddenVolHostDriveNo = -1; - - AbortProcessSilent (); - break; - - case 0: // Unsupported file system (or other non-fatal error which has already been reported) - NormalCursor (); - return 1; - - case 1: // Success - { - BOOL tmp_result; - - // Determine the maximum possible size of the hidden volume - if (DetermineMaxHiddenVolSize (hwndDlg) < 1) - { - NormalCursor (); - goto ovf_end; - } - - /* Maximum possible size of the hidden volume successfully determined */ - - // Dismount the hidden volume host - while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) - { - if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL) != IDRETRY) - { - // Cancel - NormalCursor (); - goto ovf_end; - } - } - - // Prevent having to recreate the outer volume due to inadvertent exit - bConfirmQuit = TRUE; - - hiddenVolHostDriveNo = -1; - - nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE; - - // Clear the outer volume password - WipePasswordsAndKeyfiles (); - - EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); - NormalCursor (); - - } - break; - } - break; - } - } - } - } - - else if (nCurPageNo == DEVICE_WIPE_PAGE) - { - if (AskWarnOkCancel (bHiddenOS && IsHiddenOSRunning() ? "CONFIRM_WIPE_START_DECOY_SYS_PARTITION" : "CONFIRM_WIPE_START") == IDOK) - { - WipeStart (); - ArrowWaitCursor(); - } - return 1; - } - - LoadPage (hwndDlg, nNewPageNo + 1); -ovf_end: - return 1; - } - else if (lw == IDC_PREV) - { - if (nCurPageNo == SYSENC_SPAN_PAGE) - { - // Skip irrelevant pages when going back - if (!bHiddenOS) - nNewPageNo = SYSENC_TYPE_PAGE + 1; - } - if (nCurPageNo == SYSENC_MULTI_BOOT_MODE_PAGE) - { - // Skip the drive analysis page(s) or other irrelevant pages when going back - if (bHiddenOS) - nNewPageNo = SYSENC_HIDDEN_OS_REQ_CHECK_PAGE + 1; - else if (bWholeSysDrive) - nNewPageNo = SYSENC_PRE_DRIVE_ANALYSIS_PAGE + 1; - else - nNewPageNo = SYSENC_SPAN_PAGE + 1; - } - else if (nCurPageNo == SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE) - { - if (SysEncMultiBootCfg.NumberOfSysDrives == 1) - { - // We can skip SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE (it is implied that there are multiple systems on the drive) - nNewPageNo = SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE + 1; - } - } - else if (nCurPageNo == HIDDEN_VOL_HOST_PRE_CIPHER_PAGE) - { - if (bHiddenOS) - { - if (!ChangeWizardMode (WIZARD_MODE_SYS_DEVICE)) - { - NormalCursor (); - return 1; - } - - nNewPageNo = (nMultiBoot <= 1 ? SYSENC_MULTI_BOOT_MODE_PAGE + 1 : SYSENC_MULTI_BOOT_OUTCOME_PAGE + 1); // Skip irrelevant pages - } - else - { - nNewPageNo = VOLUME_LOCATION_PAGE + 1; - } - } - else if (nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) - { - if (IsButtonChecked (GetDlgItem (hCurPage, IDC_HIDVOL_WIZ_MODE_DIRECT))) - bHiddenVolDirect = TRUE; - else - bHiddenVolDirect = FALSE; - } - else if (nCurPageNo == VOLUME_TYPE_PAGE) - { - if (WizardMode != WIZARD_MODE_SYS_DEVICE) - nNewPageNo = INTRO_PAGE + 1; // Skip irrelevant pages - } - else if (nCurPageNo == VOLUME_LOCATION_PAGE) - { - BOOL tmpbDevice; - - GetWindowText (GetDlgItem (hCurPage, IDC_COMBO_BOX), szFileName, sizeof (szFileName)); - CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); - - if (tmpbDevice == bDevice) - { - MoveEditToCombo (GetDlgItem (hCurPage, IDC_COMBO_BOX), bHistory); - SaveSettings (hCurPage); - } - - if (!bHiddenVol) - nNewPageNo = VOLUME_TYPE_PAGE + 1; // Skip the hidden volume creation wizard mode selection - } - - else if (nCurPageNo == HIDDEN_VOL_HOST_PRE_CIPHER_PAGE) - { - nNewPageNo = VOLUME_LOCATION_PAGE + 1; - } - - else if (nCurPageNo == CIPHER_PAGE) - { - LPARAM nIndex; - nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); - nVolumeEA = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); - - nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETCURSEL, 0, 0); - hash_algo = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETITEMDATA, nIndex, 0); - - RandSetHashFunction (hash_algo); - - if (WizardMode == WIZARD_MODE_SYS_DEVICE) - { - if (nMultiBoot > 1) - nNewPageNo = SYSENC_MULTI_BOOT_OUTCOME_PAGE + 1; // Skip irrelevant pages - else - nNewPageNo = SYSENC_MULTI_BOOT_MODE_PAGE + 1; // Skip irrelevant pages - } - else if (!bHiddenVol) - nNewPageNo = (bDevice ? DEVICE_TRANSFORM_MODE_PAGE : VOLUME_LOCATION_PAGE) + 1; - else if (bHiddenVolHost) - nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE + 1; // Skip the info on the hidden volume - } - - else if (nCurPageNo == SIZE_PAGE) - { - VerifySizeAndUpdate (hCurPage, TRUE); - } - - else if (nCurPageNo == FILESYS_PAGE) - { - if (nNeedToStoreFilesOver4GB != Get2RadButtonPageAnswer()) - fileSystem = FILESYS_NONE; // The user may have gone back and changed the answer, so default file system must be reselected - - nNeedToStoreFilesOver4GB = Get2RadButtonPageAnswer(); - } - - else if (nCurPageNo == PASSWORD_PAGE) - { - // Store the password in case we need to restore it after keyfile is applied to it - GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD), szRawPassword, sizeof (szRawPassword)); - - VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (MainDlg, IDC_NEXT), - GetDlgItem (hCurPage, IDC_PASSWORD), - GetDlgItem (hCurPage, IDC_VERIFY), - volumePassword.Text, - szVerify, - KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect ()); - - volumePassword.Length = strlen ((char *) volumePassword.Text); - - nNewPageNo = SIZE_PAGE + 1; // Skip the hidden volume host password page - - if (SysEncInEffect ()) - { - nNewPageNo = CIPHER_PAGE + 1; // Skip irrelevant pages - - KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); - - if (bKeyboardLayoutChanged) - { - // Restore the original keyboard layout - if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) - Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); - else - bKeyboardLayoutChanged = FALSE; - } - } - else if (bInPlaceEncNonSys) - nNewPageNo = CIPHER_PAGE + 1; - } - - else if (nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) - { - // Store the password in case we need to restore it after keyfile is applied to it - GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), szRawPassword, sizeof (szRawPassword)); - - GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), (char *) volumePassword.Text, sizeof (volumePassword.Text)); - volumePassword.Length = strlen ((char *) volumePassword.Text); - - if (!bInPlaceEncNonSys) - nNewPageNo = VOLUME_LOCATION_PAGE + 1; - } - - else if (nCurPageNo == SYSENC_COLLECTING_RANDOM_DATA_PAGE - || nCurPageNo == NONSYS_INPLACE_ENC_RAND_DATA_PAGE) - { - char tmp[RANDPOOL_DISPLAY_SIZE+1]; - - KillTimer (hwndDlg, TIMER_ID_RANDVIEW); - - // Attempt to wipe the GUI field showing portions of randpool - memset (tmp, 'X', sizeof(tmp)); - tmp [sizeof(tmp)-1] = 0; - SetWindowText (hRandPoolSys, tmp); - - nNewPageNo = PASSWORD_PAGE + 1; // Skip irrelevant pages - } - - else if (nCurPageNo == SYSENC_KEYS_GEN_PAGE) - { - char tmp[KEY_GUI_VIEW_SIZE+1]; - - // Attempt to wipe the GUI fields showing portions of the master and header keys - memset (tmp, 'X', sizeof(tmp)); - tmp [sizeof(tmp)-1] = 0; - SetWindowText (hMasterKey, tmp); - SetWindowText (hHeaderKey, tmp); - } - - else if (nCurPageNo == SYSENC_WIPE_MODE_PAGE) - { - if (bDontVerifyRescueDisk) - nNewPageNo = SYSENC_RESCUE_DISK_VERIFIED_PAGE; // Skip irrelevant pages - } - - else if (nCurPageNo == FORMAT_PAGE) - { - char tmp[RNG_POOL_SIZE*2+1]; - - KillTimer (hwndDlg, TIMER_ID_RANDVIEW); - - // Attempt to wipe the GUI fields showing portions of randpool, of the master and header keys - memset (tmp, 'X', sizeof(tmp)); - tmp [sizeof(tmp)-1] = 0; - SetWindowText (hRandPool, tmp); - SetWindowText (hMasterKey, tmp); - SetWindowText (hHeaderKey, tmp); - - if (WizardMode != WIZARD_MODE_SYS_DEVICE) - { - // Skip irrelevant pages - - if (FileSize4GBLimitQuestionNeeded () - && !CreatingHiddenSysVol() // If we're creating a hidden volume for a hidden OS, we don't need to format it with any filesystem (the entire OS will be copied to the hidden volume sector by sector). - && !bInPlaceEncNonSys) - { - nNewPageNo = FILESYS_PAGE + 1; - } - else - nNewPageNo = PASSWORD_PAGE + 1; - } - } - - LoadPage (hwndDlg, nNewPageNo - 1); - - return 1; - } - - return 0; - - case WM_ENDSESSION: - EndMainDlg (MainDlg); - localcleanup (); - return 0; - - case WM_CLOSE: - PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); - return 1; - } - - return 0; -} - -void ExtractCommandLine (HWND hwndDlg, char *lpszCommandLine) -{ - char **lpszCommandLineArgs; /* Array of command line arguments */ - int nNoCommandLineArgs; /* The number of arguments in the array */ - - if (_stricmp (lpszCommandLine, "-Embedding") == 0) - { - ComServerMode = TRUE; - return; - } - - /* Extract command line arguments */ - nNoCommandLineArgs = Win32CommandLine (lpszCommandLine, &lpszCommandLineArgs); - if (nNoCommandLineArgs > 0) - { - int i; - - for (i = 0; i < nNoCommandLineArgs; i++) - { - enum - { - OptionHistory, - OptionNoIsoCheck, - OptionQuit, - OptionTokenLib, - CommandResumeSysEncLogOn, - CommandResumeSysEnc, - CommandDecryptSysEnc, - CommandEncDev, - CommandHiddenSys, - CommandResumeInplaceLogOn, - CommandResumeHiddenSys, - CommandSysEnc, - CommandResumeInplace, - }; - - argument args[]= - { - { OptionHistory, "/history", "/h", FALSE }, - { OptionNoIsoCheck, "/noisocheck", "/n", FALSE }, - { OptionQuit, "/quit", "/q", FALSE }, - { OptionTokenLib, "/tokenlib", NULL, FALSE }, - - { CommandResumeSysEncLogOn, "/acsysenc", "/a", TRUE }, - { CommandResumeSysEnc, "/csysenc", "/c", TRUE }, - { CommandDecryptSysEnc, "/dsysenc", "/d", TRUE }, - { CommandEncDev, "/encdev", "/e", TRUE }, - { CommandHiddenSys, "/isysenc", "/i", TRUE }, - { CommandResumeInplaceLogOn, "/prinplace", "/p", TRUE }, - { CommandResumeHiddenSys, "/risysenc", "/r", TRUE }, - { CommandSysEnc, "/sysenc", "/s", TRUE }, - { CommandResumeInplace, "/zinplace", "/z", TRUE } - }; - - argumentspec as; - - int nArgPos; - int x; - - if (lpszCommandLineArgs[i] == NULL) - continue; - - as.args = args; - as.arg_cnt = sizeof(args)/ sizeof(args[0]); - - x = GetArgumentID (&as, lpszCommandLineArgs[i], &nArgPos); - - switch (x) - { - case CommandSysEnc: - // Encrypt system partition/drive (passed by Mount if system encryption hasn't started or to reverse decryption) - - // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption - if (CreateSysEncMutex ()) - { - bDirectSysEncMode = TRUE; - bDirectSysEncModeCommand = SYSENC_COMMAND_ENCRYPT; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - } - else - { - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - exit(0); - } - - break; - - case CommandDecryptSysEnc: - // Decrypt system partition/drive (passed by Mount, also to reverse encryption in progress, when paused) - - // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption - if (CreateSysEncMutex ()) - { - bDirectSysEncMode = TRUE; - bDirectSysEncModeCommand = SYSENC_COMMAND_DECRYPT; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - } - else - { - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - exit(0); - } - break; - - case CommandHiddenSys: - // Create a hidden operating system (passed by Mount when the user selects System -> Create Hidden Operating System) - - // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption - if (CreateSysEncMutex ()) - { - bDirectSysEncMode = TRUE; - bDirectSysEncModeCommand = SYSENC_COMMAND_CREATE_HIDDEN_OS; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - } - else - { - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - exit(0); - } - - break; - - case CommandResumeHiddenSys: - // Resume process of creation of a hidden operating system (passed by Wizard when the user needs to UAC-elevate the whole wizard process) - - // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption - if (CreateSysEncMutex ()) - { - bDirectSysEncMode = TRUE; - bDirectSysEncModeCommand = SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - } - else - { - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - exit(0); - } - - break; - - case CommandResumeSysEnc: - // Resume previous system-encryption operation (passed by Mount) e.g. encryption, decryption, or pretest - - // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption - if (CreateSysEncMutex ()) - { - bDirectSysEncMode = TRUE; - bDirectSysEncModeCommand = SYSENC_COMMAND_RESUME; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - } - else - { - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - exit(0); - } - break; - - case CommandResumeSysEncLogOn: - // Same as csysenc but passed only by the system (from the startup sequence) - - // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption - if (CreateSysEncMutex ()) - { - bDirectSysEncMode = TRUE; - bDirectSysEncModeCommand = SYSENC_COMMAND_STARTUP_SEQ_RESUME; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - } - else - { - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - exit(0); - } - break; - - case CommandEncDev: - // Resume process of creation of a non-sys-device-hosted volume (passed by Wizard when the user needs to UAC-elevate) - DirectDeviceEncMode = TRUE; - break; - - case CommandResumeInplace: - // Resume interrupted process of non-system in-place encryption of a partition - DirectNonSysInplaceEncResumeMode = TRUE; - break; - - case CommandResumeInplaceLogOn: - // Ask the user whether to resume interrupted process of non-system in-place encryption of a partition - // This switch is passed only by the system (from the startup sequence). - DirectPromptNonSysInplaceEncResumeMode = TRUE; - break; - - case OptionNoIsoCheck: - bDontVerifyRescueDisk = TRUE; - break; - - case OptionHistory: - { - char szTmp[8]; - GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, - szTmp, sizeof (szTmp)); - if (!_stricmp(szTmp,"y") || !_stricmp(szTmp,"yes")) - { - bHistory = TRUE; - bHistoryCmdLine = TRUE; - } - - if (!_stricmp(szTmp,"n") || !_stricmp(szTmp,"no")) - { - bHistory = FALSE; - bHistoryCmdLine = TRUE; - } - } - break; - - case OptionTokenLib: - if (GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath)) == HAS_ARGUMENT) - InitSecurityTokenLibrary(); - else - Error ("COMMAND_LINE_ERROR"); - - break; - - case OptionQuit: - { - // Used to indicate non-install elevation - char szTmp[32]; - GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp)); - } - break; - - default: - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_COMMANDHELP_DLG), hwndDlg, (DLGPROC) - CommandHelpDlgProc, (LPARAM) &as); - - exit(0); - } - } - } - - /* Free up the command line arguments */ - while (--nNoCommandLineArgs >= 0) - { - free (lpszCommandLineArgs[nNoCommandLineArgs]); - } -} - - -int DetermineMaxHiddenVolSize (HWND hwndDlg) -{ - __int64 nbrReserveBytes; - - if (nbrFreeClusters * realClusterSize < TC_MIN_HIDDEN_VOLUME_SIZE) - { - MessageBoxW (hwndDlg, GetString ("NO_SPACE_FOR_HIDDEN_VOL"), lpszTitle, ICON_HAND); - UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE); - AbortProcessSilent (); - } - - // Add a reserve (in case the user mounts the outer volume and creates new files - // on it by accident or OS writes some new data behind his or her back, such as - // System Restore etc.) - nbrReserveBytes = GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize) / 200; - if (nbrReserveBytes > BYTES_PER_MB * 10) - nbrReserveBytes = BYTES_PER_MB * 10; - - // Compute the final value - - nMaximumHiddenVolSize = nbrFreeClusters * realClusterSize - TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE - nbrReserveBytes; - nMaximumHiddenVolSize -= nMaximumHiddenVolSize % SECTOR_SIZE; // Must be a multiple of the sector size - - if (nMaximumHiddenVolSize < TC_MIN_HIDDEN_VOLUME_SIZE) - { - MessageBoxW (hwndDlg, GetString ("NO_SPACE_FOR_HIDDEN_VOL"), lpszTitle, ICON_HAND); - UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE); - AbortProcessSilent (); - } - - // Prepare the hidden volume size parameters - if (nMaximumHiddenVolSize < BYTES_PER_MB) - nMultiplier = BYTES_PER_KB; - else if (nMaximumHiddenVolSize < BYTES_PER_GB) - nMultiplier = BYTES_PER_MB; - else - nMultiplier = BYTES_PER_GB; - - nUIVolumeSize = 0; // Set the initial value for the hidden volume size input field to the max - nVolumeSize = nUIVolumeSize * nMultiplier; // Chop off possible remainder - - return 1; -} - - -// Tests whether the file system of the given volume is suitable to host a hidden volume, -// retrieves the cluster size, and scans the volume cluster bitmap. In addition, checks -// the TrueCrypt volume format version and the type of volume. -int AnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *pnbrFreeClusters) -{ - HANDLE hDevice; - DWORD bytesReturned; - DWORD dwSectorsPerCluster, dwBytesPerSector, dwNumberOfFreeClusters, dwTotalNumberOfClusters; - DWORD dwResult; - int result; - char szFileSystemNameBuffer[256]; - char tmpPath[7] = {'\\','\\','.','\\',*driveNo + 'A',':',0}; - char szRootPathName[4] = {*driveNo + 'A', ':', '\\', 0}; - BYTE readBuffer[SECTOR_SIZE*2]; - LARGE_INTEGER offset, offsetNew; - VOLUME_PROPERTIES_STRUCT volProp; - - memset (&volProp, 0, sizeof(volProp)); - volProp.driveNo = *driveNo; - if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &volProp, sizeof (volProp), &volProp, sizeof (volProp), &dwResult, NULL) || dwResult == 0) - { - handleWin32Error (hwndDlg); - Error ("CANT_ACCESS_OUTER_VOL"); - goto efsf_error; - } - - if (volProp.volFormatVersion < TC_VOLUME_FORMAT_VERSION) - { - // We do not support creating hidden volumes within volumes created by TrueCrypt 5.1a or earlier. - Error ("ERR_VOL_FORMAT_BAD"); - return 0; - } - - if (volProp.hiddenVolume) - { - // The user entered a password for a hidden volume - Error ("ERR_HIDDEN_NOT_NORMAL_VOLUME"); - return 0; - } - - if (volProp.volumeHeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC - || volProp.volumeHeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) - { - Warning ("ERR_HIDDEN_VOL_HOST_ENCRYPTED_INPLACE"); - return 0; - } - - hDevice = CreateFile (tmpPath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hDevice == INVALID_HANDLE_VALUE) - { - MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_OUTER_VOL"), lpszTitle, ICON_HAND); - goto efsf_error; - } - - offset.QuadPart = 0; - - if (SetFilePointerEx (hDevice, offset, &offsetNew, FILE_BEGIN) == 0) - { - handleWin32Error (hwndDlg); - goto efs_error; - } - - result = ReadFile(hDevice, &readBuffer, (DWORD) SECTOR_SIZE, &bytesReturned, NULL); - - if (result == 0) - { - handleWin32Error (hwndDlg); - MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_OUTER_VOL"), lpszTitle, ICON_HAND); - goto efs_error; - } - - CloseHandle (hDevice); - hDevice = INVALID_HANDLE_VALUE; - - // Determine file system type - - GetVolumeInformation(szRootPathName, NULL, 0, NULL, NULL, NULL, szFileSystemNameBuffer, sizeof(szFileSystemNameBuffer)); - - // The Windows API sometimes fails to indentify the file system correctly so we're using "raw" analysis too. - if (!strncmp (szFileSystemNameBuffer, "FAT", 3) - || (readBuffer[0x36] == 'F' && readBuffer[0x37] == 'A' && readBuffer[0x38] == 'T') - || (readBuffer[0x52] == 'F' && readBuffer[0x53] == 'A' && readBuffer[0x54] == 'T')) - { - // FAT12/FAT16/FAT32 - - // Retrieve the cluster size - *realClusterSize = ((int) readBuffer[0xb] + ((int) readBuffer[0xc] << 8)) * (int) readBuffer[0xd]; - - // Get the map of the clusters that are free and in use on the outer volume. - // The map will be scanned to determine the size of the uninterrupted block of free - // space (provided there is any) whose end is aligned with the end of the volume. - // The value will then be used to determine the maximum possible size of the hidden volume. - - return ScanVolClusterBitmap (hwndDlg, - driveNo, - hiddenVolHostSize / *realClusterSize, - pnbrFreeClusters); - } - else if (!strncmp (szFileSystemNameBuffer, "NTFS", 4)) - { - // NTFS - - if (nCurrentOS == WIN_2000) - { - Error("HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS_WIN2000"); - return 0; - } - - if (bHiddenVolDirect && GetVolumeDataAreaSize (FALSE, hiddenVolHostSize) <= TC_MAX_FAT_FS_SIZE) - Info ("HIDDEN_VOL_HOST_NTFS"); - - if (!GetDiskFreeSpace(szRootPathName, - &dwSectorsPerCluster, - &dwBytesPerSector, - &dwNumberOfFreeClusters, - &dwTotalNumberOfClusters)) - { - handleWin32Error (hwndDlg); - Error ("CANT_GET_OUTER_VOL_INFO"); - return -1; - }; - - *realClusterSize = dwBytesPerSector * dwSectorsPerCluster; - - // Get the map of the clusters that are free and in use on the outer volume. - // The map will be scanned to determine the size of the uninterrupted block of free - // space (provided there is any) whose end is aligned with the end of the volume. - // The value will then be used to determine the maximum possible size of the hidden volume. - - return ScanVolClusterBitmap (hwndDlg, - driveNo, - hiddenVolHostSize / *realClusterSize, - pnbrFreeClusters); - } - else - { - // Unsupported file system - - Error ((nCurrentOS == WIN_2000) ? "HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS_WIN2000" : "HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS"); - return 0; - } - -efs_error: - CloseHandle (hDevice); - -efsf_error: - CloseVolumeExplorerWindows (hwndDlg, *driveNo); - - return -1; -} - - -// Mounts a volume within which the user intends to create a hidden volume -int MountHiddenVolHost (HWND hwndDlg, char *volumePath, int *driveNo, Password *password, BOOL bReadOnly) -{ - MountOptions mountOptions; - ZeroMemory (&mountOptions, sizeof (mountOptions)); - - *driveNo = GetLastAvailableDrive (); - - if (*driveNo == -1) - { - *driveNo = -2; - return ERR_NO_FREE_DRIVES; - } - - mountOptions.ReadOnly = bReadOnly; - mountOptions.Removable = ConfigReadInt ("MountVolumesRemovable", FALSE); - mountOptions.ProtectHiddenVolume = FALSE; - mountOptions.PreserveTimestamp = bPreserveTimestamp; - mountOptions.PartitionInInactiveSysEncScope = FALSE; - mountOptions.UseBackupHeader = FALSE; - - if (MountVolume (hwndDlg, *driveNo, volumePath, password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1) - { - *driveNo = -3; - return ERR_VOL_MOUNT_FAILED; - } - return 0; -} - - -/* Gets the map of the clusters that are free and in use on a volume that is to host - a hidden volume. The map is scanned to determine the size of the uninterrupted - area of free space (provided there is any) whose end is aligned with the end - of the volume. The value will then be used to determine the maximum possible size - of the hidden volume. */ -int ScanVolClusterBitmap (HWND hwndDlg, int *driveNo, __int64 nbrClusters, __int64 *nbrFreeClusters) -{ - PVOLUME_BITMAP_BUFFER lpOutBuffer; - STARTING_LCN_INPUT_BUFFER lpInBuffer; - - HANDLE hDevice; - DWORD lBytesReturned; - BYTE rmnd; - char tmpPath[7] = {'\\','\\','.','\\', *driveNo + 'A', ':', 0}; - - DWORD bufLen; - __int64 bitmapCnt; - - hDevice = CreateFile (tmpPath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hDevice == INVALID_HANDLE_VALUE) - { - MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_OUTER_VOL"), lpszTitle, ICON_HAND); - goto vcmf_error; - } - - bufLen = (DWORD) (nbrClusters / 8 + 2 * sizeof(LARGE_INTEGER)); - bufLen += 100000 + bufLen/10; // Add reserve - - lpOutBuffer = (PVOLUME_BITMAP_BUFFER) malloc (bufLen); - - if (lpOutBuffer == NULL) - { - MessageBoxW (hwndDlg, GetString ("ERR_MEM_ALLOC"), lpszTitle, ICON_HAND); - goto vcmf_error; - } - - lpInBuffer.StartingLcn.QuadPart = 0; - - if ( !DeviceIoControl (hDevice, - FSCTL_GET_VOLUME_BITMAP, - &lpInBuffer, - sizeof(lpInBuffer), - lpOutBuffer, - bufLen, - &lBytesReturned, - NULL)) - { - handleWin32Error (hwndDlg); - MessageBoxW (hwndDlg, GetString ("CANT_GET_CLUSTER_BITMAP"), lpszTitle, ICON_HAND); - - goto vcm_error; - } - - rmnd = (BYTE) (lpOutBuffer->BitmapSize.QuadPart % 8); - - if ((rmnd != 0) - && ((lpOutBuffer->Buffer[lpOutBuffer->BitmapSize.QuadPart / 8] & ((1 << rmnd)-1) ) != 0)) - { - *nbrFreeClusters = 0; - } - else - { - *nbrFreeClusters = lpOutBuffer->BitmapSize.QuadPart; - bitmapCnt = lpOutBuffer->BitmapSize.QuadPart / 8; - - // Scan the bitmap from the end - while (--bitmapCnt >= 0) - { - if (lpOutBuffer->Buffer[bitmapCnt] != 0) - { - // There might be up to 7 extra free clusters in this byte of the bitmap. - // These are ignored because there is always a cluster reserve added anyway. - *nbrFreeClusters = lpOutBuffer->BitmapSize.QuadPart - ((bitmapCnt + 1) * 8); - break; - } - } - } - - CloseHandle (hDevice); - free(lpOutBuffer); - return 1; - -vcm_error: - CloseHandle (hDevice); - free(lpOutBuffer); - -vcmf_error: - return -1; -} - - -// Wipe the hidden OS config flag bits in the MBR -static BOOL WipeHiddenOSCreationConfig (void) -{ - if (!IsHiddenOSRunning()) - { - try - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - BootEncObj->WipeHiddenOSCreationConfig(); - } - catch (Exception &e) - { - e.Show (MainDlg); - return FALSE; - } - } - - return TRUE; -} - - -// Tasks that need to be performed after the WM_INITDIALOG message for the SYSENC_ENCRYPTION_PAGE dialog is -// handled should be done here (otherwise the UAC prompt causes the GUI to be only half-rendered). -static void AfterSysEncProgressWMInitTasks (HWND hwndDlg) -{ - try - { - switch (SystemEncryptionStatus) - { - case SYSENC_STATUS_ENCRYPTING: - - if (BootEncStatus.ConfiguredEncryptedAreaStart == BootEncStatus.EncryptedAreaStart - && BootEncStatus.ConfiguredEncryptedAreaEnd == BootEncStatus.EncryptedAreaEnd) - { - // The partition/drive had been fully encrypted - - ManageStartupSeqWiz (TRUE, ""); - WipeHiddenOSCreationConfig(); // For extra conservative security - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - - Info ("SYSTEM_ENCRYPTION_FINISHED"); - EndMainDlg (MainDlg); - return; - } - else - { - SysEncResume (); - } - - break; - - case SYSENC_STATUS_DECRYPTING: - SysEncResume (); - break; - - default: - - // Unexpected mode here -- fix the inconsistency - - ManageStartupSeqWiz (TRUE, ""); - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - EndMainDlg (MainDlg); - InconsistencyResolved (SRC_POS); - return; - } - } - catch (Exception &e) - { - e.Show (hwndDlg); - EndMainDlg (MainDlg); - return; - } - - InitSysEncProgressBar (); - - UpdateSysEncProgressBar (); - - UpdateSysEncControls (); -} - - -// Tasks that need to be performed after the WM_INITDIALOG message is handled must be done here. -// For example, any tasks that may invoke the UAC prompt (otherwise the UAC dialog box would not be on top). -static void AfterWMInitTasks (HWND hwndDlg) -{ - // Note that if bDirectSysEncModeCommand is not SYSENC_COMMAND_NONE, we already have the mutex. - - // SYSENC_COMMAND_DECRYPT has the highest priority because it also performs uninstallation (restores the - // original contents of the first drive cylinder, etc.) so it must be attempted regardless of the phase - // or content of configuration files. - if (bDirectSysEncModeCommand == SYSENC_COMMAND_DECRYPT) - { - if (IsHiddenOSRunning()) - { - Warning ("CANNOT_DECRYPT_HIDDEN_OS"); - AbortProcessSilent(); - } - - // Add the wizard to the system startup sequence - ManageStartupSeqWiz (FALSE, "/acsysenc"); - - ChangeSystemEncryptionStatus (SYSENC_STATUS_DECRYPTING); - LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); - return; - } - - - if (SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING - || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING) - { - try - { - BootEncStatus = BootEncObj->GetStatus(); - - if (!BootEncStatus.DriveMounted) - { - if (!BootEncStatus.DeviceFilterActive) - { - // This is an inconsistent state. SystemEncryptionStatus should never be SYSENC_STATUS_ENCRYPTING - // or SYSENC_STATUS_DECRYPTING when the drive filter is not active. Possible causes: 1) corrupted - // or stale config file, 2) corrupted system - - // Fix the inconsistency - ManageStartupSeqWiz (TRUE, ""); - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - EndMainDlg (MainDlg); - InconsistencyResolved (SRC_POS); - return; - } - else if (bDirectSysEncMode) - { - // This is an inconsistent state. We have a direct system encryption command, - // SystemEncryptionStatus is SYSENC_STATUS_ENCRYPTING or SYSENC_STATUS_DECRYPTING, the - // system drive is not 'mounted' and drive filter is active. Possible causes: 1) The drive had - // been decrypted in the pre-boot environment. 2) The OS is not located on the lowest partition, - // the drive is to be fully encrypted, but the user rebooted before encryption reached the - // system partition and then pressed Esc in the boot loader screen. 3) Corrupted or stale config - // file. 4) Damaged system. - - Warning ("SYSTEM_ENCRYPTION_SCHEDULED_BUT_PBA_FAILED"); - EndMainDlg (MainDlg); - return; - } - } - } - catch (Exception &e) - { - e.Show (MainDlg); - } - } - - - if (SystemEncryptionStatus != SYSENC_STATUS_PRETEST) - { - // Handle system encryption command line arguments (if we're not in the Pretest phase). - // Note that if bDirectSysEncModeCommand is not SYSENC_COMMAND_NONE, we already have the mutex. - // Also note that SYSENC_COMMAND_DECRYPT is handled above. - - switch (bDirectSysEncModeCommand) - { - case SYSENC_COMMAND_RESUME: - case SYSENC_COMMAND_STARTUP_SEQ_RESUME: - - if (bDirectSysEncModeCommand == SYSENC_COMMAND_STARTUP_SEQ_RESUME - && AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDNO) - { - EndMainDlg (MainDlg); - return; - } - - if (SysEncryptionOrDecryptionRequired ()) - { - if (SystemEncryptionStatus != SYSENC_STATUS_ENCRYPTING - && SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) - { - // If the config file with status was lost or not written correctly, we - // don't know whether to encrypt or decrypt (but we know that encryption or - // decryption is required). Ask the user to select encryption, decryption, - // or cancel - if (!ResolveUnknownSysEncDirection ()) - { - EndMainDlg (MainDlg); - return; - } - } - - LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); - return; - } - else - { - // Nothing to resume - Warning ("NOTHING_TO_RESUME"); - EndMainDlg (MainDlg); - - return; - } - break; - - case SYSENC_COMMAND_ENCRYPT: - - if (SysDriveOrPartitionFullyEncrypted (FALSE)) - { - Info ("SYS_PARTITION_OR_DRIVE_APPEARS_FULLY_ENCRYPTED"); - EndMainDlg (MainDlg); - return; - } - - if (SysEncryptionOrDecryptionRequired ()) - { - // System partition/drive encryption process already initiated but is incomplete. - // If we were encrypting, resume the process directly. If we were decrypting, reverse - // the process and start encrypting. - - ChangeSystemEncryptionStatus (SYSENC_STATUS_ENCRYPTING); - LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); - return; - } - else - { - // Initiate the Pretest preparation phase - if (!SwitchWizardToSysEncMode ()) - { - bDirectSysEncMode = FALSE; - EndMainDlg (MainDlg); - } - return; - } - - break; - - case SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV: - case SYSENC_COMMAND_CREATE_HIDDEN_OS: - - if (!SwitchWizardToHiddenOSMode ()) - { - bDirectSysEncMode = FALSE; - EndMainDlg (MainDlg); - } - return; - } - } - - - if (!bDirectSysEncMode - || bDirectSysEncMode && SystemEncryptionStatus == SYSENC_STATUS_NONE) - { - // Handle system encryption cases where the wizard did not start even though it - // was added to the startup sequence, as well as other weird cases and "leftovers" - - if (SystemEncryptionStatus != SYSENC_STATUS_NONE - && SystemEncryptionStatus != SYSENC_STATUS_PRETEST - && SysEncryptionOrDecryptionRequired ()) - { - // System encryption/decryption had been in progress and did not finish - - if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption - { - if (AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) - { - bDirectSysEncMode = TRUE; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); - return; - } - else - CloseSysEncMutex (); - } - } - - else if (SystemEncryptionStatus == SYSENC_STATUS_PRETEST) - { - // System pretest had been in progress but we were not launched during the startup seq - - if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption - { - // The pretest has "priority handling" - bDirectSysEncMode = TRUE; - ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); - - /* Do not return yet -- the principal pretest handler is below. */ - } - } - - else if ((SystemEncryptionStatus == SYSENC_STATUS_NONE || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING) - && !BootEncStatus.DriveEncrypted - && (BootEncStatus.DriveMounted || BootEncStatus.VolumeHeaderPresent)) - { - // The pretest may have been in progress but we can't be sure (it is not in the config file). - // Another possibility is that the user had finished decrypting the drive, but the config file - // was not correctly updated. In both cases the best thing we can do is remove the header and - // deinstall. Otherwise, the result might be some kind of deadlock. - - if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption - { - WaitCursor (); - - ForceRemoveSysEnc(); - - InconsistencyResolved (SRC_POS); - - NormalCursor(); - CloseSysEncMutex (); - } - } - } - - if (bDirectSysEncMode && CreateSysEncMutex ()) - { - // We were launched either by Mount or by the system (startup sequence). Most of such cases should have - // been handled above already. Here we handle only the pretest phase (which can also be a hidden OS - // creation phase actually) and possible inconsistencies. - - switch (SystemEncryptionStatus) - { - case SYSENC_STATUS_PRETEST: - { - unsigned int hiddenOSCreationPhase = DetermineHiddenOSCreationPhase(); - - bHiddenOS = (hiddenOSCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE); - - // Evaluate the results of the system encryption pretest (or of the hidden OS creation process) - - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (hwndDlg); - Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); - EndMainDlg (MainDlg); - return; - } - - if (BootEncStatus.DriveMounted) - { - /* Pretest successful or hidden OS has been booted during the process of hidden OS creation. */ - - switch (hiddenOSCreationPhase) - { - case TC_HIDDEN_OS_CREATION_PHASE_NONE: - - // Pretest successful (or the hidden OS has been booted for the first time since the user started installing a new decoy OS) - - if (IsHiddenOSRunning()) - { - // The hidden OS has been booted for the first time since the user started installing a - // new decoy OS (presumably, our MBR config flags have been erased). - - // As for things we are responsible for, the process of hidden OS creation is completed - // (the rest is up to the user). - - ManageStartupSeqWiz (TRUE, ""); - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - - EndMainDlg (MainDlg); - - return; - } - - // Pretest successful (no hidden operating system involved) - - LoadPage (hwndDlg, SYSENC_PRETEST_RESULT_PAGE); - return; - - case TC_HIDDEN_OS_CREATION_PHASE_WIPING: - - // Hidden OS has been booted when we are supposed to wipe the original OS - - LoadPage (hwndDlg, SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE); - return; - - case TC_HIDDEN_OS_CREATION_PHASE_WIPED: - - // Hidden OS has been booted and the original OS wiped. Now the user is required to install a new, decoy, OS. - - TextInfoDialogBox (TC_TBXID_DECOY_OS_INSTRUCTIONS); - - EndMainDlg (MainDlg); - return; - - default: - - // Unexpected/unknown status - ReportUnexpectedState (SRC_POS); - EndMainDlg (MainDlg); - return; - } - } - else - { - BOOL bAnswerTerminate = FALSE, bAnswerRetry = FALSE; - - /* Pretest failed - or hidden OS cloning has been interrupted (and non-hidden OS is running) - or wiping of the original OS has not been started (and non-hidden OS is running) */ - - if (hiddenOSCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_NONE) - { - // Pretest failed (no hidden operating system involved) - - if (AskWarnYesNo ("BOOT_PRETEST_FAILED_RETRY") == IDYES) - { - // User wants to retry the pretest - bAnswerTerminate = FALSE; - bAnswerRetry = TRUE; - } - else - { - // User doesn't want to retry the pretest - bAnswerTerminate = TRUE; - bAnswerRetry = FALSE; - } - } - else - { - // Hidden OS cloning was interrupted or wiping of the original OS has not been started - - char *tmpStr[] = {0, - hiddenOSCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_WIPING ? "OS_WIPING_NOT_FINISHED_ASK" : "HIDDEN_OS_CREATION_NOT_FINISHED_ASK", - "HIDDEN_OS_CREATION_NOT_FINISHED_CHOICE_RETRY", - "HIDDEN_OS_CREATION_NOT_FINISHED_CHOICE_TERMINATE", - "HIDDEN_OS_CREATION_NOT_FINISHED_CHOICE_ASK_LATER", - 0}; - - switch (AskMultiChoice ((void **) tmpStr, FALSE)) - { - case 1: - // User wants to restart and continue/retry - bAnswerTerminate = FALSE; - bAnswerRetry = TRUE; - break; - - case 2: - // User doesn't want to retry but wants to terminate the entire process of hidden OS creation - bAnswerTerminate = TRUE; - bAnswerRetry = FALSE; - break; - - default: - // User doesn't want to do anything now - bAnswerTerminate = FALSE; - bAnswerRetry = FALSE; - } - } - - - if (bAnswerRetry) - { - // User wants to restart and retry the pretest (or hidden OS creation) - - // We re-register the driver for boot because the user may have selected - // "Last Known Good Configuration" from the Windows boot menu. - // Note that we need to do this even when creating a hidden OS (because - // the hidden OS needs our boot driver and it will be a clone of this OS). - try - { - BootEncObj->RegisterBootDriver (bHiddenOS ? true : false); - } - catch (Exception &e) - { - e.Show (NULL); - } - - if (AskWarnYesNo ("CONFIRM_RESTART") == IDYES) - { - EndMainDlg (MainDlg); - - try - { - BootEncObj->RestartComputer (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - return; - } - - EndMainDlg (MainDlg); - return; - } - else if (bAnswerTerminate) - { - // User doesn't want to retry pretest (or OS cloning), but to terminate the entire process - - try - { - BootEncObj->Deinstall (); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - ManageStartupSeqWiz (TRUE, ""); - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - EndMainDlg (MainDlg); - return; - } - else - { - // User doesn't want to take any action now - - AbortProcessSilent(); - } - } - } - break; - - default: - - // Unexpected progress status -- fix the inconsistency - - ManageStartupSeqWiz (TRUE, ""); - ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); - EndMainDlg (MainDlg); - InconsistencyResolved (SRC_POS); - return; - } - } - else - { - if (DirectDeviceEncMode) - { - SwitchWizardToNonSysDeviceMode(); - return; - } - - if (DirectPromptNonSysInplaceEncResumeMode - && !bInPlaceEncNonSysPending) - { - // This instance of the wizard has been launched via the system startup sequence to prompt for resume of - // a non-system in-place encryption process. However, no config file indicates that any such process - // has been interrupted. This inconsistency may occur, for example, when the process is finished - // but the wizard is not removed from the startup sequence because system encryption is in progress. - // Therefore, we remove it from the startup sequence now if possible. - - if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE) - ManageStartupSeqWiz (TRUE, ""); - - AbortProcessSilent (); - } - - if (DirectNonSysInplaceEncResumeMode) - { - SwitchWizardToNonSysInplaceEncResumeMode(); - return; - } - else if (DirectPromptNonSysInplaceEncResumeMode) - { - if (NonSysInplaceEncInProgressElsewhere ()) - AbortProcessSilent (); - - if (AskNonSysInPlaceEncryptionResume() == IDYES) - SwitchWizardToNonSysInplaceEncResumeMode(); - else - AbortProcessSilent (); - - return; - } - else if (bInPlaceEncNonSysPending - && !NonSysInplaceEncInProgressElsewhere () - && AskNonSysInPlaceEncryptionResume() == IDYES) - { - SwitchWizardToNonSysInplaceEncResumeMode(); - return; - } - - LoadPage (hwndDlg, INTRO_PAGE); - } -} - -int WINAPI WINMAIN (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCommandLine, int nCmdShow) -{ - int status; - atexit (localcleanup); - - VirtualLock (&volumePassword, sizeof(volumePassword)); - VirtualLock (szVerify, sizeof(szVerify)); - VirtualLock (szRawPassword, sizeof(szRawPassword)); - - VirtualLock (MasterKeyGUIView, sizeof(MasterKeyGUIView)); - VirtualLock (HeaderKeyGUIView, sizeof(HeaderKeyGUIView)); - - VirtualLock (randPool, sizeof(randPool)); - VirtualLock (lastRandPool, sizeof(lastRandPool)); - VirtualLock (outRandPoolDispBuffer, sizeof(outRandPoolDispBuffer)); - - VirtualLock (&szFileName, sizeof(szFileName)); - VirtualLock (&szDiskFile, sizeof(szDiskFile)); - - try - { - BootEncObj = new BootEncryption (NULL); - } - catch (Exception &e) - { - e.Show (NULL); - } - - if (BootEncObj == NULL) - AbortProcess ("INIT_SYS_ENC"); - - InitCommonControls (); - InitApp (hInstance, lpszCommandLine); - - nPbar = IDC_PROGRESS_BAR; - - if (Randinit ()) - AbortProcess ("INIT_RAND"); - - RegisterRedTick(hInstance); - - /* Allocate, dup, then store away the application title */ - lpszTitle = GetString ("IDD_VOL_CREATION_WIZARD_DLG"); - - status = DriverAttach (); - if (status != 0) - { - if (status == ERR_OS_ERROR) - handleWin32Error (NULL); - else - handleError (NULL, status); - - AbortProcess ("NODRIVER"); - } - - if (!AutoTestAlgorithms()) - AbortProcess ("ERR_SELF_TESTS_FAILED"); - - /* Create the main dialog box */ - DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_VOL_CREATION_WIZARD_DLG), NULL, (DLGPROC) MainDialogProc, - (LPARAM)lpszCommandLine); - - return 0; -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "Crypto.h" +#include "Apidrvr.h" +#include "Dlgcode.h" +#include "Language.h" +#include "Combo.h" +#include "Registry.h" +#include "Boot/Windows/BootDefs.h" +#include "Common/Common.h" +#include "Common/BootEncryption.h" +#include "Common/Dictionary.h" +#include "Common/Endian.h" +#include "Common/resource.h" +#include "Platform/Finally.h" +#include "Platform/ForEach.h" +#include "Random.h" +#include "Fat.h" +#include "InPlace.h" +#include "Resource.h" +#include "TcFormat.h" +#include "Format.h" +#include "FormatCom.h" +#include "Password.h" +#include "Progress.h" +#include "Tests.h" +#include "Cmdline.h" +#include "Volumes.h" +#include "Wipe.h" +#include "Xml.h" + +using namespace TrueCrypt; + +enum wizard_pages +{ + /* IMPORTANT: IF YOU ADD/REMOVE/MOVE ANY PAGES THAT ARE RELATED TO SYSTEM ENCRYPTION, + REVISE THE 'DECOY_OS_INSTRUCTIONS_PORTION_??' STRINGS! */ + + INTRO_PAGE, + SYSENC_TYPE_PAGE, + SYSENC_HIDDEN_OS_REQ_CHECK_PAGE, + SYSENC_SPAN_PAGE, + SYSENC_PRE_DRIVE_ANALYSIS_PAGE, + SYSENC_DRIVE_ANALYSIS_PAGE, + SYSENC_MULTI_BOOT_MODE_PAGE, + SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE, + SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE, + SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE, + SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE, + SYSENC_MULTI_BOOT_OUTCOME_PAGE, + VOLUME_TYPE_PAGE, + HIDDEN_VOL_WIZARD_MODE_PAGE, + VOLUME_LOCATION_PAGE, + DEVICE_TRANSFORM_MODE_PAGE, + HIDDEN_VOL_HOST_PRE_CIPHER_PAGE, + HIDDEN_VOL_PRE_CIPHER_PAGE, + CIPHER_PAGE, + SIZE_PAGE, + HIDDEN_VOL_HOST_PASSWORD_PAGE, + PASSWORD_PAGE, + FILESYS_PAGE, + SYSENC_COLLECTING_RANDOM_DATA_PAGE, + SYSENC_KEYS_GEN_PAGE, + SYSENC_RESCUE_DISK_CREATION_PAGE, + SYSENC_RESCUE_DISK_BURN_PAGE, + SYSENC_RESCUE_DISK_VERIFIED_PAGE, + SYSENC_WIPE_MODE_PAGE, + SYSENC_PRETEST_INFO_PAGE, + SYSENC_PRETEST_RESULT_PAGE, + SYSENC_ENCRYPTION_PAGE, + NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE, + NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE, + NONSYS_INPLACE_ENC_RAND_DATA_PAGE, + NONSYS_INPLACE_ENC_WIPE_MODE_PAGE, + NONSYS_INPLACE_ENC_ENCRYPTION_PAGE, + NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE, + FORMAT_PAGE, + FORMAT_FINISHED_PAGE, + SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE, + SYSENC_HIDDEN_OS_WIPE_INFO_PAGE, + DEVICE_WIPE_MODE_PAGE, + DEVICE_WIPE_PAGE +}; + +#define TIMER_INTERVAL_RANDVIEW 30 +#define TIMER_INTERVAL_SYSENC_PROGRESS 30 +#define TIMER_INTERVAL_NONSYS_INPLACE_ENC_PROGRESS 30 +#define TIMER_INTERVAL_SYSENC_DRIVE_ANALYSIS_PROGRESS 100 +#define TIMER_INTERVAL_WIPE_PROGRESS 30 +#define TIMER_INTERVAL_KEYB_LAYOUT_GUARD 10 + +enum sys_encryption_cmd_line_switches +{ + SYSENC_COMMAND_NONE = 0, + SYSENC_COMMAND_RESUME, + SYSENC_COMMAND_STARTUP_SEQ_RESUME, + SYSENC_COMMAND_ENCRYPT, + SYSENC_COMMAND_DECRYPT, + SYSENC_COMMAND_CREATE_HIDDEN_OS, + SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV +}; + +typedef struct +{ + int NumberOfSysDrives; // Number of drives that contain an operating system. -1: unknown, 1: one, 2: two or more + int MultipleSystemsOnDrive; // Multiple systems are installed on the drive where the currently running system resides. -1: unknown, 0: no, 1: yes + int BootLoaderLocation; // Boot loader (boot manager) installed in: 1: MBR/1st cylinder, 0: partition/bootsector: -1: unknown + int BootLoaderBrand; // -1: unknown, 0: Microsoft Windows, 1: any non-Windows boot manager/loader + int SystemOnBootDrive; // If the currently running operating system is installed on the boot drive. -1: unknown, 0: no, 1: yes +} SYSENC_MULTIBOOT_CFG; + +#define SYSENC_PAUSE_RETRY_INTERVAL 100 +#define SYSENC_PAUSE_RETRIES 200 + +// Expected duration of system drive analysis, in ms +#define SYSENC_DRIVE_ANALYSIS_ETA (4*60000) + +BootEncryption *BootEncObj = NULL; +BootEncryptionStatus BootEncStatus; + +HWND hCurPage = NULL; /* Handle to current wizard page */ +int nCurPageNo = -1; /* The current wizard page */ +int nLastPageNo = -1; +volatile int WizardMode = DEFAULT_VOL_CREATION_WIZARD_MODE; /* IMPORTANT: Never change this value directly -- always use ChangeWizardMode() instead. */ +volatile BOOL bHiddenOS = FALSE; /* If TRUE, we are performing or (or supposed to perform) actions relating to an operating system installed in a hidden volume (i.e., encrypting a decoy OS partition or creating the outer/hidden volume for the hidden OS). To determine or set the phase of the process, call ChangeHiddenOSCreationPhase() and DetermineHiddenOSCreationPhase()) */ +BOOL bDirectSysEncMode = FALSE; +BOOL bDirectSysEncModeCommand = SYSENC_COMMAND_NONE; +BOOL DirectDeviceEncMode = FALSE; +BOOL DirectNonSysInplaceEncResumeMode = FALSE; +BOOL DirectPromptNonSysInplaceEncResumeMode = FALSE; +volatile BOOL bInPlaceEncNonSys = FALSE; /* If TRUE, existing data on a non-system partition/volume are to be encrypted (for system encryption, this flag is ignored) */ +volatile BOOL bInPlaceEncNonSysResumed = FALSE; /* If TRUE, the wizard is supposed to resume (or has resumed) process of non-system in-place encryption. */ +volatile BOOL bFirstNonSysInPlaceEncResumeDone = FALSE; +__int64 NonSysInplaceEncBytesDone = 0; +__int64 NonSysInplaceEncTotalSectors = 0; +BOOL bDeviceTransformModeChoiceMade = FALSE; /* TRUE if the user has at least once manually selected the 'in-place' or 'format' option (on the 'device transform mode' page). */ +int nNeedToStoreFilesOver4GB = 0; /* Whether the user wants to be able to store files larger than 4GB on the volume: -1 = Undecided or error, 0 = No, 1 = Yes */ +int nVolumeEA = 1; /* Default encryption algorithm */ +BOOL bSystemEncryptionInProgress = FALSE; /* TRUE when encrypting/decrypting the system partition/drive (FALSE when paused). */ +BOOL bWholeSysDrive = FALSE; /* Whether to encrypt the entire system drive or just the system partition. */ +static BOOL bSystemEncryptionStatusChanged = FALSE; /* TRUE if this instance changed the value of SystemEncryptionStatus (it's set to FALSE each time the system encryption settings are saved to the config file). This value is to be treated as protected -- only the wizard can change this value (others may only read it). */ +volatile BOOL bSysEncDriveAnalysisInProgress = FALSE; +volatile BOOL bSysEncDriveAnalysisTimeOutOccurred = FALSE; +int SysEncDetectHiddenSectors = -1; /* Whether the user wants us to detect and encrypt the Host Protect Area (if any): -1 = Undecided or error, 0 = No, 1 = Yes */ +int SysEncDriveAnalysisStart; +BOOL bDontVerifyRescueDisk = FALSE; +BOOL bFirstSysEncResumeDone = FALSE; +int nMultiBoot = 0; /* The number of operating systems installed on the computer, according to the user. 0: undetermined, 1: one, 2: two or more */ +volatile BOOL bHiddenVol = FALSE; /* If true, we are (or will be) creating a hidden volume. */ +volatile BOOL bHiddenVolHost = FALSE; /* If true, we are (or will be) creating the host volume (called "outer") for a hidden volume. */ +volatile BOOL bHiddenVolDirect = FALSE; /* If true, the wizard omits creating a host volume in the course of the process of hidden volume creation. */ +volatile BOOL bHiddenVolFinished = FALSE; +int hiddenVolHostDriveNo = -1; /* Drive letter for the volume intended to host a hidden volume. */ +BOOL bRemovableHostDevice = FALSE; /* TRUE when creating a device/partition-hosted volume on a removable device. State undefined when creating file-hosted volumes. */ +int realClusterSize; /* Parameter used when determining the maximum possible size of a hidden volume. */ +int hash_algo = DEFAULT_HASH_ALGORITHM; /* Which PRF to use in header key derivation (PKCS #5) and in the RNG. */ +unsigned __int64 nUIVolumeSize = 0; /* The volume size. Important: This value is not in bytes. It has to be multiplied by nMultiplier. Do not use this value when actually creating the volume (it may chop off 512 bytes, if it is not a multiple of 1024 bytes). */ +unsigned __int64 nVolumeSize = 0; /* The volume size, in bytes. */ +unsigned __int64 nHiddenVolHostSize = 0; /* Size of the hidden volume host, in bytes */ +__int64 nMaximumHiddenVolSize = 0; /* Maximum possible size of the hidden volume, in bytes */ +__int64 nbrFreeClusters = 0; +int nMultiplier = BYTES_PER_MB; /* Size selection multiplier. */ +char szFileName[TC_MAX_PATH+1]; /* The file selected by the user */ +char szDiskFile[TC_MAX_PATH+1]; /* Fully qualified name derived from szFileName */ +char szRescueDiskISO[TC_MAX_PATH+1]; /* The filename and path to the Rescue Disk ISO file to be burned (for boot encryption) */ +BOOL bDeviceWipeInProgress = FALSE; +volatile BOOL bTryToCorrectReadErrors = FALSE; +volatile BOOL DiscardUnreadableEncryptedSectors = FALSE; + +volatile BOOL bVolTransformThreadCancel = FALSE; /* TRUE if the user cancels/pauses volume encryption/format */ +volatile BOOL bVolTransformThreadRunning = FALSE; /* Is the volume encryption/format thread running */ +volatile BOOL bVolTransformThreadToRun = FALSE; /* TRUE if the Format/Encrypt button has been clicked and we are proceeding towards launching the thread. */ + +volatile BOOL bConfirmQuit = FALSE; /* If TRUE, the user is asked to confirm exit when he clicks the X icon, Exit, etc. */ +volatile BOOL bConfirmQuitSysEncPretest = FALSE; + +BOOL bDevice = FALSE; /* Is this a partition volume ? */ + +BOOL showKeys = TRUE; +volatile HWND hMasterKey = NULL; /* Text box showing hex dump of the master key */ +volatile HWND hHeaderKey = NULL; /* Text box showing hex dump of the header key */ +volatile HWND hRandPool = NULL; /* Text box showing hex dump of the random pool */ +volatile HWND hRandPoolSys = NULL; /* Text box showing hex dump of the random pool for system encryption */ +volatile HWND hPasswordInputField = NULL; /* Password input field */ +volatile HWND hVerifyPasswordInputField = NULL; /* Verify-password input field */ + +HBITMAP hbmWizardBitmapRescaled = NULL; + +char OrigKeyboardLayout [8+1] = "00000409"; +BOOL bKeyboardLayoutChanged = FALSE; /* TRUE if the keyboard layout was changed to the standard US keyboard layout (from any other layout). */ +BOOL bKeybLayoutAltKeyWarningShown = FALSE; /* TRUE if the user has been informed that it is not possible to type characters by pressing keys while the right Alt key is held down. */ + +#ifndef _DEBUG + BOOL bWarnDeviceFormatAdvanced = TRUE; +#else + BOOL bWarnDeviceFormatAdvanced = FALSE; +#endif + +BOOL bWarnOuterVolSuitableFileSys = TRUE; + +Password volumePassword; /* User password */ +char szVerify[MAX_PASSWORD + 1]; /* Tmp password buffer */ +char szRawPassword[MAX_PASSWORD + 1]; /* Password before keyfile was applied to it */ + +BOOL bHistoryCmdLine = FALSE; /* History control is always disabled */ +BOOL ComServerMode = FALSE; + +int nPbar = 0; /* Control ID of progress bar:- for format code */ + +char HeaderKeyGUIView [KEY_GUI_VIEW_SIZE]; +char MasterKeyGUIView [KEY_GUI_VIEW_SIZE]; + +#define RANDPOOL_DISPLAY_COLUMNS 15 +#define RANDPOOL_DISPLAY_ROWS 8 +#define RANDPOOL_DISPLAY_BYTE_PORTION (RANDPOOL_DISPLAY_COLUMNS * RANDPOOL_DISPLAY_ROWS) +#define RANDPOOL_DISPLAY_SIZE (RANDPOOL_DISPLAY_BYTE_PORTION * 3 + RANDPOOL_DISPLAY_ROWS + 2) +unsigned char randPool [RANDPOOL_DISPLAY_BYTE_PORTION]; +unsigned char lastRandPool [RANDPOOL_DISPLAY_BYTE_PORTION]; +unsigned char outRandPoolDispBuffer [RANDPOOL_DISPLAY_SIZE]; +BOOL bDisplayPoolContents = TRUE; + +volatile BOOL bSparseFileSwitch = FALSE; +volatile BOOL quickFormat = FALSE; /* WARNING: Meaning of this variable depends on bSparseFileSwitch. If bSparseFileSwitch is TRUE, this variable represents the sparse file flag. */ +volatile int fileSystem = FILESYS_NONE; +volatile int clusterSize = 0; + +SYSENC_MULTIBOOT_CFG SysEncMultiBootCfg; +wchar_t SysEncMultiBootCfgOutcome [4096] = {'N','/','A',0}; +volatile int NonSysInplaceEncStatus = NONSYS_INPLACE_ENC_STATUS_NONE; + +vector DeferredNonSysInPlaceEncDevices; + + +static BOOL ElevateWholeWizardProcess (string arguments) +{ + char modPath[MAX_PATH]; + + if (IsAdmin()) + return TRUE; + + if (!IsUacSupported()) + return IsAdmin(); + + GetModuleFileName (NULL, modPath, sizeof (modPath)); + + if ((int)ShellExecute (MainDlg, "runas", modPath, (string("/q UAC ") + arguments).c_str(), NULL, SW_SHOWNORMAL) > 32) + { + exit (0); + } + else + { + Error ("UAC_INIT_ERROR"); + return FALSE; + } +} + +static void WipePasswordsAndKeyfiles (void) +{ + char tmp[MAX_PASSWORD+1]; + + // Attempt to wipe passwords stored in the input field buffers + memset (tmp, 'X', MAX_PASSWORD); + tmp [MAX_PASSWORD] = 0; + SetWindowText (hPasswordInputField, tmp); + SetWindowText (hVerifyPasswordInputField, tmp); + + burn (&szVerify[0], sizeof (szVerify)); + burn (&volumePassword, sizeof (volumePassword)); + burn (&szRawPassword[0], sizeof (szRawPassword)); + + SetWindowText (hPasswordInputField, ""); + SetWindowText (hVerifyPasswordInputField, ""); + + KeyFileRemoveAll (&FirstKeyFile); + KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); +} + +static void localcleanup (void) +{ + char tmp[RANDPOOL_DISPLAY_SIZE+1]; + + // System encryption + + if (WizardMode == WIZARD_MODE_SYS_DEVICE + && InstanceHasSysEncMutex ()) + { + try + { + BootEncStatus = BootEncObj->GetStatus(); + + if (BootEncStatus.SetupInProgress) + { + BootEncObj->AbortSetup (); + } + } + catch (...) + { + // NOP + } + } + + // Mon-system in-place encryption + + if (bInPlaceEncNonSys && (bVolTransformThreadRunning || bVolTransformThreadToRun)) + { + NonSysInplaceEncPause (); + } + + CloseNonSysInplaceEncMutex (); + + + // Device wipe + + if (bDeviceWipeInProgress) + WipeAbort(); + + + WipePasswordsAndKeyfiles (); + + RandStop (TRUE); + + burn (HeaderKeyGUIView, sizeof(HeaderKeyGUIView)); + burn (MasterKeyGUIView, sizeof(MasterKeyGUIView)); + burn (randPool, sizeof(randPool)); + burn (lastRandPool, sizeof(lastRandPool)); + burn (outRandPoolDispBuffer, sizeof(outRandPoolDispBuffer)); + burn (szFileName, sizeof(szFileName)); + burn (szDiskFile, sizeof(szDiskFile)); + + // Attempt to wipe the GUI fields showing portions of randpool, of the master and header keys + memset (tmp, 'X', sizeof(tmp)); + tmp [sizeof(tmp)-1] = 0; + SetWindowText (hRandPool, tmp); + SetWindowText (hRandPoolSys, tmp); + SetWindowText (hMasterKey, tmp); + SetWindowText (hHeaderKey, tmp); + + UnregisterRedTick (hInst); + + // Delete buffered bitmaps (if any) + if (hbmWizardBitmapRescaled != NULL) + { + DeleteObject ((HGDIOBJ) hbmWizardBitmapRescaled); + hbmWizardBitmapRescaled = NULL; + } + + // Cleanup common code resources + cleanup (); + + if (BootEncObj != NULL) + { + delete BootEncObj; + BootEncObj = NULL; + } +} + +static BOOL CALLBACK BroadcastSysEncCfgUpdateCallb (HWND hwnd, LPARAM lParam) +{ + if (GetWindowLongPtr (hwnd, GWLP_USERDATA) == (LONG_PTR) 'TRUE') + { + char name[1024] = { 0 }; + GetWindowText (hwnd, name, sizeof (name) - 1); + if (hwnd != MainDlg && strstr (name, "TrueCrypt")) + { + PostMessage (hwnd, TC_APPMSG_SYSENC_CONFIG_UPDATE, 0, 0); + } + } + return TRUE; +} + +static BOOL BroadcastSysEncCfgUpdate (void) +{ + BOOL bSuccess = FALSE; + EnumWindows (BroadcastSysEncCfgUpdateCallb, (LPARAM) &bSuccess); + return bSuccess; +} + +// IMPORTANT: This function may be called only by Format (other modules can only _read_ the system encryption config). +// Returns TRUE if successful (otherwise FALSE) +static BOOL SaveSysEncSettings (HWND hwndDlg) +{ + FILE *f; + + if (!bSystemEncryptionStatusChanged) + return TRUE; + + if (hwndDlg == NULL && MainDlg != NULL) + hwndDlg = MainDlg; + + if (!CreateSysEncMutex ()) + return FALSE; // Only one instance that has the mutex can modify the system encryption settings + + if (SystemEncryptionStatus == SYSENC_STATUS_NONE) + { + if (remove (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION)) != 0) + { + Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS"); + return FALSE; + } + + bSystemEncryptionStatusChanged = FALSE; + BroadcastSysEncCfgUpdate (); + return TRUE; + } + + f = fopen (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), "w"); + if (f == NULL) + { + Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS"); + handleWin32Error (hwndDlg); + return FALSE; + } + + if (XmlWriteHeader (f) < 0 + + || fputs ("\n\t", f) < 0 + + || fprintf (f, "\n\t\t%d", SystemEncryptionStatus) < 0 + + || fprintf (f, "\n\t\t%d", (int) nWipeMode) < 0 + + || fputs ("\n\t", f) < 0 + + || XmlWriteFooter (f) < 0) + { + handleWin32Error (hwndDlg); + fclose (f); + Error ("CANNOT_SAVE_SYS_ENCRYPTION_SETTINGS"); + return FALSE; + } + + TCFlushFile (f); + + fclose (f); + + bSystemEncryptionStatusChanged = FALSE; + BroadcastSysEncCfgUpdate (); + + return TRUE; +} + +// WARNING: This function may take a long time to finish +static unsigned int DetermineHiddenOSCreationPhase (void) +{ + unsigned int phase = TC_HIDDEN_OS_CREATION_PHASE_NONE; + + try + { + phase = BootEncObj->GetHiddenOSCreationPhase(); + } + catch (Exception &e) + { + e.Show (MainDlg); + AbortProcess("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + } + + return phase; +} + +// IMPORTANT: This function may be called only by Format (other modules can only _read_ the status). +// Returns TRUE if successful (otherwise FALSE) +static BOOL ChangeHiddenOSCreationPhase (int newPhase) +{ + if (!CreateSysEncMutex ()) + { + Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + return FALSE; + } + + try + { + BootEncObj->SetHiddenOSCreationPhase (newPhase); + } + catch (Exception &e) + { + e.Show (MainDlg); + return FALSE; + } + + //// The contents of the following items might be inappropriate after a change of the phase + //szFileName[0] = 0; + //szDiskFile[0] = 0; + //nUIVolumeSize = 0; + //nVolumeSize = 0; + + return TRUE; +} + +// IMPORTANT: This function may be called only by Format (other modules can only _read_ the system encryption status). +// Returns TRUE if successful (otherwise FALSE) +static BOOL ChangeSystemEncryptionStatus (int newStatus) +{ + if (!CreateSysEncMutex ()) + { + Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + return FALSE; // Only one instance that has the mutex can modify the system encryption settings + } + + SystemEncryptionStatus = newStatus; + bSystemEncryptionStatusChanged = TRUE; + + if (newStatus == SYSENC_STATUS_ENCRYPTING) + { + // If the user has created a hidden OS and now is creating a decoy OS, we must wipe the hidden OS + // config area in the MBR. + WipeHiddenOSCreationConfig(); + } + + if (newStatus == SYSENC_STATUS_NONE && !IsHiddenOSRunning()) + { + if (DetermineHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE + && !ChangeHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE)) + return FALSE; + + WipeHiddenOSCreationConfig(); + } + + if (!SaveSysEncSettings (MainDlg)) + { + return FALSE; + } + + return TRUE; +} + +// If the return code of this function is ignored and newWizardMode == WIZARD_MODE_SYS_DEVICE, then this function +// may be called only after CreateSysEncMutex() returns TRUE. It returns TRUE if successful (otherwise FALSE). +static BOOL ChangeWizardMode (int newWizardMode) +{ + if (WizardMode != newWizardMode) + { + if (WizardMode == WIZARD_MODE_SYS_DEVICE || newWizardMode == WIZARD_MODE_SYS_DEVICE) + { + if (newWizardMode == WIZARD_MODE_SYS_DEVICE) + { + if (!CreateSysEncMutex ()) + { + Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + return FALSE; + } + } + + // If the previous mode was different, the password may have been typed using a different + // keyboard layout (which might confuse the user and cause other problems if system encryption + // was or will be involved). + WipePasswordsAndKeyfiles(); + } + + if (newWizardMode != WIZARD_MODE_NONSYS_DEVICE) + bInPlaceEncNonSys = FALSE; + + if (newWizardMode == WIZARD_MODE_NONSYS_DEVICE && !IsAdmin() && IsUacSupported()) + { + if (!ElevateWholeWizardProcess ("/e")) + return FALSE; + } + + // The contents of the following items may be inappropriate after a change of mode + szFileName[0] = 0; + szDiskFile[0] = 0; + nUIVolumeSize = 0; + nVolumeSize = 0; + + WizardMode = newWizardMode; + } + + bDevice = (WizardMode != WIZARD_MODE_FILE_CONTAINER); + + if (newWizardMode != WIZARD_MODE_SYS_DEVICE + && !bHiddenOS) + { + CloseSysEncMutex (); + } + + return TRUE; +} + +// Determines whether the wizard directly affects system encryption in any way. +// Note, for example, that when the user enters a password for a hidden volume that is to host a hidden OS, +// WizardMode is NOT set to WIZARD_MODE_SYS_DEVICE. The keyboard layout, however, has to be US. That's why +// this function has to be called instead of checking the value of WizardMode. +static BOOL SysEncInEffect (void) +{ + return (WizardMode == WIZARD_MODE_SYS_DEVICE + || CreatingHiddenSysVol()); +} + +static BOOL CreatingHiddenSysVol (void) +{ + return (bHiddenOS + && bHiddenVol && !bHiddenVolHost); +} + +static void LoadSettings (HWND hwndDlg) +{ + WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; + + LoadSysEncSettings (hwndDlg); + + if (LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) != 0) + bInPlaceEncNonSysPending = TRUE; + + defaultKeyFilesParam.EnableKeyFiles = FALSE; + + bStartOnLogon = ConfigReadInt ("StartOnLogon", FALSE); + + HiddenSectorDetectionStatus = ConfigReadInt ("HiddenSectorDetectionStatus", 0); + + bHistory = ConfigReadInt ("SaveVolumeHistory", FALSE); + + ConfigReadString ("SecurityTokenLibrary", "", SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath) - 1); + if (SecurityTokenLibraryPath[0]) + InitSecurityTokenLibrary(); + + if (hwndDlg != NULL) + { + LoadCombo (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); + return; + } + + if (bHistoryCmdLine) + return; +} + +static void SaveSettings (HWND hwndDlg) +{ + WaitCursor (); + + if (hwndDlg != NULL) + DumpCombo (GetDlgItem (hwndDlg, IDC_COMBO_BOX), !bHistory); + + ConfigWriteBegin (); + + ConfigWriteInt ("StartOnLogon", bStartOnLogon); + ConfigWriteInt ("HiddenSectorDetectionStatus", HiddenSectorDetectionStatus); + ConfigWriteInt ("SaveVolumeHistory", bHistory); + ConfigWriteString ("SecurityTokenLibrary", SecurityTokenLibraryPath[0] ? SecurityTokenLibraryPath : ""); + + if (GetPreferredLangId () != NULL) + ConfigWriteString ("Language", GetPreferredLangId ()); + + ConfigWriteEnd (); + + NormalCursor (); +} + +// WARNING: This function does NOT cause immediate application exit (use e.g. return 1 after calling it +// from a DialogProc function). +static void EndMainDlg (HWND hwndDlg) +{ + if (nCurPageNo == VOLUME_LOCATION_PAGE) + { + if (IsWindow(GetDlgItem(hCurPage, IDC_NO_HISTORY))) + bHistory = !IsButtonChecked (GetDlgItem (hCurPage, IDC_NO_HISTORY)); + + MoveEditToCombo (GetDlgItem (hCurPage, IDC_COMBO_BOX), bHistory); + SaveSettings (hCurPage); + } + else + { + SaveSettings (NULL); + } + + SaveSysEncSettings (hwndDlg); + + if (!bHistory) + CleanLastVisitedMRU (); + + EndDialog (hwndDlg, 0); +} + +// Returns TRUE if system encryption or decryption had been or is in progress and has not been completed +static BOOL SysEncryptionOrDecryptionRequired (void) +{ + /* If you update this function, revise SysEncryptionOrDecryptionRequired() in Mount.c as well. */ + + static BootEncryptionStatus locBootEncStatus; + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + return (SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING + || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING + || + ( + locBootEncStatus.DriveMounted + && + ( + locBootEncStatus.ConfiguredEncryptedAreaStart != locBootEncStatus.EncryptedAreaStart + || locBootEncStatus.ConfiguredEncryptedAreaEnd != locBootEncStatus.EncryptedAreaEnd + ) + ) + ); +} + +// Returns TRUE if the system partition/drive is completely encrypted +static BOOL SysDriveOrPartitionFullyEncrypted (BOOL bSilent) +{ + /* If you update this function, revise SysDriveOrPartitionFullyEncrypted() in Mount.c as well. */ + + static BootEncryptionStatus locBootEncStatus; + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + if (!bSilent) + e.Show (MainDlg); + } + + return (!locBootEncStatus.SetupInProgress + && locBootEncStatus.ConfiguredEncryptedAreaEnd != 0 + && locBootEncStatus.ConfiguredEncryptedAreaEnd != -1 + && locBootEncStatus.ConfiguredEncryptedAreaStart == locBootEncStatus.EncryptedAreaStart + && locBootEncStatus.ConfiguredEncryptedAreaEnd == locBootEncStatus.EncryptedAreaEnd); +} + +// This functions is to be used when the wizard mode needs to be changed to WIZARD_MODE_SYS_DEVICE. +// If the function fails to switch the mode, it returns FALSE (otherwise TRUE). +BOOL SwitchWizardToSysEncMode (void) +{ + WaitCursor (); + + try + { + BootEncStatus = BootEncObj->GetStatus(); + bWholeSysDrive = BootEncObj->SystemPartitionCoversWholeDrive(); + } + catch (Exception &e) + { + e.Show (MainDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + NormalCursor (); + return FALSE; + } + + // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption + if (!CreateSysEncMutex ()) + { + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + NormalCursor (); + return FALSE; + } + + // User-mode app may have crashed and its mutex may have gotten lost, so we need to check the driver status too + if (BootEncStatus.SetupInProgress) + { + if (AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) + { + if (SystemEncryptionStatus != SYSENC_STATUS_ENCRYPTING + && SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) + { + // The config file with status was lost or not written correctly + if (!ResolveUnknownSysEncDirection ()) + { + CloseSysEncMutex (); + NormalCursor (); + return FALSE; + } + } + + bDirectSysEncMode = TRUE; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + LoadPage (MainDlg, SYSENC_ENCRYPTION_PAGE); + NormalCursor (); + return TRUE; + } + else + { + CloseSysEncMutex (); + Error ("SYS_ENCRYPTION_OR_DECRYPTION_IN_PROGRESS"); + NormalCursor (); + return FALSE; + } + } + + if (BootEncStatus.DriveMounted + || BootEncStatus.DriveEncrypted + || SysEncryptionOrDecryptionRequired ()) + { + + if (!SysDriveOrPartitionFullyEncrypted (FALSE) + && AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) + { + if (SystemEncryptionStatus == SYSENC_STATUS_NONE) + { + // If the config file with status was lost or not written correctly, we + // don't know whether to encrypt or decrypt (but we know that encryption or + // decryption is required). Ask the user to select encryption, decryption, + // or cancel + if (!ResolveUnknownSysEncDirection ()) + { + CloseSysEncMutex (); + NormalCursor (); + return FALSE; + } + } + + bDirectSysEncMode = TRUE; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + LoadPage (MainDlg, SYSENC_ENCRYPTION_PAGE); + NormalCursor (); + return TRUE; + } + else + { + CloseSysEncMutex (); + Error ("SETUP_FAILED_BOOT_DRIVE_ENCRYPTED"); + NormalCursor (); + return FALSE; + } + } + else + { + // Check compliance with requirements for boot encryption + + if (!IsAdmin()) + { + if (!IsUacSupported()) + { + Warning ("ADMIN_PRIVILEGES_WARN_DEVICES"); + } + } + + try + { + BootEncObj->CheckRequirements (); + } + catch (Exception &e) + { + CloseSysEncMutex (); + e.Show (MainDlg); + NormalCursor (); + return FALSE; + } + + if (!ChangeWizardMode (WIZARD_MODE_SYS_DEVICE)) + { + NormalCursor (); + return FALSE; + } + + if (bSysDriveSelected || bSysPartitionSelected) + { + // The user selected the non-sys-device wizard mode but then selected a system device + + bWholeSysDrive = (bSysDriveSelected && !bSysPartitionSelected); + + bSysDriveSelected = FALSE; + bSysPartitionSelected = FALSE; + + try + { + if (!bHiddenVol) + { + if (bWholeSysDrive && !BootEncObj->SystemPartitionCoversWholeDrive()) + { + if (!IsOSAtLeast (WIN_VISTA)) + { + if (BootEncObj->SystemDriveContainsExtendedPartition()) + { + bWholeSysDrive = FALSE; + + Error ("WDE_UNSUPPORTED_FOR_EXTENDED_PARTITIONS"); + + if (AskYesNo ("ASK_ENCRYPT_PARTITION_INSTEAD_OF_DRIVE") == IDNO) + { + ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE); + return FALSE; + } + } + else + Warning ("WDE_EXTENDED_PARTITIONS_WARNING"); + } + } + else if (BootEncObj->SystemPartitionCoversWholeDrive() + && !bWholeSysDrive) + bWholeSysDrive = (AskYesNo ("WHOLE_SYC_DEVICE_RECOM") == IDYES); + } + + } + catch (Exception &e) + { + e.Show (MainDlg); + return FALSE; + } + + if (!bHiddenVol) + { + // Skip SYSENC_SPAN_PAGE and SYSENC_TYPE_PAGE as the user already made the choice + LoadPage (MainDlg, bWholeSysDrive ? SYSENC_PRE_DRIVE_ANALYSIS_PAGE : SYSENC_MULTI_BOOT_MODE_PAGE); + } + else + { + // The user selected the non-sys-device wizard mode but then selected a system device. + // In addition, he selected the hidden volume mode. + + if (bWholeSysDrive) + Warning ("HIDDEN_OS_PRECLUDES_SINGLE_KEY_WDE"); + + bWholeSysDrive = FALSE; + + LoadPage (MainDlg, SYSENC_TYPE_PAGE); + } + } + else + LoadPage (MainDlg, SYSENC_TYPE_PAGE); + + NormalCursor (); + return TRUE; + } +} + +void SwitchWizardToFileContainerMode (void) +{ + ChangeWizardMode (WIZARD_MODE_FILE_CONTAINER); + + LoadPage (MainDlg, VOLUME_LOCATION_PAGE); + + NormalCursor (); +} + +void SwitchWizardToNonSysDeviceMode (void) +{ + ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE); + + LoadPage (MainDlg, VOLUME_TYPE_PAGE); + + NormalCursor (); +} + +BOOL SwitchWizardToHiddenOSMode (void) +{ + if (SwitchWizardToSysEncMode()) + { + if (nCurPageNo != SYSENC_ENCRYPTION_PAGE) // If the user did not manually choose to resume encryption or decryption of the system partition/drive + { + bHiddenOS = TRUE; + bHiddenVol = TRUE; + bHiddenVolHost = TRUE; + bHiddenVolDirect = FALSE; + bWholeSysDrive = FALSE; + bInPlaceEncNonSys = FALSE; + + if (bDirectSysEncModeCommand == SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV) + { + // Some of the requirements for hidden OS should have already been checked by the wizard process + // that launched us (in order to elevate), but we must recheck them. Otherwise, an advanced user + // could bypass the checks by using the undocumented CLI switch. Moreover, some requirements + // can be checked only at this point (when we are elevated). + try + { + BootEncObj->CheckRequirementsHiddenOS (); + + BootEncObj->InitialSecurityChecksForHiddenOS (); + } + catch (Exception &e) + { + e.Show (MainDlg); + return FALSE; + } + + LoadPage (MainDlg, SYSENC_MULTI_BOOT_MODE_PAGE); + } + else + LoadPage (MainDlg, SYSENC_HIDDEN_OS_REQ_CHECK_PAGE); + + NormalCursor (); + } + else + return TRUE; + } + else + return FALSE; + + return TRUE; +} + +void SwitchWizardToNonSysInplaceEncResumeMode (void) +{ + if (!IsAdmin() && IsUacSupported()) + { + if (!ElevateWholeWizardProcess ("/zinplace")) + AbortProcessSilent (); + } + + if (!IsAdmin()) + AbortProcess("ADMIN_PRIVILEGES_WARN_DEVICES"); + + CreateNonSysInplaceEncMutex (); + + bInPlaceEncNonSys = TRUE; + bInPlaceEncNonSysResumed = TRUE; + + ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE); + + LoadPage (MainDlg, NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE); +} + +// Use this function e.g. if the config file with the system encryption settings was lost or not written +// correctly, and we don't know whether to encrypt or decrypt (but we know that encryption or decryption +// is required). Returns FALSE if failed or cancelled. +static BOOL ResolveUnknownSysEncDirection (void) +{ + if (CreateSysEncMutex ()) + { + if (SystemEncryptionStatus != SYSENC_STATUS_ENCRYPTING + && SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) + { + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + return FALSE; + } + + if (BootEncStatus.SetupInProgress) + { + return ChangeSystemEncryptionStatus ( + (BootEncStatus.SetupMode != SetupDecryption) ? SYSENC_STATUS_ENCRYPTING : SYSENC_STATUS_DECRYPTING); + } + else + { + // Ask the user to select encryption, decryption, or cancel + + char *tmpStr[] = {0, + !BootEncStatus.DriveEncrypted ? "CHOOSE_ENCRYPT_OR_DECRYPT_FINALIZE_DECRYPT_NOTE" : "CHOOSE_ENCRYPT_OR_DECRYPT", + "ENCRYPT", + "DECRYPT", + "IDCANCEL", + 0}; + + switch (AskMultiChoice ((void **) tmpStr, FALSE)) + { + case 1: + return ChangeSystemEncryptionStatus (SYSENC_STATUS_ENCRYPTING); + case 2: + return ChangeSystemEncryptionStatus (SYSENC_STATUS_DECRYPTING); + default: + return FALSE; + } + } + } + else + return TRUE; + } + else + { + Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + return FALSE; + } +} + +// This function should be used to resolve inconsistencies that might lead to a deadlock (inability to encrypt or +// decrypt the system partition/drive and to uninstall TrueCrypt). The function removes the system encryption key +// data ("volume header"), the TrueCrypt boot loader, restores the original system loader (if available), +// unregisters the boot driver, etc. Note that if the system partition/drive is encrypted, it will start decrypting +// it in the background (therefore, it should be used when the system partition/drive is not encrypted, ideally). +// Exceptions are handled and errors are reported within the function. Returns TRUE if successful. +static BOOL ForceRemoveSysEnc (void) +{ + if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption + { + BootEncryptionStatus locBootEncStatus; + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + + if (locBootEncStatus.SetupInProgress) + BootEncObj->AbortSetupWait (); + + locBootEncStatus = BootEncObj->GetStatus(); + + if (locBootEncStatus.DriveMounted) + { + // Remove the header + BootEncObj->StartDecryption (DiscardUnreadableEncryptedSectors); + locBootEncStatus = BootEncObj->GetStatus(); + + while (locBootEncStatus.SetupInProgress) + { + Sleep (100); + locBootEncStatus = BootEncObj->GetStatus(); + } + + BootEncObj->CheckEncryptionSetupResult (); + } + + Sleep (50); + } + catch (Exception &e) + { + e.Show (MainDlg); + return FALSE; + } + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + + if (!locBootEncStatus.DriveMounted) + BootEncObj->Deinstall (); + } + catch (Exception &e) + { + e.Show (MainDlg); + return FALSE; + } + + return TRUE; + } + else + return FALSE; +} + +// Returns 0 if there's an error. +__int64 GetSystemPartitionSize (void) +{ + try + { + return BootEncObj->GetSystemDriveConfiguration().SystemPartition.Info.PartitionLength.QuadPart; + } + catch (Exception &e) + { + e.Show (MainDlg); + return 0; + } +} + +void ComboSelChangeEA (HWND hwndDlg) +{ + LPARAM nIndex = SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); + + if (nIndex == CB_ERR) + { + SetWindowText (GetDlgItem (hwndDlg, IDC_BOX_HELP), ""); + } + else + { + char name[100]; + wchar_t auxLine[4096]; + wchar_t hyperLink[256] = { 0 }; + int cipherIDs[5]; + int i, cnt = 0; + + nIndex = SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); + EAGetName (name, nIndex); + + if (strcmp (name, "AES") == 0) + { + swprintf_s (hyperLink, sizeof(hyperLink) / 2, GetString ("MORE_INFO_ABOUT"), name); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("AES_HELP")); + } + else if (strcmp (name, "Serpent") == 0) + { + swprintf_s (hyperLink, sizeof(hyperLink) / 2, GetString ("MORE_INFO_ABOUT"), name); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SERPENT_HELP")); + } + else if (strcmp (name, "Twofish") == 0) + { + swprintf_s (hyperLink, sizeof(hyperLink) / 2, GetString ("MORE_INFO_ABOUT"), name); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("TWOFISH_HELP")); + } + else if (EAGetCipherCount (nIndex) > 1) + { + // Cascade + cipherIDs[cnt++] = i = EAGetLastCipher(nIndex); + while (i = EAGetPreviousCipher(nIndex, i)) + { + cipherIDs[cnt] = i; + cnt++; + } + + switch (cnt) // Number of ciphers in the cascade + { + case 2: + swprintf (auxLine, GetString ("TWO_LAYER_CASCADE_HELP"), + CipherGetName (cipherIDs[1]), + CipherGetKeySize (cipherIDs[1])*8, + CipherGetName (cipherIDs[0]), + CipherGetKeySize (cipherIDs[0])*8); + break; + + case 3: + swprintf (auxLine, GetString ("THREE_LAYER_CASCADE_HELP"), + CipherGetName (cipherIDs[2]), + CipherGetKeySize (cipherIDs[2])*8, + CipherGetName (cipherIDs[1]), + CipherGetKeySize (cipherIDs[1])*8, + CipherGetName (cipherIDs[0]), + CipherGetKeySize (cipherIDs[0])*8); + break; + } + + wcscpy_s (hyperLink, sizeof(hyperLink) / 2, GetString ("IDC_LINK_MORE_INFO_ABOUT_CIPHER")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), auxLine); + } + else + { + // No info available for this encryption algorithm + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), L""); + } + + + // Update hyperlink + SetWindowTextW (GetDlgItem (hwndDlg, IDC_LINK_MORE_INFO_ABOUT_CIPHER), hyperLink); + AccommodateTextField (hwndDlg, IDC_LINK_MORE_INFO_ABOUT_CIPHER, FALSE); + } +} + +static void VerifySizeAndUpdate (HWND hwndDlg, BOOL bUpdate) +{ + BOOL bEnable = TRUE; + char szTmp[50]; + __int64 lTmp; + size_t i; + static unsigned __int64 nLastVolumeSize = 0; + + GetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTmp, sizeof (szTmp)); + + for (i = 0; i < strlen (szTmp); i++) + { + if (szTmp[i] >= '0' && szTmp[i] <= '9') + continue; + else + { + bEnable = FALSE; + break; + } + } + + if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_KB))) + nMultiplier = BYTES_PER_KB; + else if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_MB))) + nMultiplier = BYTES_PER_MB; + else + nMultiplier = BYTES_PER_GB; + + if (bDevice && !(bHiddenVol && !bHiddenVolHost)) // If raw device but not a hidden volume + { + lTmp = nVolumeSize; + i = 1; + } + else + { + i = nMultiplier; + lTmp = _atoi64 (szTmp); + } + + if (bEnable) + { + if (lTmp * i < (bHiddenVolHost ? TC_MIN_HIDDEN_VOLUME_HOST_SIZE : (bHiddenVol ? TC_MIN_HIDDEN_VOLUME_SIZE : TC_MIN_VOLUME_SIZE))) + bEnable = FALSE; + + if (!bHiddenVolHost && bHiddenVol) + { + if (lTmp * i > nMaximumHiddenVolSize) + bEnable = FALSE; + } + else + { + if (lTmp * i > (bHiddenVolHost ? TC_MAX_HIDDEN_VOLUME_HOST_SIZE : TC_MAX_VOLUME_SIZE)) + bEnable = FALSE; + } + + if (lTmp * i % SECTOR_SIZE != 0) + bEnable = FALSE; + } + + if (bUpdate) + { + nUIVolumeSize = lTmp; + + if (!bDevice || (bHiddenVol && !bHiddenVolHost)) // Update only if it's not a raw device or if it's a hidden volume + nVolumeSize = i * lTmp; + } + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), bEnable); + + if (nVolumeSize != nLastVolumeSize) + { + // Change of volume size may make some file systems allowed or disallowed, so the default filesystem must + // be reselected. + fileSystem = FILESYS_NONE; + nLastVolumeSize = nVolumeSize; + } +} + +static void UpdateWizardModeControls (HWND hwndDlg, int setWizardMode) +{ + SendMessage (GetDlgItem (hwndDlg, IDC_FILE_CONTAINER), + BM_SETCHECK, + setWizardMode == WIZARD_MODE_FILE_CONTAINER ? BST_CHECKED : BST_UNCHECKED, + 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_NONSYS_DEVICE), + BM_SETCHECK, + setWizardMode == WIZARD_MODE_NONSYS_DEVICE ? BST_CHECKED : BST_UNCHECKED, + 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_SYS_DEVICE), + BM_SETCHECK, + setWizardMode == WIZARD_MODE_SYS_DEVICE ? BST_CHECKED : BST_UNCHECKED, + 0); +} + +static int GetSelectedWizardMode (HWND hwndDlg) +{ + if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_FILE_CONTAINER))) + return WIZARD_MODE_FILE_CONTAINER; + + if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_NONSYS_DEVICE))) + return WIZARD_MODE_NONSYS_DEVICE; + + if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_SYS_DEVICE))) + return WIZARD_MODE_SYS_DEVICE; + + return DEFAULT_VOL_CREATION_WIZARD_MODE; +} + +static void RefreshMultiBootControls (HWND hwndDlg) +{ +#ifdef DEBUG + if (nMultiBoot == 0) + nMultiBoot = 1; +#endif + + SendMessage (GetDlgItem (hwndDlg, IDC_SINGLE_BOOT), + BM_SETCHECK, + nMultiBoot == 1 ? BST_CHECKED : BST_UNCHECKED, + 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_BOOT), + BM_SETCHECK, + nMultiBoot > 1 ? BST_CHECKED : BST_UNCHECKED, + 0); +} + +// -1 = Undecided or error, 0 = No, 1 = Yes +static int Get2RadButtonPageAnswer (void) +{ + if (IsButtonChecked (GetDlgItem (hCurPage, IDC_CHOICE1))) + return 1; + + if (IsButtonChecked (GetDlgItem (hCurPage, IDC_CHOICE2))) + return 0; + + return -1; +} + +// 0 = No, 1 = Yes +static void Update2RadButtonPage (int answer) +{ + SendMessage (GetDlgItem (hCurPage, IDC_CHOICE1), + BM_SETCHECK, + answer == 1 ? BST_CHECKED : BST_UNCHECKED, + 0); + + SendMessage (GetDlgItem (hCurPage, IDC_CHOICE2), + BM_SETCHECK, + answer == 0 ? BST_CHECKED : BST_UNCHECKED, + 0); +} + +// -1 = Undecided, 0 = No, 1 = Yes +static void Init2RadButtonPageYesNo (int answer) +{ + SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE1), GetString ("UISTR_YES")); + SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE2), GetString ("UISTR_NO")); + + SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), answer >= 0); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), TRUE); + + Update2RadButtonPage (answer); +} + +static void UpdateSysEncProgressBar (void) +{ + BootEncryptionStatus locBootEncStatus; + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + } + catch (...) + { + return; + } + + if (locBootEncStatus.EncryptedAreaEnd == -1 + || locBootEncStatus.EncryptedAreaStart == -1) + { + UpdateProgressBarProc (0); + } + else + { + UpdateProgressBarProc ((locBootEncStatus.EncryptedAreaEnd - locBootEncStatus.EncryptedAreaStart + 1) / SECTOR_SIZE); + + if (locBootEncStatus.SetupInProgress) + { + wchar_t tmpStr[100]; + + // Status + + if (locBootEncStatus.TransformWaitingForIdle) + wcscpy (tmpStr, GetString ("PROGRESS_STATUS_WAITING")); + else + wcscpy (tmpStr, GetString (SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING ? "PROGRESS_STATUS_DECRYPTING" : "PROGRESS_STATUS_ENCRYPTING")); + + wcscat (tmpStr, L" "); + + SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), tmpStr); + } + } +} + +static void InitSysEncProgressBar (void) +{ + BootEncryptionStatus locBootEncStatus; + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + } + catch (...) + { + return; + } + + if (locBootEncStatus.ConfiguredEncryptedAreaEnd == -1 + || locBootEncStatus.ConfiguredEncryptedAreaStart == -1) + return; + + InitProgressBar ((locBootEncStatus.ConfiguredEncryptedAreaEnd + - locBootEncStatus.ConfiguredEncryptedAreaStart + 1) / SECTOR_SIZE, + (locBootEncStatus.EncryptedAreaEnd == locBootEncStatus.EncryptedAreaStart || locBootEncStatus.EncryptedAreaEnd == -1) ? + 0 : locBootEncStatus.EncryptedAreaEnd - locBootEncStatus.EncryptedAreaStart + 1, + SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING, + TRUE, + TRUE, + TRUE); +} + +static void UpdateSysEncControls (void) +{ + BootEncryptionStatus locBootEncStatus; + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + } + catch (...) + { + return; + } + + EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), + !locBootEncStatus.SetupInProgress + && SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING); + + SetWindowTextW (GetDlgItem (hCurPage, IDC_PAUSE), + GetString (locBootEncStatus.SetupInProgress ? "IDC_PAUSE" : "RESUME")); + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), !locBootEncStatus.SetupInProgress && !bFirstSysEncResumeDone); + + if (!locBootEncStatus.SetupInProgress) + { + wchar_t tmpStr[100]; + + wcscpy (tmpStr, GetString ((SysDriveOrPartitionFullyEncrypted (TRUE) || !locBootEncStatus.DriveMounted) ? + "PROGRESS_STATUS_FINISHED" : "PROGRESS_STATUS_PAUSED")); + wcscat (tmpStr, L" "); + + // Status + SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), tmpStr); + + if (SysDriveOrPartitionFullyEncrypted (TRUE) || SystemEncryptionStatus == SYSENC_STATUS_NONE) + { + wcscpy (tmpStr, GetString ("PROCESSED_PORTION_100_PERCENT")); + wcscat (tmpStr, L" "); + + SetWindowTextW (GetDlgItem (hCurPage, IDC_BYTESWRITTEN), tmpStr); + } + + SetWindowText (GetDlgItem (hCurPage, IDC_TIMEREMAIN), " "); + } +} + +static void SysEncPause (void) +{ + BootEncryptionStatus locBootEncStatus; + + if (CreateSysEncMutex ()) + { + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + return; + } + + if (!locBootEncStatus.SetupInProgress) + { + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + return; + } + + WaitCursor (); + + try + { + int attempts = SYSENC_PAUSE_RETRIES; + + BootEncObj->AbortSetup (); + + locBootEncStatus = BootEncObj->GetStatus(); + + while (locBootEncStatus.SetupInProgress && attempts > 0) + { + Sleep (SYSENC_PAUSE_RETRY_INTERVAL); + attempts--; + locBootEncStatus = BootEncObj->GetStatus(); + } + + if (!locBootEncStatus.SetupInProgress) + BootEncObj->CheckEncryptionSetupResult (); + + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + NormalCursor (); + + if (locBootEncStatus.SetupInProgress) + { + SetTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS, TIMER_INTERVAL_SYSENC_PROGRESS, NULL); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + Error ("FAILED_TO_INTERRUPT_SYSTEM_ENCRYPTION"); + return; + } + + UpdateSysEncControls (); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + } + else + Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); +} + + +static void SysEncResume (void) +{ + BootEncryptionStatus locBootEncStatus; + + if (CreateSysEncMutex ()) + { + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); + + try + { + locBootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + return; + } + + if (locBootEncStatus.SetupInProgress) + { + bSystemEncryptionInProgress = TRUE; + UpdateSysEncControls (); + SetTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS, TIMER_INTERVAL_SYSENC_PROGRESS, NULL); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + return; + } + + bSystemEncryptionInProgress = FALSE; + WaitCursor (); + + try + { + switch (SystemEncryptionStatus) + { + case SYSENC_STATUS_ENCRYPTING: + + BootEncObj->StartEncryption (nWipeMode, bTryToCorrectReadErrors ? true : false); + break; + + case SYSENC_STATUS_DECRYPTING: + + if (locBootEncStatus.DriveMounted) // If the drive is not encrypted we will just deinstall + BootEncObj->StartDecryption (DiscardUnreadableEncryptedSectors); + + break; + } + + bSystemEncryptionInProgress = TRUE; + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + NormalCursor (); + + if (!bSystemEncryptionInProgress) + { + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + Error ("FAILED_TO_RESUME_SYSTEM_ENCRYPTION"); + return; + } + + bFirstSysEncResumeDone = TRUE; + InitSysEncProgressBar (); + UpdateSysEncProgressBar (); + UpdateSysEncControls (); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), TRUE); + SetTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS, TIMER_INTERVAL_SYSENC_PROGRESS, NULL); + } + else + Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); +} + + +static BOOL GetDevicePathForHiddenOS (void) +{ + BOOL tmpbDevice = FALSE; + + try + { + strncpy (szFileName, BootEncObj->GetPartitionForHiddenOS().DevicePath.c_str(), sizeof(szFileName)); + + CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); + } + catch (Exception &e) + { + e.Show (MainDlg); + return FALSE; + } + + return (szFileName[0] != 0 + && szDiskFile[0] != 0 + && tmpbDevice); +} + + +// Returns TRUE if there is unallocated space greater than 64 MB (max possible slack space size) between the +// boot partition and the first partition behind it. If there's none or if an error occurs, returns FALSE. +static BOOL CheckGapBetweenSysAndHiddenOS (void) +{ + try + { + SystemDriveConfiguration sysDriveCfg = BootEncObj->GetSystemDriveConfiguration(); + + return (sysDriveCfg.SystemPartition.Info.StartingOffset.QuadPart + + sysDriveCfg.SystemPartition.Info.PartitionLength.QuadPart + + 64 * BYTES_PER_MB + + 128 * BYTES_PER_KB + <= BootEncObj->GetPartitionForHiddenOS().Info.StartingOffset.QuadPart); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + return FALSE; +} + + +static void NonSysInplaceEncPause (void) +{ + bVolTransformThreadCancel = TRUE; + + WaitCursor (); + + int waitThreshold = 100; // Do not block GUI events for more than 10 seconds. IMPORTANT: This prevents deadlocks when the thread calls us back e.g. to update GUI! + + while (bVolTransformThreadRunning || bVolTransformThreadToRun) + { + MSG guiMsg; + + bVolTransformThreadCancel = TRUE; + + if (waitThreshold <= 0) + { + while (PeekMessage (&guiMsg, NULL, 0, 0, PM_REMOVE) != 0) + { + DispatchMessage (&guiMsg); + } + } + else + waitThreshold--; + + Sleep (100); + } +} + + +static void NonSysInplaceEncResume (void) +{ + if (bVolTransformThreadRunning || bVolTransformThreadToRun || bVolTransformThreadCancel) + return; + + if (!bInPlaceEncNonSysResumed + && !FinalPreTransformPrompts ()) + { + return; + } + + CreateNonSysInplaceEncMutex (); + + bFirstNonSysInPlaceEncResumeDone = TRUE; + + SetTimer (MainDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS, TIMER_INTERVAL_NONSYS_INPLACE_ENC_PROGRESS, NULL); + + bVolTransformThreadCancel = FALSE; + bVolTransformThreadToRun = TRUE; + + UpdateNonSysInPlaceEncControls (); + + LastDialogId = "NONSYS_INPLACE_ENC_IN_PROGRESS"; + + _beginthread (volTransformThreadFunction, 0, MainDlg); + + return; +} + + +void ShowNonSysInPlaceEncUIStatus (void) +{ + wchar_t nonSysInplaceEncUIStatus [300] = {0}; + + switch (NonSysInplaceEncStatus) + { + case NONSYS_INPLACE_ENC_STATUS_PAUSED: + wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_PAUSED")); + break; + case NONSYS_INPLACE_ENC_STATUS_PREPARING: + wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_PREPARING")); + break; + case NONSYS_INPLACE_ENC_STATUS_RESIZING: + wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_RESIZING")); + break; + case NONSYS_INPLACE_ENC_STATUS_ENCRYPTING: + wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_ENCRYPTING")); + break; + case NONSYS_INPLACE_ENC_STATUS_FINALIZING: + wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_FINALIZING")); + break; + case NONSYS_INPLACE_ENC_STATUS_FINISHED: + wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_FINISHED")); + break; + case NONSYS_INPLACE_ENC_STATUS_ERROR: + wcscpy (nonSysInplaceEncUIStatus, GetString ("PROGRESS_STATUS_ERROR")); + break; + } + + wcscat (nonSysInplaceEncUIStatus, L" "); + + SetWindowTextW (GetDlgItem (hCurPage, IDC_WRITESPEED), nonSysInplaceEncUIStatus); +} + + +void UpdateNonSysInPlaceEncControls (void) +{ + EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), !(bVolTransformThreadRunning || bVolTransformThreadToRun)); + + SetWindowTextW (GetDlgItem (hCurPage, IDC_PAUSE), + GetString ((bVolTransformThreadRunning || bVolTransformThreadToRun) ? "IDC_PAUSE" : "RESUME")); + + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString (bInPlaceEncNonSysResumed ? "DEFER" : "CANCEL")); + + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), bFirstNonSysInPlaceEncResumeDone + && NonSysInplaceEncStatus != NONSYS_INPLACE_ENC_STATUS_FINALIZING + && NonSysInplaceEncStatus != NONSYS_INPLACE_ENC_STATUS_FINISHED); + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), !(bVolTransformThreadRunning || bVolTransformThreadToRun) && !bFirstNonSysInPlaceEncResumeDone); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), !(bVolTransformThreadRunning || bVolTransformThreadToRun) && !bInPlaceEncNonSysResumed); + EnableWindow (GetDlgItem (MainDlg, IDCANCEL), + !(bVolTransformThreadToRun + || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_PREPARING + || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_RESIZING + || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINALIZING + || NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)); + + if (bVolTransformThreadRunning || bVolTransformThreadToRun) + { + switch (NonSysInplaceEncStatus) + { + case NONSYS_INPLACE_ENC_STATUS_PREPARING: + case NONSYS_INPLACE_ENC_STATUS_RESIZING: + case NONSYS_INPLACE_ENC_STATUS_FINALIZING: + ArrowWaitCursor (); + break; + + case NONSYS_INPLACE_ENC_STATUS_ENCRYPTING: + NormalCursor (); + break; + + default: + NormalCursor (); + break; + } + + if (bVolTransformThreadCancel) + WaitCursor (); + } + else + { + NormalCursor (); + + if (bInPlaceEncNonSysResumed) + { + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED); + } + else + SetWindowText (GetDlgItem (hCurPage, IDC_WRITESPEED), " "); + + SetWindowText (GetDlgItem (hCurPage, IDC_TIMEREMAIN), " "); + } + + ShowNonSysInPlaceEncUIStatus (); + + UpdateNonSysInplaceEncProgressBar (); +} + + +static void UpdateNonSysInplaceEncProgressBar (void) +{ + static int lastNonSysInplaceEncStatus = NONSYS_INPLACE_ENC_STATUS_NONE; + int nonSysInplaceEncStatus = NonSysInplaceEncStatus; + __int64 totalSectors; + + totalSectors = NonSysInplaceEncTotalSectors; + + if (bVolTransformThreadRunning + && (nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_ENCRYPTING + || nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINALIZING + || nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)) + { + if (lastNonSysInplaceEncStatus != nonSysInplaceEncStatus + && nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_ENCRYPTING) + { + InitNonSysInplaceEncProgressBar (); + } + else + { + if (totalSectors <= 0 && nVolumeSize > 0) + totalSectors = nVolumeSize / SECTOR_SIZE; + + if (totalSectors > 0) + UpdateProgressBarProc (NonSysInplaceEncBytesDone / SECTOR_SIZE); + } + } + + ShowNonSysInPlaceEncUIStatus (); + + lastNonSysInplaceEncStatus = nonSysInplaceEncStatus; +} + + +static void InitNonSysInplaceEncProgressBar (void) +{ + __int64 totalSectors = NonSysInplaceEncTotalSectors; + + if (totalSectors <= 0) + { + if (nVolumeSize <= 0) + return; + + totalSectors = nVolumeSize / SECTOR_SIZE; + } + + InitProgressBar (totalSectors, + NonSysInplaceEncBytesDone, + FALSE, + TRUE, + TRUE, + TRUE); +} + + +void DisplayRandPool (HWND hPoolDisplay, BOOL bShow) +{ + unsigned char tmp[4]; + unsigned char tmpByte; + int col, row; + static BOOL bRandPoolDispAscii = FALSE; + + if (!bShow) + { + SetWindowText (hPoolDisplay, ""); + return; + } + + RandpeekBytes (randPool, sizeof (randPool)); + + if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) + { + outRandPoolDispBuffer[0] = 0; + + for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) + { + for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) + { + tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; + + sprintf ((char *) tmp, bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != '&') ? " %c " : " . ") : "%02X ", tmpByte); + strcat ((char *) outRandPoolDispBuffer, (char *) tmp); + } + strcat ((char *) outRandPoolDispBuffer, "\n"); + } + SetWindowText (hPoolDisplay, (char *) outRandPoolDispBuffer); + + memcpy (lastRandPool, randPool, sizeof(lastRandPool)); + } +} + + +static void WipeAbort (void) +{ + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); + + if (bHiddenOS && IsHiddenOSRunning()) + { + /* Decoy system partition wipe */ + + DecoySystemWipeStatus decoySysPartitionWipeStatus; + + try + { + decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); + return; + } + + if (!decoySysPartitionWipeStatus.WipeInProgress) + { + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); + return; + } + + WaitCursor (); + + try + { + int attempts = SYSENC_PAUSE_RETRIES; + + BootEncObj->AbortDecoyOSWipe (); + + decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); + + while (decoySysPartitionWipeStatus.WipeInProgress && attempts > 0) + { + Sleep (SYSENC_PAUSE_RETRY_INTERVAL); + attempts--; + decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); + } + + if (!decoySysPartitionWipeStatus.WipeInProgress) + BootEncObj->CheckDecoyOSWipeResult (); + + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + NormalCursor (); + + if (decoySysPartitionWipeStatus.WipeInProgress) + { + SetTimer (MainDlg, TIMER_ID_WIPE_PROGRESS, TIMER_INTERVAL_WIPE_PROGRESS, NULL); + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); + Error ("FAILED_TO_INTERRUPT_WIPING"); + return; + } + } + else + { + /* Regular device wipe (not decoy system partition wipe) */ + } + + UpdateWipeControls (); + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); +} + + +static void WipeStart (void) +{ + if (bHiddenOS && IsHiddenOSRunning()) + { + /* Decoy system partition wipe */ + + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); + + bDeviceWipeInProgress = FALSE; + WaitCursor (); + + try + { + BootEncObj->StartDecoyOSWipe (nWipeMode); + + bDeviceWipeInProgress = TRUE; + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + NormalCursor (); + + if (!bDeviceWipeInProgress) + { + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); + Error ("FAILED_TO_START_WIPING"); + return; + } + } + else + { + /* Regular device wipe (not decoy system partition wipe) */ + } + + InitWipeProgressBar (); + UpdateWipeProgressBar (); + UpdateWipeControls (); + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); + SetTimer (MainDlg, TIMER_ID_WIPE_PROGRESS, TIMER_INTERVAL_WIPE_PROGRESS, NULL); +} + + +static void UpdateWipeProgressBar (void) +{ + if (bHiddenOS && IsHiddenOSRunning()) + { + /* Decoy system partition wipe */ + + DecoySystemWipeStatus decoySysPartitionWipeStatus; + + try + { + decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); + BootEncStatus = BootEncObj->GetStatus(); + } + catch (...) + { + return; + } + + if (decoySysPartitionWipeStatus.WipedAreaEnd == -1) + UpdateProgressBarProc (0); + else + UpdateProgressBarProc ((decoySysPartitionWipeStatus.WipedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1) / SECTOR_SIZE); + } + else + { + /* Regular device wipe (not decoy system partition wipe) */ + } +} + + +static void InitWipeProgressBar (void) +{ + if (bHiddenOS && IsHiddenOSRunning()) + { + /* Decoy system partition wipe */ + + DecoySystemWipeStatus decoySysPartitionWipeStatus; + + try + { + decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); + BootEncStatus = BootEncObj->GetStatus(); + } + catch (...) + { + return; + } + + if (BootEncStatus.ConfiguredEncryptedAreaEnd == -1 + || BootEncStatus.ConfiguredEncryptedAreaStart == -1) + return; + + InitProgressBar ((BootEncStatus.ConfiguredEncryptedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1) / SECTOR_SIZE, + (decoySysPartitionWipeStatus.WipedAreaEnd == BootEncStatus.ConfiguredEncryptedAreaStart || decoySysPartitionWipeStatus.WipedAreaEnd == -1) ? + 0 : decoySysPartitionWipeStatus.WipedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1, + FALSE, + TRUE, + FALSE, + TRUE); + } + else + { + /* Regular device wipe (not decoy system partition wipe) */ + } +} + + +static void UpdateWipeControls (void) +{ + if (bHiddenOS && IsHiddenOSRunning()) + { + /* Decoy system partition wipe */ + + DecoySystemWipeStatus decoySysPartitionWipeStatus; + + try + { + decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); + BootEncStatus = BootEncObj->GetStatus(); + } + catch (...) + { + return; + } + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), !decoySysPartitionWipeStatus.WipeInProgress); + } + else + { + /* Regular device wipe (not decoy system partition wipe) */ + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), bDeviceWipeInProgress); + + if (!bDeviceWipeInProgress) + { + SetWindowText (GetDlgItem (hCurPage, IDC_TIMEREMAIN), " "); + } + } + + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), bDeviceWipeInProgress); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), !bDeviceWipeInProgress); + + bConfirmQuit = bDeviceWipeInProgress; +} + + + +static void __cdecl sysEncDriveAnalysisThread (void *hwndDlgArg) +{ + // Mark the detection process as 'in progress' + HiddenSectorDetectionStatus = 1; + SaveSettings (NULL); + BroadcastSysEncCfgUpdate (); + + try + { + BootEncObj->ProbeRealSystemDriveSize (); + bSysEncDriveAnalysisTimeOutOccurred = FALSE; + } + catch (TimeOut &) + { + bSysEncDriveAnalysisTimeOutOccurred = TRUE; + } + catch (Exception &e) + { + // There was a problem but the system did not freeze. Mark the detection process as completed. + HiddenSectorDetectionStatus = 0; + SaveSettings (NULL); + BroadcastSysEncCfgUpdate (); + + e.Show (NULL); + EndMainDlg (MainDlg); + exit(0); + } + + // Mark the detection process as completed + HiddenSectorDetectionStatus = 0; + SaveSettings (NULL); + BroadcastSysEncCfgUpdate (); + + // This artificial delay prevents user confusion on systems where the analysis ends almost instantly + Sleep (3000); + + bSysEncDriveAnalysisInProgress = FALSE; +} + +static void __cdecl volTransformThreadFunction (void *hwndDlgArg) +{ + int nStatus; + DWORD dwWin32FormatError; + BOOL bHidden; + HWND hwndDlg = (HWND) hwndDlgArg; + volatile FORMAT_VOL_PARAMETERS *volParams = (FORMAT_VOL_PARAMETERS *) malloc (sizeof(FORMAT_VOL_PARAMETERS)); + + if (volParams == NULL) + AbortProcess ("ERR_MEM_ALLOC"); + + VirtualLock ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); + + bVolTransformThreadRunning = TRUE; + bVolTransformThreadToRun = FALSE; + + // Check administrator privileges + if (!IsAdmin () && !IsUacSupported ()) + { + if (fileSystem == FILESYS_NTFS) + { + if (MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_NTFS"), lpszTitle, MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2) == IDCANCEL) + goto cancel; + } + if (bDevice) + { + if (MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_DEVICES"), lpszTitle, MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2) == IDCANCEL) + goto cancel; + } + } + + if (!bInPlaceEncNonSys) + { + if (!bDevice) + { + int x = _access (szDiskFile, 06); + if (x == 0 || errno != ENOENT) + { + wchar_t szTmp[512]; + + if (! ((bHiddenVol && !bHiddenVolHost) && errno != EACCES)) // Only ask ask for permission to overwrite an existing volume if we're not creating a hidden volume + { + _snwprintf (szTmp, sizeof szTmp / 2, + GetString (errno == EACCES ? "READONLYPROMPT" : "OVERWRITEPROMPT"), + szDiskFile); + + x = MessageBoxW (hwndDlg, szTmp, lpszTitle, YES_NO|MB_ICONWARNING|MB_DEFBUTTON2); + + if (x != IDYES) + goto cancel; + } + } + + if (_access (szDiskFile, 06) != 0) + { + if (errno == EACCES) + { + if (_chmod (szDiskFile, _S_IREAD | _S_IWRITE) != 0) + { + MessageBoxW (hwndDlg, GetString ("ACCESSMODEFAIL"), lpszTitle, ICON_HAND); + goto cancel; + } + } + } + + } + else + { + // Partition / device / dynamic volume + + if (!FinalPreTransformPrompts ()) + goto cancel; + } + } + + bHidden = bHiddenVol && !bHiddenVolHost; + + volParams->bDevice = bDevice; + volParams->hiddenVol = bHidden; + volParams->volumePath = szDiskFile; + volParams->size = nVolumeSize; + volParams->hiddenVolHostSize = nHiddenVolHostSize; + volParams->ea = nVolumeEA; + volParams->pkcs5 = hash_algo; + volParams->headerFlags = CreatingHiddenSysVol() ? TC_HEADER_FLAG_ENCRYPTED_SYSTEM : 0; + volParams->fileSystem = fileSystem; + volParams->clusterSize = clusterSize; + volParams->sparseFileSwitch = bSparseFileSwitch; + volParams->quickFormat = quickFormat; + volParams->realClusterSize = &realClusterSize; + volParams->password = &volumePassword; + volParams->hwndDlg = hwndDlg; + + if (bInPlaceEncNonSys) + { + HANDLE hPartition = INVALID_HANDLE_VALUE; + + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PREPARING); + + if (!bInPlaceEncNonSysResumed) + { + bTryToCorrectReadErrors = FALSE; + + nStatus = EncryptPartitionInPlaceBegin (volParams, &hPartition, nWipeMode); + + if (nStatus == ERR_SUCCESS) + { + nStatus = EncryptPartitionInPlaceResume (hPartition, volParams, nWipeMode, &bTryToCorrectReadErrors); + } + else if (hPartition != INVALID_HANDLE_VALUE) + { + CloseHandle (hPartition); + hPartition = INVALID_HANDLE_VALUE; + } + } + else + { + nStatus = EncryptPartitionInPlaceResume (INVALID_HANDLE_VALUE, volParams, nWipeMode, &bTryToCorrectReadErrors); + } + } + else + { + InitProgressBar (GetVolumeDataAreaSize (bHidden, nVolumeSize) / SECTOR_SIZE, 0, FALSE, FALSE, FALSE, TRUE); + + nStatus = TCFormatVolume (volParams); + } + + if (nStatus == ERR_OUTOFMEMORY) + { + AbortProcess ("OUTOFMEMORY"); + } + + if (bInPlaceEncNonSys + && nStatus == ERR_USER_ABORT + && NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED) + { + // Ignore user abort if non-system in-place encryption successfully finished + nStatus = ERR_SUCCESS; + } + + + dwWin32FormatError = GetLastError (); + + if (bHiddenVolHost && !bVolTransformThreadCancel && nStatus == 0) + { + /* Auto mount the newly created hidden volume host */ + switch (MountHiddenVolHost (hwndDlg, szDiskFile, &hiddenVolHostDriveNo, &volumePassword, FALSE)) + { + case ERR_NO_FREE_DRIVES: + MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVE_FOR_OUTER_VOL"), lpszTitle, ICON_HAND); + bVolTransformThreadCancel = TRUE; + break; + case ERR_VOL_MOUNT_FAILED: + case ERR_PASSWORD_WRONG: + MessageBoxW (hwndDlg, GetString ("CANT_MOUNT_OUTER_VOL"), lpszTitle, ICON_HAND); + bVolTransformThreadCancel = TRUE; + break; + } + } + + SetLastError (dwWin32FormatError); + + if ((bVolTransformThreadCancel || nStatus == ERR_USER_ABORT) + && !(bInPlaceEncNonSys && NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)) // Ignore user abort if non-system in-place encryption successfully finished. + { + if (!bDevice && !(bHiddenVol && !bHiddenVolHost)) // If we're not creating a hidden volume and if it's a file container + { + remove (szDiskFile); // Delete the container + } + + goto cancel; + } + + if (nStatus != ERR_USER_ABORT) + { + if (nStatus != 0) + { + /* An error occurred */ + + wchar_t szMsg[8192]; + + handleError (hwndDlg, nStatus); + + if (bInPlaceEncNonSys) + { + if (bInPlaceEncNonSysResumed) + { + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED); + Error ("INPLACE_ENC_GENERIC_ERR_RESUME"); + } + else + { + SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_ERROR); + ShowInPlaceEncErrMsgWAltSteps ("INPLACE_ENC_GENERIC_ERR_ALT_STEPS", TRUE); + } + } + else if (!(bHiddenVolHost && hiddenVolHostDriveNo < 0)) // If the error was not that the hidden volume host could not be mounted (this error has already been reported to the user) + { + swprintf (szMsg, GetString ("CREATE_FAILED"), szDiskFile); + MessageBoxW (hwndDlg, szMsg, lpszTitle, ICON_HAND); + } + + if (!bDevice && !(bHiddenVol && !bHiddenVolHost)) // If we're not creating a hidden volume and if it's a file container + { + remove (szDiskFile); // Delete the container + } + + goto cancel; + } + else + { + /* Volume successfully created */ + + RestoreDefaultKeyFilesParam (); + + if (bDevice && !bInPlaceEncNonSys) + { + // Handle assigned drive letter (if any) + + HandleOldAssignedDriveLetter (); + } + + if (!bHiddenVolHost) + { + if (bHiddenVol) + { + bHiddenVolFinished = TRUE; + + if (!bHiddenOS) + Warning ("HIDVOL_FORMAT_FINISHED_HELP"); + } + else if (bInPlaceEncNonSys) + { + Warning ("NONSYS_INPLACE_ENC_FINISHED_INFO"); + + HandleOldAssignedDriveLetter (); + } + else + { + Info("FORMAT_FINISHED_INFO"); + + if (bSparseFileSwitch && quickFormat) + Warning("SPARSE_FILE_SIZE_NOTE"); + } + } + else + { + /* We've just created an outer volume (to host a hidden volume within) */ + + bHiddenVolHost = FALSE; + bHiddenVolFinished = FALSE; + nHiddenVolHostSize = nVolumeSize; + + // Clear the outer volume password + memset(&szVerify[0], 0, sizeof (szVerify)); + memset(&szRawPassword[0], 0, sizeof (szRawPassword)); + + MessageBeep (MB_OK); + } + + if (!bInPlaceEncNonSys) + SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); + + if (volParams != NULL) + { + burn ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); + VirtualUnlock ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); + free ((LPVOID) volParams); + volParams = NULL; + } + + bVolTransformThreadRunning = FALSE; + bVolTransformThreadCancel = FALSE; + + PostMessage (hwndDlg, bInPlaceEncNonSys ? TC_APPMSG_NONSYS_INPLACE_ENC_FINISHED : TC_APPMSG_FORMAT_FINISHED, 0, 0); + + LastDialogId = "FORMAT_FINISHED"; + _endthread (); + } + } + +cancel: + LastDialogId = (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_CANCELED" : "FORMAT_CANCELED"); + + if (!bInPlaceEncNonSys) + SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); + + if (volParams != NULL) + { + burn ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); + VirtualUnlock ((LPVOID) volParams, sizeof(FORMAT_VOL_PARAMETERS)); + free ((LPVOID) volParams); + volParams = NULL; + } + + bVolTransformThreadRunning = FALSE; + bVolTransformThreadCancel = FALSE; + + PostMessage (hwndDlg, TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED, 0, 0); + + if (bHiddenVolHost && hiddenVolHostDriveNo < -1 && !bVolTransformThreadCancel) // If hidden volume host could not be mounted + AbortProcessSilent (); + + _endthread (); +} + +static void LoadPage (HWND hwndDlg, int nPageNo) +{ + RECT rD, rW; + + nLastPageNo = nCurPageNo; + + if (hCurPage != NULL) + { + // WARNING: nCurPageNo must be set to a non-existent ID here before wiping the password fields below in + // this function, etc. Otherwise, such actions (SetWindowText) would invoke the EN_CHANGE handlers, which + // would, if keyfiles were applied, e.g. use strlen() on a buffer full of random data, in most cases + // not null-terminated. + nCurPageNo = -1; + + + // Place here any actions that need to be performed at the latest possible time when leaving a wizard page + // (i.e. right before "destroying" the page). Also, code that needs to be executed both on IDC_NEXT and + // on IDC_PREV can be placed here so as to avoid code doubling. + + switch (nLastPageNo) + { + case PASSWORD_PAGE: + { + char tmp[MAX_PASSWORD+1]; + + // Attempt to wipe passwords stored in the input field buffers. This is performed here (and + // not in the IDC_PREV or IDC_NEXT sections) in order to prevent certain race conditions + // when keyfiles are used. + memset (tmp, 'X', MAX_PASSWORD); + tmp [MAX_PASSWORD] = 0; + SetWindowText (hPasswordInputField, tmp); + SetWindowText (hVerifyPasswordInputField, tmp); + } + break; + } + + DestroyWindow (hCurPage); + hCurPage = NULL; + } + + // This prevents the mouse pointer from remaining as the "hand" cursor when the user presses Enter + // while hovering over a hyperlink. + bHyperLinkBeingTracked = FALSE; + NormalCursor(); + + GetWindowRect (GetDlgItem (hwndDlg, IDC_POS_BOX), &rW); + + + nCurPageNo = nPageNo; + + + switch (nPageNo) + { + case INTRO_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INTRO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_TYPE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_TYPE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_HIDDEN_OS_REQ_CHECK_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_SPAN_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_SPAN_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_PRE_DRIVE_ANALYSIS_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_DRIVE_ANALYSIS_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_DRIVE_ANALYSIS_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_MULTI_BOOT_MODE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_MULTI_BOOT_MODE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE: + case SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE: + case SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE: + case SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_MULTI_BOOT_OUTCOME_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case VOLUME_TYPE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_VOLUME_TYPE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case HIDDEN_VOL_WIZARD_MODE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_HIDDEN_VOL_WIZARD_MODE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case VOLUME_LOCATION_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_VOLUME_LOCATION_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + + EnableWindow (GetDlgItem(hCurPage, IDC_NO_HISTORY), !bHistoryCmdLine); + + EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), + GetWindowTextLength (GetDlgItem (hCurPage, IDC_COMBO_BOX)) > 0); + + break; + + case DEVICE_TRANSFORM_MODE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_DEVICE_TRANSFORM_MODE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case HIDDEN_VOL_HOST_PRE_CIPHER_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case HIDDEN_VOL_PRE_CIPHER_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case CIPHER_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_CIPHER_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SIZE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SIZE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case HIDDEN_VOL_HOST_PASSWORD_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_PASSWORD_ENTRY_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case PASSWORD_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_PASSWORD_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case FILESYS_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_COLLECTING_RANDOM_DATA_PAGE: + case NONSYS_INPLACE_ENC_RAND_DATA_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_COLLECTING_RANDOM_DATA_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_KEYS_GEN_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_KEYS_GEN_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_RESCUE_DISK_CREATION_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_RESCUE_DISK_CREATION_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_RESCUE_DISK_BURN_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_RESCUE_DISK_BURN_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_RESCUE_DISK_VERIFIED_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_WIPE_MODE_PAGE: + case NONSYS_INPLACE_ENC_WIPE_MODE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_WIPE_MODE_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_PRETEST_INFO_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_PRETEST_RESULT_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case SYSENC_ENCRYPTION_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INPLACE_ENCRYPTION_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_PASSWORD_ENTRY_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_EXPANDED_LIST_SELECT_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INPLACE_ENCRYPTION_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case FORMAT_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_FORMAT_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + case FORMAT_FINISHED_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW ((bHiddenVol && !bHiddenVolHost && !bHiddenVolFinished) ? IDD_HIDVOL_HOST_FILL_PAGE_DLG : IDD_INFO_PAGE_DLG), hwndDlg, + (DLGPROC) PageDialogProc); + break; + + case SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); + break; + + case SYSENC_HIDDEN_OS_WIPE_INFO_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); + break; + + case DEVICE_WIPE_MODE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_DEVICE_WIPE_MODE_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); + break; + + case DEVICE_WIPE_PAGE: + hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_DEVICE_WIPE_PAGE_DLG), hwndDlg, (DLGPROC) PageDialogProc); + break; + } + + rD.left = 162; + rD.top = 25; + rD.right = 0; + rD.bottom = 0; + MapDialogRect (hwndDlg, &rD); + + if (hCurPage != NULL) + { + MoveWindow (hCurPage, rD.left, rD.top, rW.right - rW.left, rW.bottom - rW.top, TRUE); + ShowWindow (hCurPage, SW_SHOWNORMAL); + + // Place here any message boxes that need to be displayed as soon as a new page is displayed. This + // ensures that the page is fully rendered (otherwise it would remain blank, until the message box + // is closed). + switch (nPageNo) + { + case PASSWORD_PAGE: + + CheckCapsLock (hwndDlg, FALSE); + + if (CreatingHiddenSysVol()) + Warning ("PASSWORD_HIDDEN_OS_NOTE"); + + break; + + case CIPHER_PAGE: + + if (CreatingHiddenSysVol()) + Warning ("HIDDEN_OS_PRE_CIPHER_WARNING"); + + break; + } + } +} + + +int PrintFreeSpace (HWND hwndTextBox, char *lpszDrive, PLARGE_INTEGER lDiskFree) +{ + char *nResourceString; + int nMultiplier; + wchar_t szTmp2[256]; + + if (lDiskFree->QuadPart < BYTES_PER_KB) + nMultiplier = 1; + else if (lDiskFree->QuadPart < BYTES_PER_MB) + nMultiplier = BYTES_PER_KB; + else if (lDiskFree->QuadPart < BYTES_PER_GB) + nMultiplier = BYTES_PER_MB; + else + nMultiplier = BYTES_PER_GB; + + if (nMultiplier == 1) + { + if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume + nResourceString = "MAX_HIDVOL_SIZE_BYTES"; + else if (bDevice) + nResourceString = "DEVICE_FREE_BYTES"; + else + nResourceString = "DISK_FREE_BYTES"; + } + else if (nMultiplier == BYTES_PER_KB) + { + if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume + nResourceString = "MAX_HIDVOL_SIZE_KB"; + else if (bDevice) + nResourceString = "DEVICE_FREE_KB"; + else + nResourceString = "DISK_FREE_KB"; + } + else if (nMultiplier == BYTES_PER_MB) + { + if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume + nResourceString = "MAX_HIDVOL_SIZE_MB"; + else if (bDevice) + nResourceString = "DEVICE_FREE_MB"; + else + nResourceString = "DISK_FREE_MB"; + } + else + { + if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume + nResourceString = "MAX_HIDVOL_SIZE_GB"; + else if (bDevice) + nResourceString = "DEVICE_FREE_GB"; + else + nResourceString = "DISK_FREE_GB"; + } + + if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume + { + _snwprintf (szTmp2, sizeof szTmp2 / 2, GetString (nResourceString), ((double) lDiskFree->QuadPart) / nMultiplier); + SetWindowTextW (GetDlgItem (hwndTextBox, IDC_SIZEBOX), szTmp2); + } + else + _snwprintf (szTmp2, sizeof szTmp2 / 2, GetString (nResourceString), lpszDrive, ((double) lDiskFree->QuadPart) / nMultiplier); + + SetWindowTextW (hwndTextBox, szTmp2); + + if (lDiskFree->QuadPart % (__int64) BYTES_PER_MB != 0) + nMultiplier = BYTES_PER_KB; + + return nMultiplier; +} + +void DisplaySizingErrorText (HWND hwndTextBox) +{ + wchar_t szTmp[1024]; + + if (translateWin32Error (szTmp, sizeof (szTmp) / sizeof(szTmp[0]))) + { + wchar_t szTmp2[1024]; + wsprintfW (szTmp2, L"%s\n%s", GetString ("CANNOT_CALC_SPACE"), szTmp); + SetWindowTextW (hwndTextBox, szTmp2); + } + else + { + SetWindowText (hwndTextBox, ""); + } +} + +void EnableDisableFileNext (HWND hComboBox, HWND hMainButton) +{ + LPARAM nIndex = SendMessage (hComboBox, CB_GETCURSEL, 0, 0); + if (bHistory && nIndex == CB_ERR) + { + EnableWindow (hMainButton, FALSE); + SetFocus (hComboBox); + } + else + { + EnableWindow (hMainButton, TRUE); + SetFocus (hMainButton); + } +} + +// Returns TRUE if the file is a sparse file. If it's not a sparse file or in case of any error, returns FALSE. +BOOL IsSparseFile (HWND hwndDlg) +{ + HANDLE hFile; + BY_HANDLE_FILE_INFORMATION bhFileInfo; + + FILETIME ftLastAccessTime; + BOOL bTimeStampValid = FALSE; + + BOOL retCode = FALSE; + + hFile = CreateFile (szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_VOL"), lpszTitle, ICON_HAND); + return FALSE; + } + + if (bPreserveTimestamp) + { + /* Remember the container timestamp (used to reset file date and time of file-hosted + containers to preserve plausible deniability of hidden volumes) */ + if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) + { + bTimeStampValid = FALSE; + MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); + } + else + bTimeStampValid = TRUE; + } + + bhFileInfo.dwFileAttributes = 0; + + GetFileInformationByHandle(hFile, &bhFileInfo); + + retCode = bhFileInfo.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE; + + if (bTimeStampValid) + { + // Restore the container timestamp (to preserve plausible deniability). + if (SetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) + MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PREP_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); + } + CloseHandle (hFile); + return retCode; +} + + +// Note: GetFileVolSize is not to be used for devices (only for file-hosted volumes) +BOOL GetFileVolSize (HWND hwndDlg, unsigned __int64 *size) +{ + LARGE_INTEGER fileSize; + HANDLE hFile; + + FILETIME ftLastAccessTime; + BOOL bTimeStampValid = FALSE; + + hFile = CreateFile (szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_VOL"), lpszTitle, ICON_HAND); + return FALSE; + } + + if (bPreserveTimestamp) + { + /* Remember the container timestamp (used to reset file date and time of file-hosted + containers to preserve plausible deniability of hidden volumes) */ + if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) + { + bTimeStampValid = FALSE; + MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); + } + else + bTimeStampValid = TRUE; + } + + if (GetFileSizeEx(hFile, &fileSize) == 0) + { + MessageBoxW (hwndDlg, GetString ("CANT_GET_VOLSIZE"), lpszTitle, ICON_HAND); + if (bTimeStampValid) + { + // Restore the container timestamp (to preserve plausible deniability). + if (SetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) + MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PREP_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); + } + CloseHandle (hFile); + return FALSE; + } + + if (bTimeStampValid) + { + // Restore the container timestamp (to preserve plausible deniability). + if (SetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0) + MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PREP_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); + } + CloseHandle (hFile); + *size = fileSize.QuadPart; + return TRUE; +} + + +BOOL QueryFreeSpace (HWND hwndDlg, HWND hwndTextBox, BOOL display) +{ + if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume + { + LARGE_INTEGER lDiskFree; + char szTmp[TC_MAX_PATH]; + + lDiskFree.QuadPart = nMaximumHiddenVolSize; + + if (display) + PrintFreeSpace (hwndTextBox, szTmp, &lDiskFree); + + return TRUE; + } + else if (bDevice == FALSE) + { + char root[TC_MAX_PATH]; + ULARGE_INTEGER free; + + if (!GetVolumePathName (szFileName, root, sizeof (root))) + { + handleWin32Error (hwndDlg); + return FALSE; + } + + if (!GetDiskFreeSpaceEx (root, &free, 0, 0)) + { + if (display) + DisplaySizingErrorText (hwndTextBox); + + return FALSE; + } + else + { + LARGE_INTEGER lDiskFree; + lDiskFree.QuadPart = free.QuadPart; + + if (display) + PrintFreeSpace (hwndTextBox, root, &lDiskFree); + + return TRUE; + } + } + else + { + DISK_GEOMETRY driveInfo; + PARTITION_INFORMATION diskInfo; + BOOL piValid = FALSE; + BOOL gValid = FALSE; + + // Query partition size + piValid = GetPartitionInfo (szDiskFile, &diskInfo); + gValid = GetDriveGeometry (szDiskFile, &driveInfo); + + if (!piValid && !gValid) + { + if (display) + DisplaySizingErrorText (hwndTextBox); + + return FALSE; + } + + if (gValid && driveInfo.BytesPerSector != 512) + { + Error ("LARGE_SECTOR_UNSUPPORTED"); + return FALSE; + } + + if (piValid) + { + nVolumeSize = diskInfo.PartitionLength.QuadPart; + + if(display) + nMultiplier = PrintFreeSpace (hwndTextBox, szDiskFile, &diskInfo.PartitionLength); + + nUIVolumeSize = diskInfo.PartitionLength.QuadPart / nMultiplier; + + if (nVolumeSize == 0) + { + if (display) + SetWindowTextW (hwndTextBox, GetString ("EXT_PARTITION")); + + return FALSE; + } + } + else + { + LARGE_INTEGER lDiskFree; + + // Drive geometry info is used only when GetPartitionInfo() fails + lDiskFree.QuadPart = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * + driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; + + nVolumeSize = lDiskFree.QuadPart; + + if (display) + nMultiplier = PrintFreeSpace (hwndTextBox, szDiskFile, &lDiskFree); + + nUIVolumeSize = lDiskFree.QuadPart / nMultiplier; + } + + return TRUE; + } +} + + +static BOOL FinalPreTransformPrompts (void) +{ + int x; + wchar_t szTmp[4096]; + int driveNo; + WCHAR deviceName[MAX_PATH]; + + strcpy ((char *)deviceName, szFileName); + ToUNICODE ((char *)deviceName); + + driveNo = GetDiskDeviceDriveLetter (deviceName); + + if (!(bHiddenVol && !bHiddenVolHost)) // Do not ask for permission to overwrite an existing volume if we're creating a hidden volume within it + { + wchar_t drive[128]; + wchar_t volumeLabel[128]; + wchar_t *type; + BOOL bTmpIsPartition = FALSE; + + type = GetPathType (szFileName, !bInPlaceEncNonSys, &bTmpIsPartition); + + if (driveNo != -1) + { + if (!GetDriveLabel (driveNo, volumeLabel, sizeof (volumeLabel))) + volumeLabel[0] = 0; + + swprintf_s (drive, sizeof (drive)/2, volumeLabel[0] ? L" (%hc: '%s')" : L" (%hc:%s)", 'A' + driveNo, volumeLabel[0] ? volumeLabel : L""); + } + else + { + drive[0] = 0; + volumeLabel[0] = 0; + } + + if (bHiddenOS && bHiddenVolHost) + swprintf (szTmp, GetString ("OVERWRITEPROMPT_DEVICE_HIDDEN_OS_PARTITION"), szFileName, drive); + else + swprintf (szTmp, GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_CONFIRM" : "OVERWRITEPROMPT_DEVICE"), type, szFileName, drive); + + + x = MessageBoxW (MainDlg, szTmp, lpszTitle, YES_NO | MB_ICONWARNING | (bInPlaceEncNonSys ? MB_DEFBUTTON1 : MB_DEFBUTTON2)); + if (x != IDYES) + return FALSE; + + + if (driveNo != -1 && bTmpIsPartition && !bInPlaceEncNonSys) + { + float percentFreeSpace = 100.0; + __int64 occupiedBytes = 0; + + // Do a second check. If we find that the partition contains more than 1GB of data or more than 12% + // of its space is occupied, we will display an extra warning, however, this time it won't be a Yes/No + // dialog box (because users often ignore such dialog boxes). + + if (GetStatsFreeSpaceOnPartition (szFileName, &percentFreeSpace, &occupiedBytes, TRUE) != -1) + { + if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. + || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. + { + wchar_t tmpMcMsg [8000]; + wchar_t tmpMcOption1 [500]; + wchar_t tmpMcOptionCancel [50]; + + wcscpy (tmpMcMsg, GetString("OVERWRITEPROMPT_DEVICE_SECOND_WARNING_LOTS_OF_DATA")); + wcscpy (tmpMcOption1, GetString("ERASE_FILES_BY_CREATING_VOLUME")); + wcscpy (tmpMcOptionCancel, GetString("CANCEL")); + + wcscat (tmpMcMsg, L"\n\n"); + wcscat (tmpMcMsg, GetString("DRIVE_LETTER_ITEM")); + swprintf_s (szTmp, sizeof (szTmp)/2, L"%hc:", 'A' + driveNo); + wcscat (tmpMcMsg, szTmp); + + wcscat (tmpMcMsg, L"\n"); + wcscat (tmpMcMsg, GetString("LABEL_ITEM")); + wcscat (tmpMcMsg, volumeLabel[0] != 0 ? volumeLabel : GetString("NOT_APPLICABLE_OR_NOT_AVAILABLE")); + + wcscat (tmpMcMsg, L"\n"); + wcscat (tmpMcMsg, GetString("SIZE_ITEM")); + GetSizeString (nVolumeSize, szTmp); + wcscat (tmpMcMsg, szTmp); + + wcscat (tmpMcMsg, L"\n"); + wcscat (tmpMcMsg, GetString("PATH_ITEM")); + wcscat (tmpMcMsg, deviceName); + + wchar_t *tmpStr[] = {L"", tmpMcMsg, tmpMcOption1, tmpMcOptionCancel, 0}; + switch (AskMultiChoice ((void **) tmpStr, TRUE)) + { + case 1: + // Proceed + + // NOP + break; + + default: + return FALSE; + } + } + } + } + } + return TRUE; +} + +void HandleOldAssignedDriveLetter (void) +{ + if (bDevice) + { + // Handle assigned drive letter (if any) + + WCHAR deviceName[MAX_PATH]; + int driveLetter = -1; + + strcpy ((char *)deviceName, szDiskFile); + ToUNICODE ((char *)deviceName); + driveLetter = GetDiskDeviceDriveLetter (deviceName); + + if (!bHiddenVolHost + && !bHiddenOS + && driveLetter > 1) // If a drive letter is assigned to the device, but not A: or B: + { + char rootPath[] = { (char) driveLetter + 'A', ':', '\\', 0 }; + wchar_t szTmp[8192]; + + swprintf (szTmp, GetString ("AFTER_FORMAT_DRIVE_LETTER_WARN"), rootPath[0], rootPath[0], rootPath[0], rootPath[0]); + MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING); + } + } +} + + +// Returns TRUE if it makes sense to ask the user whether he wants to store files larger than 4GB in the volume. +static BOOL FileSize4GBLimitQuestionNeeded (void) +{ + uint64 dataAreaSize = GetVolumeDataAreaSize (bHiddenVol && !bHiddenVolHost, nVolumeSize); + + return (dataAreaSize > 4 * BYTES_PER_GB + TC_MIN_FAT_FS_SIZE + && dataAreaSize <= TC_MAX_FAT_FS_SIZE); +} + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static char PageDebugId[128]; + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + + hCurPage = hwndDlg; + + switch (uMsg) + { + case WM_INITDIALOG: + LocalizeDialog (hwndDlg, "IDD_VOL_CREATION_WIZARD_DLG"); + + sprintf (PageDebugId, "FORMAT_PAGE_%d", nCurPageNo); + LastDialogId = PageDebugId; + + switch (nCurPageNo) + { + case INTRO_PAGE: + + SendMessage (GetDlgItem (hwndDlg, IDC_FILE_CONTAINER), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_NONSYS_DEVICE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_SYS_DEVICE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("INTRO_TITLE")); + + ToHyperlink (hwndDlg, IDC_MORE_INFO_ON_CONTAINERS); + ToHyperlink (hwndDlg, IDC_MORE_INFO_ON_SYS_ENCRYPTION); + + EnableWindow (GetDlgItem (hwndDlg, IDC_STD_VOL), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_HIDDEN_VOL), TRUE); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + + UpdateWizardModeControls (hwndDlg, WizardMode); + break; + + case SYSENC_TYPE_PAGE: + + bHiddenVolHost = bHiddenVol = bHiddenOS; + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_TYPE_PAGE_TITLE")); + + SendMessage (GetDlgItem (hwndDlg, IDC_SYSENC_HIDDEN), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_SYSENC_NORMAL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + + CheckButton (GetDlgItem (hwndDlg, bHiddenOS ? IDC_SYSENC_HIDDEN : IDC_SYSENC_NORMAL)); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_TYPE_HELP")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP_SYSENC_NORMAL), GetString ("SYSENC_NORMAL_TYPE_HELP")); + + ToHyperlink (hwndDlg, IDC_HIDDEN_SYSENC_INFO_LINK); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bDirectSysEncMode); + + SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); + break; + + case SYSENC_HIDDEN_OS_REQ_CHECK_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_HELP")); + SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), bDirectSysEncModeCommand != SYSENC_COMMAND_CREATE_HIDDEN_OS && bDirectSysEncModeCommand != SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV); + + ToHyperlink (hwndDlg, IDC_HIDDEN_SYSENC_INFO_LINK); + break; + + case SYSENC_SPAN_PAGE: + + SendMessage (GetDlgItem (hwndDlg, IDC_WHOLE_SYS_DRIVE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_SYS_PARTITION), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_ENCRYPTION_SPAN_TITLE")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDT_WHOLE_SYS_DRIVE), GetString ("SYS_ENCRYPTION_SPAN_WHOLE_SYS_DRIVE_HELP")); + + CheckButton (GetDlgItem (hwndDlg, bWholeSysDrive ? IDC_WHOLE_SYS_DRIVE : IDC_SYS_PARTITION)); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + break; + + + case SYSENC_PRE_DRIVE_ANALYSIS_PAGE: + + Init2RadButtonPageYesNo (SysEncDetectHiddenSectors); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_PRE_DRIVE_ANALYSIS_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_PRE_DRIVE_ANALYSIS_HELP")); + break; + + + case SYSENC_DRIVE_ANALYSIS_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_DRIVE_ANALYSIS_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDT_SYSENC_DRIVE_ANALYSIS_INFO), GetString ("SYSENC_DRIVE_ANALYSIS_INFO")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), FALSE); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), FALSE); + EnableWindow (GetDlgItem (MainDlg, IDCANCEL), FALSE); + + LoadSettings (hwndDlg); + + if (HiddenSectorDetectionStatus == 1) + { + // Detection of hidden sectors was already in progress but it did not finish successfully. + // Ask the user if he wants to try again (to prevent repeated system freezing, etc.) + + char *tmpStr[] = {0, "HIDDEN_SECTOR_DETECTION_FAILED_PREVIOUSLY", "SKIP_HIDDEN_SECTOR_DETECTION", "RETRY_HIDDEN_SECTOR_DETECTION", "IDC_EXIT", 0}; + switch (AskMultiChoice ((void **) tmpStr, FALSE)) + { + case 1: + // Do not try again + LoadPage (MainDlg, SYSENC_DRIVE_ANALYSIS_PAGE + 1); + return 0; + + case 2: + // Try again + break; + + default: + EndMainDlg (MainDlg); + return 0; + } + } + + SetTimer (MainDlg, TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS, TIMER_INTERVAL_SYSENC_DRIVE_ANALYSIS_PROGRESS, NULL); + bSysEncDriveAnalysisInProgress = TRUE; + ArrowWaitCursor (); + SysEncDriveAnalysisStart = GetTickCount (); + InitProgressBar (SYSENC_DRIVE_ANALYSIS_ETA, 0, FALSE, FALSE, FALSE, TRUE); + + _beginthread (sysEncDriveAnalysisThread, 0, hwndDlg); + + break; + + + case SYSENC_MULTI_BOOT_MODE_PAGE: + + SendMessage (GetDlgItem (hwndDlg, IDC_SINGLE_BOOT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_BOOT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_MULTI_BOOT_MODE_TITLE")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); + + RefreshMultiBootControls (hwndDlg); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), nMultiBoot > 0); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); + break; + + + case SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE: + + Init2RadButtonPageYesNo (SysEncMultiBootCfg.SystemOnBootDrive); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_SYS_EQ_BOOT_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_SYS_EQ_BOOT_HELP")); + break; + + + case SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE: + + SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE1), GetString ("DIGIT_ONE")); + SetWindowTextW (GetDlgItem (hCurPage, IDC_CHOICE2), GetString ("TWO_OR_MORE")); + + SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), SysEncMultiBootCfg.NumberOfSysDrives > 0); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), TRUE); + + if (SysEncMultiBootCfg.NumberOfSysDrives == 2) + Update2RadButtonPage (0); // 2 or more drives contain an OS + else if (SysEncMultiBootCfg.NumberOfSysDrives == 1) + Update2RadButtonPage (1); // Only 1 drive contains an OS + else + Update2RadButtonPage (-1); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_HELP")); + break; + + + case SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE: + + Init2RadButtonPageYesNo (SysEncMultiBootCfg.MultipleSystemsOnDrive); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_ADJACENT_SYS_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_ADJACENT_SYS_HELP")); + break; + + + case SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE: + + Init2RadButtonPageYesNo (SysEncMultiBootCfg.BootLoaderBrand); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_HELP")); + break; + + + case SYSENC_MULTI_BOOT_OUTCOME_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_MULTI_BOOT_OUTCOME_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), SysEncMultiBootCfgOutcome); + SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), TRUE); + break; + + + case VOLUME_TYPE_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("VOLUME_TYPE_TITLE")); + + SendMessage (GetDlgItem (hwndDlg, IDC_HIDDEN_VOL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_STD_VOL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + + CheckButton (GetDlgItem (hwndDlg, bHiddenVol ? IDC_HIDDEN_VOL : IDC_STD_VOL)); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_VOLUME_TYPE_HELP")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP_NORMAL_VOL), GetString ("NORMAL_VOLUME_TYPE_HELP")); + + ToHyperlink (hwndDlg, IDC_HIDDEN_VOL_HELP); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + SetWindowTextW (GetDlgItem (MainDlg, IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (MainDlg, IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); + break; + + case HIDDEN_VOL_WIZARD_MODE_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDDEN_VOL_WIZARD_MODE_TITLE")); + + SendMessage (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_DIRECT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_FULL), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + + CheckButton (GetDlgItem (hwndDlg, bHiddenVolDirect ? IDC_HIDVOL_WIZ_MODE_DIRECT : IDC_HIDVOL_WIZ_MODE_FULL)); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_VOL_WIZARD_MODE_NORMAL_HELP")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP2), GetString ("HIDDEN_VOL_WIZARD_MODE_DIRECT_HELP")); + + EnableWindow (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_DIRECT), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_HIDVOL_WIZ_MODE_FULL), TRUE); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + break; + + case VOLUME_LOCATION_PAGE: + { + char *nID; + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_SELECT_VOLUME_LOCATION), + GetString (bDevice ? "IDC_SELECT_DEVICE" : "IDC_SELECT_FILE")); + + if (bHiddenVolDirect && bHiddenVolHost) + { + nID = "FILE_HELP_HIDDEN_HOST_VOL_DIRECT"; + } + else + { + if (bDevice) + nID = bHiddenVolHost ? "DEVICE_HELP_HIDDEN_HOST_VOL" : "DEVICE_HELP"; + else + nID = bHiddenVolHost ? "FILE_HELP_HIDDEN_HOST_VOL" : "FILE_HELP"; + } + + SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_RESETCONTENT, 0, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_LIMITTEXT, TC_MAX_PATH, 0); + + LoadCombo (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); + + SendMessage (GetDlgItem (hwndDlg, IDC_NO_HISTORY), BM_SETCHECK, bHistory ? BST_UNCHECKED : BST_CHECKED, 0); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FILE_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (nID)); + + SetFocus (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + AddComboItem (GetDlgItem (hwndDlg, IDC_COMBO_BOX), szFileName, bHistory); + + EnableDisableFileNext (GetDlgItem (hwndDlg, IDC_COMBO_BOX), + GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); + + } + break; + + case DEVICE_TRANSFORM_MODE_PAGE: + + if (!bDeviceTransformModeChoiceMade && !bInPlaceEncNonSys) + { + // The user has not chosen whether to perform in-place encryption or format yet. + // We will preselect in-place encryption if the requirements are met and if the + // filesystem does not appear empty. + + WaitCursor(); + + if (CheckRequirementsForNonSysInPlaceEnc (szDiskFile, TRUE)) + { + bInPlaceEncNonSys = (FileSystemAppearsEmpty (szDiskFile) == 0); + } + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("DEVICE_TRANSFORM_MODE_PAGE_TITLE")); + + SendMessage (GetDlgItem (hwndDlg, IDC_DEVICE_TRANSFORM_MODE_INPLACE), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_DEVICE_TRANSFORM_MODE_FORMAT), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("DEVICE_TRANSFORM_MODE_PAGE_FORMAT_HELP")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP2), GetString ("DEVICE_TRANSFORM_MODE_PAGE_INPLACE_HELP")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + CheckButton (GetDlgItem (hwndDlg, bInPlaceEncNonSys ? IDC_DEVICE_TRANSFORM_MODE_INPLACE : IDC_DEVICE_TRANSFORM_MODE_FORMAT)); + + NormalCursor(); + + break; + + case HIDDEN_VOL_HOST_PRE_CIPHER_PAGE: + { + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDVOL_HOST_PRE_CIPHER_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bHiddenOS ? "HIDVOL_HOST_PRE_CIPHER_HELP_SYSENC" : "HIDVOL_HOST_PRE_CIPHER_HELP")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + if (bHiddenOS) + { + if (!GetDevicePathForHiddenOS()) + AbortProcess ("INVALID_PATH"); + } + } + break; + + case HIDDEN_VOL_PRE_CIPHER_PAGE: + { + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDVOL_PRE_CIPHER_TITLE")); + + if (bHiddenOS) + { + // Verify whether the clone of the OS fits in the hidden volume (the hidden + // volume is to host a hidden OS). + if (nMaximumHiddenVolSize - TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH < GetSystemPartitionSize()) + { + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_VOLUME_TOO_SMALL_FOR_OS_CLONE")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("EXIT")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + + bConfirmQuit = FALSE; + bConfirmQuitSysEncPretest = FALSE; + } + else + { + // The hidden volume must be as large as the system partition + nVolumeSize = GetSystemPartitionSize() + TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_OS_PRE_CIPHER_HELP")); + } + } + else + { + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDVOL_PRE_CIPHER_HELP")); + } + } + break; + + case CIPHER_PAGE: + { + int ea, hid; + char buf[100]; + + // Encryption algorithms + + SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX), CB_RESETCONTENT, 0, 0); + + if (bHiddenVol) + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "CIPHER_HIDVOL_HOST_TITLE" : "CIPHER_HIDVOL_TITLE")); + else + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("CIPHER_TITLE")); + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (EAIsFormatEnabled (ea)) + AddComboPair (GetDlgItem (hwndDlg, IDC_COMBO_BOX), EAGetName (buf, ea), ea); + } + + SelectAlgo (GetDlgItem (hwndDlg, IDC_COMBO_BOX), &nVolumeEA); + ComboSelChangeEA (hwndDlg); + SetFocus (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); + + ToHyperlink (hwndDlg, IDC_LINK_MORE_INFO_ABOUT_CIPHER); + + // Hash algorithms + + if (SysEncInEffect ()) + { + hash_algo = DEFAULT_HASH_ALGORITHM_BOOT; + RandSetHashFunction (DEFAULT_HASH_ALGORITHM_BOOT); + } + else + hash_algo = RandGetHashFunction(); + + for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) + { + if (!HashIsDeprecated (hid)) + AddComboPair (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), HashGetName(hid), hid); + } + SelectAlgo (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), &hash_algo); + + ToHyperlink (hwndDlg, IDC_LINK_HASH_INFO); + + // Wizard buttons + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + } + break; + + case SIZE_PAGE: + { + wchar_t str[1000]; + + if (bHiddenVolHost) + { + wcsncpy (str, GetString ("SIZE_HELP_HIDDEN_HOST_VOL"), sizeof (str) / 2); + } + else + { + wcsncpy (str, GetString (bHiddenVol ? "SIZE_HELP_HIDDEN_VOL" : "SIZE_HELP"), sizeof (str) / 2); + } + + if (bDevice && !(bHiddenVol && !bHiddenVolHost)) // If raw device but not a hidden volume + { + _snwprintf (str, sizeof str / 2, L"%s%s", + GetString ((bHiddenOS && bHiddenVol) ? "SIZE_PARTITION_HIDDEN_SYSENC_HELP" : "SIZE_PARTITION_HELP"), + (bHiddenVolHost && !bHiddenOS) ? GetString ("SIZE_PARTITION_HIDDEN_VOL_HELP") : L""); + } + + SendMessage (GetDlgItem (hwndDlg, IDC_SPACE_LEFT), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_SIZEBOX), EM_LIMITTEXT, 12, 0); + + if(!QueryFreeSpace (hwndDlg, GetDlgItem (hwndDlg, IDC_SPACE_LEFT), TRUE)) + { + nUIVolumeSize=0; + nVolumeSize=0; + SetWindowTextW (GetDlgItem (hwndDlg, IDC_SIZEBOX), GetString ("UNKNOWN")); + EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_KB), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_MB), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_GB), FALSE); + + } + else if (bDevice && !(bHiddenVol && !bHiddenVolHost)) // If raw device but not a hidden volume + { + EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_KB), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_MB), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_GB), FALSE); + } + else + { + EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_KB), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_MB), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_GB), TRUE); + } + + SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_UNCHECKED, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_UNCHECKED, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_UNCHECKED, 0); + + switch (nMultiplier) + { + case BYTES_PER_KB: + SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_CHECKED, 0); + break; + case BYTES_PER_MB: + SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_CHECKED, 0); + break; + case BYTES_PER_GB: + SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_CHECKED, 0); + break; + } + + if (nUIVolumeSize != 0) + { + char szTmp[32]; + sprintf (szTmp, "%I64u", nUIVolumeSize); + SetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTmp); + } + + SetFocus (GetDlgItem (hwndDlg, IDC_SIZEBOX)); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), str); + + if (bHiddenVol) + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "SIZE_HIDVOL_HOST_TITLE" : "SIZE_HIDVOL_TITLE")); + else + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SIZE_TITLE")); + + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + VerifySizeAndUpdate (hwndDlg, FALSE); + } + break; + + case HIDDEN_VOL_HOST_PASSWORD_PAGE: + case NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE: + + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), EM_LIMITTEXT, MAX_PASSWORD, 0); + + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), szRawPassword); + + SetFocus (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT)); + + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE_HELP" : "PASSWORD_HIDDENVOL_HOST_DIRECT_HELP")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bInPlaceEncNonSys ? "PASSWORD" : "PASSWORD_HIDVOL_HOST_TITLE")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bInPlaceEncNonSys); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + + break; + + case PASSWORD_PAGE: + { + wchar_t str[1000]; + + hPasswordInputField = GetDlgItem (hwndDlg, IDC_PASSWORD); + hVerifyPasswordInputField = GetDlgItem (hwndDlg, IDC_VERIFY); + + if (SysEncInEffect ()) + { + ToBootPwdField (hwndDlg, IDC_PASSWORD); + ToBootPwdField (hwndDlg, IDC_VERIFY); + + sprintf (OrigKeyboardLayout, "%08X", (DWORD) GetKeyboardLayout (NULL) & 0xFFFF); + + if ((DWORD) GetKeyboardLayout (NULL) != 0x00000409 && (DWORD) GetKeyboardLayout (NULL) != 0x04090409) + { + DWORD keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); + EndMainDlg (MainDlg); + return 1; + } + bKeyboardLayoutChanged = TRUE; + } + + ShowWindow(GetDlgItem(hwndDlg, IDC_SHOW_PASSWORD), SW_HIDE); + + if (SetTimer (MainDlg, TIMER_ID_KEYB_LAYOUT_GUARD, TIMER_INTERVAL_KEYB_LAYOUT_GUARD, NULL) == 0) + { + Error ("CANNOT_SET_TIMER"); + EndMainDlg (MainDlg); + return 1; + } + } + + if (bHiddenVolHost) + { + wcsncpy (str, GetString (bHiddenOS ? "PASSWORD_SYSENC_OUTERVOL_HELP" : "PASSWORD_HIDDENVOL_HOST_HELP"), sizeof (str) / 2); + } + else if (bHiddenVol) + { + _snwprintf (str, sizeof str / 2, L"%s%s", + GetString (bHiddenOS ? "PASSWORD_HIDDEN_OS_HELP" : "PASSWORD_HIDDENVOL_HELP"), + GetString ("PASSWORD_HELP")); + } + else + { + wcsncpy (str, GetString ("PASSWORD_HELP"), sizeof (str) / 2); + } + + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), EM_LIMITTEXT, MAX_PASSWORD, 0); + + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), szRawPassword); + SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), szVerify); + + SetFocus (GetDlgItem (hwndDlg, IDC_PASSWORD)); + + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable && !SysEncInEffect()); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEY_FILES), KeyFilesEnable); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), str); + + if (CreatingHiddenSysVol()) + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("PASSWORD_HIDDEN_OS_TITLE")); + else if (bHiddenVol) + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "PASSWORD_HIDVOL_HOST_TITLE" : "PASSWORD_HIDVOL_TITLE")); + else if (WizardMode == WIZARD_MODE_SYS_DEVICE) + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("PASSWORD")); + else + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("PASSWORD_TITLE")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), + GetDlgItem (hwndDlg, IDC_PASSWORD), + GetDlgItem (hwndDlg, IDC_VERIFY), + NULL, + NULL, + KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect()); + volumePassword.Length = strlen ((char *) volumePassword.Text); + } + break; + + case FILESYS_PAGE: + { + wchar_t szTmp[8192]; + + Init2RadButtonPageYesNo (nNeedToStoreFilesOver4GB); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FILESYS_PAGE_TITLE")); + + wcscpy (szTmp, GetString ("FILESYS_PAGE_HELP_QUESTION")); + + if (bHiddenVolHost) + wcscat (szTmp, L"\n\n"); + else + { + wcscat (szTmp, L"\n\n\n"); + wcscat (szTmp, GetString ("NOTE_BEGINNING")); + } + + wcscat (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION")); + + if (bHiddenVolHost) + { + wcscat (szTmp, L" "); + wcscat (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION_HIDVOL")); + } + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), szTmp); + } + break; + + case SYSENC_COLLECTING_RANDOM_DATA_PAGE: + case NONSYS_INPLACE_ENC_RAND_DATA_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("COLLECTING_RANDOM_DATA_TITLE")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + SetTimer (GetParent (hwndDlg), TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); + + hRandPoolSys = GetDlgItem (hwndDlg, IDC_SYS_POOL_CONTENTS); + + SendMessage (GetDlgItem (hwndDlg, IDC_SYS_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + + SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), BM_SETCHECK, showKeys ? BST_CHECKED : BST_UNCHECKED, 0); + + DisplayRandPool (hRandPoolSys, showKeys); + + break; + + case SYSENC_KEYS_GEN_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("KEYS_GEN_TITLE")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + hMasterKey = GetDlgItem (hwndDlg, IDC_DISK_KEY); + hHeaderKey = GetDlgItem (hwndDlg, IDC_HEADER_KEY); + + SendMessage (GetDlgItem (hwndDlg, IDC_DISK_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_HEADER_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + + SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_KEYS), BM_SETCHECK, showKeys ? BST_CHECKED : BST_UNCHECKED, 0); + + SetWindowText (GetDlgItem (hwndDlg, IDC_HEADER_KEY), showKeys ? HeaderKeyGUIView : "******************************** "); + SetWindowText (GetDlgItem (hwndDlg, IDC_DISK_KEY), showKeys ? MasterKeyGUIView : "******************************** "); + + break; + + case SYSENC_RESCUE_DISK_CREATION_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("RESCUE_DISK")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (hwndDlg, IDT_RESCUE_DISK_INFO), GetString ("RESCUE_DISK_INFO")); + SetDlgItemText (hwndDlg, IDC_RESCUE_DISK_ISO_PATH, szRescueDiskISO); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_RESCUE_DISK_ISO_PATH)) > 1)); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + break; + + case SYSENC_RESCUE_DISK_BURN_PAGE: + { + wchar_t szTmp[8192]; + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bDontVerifyRescueDisk ? "RESCUE_DISK_CREATED_TITLE" : "RESCUE_DISK_RECORDING_TITLE")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + _snwprintf (szTmp, sizeof szTmp / 2, + GetString (bDontVerifyRescueDisk ? "RESCUE_DISK_BURN_INFO_NO_CHECK" : "RESCUE_DISK_BURN_INFO"), + szRescueDiskISO, IsWindowsIsoBurnerAvailable() ? L"" : GetString ("RESCUE_DISK_BURN_INFO_NONWIN_ISO_BURNER")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDT_RESCUE_DISK_BURN_INFO), szTmp); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + + /* The 'Back' button must be disabled now because the user could burn a Rescue Disk, then go back, and + generate a different master key, which would cause the Rescue Disk verification to fail (the result + would be confusion and bug reports). */ + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + + if (IsWindowsIsoBurnerAvailable()) + SetWindowTextW (GetDlgItem (hwndDlg, IDC_DOWNLOAD_CD_BURN_SOFTWARE), GetString ("LAUNCH_WIN_ISOBURN")); + + ToHyperlink (hwndDlg, IDC_DOWNLOAD_CD_BURN_SOFTWARE); + + if (IsWindowsIsoBurnerAvailable() && !bDontVerifyRescueDisk) + LaunchWindowsIsoBurner (hwndDlg, szRescueDiskISO); + } + break; + + case SYSENC_RESCUE_DISK_VERIFIED_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("RESCUE_DISK_DISK_VERIFIED_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("RESCUE_DISK_VERIFIED_INFO")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + + // Rescue Disk has been verified, no need to go back + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + + // Prevent losing the burned rescue disk by inadvertent exit + bConfirmQuit = TRUE; + + break; + + case SYSENC_WIPE_MODE_PAGE: + case NONSYS_INPLACE_ENC_WIPE_MODE_PAGE: + { + if (nWipeMode == TC_WIPE_1_RAND) + nWipeMode = TC_WIPE_NONE; + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("WIPE_MODE_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDT_WIPE_MODE_INFO), GetString ("INPLACE_ENC_WIPE_MODE_INFO")); + + PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), + SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING && !bInPlaceEncNonSys, + TRUE); + + SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + } + break; + + case SYSENC_PRETEST_INFO_PAGE: + + if (bHiddenOS) + { + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDDEN_OS_CREATION_PREINFO_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("HIDDEN_OS_CREATION_PREINFO_HELP")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("START")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + } + else + { + wchar_t finalMsg[8024] = {0}; + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_ENCRYPTION_PRETEST_TITLE")); + + try + { + wsprintfW (finalMsg, + GetString ("SYS_ENCRYPTION_PRETEST_INFO"), + BootEncObj->GetSystemDriveConfiguration().DriveNumber); + } + catch (Exception &e) + { + e.Show (hwndDlg); + EndMainDlg (MainDlg); + return 0; + } + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), finalMsg); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("TEST")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + + break; + + case SYSENC_PRETEST_RESULT_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYS_ENCRYPTION_PRETEST_RESULT_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYS_ENCRYPTION_PRETEST_RESULT_INFO")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("ENCRYPT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("DEFER")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); + + break; + + case SYSENC_ENCRYPTION_PAGE: + + if (CreateSysEncMutex ()) + { + try + { + BootEncStatus = BootEncObj->GetStatus(); + bSystemEncryptionInProgress = BootEncStatus.SetupInProgress; + } + catch (Exception &e) + { + e.Show (hwndDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + EndMainDlg (MainDlg); + return 0; + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), + GetString (SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING ? "ENCRYPTION" : "DECRYPTION")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_ENCRYPTION_PAGE_INFO")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("DEFER")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), + GetString (SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING ? "ENCRYPT" : "DECRYPT")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_PAUSE), + GetString (bSystemEncryptionInProgress ? "IDC_PAUSE" : "RESUME")); + + EnableWindow (GetDlgItem (hwndDlg, IDC_PAUSE), BootEncStatus.DriveEncrypted); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), !BootEncStatus.SetupInProgress); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDHELP), TRUE); + + ToHyperlink (hwndDlg, IDC_MORE_INFO_SYS_ENCRYPTION); + + if (SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING) + { + nWipeMode = TC_WIPE_NONE; + EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_WIPE_MODE), FALSE); + PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), TRUE, TRUE); + SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); + } + else + { + EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), !bSystemEncryptionInProgress); + PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, TRUE); + SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); + } + + PostMessage (hwndDlg, TC_APPMSG_PERFORM_POST_SYSENC_WMINIT_TASKS, 0, 0); + } + else + { + Error ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + EndMainDlg (MainDlg); + return 0; + } + return 0; + + case NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE: + + { + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FILE_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_RESUME_VOL_SELECT_HELP")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); + + foreach (const HostDevice &device, DeferredNonSysInPlaceEncDevices) + { + SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_ADDSTRING, 0, (LPARAM) device.Path.c_str()); + } + + // Deselect all + SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_SETCURSEL, (WPARAM) -1, 0); + } + + break; + + case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE: + + if (bInPlaceEncNonSysResumed) + { + WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; + + if (LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) != 0) + nWipeMode = savedWipeAlgorithm; + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("ENCRYPTION")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_ENCRYPTION_PAGE_INFO")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString (bInPlaceEncNonSysResumed ? "DEFER" : "CANCEL")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString (bInPlaceEncNonSysResumed ? "RESUME" : "ENCRYPT")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_PAUSE), GetString ("IDC_PAUSE")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bInPlaceEncNonSysResumed); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDHELP), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_PAUSE), FALSE); + + ShowWindow (GetDlgItem (hwndDlg, IDC_MORE_INFO_SYS_ENCRYPTION), SW_HIDE); + + EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), TRUE); + PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, TRUE); + SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); + + break; + + case NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE: + + bConfirmQuit = FALSE; + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("NONSYS_INPLACE_ENC_FINISHED_TITLE")); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_FINISHED_INFO")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("FINALIZE")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("EXIT")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), FALSE); + + break; + + case FORMAT_PAGE: + { + BOOL bNTFSallowed = FALSE; + BOOL bFATallowed = FALSE; + BOOL bNoFSallowed = FALSE; + + SetTimer (GetParent (hwndDlg), TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); + + hMasterKey = GetDlgItem (hwndDlg, IDC_DISK_KEY); + hHeaderKey = GetDlgItem (hwndDlg, IDC_HEADER_KEY); + hRandPool = GetDlgItem (hwndDlg, IDC_RANDOM_BYTES); + + SendMessage (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_DISK_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + SendMessage (GetDlgItem (hwndDlg, IDC_HEADER_KEY), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), + GetString (bHiddenVolHost ? "FORMAT_HIDVOL_HOST_HELP" : "FORMAT_HELP")); + + if (bHiddenVol) + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVolHost ? "FORMAT_HIDVOL_HOST_TITLE" : "FORMAT_HIDVOL_TITLE")); + else + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("FORMAT_TITLE")); + + /* Quick/Dynamic */ + + if (bHiddenVol) + { + quickFormat = !bHiddenVolHost; + bSparseFileSwitch = FALSE; + + SetCheckBox (hwndDlg, IDC_QUICKFORMAT, quickFormat); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), GetString ((bDevice || !bHiddenVolHost) ? "IDC_QUICKFORMAT" : "SPARSE_FILE")); + EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), bDevice && bHiddenVolHost); + } + else + { + if (bDevice) + { + bSparseFileSwitch = FALSE; + SetWindowTextW (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), GetString("IDC_QUICKFORMAT")); + EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), TRUE); + } + else + { + char root[TC_MAX_PATH]; + DWORD fileSystemFlags = 0; + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), GetString("SPARSE_FILE")); + + /* Check if the host file system supports sparse files */ + + if (GetVolumePathName (szFileName, root, sizeof (root))) + { + GetVolumeInformation (root, NULL, 0, NULL, NULL, &fileSystemFlags, NULL, 0); + bSparseFileSwitch = fileSystemFlags & FILE_SUPPORTS_SPARSE_FILES; + } + else + bSparseFileSwitch = FALSE; + + EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKFORMAT), bSparseFileSwitch); + } + } + + SendMessage (GetDlgItem (hwndDlg, IDC_SHOW_KEYS), BM_SETCHECK, showKeys ? BST_CHECKED : BST_UNCHECKED, 0); + SetWindowText (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), showKeys ? "" : "******************************** "); + SetWindowText (GetDlgItem (hwndDlg, IDC_HEADER_KEY), showKeys ? "" : "******************************** "); + SetWindowText (GetDlgItem (hwndDlg, IDC_DISK_KEY), showKeys ? "" : "******************************** "); + + SendMessage (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), CB_RESETCONTENT, 0, 0); + AddComboPairW (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), GetString ("DEFAULT"), 0); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "0.5 KB", 1); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "1 KB", 2); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "2 KB", 4); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "4 KB", 8); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "8 KB", 16); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "16 KB", 32); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "32 KB", 64); + AddComboPair (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), "64 KB", 128); + SendMessage (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), CB_SETCURSEL, 0, 0); + + EnableWindow (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), TRUE); + + /* Filesystems */ + + bNTFSallowed = FALSE; + bFATallowed = FALSE; + bNoFSallowed = FALSE; + + SendMessage (GetDlgItem (hwndDlg, IDC_FILESYS), CB_RESETCONTENT, 0, 0); + + EnableWindow (GetDlgItem (hwndDlg, IDC_FILESYS), TRUE); + + uint64 dataAreaSize = GetVolumeDataAreaSize (bHiddenVol && !bHiddenVolHost, nVolumeSize); + + if (!CreatingHiddenSysVol()) + { + if (dataAreaSize >= TC_MIN_NTFS_FS_SIZE && dataAreaSize <= TC_MAX_NTFS_FS_SIZE) + { + AddComboPair (GetDlgItem (hwndDlg, IDC_FILESYS), "NTFS", FILESYS_NTFS); + bNTFSallowed = TRUE; + } + + if (dataAreaSize >= TC_MIN_FAT_FS_SIZE && dataAreaSize <= TC_MAX_FAT_FS_SIZE) + { + AddComboPair (GetDlgItem (hwndDlg, IDC_FILESYS), "FAT", FILESYS_FAT); + bFATallowed = TRUE; + } + } + else + { + // We're creating a hidden volume for a hidden OS, so we don't need to format it with + // any filesystem (the entire OS will be copied to the hidden volume sector by sector). + EnableWindow (GetDlgItem (hwndDlg, IDC_FILESYS), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_CLUSTERSIZE), FALSE); + } + + if (!bHiddenVolHost) + { + AddComboPairW (GetDlgItem (hwndDlg, IDC_FILESYS), GetString ("NONE"), FILESYS_NONE); + bNoFSallowed = TRUE; + } + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + + if (fileSystem == FILESYS_NONE) // If no file system has been previously selected + { + // Set default file system + + if (bFATallowed && !(nNeedToStoreFilesOver4GB == 1 && bNTFSallowed)) + fileSystem = FILESYS_FAT; + else if (bNTFSallowed) + fileSystem = FILESYS_NTFS; + else if (bNoFSallowed) + fileSystem = FILESYS_NONE; + else + { + AddComboPair (GetDlgItem (hwndDlg, IDC_FILESYS), "---", 0); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); + } + } + + SendMessage (GetDlgItem (hwndDlg, IDC_FILESYS), CB_SETCURSEL, 0, 0); + SelectAlgo (GetDlgItem (hwndDlg, IDC_FILESYS), (int *) &fileSystem); + + EnableWindow (GetDlgItem (hwndDlg, IDC_ABORT_BUTTON), FALSE); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("FORMAT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + SetFocus (GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); + } + break; + + case FORMAT_FINISHED_PAGE: + { + if (!bHiddenVolHost && bHiddenVol && !bHiddenVolFinished) + { + wchar_t msg[4096]; + + nNeedToStoreFilesOver4GB = -1; + + if (bHiddenOS) + { + wchar_t szMaxRecomOuterVolFillSize[100]; + + __int64 maxRecomOuterVolFillSize = 0; + + // Determine the maximum recommended total size of files that can be copied to the outer volume + // while leaving enough space for the hidden volume, which must contain a clone of the OS + + maxRecomOuterVolFillSize = nVolumeSize - GetSystemPartitionSize(); + + // -50% reserve for filesystem "peculiarities" + maxRecomOuterVolFillSize /= 2; + + swprintf (szMaxRecomOuterVolFillSize, L"%I64d %s", maxRecomOuterVolFillSize / BYTES_PER_MB, GetString ("MB")); + + swprintf (msg, GetString ("HIDVOL_HOST_FILLING_HELP_SYSENC"), hiddenVolHostDriveNo + 'A', szMaxRecomOuterVolFillSize); + } + else + swprintf (msg, GetString ("HIDVOL_HOST_FILLING_HELP"), hiddenVolHostDriveNo + 'A'); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), msg); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("HIDVOL_HOST_FILLING_TITLE")); + } + else + { + if (bHiddenOS) + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_VOL_FORMAT_FINISHED_HELP")); + else + { + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_FINISHED_INFO" : "FORMAT_FINISHED_HELP")); + bConfirmQuit = FALSE; + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bHiddenVol ? "HIDVOL_FORMAT_FINISHED_TITLE" : "FORMAT_FINISHED_TITLE")); + } + + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), (!bHiddenVol || bHiddenVolFinished) && !bHiddenOS && !bInPlaceEncNonSys); + + if ((!bHiddenVol || bHiddenVolFinished) && !bHiddenOS) + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("EXIT")); + } + break; + + case SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE: + + if (!IsHiddenOSRunning() || !bHiddenOS) + { + ReportUnexpectedState (SRC_POS); + EndMainDlg (MainDlg); + return 0; + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_HIDDEN_OS_INITIAL_INFO_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("FIRST_HIDDEN_OS_BOOT_INFO")); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("DEFER")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); + break; + + case SYSENC_HIDDEN_OS_WIPE_INFO_PAGE: + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("SYSENC_HIDDEN_OS_WIPE_INFO_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("SYSENC_HIDDEN_OS_WIPE_INFO")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + break; + + case DEVICE_WIPE_MODE_PAGE: + + if (nWipeMode == TC_WIPE_NONE) + nWipeMode = TC_WIPE_1_RAND; + + if (bHiddenOS && IsHiddenOSRunning()) + { + // Decoy system partition wipe + + WipeAbort(); // In case the GUI previously crashed and the driver is still wiping + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL")); + } + else + { + // Regular device wipe (not decoy system partition wipe) + + // Title bar + SetWindowText (MainDlg, TC_APP_NAME); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE); + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("WIPE_MODE_TITLE")); + SetWindowTextW (GetDlgItem (hwndDlg, IDT_WIPE_MODE_INFO), GetString ("WIPE_MODE_INFO")); + + PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, FALSE); + + SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode); + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("NEXT")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV")); + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE); + + break; + + case DEVICE_WIPE_PAGE: + + if (bHiddenOS && IsHiddenOSRunning()) + { + // Decoy system partition wipe + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("DEVICE_WIPE_PAGE_INFO_HIDDEN_OS")); + } + else + { + // Regular device wipe (not decoy system partition wipe) + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("DEVICE_WIPE_PAGE_INFO")); + } + + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("DEVICE_WIPE_PAGE_TITLE")); + SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("WIPE")); + SetWindowTextW (GetDlgItem (hCurPage, IDC_WIPE_MODE), (wstring (L" ") + GetWipeModeName (nWipeMode)).c_str()); + + EnableWindow (GetDlgItem (hwndDlg, IDC_ABORT_BUTTON), FALSE); + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), TRUE); + + break; + } + return 0; + + case WM_HELP: + OpenPageHelp (GetParent (hwndDlg), nCurPageNo); + return 1; + + case TC_APPMSG_PERFORM_POST_SYSENC_WMINIT_TASKS: + AfterSysEncProgressWMInitTasks (hwndDlg); + return 1; + + case WM_COMMAND: + + if (nCurPageNo == INTRO_PAGE) + { + switch (lw) + { + case IDC_FILE_CONTAINER: + UpdateWizardModeControls (hwndDlg, WIZARD_MODE_FILE_CONTAINER); + return 1; + + case IDC_NONSYS_DEVICE: + UpdateWizardModeControls (hwndDlg, WIZARD_MODE_NONSYS_DEVICE); + return 1; + + case IDC_SYS_DEVICE: + UpdateWizardModeControls (hwndDlg, WIZARD_MODE_SYS_DEVICE); + return 1; + + case IDC_MORE_INFO_ON_CONTAINERS: + Applink ("introcontainer", TRUE, ""); + return 1; + + case IDC_MORE_INFO_ON_SYS_ENCRYPTION: + Applink ("introsysenc", TRUE, ""); + return 1; + } + } + + if (nCurPageNo == SYSENC_TYPE_PAGE) + { + switch (lw) + { + case IDC_SYSENC_HIDDEN: + bHiddenOS = TRUE; + bHiddenVol = TRUE; + bHiddenVolHost = TRUE; + return 1; + + case IDC_SYSENC_NORMAL: + bHiddenOS = FALSE; + bHiddenVol = FALSE; + bHiddenVolHost = FALSE; + return 1; + + case IDC_HIDDEN_SYSENC_INFO_LINK: + Applink ("hiddensysenc", TRUE, ""); + return 1; + } + } + + if (nCurPageNo == SYSENC_HIDDEN_OS_REQ_CHECK_PAGE && lw == IDC_HIDDEN_SYSENC_INFO_LINK) + { + Applink ("hiddensysenc", TRUE, ""); + return 1; + } + + if (nCurPageNo == SYSENC_SPAN_PAGE) + { + switch (lw) + { + case IDC_WHOLE_SYS_DRIVE: + bWholeSysDrive = TRUE; + return 1; + case IDC_SYS_PARTITION: + bWholeSysDrive = FALSE; + return 1; + } + + } + + if (nCurPageNo == SYSENC_MULTI_BOOT_MODE_PAGE) + { + switch (lw) + { + case IDC_SINGLE_BOOT: + nMultiBoot = 1; + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + return 1; + case IDC_MULTI_BOOT: + nMultiBoot = 2; + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + return 1; + } + } + + // Dual choice pages + switch (nCurPageNo) + { + case SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE: + case SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE: + case SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE: + case SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE: + case SYSENC_PRE_DRIVE_ANALYSIS_PAGE: + + if (lw == IDC_CHOICE1 || lw == IDC_CHOICE2) + { + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + return 1; + } + break; + } + + if (nCurPageNo == FILESYS_PAGE && (lw == IDC_CHOICE1 || lw == IDC_CHOICE2)) + { + if (bWarnOuterVolSuitableFileSys && lw == IDC_CHOICE1 && bHiddenVolHost) + { + wchar_t szTmp [4096]; + + bWarnOuterVolSuitableFileSys = FALSE; // Do not show this warning anymore (this also prevents potential endless repetition due to some race conditions) + + wcscpy (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION_HIDVOL")); + wcscat (szTmp, L"\n\n"); + wcscat (szTmp, GetString ("FILESYS_PAGE_HELP_EXPLANATION_HIDVOL_CONFIRM")); + + if (MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2) == IDNO) + { + nNeedToStoreFilesOver4GB = 0; + Init2RadButtonPageYesNo (nNeedToStoreFilesOver4GB); + } + } + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + return 1; + } + + if (lw == IDC_HIDDEN_VOL && nCurPageNo == VOLUME_TYPE_PAGE) + { + bHiddenVol = TRUE; + bHiddenVolHost = TRUE; + bInPlaceEncNonSys = FALSE; + return 1; + } + + if (lw == IDC_STD_VOL && nCurPageNo == VOLUME_TYPE_PAGE) + { + bHiddenVol = FALSE; + bHiddenVolHost = FALSE; + return 1; + } + + if (nCurPageNo == SYSENC_ENCRYPTION_PAGE) + { + BootEncryptionStatus locBootEncStatus; + + switch (lw) + { + case IDC_PAUSE: + try + { + locBootEncStatus = BootEncObj->GetStatus(); + + if (locBootEncStatus.SetupInProgress) + SysEncPause (); + else + SysEncResume (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + return 1; + + case IDC_WIPE_MODE: + if (hw == CBN_SELCHANGE) + { + nWipeMode = (WipeAlgorithmId) SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), + CB_GETITEMDATA, + SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), CB_GETCURSEL, 0, 0), + 0); + + return 1; + } + break; + + case IDC_MORE_INFO_SYS_ENCRYPTION: + Applink ("sysencprogressinfo", TRUE, ""); + return 1; + } + } + + if (bInPlaceEncNonSys) + { + switch (nCurPageNo) + { + case NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE: + + if (lw == IDC_LIST_BOX + && (hw == LBN_SELCHANGE || hw == LBN_DBLCLK)) + { + BOOL tmpbDevice = FALSE; + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); + + int selPartitionItemId = (int) SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_GETCURSEL, 0, 0); + + if (selPartitionItemId == LB_ERR) + { + // Deselect all + SendMessage (GetDlgItem (hwndDlg, IDC_LIST_BOX), LB_SETCURSEL, (WPARAM) -1, 0); + + SetFocus (GetDlgItem (MainDlg, IDC_NEXT)); + return 1; + } + + SetFocus (GetDlgItem (MainDlg, IDC_NEXT)); + + strcpy (szFileName, DeferredNonSysInPlaceEncDevices [selPartitionItemId].Path.c_str()); + CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); + + nVolumeSize = GetDeviceSize (szDiskFile); + if (nVolumeSize == -1) + { + handleWin32Error (MainDlg); + return 1; + } + + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + + return 1; + } + break; + + case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE: + { + switch (lw) + { + case IDC_PAUSE: + + // Pause/resume non-system in-place encryption + + if (bVolTransformThreadRunning || bVolTransformThreadToRun) + { + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); + NonSysInplaceEncPause (); + } + else + NonSysInplaceEncResume (); + + return 1; + + case IDC_WIPE_MODE: + if (hw == CBN_SELCHANGE) + { + nWipeMode = (WipeAlgorithmId) SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), + CB_GETITEMDATA, + SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), CB_GETCURSEL, 0, 0), + 0); + + return 1; + } + break; + } + } + break; + } + } + + + if (lw == IDC_OPEN_OUTER_VOLUME && nCurPageNo == FORMAT_FINISHED_PAGE) + { + OpenVolumeExplorerWindow (hiddenVolHostDriveNo); + return 1; + } + + if (lw == IDC_HIDDEN_VOL_HELP && nCurPageNo == VOLUME_TYPE_PAGE) + { + Applink ("hiddenvolume", TRUE, ""); + return 1; + } + + if (lw == IDC_ABORT_BUTTON && nCurPageNo == FORMAT_PAGE) + { + if (MessageBoxW (hwndDlg, GetString ("FORMAT_ABORT"), lpszTitle, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 ) == IDYES) + bVolTransformThreadCancel = TRUE; + return 1; + } + + if (lw == IDC_CIPHER_TEST && nCurPageNo == CIPHER_PAGE) + { + LPARAM nIndex; + int c; + + nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); + nVolumeEA = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); + + for (c = EAGetLastCipher (nVolumeEA); c != 0; c = EAGetPreviousCipher (nVolumeEA, c)) + { + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_CIPHER_TEST_DLG), + GetParent (hwndDlg), (DLGPROC) CipherTestDialogProc, (LPARAM) c); + } + return 1; + } + + if (lw == IDC_WIZ_BENCHMARK && nCurPageNo == CIPHER_PAGE) + { + // Reduce CPU load + bFastPollEnabled = FALSE; + bRandmixEnabled = FALSE; + + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_BENCHMARK_DLG), hwndDlg, + (DLGPROC) BenchmarkDlgProc, (LPARAM) NULL); + + bFastPollEnabled = TRUE; + bRandmixEnabled = TRUE; + + return 1; + } + + if (lw == IDC_LINK_MORE_INFO_ABOUT_CIPHER && nCurPageNo == CIPHER_PAGE) + { + char name[100]; + + int nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); + nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); + EAGetName (name, nIndex); + + if (strcmp (name, "AES") == 0) + Applink ("aes", FALSE, ""); + else if (strcmp (name, "Serpent") == 0) + Applink ("serpent", FALSE, ""); + else if (strcmp (name, "Twofish") == 0) + Applink ("twofish", FALSE, ""); + else if (EAGetCipherCount (nIndex) > 1) + Applink ("cascades", TRUE, ""); + + return 1; + } + + if (lw == IDC_LINK_HASH_INFO && nCurPageNo == CIPHER_PAGE) + { + Applink ("hashalgorithms", TRUE, ""); + return 1; + } + + if (hw == CBN_EDITCHANGE && nCurPageNo == VOLUME_LOCATION_PAGE) + { + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), + GetWindowTextLength (GetDlgItem (hCurPage, IDC_COMBO_BOX)) > 0); + + bDeviceTransformModeChoiceMade = FALSE; + bInPlaceEncNonSys = FALSE; + + return 1; + } + + if (hw == CBN_SELCHANGE && nCurPageNo == VOLUME_LOCATION_PAGE) + { + LPARAM nIndex; + + nIndex = MoveEditToCombo ((HWND) lParam, bHistory); + nIndex = UpdateComboOrder (GetDlgItem (hwndDlg, IDC_COMBO_BOX)); + + if (nIndex != CB_ERR) + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE); + else + EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), FALSE); + + bDeviceTransformModeChoiceMade = FALSE; + bInPlaceEncNonSys = FALSE; + + return 1; + } + + if (hw == EN_CHANGE && nCurPageNo == SIZE_PAGE) + { + VerifySizeAndUpdate (hwndDlg, FALSE); + return 1; + } + + if (hw == EN_CHANGE && nCurPageNo == PASSWORD_PAGE) + { + VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), + GetDlgItem (hwndDlg, IDC_PASSWORD), + GetDlgItem (hwndDlg, IDC_VERIFY), + NULL, + NULL, + KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect()); + volumePassword.Length = strlen ((char *) volumePassword.Text); + + return 1; + } + + if (lw == IDC_SHOW_PASSWORD && nCurPageNo == PASSWORD_PAGE) + { + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD) ? 0 : '*', + 0); + SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD) ? 0 : '*', + 0); + InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); + InvalidateRect (GetDlgItem (hwndDlg, IDC_VERIFY), NULL, TRUE); + return 1; + } + + if (nCurPageNo == PASSWORD_PAGE + || nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) + { + if (lw == IDC_KEY_FILES) + { + if (SysEncInEffect()) + { + Warning ("KEYFILES_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); + return 1; + } + + KeyFilesDlgParam param; + param.EnableKeyFiles = KeyFilesEnable; + param.FirstKeyFile = FirstKeyFile; + + if (IDOK == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, + (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m)) + { + KeyFilesEnable = param.EnableKeyFiles; + FirstKeyFile = param.FirstKeyFile; + + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); + + if (nCurPageNo != HIDDEN_VOL_HOST_PASSWORD_PAGE && nCurPageNo != NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) + EnableWindow (GetDlgItem (hwndDlg, IDC_KEY_FILES), KeyFilesEnable); + + if (nCurPageNo != HIDDEN_VOL_HOST_PASSWORD_PAGE && nCurPageNo != NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) + { + VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), + GetDlgItem (hCurPage, IDC_PASSWORD), + GetDlgItem (hCurPage, IDC_VERIFY), + volumePassword.Text, szVerify, KeyFilesEnable && FirstKeyFile!=NULL); + } + } + + return 1; + } + + if (lw == IDC_KEYFILES_ENABLE) + { + KeyFilesEnable = GetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE); + + if (nCurPageNo != HIDDEN_VOL_HOST_PASSWORD_PAGE && nCurPageNo != NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) + { + EnableWindow (GetDlgItem (hwndDlg, IDC_KEY_FILES), KeyFilesEnable); + + VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (GetParent (hwndDlg), IDC_NEXT), + GetDlgItem (hCurPage, IDC_PASSWORD), + GetDlgItem (hCurPage, IDC_VERIFY), + volumePassword.Text, szVerify, KeyFilesEnable && FirstKeyFile!=NULL); + } + + return 1; + } + } + + if (nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) + { + if (hw == EN_CHANGE) + { + GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), (char *) volumePassword.Text, sizeof (volumePassword.Text)); + volumePassword.Length = strlen ((char *) volumePassword.Text); + return 1; + } + + if (lw == IDC_SHOW_PASSWORD_SINGLE) + { + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_SINGLE) ? 0 : '*', + 0); + InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD_DIRECT), NULL, TRUE); + return 1; + } + } + + if ((lw == IDC_KB || lw == IDC_MB || lw == IDC_GB) && nCurPageNo == SIZE_PAGE) + { + SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_UNCHECKED, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_UNCHECKED, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_UNCHECKED, 0); + + switch (lw) + { + case IDC_KB: + SendMessage (GetDlgItem (hwndDlg, IDC_KB), BM_SETCHECK, BST_CHECKED, 0); + break; + case IDC_MB: + SendMessage (GetDlgItem (hwndDlg, IDC_MB), BM_SETCHECK, BST_CHECKED, 0); + break; + case IDC_GB: + SendMessage (GetDlgItem (hwndDlg, IDC_GB), BM_SETCHECK, BST_CHECKED, 0); + break; + } + + VerifySizeAndUpdate (hwndDlg, FALSE); + return 1; + } + + if (lw == IDC_HIDVOL_WIZ_MODE_DIRECT && nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) + { + bHiddenVolDirect = TRUE; + return 1; + } + + if (lw == IDC_HIDVOL_WIZ_MODE_FULL && nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) + { + bHiddenVolDirect = FALSE; + return 1; + } + + if (lw == IDC_SELECT_VOLUME_LOCATION && nCurPageNo == VOLUME_LOCATION_PAGE) + { + if (!bDevice) + { + // Select file + + if (BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, !bHiddenVolDirect, NULL) == FALSE) + return 1; + + AddComboItem (GetDlgItem (hwndDlg, IDC_COMBO_BOX), szFileName, bHistory); + + EnableDisableFileNext (GetDlgItem (hwndDlg, IDC_COMBO_BOX), + GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); + + return 1; + } + else + { + // Select device + + int nResult = DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_RAWDEVICES_DLG), GetParent (hwndDlg), + (DLGPROC) RawDevicesDlgProc, (LPARAM) & szFileName[0]); + + // Check administrator privileges + if (!strstr (szFileName, "Floppy") && !IsAdmin() && !IsUacSupported ()) + MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_DEVICES"), lpszTitle, MB_OK|MB_ICONWARNING); + + if (nResult == IDOK && strlen (szFileName) > 0) + { + AddComboItem (GetDlgItem (hwndDlg, IDC_COMBO_BOX), szFileName, bHistory); + + EnableDisableFileNext (GetDlgItem (hwndDlg, IDC_COMBO_BOX), + GetDlgItem (GetParent (hwndDlg), IDC_NEXT)); + + bDeviceTransformModeChoiceMade = FALSE; + bInPlaceEncNonSys = FALSE; + } + return 1; + } + } + + if (nCurPageNo == DEVICE_TRANSFORM_MODE_PAGE) + { + switch (lw) + { + case IDC_DEVICE_TRANSFORM_MODE_FORMAT: + + bInPlaceEncNonSys = FALSE; + bDeviceTransformModeChoiceMade = TRUE; + + return 1; + + case IDC_DEVICE_TRANSFORM_MODE_INPLACE: + + bInPlaceEncNonSys = TRUE; + bDeviceTransformModeChoiceMade = TRUE; + + bHiddenVol = FALSE; + bHiddenVolDirect = FALSE; + bHiddenVolHost = FALSE; + bSparseFileSwitch = FALSE; + quickFormat = FALSE; + + return 1; + } + } + + if (lw == IDC_HIDVOL_WIZ_MODE_FULL && nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) + { + bHiddenVolDirect = FALSE; + return 1; + } + + if (hw == CBN_SELCHANGE && nCurPageNo == CIPHER_PAGE) + { + switch (lw) + { + case IDC_COMBO_BOX: + ComboSelChangeEA (hwndDlg); + break; + + case IDC_COMBO_BOX_HASH_ALGO: + if (SysEncInEffect () + && SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), CB_GETITEMDATA, + SendMessage (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), CB_GETCURSEL, 0, 0), 0) + != DEFAULT_HASH_ALGORITHM_BOOT) + { + hash_algo = DEFAULT_HASH_ALGORITHM_BOOT; + RandSetHashFunction (DEFAULT_HASH_ALGORITHM_BOOT); + Info ("ALGO_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); + SelectAlgo (GetDlgItem (hwndDlg, IDC_COMBO_BOX_HASH_ALGO), &hash_algo); + } + break; + } + return 1; + + } + + if (lw == IDC_QUICKFORMAT && IsButtonChecked (GetDlgItem (hCurPage, IDC_QUICKFORMAT))) + { + if (bSparseFileSwitch) + { + if (AskWarnYesNo("CONFIRM_SPARSE_FILE") == IDNO) + SetCheckBox (hwndDlg, IDC_QUICKFORMAT, FALSE); + } + else + { + if (AskWarnYesNo("WARN_QUICK_FORMAT") == IDNO) + SetCheckBox (hwndDlg, IDC_QUICKFORMAT, FALSE); + } + return 1; + } + + if (lw == IDC_FILESYS && hw == CBN_SELCHANGE) + { + fileSystem = SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETITEMDATA, + SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETCURSEL, 0, 0) , 0); + + return 1; + } + + if (lw == IDC_SHOW_KEYS && nCurPageNo == FORMAT_PAGE) + { + showKeys = IsButtonChecked (GetDlgItem (hCurPage, IDC_SHOW_KEYS)); + + SetWindowText (GetDlgItem (hCurPage, IDC_RANDOM_BYTES), showKeys ? " " : "******************************** "); + SetWindowText (GetDlgItem (hCurPage, IDC_HEADER_KEY), showKeys ? "" : "******************************** "); + SetWindowText (GetDlgItem (hCurPage, IDC_DISK_KEY), showKeys ? "" : "******************************** "); + return 1; + } + + if (lw == IDC_DISPLAY_POOL_CONTENTS + && (nCurPageNo == SYSENC_COLLECTING_RANDOM_DATA_PAGE || nCurPageNo == NONSYS_INPLACE_ENC_RAND_DATA_PAGE)) + { + showKeys = IsButtonChecked (GetDlgItem (hCurPage, IDC_DISPLAY_POOL_CONTENTS)); + DisplayRandPool (hRandPoolSys, showKeys); + + return 1; + } + + if (lw == IDC_DISPLAY_KEYS && nCurPageNo == SYSENC_KEYS_GEN_PAGE) + { + showKeys = IsButtonChecked (GetDlgItem (hCurPage, IDC_DISPLAY_KEYS)); + + SetWindowText (GetDlgItem (hwndDlg, IDC_HEADER_KEY), showKeys ? HeaderKeyGUIView : "******************************** "); + SetWindowText (GetDlgItem (hwndDlg, IDC_DISK_KEY), showKeys ? MasterKeyGUIView : "******************************** "); + return 1; + } + + if (nCurPageNo == SYSENC_RESCUE_DISK_CREATION_PAGE) + { + if (lw == IDC_BROWSE) + { + char tmpszRescueDiskISO [TC_MAX_PATH+1]; + + if (!BrowseFiles (hwndDlg, "OPEN_TITLE", tmpszRescueDiskISO, FALSE, TRUE, NULL)) + return 1; + + strcpy (szRescueDiskISO, tmpszRescueDiskISO); + + SetDlgItemText (hwndDlg, IDC_RESCUE_DISK_ISO_PATH, szRescueDiskISO); + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_RESCUE_DISK_ISO_PATH)) > 1)); + return 1; + } + + if ( hw == EN_CHANGE ) + { + GetDlgItemText (hwndDlg, IDC_RESCUE_DISK_ISO_PATH, szRescueDiskISO, sizeof(szRescueDiskISO)); + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_RESCUE_DISK_ISO_PATH)) > 1)); + return 1; + } + } + + if (nCurPageNo == SYSENC_RESCUE_DISK_BURN_PAGE && lw == IDC_DOWNLOAD_CD_BURN_SOFTWARE) + { + if (IsWindowsIsoBurnerAvailable()) + LaunchWindowsIsoBurner (hwndDlg, szRescueDiskISO); + else + Applink ("isoburning", TRUE, ""); + + return 1; + } + + if ((nCurPageNo == SYSENC_WIPE_MODE_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_WIPE_MODE_PAGE + || nCurPageNo == DEVICE_WIPE_MODE_PAGE) + && hw == CBN_SELCHANGE) + { + nWipeMode = (WipeAlgorithmId) SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), + CB_GETITEMDATA, + SendMessage (GetDlgItem (hCurPage, IDC_WIPE_MODE), CB_GETCURSEL, 0, 0), + 0); + + return 1; + } + + if (nCurPageNo == DEVICE_WIPE_PAGE) + { + switch (lw) + { + case IDC_ABORT_BUTTON: + + if (AskWarnNoYes ("CONFIRM_WIPE_ABORT") == IDYES) + WipeAbort(); + + return 1; + } + } + + if (lw == IDC_NO_HISTORY) + { + if (!(bHistory = !IsButtonChecked (GetDlgItem (hCurPage, IDC_NO_HISTORY)))) + ClearHistory (GetDlgItem (hCurPage, IDC_COMBO_BOX)); + + return 1; + } + + return 0; + } + + return 0; +} + +/* Except in response to the WM_INITDIALOG and WM_ENDSESSION messages, the dialog box procedure + should return nonzero if it processes the message, and zero if it does not. - see DialogProc */ +BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + + int nNewPageNo = nCurPageNo; + + switch (uMsg) + { + case WM_INITDIALOG: + { + MainDlg = hwndDlg; + InitDialog (hwndDlg); + LocalizeDialog (hwndDlg, "IDD_VOL_CREATION_WIZARD_DLG"); + + if (IsTrueCryptInstallerRunning()) + AbortProcess ("TC_INSTALLER_IS_RUNNING"); + + // Resize the bitmap if the user has a non-default DPI + if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) + { + hbmWizardBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_WIZARD), + GetDlgItem (hwndDlg, IDC_BITMAP_WIZARD), + 0, 0, 0, 0, FALSE, FALSE); + } + + LoadSettings (hwndDlg); + + LoadDefaultKeyFilesParam (); + RestoreDefaultKeyFilesParam (); + + SysEncMultiBootCfg.NumberOfSysDrives = -1; + SysEncMultiBootCfg.MultipleSystemsOnDrive = -1; + SysEncMultiBootCfg.BootLoaderLocation = -1; + SysEncMultiBootCfg.BootLoaderBrand = -1; + SysEncMultiBootCfg.SystemOnBootDrive = -1; + + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (hwndDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + EndMainDlg (MainDlg); + return 0; + } + + SendMessage (GetDlgItem (hwndDlg, IDC_BOX_TITLE), WM_SETFONT, (WPARAM) hTitleFont, (LPARAM) TRUE); + SetWindowTextW (hwndDlg, lpszTitle); + + ExtractCommandLine (hwndDlg, (char *) lParam); + + if (ComServerMode) + { + InitDialog (hwndDlg); + + if (!ComServerFormat ()) + { + handleWin32Error (hwndDlg); + exit (1); + } + exit (0); + } + + SHGetFolderPath (NULL, CSIDL_MYDOCUMENTS, NULL, 0, szRescueDiskISO); + strcat (szRescueDiskISO, "\\TrueCrypt Rescue Disk.iso"); + + if (IsOSAtLeast (WIN_VISTA)) + { + // Availability of in-place encryption (which is pre-selected by default whenever + // possible) makes partition-hosted volume creation safer. + bWarnDeviceFormatAdvanced = FALSE; + } + +#ifdef _DEBUG + // For faster testing + strcpy (szVerify, "q"); + strcpy (szRawPassword, "q"); +#endif + + PostMessage (hwndDlg, TC_APPMSG_PERFORM_POST_WMINIT_TASKS, 0, 0); + } + return 0; + + case WM_SYSCOMMAND: + if (lw == IDC_ABOUT) + { + DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc); + return 1; + } + return 0; + + case WM_TIMER: + + switch (wParam) + { + case TIMER_ID_RANDVIEW: + + if (WizardMode == WIZARD_MODE_SYS_DEVICE + || bInPlaceEncNonSys) + { + DisplayRandPool (hRandPoolSys, showKeys); + } + else + { + unsigned char tmp[17]; + char tmp2[43]; + int i; + + if (!showKeys) + return 1; + + RandpeekBytes (tmp, sizeof (tmp)); + + tmp2[0] = 0; + + for (i = 0; i < sizeof (tmp); i++) + { + char tmp3[8]; + sprintf (tmp3, "%02X", (int) (unsigned char) tmp[i]); + strcat (tmp2, tmp3); + } + + tmp2[32] = 0; + + SetWindowText (GetDlgItem (hCurPage, IDC_RANDOM_BYTES), tmp2); + + burn (tmp, sizeof(tmp)); + burn (tmp2, sizeof(tmp2)); + } + return 1; + + case TIMER_ID_SYSENC_PROGRESS: + { + // Manage system encryption/decryption and update related GUI + + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + KillTimer (MainDlg, TIMER_ID_SYSENC_PROGRESS); + + try + { + BootEncObj->AbortSetup (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + e.Show (hwndDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + EndMainDlg (MainDlg); + return 1; + } + + if (BootEncStatus.SetupInProgress) + UpdateSysEncProgressBar (); + + if (bSystemEncryptionInProgress != BootEncStatus.SetupInProgress) + { + bSystemEncryptionInProgress = BootEncStatus.SetupInProgress; + + UpdateSysEncProgressBar (); + UpdateSysEncControls (); + + if (!bSystemEncryptionInProgress) + { + // The driver stopped encrypting/decrypting + + KillTimer (hwndDlg, TIMER_ID_SYSENC_PROGRESS); + + try + { + if (BootEncStatus.DriveMounted) // If we had been really encrypting/decrypting (not just proceeding to deinstall) + BootEncObj->CheckEncryptionSetupResult(); + } + catch (SystemException &e) + { + if (!bTryToCorrectReadErrors + && SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING + && (IsDiskReadError (e.ErrorCode))) + { + bTryToCorrectReadErrors = (AskWarnYesNo ("ENABLE_BAD_SECTOR_ZEROING") == IDYES); + + if (bTryToCorrectReadErrors) + { + SysEncResume(); + return 1; + } + } + else if (!DiscardUnreadableEncryptedSectors + && SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING + && (IsDiskReadError (e.ErrorCode))) + { + DiscardUnreadableEncryptedSectors = (AskWarnYesNo ("DISCARD_UNREADABLE_ENCRYPTED_SECTORS") == IDYES); + + if (DiscardUnreadableEncryptedSectors) + { + SysEncResume(); + return 1; + } + } + + e.Show (hwndDlg); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + switch (SystemEncryptionStatus) + { + case SYSENC_STATUS_ENCRYPTING: + + if (BootEncStatus.ConfiguredEncryptedAreaStart == BootEncStatus.EncryptedAreaStart + && BootEncStatus.ConfiguredEncryptedAreaEnd == BootEncStatus.EncryptedAreaEnd) + { + // The partition/drive has been fully encrypted + + ManageStartupSeqWiz (TRUE, ""); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_NEXT), GetString ("FINALIZE")); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); + + WipeHiddenOSCreationConfig(); // For extra conservative security + + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + + Info ("SYSTEM_ENCRYPTION_FINISHED"); + return 1; + } + break; + + case SYSENC_STATUS_DECRYPTING: + + if (!BootEncStatus.DriveEncrypted) + { + // The partition/drive has been fully decrypted + + try + { + // Finalize the process + BootEncObj->Deinstall (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + ManageStartupSeqWiz (TRUE, ""); + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_NEXT), GetString ("FINALIZE")); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), FALSE); + + Info ("SYSTEM_DECRYPTION_FINISHED"); + + return 1; + } + break; + } + } + } + } + return 1; + + case TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS: + + if (bInPlaceEncNonSys) + { + // Non-system in-place encryption + + if (!bVolTransformThreadRunning && !bVolTransformThreadToRun) + { + KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS); + } + + UpdateNonSysInPlaceEncControls (); + } + return 1; + + case TIMER_ID_KEYB_LAYOUT_GUARD: + if (SysEncInEffect ()) + { + DWORD keybLayout = (DWORD) GetKeyboardLayout (NULL); + + /* Watch the keyboard layout */ + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + // Keyboard layout is not standard US + + WipePasswordsAndKeyfiles (); + + SetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD), szRawPassword); + SetWindowText (GetDlgItem (hCurPage, IDC_VERIFY), szVerify); + + keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); + Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); + EndMainDlg (MainDlg); + return 1; + } + + bKeyboardLayoutChanged = TRUE; + + wchar_t szTmp [4096]; + wcscpy (szTmp, GetString ("KEYB_LAYOUT_CHANGE_PREVENTED")); + wcscat (szTmp, L"\n\n"); + wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); + MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + } + + /* Watch the right Alt key (which is used to enter various characters on non-US keyboards) */ + + if (bKeyboardLayoutChanged && !bKeybLayoutAltKeyWarningShown) + { + if (GetAsyncKeyState (VK_RMENU) < 0) + { + bKeybLayoutAltKeyWarningShown = TRUE; + + wchar_t szTmp [4096]; + wcscpy (szTmp, GetString ("ALT_KEY_CHARS_NOT_FOR_SYS_ENCRYPTION")); + wcscat (szTmp, L"\n\n"); + wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); + MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); + } + } + } + return 1; + + case TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS: + + if (bSysEncDriveAnalysisInProgress) + { + UpdateProgressBarProc (GetTickCount() - SysEncDriveAnalysisStart); + + if (GetTickCount() - SysEncDriveAnalysisStart > SYSENC_DRIVE_ANALYSIS_ETA) + { + // It's taking longer than expected -- reinit the progress bar + SysEncDriveAnalysisStart = GetTickCount (); + InitProgressBar (SYSENC_DRIVE_ANALYSIS_ETA, 0, FALSE, FALSE, FALSE, TRUE); + } + + ArrowWaitCursor (); + } + else + { + KillTimer (hwndDlg, TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS); + UpdateProgressBarProc (SYSENC_DRIVE_ANALYSIS_ETA); + Sleep (1500); // User-friendly GUI + + if (bSysEncDriveAnalysisTimeOutOccurred) + Warning ("SYS_DRIVE_SIZE_PROBE_TIMEOUT"); + + LoadPage (hwndDlg, SYSENC_DRIVE_ANALYSIS_PAGE + 1); + } + return 1; + + case TIMER_ID_WIPE_PROGRESS: + + // Manage device wipe and update related GUI + + if (bHiddenOS && IsHiddenOSRunning()) + { + // Decoy system partition wipe + + DecoySystemWipeStatus decoySysPartitionWipeStatus; + + try + { + decoySysPartitionWipeStatus = BootEncObj->GetDecoyOSWipeStatus(); + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + KillTimer (MainDlg, TIMER_ID_WIPE_PROGRESS); + + try + { + BootEncObj->AbortDecoyOSWipe (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + e.Show (hwndDlg); + EndMainDlg (MainDlg); + return 1; + } + + if (decoySysPartitionWipeStatus.WipeInProgress) + { + ArrowWaitCursor (); + + UpdateWipeProgressBar (); + } + + if (bDeviceWipeInProgress != decoySysPartitionWipeStatus.WipeInProgress) + { + bDeviceWipeInProgress = decoySysPartitionWipeStatus.WipeInProgress; + + UpdateWipeProgressBar (); + UpdateWipeControls (); + + if (!bDeviceWipeInProgress) + { + // The driver stopped wiping + + KillTimer (hwndDlg, TIMER_ID_WIPE_PROGRESS); + + try + { + BootEncObj->CheckDecoyOSWipeResult(); + } + catch (Exception &e) + { + e.Show (hwndDlg); + AbortProcessSilent(); + } + + if (BootEncStatus.ConfiguredEncryptedAreaEnd == decoySysPartitionWipeStatus.WipedAreaEnd) + { + // Decoy system partition has been fully wiped + + ChangeHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED); + + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("EXIT")); + EnableWindow (GetDlgItem (MainDlg, IDCANCEL), TRUE); + EnableWindow (GetDlgItem (MainDlg, IDC_PREV), FALSE); + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); + + Info ("WIPE_FINISHED_DECOY_SYSTEM_PARTITION"); + + TextInfoDialogBox (TC_TBXID_DECOY_OS_INSTRUCTIONS); + + if (BootEncObj->GetSystemDriveConfiguration().ExtraBootPartitionPresent) + Warning ("DECOY_OS_VERSION_WARNING"); + + return 1; + } + } + } + } + else + { + // Regular device wipe (not decoy system partition wipe) + + //Info ("WIPE_FINISHED"); + } + return 1; + } + + return 0; + + + case TC_APPMSG_PERFORM_POST_WMINIT_TASKS: + + AfterWMInitTasks (hwndDlg); + return 1; + + case TC_APPMSG_FORMAT_FINISHED: + { + char tmp[RNG_POOL_SIZE*2+1]; + + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREV), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDHELP), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); + SetFocus (GetDlgItem (hwndDlg, IDC_NEXT)); + + if (nCurPageNo == FORMAT_PAGE) + KillTimer (hwndDlg, TIMER_ID_RANDVIEW); + + // Attempt to wipe the GUI fields showing portions of randpool, of the master and header keys + memset (tmp, 'X', sizeof(tmp)); + tmp [sizeof(tmp)-1] = 0; + SetWindowText (hRandPool, tmp); + SetWindowText (hMasterKey, tmp); + SetWindowText (hHeaderKey, tmp); + + LoadPage (hwndDlg, FORMAT_FINISHED_PAGE); + } + return 1; + + case TC_APPMSG_NONSYS_INPLACE_ENC_FINISHED: + + // A partition has just been fully encrypted in place + + KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS); + + LoadPage (hwndDlg, NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE); + + return 1; + + case TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED: + + if (bInPlaceEncNonSys) + { + // In-place encryption was interrupted/paused (did not finish) + + KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS); + + UpdateNonSysInPlaceEncControls (); + } + else + { + // Format has been aborted (did not finish) + + EnableWindow (GetDlgItem (hCurPage, IDC_QUICKFORMAT), (bDevice || bSparseFileSwitch) && !(bHiddenVol && !bHiddenVolHost)); + EnableWindow (GetDlgItem (hCurPage, IDC_FILESYS), TRUE); + EnableWindow (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREV), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDHELP), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), TRUE); + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), TRUE); + SendMessage (GetDlgItem (hCurPage, IDC_PROGRESS_BAR), PBM_SETPOS, 0, 0L); + SetFocus (GetDlgItem (hwndDlg, IDC_NEXT)); + } + + NormalCursor (); + return 1; + + case WM_HELP: + + OpenPageHelp (hwndDlg, nCurPageNo); + return 1; + + case TC_APPMSG_FORMAT_USER_QUIT: + + if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_PAGE + && (bVolTransformThreadRunning || bVolTransformThreadToRun || bInPlaceEncNonSysResumed)) + { + // Non-system encryption in progress + if (AskNoYes ("NONSYS_INPLACE_ENC_DEFER_CONFIRM") == IDYES) + { + NonSysInplaceEncPause (); + + EndMainDlg (hwndDlg); + return 1; + } + else + return 1; // Disallow close + } + else if (bVolTransformThreadRunning || bVolTransformThreadToRun) + { + // Format (non-in-place encryption) in progress + if (AskNoYes ("FORMAT_ABORT") == IDYES) + { + bVolTransformThreadCancel = TRUE; + + EndMainDlg (hwndDlg); + return 1; + } + else + return 1; // Disallow close + } + else if ((nCurPageNo == SYSENC_ENCRYPTION_PAGE || nCurPageNo == SYSENC_PRETEST_RESULT_PAGE) + && SystemEncryptionStatus != SYSENC_STATUS_NONE + && InstanceHasSysEncMutex ()) + { + // System encryption/decryption in progress + + if (AskYesNo (SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING ? + "SYSTEM_DECRYPTION_DEFER_CONFIRM" : "SYSTEM_ENCRYPTION_DEFER_CONFIRM") == IDYES) + { + if (nCurPageNo == SYSENC_PRETEST_RESULT_PAGE) + TextInfoDialogBox (TC_TBXID_SYS_ENC_RESCUE_DISK); + + try + { + BootEncStatus = BootEncObj->GetStatus(); + + if (BootEncStatus.SetupInProgress) + { + BootEncObj->AbortSetupWait (); + Sleep (200); + BootEncStatus = BootEncObj->GetStatus(); + } + + if (!BootEncStatus.SetupInProgress) + { + EndMainDlg (MainDlg); + return 1; + } + else + { + Error ("FAILED_TO_INTERRUPT_SYSTEM_ENCRYPTION"); + return 1; // Disallow close + } + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + return 1; // Disallow close + } + else + return 1; // Disallow close + } + else if (bConfirmQuitSysEncPretest) + { + if (AskWarnNoYes (bHiddenOS ? "CONFIRM_CANCEL_HIDDEN_OS_CREATION" : "CONFIRM_CANCEL_SYS_ENC_PRETEST") == IDNO) + return 1; // Disallow close + } + else if (bConfirmQuit) + { + if (AskWarnNoYes ("CONFIRM_EXIT_UNIVERSAL") == IDNO) + return 1; // Disallow close + } + + if (hiddenVolHostDriveNo > -1) + { + CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); + UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE); + } + + EndMainDlg (hwndDlg); + return 1; + + + case WM_COMMAND: + + if (lw == IDHELP) + { + OpenPageHelp (hwndDlg, nCurPageNo); + return 1; + } + else if (lw == IDCANCEL) + { + PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); + return 1; + } + else if (lw == IDC_NEXT) + { + if (nCurPageNo == INTRO_PAGE) + { + switch (GetSelectedWizardMode (hCurPage)) + { + case WIZARD_MODE_FILE_CONTAINER: + + if (CurrentOSMajor >= 6 && IsUacSupported() && IsAdmin() && !IsBuiltInAdmin() && !IsNonInstallMode()) + { + static bool warningConfirmed = false; + if (!warningConfirmed) + { + if (AskWarnYesNo ("CONTAINER_ADMIN_WARNING") == IDYES) + exit (0); + + warningConfirmed = true; + } + } + + WaitCursor (); + CloseSysEncMutex (); + ChangeWizardMode (WIZARD_MODE_FILE_CONTAINER); + bHiddenOS = FALSE; + bInPlaceEncNonSys = FALSE; + nNewPageNo = VOLUME_TYPE_PAGE - 1; // Skip irrelevant pages + break; + + case WIZARD_MODE_NONSYS_DEVICE: + + WaitCursor (); + CloseSysEncMutex (); + + if (!ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE)) + { + NormalCursor (); + return 1; + } + + bHiddenOS = FALSE; + nNewPageNo = VOLUME_TYPE_PAGE - 1; // Skip irrelevant pages + break; + + case WIZARD_MODE_SYS_DEVICE: + + WaitCursor (); + bHiddenVol = FALSE; + bInPlaceEncNonSys = FALSE; + SwitchWizardToSysEncMode (); + return 1; + } + } + else if (nCurPageNo == SYSENC_TYPE_PAGE) + { + if (bHiddenOS) + { + bWholeSysDrive = FALSE; + bHiddenVolDirect = FALSE; + } + + if (!bHiddenOS) + nNewPageNo = SYSENC_SPAN_PAGE - 1; // Skip irrelevant pages + } + else if (nCurPageNo == SYSENC_HIDDEN_OS_REQ_CHECK_PAGE) + { + WaitCursor (); + try + { + BootEncObj->CheckRequirementsHiddenOS (); + + if (CheckGapBetweenSysAndHiddenOS ()) + Warning ("GAP_BETWEEN_SYS_AND_HIDDEN_OS_PARTITION"); + } + catch (Exception &e) + { + e.Show (hwndDlg); + NormalCursor (); + return 1; + } + + if (AskWarnYesNo ("DECOY_OS_REINSTALL_WARNING") == IDNO) + { + NormalCursor (); + return 1; + } + + WarningDirect ((wstring (GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO")) + + L"\n\n" + + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION")).c_str()); + + if (!IsAdmin() && IsUacSupported()) + { + // If UAC elevation is needed, we need to elevate the complete wizard process here, because + // we will need to switch to the non-sys-device mode, which requires the whole wizard process + // to have admin rights. + + CloseSysEncMutex (); + + if (!ElevateWholeWizardProcess ("/r")) + { + // Failed to obtain admin rights + + NormalCursor (); + + if (!CreateSysEncMutex ()) + AbortProcess ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + + return 1; + } + } + + // This check requires admin rights + try + { + BootEncObj->InitialSecurityChecksForHiddenOS (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + EndMainDlg (MainDlg); // Some of the checks need the wizard to be restarted (results are cached until exit and the checks would fail even if the issues were rectified). + return 1; + } + + nNewPageNo = SYSENC_MULTI_BOOT_MODE_PAGE - 1; // Skip irrelevant pages + } + else if (nCurPageNo == SYSENC_SPAN_PAGE) + { + try + { + if (bWholeSysDrive && !BootEncObj->SystemPartitionCoversWholeDrive()) + { + if (!IsOSAtLeast (WIN_VISTA)) + { + if (BootEncObj->SystemDriveContainsExtendedPartition()) + { + Error ("WDE_UNSUPPORTED_FOR_EXTENDED_PARTITIONS"); + + if (AskYesNo ("ASK_ENCRYPT_PARTITION_INSTEAD_OF_DRIVE") == IDNO) + return 1; + + bWholeSysDrive = FALSE; + } + else + Warning ("WDE_EXTENDED_PARTITIONS_WARNING"); + } + } + + if (!bWholeSysDrive && BootEncObj->SystemPartitionCoversWholeDrive()) + bWholeSysDrive = (AskYesNo ("WHOLE_SYC_DEVICE_RECOM") == IDYES); + } + catch (Exception &e) + { + e.Show (hwndDlg); + NormalCursor (); + return 1; + } + + if (!bWholeSysDrive) + nNewPageNo = SYSENC_MULTI_BOOT_MODE_PAGE - 1; // Skip irrelevant pages + } + else if (nCurPageNo == SYSENC_PRE_DRIVE_ANALYSIS_PAGE) + { + if ((SysEncDetectHiddenSectors = Get2RadButtonPageAnswer()) != 1) + { + // Skip drive analysis + nNewPageNo = SYSENC_DRIVE_ANALYSIS_PAGE; + + // If the user had already searched for hidden sectors, we must clear (invalidate) the + // result because now he changed his mind and no longer wishes to encrypt the hidden sectors. + try + { + BootEncObj->InvalidateCachedSysDriveProperties (); + } + catch (Exception &e) + { + e.Show (MainDlg); + EndMainDlg (MainDlg); + exit(0); + } + } + } + else if (nCurPageNo == SYSENC_MULTI_BOOT_MODE_PAGE) + { + if (nMultiBoot <= 1) + { + if (bHiddenOS) + { + if (IsOSAtLeast (WIN_7) + && BootEncObj->GetSystemDriveConfiguration().ExtraBootPartitionPresent + && AskWarnYesNo ("CONFIRM_HIDDEN_OS_EXTRA_BOOT_PARTITION") == IDNO) + { + TextInfoDialogBox (TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS); + NormalCursor (); + return 1; + } + + if (AskWarnYesNo ("DECOY_OS_REQUIREMENTS") == IDNO) + { + NormalCursor (); + return 1; + } + + if (!ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE)) + { + NormalCursor (); + return 1; + } + + nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE - 1; // Skip irrelevant pages + } + else + nNewPageNo = CIPHER_PAGE - 1; // Skip irrelevant pages + } + else if (bHiddenOS) + AbortProcess ("MULTI_BOOT_HIDDEN_OS_NOT_SUPPORTED"); + else if (AskWarnNoYes ("MULTI_BOOT_FOR_ADVANCED_ONLY") == IDNO) + return 1; + } + else if (nCurPageNo == SYSENC_MULTI_BOOT_SYS_EQ_BOOT_PAGE) + { + SysEncMultiBootCfg.SystemOnBootDrive = Get2RadButtonPageAnswer (); + + if (!SysEncMultiBootCfg.SystemOnBootDrive) + { + Error ("SYS_PARTITION_MUST_BE_ON_BOOT_DRIVE"); + EndMainDlg (MainDlg); + return 1; + } + } + else if (nCurPageNo == SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE) + { + if (Get2RadButtonPageAnswer () == 0) + { + // 2 or more drives contain an OS + + SysEncMultiBootCfg.NumberOfSysDrives = 2; + } + else if (Get2RadButtonPageAnswer () == 1) + { + // Only 1 drive contains an OS + + SysEncMultiBootCfg.NumberOfSysDrives = 1; + + if (bWholeSysDrive) + { + // Whole-system-drive encryption is currently not supported if the drive contains + // more than one system + Error ("WDE_UNSUPPORTED_FOR_MULTIPLE_SYSTEMS_ON_ONE_DRIVE"); + return 1; + } + + // Ask whether there is a non-Windows boot loader in the MBR + nNewPageNo = SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE - 1; + } + } + else if (nCurPageNo == SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE) + { + SysEncMultiBootCfg.MultipleSystemsOnDrive = Get2RadButtonPageAnswer (); + + if (SysEncMultiBootCfg.MultipleSystemsOnDrive && bWholeSysDrive) + { + // Whole-system-drive encryption is currently not supported if the drive contains + // more than one system + Error ("WDE_UNSUPPORTED_FOR_MULTIPLE_SYSTEMS_ON_ONE_DRIVE"); + return 1; + } + } + + else if (nCurPageNo == SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE) + { + SysEncMultiBootCfg.BootLoaderBrand = Get2RadButtonPageAnswer (); + + if (SysEncMultiBootCfg.BootLoaderBrand) + { + // A non-Windows boot manager in the MBR + Error ("CUSTOM_BOOT_MANAGERS_IN_MBR_UNSUPPORTED"); + EndMainDlg (MainDlg); + return 1; + } + else + { + // Either a standard Windows boot manager or no boot manager + wcscpy_s (SysEncMultiBootCfgOutcome, sizeof(SysEncMultiBootCfgOutcome) / 2, GetString ("WINDOWS_BOOT_LOADER_HINTS")); + } + } + + else if (nCurPageNo == SYSENC_MULTI_BOOT_OUTCOME_PAGE) + { + SYSTEMTIME sysTime; + GetLocalTime (&sysTime); + + if (sysTime.wYear <= 2010) + Warning ("MULTI_BOOT_VISTA_SP1"); + + if (bHiddenOS) + { + if (!ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE)) + { + NormalCursor (); + return 1; + } + + nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE - 1; // Skip irrelevant pages + } + else + nNewPageNo = CIPHER_PAGE - 1; // Skip irrelevant pages + } + + else if (nCurPageNo == VOLUME_TYPE_PAGE) + { + if (IsButtonChecked (GetDlgItem (hCurPage, IDC_HIDDEN_VOL))) + { + if (!IsAdmin() && !IsUacSupported () + && IDNO == MessageBoxW (hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_HIDVOL"), + lpszTitle, MB_ICONWARNING|MB_YESNO|MB_DEFBUTTON2)) + { + return 1; + } + else + { + bHiddenVol = TRUE; + bHiddenVolHost = TRUE; + bInPlaceEncNonSys = FALSE; + } + } + else + { + if (IsHiddenOSRunning()) + { + WarningDirect ((wstring (GetString ("CAN_CREATE_ONLY_HIDDEN_VOLUMES_UNDER_HIDDEN_OS")) + + L"\n\n" + + GetString ("NOTE_BEGINNING") + + GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO") + + L" " + + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION")).c_str()); + + NormalCursor (); + return 1; + } + + bHiddenVol = FALSE; + bHiddenVolHost = FALSE; + bHiddenVolDirect = FALSE; + nNewPageNo = VOLUME_LOCATION_PAGE - 1; // Skip the hidden volume creation wizard mode selection + } + } + + else if (nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) + { + if (IsButtonChecked (GetDlgItem (hCurPage, IDC_HIDVOL_WIZ_MODE_DIRECT))) + bHiddenVolDirect = TRUE; + else + { + if (IsHiddenOSRunning()) + { + WarningDirect ((wstring (GetString ("HIDDEN_VOL_CREATION_UNDER_HIDDEN_OS_HOWTO")) + + L"\n\n" + + GetString ("NOTE_BEGINNING") + + GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO") + + L" " + + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION")).c_str()); + NormalCursor (); + return 1; + } + + bHiddenVolDirect = FALSE; + } + } + + else if (nCurPageNo == VOLUME_LOCATION_PAGE) + { + BOOL tmpbDevice; + + WaitCursor(); + + GetWindowText (GetDlgItem (hCurPage, IDC_COMBO_BOX), szFileName, sizeof (szFileName)); + CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); + + if (tmpbDevice != bDevice) + { + if (bDevice) + { + // Not a valid device path + Error ("CANNOT_CALC_SPACE"); + NormalCursor (); + return 1; + } + else + { + if (AskWarnYesNo ("DEVICE_SELECTED_IN_NON_DEVICE_MODE") == IDNO) + { + NormalCursor (); + return 1; + } + + SwitchWizardToNonSysDeviceMode (); + NormalCursor (); + return 1; + } + } + + MoveEditToCombo (GetDlgItem (hCurPage, IDC_COMBO_BOX), bHistory); + + if (IsMountedVolume (szDiskFile)) + { + Error ("ALREADY_MOUNTED"); + NormalCursor (); + return 1; + } + + if (bDevice) + { + switch (IsSystemDevicePath (szDiskFile, hCurPage, TRUE)) + { + case 1: + case 2: + if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE") == IDNO) + { + NormalCursor (); + return 1; + } + szFileName[0] = 0; + szDiskFile[0] = 0; + SwitchWizardToSysEncMode (); + NormalCursor (); + return 1; + + case -1: + // In some environments (such as PE), the system volume is not located on a hard drive. + // Therefore, we must interpret this return code as "Not a system device path" (otherwise, + // non-system devices could not be TC-formatted in such environments). Note that this is + // rather safe, because bReliableRequired is set to TRUE. + + // NOP + break; + } + } + else + { + if (CheckFileExtension(szFileName) + && AskWarnNoYes ("EXE_FILE_EXTENSION_CONFIRM") == IDNO) + { + NormalCursor (); + return 1; + } + } + + bHistory = !IsButtonChecked (GetDlgItem (hCurPage, IDC_NO_HISTORY)); + + SaveSettings (hCurPage); + + if (bHiddenVolDirect && bHiddenVolHost) + { + nNewPageNo = HIDDEN_VOL_HOST_PASSWORD_PAGE - 1; + + if (bDevice) + { + if(!QueryFreeSpace (hwndDlg, GetDlgItem (hwndDlg, IDC_SPACE_LEFT), FALSE)) + { + MessageBoxW (hwndDlg, GetString ("CANT_GET_VOLSIZE"), lpszTitle, ICON_HAND); + NormalCursor (); + return 1; + } + else + nHiddenVolHostSize = nVolumeSize; + } + else + { + if (!GetFileVolSize (hwndDlg, &nHiddenVolHostSize)) + { + NormalCursor (); + return 1; + } + else if (IsSparseFile (hwndDlg)) + { + // Hidden volumes must not be created within sparse file containers + Warning ("HIDDEN_VOL_HOST_SPARSE"); + NormalCursor (); + return 1; + } + } + } + else + { + if (!bHiddenVol && !bDevice) + nNewPageNo = CIPHER_PAGE - 1; + else if (bHiddenVol) + nNewPageNo = (bHiddenVolHost ? HIDDEN_VOL_HOST_PRE_CIPHER_PAGE : HIDDEN_VOL_PRE_CIPHER_PAGE) - 1; + } + } + + else if (nCurPageNo == DEVICE_TRANSFORM_MODE_PAGE) + { + if (bInPlaceEncNonSys) + { + // Check requirements for non-system in-place encryption + + if (!CheckRequirementsForNonSysInPlaceEnc (szDiskFile, FALSE)) + { + return 1; + } + + // We are going to skip the Size page so we must get the size here + nVolumeSize = GetDeviceSize (szDiskFile); + + if (nVolumeSize == -1) + { + handleWin32Error (MainDlg); + return 1; + } + + if (AskWarnYesNo ("NONSYS_INPLACE_ENC_CONFIRM_BACKUP") == IDNO) + return 1; + } + nNewPageNo = CIPHER_PAGE - 1; + } + + else if (nCurPageNo == HIDDEN_VOL_HOST_PRE_CIPHER_PAGE) + { + if (bHiddenVolHost) + nNewPageNo = CIPHER_PAGE - 1; // Skip the info on the hiddem volume + } + + else if (nCurPageNo == CIPHER_PAGE) + { + LPARAM nIndex; + nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); + nVolumeEA = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); + + if (SysEncInEffect () + && EAGetCipherCount (nVolumeEA) > 1) // Cascade? + { + if (AskWarnNoYes ("CONFIRM_CASCADE_FOR_SYS_ENCRYPTION") == IDNO) + return 1; + + Info ("NOTE_CASCADE_FOR_SYS_ENCRYPTION"); + } + + nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETCURSEL, 0, 0); + hash_algo = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETITEMDATA, nIndex, 0); + + RandSetHashFunction (hash_algo); + + if (SysEncInEffect () || bInPlaceEncNonSys) + nNewPageNo = PASSWORD_PAGE - 1; // Skip irrelevant pages + } + + else if (nCurPageNo == SIZE_PAGE) + { + char szFileSystemNameBuffer[256]; + + VerifySizeAndUpdate (hCurPage, TRUE); + + if (!bDevice) + { + /* Verify that the volume would not be too large for the host file system */ + + char root[TC_MAX_PATH]; + + if (GetVolumePathName (szDiskFile, root, sizeof (root)) + && GetVolumeInformation (root, NULL, 0, NULL, NULL, NULL, szFileSystemNameBuffer, sizeof(szFileSystemNameBuffer)) + && !strncmp (szFileSystemNameBuffer, "FAT32", 5)) + { + // The host file system is FAT32 + if (nUIVolumeSize * nMultiplier >= 4 * BYTES_PER_GB) + { + Error ("VOLUME_TOO_LARGE_FOR_FAT32"); + return 1; + } + } + } + + if (bHiddenVol && !bHiddenVolHost) // If it's a hidden volume + { + /* Ask for confirmation if the hidden volume is too large for the user to be + able to write much more data to the outer volume. */ + + if (((double) nUIVolumeSize / (nMaximumHiddenVolSize / nMultiplier)) > 0.85) // 85% + { + if (AskWarnNoYes ("FREE_SPACE_FOR_WRITING_TO_OUTER_VOLUME") == IDNO) + return 1; + } + } + + if (!(bHiddenVolDirect && bHiddenVolHost)) + nNewPageNo = PASSWORD_PAGE - 1; + } + + else if (nCurPageNo == PASSWORD_PAGE) + { + VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (MainDlg, IDC_NEXT), + GetDlgItem (hCurPage, IDC_PASSWORD), + GetDlgItem (hCurPage, IDC_VERIFY), + volumePassword.Text, + szVerify, + KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect()); + + volumePassword.Length = strlen ((char *) volumePassword.Text); + + if (volumePassword.Length > 0) + { + // Password character encoding + if (!CheckPasswordCharEncoding (GetDlgItem (hCurPage, IDC_PASSWORD), NULL)) + { + Error ("UNSUPPORTED_CHARS_IN_PWD"); + return 1; + } + // Check password length (do not check if it's for an outer volume). + else if (!bHiddenVolHost + && !CheckPasswordLength (hwndDlg, GetDlgItem (hCurPage, IDC_PASSWORD))) + { + return 1; + } + } + + // Store the password in case we need to restore it after keyfile is applied to it + GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD), szRawPassword, sizeof (szRawPassword)); + + if (!SysEncInEffect ()) + { + if (KeyFilesEnable) + { + WaitCursor (); + + if (!KeyFilesApply (&volumePassword, FirstKeyFile)) + { + NormalCursor (); + return 1; + } + + NormalCursor (); + } + + } + else + { + KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); + + if (bKeyboardLayoutChanged) + { + // Restore the original keyboard layout + if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) + Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); + else + bKeyboardLayoutChanged = FALSE; + } + + nNewPageNo = SYSENC_COLLECTING_RANDOM_DATA_PAGE - 1; // Skip irrelevant pages + } + + if (bInPlaceEncNonSys) + { + nNewPageNo = NONSYS_INPLACE_ENC_RAND_DATA_PAGE - 1; // Skip irrelevant pages + } + else if (WizardMode != WIZARD_MODE_SYS_DEVICE + && !FileSize4GBLimitQuestionNeeded () + || CreatingHiddenSysVol()) // If we're creating a hidden volume for a hidden OS, we don't need to format it with any filesystem (the entire OS will be copied to the hidden volume sector by sector). + { + nNewPageNo = FORMAT_PAGE - 1; // Skip irrelevant pages + } + } + + else if (nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) + { + WaitCursor (); + + GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), (char *) volumePassword.Text, sizeof (volumePassword.Text)); + volumePassword.Length = strlen ((char *) volumePassword.Text); + + // Store the password in case we need to restore it after keyfile is applied to it + GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), szRawPassword, sizeof (szRawPassword)); + + if (KeyFilesEnable) + { + KeyFilesApply (&volumePassword, FirstKeyFile); + } + + if (!bInPlaceEncNonSys) + { + + /* Mount the volume which is to host the new hidden volume as read only */ + + if (hiddenVolHostDriveNo >= 0) // If the hidden volume host is currently mounted (e.g. after previous unsuccessful dismount attempt) + { + BOOL tmp_result; + + // Dismount the hidden volume host (in order to remount it as read-only subsequently) + while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) + { + if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL) != IDRETRY) + { + // Cancel + NormalCursor(); + return 1; + } + } + if (tmp_result) // If dismounted + hiddenVolHostDriveNo = -1; + } + + if (hiddenVolHostDriveNo < 0) // If the hidden volume host is not mounted + { + int retCode; + + // Mount the hidden volume host as read-only (to ensure consistent and secure + // results of the volume bitmap scanning) + switch (MountHiddenVolHost (hwndDlg, szDiskFile, &hiddenVolHostDriveNo, &volumePassword, TRUE)) + { + case ERR_NO_FREE_DRIVES: + NormalCursor (); + MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVE_FOR_OUTER_VOL"), lpszTitle, ICON_HAND); + return 1; + case ERR_VOL_MOUNT_FAILED: + case ERR_PASSWORD_WRONG: + NormalCursor (); + return 1; + case 0: + + /* Hidden volume host successfully mounted as read-only */ + + WaitCursor (); + + // Verify that the outer volume contains a suitable file system, retrieve cluster size, and + // scan the volume bitmap + if (!IsAdmin () && IsUacSupported ()) + retCode = UacAnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); + else + retCode = AnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); + + switch (retCode) + { + case -1: // Fatal error + CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); + + if (UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE)) + hiddenVolHostDriveNo = -1; + + AbortProcessSilent (); + break; + + case 0: // Unsupported file system (or other non-fatal error which has already been reported) + if (bHiddenVolDirect) + { + CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); + + if (UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE)) + hiddenVolHostDriveNo = -1; + } + NormalCursor (); + return 1; + + case 1: + + // Determine the maximum possible size of the hidden volume + if (DetermineMaxHiddenVolSize (hwndDlg) < 1) + { + // Non-fatal error while determining maximum possible size of the hidden volume + NormalCursor(); + return 1; + } + else + { + BOOL tmp_result; + + /* Maximum possible size of the hidden volume successfully determined */ + + // Dismount the hidden volume host + while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) + { + if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL) != IDRETRY) + { + // Cancel + NormalCursor(); + return 1; + } + } + + if (tmp_result) // If dismounted + { + hiddenVolHostDriveNo = -1; + + bHiddenVolHost = FALSE; + bHiddenVolFinished = FALSE; + + // Clear the outer volume password + WipePasswordsAndKeyfiles (); + + RestoreDefaultKeyFilesParam (); + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); + NormalCursor (); + + nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE; + } + } + break; + } + break; + } + } + } + else + { + /* Scan all available partitions to discover all partitions where non-system in-place + encryption has been interrupted. */ + + BOOL tmpbDevice; + DeferredNonSysInPlaceEncDevices.clear(); + + foreach (const HostDevice &device, GetAvailableHostDevices (true, true)) + { + if (device.IsPartition || device.DynamicVolume) + { + OpenVolumeContext volume; + + if (OpenVolume (&volume, device.Path.c_str(), &volumePassword, FALSE, FALSE, TRUE) == ERR_SUCCESS) + { + if ((volume.CryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0 + && volume.CryptoInfo->EncryptedAreaLength.Value != volume.CryptoInfo->VolumeSize.Value) + { + DeferredNonSysInPlaceEncDevices.push_back (device); + } + + CloseVolume (&volume); + } + } + } + + if (DeferredNonSysInPlaceEncDevices.empty()) + { + Warning ("FOUND_NO_PARTITION_W_DEFERRED_INPLACE_ENC"); + + NormalCursor(); + return 1; + } + else if (DeferredNonSysInPlaceEncDevices.size() == 1) + { + CreateFullVolumePath (szDiskFile, DeferredNonSysInPlaceEncDevices.front().Path.c_str(), &tmpbDevice); + + nVolumeSize = GetDeviceSize (szDiskFile); + if (nVolumeSize == -1) + { + handleWin32Error (MainDlg); + NormalCursor(); + return 1; + } + + nNewPageNo = NONSYS_INPLACE_ENC_ENCRYPTION_PAGE - 1; // Skip irrelevant pages + } + + NormalCursor(); + } + + } + + else if (nCurPageNo == FILESYS_PAGE) + { + if (nNeedToStoreFilesOver4GB != Get2RadButtonPageAnswer()) + fileSystem = FILESYS_NONE; // The user may have gone back and changed the answer, so default file system must be reselected + + nNeedToStoreFilesOver4GB = Get2RadButtonPageAnswer(); + + nNewPageNo = FORMAT_PAGE - 1; // Skip irrelevant pages + } + + else if (nCurPageNo == SYSENC_COLLECTING_RANDOM_DATA_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_RAND_DATA_PAGE) + { + char tmp[RANDPOOL_DISPLAY_SIZE+1]; + + if (!bInPlaceEncNonSys) + { + /* Generate master key and other related data (except the rescue disk) for system encryption. */ + + try + { + WaitCursor(); + BootEncObj->PrepareInstallation (!bWholeSysDrive, volumePassword, nVolumeEA, FIRST_MODE_OF_OPERATION_ID, hash_algo, ""); + } + catch (Exception &e) + { + e.Show (hwndDlg); + NormalCursor (); + return 1; + } + } + + KillTimer (hwndDlg, TIMER_ID_RANDVIEW); + + // Attempt to wipe the GUI field showing portions of randpool + memset (tmp, 'X', sizeof(tmp)); + tmp [sizeof(tmp)-1] = 0; + SetWindowText (hRandPoolSys, tmp); + + NormalCursor (); + } + + else if (nCurPageNo == SYSENC_KEYS_GEN_PAGE) + { + char tmp[KEY_GUI_VIEW_SIZE+1]; + + // Attempt to wipe the GUI fields showing portions of the master and header keys + memset (tmp, 'X', sizeof(tmp)); + tmp [sizeof(tmp)-1] = 0; + SetWindowText (hMasterKey, tmp); + SetWindowText (hHeaderKey, tmp); + } + + else if (nCurPageNo == SYSENC_RESCUE_DISK_CREATION_PAGE) + { + /* Generate rescue disk for boot encryption */ + + GetWindowText (GetDlgItem (hCurPage, IDC_RESCUE_DISK_ISO_PATH), szRescueDiskISO, sizeof (szRescueDiskISO)); + + try + { + WaitCursor(); + BootEncObj->CreateRescueIsoImage (true, szRescueDiskISO); + + } + catch (Exception &e) + { + e.Show (hwndDlg); + NormalCursor (); + return 1; + } + + if (IsWindowsIsoBurnerAvailable() && !bDontVerifyRescueDisk) + Info ("RESCUE_DISK_WIN_ISOBURN_PRELAUNCH_NOTE"); + + NormalCursor (); + } + + else if (nCurPageNo == SYSENC_RESCUE_DISK_BURN_PAGE) + { + if (!bDontVerifyRescueDisk) + { + /* Verify that the rescue disk has been written correctly */ + + try + { + WaitCursor(); + if (!BootEncObj->VerifyRescueDisk ()) + { + wchar_t szTmp[8000]; + + swprintf (szTmp, GetString ("RESCUE_DISK_CHECK_FAILED"), + IsWindowsIsoBurnerAvailable () ? L"" : GetString ("RESCUE_DISK_CHECK_FAILED_SENTENCE_APPENDIX")); + + ErrorDirect (szTmp); + + NormalCursor (); +#ifndef _DEBUG + return 1; +#endif + } + } + catch (Exception &e) + { + e.Show (hwndDlg); + NormalCursor (); + return 1; + } + NormalCursor (); + } + else + { + Warning ("RESCUE_DISK_BURN_NO_CHECK_WARN"); + nNewPageNo = SYSENC_RESCUE_DISK_VERIFIED_PAGE; // Skip irrelevant pages + } + } + + else if (nCurPageNo == SYSENC_WIPE_MODE_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_WIPE_MODE_PAGE) + { + if (nWipeMode > 0 + && AskWarnYesNo ("WIPE_MODE_WARN") == IDNO) + return 1; + } + + else if (nCurPageNo == SYSENC_PRETEST_INFO_PAGE) + { + if (LocalizationActive + && AskWarnYesNo ("PREBOOT_NOT_LOCALIZED") == IDNO) + return 1; + + bConfirmQuitSysEncPretest = TRUE; + + if (!bHiddenOS) // This text is not tailored to hidden OS + TextInfoDialogBox (TC_TBXID_SYS_ENCRYPTION_PRETEST); + + if (AskWarnYesNo ("CONFIRM_RESTART") == IDNO) + return 1; + + /* Install the pre-boot authentication component and initiate the system encryption pretest. + If we are creating a hidden OS, pretest is omitted and OS cloning will follow. */ + + try + { + WaitCursor(); + +#if 0 + // Make sure the Rescue Disk is not in the drive + while (BootEncObj->VerifyRescueDisk ()) + { + Error ("REMOVE_RESCUE_DISK_FROM_DRIVE"); + } +#endif + + BootEncObj->Install (bHiddenOS ? true : false); + } + catch (Exception &e) + { + e.Show (hwndDlg); + Error (bHiddenOS ? "CANNOT_INITIATE_HIDDEN_OS_CREATION" : "CANNOT_INITIATE_SYS_ENCRYPTION_PRETEST"); + NormalCursor (); + return 1; + } + + + /* Add the main TrueCrypt app to the system startup sequence (the TrueCrypt Background Task), which + we need e.g. for notifications about prevented hibernation, about hidden OS leak protection, about + inconsistent hidden OS installs (TrueCrypt upgraded in the decoy system but not in the hidden one), etc. + Note that this must be done before calling ChangeSystemEncryptionStatus(), which broadcasts the change, + so that the main app (if it's running with different cached settings) will not overwrite our new + settings when it exits. */ + bStartOnLogon = TRUE; + SaveSettings (NULL); + ManageStartupSeq (); + + + if (bHiddenOS) + { + /* When we are going to create a hidden OS, the system encryption status is set + to SYSENC_STATUS_PRETEST (not to any special hidden-OS status), in case the XML + configuration file and its properties somehow leaks somewhere outside the system + partition (which will be wiped later on) indicating that a hidden OS has been created + on the computer. Instead, we update our raw config flags in the master boot record + (which is also altered when our boot loader is installed). */ + + if (!ChangeSystemEncryptionStatus (SYSENC_STATUS_PRETEST) + || !ChangeHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING)) + { + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + Error ("CANNOT_INITIATE_HIDDEN_OS_CREATION"); + NormalCursor (); + return 1; + } + } + else if (!ChangeSystemEncryptionStatus (SYSENC_STATUS_PRETEST)) + { + Error ("CANNOT_INITIATE_SYS_ENCRYPTION_PRETEST"); + NormalCursor (); + return 1; + } + + // Add the wizard to the system startup sequence + ManageStartupSeqWiz (FALSE, "/acsysenc"); + + EndMainDlg (MainDlg); + + try + { + BootEncObj->RestartComputer (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + return 1; + } + + else if (nCurPageNo == SYSENC_PRETEST_RESULT_PAGE) + { + TextInfoDialogBox (TC_TBXID_SYS_ENC_RESCUE_DISK); + + // Begin the actual encryption process + + ChangeSystemEncryptionStatus (SYSENC_STATUS_ENCRYPTING); + } + + else if (nCurPageNo == SYSENC_ENCRYPTION_PAGE + && CreateSysEncMutex ()) + { + // The 'Next' button functions as Finish or Resume + + if (SystemEncryptionStatus != SYSENC_STATUS_NONE) + { + try + { + // Resume + SysEncResume (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + } + else + { + // Finish + PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); + } + + return 1; + } + else if (nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE) + { + nNewPageNo = NONSYS_INPLACE_ENC_ENCRYPTION_PAGE - 1; // Skip irrelevant pages + } + else if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_PAGE) + { + /* In-place encryption start (the 'Next' button has been clicked) */ + + NonSysInplaceEncResume (); + return 1; + } + else if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE) + { + PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); + return 1; + } + else if (nCurPageNo == FORMAT_PAGE) + { + /* Format start (the 'Next' button has been clicked on the Format page) */ + + if (bVolTransformThreadRunning || bVolTransformThreadToRun) + return 1; + + bVolTransformThreadCancel = FALSE; + + bVolTransformThreadToRun = TRUE; + + fileSystem = SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETITEMDATA, + SendMessage (GetDlgItem (hCurPage, IDC_FILESYS), CB_GETCURSEL, 0, 0) , 0); + + clusterSize = SendMessage (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), CB_GETITEMDATA, + SendMessage (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), CB_GETCURSEL, 0, 0) , 0); + + quickFormat = IsButtonChecked (GetDlgItem (hCurPage, IDC_QUICKFORMAT)); + + if (bHiddenVolHost) + { + hiddenVolHostDriveNo = -1; + nMaximumHiddenVolSize = 0; + + if (fileSystem == FILESYS_NTFS) + { + if (bHiddenOS + && (double) nVolumeSize / GetSystemPartitionSize() < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS) + { + Error("OUTER_VOLUME_TOO_SMALL_FOR_HIDDEN_OS_NTFS"); + + if (GetVolumeDataAreaSize (FALSE, nVolumeSize) <= TC_MAX_FAT_FS_SIZE + && AskYesNo("OFFER_FAT_FORMAT_ALTERNATIVE") == IDYES) + { + fileSystem = FILESYS_FAT; + SelectAlgo (GetDlgItem (hCurPage, IDC_FILESYS), (int *) &fileSystem); + } + else + { + bVolTransformThreadToRun = FALSE; + return 1; + } + } + + if (fileSystem == FILESYS_NTFS) // The file system may have been changed in the previous block + { + if (nCurrentOS == WIN_2000) + { + Error("HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS_WIN2000"); + bVolTransformThreadToRun = FALSE; + return 1; + } + else if (GetVolumeDataAreaSize (FALSE, nVolumeSize) <= TC_MAX_FAT_FS_SIZE + && AskYesNo("HIDDEN_VOL_HOST_NTFS_ASK") == IDNO) + { + bVolTransformThreadToRun = FALSE; + return 1; + } + } + } + } + else if (bHiddenVol) + { + // Hidden volume is always quick-formatted (if, however, the meaning of quickFormat is + // whether to create a sparse file, it must be set to FALSE). + quickFormat = !bSparseFileSwitch; + } + + + if (fileSystem == FILESYS_FAT + && nNeedToStoreFilesOver4GB == 1 + && AskWarnNoYes("CONFIRM_FAT_FOR_FILES_OVER_4GB") == IDNO) + { + bVolTransformThreadToRun = FALSE; + return 1; + } + + EnableWindow (GetDlgItem (hwndDlg, IDC_PREV), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEXT), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDHELP), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_QUICKFORMAT), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_CLUSTERSIZE), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_FILESYS), FALSE); + EnableWindow (GetDlgItem (hCurPage, IDC_ABORT_BUTTON), TRUE); + SetFocus (GetDlgItem (hCurPage, IDC_ABORT_BUTTON)); + + // Increase cluster size if it's too small for this volume size + if (fileSystem == FILESYS_FAT && clusterSize > 0) + { + BOOL fixed = FALSE; + while (clusterSize < 128 + && nVolumeSize / clusterSize > 17179869184I64) + { + clusterSize *= 2; + fixed = TRUE; + } + if (fixed) + MessageBoxW (hwndDlg, GetString ("CLUSTER_TOO_SMALL"), lpszTitle, MB_ICONWARNING); + } + + LastDialogId = "FORMAT_IN_PROGRESS"; + ArrowWaitCursor (); + _beginthread (volTransformThreadFunction, 0, MainDlg); + + return 1; + } + + else if (nCurPageNo == FORMAT_FINISHED_PAGE) + { + if (!bHiddenVol || bHiddenVolFinished) + { + /* Wizard loop restart */ + + if (bHiddenOS) + { + if (!ChangeWizardMode (WIZARD_MODE_SYS_DEVICE)) + return 1; + + // Hidden volume for hidden OS has been created. Now we will prepare our boot loader + // that will handle the OS cloning. + try + { + WaitCursor(); + + BootEncObj->PrepareHiddenOSCreation (nVolumeEA, FIRST_MODE_OF_OPERATION_ID, hash_algo); + } + catch (Exception &e) + { + e.Show (MainDlg); + NormalCursor(); + return 1; + } + + bHiddenVol = FALSE; + + LoadPage (hwndDlg, SYSENC_PRETEST_INFO_PAGE); + } + else + LoadPage (hwndDlg, INTRO_PAGE); + + SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString ("CANCEL")); + bHiddenVolFinished = FALSE; + WipePasswordsAndKeyfiles (); + + return 1; + } + else + { + /* We're going to scan the bitmap of the hidden volume host (in the non-Direct hidden volume wizard mode) */ + int retCode; + WaitCursor (); + + if (hiddenVolHostDriveNo != -1) // If the hidden volume host is mounted + { + BOOL tmp_result; + + // Dismount the hidden volume host (in order to remount it as read-only subsequently) + CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); + while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) + { + if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL | MB_ICONERROR | MB_SETFOREGROUND) != IDRETRY) + { + // Cancel + NormalCursor(); + return 1; + } + } + if (tmp_result) // If dismounted + hiddenVolHostDriveNo = -1; + } + + if (hiddenVolHostDriveNo < 0) // If the hidden volume host is not mounted + { + // Remount the hidden volume host as read-only (to ensure consistent and secure + // results of the volume bitmap scanning) + switch (MountHiddenVolHost (hwndDlg, szDiskFile, &hiddenVolHostDriveNo, &volumePassword, TRUE)) + { + case ERR_NO_FREE_DRIVES: + MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVE_FOR_OUTER_VOL"), lpszTitle, ICON_HAND); + NormalCursor (); + return 1; + + case ERR_VOL_MOUNT_FAILED: + case ERR_PASSWORD_WRONG: + NormalCursor (); + return 1; + + case 0: + + /* Hidden volume host successfully mounted as read-only */ + + // Verify that the outer volume contains a suitable file system, retrieve cluster size, and + // scan the volume bitmap + if (!IsAdmin () && IsUacSupported ()) + retCode = UacAnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); + else + retCode = AnalyzeHiddenVolumeHost (hwndDlg, &hiddenVolHostDriveNo, GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize), &realClusterSize, &nbrFreeClusters); + + switch (retCode) + { + case -1: // Fatal error + CloseVolumeExplorerWindows (hwndDlg, hiddenVolHostDriveNo); + + if (UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE)) + hiddenVolHostDriveNo = -1; + + AbortProcessSilent (); + break; + + case 0: // Unsupported file system (or other non-fatal error which has already been reported) + NormalCursor (); + return 1; + + case 1: // Success + { + BOOL tmp_result; + + // Determine the maximum possible size of the hidden volume + if (DetermineMaxHiddenVolSize (hwndDlg) < 1) + { + NormalCursor (); + goto ovf_end; + } + + /* Maximum possible size of the hidden volume successfully determined */ + + // Dismount the hidden volume host + while (!(tmp_result = UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE))) + { + if (MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_OUTER_VOL"), lpszTitle, MB_RETRYCANCEL) != IDRETRY) + { + // Cancel + NormalCursor (); + goto ovf_end; + } + } + + // Prevent having to recreate the outer volume due to inadvertent exit + bConfirmQuit = TRUE; + + hiddenVolHostDriveNo = -1; + + nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE; + + // Clear the outer volume password + WipePasswordsAndKeyfiles (); + + EnableWindow (GetDlgItem (MainDlg, IDC_NEXT), TRUE); + NormalCursor (); + + } + break; + } + break; + } + } + } + } + + else if (nCurPageNo == DEVICE_WIPE_PAGE) + { + if (AskWarnOkCancel (bHiddenOS && IsHiddenOSRunning() ? "CONFIRM_WIPE_START_DECOY_SYS_PARTITION" : "CONFIRM_WIPE_START") == IDOK) + { + WipeStart (); + ArrowWaitCursor(); + } + return 1; + } + + LoadPage (hwndDlg, nNewPageNo + 1); +ovf_end: + return 1; + } + else if (lw == IDC_PREV) + { + if (nCurPageNo == SYSENC_SPAN_PAGE) + { + // Skip irrelevant pages when going back + if (!bHiddenOS) + nNewPageNo = SYSENC_TYPE_PAGE + 1; + } + if (nCurPageNo == SYSENC_MULTI_BOOT_MODE_PAGE) + { + // Skip the drive analysis page(s) or other irrelevant pages when going back + if (bHiddenOS) + nNewPageNo = SYSENC_HIDDEN_OS_REQ_CHECK_PAGE + 1; + else if (bWholeSysDrive) + nNewPageNo = SYSENC_PRE_DRIVE_ANALYSIS_PAGE + 1; + else + nNewPageNo = SYSENC_SPAN_PAGE + 1; + } + else if (nCurPageNo == SYSENC_MULTI_BOOT_NONWIN_BOOT_LOADER_PAGE) + { + if (SysEncMultiBootCfg.NumberOfSysDrives == 1) + { + // We can skip SYSENC_MULTI_BOOT_ADJACENT_SYS_PAGE (it is implied that there are multiple systems on the drive) + nNewPageNo = SYSENC_MULTI_BOOT_NBR_SYS_DRIVES_PAGE + 1; + } + } + else if (nCurPageNo == HIDDEN_VOL_HOST_PRE_CIPHER_PAGE) + { + if (bHiddenOS) + { + if (!ChangeWizardMode (WIZARD_MODE_SYS_DEVICE)) + { + NormalCursor (); + return 1; + } + + nNewPageNo = (nMultiBoot <= 1 ? SYSENC_MULTI_BOOT_MODE_PAGE + 1 : SYSENC_MULTI_BOOT_OUTCOME_PAGE + 1); // Skip irrelevant pages + } + else + { + nNewPageNo = VOLUME_LOCATION_PAGE + 1; + } + } + else if (nCurPageNo == HIDDEN_VOL_WIZARD_MODE_PAGE) + { + if (IsButtonChecked (GetDlgItem (hCurPage, IDC_HIDVOL_WIZ_MODE_DIRECT))) + bHiddenVolDirect = TRUE; + else + bHiddenVolDirect = FALSE; + } + else if (nCurPageNo == VOLUME_TYPE_PAGE) + { + if (WizardMode != WIZARD_MODE_SYS_DEVICE) + nNewPageNo = INTRO_PAGE + 1; // Skip irrelevant pages + } + else if (nCurPageNo == VOLUME_LOCATION_PAGE) + { + BOOL tmpbDevice; + + GetWindowText (GetDlgItem (hCurPage, IDC_COMBO_BOX), szFileName, sizeof (szFileName)); + CreateFullVolumePath (szDiskFile, szFileName, &tmpbDevice); + + if (tmpbDevice == bDevice) + { + MoveEditToCombo (GetDlgItem (hCurPage, IDC_COMBO_BOX), bHistory); + SaveSettings (hCurPage); + } + + if (!bHiddenVol) + nNewPageNo = VOLUME_TYPE_PAGE + 1; // Skip the hidden volume creation wizard mode selection + } + + else if (nCurPageNo == HIDDEN_VOL_HOST_PRE_CIPHER_PAGE) + { + nNewPageNo = VOLUME_LOCATION_PAGE + 1; + } + + else if (nCurPageNo == CIPHER_PAGE) + { + LPARAM nIndex; + nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETCURSEL, 0, 0); + nVolumeEA = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX), CB_GETITEMDATA, nIndex, 0); + + nIndex = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETCURSEL, 0, 0); + hash_algo = SendMessage (GetDlgItem (hCurPage, IDC_COMBO_BOX_HASH_ALGO), CB_GETITEMDATA, nIndex, 0); + + RandSetHashFunction (hash_algo); + + if (WizardMode == WIZARD_MODE_SYS_DEVICE) + { + if (nMultiBoot > 1) + nNewPageNo = SYSENC_MULTI_BOOT_OUTCOME_PAGE + 1; // Skip irrelevant pages + else + nNewPageNo = SYSENC_MULTI_BOOT_MODE_PAGE + 1; // Skip irrelevant pages + } + else if (!bHiddenVol) + nNewPageNo = (bDevice ? DEVICE_TRANSFORM_MODE_PAGE : VOLUME_LOCATION_PAGE) + 1; + else if (bHiddenVolHost) + nNewPageNo = HIDDEN_VOL_HOST_PRE_CIPHER_PAGE + 1; // Skip the info on the hidden volume + } + + else if (nCurPageNo == SIZE_PAGE) + { + VerifySizeAndUpdate (hCurPage, TRUE); + } + + else if (nCurPageNo == FILESYS_PAGE) + { + if (nNeedToStoreFilesOver4GB != Get2RadButtonPageAnswer()) + fileSystem = FILESYS_NONE; // The user may have gone back and changed the answer, so default file system must be reselected + + nNeedToStoreFilesOver4GB = Get2RadButtonPageAnswer(); + } + + else if (nCurPageNo == PASSWORD_PAGE) + { + // Store the password in case we need to restore it after keyfile is applied to it + GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD), szRawPassword, sizeof (szRawPassword)); + + VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (MainDlg, IDC_NEXT), + GetDlgItem (hCurPage, IDC_PASSWORD), + GetDlgItem (hCurPage, IDC_VERIFY), + volumePassword.Text, + szVerify, + KeyFilesEnable && FirstKeyFile!=NULL && !SysEncInEffect ()); + + volumePassword.Length = strlen ((char *) volumePassword.Text); + + nNewPageNo = SIZE_PAGE + 1; // Skip the hidden volume host password page + + if (SysEncInEffect ()) + { + nNewPageNo = CIPHER_PAGE + 1; // Skip irrelevant pages + + KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); + + if (bKeyboardLayoutChanged) + { + // Restore the original keyboard layout + if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) + Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); + else + bKeyboardLayoutChanged = FALSE; + } + } + else if (bInPlaceEncNonSys) + nNewPageNo = CIPHER_PAGE + 1; + } + + else if (nCurPageNo == HIDDEN_VOL_HOST_PASSWORD_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE) + { + // Store the password in case we need to restore it after keyfile is applied to it + GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), szRawPassword, sizeof (szRawPassword)); + + GetWindowText (GetDlgItem (hCurPage, IDC_PASSWORD_DIRECT), (char *) volumePassword.Text, sizeof (volumePassword.Text)); + volumePassword.Length = strlen ((char *) volumePassword.Text); + + if (!bInPlaceEncNonSys) + nNewPageNo = VOLUME_LOCATION_PAGE + 1; + } + + else if (nCurPageNo == SYSENC_COLLECTING_RANDOM_DATA_PAGE + || nCurPageNo == NONSYS_INPLACE_ENC_RAND_DATA_PAGE) + { + char tmp[RANDPOOL_DISPLAY_SIZE+1]; + + KillTimer (hwndDlg, TIMER_ID_RANDVIEW); + + // Attempt to wipe the GUI field showing portions of randpool + memset (tmp, 'X', sizeof(tmp)); + tmp [sizeof(tmp)-1] = 0; + SetWindowText (hRandPoolSys, tmp); + + nNewPageNo = PASSWORD_PAGE + 1; // Skip irrelevant pages + } + + else if (nCurPageNo == SYSENC_KEYS_GEN_PAGE) + { + char tmp[KEY_GUI_VIEW_SIZE+1]; + + // Attempt to wipe the GUI fields showing portions of the master and header keys + memset (tmp, 'X', sizeof(tmp)); + tmp [sizeof(tmp)-1] = 0; + SetWindowText (hMasterKey, tmp); + SetWindowText (hHeaderKey, tmp); + } + + else if (nCurPageNo == SYSENC_WIPE_MODE_PAGE) + { + if (bDontVerifyRescueDisk) + nNewPageNo = SYSENC_RESCUE_DISK_VERIFIED_PAGE; // Skip irrelevant pages + } + + else if (nCurPageNo == FORMAT_PAGE) + { + char tmp[RNG_POOL_SIZE*2+1]; + + KillTimer (hwndDlg, TIMER_ID_RANDVIEW); + + // Attempt to wipe the GUI fields showing portions of randpool, of the master and header keys + memset (tmp, 'X', sizeof(tmp)); + tmp [sizeof(tmp)-1] = 0; + SetWindowText (hRandPool, tmp); + SetWindowText (hMasterKey, tmp); + SetWindowText (hHeaderKey, tmp); + + if (WizardMode != WIZARD_MODE_SYS_DEVICE) + { + // Skip irrelevant pages + + if (FileSize4GBLimitQuestionNeeded () + && !CreatingHiddenSysVol() // If we're creating a hidden volume for a hidden OS, we don't need to format it with any filesystem (the entire OS will be copied to the hidden volume sector by sector). + && !bInPlaceEncNonSys) + { + nNewPageNo = FILESYS_PAGE + 1; + } + else + nNewPageNo = PASSWORD_PAGE + 1; + } + } + + LoadPage (hwndDlg, nNewPageNo - 1); + + return 1; + } + + return 0; + + case WM_ENDSESSION: + EndMainDlg (MainDlg); + localcleanup (); + return 0; + + case WM_CLOSE: + PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0); + return 1; + } + + return 0; +} + +void ExtractCommandLine (HWND hwndDlg, char *lpszCommandLine) +{ + char **lpszCommandLineArgs; /* Array of command line arguments */ + int nNoCommandLineArgs; /* The number of arguments in the array */ + + if (_stricmp (lpszCommandLine, "-Embedding") == 0) + { + ComServerMode = TRUE; + return; + } + + /* Extract command line arguments */ + nNoCommandLineArgs = Win32CommandLine (lpszCommandLine, &lpszCommandLineArgs); + if (nNoCommandLineArgs > 0) + { + int i; + + for (i = 0; i < nNoCommandLineArgs; i++) + { + enum + { + OptionHistory, + OptionNoIsoCheck, + OptionQuit, + OptionTokenLib, + CommandResumeSysEncLogOn, + CommandResumeSysEnc, + CommandDecryptSysEnc, + CommandEncDev, + CommandHiddenSys, + CommandResumeInplaceLogOn, + CommandResumeHiddenSys, + CommandSysEnc, + CommandResumeInplace, + }; + + argument args[]= + { + { OptionHistory, "/history", "/h", FALSE }, + { OptionNoIsoCheck, "/noisocheck", "/n", FALSE }, + { OptionQuit, "/quit", "/q", FALSE }, + { OptionTokenLib, "/tokenlib", NULL, FALSE }, + + { CommandResumeSysEncLogOn, "/acsysenc", "/a", TRUE }, + { CommandResumeSysEnc, "/csysenc", "/c", TRUE }, + { CommandDecryptSysEnc, "/dsysenc", "/d", TRUE }, + { CommandEncDev, "/encdev", "/e", TRUE }, + { CommandHiddenSys, "/isysenc", "/i", TRUE }, + { CommandResumeInplaceLogOn, "/prinplace", "/p", TRUE }, + { CommandResumeHiddenSys, "/risysenc", "/r", TRUE }, + { CommandSysEnc, "/sysenc", "/s", TRUE }, + { CommandResumeInplace, "/zinplace", "/z", TRUE } + }; + + argumentspec as; + + int nArgPos; + int x; + + if (lpszCommandLineArgs[i] == NULL) + continue; + + as.args = args; + as.arg_cnt = sizeof(args)/ sizeof(args[0]); + + x = GetArgumentID (&as, lpszCommandLineArgs[i], &nArgPos); + + switch (x) + { + case CommandSysEnc: + // Encrypt system partition/drive (passed by Mount if system encryption hasn't started or to reverse decryption) + + // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption + if (CreateSysEncMutex ()) + { + bDirectSysEncMode = TRUE; + bDirectSysEncModeCommand = SYSENC_COMMAND_ENCRYPT; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + } + else + { + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + exit(0); + } + + break; + + case CommandDecryptSysEnc: + // Decrypt system partition/drive (passed by Mount, also to reverse encryption in progress, when paused) + + // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption + if (CreateSysEncMutex ()) + { + bDirectSysEncMode = TRUE; + bDirectSysEncModeCommand = SYSENC_COMMAND_DECRYPT; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + } + else + { + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + exit(0); + } + break; + + case CommandHiddenSys: + // Create a hidden operating system (passed by Mount when the user selects System -> Create Hidden Operating System) + + // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption + if (CreateSysEncMutex ()) + { + bDirectSysEncMode = TRUE; + bDirectSysEncModeCommand = SYSENC_COMMAND_CREATE_HIDDEN_OS; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + } + else + { + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + exit(0); + } + + break; + + case CommandResumeHiddenSys: + // Resume process of creation of a hidden operating system (passed by Wizard when the user needs to UAC-elevate the whole wizard process) + + // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption + if (CreateSysEncMutex ()) + { + bDirectSysEncMode = TRUE; + bDirectSysEncModeCommand = SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + } + else + { + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + exit(0); + } + + break; + + case CommandResumeSysEnc: + // Resume previous system-encryption operation (passed by Mount) e.g. encryption, decryption, or pretest + + // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption + if (CreateSysEncMutex ()) + { + bDirectSysEncMode = TRUE; + bDirectSysEncModeCommand = SYSENC_COMMAND_RESUME; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + } + else + { + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + exit(0); + } + break; + + case CommandResumeSysEncLogOn: + // Same as csysenc but passed only by the system (from the startup sequence) + + // From now on, we should be the only instance of the TC wizard allowed to deal with system encryption + if (CreateSysEncMutex ()) + { + bDirectSysEncMode = TRUE; + bDirectSysEncModeCommand = SYSENC_COMMAND_STARTUP_SEQ_RESUME; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + } + else + { + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + exit(0); + } + break; + + case CommandEncDev: + // Resume process of creation of a non-sys-device-hosted volume (passed by Wizard when the user needs to UAC-elevate) + DirectDeviceEncMode = TRUE; + break; + + case CommandResumeInplace: + // Resume interrupted process of non-system in-place encryption of a partition + DirectNonSysInplaceEncResumeMode = TRUE; + break; + + case CommandResumeInplaceLogOn: + // Ask the user whether to resume interrupted process of non-system in-place encryption of a partition + // This switch is passed only by the system (from the startup sequence). + DirectPromptNonSysInplaceEncResumeMode = TRUE; + break; + + case OptionNoIsoCheck: + bDontVerifyRescueDisk = TRUE; + break; + + case OptionHistory: + { + char szTmp[8]; + GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, + szTmp, sizeof (szTmp)); + if (!_stricmp(szTmp,"y") || !_stricmp(szTmp,"yes")) + { + bHistory = TRUE; + bHistoryCmdLine = TRUE; + } + + if (!_stricmp(szTmp,"n") || !_stricmp(szTmp,"no")) + { + bHistory = FALSE; + bHistoryCmdLine = TRUE; + } + } + break; + + case OptionTokenLib: + if (GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath)) == HAS_ARGUMENT) + InitSecurityTokenLibrary(); + else + Error ("COMMAND_LINE_ERROR"); + + break; + + case OptionQuit: + { + // Used to indicate non-install elevation + char szTmp[32]; + GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp)); + } + break; + + default: + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_COMMANDHELP_DLG), hwndDlg, (DLGPROC) + CommandHelpDlgProc, (LPARAM) &as); + + exit(0); + } + } + } + + /* Free up the command line arguments */ + while (--nNoCommandLineArgs >= 0) + { + free (lpszCommandLineArgs[nNoCommandLineArgs]); + } +} + + +int DetermineMaxHiddenVolSize (HWND hwndDlg) +{ + __int64 nbrReserveBytes; + + if (nbrFreeClusters * realClusterSize < TC_MIN_HIDDEN_VOLUME_SIZE) + { + MessageBoxW (hwndDlg, GetString ("NO_SPACE_FOR_HIDDEN_VOL"), lpszTitle, ICON_HAND); + UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE); + AbortProcessSilent (); + } + + // Add a reserve (in case the user mounts the outer volume and creates new files + // on it by accident or OS writes some new data behind his or her back, such as + // System Restore etc.) + nbrReserveBytes = GetVolumeDataAreaSize (FALSE, nHiddenVolHostSize) / 200; + if (nbrReserveBytes > BYTES_PER_MB * 10) + nbrReserveBytes = BYTES_PER_MB * 10; + + // Compute the final value + + nMaximumHiddenVolSize = nbrFreeClusters * realClusterSize - TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE - nbrReserveBytes; + nMaximumHiddenVolSize -= nMaximumHiddenVolSize % SECTOR_SIZE; // Must be a multiple of the sector size + + if (nMaximumHiddenVolSize < TC_MIN_HIDDEN_VOLUME_SIZE) + { + MessageBoxW (hwndDlg, GetString ("NO_SPACE_FOR_HIDDEN_VOL"), lpszTitle, ICON_HAND); + UnmountVolume (hwndDlg, hiddenVolHostDriveNo, FALSE); + AbortProcessSilent (); + } + + // Prepare the hidden volume size parameters + if (nMaximumHiddenVolSize < BYTES_PER_MB) + nMultiplier = BYTES_PER_KB; + else if (nMaximumHiddenVolSize < BYTES_PER_GB) + nMultiplier = BYTES_PER_MB; + else + nMultiplier = BYTES_PER_GB; + + nUIVolumeSize = 0; // Set the initial value for the hidden volume size input field to the max + nVolumeSize = nUIVolumeSize * nMultiplier; // Chop off possible remainder + + return 1; +} + + +// Tests whether the file system of the given volume is suitable to host a hidden volume, +// retrieves the cluster size, and scans the volume cluster bitmap. In addition, checks +// the TrueCrypt volume format version and the type of volume. +int AnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *pnbrFreeClusters) +{ + HANDLE hDevice; + DWORD bytesReturned; + DWORD dwSectorsPerCluster, dwBytesPerSector, dwNumberOfFreeClusters, dwTotalNumberOfClusters; + DWORD dwResult; + int result; + char szFileSystemNameBuffer[256]; + char tmpPath[7] = {'\\','\\','.','\\',(char) *driveNo + 'A',':',0}; + char szRootPathName[4] = {(char) *driveNo + 'A', ':', '\\', 0}; + BYTE readBuffer[SECTOR_SIZE*2]; + LARGE_INTEGER offset, offsetNew; + VOLUME_PROPERTIES_STRUCT volProp; + + memset (&volProp, 0, sizeof(volProp)); + volProp.driveNo = *driveNo; + if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &volProp, sizeof (volProp), &volProp, sizeof (volProp), &dwResult, NULL) || dwResult == 0) + { + handleWin32Error (hwndDlg); + Error ("CANT_ACCESS_OUTER_VOL"); + goto efsf_error; + } + + if (volProp.volFormatVersion < TC_VOLUME_FORMAT_VERSION) + { + // We do not support creating hidden volumes within volumes created by TrueCrypt 5.1a or earlier. + Error ("ERR_VOL_FORMAT_BAD"); + return 0; + } + + if (volProp.hiddenVolume) + { + // The user entered a password for a hidden volume + Error ("ERR_HIDDEN_NOT_NORMAL_VOLUME"); + return 0; + } + + if (volProp.volumeHeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC + || volProp.volumeHeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) + { + Warning ("ERR_HIDDEN_VOL_HOST_ENCRYPTED_INPLACE"); + return 0; + } + + hDevice = CreateFile (tmpPath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hDevice == INVALID_HANDLE_VALUE) + { + MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_OUTER_VOL"), lpszTitle, ICON_HAND); + goto efsf_error; + } + + offset.QuadPart = 0; + + if (SetFilePointerEx (hDevice, offset, &offsetNew, FILE_BEGIN) == 0) + { + handleWin32Error (hwndDlg); + goto efs_error; + } + + result = ReadFile(hDevice, &readBuffer, (DWORD) SECTOR_SIZE, &bytesReturned, NULL); + + if (result == 0) + { + handleWin32Error (hwndDlg); + MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_OUTER_VOL"), lpszTitle, ICON_HAND); + goto efs_error; + } + + CloseHandle (hDevice); + hDevice = INVALID_HANDLE_VALUE; + + // Determine file system type + + GetVolumeInformation(szRootPathName, NULL, 0, NULL, NULL, NULL, szFileSystemNameBuffer, sizeof(szFileSystemNameBuffer)); + + // The Windows API sometimes fails to indentify the file system correctly so we're using "raw" analysis too. + if (!strncmp (szFileSystemNameBuffer, "FAT", 3) + || (readBuffer[0x36] == 'F' && readBuffer[0x37] == 'A' && readBuffer[0x38] == 'T') + || (readBuffer[0x52] == 'F' && readBuffer[0x53] == 'A' && readBuffer[0x54] == 'T')) + { + // FAT12/FAT16/FAT32 + + // Retrieve the cluster size + *realClusterSize = ((int) readBuffer[0xb] + ((int) readBuffer[0xc] << 8)) * (int) readBuffer[0xd]; + + // Get the map of the clusters that are free and in use on the outer volume. + // The map will be scanned to determine the size of the uninterrupted block of free + // space (provided there is any) whose end is aligned with the end of the volume. + // The value will then be used to determine the maximum possible size of the hidden volume. + + return ScanVolClusterBitmap (hwndDlg, + driveNo, + hiddenVolHostSize / *realClusterSize, + pnbrFreeClusters); + } + else if (!strncmp (szFileSystemNameBuffer, "NTFS", 4)) + { + // NTFS + + if (nCurrentOS == WIN_2000) + { + Error("HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS_WIN2000"); + return 0; + } + + if (bHiddenVolDirect && GetVolumeDataAreaSize (FALSE, hiddenVolHostSize) <= TC_MAX_FAT_FS_SIZE) + Info ("HIDDEN_VOL_HOST_NTFS"); + + if (!GetDiskFreeSpace(szRootPathName, + &dwSectorsPerCluster, + &dwBytesPerSector, + &dwNumberOfFreeClusters, + &dwTotalNumberOfClusters)) + { + handleWin32Error (hwndDlg); + Error ("CANT_GET_OUTER_VOL_INFO"); + return -1; + }; + + *realClusterSize = dwBytesPerSector * dwSectorsPerCluster; + + // Get the map of the clusters that are free and in use on the outer volume. + // The map will be scanned to determine the size of the uninterrupted block of free + // space (provided there is any) whose end is aligned with the end of the volume. + // The value will then be used to determine the maximum possible size of the hidden volume. + + return ScanVolClusterBitmap (hwndDlg, + driveNo, + hiddenVolHostSize / *realClusterSize, + pnbrFreeClusters); + } + else + { + // Unsupported file system + + Error ((nCurrentOS == WIN_2000) ? "HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS_WIN2000" : "HIDDEN_VOL_HOST_UNSUPPORTED_FILESYS"); + return 0; + } + +efs_error: + CloseHandle (hDevice); + +efsf_error: + CloseVolumeExplorerWindows (hwndDlg, *driveNo); + + return -1; +} + + +// Mounts a volume within which the user intends to create a hidden volume +int MountHiddenVolHost (HWND hwndDlg, char *volumePath, int *driveNo, Password *password, BOOL bReadOnly) +{ + MountOptions mountOptions; + ZeroMemory (&mountOptions, sizeof (mountOptions)); + + *driveNo = GetLastAvailableDrive (); + + if (*driveNo == -1) + { + *driveNo = -2; + return ERR_NO_FREE_DRIVES; + } + + mountOptions.ReadOnly = bReadOnly; + mountOptions.Removable = ConfigReadInt ("MountVolumesRemovable", FALSE); + mountOptions.ProtectHiddenVolume = FALSE; + mountOptions.PreserveTimestamp = bPreserveTimestamp; + mountOptions.PartitionInInactiveSysEncScope = FALSE; + mountOptions.UseBackupHeader = FALSE; + + if (MountVolume (hwndDlg, *driveNo, volumePath, password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1) + { + *driveNo = -3; + return ERR_VOL_MOUNT_FAILED; + } + return 0; +} + + +/* Gets the map of the clusters that are free and in use on a volume that is to host + a hidden volume. The map is scanned to determine the size of the uninterrupted + area of free space (provided there is any) whose end is aligned with the end + of the volume. The value will then be used to determine the maximum possible size + of the hidden volume. */ +int ScanVolClusterBitmap (HWND hwndDlg, int *driveNo, __int64 nbrClusters, __int64 *nbrFreeClusters) +{ + PVOLUME_BITMAP_BUFFER lpOutBuffer; + STARTING_LCN_INPUT_BUFFER lpInBuffer; + + HANDLE hDevice; + DWORD lBytesReturned; + BYTE rmnd; + char tmpPath[7] = {'\\','\\','.','\\', (char) *driveNo + 'A', ':', 0}; + + DWORD bufLen; + __int64 bitmapCnt; + + hDevice = CreateFile (tmpPath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hDevice == INVALID_HANDLE_VALUE) + { + MessageBoxW (hwndDlg, GetString ("CANT_ACCESS_OUTER_VOL"), lpszTitle, ICON_HAND); + goto vcmf_error; + } + + bufLen = (DWORD) (nbrClusters / 8 + 2 * sizeof(LARGE_INTEGER)); + bufLen += 100000 + bufLen/10; // Add reserve + + lpOutBuffer = (PVOLUME_BITMAP_BUFFER) malloc (bufLen); + + if (lpOutBuffer == NULL) + { + MessageBoxW (hwndDlg, GetString ("ERR_MEM_ALLOC"), lpszTitle, ICON_HAND); + goto vcmf_error; + } + + lpInBuffer.StartingLcn.QuadPart = 0; + + if ( !DeviceIoControl (hDevice, + FSCTL_GET_VOLUME_BITMAP, + &lpInBuffer, + sizeof(lpInBuffer), + lpOutBuffer, + bufLen, + &lBytesReturned, + NULL)) + { + handleWin32Error (hwndDlg); + MessageBoxW (hwndDlg, GetString ("CANT_GET_CLUSTER_BITMAP"), lpszTitle, ICON_HAND); + + goto vcm_error; + } + + rmnd = (BYTE) (lpOutBuffer->BitmapSize.QuadPart % 8); + + if ((rmnd != 0) + && ((lpOutBuffer->Buffer[lpOutBuffer->BitmapSize.QuadPart / 8] & ((1 << rmnd)-1) ) != 0)) + { + *nbrFreeClusters = 0; + } + else + { + *nbrFreeClusters = lpOutBuffer->BitmapSize.QuadPart; + bitmapCnt = lpOutBuffer->BitmapSize.QuadPart / 8; + + // Scan the bitmap from the end + while (--bitmapCnt >= 0) + { + if (lpOutBuffer->Buffer[bitmapCnt] != 0) + { + // There might be up to 7 extra free clusters in this byte of the bitmap. + // These are ignored because there is always a cluster reserve added anyway. + *nbrFreeClusters = lpOutBuffer->BitmapSize.QuadPart - ((bitmapCnt + 1) * 8); + break; + } + } + } + + CloseHandle (hDevice); + free(lpOutBuffer); + return 1; + +vcm_error: + CloseHandle (hDevice); + free(lpOutBuffer); + +vcmf_error: + return -1; +} + + +// Wipe the hidden OS config flag bits in the MBR +static BOOL WipeHiddenOSCreationConfig (void) +{ + if (!IsHiddenOSRunning()) + { + try + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + BootEncObj->WipeHiddenOSCreationConfig(); + } + catch (Exception &e) + { + e.Show (MainDlg); + return FALSE; + } + } + + return TRUE; +} + + +// Tasks that need to be performed after the WM_INITDIALOG message for the SYSENC_ENCRYPTION_PAGE dialog is +// handled should be done here (otherwise the UAC prompt causes the GUI to be only half-rendered). +static void AfterSysEncProgressWMInitTasks (HWND hwndDlg) +{ + try + { + switch (SystemEncryptionStatus) + { + case SYSENC_STATUS_ENCRYPTING: + + if (BootEncStatus.ConfiguredEncryptedAreaStart == BootEncStatus.EncryptedAreaStart + && BootEncStatus.ConfiguredEncryptedAreaEnd == BootEncStatus.EncryptedAreaEnd) + { + // The partition/drive had been fully encrypted + + ManageStartupSeqWiz (TRUE, ""); + WipeHiddenOSCreationConfig(); // For extra conservative security + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + + Info ("SYSTEM_ENCRYPTION_FINISHED"); + EndMainDlg (MainDlg); + return; + } + else + { + SysEncResume (); + } + + break; + + case SYSENC_STATUS_DECRYPTING: + SysEncResume (); + break; + + default: + + // Unexpected mode here -- fix the inconsistency + + ManageStartupSeqWiz (TRUE, ""); + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + EndMainDlg (MainDlg); + InconsistencyResolved (SRC_POS); + return; + } + } + catch (Exception &e) + { + e.Show (hwndDlg); + EndMainDlg (MainDlg); + return; + } + + InitSysEncProgressBar (); + + UpdateSysEncProgressBar (); + + UpdateSysEncControls (); +} + + +// Tasks that need to be performed after the WM_INITDIALOG message is handled must be done here. +// For example, any tasks that may invoke the UAC prompt (otherwise the UAC dialog box would not be on top). +static void AfterWMInitTasks (HWND hwndDlg) +{ + // Note that if bDirectSysEncModeCommand is not SYSENC_COMMAND_NONE, we already have the mutex. + + // SYSENC_COMMAND_DECRYPT has the highest priority because it also performs uninstallation (restores the + // original contents of the first drive cylinder, etc.) so it must be attempted regardless of the phase + // or content of configuration files. + if (bDirectSysEncModeCommand == SYSENC_COMMAND_DECRYPT) + { + if (IsHiddenOSRunning()) + { + Warning ("CANNOT_DECRYPT_HIDDEN_OS"); + AbortProcessSilent(); + } + + // Add the wizard to the system startup sequence + ManageStartupSeqWiz (FALSE, "/acsysenc"); + + ChangeSystemEncryptionStatus (SYSENC_STATUS_DECRYPTING); + LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); + return; + } + + + if (SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING + || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING) + { + try + { + BootEncStatus = BootEncObj->GetStatus(); + + if (!BootEncStatus.DriveMounted) + { + if (!BootEncStatus.DeviceFilterActive) + { + // This is an inconsistent state. SystemEncryptionStatus should never be SYSENC_STATUS_ENCRYPTING + // or SYSENC_STATUS_DECRYPTING when the drive filter is not active. Possible causes: 1) corrupted + // or stale config file, 2) corrupted system + + // Fix the inconsistency + ManageStartupSeqWiz (TRUE, ""); + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + EndMainDlg (MainDlg); + InconsistencyResolved (SRC_POS); + return; + } + else if (bDirectSysEncMode) + { + // This is an inconsistent state. We have a direct system encryption command, + // SystemEncryptionStatus is SYSENC_STATUS_ENCRYPTING or SYSENC_STATUS_DECRYPTING, the + // system drive is not 'mounted' and drive filter is active. Possible causes: 1) The drive had + // been decrypted in the pre-boot environment. 2) The OS is not located on the lowest partition, + // the drive is to be fully encrypted, but the user rebooted before encryption reached the + // system partition and then pressed Esc in the boot loader screen. 3) Corrupted or stale config + // file. 4) Damaged system. + + Warning ("SYSTEM_ENCRYPTION_SCHEDULED_BUT_PBA_FAILED"); + EndMainDlg (MainDlg); + return; + } + } + } + catch (Exception &e) + { + e.Show (MainDlg); + } + } + + + if (SystemEncryptionStatus != SYSENC_STATUS_PRETEST) + { + // Handle system encryption command line arguments (if we're not in the Pretest phase). + // Note that if bDirectSysEncModeCommand is not SYSENC_COMMAND_NONE, we already have the mutex. + // Also note that SYSENC_COMMAND_DECRYPT is handled above. + + switch (bDirectSysEncModeCommand) + { + case SYSENC_COMMAND_RESUME: + case SYSENC_COMMAND_STARTUP_SEQ_RESUME: + + if (bDirectSysEncModeCommand == SYSENC_COMMAND_STARTUP_SEQ_RESUME + && AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDNO) + { + EndMainDlg (MainDlg); + return; + } + + if (SysEncryptionOrDecryptionRequired ()) + { + if (SystemEncryptionStatus != SYSENC_STATUS_ENCRYPTING + && SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) + { + // If the config file with status was lost or not written correctly, we + // don't know whether to encrypt or decrypt (but we know that encryption or + // decryption is required). Ask the user to select encryption, decryption, + // or cancel + if (!ResolveUnknownSysEncDirection ()) + { + EndMainDlg (MainDlg); + return; + } + } + + LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); + return; + } + else + { + // Nothing to resume + Warning ("NOTHING_TO_RESUME"); + EndMainDlg (MainDlg); + + return; + } + break; + + case SYSENC_COMMAND_ENCRYPT: + + if (SysDriveOrPartitionFullyEncrypted (FALSE)) + { + Info ("SYS_PARTITION_OR_DRIVE_APPEARS_FULLY_ENCRYPTED"); + EndMainDlg (MainDlg); + return; + } + + if (SysEncryptionOrDecryptionRequired ()) + { + // System partition/drive encryption process already initiated but is incomplete. + // If we were encrypting, resume the process directly. If we were decrypting, reverse + // the process and start encrypting. + + ChangeSystemEncryptionStatus (SYSENC_STATUS_ENCRYPTING); + LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); + return; + } + else + { + // Initiate the Pretest preparation phase + if (!SwitchWizardToSysEncMode ()) + { + bDirectSysEncMode = FALSE; + EndMainDlg (MainDlg); + } + return; + } + + break; + + case SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV: + case SYSENC_COMMAND_CREATE_HIDDEN_OS: + + if (!SwitchWizardToHiddenOSMode ()) + { + bDirectSysEncMode = FALSE; + EndMainDlg (MainDlg); + } + return; + } + } + + + if (!bDirectSysEncMode + || bDirectSysEncMode && SystemEncryptionStatus == SYSENC_STATUS_NONE) + { + // Handle system encryption cases where the wizard did not start even though it + // was added to the startup sequence, as well as other weird cases and "leftovers" + + if (SystemEncryptionStatus != SYSENC_STATUS_NONE + && SystemEncryptionStatus != SYSENC_STATUS_PRETEST + && SysEncryptionOrDecryptionRequired ()) + { + // System encryption/decryption had been in progress and did not finish + + if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption + { + if (AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) + { + bDirectSysEncMode = TRUE; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + LoadPage (hwndDlg, SYSENC_ENCRYPTION_PAGE); + return; + } + else + CloseSysEncMutex (); + } + } + + else if (SystemEncryptionStatus == SYSENC_STATUS_PRETEST) + { + // System pretest had been in progress but we were not launched during the startup seq + + if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption + { + // The pretest has "priority handling" + bDirectSysEncMode = TRUE; + ChangeWizardMode (WIZARD_MODE_SYS_DEVICE); + + /* Do not return yet -- the principal pretest handler is below. */ + } + } + + else if ((SystemEncryptionStatus == SYSENC_STATUS_NONE || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING) + && !BootEncStatus.DriveEncrypted + && (BootEncStatus.DriveMounted || BootEncStatus.VolumeHeaderPresent)) + { + // The pretest may have been in progress but we can't be sure (it is not in the config file). + // Another possibility is that the user had finished decrypting the drive, but the config file + // was not correctly updated. In both cases the best thing we can do is remove the header and + // deinstall. Otherwise, the result might be some kind of deadlock. + + if (CreateSysEncMutex ()) // If no other instance is currently taking care of system encryption + { + WaitCursor (); + + ForceRemoveSysEnc(); + + InconsistencyResolved (SRC_POS); + + NormalCursor(); + CloseSysEncMutex (); + } + } + } + + if (bDirectSysEncMode && CreateSysEncMutex ()) + { + // We were launched either by Mount or by the system (startup sequence). Most of such cases should have + // been handled above already. Here we handle only the pretest phase (which can also be a hidden OS + // creation phase actually) and possible inconsistencies. + + switch (SystemEncryptionStatus) + { + case SYSENC_STATUS_PRETEST: + { + unsigned int hiddenOSCreationPhase = DetermineHiddenOSCreationPhase(); + + bHiddenOS = (hiddenOSCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE); + + // Evaluate the results of the system encryption pretest (or of the hidden OS creation process) + + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (hwndDlg); + Error ("ERR_GETTING_SYSTEM_ENCRYPTION_STATUS"); + EndMainDlg (MainDlg); + return; + } + + if (BootEncStatus.DriveMounted) + { + /* Pretest successful or hidden OS has been booted during the process of hidden OS creation. */ + + switch (hiddenOSCreationPhase) + { + case TC_HIDDEN_OS_CREATION_PHASE_NONE: + + // Pretest successful (or the hidden OS has been booted for the first time since the user started installing a new decoy OS) + + if (IsHiddenOSRunning()) + { + // The hidden OS has been booted for the first time since the user started installing a + // new decoy OS (presumably, our MBR config flags have been erased). + + // As for things we are responsible for, the process of hidden OS creation is completed + // (the rest is up to the user). + + ManageStartupSeqWiz (TRUE, ""); + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + + EndMainDlg (MainDlg); + + return; + } + + // Pretest successful (no hidden operating system involved) + + LoadPage (hwndDlg, SYSENC_PRETEST_RESULT_PAGE); + return; + + case TC_HIDDEN_OS_CREATION_PHASE_WIPING: + + // Hidden OS has been booted when we are supposed to wipe the original OS + + LoadPage (hwndDlg, SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE); + return; + + case TC_HIDDEN_OS_CREATION_PHASE_WIPED: + + // Hidden OS has been booted and the original OS wiped. Now the user is required to install a new, decoy, OS. + + TextInfoDialogBox (TC_TBXID_DECOY_OS_INSTRUCTIONS); + + EndMainDlg (MainDlg); + return; + + default: + + // Unexpected/unknown status + ReportUnexpectedState (SRC_POS); + EndMainDlg (MainDlg); + return; + } + } + else + { + BOOL bAnswerTerminate = FALSE, bAnswerRetry = FALSE; + + /* Pretest failed + or hidden OS cloning has been interrupted (and non-hidden OS is running) + or wiping of the original OS has not been started (and non-hidden OS is running) */ + + if (hiddenOSCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_NONE) + { + // Pretest failed (no hidden operating system involved) + + if (AskWarnYesNo ("BOOT_PRETEST_FAILED_RETRY") == IDYES) + { + // User wants to retry the pretest + bAnswerTerminate = FALSE; + bAnswerRetry = TRUE; + } + else + { + // User doesn't want to retry the pretest + bAnswerTerminate = TRUE; + bAnswerRetry = FALSE; + } + } + else + { + // Hidden OS cloning was interrupted or wiping of the original OS has not been started + + char *tmpStr[] = {0, + hiddenOSCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_WIPING ? "OS_WIPING_NOT_FINISHED_ASK" : "HIDDEN_OS_CREATION_NOT_FINISHED_ASK", + "HIDDEN_OS_CREATION_NOT_FINISHED_CHOICE_RETRY", + "HIDDEN_OS_CREATION_NOT_FINISHED_CHOICE_TERMINATE", + "HIDDEN_OS_CREATION_NOT_FINISHED_CHOICE_ASK_LATER", + 0}; + + switch (AskMultiChoice ((void **) tmpStr, FALSE)) + { + case 1: + // User wants to restart and continue/retry + bAnswerTerminate = FALSE; + bAnswerRetry = TRUE; + break; + + case 2: + // User doesn't want to retry but wants to terminate the entire process of hidden OS creation + bAnswerTerminate = TRUE; + bAnswerRetry = FALSE; + break; + + default: + // User doesn't want to do anything now + bAnswerTerminate = FALSE; + bAnswerRetry = FALSE; + } + } + + + if (bAnswerRetry) + { + // User wants to restart and retry the pretest (or hidden OS creation) + + // We re-register the driver for boot because the user may have selected + // "Last Known Good Configuration" from the Windows boot menu. + // Note that we need to do this even when creating a hidden OS (because + // the hidden OS needs our boot driver and it will be a clone of this OS). + try + { + BootEncObj->RegisterBootDriver (bHiddenOS ? true : false); + } + catch (Exception &e) + { + e.Show (NULL); + } + + if (AskWarnYesNo ("CONFIRM_RESTART") == IDYES) + { + EndMainDlg (MainDlg); + + try + { + BootEncObj->RestartComputer (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + return; + } + + EndMainDlg (MainDlg); + return; + } + else if (bAnswerTerminate) + { + // User doesn't want to retry pretest (or OS cloning), but to terminate the entire process + + try + { + BootEncObj->Deinstall (); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + ManageStartupSeqWiz (TRUE, ""); + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + EndMainDlg (MainDlg); + return; + } + else + { + // User doesn't want to take any action now + + AbortProcessSilent(); + } + } + } + break; + + default: + + // Unexpected progress status -- fix the inconsistency + + ManageStartupSeqWiz (TRUE, ""); + ChangeSystemEncryptionStatus (SYSENC_STATUS_NONE); + EndMainDlg (MainDlg); + InconsistencyResolved (SRC_POS); + return; + } + } + else + { + if (DirectDeviceEncMode) + { + SwitchWizardToNonSysDeviceMode(); + return; + } + + if (DirectPromptNonSysInplaceEncResumeMode + && !bInPlaceEncNonSysPending) + { + // This instance of the wizard has been launched via the system startup sequence to prompt for resume of + // a non-system in-place encryption process. However, no config file indicates that any such process + // has been interrupted. This inconsistency may occur, for example, when the process is finished + // but the wizard is not removed from the startup sequence because system encryption is in progress. + // Therefore, we remove it from the startup sequence now if possible. + + if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE) + ManageStartupSeqWiz (TRUE, ""); + + AbortProcessSilent (); + } + + if (DirectNonSysInplaceEncResumeMode) + { + SwitchWizardToNonSysInplaceEncResumeMode(); + return; + } + else if (DirectPromptNonSysInplaceEncResumeMode) + { + if (NonSysInplaceEncInProgressElsewhere ()) + AbortProcessSilent (); + + if (AskNonSysInPlaceEncryptionResume() == IDYES) + SwitchWizardToNonSysInplaceEncResumeMode(); + else + AbortProcessSilent (); + + return; + } + else if (bInPlaceEncNonSysPending + && !NonSysInplaceEncInProgressElsewhere () + && AskNonSysInPlaceEncryptionResume() == IDYES) + { + SwitchWizardToNonSysInplaceEncResumeMode(); + return; + } + + LoadPage (hwndDlg, INTRO_PAGE); + } +} + +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCommandLine, int nCmdShow) +{ + int status; + atexit (localcleanup); + + VirtualLock (&volumePassword, sizeof(volumePassword)); + VirtualLock (szVerify, sizeof(szVerify)); + VirtualLock (szRawPassword, sizeof(szRawPassword)); + + VirtualLock (MasterKeyGUIView, sizeof(MasterKeyGUIView)); + VirtualLock (HeaderKeyGUIView, sizeof(HeaderKeyGUIView)); + + VirtualLock (randPool, sizeof(randPool)); + VirtualLock (lastRandPool, sizeof(lastRandPool)); + VirtualLock (outRandPoolDispBuffer, sizeof(outRandPoolDispBuffer)); + + VirtualLock (&szFileName, sizeof(szFileName)); + VirtualLock (&szDiskFile, sizeof(szDiskFile)); + + try + { + BootEncObj = new BootEncryption (NULL); + } + catch (Exception &e) + { + e.Show (NULL); + } + + if (BootEncObj == NULL) + AbortProcess ("INIT_SYS_ENC"); + + InitCommonControls (); + InitApp (hInstance, lpszCommandLine); + + // Write block size greater than 64 KB causes a performance drop when writing to files on XP/Vista + if (!IsOSAtLeast (WIN_7)) + FormatWriteBufferSize = 64 * 1024; + + nPbar = IDC_PROGRESS_BAR; + + if (Randinit ()) + AbortProcess ("INIT_RAND"); + + RegisterRedTick(hInstance); + + /* Allocate, dup, then store away the application title */ + lpszTitle = GetString ("IDD_VOL_CREATION_WIZARD_DLG"); + + status = DriverAttach (); + if (status != 0) + { + if (status == ERR_OS_ERROR) + handleWin32Error (NULL); + else + handleError (NULL, status); + + AbortProcess ("NODRIVER"); + } + + if (!AutoTestAlgorithms()) + AbortProcess ("ERR_SELF_TESTS_FAILED"); + + /* Create the main dialog box */ + DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_VOL_CREATION_WIZARD_DLG), NULL, (DLGPROC) MainDialogProc, + (LPARAM)lpszCommandLine); + + return 0; +} diff --git a/Format/TCFORMAT.H b/Format/TCFORMAT.H index 5abbe56..f2c3f04 100644 --- a/Format/TCFORMAT.H +++ b/Format/TCFORMAT.H @@ -1,103 +1,102 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Common/Common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define NBR_KEY_BYTES_TO_DISPLAY 16 -#define KEY_GUI_VIEW_SIZE 64 // Max characters of the key hex dump to display - -enum timer_ids -{ - TIMER_ID_RANDVIEW = 0xff, - TIMER_ID_SYSENC_PROGRESS, - TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS, - TIMER_ID_WIPE_PROGRESS, - TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS, - TIMER_ID_KEYB_LAYOUT_GUARD -}; - -void localcleanup ( void ); -void LoadSettings ( HWND hwndDlg ); -void SaveSettings ( HWND hwndDlg ); -void EndMainDlg ( HWND hwndDlg ); -void ComboSelChangeEA ( HWND hwndDlg ); -void VerifySizeAndUpdate ( HWND hwndDlg , BOOL bUpdate ); -void __cdecl sysEncDriveAnalysisThread (void *hwndDlgArg); -void __cdecl volTransformThreadFunction ( void *hwndDlg ); -void LoadPage ( HWND hwndDlg , int nPageNo ); -int PrintFreeSpace ( HWND hwndTextBox , char *lpszDrive , PLARGE_INTEGER lDiskFree ); -void DisplaySizingErrorText ( HWND hwndTextBox ); -void EnableDisableFileNext ( HWND hComboBox , HWND hMainButton ); -BOOL QueryFreeSpace ( HWND hwndDlg , HWND hwndTextBox , BOOL display ); -BOOL FinalPreTransformPrompts (void); -void HandleOldAssignedDriveLetter (void); -void AddCipher ( HWND hComboBox , char *lpszCipher , int nCipher ); -BOOL CALLBACK PageDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); -BOOL CALLBACK MainDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); -void ExtractCommandLine ( HWND hwndDlg , char *lpszCommandLine ); -void DisplayRandPool (HWND hPoolDisplay, BOOL bShow); -int DetermineMaxHiddenVolSize (HWND hwndDlg); -BOOL IsSparseFile (HWND hwndDlg); -BOOL GetFileVolSize (HWND hwndDlg, unsigned __int64 *size); -BOOL SwitchWizardToSysEncMode (void); -void SwitchWizardToFileContainerMode (void); -BOOL ResolveUnknownSysEncDirection (void); -BOOL WipeHiddenOSCreationConfig (void); -void AfterWMInitTasks (HWND hwndDlg); -void AfterSysEncProgressWMInitTasks (HWND hwndDlg); -void InitSysEncProgressBar (void); -void InitNonSysInplaceEncProgressBar (void); -void UpdateNonSysInplaceEncProgressBar (void); -BOOL SysEncInEffect (void); -BOOL CreatingHiddenSysVol(void); -void NonSysInplaceEncPause (void); -void NonSysInplaceEncResume (void); -void ShowNonSysInPlaceEncUIStatus (void); -void UpdateNonSysInPlaceEncControls (void); -int MountHiddenVolHost ( HWND hwndDlg, char *volumePath, int *driveNo, Password *password, BOOL bReadOnly ); -int AnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *pnbrFreeClusters); -int ScanVolClusterBitmap ( HWND hwndDlg, int *driveNo, __int64 nbrClusters, __int64 *nbrFreeClusters); -int WINAPI WINMAIN ( HINSTANCE hInstance , HINSTANCE hPrevInstance , char *lpszCommandLine , int nCmdShow ); -void WipeStart (void); -void WipeAbort (void); -void UpdateWipeProgressBar (void); -void InitWipeProgressBar (void); -void UpdateWipeControls (void); - -extern BOOL showKeys; -extern volatile HWND hMasterKey; -extern volatile HWND hHeaderKey; -extern volatile BOOL bHiddenVolHost; -extern volatile BOOL bHiddenVolDirect; -extern BOOL bRemovableHostDevice; -extern BOOL bWarnDeviceFormatAdvanced; -extern HWND hCurPage; -extern HWND hProgressBar; -extern volatile BOOL bVolTransformThreadCancel; -extern volatile BOOL bInPlaceEncNonSysResumed; -extern volatile BOOL bFirstNonSysInPlaceEncResumeDone; -extern volatile BOOL bInPlaceEncNonSys; -extern __int64 NonSysInplaceEncBytesDone; -extern __int64 NonSysInplaceEncTotalSectors; -extern int nPbar; -extern volatile int WizardMode; - -extern char HeaderKeyGUIView [KEY_GUI_VIEW_SIZE]; -extern char MasterKeyGUIView [KEY_GUI_VIEW_SIZE]; -extern volatile int NonSysInplaceEncStatus; - -#ifdef __cplusplus -} -#endif +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Common/Common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NBR_KEY_BYTES_TO_DISPLAY 16 +#define KEY_GUI_VIEW_SIZE 64 // Max characters of the key hex dump to display + +enum timer_ids +{ + TIMER_ID_RANDVIEW = 0xff, + TIMER_ID_SYSENC_PROGRESS, + TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS, + TIMER_ID_WIPE_PROGRESS, + TIMER_ID_SYSENC_DRIVE_ANALYSIS_PROGRESS, + TIMER_ID_KEYB_LAYOUT_GUARD +}; + +static void localcleanup ( void ); +static void LoadSettings ( HWND hwndDlg ); +static void SaveSettings ( HWND hwndDlg ); +static void EndMainDlg ( HWND hwndDlg ); +void ComboSelChangeEA ( HWND hwndDlg ); +static void VerifySizeAndUpdate ( HWND hwndDlg , BOOL bUpdate ); +static void __cdecl sysEncDriveAnalysisThread (void *hwndDlgArg); +static void __cdecl volTransformThreadFunction ( void *hwndDlg ); +static void LoadPage ( HWND hwndDlg , int nPageNo ); +int PrintFreeSpace ( HWND hwndTextBox , char *lpszDrive , PLARGE_INTEGER lDiskFree ); +void DisplaySizingErrorText ( HWND hwndTextBox ); +void EnableDisableFileNext ( HWND hComboBox , HWND hMainButton ); +BOOL QueryFreeSpace ( HWND hwndDlg , HWND hwndTextBox , BOOL display ); +static BOOL FinalPreTransformPrompts (void); +void HandleOldAssignedDriveLetter (void); +void AddCipher ( HWND hComboBox , char *lpszCipher , int nCipher ); +BOOL CALLBACK PageDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); +BOOL CALLBACK MainDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); +void ExtractCommandLine ( HWND hwndDlg , char *lpszCommandLine ); +void DisplayRandPool (HWND hPoolDisplay, BOOL bShow); +int DetermineMaxHiddenVolSize (HWND hwndDlg); +BOOL IsSparseFile (HWND hwndDlg); +BOOL GetFileVolSize (HWND hwndDlg, unsigned __int64 *size); +BOOL SwitchWizardToSysEncMode (void); +void SwitchWizardToFileContainerMode (void); +static BOOL ResolveUnknownSysEncDirection (void); +static BOOL WipeHiddenOSCreationConfig (void); +static void AfterWMInitTasks (HWND hwndDlg); +static void AfterSysEncProgressWMInitTasks (HWND hwndDlg); +static void InitSysEncProgressBar (void); +static void InitNonSysInplaceEncProgressBar (void); +static void UpdateNonSysInplaceEncProgressBar (void); +static BOOL SysEncInEffect (void); +static BOOL CreatingHiddenSysVol(void); +static void NonSysInplaceEncPause (void); +static void NonSysInplaceEncResume (void); +void ShowNonSysInPlaceEncUIStatus (void); +void UpdateNonSysInPlaceEncControls (void); +int MountHiddenVolHost ( HWND hwndDlg, char *volumePath, int *driveNo, Password *password, BOOL bReadOnly ); +int AnalyzeHiddenVolumeHost (HWND hwndDlg, int *driveNo, __int64 hiddenVolHostSize, int *realClusterSize, __int64 *pnbrFreeClusters); +int ScanVolClusterBitmap ( HWND hwndDlg, int *driveNo, __int64 nbrClusters, __int64 *nbrFreeClusters); +static void WipeStart (void); +static void WipeAbort (void); +static void UpdateWipeProgressBar (void); +static void InitWipeProgressBar (void); +static void UpdateWipeControls (void); + +extern BOOL showKeys; +extern volatile HWND hMasterKey; +extern volatile HWND hHeaderKey; +extern volatile BOOL bHiddenVolHost; +extern volatile BOOL bHiddenVolDirect; +extern BOOL bRemovableHostDevice; +extern BOOL bWarnDeviceFormatAdvanced; +extern HWND hCurPage; +extern HWND hProgressBar; +extern volatile BOOL bVolTransformThreadCancel; +extern volatile BOOL bInPlaceEncNonSysResumed; +extern volatile BOOL bFirstNonSysInPlaceEncResumeDone; +extern volatile BOOL bInPlaceEncNonSys; +extern __int64 NonSysInplaceEncBytesDone; +extern __int64 NonSysInplaceEncTotalSectors; +extern int nPbar; +extern volatile int WizardMode; + +extern char HeaderKeyGUIView [KEY_GUI_VIEW_SIZE]; +extern char MasterKeyGUIView [KEY_GUI_VIEW_SIZE]; +extern volatile int NonSysInplaceEncStatus; + +#ifdef __cplusplus +} +#endif diff --git a/Format/resource.h b/Format/resource.h index 2ccfce4..3f9e753 100644 --- a/Format/resource.h +++ b/Format/resource.h @@ -1,151 +1,151 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Format.rc -// -#define IDR_FORMAT_TLB 1 -#define IDD_VOL_CREATION_WIZARD_DLG 101 -#define IDD_CIPHER_PAGE_DLG 102 -#define IDD_SIZE_PAGE_DLG 103 -#define IDD_PASSWORD_PAGE_DLG 104 -#define IDD_VOLUME_LOCATION_PAGE_DLG 105 -#define IDD_FORMAT_PAGE_DLG 106 -#define IDD_INTRO_PAGE_DLG 107 -#define IDD_INFO_PAGE_DLG 108 -#define IDD_HIDVOL_HOST_FILL_PAGE_DLG 109 -#define IDD_HIDDEN_VOL_WIZARD_MODE_PAGE_DLG 110 -#define IDD_PASSWORD_ENTRY_PAGE_DLG 111 -#define IDS_UACSTRING_FMT 112 -#define IDD_VOLUME_TYPE_PAGE_DLG 113 -#define IDR_FORMAT_RSRC_HEADER 114 -#define IDD_SYSENC_SPAN_PAGE_DLG 115 -#define IDB_WIZARD 116 -#define IDD_SYSENC_RESCUE_DISK_CREATION_DLG 117 -#define IDD_SYSENC_COLLECTING_RANDOM_DATA_DLG 118 -#define IDD_SYSENC_MULTI_BOOT_MODE_PAGE_DLG 119 -#define IDD_SYSENC_RESCUE_DISK_BURN_PAGE_DLG 120 -#define IDD_SYSENC_WIPE_MODE_PAGE_DLG 121 -#define IDD_INPLACE_ENCRYPTION_PAGE_DLG 122 -#define IDD_SYSENC_KEYS_GEN_PAGE_DLG 123 -#define IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG 124 -#define IDD_SYSENC_DRIVE_ANALYSIS_PAGE_DLG 125 -#define IDD_SYSENC_TYPE_PAGE_DLG 126 -#define IDD_SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_DLG 127 -#define IDD_DEVICE_WIPE_PAGE_DLG 128 -#define IDD_DEVICE_WIPE_MODE_PAGE_DLG 129 -#define IDD_DEVICE_TRANSFORM_MODE_DLG 130 -#define IDD_EXPANDED_LIST_SELECT_PAGE_DLG 131 -#define IDC_BOX_TITLE 1000 -#define IDC_RESCUE_DISK_ISO_PATH 1001 -#define IDC_COMBO_BOX 1002 -#define IDC_BOX_HELP 1003 -#define IDC_PASSWORD 1004 -#define IDC_BROWSE 1005 -#define IDC_BOX_HELP2 1006 -#define IDC_COMBO_BOX_HASH 1007 -#define IDC_COMBO_BOX_HASH_ALGO 1008 -#define IDC_SPACE_LEFT 1009 -#define IDC_VERIFY 1010 -#define IDC_KB 1011 -#define IDC_NO_HISTORY 1012 -#define IDC_MB 1013 -#define IDC_PROGRESS_BAR 1014 -#define IDC_GB 1015 -#define IDC_ABORT_BUTTON 1016 -#define IDC_HEADER_KEY 1017 -#define IDC_LIST_BOX 1018 -#define IDC_DISK_KEY 1019 -#define IDC_RANDOM_BYTES 1020 -#define IDC_CIPHER_TEST 1021 -#define IDC_WIZ_BENCHMARK 1022 -#define IDC_QUICKFORMAT 1023 -#define IDC_BYTESWRITTEN 1024 -#define IDC_WRITESPEED 1025 -#define IDC_KEY_FILES 1026 -#define IDC_TIMEREMAIN 1027 -#define IDC_CLUSTERSIZE 1028 -#define IDC_FILESYS 1029 -#define IDC_SHOW_KEYS 1030 -#define IDC_STD_VOL 1031 -#define IDC_HIDDEN_VOL 1032 -#define IDC_HIDDEN_VOL_HELP 1033 -#define IDC_OPEN_OUTER_VOLUME 1034 -#define IDC_HIDVOL_WIZ_MODE_FULL 1035 -#define IDC_HIDVOL_WIZ_MODE_DIRECT 1036 -#define IDC_PASSWORD_DIRECT 1037 -#define IDC_SIZEBOX 1038 -#define IDC_SELECT_VOLUME_LOCATION 1039 -#define IDC_NEXT 1040 -#define IDC_PREV 1041 -#define IDT_ENCRYPTION_ALGO 1042 -#define IDT_HASH_ALGO 1043 -#define IDT_FORMAT_OPTIONS 1044 -#define IDT_FILESYSTEM 1045 -#define IDT_CLUSTER 1046 -#define IDT_RANDOM_POOL 1047 -#define IDT_HEADER_KEY 1048 -#define IDT_MASTER_KEY 1049 -#define IDT_DONE 1050 -#define IDT_SPEED 1051 -#define IDT_LEFT 1052 -#define IDT_CONFIRM 1053 -#define IDT_PASSWORD 1054 -#define IDC_SHOW_PASSWORD_SINGLE 1055 -#define IDC_SHOW_PASSWORD 1056 -#define IDC_LINK_MORE_INFO_ABOUT_CIPHER 1057 -#define IDC_LINK_HASH_INFO 1058 -#define IDC_POS_BOX 1059 -#define IDC_BITMAP_WIZARD 1060 -#define IDC_FILE_CONTAINER 1061 -#define IDC_NONSYS_DEVICE 1062 -#define IDC_SYS_DEVICE 1063 -#define IDT_FILE_CONTAINER 1064 -#define IDT_NON_SYS_DEVICE 1065 -#define IDT_SYS_DEVICE 1066 -#define IDC_WHOLE_SYS_DRIVE 1067 -#define IDC_SYS_PARTITION 1068 -#define IDT_WHOLE_SYS_DRIVE 1069 -#define IDT_SYS_PARTITION 1070 -#define IDT_RESCUE_DISK_INFO 1071 -#define IDC_MORE_INFO 1072 -#define IDC_MORE_INFO_ON_SYS_ENCRYPTION 1073 -#define IDT_COLLECTING_RANDOM_DATA_NOTE 1074 -#define IDC_MORE_INFO_ON_CONTAINERS 1075 -#define IDC_SINGLE_BOOT 1076 -#define IDC_MULTI_BOOT 1077 -#define IDT_MULTI_BOOT 1078 -#define IDT_SINGLE_BOOT 1079 -#define IDC_SYS_POOL_CONTENTS 1080 -#define IDT_PARTIAL_POOL_CONTENTS 1081 -#define IDC_DOWNLOAD_CD_BURN_SOFTWARE 1082 -#define IDT_RESCUE_DISK_BURN_INFO 1083 -#define IDT_WIPE_MODE_INFO 1084 -#define IDC_WIPE_MODE 1085 -#define IDC_SELECT 1086 -#define IDT_SYSENC_KEYS_GEN_INFO 1087 -#define IDC_DISPLAY_KEYS 1088 -#define IDC_PAUSE 1089 -#define IDT_WIPE_MODE 1090 -#define IDC_MORE_INFO_SYS_ENCRYPTION 1091 -#define IDC_BOX_HELP_NORMAL_VOL 1092 -#define IDT_STATUS 1093 -#define IDT_PROGRESS 1094 -#define IDT_SYSENC_DRIVE_ANALYSIS_INFO 1095 -#define IDC_SYSENC_NORMAL 1096 -#define IDC_SYSENC_HIDDEN 1097 -#define IDC_BOX_HELP_SYSENC_NORMAL 1098 -#define IDC_HIDDEN_SYSENC_INFO_LINK 1099 -#define IDT_PASS 1100 -#define IDC_DEVICE_TRANSFORM_MODE_FORMAT 1101 -#define IDC_DEVICE_TRANSFORM_MODE_INPLACE 1102 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 132 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1103 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Format.rc +// +#define IDR_FORMAT_TLB 1 +#define IDD_VOL_CREATION_WIZARD_DLG 101 +#define IDD_CIPHER_PAGE_DLG 102 +#define IDD_SIZE_PAGE_DLG 103 +#define IDD_PASSWORD_PAGE_DLG 104 +#define IDD_VOLUME_LOCATION_PAGE_DLG 105 +#define IDD_FORMAT_PAGE_DLG 106 +#define IDD_INTRO_PAGE_DLG 107 +#define IDD_INFO_PAGE_DLG 108 +#define IDD_HIDVOL_HOST_FILL_PAGE_DLG 109 +#define IDD_HIDDEN_VOL_WIZARD_MODE_PAGE_DLG 110 +#define IDD_PASSWORD_ENTRY_PAGE_DLG 111 +#define IDS_UACSTRING_FMT 112 +#define IDD_VOLUME_TYPE_PAGE_DLG 113 +#define IDR_FORMAT_RSRC_HEADER 114 +#define IDD_SYSENC_SPAN_PAGE_DLG 115 +#define IDB_WIZARD 116 +#define IDD_SYSENC_RESCUE_DISK_CREATION_DLG 117 +#define IDD_SYSENC_COLLECTING_RANDOM_DATA_DLG 118 +#define IDD_SYSENC_MULTI_BOOT_MODE_PAGE_DLG 119 +#define IDD_SYSENC_RESCUE_DISK_BURN_PAGE_DLG 120 +#define IDD_SYSENC_WIPE_MODE_PAGE_DLG 121 +#define IDD_INPLACE_ENCRYPTION_PAGE_DLG 122 +#define IDD_SYSENC_KEYS_GEN_PAGE_DLG 123 +#define IDD_UNIVERSAL_DUAL_CHOICE_PAGE_DLG 124 +#define IDD_SYSENC_DRIVE_ANALYSIS_PAGE_DLG 125 +#define IDD_SYSENC_TYPE_PAGE_DLG 126 +#define IDD_SYSENC_HIDDEN_OS_REQ_CHECK_PAGE_DLG 127 +#define IDD_DEVICE_WIPE_PAGE_DLG 128 +#define IDD_DEVICE_WIPE_MODE_PAGE_DLG 129 +#define IDD_DEVICE_TRANSFORM_MODE_DLG 130 +#define IDD_EXPANDED_LIST_SELECT_PAGE_DLG 131 +#define IDC_BOX_TITLE 1000 +#define IDC_RESCUE_DISK_ISO_PATH 1001 +#define IDC_COMBO_BOX 1002 +#define IDC_BOX_HELP 1003 +#define IDC_PASSWORD 1004 +#define IDC_BROWSE 1005 +#define IDC_BOX_HELP2 1006 +#define IDC_COMBO_BOX_HASH 1007 +#define IDC_COMBO_BOX_HASH_ALGO 1008 +#define IDC_SPACE_LEFT 1009 +#define IDC_VERIFY 1010 +#define IDC_KB 1011 +#define IDC_NO_HISTORY 1012 +#define IDC_MB 1013 +#define IDC_PROGRESS_BAR 1014 +#define IDC_GB 1015 +#define IDC_ABORT_BUTTON 1016 +#define IDC_HEADER_KEY 1017 +#define IDC_LIST_BOX 1018 +#define IDC_DISK_KEY 1019 +#define IDC_RANDOM_BYTES 1020 +#define IDC_CIPHER_TEST 1021 +#define IDC_WIZ_BENCHMARK 1022 +#define IDC_QUICKFORMAT 1023 +#define IDC_BYTESWRITTEN 1024 +#define IDC_WRITESPEED 1025 +#define IDC_KEY_FILES 1026 +#define IDC_TIMEREMAIN 1027 +#define IDC_CLUSTERSIZE 1028 +#define IDC_FILESYS 1029 +#define IDC_SHOW_KEYS 1030 +#define IDC_STD_VOL 1031 +#define IDC_HIDDEN_VOL 1032 +#define IDC_HIDDEN_VOL_HELP 1033 +#define IDC_OPEN_OUTER_VOLUME 1034 +#define IDC_HIDVOL_WIZ_MODE_FULL 1035 +#define IDC_HIDVOL_WIZ_MODE_DIRECT 1036 +#define IDC_PASSWORD_DIRECT 1037 +#define IDC_SIZEBOX 1038 +#define IDC_SELECT_VOLUME_LOCATION 1039 +#define IDC_NEXT 1040 +#define IDC_PREV 1041 +#define IDT_ENCRYPTION_ALGO 1042 +#define IDT_HASH_ALGO 1043 +#define IDT_FORMAT_OPTIONS 1044 +#define IDT_FILESYSTEM 1045 +#define IDT_CLUSTER 1046 +#define IDT_RANDOM_POOL 1047 +#define IDT_HEADER_KEY 1048 +#define IDT_MASTER_KEY 1049 +#define IDT_DONE 1050 +#define IDT_SPEED 1051 +#define IDT_LEFT 1052 +#define IDT_CONFIRM 1053 +#define IDT_PASSWORD 1054 +#define IDC_SHOW_PASSWORD_SINGLE 1055 +#define IDC_SHOW_PASSWORD 1056 +#define IDC_LINK_MORE_INFO_ABOUT_CIPHER 1057 +#define IDC_LINK_HASH_INFO 1058 +#define IDC_POS_BOX 1059 +#define IDC_BITMAP_WIZARD 1060 +#define IDC_FILE_CONTAINER 1061 +#define IDC_NONSYS_DEVICE 1062 +#define IDC_SYS_DEVICE 1063 +#define IDT_FILE_CONTAINER 1064 +#define IDT_NON_SYS_DEVICE 1065 +#define IDT_SYS_DEVICE 1066 +#define IDC_WHOLE_SYS_DRIVE 1067 +#define IDC_SYS_PARTITION 1068 +#define IDT_WHOLE_SYS_DRIVE 1069 +#define IDT_SYS_PARTITION 1070 +#define IDT_RESCUE_DISK_INFO 1071 +#define IDC_MORE_INFO 1072 +#define IDC_MORE_INFO_ON_SYS_ENCRYPTION 1073 +#define IDT_COLLECTING_RANDOM_DATA_NOTE 1074 +#define IDC_MORE_INFO_ON_CONTAINERS 1075 +#define IDC_SINGLE_BOOT 1076 +#define IDC_MULTI_BOOT 1077 +#define IDT_MULTI_BOOT 1078 +#define IDT_SINGLE_BOOT 1079 +#define IDC_SYS_POOL_CONTENTS 1080 +#define IDT_PARTIAL_POOL_CONTENTS 1081 +#define IDC_DOWNLOAD_CD_BURN_SOFTWARE 1082 +#define IDT_RESCUE_DISK_BURN_INFO 1083 +#define IDT_WIPE_MODE_INFO 1084 +#define IDC_WIPE_MODE 1085 +#define IDC_SELECT 1086 +#define IDT_SYSENC_KEYS_GEN_INFO 1087 +#define IDC_DISPLAY_KEYS 1088 +#define IDC_PAUSE 1089 +#define IDT_WIPE_MODE 1090 +#define IDC_MORE_INFO_SYS_ENCRYPTION 1091 +#define IDC_BOX_HELP_NORMAL_VOL 1092 +#define IDT_STATUS 1093 +#define IDT_PROGRESS 1094 +#define IDT_SYSENC_DRIVE_ANALYSIS_INFO 1095 +#define IDC_SYSENC_NORMAL 1096 +#define IDC_SYSENC_HIDDEN 1097 +#define IDC_BOX_HELP_SYSENC_NORMAL 1098 +#define IDC_HIDDEN_SYSENC_INFO_LINK 1099 +#define IDT_PASS 1100 +#define IDC_DEVICE_TRANSFORM_MODE_FORMAT 1101 +#define IDC_DEVICE_TRANSFORM_MODE_INPLACE 1102 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1103 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/License.html b/License.html index c8b182c..8096a21 100644 --- a/License.html +++ b/License.html @@ -1,177 +1,177 @@ - - - - -TrueCrypt License - - - -TrueCrypt License Version 2.7
-
-Software distributed under this license is distributed on an "AS IS" BASIS WITHOUT WARRANTIES OF ANY KIND. THE AUTHORS AND DISTRIBUTORS OF THE SOFTWARE DISCLAIM ANY LIABILITY. ANYONE WHO USES, COPIES, MODIFIES, OR (RE)DISTRIBUTES ANY PART OF THE SOFTWARE IS, BY SUCH ACTION(S), ACCEPTING AND AGREEING TO BE BOUND BY ALL TERMS AND CONDITIONS OF THIS LICENSE. IF YOU DO NOT ACCEPT THEM, DO NOT USE, COPY, MODIFY, NOR (RE)DISTRIBUTE THE SOFTWARE, NOR ANY PART(S) THEREOF.
-
-
I. Definitions
-
1. "This Product" means the work (including, but not limited to, source code, graphics, texts, and accompanying files) made available under and governed by this version of this license ("License"), as may be indicated by, but is not limited to, copyright notice(s) attached to or included in the work.
-
2. "You" means (and "Your" refers to) an individual or a legal entity (e.g., a non-profit organization, commercial organization, government agency, etc.) exercising permissions granted by this License.
-
3. "Modification" means (and "modify" refers to) any alteration of This Product, including, but not limited to, addition to or deletion from the substance or structure of This Product, translation into another language, repackaging, alteration or removal of any file included with This Product, and addition of any new files to This Product.
-
-4. "Your Product" means This Product modified by You, or any work You derive from (or base on) any part of This Product. In addition, "Your Product" means any work in which You include any (modified or unmodified) portion of This Product. However, if the work in which you include it is an aggregate software distribution (such as an operating system distribution or a cover CD-ROM of a magazine) containing multiple separate products, then the term "Your Product" includes only those products (in the aggregate software distribution) that use, include, or depend on a modified or unmodified version of This Product (and the term "Your Product" does not include the whole aggregate software distribution). For the purposes of this License, a product suite consisting of two or more products is considered a single product (operating system distributions and cover media of magazines are not considered product suites).
-
5. "Distribution" means (and "distribute" refers to), regardless of means or methods, conveyance, transfer, providing, or making available of This/Your Product or portions thereof to third parties (including, but not limited to, making This/Your Product, or portions thereof, available for download to third parties, whether or not any third party has downloaded the product, or any portion thereof, made available for download).
-

-
II. Terms and Conditions for Use, Copying, and Distribution
-
-1. Provided that You comply with all applicable terms and conditions of this License, You may make copies of This Product (unmodified) and distribute copies of This Product (unmodified) that are not included in another product forming Your Product (except as permitted under Chapter III). Note: For terms and conditions for copying and distribution of modified versions of This Product, see Chapter III.
-
2. Provided that You comply with all applicable terms and conditions of this License, You may use This Product freely (see also Chapter III) on any number of computers/systems for non-commercial and/or commercial purposes.
-

-
III. Terms and Conditions for Modification and Derivation of New Products
-
-1. If all conditions specified in the following paragraphs in this Chapter (III) are met (for exceptions, see Section III.2) and if You comply with all other applicable terms and conditions of this License, You may modify This Product (thus forming Your Product), derive new works from This Product or portions thereof (thus forming Your Product), include This Product or portions thereof in another product (thus forming Your Product, unless defined otherwise in Chapter I), and You may use (for non-commercial and/or commercial purposes), copy, and/or distribute Your Product.
-
-

    -
  1. The name of Your Product (or of Your modified version of This Product) must not contain the name TrueCrypt (for example, the following names are not allowed: TrueCrypt, TrueCrypt+, TrueCrypt Professional, iTrueCrypt, etc.) nor any other names confusingly similar to the name TrueCrypt (e.g., True-Crypt, True Crypt, TruKrypt, etc.)
    -
    - Note: TrueCrypt and the TrueCrypt logos are trademarks of the TrueCrypt Foundation. The goal is not to monetize the name or the product, but to protect the reputation of TrueCrypt, and to prevent support issues and other kinds of issues that might arise from the existence of similar products with the same or similar name. Even though TrueCrypt and the TrueCrypt logos are trademarks, TrueCrypt is and will remain open-source and free software.
    -
    - All occurrences of the name TrueCrypt that could reasonably be considered to identify Your Product must be removed from Your Product and from any associated materials. Logo(s) included in (or attached to) Your Product (and in/to associated materials) must not incorporate and must not be confusingly similar to any of the TrueCrypt logos (including the non-textual logo consisting primarily of a key in stylized form) or portion(s) thereof. All graphics contained in This Product (logos, icons, etc.) must be removed from Your Product (or from Your modified version of This Product) and from any associated materials.
    -
    -
  2. -
  3. The following phrases must be removed from Your Product and from any associated materials, except the text of this License: "A TrueCrypt Foundation Release", "Released by TrueCrypt Foundation", "This is a TrueCrypt Foundation release."
    -
    -
  4. -
  5. Phrase "Based on TrueCrypt, freely available at http://www.truecrypt.org/" must be displayed by Your Product (if technically feasible) and contained in its documentation. Alternatively, if This Product or its portion You included in Your Product constitutes only a minor portion of Your Product, phrase "Portions of this product are based in part on TrueCrypt, freely available at http://www.truecrypt.org/" may be displayed instead. In each of the cases mentioned above in this paragraph, "http://www.truecrypt.org/" must be a hyperlink (if technically feasible) pointing to http://www.truecrypt.org/ and You may freely choose the location within the user interface (if there is any) of Your Product (e.g., an "About" window, etc.) and the way in which Your Product will display the respective phrase.
    -
    - Your Product (and any associated materials, e.g., the documentation, the content of the official web site of Your Product, etc.) must not present any Internet address containing the domain name truecrypt.org (or any domain name that forwards to the domain name truecrypt.org) in a manner that might suggest that it is where information about Your Product may be obtained or where bugs found in Your Product may be reported or where support for Your Product may be available or otherwise attempt to indicate that the domain name truecrypt.org is associated with Your Product.
    -
    -
  6. -
  7. The complete source code of Your Product must be freely and publicly available (for exceptions, see Section III.2) at least until You cease to distribute Your Product and there must be a well-publicized means of obtaining the source code free of charge or for a reasonable reproduction fee (at least until You cease to distribute Your Product). Examples of possible ways to meet these conditions: (i) You include the source code with every copy of Your Product that You make and distribute (see also below in this Subsection III.1.d for conditions that licenses governing the source code must meet) provided that You make the copies available to the general public free of charge or for a reasonable reproduction fee, or (ii) You include information (valid and correct at least until You cease to distribute Your Product) about where the source code can be freely obtained (e.g., an Internet address, etc.) with every copy of Your Product that You make and distribute (see also below in this Subsection III.1.d for conditions that licenses governing the source code must meet) provided that You make the copies available to the general public free of charge or for a reasonable reproduction fee.
    -
    - Portions of the source code of Your Product not contained in This Product (e.g., portions added by You in creating Your Product, whether created by You or by third parties) must be available under license(s) that (however, see also Subsection III.1.e) allow(s) anyone to modify and derive new works from the portions of the source code that are not contained in This Product and to use, copy, and redistribute such modifications and/or derivative works. The license(s) must be perpetual, non-exclusive, royalty-free, no-charge, and worldwide, and must not invalidate, weaken, restrict, interpret, amend, modify, interfere with or otherwise affect any part, term, provision, or clause of this License. The text(s) of the license(s) must be included with every copy of Your Product that You make and distribute. The source code must not be deliberately obfuscated, and it must not be in an intermediate form (e.g., the output of a preprocessor). Source code means the preferred form in which a programmer would usually modify the program.
    -
    - Note: If you cannot comply with the above requirements, we may grant an exception under certain conditions. You may request an exception at: licensing@truecrypt.org

    -
  8. -
  9. You must not change the license terms of This Product in any way (adding any new terms is considered changing the license terms even if the original terms are retained), which means, e.g., that no part of This Product may be put under another license. You must keep intact all the legal notices contained in the source code files. You must include the following items with every copy of Your Product that You make and distribute: a clear and conspicuous notice stating that Your Product or portion(s) thereof is/are governed by this version of the TrueCrypt License, a verbatim copy of this version of the TrueCrypt License (as contained herein), a clear and conspicuous notice containing information about where the included copy of the License can be found, and an appropriate copyright notice.
    -
  10. -
-2. You are not obligated to comply with Subsection III.1.d if Your Product is not distributed (i.e., Your Product is available only to You).
-
- Note: If you cannot comply with Subsection III.1.d, we may grant an exception under certain conditions. You may request an exception at: licensing@truecrypt.org
-
-
-
- IV. Disclaimer of Liability, Disclaimer of Warranty, Indemnification
-
- You expressly acknowledge and agree to the following:
-
- 1. IN NO EVENT WILL ANY (CO)AUTHOR OF THIS PRODUCT, OR ANY APPLICABLE COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY WHO MAY COPY AND/OR (RE)DISTRIBUTE THIS PRODUCT OR PORTIONS THEREOF, AS MAY BE PERMITTED HEREIN, BE LIABLE TO YOU OR TO ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, ANY DIRECT, INDIRECT, GENERAL, SPECIAL, INCIDENTAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, CORRUPTION OR LOSS OF DATA, ANY LOSSES SUSTAINED BY YOU OR THIRD PARTIES, A FAILURE OF THIS PRODUCT TO OPERATE WITH ANY OTHER PRODUCT, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR BUSINESS INTERRUPTION), WHETHER IN CONTRACT, STRICT LIABILITY, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, ARISING OUT OF THE USE, COPYING, MODIFICATION, OR (RE)DISTRIBUTION OF THIS PRODUCT (OR A PORTION THEREOF) OR OF YOUR PRODUCT (OR A PORTION THEREOF), OR INABILITY TO USE THIS PRODUCT (OR A PORTION THEREOF), EVEN IF ANY (CO)AUTHOR, COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
- 2. THIS PRODUCT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THIS PRODUCT IS WITH YOU. SHOULD THIS PRODUCT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
-
- 3. THIS PRODUCT MAY INCORPORATE IMPLEMENTATIONS OF CRYPTOGRAPHIC ALGORITHMS THAT ARE REGULATED (E.G., SUBJECT TO EXPORT/IMPORT CONTROL REGULATIONS) OR ILLEGAL IN SOME COUNTRIES. IT IS SOLELY YOUR RESPONSIBILITY TO VERIFY THAT IT IS LEGAL TO IMPORT AND/OR (RE)EXPORT AND/OR USE THIS PRODUCT (OR PORTIONS THEREOF) IN COUNTRIES WHERE YOU INTEND TO USE IT AND/OR TO WHICH YOU INTEND TO IMPORT IT AND/OR FROM WHICH YOU INTEND TO EXPORT IT, AND IT IS SOLELY YOUR RESPONSIBILITY TO COMPLY WITH ANY APPLICABLE REGULATIONS, RESTRICTIONS, AND LAWS.
-
-4. YOU SHALL INDEMNIFY, DEFEND AND HOLD ALL (CO)AUTHORS OF THIS PRODUCT, AND APPLICABLE COPYRIGHT/TRADEMARK OWNERS, HARMLESS FROM AND AGAINST ANY AND ALL LIABILITY, DAMAGES, LOSSES, SETTLEMENTS, PENALTIES, FINES, COSTS, EXPENSES (INCLUDING REASONABLE ATTORNEYS' FEES), DEMANDS, CAUSES OF ACTION, CLAIMS, ACTIONS, PROCEEDINGS, AND SUITS, DIRECTLY RELATED TO OR ARISING OUT OF YOUR USE, INABILITY TO USE, COPYING, (RE)DISTRIBUTION, IMPORT AND/OR (RE)EXPORT OF THIS PRODUCT (OR PORTIONS THEREOF) AND/OR YOUR BREACH OF ANY TERM OF THIS LICENSE.
-
-
-
- V. Trademarks
-
- This License does not grant permission to use trademarks associated with (or applying to) This Product, except for fair use as defined by applicable law and except for use expressly permitted or required by this License. Any attempt otherwise to use trademarks associated with (or applying to) This Product automatically and immediately terminates Your rights under This License and may constitute trademark infringement (which may be prosecuted).
-
- TrueCrypt is a registered trademark of the TrueCrypt Foundation registered with the World Intellectual Property Organization, an agency of the United Nations, (international trademark registration), in the U.S. Patent and Trademark Office, and in the trademark offices of other countries. All TrueCrypt logos (including the non-textual logo consisting primarily of a key in stylized form) are trademarks of the TrueCrypt Foundation.
-
- Note: The goal is not to monetize the name or the product, but to protect the reputation of TrueCrypt. TrueCrypt is and will remain open-source and free software.
-
-
-
- VI. General Terms and Conditions, Miscellaneous Provisions
-
- 1. ANYONE WHO USES AND/OR COPIES AND/OR MODIFIES AND/OR CREATES DERIVATIVE WORKS OF AND/OR (RE)DISTRIBUTES THIS PRODUCT, OR ANY PORTION(S) THEREOF, IS, BY SUCH ACTION(S), AGREEING TO BE BOUND BY AND ACCEPTING ALL TERMS AND CONDITIONS OF THIS LICENSE (AND THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS LICENSE). IF YOU DO NOT ACCEPT (AND AGREE TO BE BOUND BY) ALL TERMS AND CONDITIONS OF THIS LICENSE, DO NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY PORTION(S) THEREOF.
-
- 2. YOU MAY NOT USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) THEREOF, EXCEPT AS EXPRESSLY PROVIDED IN THIS LICENSE (EVEN IF APPLICABLE LAW GIVES YOU MORE RIGHTS). ANY ATTEMPT (EVEN IF PERMITTED BY APPLICABLE LAW) OTHERWISE TO USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) THEREOF, AUTOMATICALLY AND IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CONSTITUTE COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). ANY RESTRICTIONS CONTAINED IN THIS LICENSE ARE ALSO LIMITATIONS ON THE SCOPE OF THIS LICENSE AND ALSO DEFINE THE SCOPE OF YOUR RIGHTS UNDER THIS LICENSE. YOUR FAILURE TO COMPLY WITH THE TERMS AND CONDITIONS OF THIS LICENSE OR FAILURE TO PERFORM ANY APPLICABLE OBLIGATION IMPOSED BY THIS LICENSE AUTOMATICALLY AND IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CAUSE OR BE CONSIDERED COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). NOTHING IN THIS LICENSE SHALL IMPLY OR BE CONSTRUED AS A PROMISE, OBLIGATION, OR COVENANT NOT TO SUE FOR COPYRIGHT OR TRADEMARK INFRINGEMENT IF YOU DO NOT COMPLY WITH THE TERMS AND CONDITIONS OF THIS LICENSE.
-
- 3. This license does not constitute or imply a waiver of any intellectual property rights except as may be otherwise expressly provided in this License. This license does not transfer, assign, or convey any intellectual property rights (e.g., it does not transfer ownership of copyrights or trademarks).
-
-4. Subject to the terms and conditions of this License, You may allow a third party to use Your copy of This Product (or a copy that You make and distribute, or Your Product) provided that the third party overtly accepts and agrees to be bound by all terms and conditions of this License and the third party is not prohibited from using This Product (or portions thereof) by this License (see, e.g., Section VI.7) or by applicable law. However, You are not obligated to ensure that the third party accepts (and agrees to be bound by all terms of) this License if You distribute only the self-extracting package (containing This Product) that does not allow the user to install (nor extract) the files contained in the package until he or she accepts and agrees to be bound by all terms and conditions of this License.
-
- 5. Without specific prior written permission from the authors of This Product (or from their common representative), You must not use the name of This Product, the names of the authors of This Product, or the names of the legal entities (or informal groups) of which the authors were/are members/employees, to endorse or promote Your Product or any work in which You include a modified or unmodified version of This Product, or to endorse or promote You or Your affiliates, or in a way that might suggest that Your Product (or any work in which You include a modified or unmodified version of This Product), You, or Your affiliates is/are endorsed by one or more authors of This Product, or in a way that might suggest that one or more authors of This Product is/are affiliated with You (or Your affiliates) or directly participated in the creation of Your Product or of any work in which You include a modified or unmodified version of This Product.
-
-6. IF YOU ARE NOT SURE WHETHER YOU UNDERSTAND ALL PARTS OF THIS LICENSE OR IF YOU ARE NOT SURE WHETHER YOU CAN COMPLY WITH ALL TERMS AND CONDITIONS OF THIS LICENSE, YOU MUST NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY PORTION(S) OF IT. YOU SHOULD CONSULT WITH A LAWYER.
-
- 7. IF (IN RELEVANT CONTEXT) ANY PROVISION OF CHAPTER IV OF THIS LICENSE IS UNENFORCEABLE, INVALID, OR PROHIBITED UNDER APPLICABLE LAW IN YOUR JURISDICTION, YOU HAVE NO RIGHTS UNDER THIS LICENSE AND YOU MUST NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY PORTION(S) THEREOF.
-
- 8. Except as otherwise provided in this License, if any provision of this License, or a portion thereof, is found to be invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of this License, and such invalid or unenforceable provision shall be construed to reflect the original intent of the provision and shall be enforced to the maximum extent permitted by applicable law so as to effect the original intent of the provision as closely as possible.
-
- ____________________________________________________________
-

-Third-Party Licenses
-
-This Product contains components that were created by third parties and that are governed by third-party licenses, which are contained hereinafter (separated by lines consisting of underscores). Each of the third-party licenses applies only to (portions of) the source code file(s) in which the third-party license is contained or in which it is explicitly referenced, and to compiled or otherwise processed forms of such source code. None of the third-party licenses applies to This Product as a whole, even when it uses terms such as "product", "program", or any other equivalent terms/phrases. This Product as a whole is governed by the TrueCrypt License (see above). Some of the third-party components have been modified by the authors of This Product. Unless otherwise stated, such modifications and additions are governed by the TrueCrypt License (see above). Note: Unless otherwise stated, graphics and files that are not part of the source code are governed by the TrueCrypt License.
-
- ____________________________________________________________
-
-
- License agreement for Encryption for the Masses.
-
- Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.
-
- This product can be copied and distributed free of charge, including source code.
-
- You may modify this product and source code, and distribute such modifications, and you may derive new works based on this product, provided that:
-
- 1. Any product which is simply derived from this product cannot be called E4M, or Encryption for the Masses.
-
- 2. If you use any of the source code in your product, and your product is distributed with source code, you must include this notice with those portions of this source code that you use.
-
- Or,
-
- If your product is distributed in binary form only, you must display on any packaging, and marketing materials which reference your product, a notice which states:
-
- "This product uses components written by Paul Le Roux <pleroux@swprofessionals.com>"
-
- 3. If you use any of the source code originally by Eric Young, you must in addition follow his terms and conditions.
-
- 4. Nothing requires that you accept this License, as you have not signed it. However, nothing else grants you permission to modify or distribute the product or its derivative works.
-
- These actions are prohibited by law if you do not accept this License.
-
- 5. If any of these license terms is found to be to broad in scope, and declared invalid by any court or legal process, you agree that all other terms shall not be so affected, and shall remain valid and enforceable.
-
- 6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 7. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS, EVEN IF SUCH HOLDER OR OTHER PARTY HAD PREVIOUSLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- ____________________________________________________________
-
- Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
-
- LICENSE TERMS
-
-The free distribution and use of this software is allowed (with or without changes) provided that:
-
    -
  1. source code distributions include the above copyright notice, this list of conditions and the following disclaimer;
    -
  2. -
  3. binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation;
    -
  4. -
  5. the name of the copyright holder is not used to endorse products built using this software without specific written permission.
  6. -
- DISCLAIMER
-
- This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose.
- ____________________________________________________________
-
- Copyright (C) 2002-2004 Mark Adler, all rights reserved
- version 1.8, 9 Jan 2004
-
- This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
-
    -
  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  2. -
  3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  4. -
  5. This notice may not be removed or altered from any source distribution.
  6. -
-____________________________________________________________
- - + + + + +TrueCrypt License + + + +TrueCrypt License Version 2.8
+
+Software distributed under this license is distributed on an "AS IS" BASIS WITHOUT WARRANTIES OF ANY KIND. THE AUTHORS AND DISTRIBUTORS OF THE SOFTWARE DISCLAIM ANY LIABILITY. ANYONE WHO USES, COPIES, MODIFIES, OR (RE)DISTRIBUTES ANY PART OF THE SOFTWARE IS, BY SUCH ACTION(S), ACCEPTING AND AGREEING TO BE BOUND BY ALL TERMS AND CONDITIONS OF THIS LICENSE. IF YOU DO NOT ACCEPT THEM, DO NOT USE, COPY, MODIFY, NOR (RE)DISTRIBUTE THE SOFTWARE, NOR ANY PART(S) THEREOF.
+
+
I. Definitions
+
1. "This Product" means the work (including, but not limited to, source code, graphics, texts, and accompanying files) made available under and governed by this version of this license ("License"), as may be indicated by, but is not limited to, copyright notice(s) attached to or included in the work.
+
2. "You" means (and "Your" refers to) an individual or a legal entity (e.g., a non-profit organization, commercial organization, government agency, etc.) exercising permissions granted by this License.
+
3. "Modification" means (and "modify" refers to) any alteration of This Product, including, but not limited to, addition to or deletion from the substance or structure of This Product, translation into another language, repackaging, alteration or removal of any file included with This Product, and addition of any new files to This Product.
+
+4. "Your Product" means This Product modified by You, or any work You derive from (or base on) any part of This Product. In addition, "Your Product" means any work in which You include any (modified or unmodified) portion of This Product. However, if the work in which you include it is an aggregate software distribution (such as an operating system distribution or a cover CD-ROM of a magazine) containing multiple separate products, then the term "Your Product" includes only those products (in the aggregate software distribution) that use, include, or depend on a modified or unmodified version of This Product (and the term "Your Product" does not include the whole aggregate software distribution). For the purposes of this License, a product suite consisting of two or more products is considered a single product (operating system distributions and cover media of magazines are not considered product suites).
+
5. "Distribution" means (and "distribute" refers to), regardless of means or methods, conveyance, transfer, providing, or making available of This/Your Product or portions thereof to third parties (including, but not limited to, making This/Your Product, or portions thereof, available for download to third parties, whether or not any third party has downloaded the product, or any portion thereof, made available for download).
+

+
II. Terms and Conditions for Use, Copying, and Distribution
+
+1. Provided that You comply with all applicable terms and conditions of this License, You may make copies of This Product (unmodified) and distribute copies of This Product (unmodified) that are not included in another product forming Your Product (except as permitted under Chapter III). Note: For terms and conditions for copying and distribution of modified versions of This Product, see Chapter III.
+
2. Provided that You comply with all applicable terms and conditions of this License, You may use This Product freely (see also Chapter III) on any number of computers/systems for non-commercial and/or commercial purposes.
+

+
III. Terms and Conditions for Modification and Derivation of New Products
+
+1. If all conditions specified in the following paragraphs in this Chapter (III) are met (for exceptions, see Section III.2) and if You comply with all other applicable terms and conditions of this License, You may modify This Product (thus forming Your Product), derive new works from This Product or portions thereof (thus forming Your Product), include This Product or portions thereof in another product (thus forming Your Product, unless defined otherwise in Chapter I), and You may use (for non-commercial and/or commercial purposes), copy, and/or distribute Your Product.
+
+
    +
  1. The name of Your Product (or of Your modified version of This Product) must not contain the name TrueCrypt (for example, the following names are not allowed: TrueCrypt, TrueCrypt+, TrueCrypt Professional, iTrueCrypt, etc.) nor any other names confusingly similar to the name TrueCrypt (e.g., True-Crypt, True Crypt, TruKrypt, etc.)
    +
    + Note: TrueCrypt and the TrueCrypt logos are trademarks of the TrueCrypt Foundation. The goal is not to monetize the name or the product, but to protect the reputation of TrueCrypt, and to prevent support issues and other kinds of issues that might arise from the existence of similar products with the same or similar name. Even though TrueCrypt and the TrueCrypt logos are trademarks, TrueCrypt is and will remain open-source and free software.
    +
    + All occurrences of the name TrueCrypt that could reasonably be considered to identify Your Product must be removed from Your Product and from any associated materials. Logo(s) included in (or attached to) Your Product (and in/to associated materials) must not incorporate and must not be confusingly similar to any of the TrueCrypt logos (including, but not limited to, the non-textual logo consisting primarily of a key in stylized form) or portion(s) thereof. All graphics contained in This Product (logos, icons, etc.) must be removed from Your Product (or from Your modified version of This Product) and from any associated materials.
    +
    +
  2. +
  3. The following phrases must be removed from Your Product and from any associated materials, except the text of this License: "A TrueCrypt Foundation Release", "Released by TrueCrypt Foundation", "This is a TrueCrypt Foundation release."
    +
    +
  4. +
  5. Phrase "Based on TrueCrypt, freely available at http://www.truecrypt.org/" must be displayed by Your Product (if technically feasible) and contained in its documentation. Alternatively, if This Product or its portion You included in Your Product constitutes only a minor portion of Your Product, phrase "Portions of this product are based in part on TrueCrypt, freely available at http://www.truecrypt.org/" may be displayed instead. In each of the cases mentioned above in this paragraph, "http://www.truecrypt.org/" must be a hyperlink (if technically feasible) pointing to http://www.truecrypt.org/ and You may freely choose the location within the user interface (if there is any) of Your Product (e.g., an "About" window, etc.) and the way in which Your Product will display the respective phrase.
    +
    + Your Product (and any associated materials, e.g., the documentation, the content of the official web site of Your Product, etc.) must not present any Internet address containing the domain name truecrypt.org (or any domain name that forwards to the domain name truecrypt.org) in a manner that might suggest that it is where information about Your Product may be obtained or where bugs found in Your Product may be reported or where support for Your Product may be available or otherwise attempt to indicate that the domain name truecrypt.org is associated with Your Product.
    +
    +
  6. +
  7. The complete source code of Your Product must be freely and publicly available (for exceptions, see Section III.2) at least until You cease to distribute Your Product and there must be a well-publicized means of obtaining the source code free of charge or for a reasonable reproduction fee (at least until You cease to distribute Your Product). Examples of possible ways to meet these conditions: (i) You include the source code with every copy of Your Product that You make and distribute (see also below in this Subsection III.1.d for conditions that licenses governing the source code must meet) provided that You make the copies available to the general public free of charge or for a reasonable reproduction fee, or (ii) You include information (valid and correct at least until You cease to distribute Your Product) about where the source code can be freely obtained (e.g., an Internet address, etc.) with every copy of Your Product that You make and distribute (see also below in this Subsection III.1.d for conditions that licenses governing the source code must meet) provided that You make the copies available to the general public free of charge or for a reasonable reproduction fee.
    +
    + Portions of the source code of Your Product not contained in This Product (e.g., portions added by You in creating Your Product, whether created by You or by third parties) must be available under license(s) that (however, see also Subsection III.1.e) allow(s) anyone to modify and derive new works from the portions of the source code that are not contained in This Product and to use, copy, and redistribute such modifications and/or derivative works. The license(s) must be perpetual, non-exclusive, royalty-free, no-charge, and worldwide, and must not invalidate, weaken, restrict, interpret, amend, modify, interfere with or otherwise affect any part, term, provision, or clause of this License. The text(s) of the license(s) must be included with every copy of Your Product that You make and distribute. The source code must not be deliberately obfuscated, and it must not be in an intermediate form (e.g., the output of a preprocessor). Source code means the preferred form in which a programmer would usually modify the program.
    +
    + Note: If you cannot comply with the above requirements, we may grant an exception under certain conditions. You may request an exception at: licensing@truecrypt.org

    +
  8. +
  9. You must not change the license terms of This Product in any way (adding any new terms is considered changing the license terms even if the original terms are retained), which means, e.g., that no part of This Product may be put under another license. You must keep intact all the legal notices contained in the source code files. You must include the following items with every copy of Your Product that You make and distribute: a clear and conspicuous notice stating that Your Product or portion(s) thereof is/are governed by this version of the TrueCrypt License, a verbatim copy of this version of the TrueCrypt License (as contained herein), a clear and conspicuous notice containing information about where the included copy of the License can be found, and an appropriate copyright notice.
    +
  10. +
+2. You are not obligated to comply with Subsection III.1.d if Your Product is not distributed (i.e., Your Product is available only to You).
+
+ Note: If you cannot comply with Subsection III.1.d, we may grant an exception under certain conditions. You may request an exception at: licensing@truecrypt.org
+
+
+
+ IV. Disclaimer of Liability, Disclaimer of Warranty, Indemnification
+
+ You expressly acknowledge and agree to the following:
+
+ 1. IN NO EVENT WILL ANY (CO)AUTHOR OF THIS PRODUCT, OR ANY APPLICABLE COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY WHO MAY COPY AND/OR (RE)DISTRIBUTE THIS PRODUCT OR PORTIONS THEREOF, AS MAY BE PERMITTED HEREIN, BE LIABLE TO YOU OR TO ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, ANY DIRECT, INDIRECT, GENERAL, SPECIAL, INCIDENTAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, CORRUPTION OR LOSS OF DATA, ANY LOSSES SUSTAINED BY YOU OR THIRD PARTIES, A FAILURE OF THIS PRODUCT TO OPERATE WITH ANY OTHER PRODUCT, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR BUSINESS INTERRUPTION), WHETHER IN CONTRACT, STRICT LIABILITY, TORT (INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE) OR OTHERWISE, ARISING OUT OF THE USE, COPYING, MODIFICATION, OR (RE)DISTRIBUTION OF THIS PRODUCT (OR A PORTION THEREOF) OR OF YOUR PRODUCT (OR A PORTION THEREOF), OR INABILITY TO USE THIS PRODUCT (OR A PORTION THEREOF), EVEN IF ANY (CO)AUTHOR, COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ 2. THIS PRODUCT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THIS PRODUCT IS WITH YOU. SHOULD THIS PRODUCT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+ 3. THIS PRODUCT MAY INCORPORATE IMPLEMENTATIONS OF CRYPTOGRAPHIC ALGORITHMS THAT ARE REGULATED (E.G., SUBJECT TO EXPORT/IMPORT CONTROL REGULATIONS) OR ILLEGAL IN SOME COUNTRIES. IT IS SOLELY YOUR RESPONSIBILITY TO VERIFY THAT IT IS LEGAL TO IMPORT AND/OR (RE)EXPORT AND/OR USE THIS PRODUCT (OR PORTIONS THEREOF) IN COUNTRIES WHERE YOU INTEND TO USE IT AND/OR TO WHICH YOU INTEND TO IMPORT IT AND/OR FROM WHICH YOU INTEND TO EXPORT IT, AND IT IS SOLELY YOUR RESPONSIBILITY TO COMPLY WITH ANY APPLICABLE REGULATIONS, RESTRICTIONS, AND LAWS.
+
+4. YOU SHALL INDEMNIFY, DEFEND AND HOLD ALL (CO)AUTHORS OF THIS PRODUCT, AND APPLICABLE COPYRIGHT/TRADEMARK OWNERS, HARMLESS FROM AND AGAINST ANY AND ALL LIABILITY, DAMAGES, LOSSES, SETTLEMENTS, PENALTIES, FINES, COSTS, EXPENSES (INCLUDING REASONABLE ATTORNEYS' FEES), DEMANDS, CAUSES OF ACTION, CLAIMS, ACTIONS, PROCEEDINGS, AND SUITS, DIRECTLY RELATED TO OR ARISING OUT OF YOUR USE, INABILITY TO USE, COPYING, (RE)DISTRIBUTION, IMPORT AND/OR (RE)EXPORT OF THIS PRODUCT (OR PORTIONS THEREOF) AND/OR YOUR BREACH OF ANY TERM OF THIS LICENSE.
+
+
+
+ V. Trademarks
+
+ This License does not grant permission to use trademarks associated with (or applying to) This Product, except for fair use as defined by applicable law and except for use expressly permitted or required by this License. Any attempt otherwise to use trademarks associated with (or applying to) This Product automatically and immediately terminates Your rights under This License and may constitute trademark infringement (which may be prosecuted).
+
+ TrueCrypt is a registered trademark of the TrueCrypt Foundation registered with the World Intellectual Property Organization, an agency of the United Nations, (international trademark registration), in the U.S. Patent and Trademark Office, and in the trademark offices of other countries. All TrueCrypt logos (including the non-textual logo consisting primarily of a key in stylized form) are trademarks of the TrueCrypt Foundation.
+
+ Note: The goal is not to monetize the name or the product, but to protect the reputation of TrueCrypt. TrueCrypt is and will remain open-source and free software.
+
+
+
+ VI. General Terms and Conditions, Miscellaneous Provisions
+
+ 1. ANYONE WHO USES AND/OR COPIES AND/OR MODIFIES AND/OR CREATES DERIVATIVE WORKS OF AND/OR (RE)DISTRIBUTES THIS PRODUCT, OR ANY PORTION(S) THEREOF, IS, BY SUCH ACTION(S), AGREEING TO BE BOUND BY AND ACCEPTING ALL TERMS AND CONDITIONS OF THIS LICENSE (AND THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS LICENSE). IF YOU DO NOT ACCEPT (AND AGREE TO BE BOUND BY) ALL TERMS AND CONDITIONS OF THIS LICENSE, DO NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY PORTION(S) THEREOF.
+
+2. YOU MAY NOT USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) THEREOF, EXCEPT AS EXPRESSLY PROVIDED IN THIS LICENSE (EVEN IF APPLICABLE LAW GIVES YOU MORE RIGHTS). ANY ATTEMPT (EVEN IF PERMITTED BY APPLICABLE LAW) OTHERWISE TO USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) THEREOF, AUTOMATICALLY AND IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CONSTITUTE COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). ANY CONDITIONS AND RESTRICTIONS CONTAINED IN THIS LICENSE ARE ALSO LIMITATIONS ON THE SCOPE OF THIS LICENSE AND ALSO DEFINE THE SCOPE OF YOUR RIGHTS UNDER THIS LICENSE. YOUR FAILURE TO COMPLY WITH THE TERMS AND CONDITIONS OF THIS LICENSE OR FAILURE TO PERFORM ANY APPLICABLE OBLIGATION IMPOSED BY THIS LICENSE AUTOMATICALLY AND IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CAUSE OR BE CONSIDERED COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). NOTHING IN THIS LICENSE SHALL IMPLY OR BE CONSTRUED AS A PROMISE, OBLIGATION, OR COVENANT NOT TO SUE FOR COPYRIGHT OR TRADEMARK INFRINGEMENT IF YOU DO NOT COMPLY WITH THE TERMS AND CONDITIONS OF THIS LICENSE.
+
+ 3. This license does not constitute or imply a waiver of any intellectual property rights except as may be otherwise expressly provided in this License. This license does not transfer, assign, or convey any intellectual property rights (e.g., it does not transfer ownership of copyrights or trademarks).
+
+4. Subject to the terms and conditions of this License, You may allow a third party to use Your copy of This Product (or a copy that You make and distribute, or Your Product) provided that the third party overtly accepts and agrees to be bound by all terms and conditions of this License and the third party is not prohibited from using This Product (or portions thereof) by this License (see, e.g., Section VI.7) or by applicable law. However, You are not obligated to ensure that the third party accepts (and agrees to be bound by all terms of) this License if You distribute only the self-extracting package (containing This Product) that does not allow the user to install (nor extract) the files contained in the package until he or she accepts and agrees to be bound by all terms and conditions of this License.
+
+ 5. Without specific prior written permission from the authors of This Product (or from their common representative), You must not use the name of This Product, the names of the authors of This Product, or the names of the legal entities (or informal groups) of which the authors were/are members/employees, to endorse or promote Your Product or any work in which You include a modified or unmodified version of This Product, or to endorse or promote You or Your affiliates, or in a way that might suggest that Your Product (or any work in which You include a modified or unmodified version of This Product), You, or Your affiliates is/are endorsed by one or more authors of This Product, or in a way that might suggest that one or more authors of This Product is/are affiliated with You (or Your affiliates) or directly participated in the creation of Your Product or of any work in which You include a modified or unmodified version of This Product.
+
+6. IF YOU ARE NOT SURE WHETHER YOU UNDERSTAND ALL PARTS OF THIS LICENSE OR IF YOU ARE NOT SURE WHETHER YOU CAN COMPLY WITH ALL TERMS AND CONDITIONS OF THIS LICENSE, YOU MUST NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY PORTION(S) OF IT. YOU SHOULD CONSULT WITH A LAWYER.
+
+ 7. IF (IN RELEVANT CONTEXT) ANY PROVISION OF CHAPTER IV OF THIS LICENSE IS UNENFORCEABLE, INVALID, OR PROHIBITED UNDER APPLICABLE LAW IN YOUR JURISDICTION, YOU HAVE NO RIGHTS UNDER THIS LICENSE AND YOU MUST NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY PORTION(S) THEREOF.
+
+ 8. Except as otherwise provided in this License, if any provision of this License, or a portion thereof, is found to be invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of this License, and such invalid or unenforceable provision shall be construed to reflect the original intent of the provision and shall be enforced to the maximum extent permitted by applicable law so as to effect the original intent of the provision as closely as possible.
+
+ ____________________________________________________________
+

+Third-Party Licenses
+
+This Product contains components that were created by third parties and that are governed by third-party licenses, which are contained hereinafter (separated by lines consisting of underscores). Each of the third-party licenses applies only to (portions of) the source code file(s) in which the third-party license is contained or in which it is explicitly referenced, and to compiled or otherwise processed forms of such source code. None of the third-party licenses applies to This Product as a whole, even when it uses terms such as "product", "program", or any other equivalent terms/phrases. This Product as a whole is governed by the TrueCrypt License (see above). Some of the third-party components have been modified by the authors of This Product. Unless otherwise stated, such modifications and additions are governed by the TrueCrypt License (see above). Note: Unless otherwise stated, graphics and files that are not part of the source code are governed by the TrueCrypt License.
+
+ ____________________________________________________________
+
+
+ License agreement for Encryption for the Masses.
+
+ Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.
+
+ This product can be copied and distributed free of charge, including source code.
+
+ You may modify this product and source code, and distribute such modifications, and you may derive new works based on this product, provided that:
+
+ 1. Any product which is simply derived from this product cannot be called E4M, or Encryption for the Masses.
+
+ 2. If you use any of the source code in your product, and your product is distributed with source code, you must include this notice with those portions of this source code that you use.
+
+ Or,
+
+ If your product is distributed in binary form only, you must display on any packaging, and marketing materials which reference your product, a notice which states:
+
+ "This product uses components written by Paul Le Roux <pleroux@swprofessionals.com>"
+
+ 3. If you use any of the source code originally by Eric Young, you must in addition follow his terms and conditions.
+
+ 4. Nothing requires that you accept this License, as you have not signed it. However, nothing else grants you permission to modify or distribute the product or its derivative works.
+
+ These actions are prohibited by law if you do not accept this License.
+
+ 5. If any of these license terms is found to be to broad in scope, and declared invalid by any court or legal process, you agree that all other terms shall not be so affected, and shall remain valid and enforceable.
+
+ 6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 7. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS, EVEN IF SUCH HOLDER OR OTHER PARTY HAD PREVIOUSLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ ____________________________________________________________
+
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+The free distribution and use of this software is allowed (with or without changes) provided that:
+
    +
  1. source code distributions include the above copyright notice, this list of conditions and the following disclaimer;
    +
  2. +
  3. binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation;
    +
  4. +
  5. the name of the copyright holder is not used to endorse products built using this software without specific written permission.
  6. +
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose.
+ ____________________________________________________________
+
+ Copyright (C) 2002-2004 Mark Adler, all rights reserved
+ version 1.8, 9 Jan 2004
+
+ This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
    +
  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  2. +
  3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  4. +
  5. This notice may not be removed or altered from any source distribution.
  6. +
+____________________________________________________________
+ + diff --git a/License.txt b/License.txt index 0bb3c64..52c0dd9 100644 --- a/License.txt +++ b/License.txt @@ -1,531 +1,533 @@ -TrueCrypt License Version 2.7 - -Software distributed under this license is distributed on an "AS -IS" BASIS WITHOUT WARRANTIES OF ANY KIND. THE AUTHORS AND -DISTRIBUTORS OF THE SOFTWARE DISCLAIM ANY LIABILITY. ANYONE WHO -USES, COPIES, MODIFIES, OR (RE)DISTRIBUTES ANY PART OF THE -SOFTWARE IS, BY SUCH ACTION(S), ACCEPTING AND AGREEING TO BE -BOUND BY ALL TERMS AND CONDITIONS OF THIS LICENSE. IF YOU DO NOT -ACCEPT THEM, DO NOT USE, COPY, MODIFY, NOR (RE)DISTRIBUTE THE -SOFTWARE, NOR ANY PART(S) THEREOF. - - -I. Definitions - -1. "This Product" means the work (including, but not limited to, -source code, graphics, texts, and accompanying files) made -available under and governed by this version of this license -("License"), as may be indicated by, but is not limited to, -copyright notice(s) attached to or included in the work. - -2. "You" means (and "Your" refers to) an individual or a legal -entity (e.g., a non-profit organization, commercial -organization, government agency, etc.) exercising permissions -granted by this License. - -3. "Modification" means (and "modify" refers to) any alteration -of This Product, including, but not limited to, addition to or -deletion from the substance or structure of This Product, -translation into another language, repackaging, alteration or -removal of any file included with This Product, and addition of -any new files to This Product. - -4. "Your Product" means This Product modified by You, or any -work You derive from (or base on) any part of This Product. In -addition, "Your Product" means any work in which You include any -(modified or unmodified) portion of This Product. However, if -the work in which you include it is an aggregate software -distribution (such as an operating system distribution or a -cover CD-ROM of a magazine) containing multiple separate -products, then the term "Your Product" includes only those -products (in the aggregate software distribution) that use, -include, or depend on a modified or unmodified version of This -Product (and the term "Your Product" does not include the whole -aggregate software distribution). For the purposes of this -License, a product suite consisting of two or more products is -considered a single product (operating system distributions and -cover media of magazines are not considered product suites). - -5. "Distribution" means (and "distribute" refers to), regardless -of means or methods, conveyance, transfer, providing, or making -available of This/Your Product or portions thereof to third -parties (including, but not limited to, making This/Your -Product, or portions thereof, available for download to third -parties, whether or not any third party has downloaded the -product, or any portion thereof, made available for download). - - - -II. Terms and Conditions for Use, Copying, and Distribution - -1. Provided that You comply with all applicable terms and -conditions of this License, You may make copies of This Product -(unmodified) and distribute copies of This Product (unmodified) -that are not included in another product forming Your Product -(except as permitted under Chapter III). Note: For terms and -conditions for copying and distribution of modified versions of -This Product, see Chapter III. - -2. Provided that You comply with all applicable terms and -conditions of this License, You may use This Product freely (see -also Chapter III) on any number of computers/systems for non- -commercial and/or commercial purposes. - - - -III. Terms and Conditions for Modification and Derivation of New -Products - -1. If all conditions specified in the following paragraphs in -this Chapter (III) are met (for exceptions, see Section III.2) -and if You comply with all other applicable terms and conditions -of this License, You may modify This Product (thus forming Your -Product), derive new works from This Product or portions thereof -(thus forming Your Product), include This Product or portions -thereof in another product (thus forming Your Product, unless -defined otherwise in Chapter I), and You may use (for non- -commercial and/or commercial purposes), copy, and/or distribute -Your Product. - - a. The name of Your Product (or of Your modified version of - This Product) must not contain the name TrueCrypt (for - example, the following names are not allowed: TrueCrypt, - TrueCrypt+, TrueCrypt Professional, iTrueCrypt, etc.) nor - any other names confusingly similar to the name TrueCrypt - (e.g., True-Crypt, True Crypt, TruKrypt, etc.) - - Note: TrueCrypt and the TrueCrypt logos are trademarks of - the TrueCrypt Foundation. The goal is not to monetize the - name or the product, but to protect the reputation of - TrueCrypt, and to prevent support issues and other kinds of - issues that might arise from the existence of similar - products with the same or similar name. Even though - TrueCrypt and the TrueCrypt logos are trademarks, TrueCrypt - is and will remain open-source and free software. - - All occurrences of the name TrueCrypt that could reasonably - be considered to identify Your Product must be removed from - Your Product and from any associated materials. Logo(s) - included in (or attached to) Your Product (and in/to - associated materials) must not incorporate and must not be - confusingly similar to any of the TrueCrypt logos (including - the non-textual logo consisting primarily of a key in - stylized form) or portion(s) thereof. All graphics contained - in This Product (logos, icons, etc.) must be removed from - Your Product (or from Your modified version of This Product) - and from any associated materials. - - b. The following phrases must be removed from Your Product - and from any associated materials, except the text of this - License: "A TrueCrypt Foundation Release", "Released by - TrueCrypt Foundation", "This is a TrueCrypt Foundation - release." - - c. Phrase "Based on TrueCrypt, freely available at - http://www.truecrypt.org/" must be displayed by Your Product - (if technically feasible) and contained in its - documentation. Alternatively, if This Product or its portion - You included in Your Product constitutes only a minor - portion of Your Product, phrase "Portions of this product - are based in part on TrueCrypt, freely available at - http://www.truecrypt.org/" may be displayed instead. In each - of the cases mentioned above in this paragraph, - "http://www.truecrypt.org/" must be a hyperlink (if - technically feasible) pointing to http://www.truecrypt.org/ - and You may freely choose the location within the user - interface (if there is any) of Your Product (e.g., an - "About" window, etc.) and the way in which Your Product will - display the respective phrase. - - Your Product (and any associated materials, e.g., the - documentation, the content of the official web site of Your - Product, etc.) must not present any Internet address - containing the domain name truecrypt.org (or any domain name - that forwards to the domain name truecrypt.org) in a manner - that might suggest that it is where information about Your - Product may be obtained or where bugs found in Your Product - may be reported or where support for Your Product may be - available or otherwise attempt to indicate that the domain - name truecrypt.org is associated with Your Product. - - d. The complete source code of Your Product must be freely - and publicly available (for exceptions, see Section III.2) - at least until You cease to distribute Your Product and - there must be a well-publicized means of obtaining the - source code free of charge or for a reasonable reproduction - fee (at least until You cease to distribute Your Product). - Examples of possible ways to meet these conditions: (i) You - include the source code with every copy of Your Product that - You make and distribute (see also below in this Subsection - III.1.d for conditions that licenses governing the source - code must meet) provided that You make the copies available - to the general public free of charge or for a reasonable - reproduction fee, or (ii) You include information (valid and - correct at least until You cease to distribute Your Product) - about where the source code can be freely obtained (e.g., an - Internet address, etc.) with every copy of Your Product that - You make and distribute (see also below in this Subsection - III.1.d for conditions that licenses governing the source - code must meet) provided that You make the copies available - to the general public free of charge or for a reasonable - reproduction fee. - - Portions of the source code of Your Product not contained in - This Product (e.g., portions added by You in creating Your - Product, whether created by You or by third parties) must be - available under license(s) that (however, see also - Subsection III.1.e) allow(s) anyone to modify and derive new - works from the portions of the source code that are not - contained in This Product and to use, copy, and redistribute - such modifications and/or derivative works. The license(s) - must be perpetual, non-exclusive, royalty-free, no-charge, - and worldwide, and must not invalidate, weaken, restrict, - interpret, amend, modify, interfere with or otherwise affect - any part, term, provision, or clause of this License. The - text(s) of the license(s) must be included with every copy - of Your Product that You make and distribute. The source - code must not be deliberately obfuscated, and it must not be - in an intermediate form (e.g., the output of a - preprocessor). Source code means the preferred form in which - a programmer would usually modify the program. - - Note: If you cannot comply with the above requirements, we - may grant an exception under certain conditions. You may - request an exception at: licensing@truecrypt.org - - e. You must not change the license terms of This Product in - any way (adding any new terms is considered changing the - license terms even if the original terms are retained), - which means, e.g., that no part of This Product may be put - under another license. You must keep intact all the legal - notices contained in the source code files. You must include - the following items with every copy of Your Product that You - make and distribute: a clear and conspicuous notice stating - that Your Product or portion(s) thereof is/are governed by - this version of the TrueCrypt License, a verbatim copy of - this version of the TrueCrypt License (as contained herein), - a clear and conspicuous notice containing information about - where the included copy of the License can be found, and an - appropriate copyright notice. - - -2. You are not obligated to comply with Subsection III.1.d if -Your Product is not distributed (i.e., Your Product is available -only to You). - -Note: If you cannot comply with Subsection III.1.d, we may grant -an exception under certain conditions. You may request an -exception at: licensing@truecrypt.org - - - -IV. Disclaimer of Liability, Disclaimer of Warranty, -Indemnification - -You expressly acknowledge and agree to the following: - -1. IN NO EVENT WILL ANY (CO)AUTHOR OF THIS PRODUCT, OR ANY -APPLICABLE COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY WHO MAY -COPY AND/OR (RE)DISTRIBUTE THIS PRODUCT OR PORTIONS THEREOF, AS -MAY BE PERMITTED HEREIN, BE LIABLE TO YOU OR TO ANY OTHER PARTY -FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, ANY DIRECT, -INDIRECT, GENERAL, SPECIAL, INCIDENTAL, PUNITIVE, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, CORRUPTION -OR LOSS OF DATA, ANY LOSSES SUSTAINED BY YOU OR THIRD PARTIES, A -FAILURE OF THIS PRODUCT TO OPERATE WITH ANY OTHER PRODUCT, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR BUSINESS -INTERRUPTION), WHETHER IN CONTRACT, STRICT LIABILITY, TORT -(INCLUDING NEGLIGENCE) OR OTHERWISE, ARISING OUT OF THE USE, -COPYING, MODIFICATION, OR (RE)DISTRIBUTION OF THIS PRODUCT (OR A -PORTION THEREOF) OR OF YOUR PRODUCT (OR A PORTION THEREOF), OR -INABILITY TO USE THIS PRODUCT (OR A PORTION THEREOF), EVEN IF -ANY (CO)AUTHOR, COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY -HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -2. THIS PRODUCT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY -KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT -LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE ENTIRE RISK AS TO -THE QUALITY AND PERFORMANCE OF THIS PRODUCT IS WITH YOU. SHOULD -THIS PRODUCT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL -NECESSARY SERVICING, REPAIR, OR CORRECTION. - -3. THIS PRODUCT MAY INCORPORATE IMPLEMENTATIONS OF CRYPTOGRAPHIC -ALGORITHMS THAT ARE REGULATED (E.G., SUBJECT TO EXPORT/IMPORT -CONTROL REGULATIONS) OR ILLEGAL IN SOME COUNTRIES. IT IS SOLELY -YOUR RESPONSIBILITY TO VERIFY THAT IT IS LEGAL TO IMPORT AND/OR -(RE)EXPORT AND/OR USE THIS PRODUCT (OR PORTIONS THEREOF) IN -COUNTRIES WHERE YOU INTEND TO USE IT AND/OR TO WHICH YOU INTEND -TO IMPORT IT AND/OR FROM WHICH YOU INTEND TO EXPORT IT, AND IT -IS SOLELY YOUR RESPONSIBILITY TO COMPLY WITH ANY APPLICABLE -REGULATIONS, RESTRICTIONS, AND LAWS. - -4. YOU SHALL INDEMNIFY, DEFEND AND HOLD ALL (CO)AUTHORS OF THIS -PRODUCT, AND APPLICABLE COPYRIGHT/TRADEMARK OWNERS, HARMLESS -FROM AND AGAINST ANY AND ALL LIABILITY, DAMAGES, LOSSES, -SETTLEMENTS, PENALTIES, FINES, COSTS, EXPENSES (INCLUDING -REASONABLE ATTORNEYS' FEES), DEMANDS, CAUSES OF ACTION, CLAIMS, -ACTIONS, PROCEEDINGS, AND SUITS, DIRECTLY RELATED TO OR ARISING -OUT OF YOUR USE, INABILITY TO USE, COPYING, (RE)DISTRIBUTION, -IMPORT AND/OR (RE)EXPORT OF THIS PRODUCT (OR PORTIONS THEREOF) -AND/OR YOUR BREACH OF ANY TERM OF THIS LICENSE. - - - -V. Trademarks - -This License does not grant permission to use trademarks -associated with (or applying to) This Product, except for fair -use as defined by applicable law and except for use expressly -permitted or required by this License. Any attempt otherwise to -use trademarks associated with (or applying to) This Product -automatically and immediately terminates Your rights under This -License and may constitute trademark infringement (which may be -prosecuted). - -TrueCrypt is a registered trademark of the TrueCrypt Foundation -registered with the World Intellectual Property Organization, an -agency of the United Nations, (international trademark -registration), in the U.S. Patent and Trademark Office, and in -the trademark offices of other countries. All TrueCrypt logos -(including the non-textual logo consisting primarily of a key in -stylized form) are trademarks of the TrueCrypt Foundation. - -Note: The goal is not to monetize the name or the product, but -to protect the reputation of TrueCrypt. TrueCrypt is and will -remain open-source and free software. - - - -VI. General Terms and Conditions, Miscellaneous Provisions - -1. ANYONE WHO USES AND/OR COPIES AND/OR MODIFIES AND/OR CREATES -DERIVATIVE WORKS OF AND/OR (RE)DISTRIBUTES THIS PRODUCT, OR ANY -PORTION(S) THEREOF, IS, BY SUCH ACTION(S), AGREEING TO BE BOUND -BY AND ACCEPTING ALL TERMS AND CONDITIONS OF THIS LICENSE (AND -THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS LICENSE). -IF YOU DO NOT ACCEPT (AND AGREE TO BE BOUND BY) ALL TERMS AND -CONDITIONS OF THIS LICENSE, DO NOT USE, COPY, MODIFY, CREATE -DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY -PORTION(S) THEREOF. - -2. YOU MAY NOT USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, -(RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) -THEREOF, EXCEPT AS EXPRESSLY PROVIDED IN THIS LICENSE (EVEN IF -APPLICABLE LAW GIVES YOU MORE RIGHTS). ANY ATTEMPT (EVEN IF -PERMITTED BY APPLICABLE LAW) OTHERWISE TO USE, MODIFY, COPY, -CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS -PRODUCT, OR PORTION(S) THEREOF, AUTOMATICALLY AND IMMEDIATELY -TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CONSTITUTE -COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). ANY -RESTRICTIONS CONTAINED IN THIS LICENSE ARE ALSO LIMITATIONS ON -THE SCOPE OF THIS LICENSE AND ALSO DEFINE THE SCOPE OF YOUR -RIGHTS UNDER THIS LICENSE. YOUR FAILURE TO COMPLY WITH THE TERMS -AND CONDITIONS OF THIS LICENSE OR FAILURE TO PERFORM ANY -APPLICABLE OBLIGATION IMPOSED BY THIS LICENSE AUTOMATICALLY AND -IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN -CAUSE OR BE CONSIDERED COPYRIGHT INFRINGEMENT (WHICH MAY BE -PROSECUTED). NOTHING IN THIS LICENSE SHALL IMPLY OR BE CONSTRUED -AS A PROMISE, OBLIGATION, OR COVENANT NOT TO SUE FOR COPYRIGHT -OR TRADEMARK INFRINGEMENT IF YOU DO NOT COMPLY WITH THE TERMS -AND CONDITIONS OF THIS LICENSE. - -3. This license does not constitute or imply a waiver of any -intellectual property rights except as may be otherwise -expressly provided in this License. This license does not -transfer, assign, or convey any intellectual property rights -(e.g., it does not transfer ownership of copyrights or -trademarks). - -4. Subject to the terms and conditions of this License, You may -allow a third party to use Your copy of This Product (or a copy -that You make and distribute, or Your Product) provided that the -third party overtly accepts and agrees to be bound by all terms -and conditions of this License and the third party is not -prohibited from using This Product (or portions thereof) by this -License (see, e.g., Section VI.7) or by applicable law. However, -You are not obligated to ensure that the third party accepts -(and agrees to be bound by all terms of) this License if You -distribute only the self-extracting package (containing This -Product) that does not allow the user to install (nor extract) -the files contained in the package until he or she accepts and -agrees to be bound by all terms and conditions of this License. - -5. Without specific prior written permission from the authors of -This Product (or from their common representative), You must not -use the name of This Product, the names of the authors of This -Product, or the names of the legal entities (or informal groups) -of which the authors were/are members/employees, to endorse or -promote Your Product or any work in which You include a modified -or unmodified version of This Product, or to endorse or promote -You or Your affiliates, or in a way that might suggest that Your -Product (or any work in which You include a modified or -unmodified version of This Product), You, or Your affiliates -is/are endorsed by one or more authors of This Product, or in a -way that might suggest that one or more authors of This Product -is/are affiliated with You (or Your affiliates) or directly -participated in the creation of Your Product or of any work in -which You include a modified or unmodified version of This -Product. - -6. IF YOU ARE NOT SURE WHETHER YOU UNDERSTAND ALL PARTS OF THIS -LICENSE OR IF YOU ARE NOT SURE WHETHER YOU CAN COMPLY WITH ALL -TERMS AND CONDITIONS OF THIS LICENSE, YOU MUST NOT USE, COPY, -MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS -PRODUCT, NOR ANY PORTION(S) OF IT. YOU SHOULD CONSULT WITH A -LAWYER. - -7. IF (IN RELEVANT CONTEXT) ANY PROVISION OF CHAPTER IV OF THIS -LICENSE IS UNENFORCEABLE, INVALID, OR PROHIBITED UNDER -APPLICABLE LAW IN YOUR JURISDICTION, YOU HAVE NO RIGHTS UNDER -THIS LICENSE AND YOU MUST NOT USE, COPY, MODIFY, CREATE -DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY -PORTION(S) THEREOF. - -8. Except as otherwise provided in this License, if any -provision of this License, or a portion thereof, is found to be -invalid or unenforceable under applicable law, it shall not -affect the validity or enforceability of the remainder of this -License, and such invalid or unenforceable provision shall be -construed to reflect the original intent of the provision and -shall be enforced to the maximum extent permitted by applicable -law so as to effect the original intent of the provision as -closely as possible. - -____________________________________________________________ - - -Third-Party Licenses - -This Product contains components that were created by third -parties and that are governed by third-party licenses, which are -contained hereinafter (separated by lines consisting of -underscores). Each of the third-party licenses applies only to -(portions of) the source code file(s) in which the third-party -license is contained or in which it is explicitly referenced, -and to compiled or otherwise processed forms of such source -code. None of the third-party licenses applies to This Product -as a whole, even when it uses terms such as "product", -"program", or any other equivalent terms/phrases. This Product -as a whole is governed by the TrueCrypt License (see above). -Some of the third-party components have been modified by the -authors of This Product. Unless otherwise stated, such -modifications and additions are governed by the TrueCrypt -License (see above). Note: Unless otherwise stated, graphics and -files that are not part of the source code are governed by the -TrueCrypt License. - -____________________________________________________________ - -License agreement for Encryption for the Masses. - -Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved. - -This product can be copied and distributed free of charge, -including source code. - -You may modify this product and source code, and distribute such -modifications, and you may derive new works based on this -product, provided that: - -1. Any product which is simply derived from this product cannot -be called E4M, or Encryption for the Masses. - -2. If you use any of the source code in your product, and your -product is distributed with source code, you must include this -notice with those portions of this source code that you use. - -Or, - -If your product is distributed in binary form only, you must -display on any packaging, and marketing materials which -reference your product, a notice which states: - -"This product uses components written by Paul Le Roux -" - -3. If you use any of the source code originally by Eric Young, -you must in addition follow his terms and conditions. - -4. Nothing requires that you accept this License, as you have -not signed it. However, nothing else grants you permission to -modify or distribute the product or its derivative works. - -These actions are prohibited by law if you do not accept this -License. - -5. If any of these license terms is found to be to broad in -scope, and declared invalid by any court or legal process, you -agree that all other terms shall not be so affected, and shall -remain valid and enforceable. - -6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE THERE -IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED -"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR -IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE -ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS -WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE -COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -7. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY -MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, -INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS -OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH -ANY OTHER PROGRAMS, EVEN IF SUCH HOLDER OR OTHER PARTY HAD -PREVIOUSLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -____________________________________________________________ - -Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. -All rights reserved. - -LICENSE TERMS - -The free distribution and use of this software is allowed (with -or without changes) provided that: - - 1. source code distributions include the above copyright - notice, this list of conditions and the following - disclaimer; - - 2. binary distributions include the above copyright notice, - this list of conditions and the following disclaimer in - their documentation; - - 3. the name of the copyright holder is not used to endorse - products built using this software without specific written - permission. - -DISCLAIMER - -This software is provided 'as is' with no explicit or implied -warranties in respect of its properties, including, but not -limited to, correctness and/or fitness for purpose. -____________________________________________________________ - -Copyright (C) 2002-2004 Mark Adler, all rights reserved -version 1.8, 9 Jan 2004 - -This software is provided 'as-is', without any express or -implied warranty. In no event will the author be held liable -for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you - must not claim that you wrote the original software. If you - use this software in a product, an acknowledgment in the - product documentation would be appreciated but is not - required. -2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source - distribution. -____________________________________________________________ +TrueCrypt License Version 2.8 + +Software distributed under this license is distributed on an "AS +IS" BASIS WITHOUT WARRANTIES OF ANY KIND. THE AUTHORS AND +DISTRIBUTORS OF THE SOFTWARE DISCLAIM ANY LIABILITY. ANYONE WHO +USES, COPIES, MODIFIES, OR (RE)DISTRIBUTES ANY PART OF THE +SOFTWARE IS, BY SUCH ACTION(S), ACCEPTING AND AGREEING TO BE +BOUND BY ALL TERMS AND CONDITIONS OF THIS LICENSE. IF YOU DO NOT +ACCEPT THEM, DO NOT USE, COPY, MODIFY, NOR (RE)DISTRIBUTE THE +SOFTWARE, NOR ANY PART(S) THEREOF. + + +I. Definitions + +1. "This Product" means the work (including, but not limited to, +source code, graphics, texts, and accompanying files) made +available under and governed by this version of this license +("License"), as may be indicated by, but is not limited to, +copyright notice(s) attached to or included in the work. + +2. "You" means (and "Your" refers to) an individual or a legal +entity (e.g., a non-profit organization, commercial +organization, government agency, etc.) exercising permissions +granted by this License. + +3. "Modification" means (and "modify" refers to) any alteration +of This Product, including, but not limited to, addition to or +deletion from the substance or structure of This Product, +translation into another language, repackaging, alteration or +removal of any file included with This Product, and addition of +any new files to This Product. + +4. "Your Product" means This Product modified by You, or any +work You derive from (or base on) any part of This Product. In +addition, "Your Product" means any work in which You include any +(modified or unmodified) portion of This Product. However, if +the work in which you include it is an aggregate software +distribution (such as an operating system distribution or a +cover CD-ROM of a magazine) containing multiple separate +products, then the term "Your Product" includes only those +products (in the aggregate software distribution) that use, +include, or depend on a modified or unmodified version of This +Product (and the term "Your Product" does not include the whole +aggregate software distribution). For the purposes of this +License, a product suite consisting of two or more products is +considered a single product (operating system distributions and +cover media of magazines are not considered product suites). + +5. "Distribution" means (and "distribute" refers to), regardless +of means or methods, conveyance, transfer, providing, or making +available of This/Your Product or portions thereof to third +parties (including, but not limited to, making This/Your +Product, or portions thereof, available for download to third +parties, whether or not any third party has downloaded the +product, or any portion thereof, made available for download). + + + +II. Terms and Conditions for Use, Copying, and Distribution + +1. Provided that You comply with all applicable terms and +conditions of this License, You may make copies of This Product +(unmodified) and distribute copies of This Product (unmodified) +that are not included in another product forming Your Product +(except as permitted under Chapter III). Note: For terms and +conditions for copying and distribution of modified versions of +This Product, see Chapter III. + +2. Provided that You comply with all applicable terms and +conditions of this License, You may use This Product freely (see +also Chapter III) on any number of computers/systems for non- +commercial and/or commercial purposes. + + + +III. Terms and Conditions for Modification and Derivation of New +Products + +1. If all conditions specified in the following paragraphs in +this Chapter (III) are met (for exceptions, see Section III.2) +and if You comply with all other applicable terms and conditions +of this License, You may modify This Product (thus forming Your +Product), derive new works from This Product or portions thereof +(thus forming Your Product), include This Product or portions +thereof in another product (thus forming Your Product, unless +defined otherwise in Chapter I), and You may use (for non- +commercial and/or commercial purposes), copy, and/or distribute +Your Product. + + a. The name of Your Product (or of Your modified version of + This Product) must not contain the name TrueCrypt (for + example, the following names are not allowed: TrueCrypt, + TrueCrypt+, TrueCrypt Professional, iTrueCrypt, etc.) nor + any other names confusingly similar to the name TrueCrypt + (e.g., True-Crypt, True Crypt, TruKrypt, etc.) + + Note: TrueCrypt and the TrueCrypt logos are trademarks of + the TrueCrypt Foundation. The goal is not to monetize the + name or the product, but to protect the reputation of + TrueCrypt, and to prevent support issues and other kinds of + issues that might arise from the existence of similar + products with the same or similar name. Even though + TrueCrypt and the TrueCrypt logos are trademarks, TrueCrypt + is and will remain open-source and free software. + + All occurrences of the name TrueCrypt that could reasonably + be considered to identify Your Product must be removed from + Your Product and from any associated materials. Logo(s) + included in (or attached to) Your Product (and in/to + associated materials) must not incorporate and must not be + confusingly similar to any of the TrueCrypt logos + (including, but not limited to, the non-textual logo + consisting primarily of a key in stylized form) or + portion(s) thereof. All graphics contained in This Product + (logos, icons, etc.) must be removed from Your Product (or + from Your modified version of This Product) and from any + associated materials. + + b. The following phrases must be removed from Your Product + and from any associated materials, except the text of this + License: "A TrueCrypt Foundation Release", "Released by + TrueCrypt Foundation", "This is a TrueCrypt Foundation + release." + + c. Phrase "Based on TrueCrypt, freely available at + http://www.truecrypt.org/" must be displayed by Your Product + (if technically feasible) and contained in its + documentation. Alternatively, if This Product or its portion + You included in Your Product constitutes only a minor + portion of Your Product, phrase "Portions of this product + are based in part on TrueCrypt, freely available at + http://www.truecrypt.org/" may be displayed instead. In each + of the cases mentioned above in this paragraph, + "http://www.truecrypt.org/" must be a hyperlink (if + technically feasible) pointing to http://www.truecrypt.org/ + and You may freely choose the location within the user + interface (if there is any) of Your Product (e.g., an + "About" window, etc.) and the way in which Your Product will + display the respective phrase. + + Your Product (and any associated materials, e.g., the + documentation, the content of the official web site of Your + Product, etc.) must not present any Internet address + containing the domain name truecrypt.org (or any domain name + that forwards to the domain name truecrypt.org) in a manner + that might suggest that it is where information about Your + Product may be obtained or where bugs found in Your Product + may be reported or where support for Your Product may be + available or otherwise attempt to indicate that the domain + name truecrypt.org is associated with Your Product. + + d. The complete source code of Your Product must be freely + and publicly available (for exceptions, see Section III.2) + at least until You cease to distribute Your Product and + there must be a well-publicized means of obtaining the + source code free of charge or for a reasonable reproduction + fee (at least until You cease to distribute Your Product). + Examples of possible ways to meet these conditions: (i) You + include the source code with every copy of Your Product that + You make and distribute (see also below in this Subsection + III.1.d for conditions that licenses governing the source + code must meet) provided that You make the copies available + to the general public free of charge or for a reasonable + reproduction fee, or (ii) You include information (valid and + correct at least until You cease to distribute Your Product) + about where the source code can be freely obtained (e.g., an + Internet address, etc.) with every copy of Your Product that + You make and distribute (see also below in this Subsection + III.1.d for conditions that licenses governing the source + code must meet) provided that You make the copies available + to the general public free of charge or for a reasonable + reproduction fee. + + Portions of the source code of Your Product not contained in + This Product (e.g., portions added by You in creating Your + Product, whether created by You or by third parties) must be + available under license(s) that (however, see also + Subsection III.1.e) allow(s) anyone to modify and derive new + works from the portions of the source code that are not + contained in This Product and to use, copy, and redistribute + such modifications and/or derivative works. The license(s) + must be perpetual, non-exclusive, royalty-free, no-charge, + and worldwide, and must not invalidate, weaken, restrict, + interpret, amend, modify, interfere with or otherwise affect + any part, term, provision, or clause of this License. The + text(s) of the license(s) must be included with every copy + of Your Product that You make and distribute. The source + code must not be deliberately obfuscated, and it must not be + in an intermediate form (e.g., the output of a + preprocessor). Source code means the preferred form in which + a programmer would usually modify the program. + + Note: If you cannot comply with the above requirements, we + may grant an exception under certain conditions. You may + request an exception at: licensing@truecrypt.org + + e. You must not change the license terms of This Product in + any way (adding any new terms is considered changing the + license terms even if the original terms are retained), + which means, e.g., that no part of This Product may be put + under another license. You must keep intact all the legal + notices contained in the source code files. You must include + the following items with every copy of Your Product that You + make and distribute: a clear and conspicuous notice stating + that Your Product or portion(s) thereof is/are governed by + this version of the TrueCrypt License, a verbatim copy of + this version of the TrueCrypt License (as contained herein), + a clear and conspicuous notice containing information about + where the included copy of the License can be found, and an + appropriate copyright notice. + + +2. You are not obligated to comply with Subsection III.1.d if +Your Product is not distributed (i.e., Your Product is available +only to You). + +Note: If you cannot comply with Subsection III.1.d, we may grant +an exception under certain conditions. You may request an +exception at: licensing@truecrypt.org + + + +IV. Disclaimer of Liability, Disclaimer of Warranty, +Indemnification + +You expressly acknowledge and agree to the following: + +1. IN NO EVENT WILL ANY (CO)AUTHOR OF THIS PRODUCT, OR ANY +APPLICABLE COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY WHO MAY +COPY AND/OR (RE)DISTRIBUTE THIS PRODUCT OR PORTIONS THEREOF, AS +MAY BE PERMITTED HEREIN, BE LIABLE TO YOU OR TO ANY OTHER PARTY +FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, ANY DIRECT, +INDIRECT, GENERAL, SPECIAL, INCIDENTAL, PUNITIVE, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, CORRUPTION +OR LOSS OF DATA, ANY LOSSES SUSTAINED BY YOU OR THIRD PARTIES, A +FAILURE OF THIS PRODUCT TO OPERATE WITH ANY OTHER PRODUCT, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR BUSINESS +INTERRUPTION), WHETHER IN CONTRACT, STRICT LIABILITY, TORT +(INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE) OR OTHERWISE, +ARISING OUT OF THE USE, COPYING, MODIFICATION, OR +(RE)DISTRIBUTION OF THIS PRODUCT (OR A PORTION THEREOF) OR OF +YOUR PRODUCT (OR A PORTION THEREOF), OR INABILITY TO USE THIS +PRODUCT (OR A PORTION THEREOF), EVEN IF ANY (CO)AUTHOR, +COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY HAS BEEN ADVISED +OF THE POSSIBILITY OF SUCH DAMAGES. + +2. THIS PRODUCT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY +KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT +LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE ENTIRE RISK AS TO +THE QUALITY AND PERFORMANCE OF THIS PRODUCT IS WITH YOU. SHOULD +THIS PRODUCT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL +NECESSARY SERVICING, REPAIR, OR CORRECTION. + +3. THIS PRODUCT MAY INCORPORATE IMPLEMENTATIONS OF CRYPTOGRAPHIC +ALGORITHMS THAT ARE REGULATED (E.G., SUBJECT TO EXPORT/IMPORT +CONTROL REGULATIONS) OR ILLEGAL IN SOME COUNTRIES. IT IS SOLELY +YOUR RESPONSIBILITY TO VERIFY THAT IT IS LEGAL TO IMPORT AND/OR +(RE)EXPORT AND/OR USE THIS PRODUCT (OR PORTIONS THEREOF) IN +COUNTRIES WHERE YOU INTEND TO USE IT AND/OR TO WHICH YOU INTEND +TO IMPORT IT AND/OR FROM WHICH YOU INTEND TO EXPORT IT, AND IT +IS SOLELY YOUR RESPONSIBILITY TO COMPLY WITH ANY APPLICABLE +REGULATIONS, RESTRICTIONS, AND LAWS. + +4. YOU SHALL INDEMNIFY, DEFEND AND HOLD ALL (CO)AUTHORS OF THIS +PRODUCT, AND APPLICABLE COPYRIGHT/TRADEMARK OWNERS, HARMLESS +FROM AND AGAINST ANY AND ALL LIABILITY, DAMAGES, LOSSES, +SETTLEMENTS, PENALTIES, FINES, COSTS, EXPENSES (INCLUDING +REASONABLE ATTORNEYS' FEES), DEMANDS, CAUSES OF ACTION, CLAIMS, +ACTIONS, PROCEEDINGS, AND SUITS, DIRECTLY RELATED TO OR ARISING +OUT OF YOUR USE, INABILITY TO USE, COPYING, (RE)DISTRIBUTION, +IMPORT AND/OR (RE)EXPORT OF THIS PRODUCT (OR PORTIONS THEREOF) +AND/OR YOUR BREACH OF ANY TERM OF THIS LICENSE. + + + +V. Trademarks + +This License does not grant permission to use trademarks +associated with (or applying to) This Product, except for fair +use as defined by applicable law and except for use expressly +permitted or required by this License. Any attempt otherwise to +use trademarks associated with (or applying to) This Product +automatically and immediately terminates Your rights under This +License and may constitute trademark infringement (which may be +prosecuted). + +TrueCrypt is a registered trademark of the TrueCrypt Foundation +registered with the World Intellectual Property Organization, an +agency of the United Nations, (international trademark +registration), in the U.S. Patent and Trademark Office, and in +the trademark offices of other countries. All TrueCrypt logos +(including the non-textual logo consisting primarily of a key in +stylized form) are trademarks of the TrueCrypt Foundation. + +Note: The goal is not to monetize the name or the product, but +to protect the reputation of TrueCrypt. TrueCrypt is and will +remain open-source and free software. + + + +VI. General Terms and Conditions, Miscellaneous Provisions + +1. ANYONE WHO USES AND/OR COPIES AND/OR MODIFIES AND/OR CREATES +DERIVATIVE WORKS OF AND/OR (RE)DISTRIBUTES THIS PRODUCT, OR ANY +PORTION(S) THEREOF, IS, BY SUCH ACTION(S), AGREEING TO BE BOUND +BY AND ACCEPTING ALL TERMS AND CONDITIONS OF THIS LICENSE (AND +THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS LICENSE). +IF YOU DO NOT ACCEPT (AND AGREE TO BE BOUND BY) ALL TERMS AND +CONDITIONS OF THIS LICENSE, DO NOT USE, COPY, MODIFY, CREATE +DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY +PORTION(S) THEREOF. + +2. YOU MAY NOT USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, +(RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) +THEREOF, EXCEPT AS EXPRESSLY PROVIDED IN THIS LICENSE (EVEN IF +APPLICABLE LAW GIVES YOU MORE RIGHTS). ANY ATTEMPT (EVEN IF +PERMITTED BY APPLICABLE LAW) OTHERWISE TO USE, MODIFY, COPY, +CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS +PRODUCT, OR PORTION(S) THEREOF, AUTOMATICALLY AND IMMEDIATELY +TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CONSTITUTE +COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). ANY CONDITIONS +AND RESTRICTIONS CONTAINED IN THIS LICENSE ARE ALSO LIMITATIONS +ON THE SCOPE OF THIS LICENSE AND ALSO DEFINE THE SCOPE OF YOUR +RIGHTS UNDER THIS LICENSE. YOUR FAILURE TO COMPLY WITH THE TERMS +AND CONDITIONS OF THIS LICENSE OR FAILURE TO PERFORM ANY +APPLICABLE OBLIGATION IMPOSED BY THIS LICENSE AUTOMATICALLY AND +IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN +CAUSE OR BE CONSIDERED COPYRIGHT INFRINGEMENT (WHICH MAY BE +PROSECUTED). NOTHING IN THIS LICENSE SHALL IMPLY OR BE CONSTRUED +AS A PROMISE, OBLIGATION, OR COVENANT NOT TO SUE FOR COPYRIGHT +OR TRADEMARK INFRINGEMENT IF YOU DO NOT COMPLY WITH THE TERMS +AND CONDITIONS OF THIS LICENSE. + +3. This license does not constitute or imply a waiver of any +intellectual property rights except as may be otherwise +expressly provided in this License. This license does not +transfer, assign, or convey any intellectual property rights +(e.g., it does not transfer ownership of copyrights or +trademarks). + +4. Subject to the terms and conditions of this License, You may +allow a third party to use Your copy of This Product (or a copy +that You make and distribute, or Your Product) provided that the +third party overtly accepts and agrees to be bound by all terms +and conditions of this License and the third party is not +prohibited from using This Product (or portions thereof) by this +License (see, e.g., Section VI.7) or by applicable law. However, +You are not obligated to ensure that the third party accepts +(and agrees to be bound by all terms of) this License if You +distribute only the self-extracting package (containing This +Product) that does not allow the user to install (nor extract) +the files contained in the package until he or she accepts and +agrees to be bound by all terms and conditions of this License. + +5. Without specific prior written permission from the authors of +This Product (or from their common representative), You must not +use the name of This Product, the names of the authors of This +Product, or the names of the legal entities (or informal groups) +of which the authors were/are members/employees, to endorse or +promote Your Product or any work in which You include a modified +or unmodified version of This Product, or to endorse or promote +You or Your affiliates, or in a way that might suggest that Your +Product (or any work in which You include a modified or +unmodified version of This Product), You, or Your affiliates +is/are endorsed by one or more authors of This Product, or in a +way that might suggest that one or more authors of This Product +is/are affiliated with You (or Your affiliates) or directly +participated in the creation of Your Product or of any work in +which You include a modified or unmodified version of This +Product. + +6. IF YOU ARE NOT SURE WHETHER YOU UNDERSTAND ALL PARTS OF THIS +LICENSE OR IF YOU ARE NOT SURE WHETHER YOU CAN COMPLY WITH ALL +TERMS AND CONDITIONS OF THIS LICENSE, YOU MUST NOT USE, COPY, +MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS +PRODUCT, NOR ANY PORTION(S) OF IT. YOU SHOULD CONSULT WITH A +LAWYER. + +7. IF (IN RELEVANT CONTEXT) ANY PROVISION OF CHAPTER IV OF THIS +LICENSE IS UNENFORCEABLE, INVALID, OR PROHIBITED UNDER +APPLICABLE LAW IN YOUR JURISDICTION, YOU HAVE NO RIGHTS UNDER +THIS LICENSE AND YOU MUST NOT USE, COPY, MODIFY, CREATE +DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY +PORTION(S) THEREOF. + +8. Except as otherwise provided in this License, if any +provision of this License, or a portion thereof, is found to be +invalid or unenforceable under applicable law, it shall not +affect the validity or enforceability of the remainder of this +License, and such invalid or unenforceable provision shall be +construed to reflect the original intent of the provision and +shall be enforced to the maximum extent permitted by applicable +law so as to effect the original intent of the provision as +closely as possible. + +____________________________________________________________ + + +Third-Party Licenses + +This Product contains components that were created by third +parties and that are governed by third-party licenses, which are +contained hereinafter (separated by lines consisting of +underscores). Each of the third-party licenses applies only to +(portions of) the source code file(s) in which the third-party +license is contained or in which it is explicitly referenced, +and to compiled or otherwise processed forms of such source +code. None of the third-party licenses applies to This Product +as a whole, even when it uses terms such as "product", +"program", or any other equivalent terms/phrases. This Product +as a whole is governed by the TrueCrypt License (see above). +Some of the third-party components have been modified by the +authors of This Product. Unless otherwise stated, such +modifications and additions are governed by the TrueCrypt +License (see above). Note: Unless otherwise stated, graphics and +files that are not part of the source code are governed by the +TrueCrypt License. + +____________________________________________________________ + +License agreement for Encryption for the Masses. + +Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved. + +This product can be copied and distributed free of charge, +including source code. + +You may modify this product and source code, and distribute such +modifications, and you may derive new works based on this +product, provided that: + +1. Any product which is simply derived from this product cannot +be called E4M, or Encryption for the Masses. + +2. If you use any of the source code in your product, and your +product is distributed with source code, you must include this +notice with those portions of this source code that you use. + +Or, + +If your product is distributed in binary form only, you must +display on any packaging, and marketing materials which +reference your product, a notice which states: + +"This product uses components written by Paul Le Roux +" + +3. If you use any of the source code originally by Eric Young, +you must in addition follow his terms and conditions. + +4. Nothing requires that you accept this License, as you have +not signed it. However, nothing else grants you permission to +modify or distribute the product or its derivative works. + +These actions are prohibited by law if you do not accept this +License. + +5. If any of these license terms is found to be to broad in +scope, and declared invalid by any court or legal process, you +agree that all other terms shall not be so affected, and shall +remain valid and enforceable. + +6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE THERE +IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR +IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS +WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE +COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +7. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY +MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE +LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS +OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH +ANY OTHER PROGRAMS, EVEN IF SUCH HOLDER OR OTHER PARTY HAD +PREVIOUSLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +____________________________________________________________ + +Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. +All rights reserved. + +LICENSE TERMS + +The free distribution and use of this software is allowed (with +or without changes) provided that: + + 1. source code distributions include the above copyright + notice, this list of conditions and the following + disclaimer; + + 2. binary distributions include the above copyright notice, + this list of conditions and the following disclaimer in + their documentation; + + 3. the name of the copyright holder is not used to endorse + products built using this software without specific written + permission. + +DISCLAIMER + +This software is provided 'as is' with no explicit or implied +warranties in respect of its properties, including, but not +limited to, correctness and/or fitness for purpose. +____________________________________________________________ + +Copyright (C) 2002-2004 Mark Adler, all rights reserved +version 1.8, 9 Jan 2004 + +This software is provided 'as-is', without any express or +implied warranty. In no event will the author be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you + use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not + required. +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source + distribution. +____________________________________________________________ diff --git a/Main/Application.cpp b/Main/Application.cpp index 281116e..12fdabb 100644 --- a/Main/Application.cpp +++ b/Main/Application.cpp @@ -1,98 +1,98 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include -#include "Main.h" -#include "Application.h" -#include "CommandLineInterface.h" -#ifndef TC_NO_GUI -#include "GraphicUserInterface.h" -#endif -#include "TextUserInterface.h" - -namespace TrueCrypt -{ - wxApp* Application::CreateConsoleApp () - { - mUserInterface = new TextUserInterface; - mUserInterfaceType = UserInterfaceType::Text; - return mUserInterface; - } - -#ifndef TC_NO_GUI - wxApp* Application::CreateGuiApp () - { - mUserInterface = new GraphicUserInterface; - mUserInterfaceType = UserInterfaceType::Graphic; - return mUserInterface; - } -#endif - - FilePath Application::GetConfigFilePath (const wxString &configFileName, bool createConfigDir) - { - wxStandardPaths stdPaths; - DirectoryPath configDir; - - if (!Core->IsInTravelMode()) - { -#ifdef TC_MACOSX - wxFileName configPath (L"~/Library/Application Support/TrueCrypt"); - configPath.Normalize(); - configDir = wstring (configPath.GetFullPath()); -#else - configDir = wstring (stdPaths.GetUserDataDir()); -#endif - } - else - configDir = GetExecutableDirectory(); - - if (createConfigDir && !configDir.IsDirectory()) - Directory::Create (configDir); - - FilePath filePath = wstring (wxFileName (wstring (configDir), configFileName).GetFullPath()); - return filePath; - } - - DirectoryPath Application::GetExecutableDirectory () - { - return wstring (wxFileName (wxStandardPaths().GetExecutablePath()).GetPath()); - } - - FilePath Application::GetExecutablePath () - { - return wstring (wxStandardPaths().GetExecutablePath()); - } - - void Application::Initialize (UserInterfaceType::Enum type) - { - switch (type) - { - case UserInterfaceType::Text: - { - wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) CreateConsoleApp); - break; - } - -#ifndef TC_NO_GUI - case UserInterfaceType::Graphic: - { - wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) CreateGuiApp); - break; - } -#endif - - default: - throw ParameterIncorrect (SRC_POS); - } - } - - int Application::ExitCode = 0; - UserInterface *Application::mUserInterface = nullptr; - UserInterfaceType::Enum Application::mUserInterfaceType; -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include +#include "Main.h" +#include "Application.h" +#include "CommandLineInterface.h" +#ifndef TC_NO_GUI +#include "GraphicUserInterface.h" +#endif +#include "TextUserInterface.h" + +namespace TrueCrypt +{ + wxApp* Application::CreateConsoleApp () + { + mUserInterface = new TextUserInterface; + mUserInterfaceType = UserInterfaceType::Text; + return mUserInterface; + } + +#ifndef TC_NO_GUI + wxApp* Application::CreateGuiApp () + { + mUserInterface = new GraphicUserInterface; + mUserInterfaceType = UserInterfaceType::Graphic; + return mUserInterface; + } +#endif + + FilePath Application::GetConfigFilePath (const wxString &configFileName, bool createConfigDir) + { + wxStandardPaths stdPaths; + DirectoryPath configDir; + + if (!Core->IsInPortableMode()) + { +#ifdef TC_MACOSX + wxFileName configPath (L"~/Library/Application Support/TrueCrypt"); + configPath.Normalize(); + configDir = wstring (configPath.GetFullPath()); +#else + configDir = wstring (stdPaths.GetUserDataDir()); +#endif + } + else + configDir = GetExecutableDirectory(); + + if (createConfigDir && !configDir.IsDirectory()) + Directory::Create (configDir); + + FilePath filePath = wstring (wxFileName (wstring (configDir), configFileName).GetFullPath()); + return filePath; + } + + DirectoryPath Application::GetExecutableDirectory () + { + return wstring (wxFileName (wxStandardPaths().GetExecutablePath()).GetPath()); + } + + FilePath Application::GetExecutablePath () + { + return wstring (wxStandardPaths().GetExecutablePath()); + } + + void Application::Initialize (UserInterfaceType::Enum type) + { + switch (type) + { + case UserInterfaceType::Text: + { + wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) CreateConsoleApp); + break; + } + +#ifndef TC_NO_GUI + case UserInterfaceType::Graphic: + { + wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) CreateGuiApp); + break; + } +#endif + + default: + throw ParameterIncorrect (SRC_POS); + } + } + + int Application::ExitCode = 0; + UserInterface *Application::mUserInterface = nullptr; + UserInterfaceType::Enum Application::mUserInterfaceType; +} diff --git a/Main/Application.h b/Main/Application.h index 73c06ef..cfbf418 100644 --- a/Main/Application.h +++ b/Main/Application.h @@ -1,40 +1,40 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_AppMain -#define TC_HEADER_Main_AppMain - -#include "Main.h" -#include "UserInterface.h" -#include "UserInterfaceType.h" - -namespace TrueCrypt -{ - class Application - { - public: - static wxApp* CreateConsoleApp (); - static wxApp* CreateGuiApp (); - static FilePath GetConfigFilePath (const wxString &configFileName, bool createConfigDir = false); - static DirectoryPath GetExecutableDirectory (); - static FilePath GetExecutablePath (); - static int GetExitCode () { return ExitCode; } - static wstring GetName () { return L"TrueCrypt"; } - static UserInterface *GetUserInterface () { return mUserInterface; } - static UserInterfaceType::Enum GetUserInterfaceType () { return mUserInterfaceType; } - static void Initialize (UserInterfaceType::Enum type); - static void SetExitCode (int code) { ExitCode = code; } - - protected: - static int ExitCode; - static UserInterface *mUserInterface; - static UserInterfaceType::Enum mUserInterfaceType; - }; -} - -#endif // TC_HEADER_Main_AppMain +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_AppMain +#define TC_HEADER_Main_AppMain + +#include "Main.h" +#include "UserInterface.h" +#include "UserInterfaceType.h" + +namespace TrueCrypt +{ + class Application + { + public: + static wxApp* CreateConsoleApp (); + static wxApp* CreateGuiApp (); + static FilePath GetConfigFilePath (const wxString &configFileName, bool createConfigDir = false); + static DirectoryPath GetExecutableDirectory (); + static FilePath GetExecutablePath (); + static int GetExitCode () { return ExitCode; } + static wstring GetName () { return L"TrueCrypt"; } + static UserInterface *GetUserInterface () { return mUserInterface; } + static UserInterfaceType::Enum GetUserInterfaceType () { return mUserInterfaceType; } + static void Initialize (UserInterfaceType::Enum type); + static void SetExitCode (int code) { ExitCode = code; } + + protected: + static int ExitCode; + static UserInterface *mUserInterface; + static UserInterfaceType::Enum mUserInterfaceType; + }; +} + +#endif // TC_HEADER_Main_AppMain diff --git a/Main/CommandLineInterface.cpp b/Main/CommandLineInterface.cpp index 48a65b8..33cb041 100644 --- a/Main/CommandLineInterface.cpp +++ b/Main/CommandLineInterface.cpp @@ -1,560 +1,567 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include -#include -#include "Core/Core.h" -#include "Application.h" -#include "CommandLineInterface.h" -#include "LanguageStrings.h" -#include "UserInterfaceException.h" - -namespace TrueCrypt -{ - CommandLineInterface::CommandLineInterface (wxCmdLineParser &parser, UserInterfaceType::Enum interfaceType) : - ArgCommand (CommandId::None), - ArgFilesystem (VolumeCreationOptions::FilesystemType::Unknown), - ArgNoHiddenVolumeProtection (false), - ArgSize (0), - ArgVolumeType (VolumeType::Unknown), - StartBackgroundTask (false) - { - parser.SetSwitchChars (L"-"); - - parser.AddOption (L"", L"auto-mount", _("Auto mount device-hosted/favorite volumes")); - parser.AddSwitch (L"", L"backup-headers", _("Backup volume headers")); - parser.AddSwitch (L"", L"background-task", _("Start Background Task")); -#ifdef TC_WINDOWS - parser.AddSwitch (L"", L"cache", _("Cache passwords and keyfiles")); -#endif - parser.AddSwitch (L"C", L"change", _("Change password or keyfiles")); - parser.AddSwitch (L"c", L"create", _("Create new volume")); - parser.AddSwitch (L"", L"create-keyfile", _("Create new keyfile")); - parser.AddSwitch (L"", L"delete-token-keyfiles", _("Delete security token keyfiles")); - parser.AddSwitch (L"d", L"dismount", _("Dismount volume")); - parser.AddOption (L"", L"encryption", _("Encryption algorithm")); - parser.AddSwitch (L"", L"explore", _("Open explorer window for mounted volume")); - parser.AddOption (L"", L"filesystem", _("Filesystem type")); - parser.AddSwitch (L"f", L"force", _("Force mount/dismount/overwrite")); -#if !defined(TC_WINDOWS) && !defined(TC_MACOSX) - parser.AddOption (L"", L"fs-options", _("Filesystem mount options")); -#endif - parser.AddOption (L"", L"hash", _("Hash algorithm")); - parser.AddSwitch (L"h", L"help", _("Display detailed command line help"), wxCMD_LINE_OPTION_HELP); - parser.AddSwitch (L"", L"import-token-keyfiles", _("Import keyfiles to security token")); - parser.AddOption (L"k", L"keyfiles", _("Keyfiles")); - parser.AddSwitch (L"l", L"list", _("List mounted volumes")); - parser.AddSwitch (L"", L"list-token-keyfiles", _("List security token keyfiles")); - parser.AddSwitch (L"", L"load-preferences", _("Load user preferences")); - parser.AddSwitch (L"", L"mount", _("Mount volume interactively")); - parser.AddOption (L"m", L"mount-options", _("TrueCrypt volume mount options")); - parser.AddOption (L"", L"new-keyfiles", _("New keyfiles")); - parser.AddOption (L"", L"new-password", _("New password")); - parser.AddSwitch (L"", L"non-interactive", _("Do not interact with user")); - parser.AddOption (L"p", L"password", _("Password")); - parser.AddOption (L"", L"protect-hidden", _("Protect hidden volume")); - parser.AddOption (L"", L"protection-keyfiles", _("Keyfiles for protected hidden volume")); - parser.AddOption (L"", L"protection-password", _("Password for protected hidden volume")); - parser.AddOption (L"", L"random-source", _("Use file as source of random data")); - parser.AddSwitch (L"", L"restore-headers", _("Restore volume headers")); - parser.AddSwitch (L"", L"quick", _("Enable quick format")); - parser.AddOption (L"", L"size", _("Size in bytes")); - parser.AddOption (L"", L"slot", _("Volume slot number")); - parser.AddSwitch (L"", L"test", _("Test internal algorithms")); - parser.AddSwitch (L"t", L"text", _("Use text user interface")); - parser.AddOption (L"", L"token-lib", _("Security token library")); - parser.AddSwitch (L"v", L"verbose", _("Enable verbose output")); - parser.AddSwitch (L"", L"version", _("Display version information")); - parser.AddSwitch (L"", L"volume-properties", _("Display volume properties")); - parser.AddOption (L"", L"volume-type", _("Volume type")); - parser.AddParam ( _("Volume path"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); - parser.AddParam ( _("Mount point"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); - - wxString str; - bool param1IsVolume = false; - bool param1IsMountedVolumeSpec = false; - bool param1IsMountPoint = false; - bool param1IsFile = false; - - if (parser.Parse () > 0) - throw_err (_("Incorrect command line specified.")); - - if (parser.Found (L"help")) - { - ArgCommand = CommandId::Help; - return; - } - - if (parser.Found (L"text") && interfaceType != UserInterfaceType::Text) - { - wstring msg = wstring (_("Option -t or --text must be specified as the first argument.")); - wcerr << msg << endl; - throw_err (msg); - } - - if (parser.Found (L"version")) - { - ArgCommand = CommandId::DisplayVersion; - return; - } - - // Preferences - if (parser.Found (L"load-preferences")) - { - // Load preferences first to allow command line options to override them - Preferences.Load(); - ArgMountOptions = Preferences.DefaultMountOptions; - } - - // Commands - if (parser.Found (L"auto-mount", &str)) - { - CheckCommandSingle(); - - wxStringTokenizer tokenizer (str, L","); - while (tokenizer.HasMoreTokens()) - { - wxString token = tokenizer.GetNextToken(); - - if (token == L"devices") - { - if (ArgCommand == CommandId::AutoMountFavorites) - ArgCommand = CommandId::AutoMountDevicesFavorites; - else - ArgCommand = CommandId::AutoMountDevices; - - param1IsMountPoint = true; - } - else if (token == L"favorites") - { - if (ArgCommand == CommandId::AutoMountDevices) - ArgCommand = CommandId::AutoMountDevicesFavorites; - else - ArgCommand = CommandId::AutoMountFavorites; - } - else - { - throw_err (LangString["UNKNOWN_OPTION"] + L": " + token); - } - } - } - - if (parser.Found (L"backup-headers")) - { - CheckCommandSingle(); - ArgCommand = CommandId::BackupHeaders; - param1IsVolume = true; - } - - if (parser.Found (L"change")) - { - CheckCommandSingle(); - ArgCommand = CommandId::ChangePassword; - param1IsVolume = true; - } - - if (parser.Found (L"create")) - { - CheckCommandSingle(); - ArgCommand = CommandId::CreateVolume; - param1IsVolume = true; - } - - if (parser.Found (L"create-keyfile")) - { - CheckCommandSingle(); - ArgCommand = CommandId::CreateKeyfile; - param1IsFile = true; - } - - if (parser.Found (L"delete-token-keyfiles")) - { - CheckCommandSingle(); - ArgCommand = CommandId::DeleteSecurityTokenKeyfiles; - } - - if (parser.Found (L"dismount")) - { - CheckCommandSingle(); - ArgCommand = CommandId::DismountVolumes; - param1IsMountedVolumeSpec = true; - } - - if (parser.Found (L"import-token-keyfiles")) - { - CheckCommandSingle(); - ArgCommand = CommandId::ImportSecurityTokenKeyfiles; - } - - if (parser.Found (L"list")) - { - CheckCommandSingle(); - ArgCommand = CommandId::ListVolumes; - param1IsMountedVolumeSpec = true; - } - - if (parser.Found (L"list-token-keyfiles")) - { - CheckCommandSingle(); - ArgCommand = CommandId::ListSecurityTokenKeyfiles; - } - - if (parser.Found (L"mount")) - { - CheckCommandSingle(); - ArgCommand = CommandId::MountVolume; - param1IsVolume = true; - } - - if (parser.Found (L"test")) - { - CheckCommandSingle(); - ArgCommand = CommandId::Test; - } - - if (parser.Found (L"volume-properties")) - { - CheckCommandSingle(); - ArgCommand = CommandId::DisplayVolumeProperties; - param1IsMountedVolumeSpec = true; - } - - // Options - if (parser.Found (L"background-task")) - StartBackgroundTask = true; - -#ifdef TC_WINDOWS - if (parser.Found (L"cache")) - ArgMountOptions.CachePassword = true; -#endif - - if (parser.Found (L"encryption", &str)) - { - ArgEncryptionAlgorithm.reset(); - - foreach (shared_ptr ea, EncryptionAlgorithm::GetAvailableAlgorithms()) - { - if (wxString (ea->GetName()).IsSameAs (str, false)) - ArgEncryptionAlgorithm = ea; - } - - if (!ArgEncryptionAlgorithm) - throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); - } - - if (parser.Found (L"explore")) - Preferences.OpenExplorerWindowAfterMount = true; - - if (parser.Found (L"filesystem", &str)) - { - if (str.IsSameAs (L"none", false)) - { - ArgMountOptions.NoFilesystem = true; - ArgFilesystem = VolumeCreationOptions::FilesystemType::None; - } - else - { - ArgMountOptions.FilesystemType = wstring (str); - - if (str.IsSameAs (L"FAT", false)) - ArgFilesystem = VolumeCreationOptions::FilesystemType::FAT; - } - } - - ArgForce = parser.Found (L"force"); - -#if !defined(TC_WINDOWS) && !defined(TC_MACOSX) - if (parser.Found (L"fs-options", &str)) - ArgMountOptions.FilesystemOptions = str; -#endif - - if (parser.Found (L"hash", &str)) - { - ArgHash.reset(); - - foreach (shared_ptr hash, Hash::GetAvailableAlgorithms()) - { - if (wxString (hash->GetName()).IsSameAs (str, false)) - ArgHash = hash; - } - - if (!ArgHash) - throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); - } - - if (parser.Found (L"keyfiles", &str)) - ArgKeyfiles = ToKeyfileList (str); - - if (parser.Found (L"mount-options", &str)) - { - wxStringTokenizer tokenizer (str, L","); - while (tokenizer.HasMoreTokens()) - { - wxString token = tokenizer.GetNextToken(); - - if (token == L"headerbak") - ArgMountOptions.UseBackupHeaders = true; - else if (token == L"nokernelcrypto") - ArgMountOptions.NoKernelCrypto = true; - else if (token == L"readonly" || token == L"ro") - ArgMountOptions.Protection = VolumeProtection::ReadOnly; - else if (token == L"system") - ArgMountOptions.PartitionInSystemEncryptionScope = true; - else if (token == L"timestamp" || token == L"ts") - ArgMountOptions.PreserveTimestamps = false; -#ifdef TC_WINDOWS - else if (token == L"removable" || token == L"rm") - ArgMountOptions.Removable = true; -#endif - else - throw_err (LangString["UNKNOWN_OPTION"] + L": " + token); - } - } - - if (parser.Found (L"new-keyfiles", &str)) - ArgNewKeyfiles = ToKeyfileList (str); - - if (parser.Found (L"new-password", &str)) - ArgNewPassword.reset (new VolumePassword (wstring (str))); - - if (parser.Found (L"non-interactive")) - Preferences.NonInteractive = true; - - if (parser.Found (L"password", &str)) - ArgPassword.reset (new VolumePassword (wstring (str))); - - if (parser.Found (L"protect-hidden", &str)) - { - if (str == L"yes") - { - if (ArgMountOptions.Protection != VolumeProtection::ReadOnly) - ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly; - } - else if (str == L"no") - ArgNoHiddenVolumeProtection = true; - else - throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); - } - - if (parser.Found (L"protection-keyfiles", &str)) - { - ArgMountOptions.ProtectionKeyfiles = ToKeyfileList (str); - ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly; - } - - if (parser.Found (L"protection-password", &str)) - { - ArgMountOptions.ProtectionPassword.reset (new VolumePassword (wstring (str))); - ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly; - } - - ArgQuick = parser.Found (L"quick"); - - if (parser.Found (L"random-source", &str)) - ArgRandomSourcePath = FilesystemPath (str); - - if (parser.Found (L"restore-headers")) - { - CheckCommandSingle(); - ArgCommand = CommandId::RestoreHeaders; - param1IsVolume = true; - } - - if (parser.Found (L"slot", &str)) - { - unsigned long number; - if (!str.ToULong (&number) || number < Core->GetFirstSlotNumber() || number > Core->GetLastSlotNumber()) - throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); - - ArgMountOptions.SlotNumber = number; - - if (param1IsMountedVolumeSpec) - { - shared_ptr volume = Core->GetMountedVolume (number); - if (!volume) - throw_err (_("No such volume is mounted.")); - - ArgVolumes.push_back (volume); - param1IsMountedVolumeSpec = false; - } - } - - if (parser.Found (L"size", &str)) - { - try - { - ArgSize = StringConverter::ToUInt64 (wstring (str)); - } - catch (...) - { - throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); - } - } - - if (parser.Found (L"token-lib", &str)) - Preferences.SecurityTokenModule = wstring (str); - - if (parser.Found (L"verbose")) - Preferences.Verbose = true; - - if (parser.Found (L"volume-type", &str)) - { - if (str.IsSameAs (L"normal", false)) - ArgVolumeType = VolumeType::Normal; - else if (str.IsSameAs (L"hidden", false)) - ArgVolumeType = VolumeType::Hidden; - else - throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); - } - - // Parameters - if (parser.GetParamCount() > 0) - { - if (ArgCommand == CommandId::None) - { - ArgCommand = CommandId::MountVolume; - param1IsVolume = true; - } - - if (param1IsVolume) - { - wxFileName volPath (parser.GetParam (0)); - -#ifdef TC_WINDOWS - if (!parser.GetParam (0).StartsWith (L"\\Device\\")) -#endif - volPath.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS); - - ArgVolumePath.reset (new VolumePath (wstring (volPath.GetFullPath()))); - } - - if (param1IsMountPoint || parser.GetParamCount() >= 2) - { - wstring s (parser.GetParam (param1IsMountPoint ? 0 : 1)); - - if (s.empty()) - ArgMountOptions.NoFilesystem = true; - - wxFileName mountPoint (wstring (Directory::AppendSeparator (s))); - mountPoint.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS); - ArgMountPoint.reset (new DirectoryPath (wstring (mountPoint.GetPath()))); - } - - if (param1IsFile) - { - ArgFilePath.reset (new FilePath (parser.GetParam (0))); - } - } - - if (param1IsMountedVolumeSpec) - ArgVolumes = GetMountedVolumes (parser.GetParamCount() > 0 ? parser.GetParam (0) : wxString()); - - if (ArgCommand == CommandId::None && Application::GetUserInterfaceType() == UserInterfaceType::Text) - parser.Usage(); - } - - CommandLineInterface::~CommandLineInterface () - { - } - - void CommandLineInterface::CheckCommandSingle () const - { - if (ArgCommand != CommandId::None) - throw_err (_("Only a single command can be specified at a time.")); - } - - shared_ptr CommandLineInterface::ToKeyfileList (const wxString &arg) const - { - wxStringTokenizer tokenizer (arg, L",", wxTOKEN_RET_EMPTY_ALL); - - // Handle escaped separator - wxArrayString arr; - bool prevEmpty = false; - while (tokenizer.HasMoreTokens()) - { - wxString token = tokenizer.GetNextToken(); - - if (prevEmpty && token.empty() && tokenizer.HasMoreTokens()) - { - token = tokenizer.GetNextToken(); - if (!token.empty()) - { - arr.Add (token); - prevEmpty = true; - continue; - } - } - - if (token.empty() && !tokenizer.HasMoreTokens()) - break; - - if (prevEmpty || token.empty()) - { - if (arr.Count() < 1) - { - arr.Add (L""); - continue; - } - arr.Last() += token.empty() ? L',' : token; - } - else - arr.Add (token); - - prevEmpty = token.empty(); - } - - make_shared_auto (KeyfileList, keyfileList); - for (size_t i = 0; i < arr.GetCount(); i++) - { - if (!arr[i].empty()) - keyfileList->push_back (make_shared (wstring (arr[i]))); - } - - return keyfileList; - } - - VolumeInfoList CommandLineInterface::GetMountedVolumes (const wxString &mountedVolumeSpec) const - { - VolumeInfoList volumes = Core->GetMountedVolumes (); - VolumeInfoList filteredVolumes; - - wxFileName pathFilter; - if (!mountedVolumeSpec.empty()) - { - pathFilter = mountedVolumeSpec; - pathFilter.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS); - } - else - return volumes; - - foreach (shared_ptr volume, volumes) - { - if (mountedVolumeSpec.empty()) - { - filteredVolumes.push_back (volume); - } - else if (wxString (volume->Path) == pathFilter.GetFullPath()) - { - filteredVolumes.push_back (volume); - } - else if (wxString (volume->MountPoint) == pathFilter.GetFullPath() - || (wxString (volume->MountPoint) + wxFileName::GetPathSeparator()) == pathFilter.GetFullPath()) - { - filteredVolumes.push_back (volume); - } - } - - if (!mountedVolumeSpec.IsEmpty() && filteredVolumes.size() < 1) - throw_err (_("No such volume is mounted.")); - - return filteredVolumes; - } - - auto_ptr CmdLine; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include +#include +#include "Core/Core.h" +#include "Application.h" +#include "CommandLineInterface.h" +#include "LanguageStrings.h" +#include "UserInterfaceException.h" + +namespace TrueCrypt +{ + CommandLineInterface::CommandLineInterface (wxCmdLineParser &parser, UserInterfaceType::Enum interfaceType) : + ArgCommand (CommandId::None), + ArgFilesystem (VolumeCreationOptions::FilesystemType::Unknown), + ArgNoHiddenVolumeProtection (false), + ArgSize (0), + ArgVolumeType (VolumeType::Unknown), + StartBackgroundTask (false) + { + parser.SetSwitchChars (L"-"); + + parser.AddOption (L"", L"auto-mount", _("Auto mount device-hosted/favorite volumes")); + parser.AddSwitch (L"", L"backup-headers", _("Backup volume headers")); + parser.AddSwitch (L"", L"background-task", _("Start Background Task")); +#ifdef TC_WINDOWS + parser.AddSwitch (L"", L"cache", _("Cache passwords and keyfiles")); +#endif + parser.AddSwitch (L"C", L"change", _("Change password or keyfiles")); + parser.AddSwitch (L"c", L"create", _("Create new volume")); + parser.AddSwitch (L"", L"create-keyfile", _("Create new keyfile")); + parser.AddSwitch (L"", L"delete-token-keyfiles", _("Delete security token keyfiles")); + parser.AddSwitch (L"d", L"dismount", _("Dismount volume")); + parser.AddOption (L"", L"encryption", _("Encryption algorithm")); + parser.AddSwitch (L"", L"explore", _("Open explorer window for mounted volume")); + parser.AddSwitch (L"", L"export-token-keyfile",_("Export keyfile from security token")); + parser.AddOption (L"", L"filesystem", _("Filesystem type")); + parser.AddSwitch (L"f", L"force", _("Force mount/dismount/overwrite")); +#if !defined(TC_WINDOWS) && !defined(TC_MACOSX) + parser.AddOption (L"", L"fs-options", _("Filesystem mount options")); +#endif + parser.AddOption (L"", L"hash", _("Hash algorithm")); + parser.AddSwitch (L"h", L"help", _("Display detailed command line help"), wxCMD_LINE_OPTION_HELP); + parser.AddSwitch (L"", L"import-token-keyfiles", _("Import keyfiles to security token")); + parser.AddOption (L"k", L"keyfiles", _("Keyfiles")); + parser.AddSwitch (L"l", L"list", _("List mounted volumes")); + parser.AddSwitch (L"", L"list-token-keyfiles", _("List security token keyfiles")); + parser.AddSwitch (L"", L"load-preferences", _("Load user preferences")); + parser.AddSwitch (L"", L"mount", _("Mount volume interactively")); + parser.AddOption (L"m", L"mount-options", _("TrueCrypt volume mount options")); + parser.AddOption (L"", L"new-keyfiles", _("New keyfiles")); + parser.AddOption (L"", L"new-password", _("New password")); + parser.AddSwitch (L"", L"non-interactive", _("Do not interact with user")); + parser.AddOption (L"p", L"password", _("Password")); + parser.AddOption (L"", L"protect-hidden", _("Protect hidden volume")); + parser.AddOption (L"", L"protection-keyfiles", _("Keyfiles for protected hidden volume")); + parser.AddOption (L"", L"protection-password", _("Password for protected hidden volume")); + parser.AddOption (L"", L"random-source", _("Use file as source of random data")); + parser.AddSwitch (L"", L"restore-headers", _("Restore volume headers")); + parser.AddSwitch (L"", L"quick", _("Enable quick format")); + parser.AddOption (L"", L"size", _("Size in bytes")); + parser.AddOption (L"", L"slot", _("Volume slot number")); + parser.AddSwitch (L"", L"test", _("Test internal algorithms")); + parser.AddSwitch (L"t", L"text", _("Use text user interface")); + parser.AddOption (L"", L"token-lib", _("Security token library")); + parser.AddSwitch (L"v", L"verbose", _("Enable verbose output")); + parser.AddSwitch (L"", L"version", _("Display version information")); + parser.AddSwitch (L"", L"volume-properties", _("Display volume properties")); + parser.AddOption (L"", L"volume-type", _("Volume type")); + parser.AddParam ( _("Volume path"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); + parser.AddParam ( _("Mount point"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL); + + wxString str; + bool param1IsVolume = false; + bool param1IsMountedVolumeSpec = false; + bool param1IsMountPoint = false; + bool param1IsFile = false; + + if (parser.Parse () > 0) + throw_err (_("Incorrect command line specified.")); + + if (parser.Found (L"help")) + { + ArgCommand = CommandId::Help; + return; + } + + if (parser.Found (L"text") && interfaceType != UserInterfaceType::Text) + { + wstring msg = wstring (_("Option -t or --text must be specified as the first argument.")); + wcerr << msg << endl; + throw_err (msg); + } + + if (parser.Found (L"version")) + { + ArgCommand = CommandId::DisplayVersion; + return; + } + + // Preferences + if (parser.Found (L"load-preferences")) + { + // Load preferences first to allow command line options to override them + Preferences.Load(); + ArgMountOptions = Preferences.DefaultMountOptions; + } + + // Commands + if (parser.Found (L"auto-mount", &str)) + { + CheckCommandSingle(); + + wxStringTokenizer tokenizer (str, L","); + while (tokenizer.HasMoreTokens()) + { + wxString token = tokenizer.GetNextToken(); + + if (token == L"devices") + { + if (ArgCommand == CommandId::AutoMountFavorites) + ArgCommand = CommandId::AutoMountDevicesFavorites; + else + ArgCommand = CommandId::AutoMountDevices; + + param1IsMountPoint = true; + } + else if (token == L"favorites") + { + if (ArgCommand == CommandId::AutoMountDevices) + ArgCommand = CommandId::AutoMountDevicesFavorites; + else + ArgCommand = CommandId::AutoMountFavorites; + } + else + { + throw_err (LangString["UNKNOWN_OPTION"] + L": " + token); + } + } + } + + if (parser.Found (L"backup-headers")) + { + CheckCommandSingle(); + ArgCommand = CommandId::BackupHeaders; + param1IsVolume = true; + } + + if (parser.Found (L"change")) + { + CheckCommandSingle(); + ArgCommand = CommandId::ChangePassword; + param1IsVolume = true; + } + + if (parser.Found (L"create")) + { + CheckCommandSingle(); + ArgCommand = CommandId::CreateVolume; + param1IsVolume = true; + } + + if (parser.Found (L"create-keyfile")) + { + CheckCommandSingle(); + ArgCommand = CommandId::CreateKeyfile; + param1IsFile = true; + } + + if (parser.Found (L"delete-token-keyfiles")) + { + CheckCommandSingle(); + ArgCommand = CommandId::DeleteSecurityTokenKeyfiles; + } + + if (parser.Found (L"dismount")) + { + CheckCommandSingle(); + ArgCommand = CommandId::DismountVolumes; + param1IsMountedVolumeSpec = true; + } + + if (parser.Found (L"export-token-keyfile")) + { + CheckCommandSingle(); + ArgCommand = CommandId::ExportSecurityTokenKeyfile; + } + + if (parser.Found (L"import-token-keyfiles")) + { + CheckCommandSingle(); + ArgCommand = CommandId::ImportSecurityTokenKeyfiles; + } + + if (parser.Found (L"list")) + { + CheckCommandSingle(); + ArgCommand = CommandId::ListVolumes; + param1IsMountedVolumeSpec = true; + } + + if (parser.Found (L"list-token-keyfiles")) + { + CheckCommandSingle(); + ArgCommand = CommandId::ListSecurityTokenKeyfiles; + } + + if (parser.Found (L"mount")) + { + CheckCommandSingle(); + ArgCommand = CommandId::MountVolume; + param1IsVolume = true; + } + + if (parser.Found (L"test")) + { + CheckCommandSingle(); + ArgCommand = CommandId::Test; + } + + if (parser.Found (L"volume-properties")) + { + CheckCommandSingle(); + ArgCommand = CommandId::DisplayVolumeProperties; + param1IsMountedVolumeSpec = true; + } + + // Options + if (parser.Found (L"background-task")) + StartBackgroundTask = true; + +#ifdef TC_WINDOWS + if (parser.Found (L"cache")) + ArgMountOptions.CachePassword = true; +#endif + + if (parser.Found (L"encryption", &str)) + { + ArgEncryptionAlgorithm.reset(); + + foreach (shared_ptr ea, EncryptionAlgorithm::GetAvailableAlgorithms()) + { + if (wxString (ea->GetName()).IsSameAs (str, false)) + ArgEncryptionAlgorithm = ea; + } + + if (!ArgEncryptionAlgorithm) + throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); + } + + if (parser.Found (L"explore")) + Preferences.OpenExplorerWindowAfterMount = true; + + if (parser.Found (L"filesystem", &str)) + { + if (str.IsSameAs (L"none", false)) + { + ArgMountOptions.NoFilesystem = true; + ArgFilesystem = VolumeCreationOptions::FilesystemType::None; + } + else + { + ArgMountOptions.FilesystemType = wstring (str); + + if (str.IsSameAs (L"FAT", false)) + ArgFilesystem = VolumeCreationOptions::FilesystemType::FAT; + } + } + + ArgForce = parser.Found (L"force"); + +#if !defined(TC_WINDOWS) && !defined(TC_MACOSX) + if (parser.Found (L"fs-options", &str)) + ArgMountOptions.FilesystemOptions = str; +#endif + + if (parser.Found (L"hash", &str)) + { + ArgHash.reset(); + + foreach (shared_ptr hash, Hash::GetAvailableAlgorithms()) + { + if (wxString (hash->GetName()).IsSameAs (str, false)) + ArgHash = hash; + } + + if (!ArgHash) + throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); + } + + if (parser.Found (L"keyfiles", &str)) + ArgKeyfiles = ToKeyfileList (str); + + if (parser.Found (L"mount-options", &str)) + { + wxStringTokenizer tokenizer (str, L","); + while (tokenizer.HasMoreTokens()) + { + wxString token = tokenizer.GetNextToken(); + + if (token == L"headerbak") + ArgMountOptions.UseBackupHeaders = true; + else if (token == L"nokernelcrypto") + ArgMountOptions.NoKernelCrypto = true; + else if (token == L"readonly" || token == L"ro") + ArgMountOptions.Protection = VolumeProtection::ReadOnly; + else if (token == L"system") + ArgMountOptions.PartitionInSystemEncryptionScope = true; + else if (token == L"timestamp" || token == L"ts") + ArgMountOptions.PreserveTimestamps = false; +#ifdef TC_WINDOWS + else if (token == L"removable" || token == L"rm") + ArgMountOptions.Removable = true; +#endif + else + throw_err (LangString["UNKNOWN_OPTION"] + L": " + token); + } + } + + if (parser.Found (L"new-keyfiles", &str)) + ArgNewKeyfiles = ToKeyfileList (str); + + if (parser.Found (L"new-password", &str)) + ArgNewPassword.reset (new VolumePassword (wstring (str))); + + if (parser.Found (L"non-interactive")) + Preferences.NonInteractive = true; + + if (parser.Found (L"password", &str)) + ArgPassword.reset (new VolumePassword (wstring (str))); + + if (parser.Found (L"protect-hidden", &str)) + { + if (str == L"yes") + { + if (ArgMountOptions.Protection != VolumeProtection::ReadOnly) + ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly; + } + else if (str == L"no") + ArgNoHiddenVolumeProtection = true; + else + throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); + } + + if (parser.Found (L"protection-keyfiles", &str)) + { + ArgMountOptions.ProtectionKeyfiles = ToKeyfileList (str); + ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly; + } + + if (parser.Found (L"protection-password", &str)) + { + ArgMountOptions.ProtectionPassword.reset (new VolumePassword (wstring (str))); + ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly; + } + + ArgQuick = parser.Found (L"quick"); + + if (parser.Found (L"random-source", &str)) + ArgRandomSourcePath = FilesystemPath (str); + + if (parser.Found (L"restore-headers")) + { + CheckCommandSingle(); + ArgCommand = CommandId::RestoreHeaders; + param1IsVolume = true; + } + + if (parser.Found (L"slot", &str)) + { + unsigned long number; + if (!str.ToULong (&number) || number < Core->GetFirstSlotNumber() || number > Core->GetLastSlotNumber()) + throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); + + ArgMountOptions.SlotNumber = number; + + if (param1IsMountedVolumeSpec) + { + shared_ptr volume = Core->GetMountedVolume (number); + if (!volume) + throw_err (_("No such volume is mounted.")); + + ArgVolumes.push_back (volume); + param1IsMountedVolumeSpec = false; + } + } + + if (parser.Found (L"size", &str)) + { + try + { + ArgSize = StringConverter::ToUInt64 (wstring (str)); + } + catch (...) + { + throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); + } + } + + if (parser.Found (L"token-lib", &str)) + Preferences.SecurityTokenModule = wstring (str); + + if (parser.Found (L"verbose")) + Preferences.Verbose = true; + + if (parser.Found (L"volume-type", &str)) + { + if (str.IsSameAs (L"normal", false)) + ArgVolumeType = VolumeType::Normal; + else if (str.IsSameAs (L"hidden", false)) + ArgVolumeType = VolumeType::Hidden; + else + throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); + } + + // Parameters + if (parser.GetParamCount() > 0) + { + if (ArgCommand == CommandId::None) + { + ArgCommand = CommandId::MountVolume; + param1IsVolume = true; + } + + if (param1IsVolume) + { + wxFileName volPath (parser.GetParam (0)); + +#ifdef TC_WINDOWS + if (!parser.GetParam (0).StartsWith (L"\\Device\\")) +#endif + volPath.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS); + + ArgVolumePath.reset (new VolumePath (wstring (volPath.GetFullPath()))); + } + + if (param1IsMountPoint || parser.GetParamCount() >= 2) + { + wstring s (parser.GetParam (param1IsMountPoint ? 0 : 1)); + + if (s.empty()) + ArgMountOptions.NoFilesystem = true; + + wxFileName mountPoint (wstring (Directory::AppendSeparator (s))); + mountPoint.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS); + ArgMountPoint.reset (new DirectoryPath (wstring (mountPoint.GetPath()))); + } + + if (param1IsFile) + { + ArgFilePath.reset (new FilePath (parser.GetParam (0))); + } + } + + if (param1IsMountedVolumeSpec) + ArgVolumes = GetMountedVolumes (parser.GetParamCount() > 0 ? parser.GetParam (0) : wxString()); + + if (ArgCommand == CommandId::None && Application::GetUserInterfaceType() == UserInterfaceType::Text) + parser.Usage(); + } + + CommandLineInterface::~CommandLineInterface () + { + } + + void CommandLineInterface::CheckCommandSingle () const + { + if (ArgCommand != CommandId::None) + throw_err (_("Only a single command can be specified at a time.")); + } + + shared_ptr CommandLineInterface::ToKeyfileList (const wxString &arg) const + { + wxStringTokenizer tokenizer (arg, L",", wxTOKEN_RET_EMPTY_ALL); + + // Handle escaped separator + wxArrayString arr; + bool prevEmpty = false; + while (tokenizer.HasMoreTokens()) + { + wxString token = tokenizer.GetNextToken(); + + if (prevEmpty && token.empty() && tokenizer.HasMoreTokens()) + { + token = tokenizer.GetNextToken(); + if (!token.empty()) + { + arr.Add (token); + prevEmpty = true; + continue; + } + } + + if (token.empty() && !tokenizer.HasMoreTokens()) + break; + + if (prevEmpty || token.empty()) + { + if (arr.Count() < 1) + { + arr.Add (L""); + continue; + } + arr.Last() += token.empty() ? L',' : token; + } + else + arr.Add (token); + + prevEmpty = token.empty(); + } + + make_shared_auto (KeyfileList, keyfileList); + for (size_t i = 0; i < arr.GetCount(); i++) + { + if (!arr[i].empty()) + keyfileList->push_back (make_shared (wstring (arr[i]))); + } + + return keyfileList; + } + + VolumeInfoList CommandLineInterface::GetMountedVolumes (const wxString &mountedVolumeSpec) const + { + VolumeInfoList volumes = Core->GetMountedVolumes (); + VolumeInfoList filteredVolumes; + + wxFileName pathFilter; + if (!mountedVolumeSpec.empty()) + { + pathFilter = mountedVolumeSpec; + pathFilter.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS); + } + else + return volumes; + + foreach (shared_ptr volume, volumes) + { + if (mountedVolumeSpec.empty()) + { + filteredVolumes.push_back (volume); + } + else if (wxString (volume->Path) == pathFilter.GetFullPath()) + { + filteredVolumes.push_back (volume); + } + else if (wxString (volume->MountPoint) == pathFilter.GetFullPath() + || (wxString (volume->MountPoint) + wxFileName::GetPathSeparator()) == pathFilter.GetFullPath()) + { + filteredVolumes.push_back (volume); + } + } + + if (!mountedVolumeSpec.IsEmpty() && filteredVolumes.size() < 1) + throw_err (_("No such volume is mounted.")); + + return filteredVolumes; + } + + auto_ptr CmdLine; +} diff --git a/Main/CommandLineInterface.h b/Main/CommandLineInterface.h index 3e73570..dc76fee 100644 --- a/Main/CommandLineInterface.h +++ b/Main/CommandLineInterface.h @@ -1,91 +1,92 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_CommandInterface -#define TC_HEADER_Main_CommandInterface - -#include "System.h" -#include "Main.h" -#include "Volume/VolumeInfo.h" -#include "Core/MountOptions.h" -#include "Core/VolumeCreator.h" -#include "UserPreferences.h" -#include "UserInterfaceType.h" - -namespace TrueCrypt -{ - struct CommandId - { - enum Enum - { - None, - AutoMountDevices, - AutoMountDevicesFavorites, - AutoMountFavorites, - BackupHeaders, - ChangePassword, - CreateKeyfile, - CreateVolume, - DeleteSecurityTokenKeyfiles, - DismountVolumes, - DisplayVersion, - DisplayVolumeProperties, - Help, - ImportSecurityTokenKeyfiles, - ListSecurityTokenKeyfiles, - ListVolumes, - MountVolume, - RestoreHeaders, - Test - }; - }; - - struct CommandLineInterface - { - public: - CommandLineInterface (wxCmdLineParser &parser, UserInterfaceType::Enum interfaceType); - virtual ~CommandLineInterface (); - - - CommandId::Enum ArgCommand; - shared_ptr ArgEncryptionAlgorithm; - shared_ptr ArgFilePath; - VolumeCreationOptions::FilesystemType::Enum ArgFilesystem; - bool ArgForce; - shared_ptr ArgHash; - shared_ptr ArgKeyfiles; - MountOptions ArgMountOptions; - shared_ptr ArgMountPoint; - shared_ptr ArgNewKeyfiles; - shared_ptr ArgNewPassword; - bool ArgNoHiddenVolumeProtection; - shared_ptr ArgPassword; - bool ArgQuick; - FilesystemPath ArgRandomSourcePath; - uint64 ArgSize; - shared_ptr ArgVolumePath; - VolumeInfoList ArgVolumes; - VolumeType::Enum ArgVolumeType; - - bool StartBackgroundTask; - UserPreferences Preferences; - - protected: - void CheckCommandSingle () const; - shared_ptr ToKeyfileList (const wxString &arg) const; - VolumeInfoList GetMountedVolumes (const wxString &filter) const; - - private: - CommandLineInterface (const CommandLineInterface &); - CommandLineInterface &operator= (const CommandLineInterface &); - }; - - extern auto_ptr CmdLine; -} - -#endif // TC_HEADER_Main_CommandInterface +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_CommandInterface +#define TC_HEADER_Main_CommandInterface + +#include "System.h" +#include "Main.h" +#include "Volume/VolumeInfo.h" +#include "Core/MountOptions.h" +#include "Core/VolumeCreator.h" +#include "UserPreferences.h" +#include "UserInterfaceType.h" + +namespace TrueCrypt +{ + struct CommandId + { + enum Enum + { + None, + AutoMountDevices, + AutoMountDevicesFavorites, + AutoMountFavorites, + BackupHeaders, + ChangePassword, + CreateKeyfile, + CreateVolume, + DeleteSecurityTokenKeyfiles, + DismountVolumes, + DisplayVersion, + DisplayVolumeProperties, + ExportSecurityTokenKeyfile, + Help, + ImportSecurityTokenKeyfiles, + ListSecurityTokenKeyfiles, + ListVolumes, + MountVolume, + RestoreHeaders, + Test + }; + }; + + struct CommandLineInterface + { + public: + CommandLineInterface (wxCmdLineParser &parser, UserInterfaceType::Enum interfaceType); + virtual ~CommandLineInterface (); + + + CommandId::Enum ArgCommand; + shared_ptr ArgEncryptionAlgorithm; + shared_ptr ArgFilePath; + VolumeCreationOptions::FilesystemType::Enum ArgFilesystem; + bool ArgForce; + shared_ptr ArgHash; + shared_ptr ArgKeyfiles; + MountOptions ArgMountOptions; + shared_ptr ArgMountPoint; + shared_ptr ArgNewKeyfiles; + shared_ptr ArgNewPassword; + bool ArgNoHiddenVolumeProtection; + shared_ptr ArgPassword; + bool ArgQuick; + FilesystemPath ArgRandomSourcePath; + uint64 ArgSize; + shared_ptr ArgVolumePath; + VolumeInfoList ArgVolumes; + VolumeType::Enum ArgVolumeType; + + bool StartBackgroundTask; + UserPreferences Preferences; + + protected: + void CheckCommandSingle () const; + shared_ptr ToKeyfileList (const wxString &arg) const; + VolumeInfoList GetMountedVolumes (const wxString &filter) const; + + private: + CommandLineInterface (const CommandLineInterface &); + CommandLineInterface &operator= (const CommandLineInterface &); + }; + + extern auto_ptr CmdLine; +} + +#endif // TC_HEADER_Main_CommandInterface diff --git a/Main/FatalErrorHandler.cpp b/Main/FatalErrorHandler.cpp index a23736f..b4f06e2 100644 --- a/Main/FatalErrorHandler.cpp +++ b/Main/FatalErrorHandler.cpp @@ -1,274 +1,274 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include - -#include "Main.h" -#include "Application.h" -#include "UserInterface.h" -#include "GraphicUserInterface.h" -#include "Volume/Crc32.h" - -#ifdef TC_UNIX -#include -#endif - -#ifdef TC_MACOSX -# ifdef __ppc__ -# include -# else -# include -# endif -#elif defined (TC_BSD) -# include -#endif - -#include "FatalErrorHandler.h" - -namespace TrueCrypt -{ - static terminate_handler DefaultTerminateHandler; - - struct FatalErrorReport - { - bool UnhandledException; - }; - -#ifdef TC_UNIX - static void OnFatalProgramErrorSignal (int, siginfo_t *signalInfo, void *contextArg) - { - TC_UNUSED_VAR ucontext_t *context = (ucontext_t *) contextArg; - uint64 faultingInstructionAddress = 0; - -#ifdef TC_LINUX -# ifdef REG_EIP - faultingInstructionAddress = context->uc_mcontext.gregs[REG_EIP]; -# elif defined (REG_RIP) - faultingInstructionAddress = context->uc_mcontext.gregs[REG_RIP]; -# endif - -#elif defined (TC_MACOSX) -# ifdef __ppc__ - faultingInstructionAddress = context->uc_mcontext->ss.srr0; -# elif defined (__x86_64__) - faultingInstructionAddress = context->uc_mcontext->ss.rip; -# else - faultingInstructionAddress = context->uc_mcontext->ss.eip; -# endif - -#endif - wstringstream vars; - - vars << L"cpus=" << wxThread::GetCPUCount(); - vars << L"&cksum=" << hex << FatalErrorHandler::GetAppChecksum() << dec; - vars << L"&err=" << signalInfo->si_signo; - vars << L"&addr=" << hex << faultingInstructionAddress << dec; - vars << FatalErrorHandler::GetCallStack (16); - - wxString url = Gui->GetHomepageLinkURL (L"err-report", true, vars.str()); - url.Replace (L"=0x", L"="); - url.Replace (L"=0X0x", L"=0x"); - url.Replace (L"=0X", L"=0x"); - - wxString msg = L"A critical error has occurred and TrueCrypt must be terminated. If this is caused by a bug in TrueCrypt, we would like to fix it. To help us, you can send us an automatically generated error report containing the following items:\n\n- Program version\n- Operating system version\n- Hardware architecture\n- Checksum of TrueCrypt executable\n- Error category\n- Error address\n"; -#if wxUSE_STACKWALKER == 1 - msg += L"- TrueCrypt call stack\n"; -#endif - msg += L"\nIf you select 'Yes', the following URL (which contains the entire error report) will be opened in your default Internet browser.\n\n"; - -#ifdef __WXGTK__ - wxString fUrl = url; - fUrl.Replace (L"&st", L" &st"); - msg += fUrl; -#else - msg += url; -#endif - - msg += L"\n\nDo you want to send us the error report?"; - - if (Gui->AskYesNo (msg, true)) - wxLaunchDefaultBrowser (url, wxBROWSER_NEW_WINDOW); - - _exit (1); - } -#endif // TC_UNIX - - void FatalErrorHandler::Deregister() - { -#ifdef TC_UNIX - signal (SIGILL, SIG_DFL); - signal (SIGFPE, SIG_DFL); - signal (SIGSEGV, SIG_DFL); - signal (SIGBUS, SIG_DFL); - signal (SIGSYS, SIG_DFL); -#endif - -#ifndef TC_WINDOWS - std::set_terminate (DefaultTerminateHandler); -#endif - } - - uint32 FatalErrorHandler::GetAppChecksum () - { - uint32 checkSum = 0; - try - { - File executable; - executable.Open (Application::GetExecutablePath()); - - Buffer executableData (executable.Length()); - executable.ReadCompleteBuffer (executableData); - checkSum = Crc32::ProcessBuffer (executableData); - } - catch (...) { } - - return checkSum; - } - - wstring FatalErrorHandler::GetCallStack (int depth) - { -#if wxUSE_STACKWALKER == 1 - - class StackWalker : public wxStackWalker - { - public: - StackWalker () : FrameCount (0) { } - - void OnStackFrame (const wxStackFrame &frame) - { - if (FrameCount >= 32) - return; - - StackVars << L"&st" << FrameCount++ << L"="; - - wxString functionName = frame.GetName(); - if (!functionName.empty() && !frame.GetModule().empty()) - { - int p = functionName.Find (L"("); - if (p != wxNOT_FOUND) - functionName = functionName.Mid (0, p); - - for (size_t i = 0; i < functionName.size(); ++i) - { - if (!isalnum (functionName[i])) - functionName[i] = L'_'; - } - - while (functionName.Replace (L"__", L"_")); - - StackVars << wstring (functionName); - } - else - StackVars << "0X" << hex << frame.GetAddress() << dec; - } - - int FrameCount; - wstringstream StackVars; - }; - - StackWalker stackWalker; - stackWalker.Walk (2); - - return stackWalker.StackVars.str(); - -#else // wxUSE_STACKWALKER - - return wstring(); - -#endif // wxUSE_STACKWALKER - } - - void FatalErrorHandler::OnTerminate () - { - try - { - throw; - } - catch (UserAbort&) - { - } - catch (Exception &e) - { - wxString vars; - - wxString exName = StringConverter::ToWide (StringConverter::GetTypeName (typeid (e))); - if (exName.find (L"TrueCrypt::") != string::npos) - exName = exName.Mid (11); - - wxString exPos = StringConverter::ToWide (e.what()); - if (exPos.find (L"TrueCrypt::") != string::npos) - exPos = exPos.Mid (11); - - vars << L"cpus=" << wxThread::GetCPUCount(); - vars << wxString::Format (L"&cksum=%x", GetAppChecksum()); - vars << L"&exception=" << exName; - vars << L"&exlocation=" << exPos; - vars << FatalErrorHandler::GetCallStack (16); - - vars.Replace (L"::", L"."); - vars.Replace (L":", L"."); - - wxString url = Gui->GetHomepageLinkURL (L"err-report", true, vars); - url.Replace (L"=0x", L"="); - url.Replace (L"=0X0x", L"=0x"); - url.Replace (L"=0X", L"=0x"); - - wxString msg = L"An unhandled exception has occurred and TrueCrypt must be terminated. If this is caused by a bug in TrueCrypt, we would like to fix it. To help us, you can send us an automatically generated error report containing the following items:\n\n- Program version\n- Operating system version\n- Hardware architecture\n- Checksum of TrueCrypt executable\n- Error description\n- Error location\n"; -#if wxUSE_STACKWALKER == 1 - msg += L"- TrueCrypt call stack\n"; -#endif - msg += L"\nIf you select 'Yes', the following URL (which contains the entire error report) will be opened in your default Internet browser.\n\n"; - -#ifdef __WXGTK__ - wxString fUrl = url; - fUrl.Replace (L"&st", L" &st"); - msg += fUrl; -#else - msg += url; -#endif - - msg += L"\n\nDo you want to send us the error report?"; - - if (Gui->AskYesNo (msg, true)) - wxLaunchDefaultBrowser (url, wxBROWSER_NEW_WINDOW); - - } - catch (exception &e) - { - Gui->ShowError (e); - } - catch (...) - { - Gui->ShowError (_("Unknown exception occurred.")); - } - - _exit (1); - } - - void FatalErrorHandler::Register () - { -#ifndef TC_WINDOWS - // OnUnhandledException() seems to be called only on Windows - DefaultTerminateHandler = std::set_terminate (OnTerminate); -#endif - -#ifdef TC_UNIX - struct sigaction action; - Memory::Zero (&action, sizeof (action)); - action.sa_flags = SA_SIGINFO; - action.sa_sigaction = OnFatalProgramErrorSignal; - - throw_sys_if (sigaction (SIGILL, &action, nullptr) == -1); - throw_sys_if (sigaction (SIGFPE, &action, nullptr) == -1); - throw_sys_if (sigaction (SIGSEGV, &action, nullptr) == -1); - throw_sys_if (sigaction (SIGBUS, &action, nullptr) == -1); - throw_sys_if (sigaction (SIGSYS, &action, nullptr) == -1); -#endif - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include + +#include "Main.h" +#include "Application.h" +#include "UserInterface.h" +#include "GraphicUserInterface.h" +#include "Volume/Crc32.h" + +#ifdef TC_UNIX +#include +#endif + +#ifdef TC_MACOSX +# ifdef __ppc__ +# include +# else +# include +# endif +#elif defined (TC_BSD) +# include +#endif + +#include "FatalErrorHandler.h" + +namespace TrueCrypt +{ + static terminate_handler DefaultTerminateHandler; + + struct FatalErrorReport + { + bool UnhandledException; + }; + +#ifdef TC_UNIX + static void OnFatalProgramErrorSignal (int, siginfo_t *signalInfo, void *contextArg) + { + TC_UNUSED_VAR ucontext_t *context = (ucontext_t *) contextArg; + uint64 faultingInstructionAddress = 0; + +#ifdef TC_LINUX +# ifdef REG_EIP + faultingInstructionAddress = context->uc_mcontext.gregs[REG_EIP]; +# elif defined (REG_RIP) + faultingInstructionAddress = context->uc_mcontext.gregs[REG_RIP]; +# endif + +#elif defined (TC_MACOSX) +# ifdef __ppc__ + faultingInstructionAddress = context->uc_mcontext->ss.srr0; +# elif defined (__x86_64__) + faultingInstructionAddress = context->uc_mcontext->ss.rip; +# else + faultingInstructionAddress = context->uc_mcontext->ss.eip; +# endif + +#endif + wstringstream vars; + + vars << L"cpus=" << wxThread::GetCPUCount(); + vars << L"&cksum=" << hex << FatalErrorHandler::GetAppChecksum() << dec; + vars << L"&err=" << signalInfo->si_signo; + vars << L"&addr=" << hex << faultingInstructionAddress << dec; + vars << FatalErrorHandler::GetCallStack (16); + + wxString url = Gui->GetHomepageLinkURL (L"err-report", true, vars.str()); + url.Replace (L"=0x", L"="); + url.Replace (L"=0X0x", L"=0x"); + url.Replace (L"=0X", L"=0x"); + + wxString msg = L"A critical error has occurred and TrueCrypt must be terminated. If this is caused by a bug in TrueCrypt, we would like to fix it. To help us, you can send us an automatically generated error report containing the following items:\n\n- Program version\n- Operating system version\n- Hardware architecture\n- Checksum of TrueCrypt executable\n- Error category\n- Error address\n"; +#if wxUSE_STACKWALKER == 1 + msg += L"- TrueCrypt call stack\n"; +#endif + msg += L"\nIf you select 'Yes', the following URL (which contains the entire error report) will be opened in your default Internet browser.\n\n"; + +#ifdef __WXGTK__ + wxString fUrl = url; + fUrl.Replace (L"&st", L" &st"); + msg += fUrl; +#else + msg += url; +#endif + + msg += L"\n\nDo you want to send us the error report?"; + + if (Gui->AskYesNo (msg, true)) + wxLaunchDefaultBrowser (url, wxBROWSER_NEW_WINDOW); + + _exit (1); + } +#endif // TC_UNIX + + void FatalErrorHandler::Deregister() + { +#ifdef TC_UNIX + signal (SIGILL, SIG_DFL); + signal (SIGFPE, SIG_DFL); + signal (SIGSEGV, SIG_DFL); + signal (SIGBUS, SIG_DFL); + signal (SIGSYS, SIG_DFL); +#endif + +#ifndef TC_WINDOWS + std::set_terminate (DefaultTerminateHandler); +#endif + } + + uint32 FatalErrorHandler::GetAppChecksum () + { + uint32 checkSum = 0; + try + { + File executable; + executable.Open (Application::GetExecutablePath()); + + Buffer executableData (executable.Length()); + executable.ReadCompleteBuffer (executableData); + checkSum = Crc32::ProcessBuffer (executableData); + } + catch (...) { } + + return checkSum; + } + + wstring FatalErrorHandler::GetCallStack (int depth) + { +#if wxUSE_STACKWALKER == 1 + + class StackWalker : public wxStackWalker + { + public: + StackWalker () : FrameCount (0) { } + + void OnStackFrame (const wxStackFrame &frame) + { + if (FrameCount >= 32) + return; + + StackVars << L"&st" << FrameCount++ << L"="; + + wxString functionName = frame.GetName(); + if (!functionName.empty() && !frame.GetModule().empty()) + { + int p = functionName.Find (L"("); + if (p != wxNOT_FOUND) + functionName = functionName.Mid (0, p); + + for (size_t i = 0; i < functionName.size(); ++i) + { + if (!isalnum (functionName[i])) + functionName[i] = L'_'; + } + + while (functionName.Replace (L"__", L"_")); + + StackVars << wstring (functionName); + } + else + StackVars << "0X" << hex << frame.GetAddress() << dec; + } + + int FrameCount; + wstringstream StackVars; + }; + + StackWalker stackWalker; + stackWalker.Walk (2); + + return stackWalker.StackVars.str(); + +#else // wxUSE_STACKWALKER + + return wstring(); + +#endif // wxUSE_STACKWALKER + } + + void FatalErrorHandler::OnTerminate () + { + try + { + throw; + } + catch (UserAbort&) + { + } + catch (Exception &e) + { + wxString vars; + + wxString exName = StringConverter::ToWide (StringConverter::GetTypeName (typeid (e))); + if (exName.find (L"TrueCrypt::") != string::npos) + exName = exName.Mid (11); + + wxString exPos = StringConverter::ToWide (e.what()); + if (exPos.find (L"TrueCrypt::") != string::npos) + exPos = exPos.Mid (11); + + vars << L"cpus=" << wxThread::GetCPUCount(); + vars << wxString::Format (L"&cksum=%x", GetAppChecksum()); + vars << L"&exception=" << exName; + vars << L"&exlocation=" << exPos; + vars << FatalErrorHandler::GetCallStack (16); + + vars.Replace (L"::", L"."); + vars.Replace (L":", L"."); + + wxString url = Gui->GetHomepageLinkURL (L"err-report", true, vars); + url.Replace (L"=0x", L"="); + url.Replace (L"=0X0x", L"=0x"); + url.Replace (L"=0X", L"=0x"); + + wxString msg = L"An unhandled exception has occurred and TrueCrypt must be terminated. If this is caused by a bug in TrueCrypt, we would like to fix it. To help us, you can send us an automatically generated error report containing the following items:\n\n- Program version\n- Operating system version\n- Hardware architecture\n- Checksum of TrueCrypt executable\n- Error description\n- Error location\n"; +#if wxUSE_STACKWALKER == 1 + msg += L"- TrueCrypt call stack\n"; +#endif + msg += L"\nIf you select 'Yes', the following URL (which contains the entire error report) will be opened in your default Internet browser.\n\n"; + +#ifdef __WXGTK__ + wxString fUrl = url; + fUrl.Replace (L"&st", L" &st"); + msg += fUrl; +#else + msg += url; +#endif + + msg += L"\n\nDo you want to send us the error report?"; + + if (Gui->AskYesNo (msg, true)) + wxLaunchDefaultBrowser (url, wxBROWSER_NEW_WINDOW); + + } + catch (exception &e) + { + Gui->ShowError (e); + } + catch (...) + { + Gui->ShowError (_("Unknown exception occurred.")); + } + + _exit (1); + } + + void FatalErrorHandler::Register () + { +#ifndef TC_WINDOWS + // OnUnhandledException() seems to be called only on Windows + DefaultTerminateHandler = std::set_terminate (OnTerminate); +#endif + +#ifdef TC_UNIX + struct sigaction action; + Memory::Zero (&action, sizeof (action)); + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = OnFatalProgramErrorSignal; + + throw_sys_if (sigaction (SIGILL, &action, nullptr) == -1); + throw_sys_if (sigaction (SIGFPE, &action, nullptr) == -1); + throw_sys_if (sigaction (SIGSEGV, &action, nullptr) == -1); + throw_sys_if (sigaction (SIGBUS, &action, nullptr) == -1); + throw_sys_if (sigaction (SIGSYS, &action, nullptr) == -1); +#endif + } +} diff --git a/Main/FatalErrorHandler.h b/Main/FatalErrorHandler.h index a9cfece..1a831ae 100644 --- a/Main/FatalErrorHandler.h +++ b/Main/FatalErrorHandler.h @@ -1,33 +1,33 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_FatalErrorHandler -#define TC_HEADER_Main_FatalErrorHandler - -#include "System.h" - -namespace TrueCrypt -{ - class FatalErrorHandler - { - public: - static void Deregister(); - static uint32 GetAppChecksum (); - static wstring GetCallStack (int depth); - static void Register(); - - protected: - static void OnSignal (int signal); - static void OnTerminate (); - - private: - FatalErrorHandler (); - }; -} - -#endif // TC_HEADER_Main_FatalErrorHandler +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_FatalErrorHandler +#define TC_HEADER_Main_FatalErrorHandler + +#include "System.h" + +namespace TrueCrypt +{ + class FatalErrorHandler + { + public: + static void Deregister(); + static uint32 GetAppChecksum (); + static wstring GetCallStack (int depth); + static void Register(); + + protected: + static void OnSignal (int signal); + static void OnTerminate (); + + private: + FatalErrorHandler (); + }; +} + +#endif // TC_HEADER_Main_FatalErrorHandler diff --git a/Main/FavoriteVolume.cpp b/Main/FavoriteVolume.cpp index 3d5914a..4017832 100644 --- a/Main/FavoriteVolume.cpp +++ b/Main/FavoriteVolume.cpp @@ -1,94 +1,94 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Application.h" -#include "FavoriteVolume.h" -#include "Xml.h" - -namespace TrueCrypt -{ - FavoriteVolumeList FavoriteVolume::LoadList () - { - FavoriteVolumeList favorites; - - FilePath path = Application::GetConfigFilePath (GetFileName()); - - if (path.IsFile()) - { - foreach (XmlNode node, XmlParser (path).GetNodes (L"volume")) - { - VolumeSlotNumber slotNumber = 0; - wstring attr = wstring (node.Attributes[L"slotnumber"]); - if (!attr.empty()) - slotNumber = StringConverter::ToUInt64 (attr); - - bool readOnly = false; - attr = wstring (node.Attributes[L"readonly"]); - if (!attr.empty()) - readOnly = (StringConverter::ToUInt32 (attr) != 0 ? true : false); - - bool system = false; - attr = wstring (node.Attributes[L"system"]); - if (!attr.empty()) - system = (StringConverter::ToUInt32 (attr) != 0 ? true : false); - - favorites.push_back (shared_ptr ( - new FavoriteVolume ((wstring) node.InnerText, wstring (node.Attributes[L"mountpoint"]), slotNumber, readOnly, system))); - } - } - - return favorites; - } - - void FavoriteVolume::SaveList (const FavoriteVolumeList &favorites) - { - FilePath favoritesCfgPath = Application::GetConfigFilePath (GetFileName(), true); - - if (favorites.empty()) - { - if (favoritesCfgPath.IsFile()) - favoritesCfgPath.Delete(); - } - else - { - XmlNode favoritesXml (L"favorites"); - - foreach_ref (const FavoriteVolume &favorite, favorites) - { - XmlNode node (L"volume", wstring (favorite.Path)); - node.Attributes[L"mountpoint"] = wstring (favorite.MountPoint); - node.Attributes[L"slotnumber"] = StringConverter::FromNumber (favorite.SlotNumber); - node.Attributes[L"readonly"] = StringConverter::FromNumber (favorite.ReadOnly ? 1 : 0); - node.Attributes[L"system"] = StringConverter::FromNumber (favorite.System ? 1 : 0); - - favoritesXml.InnerNodes.push_back (node); - } - - XmlWriter favoritesWriter (favoritesCfgPath); - favoritesWriter.WriteNode (favoritesXml); - favoritesWriter.Close(); - } - } - - void FavoriteVolume::ToMountOptions (MountOptions &options) const - { - if (MountPoint.IsEmpty()) - { - options.MountPoint.reset(); - options.NoFilesystem = true; - } - else - options.MountPoint.reset (new DirectoryPath (MountPoint)); - - options.Path.reset (new VolumePath (Path)); - options.PartitionInSystemEncryptionScope = System; - options.Protection = (ReadOnly ? VolumeProtection::ReadOnly : VolumeProtection::None); - options.SlotNumber = SlotNumber; - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Application.h" +#include "FavoriteVolume.h" +#include "Xml.h" + +namespace TrueCrypt +{ + FavoriteVolumeList FavoriteVolume::LoadList () + { + FavoriteVolumeList favorites; + + FilePath path = Application::GetConfigFilePath (GetFileName()); + + if (path.IsFile()) + { + foreach (XmlNode node, XmlParser (path).GetNodes (L"volume")) + { + VolumeSlotNumber slotNumber = 0; + wstring attr = wstring (node.Attributes[L"slotnumber"]); + if (!attr.empty()) + slotNumber = StringConverter::ToUInt64 (attr); + + bool readOnly = false; + attr = wstring (node.Attributes[L"readonly"]); + if (!attr.empty()) + readOnly = (StringConverter::ToUInt32 (attr) != 0 ? true : false); + + bool system = false; + attr = wstring (node.Attributes[L"system"]); + if (!attr.empty()) + system = (StringConverter::ToUInt32 (attr) != 0 ? true : false); + + favorites.push_back (shared_ptr ( + new FavoriteVolume ((wstring) node.InnerText, wstring (node.Attributes[L"mountpoint"]), slotNumber, readOnly, system))); + } + } + + return favorites; + } + + void FavoriteVolume::SaveList (const FavoriteVolumeList &favorites) + { + FilePath favoritesCfgPath = Application::GetConfigFilePath (GetFileName(), true); + + if (favorites.empty()) + { + if (favoritesCfgPath.IsFile()) + favoritesCfgPath.Delete(); + } + else + { + XmlNode favoritesXml (L"favorites"); + + foreach_ref (const FavoriteVolume &favorite, favorites) + { + XmlNode node (L"volume", wstring (favorite.Path)); + node.Attributes[L"mountpoint"] = wstring (favorite.MountPoint); + node.Attributes[L"slotnumber"] = StringConverter::FromNumber (favorite.SlotNumber); + node.Attributes[L"readonly"] = StringConverter::FromNumber (favorite.ReadOnly ? 1 : 0); + node.Attributes[L"system"] = StringConverter::FromNumber (favorite.System ? 1 : 0); + + favoritesXml.InnerNodes.push_back (node); + } + + XmlWriter favoritesWriter (favoritesCfgPath); + favoritesWriter.WriteNode (favoritesXml); + favoritesWriter.Close(); + } + } + + void FavoriteVolume::ToMountOptions (MountOptions &options) const + { + if (MountPoint.IsEmpty()) + { + options.MountPoint.reset(); + options.NoFilesystem = true; + } + else + options.MountPoint.reset (new DirectoryPath (MountPoint)); + + options.Path.reset (new VolumePath (Path)); + options.PartitionInSystemEncryptionScope = System; + options.Protection = (ReadOnly ? VolumeProtection::ReadOnly : VolumeProtection::None); + options.SlotNumber = SlotNumber; + } +} diff --git a/Main/FavoriteVolume.h b/Main/FavoriteVolume.h index fc36272..4f994fa 100644 --- a/Main/FavoriteVolume.h +++ b/Main/FavoriteVolume.h @@ -1,53 +1,53 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_FavoriteVolume -#define TC_HEADER_Main_FavoriteVolume - -#include "System.h" -#include "Main.h" - -namespace TrueCrypt -{ - struct FavoriteVolume; - typedef list < shared_ptr > FavoriteVolumeList; - - struct FavoriteVolume - { - public: - FavoriteVolume () - : ReadOnly (false), - System (false) - { - } - - FavoriteVolume (const VolumePath &path, const DirectoryPath &mountPoint, VolumeSlotNumber slotNumber, bool readOnly, bool system) - : MountPoint (mountPoint), - Path (path), - ReadOnly (readOnly), - SlotNumber (slotNumber), - System (system) - { - } - - static FavoriteVolumeList LoadList (); - static void SaveList (const FavoriteVolumeList &favorites); - void ToMountOptions (MountOptions &options) const; - - DirectoryPath MountPoint; - VolumePath Path; - bool ReadOnly; - VolumeSlotNumber SlotNumber; - bool System; - - protected: - static wxString GetFileName () { return L"Favorite Volumes.xml"; } - }; -} - -#endif // TC_HEADER_Main_FavoriteVolume +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_FavoriteVolume +#define TC_HEADER_Main_FavoriteVolume + +#include "System.h" +#include "Main.h" + +namespace TrueCrypt +{ + struct FavoriteVolume; + typedef list < shared_ptr > FavoriteVolumeList; + + struct FavoriteVolume + { + public: + FavoriteVolume () + : ReadOnly (false), + System (false) + { + } + + FavoriteVolume (const VolumePath &path, const DirectoryPath &mountPoint, VolumeSlotNumber slotNumber, bool readOnly, bool system) + : MountPoint (mountPoint), + Path (path), + ReadOnly (readOnly), + SlotNumber (slotNumber), + System (system) + { + } + + static FavoriteVolumeList LoadList (); + static void SaveList (const FavoriteVolumeList &favorites); + void ToMountOptions (MountOptions &options) const; + + DirectoryPath MountPoint; + VolumePath Path; + bool ReadOnly; + VolumeSlotNumber SlotNumber; + bool System; + + protected: + static wxString GetFileName () { return L"Favorite Volumes.xml"; } + }; +} + +#endif // TC_HEADER_Main_FavoriteVolume diff --git a/Main/Forms/AboutDialog.cpp b/Main/Forms/AboutDialog.cpp index 0c72c07..32491fc 100644 --- a/Main/Forms/AboutDialog.cpp +++ b/Main/Forms/AboutDialog.cpp @@ -1,62 +1,62 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Volume/Version.h" -#include "Main/Application.h" -#include "Main/GraphicUserInterface.h" -#include "Main/Resources.h" -#include "AboutDialog.h" - -namespace TrueCrypt -{ - AboutDialog::AboutDialog (wxWindow* parent) : AboutDialogBase (parent) - { - LogoBitmap->SetBitmap (Resources::GetTextualLogoBitmap()); - - VersionStaticText->SetLabel (Application::GetName() + L" " + StringConverter::ToWide (Version::String())); - CopyrightStaticText->SetLabel (L"Copyright \xA9 2003-2009 TrueCrypt Foundation"); - WebsiteHyperlink->SetLabel (L"www.truecrypt.org"); - - CreditsTextCtrl->SetMinSize (wxSize ( - Gui->GetCharWidth (CreditsTextCtrl) * 70, - Gui->GetCharHeight (CreditsTextCtrl) * 6 -#ifdef TC_WINDOWS - - 5 -#else - - 11 -#endif - )); - - Layout(); - Fit(); - Center(); - - CreditsTextCtrl->ChangeValue ( - L"Portions of this software are based in part on the works of the following people: " - L"Paul Le Roux, " - L"Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, Niels Ferguson, " - L"Lars Knudsen, Ross Anderson, Eli Biham, " - L"Joan Daemen, Vincent Rijmen, " - L"Phillip Rogaway, " - L"Hans Dobbertin, Antoon Bosselaers, Bart Preneel, " - L"Paulo Barreto, Brian Gladman, Wei Dai, Peter Gutmann, and many others.\n\n" - - L"Portions of this software:\n" - L"Copyright \xA9 2003-2009 TrueCrypt Foundation. All Rights Reserved.\n" - L"Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\n" - L"Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\n" - - L"\nThis software as a whole:\n" - L"Copyright \xA9 2009 TrueCrypt Foundation. All rights reserved.\n\n" - - L"This software uses wxWidgets library, which is copyright \xA9 1998-2009 Julian Smart, Robert Roebling et al.\n\n" - - L"A TrueCrypt Foundation Release"); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Volume/Version.h" +#include "Main/Application.h" +#include "Main/GraphicUserInterface.h" +#include "Main/Resources.h" +#include "AboutDialog.h" + +namespace TrueCrypt +{ + AboutDialog::AboutDialog (wxWindow* parent) : AboutDialogBase (parent) + { + LogoBitmap->SetBitmap (Resources::GetTextualLogoBitmap()); + + VersionStaticText->SetLabel (Application::GetName() + L" " + StringConverter::ToWide (Version::String())); + CopyrightStaticText->SetLabel (StringConverter::ToWide (TC_STR_RELEASED_BY)); + WebsiteHyperlink->SetLabel (L"www.truecrypt.org"); + + CreditsTextCtrl->SetMinSize (wxSize ( + Gui->GetCharWidth (CreditsTextCtrl) * 70, + Gui->GetCharHeight (CreditsTextCtrl) * 6 +#ifdef TC_WINDOWS + - 5 +#else + - 11 +#endif + )); + + Layout(); + Fit(); + Center(); + + CreditsTextCtrl->ChangeValue ( + L"Portions of this software are based in part on the works of the following people: " + L"Paul Le Roux, " + L"Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, Niels Ferguson, " + L"Lars Knudsen, Ross Anderson, Eli Biham, " + L"Joan Daemen, Vincent Rijmen, " + L"Phillip Rogaway, " + L"Hans Dobbertin, Antoon Bosselaers, Bart Preneel, " + L"Paulo Barreto, Brian Gladman, Wei Dai, Peter Gutmann, and many others.\n\n" + + L"Portions of this software:\n" + L"Copyright \xA9 2003-2009 TrueCrypt Foundation. All Rights Reserved.\n" + L"Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\n" + L"Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\n" + + L"\nThis software as a whole:\n" + L"Copyright \xA9 2009 TrueCrypt Foundation. All rights reserved.\n\n" + + L"This software uses wxWidgets library, which is copyright \xA9 1998-2009 Julian Smart, Robert Roebling et al.\n\n" + + L"A TrueCrypt Foundation Release"); + } +} diff --git a/Main/Forms/AboutDialog.h b/Main/Forms/AboutDialog.h index 07ab1b4..c5d8b05 100644 --- a/Main/Forms/AboutDialog.h +++ b/Main/Forms/AboutDialog.h @@ -1,26 +1,26 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_AboutDialog -#define TC_HEADER_Main_Forms_AboutDialog - -#include "Forms.h" - -namespace TrueCrypt -{ - class AboutDialog : public AboutDialogBase - { - public: - AboutDialog (wxWindow* parent); - - void OnDonationsButtonClick (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"donate"); } - void OnWebsiteHyperlinkClick (wxHyperlinkEvent& event) { Gui->OpenHomepageLink (this, L"main"); } - }; -} - -#endif // TC_HEADER_Main_Forms_AboutDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_AboutDialog +#define TC_HEADER_Main_Forms_AboutDialog + +#include "Forms.h" + +namespace TrueCrypt +{ + class AboutDialog : public AboutDialogBase + { + public: + AboutDialog (wxWindow* parent); + + void OnDonationsButtonClick (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"donate"); } + void OnWebsiteHyperlinkClick (wxHyperlinkEvent& event) { Gui->OpenHomepageLink (this, L"main"); } + }; +} + +#endif // TC_HEADER_Main_Forms_AboutDialog diff --git a/Main/Forms/ChangePasswordDialog.cpp b/Main/Forms/ChangePasswordDialog.cpp index 11f0119..95ff089 100644 --- a/Main/Forms/ChangePasswordDialog.cpp +++ b/Main/Forms/ChangePasswordDialog.cpp @@ -1,191 +1,191 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/Main.h" -#include "Main/GraphicUserInterface.h" -#include "ChangePasswordDialog.h" - -namespace TrueCrypt -{ - ChangePasswordDialog::ChangePasswordDialog (wxWindow* parent, shared_ptr volumePath, Mode::Enum mode, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles) - : ChangePasswordDialogBase (parent), DialogMode (mode), Path (volumePath) - { - bool enableNewPassword = false; - bool enableNewKeyfiles = false; - bool enablePkcs5Prf = false; - - switch (mode) - { - case Mode::ChangePasswordAndKeyfiles: - enableNewPassword = true; - enableNewKeyfiles = true; - enablePkcs5Prf = true; - SetTitle (_("Change Volume Password and Keyfiles")); - break; - - case Mode::ChangeKeyfiles: - enableNewKeyfiles = true; - SetTitle (_("Add/Remove Keyfiles to/from Volume")); - break; - - case Mode::RemoveAllKeyfiles: - SetTitle (_("Remove All Keyfiles from Volume")); - break; - - case Mode::ChangePkcs5Prf: - enablePkcs5Prf = true; - SetTitle (_("Change Header Key Derivation Algorithm")); - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - - CurrentPasswordPanel = new VolumePasswordPanel (this, password, keyfiles); - CurrentPasswordPanel->UpdateEvent.Connect (EventConnector (this, &ChangePasswordDialog::OnPasswordPanelUpdate)); - CurrentPasswordPanelSizer->Add (CurrentPasswordPanel, 1, wxALL | wxEXPAND); - - NewPasswordPanel = new VolumePasswordPanel (this, newPassword, newKeyfiles, false, enableNewPassword, enableNewKeyfiles, enableNewPassword, enablePkcs5Prf); - NewPasswordPanel->UpdateEvent.Connect (EventConnector (this, &ChangePasswordDialog::OnPasswordPanelUpdate)); - NewPasswordPanelSizer->Add (NewPasswordPanel, 1, wxALL | wxEXPAND); - - if (mode == Mode::RemoveAllKeyfiles) - NewSizer->Show (false); - - Layout(); - Fit(); - Center(); - - OnPasswordPanelUpdate(); - CurrentPasswordPanel->SetFocusToPasswordTextCtrl(); - } - - ChangePasswordDialog::~ChangePasswordDialog () - { - CurrentPasswordPanel->UpdateEvent.Disconnect (this); - NewPasswordPanel->UpdateEvent.Disconnect (this); - } - - void ChangePasswordDialog::OnOKButtonClick (wxCommandEvent& event) - { - try - { - shared_ptr newPassword; - if (DialogMode == Mode::ChangePasswordAndKeyfiles) - { - newPassword = NewPasswordPanel->GetPassword(); - newPassword->CheckPortability(); - - if (newPassword->Size() > 0 && newPassword->Size() < VolumePassword::WarningSizeThreshold - && !Gui->AskYesNo (LangString ["PASSWORD_LENGTH_WARNING"], false, true)) - { - NewPasswordPanel->SetFocusToPasswordTextCtrl(); - return; - } - } - else - newPassword = CurrentPasswordPanel->GetPassword(); - - shared_ptr newKeyfiles; - if (DialogMode == Mode::ChangePasswordAndKeyfiles || DialogMode == Mode::ChangeKeyfiles) - newKeyfiles = NewPasswordPanel->GetKeyfiles(); - else if (DialogMode != Mode::RemoveAllKeyfiles) - newKeyfiles = CurrentPasswordPanel->GetKeyfiles(); - - Gui->UserEnrichRandomPool (this, NewPasswordPanel->GetPkcs5Kdf() ? NewPasswordPanel->GetPkcs5Kdf()->GetHash() : shared_ptr ()); - - { -#ifdef TC_UNIX - // Temporarily take ownership of a device if the user is not an administrator - UserId origDeviceOwner ((uid_t) -1); - - if (!Core->HasAdminPrivileges() && Path->IsDevice()) - { - origDeviceOwner = FilesystemPath (wstring (*Path)).GetOwner(); - Core->SetFileOwner (*Path, UserId (getuid())); - } - - finally_do_arg2 (FilesystemPath, *Path, UserId, origDeviceOwner, - { - if (finally_arg2.SystemId != (uid_t) -1) - Core->SetFileOwner (finally_arg, finally_arg2); - }); -#endif - wxBusyCursor busy; - Core->ChangePassword (Path, Gui->GetPreferences().DefaultMountOptions.PreserveTimestamps, - CurrentPasswordPanel->GetPassword(), CurrentPasswordPanel->GetKeyfiles(), - newPassword, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf()); - } - - switch (DialogMode) - { - case Mode::ChangePasswordAndKeyfiles: - Gui->ShowInfo ("PASSWORD_CHANGED"); - break; - - case Mode::ChangeKeyfiles: - case Mode::RemoveAllKeyfiles: - Gui->ShowInfo ("KEYFILE_CHANGED"); - break; - - case Mode::ChangePkcs5Prf: - Gui->ShowInfo ("PKCS5_PRF_CHANGED"); - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - - EndModal (wxID_OK); - } - catch (UnportablePassword &e) - { - Gui->ShowError (e); - NewPasswordPanel->SetFocusToPasswordTextCtrl(); - } - catch (PasswordException &e) - { - Gui->ShowWarning (e); - CurrentPasswordPanel->SetFocusToPasswordTextCtrl(); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void ChangePasswordDialog::OnPasswordPanelUpdate () - { - bool ok = true; - - bool passwordEmpty = CurrentPasswordPanel->GetPassword()->IsEmpty(); - bool keyfilesEmpty = !CurrentPasswordPanel->GetKeyfiles() || CurrentPasswordPanel->GetKeyfiles()->empty(); - - if (passwordEmpty && keyfilesEmpty) - ok = false; - - if (DialogMode == Mode::RemoveAllKeyfiles && (passwordEmpty || keyfilesEmpty)) - ok = false; - - if (DialogMode == Mode::ChangePasswordAndKeyfiles || DialogMode == Mode::ChangeKeyfiles) - { - bool newKeyfilesEmpty = !NewPasswordPanel->GetKeyfiles() || NewPasswordPanel->GetKeyfiles()->empty(); - - if (DialogMode == Mode::ChangeKeyfiles - && ((passwordEmpty && newKeyfilesEmpty) || (keyfilesEmpty && newKeyfilesEmpty))) - ok = false; - - if (DialogMode == Mode::ChangePasswordAndKeyfiles - && ((NewPasswordPanel->GetPassword()->IsEmpty() && newKeyfilesEmpty) || !NewPasswordPanel->PasswordsMatch())) - ok = false; - } - - OKButton->Enable (ok); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/Main.h" +#include "Main/GraphicUserInterface.h" +#include "ChangePasswordDialog.h" + +namespace TrueCrypt +{ + ChangePasswordDialog::ChangePasswordDialog (wxWindow* parent, shared_ptr volumePath, Mode::Enum mode, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles) + : ChangePasswordDialogBase (parent), DialogMode (mode), Path (volumePath) + { + bool enableNewPassword = false; + bool enableNewKeyfiles = false; + bool enablePkcs5Prf = false; + + switch (mode) + { + case Mode::ChangePasswordAndKeyfiles: + enableNewPassword = true; + enableNewKeyfiles = true; + enablePkcs5Prf = true; + SetTitle (_("Change Volume Password and Keyfiles")); + break; + + case Mode::ChangeKeyfiles: + enableNewKeyfiles = true; + SetTitle (_("Add/Remove Keyfiles to/from Volume")); + break; + + case Mode::RemoveAllKeyfiles: + SetTitle (_("Remove All Keyfiles from Volume")); + break; + + case Mode::ChangePkcs5Prf: + enablePkcs5Prf = true; + SetTitle (_("Change Header Key Derivation Algorithm")); + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + + CurrentPasswordPanel = new VolumePasswordPanel (this, password, keyfiles); + CurrentPasswordPanel->UpdateEvent.Connect (EventConnector (this, &ChangePasswordDialog::OnPasswordPanelUpdate)); + CurrentPasswordPanelSizer->Add (CurrentPasswordPanel, 1, wxALL | wxEXPAND); + + NewPasswordPanel = new VolumePasswordPanel (this, newPassword, newKeyfiles, false, enableNewPassword, enableNewKeyfiles, enableNewPassword, enablePkcs5Prf); + NewPasswordPanel->UpdateEvent.Connect (EventConnector (this, &ChangePasswordDialog::OnPasswordPanelUpdate)); + NewPasswordPanelSizer->Add (NewPasswordPanel, 1, wxALL | wxEXPAND); + + if (mode == Mode::RemoveAllKeyfiles) + NewSizer->Show (false); + + Layout(); + Fit(); + Center(); + + OnPasswordPanelUpdate(); + CurrentPasswordPanel->SetFocusToPasswordTextCtrl(); + } + + ChangePasswordDialog::~ChangePasswordDialog () + { + CurrentPasswordPanel->UpdateEvent.Disconnect (this); + NewPasswordPanel->UpdateEvent.Disconnect (this); + } + + void ChangePasswordDialog::OnOKButtonClick (wxCommandEvent& event) + { + try + { + shared_ptr newPassword; + if (DialogMode == Mode::ChangePasswordAndKeyfiles) + { + newPassword = NewPasswordPanel->GetPassword(); + newPassword->CheckPortability(); + + if (newPassword->Size() > 0 && newPassword->Size() < VolumePassword::WarningSizeThreshold + && !Gui->AskYesNo (LangString ["PASSWORD_LENGTH_WARNING"], false, true)) + { + NewPasswordPanel->SetFocusToPasswordTextCtrl(); + return; + } + } + else + newPassword = CurrentPasswordPanel->GetPassword(); + + shared_ptr newKeyfiles; + if (DialogMode == Mode::ChangePasswordAndKeyfiles || DialogMode == Mode::ChangeKeyfiles) + newKeyfiles = NewPasswordPanel->GetKeyfiles(); + else if (DialogMode != Mode::RemoveAllKeyfiles) + newKeyfiles = CurrentPasswordPanel->GetKeyfiles(); + + Gui->UserEnrichRandomPool (this, NewPasswordPanel->GetPkcs5Kdf() ? NewPasswordPanel->GetPkcs5Kdf()->GetHash() : shared_ptr ()); + + { +#ifdef TC_UNIX + // Temporarily take ownership of a device if the user is not an administrator + UserId origDeviceOwner ((uid_t) -1); + + if (!Core->HasAdminPrivileges() && Path->IsDevice()) + { + origDeviceOwner = FilesystemPath (wstring (*Path)).GetOwner(); + Core->SetFileOwner (*Path, UserId (getuid())); + } + + finally_do_arg2 (FilesystemPath, *Path, UserId, origDeviceOwner, + { + if (finally_arg2.SystemId != (uid_t) -1) + Core->SetFileOwner (finally_arg, finally_arg2); + }); +#endif + wxBusyCursor busy; + Core->ChangePassword (Path, Gui->GetPreferences().DefaultMountOptions.PreserveTimestamps, + CurrentPasswordPanel->GetPassword(), CurrentPasswordPanel->GetKeyfiles(), + newPassword, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf()); + } + + switch (DialogMode) + { + case Mode::ChangePasswordAndKeyfiles: + Gui->ShowInfo ("PASSWORD_CHANGED"); + break; + + case Mode::ChangeKeyfiles: + case Mode::RemoveAllKeyfiles: + Gui->ShowInfo ("KEYFILE_CHANGED"); + break; + + case Mode::ChangePkcs5Prf: + Gui->ShowInfo ("PKCS5_PRF_CHANGED"); + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + + EndModal (wxID_OK); + } + catch (UnportablePassword &e) + { + Gui->ShowError (e); + NewPasswordPanel->SetFocusToPasswordTextCtrl(); + } + catch (PasswordException &e) + { + Gui->ShowWarning (e); + CurrentPasswordPanel->SetFocusToPasswordTextCtrl(); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void ChangePasswordDialog::OnPasswordPanelUpdate () + { + bool ok = true; + + bool passwordEmpty = CurrentPasswordPanel->GetPassword()->IsEmpty(); + bool keyfilesEmpty = !CurrentPasswordPanel->GetKeyfiles() || CurrentPasswordPanel->GetKeyfiles()->empty(); + + if (passwordEmpty && keyfilesEmpty) + ok = false; + + if (DialogMode == Mode::RemoveAllKeyfiles && (passwordEmpty || keyfilesEmpty)) + ok = false; + + if (DialogMode == Mode::ChangePasswordAndKeyfiles || DialogMode == Mode::ChangeKeyfiles) + { + bool newKeyfilesEmpty = !NewPasswordPanel->GetKeyfiles() || NewPasswordPanel->GetKeyfiles()->empty(); + + if (DialogMode == Mode::ChangeKeyfiles + && ((passwordEmpty && newKeyfilesEmpty) || (keyfilesEmpty && newKeyfilesEmpty))) + ok = false; + + if (DialogMode == Mode::ChangePasswordAndKeyfiles + && ((NewPasswordPanel->GetPassword()->IsEmpty() && newKeyfilesEmpty) || !NewPasswordPanel->PasswordsMatch())) + ok = false; + } + + OKButton->Enable (ok); + } +} diff --git a/Main/Forms/ChangePasswordDialog.h b/Main/Forms/ChangePasswordDialog.h index d05815d..ec7668b 100644 --- a/Main/Forms/ChangePasswordDialog.h +++ b/Main/Forms/ChangePasswordDialog.h @@ -1,48 +1,48 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_ChangePasswordDialog -#define TC_HEADER_Main_Forms_ChangePasswordDialog - -#include "Forms.h" -#include "Main/Main.h" -#include "VolumePasswordPanel.h" - -namespace TrueCrypt -{ - class ChangePasswordDialog : public ChangePasswordDialogBase - { - public: - struct Mode - { - enum Enum - { - ChangePasswordAndKeyfiles, - ChangeKeyfiles, - RemoveAllKeyfiles, - ChangePkcs5Prf - }; - }; - - ChangePasswordDialog (wxWindow* parent, shared_ptr volumePath, Mode::Enum mode = Mode::ChangePasswordAndKeyfiles, shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr ()); - virtual ~ChangePasswordDialog (); - - protected: - void OnOKButtonClick (wxCommandEvent& event); - void OnPasswordPanelUpdate (); - void OnPasswordPanelUpdate (EventArgs &args) { OnPasswordPanelUpdate(); } - - Mode::Enum DialogMode; - - VolumePasswordPanel *CurrentPasswordPanel; - VolumePasswordPanel *NewPasswordPanel; - shared_ptr Path; - }; -} - -#endif // TC_HEADER_Main_Forms_ChangePasswordDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_ChangePasswordDialog +#define TC_HEADER_Main_Forms_ChangePasswordDialog + +#include "Forms.h" +#include "Main/Main.h" +#include "VolumePasswordPanel.h" + +namespace TrueCrypt +{ + class ChangePasswordDialog : public ChangePasswordDialogBase + { + public: + struct Mode + { + enum Enum + { + ChangePasswordAndKeyfiles, + ChangeKeyfiles, + RemoveAllKeyfiles, + ChangePkcs5Prf + }; + }; + + ChangePasswordDialog (wxWindow* parent, shared_ptr volumePath, Mode::Enum mode = Mode::ChangePasswordAndKeyfiles, shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr ()); + virtual ~ChangePasswordDialog (); + + protected: + void OnOKButtonClick (wxCommandEvent& event); + void OnPasswordPanelUpdate (); + void OnPasswordPanelUpdate (EventArgs &args) { OnPasswordPanelUpdate(); } + + Mode::Enum DialogMode; + + VolumePasswordPanel *CurrentPasswordPanel; + VolumePasswordPanel *NewPasswordPanel; + shared_ptr Path; + }; +} + +#endif // TC_HEADER_Main_Forms_ChangePasswordDialog diff --git a/Main/Forms/DeviceSelectionDialog.cpp b/Main/Forms/DeviceSelectionDialog.cpp index edc3c12..be52545 100644 --- a/Main/Forms/DeviceSelectionDialog.cpp +++ b/Main/Forms/DeviceSelectionDialog.cpp @@ -1,120 +1,120 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "Main/Resources.h" -#include "DeviceSelectionDialog.h" - -namespace TrueCrypt -{ - DeviceSelectionDialog::DeviceSelectionDialog (wxWindow* parent) - : DeviceSelectionDialogBase (parent) - { - wxBusyCursor busy; - - list colPermilles; - - DeviceListCtrl->InsertColumn (ColumnDevice, LangString["DEVICE"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (447); -#ifdef TC_WINDOWS - DeviceListCtrl->InsertColumn (ColumnDrive, LangString["DRIVE"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (91); -#endif - DeviceListCtrl->InsertColumn (ColumnSize, LangString["SIZE"], wxLIST_FORMAT_RIGHT, 1); - colPermilles.push_back (153); -#ifdef TC_WINDOWS - DeviceListCtrl->InsertColumn (ColumnName, LangString["VOLUME_LABEL"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (307); -#else - DeviceListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (396); -#endif - - wxImageList *imageList = new wxImageList (16, 12, true); - imageList->Add (Resources::GetDriveIconBitmap(), Resources::GetDriveIconMaskBitmap()); - DeviceListCtrl->AssignImageList (imageList, wxIMAGE_LIST_SMALL); - - DeviceList = Core->GetHostDevices(); - - foreach_ref (HostDevice &device, DeviceList) - { - if (device.Size == 0) - continue; - - vector fields (DeviceListCtrl->GetColumnCount()); - - if (DeviceListCtrl->GetItemCount() > 0) - Gui->AppendToListCtrl (DeviceListCtrl, fields); - -#ifdef TC_WINDOWS - fields[ColumnDevice] = StringFormatter (L"{0} {1}:", _("Harddisk"), device.SystemNumber); - fields[ColumnDrive] = device.MountPoint; - fields[ColumnName] = device.Name; -#else - fields[ColumnDevice] = wstring (device.Path) + L":"; - fields[ColumnMountPoint] = device.MountPoint; -#endif - fields[ColumnSize] = Gui->SizeToString (device.Size); - Gui->AppendToListCtrl (DeviceListCtrl, fields, 0, &device); - - foreach_ref (HostDevice &partition, device.Partitions) - { - fields[ColumnDevice] = -#ifndef TC_WINDOWS - wstring (L" ") + -#endif - wstring (partition.Path); - -#ifdef TC_WINDOWS - fields[ColumnDrive] = partition.MountPoint; - fields[ColumnName] = partition.Name; -#else - fields[ColumnMountPoint] = partition.MountPoint; -#endif - fields[ColumnSize] = Gui->SizeToString (partition.Size); - Gui->AppendToListCtrl (DeviceListCtrl, fields, -1, &partition); - } - } - - Gui->SetListCtrlWidth (DeviceListCtrl, 73); - Gui->SetListCtrlHeight (DeviceListCtrl, 16); - Gui->SetListCtrlColumnWidths (DeviceListCtrl, colPermilles); - - Fit(); - Layout(); - Center(); - - StdButtonsOK->Disable(); - StdButtonsOK->SetDefault(); - } - - void DeviceSelectionDialog::OnListItemActivated (wxListEvent& event) - { - if (StdButtonsOK->IsEnabled()) - EndModal (wxID_OK); - } - - void DeviceSelectionDialog::OnListItemDeselected (wxListEvent& event) - { - if (DeviceListCtrl->GetSelectedItemCount() == 0) - StdButtonsOK->Disable(); - } - - void DeviceSelectionDialog::OnListItemSelected (wxListEvent& event) - { - HostDevice *device = (HostDevice *) (event.GetItem().GetData()); - if (device) - { - SelectedDevice = *device; - StdButtonsOK->Enable(); - } - else - StdButtonsOK->Disable(); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "Main/Resources.h" +#include "DeviceSelectionDialog.h" + +namespace TrueCrypt +{ + DeviceSelectionDialog::DeviceSelectionDialog (wxWindow* parent) + : DeviceSelectionDialogBase (parent) + { + wxBusyCursor busy; + + list colPermilles; + + DeviceListCtrl->InsertColumn (ColumnDevice, LangString["DEVICE"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (447); +#ifdef TC_WINDOWS + DeviceListCtrl->InsertColumn (ColumnDrive, LangString["DRIVE"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (91); +#endif + DeviceListCtrl->InsertColumn (ColumnSize, LangString["SIZE"], wxLIST_FORMAT_RIGHT, 1); + colPermilles.push_back (153); +#ifdef TC_WINDOWS + DeviceListCtrl->InsertColumn (ColumnName, LangString["VOLUME_LABEL"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (307); +#else + DeviceListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (396); +#endif + + wxImageList *imageList = new wxImageList (16, 12, true); + imageList->Add (Resources::GetDriveIconBitmap(), Resources::GetDriveIconMaskBitmap()); + DeviceListCtrl->AssignImageList (imageList, wxIMAGE_LIST_SMALL); + + DeviceList = Core->GetHostDevices(); + + foreach_ref (HostDevice &device, DeviceList) + { + if (device.Size == 0) + continue; + + vector fields (DeviceListCtrl->GetColumnCount()); + + if (DeviceListCtrl->GetItemCount() > 0) + Gui->AppendToListCtrl (DeviceListCtrl, fields); + +#ifdef TC_WINDOWS + fields[ColumnDevice] = StringFormatter (L"{0} {1}:", _("Harddisk"), device.SystemNumber); + fields[ColumnDrive] = device.MountPoint; + fields[ColumnName] = device.Name; +#else + fields[ColumnDevice] = wstring (device.Path) + L":"; + fields[ColumnMountPoint] = device.MountPoint; +#endif + fields[ColumnSize] = Gui->SizeToString (device.Size); + Gui->AppendToListCtrl (DeviceListCtrl, fields, 0, &device); + + foreach_ref (HostDevice &partition, device.Partitions) + { + fields[ColumnDevice] = +#ifndef TC_WINDOWS + wstring (L" ") + +#endif + wstring (partition.Path); + +#ifdef TC_WINDOWS + fields[ColumnDrive] = partition.MountPoint; + fields[ColumnName] = partition.Name; +#else + fields[ColumnMountPoint] = partition.MountPoint; +#endif + fields[ColumnSize] = Gui->SizeToString (partition.Size); + Gui->AppendToListCtrl (DeviceListCtrl, fields, -1, &partition); + } + } + + Gui->SetListCtrlWidth (DeviceListCtrl, 73); + Gui->SetListCtrlHeight (DeviceListCtrl, 16); + Gui->SetListCtrlColumnWidths (DeviceListCtrl, colPermilles); + + Fit(); + Layout(); + Center(); + + StdButtonsOK->Disable(); + StdButtonsOK->SetDefault(); + } + + void DeviceSelectionDialog::OnListItemActivated (wxListEvent& event) + { + if (StdButtonsOK->IsEnabled()) + EndModal (wxID_OK); + } + + void DeviceSelectionDialog::OnListItemDeselected (wxListEvent& event) + { + if (DeviceListCtrl->GetSelectedItemCount() == 0) + StdButtonsOK->Disable(); + } + + void DeviceSelectionDialog::OnListItemSelected (wxListEvent& event) + { + HostDevice *device = (HostDevice *) (event.GetItem().GetData()); + if (device) + { + SelectedDevice = *device; + StdButtonsOK->Enable(); + } + else + StdButtonsOK->Disable(); + } +} diff --git a/Main/Forms/DeviceSelectionDialog.h b/Main/Forms/DeviceSelectionDialog.h index d852f94..690bba3 100644 --- a/Main/Forms/DeviceSelectionDialog.h +++ b/Main/Forms/DeviceSelectionDialog.h @@ -1,46 +1,46 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_DeviceSelectionDialog -#define TC_HEADER_Main_Forms_DeviceSelectionDialog - -#include "Forms.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class DeviceSelectionDialog : public DeviceSelectionDialogBase - { - public: - DeviceSelectionDialog (wxWindow* parent); - - HostDeviceList DeviceList; - HostDevice SelectedDevice; - - protected: - enum - { - ColumnDevice = 0, -#ifdef TC_WINDOWS - ColumnDrive, -#endif - ColumnSize, -#ifdef TC_WINDOWS - ColumnName -#else - ColumnMountPoint -#endif - }; - - void OnListItemActivated (wxListEvent& event); - void OnListItemDeselected (wxListEvent& event); - void OnListItemSelected (wxListEvent& event); - }; -} - -#endif // TC_HEADER_Main_Forms_DeviceSelectionDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_DeviceSelectionDialog +#define TC_HEADER_Main_Forms_DeviceSelectionDialog + +#include "Forms.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class DeviceSelectionDialog : public DeviceSelectionDialogBase + { + public: + DeviceSelectionDialog (wxWindow* parent); + + HostDeviceList DeviceList; + HostDevice SelectedDevice; + + protected: + enum + { + ColumnDevice = 0, +#ifdef TC_WINDOWS + ColumnDrive, +#endif + ColumnSize, +#ifdef TC_WINDOWS + ColumnName +#else + ColumnMountPoint +#endif + }; + + void OnListItemActivated (wxListEvent& event); + void OnListItemDeselected (wxListEvent& event); + void OnListItemSelected (wxListEvent& event); + }; +} + +#endif // TC_HEADER_Main_Forms_DeviceSelectionDialog diff --git a/Main/Forms/EncryptionOptionsWizardPage.cpp b/Main/Forms/EncryptionOptionsWizardPage.cpp index c3e70d2..ca116ea 100644 --- a/Main/Forms/EncryptionOptionsWizardPage.cpp +++ b/Main/Forms/EncryptionOptionsWizardPage.cpp @@ -1,134 +1,134 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Volume/EncryptionTest.h" -#include "Volume/Hash.h" -#include "Main/GraphicUserInterface.h" -#include "EncryptionOptionsWizardPage.h" -#include "EncryptionTestDialog.h" - -namespace TrueCrypt -{ - EncryptionOptionsWizardPage::EncryptionOptionsWizardPage (wxPanel* parent) - : EncryptionOptionsWizardPageBase (parent) - { - - EncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms(); - foreach (shared_ptr ea, EncryptionAlgorithms) - { - if (!ea->IsDeprecated()) - EncryptionAlgorithmChoice->Append (ea->GetName(), ea.get()); - } - - EncryptionAlgorithmChoice->Select (0); - - Hashes = Hash::GetAvailableAlgorithms(); - foreach (shared_ptr hash, Hashes) - { - if (!hash->IsDeprecated()) - HashChoice->Append (hash->GetName(), hash.get()); - } - - HashChoice->Select (0); - OnEncryptionAlgorithmSelected(); - - } - - shared_ptr EncryptionOptionsWizardPage::GetEncryptionAlgorithm () const - { - return Gui->GetSelectedData (EncryptionAlgorithmChoice)->GetNew(); - } - - shared_ptr EncryptionOptionsWizardPage::GetHash () const - { - return Gui->GetSelectedData (HashChoice)->GetNew(); - } - - void EncryptionOptionsWizardPage::OnBenchmarkButtonClick (wxCommandEvent& event) - { - } - - void EncryptionOptionsWizardPage::OnEncryptionAlgorithmSelected () - { - FreezeScope freeze (this); - - shared_ptr ea = GetEncryptionAlgorithm(); - CipherList ciphers = ea->GetCiphers(); - - if (ciphers.size() == 1) - { - EncryptionAlgorithmHyperlink->SetLabel (StringFormatter (LangString["MORE_INFO_ABOUT"], ea->GetName())); - - if (typeid (*ea) == typeid (AES)) - EncryptionAlgorithmStaticText->SetLabel (LangString["AES_HELP"]); - else if (typeid (*ea) == typeid (Serpent)) - EncryptionAlgorithmStaticText->SetLabel (LangString["SERPENT_HELP"]); - else if (typeid (*ea) == typeid (Twofish)) - EncryptionAlgorithmStaticText->SetLabel (LangString["TWOFISH_HELP"]); - else - EncryptionAlgorithmStaticText->SetLabel (L""); - } - else - { - if (ciphers.size() == 2) - { - EncryptionAlgorithmStaticText->SetLabel (StringFormatter (LangString["TWO_LAYER_CASCADE_HELP"], - ciphers[0]->GetName(), (int) ciphers[0]->GetKeySize() * 8, - ciphers[1]->GetName(), (int) ciphers[1]->GetKeySize() * 8)); - } - else if (ciphers.size() == 3) - { - EncryptionAlgorithmStaticText->SetLabel (StringFormatter (LangString["THREE_LAYER_CASCADE_HELP"], - ciphers[0]->GetName(), (int) ciphers[0]->GetKeySize() * 8, - ciphers[1]->GetName(), (int) ciphers[1]->GetKeySize() * 8, - ciphers[2]->GetName(), (int) ciphers[2]->GetKeySize() * 8)); - } - else - EncryptionAlgorithmStaticText->SetLabel (L""); - - EncryptionAlgorithmHyperlink->SetLabel (_("More information")); - } - - Layout(); - } - - void EncryptionOptionsWizardPage::OnEncryptionAlgorithmHyperlinkClick (wxHyperlinkEvent& event) - { - if (GetEncryptionAlgorithm()->GetCiphers().size() == 1) - Gui->OpenHomepageLink (this, wxString (GetEncryptionAlgorithm()->GetName()).Lower()); - else - Gui->OpenHomepageLink (this, L"cascades"); - } - - void EncryptionOptionsWizardPage::OnHashHyperlinkClick (wxHyperlinkEvent& event) - { - Gui->OpenHomepageLink (this, L"hashalgorithms"); - } - - void EncryptionOptionsWizardPage::OnTestButtonClick (wxCommandEvent& event) - { - EncryptionTestDialog dialog (this); - dialog.ShowModal(); - } - - void EncryptionOptionsWizardPage::SetEncryptionAlgorithm (shared_ptr algorithm) - { - if (algorithm) - { - EncryptionAlgorithmChoice->SetStringSelection (algorithm->GetName()); - OnEncryptionAlgorithmSelected (); - } - } - - void EncryptionOptionsWizardPage::SetHash (shared_ptr hash) - { - if (hash) - HashChoice->SetStringSelection (hash->GetName()); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Volume/EncryptionTest.h" +#include "Volume/Hash.h" +#include "Main/GraphicUserInterface.h" +#include "EncryptionOptionsWizardPage.h" +#include "EncryptionTestDialog.h" + +namespace TrueCrypt +{ + EncryptionOptionsWizardPage::EncryptionOptionsWizardPage (wxPanel* parent) + : EncryptionOptionsWizardPageBase (parent) + { + + EncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms(); + foreach (shared_ptr ea, EncryptionAlgorithms) + { + if (!ea->IsDeprecated()) + EncryptionAlgorithmChoice->Append (ea->GetName(), ea.get()); + } + + EncryptionAlgorithmChoice->Select (0); + + Hashes = Hash::GetAvailableAlgorithms(); + foreach (shared_ptr hash, Hashes) + { + if (!hash->IsDeprecated()) + HashChoice->Append (hash->GetName(), hash.get()); + } + + HashChoice->Select (0); + OnEncryptionAlgorithmSelected(); + + } + + shared_ptr EncryptionOptionsWizardPage::GetEncryptionAlgorithm () const + { + return Gui->GetSelectedData (EncryptionAlgorithmChoice)->GetNew(); + } + + shared_ptr EncryptionOptionsWizardPage::GetHash () const + { + return Gui->GetSelectedData (HashChoice)->GetNew(); + } + + void EncryptionOptionsWizardPage::OnBenchmarkButtonClick (wxCommandEvent& event) + { + } + + void EncryptionOptionsWizardPage::OnEncryptionAlgorithmSelected () + { + FreezeScope freeze (this); + + shared_ptr ea = GetEncryptionAlgorithm(); + CipherList ciphers = ea->GetCiphers(); + + if (ciphers.size() == 1) + { + EncryptionAlgorithmHyperlink->SetLabel (StringFormatter (LangString["MORE_INFO_ABOUT"], ea->GetName())); + + if (typeid (*ea) == typeid (AES)) + EncryptionAlgorithmStaticText->SetLabel (LangString["AES_HELP"]); + else if (typeid (*ea) == typeid (Serpent)) + EncryptionAlgorithmStaticText->SetLabel (LangString["SERPENT_HELP"]); + else if (typeid (*ea) == typeid (Twofish)) + EncryptionAlgorithmStaticText->SetLabel (LangString["TWOFISH_HELP"]); + else + EncryptionAlgorithmStaticText->SetLabel (L""); + } + else + { + if (ciphers.size() == 2) + { + EncryptionAlgorithmStaticText->SetLabel (StringFormatter (LangString["TWO_LAYER_CASCADE_HELP"], + ciphers[0]->GetName(), (int) ciphers[0]->GetKeySize() * 8, + ciphers[1]->GetName(), (int) ciphers[1]->GetKeySize() * 8)); + } + else if (ciphers.size() == 3) + { + EncryptionAlgorithmStaticText->SetLabel (StringFormatter (LangString["THREE_LAYER_CASCADE_HELP"], + ciphers[0]->GetName(), (int) ciphers[0]->GetKeySize() * 8, + ciphers[1]->GetName(), (int) ciphers[1]->GetKeySize() * 8, + ciphers[2]->GetName(), (int) ciphers[2]->GetKeySize() * 8)); + } + else + EncryptionAlgorithmStaticText->SetLabel (L""); + + EncryptionAlgorithmHyperlink->SetLabel (_("More information")); + } + + Layout(); + } + + void EncryptionOptionsWizardPage::OnEncryptionAlgorithmHyperlinkClick (wxHyperlinkEvent& event) + { + if (GetEncryptionAlgorithm()->GetCiphers().size() == 1) + Gui->OpenHomepageLink (this, wxString (GetEncryptionAlgorithm()->GetName()).Lower()); + else + Gui->OpenHomepageLink (this, L"cascades"); + } + + void EncryptionOptionsWizardPage::OnHashHyperlinkClick (wxHyperlinkEvent& event) + { + Gui->OpenHomepageLink (this, L"hashalgorithms"); + } + + void EncryptionOptionsWizardPage::OnTestButtonClick (wxCommandEvent& event) + { + EncryptionTestDialog dialog (this); + dialog.ShowModal(); + } + + void EncryptionOptionsWizardPage::SetEncryptionAlgorithm (shared_ptr algorithm) + { + if (algorithm) + { + EncryptionAlgorithmChoice->SetStringSelection (algorithm->GetName()); + OnEncryptionAlgorithmSelected (); + } + } + + void EncryptionOptionsWizardPage::SetHash (shared_ptr hash) + { + if (hash) + HashChoice->SetStringSelection (hash->GetName()); + } +} diff --git a/Main/Forms/EncryptionOptionsWizardPage.h b/Main/Forms/EncryptionOptionsWizardPage.h index 38c07f5..5a51332 100644 --- a/Main/Forms/EncryptionOptionsWizardPage.h +++ b/Main/Forms/EncryptionOptionsWizardPage.h @@ -1,41 +1,41 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_EncryptionOptionsWizardPage -#define TC_HEADER_Main_Forms_EncryptionOptionsWizardPage - -#include "Forms.h" - -namespace TrueCrypt -{ - class EncryptionOptionsWizardPage : public EncryptionOptionsWizardPageBase - { - public: - EncryptionOptionsWizardPage (wxPanel* parent); - - shared_ptr GetEncryptionAlgorithm () const; - shared_ptr GetHash () const; - bool IsValid () { return true; } - void SetPageText (const wxString &text) { } - void SetEncryptionAlgorithm (shared_ptr algorithm); - void SetHash (shared_ptr hash); - - protected: - void OnBenchmarkButtonClick (wxCommandEvent& event); - void OnEncryptionAlgorithmHyperlinkClick (wxHyperlinkEvent& event); - void OnEncryptionAlgorithmSelected (); - void OnEncryptionAlgorithmSelected (wxCommandEvent& event) { OnEncryptionAlgorithmSelected(); } - void OnHashHyperlinkClick (wxHyperlinkEvent& event); - void OnTestButtonClick (wxCommandEvent& event); - - EncryptionAlgorithmList EncryptionAlgorithms; - HashList Hashes; - }; -} - -#endif // TC_HEADER_Main_Forms_EncryptionOptionsWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_EncryptionOptionsWizardPage +#define TC_HEADER_Main_Forms_EncryptionOptionsWizardPage + +#include "Forms.h" + +namespace TrueCrypt +{ + class EncryptionOptionsWizardPage : public EncryptionOptionsWizardPageBase + { + public: + EncryptionOptionsWizardPage (wxPanel* parent); + + shared_ptr GetEncryptionAlgorithm () const; + shared_ptr GetHash () const; + bool IsValid () { return true; } + void SetPageText (const wxString &text) { } + void SetEncryptionAlgorithm (shared_ptr algorithm); + void SetHash (shared_ptr hash); + + protected: + void OnBenchmarkButtonClick (wxCommandEvent& event); + void OnEncryptionAlgorithmHyperlinkClick (wxHyperlinkEvent& event); + void OnEncryptionAlgorithmSelected (); + void OnEncryptionAlgorithmSelected (wxCommandEvent& event) { OnEncryptionAlgorithmSelected(); } + void OnHashHyperlinkClick (wxHyperlinkEvent& event); + void OnTestButtonClick (wxCommandEvent& event); + + EncryptionAlgorithmList EncryptionAlgorithms; + HashList Hashes; + }; +} + +#endif // TC_HEADER_Main_Forms_EncryptionOptionsWizardPage diff --git a/Main/Forms/EncryptionTestDialog.cpp b/Main/Forms/EncryptionTestDialog.cpp index 69e02c4..af154ce 100644 --- a/Main/Forms/EncryptionTestDialog.cpp +++ b/Main/Forms/EncryptionTestDialog.cpp @@ -1,227 +1,227 @@ -/* -Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - -Governed by the TrueCrypt License 2.7 the full text of which is contained -in the file License.txt included in TrueCrypt binary and source code -distribution packages. -*/ - -#include "System.h" -#include "Volume/EncryptionModeXTS.h" -#include "Volume/EncryptionTest.h" -#include "Main/GraphicUserInterface.h" -#include "EncryptionTestDialog.h" - -namespace TrueCrypt -{ - EncryptionTestDialog::EncryptionTestDialog (wxWindow* parent) - : EncryptionTestDialogBase (parent) - { - EncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms(); - foreach (shared_ptr ea, EncryptionAlgorithms) - { - if (!ea->IsDeprecated()) - EncryptionAlgorithmChoice->Append (ea->GetName(), ea.get()); - } - - EncryptionAlgorithmChoice->Select (0); - Reset(); - - Fit(); - Layout(); - Center(); - } - - void EncryptionTestDialog::EncryptOrDecrypt (bool encrypt) - { - try - { - bool xts = XtsModeCheckBox->IsChecked(); - - shared_ptr ea = GetSelectedEncryptionAlgorithm(); - - Buffer key; - GetTextCtrlData (KeyTextCtrl, key); - - if (key.Size() != ea->GetKeySize()) - throw_err (LangString["TEST_KEY_SIZE"]); - - ea->SetKey (key); - - Buffer data; - GetTextCtrlData (encrypt ? PlainTextTextCtrl : CipherTextTextCtrl, data); - - if (data.Size() != ea->GetMaxBlockSize()) - throw_err (LangString[encrypt ? "TEST_PLAINTEXT_SIZE" : "TEST_CIPHERTEXT_SIZE"]); - - if (xts) - { - Buffer secondaryKey; - GetTextCtrlData (SecondaryKeyTextCtrl, secondaryKey); - - if (secondaryKey.Size() != ea->GetKeySize()) - throw_err (LangString["TEST_INCORRECT_SECONDARY_KEY_SIZE"]); - - uint64 dataUnitNumber; - size_t blockNumber; - - try - { - dataUnitNumber = StringConverter::ToUInt64 (wstring (DataUnitNumberTextCtrl->GetValue())); - } - catch (...) - { - DataUnitNumberTextCtrl->SetFocus(); - throw StringConversionFailed (SRC_POS); - } - - try - { - blockNumber = StringConverter::ToUInt32 (wstring (BlockNumberTextCtrl->GetValue())); - if (blockNumber > 31) - { - blockNumber = 31; - BlockNumberTextCtrl->SetValue (L"31"); - } - } - catch (...) - { - BlockNumberTextCtrl->SetFocus(); - throw StringConversionFailed (SRC_POS); - } - - shared_ptr xts (new EncryptionModeXTS); - xts->SetKey (secondaryKey); - ea->SetMode (xts); - - Buffer sector (ENCRYPTION_DATA_UNIT_SIZE); - BufferPtr block = sector.GetRange (blockNumber * ea->GetMaxBlockSize(), ea->GetMaxBlockSize()); - - block.CopyFrom (data); - - if (encrypt) - ea->EncryptSectors (sector, dataUnitNumber, 1, sector.Size()); - else - ea->DecryptSectors (sector, dataUnitNumber, 1, sector.Size()); - - data.CopyFrom (block); - } - else - { - if (encrypt) - ea->GetCiphers().front()->EncryptBlock (data); - else - ea->GetCiphers().front()->DecryptBlock (data); - } - - SetTextCtrlData (encrypt ? CipherTextTextCtrl : PlainTextTextCtrl, data); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - shared_ptr EncryptionTestDialog::GetSelectedEncryptionAlgorithm () const - { - return Gui->GetSelectedData (EncryptionAlgorithmChoice)->GetNew(); - } - - void EncryptionTestDialog::GetTextCtrlData (wxTextCtrl *textCtrl, Buffer &buffer) const - { - vector data; - string dataStr = StringConverter::ToSingle (wstring (textCtrl->GetValue())); - - for (size_t i = 0; i < dataStr.size() / 2; ++i) - { - unsigned int dataByte; - if (sscanf (dataStr.substr (i * 2, 2).c_str(), "%x", &dataByte) != 1) - { - textCtrl->SetFocus(); - throw StringConversionFailed (SRC_POS); - } - - data.push_back ((byte) dataByte); - } - - if (data.empty()) - return; - - buffer.CopyFrom (ConstBufferPtr (&data.front(), data.size())); - } - - void EncryptionTestDialog::OnAutoTestAllButtonClick (wxCommandEvent& event) - { - try - { - { - wxBusyCursor busy; - EncryptionTest::TestAll(); - } - - Gui->ShowInfo ("TESTS_PASSED"); - } - catch (Exception &e) - { - Gui->ShowError (e); - Gui->ShowError ("TESTS_FAILED"); - } - } - - void EncryptionTestDialog::OnEncryptionAlgorithmSelected () - { - shared_ptr ea = GetSelectedEncryptionAlgorithm(); - - KeySizeStaticText->SetLabel (StringFormatter (L"{0} {1}", (uint32) ea->GetKeySize() * 8, LangString["BITS"])); - - Buffer key (ea->GetKeySize()); - key.Zero(); - SetTextCtrlData (KeyTextCtrl, key); - SetTextCtrlData (SecondaryKeyTextCtrl, key); - - Buffer block (ea->GetMaxBlockSize()); - block.Zero(); - SetTextCtrlData (PlainTextTextCtrl, block); - SetTextCtrlData (CipherTextTextCtrl, block); - - if (ea->GetCiphers().size() > 1) - { - XtsModeCheckBox->Disable(); - XtsModeCheckBox->SetValue (true); - SecondaryKeyTextCtrl->Enable (true); - DataUnitNumberTextCtrl->Enable (true); - BlockNumberTextCtrl->Enable (true); - } - else - XtsModeCheckBox->Enable(); - } - - void EncryptionTestDialog::OnXtsModeCheckBoxClick (wxCommandEvent& event) - { - bool enabled = event.IsChecked(); - SecondaryKeyTextCtrl->Enable (enabled); - DataUnitNumberTextCtrl->Enable (enabled); - BlockNumberTextCtrl->Enable (enabled); - } - - void EncryptionTestDialog::SetTextCtrlData (wxTextCtrl *textCtrl, const BufferPtr &data) - { - wstring str; - for (size_t i = 0; i < data.Size(); i++) - { - char strBuf[3]; - sprintf (strBuf, "%02x", (int) data[i]); - str += StringConverter::ToWide (strBuf); - } - - textCtrl->SetValue (str); - } - - void EncryptionTestDialog::Reset () - { - OnEncryptionAlgorithmSelected(); - - DataUnitNumberTextCtrl->SetValue (L"0"); - BlockNumberTextCtrl->SetValue (L"0"); - } -} +/* +Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + +Governed by the TrueCrypt License 2.8 the full text of which is contained +in the file License.txt included in TrueCrypt binary and source code +distribution packages. +*/ + +#include "System.h" +#include "Volume/EncryptionModeXTS.h" +#include "Volume/EncryptionTest.h" +#include "Main/GraphicUserInterface.h" +#include "EncryptionTestDialog.h" + +namespace TrueCrypt +{ + EncryptionTestDialog::EncryptionTestDialog (wxWindow* parent) + : EncryptionTestDialogBase (parent) + { + EncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms(); + foreach (shared_ptr ea, EncryptionAlgorithms) + { + if (!ea->IsDeprecated()) + EncryptionAlgorithmChoice->Append (ea->GetName(), ea.get()); + } + + EncryptionAlgorithmChoice->Select (0); + Reset(); + + Fit(); + Layout(); + Center(); + } + + void EncryptionTestDialog::EncryptOrDecrypt (bool encrypt) + { + try + { + bool xts = XtsModeCheckBox->IsChecked(); + + shared_ptr ea = GetSelectedEncryptionAlgorithm(); + + Buffer key; + GetTextCtrlData (KeyTextCtrl, key); + + if (key.Size() != ea->GetKeySize()) + throw_err (LangString["TEST_KEY_SIZE"]); + + ea->SetKey (key); + + Buffer data; + GetTextCtrlData (encrypt ? PlainTextTextCtrl : CipherTextTextCtrl, data); + + if (data.Size() != ea->GetMaxBlockSize()) + throw_err (LangString[encrypt ? "TEST_PLAINTEXT_SIZE" : "TEST_CIPHERTEXT_SIZE"]); + + if (xts) + { + Buffer secondaryKey; + GetTextCtrlData (SecondaryKeyTextCtrl, secondaryKey); + + if (secondaryKey.Size() != ea->GetKeySize()) + throw_err (LangString["TEST_INCORRECT_SECONDARY_KEY_SIZE"]); + + uint64 dataUnitNumber; + size_t blockNumber; + + try + { + dataUnitNumber = StringConverter::ToUInt64 (wstring (DataUnitNumberTextCtrl->GetValue())); + } + catch (...) + { + DataUnitNumberTextCtrl->SetFocus(); + throw StringConversionFailed (SRC_POS); + } + + try + { + blockNumber = StringConverter::ToUInt32 (wstring (BlockNumberTextCtrl->GetValue())); + if (blockNumber > 31) + { + blockNumber = 31; + BlockNumberTextCtrl->SetValue (L"31"); + } + } + catch (...) + { + BlockNumberTextCtrl->SetFocus(); + throw StringConversionFailed (SRC_POS); + } + + shared_ptr xts (new EncryptionModeXTS); + xts->SetKey (secondaryKey); + ea->SetMode (xts); + + Buffer sector (ENCRYPTION_DATA_UNIT_SIZE); + BufferPtr block = sector.GetRange (blockNumber * ea->GetMaxBlockSize(), ea->GetMaxBlockSize()); + + block.CopyFrom (data); + + if (encrypt) + ea->EncryptSectors (sector, dataUnitNumber, 1, sector.Size()); + else + ea->DecryptSectors (sector, dataUnitNumber, 1, sector.Size()); + + data.CopyFrom (block); + } + else + { + if (encrypt) + ea->GetCiphers().front()->EncryptBlock (data); + else + ea->GetCiphers().front()->DecryptBlock (data); + } + + SetTextCtrlData (encrypt ? CipherTextTextCtrl : PlainTextTextCtrl, data); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + shared_ptr EncryptionTestDialog::GetSelectedEncryptionAlgorithm () const + { + return Gui->GetSelectedData (EncryptionAlgorithmChoice)->GetNew(); + } + + void EncryptionTestDialog::GetTextCtrlData (wxTextCtrl *textCtrl, Buffer &buffer) const + { + vector data; + string dataStr = StringConverter::ToSingle (wstring (textCtrl->GetValue())); + + for (size_t i = 0; i < dataStr.size() / 2; ++i) + { + unsigned int dataByte; + if (sscanf (dataStr.substr (i * 2, 2).c_str(), "%x", &dataByte) != 1) + { + textCtrl->SetFocus(); + throw StringConversionFailed (SRC_POS); + } + + data.push_back ((byte) dataByte); + } + + if (data.empty()) + return; + + buffer.CopyFrom (ConstBufferPtr (&data.front(), data.size())); + } + + void EncryptionTestDialog::OnAutoTestAllButtonClick (wxCommandEvent& event) + { + try + { + { + wxBusyCursor busy; + EncryptionTest::TestAll(); + } + + Gui->ShowInfo ("TESTS_PASSED"); + } + catch (Exception &e) + { + Gui->ShowError (e); + Gui->ShowError ("TESTS_FAILED"); + } + } + + void EncryptionTestDialog::OnEncryptionAlgorithmSelected () + { + shared_ptr ea = GetSelectedEncryptionAlgorithm(); + + KeySizeStaticText->SetLabel (StringFormatter (L"{0} {1}", (uint32) ea->GetKeySize() * 8, LangString["BITS"])); + + Buffer key (ea->GetKeySize()); + key.Zero(); + SetTextCtrlData (KeyTextCtrl, key); + SetTextCtrlData (SecondaryKeyTextCtrl, key); + + Buffer block (ea->GetMaxBlockSize()); + block.Zero(); + SetTextCtrlData (PlainTextTextCtrl, block); + SetTextCtrlData (CipherTextTextCtrl, block); + + if (ea->GetCiphers().size() > 1) + { + XtsModeCheckBox->Disable(); + XtsModeCheckBox->SetValue (true); + SecondaryKeyTextCtrl->Enable (true); + DataUnitNumberTextCtrl->Enable (true); + BlockNumberTextCtrl->Enable (true); + } + else + XtsModeCheckBox->Enable(); + } + + void EncryptionTestDialog::OnXtsModeCheckBoxClick (wxCommandEvent& event) + { + bool enabled = event.IsChecked(); + SecondaryKeyTextCtrl->Enable (enabled); + DataUnitNumberTextCtrl->Enable (enabled); + BlockNumberTextCtrl->Enable (enabled); + } + + void EncryptionTestDialog::SetTextCtrlData (wxTextCtrl *textCtrl, const BufferPtr &data) + { + wstring str; + for (size_t i = 0; i < data.Size(); i++) + { + char strBuf[3]; + sprintf (strBuf, "%02x", (int) data[i]); + str += StringConverter::ToWide (strBuf); + } + + textCtrl->SetValue (str); + } + + void EncryptionTestDialog::Reset () + { + OnEncryptionAlgorithmSelected(); + + DataUnitNumberTextCtrl->SetValue (L"0"); + BlockNumberTextCtrl->SetValue (L"0"); + } +} diff --git a/Main/Forms/EncryptionTestDialog.h b/Main/Forms/EncryptionTestDialog.h index 28c86d9..2d4cb7c 100644 --- a/Main/Forms/EncryptionTestDialog.h +++ b/Main/Forms/EncryptionTestDialog.h @@ -1,40 +1,40 @@ -/* -Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - -Governed by the TrueCrypt License 2.7 the full text of which is contained -in the file License.txt included in TrueCrypt binary and source code -distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_EncryptionTestDialog -#define TC_HEADER_Main_Forms_EncryptionTestDialog - -#include "Forms.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class EncryptionTestDialog : public EncryptionTestDialogBase - { - public: - EncryptionTestDialog (wxWindow* parent); - - protected: - void EncryptOrDecrypt (bool encrypt); - shared_ptr GetSelectedEncryptionAlgorithm () const; - void GetTextCtrlData (wxTextCtrl *textCtrl, Buffer &buffer) const; - void OnAutoTestAllButtonClick (wxCommandEvent& event); - void OnDecryptButtonClick (wxCommandEvent& event) { EncryptOrDecrypt (false); } - void OnEncryptButtonClick (wxCommandEvent& event) { EncryptOrDecrypt (true); } - void OnEncryptionAlgorithmSelected (); - void OnEncryptionAlgorithmSelected (wxCommandEvent& event) { OnEncryptionAlgorithmSelected(); } - void OnResetButtonClick (wxCommandEvent& event) { Reset(); } - void OnXtsModeCheckBoxClick (wxCommandEvent& event); - void SetTextCtrlData (wxTextCtrl *textCtrl, const BufferPtr &data); - void Reset (); - - EncryptionAlgorithmList EncryptionAlgorithms; - }; -} - -#endif // TC_HEADER_Main_Forms_EncryptionTestDialog +/* +Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + +Governed by the TrueCrypt License 2.8 the full text of which is contained +in the file License.txt included in TrueCrypt binary and source code +distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_EncryptionTestDialog +#define TC_HEADER_Main_Forms_EncryptionTestDialog + +#include "Forms.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class EncryptionTestDialog : public EncryptionTestDialogBase + { + public: + EncryptionTestDialog (wxWindow* parent); + + protected: + void EncryptOrDecrypt (bool encrypt); + shared_ptr GetSelectedEncryptionAlgorithm () const; + void GetTextCtrlData (wxTextCtrl *textCtrl, Buffer &buffer) const; + void OnAutoTestAllButtonClick (wxCommandEvent& event); + void OnDecryptButtonClick (wxCommandEvent& event) { EncryptOrDecrypt (false); } + void OnEncryptButtonClick (wxCommandEvent& event) { EncryptOrDecrypt (true); } + void OnEncryptionAlgorithmSelected (); + void OnEncryptionAlgorithmSelected (wxCommandEvent& event) { OnEncryptionAlgorithmSelected(); } + void OnResetButtonClick (wxCommandEvent& event) { Reset(); } + void OnXtsModeCheckBoxClick (wxCommandEvent& event); + void SetTextCtrlData (wxTextCtrl *textCtrl, const BufferPtr &data); + void Reset (); + + EncryptionAlgorithmList EncryptionAlgorithms; + }; +} + +#endif // TC_HEADER_Main_Forms_EncryptionTestDialog diff --git a/Main/Forms/FavoriteVolumesDialog.cpp b/Main/Forms/FavoriteVolumesDialog.cpp index 6b1f1b5..1e7caaf 100644 --- a/Main/Forms/FavoriteVolumesDialog.cpp +++ b/Main/Forms/FavoriteVolumesDialog.cpp @@ -1,118 +1,118 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "FavoriteVolumesDialog.h" - -namespace TrueCrypt -{ - FavoriteVolumesDialog::FavoriteVolumesDialog (wxWindow* parent, const FavoriteVolumeList &favorites, size_t newItemCount) - : FavoriteVolumesDialogBase (parent), Favorites (favorites) - { - list colPermilles; - FavoritesListCtrl->InsertColumn (ColumnVolumePath, LangString["VOLUME"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (500); - FavoritesListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (500); - - FavoritesListCtrl->SetMinSize (wxSize (400, -1)); - Gui->SetListCtrlHeight (FavoritesListCtrl, 15); - Gui->SetListCtrlColumnWidths (FavoritesListCtrl, colPermilles); - - Layout(); - Fit(); - Center(); - -#ifdef TC_MACOSX - // wxMac cannot insert items to wxListCtrl due to a bug - MoveUpButton->Show (false); - MoveDownButton->Show (false); -#endif - - vector fields (FavoritesListCtrl->GetColumnCount()); - size_t itemCount = 0; - foreach (shared_ptr favorite, Favorites) - { - fields[ColumnVolumePath] = favorite->Path; - fields[ColumnMountPoint] = favorite->MountPoint; - Gui->AppendToListCtrl (FavoritesListCtrl, fields, -1, favorite.get()); - - if (++itemCount > Favorites.size() - newItemCount) - { - FavoritesListCtrl->SetItemState (itemCount - 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); - FavoritesListCtrl->EnsureVisible (itemCount - 1); - } - } - - UpdateButtons(); - FavoritesListCtrl->SetFocus(); - } - - void FavoriteVolumesDialog::OnMoveDownButtonClick (wxCommandEvent& event) - { - FreezeScope freeze (this); - foreach_reverse (long itemIndex, Gui->GetListCtrlSelectedItems (FavoritesListCtrl)) - { - if (itemIndex >= FavoritesListCtrl->GetItemCount() - 1) - break; - Gui->MoveListCtrlItem (FavoritesListCtrl, itemIndex, itemIndex + 1); - } - UpdateButtons(); - } - - void FavoriteVolumesDialog::OnMoveUpButtonClick (wxCommandEvent& event) - { - FreezeScope freeze (this); - foreach (long itemIndex, Gui->GetListCtrlSelectedItems (FavoritesListCtrl)) - { - if (itemIndex == 0) - break; - - Gui->MoveListCtrlItem (FavoritesListCtrl, itemIndex, itemIndex - 1); - } - UpdateButtons(); - } - - void FavoriteVolumesDialog::OnOKButtonClick (wxCommandEvent& event) - { - FavoriteVolumeList newFavorites; - - for (long i = 0; i < FavoritesListCtrl->GetItemCount(); i++) - { - newFavorites.push_back (make_shared ( - *reinterpret_cast (FavoritesListCtrl->GetItemData (i)))); - } - - Favorites = newFavorites; - EndModal (wxID_OK); - } - - void FavoriteVolumesDialog::OnRemoveAllButtonClick (wxCommandEvent& event) - { - FavoritesListCtrl->DeleteAllItems(); - UpdateButtons(); - } - - void FavoriteVolumesDialog::OnRemoveButtonClick (wxCommandEvent& event) - { - long offset = 0; - foreach (long item, Gui->GetListCtrlSelectedItems (FavoritesListCtrl)) - FavoritesListCtrl->DeleteItem (item - offset++); - } - - void FavoriteVolumesDialog::UpdateButtons () - { - bool selected = FavoritesListCtrl->GetSelectedItemCount() > 0; - - MoveDownButton->Enable (selected); - MoveUpButton->Enable (selected); - RemoveAllButton->Enable (FavoritesListCtrl->GetItemCount() > 0); - RemoveButton->Enable (selected); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "FavoriteVolumesDialog.h" + +namespace TrueCrypt +{ + FavoriteVolumesDialog::FavoriteVolumesDialog (wxWindow* parent, const FavoriteVolumeList &favorites, size_t newItemCount) + : FavoriteVolumesDialogBase (parent), Favorites (favorites) + { + list colPermilles; + FavoritesListCtrl->InsertColumn (ColumnVolumePath, LangString["VOLUME"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (500); + FavoritesListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (500); + + FavoritesListCtrl->SetMinSize (wxSize (400, -1)); + Gui->SetListCtrlHeight (FavoritesListCtrl, 15); + Gui->SetListCtrlColumnWidths (FavoritesListCtrl, colPermilles); + + Layout(); + Fit(); + Center(); + +#ifdef TC_MACOSX + // wxMac cannot insert items to wxListCtrl due to a bug + MoveUpButton->Show (false); + MoveDownButton->Show (false); +#endif + + vector fields (FavoritesListCtrl->GetColumnCount()); + size_t itemCount = 0; + foreach (shared_ptr favorite, Favorites) + { + fields[ColumnVolumePath] = favorite->Path; + fields[ColumnMountPoint] = favorite->MountPoint; + Gui->AppendToListCtrl (FavoritesListCtrl, fields, -1, favorite.get()); + + if (++itemCount > Favorites.size() - newItemCount) + { + FavoritesListCtrl->SetItemState (itemCount - 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + FavoritesListCtrl->EnsureVisible (itemCount - 1); + } + } + + UpdateButtons(); + FavoritesListCtrl->SetFocus(); + } + + void FavoriteVolumesDialog::OnMoveDownButtonClick (wxCommandEvent& event) + { + FreezeScope freeze (this); + foreach_reverse (long itemIndex, Gui->GetListCtrlSelectedItems (FavoritesListCtrl)) + { + if (itemIndex >= FavoritesListCtrl->GetItemCount() - 1) + break; + Gui->MoveListCtrlItem (FavoritesListCtrl, itemIndex, itemIndex + 1); + } + UpdateButtons(); + } + + void FavoriteVolumesDialog::OnMoveUpButtonClick (wxCommandEvent& event) + { + FreezeScope freeze (this); + foreach (long itemIndex, Gui->GetListCtrlSelectedItems (FavoritesListCtrl)) + { + if (itemIndex == 0) + break; + + Gui->MoveListCtrlItem (FavoritesListCtrl, itemIndex, itemIndex - 1); + } + UpdateButtons(); + } + + void FavoriteVolumesDialog::OnOKButtonClick (wxCommandEvent& event) + { + FavoriteVolumeList newFavorites; + + for (long i = 0; i < FavoritesListCtrl->GetItemCount(); i++) + { + newFavorites.push_back (make_shared ( + *reinterpret_cast (FavoritesListCtrl->GetItemData (i)))); + } + + Favorites = newFavorites; + EndModal (wxID_OK); + } + + void FavoriteVolumesDialog::OnRemoveAllButtonClick (wxCommandEvent& event) + { + FavoritesListCtrl->DeleteAllItems(); + UpdateButtons(); + } + + void FavoriteVolumesDialog::OnRemoveButtonClick (wxCommandEvent& event) + { + long offset = 0; + foreach (long item, Gui->GetListCtrlSelectedItems (FavoritesListCtrl)) + FavoritesListCtrl->DeleteItem (item - offset++); + } + + void FavoriteVolumesDialog::UpdateButtons () + { + bool selected = FavoritesListCtrl->GetSelectedItemCount() > 0; + + MoveDownButton->Enable (selected); + MoveUpButton->Enable (selected); + RemoveAllButton->Enable (FavoritesListCtrl->GetItemCount() > 0); + RemoveButton->Enable (selected); + } +} diff --git a/Main/Forms/FavoriteVolumesDialog.h b/Main/Forms/FavoriteVolumesDialog.h index f6406a6..b5ed2ab 100644 --- a/Main/Forms/FavoriteVolumesDialog.h +++ b/Main/Forms/FavoriteVolumesDialog.h @@ -1,45 +1,45 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_FavoriteVolumesDialog -#define TC_HEADER_Main_Forms_FavoriteVolumesDialog - -#include "Forms.h" -#include "Main/Main.h" -#include "Main/FavoriteVolume.h" - -namespace TrueCrypt -{ - class FavoriteVolumesDialog : public FavoriteVolumesDialogBase - { - public: - FavoriteVolumesDialog (wxWindow* parent, const FavoriteVolumeList &favorites, size_t newItemCount = 0); - - FavoriteVolumeList GetFavorites () const { return Favorites; } - - protected: - void OnListItemDeselected (wxListEvent& event) { UpdateButtons (); } - void OnListItemSelected (wxListEvent& event) { UpdateButtons (); } - void OnMoveUpButtonClick (wxCommandEvent& event); - void OnMoveDownButtonClick (wxCommandEvent& event); - void OnOKButtonClick (wxCommandEvent& event); - void OnRemoveAllButtonClick (wxCommandEvent& event); - void OnRemoveButtonClick (wxCommandEvent& event); - void UpdateButtons (); - - enum - { - ColumnVolumePath = 0, - ColumnMountPoint - }; - - FavoriteVolumeList Favorites; - }; -} - -#endif // TC_HEADER_Main_Forms_FavoriteVolumesDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_FavoriteVolumesDialog +#define TC_HEADER_Main_Forms_FavoriteVolumesDialog + +#include "Forms.h" +#include "Main/Main.h" +#include "Main/FavoriteVolume.h" + +namespace TrueCrypt +{ + class FavoriteVolumesDialog : public FavoriteVolumesDialogBase + { + public: + FavoriteVolumesDialog (wxWindow* parent, const FavoriteVolumeList &favorites, size_t newItemCount = 0); + + FavoriteVolumeList GetFavorites () const { return Favorites; } + + protected: + void OnListItemDeselected (wxListEvent& event) { UpdateButtons (); } + void OnListItemSelected (wxListEvent& event) { UpdateButtons (); } + void OnMoveUpButtonClick (wxCommandEvent& event); + void OnMoveDownButtonClick (wxCommandEvent& event); + void OnOKButtonClick (wxCommandEvent& event); + void OnRemoveAllButtonClick (wxCommandEvent& event); + void OnRemoveButtonClick (wxCommandEvent& event); + void UpdateButtons (); + + enum + { + ColumnVolumePath = 0, + ColumnMountPoint + }; + + FavoriteVolumeList Favorites; + }; +} + +#endif // TC_HEADER_Main_Forms_FavoriteVolumesDialog diff --git a/Main/Forms/Forms.cpp b/Main/Forms/Forms.cpp index 699ac9c..f584790 100644 --- a/Main/Forms/Forms.cpp +++ b/Main/Forms/Forms.cpp @@ -1,3076 +1,2989 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder -// http://www.wxformbuilder.org/ -// -// PLEASE DO "NOT" EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#include "System.h" - -#include "Forms.h" - -/////////////////////////////////////////////////////////////////////////// -using namespace TrueCrypt; - -MainFrameBase::MainFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( -1,496 ), wxDefaultSize ); - - MainMenuBar = new wxMenuBar( 0 ); - VolumesMenu = new wxMenu(); - MountVolumeMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Mount Volume") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( MountVolumeMenuItem ); - - wxMenuItem* AutoMountDevicesMenuItem; - AutoMountDevicesMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Auto-Mount All Device-Hosted Volumes") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( AutoMountDevicesMenuItem ); - - VolumesMenu->AppendSeparator(); - - DismountVolumeMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Dismount Volume") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( DismountVolumeMenuItem ); - - DismountAllMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Dismount All Mounted Volumes") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( DismountAllMenuItem ); - - VolumesMenu->AppendSeparator(); - - wxMenuItem* CreateNewVolumeMenuItem; - CreateNewVolumeMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Create New Volume...") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( CreateNewVolumeMenuItem ); - - wxMenuItem* ChangePasswordMenuItem; - ChangePasswordMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Change Volume Password...") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( ChangePasswordMenuItem ); - - wxMenuItem* ChangePkcs5PrfMenuItem; - ChangePkcs5PrfMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Change Header Key Derivation Algorithm...") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( ChangePkcs5PrfMenuItem ); - - VolumesMenu->AppendSeparator(); - - VolumePropertiesMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Volume Properties...") ) , wxEmptyString, wxITEM_NORMAL ); - VolumesMenu->Append( VolumePropertiesMenuItem ); - - MainMenuBar->Append( VolumesMenu, _("&Volumes") ); - - KeyfilesMenu = new wxMenu(); - wxMenuItem* ChangeKeyfilesMenuItem; - ChangeKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Add/Remove Keyfiles to/from Volume...") ) , wxEmptyString, wxITEM_NORMAL ); - KeyfilesMenu->Append( ChangeKeyfilesMenuItem ); - - wxMenuItem* RemoveKeyfilesMenuItem; - RemoveKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Remove All Keyfiles from Volume...") ) , wxEmptyString, wxITEM_NORMAL ); - KeyfilesMenu->Append( RemoveKeyfilesMenuItem ); - - KeyfilesMenu->AppendSeparator(); - - wxMenuItem* CreateKeyfileMenuItem; - CreateKeyfileMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Generate Random Keyfile...") ) , wxEmptyString, wxITEM_NORMAL ); - KeyfilesMenu->Append( CreateKeyfileMenuItem ); - - KeyfilesMenu->AppendSeparator(); - - wxMenuItem* ManageSecurityTokenKeyfilesMenuItem; - ManageSecurityTokenKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Manage Security Token Keyfiles...") ) , wxEmptyString, wxITEM_NORMAL ); - KeyfilesMenu->Append( ManageSecurityTokenKeyfilesMenuItem ); - - wxMenuItem* CloseAllSecurityTokenSessionsMenuItem; - CloseAllSecurityTokenSessionsMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Close All Security Token Sessions") ) , wxEmptyString, wxITEM_NORMAL ); - KeyfilesMenu->Append( CloseAllSecurityTokenSessionsMenuItem ); - - KeyfilesMenu->AppendSeparator(); - - wxMenuItem* SetDefaultKeyfilesMenuItem; - SetDefaultKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Set Default Keyfiles/Paths...") ) , wxEmptyString, wxITEM_NORMAL ); - KeyfilesMenu->Append( SetDefaultKeyfilesMenuItem ); - - MainMenuBar->Append( KeyfilesMenu, _("&Keyfiles") ); - - FavoritesMenu = new wxMenu(); - AddToFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Add Selected Volume...") ) , wxEmptyString, wxITEM_NORMAL ); - FavoritesMenu->Append( AddToFavoritesMenuItem ); - - AddAllMountedToFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Add All Mounted Volumes...") ) , wxEmptyString, wxITEM_NORMAL ); - FavoritesMenu->Append( AddAllMountedToFavoritesMenuItem ); - - wxMenuItem* OrganizeFavoritesMenuItem; - OrganizeFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Organize Favorite Volumes...") ) , wxEmptyString, wxITEM_NORMAL ); - FavoritesMenu->Append( OrganizeFavoritesMenuItem ); - - FavoritesMenu->AppendSeparator(); - - wxMenuItem* MountAllFavoritesMenuItem; - MountAllFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Mount All Favorite Volumes") ) , wxEmptyString, wxITEM_NORMAL ); - FavoritesMenu->Append( MountAllFavoritesMenuItem ); - - FavoritesMenu->AppendSeparator(); - - MainMenuBar->Append( FavoritesMenu, _("&Favorites") ); - - ToolsMenu = new wxMenu(); - wxMenuItem* EncryptionTestMenuItem; - EncryptionTestMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Test Vectors...") ) , wxEmptyString, wxITEM_NORMAL ); - ToolsMenu->Append( EncryptionTestMenuItem ); - - ToolsMenu->AppendSeparator(); - - wxMenuItem* VolumeCreationWizardMenuItem; - VolumeCreationWizardMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Volume Creation Wizard") ) , wxEmptyString, wxITEM_NORMAL ); - ToolsMenu->Append( VolumeCreationWizardMenuItem ); - - TravelerDiskWizardMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Traveller Disk Wizard...") ) , wxEmptyString, wxITEM_NORMAL ); - ToolsMenu->Append( TravelerDiskWizardMenuItem ); - - ToolsMenu->AppendSeparator(); - - BackupVolumeHeadersMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Backup Volume Header...") ) , wxEmptyString, wxITEM_NORMAL ); - ToolsMenu->Append( BackupVolumeHeadersMenuItem ); - - RestoreVolumeHeaderMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Restore Volume Header...") ) , wxEmptyString, wxITEM_NORMAL ); - ToolsMenu->Append( RestoreVolumeHeaderMenuItem ); - - ToolsMenu->AppendSeparator(); - - WipeCachedPasswordsMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Wipe Cached Passwords") ) , wxEmptyString, wxITEM_NORMAL ); - ToolsMenu->Append( WipeCachedPasswordsMenuItem ); - - MainMenuBar->Append( ToolsMenu, _("T&ools") ); - - SettingsMenu = new wxMenu(); - HotkeysMenuItem = new wxMenuItem( SettingsMenu, wxID_ANY, wxString( _("Hotkeys...") ) , wxEmptyString, wxITEM_NORMAL ); - SettingsMenu->Append( HotkeysMenuItem ); - - wxMenuItem* DefaultKeyfilesMenuItem; - DefaultKeyfilesMenuItem = new wxMenuItem( SettingsMenu, wxID_ANY, wxString( _("Default Keyfiles...") ) , wxEmptyString, wxITEM_NORMAL ); - SettingsMenu->Append( DefaultKeyfilesMenuItem ); - - wxMenuItem* SecurityTokenPreferencesMenuItem; - SecurityTokenPreferencesMenuItem = new wxMenuItem( SettingsMenu, wxID_ANY, wxString( _("Security Tokens...") ) , wxEmptyString, wxITEM_NORMAL ); - SettingsMenu->Append( SecurityTokenPreferencesMenuItem ); - - SettingsMenu->AppendSeparator(); - - PreferencesMenuItem = new wxMenuItem( SettingsMenu, wxID_PREFERENCES, wxString( _("&Preferences...") ) , wxEmptyString, wxITEM_NORMAL ); - SettingsMenu->Append( PreferencesMenuItem ); - - MainMenuBar->Append( SettingsMenu, _("Settin&gs") ); - - HelpMenu = new wxMenu(); - wxMenuItem* UserGuideMenuItem; - UserGuideMenuItem = new wxMenuItem( HelpMenu, wxID_HELP, wxString( _("User's Guide") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( UserGuideMenuItem ); - - wxMenuItem* OnlineHelpMenuItem; - OnlineHelpMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Online Help") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( OnlineHelpMenuItem ); - - wxMenuItem* BeginnersTutorialMenuItem; - BeginnersTutorialMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Beginner's Tutorial") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( BeginnersTutorialMenuItem ); - - wxMenuItem* FaqMenuItem; - FaqMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Frequently Asked Questions") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( FaqMenuItem ); - - HelpMenu->AppendSeparator(); - - wxMenuItem* WebsiteMenuItem; - WebsiteMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("TrueCrypt Website") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( WebsiteMenuItem ); - - wxMenuItem* DownloadsMenuItem; - DownloadsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Downloads") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( DownloadsMenuItem ); - - wxMenuItem* NewsMenuItem; - NewsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("News") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( NewsMenuItem ); - - HelpMenu->AppendSeparator(); - - wxMenuItem* VersionHistoryMenuItem; - VersionHistoryMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Version History") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( VersionHistoryMenuItem ); - - wxMenuItem* LegalNoticesMenuItem; - LegalNoticesMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Legal Notices") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( LegalNoticesMenuItem ); - - HelpMenu->AppendSeparator(); - - wxMenuItem* ReportBugMenuItem; - ReportBugMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Report a Bug...") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( ReportBugMenuItem ); - - wxMenuItem* ForumsMenuItem; - ForumsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Forums") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( ForumsMenuItem ); - - wxMenuItem* ContactMenuItem; - ContactMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Contact...") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( ContactMenuItem ); - - HelpMenu->AppendSeparator(); - - wxMenuItem* DonationsMenuItem; - DonationsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Donations...") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( DonationsMenuItem ); - - HelpMenu->AppendSeparator(); - - wxMenuItem* AboutMenuItem; - AboutMenuItem = new wxMenuItem( HelpMenu, wxID_ABOUT, wxString( _("About...") ) , wxEmptyString, wxITEM_NORMAL ); - HelpMenu->Append( AboutMenuItem ); - - MainMenuBar->Append( HelpMenu, _("&Help") ); - - this->SetMenuBar( MainMenuBar ); - - wxBoxSizer* bSizer1; - bSizer1 = new wxBoxSizer( wxVERTICAL ); - - MainPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer2; - bSizer2 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer48; - bSizer48 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer1; - sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - SlotListCtrl = new wxListCtrl( MainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxSUNKEN_BORDER ); - SlotListCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) ); - - sbSizer1->Add( SlotListCtrl, 1, wxALL|wxEXPAND, 5 ); - - bSizer48->Add( sbSizer1, 1, wxEXPAND, 5 ); - - LowStaticBoxSizer = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - HigherButtonSizer = new wxBoxSizer( wxVERTICAL ); - - LowStaticBoxSizer->Add( HigherButtonSizer, 0, wxEXPAND|wxTOP, 2 ); - - wxGridSizer* gSizer1; - gSizer1 = new wxGridSizer( 1, 3, 0, 0 ); - - wxBoxSizer* bSizer17; - bSizer17 = new wxBoxSizer( wxVERTICAL ); - - bSizer17->SetMinSize( wxSize( 138,34 ) ); - CreateVolumeButton = new wxButton( MainPanel, wxID_ANY, _("&Create Volume"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer17->Add( CreateVolumeButton, 1, wxALL|wxEXPAND, 5 ); - - gSizer1->Add( bSizer17, 0, 0, 5 ); - - wxBoxSizer* bSizer18; - bSizer18 = new wxBoxSizer( wxVERTICAL ); - - bSizer18->SetMinSize( wxSize( 138,34 ) ); - VolumePropertiesButton = new wxButton( MainPanel, wxID_ANY, _("&Volume Properties..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer18->Add( VolumePropertiesButton, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - gSizer1->Add( bSizer18, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer19; - bSizer19 = new wxBoxSizer( wxVERTICAL ); - - bSizer19->SetMinSize( wxSize( 138,34 ) ); - WipeCacheButton = new wxButton( MainPanel, wxID_ANY, _("&Wipe Cache"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer19->Add( WipeCacheButton, 1, wxALL|wxALIGN_RIGHT|wxEXPAND, 5 ); - - gSizer1->Add( bSizer19, 0, wxALIGN_RIGHT, 5 ); - - LowStaticBoxSizer->Add( gSizer1, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - - LowStaticBoxSizer->Add( 0, 0, 0, 0, 5 ); - - VolumeStaticBoxSizer = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, _("Volume") ), wxVERTICAL ); - - VolumeGridBagSizer = new wxGridBagSizer( 0, 0 ); - VolumeGridBagSizer->AddGrowableCol( 1 ); - VolumeGridBagSizer->AddGrowableRow( 0 ); - VolumeGridBagSizer->SetFlexibleDirection( wxBOTH ); - VolumeGridBagSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - LogoBitmap = new wxStaticBitmap( MainPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER ); - LogoBitmap->SetMinSize( wxSize( 42,52 ) ); - - VolumeGridBagSizer->Add( LogoBitmap, wxGBPosition( 0, 0 ), wxGBSpan( 2, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - VolumePathComboBox = new wxComboBox( MainPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN ); - VolumeGridBagSizer->Add( VolumePathComboBox, wxGBPosition( 0, 1 ), wxGBSpan( 1, 2 ), wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer191; - bSizer191 = new wxBoxSizer( wxVERTICAL ); - - bSizer191->SetMinSize( wxSize( 138,34 ) ); - SelectFileButton = new wxButton( MainPanel, wxID_ANY, _("Select &File..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer191->Add( SelectFileButton, 1, wxALL|wxEXPAND, 5 ); - - VolumeGridBagSizer->Add( bSizer191, wxGBPosition( 0, 3 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 ); - - NoHistoryCheckBox = new wxCheckBox( MainPanel, wxID_ANY, _("&Never save history"), wxDefaultPosition, wxDefaultSize, 0 ); - - VolumeGridBagSizer->Add( NoHistoryCheckBox, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer20; - bSizer20 = new wxBoxSizer( wxVERTICAL ); - - bSizer20->SetMinSize( wxSize( 138,34 ) ); - VolumeToolsButton = new wxButton( MainPanel, wxID_ANY, _("Volume &Tools..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer20->Add( VolumeToolsButton, 1, wxALL|wxEXPAND, 5 ); - - VolumeGridBagSizer->Add( bSizer20, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_RIGHT, 5 ); - - wxBoxSizer* bSizer21; - bSizer21 = new wxBoxSizer( wxVERTICAL ); - - bSizer21->SetMinSize( wxSize( 138,34 ) ); - SelectDeviceButton = new wxButton( MainPanel, wxID_ANY, _("Select D&evice..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer21->Add( SelectDeviceButton, 1, wxEXPAND|wxALL, 5 ); - - VolumeGridBagSizer->Add( bSizer21, wxGBPosition( 1, 3 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 ); - - VolumeStaticBoxSizer->Add( VolumeGridBagSizer, 1, wxEXPAND|wxALL, 4 ); - - LowStaticBoxSizer->Add( VolumeStaticBoxSizer, 1, wxEXPAND, 5 ); - - - LowStaticBoxSizer->Add( 0, 0, 0, 0, 5 ); - - wxGridSizer* gSizer2; - gSizer2 = new wxGridSizer( 1, 4, 0, 0 ); - - wxStaticBoxSizer* sbSizer4; - sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - sbSizer4->SetMinSize( wxSize( 139,-1 ) ); - VolumeButton = new wxButton( MainPanel, wxID_ANY, _("&Mount"), wxDefaultPosition, wxDefaultSize, 0 ); - VolumeButton->SetDefault(); - VolumeButton->SetMinSize( wxSize( -1,32 ) ); - - sbSizer4->Add( VolumeButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); - - gSizer2->Add( sbSizer4, 1, wxEXPAND, 0 ); - - wxStaticBoxSizer* sbSizer41; - sbSizer41 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - MountAllDevicesButton = new wxButton( MainPanel, wxID_ANY, _("&Auto-Mount Devices"), wxDefaultPosition, wxDefaultSize, 0 ); - MountAllDevicesButton->SetMinSize( wxSize( -1,32 ) ); - - sbSizer41->Add( MountAllDevicesButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); - - gSizer2->Add( sbSizer41, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer42; - sbSizer42 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - DismountAllButton = new wxButton( MainPanel, wxID_ANY, _("Di&smount All"), wxDefaultPosition, wxDefaultSize, 0 ); - DismountAllButton->SetMinSize( wxSize( -1,32 ) ); - - sbSizer42->Add( DismountAllButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); - - gSizer2->Add( sbSizer42, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer43; - sbSizer43 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - ExitButton = new wxButton( MainPanel, wxID_ANY, _("E&xit"), wxDefaultPosition, wxDefaultSize, 0 ); - ExitButton->SetMinSize( wxSize( -1,32 ) ); - - sbSizer43->Add( ExitButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); - - gSizer2->Add( sbSizer43, 1, wxALIGN_RIGHT|wxEXPAND, 5 ); - - LowStaticBoxSizer->Add( gSizer2, 0, wxEXPAND, 5 ); - - bSizer48->Add( LowStaticBoxSizer, 0, wxEXPAND, 5 ); - - bSizer2->Add( bSizer48, 1, wxEXPAND, 5 ); - - MainPanel->SetSizer( bSizer2 ); - MainPanel->Layout(); - bSizer2->Fit( MainPanel ); - bSizer1->Add( MainPanel, 1, wxEXPAND, 0 ); - - this->SetSizer( bSizer1 ); - this->Layout(); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_ACTIVATE, wxActivateEventHandler( MainFrameBase::OnActivate ) ); - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainFrameBase::OnClose ) ); - this->Connect( MountVolumeMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountVolumeMenuItemSelected ) ); - this->Connect( AutoMountDevicesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ) ); - this->Connect( DismountVolumeMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountVolumeMenuItemSelected ) ); - this->Connect( DismountAllMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ) ); - this->Connect( CreateNewVolumeMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); - this->Connect( ChangePasswordMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePasswordMenuItemSelected ) ); - this->Connect( ChangePkcs5PrfMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePkcs5PrfMenuItemSelected ) ); - this->Connect( VolumePropertiesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ) ); - this->Connect( ChangeKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangeKeyfilesMenuItemSelected ) ); - this->Connect( RemoveKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRemoveKeyfilesMenuItemSelected ) ); - this->Connect( CreateKeyfileMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateKeyfileMenuItemSelected ) ); - this->Connect( ManageSecurityTokenKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnManageSecurityTokenKeyfilesMenuItemSelected ) ); - this->Connect( CloseAllSecurityTokenSessionsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCloseAllSecurityTokenSessionsMenuItemSelected ) ); - this->Connect( SetDefaultKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); - this->Connect( AddToFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddToFavoritesMenuItemSelected ) ); - this->Connect( AddAllMountedToFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddAllMountedToFavoritesMenuItemSelected ) ); - this->Connect( OrganizeFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOrganizeFavoritesMenuItemSelected ) ); - this->Connect( MountAllFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllFavoritesMenuItemSelected ) ); - this->Connect( EncryptionTestMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnEncryptionTestMenuItemSelected ) ); - this->Connect( VolumeCreationWizardMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); - this->Connect( TravelerDiskWizardMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnTravelerDiskWizardMenuItemSelected ) ); - this->Connect( BackupVolumeHeadersMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBackupVolumeHeadersMenuItemSelected ) ); - this->Connect( RestoreVolumeHeaderMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRestoreVolumeHeaderMenuItemSelected ) ); - this->Connect( WipeCachedPasswordsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ) ); - this->Connect( HotkeysMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnHotkeysMenuItemSelected ) ); - this->Connect( DefaultKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); - this->Connect( SecurityTokenPreferencesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnSecurityTokenPreferencesMenuItemSelected ) ); - this->Connect( PreferencesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnPreferencesMenuItemSelected ) ); - this->Connect( UserGuideMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnUserGuideMenuItemSelected ) ); - this->Connect( OnlineHelpMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOnlineHelpMenuItemSelected ) ); - this->Connect( BeginnersTutorialMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBeginnersTutorialMenuItemSelected ) ); - this->Connect( FaqMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnFaqMenuItemSelected ) ); - this->Connect( WebsiteMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWebsiteMenuItemSelected ) ); - this->Connect( DownloadsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDownloadsMenuItemSelected ) ); - this->Connect( NewsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnNewsMenuItemSelected ) ); - this->Connect( VersionHistoryMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVersionHistoryMenuItemSelected ) ); - this->Connect( LegalNoticesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnLegalNoticesMenuItemSelected ) ); - this->Connect( ReportBugMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnReportBugMenuItemSelected ) ); - this->Connect( ForumsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnForumsMenuItemSelected ) ); - this->Connect( ContactMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnContactMenuItemSelected ) ); - this->Connect( DonationsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDonationsMenuItemSelected ) ); - this->Connect( AboutMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAboutMenuItemSelected ) ); - SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( MainFrameBase::OnListItemActivated ), NULL, this ); - SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( MainFrameBase::OnListItemDeselected ), NULL, this ); - SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( MainFrameBase::OnListItemRightClick ), NULL, this ); - SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( MainFrameBase::OnListItemSelected ), NULL, this ); - CreateVolumeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ), NULL, this ); - VolumePropertiesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ), NULL, this ); - WipeCacheButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ), NULL, this ); - LogoBitmap->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( MainFrameBase::OnLogoBitmapClick ), NULL, this ); - SelectFileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectFileButtonClick ), NULL, this ); - NoHistoryCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrameBase::OnNoHistoryCheckBoxClick ), NULL, this ); - VolumeToolsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeToolsButtonClick ), NULL, this ); - SelectDeviceButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectDeviceButtonClick ), NULL, this ); - VolumeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeButtonClick ), NULL, this ); - MountAllDevicesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ), NULL, this ); - DismountAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ), NULL, this ); - ExitButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnExitButtonClick ), NULL, this ); -} - -MainFrameBase::~MainFrameBase() -{ - // Disconnect Events - this->Disconnect( wxEVT_ACTIVATE, wxActivateEventHandler( MainFrameBase::OnActivate ) ); - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainFrameBase::OnClose ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountVolumeMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountVolumeMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePasswordMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePkcs5PrfMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangeKeyfilesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRemoveKeyfilesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateKeyfileMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnManageSecurityTokenKeyfilesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCloseAllSecurityTokenSessionsMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddToFavoritesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddAllMountedToFavoritesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOrganizeFavoritesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllFavoritesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnEncryptionTestMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnTravelerDiskWizardMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBackupVolumeHeadersMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRestoreVolumeHeaderMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnHotkeysMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnSecurityTokenPreferencesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnPreferencesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnUserGuideMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOnlineHelpMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBeginnersTutorialMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnFaqMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWebsiteMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDownloadsMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnNewsMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVersionHistoryMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnLegalNoticesMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnReportBugMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnForumsMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnContactMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDonationsMenuItemSelected ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAboutMenuItemSelected ) ); - SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( MainFrameBase::OnListItemActivated ), NULL, this ); - SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( MainFrameBase::OnListItemDeselected ), NULL, this ); - SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( MainFrameBase::OnListItemRightClick ), NULL, this ); - SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( MainFrameBase::OnListItemSelected ), NULL, this ); - CreateVolumeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ), NULL, this ); - VolumePropertiesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ), NULL, this ); - WipeCacheButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ), NULL, this ); - LogoBitmap->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( MainFrameBase::OnLogoBitmapClick ), NULL, this ); - SelectFileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectFileButtonClick ), NULL, this ); - NoHistoryCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrameBase::OnNoHistoryCheckBoxClick ), NULL, this ); - VolumeToolsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeToolsButtonClick ), NULL, this ); - SelectDeviceButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectDeviceButtonClick ), NULL, this ); - VolumeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeButtonClick ), NULL, this ); - MountAllDevicesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ), NULL, this ); - DismountAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ), NULL, this ); - ExitButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnExitButtonClick ), NULL, this ); -} - -WizardFrameBase::WizardFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer92; - bSizer92 = new wxBoxSizer( wxVERTICAL ); - - MainPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer63; - bSizer63 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer64; - bSizer64 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer27; - sbSizer27 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxHORIZONTAL ); - - WizardBitmap = new wxStaticBitmap( MainPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer27->Add( WizardBitmap, 0, wxALL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer66; - bSizer66 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer126; - bSizer126 = new wxBoxSizer( wxHORIZONTAL ); - - PageTitleStaticText = new wxStaticText( MainPanel, wxID_ANY, _("Page Title"), wxDefaultPosition, wxDefaultSize, 0 ); - PageTitleStaticText->Wrap( -1 ); - PageTitleStaticText->SetFont( wxFont( 16, 70, 90, 90, false, wxT("Times New Roman") ) ); - - bSizer126->Add( PageTitleStaticText, 0, wxALL, 5 ); - - bSizer66->Add( bSizer126, 0, wxLEFT, 5 ); - - PageSizer = new wxBoxSizer( wxVERTICAL ); - - bSizer66->Add( PageSizer, 1, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - sbSizer27->Add( bSizer66, 1, wxEXPAND|wxLEFT, 5 ); - - bSizer64->Add( sbSizer27, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer70; - bSizer70 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer70->Add( 0, 0, 1, wxEXPAND, 5 ); - - HelpButton = new wxButton( MainPanel, wxID_HELP, _("&Help"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer70->Add( HelpButton, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer70->Add( 0, 0, 0, wxLEFT|wxALIGN_RIGHT, 5 ); - - PreviousButton = new wxButton( MainPanel, wxID_ANY, _("< &Prev"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer70->Add( PreviousButton, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - NextButton = new wxButton( MainPanel, wxID_ANY, _("&Next >"), wxDefaultPosition, wxDefaultSize, 0|wxWANTS_CHARS ); - NextButton->SetDefault(); - bSizer70->Add( NextButton, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer70->Add( 0, 0, 0, wxLEFT|wxALIGN_RIGHT, 5 ); - - CancelButton = new wxButton( MainPanel, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer70->Add( CancelButton, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer64->Add( bSizer70, 0, wxEXPAND|wxALIGN_RIGHT|wxALL, 5 ); - - bSizer63->Add( bSizer64, 1, wxEXPAND, 5 ); - - MainPanel->SetSizer( bSizer63 ); - MainPanel->Layout(); - bSizer63->Fit( MainPanel ); - bSizer92->Add( MainPanel, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer92 ); - this->Layout(); - bSizer92->Fit( this ); - - // Connect Events - this->Connect( wxEVT_ACTIVATE, wxActivateEventHandler( WizardFrameBase::OnActivate ) ); - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WizardFrameBase::OnClose ) ); - MainPanel->Connect( wxEVT_MOTION, wxMouseEventHandler( WizardFrameBase::OnMouseMotion ), NULL, this ); - HelpButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnHelpButtonClick ), NULL, this ); - PreviousButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnPreviousButtonClick ), NULL, this ); - NextButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnNextButtonClick ), NULL, this ); - CancelButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnCancelButtonClick ), NULL, this ); -} - -WizardFrameBase::~WizardFrameBase() -{ - // Disconnect Events - this->Disconnect( wxEVT_ACTIVATE, wxActivateEventHandler( WizardFrameBase::OnActivate ) ); - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WizardFrameBase::OnClose ) ); - MainPanel->Disconnect( wxEVT_MOTION, wxMouseEventHandler( WizardFrameBase::OnMouseMotion ), NULL, this ); - HelpButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnHelpButtonClick ), NULL, this ); - PreviousButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnPreviousButtonClick ), NULL, this ); - NextButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnNextButtonClick ), NULL, this ); - CancelButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnCancelButtonClick ), NULL, this ); -} - -AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer116; - bSizer116 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer117; - bSizer117 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer120; - bSizer120 = new wxBoxSizer( wxVERTICAL ); - - bSizer120->SetMinSize( wxSize( -1,78 ) ); - m_panel14 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel14->SetBackgroundColour( wxColour( 10, 108, 206 ) ); - - wxBoxSizer* bSizer121; - bSizer121 = new wxBoxSizer( wxVERTICAL ); - - - bSizer121->Add( 0, 0, 1, wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer122; - bSizer122 = new wxBoxSizer( wxVERTICAL ); - - LogoBitmap = new wxStaticBitmap( m_panel14, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer122->Add( LogoBitmap, 0, wxALL, 10 ); - - bSizer121->Add( bSizer122, 0, wxEXPAND|wxLEFT, 8 ); - - m_panel14->SetSizer( bSizer121 ); - m_panel14->Layout(); - bSizer121->Fit( m_panel14 ); - bSizer120->Add( m_panel14, 1, wxEXPAND, 5 ); - - bSizer117->Add( bSizer120, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer118; - bSizer118 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer123; - bSizer123 = new wxBoxSizer( wxVERTICAL ); - - VersionStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - VersionStaticText->Wrap( -1 ); - VersionStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer123->Add( VersionStaticText, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - - bSizer123->Add( 0, 0, 0, wxTOP, 3 ); - - CopyrightStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - CopyrightStaticText->Wrap( -1 ); - bSizer123->Add( CopyrightStaticText, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer123->Add( 0, 0, 0, wxTOP, 3 ); - - WebsiteHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, wxEmptyString, wxT("."), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - - WebsiteHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - WebsiteHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - WebsiteHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - bSizer123->Add( WebsiteHyperlink, 0, wxALL, 5 ); - - bSizer118->Add( bSizer123, 1, wxEXPAND|wxLEFT, 5 ); - - bSizer117->Add( bSizer118, 1, wxALL|wxEXPAND, 15 ); - - m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer117->Add( m_staticline3, 0, wxEXPAND|wxBOTTOM, 5 ); - - CreditsTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxSUNKEN_BORDER ); - bSizer117->Add( CreditsTextCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); - - - bSizer117->Add( 0, 0, 0, wxTOP, 5 ); - - m_staticline4 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer117->Add( m_staticline4, 0, wxEXPAND|wxTOP|wxBOTTOM, 3 ); - - m_staticline5 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer117->Add( m_staticline5, 0, wxEXPAND|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer119; - bSizer119 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer119->Add( 0, 0, 1, wxEXPAND|wxALL, 5 ); - - DonationsButton = new wxButton( this, wxID_ANY, _("Donations..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer119->Add( DonationsButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - wxButton* OKButton; - OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - OKButton->SetDefault(); - bSizer119->Add( OKButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer119->Add( 0, 0, 0, wxLEFT, 5 ); - - bSizer117->Add( bSizer119, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 6 ); - - bSizer116->Add( bSizer117, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer116 ); - this->Layout(); - bSizer116->Fit( this ); - - // Connect Events - WebsiteHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( AboutDialogBase::OnWebsiteHyperlinkClick ), NULL, this ); - DonationsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDialogBase::OnDonationsButtonClick ), NULL, this ); -} - -AboutDialogBase::~AboutDialogBase() -{ - // Disconnect Events - WebsiteHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( AboutDialogBase::OnWebsiteHyperlinkClick ), NULL, this ); - DonationsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDialogBase::OnDonationsButtonClick ), NULL, this ); -} - -ChangePasswordDialogBase::ChangePasswordDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); - - wxBoxSizer* bSizer30; - bSizer30 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer31; - bSizer31 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer32; - bSizer32 = new wxBoxSizer( wxVERTICAL ); - - CurrentSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Current") ), wxVERTICAL ); - - CurrentPasswordPanelSizer = new wxBoxSizer( wxVERTICAL ); - - CurrentSizer->Add( CurrentPasswordPanelSizer, 0, wxALIGN_RIGHT, 5 ); - - bSizer32->Add( CurrentSizer, 0, wxEXPAND, 5 ); - - NewSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("New") ), wxVERTICAL ); - - NewPasswordPanelSizer = new wxBoxSizer( wxVERTICAL ); - - NewSizer->Add( NewPasswordPanelSizer, 0, wxALIGN_RIGHT, 5 ); - - bSizer32->Add( NewSizer, 0, wxTOP|wxEXPAND, 5 ); - - bSizer31->Add( bSizer32, 1, wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer33; - bSizer33 = new wxBoxSizer( wxVERTICAL ); - - OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - OKButton->SetDefault(); - bSizer33->Add( OKButton, 0, wxALL|wxEXPAND, 5 ); - - CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer33->Add( CancelButton, 0, wxALL|wxEXPAND, 5 ); - - bSizer31->Add( bSizer33, 0, 0, 5 ); - - bSizer30->Add( bSizer31, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer30 ); - this->Layout(); - bSizer30->Fit( this ); - - // Connect Events - OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ChangePasswordDialogBase::OnOKButtonClick ), NULL, this ); -} - -ChangePasswordDialogBase::~ChangePasswordDialogBase() -{ - // Disconnect Events - OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ChangePasswordDialogBase::OnOKButtonClick ), NULL, this ); -} - -DeviceSelectionDialogBase::DeviceSelectionDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); - - wxBoxSizer* bSizer3; - bSizer3 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer4; - bSizer4 = new wxBoxSizer( wxVERTICAL ); - - DeviceListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxSUNKEN_BORDER ); - bSizer4->Add( DeviceListCtrl, 1, wxALL|wxEXPAND, 5 ); - - StdButtons = new wxStdDialogButtonSizer(); - StdButtonsOK = new wxButton( this, wxID_OK ); - StdButtons->AddButton( StdButtonsOK ); - StdButtonsCancel = new wxButton( this, wxID_CANCEL ); - StdButtons->AddButton( StdButtonsCancel ); - StdButtons->Realize(); - bSizer4->Add( StdButtons, 0, wxEXPAND|wxALL, 5 ); - - bSizer3->Add( bSizer4, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer3 ); - this->Layout(); - bSizer3->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - DeviceListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemActivated ), NULL, this ); - DeviceListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemDeselected ), NULL, this ); - DeviceListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemSelected ), NULL, this ); -} - -DeviceSelectionDialogBase::~DeviceSelectionDialogBase() -{ - // Disconnect Events - DeviceListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemActivated ), NULL, this ); - DeviceListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemDeselected ), NULL, this ); - DeviceListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemSelected ), NULL, this ); -} - -EncryptionTestDialogBase::EncryptionTestDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer132; - bSizer132 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer133; - bSizer133 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* m_staticText41; - m_staticText41 = new wxStaticText( this, wxID_ANY, _("Encryption algorithm:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText41->Wrap( -1 ); - bSizer134->Add( m_staticText41, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - wxArrayString EncryptionAlgorithmChoiceChoices; - EncryptionAlgorithmChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, EncryptionAlgorithmChoiceChoices, 0 ); - EncryptionAlgorithmChoice->SetSelection( 0 ); - bSizer134->Add( EncryptionAlgorithmChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - XtsModeCheckBox = new wxCheckBox( this, wxID_ANY, _("XTS mode"), wxDefaultPosition, wxDefaultSize, 0 ); - XtsModeCheckBox->SetValue(true); - - bSizer134->Add( XtsModeCheckBox, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer133->Add( bSizer134, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxStaticBoxSizer* sbSizer38; - sbSizer38 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Key (hexadecimal)") ), wxVERTICAL ); - - KeyTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - KeyTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); - - sbSizer38->Add( KeyTextCtrl, 1, wxALL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer135; - bSizer135 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* m_staticText43; - m_staticText43 = new wxStaticText( this, wxID_ANY, _("Key size:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText43->Wrap( -1 ); - bSizer135->Add( m_staticText43, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - KeySizeStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - KeySizeStaticText->Wrap( -1 ); - bSizer135->Add( KeySizeStaticText, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); - - sbSizer38->Add( bSizer135, 0, wxEXPAND, 5 ); - - bSizer133->Add( sbSizer38, 0, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer39; - sbSizer39 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("XTS mode") ), wxVERTICAL ); - - wxStaticText* m_staticText45; - m_staticText45 = new wxStaticText( this, wxID_ANY, _("Secondary key (hexadecimal)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText45->Wrap( -1 ); - sbSizer39->Add( m_staticText45, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - SecondaryKeyTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - SecondaryKeyTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); - - sbSizer39->Add( SecondaryKeyTextCtrl, 0, wxEXPAND|wxALL, 5 ); - - wxStaticText* m_staticText46; - m_staticText46 = new wxStaticText( this, wxID_ANY, _("Data unit number (64-bit, data unit size is 512 bytes)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText46->Wrap( -1 ); - sbSizer39->Add( m_staticText46, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - DataUnitNumberTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer39->Add( DataUnitNumberTextCtrl, 0, wxALL, 5 ); - - wxStaticText* m_staticText47; - m_staticText47 = new wxStaticText( this, wxID_ANY, _("Block number:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText47->Wrap( -1 ); - sbSizer39->Add( m_staticText47, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - BlockNumberTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer39->Add( BlockNumberTextCtrl, 0, wxALL, 5 ); - - bSizer133->Add( sbSizer39, 1, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer40; - sbSizer40 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Plaintext (hexadecimal)") ), wxVERTICAL ); - - PlainTextTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - PlainTextTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); - - sbSizer40->Add( PlainTextTextCtrl, 0, wxALL|wxEXPAND, 5 ); - - bSizer133->Add( sbSizer40, 0, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer41; - sbSizer41 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Ciphertext (hexadecimal)") ), wxVERTICAL ); - - CipherTextTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - CipherTextTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); - - sbSizer41->Add( CipherTextTextCtrl, 0, wxALL|wxEXPAND, 5 ); - - bSizer133->Add( sbSizer41, 0, wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer136; - bSizer136 = new wxBoxSizer( wxHORIZONTAL ); - - EncryptButton = new wxButton( this, wxID_ANY, _("&Encrypt"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer136->Add( EncryptButton, 0, wxALL, 5 ); - - DecryptButton = new wxButton( this, wxID_ANY, _("&Decrypt"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer136->Add( DecryptButton, 0, wxALL, 5 ); - - AutoTestAllButton = new wxButton( this, wxID_ANY, _("&Auto-Test All"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer136->Add( AutoTestAllButton, 0, wxALL, 5 ); - - ResetButton = new wxButton( this, wxID_ANY, _("&Reset"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer136->Add( ResetButton, 0, wxALL, 5 ); - - CloseButton = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer136->Add( CloseButton, 0, wxALL, 5 ); - - bSizer133->Add( bSizer136, 0, wxEXPAND, 5 ); - - bSizer132->Add( bSizer133, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer132 ); - this->Layout(); - bSizer132->Fit( this ); - - // Connect Events - EncryptionAlgorithmChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptionAlgorithmSelected ), NULL, this ); - XtsModeCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnXtsModeCheckBoxClick ), NULL, this ); - EncryptButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptButtonClick ), NULL, this ); - DecryptButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnDecryptButtonClick ), NULL, this ); - AutoTestAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnAutoTestAllButtonClick ), NULL, this ); - ResetButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnResetButtonClick ), NULL, this ); -} - -EncryptionTestDialogBase::~EncryptionTestDialogBase() -{ - // Disconnect Events - EncryptionAlgorithmChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptionAlgorithmSelected ), NULL, this ); - XtsModeCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnXtsModeCheckBoxClick ), NULL, this ); - EncryptButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptButtonClick ), NULL, this ); - DecryptButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnDecryptButtonClick ), NULL, this ); - AutoTestAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnAutoTestAllButtonClick ), NULL, this ); - ResetButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnResetButtonClick ), NULL, this ); -} - -FavoriteVolumesDialogBase::FavoriteVolumesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer57; - bSizer57 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer60; - bSizer60 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer58; - bSizer58 = new wxBoxSizer( wxVERTICAL ); - - FavoritesListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_VRULES|wxSUNKEN_BORDER ); - bSizer58->Add( FavoritesListCtrl, 1, wxALL|wxEXPAND, 5 ); - - wxGridSizer* gSizer5; - gSizer5 = new wxGridSizer( 1, 4, 0, 0 ); - - MoveUpButton = new wxButton( this, wxID_ANY, _("Move &Up"), wxDefaultPosition, wxDefaultSize, 0 ); - gSizer5->Add( MoveUpButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - MoveDownButton = new wxButton( this, wxID_ANY, _("Move &Down"), wxDefaultPosition, wxDefaultSize, 0 ); - gSizer5->Add( MoveDownButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - RemoveButton = new wxButton( this, wxID_ANY, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0 ); - gSizer5->Add( RemoveButton, 0, wxALIGN_RIGHT|wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - RemoveAllButton = new wxButton( this, wxID_ANY, _("Remove &All"), wxDefaultPosition, wxDefaultSize, 0 ); - gSizer5->Add( RemoveAllButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - bSizer58->Add( gSizer5, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - wxFlexGridSizer* fgSizer4; - fgSizer4 = new wxFlexGridSizer( 1, 5, 0, 0 ); - fgSizer4->AddGrowableCol( 2 ); - fgSizer4->SetFlexibleDirection( wxBOTH ); - fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer58->Add( fgSizer4, 0, wxEXPAND, 5 ); - - bSizer60->Add( bSizer58, 1, wxEXPAND, 5 ); - - wxBoxSizer* bSizer59; - bSizer59 = new wxBoxSizer( wxVERTICAL ); - - OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - OKButton->SetDefault(); - bSizer59->Add( OKButton, 0, wxALL, 5 ); - - CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer59->Add( CancelButton, 0, wxALL, 5 ); - - bSizer60->Add( bSizer59, 0, wxEXPAND, 5 ); - - bSizer57->Add( bSizer60, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer57 ); - this->Layout(); - bSizer57->Fit( this ); - - // Connect Events - FavoritesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemDeselected ), NULL, this ); - FavoritesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemSelected ), NULL, this ); - MoveUpButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveUpButtonClick ), NULL, this ); - MoveDownButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveDownButtonClick ), NULL, this ); - RemoveButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveButtonClick ), NULL, this ); - RemoveAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveAllButtonClick ), NULL, this ); - OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnOKButtonClick ), NULL, this ); -} - -FavoriteVolumesDialogBase::~FavoriteVolumesDialogBase() -{ - // Disconnect Events - FavoritesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemDeselected ), NULL, this ); - FavoritesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemSelected ), NULL, this ); - MoveUpButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveUpButtonClick ), NULL, this ); - MoveDownButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveDownButtonClick ), NULL, this ); - RemoveButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveButtonClick ), NULL, this ); - RemoveAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveAllButtonClick ), NULL, this ); - OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnOKButtonClick ), NULL, this ); -} - -KeyfilesDialogBase::KeyfilesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); - - wxBoxSizer* bSizer26; - bSizer26 = new wxBoxSizer( wxVERTICAL ); - - UpperSizer = new wxBoxSizer( wxHORIZONTAL ); - - PanelSizer = new wxBoxSizer( wxVERTICAL ); - - UpperSizer->Add( PanelSizer, 1, wxEXPAND, 5 ); - - wxBoxSizer* bSizer22; - bSizer22 = new wxBoxSizer( wxVERTICAL ); - - OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - OKButton->SetDefault(); - bSizer22->Add( OKButton, 0, wxALL|wxEXPAND, 5 ); - - CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer22->Add( CancelButton, 0, wxALL|wxEXPAND, 5 ); - - WarningStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - WarningStaticText->Wrap( -1 ); - bSizer22->Add( WarningStaticText, 1, wxALL|wxEXPAND, 5 ); - - UpperSizer->Add( bSizer22, 0, wxEXPAND, 5 ); - - bSizer26->Add( UpperSizer, 1, wxTOP|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer23; - bSizer23 = new wxBoxSizer( wxVERTICAL ); - - KeyfilesNoteSizer = new wxBoxSizer( wxVERTICAL ); - - wxStaticLine* m_staticline1; - m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - KeyfilesNoteSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 ); - - KeyfilesNoteStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - KeyfilesNoteStaticText->Wrap( -1 ); - KeyfilesNoteSizer->Add( KeyfilesNoteStaticText, 0, wxALL|wxEXPAND, 5 ); - - wxStaticLine* m_staticline2; - m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - KeyfilesNoteSizer->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 ); - - bSizer23->Add( KeyfilesNoteSizer, 1, wxEXPAND, 5 ); - - wxFlexGridSizer* fgSizer2; - fgSizer2 = new wxFlexGridSizer( 1, 2, 0, 0 ); - fgSizer2->AddGrowableCol( 0 ); - fgSizer2->SetFlexibleDirection( wxBOTH ); - fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - KeyfilesHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, _("More information on keyfiles"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - - KeyfilesHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - KeyfilesHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - KeyfilesHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - fgSizer2->Add( KeyfilesHyperlink, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - CreateKeyfileButtton = new wxButton( this, wxID_ANY, _("&Generate Random Keyfile..."), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer2->Add( CreateKeyfileButtton, 0, wxALL, 5 ); - - bSizer23->Add( fgSizer2, 0, wxEXPAND, 5 ); - - bSizer26->Add( bSizer23, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - this->SetSizer( bSizer26 ); - this->Layout(); - bSizer26->Fit( this ); - - // Connect Events - KeyfilesHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( KeyfilesDialogBase::OnKeyfilesHyperlinkClick ), NULL, this ); - CreateKeyfileButtton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesDialogBase::OnCreateKeyfileButttonClick ), NULL, this ); -} - -KeyfilesDialogBase::~KeyfilesDialogBase() -{ - // Disconnect Events - KeyfilesHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( KeyfilesDialogBase::OnKeyfilesHyperlinkClick ), NULL, this ); - CreateKeyfileButtton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesDialogBase::OnCreateKeyfileButttonClick ), NULL, this ); -} - -KeyfileGeneratorDialogBase::KeyfileGeneratorDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - MainSizer = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer144; - bSizer144 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer145; - bSizer145 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); - - wxStaticText* m_staticText49; - m_staticText49 = new wxStaticText( this, wxID_ANY, _("Mixing PRF:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText49->Wrap( -1 ); - bSizer145->Add( m_staticText49, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - wxArrayString HashChoiceChoices; - HashChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, HashChoiceChoices, 0 ); - HashChoice->SetSelection( 0 ); - bSizer145->Add( HashChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer144->Add( bSizer145, 0, wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer43; - sbSizer43 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxBoxSizer* bSizer147; - bSizer147 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* m_staticText52; - m_staticText52 = new wxStaticText( this, wxID_ANY, _("Random Pool:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText52->Wrap( -1 ); - bSizer147->Add( m_staticText52, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - RandomPoolStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - RandomPoolStaticText->Wrap( -1 ); - RandomPoolStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); - - bSizer147->Add( RandomPoolStaticText, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - ShowRandomPoolCheckBox = new wxCheckBox( this, wxID_ANY, _("Show"), wxDefaultPosition, wxDefaultSize, 0 ); - ShowRandomPoolCheckBox->SetValue(true); - - bSizer147->Add( ShowRandomPoolCheckBox, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer43->Add( bSizer147, 0, wxEXPAND|wxTOP, 5 ); - - - sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); - - MouseStaticText = new wxStaticText( this, wxID_ANY, _("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."), wxDefaultPosition, wxDefaultSize, 0 ); - MouseStaticText->Wrap( -1 ); - sbSizer43->Add( MouseStaticText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer144->Add( sbSizer43, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer146; - bSizer146 = new wxBoxSizer( wxHORIZONTAL ); - - GenerateButton = new wxButton( this, wxID_ANY, _("Generate and Save Keyfile..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer146->Add( GenerateButton, 0, wxALL, 5 ); - - - bSizer146->Add( 0, 0, 1, wxEXPAND, 5 ); - - wxButton* m_button61; - m_button61 = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer146->Add( m_button61, 0, wxALL, 5 ); - - bSizer144->Add( bSizer146, 0, wxEXPAND, 5 ); - - MainSizer->Add( bSizer144, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( MainSizer ); - this->Layout(); - MainSizer->Fit( this ); - - // Connect Events - this->Connect( wxEVT_MOTION, wxMouseEventHandler( KeyfileGeneratorDialogBase::OnMouseMotion ) ); - HashChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnHashSelected ), NULL, this ); - ShowRandomPoolCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); - GenerateButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnGenerateButtonClick ), NULL, this ); -} - -KeyfileGeneratorDialogBase::~KeyfileGeneratorDialogBase() -{ - // Disconnect Events - this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( KeyfileGeneratorDialogBase::OnMouseMotion ) ); - HashChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnHashSelected ), NULL, this ); - ShowRandomPoolCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); - GenerateButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnGenerateButtonClick ), NULL, this ); -} - -LegalNoticesDialogBase::LegalNoticesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer114; - bSizer114 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer115; - bSizer115 = new wxBoxSizer( wxVERTICAL ); - - LegalNoticesTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); - bSizer115->Add( LegalNoticesTextCtrl, 1, wxALL|wxEXPAND, 5 ); - - wxButton* OKButton; - OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - OKButton->SetDefault(); - bSizer115->Add( OKButton, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer114->Add( bSizer115, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer114 ); - this->Layout(); - bSizer114->Fit( this ); -} - -LegalNoticesDialogBase::~LegalNoticesDialogBase() -{ -} - -MountOptionsDialogBase::MountOptionsDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); - - wxBoxSizer* bSizer5; - bSizer5 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer19; - bSizer19 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer14; - bSizer14 = new wxBoxSizer( wxHORIZONTAL ); - - PasswordSizer = new wxBoxSizer( wxVERTICAL ); - - bSizer14->Add( PasswordSizer, 1, wxEXPAND, 5 ); - - wxBoxSizer* bSizer9; - bSizer9 = new wxBoxSizer( wxVERTICAL ); - - OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - OKButton->SetDefault(); - bSizer9->Add( OKButton, 0, wxALL|wxEXPAND, 5 ); - - CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer9->Add( CancelButton, 0, wxALL|wxEXPAND, 5 ); - - - bSizer9->Add( 0, 0, 1, wxTOP|wxEXPAND, 5 ); - - OptionsButton = new wxButton( this, wxID_ANY, _("Op&tions"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer9->Add( OptionsButton, 0, wxALL|wxEXPAND, 5 ); - - bSizer14->Add( bSizer9, 0, wxEXPAND, 5 ); - - bSizer19->Add( bSizer14, 0, wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer6; - bSizer6 = new wxBoxSizer( wxVERTICAL ); - - OptionsPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - OptionsSizer = new wxStaticBoxSizer( new wxStaticBox( OptionsPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - - OptionsSizer->Add( 0, 0, 0, wxTOP, 5 ); - - ReadOnlyCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("Mount volume as &read-only"), wxDefaultPosition, wxDefaultSize, 0 ); - - OptionsSizer->Add( ReadOnlyCheckBox, 0, wxALL, 5 ); - - RemovableCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("Mount volume as removable &medium"), wxDefaultPosition, wxDefaultSize, 0 ); - - OptionsSizer->Add( RemovableCheckBox, 0, wxALL, 5 ); - - PartitionInSystemEncryptionScopeCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("Mount partition &using system encryption (preboot authentication)"), wxDefaultPosition, wxDefaultSize, 0 ); - - OptionsSizer->Add( PartitionInSystemEncryptionScopeCheckBox, 0, wxALL, 5 ); - - ProtectionSizer = new wxStaticBoxSizer( new wxStaticBox( OptionsPanel, wxID_ANY, _("Hidden Volume Protection") ), wxVERTICAL ); - - ProtectionCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("&Protect hidden volume when mounting outer volume"), wxDefaultPosition, wxDefaultSize, 0 ); - - ProtectionSizer->Add( ProtectionCheckBox, 0, wxALL, 5 ); - - ProtectionPasswordSizer = new wxBoxSizer( wxVERTICAL ); - - ProtectionSizer->Add( ProtectionPasswordSizer, 1, wxEXPAND|wxLEFT, 5 ); - - ProtectionHyperlinkCtrl = new wxHyperlinkCtrl( OptionsPanel, wxID_ANY, _("What is hidden volume protection?"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - - ProtectionHyperlinkCtrl->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - ProtectionHyperlinkCtrl->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - ProtectionHyperlinkCtrl->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - ProtectionSizer->Add( ProtectionHyperlinkCtrl, 0, wxALL, 5 ); - - OptionsSizer->Add( ProtectionSizer, 1, wxEXPAND|wxALL, 5 ); - - FilesystemSizer = new wxBoxSizer( wxVERTICAL ); - - m_panel8 = new wxPanel( OptionsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxStaticBoxSizer* sbSizer28; - sbSizer28 = new wxStaticBoxSizer( new wxStaticBox( m_panel8, wxID_ANY, _("Filesystem") ), wxVERTICAL ); - - wxBoxSizer* bSizer54; - bSizer54 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer55; - bSizer55 = new wxBoxSizer( wxVERTICAL ); - - NoFilesystemCheckBox = new wxCheckBox( m_panel8, wxID_ANY, _("Do ¬ mount"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer55->Add( NoFilesystemCheckBox, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - bSizer54->Add( bSizer55, 1, wxEXPAND, 5 ); - - FilesystemOptionsSizer = new wxGridBagSizer( 0, 0 ); - FilesystemOptionsSizer->AddGrowableCol( 1 ); - FilesystemOptionsSizer->SetFlexibleDirection( wxBOTH ); - FilesystemOptionsSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - FilesystemOptionsSizer->SetEmptyCellSize( wxSize( 0,0 ) ); - - FilesystemSpacer = new wxBoxSizer( wxVERTICAL ); - - FilesystemOptionsSizer->Add( FilesystemSpacer, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP, 5 ); - - MountPointTextCtrlStaticText = new wxStaticText( m_panel8, wxID_ANY, _("Mount at directory:"), wxDefaultPosition, wxDefaultSize, 0 ); - MountPointTextCtrlStaticText->Wrap( -1 ); - FilesystemOptionsSizer->Add( MountPointTextCtrlStaticText, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - MountPointTextCtrl = new wxTextCtrl( m_panel8, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - FilesystemOptionsSizer->Add( MountPointTextCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - MountPointButton = new wxButton( m_panel8, wxID_ANY, _("Se&lect..."), wxDefaultPosition, wxDefaultSize, 0 ); - FilesystemOptionsSizer->Add( MountPointButton, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - FilesystemOptionsStaticText = new wxStaticText( m_panel8, wxID_ANY, _("Mount options:"), wxDefaultPosition, wxDefaultSize, 0 ); - FilesystemOptionsStaticText->Wrap( -1 ); - FilesystemOptionsSizer->Add( FilesystemOptionsStaticText, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxLEFT, 5 ); - - FilesystemOptionsTextCtrl = new wxTextCtrl( m_panel8, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - FilesystemOptionsSizer->Add( FilesystemOptionsTextCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - - bSizer54->Add( FilesystemOptionsSizer, 0, wxEXPAND, 5 ); - - sbSizer28->Add( bSizer54, 0, wxEXPAND|wxBOTTOM, 5 ); - - m_panel8->SetSizer( sbSizer28 ); - m_panel8->Layout(); - sbSizer28->Fit( m_panel8 ); - FilesystemSizer->Add( m_panel8, 0, wxEXPAND | wxALL, 5 ); - - OptionsSizer->Add( FilesystemSizer, 0, wxEXPAND, 5 ); - - OptionsPanel->SetSizer( OptionsSizer ); - OptionsPanel->Layout(); - OptionsSizer->Fit( OptionsPanel ); - bSizer6->Add( OptionsPanel, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizer19->Add( bSizer6, 0, wxEXPAND, 5 ); - - bSizer5->Add( bSizer19, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer5 ); - this->Layout(); - bSizer5->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( MountOptionsDialogBase::OnInitDialog ) ); - OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOKButtonClick ), NULL, this ); - OptionsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOptionsButtonClick ), NULL, this ); - ReadOnlyCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnReadOnlyCheckBoxClick ), NULL, this ); - ProtectionCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnProtectionCheckBoxClick ), NULL, this ); - ProtectionHyperlinkCtrl->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MountOptionsDialogBase::OnProtectionHyperlinkClick ), NULL, this ); - NoFilesystemCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnNoFilesystemCheckBoxClick ), NULL, this ); - MountPointButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnMountPointButtonClick ), NULL, this ); -} - -MountOptionsDialogBase::~MountOptionsDialogBase() -{ - // Disconnect Events - this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( MountOptionsDialogBase::OnInitDialog ) ); - OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOKButtonClick ), NULL, this ); - OptionsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOptionsButtonClick ), NULL, this ); - ReadOnlyCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnReadOnlyCheckBoxClick ), NULL, this ); - ProtectionCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnProtectionCheckBoxClick ), NULL, this ); - ProtectionHyperlinkCtrl->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MountOptionsDialogBase::OnProtectionHyperlinkClick ), NULL, this ); - NoFilesystemCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnNoFilesystemCheckBoxClick ), NULL, this ); - MountPointButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnMountPointButtonClick ), NULL, this ); -} - -NewSecurityTokenKeyfileDialogBase::NewSecurityTokenKeyfileDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer143; - bSizer143 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer144; - bSizer144 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer42; - sbSizer42 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxFlexGridSizer* fgSizer7; - fgSizer7 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer7->SetFlexibleDirection( wxBOTH ); - fgSizer7->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxStaticText* m_staticText47; - m_staticText47 = new wxStaticText( this, wxID_ANY, _("Security token:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); - m_staticText47->Wrap( -1 ); - fgSizer7->Add( m_staticText47, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - wxArrayString SecurityTokenChoiceChoices; - SecurityTokenChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, SecurityTokenChoiceChoices, 0 ); - SecurityTokenChoice->SetSelection( 0 ); - fgSizer7->Add( SecurityTokenChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxStaticText* m_staticText48; - m_staticText48 = new wxStaticText( this, wxID_ANY, _("Keyfile name:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); - m_staticText48->Wrap( -1 ); - fgSizer7->Add( m_staticText48, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - KeyfileNameTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer7->Add( KeyfileNameTextCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); - - sbSizer42->Add( fgSizer7, 1, wxEXPAND|wxTOP, 5 ); - - bSizer144->Add( sbSizer42, 1, wxEXPAND|wxALL, 5 ); - - StdButtons = new wxStdDialogButtonSizer(); - StdButtonsOK = new wxButton( this, wxID_OK ); - StdButtons->AddButton( StdButtonsOK ); - StdButtonsCancel = new wxButton( this, wxID_CANCEL ); - StdButtons->AddButton( StdButtonsCancel ); - StdButtons->Realize(); - bSizer144->Add( StdButtons, 0, wxALIGN_RIGHT|wxALL, 5 ); - - bSizer143->Add( bSizer144, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer143 ); - this->Layout(); - bSizer143->Fit( this ); - - // Connect Events - KeyfileNameTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( NewSecurityTokenKeyfileDialogBase::OnKeyfileNameChanged ), NULL, this ); -} - -NewSecurityTokenKeyfileDialogBase::~NewSecurityTokenKeyfileDialogBase() -{ - // Disconnect Events - KeyfileNameTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( NewSecurityTokenKeyfileDialogBase::OnKeyfileNameChanged ), NULL, this ); -} - -PreferencesDialogBase::PreferencesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); - - wxBoxSizer* bSizer32; - bSizer32 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer41; - bSizer41 = new wxBoxSizer( wxVERTICAL ); - - PreferencesNotebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - SecurityPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer44; - bSizer44 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer33; - bSizer33 = new wxBoxSizer( wxVERTICAL ); - - AutoDismountSizer = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Auto-Dismount") ), wxVERTICAL ); - - wxStaticBoxSizer* sbSizer13; - sbSizer13 = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Dismount All Volumes When") ), wxVERTICAL ); - - DismountOnLogOffCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("User logs off"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer13->Add( DismountOnLogOffCheckBox, 0, wxALL, 5 ); - - DismountOnScreenSaverCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Screen saver is launched"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer13->Add( DismountOnScreenSaverCheckBox, 0, wxALL, 5 ); - - DismountOnPowerSavingCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("System is entering power saving mode"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer13->Add( DismountOnPowerSavingCheckBox, 0, wxALL, 5 ); - - AutoDismountSizer->Add( sbSizer13, 0, wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer34; - bSizer34 = new wxBoxSizer( wxHORIZONTAL ); - - DismountOnInactivityCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Auto-dismount volume after no data has been read/written to it for"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer34->Add( DismountOnInactivityCheckBox, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - DismountOnInactivitySpinCtrl = new wxSpinCtrl( SecurityPage, wxID_ANY, wxT("1"), wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 1, 9999, 1 ); - bSizer34->Add( DismountOnInactivitySpinCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - wxStaticText* m_staticText5; - m_staticText5 = new wxStaticText( SecurityPage, wxID_ANY, _("minutes"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText5->Wrap( -1 ); - bSizer34->Add( m_staticText5, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - AutoDismountSizer->Add( bSizer34, 0, wxEXPAND, 5 ); - - ForceAutoDismountCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Force auto-dismount even if volume contains open files or directories"), wxDefaultPosition, wxDefaultSize, 0 ); - - AutoDismountSizer->Add( ForceAutoDismountCheckBox, 0, wxALL, 5 ); - - bSizer33->Add( AutoDismountSizer, 0, wxEXPAND|wxALL, 5 ); - - FilesystemSecuritySizer = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Filesystem") ), wxVERTICAL ); - - PreserveTimestampsCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Preserve modification time of file containers"), wxDefaultPosition, wxDefaultSize, 0 ); - - FilesystemSecuritySizer->Add( PreserveTimestampsCheckBox, 0, wxALL, 5 ); - - bSizer33->Add( FilesystemSecuritySizer, 0, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer14; - sbSizer14 = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Password Cache") ), wxVERTICAL ); - - WipeCacheOnCloseCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Wipe after TrueCrypt window has been closed"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer14->Add( WipeCacheOnCloseCheckBox, 0, wxALL, 5 ); - - WipeCacheOnAutoDismountCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Wipe after volume has been auto-dismounted"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer14->Add( WipeCacheOnAutoDismountCheckBox, 0, wxALL, 5 ); - - bSizer33->Add( sbSizer14, 0, wxEXPAND|wxALL, 5 ); - - bSizer44->Add( bSizer33, 1, wxEXPAND|wxALL, 5 ); - - SecurityPage->SetSizer( bSizer44 ); - SecurityPage->Layout(); - bSizer44->Fit( SecurityPage ); - PreferencesNotebook->AddPage( SecurityPage, _("Security"), true ); - DefaultMountOptionsPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer46; - bSizer46 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer35; - bSizer35 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer15; - sbSizer15 = new wxStaticBoxSizer( new wxStaticBox( DefaultMountOptionsPage, wxID_ANY, _("Default Mount Options") ), wxVERTICAL ); - - MountReadOnlyCheckBox = new wxCheckBox( DefaultMountOptionsPage, wxID_ANY, _("Mount volumes as read-only"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer15->Add( MountReadOnlyCheckBox, 0, wxALL, 5 ); - - MountRemovableCheckBox = new wxCheckBox( DefaultMountOptionsPage, wxID_ANY, _("Mount volumes as removable media"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer15->Add( MountRemovableCheckBox, 0, wxALL, 5 ); - - CachePasswordsCheckBox = new wxCheckBox( DefaultMountOptionsPage, wxID_ANY, _("Cache passwords in memory"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer15->Add( CachePasswordsCheckBox, 0, wxALL, 5 ); - - bSizer35->Add( sbSizer15, 0, wxEXPAND|wxALL, 5 ); - - FilesystemSizer = new wxStaticBoxSizer( new wxStaticBox( DefaultMountOptionsPage, wxID_ANY, _("Filesystem") ), wxVERTICAL ); - - wxFlexGridSizer* fgSizer3; - fgSizer3 = new wxFlexGridSizer( 1, 2, 0, 0 ); - fgSizer3->AddGrowableCol( 1 ); - fgSizer3->SetFlexibleDirection( wxBOTH ); - fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxStaticText* m_staticText6; - m_staticText6 = new wxStaticText( DefaultMountOptionsPage, wxID_ANY, _("Mount options:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText6->Wrap( -1 ); - fgSizer3->Add( m_staticText6, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - - FilesystemOptionsTextCtrl = new wxTextCtrl( DefaultMountOptionsPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer3->Add( FilesystemOptionsTextCtrl, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - FilesystemSizer->Add( fgSizer3, 1, wxEXPAND, 5 ); - - bSizer35->Add( FilesystemSizer, 0, wxEXPAND|wxALL, 5 ); - - bSizer46->Add( bSizer35, 1, wxEXPAND|wxALL, 5 ); - - DefaultMountOptionsPage->SetSizer( bSizer46 ); - DefaultMountOptionsPage->Layout(); - bSizer46->Fit( DefaultMountOptionsPage ); - PreferencesNotebook->AddPage( DefaultMountOptionsPage, _("Mount Options"), false ); - BackgroundTaskPanel = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer61; - bSizer61 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer62; - bSizer62 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer18; - sbSizer18 = new wxStaticBoxSizer( new wxStaticBox( BackgroundTaskPanel, wxID_ANY, _("TrueCrypt Background Task") ), wxVERTICAL ); - - BackgroundTaskEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Enabled"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer18->Add( BackgroundTaskEnabledCheckBox, 0, wxALL, 5 ); - - CloseBackgroundTaskOnNoVolumesCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Exit when there are no mounted volumes"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer18->Add( CloseBackgroundTaskOnNoVolumesCheckBox, 0, wxALL, 5 ); - - wxStaticBoxSizer* sbSizer26; - sbSizer26 = new wxStaticBoxSizer( new wxStaticBox( BackgroundTaskPanel, wxID_ANY, _("Task Icon Menu Items") ), wxVERTICAL ); - - BackgroundTaskMenuMountItemsEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Mount Favorite Volumes"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer26->Add( BackgroundTaskMenuMountItemsEnabledCheckBox, 0, wxALL, 5 ); - - BackgroundTaskMenuOpenItemsEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Open Mounted Volumes"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer26->Add( BackgroundTaskMenuOpenItemsEnabledCheckBox, 0, wxALL, 5 ); - - BackgroundTaskMenuDismountItemsEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Dismount Mounted Volumes"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer26->Add( BackgroundTaskMenuDismountItemsEnabledCheckBox, 0, wxALL, 5 ); - - sbSizer18->Add( sbSizer26, 1, wxEXPAND|wxALL, 5 ); - - bSizer62->Add( sbSizer18, 0, wxEXPAND|wxALL, 5 ); - - bSizer61->Add( bSizer62, 1, wxEXPAND|wxALL, 5 ); - - BackgroundTaskPanel->SetSizer( bSizer61 ); - BackgroundTaskPanel->Layout(); - bSizer61->Fit( BackgroundTaskPanel ); - PreferencesNotebook->AddPage( BackgroundTaskPanel, _("Background Task"), false ); - SystemIntegrationPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer49; - bSizer49 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer37; - bSizer37 = new wxBoxSizer( wxVERTICAL ); - - LogOnSizer = new wxStaticBoxSizer( new wxStaticBox( SystemIntegrationPage, wxID_ANY, _("Actions to Perform when User Logs On") ), wxVERTICAL ); - - StartOnLogonCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Start TrueCrypt Background Task"), wxDefaultPosition, wxDefaultSize, 0 ); - - LogOnSizer->Add( StartOnLogonCheckBox, 0, wxALL, 5 ); - - MountFavoritesOnLogonCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Mount favorite volumes"), wxDefaultPosition, wxDefaultSize, 0 ); - - LogOnSizer->Add( MountFavoritesOnLogonCheckBox, 0, wxALL, 5 ); - - MountDevicesOnLogonCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Mount all device-hosted TrueCrypt volumes"), wxDefaultPosition, wxDefaultSize, 0 ); - - LogOnSizer->Add( MountDevicesOnLogonCheckBox, 0, wxALL, 5 ); - - bSizer37->Add( LogOnSizer, 0, wxALL|wxEXPAND, 5 ); - - ExplorerSizer = new wxStaticBoxSizer( new wxStaticBox( SystemIntegrationPage, wxID_ANY, _("Filesystem Explorer") ), wxVERTICAL ); - - OpenExplorerWindowAfterMountCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Open Explorer window for successfully mounted volume"), wxDefaultPosition, wxDefaultSize, 0 ); - - ExplorerSizer->Add( OpenExplorerWindowAfterMountCheckBox, 0, wxALL, 5 ); - - CloseExplorerWindowsOnDismountCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Close all Explorer windows of volume being dismounted"), wxDefaultPosition, wxDefaultSize, 0 ); - - ExplorerSizer->Add( CloseExplorerWindowsOnDismountCheckBox, 0, wxALL, 5 ); - - bSizer37->Add( ExplorerSizer, 0, wxEXPAND|wxALL, 5 ); - - KernelServicesSizer = new wxStaticBoxSizer( new wxStaticBox( SystemIntegrationPage, wxID_ANY, _("Kernel Services") ), wxVERTICAL ); - - NoKernelCryptoCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Do not use kernel cryptographic services"), wxDefaultPosition, wxDefaultSize, 0 ); - - KernelServicesSizer->Add( NoKernelCryptoCheckBox, 0, wxALL, 5 ); - - bSizer37->Add( KernelServicesSizer, 0, wxEXPAND|wxALL, 5 ); - - bSizer49->Add( bSizer37, 1, wxEXPAND|wxALL, 5 ); - - SystemIntegrationPage->SetSizer( bSizer49 ); - SystemIntegrationPage->Layout(); - bSizer49->Fit( SystemIntegrationPage ); - PreferencesNotebook->AddPage( SystemIntegrationPage, _("System Integration"), false ); - DefaultKeyfilesPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer40; - bSizer40 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer43; - bSizer43 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* bSizer42; - bSizer42 = new wxStaticBoxSizer( new wxStaticBox( DefaultKeyfilesPage, wxID_ANY, _("Default Keyfiles") ), wxVERTICAL ); - - DefaultKeyfilesSizer = new wxBoxSizer( wxVERTICAL ); - - bSizer42->Add( DefaultKeyfilesSizer, 1, wxEXPAND, 5 ); - - bSizer43->Add( bSizer42, 1, wxEXPAND|wxALL, 5 ); - - UseKeyfilesCheckBox = new wxCheckBox( DefaultKeyfilesPage, wxID_ANY, _("Use keyfiles by default"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer43->Add( UseKeyfilesCheckBox, 0, wxALL, 5 ); - - bSizer40->Add( bSizer43, 1, wxEXPAND|wxALL, 5 ); - - DefaultKeyfilesPage->SetSizer( bSizer40 ); - DefaultKeyfilesPage->Layout(); - bSizer40->Fit( DefaultKeyfilesPage ); - PreferencesNotebook->AddPage( DefaultKeyfilesPage, _("Keyfiles"), false ); - SecurityTokensPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer127; - bSizer127 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer128; - bSizer128 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer36; - sbSizer36 = new wxStaticBoxSizer( new wxStaticBox( SecurityTokensPage, wxID_ANY, _("PKCS #11 Library Path") ), wxVERTICAL ); - - wxBoxSizer* bSizer129; - bSizer129 = new wxBoxSizer( wxHORIZONTAL ); - - Pkcs11ModulePathTextCtrl = new wxTextCtrl( SecurityTokensPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer129->Add( Pkcs11ModulePathTextCtrl, 1, wxALL, 5 ); - - SelectPkcs11ModuleButton = new wxButton( SecurityTokensPage, wxID_ANY, _("Select &Library..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer129->Add( SelectPkcs11ModuleButton, 0, wxALL, 5 ); - - sbSizer36->Add( bSizer129, 1, wxEXPAND, 5 ); - - bSizer128->Add( sbSizer36, 0, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer37; - sbSizer37 = new wxStaticBoxSizer( new wxStaticBox( SecurityTokensPage, wxID_ANY, _("Security Options") ), wxVERTICAL ); - - CloseSecurityTokenSessionsAfterMountCheckBox = new wxCheckBox( SecurityTokensPage, wxID_ANY, _("&Close token session (log out) after a volume is successfully mounted"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer37->Add( CloseSecurityTokenSessionsAfterMountCheckBox, 0, wxALL, 5 ); - - bSizer128->Add( sbSizer37, 0, wxEXPAND|wxALL, 5 ); - - bSizer127->Add( bSizer128, 1, wxEXPAND|wxALL, 5 ); - - SecurityTokensPage->SetSizer( bSizer127 ); - SecurityTokensPage->Layout(); - bSizer127->Fit( SecurityTokensPage ); - PreferencesNotebook->AddPage( SecurityTokensPage, _("Security Tokens"), false ); - HotkeysPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer51; - bSizer51 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer38; - bSizer38 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer21; - sbSizer21 = new wxStaticBoxSizer( new wxStaticBox( HotkeysPage, wxID_ANY, _("System-Wide Hotkeys") ), wxVERTICAL ); - - HotkeyListCtrl = new wxListCtrl( HotkeysPage, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxSUNKEN_BORDER ); - sbSizer21->Add( HotkeyListCtrl, 1, wxALL|wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer23; - sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( HotkeysPage, wxID_ANY, _("Shortcut") ), wxVERTICAL ); - - wxFlexGridSizer* fgSizer4; - fgSizer4 = new wxFlexGridSizer( 2, 3, 0, 0 ); - fgSizer4->SetFlexibleDirection( wxBOTH ); - fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxStaticText* m_staticText10; - m_staticText10 = new wxStaticText( HotkeysPage, wxID_ANY, _("Key to assign:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText10->Wrap( -1 ); - fgSizer4->Add( m_staticText10, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - HotkeyTextCtrl = new wxTextCtrl( HotkeysPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer4->Add( HotkeyTextCtrl, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - AssignHotkeyButton = new wxButton( HotkeysPage, wxID_ANY, _("Assign"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer4->Add( AssignHotkeyButton, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); - - wxGridSizer* gSizer4; - gSizer4 = new wxGridSizer( 1, 4, 0, 0 ); - - HotkeyControlCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Control"), wxDefaultPosition, wxDefaultSize, 0 ); - - gSizer4->Add( HotkeyControlCheckBox, 0, wxALL, 5 ); - - HotkeyShiftCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Shift"), wxDefaultPosition, wxDefaultSize, 0 ); - - gSizer4->Add( HotkeyShiftCheckBox, 0, wxALL, 5 ); - - HotkeyAltCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Alt"), wxDefaultPosition, wxDefaultSize, 0 ); - - gSizer4->Add( HotkeyAltCheckBox, 0, wxALL, 5 ); - - HotkeyWinCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Win"), wxDefaultPosition, wxDefaultSize, 0 ); - - gSizer4->Add( HotkeyWinCheckBox, 0, wxALL, 5 ); - - fgSizer4->Add( gSizer4, 1, wxEXPAND, 5 ); - - RemoveHotkeyButton = new wxButton( HotkeysPage, wxID_ANY, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer4->Add( RemoveHotkeyButton, 1, wxALL, 5 ); - - sbSizer23->Add( fgSizer4, 1, wxALIGN_RIGHT, 5 ); - - sbSizer21->Add( sbSizer23, 0, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer24; - sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( HotkeysPage, wxID_ANY, _("Options") ), wxVERTICAL ); - - BeepAfterHotkeyMountDismountCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Play system notification sound after mount/dismount"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer24->Add( BeepAfterHotkeyMountDismountCheckBox, 0, wxALL, 5 ); - - DisplayMessageAfterHotkeyDismountCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Display confirmation message box after dismount"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer24->Add( DisplayMessageAfterHotkeyDismountCheckBox, 0, wxALL, 5 ); - - sbSizer21->Add( sbSizer24, 0, wxEXPAND|wxALL, 5 ); - - bSizer38->Add( sbSizer21, 1, wxEXPAND|wxALL, 5 ); - - bSizer51->Add( bSizer38, 1, wxEXPAND|wxALL, 5 ); - - HotkeysPage->SetSizer( bSizer51 ); - HotkeysPage->Layout(); - bSizer51->Fit( HotkeysPage ); - PreferencesNotebook->AddPage( HotkeysPage, _("Hotkeys"), false ); - - bSizer41->Add( PreferencesNotebook, 1, wxEXPAND | wxALL, 5 ); - - StdButtons = new wxStdDialogButtonSizer(); - StdButtonsOK = new wxButton( this, wxID_OK ); - StdButtons->AddButton( StdButtonsOK ); - StdButtonsCancel = new wxButton( this, wxID_CANCEL ); - StdButtons->AddButton( StdButtonsCancel ); - StdButtons->Realize(); - bSizer41->Add( StdButtons, 0, wxEXPAND|wxALL, 5 ); - - bSizer32->Add( bSizer41, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer32 ); - this->Layout(); - bSizer32->Fit( this ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PreferencesDialogBase::OnClose ) ); - DismountOnScreenSaverCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnScreenSaverCheckBoxClick ), NULL, this ); - DismountOnPowerSavingCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnPowerSavingCheckBoxClick ), NULL, this ); - ForceAutoDismountCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnForceAutoDismountCheckBoxClick ), NULL, this ); - PreserveTimestampsCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnPreserveTimestampsCheckBoxClick ), NULL, this ); - BackgroundTaskEnabledCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnBackgroundTaskEnabledCheckBoxClick ), NULL, this ); - NoKernelCryptoCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnNoKernelCryptoCheckBoxClick ), NULL, this ); - SelectPkcs11ModuleButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnSelectPkcs11ModuleButtonClick ), NULL, this ); - HotkeyListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemDeselected ), NULL, this ); - HotkeyListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemSelected ), NULL, this ); - AssignHotkeyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnAssignHotkeyButtonClick ), NULL, this ); - RemoveHotkeyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnRemoveHotkeyButtonClick ), NULL, this ); - StdButtonsCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnCancelButtonClick ), NULL, this ); - StdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnOKButtonClick ), NULL, this ); -} - -PreferencesDialogBase::~PreferencesDialogBase() -{ - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PreferencesDialogBase::OnClose ) ); - DismountOnScreenSaverCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnScreenSaverCheckBoxClick ), NULL, this ); - DismountOnPowerSavingCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnPowerSavingCheckBoxClick ), NULL, this ); - ForceAutoDismountCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnForceAutoDismountCheckBoxClick ), NULL, this ); - PreserveTimestampsCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnPreserveTimestampsCheckBoxClick ), NULL, this ); - BackgroundTaskEnabledCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnBackgroundTaskEnabledCheckBoxClick ), NULL, this ); - NoKernelCryptoCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnNoKernelCryptoCheckBoxClick ), NULL, this ); - SelectPkcs11ModuleButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnSelectPkcs11ModuleButtonClick ), NULL, this ); - HotkeyListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemDeselected ), NULL, this ); - HotkeyListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemSelected ), NULL, this ); - AssignHotkeyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnAssignHotkeyButtonClick ), NULL, this ); - RemoveHotkeyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnRemoveHotkeyButtonClick ), NULL, this ); - StdButtonsCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnCancelButtonClick ), NULL, this ); - StdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnOKButtonClick ), NULL, this ); -} - -RandomPoolEnrichmentDialogBase::RandomPoolEnrichmentDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - MainSizer = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer144; - bSizer144 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer145; - bSizer145 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); - - wxStaticText* m_staticText49; - m_staticText49 = new wxStaticText( this, wxID_ANY, _("Mixing PRF:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText49->Wrap( -1 ); - bSizer145->Add( m_staticText49, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - wxArrayString HashChoiceChoices; - HashChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, HashChoiceChoices, 0 ); - HashChoice->SetSelection( 0 ); - bSizer145->Add( HashChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer144->Add( bSizer145, 0, wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer43; - sbSizer43 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxBoxSizer* bSizer147; - bSizer147 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* m_staticText52; - m_staticText52 = new wxStaticText( this, wxID_ANY, _("Random Pool:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText52->Wrap( -1 ); - bSizer147->Add( m_staticText52, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - RandomPoolStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - RandomPoolStaticText->Wrap( -1 ); - RandomPoolStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); - - bSizer147->Add( RandomPoolStaticText, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - ShowRandomPoolCheckBox = new wxCheckBox( this, wxID_ANY, _("Show"), wxDefaultPosition, wxDefaultSize, 0 ); - ShowRandomPoolCheckBox->SetValue(true); - - bSizer147->Add( ShowRandomPoolCheckBox, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer43->Add( bSizer147, 0, wxEXPAND|wxTOP, 5 ); - - - sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); - - MouseStaticText = new wxStaticText( this, wxID_ANY, _("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'."), wxDefaultPosition, wxDefaultSize, 0 ); - MouseStaticText->Wrap( -1 ); - sbSizer43->Add( MouseStaticText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer144->Add( sbSizer43, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer146; - bSizer146 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer146->Add( 0, 0, 1, wxEXPAND, 5 ); - - ContinueButton = new wxButton( this, wxID_OK, _("&Continue"), wxDefaultPosition, wxDefaultSize, 0 ); - ContinueButton->SetDefault(); - bSizer146->Add( ContinueButton, 0, wxALL, 5 ); - - - bSizer146->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer144->Add( bSizer146, 0, wxEXPAND, 5 ); - - MainSizer->Add( bSizer144, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( MainSizer ); - this->Layout(); - MainSizer->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_MOTION, wxMouseEventHandler( RandomPoolEnrichmentDialogBase::OnMouseMotion ) ); - HashChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnHashSelected ), NULL, this ); - ShowRandomPoolCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); -} - -RandomPoolEnrichmentDialogBase::~RandomPoolEnrichmentDialogBase() -{ - // Disconnect Events - this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( RandomPoolEnrichmentDialogBase::OnMouseMotion ) ); - HashChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnHashSelected ), NULL, this ); - ShowRandomPoolCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); -} - -SecurityTokenKeyfilesDialogBase::SecurityTokenKeyfilesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); - - wxBoxSizer* bSizer3; - bSizer3 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer138; - bSizer138 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer142; - bSizer142 = new wxBoxSizer( wxVERTICAL ); - - SecurityTokenKeyfileListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_VRULES|wxSUNKEN_BORDER ); - bSizer142->Add( SecurityTokenKeyfileListCtrl, 1, wxALL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer141; - bSizer141 = new wxBoxSizer( wxHORIZONTAL ); - - ExportButton = new wxButton( this, wxID_ANY, _("&Export..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer141->Add( ExportButton, 0, wxALL, 5 ); - - DeleteButton = new wxButton( this, wxID_ANY, _("&Delete"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer141->Add( DeleteButton, 0, wxALL, 5 ); - - - bSizer141->Add( 0, 0, 1, wxEXPAND|wxLEFT, 5 ); - - ImportButton = new wxButton( this, wxID_ANY, _("&Import Keyfile to Token..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer141->Add( ImportButton, 0, wxALL, 5 ); - - bSizer142->Add( bSizer141, 0, wxEXPAND, 5 ); - - bSizer138->Add( bSizer142, 1, wxEXPAND, 5 ); - - wxBoxSizer* bSizer139; - bSizer139 = new wxBoxSizer( wxVERTICAL ); - - OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - OKButton->SetDefault(); - bSizer139->Add( OKButton, 0, wxALL, 5 ); - - CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer139->Add( CancelButton, 0, wxALL, 5 ); - - bSizer138->Add( bSizer139, 0, wxEXPAND, 5 ); - - bSizer3->Add( bSizer138, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer3 ); - this->Layout(); - bSizer3->Fit( this ); - - // Connect Events - SecurityTokenKeyfileListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemActivated ), NULL, this ); - SecurityTokenKeyfileListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemDeselected ), NULL, this ); - SecurityTokenKeyfileListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemSelected ), NULL, this ); - ExportButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnExportButtonClick ), NULL, this ); - DeleteButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnDeleteButtonClick ), NULL, this ); - ImportButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnImportButtonClick ), NULL, this ); - OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnOKButtonClick ), NULL, this ); -} - -SecurityTokenKeyfilesDialogBase::~SecurityTokenKeyfilesDialogBase() -{ - // Disconnect Events - SecurityTokenKeyfileListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemActivated ), NULL, this ); - SecurityTokenKeyfileListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemDeselected ), NULL, this ); - SecurityTokenKeyfileListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemSelected ), NULL, this ); - ExportButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnExportButtonClick ), NULL, this ); - DeleteButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnDeleteButtonClick ), NULL, this ); - ImportButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnImportButtonClick ), NULL, this ); - OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnOKButtonClick ), NULL, this ); -} - -VolumePropertiesDialogBase::VolumePropertiesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer49; - bSizer49 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer50; - bSizer50 = new wxBoxSizer( wxVERTICAL ); - - PropertiesListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_VRULES|wxSUNKEN_BORDER ); - bSizer50->Add( PropertiesListCtrl, 1, wxALL|wxEXPAND, 5 ); - - StdButtons = new wxStdDialogButtonSizer(); - StdButtonsOK = new wxButton( this, wxID_OK ); - StdButtons->AddButton( StdButtonsOK ); - StdButtons->Realize(); - bSizer50->Add( StdButtons, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer49->Add( bSizer50, 1, wxEXPAND|wxALL, 5 ); - - this->SetSizer( bSizer49 ); - this->Layout(); - bSizer49->Fit( this ); -} - -VolumePropertiesDialogBase::~VolumePropertiesDialogBase() -{ -} - -EncryptionOptionsWizardPageBase::EncryptionOptionsWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer93; - bSizer93 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer94; - bSizer94 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer29; - sbSizer29 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Encryption Algorithm") ), wxVERTICAL ); - - wxBoxSizer* bSizer96; - bSizer96 = new wxBoxSizer( wxHORIZONTAL ); - - wxArrayString EncryptionAlgorithmChoiceChoices; - EncryptionAlgorithmChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, EncryptionAlgorithmChoiceChoices, 0 ); - EncryptionAlgorithmChoice->SetSelection( 0 ); - bSizer96->Add( EncryptionAlgorithmChoice, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - TestButton = new wxButton( this, wxID_ANY, _("&Test"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer96->Add( TestButton, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - sbSizer29->Add( bSizer96, 0, wxEXPAND, 5 ); - - EncryptionAlgorithmStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - EncryptionAlgorithmStaticText->Wrap( -1 ); - sbSizer29->Add( EncryptionAlgorithmStaticText, 1, wxALL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer97; - bSizer97 = new wxBoxSizer( wxHORIZONTAL ); - - EncryptionAlgorithmHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, _("More information"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - - EncryptionAlgorithmHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - EncryptionAlgorithmHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - EncryptionAlgorithmHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - bSizer97->Add( EncryptionAlgorithmHyperlink, 0, wxALL, 5 ); - - - bSizer97->Add( 0, 0, 1, wxEXPAND, 5 ); - - BenchmarkButton = new wxButton( this, wxID_ANY, _("&Benchmark"), wxDefaultPosition, wxDefaultSize, 0 ); - BenchmarkButton->Hide(); - - bSizer97->Add( BenchmarkButton, 0, wxALL, 5 ); - - sbSizer29->Add( bSizer97, 0, wxEXPAND, 5 ); - - bSizer95->Add( sbSizer29, 1, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer30; - sbSizer30 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Hash Algorithm") ), wxHORIZONTAL ); - - wxArrayString HashChoiceChoices; - HashChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, HashChoiceChoices, 0 ); - HashChoice->SetSelection( 0 ); - sbSizer30->Add( HashChoice, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - HashHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, _("Information on hash algorithms"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - - HashHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - HashHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - HashHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); - sbSizer30->Add( HashHyperlink, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer95->Add( sbSizer30, 0, wxEXPAND|wxALL, 5 ); - - bSizer94->Add( bSizer95, 1, wxEXPAND, 5 ); - - bSizer93->Add( bSizer94, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer93 ); - this->Layout(); - bSizer93->Fit( this ); - - // Connect Events - EncryptionAlgorithmChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmSelected ), NULL, this ); - TestButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnTestButtonClick ), NULL, this ); - EncryptionAlgorithmHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmHyperlinkClick ), NULL, this ); - BenchmarkButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnBenchmarkButtonClick ), NULL, this ); - HashHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnHashHyperlinkClick ), NULL, this ); -} - -EncryptionOptionsWizardPageBase::~EncryptionOptionsWizardPageBase() -{ - // Disconnect Events - EncryptionAlgorithmChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmSelected ), NULL, this ); - TestButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnTestButtonClick ), NULL, this ); - EncryptionAlgorithmHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmHyperlinkClick ), NULL, this ); - BenchmarkButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnBenchmarkButtonClick ), NULL, this ); - HashHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnHashHyperlinkClick ), NULL, this ); -} - -InfoWizardPageBase::InfoWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer71; - bSizer71 = new wxBoxSizer( wxVERTICAL ); - - InfoPageSizer = new wxBoxSizer( wxVERTICAL ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - InfoPageSizer->Add( InfoStaticText, 1, wxALL|wxEXPAND, 5 ); - - bSizer71->Add( InfoPageSizer, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer71 ); - this->Layout(); - bSizer71->Fit( this ); -} - -InfoWizardPageBase::~InfoWizardPageBase() -{ -} - -KeyfilesPanelBase::KeyfilesPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer19; - bSizer19 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer20; - bSizer20 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer21; - bSizer21 = new wxBoxSizer( wxVERTICAL ); - - KeyfilesListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxSUNKEN_BORDER ); - bSizer21->Add( KeyfilesListCtrl, 1, wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer137; - bSizer137 = new wxBoxSizer( wxHORIZONTAL ); - - AddFilesButton = new wxButton( this, wxID_ANY, _("Add &Files..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer137->Add( AddFilesButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - AddDirectoryButton = new wxButton( this, wxID_ANY, _("Add &Path..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer137->Add( AddDirectoryButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - AddSecurityTokenSignatureButton = new wxButton( this, wxID_ANY, _("Add &Token Files..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer137->Add( AddSecurityTokenSignatureButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - RemoveButton = new wxButton( this, wxID_ANY, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer137->Add( RemoveButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - RemoveAllButton = new wxButton( this, wxID_ANY, _("Remove &All"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer137->Add( RemoveAllButton, 0, wxEXPAND|wxALL, 5 ); - - bSizer21->Add( bSizer137, 0, wxEXPAND, 5 ); - - bSizer20->Add( bSizer21, 1, wxEXPAND, 5 ); - - bSizer19->Add( bSizer20, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer19 ); - this->Layout(); - - // Connect Events - KeyfilesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemDeselected ), NULL, this ); - KeyfilesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemSelected ), NULL, this ); - KeyfilesListCtrl->Connect( wxEVT_SIZE, wxSizeEventHandler( KeyfilesPanelBase::OnListSizeChanged ), NULL, this ); - AddFilesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddFilesButtonClick ), NULL, this ); - AddDirectoryButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddDirectoryButtonClick ), NULL, this ); - AddSecurityTokenSignatureButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddSecurityTokenSignatureButtonClick ), NULL, this ); - RemoveButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveButtonClick ), NULL, this ); - RemoveAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveAllButtonClick ), NULL, this ); -} - -KeyfilesPanelBase::~KeyfilesPanelBase() -{ - // Disconnect Events - KeyfilesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemDeselected ), NULL, this ); - KeyfilesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemSelected ), NULL, this ); - KeyfilesListCtrl->Disconnect( wxEVT_SIZE, wxSizeEventHandler( KeyfilesPanelBase::OnListSizeChanged ), NULL, this ); - AddFilesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddFilesButtonClick ), NULL, this ); - AddDirectoryButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddDirectoryButtonClick ), NULL, this ); - AddSecurityTokenSignatureButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddSecurityTokenSignatureButtonClick ), NULL, this ); - RemoveButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveButtonClick ), NULL, this ); - RemoveAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveAllButtonClick ), NULL, this ); -} - -ProgressWizardPageBase::ProgressWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer81; - bSizer81 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer82; - bSizer82 = new wxBoxSizer( wxVERTICAL ); - - ProgressSizer = new wxBoxSizer( wxHORIZONTAL ); - - ProgressGauge = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,-1 ), wxGA_HORIZONTAL|wxGA_SMOOTH ); - ProgressGauge->SetValue( 0 ); - ProgressSizer->Add( ProgressGauge, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - AbortButton = new wxButton( this, wxID_ANY, _("&Abort"), wxDefaultPosition, wxDefaultSize, 0 ); - AbortButton->Enable( false ); - - ProgressSizer->Add( AbortButton, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer82->Add( ProgressSizer, 0, wxEXPAND, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer82->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); - - bSizer81->Add( bSizer82, 0, wxEXPAND, 5 ); - - this->SetSizer( bSizer81 ); - this->Layout(); - bSizer81->Fit( this ); - - // Connect Events - AbortButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); -} - -ProgressWizardPageBase::~ProgressWizardPageBase() -{ - // Disconnect Events - AbortButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); -} - -SelectDirectoryWizardPageBase::SelectDirectoryWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer68; - bSizer68 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer69; - bSizer69 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer70; - bSizer70 = new wxBoxSizer( wxHORIZONTAL ); - - DirectoryTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer70->Add( DirectoryTextCtrl, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - BrowseButton = new wxButton( this, wxID_ANY, _("&Browse..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer70->Add( BrowseButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer69->Add( bSizer70, 0, wxEXPAND, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( 300 ); - bSizer69->Add( InfoStaticText, 1, wxALL|wxEXPAND, 5 ); - - bSizer68->Add( bSizer69, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer68 ); - this->Layout(); - - // Connect Events - DirectoryTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnDirectoryTextChanged ), NULL, this ); - BrowseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnBrowseButtonClick ), NULL, this ); -} - -SelectDirectoryWizardPageBase::~SelectDirectoryWizardPageBase() -{ - // Disconnect Events - DirectoryTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnDirectoryTextChanged ), NULL, this ); - BrowseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnBrowseButtonClick ), NULL, this ); -} - -SingleChoiceWizardPageBase::SingleChoiceWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer71; - bSizer71 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer77; - bSizer77 = new wxBoxSizer( wxVERTICAL ); - - - bSizer77->Add( 0, 0, 0, wxEXPAND|wxTOP, 5 ); - - OuterChoicesSizer = new wxBoxSizer( wxVERTICAL ); - - ChoicesSizer = new wxBoxSizer( wxVERTICAL ); - - OuterChoicesSizer->Add( ChoicesSizer, 0, wxEXPAND, 5 ); - - bSizer77->Add( OuterChoicesSizer, 0, wxEXPAND, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer77->Add( InfoStaticText, 1, wxALL|wxEXPAND, 5 ); - - bSizer71->Add( bSizer77, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer71 ); - this->Layout(); - bSizer71->Fit( this ); -} - -SingleChoiceWizardPageBase::~SingleChoiceWizardPageBase() -{ -} - -TravelerMountOptionsWizardPageBase::TravelerMountOptionsWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer78; - bSizer78 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer79; - bSizer79 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer28; - sbSizer28 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxStaticText* m_staticText15; - m_staticText15 = new wxStaticText( this, wxID_ANY, _("TrueCrypt volume to mount:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText15->Wrap( -1 ); - sbSizer28->Add( m_staticText15, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer80; - bSizer80 = new wxBoxSizer( wxHORIZONTAL ); - - VolumePathTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer80->Add( VolumePathTextCtrl, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - SelectVolumeButton = new wxButton( this, wxID_ANY, _("Select..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer80->Add( SelectVolumeButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - sbSizer28->Add( bSizer80, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer81; - bSizer81 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* m_staticText16; - m_staticText16 = new wxStaticText( this, wxID_ANY, _("Mount volume as drive letter:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText16->Wrap( -1 ); - bSizer81->Add( m_staticText16, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - wxArrayString MountPointChoiceChoices; - MountPointChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, MountPointChoiceChoices, 0 ); - MountPointChoice->SetSelection( 0 ); - bSizer81->Add( MountPointChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer28->Add( bSizer81, 0, wxEXPAND, 5 ); - - BackgroundTaskCheckBox = new wxCheckBox( this, wxID_ANY, _("Enable Background Task until volume is dismounted"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer28->Add( BackgroundTaskCheckBox, 0, wxALL, 5 ); - - OpenExplorerCheckBox = new wxCheckBox( this, wxID_ANY, _("Open &Explorer window for mounted volume"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer28->Add( OpenExplorerCheckBox, 0, wxALL, 5 ); - - MountReadOnlyCheckBox = new wxCheckBox( this, wxID_ANY, _("Mount volume as read-&only"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer28->Add( MountReadOnlyCheckBox, 0, wxALL, 5 ); - - CachePasswordCheckBox = new wxCheckBox( this, wxID_ANY, _("Cach&e passwords and keyfiles in memory"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer28->Add( CachePasswordCheckBox, 0, wxALL, 5 ); - - bSizer79->Add( sbSizer28, 0, wxEXPAND, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer79->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); - - bSizer78->Add( bSizer79, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer78 ); - this->Layout(); - bSizer78->Fit( this ); - - // Connect Events - VolumePathTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( TravelerMountOptionsWizardPageBase::OnVolumePathTextChanged ), NULL, this ); - SelectVolumeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TravelerMountOptionsWizardPageBase::OnSelectVolumeButtonClick ), NULL, this ); -} - -TravelerMountOptionsWizardPageBase::~TravelerMountOptionsWizardPageBase() -{ - // Disconnect Events - VolumePathTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( TravelerMountOptionsWizardPageBase::OnVolumePathTextChanged ), NULL, this ); - SelectVolumeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TravelerMountOptionsWizardPageBase::OnSelectVolumeButtonClick ), NULL, this ); -} - -VolumeCreationProgressWizardPageBase::VolumeCreationProgressWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer104; - bSizer104 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer105; - bSizer105 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer31; - sbSizer31 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - KeySamplesUpperSizer = new wxBoxSizer( wxVERTICAL ); - - KeySamplesUpperInnerSizer = new wxBoxSizer( wxVERTICAL ); - - KeySamplesUpperSizer->Add( KeySamplesUpperInnerSizer, 1, wxEXPAND|wxTOP, 3 ); - - sbSizer31->Add( KeySamplesUpperSizer, 1, wxEXPAND, 30 ); - - wxFlexGridSizer* fgSizer5; - fgSizer5 = new wxFlexGridSizer( 3, 2, 0, 0 ); - fgSizer5->SetFlexibleDirection( wxBOTH ); - fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxStaticText* m_staticText25; - m_staticText25 = new wxStaticText( this, wxID_ANY, _("Random Pool:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText25->Wrap( -1 ); - fgSizer5->Add( m_staticText25, 0, wxALL|wxALIGN_RIGHT|wxALIGN_BOTTOM, 5 ); - - wxBoxSizer* bSizer126; - bSizer126 = new wxBoxSizer( wxHORIZONTAL ); - - RandomPoolSampleStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - RandomPoolSampleStaticText->Wrap( -1 ); - RandomPoolSampleStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); - - bSizer126->Add( RandomPoolSampleStaticText, 0, wxEXPAND|wxTOP|wxRIGHT|wxALIGN_BOTTOM, 7 ); - - DisplayKeysCheckBox = new wxCheckBox( this, wxID_ANY, _("Show"), wxDefaultPosition, wxDefaultSize, 0 ); - DisplayKeysCheckBox->SetValue(true); - - bSizer126->Add( DisplayKeysCheckBox, 0, wxEXPAND|wxRIGHT, 5 ); - - fgSizer5->Add( bSizer126, 1, wxEXPAND|wxALIGN_BOTTOM, 5 ); - - wxStaticText* m_staticText28; - m_staticText28 = new wxStaticText( this, wxID_ANY, _("Header Key:"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticText28->Wrap( -1 ); - fgSizer5->Add( m_staticText28, 0, wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_BOTTOM, 5 ); - - HeaderKeySampleStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - HeaderKeySampleStaticText->Wrap( -1 ); - HeaderKeySampleStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); - - fgSizer5->Add( HeaderKeySampleStaticText, 0, wxALIGN_BOTTOM|wxEXPAND|wxTOP|wxRIGHT, 2 ); - - wxStaticText* m_staticText29; - m_staticText29 = new wxStaticText( this, wxID_ANY, _("Master Key:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText29->Wrap( -1 ); - fgSizer5->Add( m_staticText29, 0, wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_BOTTOM, 5 ); - - MasterKeySampleStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - MasterKeySampleStaticText->Wrap( -1 ); - MasterKeySampleStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); - - fgSizer5->Add( MasterKeySampleStaticText, 0, wxEXPAND|wxALIGN_BOTTOM|wxTOP|wxRIGHT, 2 ); - - sbSizer31->Add( fgSizer5, 0, wxEXPAND, 5 ); - - bSizer105->Add( sbSizer31, 0, wxALL|wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer32; - sbSizer32 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxBoxSizer* bSizer106; - bSizer106 = new wxBoxSizer( wxHORIZONTAL ); - - ProgressGauge = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL|wxGA_SMOOTH ); - bSizer106->Add( ProgressGauge, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - AbortButton = new wxButton( this, wxID_ANY, _("Abort"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer106->Add( AbortButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - sbSizer32->Add( bSizer106, 0, wxEXPAND, 5 ); - - wxGridSizer* gSizer6; - gSizer6 = new wxGridSizer( 1, 3, 0, 0 ); - - wxBoxSizer* bSizer108; - bSizer108 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText31 = new wxStaticText( this, wxID_ANY, _("Done"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText31->Wrap( -1 ); - bSizer108->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_panel12 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxSUNKEN_BORDER ); - wxBoxSizer* bSizer115; - bSizer115 = new wxBoxSizer( wxHORIZONTAL ); - - SizeDoneStaticText = new wxStaticText( m_panel12, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT|wxST_NO_AUTORESIZE ); - SizeDoneStaticText->Wrap( -1 ); - bSizer115->Add( SizeDoneStaticText, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 3 ); - - m_panel12->SetSizer( bSizer115 ); - m_panel12->Layout(); - bSizer115->Fit( m_panel12 ); - bSizer108->Add( m_panel12, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - gSizer6->Add( bSizer108, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer1081; - bSizer1081 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText311 = new wxStaticText( this, wxID_ANY, _("Speed"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText311->Wrap( -1 ); - bSizer1081->Add( m_staticText311, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_panel121 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER ); - wxBoxSizer* bSizer1151; - bSizer1151 = new wxBoxSizer( wxHORIZONTAL ); - - SpeedStaticText = new wxStaticText( m_panel121, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT|wxST_NO_AUTORESIZE ); - SpeedStaticText->Wrap( -1 ); - bSizer1151->Add( SpeedStaticText, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 3 ); - - m_panel121->SetSizer( bSizer1151 ); - m_panel121->Layout(); - bSizer1151->Fit( m_panel121 ); - bSizer1081->Add( m_panel121, 1, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - gSizer6->Add( bSizer1081, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer1082; - bSizer1082 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText312 = new wxStaticText( this, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText312->Wrap( -1 ); - bSizer1082->Add( m_staticText312, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_panel122 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1152; - bSizer1152 = new wxBoxSizer( wxHORIZONTAL ); - - TimeLeftStaticText = new wxStaticText( m_panel122, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT|wxST_NO_AUTORESIZE ); - TimeLeftStaticText->Wrap( -1 ); - bSizer1152->Add( TimeLeftStaticText, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 3 ); - - m_panel122->SetSizer( bSizer1152 ); - m_panel122->Layout(); - bSizer1152->Fit( m_panel122 ); - bSizer1082->Add( m_panel122, 1, wxALL|wxEXPAND, 5 ); - - gSizer6->Add( bSizer1082, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - - sbSizer32->Add( gSizer6, 0, wxEXPAND|wxTOP, 2 ); - - bSizer105->Add( sbSizer32, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer105->Add( 0, 0, 0, wxTOP|wxBOTTOM, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer105->Add( InfoStaticText, 0, wxALL, 5 ); - - bSizer104->Add( bSizer105, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer104 ); - this->Layout(); - bSizer104->Fit( this ); - - // Connect Events - DisplayKeysCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnDisplayKeysCheckBoxClick ), NULL, this ); - AbortButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); -} - -VolumeCreationProgressWizardPageBase::~VolumeCreationProgressWizardPageBase() -{ - // Disconnect Events - DisplayKeysCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnDisplayKeysCheckBoxClick ), NULL, this ); - AbortButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); -} - -VolumeLocationWizardPageBase::VolumeLocationWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer86; - bSizer86 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer87; - bSizer87 = new wxBoxSizer( wxVERTICAL ); - - - bSizer87->Add( 0, 0, 0, wxEXPAND|wxTOP, 5 ); - - wxBoxSizer* bSizer88; - bSizer88 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer89; - bSizer89 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer126; - bSizer126 = new wxBoxSizer( wxHORIZONTAL ); - - VolumePathComboBox = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN ); - bSizer126->Add( VolumePathComboBox, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer90; - bSizer90 = new wxBoxSizer( wxVERTICAL ); - - SelectFileButton = new wxButton( this, wxID_ANY, _("Select &File..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer90->Add( SelectFileButton, 0, wxALL|wxEXPAND, 5 ); - - SelectDeviceButton = new wxButton( this, wxID_ANY, _("Select D&evice..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer90->Add( SelectDeviceButton, 0, wxALL|wxEXPAND, 5 ); - - bSizer126->Add( bSizer90, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer89->Add( bSizer126, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer91; - bSizer91 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer91->Add( 0, 0, 0, wxLEFT, 5 ); - - NoHistoryCheckBox = new wxCheckBox( this, wxID_ANY, _("&Never save history"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer91->Add( NoHistoryCheckBox, 0, wxALL|wxEXPAND, 5 ); - - bSizer89->Add( bSizer91, 0, wxEXPAND, 5 ); - - bSizer88->Add( bSizer89, 1, wxEXPAND, 5 ); - - bSizer87->Add( bSizer88, 0, wxEXPAND, 5 ); - - - bSizer87->Add( 0, 0, 0, wxEXPAND|wxBOTTOM, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer87->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); - - bSizer86->Add( bSizer87, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer86 ); - this->Layout(); - bSizer86->Fit( this ); - - // Connect Events - VolumePathComboBox->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnVolumePathTextChanged ), NULL, this ); - SelectFileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectFileButtonClick ), NULL, this ); - SelectDeviceButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectDeviceButtonClick ), NULL, this ); - NoHistoryCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnNoHistoryCheckBoxClick ), NULL, this ); -} - -VolumeLocationWizardPageBase::~VolumeLocationWizardPageBase() -{ - // Disconnect Events - VolumePathComboBox->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnVolumePathTextChanged ), NULL, this ); - SelectFileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectFileButtonClick ), NULL, this ); - SelectDeviceButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectDeviceButtonClick ), NULL, this ); - NoHistoryCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnNoHistoryCheckBoxClick ), NULL, this ); -} - -VolumeFormatOptionsWizardPageBase::VolumeFormatOptionsWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer124; - bSizer124 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer125; - bSizer125 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer33; - sbSizer33 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Filesystem Options") ), wxVERTICAL ); - - wxFlexGridSizer* fgSizer6; - fgSizer6 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer6->SetFlexibleDirection( wxBOTH ); - fgSizer6->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_staticText43 = new wxStaticText( this, wxID_ANY, _("Filesystem type:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText43->Wrap( -1 ); - fgSizer6->Add( m_staticText43, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - wxArrayString FilesystemTypeChoiceChoices; - FilesystemTypeChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, FilesystemTypeChoiceChoices, 0 ); - FilesystemTypeChoice->SetSelection( 0 ); - fgSizer6->Add( FilesystemTypeChoice, 0, wxALL, 5 ); - - sbSizer33->Add( fgSizer6, 1, wxEXPAND, 5 ); - - bSizer125->Add( sbSizer33, 0, wxEXPAND|wxALL, 5 ); - - wxStaticBoxSizer* sbSizer34; - sbSizer34 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Volume Format Options") ), wxVERTICAL ); - - QuickFormatCheckBox = new wxCheckBox( this, wxID_ANY, _("Quick format"), wxDefaultPosition, wxDefaultSize, 0 ); - - sbSizer34->Add( QuickFormatCheckBox, 0, wxALL, 5 ); - - bSizer125->Add( sbSizer34, 0, wxEXPAND|wxALL, 5 ); - - - bSizer125->Add( 0, 0, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer125->Add( InfoStaticText, 0, wxALL, 5 ); - - bSizer124->Add( bSizer125, 0, wxEXPAND, 5 ); - - this->SetSizer( bSizer124 ); - this->Layout(); - bSizer124->Fit( this ); - - // Connect Events - FilesystemTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnFilesystemTypeSelected ), NULL, this ); - QuickFormatCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnQuickFormatCheckBoxClick ), NULL, this ); -} - -VolumeFormatOptionsWizardPageBase::~VolumeFormatOptionsWizardPageBase() -{ - // Disconnect Events - FilesystemTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnFilesystemTypeSelected ), NULL, this ); - QuickFormatCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnQuickFormatCheckBoxClick ), NULL, this ); -} - -VolumePasswordPanelBase::VolumePasswordPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer7; - bSizer7 = new wxBoxSizer( wxVERTICAL ); - - GridBagSizer = new wxGridBagSizer( 0, 0 ); - GridBagSizer->AddGrowableCol( 1 ); - GridBagSizer->SetFlexibleDirection( wxBOTH ); - GridBagSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - GridBagSizer->SetEmptyCellSize( wxSize( 0,0 ) ); - - PasswordStaticText = new wxStaticText( this, wxID_ANY, _("Password:"), wxDefaultPosition, wxDefaultSize, 0 ); - PasswordStaticText->Wrap( -1 ); - GridBagSizer->Add( PasswordStaticText, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxBOTTOM|wxRIGHT, 5 ); - - PasswordTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD ); - PasswordTextCtrl->SetMaxLength( 1 ); - PasswordTextCtrl->SetMinSize( wxSize( 232,-1 ) ); - - GridBagSizer->Add( PasswordTextCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - ConfirmPasswordStaticText = new wxStaticText( this, wxID_ANY, _("Confirm password:"), wxDefaultPosition, wxDefaultSize, 0 ); - ConfirmPasswordStaticText->Wrap( -1 ); - GridBagSizer->Add( ConfirmPasswordStaticText, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); - - ConfirmPasswordTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD ); - ConfirmPasswordTextCtrl->SetMaxLength( 1 ); - ConfirmPasswordTextCtrl->SetMinSize( wxSize( 232,-1 ) ); - - GridBagSizer->Add( ConfirmPasswordTextCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - CacheCheckBox = new wxCheckBox( this, wxID_ANY, _("Cach&e passwords and keyfiles in memory "), wxDefaultPosition, wxDefaultSize, 0 ); - - GridBagSizer->Add( CacheCheckBox, wxGBPosition( 3, 1 ), wxGBSpan( 1, 2 ), wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - DisplayPasswordCheckBox = new wxCheckBox( this, wxID_ANY, _("&Display password"), wxDefaultPosition, wxDefaultSize, 0 ); - - GridBagSizer->Add( DisplayPasswordCheckBox, wxGBPosition( 4, 1 ), wxGBSpan( 1, 2 ), wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - UseKeyfilesCheckBox = new wxCheckBox( this, wxID_ANY, _("U&se keyfiles"), wxDefaultPosition, wxDefaultSize, 0 ); - - GridBagSizer->Add( UseKeyfilesCheckBox, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxTOP|wxRIGHT|wxLEFT, 5 ); - - KeyfilesButton = new wxButton( this, wxID_ANY, _("&Keyfiles..."), wxDefaultPosition, wxDefaultSize, 0 ); - GridBagSizer->Add( KeyfilesButton, wxGBPosition( 5, 2 ), wxGBSpan( 1, 1 ), wxALIGN_RIGHT|wxALIGN_BOTTOM|wxLEFT, 5 ); - - Pkcs5PrfSizer = new wxBoxSizer( wxVERTICAL ); - - GridBagSizer->Add( Pkcs5PrfSizer, wxGBPosition( 6, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - Pkcs5PrfStaticText = new wxStaticText( this, wxID_ANY, _("PKCS-5 PRF:"), wxDefaultPosition, wxDefaultSize, 0 ); - Pkcs5PrfStaticText->Wrap( -1 ); - GridBagSizer->Add( Pkcs5PrfStaticText, wxGBPosition( 7, 0 ), wxGBSpan( 1, 1 ), wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - wxString Pkcs5PrfChoiceChoices[] = { _("Unchanged") }; - int Pkcs5PrfChoiceNChoices = sizeof( Pkcs5PrfChoiceChoices ) / sizeof( wxString ); - Pkcs5PrfChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, Pkcs5PrfChoiceNChoices, Pkcs5PrfChoiceChoices, 0 ); - Pkcs5PrfChoice->SetSelection( 0 ); - GridBagSizer->Add( Pkcs5PrfChoice, wxGBPosition( 7, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - PasswordPlaceholderSizer = new wxBoxSizer( wxVERTICAL ); - - GridBagSizer->Add( PasswordPlaceholderSizer, wxGBPosition( 8, 1 ), wxGBSpan( 1, 2 ), wxTOP|wxEXPAND, 5 ); - - bSizer7->Add( GridBagSizer, 1, wxALL|wxEXPAND, 5 ); - - this->SetSizer( bSizer7 ); - this->Layout(); - bSizer7->Fit( this ); - - // Connect Events - PasswordTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); - ConfirmPasswordTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); - DisplayPasswordCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnDisplayPasswordCheckBoxClick ), NULL, this ); - UseKeyfilesCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnUseKeyfilesCheckBoxClick ), NULL, this ); - KeyfilesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonClick ), NULL, this ); - KeyfilesButton->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightDown ), NULL, this ); - KeyfilesButton->Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightClick ), NULL, this ); -} - -VolumePasswordPanelBase::~VolumePasswordPanelBase() -{ - // Disconnect Events - PasswordTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); - ConfirmPasswordTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); - DisplayPasswordCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnDisplayPasswordCheckBoxClick ), NULL, this ); - UseKeyfilesCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnUseKeyfilesCheckBoxClick ), NULL, this ); - KeyfilesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonClick ), NULL, this ); - KeyfilesButton->Disconnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightDown ), NULL, this ); - KeyfilesButton->Disconnect( wxEVT_RIGHT_UP, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightClick ), NULL, this ); -} - -VolumePasswordWizardPageBase::VolumePasswordWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer101; - bSizer101 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer102; - bSizer102 = new wxBoxSizer( wxVERTICAL ); - - PasswordPanelSizer = new wxBoxSizer( wxVERTICAL ); - - bSizer102->Add( PasswordPanelSizer, 0, wxEXPAND, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer102->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); - - bSizer101->Add( bSizer102, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer101 ); - this->Layout(); - bSizer101->Fit( this ); -} - -VolumePasswordWizardPageBase::~VolumePasswordWizardPageBase() -{ -} - -VolumeSizeWizardPageBase::VolumeSizeWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer98; - bSizer98 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer99; - bSizer99 = new wxBoxSizer( wxVERTICAL ); - - - bSizer99->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer100; - bSizer100 = new wxBoxSizer( wxHORIZONTAL ); - - VolumeSizeTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer100->Add( VolumeSizeTextCtrl, 0, wxALL, 5 ); - - wxArrayString VolumeSizePrefixChoiceChoices; - VolumeSizePrefixChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, VolumeSizePrefixChoiceChoices, 0 ); - VolumeSizePrefixChoice->SetSelection( 0 ); - bSizer100->Add( VolumeSizePrefixChoice, 0, wxALL, 5 ); - - bSizer99->Add( bSizer100, 0, wxEXPAND, 5 ); - - - bSizer99->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - FreeSpaceStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - FreeSpaceStaticText->Wrap( -1 ); - bSizer99->Add( FreeSpaceStaticText, 0, wxALL|wxEXPAND, 5 ); - - - bSizer99->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - InfoStaticText->Wrap( -1 ); - bSizer99->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); - - bSizer98->Add( bSizer99, 0, wxEXPAND, 5 ); - - this->SetSizer( bSizer98 ); - this->Layout(); - bSizer98->Fit( this ); - - // Connect Events - VolumeSizeTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizeTextChanged ), NULL, this ); - VolumeSizePrefixChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizePrefixSelected ), NULL, this ); -} - -VolumeSizeWizardPageBase::~VolumeSizeWizardPageBase() -{ - // Disconnect Events - VolumeSizeTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizeTextChanged ), NULL, this ); - VolumeSizePrefixChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizePrefixSelected ), NULL, this ); -} +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "System.h" + +#include "Forms.h" + +/////////////////////////////////////////////////////////////////////////// +using namespace TrueCrypt; + +MainFrameBase::MainFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( -1,496 ), wxDefaultSize ); + + MainMenuBar = new wxMenuBar( 0 ); + VolumesMenu = new wxMenu(); + MountVolumeMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Mount Volume") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( MountVolumeMenuItem ); + + wxMenuItem* AutoMountDevicesMenuItem; + AutoMountDevicesMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Auto-Mount All Device-Hosted Volumes") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( AutoMountDevicesMenuItem ); + + VolumesMenu->AppendSeparator(); + + DismountVolumeMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Dismount Volume") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( DismountVolumeMenuItem ); + + DismountAllMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Dismount All Mounted Volumes") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( DismountAllMenuItem ); + + VolumesMenu->AppendSeparator(); + + wxMenuItem* CreateNewVolumeMenuItem; + CreateNewVolumeMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Create New Volume...") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( CreateNewVolumeMenuItem ); + + wxMenuItem* ChangePasswordMenuItem; + ChangePasswordMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Change Volume Password...") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( ChangePasswordMenuItem ); + + wxMenuItem* ChangePkcs5PrfMenuItem; + ChangePkcs5PrfMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Change Header Key Derivation Algorithm...") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( ChangePkcs5PrfMenuItem ); + + VolumesMenu->AppendSeparator(); + + VolumePropertiesMenuItem = new wxMenuItem( VolumesMenu, wxID_ANY, wxString( _("Volume Properties...") ) , wxEmptyString, wxITEM_NORMAL ); + VolumesMenu->Append( VolumePropertiesMenuItem ); + + MainMenuBar->Append( VolumesMenu, _("&Volumes") ); + + KeyfilesMenu = new wxMenu(); + wxMenuItem* ChangeKeyfilesMenuItem; + ChangeKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Add/Remove Keyfiles to/from Volume...") ) , wxEmptyString, wxITEM_NORMAL ); + KeyfilesMenu->Append( ChangeKeyfilesMenuItem ); + + wxMenuItem* RemoveKeyfilesMenuItem; + RemoveKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Remove All Keyfiles from Volume...") ) , wxEmptyString, wxITEM_NORMAL ); + KeyfilesMenu->Append( RemoveKeyfilesMenuItem ); + + KeyfilesMenu->AppendSeparator(); + + wxMenuItem* CreateKeyfileMenuItem; + CreateKeyfileMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Generate Random Keyfile...") ) , wxEmptyString, wxITEM_NORMAL ); + KeyfilesMenu->Append( CreateKeyfileMenuItem ); + + KeyfilesMenu->AppendSeparator(); + + wxMenuItem* ManageSecurityTokenKeyfilesMenuItem; + ManageSecurityTokenKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Manage Security Token Keyfiles...") ) , wxEmptyString, wxITEM_NORMAL ); + KeyfilesMenu->Append( ManageSecurityTokenKeyfilesMenuItem ); + + wxMenuItem* CloseAllSecurityTokenSessionsMenuItem; + CloseAllSecurityTokenSessionsMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Close All Security Token Sessions") ) , wxEmptyString, wxITEM_NORMAL ); + KeyfilesMenu->Append( CloseAllSecurityTokenSessionsMenuItem ); + + KeyfilesMenu->AppendSeparator(); + + wxMenuItem* SetDefaultKeyfilesMenuItem; + SetDefaultKeyfilesMenuItem = new wxMenuItem( KeyfilesMenu, wxID_ANY, wxString( _("Set Default Keyfiles/Paths...") ) , wxEmptyString, wxITEM_NORMAL ); + KeyfilesMenu->Append( SetDefaultKeyfilesMenuItem ); + + MainMenuBar->Append( KeyfilesMenu, _("&Keyfiles") ); + + FavoritesMenu = new wxMenu(); + AddToFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Add Selected Volume...") ) , wxEmptyString, wxITEM_NORMAL ); + FavoritesMenu->Append( AddToFavoritesMenuItem ); + + AddAllMountedToFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Add All Mounted Volumes...") ) , wxEmptyString, wxITEM_NORMAL ); + FavoritesMenu->Append( AddAllMountedToFavoritesMenuItem ); + + wxMenuItem* OrganizeFavoritesMenuItem; + OrganizeFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Organize Favorite Volumes...") ) , wxEmptyString, wxITEM_NORMAL ); + FavoritesMenu->Append( OrganizeFavoritesMenuItem ); + + FavoritesMenu->AppendSeparator(); + + wxMenuItem* MountAllFavoritesMenuItem; + MountAllFavoritesMenuItem = new wxMenuItem( FavoritesMenu, wxID_ANY, wxString( _("Mount All Favorite Volumes") ) , wxEmptyString, wxITEM_NORMAL ); + FavoritesMenu->Append( MountAllFavoritesMenuItem ); + + FavoritesMenu->AppendSeparator(); + + MainMenuBar->Append( FavoritesMenu, _("&Favorites") ); + + ToolsMenu = new wxMenu(); + wxMenuItem* EncryptionTestMenuItem; + EncryptionTestMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Test Vectors...") ) , wxEmptyString, wxITEM_NORMAL ); + ToolsMenu->Append( EncryptionTestMenuItem ); + + ToolsMenu->AppendSeparator(); + + wxMenuItem* VolumeCreationWizardMenuItem; + VolumeCreationWizardMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Volume Creation Wizard") ) , wxEmptyString, wxITEM_NORMAL ); + ToolsMenu->Append( VolumeCreationWizardMenuItem ); + + ToolsMenu->AppendSeparator(); + + BackupVolumeHeadersMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Backup Volume Header...") ) , wxEmptyString, wxITEM_NORMAL ); + ToolsMenu->Append( BackupVolumeHeadersMenuItem ); + + RestoreVolumeHeaderMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Restore Volume Header...") ) , wxEmptyString, wxITEM_NORMAL ); + ToolsMenu->Append( RestoreVolumeHeaderMenuItem ); + + ToolsMenu->AppendSeparator(); + + WipeCachedPasswordsMenuItem = new wxMenuItem( ToolsMenu, wxID_ANY, wxString( _("Wipe Cached Passwords") ) , wxEmptyString, wxITEM_NORMAL ); + ToolsMenu->Append( WipeCachedPasswordsMenuItem ); + + MainMenuBar->Append( ToolsMenu, _("T&ools") ); + + SettingsMenu = new wxMenu(); + HotkeysMenuItem = new wxMenuItem( SettingsMenu, wxID_ANY, wxString( _("Hotkeys...") ) , wxEmptyString, wxITEM_NORMAL ); + SettingsMenu->Append( HotkeysMenuItem ); + + wxMenuItem* DefaultKeyfilesMenuItem; + DefaultKeyfilesMenuItem = new wxMenuItem( SettingsMenu, wxID_ANY, wxString( _("Default Keyfiles...") ) , wxEmptyString, wxITEM_NORMAL ); + SettingsMenu->Append( DefaultKeyfilesMenuItem ); + + wxMenuItem* SecurityTokenPreferencesMenuItem; + SecurityTokenPreferencesMenuItem = new wxMenuItem( SettingsMenu, wxID_ANY, wxString( _("Security Tokens...") ) , wxEmptyString, wxITEM_NORMAL ); + SettingsMenu->Append( SecurityTokenPreferencesMenuItem ); + + SettingsMenu->AppendSeparator(); + + PreferencesMenuItem = new wxMenuItem( SettingsMenu, wxID_PREFERENCES, wxString( _("&Preferences...") ) , wxEmptyString, wxITEM_NORMAL ); + SettingsMenu->Append( PreferencesMenuItem ); + + MainMenuBar->Append( SettingsMenu, _("Settin&gs") ); + + HelpMenu = new wxMenu(); + wxMenuItem* UserGuideMenuItem; + UserGuideMenuItem = new wxMenuItem( HelpMenu, wxID_HELP, wxString( _("User's Guide") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( UserGuideMenuItem ); + + wxMenuItem* OnlineHelpMenuItem; + OnlineHelpMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Online Help") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( OnlineHelpMenuItem ); + + wxMenuItem* BeginnersTutorialMenuItem; + BeginnersTutorialMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Beginner's Tutorial") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( BeginnersTutorialMenuItem ); + + wxMenuItem* FaqMenuItem; + FaqMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Frequently Asked Questions") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( FaqMenuItem ); + + HelpMenu->AppendSeparator(); + + wxMenuItem* WebsiteMenuItem; + WebsiteMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("TrueCrypt Website") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( WebsiteMenuItem ); + + wxMenuItem* DownloadsMenuItem; + DownloadsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Downloads") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( DownloadsMenuItem ); + + wxMenuItem* NewsMenuItem; + NewsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("News") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( NewsMenuItem ); + + HelpMenu->AppendSeparator(); + + wxMenuItem* VersionHistoryMenuItem; + VersionHistoryMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Version History") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( VersionHistoryMenuItem ); + + wxMenuItem* LegalNoticesMenuItem; + LegalNoticesMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Legal Notices") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( LegalNoticesMenuItem ); + + HelpMenu->AppendSeparator(); + + wxMenuItem* ReportBugMenuItem; + ReportBugMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Report a Bug...") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( ReportBugMenuItem ); + + wxMenuItem* ForumsMenuItem; + ForumsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Forums") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( ForumsMenuItem ); + + wxMenuItem* ContactMenuItem; + ContactMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Contact...") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( ContactMenuItem ); + + HelpMenu->AppendSeparator(); + + wxMenuItem* DonationsMenuItem; + DonationsMenuItem = new wxMenuItem( HelpMenu, wxID_ANY, wxString( _("Donations...") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( DonationsMenuItem ); + + HelpMenu->AppendSeparator(); + + wxMenuItem* AboutMenuItem; + AboutMenuItem = new wxMenuItem( HelpMenu, wxID_ABOUT, wxString( _("About...") ) , wxEmptyString, wxITEM_NORMAL ); + HelpMenu->Append( AboutMenuItem ); + + MainMenuBar->Append( HelpMenu, _("&Help") ); + + this->SetMenuBar( MainMenuBar ); + + wxBoxSizer* bSizer1; + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + MainPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer48; + bSizer48 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer1; + sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + SlotListCtrl = new wxListCtrl( MainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxSUNKEN_BORDER ); + SlotListCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) ); + + sbSizer1->Add( SlotListCtrl, 1, wxALL|wxEXPAND, 5 ); + + bSizer48->Add( sbSizer1, 1, wxEXPAND, 5 ); + + LowStaticBoxSizer = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + HigherButtonSizer = new wxBoxSizer( wxVERTICAL ); + + LowStaticBoxSizer->Add( HigherButtonSizer, 0, wxEXPAND|wxTOP, 2 ); + + wxGridSizer* gSizer1; + gSizer1 = new wxGridSizer( 1, 3, 0, 0 ); + + wxBoxSizer* bSizer17; + bSizer17 = new wxBoxSizer( wxVERTICAL ); + + bSizer17->SetMinSize( wxSize( 138,34 ) ); + CreateVolumeButton = new wxButton( MainPanel, wxID_ANY, _("&Create Volume"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer17->Add( CreateVolumeButton, 1, wxALL|wxEXPAND, 5 ); + + gSizer1->Add( bSizer17, 0, 0, 5 ); + + wxBoxSizer* bSizer18; + bSizer18 = new wxBoxSizer( wxVERTICAL ); + + bSizer18->SetMinSize( wxSize( 138,34 ) ); + VolumePropertiesButton = new wxButton( MainPanel, wxID_ANY, _("&Volume Properties..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer18->Add( VolumePropertiesButton, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + gSizer1->Add( bSizer18, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer19; + bSizer19 = new wxBoxSizer( wxVERTICAL ); + + bSizer19->SetMinSize( wxSize( 138,34 ) ); + WipeCacheButton = new wxButton( MainPanel, wxID_ANY, _("&Wipe Cache"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer19->Add( WipeCacheButton, 1, wxALL|wxALIGN_RIGHT|wxEXPAND, 5 ); + + gSizer1->Add( bSizer19, 0, wxALIGN_RIGHT, 5 ); + + LowStaticBoxSizer->Add( gSizer1, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + + LowStaticBoxSizer->Add( 0, 0, 0, 0, 5 ); + + VolumeStaticBoxSizer = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, _("Volume") ), wxVERTICAL ); + + VolumeGridBagSizer = new wxGridBagSizer( 0, 0 ); + VolumeGridBagSizer->AddGrowableCol( 1 ); + VolumeGridBagSizer->AddGrowableRow( 0 ); + VolumeGridBagSizer->SetFlexibleDirection( wxBOTH ); + VolumeGridBagSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + LogoBitmap = new wxStaticBitmap( MainPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER ); + LogoBitmap->SetMinSize( wxSize( 42,52 ) ); + + VolumeGridBagSizer->Add( LogoBitmap, wxGBPosition( 0, 0 ), wxGBSpan( 2, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + VolumePathComboBox = new wxComboBox( MainPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN ); + VolumeGridBagSizer->Add( VolumePathComboBox, wxGBPosition( 0, 1 ), wxGBSpan( 1, 2 ), wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer191; + bSizer191 = new wxBoxSizer( wxVERTICAL ); + + bSizer191->SetMinSize( wxSize( 138,34 ) ); + SelectFileButton = new wxButton( MainPanel, wxID_ANY, _("Select &File..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer191->Add( SelectFileButton, 1, wxALL|wxEXPAND, 5 ); + + VolumeGridBagSizer->Add( bSizer191, wxGBPosition( 0, 3 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 ); + + NoHistoryCheckBox = new wxCheckBox( MainPanel, wxID_ANY, _("&Never save history"), wxDefaultPosition, wxDefaultSize, 0 ); + + VolumeGridBagSizer->Add( NoHistoryCheckBox, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer20; + bSizer20 = new wxBoxSizer( wxVERTICAL ); + + bSizer20->SetMinSize( wxSize( 138,34 ) ); + VolumeToolsButton = new wxButton( MainPanel, wxID_ANY, _("Volume &Tools..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer20->Add( VolumeToolsButton, 1, wxALL|wxEXPAND, 5 ); + + VolumeGridBagSizer->Add( bSizer20, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_RIGHT, 5 ); + + wxBoxSizer* bSizer21; + bSizer21 = new wxBoxSizer( wxVERTICAL ); + + bSizer21->SetMinSize( wxSize( 138,34 ) ); + SelectDeviceButton = new wxButton( MainPanel, wxID_ANY, _("Select D&evice..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer21->Add( SelectDeviceButton, 1, wxEXPAND|wxALL, 5 ); + + VolumeGridBagSizer->Add( bSizer21, wxGBPosition( 1, 3 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 ); + + VolumeStaticBoxSizer->Add( VolumeGridBagSizer, 1, wxEXPAND|wxALL, 4 ); + + LowStaticBoxSizer->Add( VolumeStaticBoxSizer, 1, wxEXPAND, 5 ); + + + LowStaticBoxSizer->Add( 0, 0, 0, 0, 5 ); + + wxGridSizer* gSizer2; + gSizer2 = new wxGridSizer( 1, 4, 0, 0 ); + + wxStaticBoxSizer* sbSizer4; + sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + sbSizer4->SetMinSize( wxSize( 139,-1 ) ); + VolumeButton = new wxButton( MainPanel, wxID_ANY, _("&Mount"), wxDefaultPosition, wxDefaultSize, 0 ); + VolumeButton->SetDefault(); + VolumeButton->SetMinSize( wxSize( -1,32 ) ); + + sbSizer4->Add( VolumeButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); + + gSizer2->Add( sbSizer4, 1, wxEXPAND, 0 ); + + wxStaticBoxSizer* sbSizer41; + sbSizer41 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + MountAllDevicesButton = new wxButton( MainPanel, wxID_ANY, _("&Auto-Mount Devices"), wxDefaultPosition, wxDefaultSize, 0 ); + MountAllDevicesButton->SetMinSize( wxSize( -1,32 ) ); + + sbSizer41->Add( MountAllDevicesButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); + + gSizer2->Add( sbSizer41, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer42; + sbSizer42 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + DismountAllButton = new wxButton( MainPanel, wxID_ANY, _("Di&smount All"), wxDefaultPosition, wxDefaultSize, 0 ); + DismountAllButton->SetMinSize( wxSize( -1,32 ) ); + + sbSizer42->Add( DismountAllButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); + + gSizer2->Add( sbSizer42, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer43; + sbSizer43 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + ExitButton = new wxButton( MainPanel, wxID_ANY, _("E&xit"), wxDefaultPosition, wxDefaultSize, 0 ); + ExitButton->SetMinSize( wxSize( -1,32 ) ); + + sbSizer43->Add( ExitButton, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 2 ); + + gSizer2->Add( sbSizer43, 1, wxALIGN_RIGHT|wxEXPAND, 5 ); + + LowStaticBoxSizer->Add( gSizer2, 0, wxEXPAND, 5 ); + + bSizer48->Add( LowStaticBoxSizer, 0, wxEXPAND, 5 ); + + bSizer2->Add( bSizer48, 1, wxEXPAND, 5 ); + + MainPanel->SetSizer( bSizer2 ); + MainPanel->Layout(); + bSizer2->Fit( MainPanel ); + bSizer1->Add( MainPanel, 1, wxEXPAND, 0 ); + + this->SetSizer( bSizer1 ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_ACTIVATE, wxActivateEventHandler( MainFrameBase::OnActivate ) ); + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainFrameBase::OnClose ) ); + this->Connect( MountVolumeMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountVolumeMenuItemSelected ) ); + this->Connect( AutoMountDevicesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ) ); + this->Connect( DismountVolumeMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountVolumeMenuItemSelected ) ); + this->Connect( DismountAllMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ) ); + this->Connect( CreateNewVolumeMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); + this->Connect( ChangePasswordMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePasswordMenuItemSelected ) ); + this->Connect( ChangePkcs5PrfMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePkcs5PrfMenuItemSelected ) ); + this->Connect( VolumePropertiesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ) ); + this->Connect( ChangeKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangeKeyfilesMenuItemSelected ) ); + this->Connect( RemoveKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRemoveKeyfilesMenuItemSelected ) ); + this->Connect( CreateKeyfileMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateKeyfileMenuItemSelected ) ); + this->Connect( ManageSecurityTokenKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnManageSecurityTokenKeyfilesMenuItemSelected ) ); + this->Connect( CloseAllSecurityTokenSessionsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCloseAllSecurityTokenSessionsMenuItemSelected ) ); + this->Connect( SetDefaultKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); + this->Connect( AddToFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddToFavoritesMenuItemSelected ) ); + this->Connect( AddAllMountedToFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddAllMountedToFavoritesMenuItemSelected ) ); + this->Connect( OrganizeFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOrganizeFavoritesMenuItemSelected ) ); + this->Connect( MountAllFavoritesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllFavoritesMenuItemSelected ) ); + this->Connect( EncryptionTestMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnEncryptionTestMenuItemSelected ) ); + this->Connect( VolumeCreationWizardMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); + this->Connect( BackupVolumeHeadersMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBackupVolumeHeadersMenuItemSelected ) ); + this->Connect( RestoreVolumeHeaderMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRestoreVolumeHeaderMenuItemSelected ) ); + this->Connect( WipeCachedPasswordsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ) ); + this->Connect( HotkeysMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnHotkeysMenuItemSelected ) ); + this->Connect( DefaultKeyfilesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); + this->Connect( SecurityTokenPreferencesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnSecurityTokenPreferencesMenuItemSelected ) ); + this->Connect( PreferencesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnPreferencesMenuItemSelected ) ); + this->Connect( UserGuideMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnUserGuideMenuItemSelected ) ); + this->Connect( OnlineHelpMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOnlineHelpMenuItemSelected ) ); + this->Connect( BeginnersTutorialMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBeginnersTutorialMenuItemSelected ) ); + this->Connect( FaqMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnFaqMenuItemSelected ) ); + this->Connect( WebsiteMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWebsiteMenuItemSelected ) ); + this->Connect( DownloadsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDownloadsMenuItemSelected ) ); + this->Connect( NewsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnNewsMenuItemSelected ) ); + this->Connect( VersionHistoryMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVersionHistoryMenuItemSelected ) ); + this->Connect( LegalNoticesMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnLegalNoticesMenuItemSelected ) ); + this->Connect( ReportBugMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnReportBugMenuItemSelected ) ); + this->Connect( ForumsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnForumsMenuItemSelected ) ); + this->Connect( ContactMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnContactMenuItemSelected ) ); + this->Connect( DonationsMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDonationsMenuItemSelected ) ); + this->Connect( AboutMenuItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAboutMenuItemSelected ) ); + SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( MainFrameBase::OnListItemActivated ), NULL, this ); + SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( MainFrameBase::OnListItemDeselected ), NULL, this ); + SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( MainFrameBase::OnListItemRightClick ), NULL, this ); + SlotListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( MainFrameBase::OnListItemSelected ), NULL, this ); + CreateVolumeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ), NULL, this ); + VolumePropertiesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ), NULL, this ); + WipeCacheButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ), NULL, this ); + LogoBitmap->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( MainFrameBase::OnLogoBitmapClick ), NULL, this ); + SelectFileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectFileButtonClick ), NULL, this ); + NoHistoryCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrameBase::OnNoHistoryCheckBoxClick ), NULL, this ); + VolumeToolsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeToolsButtonClick ), NULL, this ); + SelectDeviceButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectDeviceButtonClick ), NULL, this ); + VolumeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeButtonClick ), NULL, this ); + MountAllDevicesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ), NULL, this ); + DismountAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ), NULL, this ); + ExitButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnExitButtonClick ), NULL, this ); +} + +MainFrameBase::~MainFrameBase() +{ + // Disconnect Events + this->Disconnect( wxEVT_ACTIVATE, wxActivateEventHandler( MainFrameBase::OnActivate ) ); + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainFrameBase::OnClose ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountVolumeMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountVolumeMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePasswordMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangePkcs5PrfMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnChangeKeyfilesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRemoveKeyfilesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateKeyfileMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnManageSecurityTokenKeyfilesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCloseAllSecurityTokenSessionsMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddToFavoritesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAddAllMountedToFavoritesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOrganizeFavoritesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnMountAllFavoritesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnEncryptionTestMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBackupVolumeHeadersMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnRestoreVolumeHeaderMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnHotkeysMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDefaultKeyfilesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnSecurityTokenPreferencesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnPreferencesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnUserGuideMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnOnlineHelpMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnBeginnersTutorialMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnFaqMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnWebsiteMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDownloadsMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnNewsMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnVersionHistoryMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnLegalNoticesMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnReportBugMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnForumsMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnContactMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnDonationsMenuItemSelected ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrameBase::OnAboutMenuItemSelected ) ); + SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( MainFrameBase::OnListItemActivated ), NULL, this ); + SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( MainFrameBase::OnListItemDeselected ), NULL, this ); + SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( MainFrameBase::OnListItemRightClick ), NULL, this ); + SlotListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( MainFrameBase::OnListItemSelected ), NULL, this ); + CreateVolumeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnCreateVolumeButtonClick ), NULL, this ); + VolumePropertiesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumePropertiesButtonClick ), NULL, this ); + WipeCacheButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnWipeCacheButtonClick ), NULL, this ); + LogoBitmap->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( MainFrameBase::OnLogoBitmapClick ), NULL, this ); + SelectFileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectFileButtonClick ), NULL, this ); + NoHistoryCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainFrameBase::OnNoHistoryCheckBoxClick ), NULL, this ); + VolumeToolsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeToolsButtonClick ), NULL, this ); + SelectDeviceButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnSelectDeviceButtonClick ), NULL, this ); + VolumeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnVolumeButtonClick ), NULL, this ); + MountAllDevicesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnMountAllDevicesButtonClick ), NULL, this ); + DismountAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnDismountAllButtonClick ), NULL, this ); + ExitButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrameBase::OnExitButtonClick ), NULL, this ); +} + +WizardFrameBase::WizardFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer92; + bSizer92 = new wxBoxSizer( wxVERTICAL ); + + MainPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer63; + bSizer63 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer64; + bSizer64 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer27; + sbSizer27 = new wxStaticBoxSizer( new wxStaticBox( MainPanel, wxID_ANY, wxEmptyString ), wxHORIZONTAL ); + + WizardBitmap = new wxStaticBitmap( MainPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer27->Add( WizardBitmap, 0, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer66; + bSizer66 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer126; + bSizer126 = new wxBoxSizer( wxHORIZONTAL ); + + PageTitleStaticText = new wxStaticText( MainPanel, wxID_ANY, _("Page Title"), wxDefaultPosition, wxDefaultSize, 0 ); + PageTitleStaticText->Wrap( -1 ); + PageTitleStaticText->SetFont( wxFont( 16, 70, 90, 90, false, wxT("Times New Roman") ) ); + + bSizer126->Add( PageTitleStaticText, 0, wxALL, 5 ); + + bSizer66->Add( bSizer126, 0, wxLEFT, 5 ); + + PageSizer = new wxBoxSizer( wxVERTICAL ); + + bSizer66->Add( PageSizer, 1, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + sbSizer27->Add( bSizer66, 1, wxEXPAND|wxLEFT, 5 ); + + bSizer64->Add( sbSizer27, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer70; + bSizer70 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer70->Add( 0, 0, 1, wxEXPAND, 5 ); + + HelpButton = new wxButton( MainPanel, wxID_HELP, _("&Help"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer70->Add( HelpButton, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer70->Add( 0, 0, 0, wxLEFT|wxALIGN_RIGHT, 5 ); + + PreviousButton = new wxButton( MainPanel, wxID_ANY, _("< &Prev"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer70->Add( PreviousButton, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + NextButton = new wxButton( MainPanel, wxID_ANY, _("&Next >"), wxDefaultPosition, wxDefaultSize, 0|wxWANTS_CHARS ); + NextButton->SetDefault(); + bSizer70->Add( NextButton, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer70->Add( 0, 0, 0, wxLEFT|wxALIGN_RIGHT, 5 ); + + CancelButton = new wxButton( MainPanel, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer70->Add( CancelButton, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer64->Add( bSizer70, 0, wxEXPAND|wxALIGN_RIGHT|wxALL, 5 ); + + bSizer63->Add( bSizer64, 1, wxEXPAND, 5 ); + + MainPanel->SetSizer( bSizer63 ); + MainPanel->Layout(); + bSizer63->Fit( MainPanel ); + bSizer92->Add( MainPanel, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer92 ); + this->Layout(); + bSizer92->Fit( this ); + + // Connect Events + this->Connect( wxEVT_ACTIVATE, wxActivateEventHandler( WizardFrameBase::OnActivate ) ); + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WizardFrameBase::OnClose ) ); + MainPanel->Connect( wxEVT_MOTION, wxMouseEventHandler( WizardFrameBase::OnMouseMotion ), NULL, this ); + HelpButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnHelpButtonClick ), NULL, this ); + PreviousButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnPreviousButtonClick ), NULL, this ); + NextButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnNextButtonClick ), NULL, this ); + CancelButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnCancelButtonClick ), NULL, this ); +} + +WizardFrameBase::~WizardFrameBase() +{ + // Disconnect Events + this->Disconnect( wxEVT_ACTIVATE, wxActivateEventHandler( WizardFrameBase::OnActivate ) ); + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WizardFrameBase::OnClose ) ); + MainPanel->Disconnect( wxEVT_MOTION, wxMouseEventHandler( WizardFrameBase::OnMouseMotion ), NULL, this ); + HelpButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnHelpButtonClick ), NULL, this ); + PreviousButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnPreviousButtonClick ), NULL, this ); + NextButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnNextButtonClick ), NULL, this ); + CancelButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WizardFrameBase::OnCancelButtonClick ), NULL, this ); +} + +AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer116; + bSizer116 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer117; + bSizer117 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer120; + bSizer120 = new wxBoxSizer( wxVERTICAL ); + + bSizer120->SetMinSize( wxSize( -1,78 ) ); + m_panel14 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel14->SetBackgroundColour( wxColour( 10, 108, 206 ) ); + + wxBoxSizer* bSizer121; + bSizer121 = new wxBoxSizer( wxVERTICAL ); + + + bSizer121->Add( 0, 0, 1, wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer122; + bSizer122 = new wxBoxSizer( wxVERTICAL ); + + LogoBitmap = new wxStaticBitmap( m_panel14, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer122->Add( LogoBitmap, 0, wxALL, 10 ); + + bSizer121->Add( bSizer122, 0, wxEXPAND|wxLEFT, 8 ); + + m_panel14->SetSizer( bSizer121 ); + m_panel14->Layout(); + bSizer121->Fit( m_panel14 ); + bSizer120->Add( m_panel14, 1, wxEXPAND, 5 ); + + bSizer117->Add( bSizer120, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer118; + bSizer118 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer123; + bSizer123 = new wxBoxSizer( wxVERTICAL ); + + VersionStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + VersionStaticText->Wrap( -1 ); + VersionStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); + + bSizer123->Add( VersionStaticText, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + bSizer123->Add( 0, 0, 0, wxTOP, 3 ); + + CopyrightStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + CopyrightStaticText->Wrap( -1 ); + bSizer123->Add( CopyrightStaticText, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + bSizer123->Add( 0, 0, 0, wxTOP, 3 ); + + WebsiteHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, wxEmptyString, wxT("."), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + + WebsiteHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + WebsiteHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + WebsiteHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + bSizer123->Add( WebsiteHyperlink, 0, wxALL, 5 ); + + bSizer118->Add( bSizer123, 1, wxEXPAND|wxLEFT, 5 ); + + bSizer117->Add( bSizer118, 1, wxALL|wxEXPAND, 15 ); + + m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer117->Add( m_staticline3, 0, wxEXPAND|wxBOTTOM, 5 ); + + CreditsTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxSUNKEN_BORDER ); + bSizer117->Add( CreditsTextCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + + + bSizer117->Add( 0, 0, 0, wxTOP, 5 ); + + m_staticline4 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer117->Add( m_staticline4, 0, wxEXPAND|wxTOP|wxBOTTOM, 3 ); + + m_staticline5 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer117->Add( m_staticline5, 0, wxEXPAND|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer119; + bSizer119 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer119->Add( 0, 0, 1, wxEXPAND|wxALL, 5 ); + + DonationsButton = new wxButton( this, wxID_ANY, _("Donations..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer119->Add( DonationsButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxButton* OKButton; + OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + OKButton->SetDefault(); + bSizer119->Add( OKButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer119->Add( 0, 0, 0, wxLEFT, 5 ); + + bSizer117->Add( bSizer119, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 6 ); + + bSizer116->Add( bSizer117, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer116 ); + this->Layout(); + bSizer116->Fit( this ); + + // Connect Events + WebsiteHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( AboutDialogBase::OnWebsiteHyperlinkClick ), NULL, this ); + DonationsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDialogBase::OnDonationsButtonClick ), NULL, this ); +} + +AboutDialogBase::~AboutDialogBase() +{ + // Disconnect Events + WebsiteHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( AboutDialogBase::OnWebsiteHyperlinkClick ), NULL, this ); + DonationsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDialogBase::OnDonationsButtonClick ), NULL, this ); +} + +ChangePasswordDialogBase::ChangePasswordDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); + + wxBoxSizer* bSizer30; + bSizer30 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer31; + bSizer31 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer32; + bSizer32 = new wxBoxSizer( wxVERTICAL ); + + CurrentSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Current") ), wxVERTICAL ); + + CurrentPasswordPanelSizer = new wxBoxSizer( wxVERTICAL ); + + CurrentSizer->Add( CurrentPasswordPanelSizer, 0, wxALIGN_RIGHT, 5 ); + + bSizer32->Add( CurrentSizer, 0, wxEXPAND, 5 ); + + NewSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("New") ), wxVERTICAL ); + + NewPasswordPanelSizer = new wxBoxSizer( wxVERTICAL ); + + NewSizer->Add( NewPasswordPanelSizer, 0, wxALIGN_RIGHT, 5 ); + + bSizer32->Add( NewSizer, 0, wxTOP|wxEXPAND, 5 ); + + bSizer31->Add( bSizer32, 1, wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer33; + bSizer33 = new wxBoxSizer( wxVERTICAL ); + + OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + OKButton->SetDefault(); + bSizer33->Add( OKButton, 0, wxALL|wxEXPAND, 5 ); + + CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer33->Add( CancelButton, 0, wxALL|wxEXPAND, 5 ); + + bSizer31->Add( bSizer33, 0, 0, 5 ); + + bSizer30->Add( bSizer31, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer30 ); + this->Layout(); + bSizer30->Fit( this ); + + // Connect Events + OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ChangePasswordDialogBase::OnOKButtonClick ), NULL, this ); +} + +ChangePasswordDialogBase::~ChangePasswordDialogBase() +{ + // Disconnect Events + OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ChangePasswordDialogBase::OnOKButtonClick ), NULL, this ); +} + +DeviceSelectionDialogBase::DeviceSelectionDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); + this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); + + wxBoxSizer* bSizer3; + bSizer3 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer4; + bSizer4 = new wxBoxSizer( wxVERTICAL ); + + DeviceListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxSUNKEN_BORDER ); + bSizer4->Add( DeviceListCtrl, 1, wxALL|wxEXPAND, 5 ); + + StdButtons = new wxStdDialogButtonSizer(); + StdButtonsOK = new wxButton( this, wxID_OK ); + StdButtons->AddButton( StdButtonsOK ); + StdButtonsCancel = new wxButton( this, wxID_CANCEL ); + StdButtons->AddButton( StdButtonsCancel ); + StdButtons->Realize(); + bSizer4->Add( StdButtons, 0, wxEXPAND|wxALL, 5 ); + + bSizer3->Add( bSizer4, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer3 ); + this->Layout(); + bSizer3->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + DeviceListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemActivated ), NULL, this ); + DeviceListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemDeselected ), NULL, this ); + DeviceListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemSelected ), NULL, this ); +} + +DeviceSelectionDialogBase::~DeviceSelectionDialogBase() +{ + // Disconnect Events + DeviceListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemActivated ), NULL, this ); + DeviceListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemDeselected ), NULL, this ); + DeviceListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( DeviceSelectionDialogBase::OnListItemSelected ), NULL, this ); +} + +EncryptionTestDialogBase::EncryptionTestDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer132; + bSizer132 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer133; + bSizer133 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer134; + bSizer134 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticText* m_staticText41; + m_staticText41 = new wxStaticText( this, wxID_ANY, _("Encryption algorithm:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText41->Wrap( -1 ); + bSizer134->Add( m_staticText41, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + wxArrayString EncryptionAlgorithmChoiceChoices; + EncryptionAlgorithmChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, EncryptionAlgorithmChoiceChoices, 0 ); + EncryptionAlgorithmChoice->SetSelection( 0 ); + bSizer134->Add( EncryptionAlgorithmChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + XtsModeCheckBox = new wxCheckBox( this, wxID_ANY, _("XTS mode"), wxDefaultPosition, wxDefaultSize, 0 ); + XtsModeCheckBox->SetValue(true); + + bSizer134->Add( XtsModeCheckBox, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer133->Add( bSizer134, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxStaticBoxSizer* sbSizer38; + sbSizer38 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Key (hexadecimal)") ), wxVERTICAL ); + + KeyTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + KeyTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); + + sbSizer38->Add( KeyTextCtrl, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer135; + bSizer135 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticText* m_staticText43; + m_staticText43 = new wxStaticText( this, wxID_ANY, _("Key size:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText43->Wrap( -1 ); + bSizer135->Add( m_staticText43, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + KeySizeStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + KeySizeStaticText->Wrap( -1 ); + bSizer135->Add( KeySizeStaticText, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); + + sbSizer38->Add( bSizer135, 0, wxEXPAND, 5 ); + + bSizer133->Add( sbSizer38, 0, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer39; + sbSizer39 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("XTS mode") ), wxVERTICAL ); + + wxStaticText* m_staticText45; + m_staticText45 = new wxStaticText( this, wxID_ANY, _("Secondary key (hexadecimal)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText45->Wrap( -1 ); + sbSizer39->Add( m_staticText45, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + SecondaryKeyTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + SecondaryKeyTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); + + sbSizer39->Add( SecondaryKeyTextCtrl, 0, wxEXPAND|wxALL, 5 ); + + wxStaticText* m_staticText46; + m_staticText46 = new wxStaticText( this, wxID_ANY, _("Data unit number (64-bit, data unit size is 512 bytes)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText46->Wrap( -1 ); + sbSizer39->Add( m_staticText46, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + DataUnitNumberTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer39->Add( DataUnitNumberTextCtrl, 0, wxALL, 5 ); + + wxStaticText* m_staticText47; + m_staticText47 = new wxStaticText( this, wxID_ANY, _("Block number:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText47->Wrap( -1 ); + sbSizer39->Add( m_staticText47, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + BlockNumberTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer39->Add( BlockNumberTextCtrl, 0, wxALL, 5 ); + + bSizer133->Add( sbSizer39, 1, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer40; + sbSizer40 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Plaintext (hexadecimal)") ), wxVERTICAL ); + + PlainTextTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + PlainTextTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); + + sbSizer40->Add( PlainTextTextCtrl, 0, wxALL|wxEXPAND, 5 ); + + bSizer133->Add( sbSizer40, 0, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer41; + sbSizer41 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Ciphertext (hexadecimal)") ), wxVERTICAL ); + + CipherTextTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + CipherTextTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier") ) ); + + sbSizer41->Add( CipherTextTextCtrl, 0, wxALL|wxEXPAND, 5 ); + + bSizer133->Add( sbSizer41, 0, wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer136; + bSizer136 = new wxBoxSizer( wxHORIZONTAL ); + + EncryptButton = new wxButton( this, wxID_ANY, _("&Encrypt"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer136->Add( EncryptButton, 0, wxALL, 5 ); + + DecryptButton = new wxButton( this, wxID_ANY, _("&Decrypt"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer136->Add( DecryptButton, 0, wxALL, 5 ); + + AutoTestAllButton = new wxButton( this, wxID_ANY, _("&Auto-Test All"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer136->Add( AutoTestAllButton, 0, wxALL, 5 ); + + ResetButton = new wxButton( this, wxID_ANY, _("&Reset"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer136->Add( ResetButton, 0, wxALL, 5 ); + + CloseButton = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer136->Add( CloseButton, 0, wxALL, 5 ); + + bSizer133->Add( bSizer136, 0, wxEXPAND, 5 ); + + bSizer132->Add( bSizer133, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer132 ); + this->Layout(); + bSizer132->Fit( this ); + + // Connect Events + EncryptionAlgorithmChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptionAlgorithmSelected ), NULL, this ); + XtsModeCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnXtsModeCheckBoxClick ), NULL, this ); + EncryptButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptButtonClick ), NULL, this ); + DecryptButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnDecryptButtonClick ), NULL, this ); + AutoTestAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnAutoTestAllButtonClick ), NULL, this ); + ResetButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnResetButtonClick ), NULL, this ); +} + +EncryptionTestDialogBase::~EncryptionTestDialogBase() +{ + // Disconnect Events + EncryptionAlgorithmChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptionAlgorithmSelected ), NULL, this ); + XtsModeCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnXtsModeCheckBoxClick ), NULL, this ); + EncryptButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnEncryptButtonClick ), NULL, this ); + DecryptButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnDecryptButtonClick ), NULL, this ); + AutoTestAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnAutoTestAllButtonClick ), NULL, this ); + ResetButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionTestDialogBase::OnResetButtonClick ), NULL, this ); +} + +FavoriteVolumesDialogBase::FavoriteVolumesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer57; + bSizer57 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer60; + bSizer60 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer58; + bSizer58 = new wxBoxSizer( wxVERTICAL ); + + FavoritesListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_VRULES|wxSUNKEN_BORDER ); + bSizer58->Add( FavoritesListCtrl, 1, wxALL|wxEXPAND, 5 ); + + wxGridSizer* gSizer5; + gSizer5 = new wxGridSizer( 1, 4, 0, 0 ); + + MoveUpButton = new wxButton( this, wxID_ANY, _("Move &Up"), wxDefaultPosition, wxDefaultSize, 0 ); + gSizer5->Add( MoveUpButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + MoveDownButton = new wxButton( this, wxID_ANY, _("Move &Down"), wxDefaultPosition, wxDefaultSize, 0 ); + gSizer5->Add( MoveDownButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + RemoveButton = new wxButton( this, wxID_ANY, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0 ); + gSizer5->Add( RemoveButton, 0, wxALIGN_RIGHT|wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + RemoveAllButton = new wxButton( this, wxID_ANY, _("Remove &All"), wxDefaultPosition, wxDefaultSize, 0 ); + gSizer5->Add( RemoveAllButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + bSizer58->Add( gSizer5, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + wxFlexGridSizer* fgSizer4; + fgSizer4 = new wxFlexGridSizer( 1, 5, 0, 0 ); + fgSizer4->AddGrowableCol( 2 ); + fgSizer4->SetFlexibleDirection( wxBOTH ); + fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer58->Add( fgSizer4, 0, wxEXPAND, 5 ); + + bSizer60->Add( bSizer58, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer59; + bSizer59 = new wxBoxSizer( wxVERTICAL ); + + OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + OKButton->SetDefault(); + bSizer59->Add( OKButton, 0, wxALL, 5 ); + + CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer59->Add( CancelButton, 0, wxALL, 5 ); + + bSizer60->Add( bSizer59, 0, wxEXPAND, 5 ); + + bSizer57->Add( bSizer60, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer57 ); + this->Layout(); + bSizer57->Fit( this ); + + // Connect Events + FavoritesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemDeselected ), NULL, this ); + FavoritesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemSelected ), NULL, this ); + MoveUpButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveUpButtonClick ), NULL, this ); + MoveDownButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveDownButtonClick ), NULL, this ); + RemoveButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveButtonClick ), NULL, this ); + RemoveAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveAllButtonClick ), NULL, this ); + OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnOKButtonClick ), NULL, this ); +} + +FavoriteVolumesDialogBase::~FavoriteVolumesDialogBase() +{ + // Disconnect Events + FavoritesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemDeselected ), NULL, this ); + FavoritesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( FavoriteVolumesDialogBase::OnListItemSelected ), NULL, this ); + MoveUpButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveUpButtonClick ), NULL, this ); + MoveDownButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnMoveDownButtonClick ), NULL, this ); + RemoveButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveButtonClick ), NULL, this ); + RemoveAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnRemoveAllButtonClick ), NULL, this ); + OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FavoriteVolumesDialogBase::OnOKButtonClick ), NULL, this ); +} + +KeyfilesDialogBase::KeyfilesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); + + wxBoxSizer* bSizer26; + bSizer26 = new wxBoxSizer( wxVERTICAL ); + + UpperSizer = new wxBoxSizer( wxHORIZONTAL ); + + PanelSizer = new wxBoxSizer( wxVERTICAL ); + + UpperSizer->Add( PanelSizer, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer22; + bSizer22 = new wxBoxSizer( wxVERTICAL ); + + OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + OKButton->SetDefault(); + bSizer22->Add( OKButton, 0, wxALL|wxEXPAND, 5 ); + + CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer22->Add( CancelButton, 0, wxALL|wxEXPAND, 5 ); + + WarningStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + WarningStaticText->Wrap( -1 ); + bSizer22->Add( WarningStaticText, 1, wxALL|wxEXPAND, 5 ); + + UpperSizer->Add( bSizer22, 0, wxEXPAND, 5 ); + + bSizer26->Add( UpperSizer, 1, wxTOP|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer23; + bSizer23 = new wxBoxSizer( wxVERTICAL ); + + KeyfilesNoteSizer = new wxBoxSizer( wxVERTICAL ); + + wxStaticLine* m_staticline1; + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + KeyfilesNoteSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 ); + + KeyfilesNoteStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + KeyfilesNoteStaticText->Wrap( -1 ); + KeyfilesNoteSizer->Add( KeyfilesNoteStaticText, 0, wxALL|wxEXPAND, 5 ); + + wxStaticLine* m_staticline2; + m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + KeyfilesNoteSizer->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 ); + + bSizer23->Add( KeyfilesNoteSizer, 1, wxEXPAND, 5 ); + + wxFlexGridSizer* fgSizer2; + fgSizer2 = new wxFlexGridSizer( 1, 2, 0, 0 ); + fgSizer2->AddGrowableCol( 0 ); + fgSizer2->SetFlexibleDirection( wxBOTH ); + fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + KeyfilesHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, _("More information on keyfiles"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + + KeyfilesHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + KeyfilesHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + KeyfilesHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + fgSizer2->Add( KeyfilesHyperlink, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + CreateKeyfileButtton = new wxButton( this, wxID_ANY, _("&Generate Random Keyfile..."), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->Add( CreateKeyfileButtton, 0, wxALL, 5 ); + + bSizer23->Add( fgSizer2, 0, wxEXPAND, 5 ); + + bSizer26->Add( bSizer23, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + this->SetSizer( bSizer26 ); + this->Layout(); + bSizer26->Fit( this ); + + // Connect Events + KeyfilesHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( KeyfilesDialogBase::OnKeyfilesHyperlinkClick ), NULL, this ); + CreateKeyfileButtton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesDialogBase::OnCreateKeyfileButttonClick ), NULL, this ); +} + +KeyfilesDialogBase::~KeyfilesDialogBase() +{ + // Disconnect Events + KeyfilesHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( KeyfilesDialogBase::OnKeyfilesHyperlinkClick ), NULL, this ); + CreateKeyfileButtton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesDialogBase::OnCreateKeyfileButttonClick ), NULL, this ); +} + +KeyfileGeneratorDialogBase::KeyfileGeneratorDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + MainSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer144; + bSizer144 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer145; + bSizer145 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxStaticText* m_staticText49; + m_staticText49 = new wxStaticText( this, wxID_ANY, _("Mixing PRF:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText49->Wrap( -1 ); + bSizer145->Add( m_staticText49, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString HashChoiceChoices; + HashChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, HashChoiceChoices, 0 ); + HashChoice->SetSelection( 0 ); + bSizer145->Add( HashChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer144->Add( bSizer145, 0, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer43; + sbSizer43 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxBoxSizer* bSizer147; + bSizer147 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticText* m_staticText52; + m_staticText52 = new wxStaticText( this, wxID_ANY, _("Random Pool:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText52->Wrap( -1 ); + bSizer147->Add( m_staticText52, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + RandomPoolStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + RandomPoolStaticText->Wrap( -1 ); + RandomPoolStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); + + bSizer147->Add( RandomPoolStaticText, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + ShowRandomPoolCheckBox = new wxCheckBox( this, wxID_ANY, _("Show"), wxDefaultPosition, wxDefaultSize, 0 ); + ShowRandomPoolCheckBox->SetValue(true); + + bSizer147->Add( ShowRandomPoolCheckBox, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer43->Add( bSizer147, 0, wxEXPAND|wxTOP, 5 ); + + + sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); + + MouseStaticText = new wxStaticText( this, wxID_ANY, _("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."), wxDefaultPosition, wxDefaultSize, 0 ); + MouseStaticText->Wrap( -1 ); + sbSizer43->Add( MouseStaticText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer144->Add( sbSizer43, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer146; + bSizer146 = new wxBoxSizer( wxHORIZONTAL ); + + GenerateButton = new wxButton( this, wxID_ANY, _("Generate and Save Keyfile..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer146->Add( GenerateButton, 0, wxALL, 5 ); + + + bSizer146->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxButton* m_button61; + m_button61 = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer146->Add( m_button61, 0, wxALL, 5 ); + + bSizer144->Add( bSizer146, 0, wxEXPAND, 5 ); + + MainSizer->Add( bSizer144, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( MainSizer ); + this->Layout(); + MainSizer->Fit( this ); + + // Connect Events + this->Connect( wxEVT_MOTION, wxMouseEventHandler( KeyfileGeneratorDialogBase::OnMouseMotion ) ); + HashChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnHashSelected ), NULL, this ); + ShowRandomPoolCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); + GenerateButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnGenerateButtonClick ), NULL, this ); +} + +KeyfileGeneratorDialogBase::~KeyfileGeneratorDialogBase() +{ + // Disconnect Events + this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( KeyfileGeneratorDialogBase::OnMouseMotion ) ); + HashChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnHashSelected ), NULL, this ); + ShowRandomPoolCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); + GenerateButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfileGeneratorDialogBase::OnGenerateButtonClick ), NULL, this ); +} + +LegalNoticesDialogBase::LegalNoticesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer114; + bSizer114 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer115; + bSizer115 = new wxBoxSizer( wxVERTICAL ); + + LegalNoticesTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); + bSizer115->Add( LegalNoticesTextCtrl, 1, wxALL|wxEXPAND, 5 ); + + wxButton* OKButton; + OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + OKButton->SetDefault(); + bSizer115->Add( OKButton, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer114->Add( bSizer115, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer114 ); + this->Layout(); + bSizer114->Fit( this ); +} + +LegalNoticesDialogBase::~LegalNoticesDialogBase() +{ +} + +MountOptionsDialogBase::MountOptionsDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); + + wxBoxSizer* bSizer5; + bSizer5 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer19; + bSizer19 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer14; + bSizer14 = new wxBoxSizer( wxHORIZONTAL ); + + PasswordSizer = new wxBoxSizer( wxVERTICAL ); + + bSizer14->Add( PasswordSizer, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer9; + bSizer9 = new wxBoxSizer( wxVERTICAL ); + + OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + OKButton->SetDefault(); + bSizer9->Add( OKButton, 0, wxALL|wxEXPAND, 5 ); + + CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer9->Add( CancelButton, 0, wxALL|wxEXPAND, 5 ); + + + bSizer9->Add( 0, 0, 1, wxTOP|wxEXPAND, 5 ); + + OptionsButton = new wxButton( this, wxID_ANY, _("Op&tions"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer9->Add( OptionsButton, 0, wxALL|wxEXPAND, 5 ); + + bSizer14->Add( bSizer9, 0, wxEXPAND, 5 ); + + bSizer19->Add( bSizer14, 0, wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer6; + bSizer6 = new wxBoxSizer( wxVERTICAL ); + + OptionsPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + OptionsSizer = new wxStaticBoxSizer( new wxStaticBox( OptionsPanel, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + + OptionsSizer->Add( 0, 0, 0, wxTOP, 5 ); + + ReadOnlyCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("Mount volume as &read-only"), wxDefaultPosition, wxDefaultSize, 0 ); + + OptionsSizer->Add( ReadOnlyCheckBox, 0, wxALL, 5 ); + + RemovableCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("Mount volume as removable &medium"), wxDefaultPosition, wxDefaultSize, 0 ); + + OptionsSizer->Add( RemovableCheckBox, 0, wxALL, 5 ); + + PartitionInSystemEncryptionScopeCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("Mount partition &using system encryption (preboot authentication)"), wxDefaultPosition, wxDefaultSize, 0 ); + + OptionsSizer->Add( PartitionInSystemEncryptionScopeCheckBox, 0, wxALL, 5 ); + + ProtectionSizer = new wxStaticBoxSizer( new wxStaticBox( OptionsPanel, wxID_ANY, _("Hidden Volume Protection") ), wxVERTICAL ); + + ProtectionCheckBox = new wxCheckBox( OptionsPanel, wxID_ANY, _("&Protect hidden volume when mounting outer volume"), wxDefaultPosition, wxDefaultSize, 0 ); + + ProtectionSizer->Add( ProtectionCheckBox, 0, wxALL, 5 ); + + ProtectionPasswordSizer = new wxBoxSizer( wxVERTICAL ); + + ProtectionSizer->Add( ProtectionPasswordSizer, 1, wxEXPAND|wxLEFT, 5 ); + + ProtectionHyperlinkCtrl = new wxHyperlinkCtrl( OptionsPanel, wxID_ANY, _("What is hidden volume protection?"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + + ProtectionHyperlinkCtrl->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + ProtectionHyperlinkCtrl->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + ProtectionHyperlinkCtrl->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + ProtectionSizer->Add( ProtectionHyperlinkCtrl, 0, wxALL, 5 ); + + OptionsSizer->Add( ProtectionSizer, 1, wxEXPAND|wxALL, 5 ); + + FilesystemSizer = new wxBoxSizer( wxVERTICAL ); + + m_panel8 = new wxPanel( OptionsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxStaticBoxSizer* sbSizer28; + sbSizer28 = new wxStaticBoxSizer( new wxStaticBox( m_panel8, wxID_ANY, _("Filesystem") ), wxVERTICAL ); + + wxBoxSizer* bSizer54; + bSizer54 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer55; + bSizer55 = new wxBoxSizer( wxVERTICAL ); + + NoFilesystemCheckBox = new wxCheckBox( m_panel8, wxID_ANY, _("Do ¬ mount"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer55->Add( NoFilesystemCheckBox, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + bSizer54->Add( bSizer55, 1, wxEXPAND, 5 ); + + FilesystemOptionsSizer = new wxGridBagSizer( 0, 0 ); + FilesystemOptionsSizer->AddGrowableCol( 1 ); + FilesystemOptionsSizer->SetFlexibleDirection( wxBOTH ); + FilesystemOptionsSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + FilesystemOptionsSizer->SetEmptyCellSize( wxSize( 0,0 ) ); + + FilesystemSpacer = new wxBoxSizer( wxVERTICAL ); + + FilesystemOptionsSizer->Add( FilesystemSpacer, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP, 5 ); + + MountPointTextCtrlStaticText = new wxStaticText( m_panel8, wxID_ANY, _("Mount at directory:"), wxDefaultPosition, wxDefaultSize, 0 ); + MountPointTextCtrlStaticText->Wrap( -1 ); + FilesystemOptionsSizer->Add( MountPointTextCtrlStaticText, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + MountPointTextCtrl = new wxTextCtrl( m_panel8, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + FilesystemOptionsSizer->Add( MountPointTextCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + MountPointButton = new wxButton( m_panel8, wxID_ANY, _("Se&lect..."), wxDefaultPosition, wxDefaultSize, 0 ); + FilesystemOptionsSizer->Add( MountPointButton, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + FilesystemOptionsStaticText = new wxStaticText( m_panel8, wxID_ANY, _("Mount options:"), wxDefaultPosition, wxDefaultSize, 0 ); + FilesystemOptionsStaticText->Wrap( -1 ); + FilesystemOptionsSizer->Add( FilesystemOptionsStaticText, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxLEFT, 5 ); + + FilesystemOptionsTextCtrl = new wxTextCtrl( m_panel8, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + FilesystemOptionsSizer->Add( FilesystemOptionsTextCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + bSizer54->Add( FilesystemOptionsSizer, 0, wxEXPAND, 5 ); + + sbSizer28->Add( bSizer54, 0, wxEXPAND|wxBOTTOM, 5 ); + + m_panel8->SetSizer( sbSizer28 ); + m_panel8->Layout(); + sbSizer28->Fit( m_panel8 ); + FilesystemSizer->Add( m_panel8, 0, wxEXPAND | wxALL, 5 ); + + OptionsSizer->Add( FilesystemSizer, 0, wxEXPAND, 5 ); + + OptionsPanel->SetSizer( OptionsSizer ); + OptionsPanel->Layout(); + OptionsSizer->Fit( OptionsPanel ); + bSizer6->Add( OptionsPanel, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + bSizer19->Add( bSizer6, 0, wxEXPAND, 5 ); + + bSizer5->Add( bSizer19, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer5 ); + this->Layout(); + bSizer5->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( MountOptionsDialogBase::OnInitDialog ) ); + OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOKButtonClick ), NULL, this ); + OptionsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOptionsButtonClick ), NULL, this ); + ReadOnlyCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnReadOnlyCheckBoxClick ), NULL, this ); + ProtectionCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnProtectionCheckBoxClick ), NULL, this ); + ProtectionHyperlinkCtrl->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MountOptionsDialogBase::OnProtectionHyperlinkClick ), NULL, this ); + NoFilesystemCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnNoFilesystemCheckBoxClick ), NULL, this ); + MountPointButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnMountPointButtonClick ), NULL, this ); +} + +MountOptionsDialogBase::~MountOptionsDialogBase() +{ + // Disconnect Events + this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( MountOptionsDialogBase::OnInitDialog ) ); + OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOKButtonClick ), NULL, this ); + OptionsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnOptionsButtonClick ), NULL, this ); + ReadOnlyCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnReadOnlyCheckBoxClick ), NULL, this ); + ProtectionCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnProtectionCheckBoxClick ), NULL, this ); + ProtectionHyperlinkCtrl->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MountOptionsDialogBase::OnProtectionHyperlinkClick ), NULL, this ); + NoFilesystemCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnNoFilesystemCheckBoxClick ), NULL, this ); + MountPointButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MountOptionsDialogBase::OnMountPointButtonClick ), NULL, this ); +} + +NewSecurityTokenKeyfileDialogBase::NewSecurityTokenKeyfileDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer143; + bSizer143 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer144; + bSizer144 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer42; + sbSizer42 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer7; + fgSizer7 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer7->SetFlexibleDirection( wxBOTH ); + fgSizer7->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxStaticText* m_staticText47; + m_staticText47 = new wxStaticText( this, wxID_ANY, _("Security token:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); + m_staticText47->Wrap( -1 ); + fgSizer7->Add( m_staticText47, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + wxArrayString SecurityTokenChoiceChoices; + SecurityTokenChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, SecurityTokenChoiceChoices, 0 ); + SecurityTokenChoice->SetSelection( 0 ); + fgSizer7->Add( SecurityTokenChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + wxStaticText* m_staticText48; + m_staticText48 = new wxStaticText( this, wxID_ANY, _("Keyfile name:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); + m_staticText48->Wrap( -1 ); + fgSizer7->Add( m_staticText48, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + KeyfileNameTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer7->Add( KeyfileNameTextCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); + + sbSizer42->Add( fgSizer7, 1, wxEXPAND|wxTOP, 5 ); + + bSizer144->Add( sbSizer42, 1, wxEXPAND|wxALL, 5 ); + + StdButtons = new wxStdDialogButtonSizer(); + StdButtonsOK = new wxButton( this, wxID_OK ); + StdButtons->AddButton( StdButtonsOK ); + StdButtonsCancel = new wxButton( this, wxID_CANCEL ); + StdButtons->AddButton( StdButtonsCancel ); + StdButtons->Realize(); + bSizer144->Add( StdButtons, 0, wxALIGN_RIGHT|wxALL, 5 ); + + bSizer143->Add( bSizer144, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer143 ); + this->Layout(); + bSizer143->Fit( this ); + + // Connect Events + KeyfileNameTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( NewSecurityTokenKeyfileDialogBase::OnKeyfileNameChanged ), NULL, this ); +} + +NewSecurityTokenKeyfileDialogBase::~NewSecurityTokenKeyfileDialogBase() +{ + // Disconnect Events + KeyfileNameTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( NewSecurityTokenKeyfileDialogBase::OnKeyfileNameChanged ), NULL, this ); +} + +PreferencesDialogBase::PreferencesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); + + wxBoxSizer* bSizer32; + bSizer32 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer41; + bSizer41 = new wxBoxSizer( wxVERTICAL ); + + PreferencesNotebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + SecurityPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer44; + bSizer44 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer33; + bSizer33 = new wxBoxSizer( wxVERTICAL ); + + AutoDismountSizer = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Auto-Dismount") ), wxVERTICAL ); + + wxStaticBoxSizer* sbSizer13; + sbSizer13 = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Dismount All Volumes When") ), wxVERTICAL ); + + DismountOnLogOffCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("User logs off"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer13->Add( DismountOnLogOffCheckBox, 0, wxALL, 5 ); + + DismountOnScreenSaverCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Screen saver is launched"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer13->Add( DismountOnScreenSaverCheckBox, 0, wxALL, 5 ); + + DismountOnPowerSavingCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("System is entering power saving mode"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer13->Add( DismountOnPowerSavingCheckBox, 0, wxALL, 5 ); + + AutoDismountSizer->Add( sbSizer13, 0, wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer34; + bSizer34 = new wxBoxSizer( wxHORIZONTAL ); + + DismountOnInactivityCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Auto-dismount volume after no data has been read/written to it for"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer34->Add( DismountOnInactivityCheckBox, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + DismountOnInactivitySpinCtrl = new wxSpinCtrl( SecurityPage, wxID_ANY, wxT("1"), wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 1, 9999, 1 ); + bSizer34->Add( DismountOnInactivitySpinCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + wxStaticText* m_staticText5; + m_staticText5 = new wxStaticText( SecurityPage, wxID_ANY, _("minutes"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText5->Wrap( -1 ); + bSizer34->Add( m_staticText5, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + AutoDismountSizer->Add( bSizer34, 0, wxEXPAND, 5 ); + + ForceAutoDismountCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Force auto-dismount even if volume contains open files or directories"), wxDefaultPosition, wxDefaultSize, 0 ); + + AutoDismountSizer->Add( ForceAutoDismountCheckBox, 0, wxALL, 5 ); + + bSizer33->Add( AutoDismountSizer, 0, wxEXPAND|wxALL, 5 ); + + FilesystemSecuritySizer = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Filesystem") ), wxVERTICAL ); + + PreserveTimestampsCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Preserve modification time of file containers"), wxDefaultPosition, wxDefaultSize, 0 ); + + FilesystemSecuritySizer->Add( PreserveTimestampsCheckBox, 0, wxALL, 5 ); + + bSizer33->Add( FilesystemSecuritySizer, 0, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer14; + sbSizer14 = new wxStaticBoxSizer( new wxStaticBox( SecurityPage, wxID_ANY, _("Password Cache") ), wxVERTICAL ); + + WipeCacheOnCloseCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Wipe after TrueCrypt window has been closed"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer14->Add( WipeCacheOnCloseCheckBox, 0, wxALL, 5 ); + + WipeCacheOnAutoDismountCheckBox = new wxCheckBox( SecurityPage, wxID_ANY, _("Wipe after volume has been auto-dismounted"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer14->Add( WipeCacheOnAutoDismountCheckBox, 0, wxALL, 5 ); + + bSizer33->Add( sbSizer14, 0, wxEXPAND|wxALL, 5 ); + + bSizer44->Add( bSizer33, 1, wxEXPAND|wxALL, 5 ); + + SecurityPage->SetSizer( bSizer44 ); + SecurityPage->Layout(); + bSizer44->Fit( SecurityPage ); + PreferencesNotebook->AddPage( SecurityPage, _("Security"), true ); + DefaultMountOptionsPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer46; + bSizer46 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer35; + bSizer35 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer15; + sbSizer15 = new wxStaticBoxSizer( new wxStaticBox( DefaultMountOptionsPage, wxID_ANY, _("Default Mount Options") ), wxVERTICAL ); + + MountReadOnlyCheckBox = new wxCheckBox( DefaultMountOptionsPage, wxID_ANY, _("Mount volumes as read-only"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer15->Add( MountReadOnlyCheckBox, 0, wxALL, 5 ); + + MountRemovableCheckBox = new wxCheckBox( DefaultMountOptionsPage, wxID_ANY, _("Mount volumes as removable media"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer15->Add( MountRemovableCheckBox, 0, wxALL, 5 ); + + CachePasswordsCheckBox = new wxCheckBox( DefaultMountOptionsPage, wxID_ANY, _("Cache passwords in memory"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer15->Add( CachePasswordsCheckBox, 0, wxALL, 5 ); + + bSizer35->Add( sbSizer15, 0, wxEXPAND|wxALL, 5 ); + + FilesystemSizer = new wxStaticBoxSizer( new wxStaticBox( DefaultMountOptionsPage, wxID_ANY, _("Filesystem") ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer3; + fgSizer3 = new wxFlexGridSizer( 1, 2, 0, 0 ); + fgSizer3->AddGrowableCol( 1 ); + fgSizer3->SetFlexibleDirection( wxBOTH ); + fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxStaticText* m_staticText6; + m_staticText6 = new wxStaticText( DefaultMountOptionsPage, wxID_ANY, _("Mount options:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText6->Wrap( -1 ); + fgSizer3->Add( m_staticText6, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + + FilesystemOptionsTextCtrl = new wxTextCtrl( DefaultMountOptionsPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer3->Add( FilesystemOptionsTextCtrl, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + FilesystemSizer->Add( fgSizer3, 1, wxEXPAND, 5 ); + + bSizer35->Add( FilesystemSizer, 0, wxEXPAND|wxALL, 5 ); + + bSizer46->Add( bSizer35, 1, wxEXPAND|wxALL, 5 ); + + DefaultMountOptionsPage->SetSizer( bSizer46 ); + DefaultMountOptionsPage->Layout(); + bSizer46->Fit( DefaultMountOptionsPage ); + PreferencesNotebook->AddPage( DefaultMountOptionsPage, _("Mount Options"), false ); + BackgroundTaskPanel = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer61; + bSizer61 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer62; + bSizer62 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer18; + sbSizer18 = new wxStaticBoxSizer( new wxStaticBox( BackgroundTaskPanel, wxID_ANY, _("TrueCrypt Background Task") ), wxVERTICAL ); + + BackgroundTaskEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Enabled"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer18->Add( BackgroundTaskEnabledCheckBox, 0, wxALL, 5 ); + + CloseBackgroundTaskOnNoVolumesCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Exit when there are no mounted volumes"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer18->Add( CloseBackgroundTaskOnNoVolumesCheckBox, 0, wxALL, 5 ); + + wxStaticBoxSizer* sbSizer26; + sbSizer26 = new wxStaticBoxSizer( new wxStaticBox( BackgroundTaskPanel, wxID_ANY, _("Task Icon Menu Items") ), wxVERTICAL ); + + BackgroundTaskMenuMountItemsEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Mount Favorite Volumes"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer26->Add( BackgroundTaskMenuMountItemsEnabledCheckBox, 0, wxALL, 5 ); + + BackgroundTaskMenuOpenItemsEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Open Mounted Volumes"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer26->Add( BackgroundTaskMenuOpenItemsEnabledCheckBox, 0, wxALL, 5 ); + + BackgroundTaskMenuDismountItemsEnabledCheckBox = new wxCheckBox( BackgroundTaskPanel, wxID_ANY, _("Dismount Mounted Volumes"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer26->Add( BackgroundTaskMenuDismountItemsEnabledCheckBox, 0, wxALL, 5 ); + + sbSizer18->Add( sbSizer26, 1, wxEXPAND|wxALL, 5 ); + + bSizer62->Add( sbSizer18, 0, wxEXPAND|wxALL, 5 ); + + bSizer61->Add( bSizer62, 1, wxEXPAND|wxALL, 5 ); + + BackgroundTaskPanel->SetSizer( bSizer61 ); + BackgroundTaskPanel->Layout(); + bSizer61->Fit( BackgroundTaskPanel ); + PreferencesNotebook->AddPage( BackgroundTaskPanel, _("Background Task"), false ); + SystemIntegrationPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer49; + bSizer49 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer37; + bSizer37 = new wxBoxSizer( wxVERTICAL ); + + LogOnSizer = new wxStaticBoxSizer( new wxStaticBox( SystemIntegrationPage, wxID_ANY, _("Actions to Perform when User Logs On") ), wxVERTICAL ); + + StartOnLogonCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Start TrueCrypt Background Task"), wxDefaultPosition, wxDefaultSize, 0 ); + + LogOnSizer->Add( StartOnLogonCheckBox, 0, wxALL, 5 ); + + MountFavoritesOnLogonCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Mount favorite volumes"), wxDefaultPosition, wxDefaultSize, 0 ); + + LogOnSizer->Add( MountFavoritesOnLogonCheckBox, 0, wxALL, 5 ); + + MountDevicesOnLogonCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Mount all device-hosted TrueCrypt volumes"), wxDefaultPosition, wxDefaultSize, 0 ); + + LogOnSizer->Add( MountDevicesOnLogonCheckBox, 0, wxALL, 5 ); + + bSizer37->Add( LogOnSizer, 0, wxALL|wxEXPAND, 5 ); + + ExplorerSizer = new wxStaticBoxSizer( new wxStaticBox( SystemIntegrationPage, wxID_ANY, _("Filesystem Explorer") ), wxVERTICAL ); + + OpenExplorerWindowAfterMountCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Open Explorer window for successfully mounted volume"), wxDefaultPosition, wxDefaultSize, 0 ); + + ExplorerSizer->Add( OpenExplorerWindowAfterMountCheckBox, 0, wxALL, 5 ); + + CloseExplorerWindowsOnDismountCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Close all Explorer windows of volume being dismounted"), wxDefaultPosition, wxDefaultSize, 0 ); + + ExplorerSizer->Add( CloseExplorerWindowsOnDismountCheckBox, 0, wxALL, 5 ); + + bSizer37->Add( ExplorerSizer, 0, wxEXPAND|wxALL, 5 ); + + KernelServicesSizer = new wxStaticBoxSizer( new wxStaticBox( SystemIntegrationPage, wxID_ANY, _("Kernel Services") ), wxVERTICAL ); + + NoKernelCryptoCheckBox = new wxCheckBox( SystemIntegrationPage, wxID_ANY, _("Do not use kernel cryptographic services"), wxDefaultPosition, wxDefaultSize, 0 ); + + KernelServicesSizer->Add( NoKernelCryptoCheckBox, 0, wxALL, 5 ); + + bSizer37->Add( KernelServicesSizer, 0, wxEXPAND|wxALL, 5 ); + + bSizer49->Add( bSizer37, 1, wxEXPAND|wxALL, 5 ); + + SystemIntegrationPage->SetSizer( bSizer49 ); + SystemIntegrationPage->Layout(); + bSizer49->Fit( SystemIntegrationPage ); + PreferencesNotebook->AddPage( SystemIntegrationPage, _("System Integration"), false ); + DefaultKeyfilesPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer40; + bSizer40 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer43; + bSizer43 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* bSizer42; + bSizer42 = new wxStaticBoxSizer( new wxStaticBox( DefaultKeyfilesPage, wxID_ANY, _("Default Keyfiles") ), wxVERTICAL ); + + DefaultKeyfilesSizer = new wxBoxSizer( wxVERTICAL ); + + bSizer42->Add( DefaultKeyfilesSizer, 1, wxEXPAND, 5 ); + + bSizer43->Add( bSizer42, 1, wxEXPAND|wxALL, 5 ); + + UseKeyfilesCheckBox = new wxCheckBox( DefaultKeyfilesPage, wxID_ANY, _("Use keyfiles by default"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer43->Add( UseKeyfilesCheckBox, 0, wxALL, 5 ); + + bSizer40->Add( bSizer43, 1, wxEXPAND|wxALL, 5 ); + + DefaultKeyfilesPage->SetSizer( bSizer40 ); + DefaultKeyfilesPage->Layout(); + bSizer40->Fit( DefaultKeyfilesPage ); + PreferencesNotebook->AddPage( DefaultKeyfilesPage, _("Keyfiles"), false ); + SecurityTokensPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer127; + bSizer127 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer128; + bSizer128 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer36; + sbSizer36 = new wxStaticBoxSizer( new wxStaticBox( SecurityTokensPage, wxID_ANY, _("PKCS #11 Library Path") ), wxVERTICAL ); + + wxBoxSizer* bSizer129; + bSizer129 = new wxBoxSizer( wxHORIZONTAL ); + + Pkcs11ModulePathTextCtrl = new wxTextCtrl( SecurityTokensPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer129->Add( Pkcs11ModulePathTextCtrl, 1, wxALL, 5 ); + + SelectPkcs11ModuleButton = new wxButton( SecurityTokensPage, wxID_ANY, _("Select &Library..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer129->Add( SelectPkcs11ModuleButton, 0, wxALL, 5 ); + + sbSizer36->Add( bSizer129, 1, wxEXPAND, 5 ); + + bSizer128->Add( sbSizer36, 0, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer37; + sbSizer37 = new wxStaticBoxSizer( new wxStaticBox( SecurityTokensPage, wxID_ANY, _("Security Options") ), wxVERTICAL ); + + CloseSecurityTokenSessionsAfterMountCheckBox = new wxCheckBox( SecurityTokensPage, wxID_ANY, _("&Close token session (log out) after a volume is successfully mounted"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer37->Add( CloseSecurityTokenSessionsAfterMountCheckBox, 0, wxALL, 5 ); + + bSizer128->Add( sbSizer37, 0, wxEXPAND|wxALL, 5 ); + + bSizer127->Add( bSizer128, 1, wxEXPAND|wxALL, 5 ); + + SecurityTokensPage->SetSizer( bSizer127 ); + SecurityTokensPage->Layout(); + bSizer127->Fit( SecurityTokensPage ); + PreferencesNotebook->AddPage( SecurityTokensPage, _("Security Tokens"), false ); + HotkeysPage = new wxPanel( PreferencesNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer51; + bSizer51 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer38; + bSizer38 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer21; + sbSizer21 = new wxStaticBoxSizer( new wxStaticBox( HotkeysPage, wxID_ANY, _("System-Wide Hotkeys") ), wxVERTICAL ); + + HotkeyListCtrl = new wxListCtrl( HotkeysPage, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxSUNKEN_BORDER ); + sbSizer21->Add( HotkeyListCtrl, 1, wxALL|wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer23; + sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( HotkeysPage, wxID_ANY, _("Shortcut") ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer4; + fgSizer4 = new wxFlexGridSizer( 2, 3, 0, 0 ); + fgSizer4->SetFlexibleDirection( wxBOTH ); + fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxStaticText* m_staticText10; + m_staticText10 = new wxStaticText( HotkeysPage, wxID_ANY, _("Key to assign:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText10->Wrap( -1 ); + fgSizer4->Add( m_staticText10, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + HotkeyTextCtrl = new wxTextCtrl( HotkeysPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer4->Add( HotkeyTextCtrl, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + AssignHotkeyButton = new wxButton( HotkeysPage, wxID_ANY, _("Assign"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer4->Add( AssignHotkeyButton, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxGridSizer* gSizer4; + gSizer4 = new wxGridSizer( 1, 4, 0, 0 ); + + HotkeyControlCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Control"), wxDefaultPosition, wxDefaultSize, 0 ); + + gSizer4->Add( HotkeyControlCheckBox, 0, wxALL, 5 ); + + HotkeyShiftCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Shift"), wxDefaultPosition, wxDefaultSize, 0 ); + + gSizer4->Add( HotkeyShiftCheckBox, 0, wxALL, 5 ); + + HotkeyAltCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Alt"), wxDefaultPosition, wxDefaultSize, 0 ); + + gSizer4->Add( HotkeyAltCheckBox, 0, wxALL, 5 ); + + HotkeyWinCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Win"), wxDefaultPosition, wxDefaultSize, 0 ); + + gSizer4->Add( HotkeyWinCheckBox, 0, wxALL, 5 ); + + fgSizer4->Add( gSizer4, 1, wxEXPAND, 5 ); + + RemoveHotkeyButton = new wxButton( HotkeysPage, wxID_ANY, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer4->Add( RemoveHotkeyButton, 1, wxALL, 5 ); + + sbSizer23->Add( fgSizer4, 1, wxALIGN_RIGHT, 5 ); + + sbSizer21->Add( sbSizer23, 0, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer24; + sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( HotkeysPage, wxID_ANY, _("Options") ), wxVERTICAL ); + + BeepAfterHotkeyMountDismountCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Play system notification sound after mount/dismount"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer24->Add( BeepAfterHotkeyMountDismountCheckBox, 0, wxALL, 5 ); + + DisplayMessageAfterHotkeyDismountCheckBox = new wxCheckBox( HotkeysPage, wxID_ANY, _("Display confirmation message box after dismount"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer24->Add( DisplayMessageAfterHotkeyDismountCheckBox, 0, wxALL, 5 ); + + sbSizer21->Add( sbSizer24, 0, wxEXPAND|wxALL, 5 ); + + bSizer38->Add( sbSizer21, 1, wxEXPAND|wxALL, 5 ); + + bSizer51->Add( bSizer38, 1, wxEXPAND|wxALL, 5 ); + + HotkeysPage->SetSizer( bSizer51 ); + HotkeysPage->Layout(); + bSizer51->Fit( HotkeysPage ); + PreferencesNotebook->AddPage( HotkeysPage, _("Hotkeys"), false ); + + bSizer41->Add( PreferencesNotebook, 1, wxEXPAND | wxALL, 5 ); + + StdButtons = new wxStdDialogButtonSizer(); + StdButtonsOK = new wxButton( this, wxID_OK ); + StdButtons->AddButton( StdButtonsOK ); + StdButtonsCancel = new wxButton( this, wxID_CANCEL ); + StdButtons->AddButton( StdButtonsCancel ); + StdButtons->Realize(); + bSizer41->Add( StdButtons, 0, wxEXPAND|wxALL, 5 ); + + bSizer32->Add( bSizer41, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer32 ); + this->Layout(); + bSizer32->Fit( this ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PreferencesDialogBase::OnClose ) ); + DismountOnScreenSaverCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnScreenSaverCheckBoxClick ), NULL, this ); + DismountOnPowerSavingCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnPowerSavingCheckBoxClick ), NULL, this ); + ForceAutoDismountCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnForceAutoDismountCheckBoxClick ), NULL, this ); + PreserveTimestampsCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnPreserveTimestampsCheckBoxClick ), NULL, this ); + BackgroundTaskEnabledCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnBackgroundTaskEnabledCheckBoxClick ), NULL, this ); + NoKernelCryptoCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnNoKernelCryptoCheckBoxClick ), NULL, this ); + SelectPkcs11ModuleButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnSelectPkcs11ModuleButtonClick ), NULL, this ); + HotkeyListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemDeselected ), NULL, this ); + HotkeyListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemSelected ), NULL, this ); + AssignHotkeyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnAssignHotkeyButtonClick ), NULL, this ); + RemoveHotkeyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnRemoveHotkeyButtonClick ), NULL, this ); + StdButtonsCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnCancelButtonClick ), NULL, this ); + StdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnOKButtonClick ), NULL, this ); +} + +PreferencesDialogBase::~PreferencesDialogBase() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PreferencesDialogBase::OnClose ) ); + DismountOnScreenSaverCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnScreenSaverCheckBoxClick ), NULL, this ); + DismountOnPowerSavingCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnDismountOnPowerSavingCheckBoxClick ), NULL, this ); + ForceAutoDismountCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnForceAutoDismountCheckBoxClick ), NULL, this ); + PreserveTimestampsCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnPreserveTimestampsCheckBoxClick ), NULL, this ); + BackgroundTaskEnabledCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnBackgroundTaskEnabledCheckBoxClick ), NULL, this ); + NoKernelCryptoCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnNoKernelCryptoCheckBoxClick ), NULL, this ); + SelectPkcs11ModuleButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnSelectPkcs11ModuleButtonClick ), NULL, this ); + HotkeyListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemDeselected ), NULL, this ); + HotkeyListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( PreferencesDialogBase::OnHotkeyListItemSelected ), NULL, this ); + AssignHotkeyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnAssignHotkeyButtonClick ), NULL, this ); + RemoveHotkeyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnRemoveHotkeyButtonClick ), NULL, this ); + StdButtonsCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnCancelButtonClick ), NULL, this ); + StdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PreferencesDialogBase::OnOKButtonClick ), NULL, this ); +} + +RandomPoolEnrichmentDialogBase::RandomPoolEnrichmentDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + MainSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer144; + bSizer144 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer145; + bSizer145 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxStaticText* m_staticText49; + m_staticText49 = new wxStaticText( this, wxID_ANY, _("Mixing PRF:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText49->Wrap( -1 ); + bSizer145->Add( m_staticText49, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString HashChoiceChoices; + HashChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, HashChoiceChoices, 0 ); + HashChoice->SetSelection( 0 ); + bSizer145->Add( HashChoice, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer145->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer144->Add( bSizer145, 0, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer43; + sbSizer43 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxBoxSizer* bSizer147; + bSizer147 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticText* m_staticText52; + m_staticText52 = new wxStaticText( this, wxID_ANY, _("Random Pool:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText52->Wrap( -1 ); + bSizer147->Add( m_staticText52, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + RandomPoolStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + RandomPoolStaticText->Wrap( -1 ); + RandomPoolStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); + + bSizer147->Add( RandomPoolStaticText, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + ShowRandomPoolCheckBox = new wxCheckBox( this, wxID_ANY, _("Show"), wxDefaultPosition, wxDefaultSize, 0 ); + ShowRandomPoolCheckBox->SetValue(true); + + bSizer147->Add( ShowRandomPoolCheckBox, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer43->Add( bSizer147, 0, wxEXPAND|wxTOP, 5 ); + + + sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); + + MouseStaticText = new wxStaticText( this, wxID_ANY, _("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'."), wxDefaultPosition, wxDefaultSize, 0 ); + MouseStaticText->Wrap( -1 ); + sbSizer43->Add( MouseStaticText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + sbSizer43->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer144->Add( sbSizer43, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer146; + bSizer146 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer146->Add( 0, 0, 1, wxEXPAND, 5 ); + + ContinueButton = new wxButton( this, wxID_OK, _("&Continue"), wxDefaultPosition, wxDefaultSize, 0 ); + ContinueButton->SetDefault(); + bSizer146->Add( ContinueButton, 0, wxALL, 5 ); + + + bSizer146->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer144->Add( bSizer146, 0, wxEXPAND, 5 ); + + MainSizer->Add( bSizer144, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( MainSizer ); + this->Layout(); + MainSizer->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_MOTION, wxMouseEventHandler( RandomPoolEnrichmentDialogBase::OnMouseMotion ) ); + HashChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnHashSelected ), NULL, this ); + ShowRandomPoolCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); +} + +RandomPoolEnrichmentDialogBase::~RandomPoolEnrichmentDialogBase() +{ + // Disconnect Events + this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( RandomPoolEnrichmentDialogBase::OnMouseMotion ) ); + HashChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnHashSelected ), NULL, this ); + ShowRandomPoolCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( RandomPoolEnrichmentDialogBase::OnShowRandomPoolCheckBoxClicked ), NULL, this ); +} + +SecurityTokenKeyfilesDialogBase::SecurityTokenKeyfilesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); + this->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); + + wxBoxSizer* bSizer3; + bSizer3 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer138; + bSizer138 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer142; + bSizer142 = new wxBoxSizer( wxVERTICAL ); + + SecurityTokenKeyfileListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_VRULES|wxSUNKEN_BORDER ); + bSizer142->Add( SecurityTokenKeyfileListCtrl, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer141; + bSizer141 = new wxBoxSizer( wxHORIZONTAL ); + + ExportButton = new wxButton( this, wxID_ANY, _("&Export..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer141->Add( ExportButton, 0, wxALL, 5 ); + + DeleteButton = new wxButton( this, wxID_ANY, _("&Delete"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer141->Add( DeleteButton, 0, wxALL, 5 ); + + + bSizer141->Add( 0, 0, 1, wxEXPAND|wxLEFT, 5 ); + + ImportButton = new wxButton( this, wxID_ANY, _("&Import Keyfile to Token..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer141->Add( ImportButton, 0, wxALL, 5 ); + + bSizer142->Add( bSizer141, 0, wxEXPAND, 5 ); + + bSizer138->Add( bSizer142, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer139; + bSizer139 = new wxBoxSizer( wxVERTICAL ); + + OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + OKButton->SetDefault(); + bSizer139->Add( OKButton, 0, wxALL, 5 ); + + CancelButton = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer139->Add( CancelButton, 0, wxALL, 5 ); + + bSizer138->Add( bSizer139, 0, wxEXPAND, 5 ); + + bSizer3->Add( bSizer138, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer3 ); + this->Layout(); + bSizer3->Fit( this ); + + // Connect Events + SecurityTokenKeyfileListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemActivated ), NULL, this ); + SecurityTokenKeyfileListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemDeselected ), NULL, this ); + SecurityTokenKeyfileListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemSelected ), NULL, this ); + ExportButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnExportButtonClick ), NULL, this ); + DeleteButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnDeleteButtonClick ), NULL, this ); + ImportButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnImportButtonClick ), NULL, this ); + OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnOKButtonClick ), NULL, this ); +} + +SecurityTokenKeyfilesDialogBase::~SecurityTokenKeyfilesDialogBase() +{ + // Disconnect Events + SecurityTokenKeyfileListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemActivated ), NULL, this ); + SecurityTokenKeyfileListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemDeselected ), NULL, this ); + SecurityTokenKeyfileListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( SecurityTokenKeyfilesDialogBase::OnListItemSelected ), NULL, this ); + ExportButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnExportButtonClick ), NULL, this ); + DeleteButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnDeleteButtonClick ), NULL, this ); + ImportButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnImportButtonClick ), NULL, this ); + OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SecurityTokenKeyfilesDialogBase::OnOKButtonClick ), NULL, this ); +} + +VolumePropertiesDialogBase::VolumePropertiesDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer49; + bSizer49 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer50; + bSizer50 = new wxBoxSizer( wxVERTICAL ); + + PropertiesListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_VRULES|wxSUNKEN_BORDER ); + bSizer50->Add( PropertiesListCtrl, 1, wxALL|wxEXPAND, 5 ); + + StdButtons = new wxStdDialogButtonSizer(); + StdButtonsOK = new wxButton( this, wxID_OK ); + StdButtons->AddButton( StdButtonsOK ); + StdButtons->Realize(); + bSizer50->Add( StdButtons, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer49->Add( bSizer50, 1, wxEXPAND|wxALL, 5 ); + + this->SetSizer( bSizer49 ); + this->Layout(); + bSizer49->Fit( this ); +} + +VolumePropertiesDialogBase::~VolumePropertiesDialogBase() +{ +} + +EncryptionOptionsWizardPageBase::EncryptionOptionsWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer93; + bSizer93 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer94; + bSizer94 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer95; + bSizer95 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer29; + sbSizer29 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Encryption Algorithm") ), wxVERTICAL ); + + wxBoxSizer* bSizer96; + bSizer96 = new wxBoxSizer( wxHORIZONTAL ); + + wxArrayString EncryptionAlgorithmChoiceChoices; + EncryptionAlgorithmChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, EncryptionAlgorithmChoiceChoices, 0 ); + EncryptionAlgorithmChoice->SetSelection( 0 ); + bSizer96->Add( EncryptionAlgorithmChoice, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + TestButton = new wxButton( this, wxID_ANY, _("&Test"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer96->Add( TestButton, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + sbSizer29->Add( bSizer96, 0, wxEXPAND, 5 ); + + EncryptionAlgorithmStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + EncryptionAlgorithmStaticText->Wrap( -1 ); + sbSizer29->Add( EncryptionAlgorithmStaticText, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer97; + bSizer97 = new wxBoxSizer( wxHORIZONTAL ); + + EncryptionAlgorithmHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, _("More information"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + + EncryptionAlgorithmHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + EncryptionAlgorithmHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + EncryptionAlgorithmHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + bSizer97->Add( EncryptionAlgorithmHyperlink, 0, wxALL, 5 ); + + + bSizer97->Add( 0, 0, 1, wxEXPAND, 5 ); + + BenchmarkButton = new wxButton( this, wxID_ANY, _("&Benchmark"), wxDefaultPosition, wxDefaultSize, 0 ); + BenchmarkButton->Hide(); + + bSizer97->Add( BenchmarkButton, 0, wxALL, 5 ); + + sbSizer29->Add( bSizer97, 0, wxEXPAND, 5 ); + + bSizer95->Add( sbSizer29, 1, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer30; + sbSizer30 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Hash Algorithm") ), wxHORIZONTAL ); + + wxArrayString HashChoiceChoices; + HashChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, HashChoiceChoices, 0 ); + HashChoice->SetSelection( 0 ); + sbSizer30->Add( HashChoice, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + HashHyperlink = new wxHyperlinkCtrl( this, wxID_ANY, _("Information on hash algorithms"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + + HashHyperlink->SetHoverColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + HashHyperlink->SetNormalColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + HashHyperlink->SetVisitedColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) ); + sbSizer30->Add( HashHyperlink, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer95->Add( sbSizer30, 0, wxEXPAND|wxALL, 5 ); + + bSizer94->Add( bSizer95, 1, wxEXPAND, 5 ); + + bSizer93->Add( bSizer94, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer93 ); + this->Layout(); + bSizer93->Fit( this ); + + // Connect Events + EncryptionAlgorithmChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmSelected ), NULL, this ); + TestButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnTestButtonClick ), NULL, this ); + EncryptionAlgorithmHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmHyperlinkClick ), NULL, this ); + BenchmarkButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnBenchmarkButtonClick ), NULL, this ); + HashHyperlink->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnHashHyperlinkClick ), NULL, this ); +} + +EncryptionOptionsWizardPageBase::~EncryptionOptionsWizardPageBase() +{ + // Disconnect Events + EncryptionAlgorithmChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmSelected ), NULL, this ); + TestButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnTestButtonClick ), NULL, this ); + EncryptionAlgorithmHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnEncryptionAlgorithmHyperlinkClick ), NULL, this ); + BenchmarkButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( EncryptionOptionsWizardPageBase::OnBenchmarkButtonClick ), NULL, this ); + HashHyperlink->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( EncryptionOptionsWizardPageBase::OnHashHyperlinkClick ), NULL, this ); +} + +InfoWizardPageBase::InfoWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer71; + bSizer71 = new wxBoxSizer( wxVERTICAL ); + + InfoPageSizer = new wxBoxSizer( wxVERTICAL ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + InfoPageSizer->Add( InfoStaticText, 1, wxALL|wxEXPAND, 5 ); + + bSizer71->Add( InfoPageSizer, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer71 ); + this->Layout(); + bSizer71->Fit( this ); +} + +InfoWizardPageBase::~InfoWizardPageBase() +{ +} + +KeyfilesPanelBase::KeyfilesPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer19; + bSizer19 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer20; + bSizer20 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer21; + bSizer21 = new wxBoxSizer( wxVERTICAL ); + + KeyfilesListCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxSUNKEN_BORDER ); + bSizer21->Add( KeyfilesListCtrl, 1, wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer137; + bSizer137 = new wxBoxSizer( wxHORIZONTAL ); + + AddFilesButton = new wxButton( this, wxID_ANY, _("Add &Files..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer137->Add( AddFilesButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + AddDirectoryButton = new wxButton( this, wxID_ANY, _("Add &Path..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer137->Add( AddDirectoryButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + AddSecurityTokenSignatureButton = new wxButton( this, wxID_ANY, _("Add &Token Files..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer137->Add( AddSecurityTokenSignatureButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + RemoveButton = new wxButton( this, wxID_ANY, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer137->Add( RemoveButton, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + RemoveAllButton = new wxButton( this, wxID_ANY, _("Remove &All"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer137->Add( RemoveAllButton, 0, wxEXPAND|wxALL, 5 ); + + bSizer21->Add( bSizer137, 0, wxEXPAND, 5 ); + + bSizer20->Add( bSizer21, 1, wxEXPAND, 5 ); + + bSizer19->Add( bSizer20, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer19 ); + this->Layout(); + + // Connect Events + KeyfilesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemDeselected ), NULL, this ); + KeyfilesListCtrl->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemSelected ), NULL, this ); + KeyfilesListCtrl->Connect( wxEVT_SIZE, wxSizeEventHandler( KeyfilesPanelBase::OnListSizeChanged ), NULL, this ); + AddFilesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddFilesButtonClick ), NULL, this ); + AddDirectoryButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddDirectoryButtonClick ), NULL, this ); + AddSecurityTokenSignatureButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddSecurityTokenSignatureButtonClick ), NULL, this ); + RemoveButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveButtonClick ), NULL, this ); + RemoveAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveAllButtonClick ), NULL, this ); +} + +KeyfilesPanelBase::~KeyfilesPanelBase() +{ + // Disconnect Events + KeyfilesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemDeselected ), NULL, this ); + KeyfilesListCtrl->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( KeyfilesPanelBase::OnListItemSelected ), NULL, this ); + KeyfilesListCtrl->Disconnect( wxEVT_SIZE, wxSizeEventHandler( KeyfilesPanelBase::OnListSizeChanged ), NULL, this ); + AddFilesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddFilesButtonClick ), NULL, this ); + AddDirectoryButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddDirectoryButtonClick ), NULL, this ); + AddSecurityTokenSignatureButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnAddSecurityTokenSignatureButtonClick ), NULL, this ); + RemoveButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveButtonClick ), NULL, this ); + RemoveAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( KeyfilesPanelBase::OnRemoveAllButtonClick ), NULL, this ); +} + +ProgressWizardPageBase::ProgressWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer81; + bSizer81 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer82; + bSizer82 = new wxBoxSizer( wxVERTICAL ); + + ProgressSizer = new wxBoxSizer( wxHORIZONTAL ); + + ProgressGauge = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,-1 ), wxGA_HORIZONTAL|wxGA_SMOOTH ); + ProgressGauge->SetValue( 0 ); + ProgressSizer->Add( ProgressGauge, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + AbortButton = new wxButton( this, wxID_ANY, _("&Abort"), wxDefaultPosition, wxDefaultSize, 0 ); + AbortButton->Enable( false ); + + ProgressSizer->Add( AbortButton, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer82->Add( ProgressSizer, 0, wxEXPAND, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + bSizer82->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); + + bSizer81->Add( bSizer82, 0, wxEXPAND, 5 ); + + this->SetSizer( bSizer81 ); + this->Layout(); + bSizer81->Fit( this ); + + // Connect Events + AbortButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); +} + +ProgressWizardPageBase::~ProgressWizardPageBase() +{ + // Disconnect Events + AbortButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); +} + +SelectDirectoryWizardPageBase::SelectDirectoryWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer68; + bSizer68 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer69; + bSizer69 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer70; + bSizer70 = new wxBoxSizer( wxHORIZONTAL ); + + DirectoryTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer70->Add( DirectoryTextCtrl, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + BrowseButton = new wxButton( this, wxID_ANY, _("&Browse..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer70->Add( BrowseButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer69->Add( bSizer70, 0, wxEXPAND, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( 300 ); + bSizer69->Add( InfoStaticText, 1, wxALL|wxEXPAND, 5 ); + + bSizer68->Add( bSizer69, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer68 ); + this->Layout(); + + // Connect Events + DirectoryTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnDirectoryTextChanged ), NULL, this ); + BrowseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnBrowseButtonClick ), NULL, this ); +} + +SelectDirectoryWizardPageBase::~SelectDirectoryWizardPageBase() +{ + // Disconnect Events + DirectoryTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnDirectoryTextChanged ), NULL, this ); + BrowseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectDirectoryWizardPageBase::OnBrowseButtonClick ), NULL, this ); +} + +SingleChoiceWizardPageBase::SingleChoiceWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer71; + bSizer71 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer77; + bSizer77 = new wxBoxSizer( wxVERTICAL ); + + + bSizer77->Add( 0, 0, 0, wxEXPAND|wxTOP, 5 ); + + OuterChoicesSizer = new wxBoxSizer( wxVERTICAL ); + + ChoicesSizer = new wxBoxSizer( wxVERTICAL ); + + OuterChoicesSizer->Add( ChoicesSizer, 0, wxEXPAND, 5 ); + + bSizer77->Add( OuterChoicesSizer, 0, wxEXPAND, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + bSizer77->Add( InfoStaticText, 1, wxALL|wxEXPAND, 5 ); + + bSizer71->Add( bSizer77, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer71 ); + this->Layout(); + bSizer71->Fit( this ); +} + +SingleChoiceWizardPageBase::~SingleChoiceWizardPageBase() +{ +} + +VolumeCreationProgressWizardPageBase::VolumeCreationProgressWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer104; + bSizer104 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer105; + bSizer105 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer31; + sbSizer31 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + KeySamplesUpperSizer = new wxBoxSizer( wxVERTICAL ); + + KeySamplesUpperInnerSizer = new wxBoxSizer( wxVERTICAL ); + + KeySamplesUpperSizer->Add( KeySamplesUpperInnerSizer, 1, wxEXPAND|wxTOP, 3 ); + + sbSizer31->Add( KeySamplesUpperSizer, 1, wxEXPAND, 30 ); + + wxFlexGridSizer* fgSizer5; + fgSizer5 = new wxFlexGridSizer( 3, 2, 0, 0 ); + fgSizer5->SetFlexibleDirection( wxBOTH ); + fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxStaticText* m_staticText25; + m_staticText25 = new wxStaticText( this, wxID_ANY, _("Random Pool:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText25->Wrap( -1 ); + fgSizer5->Add( m_staticText25, 0, wxALL|wxALIGN_RIGHT|wxALIGN_BOTTOM, 5 ); + + wxBoxSizer* bSizer126; + bSizer126 = new wxBoxSizer( wxHORIZONTAL ); + + RandomPoolSampleStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + RandomPoolSampleStaticText->Wrap( -1 ); + RandomPoolSampleStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); + + bSizer126->Add( RandomPoolSampleStaticText, 0, wxEXPAND|wxTOP|wxRIGHT|wxALIGN_BOTTOM, 7 ); + + DisplayKeysCheckBox = new wxCheckBox( this, wxID_ANY, _("Show"), wxDefaultPosition, wxDefaultSize, 0 ); + DisplayKeysCheckBox->SetValue(true); + + bSizer126->Add( DisplayKeysCheckBox, 0, wxEXPAND|wxRIGHT, 5 ); + + fgSizer5->Add( bSizer126, 1, wxEXPAND|wxALIGN_BOTTOM, 5 ); + + wxStaticText* m_staticText28; + m_staticText28 = new wxStaticText( this, wxID_ANY, _("Header Key:"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_staticText28->Wrap( -1 ); + fgSizer5->Add( m_staticText28, 0, wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_BOTTOM, 5 ); + + HeaderKeySampleStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + HeaderKeySampleStaticText->Wrap( -1 ); + HeaderKeySampleStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); + + fgSizer5->Add( HeaderKeySampleStaticText, 0, wxALIGN_BOTTOM|wxEXPAND|wxTOP|wxRIGHT, 2 ); + + wxStaticText* m_staticText29; + m_staticText29 = new wxStaticText( this, wxID_ANY, _("Master Key:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText29->Wrap( -1 ); + fgSizer5->Add( m_staticText29, 0, wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_BOTTOM, 5 ); + + MasterKeySampleStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + MasterKeySampleStaticText->Wrap( -1 ); + MasterKeySampleStaticText->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Courier New") ) ); + + fgSizer5->Add( MasterKeySampleStaticText, 0, wxEXPAND|wxALIGN_BOTTOM|wxTOP|wxRIGHT, 2 ); + + sbSizer31->Add( fgSizer5, 0, wxEXPAND, 5 ); + + bSizer105->Add( sbSizer31, 0, wxALL|wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer32; + sbSizer32 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxBoxSizer* bSizer106; + bSizer106 = new wxBoxSizer( wxHORIZONTAL ); + + ProgressGauge = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL|wxGA_SMOOTH ); + bSizer106->Add( ProgressGauge, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + AbortButton = new wxButton( this, wxID_ANY, _("Abort"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer106->Add( AbortButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + sbSizer32->Add( bSizer106, 0, wxEXPAND, 5 ); + + wxGridSizer* gSizer6; + gSizer6 = new wxGridSizer( 1, 3, 0, 0 ); + + wxBoxSizer* bSizer108; + bSizer108 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText31 = new wxStaticText( this, wxID_ANY, _("Done"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText31->Wrap( -1 ); + bSizer108->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_panel12 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxSUNKEN_BORDER ); + wxBoxSizer* bSizer115; + bSizer115 = new wxBoxSizer( wxHORIZONTAL ); + + SizeDoneStaticText = new wxStaticText( m_panel12, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT|wxST_NO_AUTORESIZE ); + SizeDoneStaticText->Wrap( -1 ); + bSizer115->Add( SizeDoneStaticText, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 3 ); + + m_panel12->SetSizer( bSizer115 ); + m_panel12->Layout(); + bSizer115->Fit( m_panel12 ); + bSizer108->Add( m_panel12, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + gSizer6->Add( bSizer108, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer1081; + bSizer1081 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText311 = new wxStaticText( this, wxID_ANY, _("Speed"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText311->Wrap( -1 ); + bSizer1081->Add( m_staticText311, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_panel121 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER ); + wxBoxSizer* bSizer1151; + bSizer1151 = new wxBoxSizer( wxHORIZONTAL ); + + SpeedStaticText = new wxStaticText( m_panel121, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT|wxST_NO_AUTORESIZE ); + SpeedStaticText->Wrap( -1 ); + bSizer1151->Add( SpeedStaticText, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 3 ); + + m_panel121->SetSizer( bSizer1151 ); + m_panel121->Layout(); + bSizer1151->Fit( m_panel121 ); + bSizer1081->Add( m_panel121, 1, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + gSizer6->Add( bSizer1081, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer1082; + bSizer1082 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText312 = new wxStaticText( this, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText312->Wrap( -1 ); + bSizer1082->Add( m_staticText312, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_panel122 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1152; + bSizer1152 = new wxBoxSizer( wxHORIZONTAL ); + + TimeLeftStaticText = new wxStaticText( m_panel122, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT|wxST_NO_AUTORESIZE ); + TimeLeftStaticText->Wrap( -1 ); + bSizer1152->Add( TimeLeftStaticText, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 3 ); + + m_panel122->SetSizer( bSizer1152 ); + m_panel122->Layout(); + bSizer1152->Fit( m_panel122 ); + bSizer1082->Add( m_panel122, 1, wxALL|wxEXPAND, 5 ); + + gSizer6->Add( bSizer1082, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + + sbSizer32->Add( gSizer6, 0, wxEXPAND|wxTOP, 2 ); + + bSizer105->Add( sbSizer32, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + bSizer105->Add( 0, 0, 0, wxTOP|wxBOTTOM, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + bSizer105->Add( InfoStaticText, 0, wxALL, 5 ); + + bSizer104->Add( bSizer105, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer104 ); + this->Layout(); + bSizer104->Fit( this ); + + // Connect Events + DisplayKeysCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnDisplayKeysCheckBoxClick ), NULL, this ); + AbortButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); +} + +VolumeCreationProgressWizardPageBase::~VolumeCreationProgressWizardPageBase() +{ + // Disconnect Events + DisplayKeysCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnDisplayKeysCheckBoxClick ), NULL, this ); + AbortButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeCreationProgressWizardPageBase::OnAbortButtonClick ), NULL, this ); +} + +VolumeLocationWizardPageBase::VolumeLocationWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer86; + bSizer86 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer87; + bSizer87 = new wxBoxSizer( wxVERTICAL ); + + + bSizer87->Add( 0, 0, 0, wxEXPAND|wxTOP, 5 ); + + wxBoxSizer* bSizer88; + bSizer88 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer89; + bSizer89 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer126; + bSizer126 = new wxBoxSizer( wxHORIZONTAL ); + + VolumePathComboBox = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN ); + bSizer126->Add( VolumePathComboBox, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer90; + bSizer90 = new wxBoxSizer( wxVERTICAL ); + + SelectFileButton = new wxButton( this, wxID_ANY, _("Select &File..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer90->Add( SelectFileButton, 0, wxALL|wxEXPAND, 5 ); + + SelectDeviceButton = new wxButton( this, wxID_ANY, _("Select D&evice..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer90->Add( SelectDeviceButton, 0, wxALL|wxEXPAND, 5 ); + + bSizer126->Add( bSizer90, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer89->Add( bSizer126, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer91; + bSizer91 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer91->Add( 0, 0, 0, wxLEFT, 5 ); + + NoHistoryCheckBox = new wxCheckBox( this, wxID_ANY, _("&Never save history"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer91->Add( NoHistoryCheckBox, 0, wxALL|wxEXPAND, 5 ); + + bSizer89->Add( bSizer91, 0, wxEXPAND, 5 ); + + bSizer88->Add( bSizer89, 1, wxEXPAND, 5 ); + + bSizer87->Add( bSizer88, 0, wxEXPAND, 5 ); + + + bSizer87->Add( 0, 0, 0, wxEXPAND|wxBOTTOM, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + bSizer87->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); + + bSizer86->Add( bSizer87, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer86 ); + this->Layout(); + bSizer86->Fit( this ); + + // Connect Events + VolumePathComboBox->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnVolumePathTextChanged ), NULL, this ); + SelectFileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectFileButtonClick ), NULL, this ); + SelectDeviceButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectDeviceButtonClick ), NULL, this ); + NoHistoryCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnNoHistoryCheckBoxClick ), NULL, this ); +} + +VolumeLocationWizardPageBase::~VolumeLocationWizardPageBase() +{ + // Disconnect Events + VolumePathComboBox->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnVolumePathTextChanged ), NULL, this ); + SelectFileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectFileButtonClick ), NULL, this ); + SelectDeviceButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnSelectDeviceButtonClick ), NULL, this ); + NoHistoryCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeLocationWizardPageBase::OnNoHistoryCheckBoxClick ), NULL, this ); +} + +VolumeFormatOptionsWizardPageBase::VolumeFormatOptionsWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer124; + bSizer124 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer125; + bSizer125 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer33; + sbSizer33 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Filesystem Options") ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer6; + fgSizer6 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer6->SetFlexibleDirection( wxBOTH ); + fgSizer6->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticText43 = new wxStaticText( this, wxID_ANY, _("Filesystem type:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText43->Wrap( -1 ); + fgSizer6->Add( m_staticText43, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + wxArrayString FilesystemTypeChoiceChoices; + FilesystemTypeChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, FilesystemTypeChoiceChoices, 0 ); + FilesystemTypeChoice->SetSelection( 0 ); + fgSizer6->Add( FilesystemTypeChoice, 0, wxALL, 5 ); + + sbSizer33->Add( fgSizer6, 1, wxEXPAND, 5 ); + + bSizer125->Add( sbSizer33, 0, wxEXPAND|wxALL, 5 ); + + wxStaticBoxSizer* sbSizer34; + sbSizer34 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Volume Format Options") ), wxVERTICAL ); + + QuickFormatCheckBox = new wxCheckBox( this, wxID_ANY, _("Quick format"), wxDefaultPosition, wxDefaultSize, 0 ); + + sbSizer34->Add( QuickFormatCheckBox, 0, wxALL, 5 ); + + bSizer125->Add( sbSizer34, 0, wxEXPAND|wxALL, 5 ); + + + bSizer125->Add( 0, 0, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + bSizer125->Add( InfoStaticText, 0, wxALL, 5 ); + + bSizer124->Add( bSizer125, 0, wxEXPAND, 5 ); + + this->SetSizer( bSizer124 ); + this->Layout(); + bSizer124->Fit( this ); + + // Connect Events + FilesystemTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnFilesystemTypeSelected ), NULL, this ); + QuickFormatCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnQuickFormatCheckBoxClick ), NULL, this ); +} + +VolumeFormatOptionsWizardPageBase::~VolumeFormatOptionsWizardPageBase() +{ + // Disconnect Events + FilesystemTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnFilesystemTypeSelected ), NULL, this ); + QuickFormatCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeFormatOptionsWizardPageBase::OnQuickFormatCheckBoxClick ), NULL, this ); +} + +VolumePasswordPanelBase::VolumePasswordPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); + + GridBagSizer = new wxGridBagSizer( 0, 0 ); + GridBagSizer->AddGrowableCol( 1 ); + GridBagSizer->SetFlexibleDirection( wxBOTH ); + GridBagSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + GridBagSizer->SetEmptyCellSize( wxSize( 0,0 ) ); + + PasswordStaticText = new wxStaticText( this, wxID_ANY, _("Password:"), wxDefaultPosition, wxDefaultSize, 0 ); + PasswordStaticText->Wrap( -1 ); + GridBagSizer->Add( PasswordStaticText, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxBOTTOM|wxRIGHT, 5 ); + + PasswordTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD ); + PasswordTextCtrl->SetMaxLength( 1 ); + PasswordTextCtrl->SetMinSize( wxSize( 232,-1 ) ); + + GridBagSizer->Add( PasswordTextCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + ConfirmPasswordStaticText = new wxStaticText( this, wxID_ANY, _("Confirm password:"), wxDefaultPosition, wxDefaultSize, 0 ); + ConfirmPasswordStaticText->Wrap( -1 ); + GridBagSizer->Add( ConfirmPasswordStaticText, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + + ConfirmPasswordTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD ); + ConfirmPasswordTextCtrl->SetMaxLength( 1 ); + ConfirmPasswordTextCtrl->SetMinSize( wxSize( 232,-1 ) ); + + GridBagSizer->Add( ConfirmPasswordTextCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + CacheCheckBox = new wxCheckBox( this, wxID_ANY, _("Cach&e passwords and keyfiles in memory "), wxDefaultPosition, wxDefaultSize, 0 ); + + GridBagSizer->Add( CacheCheckBox, wxGBPosition( 3, 1 ), wxGBSpan( 1, 2 ), wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + DisplayPasswordCheckBox = new wxCheckBox( this, wxID_ANY, _("&Display password"), wxDefaultPosition, wxDefaultSize, 0 ); + + GridBagSizer->Add( DisplayPasswordCheckBox, wxGBPosition( 4, 1 ), wxGBSpan( 1, 2 ), wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + UseKeyfilesCheckBox = new wxCheckBox( this, wxID_ANY, _("U&se keyfiles"), wxDefaultPosition, wxDefaultSize, 0 ); + + GridBagSizer->Add( UseKeyfilesCheckBox, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxTOP|wxRIGHT|wxLEFT, 5 ); + + KeyfilesButton = new wxButton( this, wxID_ANY, _("&Keyfiles..."), wxDefaultPosition, wxDefaultSize, 0 ); + GridBagSizer->Add( KeyfilesButton, wxGBPosition( 5, 2 ), wxGBSpan( 1, 1 ), wxALIGN_RIGHT|wxALIGN_BOTTOM|wxLEFT, 5 ); + + Pkcs5PrfSizer = new wxBoxSizer( wxVERTICAL ); + + GridBagSizer->Add( Pkcs5PrfSizer, wxGBPosition( 6, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + Pkcs5PrfStaticText = new wxStaticText( this, wxID_ANY, _("PKCS-5 PRF:"), wxDefaultPosition, wxDefaultSize, 0 ); + Pkcs5PrfStaticText->Wrap( -1 ); + GridBagSizer->Add( Pkcs5PrfStaticText, wxGBPosition( 7, 0 ), wxGBSpan( 1, 1 ), wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + wxString Pkcs5PrfChoiceChoices[] = { _("Unchanged") }; + int Pkcs5PrfChoiceNChoices = sizeof( Pkcs5PrfChoiceChoices ) / sizeof( wxString ); + Pkcs5PrfChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, Pkcs5PrfChoiceNChoices, Pkcs5PrfChoiceChoices, 0 ); + Pkcs5PrfChoice->SetSelection( 0 ); + GridBagSizer->Add( Pkcs5PrfChoice, wxGBPosition( 7, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + PasswordPlaceholderSizer = new wxBoxSizer( wxVERTICAL ); + + GridBagSizer->Add( PasswordPlaceholderSizer, wxGBPosition( 8, 1 ), wxGBSpan( 1, 2 ), wxTOP|wxEXPAND, 5 ); + + bSizer7->Add( GridBagSizer, 1, wxALL|wxEXPAND, 5 ); + + this->SetSizer( bSizer7 ); + this->Layout(); + bSizer7->Fit( this ); + + // Connect Events + PasswordTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); + ConfirmPasswordTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); + DisplayPasswordCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnDisplayPasswordCheckBoxClick ), NULL, this ); + UseKeyfilesCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnUseKeyfilesCheckBoxClick ), NULL, this ); + KeyfilesButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonClick ), NULL, this ); + KeyfilesButton->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightDown ), NULL, this ); + KeyfilesButton->Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightClick ), NULL, this ); +} + +VolumePasswordPanelBase::~VolumePasswordPanelBase() +{ + // Disconnect Events + PasswordTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); + ConfirmPasswordTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumePasswordPanelBase::OnTextChanged ), NULL, this ); + DisplayPasswordCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnDisplayPasswordCheckBoxClick ), NULL, this ); + UseKeyfilesCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnUseKeyfilesCheckBoxClick ), NULL, this ); + KeyfilesButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonClick ), NULL, this ); + KeyfilesButton->Disconnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightDown ), NULL, this ); + KeyfilesButton->Disconnect( wxEVT_RIGHT_UP, wxMouseEventHandler( VolumePasswordPanelBase::OnKeyfilesButtonRightClick ), NULL, this ); +} + +VolumePasswordWizardPageBase::VolumePasswordWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer101; + bSizer101 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer102; + bSizer102 = new wxBoxSizer( wxVERTICAL ); + + PasswordPanelSizer = new wxBoxSizer( wxVERTICAL ); + + bSizer102->Add( PasswordPanelSizer, 0, wxEXPAND, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + bSizer102->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); + + bSizer101->Add( bSizer102, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer101 ); + this->Layout(); + bSizer101->Fit( this ); +} + +VolumePasswordWizardPageBase::~VolumePasswordWizardPageBase() +{ +} + +VolumeSizeWizardPageBase::VolumeSizeWizardPageBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : WizardPage( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer98; + bSizer98 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer99; + bSizer99 = new wxBoxSizer( wxVERTICAL ); + + + bSizer99->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer100; + bSizer100 = new wxBoxSizer( wxHORIZONTAL ); + + VolumeSizeTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer100->Add( VolumeSizeTextCtrl, 0, wxALL, 5 ); + + wxArrayString VolumeSizePrefixChoiceChoices; + VolumeSizePrefixChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, VolumeSizePrefixChoiceChoices, 0 ); + VolumeSizePrefixChoice->SetSelection( 0 ); + bSizer100->Add( VolumeSizePrefixChoice, 0, wxALL, 5 ); + + bSizer99->Add( bSizer100, 0, wxEXPAND, 5 ); + + + bSizer99->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + FreeSpaceStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + FreeSpaceStaticText->Wrap( -1 ); + bSizer99->Add( FreeSpaceStaticText, 0, wxALL|wxEXPAND, 5 ); + + + bSizer99->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + InfoStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + InfoStaticText->Wrap( -1 ); + bSizer99->Add( InfoStaticText, 0, wxALL|wxEXPAND, 5 ); + + bSizer98->Add( bSizer99, 0, wxEXPAND, 5 ); + + this->SetSizer( bSizer98 ); + this->Layout(); + bSizer98->Fit( this ); + + // Connect Events + VolumeSizeTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizeTextChanged ), NULL, this ); + VolumeSizePrefixChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizePrefixSelected ), NULL, this ); +} + +VolumeSizeWizardPageBase::~VolumeSizeWizardPageBase() +{ + // Disconnect Events + VolumeSizeTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizeTextChanged ), NULL, this ); + VolumeSizePrefixChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizePrefixSelected ), NULL, this ); +} diff --git a/Main/Forms/Forms.h b/Main/Forms/Forms.h index b194876..6503f29 100644 --- a/Main/Forms/Forms.h +++ b/Main/Forms/Forms.h @@ -1,1028 +1,998 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder -// http://www.wxformbuilder.org/ -// -// PLEASE DO "NOT" EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#ifndef __Forms__ -#define __Forms__ - -#include - -class WizardPage; - -#include "WizardPage.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////// - -namespace TrueCrypt -{ - /////////////////////////////////////////////////////////////////////////////// - /// Class MainFrameBase - /////////////////////////////////////////////////////////////////////////////// - class MainFrameBase : public wxFrame - { - private: - - protected: - wxMenuBar* MainMenuBar; - wxMenu* VolumesMenu; - wxMenuItem* MountVolumeMenuItem; - wxMenuItem* DismountVolumeMenuItem; - wxMenuItem* DismountAllMenuItem; - wxMenuItem* VolumePropertiesMenuItem; - wxMenu* KeyfilesMenu; - wxMenu* FavoritesMenu; - wxMenuItem* AddToFavoritesMenuItem; - wxMenuItem* AddAllMountedToFavoritesMenuItem; - wxMenu* ToolsMenu; - wxMenuItem* TravelerDiskWizardMenuItem; - wxMenuItem* BackupVolumeHeadersMenuItem; - wxMenuItem* RestoreVolumeHeaderMenuItem; - wxMenuItem* WipeCachedPasswordsMenuItem; - wxMenu* SettingsMenu; - wxMenuItem* HotkeysMenuItem; - wxMenuItem* PreferencesMenuItem; - wxMenu* HelpMenu; - wxPanel* MainPanel; - wxListCtrl* SlotListCtrl; - wxStaticBoxSizer* LowStaticBoxSizer; - wxBoxSizer* HigherButtonSizer; - wxButton* CreateVolumeButton; - wxButton* VolumePropertiesButton; - wxButton* WipeCacheButton; - - wxStaticBoxSizer* VolumeStaticBoxSizer; - wxGridBagSizer* VolumeGridBagSizer; - wxStaticBitmap* LogoBitmap; - wxComboBox* VolumePathComboBox; - wxButton* SelectFileButton; - wxCheckBox* NoHistoryCheckBox; - wxButton* VolumeToolsButton; - wxButton* SelectDeviceButton; - - wxButton* VolumeButton; - wxButton* MountAllDevicesButton; - wxButton* DismountAllButton; - wxButton* ExitButton; - - // Virtual event handlers, overide them in your derived class - virtual void OnActivate( wxActivateEvent& event ){ event.Skip(); } - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnMountVolumeMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMountAllDevicesButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDismountVolumeMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDismountAllButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCreateVolumeButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangePasswordMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangePkcs5PrfMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnVolumePropertiesButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangeKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRemoveKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCreateKeyfileMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnManageSecurityTokenKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCloseAllSecurityTokenSessionsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDefaultKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAddToFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAddAllMountedToFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOrganizeFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMountAllFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnEncryptionTestMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnTravelerDiskWizardMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnBackupVolumeHeadersMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRestoreVolumeHeaderMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnWipeCacheButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnHotkeysMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSecurityTokenPreferencesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnPreferencesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnUserGuideMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOnlineHelpMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnBeginnersTutorialMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnFaqMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnWebsiteMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDownloadsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnNewsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnVersionHistoryMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLegalNoticesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnReportBugMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnForumsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnContactMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDonationsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAboutMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemRightClick( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } - virtual void OnLogoBitmapClick( wxMouseEvent& event ){ event.Skip(); } - virtual void OnSelectFileButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnNoHistoryCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnVolumeToolsButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSelectDeviceButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnVolumeButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnExitButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - MainFrameBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,496 ), long style = wxCAPTION|wxCLOSE_BOX|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxTAB_TRAVERSAL ); - ~MainFrameBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class WizardFrameBase - /////////////////////////////////////////////////////////////////////////////// - class WizardFrameBase : public wxFrame - { - private: - - protected: - wxPanel* MainPanel; - wxStaticBitmap* WizardBitmap; - wxStaticText* PageTitleStaticText; - wxBoxSizer* PageSizer; - - wxButton* HelpButton; - - wxButton* PreviousButton; - wxButton* NextButton; - - wxButton* CancelButton; - - // Virtual event handlers, overide them in your derived class - virtual void OnActivate( wxActivateEvent& event ){ event.Skip(); } - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnMouseMotion( wxMouseEvent& event ){ event.Skip(); } - virtual void OnHelpButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnPreviousButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnNextButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancelButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - WizardFrameBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxCAPTION|wxCLOSE_BOX|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxTAB_TRAVERSAL ); - ~WizardFrameBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class AboutDialogBase - /////////////////////////////////////////////////////////////////////////////// - class AboutDialogBase : public wxDialog - { - private: - - protected: - wxPanel* m_panel14; - - wxStaticBitmap* LogoBitmap; - wxStaticText* VersionStaticText; - - wxStaticText* CopyrightStaticText; - - wxHyperlinkCtrl* WebsiteHyperlink; - wxStaticLine* m_staticline3; - wxTextCtrl* CreditsTextCtrl; - - wxStaticLine* m_staticline4; - wxStaticLine* m_staticline5; - - wxButton* DonationsButton; - - - // Virtual event handlers, overide them in your derived class - virtual void OnWebsiteHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } - virtual void OnDonationsButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - AboutDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~AboutDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class ChangePasswordDialogBase - /////////////////////////////////////////////////////////////////////////////// - class ChangePasswordDialogBase : public wxDialog - { - private: - - protected: - wxStaticBoxSizer* CurrentSizer; - wxBoxSizer* CurrentPasswordPanelSizer; - wxStaticBoxSizer* NewSizer; - wxBoxSizer* NewPasswordPanelSizer; - wxButton* OKButton; - wxButton* CancelButton; - - // Virtual event handlers, overide them in your derived class - virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - ChangePasswordDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~ChangePasswordDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class DeviceSelectionDialogBase - /////////////////////////////////////////////////////////////////////////////// - class DeviceSelectionDialogBase : public wxDialog - { - private: - - protected: - wxListCtrl* DeviceListCtrl; - wxStdDialogButtonSizer* StdButtons; - wxButton* StdButtonsOK; - wxButton* StdButtonsCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } - - - public: - DeviceSelectionDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select a Partition or Device"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); - ~DeviceSelectionDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class EncryptionTestDialogBase - /////////////////////////////////////////////////////////////////////////////// - class EncryptionTestDialogBase : public wxDialog - { - private: - - protected: - wxChoice* EncryptionAlgorithmChoice; - wxCheckBox* XtsModeCheckBox; - wxTextCtrl* KeyTextCtrl; - wxStaticText* KeySizeStaticText; - wxTextCtrl* SecondaryKeyTextCtrl; - wxTextCtrl* DataUnitNumberTextCtrl; - wxTextCtrl* BlockNumberTextCtrl; - wxTextCtrl* PlainTextTextCtrl; - wxTextCtrl* CipherTextTextCtrl; - wxButton* EncryptButton; - wxButton* DecryptButton; - wxButton* AutoTestAllButton; - wxButton* ResetButton; - wxButton* CloseButton; - - // Virtual event handlers, overide them in your derived class - virtual void OnEncryptionAlgorithmSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnXtsModeCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnEncryptButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDecryptButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAutoTestAllButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnResetButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - EncryptionTestDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt - Test Vectors"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~EncryptionTestDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class FavoriteVolumesDialogBase - /////////////////////////////////////////////////////////////////////////////// - class FavoriteVolumesDialogBase : public wxDialog - { - private: - - protected: - wxListCtrl* FavoritesListCtrl; - wxButton* MoveUpButton; - wxButton* MoveDownButton; - wxButton* RemoveButton; - wxButton* RemoveAllButton; - - wxButton* OKButton; - wxButton* CancelButton; - - // Virtual event handlers, overide them in your derived class - virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } - virtual void OnMoveUpButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMoveDownButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRemoveButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRemoveAllButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - FavoriteVolumesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Favorite Volumes"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~FavoriteVolumesDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class KeyfilesDialogBase - /////////////////////////////////////////////////////////////////////////////// - class KeyfilesDialogBase : public wxDialog - { - private: - - protected: - wxBoxSizer* UpperSizer; - wxBoxSizer* PanelSizer; - wxButton* OKButton; - wxButton* CancelButton; - wxStaticText* WarningStaticText; - wxBoxSizer* KeyfilesNoteSizer; - wxStaticText* KeyfilesNoteStaticText; - wxHyperlinkCtrl* KeyfilesHyperlink; - wxButton* CreateKeyfileButtton; - - // Virtual event handlers, overide them in your derived class - virtual void OnKeyfilesHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } - virtual void OnCreateKeyfileButttonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - KeyfilesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Keyfiles"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~KeyfilesDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class KeyfileGeneratorDialogBase - /////////////////////////////////////////////////////////////////////////////// - class KeyfileGeneratorDialogBase : public wxDialog - { - private: - - protected: - wxBoxSizer* MainSizer; - - wxChoice* HashChoice; - - wxStaticText* RandomPoolStaticText; - wxCheckBox* ShowRandomPoolCheckBox; - - wxStaticText* MouseStaticText; - - wxButton* GenerateButton; - - - // Virtual event handlers, overide them in your derived class - virtual void OnMouseMotion( wxMouseEvent& event ){ event.Skip(); } - virtual void OnHashSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnShowRandomPoolCheckBoxClicked( wxCommandEvent& event ){ event.Skip(); } - virtual void OnGenerateButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - KeyfileGeneratorDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~KeyfileGeneratorDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class LegalNoticesDialogBase - /////////////////////////////////////////////////////////////////////////////// - class LegalNoticesDialogBase : public wxDialog - { - private: - - protected: - wxTextCtrl* LegalNoticesTextCtrl; - - public: - LegalNoticesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt - Legal Notices"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~LegalNoticesDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class MountOptionsDialogBase - /////////////////////////////////////////////////////////////////////////////// - class MountOptionsDialogBase : public wxDialog - { - private: - - protected: - wxBoxSizer* PasswordSizer; - wxButton* OKButton; - wxButton* CancelButton; - - wxButton* OptionsButton; - wxPanel* OptionsPanel; - wxStaticBoxSizer* OptionsSizer; - - wxCheckBox* ReadOnlyCheckBox; - wxCheckBox* RemovableCheckBox; - wxCheckBox* PartitionInSystemEncryptionScopeCheckBox; - wxStaticBoxSizer* ProtectionSizer; - wxCheckBox* ProtectionCheckBox; - wxBoxSizer* ProtectionPasswordSizer; - wxHyperlinkCtrl* ProtectionHyperlinkCtrl; - wxBoxSizer* FilesystemSizer; - wxPanel* m_panel8; - wxCheckBox* NoFilesystemCheckBox; - wxGridBagSizer* FilesystemOptionsSizer; - wxBoxSizer* FilesystemSpacer; - wxStaticText* MountPointTextCtrlStaticText; - wxTextCtrl* MountPointTextCtrl; - wxButton* MountPointButton; - wxStaticText* FilesystemOptionsStaticText; - wxTextCtrl* FilesystemOptionsTextCtrl; - - // Virtual event handlers, overide them in your derived class - virtual void OnInitDialog( wxInitDialogEvent& event ){ event.Skip(); } - virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOptionsButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnReadOnlyCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnProtectionCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnProtectionHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } - virtual void OnNoFilesystemCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMountPointButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - MountOptionsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Enter TrueCrypt Volume Password"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); - ~MountOptionsDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class NewSecurityTokenKeyfileDialogBase - /////////////////////////////////////////////////////////////////////////////// - class NewSecurityTokenKeyfileDialogBase : public wxDialog - { - private: - - protected: - wxChoice* SecurityTokenChoice; - wxTextCtrl* KeyfileNameTextCtrl; - wxStdDialogButtonSizer* StdButtons; - wxButton* StdButtonsOK; - wxButton* StdButtonsCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnKeyfileNameChanged( wxCommandEvent& event ){ event.Skip(); } - - - public: - NewSecurityTokenKeyfileDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("New Security Token Keyfile Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~NewSecurityTokenKeyfileDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class PreferencesDialogBase - /////////////////////////////////////////////////////////////////////////////// - class PreferencesDialogBase : public wxDialog - { - private: - - protected: - wxNotebook* PreferencesNotebook; - wxPanel* SecurityPage; - wxStaticBoxSizer* AutoDismountSizer; - wxCheckBox* DismountOnLogOffCheckBox; - wxCheckBox* DismountOnScreenSaverCheckBox; - wxCheckBox* DismountOnPowerSavingCheckBox; - wxCheckBox* DismountOnInactivityCheckBox; - wxSpinCtrl* DismountOnInactivitySpinCtrl; - wxCheckBox* ForceAutoDismountCheckBox; - wxStaticBoxSizer* FilesystemSecuritySizer; - wxCheckBox* PreserveTimestampsCheckBox; - wxCheckBox* WipeCacheOnCloseCheckBox; - wxCheckBox* WipeCacheOnAutoDismountCheckBox; - wxPanel* DefaultMountOptionsPage; - wxCheckBox* MountReadOnlyCheckBox; - wxCheckBox* MountRemovableCheckBox; - wxCheckBox* CachePasswordsCheckBox; - wxStaticBoxSizer* FilesystemSizer; - wxTextCtrl* FilesystemOptionsTextCtrl; - wxPanel* BackgroundTaskPanel; - wxCheckBox* BackgroundTaskEnabledCheckBox; - wxCheckBox* CloseBackgroundTaskOnNoVolumesCheckBox; - wxCheckBox* BackgroundTaskMenuMountItemsEnabledCheckBox; - wxCheckBox* BackgroundTaskMenuOpenItemsEnabledCheckBox; - wxCheckBox* BackgroundTaskMenuDismountItemsEnabledCheckBox; - wxPanel* SystemIntegrationPage; - wxStaticBoxSizer* LogOnSizer; - wxCheckBox* StartOnLogonCheckBox; - wxCheckBox* MountFavoritesOnLogonCheckBox; - wxCheckBox* MountDevicesOnLogonCheckBox; - wxStaticBoxSizer* ExplorerSizer; - wxCheckBox* OpenExplorerWindowAfterMountCheckBox; - wxCheckBox* CloseExplorerWindowsOnDismountCheckBox; - wxStaticBoxSizer* KernelServicesSizer; - wxCheckBox* NoKernelCryptoCheckBox; - wxBoxSizer* DefaultKeyfilesSizer; - wxCheckBox* UseKeyfilesCheckBox; - wxTextCtrl* Pkcs11ModulePathTextCtrl; - wxButton* SelectPkcs11ModuleButton; - wxCheckBox* CloseSecurityTokenSessionsAfterMountCheckBox; - wxListCtrl* HotkeyListCtrl; - wxTextCtrl* HotkeyTextCtrl; - wxButton* AssignHotkeyButton; - - wxCheckBox* HotkeyControlCheckBox; - wxCheckBox* HotkeyShiftCheckBox; - wxCheckBox* HotkeyAltCheckBox; - wxCheckBox* HotkeyWinCheckBox; - wxButton* RemoveHotkeyButton; - wxCheckBox* BeepAfterHotkeyMountDismountCheckBox; - wxCheckBox* DisplayMessageAfterHotkeyDismountCheckBox; - wxStdDialogButtonSizer* StdButtons; - wxButton* StdButtonsOK; - wxButton* StdButtonsCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnDismountOnScreenSaverCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDismountOnPowerSavingCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnForceAutoDismountCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnPreserveTimestampsCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnBackgroundTaskEnabledCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnNoKernelCryptoCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSelectPkcs11ModuleButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnHotkeyListItemDeselected( wxListEvent& event ){ event.Skip(); } - virtual void OnHotkeyListItemSelected( wxListEvent& event ){ event.Skip(); } - virtual void OnAssignHotkeyButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRemoveHotkeyButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancelButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - wxPanel* DefaultKeyfilesPage; - wxPanel* SecurityTokensPage; - wxPanel* HotkeysPage; - PreferencesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Preferences"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~PreferencesDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class RandomPoolEnrichmentDialogBase - /////////////////////////////////////////////////////////////////////////////// - class RandomPoolEnrichmentDialogBase : public wxDialog - { - private: - - protected: - wxBoxSizer* MainSizer; - - wxChoice* HashChoice; - - wxStaticText* RandomPoolStaticText; - wxCheckBox* ShowRandomPoolCheckBox; - - wxStaticText* MouseStaticText; - - - wxButton* ContinueButton; - - - // Virtual event handlers, overide them in your derived class - virtual void OnMouseMotion( wxMouseEvent& event ){ event.Skip(); } - virtual void OnHashSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnShowRandomPoolCheckBoxClicked( wxCommandEvent& event ){ event.Skip(); } - - - public: - RandomPoolEnrichmentDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt - Random Pool Enrichment"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~RandomPoolEnrichmentDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class SecurityTokenKeyfilesDialogBase - /////////////////////////////////////////////////////////////////////////////// - class SecurityTokenKeyfilesDialogBase : public wxDialog - { - private: - - protected: - wxListCtrl* SecurityTokenKeyfileListCtrl; - wxButton* ExportButton; - wxButton* DeleteButton; - - wxButton* ImportButton; - wxButton* OKButton; - wxButton* CancelButton; - - // Virtual event handlers, overide them in your derived class - virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } - virtual void OnExportButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDeleteButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnImportButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - SecurityTokenKeyfilesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Security Token Keyfiles"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); - ~SecurityTokenKeyfilesDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class VolumePropertiesDialogBase - /////////////////////////////////////////////////////////////////////////////// - class VolumePropertiesDialogBase : public wxDialog - { - private: - - protected: - wxListCtrl* PropertiesListCtrl; - wxStdDialogButtonSizer* StdButtons; - wxButton* StdButtonsOK; - - public: - VolumePropertiesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Volume Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~VolumePropertiesDialogBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class EncryptionOptionsWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class EncryptionOptionsWizardPageBase : public WizardPage - { - private: - - protected: - wxChoice* EncryptionAlgorithmChoice; - wxButton* TestButton; - wxStaticText* EncryptionAlgorithmStaticText; - wxHyperlinkCtrl* EncryptionAlgorithmHyperlink; - - wxButton* BenchmarkButton; - wxChoice* HashChoice; - wxHyperlinkCtrl* HashHyperlink; - - // Virtual event handlers, overide them in your derived class - virtual void OnEncryptionAlgorithmSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnTestButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnEncryptionAlgorithmHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } - virtual void OnBenchmarkButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnHashHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } - - - public: - EncryptionOptionsWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~EncryptionOptionsWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class InfoWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class InfoWizardPageBase : public WizardPage - { - private: - - protected: - wxBoxSizer* InfoPageSizer; - wxStaticText* InfoStaticText; - - public: - InfoWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~InfoWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class KeyfilesPanelBase - /////////////////////////////////////////////////////////////////////////////// - class KeyfilesPanelBase : public wxPanel - { - private: - - protected: - wxListCtrl* KeyfilesListCtrl; - wxButton* AddFilesButton; - wxButton* AddDirectoryButton; - wxButton* AddSecurityTokenSignatureButton; - wxButton* RemoveButton; - wxButton* RemoveAllButton; - - // Virtual event handlers, overide them in your derived class - virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } - virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } - virtual void OnListSizeChanged( wxSizeEvent& event ){ event.Skip(); } - virtual void OnAddFilesButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAddDirectoryButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAddSecurityTokenSignatureButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRemoveButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRemoveAllButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - KeyfilesPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxTAB_TRAVERSAL ); - ~KeyfilesPanelBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class ProgressWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class ProgressWizardPageBase : public WizardPage - { - private: - - protected: - wxBoxSizer* ProgressSizer; - wxGauge* ProgressGauge; - wxButton* AbortButton; - wxStaticText* InfoStaticText; - - // Virtual event handlers, overide them in your derived class - virtual void OnAbortButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - ProgressWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~ProgressWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class SelectDirectoryWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class SelectDirectoryWizardPageBase : public WizardPage - { - private: - - protected: - wxTextCtrl* DirectoryTextCtrl; - wxButton* BrowseButton; - wxStaticText* InfoStaticText; - - // Virtual event handlers, overide them in your derived class - virtual void OnDirectoryTextChanged( wxCommandEvent& event ){ event.Skip(); } - virtual void OnBrowseButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - SelectDirectoryWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 200,65 ), long style = wxTAB_TRAVERSAL ); - ~SelectDirectoryWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class SingleChoiceWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class SingleChoiceWizardPageBase : public WizardPage - { - private: - - protected: - - wxBoxSizer* OuterChoicesSizer; - wxBoxSizer* ChoicesSizer; - wxStaticText* InfoStaticText; - - public: - SingleChoiceWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~SingleChoiceWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class TravelerMountOptionsWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class TravelerMountOptionsWizardPageBase : public WizardPage - { - private: - - protected: - wxTextCtrl* VolumePathTextCtrl; - wxButton* SelectVolumeButton; - wxChoice* MountPointChoice; - wxCheckBox* BackgroundTaskCheckBox; - wxCheckBox* OpenExplorerCheckBox; - wxCheckBox* MountReadOnlyCheckBox; - wxCheckBox* CachePasswordCheckBox; - wxStaticText* InfoStaticText; - - // Virtual event handlers, overide them in your derived class - virtual void OnVolumePathTextChanged( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSelectVolumeButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - TravelerMountOptionsWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~TravelerMountOptionsWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class VolumeCreationProgressWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class VolumeCreationProgressWizardPageBase : public WizardPage - { - private: - - protected: - wxBoxSizer* KeySamplesUpperSizer; - wxBoxSizer* KeySamplesUpperInnerSizer; - wxStaticText* RandomPoolSampleStaticText; - wxCheckBox* DisplayKeysCheckBox; - wxStaticText* HeaderKeySampleStaticText; - wxStaticText* MasterKeySampleStaticText; - wxGauge* ProgressGauge; - wxButton* AbortButton; - wxStaticText* m_staticText31; - wxPanel* m_panel12; - wxStaticText* SizeDoneStaticText; - wxStaticText* m_staticText311; - wxPanel* m_panel121; - wxStaticText* SpeedStaticText; - wxStaticText* m_staticText312; - wxPanel* m_panel122; - wxStaticText* TimeLeftStaticText; - - wxStaticText* InfoStaticText; - - // Virtual event handlers, overide them in your derived class - virtual void OnDisplayKeysCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAbortButtonClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - VolumeCreationProgressWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~VolumeCreationProgressWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class VolumeLocationWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class VolumeLocationWizardPageBase : public WizardPage - { - private: - - protected: - - wxComboBox* VolumePathComboBox; - wxButton* SelectFileButton; - wxButton* SelectDeviceButton; - - wxCheckBox* NoHistoryCheckBox; - - wxStaticText* InfoStaticText; - - // Virtual event handlers, overide them in your derived class - virtual void OnVolumePathTextChanged( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSelectFileButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSelectDeviceButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnNoHistoryCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - VolumeLocationWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~VolumeLocationWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class VolumeFormatOptionsWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class VolumeFormatOptionsWizardPageBase : public WizardPage - { - private: - - protected: - wxStaticText* m_staticText43; - wxChoice* FilesystemTypeChoice; - wxCheckBox* QuickFormatCheckBox; - - wxStaticText* InfoStaticText; - - // Virtual event handlers, overide them in your derived class - virtual void OnFilesystemTypeSelected( wxCommandEvent& event ){ event.Skip(); } - virtual void OnQuickFormatCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - - - public: - VolumeFormatOptionsWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~VolumeFormatOptionsWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class VolumePasswordPanelBase - /////////////////////////////////////////////////////////////////////////////// - class VolumePasswordPanelBase : public wxPanel - { - private: - - protected: - wxGridBagSizer* GridBagSizer; - wxStaticText* PasswordStaticText; - wxTextCtrl* PasswordTextCtrl; - wxStaticText* ConfirmPasswordStaticText; - wxTextCtrl* ConfirmPasswordTextCtrl; - wxCheckBox* CacheCheckBox; - wxCheckBox* DisplayPasswordCheckBox; - wxCheckBox* UseKeyfilesCheckBox; - wxButton* KeyfilesButton; - wxBoxSizer* Pkcs5PrfSizer; - wxStaticText* Pkcs5PrfStaticText; - wxChoice* Pkcs5PrfChoice; - wxBoxSizer* PasswordPlaceholderSizer; - - // Virtual event handlers, overide them in your derived class - virtual void OnTextChanged( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDisplayPasswordCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnUseKeyfilesCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnKeyfilesButtonClick( wxCommandEvent& event ){ event.Skip(); } - virtual void OnKeyfilesButtonRightDown( wxMouseEvent& event ){ event.Skip(); } - virtual void OnKeyfilesButtonRightClick( wxMouseEvent& event ){ event.Skip(); } - - - public: - VolumePasswordPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~VolumePasswordPanelBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class VolumePasswordWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class VolumePasswordWizardPageBase : public WizardPage - { - private: - - protected: - wxBoxSizer* PasswordPanelSizer; - wxStaticText* InfoStaticText; - - public: - VolumePasswordWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~VolumePasswordWizardPageBase(); - - }; - - /////////////////////////////////////////////////////////////////////////////// - /// Class VolumeSizeWizardPageBase - /////////////////////////////////////////////////////////////////////////////// - class VolumeSizeWizardPageBase : public WizardPage - { - private: - - protected: - - wxTextCtrl* VolumeSizeTextCtrl; - wxChoice* VolumeSizePrefixChoice; - - wxStaticText* FreeSpaceStaticText; - - wxStaticText* InfoStaticText; - - // Virtual event handlers, overide them in your derived class - virtual void OnVolumeSizeTextChanged( wxCommandEvent& event ){ event.Skip(); } - virtual void OnVolumeSizePrefixSelected( wxCommandEvent& event ){ event.Skip(); } - - - public: - VolumeSizeWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~VolumeSizeWizardPageBase(); - - }; - -} // namespace TrueCrypt - -#endif //__Forms__ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __Forms__ +#define __Forms__ + +#include + +class WizardPage; + +#include "WizardPage.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +namespace TrueCrypt +{ + /////////////////////////////////////////////////////////////////////////////// + /// Class MainFrameBase + /////////////////////////////////////////////////////////////////////////////// + class MainFrameBase : public wxFrame + { + private: + + protected: + wxMenuBar* MainMenuBar; + wxMenu* VolumesMenu; + wxMenuItem* MountVolumeMenuItem; + wxMenuItem* DismountVolumeMenuItem; + wxMenuItem* DismountAllMenuItem; + wxMenuItem* VolumePropertiesMenuItem; + wxMenu* KeyfilesMenu; + wxMenu* FavoritesMenu; + wxMenuItem* AddToFavoritesMenuItem; + wxMenuItem* AddAllMountedToFavoritesMenuItem; + wxMenu* ToolsMenu; + wxMenuItem* BackupVolumeHeadersMenuItem; + wxMenuItem* RestoreVolumeHeaderMenuItem; + wxMenuItem* WipeCachedPasswordsMenuItem; + wxMenu* SettingsMenu; + wxMenuItem* HotkeysMenuItem; + wxMenuItem* PreferencesMenuItem; + wxMenu* HelpMenu; + wxPanel* MainPanel; + wxListCtrl* SlotListCtrl; + wxStaticBoxSizer* LowStaticBoxSizer; + wxBoxSizer* HigherButtonSizer; + wxButton* CreateVolumeButton; + wxButton* VolumePropertiesButton; + wxButton* WipeCacheButton; + + wxStaticBoxSizer* VolumeStaticBoxSizer; + wxGridBagSizer* VolumeGridBagSizer; + wxStaticBitmap* LogoBitmap; + wxComboBox* VolumePathComboBox; + wxButton* SelectFileButton; + wxCheckBox* NoHistoryCheckBox; + wxButton* VolumeToolsButton; + wxButton* SelectDeviceButton; + + wxButton* VolumeButton; + wxButton* MountAllDevicesButton; + wxButton* DismountAllButton; + wxButton* ExitButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnActivate( wxActivateEvent& event ){ event.Skip(); } + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnMountVolumeMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMountAllDevicesButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDismountVolumeMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDismountAllButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnCreateVolumeButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnChangePasswordMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnChangePkcs5PrfMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnVolumePropertiesButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnChangeKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRemoveKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnCreateKeyfileMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnManageSecurityTokenKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnCloseAllSecurityTokenSessionsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDefaultKeyfilesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAddToFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAddAllMountedToFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnOrganizeFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMountAllFavoritesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnEncryptionTestMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnBackupVolumeHeadersMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRestoreVolumeHeaderMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnWipeCacheButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnHotkeysMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSecurityTokenPreferencesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnPreferencesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnUserGuideMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnOnlineHelpMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnBeginnersTutorialMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnFaqMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnWebsiteMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDownloadsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnNewsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnVersionHistoryMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnLegalNoticesMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnReportBugMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnForumsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnContactMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDonationsMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAboutMenuItemSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemRightClick( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } + virtual void OnLogoBitmapClick( wxMouseEvent& event ){ event.Skip(); } + virtual void OnSelectFileButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnNoHistoryCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnVolumeToolsButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSelectDeviceButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnVolumeButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnExitButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + MainFrameBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,496 ), long style = wxCAPTION|wxCLOSE_BOX|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxTAB_TRAVERSAL ); + ~MainFrameBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class WizardFrameBase + /////////////////////////////////////////////////////////////////////////////// + class WizardFrameBase : public wxFrame + { + private: + + protected: + wxPanel* MainPanel; + wxStaticBitmap* WizardBitmap; + wxStaticText* PageTitleStaticText; + wxBoxSizer* PageSizer; + + wxButton* HelpButton; + + wxButton* PreviousButton; + wxButton* NextButton; + + wxButton* CancelButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnActivate( wxActivateEvent& event ){ event.Skip(); } + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnMouseMotion( wxMouseEvent& event ){ event.Skip(); } + virtual void OnHelpButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnPreviousButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnNextButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnCancelButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + WizardFrameBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxCAPTION|wxCLOSE_BOX|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxTAB_TRAVERSAL ); + ~WizardFrameBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class AboutDialogBase + /////////////////////////////////////////////////////////////////////////////// + class AboutDialogBase : public wxDialog + { + private: + + protected: + wxPanel* m_panel14; + + wxStaticBitmap* LogoBitmap; + wxStaticText* VersionStaticText; + + wxStaticText* CopyrightStaticText; + + wxHyperlinkCtrl* WebsiteHyperlink; + wxStaticLine* m_staticline3; + wxTextCtrl* CreditsTextCtrl; + + wxStaticLine* m_staticline4; + wxStaticLine* m_staticline5; + + wxButton* DonationsButton; + + + // Virtual event handlers, overide them in your derived class + virtual void OnWebsiteHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } + virtual void OnDonationsButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + AboutDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~AboutDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class ChangePasswordDialogBase + /////////////////////////////////////////////////////////////////////////////// + class ChangePasswordDialogBase : public wxDialog + { + private: + + protected: + wxStaticBoxSizer* CurrentSizer; + wxBoxSizer* CurrentPasswordPanelSizer; + wxStaticBoxSizer* NewSizer; + wxBoxSizer* NewPasswordPanelSizer; + wxButton* OKButton; + wxButton* CancelButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + ChangePasswordDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~ChangePasswordDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class DeviceSelectionDialogBase + /////////////////////////////////////////////////////////////////////////////// + class DeviceSelectionDialogBase : public wxDialog + { + private: + + protected: + wxListCtrl* DeviceListCtrl; + wxStdDialogButtonSizer* StdButtons; + wxButton* StdButtonsOK; + wxButton* StdButtonsCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } + + + public: + DeviceSelectionDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select a Partition or Device"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~DeviceSelectionDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class EncryptionTestDialogBase + /////////////////////////////////////////////////////////////////////////////// + class EncryptionTestDialogBase : public wxDialog + { + private: + + protected: + wxChoice* EncryptionAlgorithmChoice; + wxCheckBox* XtsModeCheckBox; + wxTextCtrl* KeyTextCtrl; + wxStaticText* KeySizeStaticText; + wxTextCtrl* SecondaryKeyTextCtrl; + wxTextCtrl* DataUnitNumberTextCtrl; + wxTextCtrl* BlockNumberTextCtrl; + wxTextCtrl* PlainTextTextCtrl; + wxTextCtrl* CipherTextTextCtrl; + wxButton* EncryptButton; + wxButton* DecryptButton; + wxButton* AutoTestAllButton; + wxButton* ResetButton; + wxButton* CloseButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnEncryptionAlgorithmSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnXtsModeCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnEncryptButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDecryptButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAutoTestAllButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnResetButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + EncryptionTestDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt - Test Vectors"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~EncryptionTestDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class FavoriteVolumesDialogBase + /////////////////////////////////////////////////////////////////////////////// + class FavoriteVolumesDialogBase : public wxDialog + { + private: + + protected: + wxListCtrl* FavoritesListCtrl; + wxButton* MoveUpButton; + wxButton* MoveDownButton; + wxButton* RemoveButton; + wxButton* RemoveAllButton; + + wxButton* OKButton; + wxButton* CancelButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } + virtual void OnMoveUpButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMoveDownButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRemoveButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRemoveAllButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + FavoriteVolumesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Favorite Volumes"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~FavoriteVolumesDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class KeyfilesDialogBase + /////////////////////////////////////////////////////////////////////////////// + class KeyfilesDialogBase : public wxDialog + { + private: + + protected: + wxBoxSizer* UpperSizer; + wxBoxSizer* PanelSizer; + wxButton* OKButton; + wxButton* CancelButton; + wxStaticText* WarningStaticText; + wxBoxSizer* KeyfilesNoteSizer; + wxStaticText* KeyfilesNoteStaticText; + wxHyperlinkCtrl* KeyfilesHyperlink; + wxButton* CreateKeyfileButtton; + + // Virtual event handlers, overide them in your derived class + virtual void OnKeyfilesHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } + virtual void OnCreateKeyfileButttonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + KeyfilesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Keyfiles"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~KeyfilesDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class KeyfileGeneratorDialogBase + /////////////////////////////////////////////////////////////////////////////// + class KeyfileGeneratorDialogBase : public wxDialog + { + private: + + protected: + wxBoxSizer* MainSizer; + + wxChoice* HashChoice; + + wxStaticText* RandomPoolStaticText; + wxCheckBox* ShowRandomPoolCheckBox; + + wxStaticText* MouseStaticText; + + wxButton* GenerateButton; + + + // Virtual event handlers, overide them in your derived class + virtual void OnMouseMotion( wxMouseEvent& event ){ event.Skip(); } + virtual void OnHashSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnShowRandomPoolCheckBoxClicked( wxCommandEvent& event ){ event.Skip(); } + virtual void OnGenerateButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + KeyfileGeneratorDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~KeyfileGeneratorDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class LegalNoticesDialogBase + /////////////////////////////////////////////////////////////////////////////// + class LegalNoticesDialogBase : public wxDialog + { + private: + + protected: + wxTextCtrl* LegalNoticesTextCtrl; + + public: + LegalNoticesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt - Legal Notices"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~LegalNoticesDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class MountOptionsDialogBase + /////////////////////////////////////////////////////////////////////////////// + class MountOptionsDialogBase : public wxDialog + { + private: + + protected: + wxBoxSizer* PasswordSizer; + wxButton* OKButton; + wxButton* CancelButton; + + wxButton* OptionsButton; + wxPanel* OptionsPanel; + wxStaticBoxSizer* OptionsSizer; + + wxCheckBox* ReadOnlyCheckBox; + wxCheckBox* RemovableCheckBox; + wxCheckBox* PartitionInSystemEncryptionScopeCheckBox; + wxStaticBoxSizer* ProtectionSizer; + wxCheckBox* ProtectionCheckBox; + wxBoxSizer* ProtectionPasswordSizer; + wxHyperlinkCtrl* ProtectionHyperlinkCtrl; + wxBoxSizer* FilesystemSizer; + wxPanel* m_panel8; + wxCheckBox* NoFilesystemCheckBox; + wxGridBagSizer* FilesystemOptionsSizer; + wxBoxSizer* FilesystemSpacer; + wxStaticText* MountPointTextCtrlStaticText; + wxTextCtrl* MountPointTextCtrl; + wxButton* MountPointButton; + wxStaticText* FilesystemOptionsStaticText; + wxTextCtrl* FilesystemOptionsTextCtrl; + + // Virtual event handlers, overide them in your derived class + virtual void OnInitDialog( wxInitDialogEvent& event ){ event.Skip(); } + virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnOptionsButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnReadOnlyCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnProtectionCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnProtectionHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } + virtual void OnNoFilesystemCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMountPointButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + MountOptionsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Enter TrueCrypt Volume Password"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~MountOptionsDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class NewSecurityTokenKeyfileDialogBase + /////////////////////////////////////////////////////////////////////////////// + class NewSecurityTokenKeyfileDialogBase : public wxDialog + { + private: + + protected: + wxChoice* SecurityTokenChoice; + wxTextCtrl* KeyfileNameTextCtrl; + wxStdDialogButtonSizer* StdButtons; + wxButton* StdButtonsOK; + wxButton* StdButtonsCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnKeyfileNameChanged( wxCommandEvent& event ){ event.Skip(); } + + + public: + NewSecurityTokenKeyfileDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("New Security Token Keyfile Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~NewSecurityTokenKeyfileDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class PreferencesDialogBase + /////////////////////////////////////////////////////////////////////////////// + class PreferencesDialogBase : public wxDialog + { + private: + + protected: + wxNotebook* PreferencesNotebook; + wxPanel* SecurityPage; + wxStaticBoxSizer* AutoDismountSizer; + wxCheckBox* DismountOnLogOffCheckBox; + wxCheckBox* DismountOnScreenSaverCheckBox; + wxCheckBox* DismountOnPowerSavingCheckBox; + wxCheckBox* DismountOnInactivityCheckBox; + wxSpinCtrl* DismountOnInactivitySpinCtrl; + wxCheckBox* ForceAutoDismountCheckBox; + wxStaticBoxSizer* FilesystemSecuritySizer; + wxCheckBox* PreserveTimestampsCheckBox; + wxCheckBox* WipeCacheOnCloseCheckBox; + wxCheckBox* WipeCacheOnAutoDismountCheckBox; + wxPanel* DefaultMountOptionsPage; + wxCheckBox* MountReadOnlyCheckBox; + wxCheckBox* MountRemovableCheckBox; + wxCheckBox* CachePasswordsCheckBox; + wxStaticBoxSizer* FilesystemSizer; + wxTextCtrl* FilesystemOptionsTextCtrl; + wxPanel* BackgroundTaskPanel; + wxCheckBox* BackgroundTaskEnabledCheckBox; + wxCheckBox* CloseBackgroundTaskOnNoVolumesCheckBox; + wxCheckBox* BackgroundTaskMenuMountItemsEnabledCheckBox; + wxCheckBox* BackgroundTaskMenuOpenItemsEnabledCheckBox; + wxCheckBox* BackgroundTaskMenuDismountItemsEnabledCheckBox; + wxPanel* SystemIntegrationPage; + wxStaticBoxSizer* LogOnSizer; + wxCheckBox* StartOnLogonCheckBox; + wxCheckBox* MountFavoritesOnLogonCheckBox; + wxCheckBox* MountDevicesOnLogonCheckBox; + wxStaticBoxSizer* ExplorerSizer; + wxCheckBox* OpenExplorerWindowAfterMountCheckBox; + wxCheckBox* CloseExplorerWindowsOnDismountCheckBox; + wxStaticBoxSizer* KernelServicesSizer; + wxCheckBox* NoKernelCryptoCheckBox; + wxBoxSizer* DefaultKeyfilesSizer; + wxCheckBox* UseKeyfilesCheckBox; + wxTextCtrl* Pkcs11ModulePathTextCtrl; + wxButton* SelectPkcs11ModuleButton; + wxCheckBox* CloseSecurityTokenSessionsAfterMountCheckBox; + wxListCtrl* HotkeyListCtrl; + wxTextCtrl* HotkeyTextCtrl; + wxButton* AssignHotkeyButton; + + wxCheckBox* HotkeyControlCheckBox; + wxCheckBox* HotkeyShiftCheckBox; + wxCheckBox* HotkeyAltCheckBox; + wxCheckBox* HotkeyWinCheckBox; + wxButton* RemoveHotkeyButton; + wxCheckBox* BeepAfterHotkeyMountDismountCheckBox; + wxCheckBox* DisplayMessageAfterHotkeyDismountCheckBox; + wxStdDialogButtonSizer* StdButtons; + wxButton* StdButtonsOK; + wxButton* StdButtonsCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnDismountOnScreenSaverCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDismountOnPowerSavingCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnForceAutoDismountCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnPreserveTimestampsCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnBackgroundTaskEnabledCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnNoKernelCryptoCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSelectPkcs11ModuleButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnHotkeyListItemDeselected( wxListEvent& event ){ event.Skip(); } + virtual void OnHotkeyListItemSelected( wxListEvent& event ){ event.Skip(); } + virtual void OnAssignHotkeyButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRemoveHotkeyButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnCancelButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + wxPanel* DefaultKeyfilesPage; + wxPanel* SecurityTokensPage; + wxPanel* HotkeysPage; + PreferencesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Preferences"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~PreferencesDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class RandomPoolEnrichmentDialogBase + /////////////////////////////////////////////////////////////////////////////// + class RandomPoolEnrichmentDialogBase : public wxDialog + { + private: + + protected: + wxBoxSizer* MainSizer; + + wxChoice* HashChoice; + + wxStaticText* RandomPoolStaticText; + wxCheckBox* ShowRandomPoolCheckBox; + + wxStaticText* MouseStaticText; + + + wxButton* ContinueButton; + + + // Virtual event handlers, overide them in your derived class + virtual void OnMouseMotion( wxMouseEvent& event ){ event.Skip(); } + virtual void OnHashSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnShowRandomPoolCheckBoxClicked( wxCommandEvent& event ){ event.Skip(); } + + + public: + RandomPoolEnrichmentDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("TrueCrypt - Random Pool Enrichment"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~RandomPoolEnrichmentDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class SecurityTokenKeyfilesDialogBase + /////////////////////////////////////////////////////////////////////////////// + class SecurityTokenKeyfilesDialogBase : public wxDialog + { + private: + + protected: + wxListCtrl* SecurityTokenKeyfileListCtrl; + wxButton* ExportButton; + wxButton* DeleteButton; + + wxButton* ImportButton; + wxButton* OKButton; + wxButton* CancelButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } + virtual void OnExportButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDeleteButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnImportButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnOKButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + SecurityTokenKeyfilesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Security Token Keyfiles"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~SecurityTokenKeyfilesDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class VolumePropertiesDialogBase + /////////////////////////////////////////////////////////////////////////////// + class VolumePropertiesDialogBase : public wxDialog + { + private: + + protected: + wxListCtrl* PropertiesListCtrl; + wxStdDialogButtonSizer* StdButtons; + wxButton* StdButtonsOK; + + public: + VolumePropertiesDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Volume Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~VolumePropertiesDialogBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class EncryptionOptionsWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class EncryptionOptionsWizardPageBase : public WizardPage + { + private: + + protected: + wxChoice* EncryptionAlgorithmChoice; + wxButton* TestButton; + wxStaticText* EncryptionAlgorithmStaticText; + wxHyperlinkCtrl* EncryptionAlgorithmHyperlink; + + wxButton* BenchmarkButton; + wxChoice* HashChoice; + wxHyperlinkCtrl* HashHyperlink; + + // Virtual event handlers, overide them in your derived class + virtual void OnEncryptionAlgorithmSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnTestButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnEncryptionAlgorithmHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } + virtual void OnBenchmarkButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnHashHyperlinkClick( wxHyperlinkEvent& event ){ event.Skip(); } + + + public: + EncryptionOptionsWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~EncryptionOptionsWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class InfoWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class InfoWizardPageBase : public WizardPage + { + private: + + protected: + wxBoxSizer* InfoPageSizer; + wxStaticText* InfoStaticText; + + public: + InfoWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~InfoWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class KeyfilesPanelBase + /////////////////////////////////////////////////////////////////////////////// + class KeyfilesPanelBase : public wxPanel + { + private: + + protected: + wxListCtrl* KeyfilesListCtrl; + wxButton* AddFilesButton; + wxButton* AddDirectoryButton; + wxButton* AddSecurityTokenSignatureButton; + wxButton* RemoveButton; + wxButton* RemoveAllButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnListItemDeselected( wxListEvent& event ){ event.Skip(); } + virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); } + virtual void OnListSizeChanged( wxSizeEvent& event ){ event.Skip(); } + virtual void OnAddFilesButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAddDirectoryButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAddSecurityTokenSignatureButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRemoveButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRemoveAllButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + KeyfilesPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxTAB_TRAVERSAL ); + ~KeyfilesPanelBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class ProgressWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class ProgressWizardPageBase : public WizardPage + { + private: + + protected: + wxBoxSizer* ProgressSizer; + wxGauge* ProgressGauge; + wxButton* AbortButton; + wxStaticText* InfoStaticText; + + // Virtual event handlers, overide them in your derived class + virtual void OnAbortButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + ProgressWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~ProgressWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class SelectDirectoryWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class SelectDirectoryWizardPageBase : public WizardPage + { + private: + + protected: + wxTextCtrl* DirectoryTextCtrl; + wxButton* BrowseButton; + wxStaticText* InfoStaticText; + + // Virtual event handlers, overide them in your derived class + virtual void OnDirectoryTextChanged( wxCommandEvent& event ){ event.Skip(); } + virtual void OnBrowseButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + SelectDirectoryWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 200,65 ), long style = wxTAB_TRAVERSAL ); + ~SelectDirectoryWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class SingleChoiceWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class SingleChoiceWizardPageBase : public WizardPage + { + private: + + protected: + + wxBoxSizer* OuterChoicesSizer; + wxBoxSizer* ChoicesSizer; + wxStaticText* InfoStaticText; + + public: + SingleChoiceWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~SingleChoiceWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class VolumeCreationProgressWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class VolumeCreationProgressWizardPageBase : public WizardPage + { + private: + + protected: + wxBoxSizer* KeySamplesUpperSizer; + wxBoxSizer* KeySamplesUpperInnerSizer; + wxStaticText* RandomPoolSampleStaticText; + wxCheckBox* DisplayKeysCheckBox; + wxStaticText* HeaderKeySampleStaticText; + wxStaticText* MasterKeySampleStaticText; + wxGauge* ProgressGauge; + wxButton* AbortButton; + wxStaticText* m_staticText31; + wxPanel* m_panel12; + wxStaticText* SizeDoneStaticText; + wxStaticText* m_staticText311; + wxPanel* m_panel121; + wxStaticText* SpeedStaticText; + wxStaticText* m_staticText312; + wxPanel* m_panel122; + wxStaticText* TimeLeftStaticText; + + wxStaticText* InfoStaticText; + + // Virtual event handlers, overide them in your derived class + virtual void OnDisplayKeysCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAbortButtonClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + VolumeCreationProgressWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~VolumeCreationProgressWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class VolumeLocationWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class VolumeLocationWizardPageBase : public WizardPage + { + private: + + protected: + + wxComboBox* VolumePathComboBox; + wxButton* SelectFileButton; + wxButton* SelectDeviceButton; + + wxCheckBox* NoHistoryCheckBox; + + wxStaticText* InfoStaticText; + + // Virtual event handlers, overide them in your derived class + virtual void OnVolumePathTextChanged( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSelectFileButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSelectDeviceButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnNoHistoryCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + VolumeLocationWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~VolumeLocationWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class VolumeFormatOptionsWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class VolumeFormatOptionsWizardPageBase : public WizardPage + { + private: + + protected: + wxStaticText* m_staticText43; + wxChoice* FilesystemTypeChoice; + wxCheckBox* QuickFormatCheckBox; + + wxStaticText* InfoStaticText; + + // Virtual event handlers, overide them in your derived class + virtual void OnFilesystemTypeSelected( wxCommandEvent& event ){ event.Skip(); } + virtual void OnQuickFormatCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + + + public: + VolumeFormatOptionsWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~VolumeFormatOptionsWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class VolumePasswordPanelBase + /////////////////////////////////////////////////////////////////////////////// + class VolumePasswordPanelBase : public wxPanel + { + private: + + protected: + wxGridBagSizer* GridBagSizer; + wxStaticText* PasswordStaticText; + wxTextCtrl* PasswordTextCtrl; + wxStaticText* ConfirmPasswordStaticText; + wxTextCtrl* ConfirmPasswordTextCtrl; + wxCheckBox* CacheCheckBox; + wxCheckBox* DisplayPasswordCheckBox; + wxCheckBox* UseKeyfilesCheckBox; + wxButton* KeyfilesButton; + wxBoxSizer* Pkcs5PrfSizer; + wxStaticText* Pkcs5PrfStaticText; + wxChoice* Pkcs5PrfChoice; + wxBoxSizer* PasswordPlaceholderSizer; + + // Virtual event handlers, overide them in your derived class + virtual void OnTextChanged( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDisplayPasswordCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnUseKeyfilesCheckBoxClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnKeyfilesButtonClick( wxCommandEvent& event ){ event.Skip(); } + virtual void OnKeyfilesButtonRightDown( wxMouseEvent& event ){ event.Skip(); } + virtual void OnKeyfilesButtonRightClick( wxMouseEvent& event ){ event.Skip(); } + + + public: + VolumePasswordPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~VolumePasswordPanelBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class VolumePasswordWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class VolumePasswordWizardPageBase : public WizardPage + { + private: + + protected: + wxBoxSizer* PasswordPanelSizer; + wxStaticText* InfoStaticText; + + public: + VolumePasswordWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~VolumePasswordWizardPageBase(); + + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Class VolumeSizeWizardPageBase + /////////////////////////////////////////////////////////////////////////////// + class VolumeSizeWizardPageBase : public WizardPage + { + private: + + protected: + + wxTextCtrl* VolumeSizeTextCtrl; + wxChoice* VolumeSizePrefixChoice; + + wxStaticText* FreeSpaceStaticText; + + wxStaticText* InfoStaticText; + + // Virtual event handlers, overide them in your derived class + virtual void OnVolumeSizeTextChanged( wxCommandEvent& event ){ event.Skip(); } + virtual void OnVolumeSizePrefixSelected( wxCommandEvent& event ){ event.Skip(); } + + + public: + VolumeSizeWizardPageBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~VolumeSizeWizardPageBase(); + + }; + +} // namespace TrueCrypt + +#endif //__Forms__ diff --git a/Main/Forms/InfoWizardPage.cpp b/Main/Forms/InfoWizardPage.cpp index f22258f..728e679 100644 --- a/Main/Forms/InfoWizardPage.cpp +++ b/Main/Forms/InfoWizardPage.cpp @@ -1,33 +1,33 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "InfoWizardPage.h" - -namespace TrueCrypt -{ - InfoWizardPage::InfoWizardPage (wxPanel *parent, const wxString &actionButtonText, shared_ptr actionFunctor) - : InfoWizardPageBase (parent) - { - if (!actionButtonText.empty()) - { - wxButton *actionButton = new wxButton (this, wxID_ANY, actionButtonText); - ActionFunctor = actionFunctor; - actionButton->Connect (wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (InfoWizardPage::OnActionButtonClick), nullptr, this); - - InfoPageSizer->Add (actionButton, 0, wxALL, 5); - } - - InfoStaticText->SetFocus(); - } - - void InfoWizardPage::SetMaxStaticTextWidth (int width) - { - InfoStaticText->Wrap (width); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "InfoWizardPage.h" + +namespace TrueCrypt +{ + InfoWizardPage::InfoWizardPage (wxPanel *parent, const wxString &actionButtonText, shared_ptr actionFunctor) + : InfoWizardPageBase (parent) + { + if (!actionButtonText.empty()) + { + wxButton *actionButton = new wxButton (this, wxID_ANY, actionButtonText); + ActionFunctor = actionFunctor; + actionButton->Connect (wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (InfoWizardPage::OnActionButtonClick), nullptr, this); + + InfoPageSizer->Add (actionButton, 0, wxALL, 5); + } + + InfoStaticText->SetFocus(); + } + + void InfoWizardPage::SetMaxStaticTextWidth (int width) + { + InfoStaticText->Wrap (width); + } +} diff --git a/Main/Forms/InfoWizardPage.h b/Main/Forms/InfoWizardPage.h index 2da5ba8..da45fa5 100644 --- a/Main/Forms/InfoWizardPage.h +++ b/Main/Forms/InfoWizardPage.h @@ -1,32 +1,32 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_InfoWizardPage -#define TC_HEADER_Main_Forms_InfoWizardPage - -#include "Forms.h" - -namespace TrueCrypt -{ - class InfoWizardPage : public InfoWizardPageBase - { - public: - InfoWizardPage (wxPanel *parent, const wxString &actionButtonText = wxEmptyString, shared_ptr actionFunctor = shared_ptr ()); - - bool IsValid () { return true; } - void SetMaxStaticTextWidth (int width); - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - - protected: - virtual void OnActionButtonClick (wxCommandEvent& event) { (*ActionFunctor)(); } - - shared_ptr ActionFunctor; - }; -} - -#endif // TC_HEADER_Main_Forms_InfoWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_InfoWizardPage +#define TC_HEADER_Main_Forms_InfoWizardPage + +#include "Forms.h" + +namespace TrueCrypt +{ + class InfoWizardPage : public InfoWizardPageBase + { + public: + InfoWizardPage (wxPanel *parent, const wxString &actionButtonText = wxEmptyString, shared_ptr actionFunctor = shared_ptr ()); + + bool IsValid () { return true; } + void SetMaxStaticTextWidth (int width); + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + + protected: + virtual void OnActionButtonClick (wxCommandEvent& event) { (*ActionFunctor)(); } + + shared_ptr ActionFunctor; + }; +} + +#endif // TC_HEADER_Main_Forms_InfoWizardPage diff --git a/Main/Forms/KeyfileGeneratorDialog.cpp b/Main/Forms/KeyfileGeneratorDialog.cpp index b264593..fb9d3ca 100644 --- a/Main/Forms/KeyfileGeneratorDialog.cpp +++ b/Main/Forms/KeyfileGeneratorDialog.cpp @@ -1,118 +1,118 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "Volume/Hash.h" -#include "KeyfileGeneratorDialog.h" - -namespace TrueCrypt -{ - KeyfileGeneratorDialog::KeyfileGeneratorDialog (wxWindow* parent) : KeyfileGeneratorDialogBase (parent) - { - RandomNumberGenerator::Start(); - - Hashes = Hash::GetAvailableAlgorithms(); - foreach (shared_ptr hash, Hashes) - { - if (!hash->IsDeprecated()) - HashChoice->Append (hash->GetName(), hash.get()); - } - - HashChoice->Select (0); - RandomNumberGenerator::SetHash (Gui->GetSelectedData (HashChoice)->GetNew()); - - ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); - MouseStaticText->Wrap (Gui->GetCharWidth (MouseStaticText) * 70); - - MainSizer->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 24)); - - Layout(); - Fit(); - Center(); - - foreach (wxWindow *c, this->GetChildren()) - c->Connect (wxEVT_MOTION, wxMouseEventHandler (KeyfileGeneratorDialog::OnMouseMotion), nullptr, this); - } - - KeyfileGeneratorDialog::~KeyfileGeneratorDialog () - { - } - - void KeyfileGeneratorDialog::OnGenerateButtonClick (wxCommandEvent& event) - { - try - { - FilePathList files = Gui->SelectFiles (Gui->GetActiveWindow(), wxEmptyString, true); - - if (files.empty()) - return; - - SecureBuffer keyfileBuffer (VolumePassword::MaxSize); - RandomNumberGenerator::GetData (keyfileBuffer); - - { - File keyfile; - keyfile.Open (*files.front(), File::CreateWrite); - keyfile.Write (keyfileBuffer); - } - - Gui->ShowInfo ("KEYFILE_CREATED"); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void KeyfileGeneratorDialog::OnHashSelected (wxCommandEvent& event) - { - RandomNumberGenerator::SetHash (Gui->GetSelectedData (HashChoice)->GetNew()); - } - - void KeyfileGeneratorDialog::OnMouseMotion (wxMouseEvent& event) - { - event.Skip(); - - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&event), sizeof (event))); - - long coord = event.GetX(); - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); - coord = event.GetY(); - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); - - if (ShowRandomPoolCheckBox->IsChecked()) - ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); - } - - void KeyfileGeneratorDialog::OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event) - { - if (!event.IsChecked()) - RandomPoolStaticText->SetLabel (L""); - } - - void KeyfileGeneratorDialog::ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots) - { - wxString str; - - for (size_t i = 0; i < buffer.Size(); ++i) - { - str += wxString::Format (L"%02X", buffer[i]); - } - - if (appendDots) - str += L".."; - - textCtrl->SetLabel (str.c_str()); - - for (size_t i = 0; i < str.size(); ++i) - { - str[i] = L'X'; - } - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "Volume/Hash.h" +#include "KeyfileGeneratorDialog.h" + +namespace TrueCrypt +{ + KeyfileGeneratorDialog::KeyfileGeneratorDialog (wxWindow* parent) : KeyfileGeneratorDialogBase (parent) + { + RandomNumberGenerator::Start(); + + Hashes = Hash::GetAvailableAlgorithms(); + foreach (shared_ptr hash, Hashes) + { + if (!hash->IsDeprecated()) + HashChoice->Append (hash->GetName(), hash.get()); + } + + HashChoice->Select (0); + RandomNumberGenerator::SetHash (Gui->GetSelectedData (HashChoice)->GetNew()); + + ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); + MouseStaticText->Wrap (Gui->GetCharWidth (MouseStaticText) * 70); + + MainSizer->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 24)); + + Layout(); + Fit(); + Center(); + + foreach (wxWindow *c, this->GetChildren()) + c->Connect (wxEVT_MOTION, wxMouseEventHandler (KeyfileGeneratorDialog::OnMouseMotion), nullptr, this); + } + + KeyfileGeneratorDialog::~KeyfileGeneratorDialog () + { + } + + void KeyfileGeneratorDialog::OnGenerateButtonClick (wxCommandEvent& event) + { + try + { + FilePathList files = Gui->SelectFiles (Gui->GetActiveWindow(), wxEmptyString, true); + + if (files.empty()) + return; + + SecureBuffer keyfileBuffer (VolumePassword::MaxSize); + RandomNumberGenerator::GetData (keyfileBuffer); + + { + File keyfile; + keyfile.Open (*files.front(), File::CreateWrite); + keyfile.Write (keyfileBuffer); + } + + Gui->ShowInfo ("KEYFILE_CREATED"); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void KeyfileGeneratorDialog::OnHashSelected (wxCommandEvent& event) + { + RandomNumberGenerator::SetHash (Gui->GetSelectedData (HashChoice)->GetNew()); + } + + void KeyfileGeneratorDialog::OnMouseMotion (wxMouseEvent& event) + { + event.Skip(); + + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&event), sizeof (event))); + + long coord = event.GetX(); + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); + coord = event.GetY(); + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); + + if (ShowRandomPoolCheckBox->IsChecked()) + ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); + } + + void KeyfileGeneratorDialog::OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event) + { + if (!event.IsChecked()) + RandomPoolStaticText->SetLabel (L""); + } + + void KeyfileGeneratorDialog::ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots) + { + wxString str; + + for (size_t i = 0; i < buffer.Size(); ++i) + { + str += wxString::Format (L"%02X", buffer[i]); + } + + if (appendDots) + str += L".."; + + textCtrl->SetLabel (str.c_str()); + + for (size_t i = 0; i < str.size(); ++i) + { + str[i] = L'X'; + } + } +} diff --git a/Main/Forms/KeyfileGeneratorDialog.h b/Main/Forms/KeyfileGeneratorDialog.h index a2fe946..fc7bdbc 100644 --- a/Main/Forms/KeyfileGeneratorDialog.h +++ b/Main/Forms/KeyfileGeneratorDialog.h @@ -1,34 +1,34 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_KeyfileGeneratorDialog -#define TC_HEADER_Main_Forms_KeyfileGeneratorDialog - -#include "Forms.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class KeyfileGeneratorDialog : public KeyfileGeneratorDialogBase - { - public: - KeyfileGeneratorDialog (wxWindow* parent); - ~KeyfileGeneratorDialog (); - - protected: - void OnGenerateButtonClick (wxCommandEvent& event); - void OnHashSelected (wxCommandEvent& event); - void OnMouseMotion (wxMouseEvent& event); - void OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event); - void ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots = true); - - HashList Hashes; - }; -} - -#endif // TC_HEADER_Main_Forms_KeyfileGeneratorDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_KeyfileGeneratorDialog +#define TC_HEADER_Main_Forms_KeyfileGeneratorDialog + +#include "Forms.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class KeyfileGeneratorDialog : public KeyfileGeneratorDialogBase + { + public: + KeyfileGeneratorDialog (wxWindow* parent); + ~KeyfileGeneratorDialog (); + + protected: + void OnGenerateButtonClick (wxCommandEvent& event); + void OnHashSelected (wxCommandEvent& event); + void OnMouseMotion (wxMouseEvent& event); + void OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event); + void ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots = true); + + HashList Hashes; + }; +} + +#endif // TC_HEADER_Main_Forms_KeyfileGeneratorDialog diff --git a/Main/Forms/KeyfilesDialog.cpp b/Main/Forms/KeyfilesDialog.cpp index d5e85c0..d03f194 100644 --- a/Main/Forms/KeyfilesDialog.cpp +++ b/Main/Forms/KeyfilesDialog.cpp @@ -1,44 +1,44 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "KeyfilesDialog.h" - -namespace TrueCrypt -{ - KeyfilesDialog::KeyfilesDialog (wxWindow* parent, shared_ptr keyfiles) - : KeyfilesDialogBase (parent), Keyfiles (keyfiles) - { - mKeyfilesPanel = new KeyfilesPanel (this, keyfiles); - PanelSizer->Add (mKeyfilesPanel, 1, wxALL | wxEXPAND); - - WarningStaticText->SetLabel (LangString["IDT_KEYFILE_WARNING"]); - WarningStaticText->Wrap (Gui->GetCharWidth (this) * 15); - - Layout(); - Fit(); - - KeyfilesNoteStaticText->SetLabel (LangString["KEYFILES_NOTE"]); - KeyfilesNoteStaticText->Wrap (UpperSizer->GetSize().GetWidth() - Gui->GetCharWidth (this) * 2); - - Layout(); - Fit(); - Center(); - } - - void KeyfilesDialog::OnCreateKeyfileButttonClick (wxCommandEvent& event) - { - Gui->CreateKeyfile(); - } - - void KeyfilesDialog::OnKeyfilesHyperlinkClick (wxHyperlinkEvent& event) - { - Gui->OpenHomepageLink (this, L"keyfiles"); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "KeyfilesDialog.h" + +namespace TrueCrypt +{ + KeyfilesDialog::KeyfilesDialog (wxWindow* parent, shared_ptr keyfiles) + : KeyfilesDialogBase (parent), Keyfiles (keyfiles) + { + mKeyfilesPanel = new KeyfilesPanel (this, keyfiles); + PanelSizer->Add (mKeyfilesPanel, 1, wxALL | wxEXPAND); + + WarningStaticText->SetLabel (LangString["IDT_KEYFILE_WARNING"]); + WarningStaticText->Wrap (Gui->GetCharWidth (this) * 15); + + Layout(); + Fit(); + + KeyfilesNoteStaticText->SetLabel (LangString["KEYFILES_NOTE"]); + KeyfilesNoteStaticText->Wrap (UpperSizer->GetSize().GetWidth() - Gui->GetCharWidth (this) * 2); + + Layout(); + Fit(); + Center(); + } + + void KeyfilesDialog::OnCreateKeyfileButttonClick (wxCommandEvent& event) + { + Gui->CreateKeyfile(); + } + + void KeyfilesDialog::OnKeyfilesHyperlinkClick (wxHyperlinkEvent& event) + { + Gui->OpenHomepageLink (this, L"keyfiles"); + } +} diff --git a/Main/Forms/KeyfilesDialog.h b/Main/Forms/KeyfilesDialog.h index de883c3..7d136e1 100644 --- a/Main/Forms/KeyfilesDialog.h +++ b/Main/Forms/KeyfilesDialog.h @@ -1,33 +1,33 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_KeyfilesDialog -#define TC_HEADER_Main_Forms_KeyfilesDialog - -#include "Forms.h" -#include "Main/Main.h" -#include "KeyfilesPanel.h" - -namespace TrueCrypt -{ - class KeyfilesDialog : public KeyfilesDialogBase - { - public: - KeyfilesDialog (wxWindow* parent, shared_ptr keyfiles); - shared_ptr GetKeyfiles () const { return mKeyfilesPanel->GetKeyfiles(); } - - protected: - void OnCreateKeyfileButttonClick (wxCommandEvent& event); - void OnKeyfilesHyperlinkClick (wxHyperlinkEvent& event); - - shared_ptr Keyfiles; - KeyfilesPanel *mKeyfilesPanel; - }; -} - -#endif // TC_HEADER_Main_Forms_KeyfilesDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_KeyfilesDialog +#define TC_HEADER_Main_Forms_KeyfilesDialog + +#include "Forms.h" +#include "Main/Main.h" +#include "KeyfilesPanel.h" + +namespace TrueCrypt +{ + class KeyfilesDialog : public KeyfilesDialogBase + { + public: + KeyfilesDialog (wxWindow* parent, shared_ptr keyfiles); + shared_ptr GetKeyfiles () const { return mKeyfilesPanel->GetKeyfiles(); } + + protected: + void OnCreateKeyfileButttonClick (wxCommandEvent& event); + void OnKeyfilesHyperlinkClick (wxHyperlinkEvent& event); + + shared_ptr Keyfiles; + KeyfilesPanel *mKeyfilesPanel; + }; +} + +#endif // TC_HEADER_Main_Forms_KeyfilesDialog diff --git a/Main/Forms/KeyfilesPanel.cpp b/Main/Forms/KeyfilesPanel.cpp index d88b344..154deb8 100644 --- a/Main/Forms/KeyfilesPanel.cpp +++ b/Main/Forms/KeyfilesPanel.cpp @@ -1,160 +1,160 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "KeyfilesPanel.h" -#include "SecurityTokenKeyfilesDialog.h" - -namespace TrueCrypt -{ - KeyfilesPanel::KeyfilesPanel (wxWindow* parent, shared_ptr keyfiles) - : KeyfilesPanelBase (parent) - { - KeyfilesListCtrl->InsertColumn (0, LangString["KEYFILE"], wxLIST_FORMAT_LEFT, 1); - Gui->SetListCtrlHeight (KeyfilesListCtrl, 10); - - Layout(); - Fit(); - - if (keyfiles) - { - foreach_ref (const Keyfile &k, *keyfiles) - { - vector fields; - fields.push_back (FilesystemPath (k)); - Gui->AppendToListCtrl (KeyfilesListCtrl, fields); - } - } - - class FileDropTarget : public wxFileDropTarget - { - public: - FileDropTarget (KeyfilesPanel *panel) : Panel (panel) { } - - wxDragResult OnDragOver (wxCoord x, wxCoord y, wxDragResult def) - { - return wxDragLink; - } - - bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString &filenames) - { - foreach (const wxString &f, filenames) - Panel->AddKeyfile (make_shared (wstring (f))); - return true; - } - - protected: - KeyfilesPanel *Panel; - }; - - SetDropTarget (new FileDropTarget (this)); - KeyfilesListCtrl->SetDropTarget (new FileDropTarget (this)); -#ifdef TC_MACOSX - foreach (wxWindow *c, GetChildren()) - c->SetDropTarget (new FileDropTarget (this)); -#endif - - UpdateButtons(); - } - - void KeyfilesPanel::AddKeyfile (shared_ptr keyfile) - { - vector fields; - fields.push_back (FilesystemPath (*keyfile)); - Gui->AppendToListCtrl (KeyfilesListCtrl, fields); - UpdateButtons(); - } - - shared_ptr KeyfilesPanel::GetKeyfiles () const - { - make_shared_auto (KeyfileList, keyfiles); - - for (long i = 0; i < KeyfilesListCtrl->GetItemCount(); i++) - keyfiles->push_back (make_shared (wstring (KeyfilesListCtrl->GetItemText (i)))); - - return keyfiles; - } - - void KeyfilesPanel::OnAddDirectoryButtonClick (wxCommandEvent& event) - { - DirectoryPath dir = Gui->SelectDirectory (this, LangString["SELECT_KEYFILE_PATH"]); - if (!dir.IsEmpty()) - { - vector fields; - fields.push_back (dir); - Gui->AppendToListCtrl (KeyfilesListCtrl, fields); - UpdateButtons(); - } - } - - void KeyfilesPanel::OnAddFilesButtonClick (wxCommandEvent& event) - { - FilePathList files = Gui->SelectFiles (this, LangString["SELECT_KEYFILES"], false, true); - - foreach_ref (const FilePath &f, files) - { - vector fields; - fields.push_back (f); - Gui->AppendToListCtrl (KeyfilesListCtrl, fields); - } - UpdateButtons(); - } - - void KeyfilesPanel::OnAddSecurityTokenSignatureButtonClick (wxCommandEvent& event) - { - try - { - SecurityTokenKeyfilesDialog dialog (this); - if (dialog.ShowModal() == wxID_OK) - { - foreach (const SecurityTokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) - { - vector fields; - fields.push_back (path); - Gui->AppendToListCtrl (KeyfilesListCtrl, fields); - } - - UpdateButtons(); - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void KeyfilesPanel::OnListSizeChanged (wxSizeEvent& event) - { - list colPermilles; - colPermilles.push_back (1000); - Gui->SetListCtrlColumnWidths (KeyfilesListCtrl, colPermilles); - event.Skip(); - } - - void KeyfilesPanel::OnRemoveAllButtonClick (wxCommandEvent& event) - { - KeyfilesListCtrl->DeleteAllItems(); - UpdateButtons(); - } - - void KeyfilesPanel::OnRemoveButtonClick (wxCommandEvent& event) - { - long offset = 0; - foreach (long item, Gui->GetListCtrlSelectedItems (KeyfilesListCtrl)) - KeyfilesListCtrl->DeleteItem (item - offset++); - - UpdateButtons(); - } - - void KeyfilesPanel::UpdateButtons () - { - RemoveAllButton->Enable (KeyfilesListCtrl->GetItemCount() > 0); - RemoveButton->Enable (KeyfilesListCtrl->GetSelectedItemCount() > 0); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "KeyfilesPanel.h" +#include "SecurityTokenKeyfilesDialog.h" + +namespace TrueCrypt +{ + KeyfilesPanel::KeyfilesPanel (wxWindow* parent, shared_ptr keyfiles) + : KeyfilesPanelBase (parent) + { + KeyfilesListCtrl->InsertColumn (0, LangString["KEYFILE"], wxLIST_FORMAT_LEFT, 1); + Gui->SetListCtrlHeight (KeyfilesListCtrl, 10); + + Layout(); + Fit(); + + if (keyfiles) + { + foreach_ref (const Keyfile &k, *keyfiles) + { + vector fields; + fields.push_back (FilesystemPath (k)); + Gui->AppendToListCtrl (KeyfilesListCtrl, fields); + } + } + + class FileDropTarget : public wxFileDropTarget + { + public: + FileDropTarget (KeyfilesPanel *panel) : Panel (panel) { } + + wxDragResult OnDragOver (wxCoord x, wxCoord y, wxDragResult def) + { + return wxDragLink; + } + + bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString &filenames) + { + foreach (const wxString &f, filenames) + Panel->AddKeyfile (make_shared (wstring (f))); + return true; + } + + protected: + KeyfilesPanel *Panel; + }; + + SetDropTarget (new FileDropTarget (this)); + KeyfilesListCtrl->SetDropTarget (new FileDropTarget (this)); +#ifdef TC_MACOSX + foreach (wxWindow *c, GetChildren()) + c->SetDropTarget (new FileDropTarget (this)); +#endif + + UpdateButtons(); + } + + void KeyfilesPanel::AddKeyfile (shared_ptr keyfile) + { + vector fields; + fields.push_back (FilesystemPath (*keyfile)); + Gui->AppendToListCtrl (KeyfilesListCtrl, fields); + UpdateButtons(); + } + + shared_ptr KeyfilesPanel::GetKeyfiles () const + { + make_shared_auto (KeyfileList, keyfiles); + + for (long i = 0; i < KeyfilesListCtrl->GetItemCount(); i++) + keyfiles->push_back (make_shared (wstring (KeyfilesListCtrl->GetItemText (i)))); + + return keyfiles; + } + + void KeyfilesPanel::OnAddDirectoryButtonClick (wxCommandEvent& event) + { + DirectoryPath dir = Gui->SelectDirectory (this, LangString["SELECT_KEYFILE_PATH"]); + if (!dir.IsEmpty()) + { + vector fields; + fields.push_back (dir); + Gui->AppendToListCtrl (KeyfilesListCtrl, fields); + UpdateButtons(); + } + } + + void KeyfilesPanel::OnAddFilesButtonClick (wxCommandEvent& event) + { + FilePathList files = Gui->SelectFiles (this, LangString["SELECT_KEYFILES"], false, true); + + foreach_ref (const FilePath &f, files) + { + vector fields; + fields.push_back (f); + Gui->AppendToListCtrl (KeyfilesListCtrl, fields); + } + UpdateButtons(); + } + + void KeyfilesPanel::OnAddSecurityTokenSignatureButtonClick (wxCommandEvent& event) + { + try + { + SecurityTokenKeyfilesDialog dialog (this); + if (dialog.ShowModal() == wxID_OK) + { + foreach (const SecurityTokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) + { + vector fields; + fields.push_back (path); + Gui->AppendToListCtrl (KeyfilesListCtrl, fields); + } + + UpdateButtons(); + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void KeyfilesPanel::OnListSizeChanged (wxSizeEvent& event) + { + list colPermilles; + colPermilles.push_back (1000); + Gui->SetListCtrlColumnWidths (KeyfilesListCtrl, colPermilles); + event.Skip(); + } + + void KeyfilesPanel::OnRemoveAllButtonClick (wxCommandEvent& event) + { + KeyfilesListCtrl->DeleteAllItems(); + UpdateButtons(); + } + + void KeyfilesPanel::OnRemoveButtonClick (wxCommandEvent& event) + { + long offset = 0; + foreach (long item, Gui->GetListCtrlSelectedItems (KeyfilesListCtrl)) + KeyfilesListCtrl->DeleteItem (item - offset++); + + UpdateButtons(); + } + + void KeyfilesPanel::UpdateButtons () + { + RemoveAllButton->Enable (KeyfilesListCtrl->GetItemCount() > 0); + RemoveButton->Enable (KeyfilesListCtrl->GetSelectedItemCount() > 0); + } +} diff --git a/Main/Forms/KeyfilesPanel.h b/Main/Forms/KeyfilesPanel.h index 44df0db..cea413a 100644 --- a/Main/Forms/KeyfilesPanel.h +++ b/Main/Forms/KeyfilesPanel.h @@ -1,37 +1,37 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_KeyfilesPanel -#define TC_HEADER_Main_Forms_KeyfilesPanel - -#include "Forms.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class KeyfilesPanel : public KeyfilesPanelBase - { - public: - KeyfilesPanel (wxWindow* parent, shared_ptr keyfiles); - void AddKeyfile (shared_ptr keyfile); - shared_ptr GetKeyfiles () const; - - protected: - void OnAddFilesButtonClick (wxCommandEvent& event); - void OnAddDirectoryButtonClick (wxCommandEvent& event); - void OnAddSecurityTokenSignatureButtonClick (wxCommandEvent& event); - void OnListItemDeselected (wxListEvent& event) { UpdateButtons(); } - void OnListItemSelected (wxListEvent& event) { UpdateButtons(); } - void OnListSizeChanged (wxSizeEvent& event); - void OnRemoveButtonClick (wxCommandEvent& event); - void OnRemoveAllButtonClick (wxCommandEvent& event); - void UpdateButtons (); - }; -} - -#endif // TC_HEADER_Main_Forms_KeyfilesPanel +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_KeyfilesPanel +#define TC_HEADER_Main_Forms_KeyfilesPanel + +#include "Forms.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class KeyfilesPanel : public KeyfilesPanelBase + { + public: + KeyfilesPanel (wxWindow* parent, shared_ptr keyfiles); + void AddKeyfile (shared_ptr keyfile); + shared_ptr GetKeyfiles () const; + + protected: + void OnAddFilesButtonClick (wxCommandEvent& event); + void OnAddDirectoryButtonClick (wxCommandEvent& event); + void OnAddSecurityTokenSignatureButtonClick (wxCommandEvent& event); + void OnListItemDeselected (wxListEvent& event) { UpdateButtons(); } + void OnListItemSelected (wxListEvent& event) { UpdateButtons(); } + void OnListSizeChanged (wxSizeEvent& event); + void OnRemoveButtonClick (wxCommandEvent& event); + void OnRemoveAllButtonClick (wxCommandEvent& event); + void UpdateButtons (); + }; +} + +#endif // TC_HEADER_Main_Forms_KeyfilesPanel diff --git a/Main/Forms/LegalNoticesDialog.cpp b/Main/Forms/LegalNoticesDialog.cpp index 3013e92..ff3b593 100644 --- a/Main/Forms/LegalNoticesDialog.cpp +++ b/Main/Forms/LegalNoticesDialog.cpp @@ -1,28 +1,28 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "LegalNoticesDialog.h" -#include "Main/GraphicUserInterface.h" -#include "Main/Resources.h" - -namespace TrueCrypt -{ - LegalNoticesDialog::LegalNoticesDialog (wxWindow* parent) : LegalNoticesDialogBase (parent) - { - LegalNoticesTextCtrl->SetMinSize (wxSize ( - Gui->GetCharWidth (LegalNoticesTextCtrl) * 88, - Gui->GetCharHeight (LegalNoticesTextCtrl) * 28)); - - Layout(); - Fit(); - Center(); - - LegalNoticesTextCtrl->ChangeValue (StringConverter::ToWide (Resources::GetLegalNotices())); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "LegalNoticesDialog.h" +#include "Main/GraphicUserInterface.h" +#include "Main/Resources.h" + +namespace TrueCrypt +{ + LegalNoticesDialog::LegalNoticesDialog (wxWindow* parent) : LegalNoticesDialogBase (parent) + { + LegalNoticesTextCtrl->SetMinSize (wxSize ( + Gui->GetCharWidth (LegalNoticesTextCtrl) * 88, + Gui->GetCharHeight (LegalNoticesTextCtrl) * 28)); + + Layout(); + Fit(); + Center(); + + LegalNoticesTextCtrl->ChangeValue (StringConverter::ToWide (Resources::GetLegalNotices())); + } +} diff --git a/Main/Forms/LegalNoticesDialog.h b/Main/Forms/LegalNoticesDialog.h index 63516c4..390f4a1 100644 --- a/Main/Forms/LegalNoticesDialog.h +++ b/Main/Forms/LegalNoticesDialog.h @@ -1,23 +1,23 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_LegalNoticesDialog -#define TC_HEADER_Main_Forms_LegalNoticesDialog - -#include "Forms.h" - -namespace TrueCrypt -{ - class LegalNoticesDialog : public LegalNoticesDialogBase - { - public: - LegalNoticesDialog (wxWindow* parent); - }; -} - -#endif // TC_HEADER_Main_Forms_LegalNoticesDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_LegalNoticesDialog +#define TC_HEADER_Main_Forms_LegalNoticesDialog + +#include "Forms.h" + +namespace TrueCrypt +{ + class LegalNoticesDialog : public LegalNoticesDialogBase + { + public: + LegalNoticesDialog (wxWindow* parent); + }; +} + +#endif // TC_HEADER_Main_Forms_LegalNoticesDialog diff --git a/Main/Forms/MainFrame.cpp b/Main/Forms/MainFrame.cpp index 6392362..77b2341 100644 --- a/Main/Forms/MainFrame.cpp +++ b/Main/Forms/MainFrame.cpp @@ -1,1515 +1,1511 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Common/SecurityToken.h" -#include "Main/Main.h" -#include "Main/Resources.h" -#include "Main/Application.h" -#include "Main/GraphicUserInterface.h" -#include "Main/VolumeHistory.h" -#include "Main/Xml.h" -#include "MainFrame.h" -#include "AboutDialog.h" -#include "ChangePasswordDialog.h" -#include "EncryptionTestDialog.h" -#include "FavoriteVolumesDialog.h" -#include "LegalNoticesDialog.h" -#include "PreferencesDialog.h" -#include "SecurityTokenKeyfilesDialog.h" -#ifdef TC_WINDOWS -#include "TravelerDiskWizard.h" -#endif -#include "VolumeCreationWizard.h" -#include "VolumePropertiesDialog.h" - -namespace TrueCrypt -{ - MainFrame::MainFrame (wxWindow* parent) : MainFrameBase (parent), - SelectedItemIndex (-1), - SelectedSlotNumber (0) - { - wxBusyCursor busy; - - SetName (Application::GetName()); - SetTitle (Application::GetName()); - SetIcon (Resources::GetTrueCryptIcon()); - - InitControls(); - InitPreferences(); - InitTaskBarIcon(); - InitEvents(); - InitMessageFilter(); - - if (!GetPreferences().SecurityTokenModule.IsEmpty() && !SecurityToken::IsInitialized()) - { - try - { - Gui->InitSecurityTokenLibrary(); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - } - - MainFrame::~MainFrame () - { - Core->VolumeMountedEvent.Disconnect (this); - Core->VolumeDismountedEvent.Disconnect (this); - Gui->OpenVolumeSystemRequestEvent.Disconnect (this); - Gui->PreferencesUpdatedEvent.Disconnect (this); - - VolumeHistory::DisconnectComboBox (VolumePathComboBox); - -#ifdef TC_WINDOWS - Hotkey::UnregisterList (this, GetPreferences().Hotkeys); -#endif - } - - void MainFrame::AddToFavorites (const VolumeInfoList &volumes) - { - try - { - FavoriteVolumeList newFavorites; - - // Delete duplicates - foreach (shared_ptr favorite, FavoriteVolume::LoadList()) - { - bool mounted = false; - foreach_ref (const VolumeInfo &volume, volumes) - { - if (volume.Path == favorite->Path) - { - mounted = true; - break; - } - } - if (!mounted) - newFavorites.push_back (favorite); - } - - size_t newItemCount = 0; - foreach_ref (const VolumeInfo &volume, volumes) - { - newFavorites.push_back (shared_ptr (new FavoriteVolume (volume.Path, volume.MountPoint, volume.SlotNumber, volume.Protection == VolumeProtection::ReadOnly, volume.SystemEncryption))); - ++newItemCount; - } - - OrganizeFavorites (newFavorites, newItemCount); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - bool MainFrame::CanExit () const - { - return Gui->IsTheOnlyTopLevelWindow (this); - } - - void MainFrame::ChangePassword (ChangePasswordDialog::Mode::Enum mode) - { - if (!CheckVolumePathNotEmpty ()) - return; - - shared_ptr volumePath = GetSelectedVolumePath(); - -#ifdef TC_WINDOWS - if (Core->IsVolumeMounted (*volumePath)) - { - Gui->ShowInfo (LangString [mode == ChangePasswordDialog::Mode::ChangePkcs5Prf ? "MOUNTED_NO_PKCS5_PRF_CHANGE" : "MOUNTED_NOPWCHANGE"]); - return; - } -#endif - - ChangePasswordDialog dialog (this, volumePath, mode); - dialog.ShowModal(); - } - - void MainFrame::CheckFilesystem (bool repair) - { - shared_ptr selectedVolume = GetSelectedVolume(); - if (selectedVolume) - { - try - { -#ifdef TC_WINDOWS - string mountPoint = selectedVolume->MountPoint; - - wstring args = StringFormatter (repair ? L"/C echo {0} & chkdsk {1} /F /X & pause" : L"/C echo {0} & chkdsk {1} & pause", - StringFormatter (LangString[repair ? "REPAIRING_FS" : "CHECKING_FS"], mountPoint), mountPoint); - - ShellExecute (static_cast (GetHandle()), - L"runas", - L"cmd.exe", args.c_str(), nullptr, SW_SHOW); -#else -# ifdef TC_MACOSX - Gui->ShowInfo (_("Disk Utility will be launched after you press 'OK'.\n\nPlease select your volume in the Disk Utility window and press 'Verify Disk' or 'Repair Disk' button on the 'First Aid' page.")); -# endif - Core->CheckFilesystem (selectedVolume, repair); - UpdateVolumeList(); -#endif - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - } - - bool MainFrame::CheckVolumePathNotEmpty () const - { - if (VolumePathComboBox->GetValue().empty()) - { - Gui->ShowInfo ("NO_VOLUME_SELECTED"); - return false; - } - return true; - } - - void MainFrame::DismountVolume (shared_ptr volume) - { - try - { - if (!volume) - volume = GetSelectedVolume(); - - if (volume) - Gui->DismountVolume (volume); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - shared_ptr MainFrame::GetSelectedVolume () const - { - return Core->GetMountedVolume (SelectedSlotNumber); - } - - void MainFrame::InitControls () - { - LogoBitmap->SetBitmap (Resources::GetLogoBitmap()); - - list colPermilles; - -#ifndef TC_WINDOWS - SettingsMenu->Remove (HotkeysMenuItem); - ToolsMenu->Remove (TravelerDiskWizardMenuItem); -#endif - -#ifdef TC_MACOSX - SettingsMenu->Remove (PreferencesMenuItem); - SettingsMenu->AppendSeparator(); - SettingsMenu->Append (PreferencesMenuItem); - - LowStaticBoxSizer->Detach (HigherButtonSizer); - VolumeStaticBoxSizer->Detach (VolumeGridBagSizer); - VolumeStaticBoxSizer->Add (VolumeGridBagSizer, 1, wxEXPAND, 0); - - ExitButton->SetLabel (_("Close")); - MountAllDevicesButton->SetLabel (_("Mount All Devices")); -#endif - -#ifdef TC_WINDOWS - SlotListCtrl->InsertColumn (ColumnSlot, LangString["DRIVE"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (75); -#else - SlotListCtrl->InsertColumn (ColumnSlot, _("Slot"), wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (82); -#endif - - SlotListCtrl->InsertColumn (ColumnPath, LangString["VOLUME"], wxLIST_FORMAT_LEFT, 1); -#ifdef TC_WINDOWS - colPermilles.push_back (487); -#else - colPermilles.push_back (429); -#endif - - SlotListCtrl->InsertColumn (ColumnSize, LangString["SIZE"], wxLIST_FORMAT_RIGHT, 1); -#ifdef TC_WINDOWS - colPermilles.push_back (126); -#else - colPermilles.push_back (130); -#endif - -#ifdef TC_WINDOWS - SlotListCtrl->InsertColumn (ColumnEA, LangString["ENCRYPTION_ALGORITHM_LV"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (233); -#else - SlotListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (259); -#endif - - SlotListCtrl->InsertColumn (ColumnType, LangString["TYPE"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (100); - - wxImageList *imageList = new wxImageList (16, 12, true); - imageList->Add (Resources::GetDriveIconBitmap(), Resources::GetDriveIconMaskBitmap()); - SlotListCtrl->AssignImageList (imageList, wxIMAGE_LIST_SMALL); - - SetMinSize (wxSize (-1, -1)); - - size_t slotListRowCount = 12; - -#ifndef TC_WINDOWS - int screenHeight = wxSystemSettings::GetMetric (wxSYS_SCREEN_Y); - - if (screenHeight < 480) - slotListRowCount = 1; - else if (screenHeight <= 600) - slotListRowCount = slotListRowCount * screenHeight / 1000; -#endif - - Gui->SetListCtrlHeight (SlotListCtrl, slotListRowCount); - -#ifdef __WXGTK__ - wxSize size (-1, (int) ((double) Gui->GetCharHeight (this) * 1.53)); - CreateVolumeButton->SetMinSize (size); - VolumePropertiesButton->SetMinSize (size); - WipeCacheButton->SetMinSize (size); - VolumePathComboBox->SetMinSize (size); - SelectFileButton->SetMinSize (size); - SelectDeviceButton->SetMinSize (size); - VolumeToolsButton->SetMinSize (size); - size = wxSize (-1, 38); - VolumeButton->SetMinSize (size); -#endif - Fit(); - Layout(); - Center(); - - VolumePathComboBox->SetMinSize (VolumePathComboBox->GetSize()); - VolumePathComboBox->SetMaxSize (VolumePathComboBox->GetSize()); - - SetMinSize (GetSize()); - SetMaxSize (GetSize()); - - Gui->SetListCtrlColumnWidths (SlotListCtrl, colPermilles); - - UpdateVolumeList(); - UpdateWipeCacheButton(); - } - - void MainFrame::InitEvents () - { - Core->VolumeMountedEvent.Connect (EventConnector (this, &MainFrame::OnVolumeMounted)); - Core->VolumeDismountedEvent.Connect (EventConnector (this, &MainFrame::OnVolumeDismounted)); - Gui->OpenVolumeSystemRequestEvent.Connect (EventConnector (this, &MainFrame::OnOpenVolumeSystemRequestEvent)); - Gui->PreferencesUpdatedEvent.Connect (EventConnector (this, &MainFrame::OnPreferencesUpdated)); - - // Drag & drop - class FileDropTarget : public wxFileDropTarget - { - public: - FileDropTarget (MainFrame *frame) : Frame (frame) { } - - wxDragResult OnDragOver (wxCoord x, wxCoord y, wxDragResult def) - { - wxPoint p; - wxWindow *w = wxFindWindowAtPointer (p); - if (w == Frame || wxGetTopLevelParent (w) == Frame) - return wxDragLink; - return wxDragNone; - } - - bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString &filenames) - { - if (!filenames.empty()) - Frame->SetVolumePath (wstring (filenames.front())); - return true; - } - - MainFrame *Frame; - }; - - SetDropTarget (new FileDropTarget (this)); -#ifdef TC_MACOSX - foreach (wxWindow *c, MainPanel->GetChildren()) - c->SetDropTarget (new FileDropTarget (this)); -#endif - - // Volume history - VolumeHistory::ConnectComboBox (VolumePathComboBox); - -#ifdef TC_WINDOWS - // Hotkeys - Hotkey::RegisterList (this, GetPreferences().Hotkeys); - Connect (wxEVT_HOTKEY, wxKeyEventHandler (MainFrame::OnHotkey)); -#endif - - // Timer - class Timer : public wxTimer - { - public: - Timer (MainFrame *frame) : Frame (frame) { } - - void Notify() - { - Frame->OnTimer(); - } - - MainFrame *Frame; - }; - - mTimer.reset (dynamic_cast (new Timer (this))); - mTimer->Start (2000); - } - -#ifdef TC_WINDOWS -#include - static WNDPROC MainFrameWndProc; - static LRESULT CALLBACK MainFrameWndProcFilter (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) - { - if (message == WM_DEVICECHANGE && !Core->IsDeviceChangeInProgress()) - { - MainFrame *frame = dynamic_cast (Gui->GetMainFrame()); - PDEV_BROADCAST_HDR hdr = (PDEV_BROADCAST_HDR) lParam; - - if (wParam == DBT_DEVICEREMOVECOMPLETE && hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) - { - PDEV_BROADCAST_VOLUME vol = (PDEV_BROADCAST_VOLUME) lParam; - for (wchar_t driveNo = 0; driveNo < 26; ++driveNo) - { - if (vol->dbcv_unitmask & (1 << driveNo)) - frame->OnDeviceChange (wstring (StringFormatter (L"{0}:\\", wchar_t (L'A' + driveNo)))); - } - } - else - { - frame->OnDeviceChange (); - } - } - - return CallWindowProc (MainFrameWndProc, hwnd, message, wParam, lParam); - } -#endif - - void MainFrame::InitMessageFilter () - { -#ifdef TC_WINDOWS - HWND mainFrameHwnd = static_cast (GetHandle()); - MainFrameWndProc = (WNDPROC) GetWindowLongPtr (mainFrameHwnd, GWL_WNDPROC); - SetWindowLongPtr (mainFrameHwnd, GWL_WNDPROC, (LONG_PTR) MainFrameWndProcFilter); -#endif - } - - void MainFrame::InitPreferences () - { - try - { - LoadPreferences(); - - VolumeSlotNumber lastSelectedSlotNumber = GetPreferences().LastSelectedSlotNumber; - if (Core->IsSlotNumberValid (lastSelectedSlotNumber)) - { - long slotIndex = SlotNumberToItemIndex (lastSelectedSlotNumber); - if (slotIndex >= 0) - { - SlotListCtrl->SetItemState (slotIndex, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); - SlotListCtrl->EnsureVisible (slotIndex); - } - } - - LoadFavoriteVolumes(); - VolumeHistory::Load(); - } - catch (exception &e) - { - Gui->ShowError (e); - Gui->ShowError (_("Error while loading configuration files located in ") + wstring (Application::GetConfigFilePath (L""))); - } - } - - void MainFrame::InitTaskBarIcon () - { - class TaskBarIcon : public wxTaskBarIcon - { - public: - TaskBarIcon (MainFrame *frame) : Busy (false), Frame (frame) - { - Connect (wxEVT_TASKBAR_LEFT_DOWN, wxTaskBarIconEventHandler (TaskBarIcon::OnLeftButtonDown)); - } - - wxMenu *CreatePopupMenu () - { - auto_ptr popup (new wxMenu); - - Gui->AppendToMenu (*popup, LangString[Gui->IsInBackgroundMode() ? "SHOW_TC" : "HIDE_TC"], this, wxCommandEventHandler (TaskBarIcon::OnShowHideMenuItemSelected)); - - popup->AppendSeparator(); - Gui->AppendToMenu (*popup, _("Mount All Favorite Volumes"), this, wxCommandEventHandler (TaskBarIcon::OnMountAllFavoritesMenuItemSelected))->Enable (!Busy); - Gui->AppendToMenu (*popup, _("Dismount All Mounted Volumes"), this, wxCommandEventHandler (TaskBarIcon::OnDismountAllMenuItemSelected))->Enable (!Busy); - - // Favorite volumes - if (Gui->GetPreferences().BackgroundTaskMenuMountItemsEnabled && !Frame->FavoriteVolumesMenuMap.empty()) - { - popup->AppendSeparator(); - typedef pair FavMapPair; - foreach (FavMapPair fp, Frame->FavoriteVolumesMenuMap) - { - Gui->AppendToMenu (*popup, LangString["MOUNT"] + L" " + wstring (fp.second.Path) + (fp.second.MountPoint.IsEmpty() ? L"" : L" " + wstring (fp.second.MountPoint)), - this, wxCommandEventHandler (TaskBarIcon::OnFavoriteVolumeMenuItemSelected), fp.first)->Enable (!Busy); - } - } - - // Mounted volumes - VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); - if (!mountedVolumes.empty()) - { - if (Gui->GetPreferences().BackgroundTaskMenuOpenItemsEnabled) - { - popup->AppendSeparator(); - OpenMap.clear(); - foreach (shared_ptr volume, mountedVolumes) - { - if (!volume->MountPoint.IsEmpty()) - { - wxString label = LangString["OPEN"] + L" " + wstring (volume->MountPoint) + L" (" + wstring (volume->Path) + L")"; - wxMenuItem *item = Gui->AppendToMenu (*popup, label, this, wxCommandEventHandler (TaskBarIcon::OnOpenMenuItemSelected)); - OpenMap[item->GetId()] = volume; - } - } - } - - if (Gui->GetPreferences().BackgroundTaskMenuDismountItemsEnabled) - { - popup->AppendSeparator(); - DismountMap.clear(); - foreach (shared_ptr volume, mountedVolumes) - { - wxString label = LangString["DISMOUNT"] + L" "; - - if (!volume->MountPoint.IsEmpty()) - label += wstring (volume->MountPoint) + L" (" + wstring (volume->Path) + L")"; - else - label += wstring (volume->Path); - - wxMenuItem *item = Gui->AppendToMenu (*popup, label, this, wxCommandEventHandler (TaskBarIcon::OnDismountMenuItemSelected)); - item->Enable (!Busy); - DismountMap[item->GetId()] = volume; - } - } - } - - popup->AppendSeparator(); - Gui->AppendToMenu (*popup, _("Preferences..."), this, wxCommandEventHandler (TaskBarIcon::OnPreferencesMenuItemSelected))->Enable (!Busy); -#ifndef TC_MACOSX - popup->AppendSeparator(); - Gui->AppendToMenu (*popup, _("Exit"), this, wxCommandEventHandler (TaskBarIcon::OnExitMenuItemSelected))->Enable (!Busy && Frame->CanExit()); -#endif - return popup.release(); - } - - void OnDismountAllMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnDismountAllButtonClick (event); Busy = false; } - void OnDismountMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->DismountVolume (DismountMap[event.GetId()]); Busy = false; } - void OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnFavoriteVolumeMenuItemSelected (event); Busy = false; } - void OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->MountAllFavorites (); Busy = false; } - - void OnExitMenuItemSelected (wxCommandEvent& event) - { - Busy = true; - if (Core->GetMountedVolumes().empty() || Gui->AskYesNo (LangString ["CONFIRM_EXIT"], false, true)) - Frame->Close (true); - Busy = false; - } - - void OnLeftButtonDown (wxTaskBarIconEvent& event) { Gui->SetBackgroundMode (false); } - void OnOpenMenuItemSelected (wxCommandEvent& event) { Gui->OpenExplorerWindow (OpenMap[event.GetId()]->MountPoint); } - void OnPreferencesMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnPreferencesMenuItemSelected (event); Busy = false; } - void OnShowHideMenuItemSelected (wxCommandEvent& event) { Gui->SetBackgroundMode (!Gui->IsInBackgroundMode()); } - - bool Busy; - map < int, shared_ptr > DismountMap; - MainFrame *Frame; - map < int, shared_ptr > OpenMap; - }; - - mTaskBarIcon.reset (new TaskBarIcon (this)); - ShowTaskBarIcon (GetPreferences().BackgroundTaskEnabled); - } - - void MainFrame::LoadFavoriteVolumes () - { - typedef pair FavMapPair; - foreach (FavMapPair p, FavoriteVolumesMenuMap) - { - FavoritesMenu->Delete (p.first); - } - FavoriteVolumesMenuMap.clear(); - - foreach_ref (const FavoriteVolume &favorite, FavoriteVolume::LoadList()) - { - wstring label = wstring (favorite.Path); - if (!favorite.MountPoint.IsEmpty()) - label += wstring (L" ") + wstring (favorite.MountPoint); - - wxMenuItem *item = Gui->AppendToMenu (*FavoritesMenu, label, this, wxCommandEventHandler (MainFrame::OnFavoriteVolumeMenuItemSelected)); - FavoriteVolumesMenuMap[item->GetId()] = favorite; - } - } - - void MainFrame::LoadPreferences () - { - UserPreferences prefs; - prefs.Load(); - Gui->SetPreferences (prefs); - NoHistoryCheckBox->SetValue (!prefs.SaveHistory); - } - - void MainFrame::MountAllDevices () - { - try - { - MountOptions mountOptions (GetPreferences().DefaultMountOptions); - - if (SlotListCtrl->GetSelectedItemCount() == 1) - mountOptions.SlotNumber = SelectedSlotNumber; - - Gui->MountAllDeviceHostedVolumes (mountOptions); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::MountAllFavorites () - { - try - { - MountOptions mountOptions (GetPreferences().DefaultMountOptions); - Gui->MountAllFavoriteVolumes (mountOptions); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::MountVolume () - { - if (!IsFreeSlotSelected()) - { - Gui->ShowWarning (_("Please select a free drive slot from the list.")); - return; - } - - if (!CheckVolumePathNotEmpty()) - return; - - MountOptions mountOptions (GetPreferences().DefaultMountOptions); - mountOptions.SlotNumber = SelectedSlotNumber; - mountOptions.Path = GetSelectedVolumePath(); - - try - { - if (Gui->MountVolume (mountOptions) && GetPreferences().SaveHistory) - VolumeHistory::Add (*mountOptions.Path); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::OnAboutMenuItemSelected (wxCommandEvent& event) - { - AboutDialog dialog (this); - dialog.ShowModal(); - } - - void MainFrame::OnActivate (wxActivateEvent& event) - { - Gui->SetActiveFrame (this); - -#ifdef TC_MACOSX - if (event.GetActive() && Gui->IsInBackgroundMode()) - Gui->SetBackgroundMode (false); -#endif - event.Skip(); - } - - void MainFrame::OnAddAllMountedToFavoritesMenuItemSelected (wxCommandEvent& event) - { - AddToFavorites (MountedVolumes); - } - - void MainFrame::OnAddToFavoritesMenuItemSelected (wxCommandEvent& event) - { - shared_ptr selectedVolume = GetSelectedVolume(); - if (selectedVolume) - { - VolumeInfoList volumes; - volumes.push_back (selectedVolume); - AddToFavorites (volumes); - } - } - - void MainFrame::OnBackupVolumeHeadersMenuItemSelected (wxCommandEvent& event) - { - if (!CheckVolumePathNotEmpty ()) - return; - - try - { - Gui->BackupVolumeHeaders (GetSelectedVolumePath()); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::OnClearSlotSelectionMenuItemSelected (wxCommandEvent& event) - { - Gui->ClearListCtrlSelection (SlotListCtrl); - UpdateControls(); - } - - void MainFrame::OnClose (wxCloseEvent& event) - { - if (GetPreferences().WipeCacheOnClose) - Core->WipePasswordCache(); - -#ifdef TC_MACOSX - if (!event.CanVeto() && GetPreferences().DismountOnLogOff) - { - try - { - Gui->DismountVolumes (Core->GetMountedVolumes(), GetPreferences().ForceAutoDismount, false); - } - catch (...) { } - } -#endif - - if (!Gui->IsTheOnlyTopLevelWindow (this)) - { - // Bring first frame to foreground - wxFrame *frame = nullptr; - foreach (wxWindow *window, wxTopLevelWindows) - { - if (window != this - && dynamic_cast (window) - && StringConverter::GetTypeName (typeid (*window)).find ("wxTaskBarIcon") == string::npos) - { - frame = dynamic_cast (window); - if (window->IsShown()) - break; - } - } - - if (frame) - { - frame->Show(); - if (frame->IsIconized()) - frame->Iconize(false); - frame->Raise(); - } - } - else if (event.CanVeto() && GetPreferences().BackgroundTaskEnabled - && (!GetPreferences().CloseBackgroundTaskOnNoVolumes || !MountedVolumes.empty())) - { - // Enter background mode - if (!Gui->IsInBackgroundMode()) - Gui->SetBackgroundMode (true); - } - else - { -#ifdef __WXGTK__ - Show(); -#endif - SavePreferences(); - - Destroy(); - } - - // Cancel close - veto is not used to prevent aborting log off procedure on Windows - return; - } - - void MainFrame::OnCloseAllSecurityTokenSessionsMenuItemSelected (wxCommandEvent& event) - { - try - { - { - wxBusyCursor busy; - SecurityToken::CloseAllSessions(); - } - Gui->ShowInfo ("ALL_TOKEN_SESSIONS_CLOSED"); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::OnCreateVolumeButtonClick (wxCommandEvent& event) - { - try - { - (new VolumeCreationWizard (nullptr))->Show(); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::OnDefaultKeyfilesMenuItemSelected (wxCommandEvent& event) - { - PreferencesDialog dialog (this); - dialog.SelectPage (dialog.DefaultKeyfilesPage); - dialog.ShowModal(); - } - - void MainFrame::OnDeviceChange (const DirectoryPath &mountPoint) - { - // Check if any host device has been removed and force dismount of volumes accordingly - VolumeInfoList removedVolumes; - foreach (shared_ptr volume, Core->GetMountedVolumes()) - { - // File-hosted volumes - if (!volume->Path.IsDevice() && !mountPoint.IsEmpty()) - { - if (wxString (volume->Path).Upper().StartsWith (wstring (mountPoint).c_str())) - { - removedVolumes.push_back (volume); - continue; - } - } - - // Device-hosted volumes - if (volume->Path.IsDevice() && !Core->IsDevicePresent (volume->Path)) - removedVolumes.push_back (volume); - } - - if (!removedVolumes.empty()) - Gui->AutoDismountVolumes (removedVolumes, true); - } - - void MainFrame::OnDismountAllButtonClick (wxCommandEvent& event) - { - Gui->DismountAllVolumes(); - } - - void MainFrame::OnEncryptionTestMenuItemSelected (wxCommandEvent& event) - { - EncryptionTestDialog dialog (this); - dialog.ShowModal(); - } - - void MainFrame::OnExitButtonClick (wxCommandEvent& event) - { - Close(); - } - - void MainFrame::OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event) - { - FavoriteVolume favorite = FavoriteVolumesMenuMap[event.GetId()]; - if (!favorite.Path.IsEmpty()) - { - SetVolumePath (favorite.Path); - - MountOptions mountOptions (GetPreferences().DefaultMountOptions); - favorite.ToMountOptions (mountOptions); - - shared_ptr volume = Gui->MountVolume (mountOptions); - if (volume) - SlotListCtrl->EnsureVisible (SlotNumberToItemIndex (volume->SlotNumber)); - } - } - - void MainFrame::OnHiddenVolumeProtectionTriggered (shared_ptr protectedVolume) - { - Gui->ShowWarningTopMost (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (protectedVolume->Path))); - } - - void MainFrame::OnHotkey (wxKeyEvent& event) - { -#ifdef TC_WINDOWS - switch (event.GetId()) - { - case Hotkey::Id::CloseAllSecurityTokenSessions: - try - { - SecurityToken::CloseAllSessions(); - Gui->ShowInfo ("ALL_TOKEN_SESSIONS_CLOSED"); - } - catch (exception &e) { Gui->ShowError (e); } - break; - - case Hotkey::Id::DismountAll: - case Hotkey::Id::DismountAllWipeCache: - { - if (event.GetId() == Hotkey::Id::DismountAllWipeCache) - WipeCache(); - - size_t mountedCount = Core->GetMountedVolumes().size(); - Gui->DismountAllVolumes(); - size_t newMountedCount = Core->GetMountedVolumes().size(); - - if (newMountedCount < mountedCount) - { - if (newMountedCount == 0 && GetPreferences().DisplayMessageAfterHotkeyDismount) - Gui->ShowInfo ("MOUNTED_VOLUMES_DISMOUNTED"); - else if (GetPreferences().BeepAfterHotkeyMountDismount) - MessageBeep((UINT) -1); - } - } - break; - - case Hotkey::Id::ForceDismountAllWipeCache: - case Hotkey::Id::ForceDismountAllWipeCacheExit: - { - bool mounted = !Core->GetMountedVolumes().empty(); - - WipeCache(); - Gui->DismountAllVolumes (true, true); - - if (mounted && GetPreferences().DisplayMessageAfterHotkeyDismount) - Gui->ShowInfo ("VOLUMES_DISMOUNTED_CACHE_WIPED"); - else if (mounted && GetPreferences().BeepAfterHotkeyMountDismount) - MessageBeep((UINT) -1); - - if (event.GetId() == Hotkey::Id::ForceDismountAllWipeCacheExit) - Close (true); - } - break; - - case Hotkey::Id::MountAllDevices: - case Hotkey::Id::MountAllFavorites: - { - size_t mountedCount = Core->GetMountedVolumes().size(); - - if (event.GetId() == Hotkey::Id::MountAllDevices) - MountAllDevices(); - else - MountAllFavorites(); - - if (Core->GetMountedVolumes().size() > mountedCount && GetPreferences().BeepAfterHotkeyMountDismount) - MessageBeep((UINT) -1); - } - break; - - case Hotkey::Id::ShowHideApplication: - Gui->SetBackgroundMode (!Gui->IsInBackgroundMode()); - break; - - case Hotkey::Id::WipeCache: - WipeCache(); - Gui->ShowInfo ("PASSWORD_CACHE_WIPED"); - break; - - default: - assert (false); - break; - } -#endif // TC_WINDOWS - } - - void MainFrame::OnHotkeysMenuItemSelected (wxCommandEvent& event) - { - PreferencesDialog dialog (this); - dialog.SelectPage (dialog.HotkeysPage); - dialog.ShowModal(); - } - - void MainFrame::OnLegalNoticesMenuItemSelected (wxCommandEvent& event) - { - LegalNoticesDialog dialog (this); - dialog.ShowModal(); - } - - void MainFrame::OnListChanged () - { - OnListItemSelectionChanged(); - UpdateControls(); - } - - void MainFrame::OnListItemActivated (wxListEvent& event) - { - if (IsMountedSlotSelected()) - OpenSelectedVolume(); - else - MountVolume(); - } - - void MainFrame::OnListItemDeleted (long itemIndex) - { - if (SelectedItemIndex > itemIndex) - --SelectedItemIndex; - } - - void MainFrame::OnListItemDeselected (wxListEvent& event) - { - OnListItemSelectionChanged(); - } - - void MainFrame::OnListItemInserted (long itemIndex) - { - if (SelectedItemIndex >= itemIndex) - ++SelectedItemIndex; - } - - void MainFrame::OnListItemRightClick (wxListEvent& event) - { -#ifdef TC_MACOSX - if (SelectedItemIndex != event.GetIndex()) - { - SelectedItemIndex = event.GetIndex(); - OnListItemSelectionChanged(); - } -#endif - wxMenu popup; - if (IsMountedSlotSelected()) - { - Gui->AppendToMenu (popup, LangString["DISMOUNT"], this, wxCommandEventHandler (MainFrame::OnDismountVolumeMenuItemSelected)); - Gui->AppendToMenu (popup, LangString["OPEN"], this, wxCommandEventHandler (MainFrame::OnOpenVolumeMenuItemSelected)); - Gui->AppendToMenu (popup, _("Deselect"), this, wxCommandEventHandler (MainFrame::OnClearSlotSelectionMenuItemSelected)); - - popup.AppendSeparator(); - Gui->AppendToMenu (popup, _("Add to Favorites..."), this, wxCommandEventHandler (MainFrame::OnAddToFavoritesMenuItemSelected)); - - popup.AppendSeparator(); - Gui->AppendToMenu (popup, LangString["IDPM_CHECK_FILESYS"], this, wxCommandEventHandler (MainFrame::OnCheckFilesystemMenuItemSelected)); - Gui->AppendToMenu (popup, LangString["IDPM_REPAIR_FILESYS"], this, wxCommandEventHandler (MainFrame::OnRepairFilesystemMenuItemSelected)); - - popup.AppendSeparator(); - Gui->AppendToMenu (popup, LangString["IDPM_PROPERTIES"], this, wxCommandEventHandler (MainFrame::OnVolumePropertiesButtonClick)); - - PopupMenu (&popup); - } - else if (IsFreeSlotSelected()) - { - Gui->AppendToMenu (popup, _("Mount Volume"), this, wxCommandEventHandler (MainFrame::OnMountVolumeMenuItemSelected)); - - popup.AppendSeparator(); - - Gui->AppendToMenu (popup, LangString["SELECT_FILE_AND_MOUNT"], this, wxCommandEventHandler (MainFrame::OnSelectFileAndMountMenuItemSelected)); - Gui->AppendToMenu (popup, LangString["SELECT_DEVICE_AND_MOUNT"], this, wxCommandEventHandler (MainFrame::OnSelectDeviceAndMountMenuItemSelected)); - - popup.AppendSeparator(); - - Gui->AppendToMenu (popup, _("Deselect"), this, wxCommandEventHandler (MainFrame::OnClearSlotSelectionMenuItemSelected)); - - PopupMenu (&popup); - } - - event.Skip(); - } - - void MainFrame::OnListItemSelected (wxListEvent& event) - { - SelectedItemIndex = event.GetIndex(); - OnListItemSelectionChanged(); - } - - void MainFrame::OnListItemSelectionChanged () - { - if (SlotListCtrl->GetSelectedItemCount() < 1) - SelectedItemIndex = -1; - - if (SelectedItemIndex >= 0) - SelectedSlotNumber = (VolumeSlotNumber) SlotListCtrl->GetItemData (SelectedItemIndex); - else - SelectedSlotNumber = 0; - - UpdateControls(); - } - - void MainFrame::OnManageSecurityTokenKeyfilesMenuItemSelected (wxCommandEvent& event) - { - try - { - SecurityTokenKeyfilesDialog dialog (this, false); - dialog.ShowModal(); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::OnMountAllDevicesButtonClick (wxCommandEvent& event) - { - MountAllDevices(); - } - - void MainFrame::OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event) - { - MountAllFavorites(); - } - - void MainFrame::OnNoHistoryCheckBoxClick (wxCommandEvent& event) - { - UserPreferences prefs = GetPreferences(); - prefs.SaveHistory = !event.IsChecked(); - Gui->SetPreferences (prefs); - - if (event.IsChecked()) - { - try - { - VolumeHistory::Clear(); - } - catch (exception &e) { Gui->ShowError (e); } - } - } - - void MainFrame::OnOrganizeFavoritesMenuItemSelected (wxCommandEvent& event) - { - try - { - OrganizeFavorites (FavoriteVolume::LoadList()); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::OnPreferencesMenuItemSelected (wxCommandEvent& event) - { - PreferencesDialog dialog (this); - dialog.ShowModal(); - } - - void MainFrame::OnPreferencesUpdated (EventArgs &args) - { - const UserPreferences &prefs = GetPreferences(); - - NoHistoryCheckBox->SetValue (!prefs.SaveHistory); - - ShowTaskBarIcon (prefs.BackgroundTaskEnabled); - if (Gui->IsInBackgroundMode() && !prefs.BackgroundTaskEnabled) - Close (true); - - SavePreferences(); - } - - void MainFrame::OnRestoreVolumeHeaderMenuItemSelected (wxCommandEvent& event) - { - if (!CheckVolumePathNotEmpty ()) - return; - - try - { - Gui->RestoreVolumeHeaders (GetSelectedVolumePath()); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void MainFrame::OnSecurityTokenPreferencesMenuItemSelected (wxCommandEvent& event) - { - PreferencesDialog dialog (this); - dialog.SelectPage (dialog.SecurityTokensPage); - dialog.ShowModal(); - } - - - void MainFrame::OnSelectDeviceAndMountMenuItemSelected (wxCommandEvent& event) - { - DevicePath path = Gui->SelectDevice (this); - - if (!path.IsEmpty()) - { - SetVolumePath (path); - OnMountVolumeMenuItemSelected (event); - } - } - - void MainFrame::OnSelectDeviceButtonClick (wxCommandEvent& event) - { - DevicePath path = Gui->SelectDevice (this); - - if (!path.IsEmpty()) - SetVolumePath (path); - } - - void MainFrame::OnSelectFileAndMountMenuItemSelected (wxCommandEvent& event) - { - FilePath path = Gui->SelectVolumeFile (this); - - if (!path.IsEmpty()) - { - SetVolumePath (path); - OnMountVolumeMenuItemSelected (event); - } - } - - void MainFrame::OnSelectFileButtonClick (wxCommandEvent& event) - { - FilePath path = Gui->SelectVolumeFile (this); - if (!path.IsEmpty()) - SetVolumePath (path); - } - - void MainFrame::OnTimer () - { - UpdateVolumeList(); - UpdateWipeCacheButton(); - - if (GetPreferences().BackgroundTaskEnabled) - { - // Inactivity auto-dismount - if (GetPreferences().DismountOnInactivity) - { - VolumeInfoList inactiveVolumes; - wxLongLong currentTime = wxGetLocalTimeMillis().GetValue(); - - map newActivityTimeMap; - - foreach (shared_ptr volume, MountedVolumes) - { - if (VolumeActivityMap.find (volume->Path) != VolumeActivityMap.end() - && VolumeActivityMap[volume->Path].SerialInstanceNumber == volume->SerialInstanceNumber) - { - VolumeActivityMapEntry ae = VolumeActivityMap[volume->Path]; - - if (volume->TotalDataRead != ae.TotalDataRead || volume->TotalDataWritten != ae.TotalDataWritten) - { - ae.LastActivityTime = currentTime; - ae.TotalDataRead = volume->TotalDataRead; - ae.TotalDataWritten = volume->TotalDataWritten; - } - else if ((currentTime - ae.LastActivityTime) > GetPreferences().MaxVolumeIdleTime * 1000LL * 60) - { - inactiveVolumes.push_back (volume); - } - - newActivityTimeMap[volume->Path] = ae; - } - else - { - newActivityTimeMap[volume->Path] = VolumeActivityMapEntry (*volume, currentTime); - } - } - - VolumeActivityMap = newActivityTimeMap; - - if (!inactiveVolumes.empty()) - Gui->AutoDismountVolumes (inactiveVolumes); - } - - // Screen saver auto-dismount - if (GetPreferences().DismountOnScreenSaver) - { -#ifdef TC_WINDOWS - bool running; - if (SystemParametersInfo (SPI_GETSCREENSAVERRUNNING, 0, &running, 0) != 0) - { - static bool previousState = false; - if (running && !previousState) - { - previousState = true; - Gui->OnAutoDismountAllEvent(); - } - else - { - previousState = running; - } - } -#endif - } - } - - if (Gui->IsInBackgroundMode()) - { - if (!GetPreferences().BackgroundTaskEnabled) - { - Close (true); - } - else if (MountedVolumes.empty() && (GetPreferences().CloseBackgroundTaskOnNoVolumes || Core->IsInTravelMode())) - { - Close (true); - } - } - } - - void MainFrame::OnTravelerDiskWizardMenuItemSelected (wxCommandEvent& event) - { -#ifdef TC_WINDOWS - (new TravelerDiskWizard (this))->Show(); -#endif - } - - void MainFrame::OnVolumeButtonClick (wxCommandEvent& event) - { - if (IsMountedSlotSelected()) - DismountVolume(); - else - MountVolume(); - } - - void MainFrame::OnVolumePropertiesButtonClick (wxCommandEvent& event) - { - shared_ptr selectedVolume = GetSelectedVolume(); - if (selectedVolume) - { - VolumePropertiesDialog dialog (this, *selectedVolume); - dialog.ShowModal(); - } - } - - void MainFrame::OnVolumeToolsButtonClick (wxCommandEvent& event) - { - if (!CheckVolumePathNotEmpty()) - return; - - wxMenu popup; - - Gui->AppendToMenu (popup, _("Change Volume Password..."), this, wxCommandEventHandler (MainFrame::OnChangePasswordMenuItemSelected)); - - popup.AppendSeparator (); - - Gui->AppendToMenu (popup, _("Add/Remove Keyfiles to/from Volume..."), this, wxCommandEventHandler (MainFrame::OnChangeKeyfilesMenuItemSelected)); - Gui->AppendToMenu (popup, _("Remove All Keyfiles from Volume..."), this, wxCommandEventHandler (MainFrame::OnRemoveKeyfilesMenuItemSelected)); - - popup.AppendSeparator (); - - Gui->AppendToMenu (popup, _("Change Header Key Derivation Algorithm..."), this, wxCommandEventHandler (MainFrame::OnChangePkcs5PrfMenuItemSelected)); - - popup.AppendSeparator (); - - Gui->AppendToMenu (popup, _("Backup Volume Header..."), this, wxCommandEventHandler (MainFrame::OnBackupVolumeHeadersMenuItemSelected)); - Gui->AppendToMenu (popup, _("Restore Volume Header..."), this, wxCommandEventHandler (MainFrame::OnRestoreVolumeHeaderMenuItemSelected)); - - PopupMenu (&popup, VolumeToolsButton->GetPosition().x + 2, VolumeToolsButton->GetPosition().y + 2); - } - - void MainFrame::OnWipeCacheButtonClick (wxCommandEvent& event) - { - WipeCache(); - Gui->ShowInfo ("PASSWORD_CACHE_WIPED"); - } - - void MainFrame::OpenSelectedVolume () const - { - shared_ptr selectedVolume = GetSelectedVolume(); - if (selectedVolume) - { - try - { - wxBusyCursor busy; - Gui->OpenExplorerWindow (selectedVolume->MountPoint); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - } - - void MainFrame::OrganizeFavorites (const FavoriteVolumeList &favorites, size_t newItemCount) - { - FavoriteVolumesDialog dialog (this, favorites, newItemCount); - - if (dialog.ShowModal() == wxID_OK) - { - FavoriteVolume::SaveList (dialog.GetFavorites()); - LoadFavoriteVolumes(); - } - } - - void MainFrame::SavePreferences () const - { - try - { - UserPreferences prefs = GetPreferences(); - prefs.LastSelectedSlotNumber = SelectedSlotNumber; - prefs.Save(); - - VolumeHistory::Save(); - } - catch (exception &e) - { - if (!Core->IsInTravelMode()) - Gui->ShowError (e); - } - } - - void MainFrame::ShowTaskBarIcon (bool show) - { - if (!show && mTaskBarIcon->IsIconInstalled()) - { - mTaskBarIcon->RemoveIcon(); - } - else if (show && !mTaskBarIcon->IsIconInstalled()) - { -#ifndef TC_MACOSX - mTaskBarIcon->SetIcon (Resources::GetTrueCryptIcon(), L"TrueCrypt"); -#endif - } - } - - long MainFrame::SlotNumberToItemIndex (uint32 slotNumber) const - { - for (long itemIndex = 0; itemIndex < SlotListCtrl->GetItemCount(); itemIndex++) - { - wxListItem item; - item.SetId (itemIndex); - if (slotNumber == SlotListCtrl->GetItemData (item)) - return itemIndex; - } - return -1; - } - - void MainFrame::UpdateControls () - { - bool mounted = IsMountedSlotSelected(); - - VolumeButton->SetLabel (mounted ? LangString["DISMOUNT"] : wxString (_("Mount"))); - VolumePropertiesButton->Enable (mounted); - - DismountVolumeMenuItem->Enable (mounted); - MountVolumeMenuItem->Enable (!mounted); - VolumePropertiesMenuItem->Enable (mounted); - AddToFavoritesMenuItem->Enable (mounted); - AddAllMountedToFavoritesMenuItem->Enable (!MountedVolumes.empty()); - UpdateWipeCacheButton(); - } - - void MainFrame::UpdateVolumeList () - { - static Mutex mutex; - ScopeLock lock (mutex); - - bool listChanged = false; - - MountedVolumes = Core->GetMountedVolumes(); - - map < VolumeSlotNumber, shared_ptr > mountedVolumesMap; - foreach (shared_ptr volume, MountedVolumes) - { - mountedVolumesMap[volume->SlotNumber] = volume; - } - - VolumeInfoList protectionTriggeredVolumes; - - // Update list - long prevItemIndex = -1; - for (VolumeSlotNumber slotNumber = Core->GetFirstSlotNumber(); slotNumber <= Core->GetLastSlotNumber(); ++slotNumber) - { - long itemIndex = SlotNumberToItemIndex (slotNumber); - vector fields (SlotListCtrl->GetColumnCount()); - - if (mountedVolumesMap.find (slotNumber) != mountedVolumesMap.end()) - { - shared_ptr volume = mountedVolumesMap[slotNumber]; - -#ifdef TC_WINDOWS - fields[ColumnSlot] = volume->MountPoint; - fields[ColumnEA] = volume->EncryptionAlgorithmName; -#else - fields[ColumnSlot] = StringConverter::FromNumber (slotNumber); - fields[ColumnMountPoint] = volume->MountPoint; -#endif - fields[ColumnPath] = volume->Path; - fields[ColumnSize] = Gui->SizeToString (volume->Size); - fields[ColumnType] = Gui->VolumeTypeToString (volume->Type, volume->Protection); - - if (volume->HiddenVolumeProtectionTriggered) - { - fields[ColumnType] += L"(!)"; - } - - bool slotUpdated = false; - if (itemIndex == -1) - { - Gui->InsertToListCtrl (SlotListCtrl, ++prevItemIndex, fields, 0, (void *) volume->SlotNumber); - OnListItemInserted (prevItemIndex); - - listChanged |= true; - slotUpdated = true; - } - else - { - if (Gui->UpdateListCtrlItem (SlotListCtrl, itemIndex, fields)) - { - listChanged = true; - slotUpdated = true; - } - prevItemIndex = itemIndex; - } - - if (slotUpdated && volume->HiddenVolumeProtectionTriggered) - protectionTriggeredVolumes.push_back (volume); - } - else - { -#ifdef TC_WINDOWS - fields[ColumnSlot] = Core->SlotNumberToMountPoint (slotNumber); -#else - fields[ColumnSlot] = StringConverter::FromNumber (slotNumber); -#endif - -#ifdef TC_WINDOWS - if (Core->IsMountPointAvailable (fields[ColumnSlot])) -#else - if (true) -#endif - { - if (itemIndex == -1) - { - Gui->InsertToListCtrl (SlotListCtrl, ++prevItemIndex, fields, 0, (void *) slotNumber); - OnListItemInserted (prevItemIndex); - listChanged |= true; - } - else - { - listChanged |= Gui->UpdateListCtrlItem (SlotListCtrl, itemIndex, fields); - prevItemIndex = itemIndex; - } - } - else if (itemIndex != -1) - { - SlotListCtrl->DeleteItem (itemIndex); - OnListItemDeleted (itemIndex); - listChanged = true; - } - } - } - - if (listChanged) - OnListChanged(); - - foreach (shared_ptr volume, protectionTriggeredVolumes) - OnHiddenVolumeProtectionTriggered (volume); - } - - void MainFrame::UpdateWipeCacheButton () - { - bool enabled = WipeCacheButton->IsEnabled(); - bool empty = Core->IsPasswordCacheEmpty(); - - if (empty && enabled) - { - WipeCacheButton->Disable(); - WipeCachedPasswordsMenuItem->Enable (false); - } - else if (!empty && !enabled) - { - WipeCacheButton->Enable(); - WipeCachedPasswordsMenuItem->Enable(); - } - } - - void MainFrame::WipeCache () - { - Core->WipePasswordCache(); - UpdateWipeCacheButton(); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Common/SecurityToken.h" +#include "Main/Main.h" +#include "Main/Resources.h" +#include "Main/Application.h" +#include "Main/GraphicUserInterface.h" +#include "Main/VolumeHistory.h" +#include "Main/Xml.h" +#include "MainFrame.h" +#include "AboutDialog.h" +#include "ChangePasswordDialog.h" +#include "EncryptionTestDialog.h" +#include "FavoriteVolumesDialog.h" +#include "LegalNoticesDialog.h" +#include "PreferencesDialog.h" +#include "SecurityTokenKeyfilesDialog.h" +#include "VolumeCreationWizard.h" +#include "VolumePropertiesDialog.h" + +namespace TrueCrypt +{ + MainFrame::MainFrame (wxWindow* parent) : MainFrameBase (parent), + SelectedItemIndex (-1), + SelectedSlotNumber (0) + { + wxBusyCursor busy; + + SetName (Application::GetName()); + SetTitle (Application::GetName()); + SetIcon (Resources::GetTrueCryptIcon()); + + InitControls(); + InitPreferences(); + InitTaskBarIcon(); + InitEvents(); + InitMessageFilter(); + + if (!GetPreferences().SecurityTokenModule.IsEmpty() && !SecurityToken::IsInitialized()) + { + try + { + Gui->InitSecurityTokenLibrary(); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + } + + MainFrame::~MainFrame () + { + Core->VolumeMountedEvent.Disconnect (this); + Core->VolumeDismountedEvent.Disconnect (this); + Gui->OpenVolumeSystemRequestEvent.Disconnect (this); + Gui->PreferencesUpdatedEvent.Disconnect (this); + + VolumeHistory::DisconnectComboBox (VolumePathComboBox); + +#ifdef TC_WINDOWS + Hotkey::UnregisterList (this, GetPreferences().Hotkeys); +#endif + } + + void MainFrame::AddToFavorites (const VolumeInfoList &volumes) + { + try + { + FavoriteVolumeList newFavorites; + + // Delete duplicates + foreach (shared_ptr favorite, FavoriteVolume::LoadList()) + { + bool mounted = false; + foreach_ref (const VolumeInfo &volume, volumes) + { + if (volume.Path == favorite->Path) + { + mounted = true; + break; + } + } + if (!mounted) + newFavorites.push_back (favorite); + } + + size_t newItemCount = 0; + foreach_ref (const VolumeInfo &volume, volumes) + { + newFavorites.push_back (shared_ptr (new FavoriteVolume (volume.Path, volume.MountPoint, volume.SlotNumber, volume.Protection == VolumeProtection::ReadOnly, volume.SystemEncryption))); + ++newItemCount; + } + + OrganizeFavorites (newFavorites, newItemCount); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + bool MainFrame::CanExit () const + { + return Gui->IsTheOnlyTopLevelWindow (this); + } + + void MainFrame::ChangePassword (ChangePasswordDialog::Mode::Enum mode) + { + if (!CheckVolumePathNotEmpty ()) + return; + + shared_ptr volumePath = GetSelectedVolumePath(); + +#ifdef TC_WINDOWS + if (Core->IsVolumeMounted (*volumePath)) + { + Gui->ShowInfo (LangString [mode == ChangePasswordDialog::Mode::ChangePkcs5Prf ? "MOUNTED_NO_PKCS5_PRF_CHANGE" : "MOUNTED_NOPWCHANGE"]); + return; + } +#endif + + ChangePasswordDialog dialog (this, volumePath, mode); + dialog.ShowModal(); + } + + void MainFrame::CheckFilesystem (bool repair) + { + shared_ptr selectedVolume = GetSelectedVolume(); + if (selectedVolume) + { + try + { +#ifdef TC_WINDOWS + string mountPoint = selectedVolume->MountPoint; + + wstring args = StringFormatter (repair ? L"/C echo {0} & chkdsk {1} /F /X & pause" : L"/C echo {0} & chkdsk {1} & pause", + StringFormatter (LangString[repair ? "REPAIRING_FS" : "CHECKING_FS"], mountPoint), mountPoint); + + ShellExecute (static_cast (GetHandle()), + L"runas", + L"cmd.exe", args.c_str(), nullptr, SW_SHOW); +#else +# ifdef TC_MACOSX + Gui->ShowInfo (_("Disk Utility will be launched after you press 'OK'.\n\nPlease select your volume in the Disk Utility window and press 'Verify Disk' or 'Repair Disk' button on the 'First Aid' page.")); +# endif + Core->CheckFilesystem (selectedVolume, repair); + UpdateVolumeList(); +#endif + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + } + + bool MainFrame::CheckVolumePathNotEmpty () const + { + if (VolumePathComboBox->GetValue().empty()) + { + Gui->ShowInfo ("NO_VOLUME_SELECTED"); + return false; + } + return true; + } + + void MainFrame::DismountVolume (shared_ptr volume) + { + try + { + if (!volume) + volume = GetSelectedVolume(); + + if (volume) + Gui->DismountVolume (volume); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + shared_ptr MainFrame::GetSelectedVolume () const + { + return Core->GetMountedVolume (SelectedSlotNumber); + } + + void MainFrame::InitControls () + { + LogoBitmap->SetBitmap (Resources::GetLogoBitmap()); + + list colPermilles; + +#ifndef TC_WINDOWS + SettingsMenu->Remove (HotkeysMenuItem); +#endif + +#ifdef TC_MACOSX + SettingsMenu->Remove (PreferencesMenuItem); + SettingsMenu->AppendSeparator(); + SettingsMenu->Append (PreferencesMenuItem); + + LowStaticBoxSizer->Detach (HigherButtonSizer); + VolumeStaticBoxSizer->Detach (VolumeGridBagSizer); + VolumeStaticBoxSizer->Add (VolumeGridBagSizer, 1, wxEXPAND, 0); + + ExitButton->SetLabel (_("Close")); + MountAllDevicesButton->SetLabel (_("Mount All Devices")); +#endif + +#ifdef TC_WINDOWS + SlotListCtrl->InsertColumn (ColumnSlot, LangString["DRIVE"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (75); +#else + SlotListCtrl->InsertColumn (ColumnSlot, _("Slot"), wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (82); +#endif + + SlotListCtrl->InsertColumn (ColumnPath, LangString["VOLUME"], wxLIST_FORMAT_LEFT, 1); +#ifdef TC_WINDOWS + colPermilles.push_back (487); +#else + colPermilles.push_back (429); +#endif + + SlotListCtrl->InsertColumn (ColumnSize, LangString["SIZE"], wxLIST_FORMAT_RIGHT, 1); +#ifdef TC_WINDOWS + colPermilles.push_back (126); +#else + colPermilles.push_back (130); +#endif + +#ifdef TC_WINDOWS + SlotListCtrl->InsertColumn (ColumnEA, LangString["ENCRYPTION_ALGORITHM_LV"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (233); +#else + SlotListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (259); +#endif + + SlotListCtrl->InsertColumn (ColumnType, LangString["TYPE"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (100); + + wxImageList *imageList = new wxImageList (16, 12, true); + imageList->Add (Resources::GetDriveIconBitmap(), Resources::GetDriveIconMaskBitmap()); + SlotListCtrl->AssignImageList (imageList, wxIMAGE_LIST_SMALL); + + SetMinSize (wxSize (-1, -1)); + + size_t slotListRowCount = 12; + +#ifndef TC_WINDOWS + int screenHeight = wxSystemSettings::GetMetric (wxSYS_SCREEN_Y); + + if (screenHeight < 480) + slotListRowCount = 1; + else if (screenHeight <= 600) + slotListRowCount = slotListRowCount * screenHeight / 1000; +#endif + + Gui->SetListCtrlHeight (SlotListCtrl, slotListRowCount); + +#ifdef __WXGTK__ + wxSize size (-1, (int) ((double) Gui->GetCharHeight (this) * 1.53)); + CreateVolumeButton->SetMinSize (size); + VolumePropertiesButton->SetMinSize (size); + WipeCacheButton->SetMinSize (size); + VolumePathComboBox->SetMinSize (size); + SelectFileButton->SetMinSize (size); + SelectDeviceButton->SetMinSize (size); + VolumeToolsButton->SetMinSize (size); + size = wxSize (-1, 38); + VolumeButton->SetMinSize (size); +#endif + Fit(); + Layout(); + Center(); + + VolumePathComboBox->SetMinSize (VolumePathComboBox->GetSize()); + VolumePathComboBox->SetMaxSize (VolumePathComboBox->GetSize()); + + SetMinSize (GetSize()); + SetMaxSize (GetSize()); + + Gui->SetListCtrlColumnWidths (SlotListCtrl, colPermilles); + + UpdateVolumeList(); + UpdateWipeCacheButton(); + } + + void MainFrame::InitEvents () + { + Core->VolumeMountedEvent.Connect (EventConnector (this, &MainFrame::OnVolumeMounted)); + Core->VolumeDismountedEvent.Connect (EventConnector (this, &MainFrame::OnVolumeDismounted)); + Gui->OpenVolumeSystemRequestEvent.Connect (EventConnector (this, &MainFrame::OnOpenVolumeSystemRequestEvent)); + Gui->PreferencesUpdatedEvent.Connect (EventConnector (this, &MainFrame::OnPreferencesUpdated)); + + // Drag & drop + class FileDropTarget : public wxFileDropTarget + { + public: + FileDropTarget (MainFrame *frame) : Frame (frame) { } + + wxDragResult OnDragOver (wxCoord x, wxCoord y, wxDragResult def) + { + wxPoint p; + wxWindow *w = wxFindWindowAtPointer (p); + if (w == Frame || wxGetTopLevelParent (w) == Frame) + return wxDragLink; + return wxDragNone; + } + + bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString &filenames) + { + if (!filenames.empty()) + Frame->SetVolumePath (wstring (filenames.front())); + return true; + } + + MainFrame *Frame; + }; + + SetDropTarget (new FileDropTarget (this)); +#ifdef TC_MACOSX + foreach (wxWindow *c, MainPanel->GetChildren()) + c->SetDropTarget (new FileDropTarget (this)); +#endif + + // Volume history + VolumeHistory::ConnectComboBox (VolumePathComboBox); + +#ifdef TC_WINDOWS + // Hotkeys + Hotkey::RegisterList (this, GetPreferences().Hotkeys); + Connect (wxEVT_HOTKEY, wxKeyEventHandler (MainFrame::OnHotkey)); +#endif + + // Timer + class Timer : public wxTimer + { + public: + Timer (MainFrame *frame) : Frame (frame) { } + + void Notify() + { + Frame->OnTimer(); + } + + MainFrame *Frame; + }; + + mTimer.reset (dynamic_cast (new Timer (this))); + mTimer->Start (2000); + } + +#ifdef TC_WINDOWS +#include + static WNDPROC MainFrameWndProc; + static LRESULT CALLBACK MainFrameWndProcFilter (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + { + if (message == WM_DEVICECHANGE && !Core->IsDeviceChangeInProgress()) + { + MainFrame *frame = dynamic_cast (Gui->GetMainFrame()); + PDEV_BROADCAST_HDR hdr = (PDEV_BROADCAST_HDR) lParam; + + if (wParam == DBT_DEVICEREMOVECOMPLETE && hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) + { + PDEV_BROADCAST_VOLUME vol = (PDEV_BROADCAST_VOLUME) lParam; + for (wchar_t driveNo = 0; driveNo < 26; ++driveNo) + { + if (vol->dbcv_unitmask & (1 << driveNo)) + frame->OnDeviceChange (wstring (StringFormatter (L"{0}:\\", wchar_t (L'A' + driveNo)))); + } + } + else + { + frame->OnDeviceChange (); + } + } + + return CallWindowProc (MainFrameWndProc, hwnd, message, wParam, lParam); + } +#endif + + void MainFrame::InitMessageFilter () + { +#ifdef TC_WINDOWS + HWND mainFrameHwnd = static_cast (GetHandle()); + MainFrameWndProc = (WNDPROC) GetWindowLongPtr (mainFrameHwnd, GWL_WNDPROC); + SetWindowLongPtr (mainFrameHwnd, GWL_WNDPROC, (LONG_PTR) MainFrameWndProcFilter); +#endif + } + + void MainFrame::InitPreferences () + { + try + { + LoadPreferences(); + + VolumeSlotNumber lastSelectedSlotNumber = GetPreferences().LastSelectedSlotNumber; + if (Core->IsSlotNumberValid (lastSelectedSlotNumber)) + { + long slotIndex = SlotNumberToItemIndex (lastSelectedSlotNumber); + if (slotIndex >= 0) + { + SlotListCtrl->SetItemState (slotIndex, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + SlotListCtrl->EnsureVisible (slotIndex); + } + } + + LoadFavoriteVolumes(); + VolumeHistory::Load(); + } + catch (exception &e) + { + Gui->ShowError (e); + Gui->ShowError (_("Error while loading configuration files located in ") + wstring (Application::GetConfigFilePath (L""))); + } + } + + void MainFrame::InitTaskBarIcon () + { + class TaskBarIcon : public wxTaskBarIcon + { + public: + TaskBarIcon (MainFrame *frame) : Busy (false), Frame (frame) + { + Connect (wxEVT_TASKBAR_LEFT_DOWN, wxTaskBarIconEventHandler (TaskBarIcon::OnLeftButtonDown)); + } + + wxMenu *CreatePopupMenu () + { + auto_ptr popup (new wxMenu); + + Gui->AppendToMenu (*popup, LangString[Gui->IsInBackgroundMode() ? "SHOW_TC" : "HIDE_TC"], this, wxCommandEventHandler (TaskBarIcon::OnShowHideMenuItemSelected)); + + popup->AppendSeparator(); + Gui->AppendToMenu (*popup, _("Mount All Favorite Volumes"), this, wxCommandEventHandler (TaskBarIcon::OnMountAllFavoritesMenuItemSelected))->Enable (!Busy); + Gui->AppendToMenu (*popup, _("Dismount All Mounted Volumes"), this, wxCommandEventHandler (TaskBarIcon::OnDismountAllMenuItemSelected))->Enable (!Busy); + + // Favorite volumes + if (Gui->GetPreferences().BackgroundTaskMenuMountItemsEnabled && !Frame->FavoriteVolumesMenuMap.empty()) + { + popup->AppendSeparator(); + typedef pair FavMapPair; + foreach (FavMapPair fp, Frame->FavoriteVolumesMenuMap) + { + Gui->AppendToMenu (*popup, LangString["MOUNT"] + L" " + wstring (fp.second.Path) + (fp.second.MountPoint.IsEmpty() ? L"" : L" " + wstring (fp.second.MountPoint)), + this, wxCommandEventHandler (TaskBarIcon::OnFavoriteVolumeMenuItemSelected), fp.first)->Enable (!Busy); + } + } + + // Mounted volumes + VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); + if (!mountedVolumes.empty()) + { + if (Gui->GetPreferences().BackgroundTaskMenuOpenItemsEnabled) + { + popup->AppendSeparator(); + OpenMap.clear(); + foreach (shared_ptr volume, mountedVolumes) + { + if (!volume->MountPoint.IsEmpty()) + { + wxString label = LangString["OPEN"] + L" " + wstring (volume->MountPoint) + L" (" + wstring (volume->Path) + L")"; + wxMenuItem *item = Gui->AppendToMenu (*popup, label, this, wxCommandEventHandler (TaskBarIcon::OnOpenMenuItemSelected)); + OpenMap[item->GetId()] = volume; + } + } + } + + if (Gui->GetPreferences().BackgroundTaskMenuDismountItemsEnabled) + { + popup->AppendSeparator(); + DismountMap.clear(); + foreach (shared_ptr volume, mountedVolumes) + { + wxString label = LangString["DISMOUNT"] + L" "; + + if (!volume->MountPoint.IsEmpty()) + label += wstring (volume->MountPoint) + L" (" + wstring (volume->Path) + L")"; + else + label += wstring (volume->Path); + + wxMenuItem *item = Gui->AppendToMenu (*popup, label, this, wxCommandEventHandler (TaskBarIcon::OnDismountMenuItemSelected)); + item->Enable (!Busy); + DismountMap[item->GetId()] = volume; + } + } + } + + popup->AppendSeparator(); + Gui->AppendToMenu (*popup, _("Preferences..."), this, wxCommandEventHandler (TaskBarIcon::OnPreferencesMenuItemSelected))->Enable (!Busy); +#ifndef TC_MACOSX + popup->AppendSeparator(); + Gui->AppendToMenu (*popup, _("Exit"), this, wxCommandEventHandler (TaskBarIcon::OnExitMenuItemSelected))->Enable (!Busy && Frame->CanExit()); +#endif + return popup.release(); + } + + void OnDismountAllMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnDismountAllButtonClick (event); Busy = false; } + void OnDismountMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->DismountVolume (DismountMap[event.GetId()]); Busy = false; } + void OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnFavoriteVolumeMenuItemSelected (event); Busy = false; } + void OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->MountAllFavorites (); Busy = false; } + + void OnExitMenuItemSelected (wxCommandEvent& event) + { + Busy = true; + if (Core->GetMountedVolumes().empty() || Gui->AskYesNo (LangString ["CONFIRM_EXIT"], false, true)) + Frame->Close (true); + Busy = false; + } + + void OnLeftButtonDown (wxTaskBarIconEvent& event) { Gui->SetBackgroundMode (false); } + void OnOpenMenuItemSelected (wxCommandEvent& event) { Gui->OpenExplorerWindow (OpenMap[event.GetId()]->MountPoint); } + void OnPreferencesMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnPreferencesMenuItemSelected (event); Busy = false; } + void OnShowHideMenuItemSelected (wxCommandEvent& event) { Gui->SetBackgroundMode (!Gui->IsInBackgroundMode()); } + + bool Busy; + map < int, shared_ptr > DismountMap; + MainFrame *Frame; + map < int, shared_ptr > OpenMap; + }; + + mTaskBarIcon.reset (new TaskBarIcon (this)); + ShowTaskBarIcon (GetPreferences().BackgroundTaskEnabled); + } + + void MainFrame::LoadFavoriteVolumes () + { + typedef pair FavMapPair; + foreach (FavMapPair p, FavoriteVolumesMenuMap) + { + FavoritesMenu->Delete (p.first); + } + FavoriteVolumesMenuMap.clear(); + + foreach_ref (const FavoriteVolume &favorite, FavoriteVolume::LoadList()) + { + wstring label = wstring (favorite.Path); + if (!favorite.MountPoint.IsEmpty()) + label += wstring (L" ") + wstring (favorite.MountPoint); + + wxMenuItem *item = Gui->AppendToMenu (*FavoritesMenu, label, this, wxCommandEventHandler (MainFrame::OnFavoriteVolumeMenuItemSelected)); + FavoriteVolumesMenuMap[item->GetId()] = favorite; + } + } + + void MainFrame::LoadPreferences () + { + UserPreferences prefs; + prefs.Load(); + Gui->SetPreferences (prefs); + NoHistoryCheckBox->SetValue (!prefs.SaveHistory); + } + + void MainFrame::MountAllDevices () + { + try + { + MountOptions mountOptions (GetPreferences().DefaultMountOptions); + + if (SlotListCtrl->GetSelectedItemCount() == 1) + mountOptions.SlotNumber = SelectedSlotNumber; + + Gui->MountAllDeviceHostedVolumes (mountOptions); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::MountAllFavorites () + { + try + { + MountOptions mountOptions (GetPreferences().DefaultMountOptions); + Gui->MountAllFavoriteVolumes (mountOptions); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::MountVolume () + { + if (!IsFreeSlotSelected()) + { + Gui->ShowWarning (_("Please select a free drive slot from the list.")); + return; + } + + if (!CheckVolumePathNotEmpty()) + return; + + MountOptions mountOptions (GetPreferences().DefaultMountOptions); + mountOptions.SlotNumber = SelectedSlotNumber; + mountOptions.Path = GetSelectedVolumePath(); + + try + { + if (Gui->MountVolume (mountOptions) && GetPreferences().SaveHistory) + VolumeHistory::Add (*mountOptions.Path); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnAboutMenuItemSelected (wxCommandEvent& event) + { + AboutDialog dialog (this); + dialog.ShowModal(); + } + + void MainFrame::OnActivate (wxActivateEvent& event) + { + Gui->SetActiveFrame (this); + +#ifdef TC_MACOSX + if (event.GetActive() && Gui->IsInBackgroundMode()) + Gui->SetBackgroundMode (false); +#endif + event.Skip(); + } + + void MainFrame::OnAddAllMountedToFavoritesMenuItemSelected (wxCommandEvent& event) + { + AddToFavorites (MountedVolumes); + } + + void MainFrame::OnAddToFavoritesMenuItemSelected (wxCommandEvent& event) + { + shared_ptr selectedVolume = GetSelectedVolume(); + if (selectedVolume) + { + VolumeInfoList volumes; + volumes.push_back (selectedVolume); + AddToFavorites (volumes); + } + } + + void MainFrame::OnBackupVolumeHeadersMenuItemSelected (wxCommandEvent& event) + { + if (!CheckVolumePathNotEmpty ()) + return; + + try + { + Gui->BackupVolumeHeaders (GetSelectedVolumePath()); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnClearSlotSelectionMenuItemSelected (wxCommandEvent& event) + { + Gui->ClearListCtrlSelection (SlotListCtrl); + UpdateControls(); + } + + void MainFrame::OnClose (wxCloseEvent& event) + { + if (GetPreferences().WipeCacheOnClose) + Core->WipePasswordCache(); + +#ifdef TC_MACOSX + if (!event.CanVeto() && GetPreferences().DismountOnLogOff) + { + try + { + Gui->DismountVolumes (Core->GetMountedVolumes(), GetPreferences().ForceAutoDismount, false); + } + catch (...) { } + } +#endif + + if (!Gui->IsTheOnlyTopLevelWindow (this)) + { + // Bring first frame to foreground + wxFrame *frame = nullptr; + foreach (wxWindow *window, wxTopLevelWindows) + { + if (window != this + && dynamic_cast (window) + && StringConverter::GetTypeName (typeid (*window)).find ("wxTaskBarIcon") == string::npos) + { + frame = dynamic_cast (window); + if (window->IsShown()) + break; + } + } + + if (frame) + { + frame->Show(); + if (frame->IsIconized()) + frame->Iconize(false); + frame->Raise(); + } + } + else if (event.CanVeto() && GetPreferences().BackgroundTaskEnabled + && (!GetPreferences().CloseBackgroundTaskOnNoVolumes || !MountedVolumes.empty())) + { + // Enter background mode + if (!Gui->IsInBackgroundMode()) + Gui->SetBackgroundMode (true); + } + else + { +#ifdef __WXGTK__ + Show(); +#endif + SavePreferences(); + + Destroy(); + } + + // Cancel close - veto is not used to prevent aborting log off procedure on Windows + return; + } + + void MainFrame::OnCloseAllSecurityTokenSessionsMenuItemSelected (wxCommandEvent& event) + { + try + { + { + wxBusyCursor busy; + SecurityToken::CloseAllSessions(); + } + Gui->ShowInfo ("ALL_TOKEN_SESSIONS_CLOSED"); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnCreateVolumeButtonClick (wxCommandEvent& event) + { + try + { + (new VolumeCreationWizard (nullptr))->Show(); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnDefaultKeyfilesMenuItemSelected (wxCommandEvent& event) + { + PreferencesDialog dialog (this); + dialog.SelectPage (dialog.DefaultKeyfilesPage); + dialog.ShowModal(); + } + + void MainFrame::OnDeviceChange (const DirectoryPath &mountPoint) + { + // Check if any host device has been removed and force dismount of volumes accordingly + VolumeInfoList removedVolumes; + foreach (shared_ptr volume, Core->GetMountedVolumes()) + { + // File-hosted volumes + if (!volume->Path.IsDevice() && !mountPoint.IsEmpty()) + { + if (wxString (volume->Path).Upper().StartsWith (wstring (mountPoint).c_str())) + { + removedVolumes.push_back (volume); + continue; + } + } + + // Device-hosted volumes + if (volume->Path.IsDevice() && !Core->IsDevicePresent (volume->Path)) + removedVolumes.push_back (volume); + } + + if (!removedVolumes.empty()) + Gui->AutoDismountVolumes (removedVolumes, true); + } + + void MainFrame::OnDismountAllButtonClick (wxCommandEvent& event) + { + Gui->DismountAllVolumes(); + } + + void MainFrame::OnEncryptionTestMenuItemSelected (wxCommandEvent& event) + { + EncryptionTestDialog dialog (this); + dialog.ShowModal(); + } + + void MainFrame::OnExitButtonClick (wxCommandEvent& event) + { + Close(); + } + + void MainFrame::OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event) + { + FavoriteVolume favorite = FavoriteVolumesMenuMap[event.GetId()]; + if (!favorite.Path.IsEmpty()) + { + SetVolumePath (favorite.Path); + + MountOptions mountOptions (GetPreferences().DefaultMountOptions); + favorite.ToMountOptions (mountOptions); + + shared_ptr volume = Gui->MountVolume (mountOptions); + if (volume) + SlotListCtrl->EnsureVisible (SlotNumberToItemIndex (volume->SlotNumber)); + } + } + + void MainFrame::OnHiddenVolumeProtectionTriggered (shared_ptr protectedVolume) + { + Gui->ShowWarningTopMost (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (protectedVolume->Path))); + } + + void MainFrame::OnHotkey (wxKeyEvent& event) + { +#ifdef TC_WINDOWS + switch (event.GetId()) + { + case Hotkey::Id::CloseAllSecurityTokenSessions: + try + { + SecurityToken::CloseAllSessions(); + Gui->ShowInfo ("ALL_TOKEN_SESSIONS_CLOSED"); + } + catch (exception &e) { Gui->ShowError (e); } + break; + + case Hotkey::Id::DismountAll: + case Hotkey::Id::DismountAllWipeCache: + { + if (event.GetId() == Hotkey::Id::DismountAllWipeCache) + WipeCache(); + + size_t mountedCount = Core->GetMountedVolumes().size(); + Gui->DismountAllVolumes(); + size_t newMountedCount = Core->GetMountedVolumes().size(); + + if (newMountedCount < mountedCount) + { + if (newMountedCount == 0 && GetPreferences().DisplayMessageAfterHotkeyDismount) + Gui->ShowInfo ("MOUNTED_VOLUMES_DISMOUNTED"); + else if (GetPreferences().BeepAfterHotkeyMountDismount) + MessageBeep((UINT) -1); + } + } + break; + + case Hotkey::Id::ForceDismountAllWipeCache: + case Hotkey::Id::ForceDismountAllWipeCacheExit: + { + bool mounted = !Core->GetMountedVolumes().empty(); + + WipeCache(); + Gui->DismountAllVolumes (true, true); + + if (mounted && GetPreferences().DisplayMessageAfterHotkeyDismount) + Gui->ShowInfo ("VOLUMES_DISMOUNTED_CACHE_WIPED"); + else if (mounted && GetPreferences().BeepAfterHotkeyMountDismount) + MessageBeep((UINT) -1); + + if (event.GetId() == Hotkey::Id::ForceDismountAllWipeCacheExit) + Close (true); + } + break; + + case Hotkey::Id::MountAllDevices: + case Hotkey::Id::MountAllFavorites: + { + size_t mountedCount = Core->GetMountedVolumes().size(); + + if (event.GetId() == Hotkey::Id::MountAllDevices) + MountAllDevices(); + else + MountAllFavorites(); + + if (Core->GetMountedVolumes().size() > mountedCount && GetPreferences().BeepAfterHotkeyMountDismount) + MessageBeep((UINT) -1); + } + break; + + case Hotkey::Id::ShowHideApplication: + Gui->SetBackgroundMode (!Gui->IsInBackgroundMode()); + break; + + case Hotkey::Id::WipeCache: + WipeCache(); + Gui->ShowInfo ("PASSWORD_CACHE_WIPED"); + break; + + default: + assert (false); + break; + } +#endif // TC_WINDOWS + } + + void MainFrame::OnHotkeysMenuItemSelected (wxCommandEvent& event) + { + PreferencesDialog dialog (this); + dialog.SelectPage (dialog.HotkeysPage); + dialog.ShowModal(); + } + + void MainFrame::OnLegalNoticesMenuItemSelected (wxCommandEvent& event) + { + LegalNoticesDialog dialog (this); + dialog.ShowModal(); + } + + void MainFrame::OnListChanged () + { + OnListItemSelectionChanged(); + UpdateControls(); + } + + void MainFrame::OnListItemActivated (wxListEvent& event) + { + if (IsMountedSlotSelected()) + OpenSelectedVolume(); + else + MountVolume(); + } + + void MainFrame::OnListItemDeleted (long itemIndex) + { + if (SelectedItemIndex > itemIndex) + --SelectedItemIndex; + } + + void MainFrame::OnListItemDeselected (wxListEvent& event) + { + OnListItemSelectionChanged(); + } + + void MainFrame::OnListItemInserted (long itemIndex) + { + if (SelectedItemIndex >= itemIndex) + ++SelectedItemIndex; + } + + void MainFrame::OnListItemRightClick (wxListEvent& event) + { +#ifdef TC_MACOSX + if (SelectedItemIndex != event.GetIndex()) + { + SelectedItemIndex = event.GetIndex(); + OnListItemSelectionChanged(); + } +#endif + wxMenu popup; + if (IsMountedSlotSelected()) + { + Gui->AppendToMenu (popup, LangString["DISMOUNT"], this, wxCommandEventHandler (MainFrame::OnDismountVolumeMenuItemSelected)); + Gui->AppendToMenu (popup, LangString["OPEN"], this, wxCommandEventHandler (MainFrame::OnOpenVolumeMenuItemSelected)); + Gui->AppendToMenu (popup, _("Deselect"), this, wxCommandEventHandler (MainFrame::OnClearSlotSelectionMenuItemSelected)); + + popup.AppendSeparator(); + Gui->AppendToMenu (popup, _("Add to Favorites..."), this, wxCommandEventHandler (MainFrame::OnAddToFavoritesMenuItemSelected)); + + popup.AppendSeparator(); + Gui->AppendToMenu (popup, LangString["IDPM_CHECK_FILESYS"], this, wxCommandEventHandler (MainFrame::OnCheckFilesystemMenuItemSelected)); + Gui->AppendToMenu (popup, LangString["IDPM_REPAIR_FILESYS"], this, wxCommandEventHandler (MainFrame::OnRepairFilesystemMenuItemSelected)); + + popup.AppendSeparator(); + Gui->AppendToMenu (popup, LangString["IDPM_PROPERTIES"], this, wxCommandEventHandler (MainFrame::OnVolumePropertiesButtonClick)); + + PopupMenu (&popup); + } + else if (IsFreeSlotSelected()) + { + Gui->AppendToMenu (popup, _("Mount Volume"), this, wxCommandEventHandler (MainFrame::OnMountVolumeMenuItemSelected)); + + popup.AppendSeparator(); + + Gui->AppendToMenu (popup, LangString["SELECT_FILE_AND_MOUNT"], this, wxCommandEventHandler (MainFrame::OnSelectFileAndMountMenuItemSelected)); + Gui->AppendToMenu (popup, LangString["SELECT_DEVICE_AND_MOUNT"], this, wxCommandEventHandler (MainFrame::OnSelectDeviceAndMountMenuItemSelected)); + + popup.AppendSeparator(); + + Gui->AppendToMenu (popup, _("Deselect"), this, wxCommandEventHandler (MainFrame::OnClearSlotSelectionMenuItemSelected)); + + PopupMenu (&popup); + } + + event.Skip(); + } + + void MainFrame::OnListItemSelected (wxListEvent& event) + { + SelectedItemIndex = event.GetIndex(); + OnListItemSelectionChanged(); + } + + void MainFrame::OnListItemSelectionChanged () + { + if (SlotListCtrl->GetSelectedItemCount() < 1) + SelectedItemIndex = -1; + + if (SelectedItemIndex >= 0) + SelectedSlotNumber = (VolumeSlotNumber) SlotListCtrl->GetItemData (SelectedItemIndex); + else + SelectedSlotNumber = 0; + + UpdateControls(); + } + + void MainFrame::OnManageSecurityTokenKeyfilesMenuItemSelected (wxCommandEvent& event) + { + try + { + SecurityTokenKeyfilesDialog dialog (this, false); + dialog.ShowModal(); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnMountAllDevicesButtonClick (wxCommandEvent& event) + { + MountAllDevices(); + } + + void MainFrame::OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event) + { + MountAllFavorites(); + } + + void MainFrame::OnNoHistoryCheckBoxClick (wxCommandEvent& event) + { + UserPreferences prefs = GetPreferences(); + prefs.SaveHistory = !event.IsChecked(); + Gui->SetPreferences (prefs); + + if (event.IsChecked()) + { + try + { + VolumeHistory::Clear(); + } + catch (exception &e) { Gui->ShowError (e); } + } + } + + void MainFrame::OnOrganizeFavoritesMenuItemSelected (wxCommandEvent& event) + { + try + { + OrganizeFavorites (FavoriteVolume::LoadList()); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnPreferencesMenuItemSelected (wxCommandEvent& event) + { + PreferencesDialog dialog (this); + dialog.ShowModal(); + } + + void MainFrame::OnPreferencesUpdated (EventArgs &args) + { + const UserPreferences &prefs = GetPreferences(); + + NoHistoryCheckBox->SetValue (!prefs.SaveHistory); + + ShowTaskBarIcon (prefs.BackgroundTaskEnabled); + if (Gui->IsInBackgroundMode() && !prefs.BackgroundTaskEnabled) + Close (true); + + SavePreferences(); + } + + void MainFrame::OnRestoreVolumeHeaderMenuItemSelected (wxCommandEvent& event) + { + if (!CheckVolumePathNotEmpty ()) + return; + + try + { + Gui->RestoreVolumeHeaders (GetSelectedVolumePath()); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnSecurityTokenPreferencesMenuItemSelected (wxCommandEvent& event) + { + PreferencesDialog dialog (this); + dialog.SelectPage (dialog.SecurityTokensPage); + dialog.ShowModal(); + } + + + void MainFrame::OnSelectDeviceAndMountMenuItemSelected (wxCommandEvent& event) + { + DevicePath path = Gui->SelectDevice (this); + + if (!path.IsEmpty()) + { + SetVolumePath (path); + OnMountVolumeMenuItemSelected (event); + } + } + + void MainFrame::OnSelectDeviceButtonClick (wxCommandEvent& event) + { + DevicePath path = Gui->SelectDevice (this); + + if (!path.IsEmpty()) + SetVolumePath (path); + } + + void MainFrame::OnSelectFileAndMountMenuItemSelected (wxCommandEvent& event) + { + FilePath path = Gui->SelectVolumeFile (this); + + if (!path.IsEmpty()) + { + SetVolumePath (path); + OnMountVolumeMenuItemSelected (event); + } + } + + void MainFrame::OnSelectFileButtonClick (wxCommandEvent& event) + { + FilePath path = Gui->SelectVolumeFile (this); + if (!path.IsEmpty()) + SetVolumePath (path); + } + + void MainFrame::OnTimer () + { + try + { + UpdateVolumeList(); + UpdateWipeCacheButton(); + + if (GetPreferences().BackgroundTaskEnabled) + { + // Inactivity auto-dismount + if (GetPreferences().DismountOnInactivity) + { + VolumeInfoList inactiveVolumes; + wxLongLong currentTime = wxGetLocalTimeMillis().GetValue(); + + map newActivityTimeMap; + + foreach (shared_ptr volume, MountedVolumes) + { + if (VolumeActivityMap.find (volume->Path) != VolumeActivityMap.end() + && VolumeActivityMap[volume->Path].SerialInstanceNumber == volume->SerialInstanceNumber) + { + VolumeActivityMapEntry ae = VolumeActivityMap[volume->Path]; + + if (volume->TotalDataRead != ae.TotalDataRead || volume->TotalDataWritten != ae.TotalDataWritten) + { + ae.LastActivityTime = currentTime; + ae.TotalDataRead = volume->TotalDataRead; + ae.TotalDataWritten = volume->TotalDataWritten; + } + else if ((currentTime - ae.LastActivityTime) > GetPreferences().MaxVolumeIdleTime * 1000LL * 60) + { + inactiveVolumes.push_back (volume); + } + + newActivityTimeMap[volume->Path] = ae; + } + else + { + newActivityTimeMap[volume->Path] = VolumeActivityMapEntry (*volume, currentTime); + } + } + + VolumeActivityMap = newActivityTimeMap; + + if (!inactiveVolumes.empty()) + Gui->AutoDismountVolumes (inactiveVolumes); + } + + // Screen saver auto-dismount + if (GetPreferences().DismountOnScreenSaver) + { +#ifdef TC_WINDOWS + bool running; + if (SystemParametersInfo (SPI_GETSCREENSAVERRUNNING, 0, &running, 0) != 0) + { + static bool previousState = false; + if (running && !previousState) + { + previousState = true; + Gui->OnAutoDismountAllEvent(); + } + else + { + previousState = running; + } + } +#endif + } + } + + if (Gui->IsInBackgroundMode()) + { + if (!GetPreferences().BackgroundTaskEnabled) + { + Close (true); + } + else if (MountedVolumes.empty() && (GetPreferences().CloseBackgroundTaskOnNoVolumes || Core->IsInPortableMode())) + { + Close (true); + } + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void MainFrame::OnVolumeButtonClick (wxCommandEvent& event) + { + if (IsMountedSlotSelected()) + DismountVolume(); + else + MountVolume(); + } + + void MainFrame::OnVolumePropertiesButtonClick (wxCommandEvent& event) + { + shared_ptr selectedVolume = GetSelectedVolume(); + if (selectedVolume) + { + VolumePropertiesDialog dialog (this, *selectedVolume); + dialog.ShowModal(); + } + } + + void MainFrame::OnVolumeToolsButtonClick (wxCommandEvent& event) + { + if (!CheckVolumePathNotEmpty()) + return; + + wxMenu popup; + + Gui->AppendToMenu (popup, _("Change Volume Password..."), this, wxCommandEventHandler (MainFrame::OnChangePasswordMenuItemSelected)); + + popup.AppendSeparator (); + + Gui->AppendToMenu (popup, _("Add/Remove Keyfiles to/from Volume..."), this, wxCommandEventHandler (MainFrame::OnChangeKeyfilesMenuItemSelected)); + Gui->AppendToMenu (popup, _("Remove All Keyfiles from Volume..."), this, wxCommandEventHandler (MainFrame::OnRemoveKeyfilesMenuItemSelected)); + + popup.AppendSeparator (); + + Gui->AppendToMenu (popup, _("Change Header Key Derivation Algorithm..."), this, wxCommandEventHandler (MainFrame::OnChangePkcs5PrfMenuItemSelected)); + + popup.AppendSeparator (); + + Gui->AppendToMenu (popup, _("Backup Volume Header..."), this, wxCommandEventHandler (MainFrame::OnBackupVolumeHeadersMenuItemSelected)); + Gui->AppendToMenu (popup, _("Restore Volume Header..."), this, wxCommandEventHandler (MainFrame::OnRestoreVolumeHeaderMenuItemSelected)); + + PopupMenu (&popup, VolumeToolsButton->GetPosition().x + 2, VolumeToolsButton->GetPosition().y + 2); + } + + void MainFrame::OnWipeCacheButtonClick (wxCommandEvent& event) + { + WipeCache(); + Gui->ShowInfo ("PASSWORD_CACHE_WIPED"); + } + + void MainFrame::OpenSelectedVolume () const + { + shared_ptr selectedVolume = GetSelectedVolume(); + if (selectedVolume) + { + try + { + wxBusyCursor busy; + Gui->OpenExplorerWindow (selectedVolume->MountPoint); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + } + + void MainFrame::OrganizeFavorites (const FavoriteVolumeList &favorites, size_t newItemCount) + { + FavoriteVolumesDialog dialog (this, favorites, newItemCount); + + if (dialog.ShowModal() == wxID_OK) + { + FavoriteVolume::SaveList (dialog.GetFavorites()); + LoadFavoriteVolumes(); + } + } + + void MainFrame::SavePreferences () const + { + try + { + UserPreferences prefs = GetPreferences(); + prefs.LastSelectedSlotNumber = SelectedSlotNumber; + prefs.Save(); + + VolumeHistory::Save(); + } + catch (exception &e) + { + if (!Core->IsInPortableMode()) + Gui->ShowError (e); + } + } + + void MainFrame::ShowTaskBarIcon (bool show) + { + if (!show && mTaskBarIcon->IsIconInstalled()) + { + mTaskBarIcon->RemoveIcon(); + } + else if (show && !mTaskBarIcon->IsIconInstalled()) + { +#ifndef TC_MACOSX + mTaskBarIcon->SetIcon (Resources::GetTrueCryptIcon(), L"TrueCrypt"); +#endif + } + } + + long MainFrame::SlotNumberToItemIndex (uint32 slotNumber) const + { + for (long itemIndex = 0; itemIndex < SlotListCtrl->GetItemCount(); itemIndex++) + { + wxListItem item; + item.SetId (itemIndex); + if (slotNumber == (uint32) SlotListCtrl->GetItemData (item)) + return itemIndex; + } + return -1; + } + + void MainFrame::UpdateControls () + { + bool mounted = IsMountedSlotSelected(); + + VolumeButton->SetLabel (mounted ? LangString["DISMOUNT"] : wxString (_("Mount"))); + VolumePropertiesButton->Enable (mounted); + + DismountVolumeMenuItem->Enable (mounted); + MountVolumeMenuItem->Enable (!mounted); + VolumePropertiesMenuItem->Enable (mounted); + AddToFavoritesMenuItem->Enable (mounted); + AddAllMountedToFavoritesMenuItem->Enable (!MountedVolumes.empty()); + UpdateWipeCacheButton(); + } + + void MainFrame::UpdateVolumeList () + { + static Mutex mutex; + ScopeLock lock (mutex); + + bool listChanged = false; + + MountedVolumes = Core->GetMountedVolumes(); + + map < VolumeSlotNumber, shared_ptr > mountedVolumesMap; + foreach (shared_ptr volume, MountedVolumes) + { + mountedVolumesMap[volume->SlotNumber] = volume; + } + + VolumeInfoList protectionTriggeredVolumes; + + // Update list + long prevItemIndex = -1; + for (VolumeSlotNumber slotNumber = Core->GetFirstSlotNumber(); slotNumber <= Core->GetLastSlotNumber(); ++slotNumber) + { + long itemIndex = SlotNumberToItemIndex (slotNumber); + vector fields (SlotListCtrl->GetColumnCount()); + + if (mountedVolumesMap.find (slotNumber) != mountedVolumesMap.end()) + { + shared_ptr volume = mountedVolumesMap[slotNumber]; + +#ifdef TC_WINDOWS + fields[ColumnSlot] = volume->MountPoint; + fields[ColumnEA] = volume->EncryptionAlgorithmName; +#else + fields[ColumnSlot] = StringConverter::FromNumber (slotNumber); + fields[ColumnMountPoint] = volume->MountPoint; +#endif + fields[ColumnPath] = volume->Path; + fields[ColumnSize] = Gui->SizeToString (volume->Size); + fields[ColumnType] = Gui->VolumeTypeToString (volume->Type, volume->Protection); + + if (volume->HiddenVolumeProtectionTriggered) + { + fields[ColumnType] += L"(!)"; + } + + bool slotUpdated = false; + if (itemIndex == -1) + { + Gui->InsertToListCtrl (SlotListCtrl, ++prevItemIndex, fields, 0, (void *) volume->SlotNumber); + OnListItemInserted (prevItemIndex); + + listChanged |= true; + slotUpdated = true; + } + else + { + if (Gui->UpdateListCtrlItem (SlotListCtrl, itemIndex, fields)) + { + listChanged = true; + slotUpdated = true; + } + prevItemIndex = itemIndex; + } + + if (slotUpdated && volume->HiddenVolumeProtectionTriggered) + protectionTriggeredVolumes.push_back (volume); + } + else + { +#ifdef TC_WINDOWS + fields[ColumnSlot] = Core->SlotNumberToMountPoint (slotNumber); +#else + fields[ColumnSlot] = StringConverter::FromNumber (slotNumber); +#endif + +#ifdef TC_WINDOWS + if (Core->IsMountPointAvailable (fields[ColumnSlot])) +#else + if (true) +#endif + { + if (itemIndex == -1) + { + Gui->InsertToListCtrl (SlotListCtrl, ++prevItemIndex, fields, 0, (void *) slotNumber); + OnListItemInserted (prevItemIndex); + listChanged |= true; + } + else + { + listChanged |= Gui->UpdateListCtrlItem (SlotListCtrl, itemIndex, fields); + prevItemIndex = itemIndex; + } + } + else if (itemIndex != -1) + { + SlotListCtrl->DeleteItem (itemIndex); + OnListItemDeleted (itemIndex); + listChanged = true; + } + } + } + + if (listChanged) + OnListChanged(); + + foreach (shared_ptr volume, protectionTriggeredVolumes) + OnHiddenVolumeProtectionTriggered (volume); + } + + void MainFrame::UpdateWipeCacheButton () + { + bool enabled = WipeCacheButton->IsEnabled(); + bool empty = Core->IsPasswordCacheEmpty(); + + if (empty && enabled) + { + WipeCacheButton->Disable(); + WipeCachedPasswordsMenuItem->Enable (false); + } + else if (!empty && !enabled) + { + WipeCacheButton->Enable(); + WipeCachedPasswordsMenuItem->Enable(); + } + } + + void MainFrame::WipeCache () + { + Core->WipePasswordCache(); + UpdateWipeCacheButton(); + } +} diff --git a/Main/Forms/MainFrame.h b/Main/Forms/MainFrame.h index a4e64db..33a6383 100644 --- a/Main/Forms/MainFrame.h +++ b/Main/Forms/MainFrame.h @@ -1,171 +1,170 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_MainFrame -#define TC_HEADER_Main_Forms_MainFrame - -#include "Forms.h" -#include "ChangePasswordDialog.h" - -namespace TrueCrypt -{ - struct FavoriteVolume; - - class MainFrame : public MainFrameBase - { - public: - MainFrame (wxWindow* parent); - virtual ~MainFrame (); - - void OnDeviceChange (const DirectoryPath &mountPoint = DirectoryPath()); - - protected: - enum - { - ColumnSlot = 0, - ColumnPath, - ColumnSize, -#ifdef TC_WINDOWS - ColumnEA, -#else - ColumnMountPoint, -#endif - ColumnType - }; - - void AddToFavorites (const VolumeInfoList &volumes); - bool CanExit () const; - void ChangePassword (ChangePasswordDialog::Mode::Enum mode = ChangePasswordDialog::Mode::ChangePasswordAndKeyfiles); - void CheckFilesystem (bool repair = false); - bool CheckVolumePathNotEmpty () const; - void DismountVolume (shared_ptr volume = shared_ptr ()); - const UserPreferences &GetPreferences () const { return Gui->GetPreferences(); } - shared_ptr GetSelectedVolume () const; - shared_ptr GetSelectedVolumePath () const { return make_shared (wstring (VolumePathComboBox->GetValue())); } - void InitControls (); - void InitEvents (); - void InitMessageFilter (); - void InitPreferences (); - void InitTaskBarIcon (); - bool IsFreeSlotSelected () const { return SlotListCtrl->GetSelectedItemCount() == 1 && Gui->GetListCtrlSubItemText (SlotListCtrl, SelectedItemIndex, ColumnPath).empty(); } - bool IsMountedSlotSelected () const { return SlotListCtrl->GetSelectedItemCount() == 1 && !Gui->GetListCtrlSubItemText (SlotListCtrl, SelectedItemIndex, ColumnPath).empty(); } - void LoadFavoriteVolumes (); - void LoadPreferences (); - void MountAllDevices (); - void MountAllFavorites (); - void MountVolume (); - void OnAboutMenuItemSelected (wxCommandEvent& event); - void OnActivate (wxActivateEvent& event); - void OnAddAllMountedToFavoritesMenuItemSelected (wxCommandEvent& event); - void OnAddToFavoritesMenuItemSelected (wxCommandEvent& event); - void OnBackupVolumeHeadersMenuItemSelected (wxCommandEvent& event); - void OnBeginnersTutorialMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"tutorial"); } - void OnChangeKeyfilesMenuItemSelected (wxCommandEvent& event) { ChangePassword (ChangePasswordDialog::Mode::ChangeKeyfiles); } - void OnChangePasswordMenuItemSelected (wxCommandEvent& event) { ChangePassword (); } - void OnChangePkcs5PrfMenuItemSelected (wxCommandEvent& event) { ChangePassword (ChangePasswordDialog::Mode::ChangePkcs5Prf); } - void OnCheckFilesystemMenuItemSelected( wxCommandEvent& event ) { CheckFilesystem (); } - void OnClearSlotSelectionMenuItemSelected (wxCommandEvent& event); - void OnClose (wxCloseEvent& event); - void OnCloseAllSecurityTokenSessionsMenuItemSelected (wxCommandEvent& event); - void OnContactMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"contact"); } - void OnCreateKeyfileMenuItemSelected (wxCommandEvent& event) { Gui->CreateKeyfile(); } - void OnCreateVolumeButtonClick (wxCommandEvent& event); - void OnDefaultKeyfilesMenuItemSelected (wxCommandEvent& event); - void OnDismountAllButtonClick (wxCommandEvent& event); - void OnDismountVolumeMenuItemSelected (wxCommandEvent& event) { DismountVolume(); } - void OnDonationsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"donations"); } - void OnDownloadsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"downloads"); } - void OnEncryptionTestMenuItemSelected (wxCommandEvent& event); - void OnExitButtonClick (wxCommandEvent& event); - void OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event); - void OnFaqMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"faq"); } - void OnForumsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"forum"); } - void OnHiddenVolumeProtectionTriggered (shared_ptr protectedVolume); - void OnHotkey (wxKeyEvent& event); - void OnHotkeysMenuItemSelected (wxCommandEvent& event); - void OnLegalNoticesMenuItemSelected (wxCommandEvent& event); - void OnListChanged (); - void OnListItemActivated (wxListEvent& event); - void OnListItemDeleted (long itemIndex); - void OnListItemDeselected (wxListEvent& event); - void OnListItemInserted (long itemIndex); - void OnListItemRightClick (wxListEvent& event); - void OnListItemSelected (wxListEvent& event); - void OnListItemSelectionChanged (); - void OnLogoBitmapClick (wxMouseEvent &event) { wxCommandEvent ev; OnAboutMenuItemSelected (ev); } - void OnManageSecurityTokenKeyfilesMenuItemSelected (wxCommandEvent& event); - void OnMountAllDevicesButtonClick (wxCommandEvent& event); - void OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event); - void OnMountVolumeMenuItemSelected (wxCommandEvent& event) { MountVolume(); } - void OnNewsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"news"); } - void OnNoHistoryCheckBoxClick (wxCommandEvent& event); - void OnOnlineHelpMenuItemSelected (wxCommandEvent& event) { Gui->OpenOnlineHelp (this); } - void OnOpenVolumeMenuItemSelected (wxCommandEvent& event) { OpenSelectedVolume(); } - void OnOpenVolumeSystemRequestEvent (EventArgs &args) { SetVolumePath (wstring (dynamic_cast (args).mVolumePath)); } - void OnOrganizeFavoritesMenuItemSelected (wxCommandEvent& event); - void OnPreferencesMenuItemSelected (wxCommandEvent& event); - void OnPreferencesUpdated (EventArgs &args); - void OnRemoveKeyfilesMenuItemSelected (wxCommandEvent& event) { ChangePassword (ChangePasswordDialog::Mode::RemoveAllKeyfiles); } - void OnRepairFilesystemMenuItemSelected( wxCommandEvent& event ) { CheckFilesystem (true); } - void OnReportBugMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"bugreport"); } - void OnRestoreVolumeHeaderMenuItemSelected (wxCommandEvent& event); - void OnSecurityTokenPreferencesMenuItemSelected (wxCommandEvent& event); - void OnSelectDeviceAndMountMenuItemSelected (wxCommandEvent& event); - void OnSelectDeviceButtonClick (wxCommandEvent& event); - void OnSelectFileAndMountMenuItemSelected (wxCommandEvent& event); - void OnSelectFileButtonClick (wxCommandEvent& event); - void OnTimer (); - void OnTravelerDiskWizardMenuItemSelected (wxCommandEvent& event); - void OnVersionHistoryMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"history"); } - void OnVolumePropertiesButtonClick (wxCommandEvent& event); - void OnVolumeToolsButtonClick (wxCommandEvent& event); - void OnVolumeButtonClick (wxCommandEvent& event); - void OnVolumeDismounted (EventArgs &args) { UpdateVolumeList(); } - void OnVolumeMounted (EventArgs &args) { UpdateVolumeList(); } - void OnUserGuideMenuItemSelected (wxCommandEvent& event) { Gui->OpenUserGuide (this); } - void OnWebsiteMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"website"); } - void OnWipeCacheButtonClick (wxCommandEvent& event); - void OrganizeFavorites (const FavoriteVolumeList &favorites, size_t newItemCount = 0); - void OpenSelectedVolume () const; - void SavePreferences () const; - long SlotNumberToItemIndex (uint32 slotNumber) const; - void SetVolumePath (const VolumePath &path) { VolumePathComboBox->SetValue (wstring (path)); } - void ShowTaskBarIcon (bool show = true); - void UpdateControls (); - void UpdateVolumeList (); - void UpdateWipeCacheButton (); - void WipeCache (); - - struct VolumeActivityMapEntry - { - VolumeActivityMapEntry () { } - - VolumeActivityMapEntry (const VolumeInfo &volume, wxLongLong lastActivityTime) - : LastActivityTime (lastActivityTime), - SerialInstanceNumber (volume.SerialInstanceNumber), - TotalDataRead (volume.TotalDataRead), - TotalDataWritten (volume.TotalDataWritten) - { } - - wxLongLong LastActivityTime; - uint64 SerialInstanceNumber; - uint64 TotalDataRead; - uint64 TotalDataWritten; - }; - - map FavoriteVolumesMenuMap; - VolumeInfoList MountedVolumes; - auto_ptr mTaskBarIcon; - auto_ptr mTimer; - long SelectedItemIndex; - VolumeSlotNumber SelectedSlotNumber; - map VolumeActivityMap; - }; -} - -#endif // TC_HEADER_Main_Forms_MainFrame +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_MainFrame +#define TC_HEADER_Main_Forms_MainFrame + +#include "Forms.h" +#include "ChangePasswordDialog.h" + +namespace TrueCrypt +{ + struct FavoriteVolume; + + class MainFrame : public MainFrameBase + { + public: + MainFrame (wxWindow* parent); + virtual ~MainFrame (); + + void OnDeviceChange (const DirectoryPath &mountPoint = DirectoryPath()); + + protected: + enum + { + ColumnSlot = 0, + ColumnPath, + ColumnSize, +#ifdef TC_WINDOWS + ColumnEA, +#else + ColumnMountPoint, +#endif + ColumnType + }; + + void AddToFavorites (const VolumeInfoList &volumes); + bool CanExit () const; + void ChangePassword (ChangePasswordDialog::Mode::Enum mode = ChangePasswordDialog::Mode::ChangePasswordAndKeyfiles); + void CheckFilesystem (bool repair = false); + bool CheckVolumePathNotEmpty () const; + void DismountVolume (shared_ptr volume = shared_ptr ()); + const UserPreferences &GetPreferences () const { return Gui->GetPreferences(); } + shared_ptr GetSelectedVolume () const; + shared_ptr GetSelectedVolumePath () const { return make_shared (wstring (VolumePathComboBox->GetValue())); } + void InitControls (); + void InitEvents (); + void InitMessageFilter (); + void InitPreferences (); + void InitTaskBarIcon (); + bool IsFreeSlotSelected () const { return SlotListCtrl->GetSelectedItemCount() == 1 && Gui->GetListCtrlSubItemText (SlotListCtrl, SelectedItemIndex, ColumnPath).empty(); } + bool IsMountedSlotSelected () const { return SlotListCtrl->GetSelectedItemCount() == 1 && !Gui->GetListCtrlSubItemText (SlotListCtrl, SelectedItemIndex, ColumnPath).empty(); } + void LoadFavoriteVolumes (); + void LoadPreferences (); + void MountAllDevices (); + void MountAllFavorites (); + void MountVolume (); + void OnAboutMenuItemSelected (wxCommandEvent& event); + void OnActivate (wxActivateEvent& event); + void OnAddAllMountedToFavoritesMenuItemSelected (wxCommandEvent& event); + void OnAddToFavoritesMenuItemSelected (wxCommandEvent& event); + void OnBackupVolumeHeadersMenuItemSelected (wxCommandEvent& event); + void OnBeginnersTutorialMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"tutorial"); } + void OnChangeKeyfilesMenuItemSelected (wxCommandEvent& event) { ChangePassword (ChangePasswordDialog::Mode::ChangeKeyfiles); } + void OnChangePasswordMenuItemSelected (wxCommandEvent& event) { ChangePassword (); } + void OnChangePkcs5PrfMenuItemSelected (wxCommandEvent& event) { ChangePassword (ChangePasswordDialog::Mode::ChangePkcs5Prf); } + void OnCheckFilesystemMenuItemSelected( wxCommandEvent& event ) { CheckFilesystem (); } + void OnClearSlotSelectionMenuItemSelected (wxCommandEvent& event); + void OnClose (wxCloseEvent& event); + void OnCloseAllSecurityTokenSessionsMenuItemSelected (wxCommandEvent& event); + void OnContactMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"contact"); } + void OnCreateKeyfileMenuItemSelected (wxCommandEvent& event) { Gui->CreateKeyfile(); } + void OnCreateVolumeButtonClick (wxCommandEvent& event); + void OnDefaultKeyfilesMenuItemSelected (wxCommandEvent& event); + void OnDismountAllButtonClick (wxCommandEvent& event); + void OnDismountVolumeMenuItemSelected (wxCommandEvent& event) { DismountVolume(); } + void OnDonationsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"donations"); } + void OnDownloadsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"downloads"); } + void OnEncryptionTestMenuItemSelected (wxCommandEvent& event); + void OnExitButtonClick (wxCommandEvent& event); + void OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event); + void OnFaqMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"faq"); } + void OnForumsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"forum"); } + void OnHiddenVolumeProtectionTriggered (shared_ptr protectedVolume); + void OnHotkey (wxKeyEvent& event); + void OnHotkeysMenuItemSelected (wxCommandEvent& event); + void OnLegalNoticesMenuItemSelected (wxCommandEvent& event); + void OnListChanged (); + void OnListItemActivated (wxListEvent& event); + void OnListItemDeleted (long itemIndex); + void OnListItemDeselected (wxListEvent& event); + void OnListItemInserted (long itemIndex); + void OnListItemRightClick (wxListEvent& event); + void OnListItemSelected (wxListEvent& event); + void OnListItemSelectionChanged (); + void OnLogoBitmapClick (wxMouseEvent &event) { wxCommandEvent ev; OnAboutMenuItemSelected (ev); } + void OnManageSecurityTokenKeyfilesMenuItemSelected (wxCommandEvent& event); + void OnMountAllDevicesButtonClick (wxCommandEvent& event); + void OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event); + void OnMountVolumeMenuItemSelected (wxCommandEvent& event) { MountVolume(); } + void OnNewsMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"news"); } + void OnNoHistoryCheckBoxClick (wxCommandEvent& event); + void OnOnlineHelpMenuItemSelected (wxCommandEvent& event) { Gui->OpenOnlineHelp (this); } + void OnOpenVolumeMenuItemSelected (wxCommandEvent& event) { OpenSelectedVolume(); } + void OnOpenVolumeSystemRequestEvent (EventArgs &args) { SetVolumePath (wstring (dynamic_cast (args).mVolumePath)); } + void OnOrganizeFavoritesMenuItemSelected (wxCommandEvent& event); + void OnPreferencesMenuItemSelected (wxCommandEvent& event); + void OnPreferencesUpdated (EventArgs &args); + void OnRemoveKeyfilesMenuItemSelected (wxCommandEvent& event) { ChangePassword (ChangePasswordDialog::Mode::RemoveAllKeyfiles); } + void OnRepairFilesystemMenuItemSelected( wxCommandEvent& event ) { CheckFilesystem (true); } + void OnReportBugMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"bugreport"); } + void OnRestoreVolumeHeaderMenuItemSelected (wxCommandEvent& event); + void OnSecurityTokenPreferencesMenuItemSelected (wxCommandEvent& event); + void OnSelectDeviceAndMountMenuItemSelected (wxCommandEvent& event); + void OnSelectDeviceButtonClick (wxCommandEvent& event); + void OnSelectFileAndMountMenuItemSelected (wxCommandEvent& event); + void OnSelectFileButtonClick (wxCommandEvent& event); + void OnTimer (); + void OnVersionHistoryMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"history"); } + void OnVolumePropertiesButtonClick (wxCommandEvent& event); + void OnVolumeToolsButtonClick (wxCommandEvent& event); + void OnVolumeButtonClick (wxCommandEvent& event); + void OnVolumeDismounted (EventArgs &args) { UpdateVolumeList(); } + void OnVolumeMounted (EventArgs &args) { UpdateVolumeList(); } + void OnUserGuideMenuItemSelected (wxCommandEvent& event) { Gui->OpenUserGuide (this); } + void OnWebsiteMenuItemSelected (wxCommandEvent& event) { Gui->OpenHomepageLink (this, L"website"); } + void OnWipeCacheButtonClick (wxCommandEvent& event); + void OrganizeFavorites (const FavoriteVolumeList &favorites, size_t newItemCount = 0); + void OpenSelectedVolume () const; + void SavePreferences () const; + long SlotNumberToItemIndex (uint32 slotNumber) const; + void SetVolumePath (const VolumePath &path) { VolumePathComboBox->SetValue (wstring (path)); } + void ShowTaskBarIcon (bool show = true); + void UpdateControls (); + void UpdateVolumeList (); + void UpdateWipeCacheButton (); + void WipeCache (); + + struct VolumeActivityMapEntry + { + VolumeActivityMapEntry () { } + + VolumeActivityMapEntry (const VolumeInfo &volume, wxLongLong lastActivityTime) + : LastActivityTime (lastActivityTime), + SerialInstanceNumber (volume.SerialInstanceNumber), + TotalDataRead (volume.TotalDataRead), + TotalDataWritten (volume.TotalDataWritten) + { } + + wxLongLong LastActivityTime; + uint64 SerialInstanceNumber; + uint64 TotalDataRead; + uint64 TotalDataWritten; + }; + + map FavoriteVolumesMenuMap; + VolumeInfoList MountedVolumes; + auto_ptr mTaskBarIcon; + auto_ptr mTimer; + long SelectedItemIndex; + VolumeSlotNumber SelectedSlotNumber; + map VolumeActivityMap; + }; +} + +#endif // TC_HEADER_Main_Forms_MainFrame diff --git a/Main/Forms/MountOptionsDialog.cpp b/Main/Forms/MountOptionsDialog.cpp index 1afc67b..4932e0b 100644 --- a/Main/Forms/MountOptionsDialog.cpp +++ b/Main/Forms/MountOptionsDialog.cpp @@ -1,174 +1,174 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/Main.h" -#include "Main/GraphicUserInterface.h" -#include "MountOptionsDialog.h" - -namespace TrueCrypt -{ - MountOptionsDialog::MountOptionsDialog (wxWindow *parent, MountOptions &options, const wxString &title, bool disableMountOptions) - : MountOptionsDialogBase (parent, wxID_ANY, wxString() -#ifdef __WXGTK__ // GTK apparently needs wxRESIZE_BORDER to support dynamic resizing - , wxDefaultPosition, wxSize (-1,-1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER -#endif - ), Options (options) - { - if (!title.empty()) - this->SetTitle (title); - else if (options.Path && !options.Path->IsEmpty()) - this->SetTitle (StringFormatter (LangString["ENTER_PASSWORD_FOR"], wstring (*options.Path))); - else - this->SetTitle (LangString["ENTER_TC_VOL_PASSWORD"]); - - if (disableMountOptions) - OptionsButton->Show (false); - - PasswordPanel = new VolumePasswordPanel (this, options.Password, options.Keyfiles, !disableMountOptions); - PasswordPanel->SetCacheCheckBoxValidator (wxGenericValidator (&Options.CachePassword)); - - PasswordSizer->Add (PasswordPanel, 1, wxALL | wxEXPAND); - -#ifdef __WXGTK__ - FilesystemOptionsSizer->Remove (FilesystemSpacer); - OptionsPanel->Show (false); - Fit(); - Layout(); - SetMinSize (GetSize()); -#endif - - NoFilesystemCheckBox->SetValidator (wxGenericValidator (&Options.NoFilesystem)); - RemovableCheckBox->SetValidator (wxGenericValidator (&Options.Removable)); - PartitionInSystemEncryptionScopeCheckBox->SetValidator (wxGenericValidator (&Options.PartitionInSystemEncryptionScope)); - - TransferDataToWindow(); - - if (Options.MountPoint && !Options.MountPoint->IsEmpty()) - MountPointTextCtrl->SetValue (wstring (*Options.MountPoint)); - - FilesystemOptionsTextCtrl->SetValue (Options.FilesystemOptions); - - ReadOnlyCheckBox->SetValue (Options.Protection == VolumeProtection::ReadOnly); - ProtectionCheckBox->SetValue (Options.Protection == VolumeProtection::HiddenVolumeReadOnly); - - OptionsButtonLabel = OptionsButton->GetLabel(); - OptionsButton->SetLabel (OptionsButtonLabel + L" >"); - OptionsPanel->Show (false); - - ProtectionPasswordPanel = new VolumePasswordPanel (OptionsPanel, options.ProtectionPassword, options.ProtectionKeyfiles, false, true, true, false, false, _("P&assword to hidden volume:")); - ProtectionPasswordSizer->Add (ProtectionPasswordPanel, 1, wxALL | wxEXPAND); - - UpdateDialog(); - Center(); - } - - void MountOptionsDialog::OnInitDialog (wxInitDialogEvent& event) - { - PasswordPanel->SetFocusToPasswordTextCtrl(); - } - - void MountOptionsDialog::OnMountPointButtonClick (wxCommandEvent& event) - { - DirectoryPath dir = Gui->SelectDirectory (this, wxEmptyString, false); - if (!dir.IsEmpty()) - MountPointTextCtrl->SetValue (wstring (dir)); - } - - void MountOptionsDialog::OnOKButtonClick (wxCommandEvent& event) - { - TransferDataFromWindow(); - - Options.Password = PasswordPanel->GetPassword(); - Options.Keyfiles = PasswordPanel->GetKeyfiles(); - - if (ReadOnlyCheckBox->IsChecked()) - { - Options.Protection = VolumeProtection::ReadOnly; - } - else if (ProtectionCheckBox->IsChecked()) - { - Options.Protection = VolumeProtection::HiddenVolumeReadOnly; - Options.ProtectionPassword = ProtectionPasswordPanel->GetPassword(); - Options.ProtectionKeyfiles = ProtectionPasswordPanel->GetKeyfiles(); - } - else - { - Options.Protection = VolumeProtection::None; - } - - wstring mountPoint (MountPointTextCtrl->GetValue()); - if (!mountPoint.empty()) - Options.MountPoint = make_shared (mountPoint); - - Options.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue(); - - try - { - if (Options.Password) - Options.Password->CheckPortability(); - } - catch (UnportablePassword &) - { - Gui->ShowWarning (LangString ["UNSUPPORTED_CHARS_IN_PWD_RECOM"]); - } - - EndModal (wxID_OK); - } - - void MountOptionsDialog::OnOptionsButtonClick (wxCommandEvent& event) - { - FreezeScope freeze (this); - OptionsPanel->Show (!OptionsPanel->IsShown()); - UpdateDialog(); - OptionsButton->SetLabel (OptionsButtonLabel + (OptionsPanel->IsShown() ? L" <" : L" >")); - } - - void MountOptionsDialog::OnProtectionCheckBoxClick (wxCommandEvent& event) - { - FreezeScope freeze (this); - ProtectionPasswordPanel->Show (event.IsChecked()); - Fit(); - Layout(); - ProtectionPasswordPanel->SetFocusToPasswordTextCtrl(); - } - - void MountOptionsDialog::OnProtectionHyperlinkClick (wxHyperlinkEvent& event) - { - Gui->OpenHomepageLink (this, L"hiddenvolprotection"); - } - - void MountOptionsDialog::UpdateDialog () - { - FreezeScope freeze (this); - -#ifdef TC_WINDOWS - FilesystemSizer->Show (false); -#else - FilesystemOptionsSizer->Show (!NoFilesystemCheckBox->IsChecked()); - -# ifdef TC_MACOSX - FilesystemOptionsStaticText->Show (false); - FilesystemOptionsTextCtrl->Show (false); -# endif - - if (!Options.Path || Options.Path->IsEmpty()) - { - MountPointTextCtrlStaticText->Show (false); - MountPointTextCtrl->Show (false); - MountPointButton->Show (false); - } - RemovableCheckBox->Show (false); -#endif - ProtectionSizer->Show (!ReadOnlyCheckBox->IsChecked()); - ProtectionPasswordPanel->Show (!ReadOnlyCheckBox->IsChecked() && ProtectionCheckBox->IsChecked()); - - Fit(); - Layout(); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/Main.h" +#include "Main/GraphicUserInterface.h" +#include "MountOptionsDialog.h" + +namespace TrueCrypt +{ + MountOptionsDialog::MountOptionsDialog (wxWindow *parent, MountOptions &options, const wxString &title, bool disableMountOptions) + : MountOptionsDialogBase (parent, wxID_ANY, wxString() +#ifdef __WXGTK__ // GTK apparently needs wxRESIZE_BORDER to support dynamic resizing + , wxDefaultPosition, wxSize (-1,-1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER +#endif + ), Options (options) + { + if (!title.empty()) + this->SetTitle (title); + else if (options.Path && !options.Path->IsEmpty()) + this->SetTitle (StringFormatter (LangString["ENTER_PASSWORD_FOR"], wstring (*options.Path))); + else + this->SetTitle (LangString["ENTER_TC_VOL_PASSWORD"]); + + if (disableMountOptions) + OptionsButton->Show (false); + + PasswordPanel = new VolumePasswordPanel (this, options.Password, options.Keyfiles, !disableMountOptions); + PasswordPanel->SetCacheCheckBoxValidator (wxGenericValidator (&Options.CachePassword)); + + PasswordSizer->Add (PasswordPanel, 1, wxALL | wxEXPAND); + +#ifdef __WXGTK__ + FilesystemOptionsSizer->Remove (FilesystemSpacer); + OptionsPanel->Show (false); + Fit(); + Layout(); + SetMinSize (GetSize()); +#endif + + NoFilesystemCheckBox->SetValidator (wxGenericValidator (&Options.NoFilesystem)); + RemovableCheckBox->SetValidator (wxGenericValidator (&Options.Removable)); + PartitionInSystemEncryptionScopeCheckBox->SetValidator (wxGenericValidator (&Options.PartitionInSystemEncryptionScope)); + + TransferDataToWindow(); + + if (Options.MountPoint && !Options.MountPoint->IsEmpty()) + MountPointTextCtrl->SetValue (wstring (*Options.MountPoint)); + + FilesystemOptionsTextCtrl->SetValue (Options.FilesystemOptions); + + ReadOnlyCheckBox->SetValue (Options.Protection == VolumeProtection::ReadOnly); + ProtectionCheckBox->SetValue (Options.Protection == VolumeProtection::HiddenVolumeReadOnly); + + OptionsButtonLabel = OptionsButton->GetLabel(); + OptionsButton->SetLabel (OptionsButtonLabel + L" >"); + OptionsPanel->Show (false); + + ProtectionPasswordPanel = new VolumePasswordPanel (OptionsPanel, options.ProtectionPassword, options.ProtectionKeyfiles, false, true, true, false, false, _("P&assword to hidden volume:")); + ProtectionPasswordSizer->Add (ProtectionPasswordPanel, 1, wxALL | wxEXPAND); + + UpdateDialog(); + Center(); + } + + void MountOptionsDialog::OnInitDialog (wxInitDialogEvent& event) + { + PasswordPanel->SetFocusToPasswordTextCtrl(); + } + + void MountOptionsDialog::OnMountPointButtonClick (wxCommandEvent& event) + { + DirectoryPath dir = Gui->SelectDirectory (this, wxEmptyString, false); + if (!dir.IsEmpty()) + MountPointTextCtrl->SetValue (wstring (dir)); + } + + void MountOptionsDialog::OnOKButtonClick (wxCommandEvent& event) + { + TransferDataFromWindow(); + + Options.Password = PasswordPanel->GetPassword(); + Options.Keyfiles = PasswordPanel->GetKeyfiles(); + + if (ReadOnlyCheckBox->IsChecked()) + { + Options.Protection = VolumeProtection::ReadOnly; + } + else if (ProtectionCheckBox->IsChecked()) + { + Options.Protection = VolumeProtection::HiddenVolumeReadOnly; + Options.ProtectionPassword = ProtectionPasswordPanel->GetPassword(); + Options.ProtectionKeyfiles = ProtectionPasswordPanel->GetKeyfiles(); + } + else + { + Options.Protection = VolumeProtection::None; + } + + wstring mountPoint (MountPointTextCtrl->GetValue()); + if (!mountPoint.empty()) + Options.MountPoint = make_shared (mountPoint); + + Options.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue(); + + try + { + if (Options.Password) + Options.Password->CheckPortability(); + } + catch (UnportablePassword &) + { + Gui->ShowWarning (LangString ["UNSUPPORTED_CHARS_IN_PWD_RECOM"]); + } + + EndModal (wxID_OK); + } + + void MountOptionsDialog::OnOptionsButtonClick (wxCommandEvent& event) + { + FreezeScope freeze (this); + OptionsPanel->Show (!OptionsPanel->IsShown()); + UpdateDialog(); + OptionsButton->SetLabel (OptionsButtonLabel + (OptionsPanel->IsShown() ? L" <" : L" >")); + } + + void MountOptionsDialog::OnProtectionCheckBoxClick (wxCommandEvent& event) + { + FreezeScope freeze (this); + ProtectionPasswordPanel->Show (event.IsChecked()); + Fit(); + Layout(); + ProtectionPasswordPanel->SetFocusToPasswordTextCtrl(); + } + + void MountOptionsDialog::OnProtectionHyperlinkClick (wxHyperlinkEvent& event) + { + Gui->OpenHomepageLink (this, L"hiddenvolprotection"); + } + + void MountOptionsDialog::UpdateDialog () + { + FreezeScope freeze (this); + +#ifdef TC_WINDOWS + FilesystemSizer->Show (false); +#else + FilesystemOptionsSizer->Show (!NoFilesystemCheckBox->IsChecked()); + +# ifdef TC_MACOSX + FilesystemOptionsStaticText->Show (false); + FilesystemOptionsTextCtrl->Show (false); +# endif + + if (!Options.Path || Options.Path->IsEmpty()) + { + MountPointTextCtrlStaticText->Show (false); + MountPointTextCtrl->Show (false); + MountPointButton->Show (false); + } + RemovableCheckBox->Show (false); +#endif + ProtectionSizer->Show (!ReadOnlyCheckBox->IsChecked()); + ProtectionPasswordPanel->Show (!ReadOnlyCheckBox->IsChecked() && ProtectionCheckBox->IsChecked()); + + Fit(); + Layout(); + } +} diff --git a/Main/Forms/MountOptionsDialog.h b/Main/Forms/MountOptionsDialog.h index e60159d..5516c55 100644 --- a/Main/Forms/MountOptionsDialog.h +++ b/Main/Forms/MountOptionsDialog.h @@ -1,42 +1,42 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_MountOptionsDialog -#define TC_HEADER_Main_Forms_MountOptionsDialog - -#include "Forms.h" -#include "Main/Main.h" -#include "VolumePasswordPanel.h" - -namespace TrueCrypt -{ - class MountOptionsDialog : public MountOptionsDialogBase - { - public: - MountOptionsDialog (wxWindow* parent, MountOptions &options, const wxString &title = wxEmptyString, bool disableMountOptions = false); - void OnShow (); - - protected: - void OnInitDialog (wxInitDialogEvent& event); - void OnMountPointButtonClick (wxCommandEvent& event); - void OnNoFilesystemCheckBoxClick (wxCommandEvent& event) { UpdateDialog(); } - void OnOKButtonClick (wxCommandEvent& event); - void OnOptionsButtonClick (wxCommandEvent& event); - void OnProtectionCheckBoxClick (wxCommandEvent& event); - void OnProtectionHyperlinkClick (wxHyperlinkEvent& event); - void OnReadOnlyCheckBoxClick (wxCommandEvent& event) { UpdateDialog(); } - void UpdateDialog (); - - MountOptions &Options; - wxString OptionsButtonLabel; - VolumePasswordPanel *PasswordPanel; - VolumePasswordPanel *ProtectionPasswordPanel; - }; -} - -#endif // TC_HEADER_Main_Forms_MountOptionsDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_MountOptionsDialog +#define TC_HEADER_Main_Forms_MountOptionsDialog + +#include "Forms.h" +#include "Main/Main.h" +#include "VolumePasswordPanel.h" + +namespace TrueCrypt +{ + class MountOptionsDialog : public MountOptionsDialogBase + { + public: + MountOptionsDialog (wxWindow* parent, MountOptions &options, const wxString &title = wxEmptyString, bool disableMountOptions = false); + void OnShow (); + + protected: + void OnInitDialog (wxInitDialogEvent& event); + void OnMountPointButtonClick (wxCommandEvent& event); + void OnNoFilesystemCheckBoxClick (wxCommandEvent& event) { UpdateDialog(); } + void OnOKButtonClick (wxCommandEvent& event); + void OnOptionsButtonClick (wxCommandEvent& event); + void OnProtectionCheckBoxClick (wxCommandEvent& event); + void OnProtectionHyperlinkClick (wxHyperlinkEvent& event); + void OnReadOnlyCheckBoxClick (wxCommandEvent& event) { UpdateDialog(); } + void UpdateDialog (); + + MountOptions &Options; + wxString OptionsButtonLabel; + VolumePasswordPanel *PasswordPanel; + VolumePasswordPanel *ProtectionPasswordPanel; + }; +} + +#endif // TC_HEADER_Main_Forms_MountOptionsDialog diff --git a/Main/Forms/NewSecurityTokenKeyfileDialog.cpp b/Main/Forms/NewSecurityTokenKeyfileDialog.cpp index 3d36fbc..d2da165 100644 --- a/Main/Forms/NewSecurityTokenKeyfileDialog.cpp +++ b/Main/Forms/NewSecurityTokenKeyfileDialog.cpp @@ -1,45 +1,45 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "NewSecurityTokenKeyfileDialog.h" - -namespace TrueCrypt -{ - NewSecurityTokenKeyfileDialog::NewSecurityTokenKeyfileDialog (wxWindow* parent, const wstring &keyfileName) : NewSecurityTokenKeyfileDialogBase (parent) - { - list tokens = SecurityToken::GetAvailableTokens(); - - if (tokens.empty()) - throw_err (LangString ["NO_TOKENS_FOUND"]); - - foreach (const SecurityTokenInfo &token, tokens) - { - wstringstream tokenLabel; - tokenLabel << L"[" << token.SlotId << L"] " << token.Label; - - SecurityTokenChoice->Append (tokenLabel.str(), (void *) token.SlotId); - } - - SecurityTokenChoice->Select (0); - KeyfileNameTextCtrl->SetValue (keyfileName); - - KeyfileNameTextCtrl->SetMinSize (wxSize (Gui->GetCharWidth (KeyfileNameTextCtrl) * 32, -1)); - - Fit(); - Layout(); - Center(); - } - - void NewSecurityTokenKeyfileDialog::OnKeyfileNameChanged (wxCommandEvent& event) - { - StdButtonsOK->Enable (!KeyfileNameTextCtrl->GetValue().empty()); - event.Skip(); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "NewSecurityTokenKeyfileDialog.h" + +namespace TrueCrypt +{ + NewSecurityTokenKeyfileDialog::NewSecurityTokenKeyfileDialog (wxWindow* parent, const wstring &keyfileName) : NewSecurityTokenKeyfileDialogBase (parent) + { + list tokens = SecurityToken::GetAvailableTokens(); + + if (tokens.empty()) + throw_err (LangString ["NO_TOKENS_FOUND"]); + + foreach (const SecurityTokenInfo &token, tokens) + { + wstringstream tokenLabel; + tokenLabel << L"[" << token.SlotId << L"] " << token.Label; + + SecurityTokenChoice->Append (tokenLabel.str(), (void *) token.SlotId); + } + + SecurityTokenChoice->Select (0); + KeyfileNameTextCtrl->SetValue (keyfileName); + + KeyfileNameTextCtrl->SetMinSize (wxSize (Gui->GetCharWidth (KeyfileNameTextCtrl) * 32, -1)); + + Fit(); + Layout(); + Center(); + } + + void NewSecurityTokenKeyfileDialog::OnKeyfileNameChanged (wxCommandEvent& event) + { + StdButtonsOK->Enable (!KeyfileNameTextCtrl->GetValue().empty()); + event.Skip(); + } +} diff --git a/Main/Forms/NewSecurityTokenKeyfileDialog.h b/Main/Forms/NewSecurityTokenKeyfileDialog.h index c7ee082..126d356 100644 --- a/Main/Forms/NewSecurityTokenKeyfileDialog.h +++ b/Main/Forms/NewSecurityTokenKeyfileDialog.h @@ -1,30 +1,30 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_NewSecurityTokenKeyfileDialog -#define TC_HEADER_Main_Forms_NewSecurityTokenKeyfileDialog - -#include "Forms.h" -#include "Common/SecurityToken.h" - -namespace TrueCrypt -{ - class NewSecurityTokenKeyfileDialog : public NewSecurityTokenKeyfileDialogBase - { - public: - NewSecurityTokenKeyfileDialog (wxWindow* parent, const wstring &keyfileName); - - wstring GetKeyfileName () const { return wstring (KeyfileNameTextCtrl->GetValue()); } - CK_SLOT_ID GetSelectedSlotId () const { return reinterpret_cast (SecurityTokenChoice->GetClientData (SecurityTokenChoice->GetSelection())); } - - protected: - void OnKeyfileNameChanged (wxCommandEvent& event); - }; -} - -#endif // TC_HEADER_Main_Forms_NewSecurityTokenKeyfileDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_NewSecurityTokenKeyfileDialog +#define TC_HEADER_Main_Forms_NewSecurityTokenKeyfileDialog + +#include "Forms.h" +#include "Common/SecurityToken.h" + +namespace TrueCrypt +{ + class NewSecurityTokenKeyfileDialog : public NewSecurityTokenKeyfileDialogBase + { + public: + NewSecurityTokenKeyfileDialog (wxWindow* parent, const wstring &keyfileName); + + wstring GetKeyfileName () const { return wstring (KeyfileNameTextCtrl->GetValue()); } + CK_SLOT_ID GetSelectedSlotId () const { return reinterpret_cast (SecurityTokenChoice->GetClientData (SecurityTokenChoice->GetSelection())); } + + protected: + void OnKeyfileNameChanged (wxCommandEvent& event); + }; +} + +#endif // TC_HEADER_Main_Forms_NewSecurityTokenKeyfileDialog diff --git a/Main/Forms/PreferencesDialog.cpp b/Main/Forms/PreferencesDialog.cpp index d542ef1..0ff0372 100644 --- a/Main/Forms/PreferencesDialog.cpp +++ b/Main/Forms/PreferencesDialog.cpp @@ -1,496 +1,496 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include -#ifdef TC_WINDOWS -#include -#endif -#include "Common/SecurityToken.h" -#include "Main/Main.h" -#include "Main/Application.h" -#include "Main/GraphicUserInterface.h" -#include "PreferencesDialog.h" - -namespace TrueCrypt -{ - PreferencesDialog::PreferencesDialog (wxWindow* parent) - : PreferencesDialogBase (parent), - LastVirtualKeyPressed (0), - Preferences (Gui->GetPreferences()), - RestoreValidatorBell (false) - { -#define TC_CHECK_BOX_VALIDATOR(NAME) (TC_JOIN(NAME,CheckBox))->SetValidator (wxGenericValidator (&Preferences.NAME)); - - // Security - TC_CHECK_BOX_VALIDATOR (DismountOnLogOff); - TC_CHECK_BOX_VALIDATOR (DismountOnPowerSaving); - TC_CHECK_BOX_VALIDATOR (DismountOnScreenSaver); - TC_CHECK_BOX_VALIDATOR (DismountOnInactivity); - DismountOnInactivitySpinCtrl->SetValidator (wxGenericValidator (&Preferences.MaxVolumeIdleTime)); - TC_CHECK_BOX_VALIDATOR (ForceAutoDismount); - PreserveTimestampsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.PreserveTimestamps)); - TC_CHECK_BOX_VALIDATOR (WipeCacheOnAutoDismount); - TC_CHECK_BOX_VALIDATOR (WipeCacheOnClose); - - // Mount options - CachePasswordsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.CachePassword)); - MountReadOnlyCheckBox->SetValue (Preferences.DefaultMountOptions.Protection == VolumeProtection::ReadOnly); - MountRemovableCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.Removable)); - - FilesystemOptionsTextCtrl->SetValue (Preferences.DefaultMountOptions.FilesystemOptions); - - // Keyfiles - TC_CHECK_BOX_VALIDATOR (UseKeyfiles); - - DefaultKeyfilesPanel = new KeyfilesPanel (DefaultKeyfilesPage, make_shared (Preferences.DefaultKeyfiles)); - DefaultKeyfilesSizer->Add (DefaultKeyfilesPanel, 1, wxALL | wxEXPAND); - DefaultKeyfilesSizer->Layout(); - - TC_CHECK_BOX_VALIDATOR (BackgroundTaskEnabled); - TC_CHECK_BOX_VALIDATOR (CloseBackgroundTaskOnNoVolumes); - CloseBackgroundTaskOnNoVolumesCheckBox->Show (!Core->IsInTravelMode()); - TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuDismountItemsEnabled); - TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuMountItemsEnabled); - TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuOpenItemsEnabled); - - // Security tokens - Pkcs11ModulePathTextCtrl->SetValue (wstring (Preferences.SecurityTokenModule)); - TC_CHECK_BOX_VALIDATOR (CloseSecurityTokenSessionsAfterMount); - - // System integration - TC_CHECK_BOX_VALIDATOR (StartOnLogon); - TC_CHECK_BOX_VALIDATOR (MountDevicesOnLogon); - TC_CHECK_BOX_VALIDATOR (MountFavoritesOnLogon); - - TC_CHECK_BOX_VALIDATOR (CloseExplorerWindowsOnDismount); - TC_CHECK_BOX_VALIDATOR (OpenExplorerWindowAfterMount); - - NoKernelCryptoCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.NoKernelCrypto)); - -#ifdef TC_WINDOWS - // Hotkeys - TC_CHECK_BOX_VALIDATOR (BeepAfterHotkeyMountDismount); - TC_CHECK_BOX_VALIDATOR (DisplayMessageAfterHotkeyDismount); -#endif - - TransferDataToWindow(); // Code below relies on TransferDataToWindow() called at this point - -#if defined (TC_WINDOWS) || defined (TC_MACOSX) - FilesystemSizer->Show (false); -#else - // Auto-dismount is not supported on Linux as dismount may require the user to enter admin password - AutoDismountSizer->Show (false); - WipeCacheOnAutoDismountCheckBox->Show (false); -#endif - -#ifndef TC_WINDOWS - LogOnSizer->Show (false); - MountRemovableCheckBox->Show (false); - CloseExplorerWindowsOnDismountCheckBox->Show (false); -#endif - -#ifndef wxHAS_POWER_EVENTS - DismountOnPowerSavingCheckBox->Show (false); -#endif - -#ifdef TC_MACOSX - DismountOnScreenSaverCheckBox->Show (false); - DismountOnLogOffCheckBox->SetLabel (_("TrueCrypt quits")); - OpenExplorerWindowAfterMountCheckBox->SetLabel (_("Open Finder window for successfully mounted volume")); - - MountRemovableCheckBox->Show (false); - FilesystemSizer->Show (false); - LogOnSizer->Show (false); - CloseExplorerWindowsOnDismountCheckBox->Show (false); -#endif - -#ifndef TC_LINUX - KernelServicesSizer->Show (false); -#endif - -#ifdef TC_WINDOWS - // Hotkeys - list colPermilles; - HotkeyListCtrl->InsertColumn (ColumnHotkeyDescription, LangString["ACTION"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (642); - HotkeyListCtrl->InsertColumn (ColumnHotkey, LangString["SHORTCUT"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (358); - - vector fields (HotkeyListCtrl->GetColumnCount()); - - UnregisteredHotkeys = Preferences.Hotkeys; - Hotkey::UnregisterList (Gui->GetMainFrame(), UnregisteredHotkeys); - - foreach (shared_ptr hotkey, Preferences.Hotkeys) - { - fields[ColumnHotkeyDescription] = hotkey->Description; - fields[ColumnHotkey] = hotkey->GetShortcutString(); - Gui->AppendToListCtrl (HotkeyListCtrl, fields, -1, hotkey.get()); - } - - Gui->SetListCtrlHeight (HotkeyListCtrl, 5); - - Layout(); - Fit(); - Gui->SetListCtrlColumnWidths (HotkeyListCtrl, colPermilles); - - RestoreValidatorBell = !wxTextValidator::IsSilent(); - wxTextValidator::SetBellOnError (true); - HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_INCLUDE_CHAR_LIST)); - - UpdateHotkeyButtons(); -#endif - - // Page setup - for (size_t page = 0; page < PreferencesNotebook->GetPageCount(); page++) - { - wxNotebookPage *np = PreferencesNotebook->GetPage (page); - if (np == HotkeysPage) - { -#ifndef TC_WINDOWS - PreferencesNotebook->RemovePage (page--); - continue; -#endif - } - - np->Layout(); - } - - Layout(); - Fit(); - Center(); - - StdButtonsOK->SetDefault(); - -#ifdef TC_WINDOWS - // Hotkey timer - class Timer : public wxTimer - { - public: - Timer (PreferencesDialog *dialog) : Dialog (dialog) { } - - void Notify() - { - Dialog->OnTimer(); - } - - PreferencesDialog *Dialog; - }; - - mTimer.reset (dynamic_cast (new Timer (this))); - mTimer->Start (25); -#endif - } - - PreferencesDialog::~PreferencesDialog () - { - if (RestoreValidatorBell) - wxTextValidator::SetBellOnError (false); - } - - void PreferencesDialog::SelectPage (wxPanel *page) - { - for (size_t pageIndex = 0; pageIndex < PreferencesNotebook->GetPageCount(); pageIndex++) - { - if (PreferencesNotebook->GetPage (pageIndex) == page) - PreferencesNotebook->ChangeSelection (pageIndex); - } - } - - void PreferencesDialog::OnAssignHotkeyButtonClick (wxCommandEvent& event) - { -#ifdef TC_WINDOWS - foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) - { - Hotkey *hotkey = reinterpret_cast (HotkeyListCtrl->GetItemData (item)); - - int mods = 0; - mods |= HotkeyShiftCheckBox->IsChecked() ? wxMOD_SHIFT : 0; - mods |= HotkeyControlCheckBox->IsChecked() ? wxMOD_CONTROL : 0; - mods |= HotkeyAltCheckBox->IsChecked() ? wxMOD_ALT : 0; - mods |= HotkeyWinCheckBox->IsChecked() ? wxMOD_WIN : 0; - - // F1 is help and F12 is reserved for use by the debugger at all times - if (mods == 0 && (LastVirtualKeyPressed == VK_F1 || LastVirtualKeyPressed == VK_F12)) - { - Gui->ShowError ("CANNOT_USE_RESERVED_KEY"); - return; - } - - // Test if the hotkey can be registered - if (!this->RegisterHotKey (hotkey->Id, mods, LastVirtualKeyPressed)) - { - Gui->ShowError (SystemException (SRC_POS)); - return; - } - UnregisterHotKey (hotkey->Id); - - foreach_ref (const Hotkey &h, Preferences.Hotkeys) - { - if (h.Id != hotkey->Id && h.VirtualKeyCode == LastVirtualKeyPressed && h.VirtualKeyModifiers == mods) - { - Gui->ShowError ("SHORTCUT_ALREADY_IN_USE"); - return; - } - } - - hotkey->VirtualKeyCode = LastVirtualKeyPressed; - hotkey->VirtualKeyModifiers = mods; - - vector fields (HotkeyListCtrl->GetColumnCount()); - fields[ColumnHotkeyDescription] = hotkey->Description; - fields[ColumnHotkey] = hotkey->GetShortcutString(); - Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields); - - UpdateHotkeyButtons(); - } -#endif // TC_WINDOWS - } - - void PreferencesDialog::OnBackgroundTaskEnabledCheckBoxClick (wxCommandEvent& event) - { - if (!event.IsChecked()) - BackgroundTaskEnabledCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_BACKGROUND_TASK_DISABLED"], false, true)); - } - - void PreferencesDialog::OnNoKernelCryptoCheckBoxClick (wxCommandEvent& event) - { - if (event.IsChecked()) - NoKernelCryptoCheckBox->SetValue (Gui->AskYesNo (_("Disabling the use of kernel cryptographic services can degrade performance.\n\nAre you sure?"), false, true)); - } - - void PreferencesDialog::OnClose (wxCloseEvent& event) - { -#ifdef TC_WINDOWS - Hotkey::RegisterList (Gui->GetMainFrame(), UnregisteredHotkeys); -#endif - event.Skip(); - } - - void PreferencesDialog::OnDismountOnPowerSavingCheckBoxClick (wxCommandEvent& event) - { - if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked()) - Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT"); - } - - void PreferencesDialog::OnDismountOnScreenSaverCheckBoxClick (wxCommandEvent& event) - { - if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked()) - Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT"); - } - - void PreferencesDialog::OnForceAutoDismountCheckBoxClick (wxCommandEvent& event) - { - if (!event.IsChecked()) - ForceAutoDismountCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_NO_FORCED_AUTODISMOUNT"], false, true)); - } - - void PreferencesDialog::OnHotkeyListItemDeselected (wxListEvent& event) - { - UpdateHotkeyButtons(); - } - - void PreferencesDialog::OnHotkeyListItemSelected (wxListEvent& event) - { - UpdateHotkeyButtons(); - HotkeyTextCtrl->ChangeValue (LangString ["PRESS_A_KEY_TO_ASSIGN"]); - AssignHotkeyButton->Enable (false); - } - - void PreferencesDialog::OnOKButtonClick (wxCommandEvent& event) - { -#ifdef TC_WINDOWS - HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_NONE)); -#endif - if (!Validate()) - return; - - TransferDataFromWindow(); - - Preferences.DefaultMountOptions.Protection = MountReadOnlyCheckBox->IsChecked() ? VolumeProtection::ReadOnly : VolumeProtection::None; - Preferences.DefaultMountOptions.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue(); - Preferences.DefaultKeyfiles = *DefaultKeyfilesPanel->GetKeyfiles(); - - bool securityTokenModuleChanged = (Preferences.SecurityTokenModule != wstring (Pkcs11ModulePathTextCtrl->GetValue())); - Preferences.SecurityTokenModule = wstring (Pkcs11ModulePathTextCtrl->GetValue()); - - Gui->SetPreferences (Preferences); - - try - { - if (securityTokenModuleChanged) - { - if (Preferences.SecurityTokenModule.IsEmpty()) - { - if (SecurityToken::IsInitialized()) - SecurityToken::CloseLibrary (); - } - else - { - Gui->InitSecurityTokenLibrary(); - } - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - -#ifdef TC_WINDOWS - // Log on actions - wxString logonKey = wxString (L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Curren") + L"tVersion\\Run"; // Splitted to prevent false antivirus heuristic alerts - if (Preferences.StartOnLogon || Preferences.MountDevicesOnLogon || Preferences.MountFavoritesOnLogon) - { - auto_ptr regKey (new wxRegKey (logonKey)); - throw_sys_sub_if (!regKey.get(), wstring (logonKey)); - - wxString cmdLine = wstring (L"\"") + wstring (Application::GetExecutablePath()) + L"\" --load-preferences"; - - wxString autoMount; - if (Preferences.MountDevicesOnLogon) - autoMount += L"devices"; - if (Preferences.MountFavoritesOnLogon) - { - if (!autoMount.empty()) - autoMount += L","; - autoMount += L"favorites"; - } - - if (!autoMount.empty()) - cmdLine += wxString (L" --auto-mount=") + autoMount; - - if (Preferences.StartOnLogon) - cmdLine += L" --background-task"; - - throw_sys_sub_if (!regKey->SetValue (Application::GetName().c_str(), cmdLine), wstring (logonKey)); - } - else - { - auto_ptr regKey (new wxRegKey (logonKey)); - regKey->DeleteValue (Application::GetName().c_str()); - } - - // Hotkeys - Hotkey::RegisterList (Gui->GetMainFrame(), Preferences.Hotkeys); -#endif - - EndModal (wxID_OK); - } - - void PreferencesDialog::OnPreserveTimestampsCheckBoxClick (wxCommandEvent& event) - { - if (!event.IsChecked()) - { - bool confirmed = Gui->AskYesNo (LangString["CONFIRM_TIMESTAMP_UPDATING"], false, true); - PreserveTimestampsCheckBox->SetValue (!confirmed); -#ifdef TC_LINUX - if (confirmed) - Gui->ShowInfo (_("Please note that disabling this option may have no effect on volumes mounted using kernel cryptographic services.")); -#endif - } - } - - void PreferencesDialog::OnRemoveHotkeyButtonClick (wxCommandEvent& event) - { -#ifdef TC_WINDOWS - foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) - { - Hotkey *hotkey = reinterpret_cast (HotkeyListCtrl->GetItemData (item)); - hotkey->VirtualKeyCode = 0; - hotkey->VirtualKeyModifiers = 0; - - vector fields (HotkeyListCtrl->GetColumnCount()); - fields[ColumnHotkeyDescription] = hotkey->Description; - fields[ColumnHotkey] = hotkey->GetShortcutString(); - Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields); - - UpdateHotkeyButtons(); - } -#endif - } - - void PreferencesDialog::OnSelectPkcs11ModuleButtonClick (wxCommandEvent& event) - { - list < pair > extensions; - wxString libExtension; - libExtension = wxDynamicLibrary::CanonicalizeName (L"x"); - -#ifdef TC_MACOSX - extensions.push_back (make_pair (L"dylib", LangString["DLL_FILES"])); -#endif - if (!libExtension.empty()) - { - extensions.push_back (make_pair (libExtension.Mid (libExtension.find (L'.') + 1), LangString["DLL_FILES"])); - extensions.push_back (make_pair (L"*", L"")); - } - - string libDir; - -#ifdef TC_WINDOWS - - char sysDir[TC_MAX_PATH]; - GetSystemDirectoryA (sysDir, sizeof (sysDir)); - libDir = sysDir; - -#elif defined (TC_MACOSX) - libDir = "/usr/local/lib"; -#elif defined (TC_UNIX) - libDir = "/usr/lib"; -#endif - - Gui->ShowInfo ("SELECT_PKCS11_MODULE_HELP"); - - FilePathList files = Gui->SelectFiles (this, LangString["SELECT_PKCS11_MODULE"], false, false, extensions, libDir); - if (!files.empty()) - Pkcs11ModulePathTextCtrl->SetValue (wstring (*files.front())); - } - - void PreferencesDialog::OnTimer () - { -#ifdef TC_WINDOWS - for (UINT vKey = 0; vKey <= 0xFF; vKey++) - { - if (GetAsyncKeyState (vKey) < 0) - { - bool shift = wxGetKeyState (WXK_SHIFT); - bool control = wxGetKeyState (WXK_CONTROL); - bool alt = wxGetKeyState (WXK_ALT); - bool win = wxGetKeyState (WXK_WINDOWS_LEFT) || wxGetKeyState (WXK_WINDOWS_RIGHT); - - if (!Hotkey::GetVirtualKeyCodeString (vKey).empty()) // If the key is allowed and its name has been resolved - { - LastVirtualKeyPressed = vKey; - - HotkeyShiftCheckBox->SetValue (shift); - HotkeyControlCheckBox->SetValue (control); - HotkeyAltCheckBox->SetValue (alt); - HotkeyWinCheckBox->SetValue (win); - - HotkeyTextCtrl->ChangeValue (Hotkey::GetVirtualKeyCodeString (LastVirtualKeyPressed)); - UpdateHotkeyButtons(); - return; - } - } - } -#endif - } - - void PreferencesDialog::UpdateHotkeyButtons() - { - AssignHotkeyButton->Enable (!HotkeyTextCtrl->IsEmpty() && HotkeyListCtrl->GetSelectedItemCount() > 0); - - bool remove = false; - foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) - { - if (reinterpret_cast (HotkeyListCtrl->GetItemData (item))->VirtualKeyCode != 0) - remove = true; - } - RemoveHotkeyButton->Enable (remove); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include +#ifdef TC_WINDOWS +#include +#endif +#include "Common/SecurityToken.h" +#include "Main/Main.h" +#include "Main/Application.h" +#include "Main/GraphicUserInterface.h" +#include "PreferencesDialog.h" + +namespace TrueCrypt +{ + PreferencesDialog::PreferencesDialog (wxWindow* parent) + : PreferencesDialogBase (parent), + LastVirtualKeyPressed (0), + Preferences (Gui->GetPreferences()), + RestoreValidatorBell (false) + { +#define TC_CHECK_BOX_VALIDATOR(NAME) (TC_JOIN(NAME,CheckBox))->SetValidator (wxGenericValidator (&Preferences.NAME)); + + // Security + TC_CHECK_BOX_VALIDATOR (DismountOnLogOff); + TC_CHECK_BOX_VALIDATOR (DismountOnPowerSaving); + TC_CHECK_BOX_VALIDATOR (DismountOnScreenSaver); + TC_CHECK_BOX_VALIDATOR (DismountOnInactivity); + DismountOnInactivitySpinCtrl->SetValidator (wxGenericValidator (&Preferences.MaxVolumeIdleTime)); + TC_CHECK_BOX_VALIDATOR (ForceAutoDismount); + PreserveTimestampsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.PreserveTimestamps)); + TC_CHECK_BOX_VALIDATOR (WipeCacheOnAutoDismount); + TC_CHECK_BOX_VALIDATOR (WipeCacheOnClose); + + // Mount options + CachePasswordsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.CachePassword)); + MountReadOnlyCheckBox->SetValue (Preferences.DefaultMountOptions.Protection == VolumeProtection::ReadOnly); + MountRemovableCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.Removable)); + + FilesystemOptionsTextCtrl->SetValue (Preferences.DefaultMountOptions.FilesystemOptions); + + // Keyfiles + TC_CHECK_BOX_VALIDATOR (UseKeyfiles); + + DefaultKeyfilesPanel = new KeyfilesPanel (DefaultKeyfilesPage, make_shared (Preferences.DefaultKeyfiles)); + DefaultKeyfilesSizer->Add (DefaultKeyfilesPanel, 1, wxALL | wxEXPAND); + DefaultKeyfilesSizer->Layout(); + + TC_CHECK_BOX_VALIDATOR (BackgroundTaskEnabled); + TC_CHECK_BOX_VALIDATOR (CloseBackgroundTaskOnNoVolumes); + CloseBackgroundTaskOnNoVolumesCheckBox->Show (!Core->IsInPortableMode()); + TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuDismountItemsEnabled); + TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuMountItemsEnabled); + TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuOpenItemsEnabled); + + // Security tokens + Pkcs11ModulePathTextCtrl->SetValue (wstring (Preferences.SecurityTokenModule)); + TC_CHECK_BOX_VALIDATOR (CloseSecurityTokenSessionsAfterMount); + + // System integration + TC_CHECK_BOX_VALIDATOR (StartOnLogon); + TC_CHECK_BOX_VALIDATOR (MountDevicesOnLogon); + TC_CHECK_BOX_VALIDATOR (MountFavoritesOnLogon); + + TC_CHECK_BOX_VALIDATOR (CloseExplorerWindowsOnDismount); + TC_CHECK_BOX_VALIDATOR (OpenExplorerWindowAfterMount); + + NoKernelCryptoCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.NoKernelCrypto)); + +#ifdef TC_WINDOWS + // Hotkeys + TC_CHECK_BOX_VALIDATOR (BeepAfterHotkeyMountDismount); + TC_CHECK_BOX_VALIDATOR (DisplayMessageAfterHotkeyDismount); +#endif + + TransferDataToWindow(); // Code below relies on TransferDataToWindow() called at this point + +#if defined (TC_WINDOWS) || defined (TC_MACOSX) + FilesystemSizer->Show (false); +#else + // Auto-dismount is not supported on Linux as dismount may require the user to enter admin password + AutoDismountSizer->Show (false); + WipeCacheOnAutoDismountCheckBox->Show (false); +#endif + +#ifndef TC_WINDOWS + LogOnSizer->Show (false); + MountRemovableCheckBox->Show (false); + CloseExplorerWindowsOnDismountCheckBox->Show (false); +#endif + +#ifndef wxHAS_POWER_EVENTS + DismountOnPowerSavingCheckBox->Show (false); +#endif + +#ifdef TC_MACOSX + DismountOnScreenSaverCheckBox->Show (false); + DismountOnLogOffCheckBox->SetLabel (_("TrueCrypt quits")); + OpenExplorerWindowAfterMountCheckBox->SetLabel (_("Open Finder window for successfully mounted volume")); + + MountRemovableCheckBox->Show (false); + FilesystemSizer->Show (false); + LogOnSizer->Show (false); + CloseExplorerWindowsOnDismountCheckBox->Show (false); +#endif + +#ifndef TC_LINUX + KernelServicesSizer->Show (false); +#endif + +#ifdef TC_WINDOWS + // Hotkeys + list colPermilles; + HotkeyListCtrl->InsertColumn (ColumnHotkeyDescription, LangString["ACTION"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (642); + HotkeyListCtrl->InsertColumn (ColumnHotkey, LangString["SHORTCUT"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (358); + + vector fields (HotkeyListCtrl->GetColumnCount()); + + UnregisteredHotkeys = Preferences.Hotkeys; + Hotkey::UnregisterList (Gui->GetMainFrame(), UnregisteredHotkeys); + + foreach (shared_ptr hotkey, Preferences.Hotkeys) + { + fields[ColumnHotkeyDescription] = hotkey->Description; + fields[ColumnHotkey] = hotkey->GetShortcutString(); + Gui->AppendToListCtrl (HotkeyListCtrl, fields, -1, hotkey.get()); + } + + Gui->SetListCtrlHeight (HotkeyListCtrl, 5); + + Layout(); + Fit(); + Gui->SetListCtrlColumnWidths (HotkeyListCtrl, colPermilles); + + RestoreValidatorBell = !wxTextValidator::IsSilent(); + wxTextValidator::SetBellOnError (true); + HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_INCLUDE_CHAR_LIST)); + + UpdateHotkeyButtons(); +#endif + + // Page setup + for (size_t page = 0; page < PreferencesNotebook->GetPageCount(); page++) + { + wxNotebookPage *np = PreferencesNotebook->GetPage (page); + if (np == HotkeysPage) + { +#ifndef TC_WINDOWS + PreferencesNotebook->RemovePage (page--); + continue; +#endif + } + + np->Layout(); + } + + Layout(); + Fit(); + Center(); + + StdButtonsOK->SetDefault(); + +#ifdef TC_WINDOWS + // Hotkey timer + class Timer : public wxTimer + { + public: + Timer (PreferencesDialog *dialog) : Dialog (dialog) { } + + void Notify() + { + Dialog->OnTimer(); + } + + PreferencesDialog *Dialog; + }; + + mTimer.reset (dynamic_cast (new Timer (this))); + mTimer->Start (25); +#endif + } + + PreferencesDialog::~PreferencesDialog () + { + if (RestoreValidatorBell) + wxTextValidator::SetBellOnError (false); + } + + void PreferencesDialog::SelectPage (wxPanel *page) + { + for (size_t pageIndex = 0; pageIndex < PreferencesNotebook->GetPageCount(); pageIndex++) + { + if (PreferencesNotebook->GetPage (pageIndex) == page) + PreferencesNotebook->ChangeSelection (pageIndex); + } + } + + void PreferencesDialog::OnAssignHotkeyButtonClick (wxCommandEvent& event) + { +#ifdef TC_WINDOWS + foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) + { + Hotkey *hotkey = reinterpret_cast (HotkeyListCtrl->GetItemData (item)); + + int mods = 0; + mods |= HotkeyShiftCheckBox->IsChecked() ? wxMOD_SHIFT : 0; + mods |= HotkeyControlCheckBox->IsChecked() ? wxMOD_CONTROL : 0; + mods |= HotkeyAltCheckBox->IsChecked() ? wxMOD_ALT : 0; + mods |= HotkeyWinCheckBox->IsChecked() ? wxMOD_WIN : 0; + + // F1 is help and F12 is reserved for use by the debugger at all times + if (mods == 0 && (LastVirtualKeyPressed == VK_F1 || LastVirtualKeyPressed == VK_F12)) + { + Gui->ShowError ("CANNOT_USE_RESERVED_KEY"); + return; + } + + // Test if the hotkey can be registered + if (!this->RegisterHotKey (hotkey->Id, mods, LastVirtualKeyPressed)) + { + Gui->ShowError (SystemException (SRC_POS)); + return; + } + UnregisterHotKey (hotkey->Id); + + foreach_ref (const Hotkey &h, Preferences.Hotkeys) + { + if (h.Id != hotkey->Id && h.VirtualKeyCode == LastVirtualKeyPressed && h.VirtualKeyModifiers == mods) + { + Gui->ShowError ("SHORTCUT_ALREADY_IN_USE"); + return; + } + } + + hotkey->VirtualKeyCode = LastVirtualKeyPressed; + hotkey->VirtualKeyModifiers = mods; + + vector fields (HotkeyListCtrl->GetColumnCount()); + fields[ColumnHotkeyDescription] = hotkey->Description; + fields[ColumnHotkey] = hotkey->GetShortcutString(); + Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields); + + UpdateHotkeyButtons(); + } +#endif // TC_WINDOWS + } + + void PreferencesDialog::OnBackgroundTaskEnabledCheckBoxClick (wxCommandEvent& event) + { + if (!event.IsChecked()) + BackgroundTaskEnabledCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_BACKGROUND_TASK_DISABLED"], false, true)); + } + + void PreferencesDialog::OnNoKernelCryptoCheckBoxClick (wxCommandEvent& event) + { + if (event.IsChecked()) + NoKernelCryptoCheckBox->SetValue (Gui->AskYesNo (_("Disabling the use of kernel cryptographic services can degrade performance.\n\nAre you sure?"), false, true)); + } + + void PreferencesDialog::OnClose (wxCloseEvent& event) + { +#ifdef TC_WINDOWS + Hotkey::RegisterList (Gui->GetMainFrame(), UnregisteredHotkeys); +#endif + event.Skip(); + } + + void PreferencesDialog::OnDismountOnPowerSavingCheckBoxClick (wxCommandEvent& event) + { + if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked()) + Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT"); + } + + void PreferencesDialog::OnDismountOnScreenSaverCheckBoxClick (wxCommandEvent& event) + { + if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked()) + Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT"); + } + + void PreferencesDialog::OnForceAutoDismountCheckBoxClick (wxCommandEvent& event) + { + if (!event.IsChecked()) + ForceAutoDismountCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_NO_FORCED_AUTODISMOUNT"], false, true)); + } + + void PreferencesDialog::OnHotkeyListItemDeselected (wxListEvent& event) + { + UpdateHotkeyButtons(); + } + + void PreferencesDialog::OnHotkeyListItemSelected (wxListEvent& event) + { + UpdateHotkeyButtons(); + HotkeyTextCtrl->ChangeValue (LangString ["PRESS_A_KEY_TO_ASSIGN"]); + AssignHotkeyButton->Enable (false); + } + + void PreferencesDialog::OnOKButtonClick (wxCommandEvent& event) + { +#ifdef TC_WINDOWS + HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_NONE)); +#endif + if (!Validate()) + return; + + TransferDataFromWindow(); + + Preferences.DefaultMountOptions.Protection = MountReadOnlyCheckBox->IsChecked() ? VolumeProtection::ReadOnly : VolumeProtection::None; + Preferences.DefaultMountOptions.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue(); + Preferences.DefaultKeyfiles = *DefaultKeyfilesPanel->GetKeyfiles(); + + bool securityTokenModuleChanged = (Preferences.SecurityTokenModule != wstring (Pkcs11ModulePathTextCtrl->GetValue())); + Preferences.SecurityTokenModule = wstring (Pkcs11ModulePathTextCtrl->GetValue()); + + Gui->SetPreferences (Preferences); + + try + { + if (securityTokenModuleChanged) + { + if (Preferences.SecurityTokenModule.IsEmpty()) + { + if (SecurityToken::IsInitialized()) + SecurityToken::CloseLibrary (); + } + else + { + Gui->InitSecurityTokenLibrary(); + } + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + +#ifdef TC_WINDOWS + // Log on actions + wxString logonKey = wxString (L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Curren") + L"tVersion\\Run"; // Splitted to prevent false antivirus heuristic alerts + if (Preferences.StartOnLogon || Preferences.MountDevicesOnLogon || Preferences.MountFavoritesOnLogon) + { + auto_ptr regKey (new wxRegKey (logonKey)); + throw_sys_sub_if (!regKey.get(), wstring (logonKey)); + + wxString cmdLine = wstring (L"\"") + wstring (Application::GetExecutablePath()) + L"\" --load-preferences"; + + wxString autoMount; + if (Preferences.MountDevicesOnLogon) + autoMount += L"devices"; + if (Preferences.MountFavoritesOnLogon) + { + if (!autoMount.empty()) + autoMount += L","; + autoMount += L"favorites"; + } + + if (!autoMount.empty()) + cmdLine += wxString (L" --auto-mount=") + autoMount; + + if (Preferences.StartOnLogon) + cmdLine += L" --background-task"; + + throw_sys_sub_if (!regKey->SetValue (Application::GetName().c_str(), cmdLine), wstring (logonKey)); + } + else + { + auto_ptr regKey (new wxRegKey (logonKey)); + regKey->DeleteValue (Application::GetName().c_str()); + } + + // Hotkeys + Hotkey::RegisterList (Gui->GetMainFrame(), Preferences.Hotkeys); +#endif + + EndModal (wxID_OK); + } + + void PreferencesDialog::OnPreserveTimestampsCheckBoxClick (wxCommandEvent& event) + { + if (!event.IsChecked()) + { + bool confirmed = Gui->AskYesNo (LangString["CONFIRM_TIMESTAMP_UPDATING"], false, true); + PreserveTimestampsCheckBox->SetValue (!confirmed); +#ifdef TC_LINUX + if (confirmed) + Gui->ShowInfo (_("Please note that disabling this option may have no effect on volumes mounted using kernel cryptographic services.")); +#endif + } + } + + void PreferencesDialog::OnRemoveHotkeyButtonClick (wxCommandEvent& event) + { +#ifdef TC_WINDOWS + foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) + { + Hotkey *hotkey = reinterpret_cast (HotkeyListCtrl->GetItemData (item)); + hotkey->VirtualKeyCode = 0; + hotkey->VirtualKeyModifiers = 0; + + vector fields (HotkeyListCtrl->GetColumnCount()); + fields[ColumnHotkeyDescription] = hotkey->Description; + fields[ColumnHotkey] = hotkey->GetShortcutString(); + Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields); + + UpdateHotkeyButtons(); + } +#endif + } + + void PreferencesDialog::OnSelectPkcs11ModuleButtonClick (wxCommandEvent& event) + { + list < pair > extensions; + wxString libExtension; + libExtension = wxDynamicLibrary::CanonicalizeName (L"x"); + +#ifdef TC_MACOSX + extensions.push_back (make_pair (L"dylib", LangString["DLL_FILES"])); +#endif + if (!libExtension.empty()) + { + extensions.push_back (make_pair (libExtension.Mid (libExtension.find (L'.') + 1), LangString["DLL_FILES"])); + extensions.push_back (make_pair (L"*", L"")); + } + + string libDir; + +#ifdef TC_WINDOWS + + char sysDir[TC_MAX_PATH]; + GetSystemDirectoryA (sysDir, sizeof (sysDir)); + libDir = sysDir; + +#elif defined (TC_MACOSX) + libDir = "/usr/local/lib"; +#elif defined (TC_UNIX) + libDir = "/usr/lib"; +#endif + + Gui->ShowInfo ("SELECT_PKCS11_MODULE_HELP"); + + FilePathList files = Gui->SelectFiles (this, LangString["SELECT_PKCS11_MODULE"], false, false, extensions, libDir); + if (!files.empty()) + Pkcs11ModulePathTextCtrl->SetValue (wstring (*files.front())); + } + + void PreferencesDialog::OnTimer () + { +#ifdef TC_WINDOWS + for (UINT vKey = 0; vKey <= 0xFF; vKey++) + { + if (GetAsyncKeyState (vKey) < 0) + { + bool shift = wxGetKeyState (WXK_SHIFT); + bool control = wxGetKeyState (WXK_CONTROL); + bool alt = wxGetKeyState (WXK_ALT); + bool win = wxGetKeyState (WXK_WINDOWS_LEFT) || wxGetKeyState (WXK_WINDOWS_RIGHT); + + if (!Hotkey::GetVirtualKeyCodeString (vKey).empty()) // If the key is allowed and its name has been resolved + { + LastVirtualKeyPressed = vKey; + + HotkeyShiftCheckBox->SetValue (shift); + HotkeyControlCheckBox->SetValue (control); + HotkeyAltCheckBox->SetValue (alt); + HotkeyWinCheckBox->SetValue (win); + + HotkeyTextCtrl->ChangeValue (Hotkey::GetVirtualKeyCodeString (LastVirtualKeyPressed)); + UpdateHotkeyButtons(); + return; + } + } + } +#endif + } + + void PreferencesDialog::UpdateHotkeyButtons() + { + AssignHotkeyButton->Enable (!HotkeyTextCtrl->IsEmpty() && HotkeyListCtrl->GetSelectedItemCount() > 0); + + bool remove = false; + foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) + { + if (reinterpret_cast (HotkeyListCtrl->GetItemData (item))->VirtualKeyCode != 0) + remove = true; + } + RemoveHotkeyButton->Enable (remove); + } +} diff --git a/Main/Forms/PreferencesDialog.h b/Main/Forms/PreferencesDialog.h index 93aa614..b326ef7 100644 --- a/Main/Forms/PreferencesDialog.h +++ b/Main/Forms/PreferencesDialog.h @@ -1,59 +1,59 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_PreferencesDialog -#define TC_HEADER_Main_Forms_PreferencesDialog - -#include "Forms.h" -#include "Main/Main.h" -#include "KeyfilesPanel.h" - -namespace TrueCrypt -{ - class PreferencesDialog : public PreferencesDialogBase - { - public: - PreferencesDialog (wxWindow* parent); - ~PreferencesDialog (); - - void SelectPage (wxPanel *page); - - protected: - void OnAssignHotkeyButtonClick (wxCommandEvent& event); - void OnBackgroundTaskEnabledCheckBoxClick (wxCommandEvent& event); - void OnCancelButtonClick (wxCommandEvent& event) { Close(); } - void OnClose (wxCloseEvent& event); - void OnDismountOnPowerSavingCheckBoxClick (wxCommandEvent& event); - void OnDismountOnScreenSaverCheckBoxClick (wxCommandEvent& event); - void OnForceAutoDismountCheckBoxClick (wxCommandEvent& event); - void OnHotkeyListItemDeselected (wxListEvent& event); - void OnHotkeyListItemSelected (wxListEvent& event); - void OnNoKernelCryptoCheckBoxClick (wxCommandEvent& event); - void OnOKButtonClick (wxCommandEvent& event); - void OnPreserveTimestampsCheckBoxClick (wxCommandEvent& event); - void OnRemoveHotkeyButtonClick (wxCommandEvent& event); - void OnSelectPkcs11ModuleButtonClick (wxCommandEvent& event); - void OnTimer (); - void UpdateHotkeyButtons(); - - enum - { - ColumnHotkeyDescription = 0, - ColumnHotkey - }; - - KeyfilesPanel *DefaultKeyfilesPanel; - int LastVirtualKeyPressed; - auto_ptr mTimer; - UserPreferences Preferences; - bool RestoreValidatorBell; - HotkeyList UnregisteredHotkeys; - }; -} - -#endif // TC_HEADER_Main_Forms_PreferencesDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_PreferencesDialog +#define TC_HEADER_Main_Forms_PreferencesDialog + +#include "Forms.h" +#include "Main/Main.h" +#include "KeyfilesPanel.h" + +namespace TrueCrypt +{ + class PreferencesDialog : public PreferencesDialogBase + { + public: + PreferencesDialog (wxWindow* parent); + ~PreferencesDialog (); + + void SelectPage (wxPanel *page); + + protected: + void OnAssignHotkeyButtonClick (wxCommandEvent& event); + void OnBackgroundTaskEnabledCheckBoxClick (wxCommandEvent& event); + void OnCancelButtonClick (wxCommandEvent& event) { Close(); } + void OnClose (wxCloseEvent& event); + void OnDismountOnPowerSavingCheckBoxClick (wxCommandEvent& event); + void OnDismountOnScreenSaverCheckBoxClick (wxCommandEvent& event); + void OnForceAutoDismountCheckBoxClick (wxCommandEvent& event); + void OnHotkeyListItemDeselected (wxListEvent& event); + void OnHotkeyListItemSelected (wxListEvent& event); + void OnNoKernelCryptoCheckBoxClick (wxCommandEvent& event); + void OnOKButtonClick (wxCommandEvent& event); + void OnPreserveTimestampsCheckBoxClick (wxCommandEvent& event); + void OnRemoveHotkeyButtonClick (wxCommandEvent& event); + void OnSelectPkcs11ModuleButtonClick (wxCommandEvent& event); + void OnTimer (); + void UpdateHotkeyButtons(); + + enum + { + ColumnHotkeyDescription = 0, + ColumnHotkey + }; + + KeyfilesPanel *DefaultKeyfilesPanel; + int LastVirtualKeyPressed; + auto_ptr mTimer; + UserPreferences Preferences; + bool RestoreValidatorBell; + HotkeyList UnregisteredHotkeys; + }; +} + +#endif // TC_HEADER_Main_Forms_PreferencesDialog diff --git a/Main/Forms/ProgressWizardPage.cpp b/Main/Forms/ProgressWizardPage.cpp index f8d55eb..2349023 100644 --- a/Main/Forms/ProgressWizardPage.cpp +++ b/Main/Forms/ProgressWizardPage.cpp @@ -1,80 +1,80 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "ProgressWizardPage.h" - -namespace TrueCrypt -{ - ProgressWizardPage::ProgressWizardPage (wxPanel* parent, bool enableAbort) - : ProgressWizardPageBase (parent), - PreviousGaugeValue (0), - ProgressBarRange (1), - RealProgressBarRange (1) - { -#ifdef TC_MACOSX - ProgressGauge->SetMinSize (wxSize (-1, 12)); // OS X apparently supports only up to 12px thick progress bars -#else - ProgressGauge->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 2)); -#endif - - ProgressValue.Set (0); - ProgressGauge->SetValue (0); - - AbortButton->Show (enableAbort); - - class Timer : public wxTimer - { - public: - Timer (ProgressWizardPage *page) : Page (page) { } - - void Notify() - { - Page->OnTimer(); - } - - ProgressWizardPage *Page; - }; - - mTimer.reset (dynamic_cast (new Timer (this))); - mTimer->Start (30); - } - - void ProgressWizardPage::OnAbortButtonClick (wxCommandEvent& event) - { - AbortEvent.Raise(); - } - - void ProgressWizardPage::OnTimer () - { - uint64 value = ProgressValue.Get(); - int gaugeValue = static_cast (value * RealProgressBarRange / ProgressBarRange); - - if (value == ProgressBarRange) - gaugeValue = RealProgressBarRange; // Prevent round-off error - - if (gaugeValue != PreviousGaugeValue) - { - ProgressGauge->SetValue (gaugeValue); - PreviousGaugeValue = gaugeValue; - } - } - - void ProgressWizardPage::SetMaxStaticTextWidth (int width) - { - InfoStaticText->Wrap (width); - } - - void ProgressWizardPage::SetProgressRange (uint64 progressBarRange) - { - ProgressBarRange = progressBarRange; - RealProgressBarRange = ProgressGauge->GetSize().GetWidth(); - ProgressGauge->SetRange (RealProgressBarRange); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "ProgressWizardPage.h" + +namespace TrueCrypt +{ + ProgressWizardPage::ProgressWizardPage (wxPanel* parent, bool enableAbort) + : ProgressWizardPageBase (parent), + PreviousGaugeValue (0), + ProgressBarRange (1), + RealProgressBarRange (1) + { +#ifdef TC_MACOSX + ProgressGauge->SetMinSize (wxSize (-1, 12)); // OS X apparently supports only up to 12px thick progress bars +#else + ProgressGauge->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 2)); +#endif + + ProgressValue.Set (0); + ProgressGauge->SetValue (0); + + AbortButton->Show (enableAbort); + + class Timer : public wxTimer + { + public: + Timer (ProgressWizardPage *page) : Page (page) { } + + void Notify() + { + Page->OnTimer(); + } + + ProgressWizardPage *Page; + }; + + mTimer.reset (dynamic_cast (new Timer (this))); + mTimer->Start (30); + } + + void ProgressWizardPage::OnAbortButtonClick (wxCommandEvent& event) + { + AbortEvent.Raise(); + } + + void ProgressWizardPage::OnTimer () + { + uint64 value = ProgressValue.Get(); + int gaugeValue = static_cast (value * RealProgressBarRange / ProgressBarRange); + + if (value == ProgressBarRange) + gaugeValue = RealProgressBarRange; // Prevent round-off error + + if (gaugeValue != PreviousGaugeValue) + { + ProgressGauge->SetValue (gaugeValue); + PreviousGaugeValue = gaugeValue; + } + } + + void ProgressWizardPage::SetMaxStaticTextWidth (int width) + { + InfoStaticText->Wrap (width); + } + + void ProgressWizardPage::SetProgressRange (uint64 progressBarRange) + { + ProgressBarRange = progressBarRange; + RealProgressBarRange = ProgressGauge->GetSize().GetWidth(); + ProgressGauge->SetRange (RealProgressBarRange); + } +} diff --git a/Main/Forms/ProgressWizardPage.h b/Main/Forms/ProgressWizardPage.h index ade4242..3d02232 100644 --- a/Main/Forms/ProgressWizardPage.h +++ b/Main/Forms/ProgressWizardPage.h @@ -1,42 +1,42 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_ProgressWizardPage -#define TC_HEADER_Main_Forms_ProgressWizardPage - -#include "Forms.h" - -namespace TrueCrypt -{ - class ProgressWizardPage : public ProgressWizardPageBase - { - public: - ProgressWizardPage (wxPanel* parent, bool enableAbort = false); - ~ProgressWizardPage () { } - - void EnableAbort (bool enable = true) { AbortButton->Enable (enable); } - bool IsValid () { return true; } - void SetMaxStaticTextWidth (int width); - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - void SetProgressRange (uint64 progressBarRange); - - Event AbortEvent; - SharedVal ProgressValue; - - protected: - void OnAbortButtonClick (wxCommandEvent& event); - void OnTimer (); - - auto_ptr mTimer; - int PreviousGaugeValue; - uint64 ProgressBarRange; - int RealProgressBarRange; - }; -} - -#endif // TC_HEADER_Main_Forms_ProgressWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_ProgressWizardPage +#define TC_HEADER_Main_Forms_ProgressWizardPage + +#include "Forms.h" + +namespace TrueCrypt +{ + class ProgressWizardPage : public ProgressWizardPageBase + { + public: + ProgressWizardPage (wxPanel* parent, bool enableAbort = false); + ~ProgressWizardPage () { } + + void EnableAbort (bool enable = true) { AbortButton->Enable (enable); } + bool IsValid () { return true; } + void SetMaxStaticTextWidth (int width); + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + void SetProgressRange (uint64 progressBarRange); + + Event AbortEvent; + SharedVal ProgressValue; + + protected: + void OnAbortButtonClick (wxCommandEvent& event); + void OnTimer (); + + auto_ptr mTimer; + int PreviousGaugeValue; + uint64 ProgressBarRange; + int RealProgressBarRange; + }; +} + +#endif // TC_HEADER_Main_Forms_ProgressWizardPage diff --git a/Main/Forms/RandomPoolEnrichmentDialog.cpp b/Main/Forms/RandomPoolEnrichmentDialog.cpp index 0ca8d81..3954744 100644 --- a/Main/Forms/RandomPoolEnrichmentDialog.cpp +++ b/Main/Forms/RandomPoolEnrichmentDialog.cpp @@ -1,93 +1,93 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "Volume/Hash.h" -#include "RandomPoolEnrichmentDialog.h" - -namespace TrueCrypt -{ - RandomPoolEnrichmentDialog::RandomPoolEnrichmentDialog (wxWindow* parent) : RandomPoolEnrichmentDialogBase (parent) - { - RandomNumberGenerator::Start(); - - Hashes = Hash::GetAvailableAlgorithms(); - foreach (shared_ptr hash, Hashes) - { - if (!hash->IsDeprecated()) - { - HashChoice->Append (hash->GetName(), hash.get()); - - if (typeid (*hash) == typeid (*RandomNumberGenerator::GetHash())) - HashChoice->Select (HashChoice->GetCount() - 1); - } - } - - ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); - MouseStaticText->Wrap (Gui->GetCharWidth (MouseStaticText) * 70); - - MainSizer->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 24)); - - Layout(); - Fit(); - Center(); - - foreach (wxWindow *c, this->GetChildren()) - c->Connect (wxEVT_MOTION, wxMouseEventHandler (RandomPoolEnrichmentDialog::OnMouseMotion), nullptr, this); - } - - RandomPoolEnrichmentDialog::~RandomPoolEnrichmentDialog () - { - } - - void RandomPoolEnrichmentDialog::OnHashSelected (wxCommandEvent& event) - { - RandomNumberGenerator::SetHash (Gui->GetSelectedData (HashChoice)->GetNew()); - } - - void RandomPoolEnrichmentDialog::OnMouseMotion (wxMouseEvent& event) - { - event.Skip(); - - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&event), sizeof (event))); - - long coord = event.GetX(); - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); - coord = event.GetY(); - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); - - if (ShowRandomPoolCheckBox->IsChecked()) - ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); - } - - void RandomPoolEnrichmentDialog::OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event) - { - if (!event.IsChecked()) - RandomPoolStaticText->SetLabel (L""); - } - - void RandomPoolEnrichmentDialog::ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer) - { - wxString str; - - for (size_t i = 0; i < buffer.Size(); ++i) - { - str += wxString::Format (L"%02X", buffer[i]); - } - - str += L".."; - - textCtrl->SetLabel (str.c_str()); - - for (size_t i = 0; i < str.size(); ++i) - { - str[i] = L'X'; - } - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "Volume/Hash.h" +#include "RandomPoolEnrichmentDialog.h" + +namespace TrueCrypt +{ + RandomPoolEnrichmentDialog::RandomPoolEnrichmentDialog (wxWindow* parent) : RandomPoolEnrichmentDialogBase (parent) + { + RandomNumberGenerator::Start(); + + Hashes = Hash::GetAvailableAlgorithms(); + foreach (shared_ptr hash, Hashes) + { + if (!hash->IsDeprecated()) + { + HashChoice->Append (hash->GetName(), hash.get()); + + if (typeid (*hash) == typeid (*RandomNumberGenerator::GetHash())) + HashChoice->Select (HashChoice->GetCount() - 1); + } + } + + ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); + MouseStaticText->Wrap (Gui->GetCharWidth (MouseStaticText) * 70); + + MainSizer->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 24)); + + Layout(); + Fit(); + Center(); + + foreach (wxWindow *c, this->GetChildren()) + c->Connect (wxEVT_MOTION, wxMouseEventHandler (RandomPoolEnrichmentDialog::OnMouseMotion), nullptr, this); + } + + RandomPoolEnrichmentDialog::~RandomPoolEnrichmentDialog () + { + } + + void RandomPoolEnrichmentDialog::OnHashSelected (wxCommandEvent& event) + { + RandomNumberGenerator::SetHash (Gui->GetSelectedData (HashChoice)->GetNew()); + } + + void RandomPoolEnrichmentDialog::OnMouseMotion (wxMouseEvent& event) + { + event.Skip(); + + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&event), sizeof (event))); + + long coord = event.GetX(); + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); + coord = event.GetY(); + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); + + if (ShowRandomPoolCheckBox->IsChecked()) + ShowBytes (RandomPoolStaticText, RandomNumberGenerator::PeekPool().GetRange (0, 24)); + } + + void RandomPoolEnrichmentDialog::OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event) + { + if (!event.IsChecked()) + RandomPoolStaticText->SetLabel (L""); + } + + void RandomPoolEnrichmentDialog::ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer) + { + wxString str; + + for (size_t i = 0; i < buffer.Size(); ++i) + { + str += wxString::Format (L"%02X", buffer[i]); + } + + str += L".."; + + textCtrl->SetLabel (str.c_str()); + + for (size_t i = 0; i < str.size(); ++i) + { + str[i] = L'X'; + } + } +} diff --git a/Main/Forms/RandomPoolEnrichmentDialog.h b/Main/Forms/RandomPoolEnrichmentDialog.h index cf75840..71da682 100644 --- a/Main/Forms/RandomPoolEnrichmentDialog.h +++ b/Main/Forms/RandomPoolEnrichmentDialog.h @@ -1,33 +1,33 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_RandomPoolEnrichmentDialog -#define TC_HEADER_Main_Forms_RandomPoolEnrichmentDialog - -#include "Forms.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class RandomPoolEnrichmentDialog : public RandomPoolEnrichmentDialogBase - { - public: - RandomPoolEnrichmentDialog (wxWindow* parent); - ~RandomPoolEnrichmentDialog (); - - protected: - void OnHashSelected (wxCommandEvent& event); - void OnMouseMotion (wxMouseEvent& event); - void OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event); - void ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer); - - HashList Hashes; - }; -} - -#endif // TC_HEADER_Main_Forms_RandomPoolEnrichmentDialog +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_RandomPoolEnrichmentDialog +#define TC_HEADER_Main_Forms_RandomPoolEnrichmentDialog + +#include "Forms.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class RandomPoolEnrichmentDialog : public RandomPoolEnrichmentDialogBase + { + public: + RandomPoolEnrichmentDialog (wxWindow* parent); + ~RandomPoolEnrichmentDialog (); + + protected: + void OnHashSelected (wxCommandEvent& event); + void OnMouseMotion (wxMouseEvent& event); + void OnShowRandomPoolCheckBoxClicked (wxCommandEvent& event); + void ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer); + + HashList Hashes; + }; +} + +#endif // TC_HEADER_Main_Forms_RandomPoolEnrichmentDialog diff --git a/Main/Forms/SecurityTokenKeyfilesDialog.cpp b/Main/Forms/SecurityTokenKeyfilesDialog.cpp index dae9afd..2bbac9e 100644 --- a/Main/Forms/SecurityTokenKeyfilesDialog.cpp +++ b/Main/Forms/SecurityTokenKeyfilesDialog.cpp @@ -1,197 +1,197 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "Common/SecurityToken.h" -#include "NewSecurityTokenKeyfileDialog.h" -#include "SecurityTokenKeyfilesDialog.h" - -namespace TrueCrypt -{ - SecurityTokenKeyfilesDialog::SecurityTokenKeyfilesDialog (wxWindow* parent, bool selectionMode) - : SecurityTokenKeyfilesDialogBase (parent) - { - if (selectionMode) - SetTitle (LangString["SELECT_TOKEN_KEYFILES"]); - - list colPermilles; - - SecurityTokenKeyfileListCtrl->InsertColumn (ColumnSecurityTokenSlotId, LangString["TOKEN_SLOT_ID"], wxLIST_FORMAT_CENTER, 1); - colPermilles.push_back (102); - SecurityTokenKeyfileListCtrl->InsertColumn (ColumnSecurityTokenLabel, LangString["TOKEN_NAME"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (368); - SecurityTokenKeyfileListCtrl->InsertColumn (ColumnSecurityTokenKeyfileLabel, LangString["TOKEN_DATA_OBJECT_LABEL"], wxLIST_FORMAT_LEFT, 1); - colPermilles.push_back (529); - - FillSecurityTokenKeyfileListCtrl(); - - Gui->SetListCtrlWidth (SecurityTokenKeyfileListCtrl, 65); - Gui->SetListCtrlHeight (SecurityTokenKeyfileListCtrl, 16); - Gui->SetListCtrlColumnWidths (SecurityTokenKeyfileListCtrl, colPermilles); - - Fit(); - Layout(); - Center(); - - DeleteButton->Disable(); - ExportButton->Disable(); - OKButton->Disable(); - OKButton->SetDefault(); - } - - void SecurityTokenKeyfilesDialog::FillSecurityTokenKeyfileListCtrl () - { - wxBusyCursor busy; - - SecurityTokenKeyfileListCtrl->DeleteAllItems(); - SecurityTokenKeyfileList = SecurityToken::GetAvailableKeyfiles(); - - size_t i = 0; - foreach (const SecurityTokenKeyfile &key, SecurityTokenKeyfileList) - { - vector fields (SecurityTokenKeyfileListCtrl->GetColumnCount()); - - fields[ColumnSecurityTokenSlotId] = StringConverter::ToWide ((uint64) key.SlotId); - fields[ColumnSecurityTokenLabel] = key.Token.Label; - fields[ColumnSecurityTokenKeyfileLabel] = key.Id; - - Gui->AppendToListCtrl (SecurityTokenKeyfileListCtrl, fields, 0, &SecurityTokenKeyfileList[i++]); - } - } - - void SecurityTokenKeyfilesDialog::OnDeleteButtonClick (wxCommandEvent& event) - { - try - { - if (!Gui->AskYesNo (LangString["CONFIRM_SEL_FILES_DELETE"])) - return; - - wxBusyCursor busy; - - foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) - { - SecurityToken::DeleteKeyfile (*reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item))); - } - - FillSecurityTokenKeyfileListCtrl(); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void SecurityTokenKeyfilesDialog::OnExportButtonClick (wxCommandEvent& event) - { - try - { - foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) - { - SecurityTokenKeyfile *keyfile = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item)); - - FilePathList files = Gui->SelectFiles (this, wxEmptyString, true); - - if (!files.empty()) - { - wxBusyCursor busy; - - vector keyfileData; - SecurityToken::GetKeyfileData (*keyfile, keyfileData); - - BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); - finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); - - File keyfile; - keyfile.Open (*files.front(), File::CreateWrite); - keyfile.Write (keyfileDataBuf); - } - else - break; - - Gui->ShowInfo ("KEYFILE_EXPORTED"); - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void SecurityTokenKeyfilesDialog::OnImportButtonClick (wxCommandEvent& event) - { - try - { - FilePathList keyfilePaths = Gui->SelectFiles (this, LangString["SELECT_KEYFILES"], false); - - if (keyfilePaths.empty()) - return; - - FilePath keyfilePath = *keyfilePaths.front(); - - File keyfile; - keyfile.Open (keyfilePath, File::OpenRead, File::ShareReadWrite, File::PreserveTimestamps); - - if (keyfile.Length() > 0) - { - vector keyfileData (keyfile.Length()); - BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); - - keyfile.ReadCompleteBuffer (keyfileDataBuf); - finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); - - NewSecurityTokenKeyfileDialog newKeyfileDialog (this, keyfilePath.ToBaseName()); - - if (newKeyfileDialog.ShowModal() == wxID_OK) - { - wxBusyCursor busy; - SecurityToken::CreateKeyfile (newKeyfileDialog.GetSelectedSlotId(), keyfileData, StringConverter::ToSingle (newKeyfileDialog.GetKeyfileName())); - - FillSecurityTokenKeyfileListCtrl(); - } - } - else - throw InsufficientData (SRC_POS, keyfilePath); - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void SecurityTokenKeyfilesDialog::OnListItemDeselected (wxListEvent& event) - { - if (SecurityTokenKeyfileListCtrl->GetSelectedItemCount() == 0) - { - DeleteButton->Disable(); - ExportButton->Disable(); - OKButton->Disable(); - } - } - - void SecurityTokenKeyfilesDialog::OnListItemSelected (wxListEvent& event) - { - if (event.GetItem().GetData() != nullptr) - { - DeleteButton->Enable(); - ExportButton->Enable(); - OKButton->Enable(); - } - } - - void SecurityTokenKeyfilesDialog::OnOKButtonClick () - { - foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) - { - SecurityTokenKeyfile *key = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item)); - SelectedSecurityTokenKeyfilePaths.push_back (*key); - } - - EndModal (wxID_OK); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "Common/SecurityToken.h" +#include "NewSecurityTokenKeyfileDialog.h" +#include "SecurityTokenKeyfilesDialog.h" + +namespace TrueCrypt +{ + SecurityTokenKeyfilesDialog::SecurityTokenKeyfilesDialog (wxWindow* parent, bool selectionMode) + : SecurityTokenKeyfilesDialogBase (parent) + { + if (selectionMode) + SetTitle (LangString["SELECT_TOKEN_KEYFILES"]); + + list colPermilles; + + SecurityTokenKeyfileListCtrl->InsertColumn (ColumnSecurityTokenSlotId, LangString["TOKEN_SLOT_ID"], wxLIST_FORMAT_CENTER, 1); + colPermilles.push_back (102); + SecurityTokenKeyfileListCtrl->InsertColumn (ColumnSecurityTokenLabel, LangString["TOKEN_NAME"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (368); + SecurityTokenKeyfileListCtrl->InsertColumn (ColumnSecurityTokenKeyfileLabel, LangString["TOKEN_DATA_OBJECT_LABEL"], wxLIST_FORMAT_LEFT, 1); + colPermilles.push_back (529); + + FillSecurityTokenKeyfileListCtrl(); + + Gui->SetListCtrlWidth (SecurityTokenKeyfileListCtrl, 65); + Gui->SetListCtrlHeight (SecurityTokenKeyfileListCtrl, 16); + Gui->SetListCtrlColumnWidths (SecurityTokenKeyfileListCtrl, colPermilles); + + Fit(); + Layout(); + Center(); + + DeleteButton->Disable(); + ExportButton->Disable(); + OKButton->Disable(); + OKButton->SetDefault(); + } + + void SecurityTokenKeyfilesDialog::FillSecurityTokenKeyfileListCtrl () + { + wxBusyCursor busy; + + SecurityTokenKeyfileListCtrl->DeleteAllItems(); + SecurityTokenKeyfileList = SecurityToken::GetAvailableKeyfiles(); + + size_t i = 0; + foreach (const SecurityTokenKeyfile &key, SecurityTokenKeyfileList) + { + vector fields (SecurityTokenKeyfileListCtrl->GetColumnCount()); + + fields[ColumnSecurityTokenSlotId] = StringConverter::ToWide ((uint64) key.SlotId); + fields[ColumnSecurityTokenLabel] = key.Token.Label; + fields[ColumnSecurityTokenKeyfileLabel] = key.Id; + + Gui->AppendToListCtrl (SecurityTokenKeyfileListCtrl, fields, 0, &SecurityTokenKeyfileList[i++]); + } + } + + void SecurityTokenKeyfilesDialog::OnDeleteButtonClick (wxCommandEvent& event) + { + try + { + if (!Gui->AskYesNo (LangString["CONFIRM_SEL_FILES_DELETE"])) + return; + + wxBusyCursor busy; + + foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) + { + SecurityToken::DeleteKeyfile (*reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item))); + } + + FillSecurityTokenKeyfileListCtrl(); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void SecurityTokenKeyfilesDialog::OnExportButtonClick (wxCommandEvent& event) + { + try + { + foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) + { + SecurityTokenKeyfile *keyfile = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item)); + + FilePathList files = Gui->SelectFiles (this, wxEmptyString, true); + + if (!files.empty()) + { + wxBusyCursor busy; + + vector keyfileData; + SecurityToken::GetKeyfileData (*keyfile, keyfileData); + + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); + finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); + + File keyfile; + keyfile.Open (*files.front(), File::CreateWrite); + keyfile.Write (keyfileDataBuf); + } + else + break; + + Gui->ShowInfo ("KEYFILE_EXPORTED"); + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void SecurityTokenKeyfilesDialog::OnImportButtonClick (wxCommandEvent& event) + { + try + { + FilePathList keyfilePaths = Gui->SelectFiles (this, LangString["SELECT_KEYFILES"], false); + + if (keyfilePaths.empty()) + return; + + FilePath keyfilePath = *keyfilePaths.front(); + + File keyfile; + keyfile.Open (keyfilePath, File::OpenRead, File::ShareReadWrite, File::PreserveTimestamps); + + if (keyfile.Length() > 0) + { + vector keyfileData (keyfile.Length()); + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); + + keyfile.ReadCompleteBuffer (keyfileDataBuf); + finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); + + NewSecurityTokenKeyfileDialog newKeyfileDialog (this, keyfilePath.ToBaseName()); + + if (newKeyfileDialog.ShowModal() == wxID_OK) + { + wxBusyCursor busy; + SecurityToken::CreateKeyfile (newKeyfileDialog.GetSelectedSlotId(), keyfileData, StringConverter::ToSingle (newKeyfileDialog.GetKeyfileName())); + + FillSecurityTokenKeyfileListCtrl(); + } + } + else + throw InsufficientData (SRC_POS, keyfilePath); + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void SecurityTokenKeyfilesDialog::OnListItemDeselected (wxListEvent& event) + { + if (SecurityTokenKeyfileListCtrl->GetSelectedItemCount() == 0) + { + DeleteButton->Disable(); + ExportButton->Disable(); + OKButton->Disable(); + } + } + + void SecurityTokenKeyfilesDialog::OnListItemSelected (wxListEvent& event) + { + if (event.GetItem().GetData() != nullptr) + { + DeleteButton->Enable(); + ExportButton->Enable(); + OKButton->Enable(); + } + } + + void SecurityTokenKeyfilesDialog::OnOKButtonClick () + { + foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) + { + SecurityTokenKeyfile *key = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item)); + SelectedSecurityTokenKeyfilePaths.push_back (*key); + } + + EndModal (wxID_OK); + } +} diff --git a/Main/Forms/SecurityTokenKeyfilesDialog.h b/Main/Forms/SecurityTokenKeyfilesDialog.h index a22a12d..781097f 100644 --- a/Main/Forms/SecurityTokenKeyfilesDialog.h +++ b/Main/Forms/SecurityTokenKeyfilesDialog.h @@ -1,47 +1,47 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_SecurityTokenKeyfilesDialog -#define TC_HEADER_Main_Forms_SecurityTokenKeyfilesDialog - -#include "Forms.h" -#include "Common/SecurityToken.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class SecurityTokenKeyfilesDialog : public SecurityTokenKeyfilesDialogBase - { - public: - SecurityTokenKeyfilesDialog (wxWindow* parent, bool selectionMode = true); - list GetSelectedSecurityTokenKeyfilePaths() const { return SelectedSecurityTokenKeyfilePaths; } - - protected: - enum - { - ColumnSecurityTokenSlotId = 0, - ColumnSecurityTokenLabel, - ColumnSecurityTokenKeyfileLabel, - }; - - void FillSecurityTokenKeyfileListCtrl (); - void OnDeleteButtonClick (wxCommandEvent& event); - void OnExportButtonClick (wxCommandEvent& event); - void OnImportButtonClick (wxCommandEvent& event); - void OnListItemActivated (wxListEvent& event) { OnOKButtonClick(); } - void OnListItemDeselected (wxListEvent& event); - void OnListItemSelected (wxListEvent& event); - void OnOKButtonClick (); - void OnOKButtonClick (wxCommandEvent& event) { OnOKButtonClick(); } - - vector SecurityTokenKeyfileList; - list SelectedSecurityTokenKeyfilePaths; - }; -} - -#endif // TC_HEADER_Main_Forms_SecurityTokenKeyfilesDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_SecurityTokenKeyfilesDialog +#define TC_HEADER_Main_Forms_SecurityTokenKeyfilesDialog + +#include "Forms.h" +#include "Common/SecurityToken.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class SecurityTokenKeyfilesDialog : public SecurityTokenKeyfilesDialogBase + { + public: + SecurityTokenKeyfilesDialog (wxWindow* parent, bool selectionMode = true); + list GetSelectedSecurityTokenKeyfilePaths() const { return SelectedSecurityTokenKeyfilePaths; } + + protected: + enum + { + ColumnSecurityTokenSlotId = 0, + ColumnSecurityTokenLabel, + ColumnSecurityTokenKeyfileLabel, + }; + + void FillSecurityTokenKeyfileListCtrl (); + void OnDeleteButtonClick (wxCommandEvent& event); + void OnExportButtonClick (wxCommandEvent& event); + void OnImportButtonClick (wxCommandEvent& event); + void OnListItemActivated (wxListEvent& event) { OnOKButtonClick(); } + void OnListItemDeselected (wxListEvent& event); + void OnListItemSelected (wxListEvent& event); + void OnOKButtonClick (); + void OnOKButtonClick (wxCommandEvent& event) { OnOKButtonClick(); } + + vector SecurityTokenKeyfileList; + list SelectedSecurityTokenKeyfilePaths; + }; +} + +#endif // TC_HEADER_Main_Forms_SecurityTokenKeyfilesDialog diff --git a/Main/Forms/SelectDirectoryWizardPage.cpp b/Main/Forms/SelectDirectoryWizardPage.cpp index ea24049..dbd01ac 100644 --- a/Main/Forms/SelectDirectoryWizardPage.cpp +++ b/Main/Forms/SelectDirectoryWizardPage.cpp @@ -1,32 +1,32 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "SelectDirectoryWizardPage.h" - -namespace TrueCrypt -{ - bool SelectDirectoryWizardPage::IsValid () - { - if (!DirectoryTextCtrl->IsEmpty()) - { - return FilesystemPath (DirectoryTextCtrl->GetValue()).IsDirectory(); - } - - return false; - } - - void SelectDirectoryWizardPage::OnBrowseButtonClick (wxCommandEvent& event) - { - DirectoryPath dir = Gui->SelectDirectory (this); - - if (!dir.IsEmpty()) - DirectoryTextCtrl->SetValue (wstring (dir)); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "SelectDirectoryWizardPage.h" + +namespace TrueCrypt +{ + bool SelectDirectoryWizardPage::IsValid () + { + if (!DirectoryTextCtrl->IsEmpty()) + { + return FilesystemPath (DirectoryTextCtrl->GetValue()).IsDirectory(); + } + + return false; + } + + void SelectDirectoryWizardPage::OnBrowseButtonClick (wxCommandEvent& event) + { + DirectoryPath dir = Gui->SelectDirectory (this); + + if (!dir.IsEmpty()) + DirectoryTextCtrl->SetValue (wstring (dir)); + } +} diff --git a/Main/Forms/SelectDirectoryWizardPage.h b/Main/Forms/SelectDirectoryWizardPage.h index 17dfd20..83af2b2 100644 --- a/Main/Forms/SelectDirectoryWizardPage.h +++ b/Main/Forms/SelectDirectoryWizardPage.h @@ -1,33 +1,33 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_SelectDirectoryWizardPage -#define TC_HEADER_Main_Forms_SelectDirectoryWizardPage - -#include "Forms.h" - -namespace TrueCrypt -{ - class SelectDirectoryWizardPage : public SelectDirectoryWizardPageBase - { - public: - SelectDirectoryWizardPage (wxPanel* parent) : SelectDirectoryWizardPageBase (parent) { } - - DirectoryPath GetDirectory () const { return DirectoryPath (DirectoryTextCtrl->GetValue()); } - bool IsValid (); - void SetDirectory (const DirectoryPath &path) { DirectoryTextCtrl->SetValue (wstring (path)); } - void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - - protected: - void OnBrowseButtonClick (wxCommandEvent& event); - void OnDirectoryTextChanged (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } - }; -} - -#endif // TC_HEADER_Main_Forms_SelectDirectoryWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_SelectDirectoryWizardPage +#define TC_HEADER_Main_Forms_SelectDirectoryWizardPage + +#include "Forms.h" + +namespace TrueCrypt +{ + class SelectDirectoryWizardPage : public SelectDirectoryWizardPageBase + { + public: + SelectDirectoryWizardPage (wxPanel* parent) : SelectDirectoryWizardPageBase (parent) { } + + DirectoryPath GetDirectory () const { return DirectoryPath (DirectoryTextCtrl->GetValue()); } + bool IsValid (); + void SetDirectory (const DirectoryPath &path) { DirectoryTextCtrl->SetValue (wstring (path)); } + void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + + protected: + void OnBrowseButtonClick (wxCommandEvent& event); + void OnDirectoryTextChanged (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } + }; +} + +#endif // TC_HEADER_Main_Forms_SelectDirectoryWizardPage diff --git a/Main/Forms/SingleChoiceWizardPage.h b/Main/Forms/SingleChoiceWizardPage.h index f59df0f..bfdf1ff 100644 --- a/Main/Forms/SingleChoiceWizardPage.h +++ b/Main/Forms/SingleChoiceWizardPage.h @@ -1,116 +1,116 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_SingleChoiceWizardPage -#define TC_HEADER_Main_Forms_SingleChoiceWizardPage - -#include "Forms.h" - -namespace TrueCrypt -{ - template - class SingleChoiceWizardPage : public SingleChoiceWizardPageBase - { - public: - SingleChoiceWizardPage (wxPanel* parent, const wxString &groupBoxText = wxEmptyString, bool choiceTextBold = false) - : SingleChoiceWizardPageBase (parent), - ChoiceTextBold (choiceTextBold) - { - if (!groupBoxText.empty()) - { - OuterChoicesSizer->Remove (ChoicesSizer); - ChoicesSizer = new wxStaticBoxSizer (wxVERTICAL, this, groupBoxText); - OuterChoicesSizer->Add (ChoicesSizer, 0, wxEXPAND, 5); - } - } - - void AddChoice (ChoiceType choice, const wxString &choiceText, const wxString &infoText = wxEmptyString, const wchar_t *infoLinkId = nullptr, const wxString &infoLinkText = wxEmptyString) - { - assert (RadioButtonMap.find (choice) == RadioButtonMap.end()); - - wxRadioButton *radioButton = new wxRadioButton (this, wxID_ANY, choiceText); - if (RadioButtonMap.empty()) - radioButton->SetValue (true); - - RadioButtonMap[choice] = radioButton; - - if (ChoiceTextBold) - { - wxFont buttonFont = radioButton->GetFont(); - buttonFont.SetWeight (wxFONTWEIGHT_BOLD); - radioButton->SetFont (buttonFont); - } - - ChoicesSizer->Add (radioButton, 0, wxALL, 5); - - wxBoxSizer *infoSizer = new wxBoxSizer (wxVERTICAL); - - wxStaticText *infoStaticText = new wxStaticText (this, wxID_ANY, infoText, wxDefaultPosition, wxDefaultSize, 0); - ChoiceInfoTexts.push_back (infoStaticText); - - infoSizer->Add (infoStaticText, 0, wxALL, 5); - ChoicesSizer->Add (infoSizer, 0, wxEXPAND | wxLEFT, Gui->GetCharWidth (this) * 3); - - if (infoLinkId) - { - wxHyperlinkCtrl *hyperlink = Gui->CreateHyperlink (this, infoLinkId, infoLinkText); - infoSizer->Add (hyperlink, 0, wxALL, 5); - hyperlink->Connect (wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler (SingleChoiceWizardPage::OnChoiceHyperlinkClick), nullptr, this); - } - - ChoicesSizer->Add (1, Gui->GetCharHeight (this) * 1, 0, wxEXPAND, 5); - } - - ChoiceType GetSelection () const - { - typedef pair MapPair; - foreach (MapPair p, RadioButtonMap) - { - if (p.second->GetValue()) - return p.first; - } - - throw NoItemSelected (SRC_POS); - } - - bool IsValid () - { - return true; - } - - void SetMaxStaticTextWidth (int width) - { - InfoStaticText->Wrap (width); - - foreach (wxStaticText *infoText, ChoiceInfoTexts) - infoText->Wrap (width - Gui->GetCharWidth (this) * 3); - } - - void SetPageText (const wxString &text) - { - InfoStaticText->SetLabel (text); - } - - void SetSelection (ChoiceType choice) - { - RadioButtonMap[choice]->SetValue (true); - } - - protected: - void OnChoiceHyperlinkClick (wxHyperlinkEvent &event) - { - Gui->OpenHomepageLink (this, event.GetURL()); - } - - bool ChoiceTextBold; - list ChoiceInfoTexts; - map RadioButtonMap; - }; -} - -#endif // TC_HEADER_Main_Forms_SingleChoiceWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_SingleChoiceWizardPage +#define TC_HEADER_Main_Forms_SingleChoiceWizardPage + +#include "Forms.h" + +namespace TrueCrypt +{ + template + class SingleChoiceWizardPage : public SingleChoiceWizardPageBase + { + public: + SingleChoiceWizardPage (wxPanel* parent, const wxString &groupBoxText = wxEmptyString, bool choiceTextBold = false) + : SingleChoiceWizardPageBase (parent), + ChoiceTextBold (choiceTextBold) + { + if (!groupBoxText.empty()) + { + OuterChoicesSizer->Remove (ChoicesSizer); + ChoicesSizer = new wxStaticBoxSizer (wxVERTICAL, this, groupBoxText); + OuterChoicesSizer->Add (ChoicesSizer, 0, wxEXPAND, 5); + } + } + + void AddChoice (ChoiceType choice, const wxString &choiceText, const wxString &infoText = wxEmptyString, const wchar_t *infoLinkId = nullptr, const wxString &infoLinkText = wxEmptyString) + { + assert (RadioButtonMap.find (choice) == RadioButtonMap.end()); + + wxRadioButton *radioButton = new wxRadioButton (this, wxID_ANY, choiceText); + if (RadioButtonMap.empty()) + radioButton->SetValue (true); + + RadioButtonMap[choice] = radioButton; + + if (ChoiceTextBold) + { + wxFont buttonFont = radioButton->GetFont(); + buttonFont.SetWeight (wxFONTWEIGHT_BOLD); + radioButton->SetFont (buttonFont); + } + + ChoicesSizer->Add (radioButton, 0, wxALL, 5); + + wxBoxSizer *infoSizer = new wxBoxSizer (wxVERTICAL); + + wxStaticText *infoStaticText = new wxStaticText (this, wxID_ANY, infoText, wxDefaultPosition, wxDefaultSize, 0); + ChoiceInfoTexts.push_back (infoStaticText); + + infoSizer->Add (infoStaticText, 0, wxALL, 5); + ChoicesSizer->Add (infoSizer, 0, wxEXPAND | wxLEFT, Gui->GetCharWidth (this) * 3); + + if (infoLinkId) + { + wxHyperlinkCtrl *hyperlink = Gui->CreateHyperlink (this, infoLinkId, infoLinkText); + infoSizer->Add (hyperlink, 0, wxALL, 5); + hyperlink->Connect (wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler (SingleChoiceWizardPage::OnChoiceHyperlinkClick), nullptr, this); + } + + ChoicesSizer->Add (1, Gui->GetCharHeight (this) * 1, 0, wxEXPAND, 5); + } + + ChoiceType GetSelection () const + { + typedef pair MapPair; + foreach (MapPair p, RadioButtonMap) + { + if (p.second->GetValue()) + return p.first; + } + + throw NoItemSelected (SRC_POS); + } + + bool IsValid () + { + return true; + } + + void SetMaxStaticTextWidth (int width) + { + InfoStaticText->Wrap (width); + + foreach (wxStaticText *infoText, ChoiceInfoTexts) + infoText->Wrap (width - Gui->GetCharWidth (this) * 3); + } + + void SetPageText (const wxString &text) + { + InfoStaticText->SetLabel (text); + } + + void SetSelection (ChoiceType choice) + { + RadioButtonMap[choice]->SetValue (true); + } + + protected: + void OnChoiceHyperlinkClick (wxHyperlinkEvent &event) + { + Gui->OpenHomepageLink (this, event.GetURL()); + } + + bool ChoiceTextBold; + list ChoiceInfoTexts; + map RadioButtonMap; + }; +} + +#endif // TC_HEADER_Main_Forms_SingleChoiceWizardPage diff --git a/Main/Forms/TrueCrypt.fbp b/Main/Forms/TrueCrypt.fbp index 7879cac..65874dc 100644 --- a/Main/Forms/TrueCrypt.fbp +++ b/Main/Forms/TrueCrypt.fbp @@ -460,21 +460,6 @@ OnCreateVolumeButtonClick - - - 0 - 1 - - wxID_ANY - wxITEM_NORMAL - Traveller Disk Wizard... - TravelerDiskWizardMenuItem - protected - - - OnTravelerDiskWizardMenuItemSelected - - none @@ -13828,621 +13813,6 @@ - - - - 1 - - - 0 - wxID_ANY - - - TravelerMountOptionsWizardPageBase - - -1,-1 - WizardPage; WizardPage.h - - - - wxTAB_TRAVERSAL - - - - - - - - - - - - - - - - - - - - - - - - - - - bSizer78 - wxVERTICAL - none - - 5 - wxEXPAND - 1 - - - bSizer79 - wxVERTICAL - none - - 5 - wxEXPAND - 0 - - wxID_ANY - - - sbSizer28 - wxVERTICAL - none - - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - - - 1 - - - 0 - wxID_ANY - TrueCrypt volume to mount: - - - m_staticText15 - none - - - - - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 0 - - - bSizer80 - wxHORIZONTAL - none - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - 1 - - - - 1 - - - 0 - wxID_ANY - - 0 - - VolumePathTextCtrl - protected - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OnVolumePathTextChanged - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL|wxALL - 0 - - - - 0 - 1 - - - 0 - wxID_ANY - Select... - - - SelectVolumeButton - protected - - - - - - - - - OnSelectVolumeButtonClick - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 0 - - - bSizer81 - wxHORIZONTAL - none - - 5 - wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT - 0 - - - - 1 - - - 0 - wxID_ANY - Mount volume as drive letter: - - - m_staticText16 - none - - - - - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - 0 - - - - - 1 - - - 0 - wxID_ANY - - - MountPointChoice - protected - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - - 0 - - 1 - - - 0 - wxID_ANY - Enable Background Task until volume is dismounted - - - BackgroundTaskCheckBox - protected - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - - 0 - - 1 - - - 0 - wxID_ANY - Open &Explorer window for mounted volume - - - OpenExplorerCheckBox - protected - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - - 0 - - 1 - - - 0 - wxID_ANY - Mount volume as read-&only - - - MountReadOnlyCheckBox - protected - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - - 0 - - 1 - - - 0 - wxID_ANY - Cach&e passwords and keyfiles in memory - - - CachePasswordCheckBox - protected - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND - 0 - - - - 1 - - - 0 - wxID_ANY - - - - InfoStaticText - protected - - - - - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Main/Forms/VolumeCreationProgressWizardPage.cpp b/Main/Forms/VolumeCreationProgressWizardPage.cpp index 694666d..47f9ee4 100644 --- a/Main/Forms/VolumeCreationProgressWizardPage.cpp +++ b/Main/Forms/VolumeCreationProgressWizardPage.cpp @@ -1,183 +1,183 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "VolumeCreationProgressWizardPage.h" - -namespace TrueCrypt -{ - VolumeCreationProgressWizardPage::VolumeCreationProgressWizardPage (wxPanel* parent, bool displayKeyInfo) - : VolumeCreationProgressWizardPageBase (parent), - PreviousGaugeValue (0), - ProgressBarRange (1), - RealProgressBarRange (1), - VolumeCreatorRunning (false) - { - DisplayKeysCheckBox->SetValue (displayKeyInfo); -#ifdef TC_WINDOWS - DisplayKeysCheckBox->SetLabel (L""); -#endif - -#ifdef TC_MACOSX - ProgressGauge->SetMinSize (wxSize (-1, 12)); // OS X apparently supports only up to 12px thick progress bars - KeySamplesUpperSizer->Remove (KeySamplesUpperInnerSizer); -#else - ProgressGauge->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 2)); -#endif - - if (DisplayKeysCheckBox->IsChecked()) - ShowBytes (RandomPoolSampleStaticText, RandomNumberGenerator::PeekPool(), true); - else - ShowAsterisks (RandomPoolSampleStaticText); - - class Timer : public wxTimer - { - public: - Timer (VolumeCreationProgressWizardPage *page) : Page (page) { } - - void Notify() - { - Page->OnRandomPoolTimer(); - } - - VolumeCreationProgressWizardPage *Page; - }; - - RandomPoolTimer.reset (dynamic_cast (new Timer (this))); - RandomPoolTimer->Start (30); - - AbortButton->Disable(); - ProgressGauge->SetValue (0); - - } - - void VolumeCreationProgressWizardPage::OnAbortButtonClick (wxCommandEvent& event) - { - AbortEvent.Raise(); - } - - void VolumeCreationProgressWizardPage::OnDisplayKeysCheckBoxClick (wxCommandEvent& event) - { - if (!event.IsChecked()) - { - ShowAsterisks (RandomPoolSampleStaticText); - ShowAsterisks (HeaderKeySampleStaticText); - ShowAsterisks (MasterKeySampleStaticText); - } - else - { - RandomPoolSampleStaticText->SetLabel (L""); - HeaderKeySampleStaticText->SetLabel (L""); - MasterKeySampleStaticText->SetLabel (L""); - } - } - - void VolumeCreationProgressWizardPage::OnRandomPoolTimer () - { - if (!VolumeCreatorRunning && DisplayKeysCheckBox->IsChecked()) - ShowBytes (RandomPoolSampleStaticText, RandomNumberGenerator::PeekPool(), true); - } - - void VolumeCreationProgressWizardPage::SetKeyInfo (const VolumeCreator::KeyInfo &keyInfo) - { - if (DisplayKeysCheckBox->IsChecked()) - { - ShowBytes (RandomPoolSampleStaticText, RandomNumberGenerator::PeekPool(), true); - ShowBytes (HeaderKeySampleStaticText, keyInfo.HeaderKey); - ShowBytes (MasterKeySampleStaticText, keyInfo.MasterKey); - } - } - - void VolumeCreationProgressWizardPage::ShowAsterisks (wxStaticText *textCtrl) - { - wxString str; - for (size_t i = 0; i < MaxDisplayedKeyBytes + 1; ++i) - { - str += L"**"; - } - - textCtrl->SetLabel (str.c_str()); - } - - void VolumeCreationProgressWizardPage::ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots) - { - wxString str; - - for (size_t i = 0; i < MaxDisplayedKeyBytes && i < buffer.Size(); ++i) - { - str += wxString::Format (L"%02X", buffer[i]); - } - - if (appendDots) - str += L".."; - - textCtrl->SetLabel (str.c_str()); - - for (size_t i = 0; i < str.size(); ++i) - { - str[i] = L'X'; - } - } - - void VolumeCreationProgressWizardPage::SetProgressValue (uint64 value) - { - int gaugeValue = static_cast (value * RealProgressBarRange / ProgressBarRange); - - if (value == ProgressBarRange) - gaugeValue = RealProgressBarRange; // Prevent round-off error - - if (gaugeValue != PreviousGaugeValue) - { - ProgressGauge->SetValue (gaugeValue); - PreviousGaugeValue = gaugeValue; - } - - if (value != 0) - { - SizeDoneStaticText->SetLabel (wxString::Format (L"%7.3f%%", 100.0 - double (ProgressBarRange - value) / (double (ProgressBarRange) / 100.0))); - - wxLongLong timeDiff = wxGetLocalTimeMillis() - StartTime; - if (timeDiff.GetValue() > 0) - { - uint64 speed = value * 1000 / timeDiff.GetValue(); - - if (ProgressBarRange != value) - SpeedStaticText->SetLabel (Gui->SpeedToString (speed)); - - TimeLeftStaticText->SetLabel (speed > 0 ? Gui->TimeSpanToString ((ProgressBarRange - value) / speed) : L""); - } - } - else - { - SizeDoneStaticText->SetLabel (L""); - SpeedStaticText->SetLabel (L""); - TimeLeftStaticText->SetLabel (L""); - } - } - - void VolumeCreationProgressWizardPage::SetMaxStaticTextWidth (int width) - { - InfoStaticText->Wrap (width); - } - - void VolumeCreationProgressWizardPage::SetProgressState (bool volumeCreatorRunning) - { - if (volumeCreatorRunning) - StartTime = wxGetLocalTimeMillis(); - - VolumeCreatorRunning = volumeCreatorRunning; - } - - void VolumeCreationProgressWizardPage::SetProgressRange (uint64 progressBarRange) - { - ProgressBarRange = progressBarRange; - RealProgressBarRange = ProgressGauge->GetSize().GetWidth(); - ProgressGauge->SetRange (RealProgressBarRange); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "VolumeCreationProgressWizardPage.h" + +namespace TrueCrypt +{ + VolumeCreationProgressWizardPage::VolumeCreationProgressWizardPage (wxPanel* parent, bool displayKeyInfo) + : VolumeCreationProgressWizardPageBase (parent), + PreviousGaugeValue (0), + ProgressBarRange (1), + RealProgressBarRange (1), + VolumeCreatorRunning (false) + { + DisplayKeysCheckBox->SetValue (displayKeyInfo); +#ifdef TC_WINDOWS + DisplayKeysCheckBox->SetLabel (L""); +#endif + +#ifdef TC_MACOSX + ProgressGauge->SetMinSize (wxSize (-1, 12)); // OS X apparently supports only up to 12px thick progress bars + KeySamplesUpperSizer->Remove (KeySamplesUpperInnerSizer); +#else + ProgressGauge->SetMinSize (wxSize (-1, Gui->GetCharHeight (this) * 2)); +#endif + + if (DisplayKeysCheckBox->IsChecked()) + ShowBytes (RandomPoolSampleStaticText, RandomNumberGenerator::PeekPool(), true); + else + ShowAsterisks (RandomPoolSampleStaticText); + + class Timer : public wxTimer + { + public: + Timer (VolumeCreationProgressWizardPage *page) : Page (page) { } + + void Notify() + { + Page->OnRandomPoolTimer(); + } + + VolumeCreationProgressWizardPage *Page; + }; + + RandomPoolTimer.reset (dynamic_cast (new Timer (this))); + RandomPoolTimer->Start (30); + + AbortButton->Disable(); + ProgressGauge->SetValue (0); + + } + + void VolumeCreationProgressWizardPage::OnAbortButtonClick (wxCommandEvent& event) + { + AbortEvent.Raise(); + } + + void VolumeCreationProgressWizardPage::OnDisplayKeysCheckBoxClick (wxCommandEvent& event) + { + if (!event.IsChecked()) + { + ShowAsterisks (RandomPoolSampleStaticText); + ShowAsterisks (HeaderKeySampleStaticText); + ShowAsterisks (MasterKeySampleStaticText); + } + else + { + RandomPoolSampleStaticText->SetLabel (L""); + HeaderKeySampleStaticText->SetLabel (L""); + MasterKeySampleStaticText->SetLabel (L""); + } + } + + void VolumeCreationProgressWizardPage::OnRandomPoolTimer () + { + if (!VolumeCreatorRunning && DisplayKeysCheckBox->IsChecked()) + ShowBytes (RandomPoolSampleStaticText, RandomNumberGenerator::PeekPool(), true); + } + + void VolumeCreationProgressWizardPage::SetKeyInfo (const VolumeCreator::KeyInfo &keyInfo) + { + if (DisplayKeysCheckBox->IsChecked()) + { + ShowBytes (RandomPoolSampleStaticText, RandomNumberGenerator::PeekPool(), true); + ShowBytes (HeaderKeySampleStaticText, keyInfo.HeaderKey); + ShowBytes (MasterKeySampleStaticText, keyInfo.MasterKey); + } + } + + void VolumeCreationProgressWizardPage::ShowAsterisks (wxStaticText *textCtrl) + { + wxString str; + for (size_t i = 0; i < MaxDisplayedKeyBytes + 1; ++i) + { + str += L"**"; + } + + textCtrl->SetLabel (str.c_str()); + } + + void VolumeCreationProgressWizardPage::ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots) + { + wxString str; + + for (size_t i = 0; i < MaxDisplayedKeyBytes && i < buffer.Size(); ++i) + { + str += wxString::Format (L"%02X", buffer[i]); + } + + if (appendDots) + str += L".."; + + textCtrl->SetLabel (str.c_str()); + + for (size_t i = 0; i < str.size(); ++i) + { + str[i] = L'X'; + } + } + + void VolumeCreationProgressWizardPage::SetProgressValue (uint64 value) + { + int gaugeValue = static_cast (value * RealProgressBarRange / ProgressBarRange); + + if (value == ProgressBarRange) + gaugeValue = RealProgressBarRange; // Prevent round-off error + + if (gaugeValue != PreviousGaugeValue) + { + ProgressGauge->SetValue (gaugeValue); + PreviousGaugeValue = gaugeValue; + } + + if (value != 0) + { + SizeDoneStaticText->SetLabel (wxString::Format (L"%7.3f%%", 100.0 - double (ProgressBarRange - value) / (double (ProgressBarRange) / 100.0))); + + wxLongLong timeDiff = wxGetLocalTimeMillis() - StartTime; + if (timeDiff.GetValue() > 0) + { + uint64 speed = value * 1000 / timeDiff.GetValue(); + + if (ProgressBarRange != value) + SpeedStaticText->SetLabel (Gui->SpeedToString (speed)); + + TimeLeftStaticText->SetLabel (speed > 0 ? Gui->TimeSpanToString ((ProgressBarRange - value) / speed) : L""); + } + } + else + { + SizeDoneStaticText->SetLabel (L""); + SpeedStaticText->SetLabel (L""); + TimeLeftStaticText->SetLabel (L""); + } + } + + void VolumeCreationProgressWizardPage::SetMaxStaticTextWidth (int width) + { + InfoStaticText->Wrap (width); + } + + void VolumeCreationProgressWizardPage::SetProgressState (bool volumeCreatorRunning) + { + if (volumeCreatorRunning) + StartTime = wxGetLocalTimeMillis(); + + VolumeCreatorRunning = volumeCreatorRunning; + } + + void VolumeCreationProgressWizardPage::SetProgressRange (uint64 progressBarRange) + { + ProgressBarRange = progressBarRange; + RealProgressBarRange = ProgressGauge->GetSize().GetWidth(); + ProgressGauge->SetRange (RealProgressBarRange); + } +} diff --git a/Main/Forms/VolumeCreationProgressWizardPage.h b/Main/Forms/VolumeCreationProgressWizardPage.h index 2b1bda2..b616e50 100644 --- a/Main/Forms/VolumeCreationProgressWizardPage.h +++ b/Main/Forms/VolumeCreationProgressWizardPage.h @@ -1,53 +1,53 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_VolumeCreationProgressWizardPage -#define TC_HEADER_Main_Forms_VolumeCreationProgressWizardPage - -#include "Forms.h" -#include "Core/VolumeCreator.h" - -namespace TrueCrypt -{ - class VolumeCreationProgressWizardPage : public VolumeCreationProgressWizardPageBase - { - public: - VolumeCreationProgressWizardPage (wxPanel* parent, bool displayKeyInfo); - ~VolumeCreationProgressWizardPage () { } - - void EnableAbort (bool enable = true) { AbortButton->Enable (enable); } - bool IsKeyInfoDisplayed () const { return DisplayKeysCheckBox->GetValue(); } - bool IsValid () { return true; } - void OnRandomPoolTimer (); - void SetKeyInfo (const VolumeCreator::KeyInfo &keyInfo); - void SetMaxStaticTextWidth (int width); - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - void SetProgressRange (uint64 progressBarRange); - void SetProgressValue (uint64 value); - void SetProgressState (bool volumeCreatorRunning); - - Event AbortEvent; - - protected: - void OnAbortButtonClick (wxCommandEvent& event); - void OnDisplayKeysCheckBoxClick (wxCommandEvent& event); - void ShowAsterisks (wxStaticText *textCtrl); - void ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots = true); - - static const int MaxDisplayedKeyBytes = 13; - - int PreviousGaugeValue; - uint64 ProgressBarRange; - auto_ptr RandomPoolTimer; - int RealProgressBarRange; - wxLongLong StartTime; - bool VolumeCreatorRunning; - }; -} - -#endif // TC_HEADER_Main_Forms_VolumeCreationProgressWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_VolumeCreationProgressWizardPage +#define TC_HEADER_Main_Forms_VolumeCreationProgressWizardPage + +#include "Forms.h" +#include "Core/VolumeCreator.h" + +namespace TrueCrypt +{ + class VolumeCreationProgressWizardPage : public VolumeCreationProgressWizardPageBase + { + public: + VolumeCreationProgressWizardPage (wxPanel* parent, bool displayKeyInfo); + ~VolumeCreationProgressWizardPage () { } + + void EnableAbort (bool enable = true) { AbortButton->Enable (enable); } + bool IsKeyInfoDisplayed () const { return DisplayKeysCheckBox->GetValue(); } + bool IsValid () { return true; } + void OnRandomPoolTimer (); + void SetKeyInfo (const VolumeCreator::KeyInfo &keyInfo); + void SetMaxStaticTextWidth (int width); + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + void SetProgressRange (uint64 progressBarRange); + void SetProgressValue (uint64 value); + void SetProgressState (bool volumeCreatorRunning); + + Event AbortEvent; + + protected: + void OnAbortButtonClick (wxCommandEvent& event); + void OnDisplayKeysCheckBoxClick (wxCommandEvent& event); + void ShowAsterisks (wxStaticText *textCtrl); + void ShowBytes (wxStaticText *textCtrl, const ConstBufferPtr &buffer, bool appendDots = true); + + static const size_t MaxDisplayedKeyBytes = 13; + + int PreviousGaugeValue; + uint64 ProgressBarRange; + auto_ptr RandomPoolTimer; + int RealProgressBarRange; + wxLongLong StartTime; + bool VolumeCreatorRunning; + }; +} + +#endif // TC_HEADER_Main_Forms_VolumeCreationProgressWizardPage diff --git a/Main/Forms/VolumeCreationWizard.cpp b/Main/Forms/VolumeCreationWizard.cpp index cc29be6..939905f 100644 --- a/Main/Forms/VolumeCreationWizard.cpp +++ b/Main/Forms/VolumeCreationWizard.cpp @@ -1,935 +1,935 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Platform/SystemInfo.h" -#ifdef TC_UNIX -#include -#include "Platform/Unix/Process.h" -#endif -#include "Core/RandomNumberGenerator.h" -#include "Core/VolumeCreator.h" -#include "Main/Application.h" -#include "Main/GraphicUserInterface.h" -#include "Main/Resources.h" -#include "VolumeCreationWizard.h" -#include "EncryptionOptionsWizardPage.h" -#include "InfoWizardPage.h" -#include "ProgressWizardPage.h" -#include "SingleChoiceWizardPage.h" -#include "VolumeCreationProgressWizardPage.h" -#include "VolumeFormatOptionsWizardPage.h" -#include "VolumeLocationWizardPage.h" -#include "VolumePasswordWizardPage.h" -#include "VolumeSizeWizardPage.h" - -namespace TrueCrypt -{ - VolumeCreationWizard::VolumeCreationWizard (wxWindow* parent) - : WizardFrame (parent), - CrossPlatformSupport (true), - DisplayKeyInfo (true), - LargeFilesSupport (false), - QuickFormatEnabled (false), - SelectedFilesystemClusterSize (0), - SelectedFilesystemType (VolumeCreationOptions::FilesystemType::FAT), - SelectedVolumeHostType (VolumeHostType::File), - SelectedVolumeType (VolumeType::Normal), - VolumeSize (0) - { - RandomNumberGenerator::Start(); - - SetTitle (LangString["INTRO_TITLE"]); - SetImage (Resources::GetVolumeCreationWizardBitmap (Gui->GetCharHeight (this) * 21)); - SetMaxStaticTextWidth (55); - - SetStep (Step::VolumeHostType); - - class Timer : public wxTimer - { - public: - Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { } - - void Notify() - { - Wizard->OnRandomPoolUpdateTimer(); - } - - VolumeCreationWizard *Wizard; - }; - - RandomPoolUpdateTimer.reset (dynamic_cast (new Timer (this))); - RandomPoolUpdateTimer->Start (200); - } - - VolumeCreationWizard::~VolumeCreationWizard () - { - } - - WizardPage *VolumeCreationWizard::GetPage (WizardStep step) - { - switch (step) - { - case Step::VolumeHostType: - { - ClearHistory(); - - OuterVolume = false; - LargeFilesSupport = false; - QuickFormatEnabled = false; - - SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); - page->SetMinSize (wxSize (Gui->GetCharWidth (this) * 58, Gui->GetCharHeight (this) * 18 + 5)); - - page->SetPageTitle (LangString["INTRO_TITLE"]); - - page->AddChoice (VolumeHostType::File, LangString["IDC_FILE_CONTAINER"], LangString["IDT_FILE_CONTAINER"], L"introcontainer", LangString["IDC_MORE_INFO_ON_CONTAINERS"]); - page->AddChoice (VolumeHostType::Device, _("Create a volume within a partition/&drive"), _("Formats and encrypts a non-system partition, entire external or secondary drive, entire USB stick, etc.")); - - page->SetSelection (SelectedVolumeHostType); - return page; - } - - case Step::VolumeType: - { - SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); - page->SetPageTitle (LangString["VOLUME_TYPE_TITLE"]); - - page->AddChoice (VolumeType::Normal, LangString["IDC_STD_VOL"], LangString["NORMAL_VOLUME_TYPE_HELP"]); - page->AddChoice (VolumeType::Hidden, LangString["IDC_HIDDEN_VOL"], LangString["HIDDEN_VOLUME_TYPE_HELP"], L"hiddenvolume", LangString["IDC_HIDDEN_VOL_HELP"]); - - page->SetSelection (SelectedVolumeType); - return page; - } - - case Step::VolumeLocation: - { - VolumeLocationWizardPage *page = new VolumeLocationWizardPage (GetPageParent(), SelectedVolumeHostType); - page->SetPageTitle (LangString["VOLUME_LOCATION"]); - - if (SelectedVolumeType == VolumeType::Hidden) - page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP_HIDDEN_HOST_VOL" : "DEVICE_HELP_HIDDEN_HOST_VOL"]); - else - page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP" : "DEVICE_HELP_NO_INPLACE"]); - - page->SetVolumePath (SelectedVolumePath); - return page; - } - - case Step::EncryptionOptions: - { - EncryptionOptionsWizardPage *page = new EncryptionOptionsWizardPage (GetPageParent()); - - if (OuterVolume) - page->SetPageTitle (LangString["CIPHER_HIDVOL_HOST_TITLE"]); - else if (SelectedVolumeType == VolumeType::Hidden) - page->SetPageTitle (LangString["CIPHER_HIDVOL_TITLE"]); - else - page->SetPageTitle (LangString["CIPHER_TITLE"]); - - page->SetEncryptionAlgorithm (SelectedEncryptionAlgorithm); - page->SetHash (SelectedHash); - return page; - } - - case Step::VolumeSize: - { - wxString freeSpaceText; - wxString pageTitle; - wxString pageText; - - if (OuterVolume) - { - pageTitle = LangString["SIZE_HIDVOL_HOST_TITLE"]; - pageText = LangString["SIZE_HELP_HIDDEN_HOST_VOL"]; - } - else if (SelectedVolumeType == VolumeType::Hidden) - { - pageTitle = LangString["SIZE_HIDVOL_TITLE"]; - pageText = LangString["SIZE_HELP_HIDDEN_VOL"] + L"\n\n" + _("Please note that if your operating system does not allocate files from the beginning of the free space, the maximum possible hidden volume size may be much smaller than the size of the free space on the outer volume. This not a bug in TrueCrypt but a limitation of the operating system."); - freeSpaceText = StringFormatter (_("Maximum possible hidden volume size for this volume is {0}."), Gui->SizeToString (MaxHiddenVolumeSize)); - } - else - { - pageTitle = LangString["SIZE_TITLE"]; - pageText = LangString["VOLUME_SIZE_HELP"]; - } - - VolumeSizeWizardPage *page = new VolumeSizeWizardPage (GetPageParent(), SelectedVolumePath, freeSpaceText); - - page->SetPageTitle (pageTitle); - page->SetPageText (pageText); - - if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden) - page->SetMaxVolumeSize (MaxHiddenVolumeSize); - else - page->SetVolumeSize (VolumeSize); - - if (OuterVolume) - page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_HOST_SIZE); - else if (SelectedVolumeType == VolumeType::Hidden) - page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_SIZE); - else - page->SetMinVolumeSize (TC_MIN_VOLUME_SIZE); - - return page; - } - - case Step::VolumePassword: - { - VolumePasswordWizardPage *page = new VolumePasswordWizardPage (GetPageParent(), Password, Keyfiles); - - if (OuterVolume) - page->SetPageTitle (LangString["PASSWORD_HIDVOL_HOST_TITLE"]); - else if (SelectedVolumeType == VolumeType::Hidden) - page->SetPageTitle (LangString["PASSWORD_HIDVOL_TITLE"]); - else - page->SetPageTitle (LangString["PASSWORD_TITLE"]); - - page->SetPageText (LangString[OuterVolume ? "PASSWORD_HIDDENVOL_HOST_HELP" : "PASSWORD_HELP"]); - return page; - } - - case Step::LargeFilesSupport: - { - SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); - page->SetPageTitle (LangString["FILESYS_PAGE_TITLE"]); - - page->AddChoice (false, _("I will not store files larger than 4 GB on the volume"), - _("Choose this option if you do not need to store files larger than 4 GB (4,294,967,296 bytes) on the volume.")); - - page->AddChoice (true, _("I will store files larger than 4 GB on the volume"), - _("Choose this option if you need to store files larger than 4 GB (4,294,967,296 bytes) on the volume.")); - - page->SetSelection (LargeFilesSupport); - return page; - } - - case Step::FormatOptions: - { - VolumeFormatOptionsWizardPage *page = new VolumeFormatOptionsWizardPage (GetPageParent(), VolumeSize, - SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden), OuterVolume, LargeFilesSupport); - - page->SetPageTitle (_("Format Options")); - page->SetFilesystemType (SelectedFilesystemType); - - if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden) - QuickFormatEnabled = true; - page->SetQuickFormat (QuickFormatEnabled); - - return page; - } - - case Step::CrossPlatformSupport: - { - SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); - page->SetPageTitle (_("Cross-Platform Support")); - - page->AddChoice (true, _("I will mount the volume on other platforms"), - _("Choose this option if you need to use the volume on other platforms.")); - - page->AddChoice (false, StringFormatter (_("I will mount the volume only on {0}"), SystemInfo::GetPlatformName()), - _("Choose this option if you do not need to use the volume on other platforms.")); - - page->SetSelection (CrossPlatformSupport); - return page; - } - - case Step::CreationProgress: - { - VolumeCreationProgressWizardPage *page = new VolumeCreationProgressWizardPage (GetPageParent(), DisplayKeyInfo); - - if (OuterVolume) - page->SetPageTitle (LangString["FORMAT_HIDVOL_HOST_TITLE"]); - else if (SelectedVolumeType == VolumeType::Hidden) - page->SetPageTitle (LangString["FORMAT_HIDVOL_TITLE"]); - else - page->SetPageTitle (LangString["FORMAT_TITLE"]); - - page->SetPageText (LangString["FORMAT_HELP"]); - page->AbortEvent.Connect (EventConnector (this, &VolumeCreationWizard::OnAbortButtonClick)); - page->SetNextButtonText (LangString["FORMAT"]); - return page; - } - - case Step::VolumeCreatedInfo: - { - InfoWizardPage *page = new InfoWizardPage (GetPageParent()); - page->SetPageTitle (LangString["FORMAT_FINISHED_TITLE"]); - page->SetPageText (LangString["FORMAT_FINISHED_HELP"]); - - SetCancelButtonText (_("Exit")); - return page; - } - - case Step::OuterVolumeContents: - { - ClearHistory(); - - MountOptions mountOptions; - mountOptions.NoKernelCrypto = true; - mountOptions.Keyfiles = Keyfiles; - mountOptions.Password = Password; - mountOptions.Path = make_shared (SelectedVolumePath); - - try - { - wxBusyCursor busy; - Gui->SetActiveFrame (this); - MountedOuterVolume = Core->MountVolume (mountOptions); - } - catch (exception &e) - { - Gui->SetActiveFrame (this); - Gui->ShowError (e); - - Close(); - return new InfoWizardPage (GetPageParent()); - } - - struct OpenOuterVolumeFunctor : public Functor - { - OpenOuterVolumeFunctor (const DirectoryPath &outerVolumeMountPoint) : OuterVolumeMountPoint (outerVolumeMountPoint) { } - - virtual void operator() () - { - Gui->OpenExplorerWindow (OuterVolumeMountPoint); - } - - DirectoryPath OuterVolumeMountPoint; - }; - - InfoWizardPage *page = new InfoWizardPage (GetPageParent(), _("Open Outer Volume"), - shared_ptr (new OpenOuterVolumeFunctor (MountedOuterVolume->MountPoint))); - - page->SetPageTitle (LangString["HIDVOL_HOST_FILLING_TITLE"]); - - page->SetPageText (StringFormatter ( - _("Outer volume has been successfully created and mounted as '{0}'. To this volume you should now copy some sensitive-looking files that you actually do NOT want to hide. The files will be there for anyone forcing you to disclose your password. You will reveal only the password for this outer volume, not for the hidden one. The files that you really care about will be stored in the hidden volume, which will be created later on. When you finish copying, click Next. Do not dismount the volume.\n\nNote: After you click Next, the outer volume will be analyzed to determine the size of uninterrupted area of free space whose end is aligned with the end of the volume. This area will accommodate the hidden volume, so it will limit its maximum possible size. The procedure ensures no data on the outer volume are overwritten by the hidden volume."), - wstring (MountedOuterVolume->MountPoint))); - - return page; - } - - case Step::HiddenVolume: - { - ClearHistory(); - OuterVolume = false; - LargeFilesSupport = false; - - InfoWizardPage *page = new InfoWizardPage (GetPageParent()); - page->SetPageTitle (LangString["HIDVOL_PRE_CIPHER_TITLE"]); - page->SetPageText (LangString["HIDVOL_PRE_CIPHER_HELP"]); - - return page; - } - - default: - throw ParameterIncorrect (SRC_POS); - } - } - - void VolumeCreationWizard::OnAbortButtonClick (EventArgs &args) - { - AbortRequested = true; - } - - void VolumeCreationWizard::OnMouseMotion (wxMouseEvent& event) - { - event.Skip(); - if (!IsWorkInProgress() && RandomNumberGenerator::IsRunning()) - { - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&event), sizeof (event))); - - long coord = event.GetX(); - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); - coord = event.GetY(); - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); - } - } - - void VolumeCreationWizard::OnProgressTimer () - { - if (!IsWorkInProgress()) - return; - - if (AbortRequested && !AbortConfirmationPending) - { - AbortConfirmationPending = true; - if (Gui->AskYesNo (LangString ["FORMAT_ABORT"], true)) - { - if (IsWorkInProgress() && Creator.get() != nullptr) - { - CreationAborted = true; - Creator->Abort(); - } - } - AbortRequested = false; - AbortConfirmationPending = false; - } - - VolumeCreator::ProgressInfo progress = Creator->GetProgressInfo(); - - VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); - page->SetProgressValue (progress.SizeDone); - - if (!progress.CreationInProgress && !AbortConfirmationPending) - { - SetWorkInProgress (false); - OnVolumeCreatorFinished (); - } - } - - void VolumeCreationWizard::OnRandomPoolUpdateTimer () - { - if (!IsWorkInProgress()) - { - wxLongLong time = wxGetLocalTimeMillis(); - RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&time), sizeof (time))); - } - } - - void VolumeCreationWizard::OnVolumeCreatorFinished () - { - VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); - - ProgressTimer.reset(); - page->SetProgressState (false); - - Gui->EndInteractiveBusyState (this); - SetWorkInProgress (false); - UpdateControls(); - - try - { - if (!CreationAborted) - { - Creator->CheckResult(); - -#ifdef TC_UNIX - // Format non-FAT filesystem - const char *fsFormatter = nullptr; - - switch (SelectedFilesystemType) - { - case VolumeCreationOptions::FilesystemType::Ext2: fsFormatter = "mkfs.ext2"; break; - case VolumeCreationOptions::FilesystemType::Ext3: fsFormatter = "mkfs.ext3"; break; - case VolumeCreationOptions::FilesystemType::MacOsExt: fsFormatter = "newfs_hfs"; break; - case VolumeCreationOptions::FilesystemType::UFS: fsFormatter = "newfs" ; break; - default: break; - } - - if (fsFormatter) - { - wxBusyCursor busy; - - MountOptions mountOptions; - mountOptions.Path = make_shared (SelectedVolumePath); - mountOptions.NoFilesystem = true; - mountOptions.Password = Password; - mountOptions.Keyfiles = Keyfiles; - mountOptions.NoKernelCrypto = Gui->GetPreferences().DefaultMountOptions.NoKernelCrypto; - - shared_ptr volume = Core->MountVolume (mountOptions); - finally_do_arg (shared_ptr , volume, { Core->DismountVolume (finally_arg, true); }); - - Thread::Sleep (2000); // Try to prevent race conditions caused by OS - - // Temporarily take ownership of the device if the user is not an administrator - UserId origDeviceOwner ((uid_t) -1); - - DevicePath virtualDevice = volume->VirtualDevice; -#ifdef TC_MACOSX - string virtualDeviceStr = virtualDevice; - if (virtualDeviceStr.find ("/dev/rdisk") != 0) - virtualDevice = "/dev/r" + virtualDeviceStr.substr (5); -#endif - try - { - File file; - file.Open (virtualDevice, File::OpenReadWrite); - } - catch (...) - { - if (!Core->HasAdminPrivileges()) - { - origDeviceOwner = virtualDevice.GetOwner(); - Core->SetFileOwner (virtualDevice, UserId (getuid())); - } - } - - finally_do_arg2 (FilesystemPath, virtualDevice, UserId, origDeviceOwner, - { - if (finally_arg2.SystemId != (uid_t) -1) - Core->SetFileOwner (finally_arg, finally_arg2); - }); - - // Create filesystem - list args; - - if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::MacOsExt && VolumeSize >= 10 * BYTES_PER_MB) - args.push_back ("-J"); - - args.push_back (string (virtualDevice)); - - Process::Execute (fsFormatter, args); - } -#endif // TC_UNIX - - if (OuterVolume) - { - SetStep (Step::OuterVolumeContents); - } - else - { - Gui->ShowInfo (SelectedVolumeType == VolumeType::Hidden ? "HIDVOL_FORMAT_FINISHED_HELP" : "FORMAT_FINISHED_INFO"); - SetStep (Step::VolumeCreatedInfo); - } - - return; - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - - page->SetProgressValue (0); - if (SelectedVolumeType == VolumeType::Normal && !SelectedVolumePath.IsDevice()) - { - try - { - FilePath (wstring (SelectedVolumePath)).Delete(); - } - catch (...) { } - } - } - - WizardFrame::WizardStep VolumeCreationWizard::ProcessPageChangeRequest (bool forward) - { - switch (GetCurrentStep()) - { - case Step::VolumeHostType: - { - SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); - - try - { - SelectedVolumeHostType = page->GetSelection(); - } - catch (NoItemSelected &) - { - return GetCurrentStep(); - } - - return Step::VolumeType; - } - - case Step::VolumeType: - { - SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); - - try - { - SelectedVolumeType = page->GetSelection(); - } - catch (NoItemSelected &) - { - return GetCurrentStep(); - } - - if (SelectedVolumeType == VolumeType::Hidden) - OuterVolume = true; - - return Step::VolumeLocation; - } - - case Step::VolumeLocation: - { - VolumeLocationWizardPage *page = dynamic_cast (GetCurrentPage()); - SelectedVolumePath = page->GetVolumePath(); - VolumeSize = 0; - - if (forward) - { - if (Core->IsVolumeMounted (SelectedVolumePath)) - { - Gui->ShowInfo ("DISMOUNT_FIRST"); - return GetCurrentStep(); - } - - if (SelectedVolumePath.IsDevice()) - { - if (!DeviceWarningConfirmed && !Gui->AskYesNo (LangString["FORMAT_DEVICE_FOR_ADVANCED_ONLY"])) - return GetCurrentStep(); - - DeviceWarningConfirmed = true; - - foreach_ref (const HostDevice &drive, Core->GetHostDevices()) - { - if (drive.Path == SelectedVolumePath && !drive.Partitions.empty()) - { - Gui->ShowError ("DEVICE_PARTITIONS_ERR"); - return GetCurrentStep(); - } - } - - try - { - VolumeSize = Core->GetDeviceSize (SelectedVolumePath); - } - catch (UserAbort&) - { - return Step::VolumeLocation; - } - catch (exception &e) - { - Gui->ShowError (e); - Gui->ShowError ("CANNOT_CALC_SPACE"); - return GetCurrentStep(); - } - - DirectoryPath mountPoint; - try - { - mountPoint = Core->GetDeviceMountPoint (SelectedVolumePath); - - if (!mountPoint.IsEmpty()) - { - if (!Gui->AskYesNo (StringFormatter (_("WARNING: Formatting of the device will destroy all data on filesystem '{0}'.\n\nDo you want to continue?"), wstring (mountPoint)), false, true)) - return GetCurrentStep(); - - try - { - Core->DismountFilesystem (mountPoint, true); - } - catch (exception &e) - { - Gui->ShowError (e); - Gui->ShowError (StringFormatter (_("The filesystem of the selected device is currently mounted. Please dismount '{0}' before proceeding."), wstring (mountPoint))); - return GetCurrentStep(); - } - } - } - catch (...) { } - } - } - - return Step::EncryptionOptions; - } - - case Step::EncryptionOptions: - { - EncryptionOptionsWizardPage *page = dynamic_cast (GetCurrentPage()); - SelectedEncryptionAlgorithm = page->GetEncryptionAlgorithm (); - SelectedHash = page->GetHash (); - - if (forward) - RandomNumberGenerator::SetHash (SelectedHash); - - if (SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden)) - return Step::VolumePassword; - else - return Step::VolumeSize; - } - - case Step::VolumeSize: - { - VolumeSizeWizardPage *page = dynamic_cast (GetCurrentPage()); - - try - { - VolumeSize = page->GetVolumeSize(); - } - catch (Exception &e) - { - if (forward) - { - Gui->ShowError (e); - return GetCurrentStep(); - } - } - - if (forward - && !OuterVolume && SelectedVolumeType == VolumeType::Hidden - && (double) VolumeSize / MaxHiddenVolumeSize > 0.85) - { - if (!Gui->AskYesNo (LangString["FREE_SPACE_FOR_WRITING_TO_OUTER_VOLUME"])) - return GetCurrentStep(); - } - - if (forward - && SelectedVolumeHostType == VolumeHostType::File - && VolumeSize > 4 * BYTES_PER_GB - && (OuterVolume || SelectedVolumeType != VolumeType::Hidden) - && !Core->FilesystemSupportsLargeFiles (SelectedVolumePath)) - { - Gui->ShowWarning (LangString["VOLUME_TOO_LARGE_FOR_FAT32"]); - } - - return Step::VolumePassword; - } - - case Step::VolumePassword: - { - VolumePasswordWizardPage *page = dynamic_cast (GetCurrentPage()); - Password = page->GetPassword(); - Keyfiles = page->GetKeyfiles(); - - if (forward && Password && !Password->IsEmpty()) - { - try - { - Password->CheckPortability(); - } - catch (UnportablePassword &e) - { - Gui->ShowError (e); - return GetCurrentStep(); - } - - if (Password->Size() < VolumePassword::WarningSizeThreshold - && !Gui->AskYesNo (LangString["PASSWORD_LENGTH_WARNING"], false, true)) - { - return GetCurrentStep(); - } - } - - if (forward && OuterVolume) - { - // Use FAT to prevent problems with free space - QuickFormatEnabled = false; - SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT; - return Step::CreationProgress; - } - - if (VolumeSize > 4 * BYTES_PER_GB) - { - if (VolumeSize < TC_MAX_FAT_FS_SIZE) - return Step::LargeFilesSupport; - else - SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative(); - } - - return Step::FormatOptions; - } - - case Step::LargeFilesSupport: - { - SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); - - try - { - LargeFilesSupport = page->GetSelection(); - } - catch (NoItemSelected &) - { - return GetCurrentStep(); - } - - if (LargeFilesSupport) - SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative(); - else - SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT; - - return Step::FormatOptions; - } - - case Step::FormatOptions: - { - VolumeFormatOptionsWizardPage *page = dynamic_cast (GetCurrentPage()); - SelectedFilesystemType = page->GetFilesystemType(); - QuickFormatEnabled = page->IsQuickFormatEnabled(); - - if (OuterVolume && SelectedFilesystemType != VolumeCreationOptions::FilesystemType::FAT) - Gui->ShowInfo (_("Please note that the FAT filesystem usually offers the maximum free space available for the hidden volume.")); - - if (SelectedFilesystemType != VolumeCreationOptions::FilesystemType::None - && SelectedFilesystemType != VolumeCreationOptions::FilesystemType::FAT) - return Step::CrossPlatformSupport; - - return Step::CreationProgress; - } - - case Step::CrossPlatformSupport: - { - SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); - - try - { - CrossPlatformSupport = page->GetSelection(); - } - catch (NoItemSelected &) - { - return GetCurrentStep(); - } - - if (forward && CrossPlatformSupport) - Gui->ShowWarning (StringFormatter (_("Please note that the volume will not be formatted with a FAT filesystem and, therefore, you may be required to install additional filesystem drivers on platforms other than {0}, which will enable you to mount the volume."), SystemInfo::GetPlatformName())); - - return Step::CreationProgress; - } - - case Step::CreationProgress: - { - VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); - - DisplayKeyInfo = page->IsKeyInfoDisplayed(); - - if (forward) - { - if (SelectedVolumeType != VolumeType::Hidden || OuterVolume) - { - if (SelectedVolumePath.IsDevice()) - { - wxString confirmMsg = LangString["OVERWRITEPROMPT_DEVICE"]; - confirmMsg.Replace (L"%hs", L"%s"); - - if (!Gui->AskYesNo (wxString::Format (confirmMsg, wxString (_("DEVICE")).c_str(), wstring (SelectedVolumePath).c_str(), L""), false, true)) - return GetCurrentStep(); - } - else if (FilesystemPath (wstring (SelectedVolumePath)).IsFile()) - { - wxString confirmMsg = LangString["OVERWRITEPROMPT"]; - confirmMsg.Replace (L"%hs", L"%s"); - - if (!Gui->AskYesNo (wxString::Format (confirmMsg, wstring (SelectedVolumePath).c_str(), false, true))) - return GetCurrentStep(); - } - } - - AbortRequested = false; - AbortConfirmationPending = false; - CreationAborted = false; - SetWorkInProgress (true); - UpdateControls(); - - Gui->BeginInteractiveBusyState (this); - - try - { - make_shared_auto (VolumeCreationOptions, options); - - options->Filesystem = SelectedFilesystemType; - options->FilesystemClusterSize = SelectedFilesystemClusterSize; - - options->EA = SelectedEncryptionAlgorithm; - options->Password = Password; - options->Keyfiles = Keyfiles; - options->Path = SelectedVolumePath; - options->Quick = QuickFormatEnabled; - options->Size = VolumeSize; - options->Type = OuterVolume ? VolumeType::Normal : SelectedVolumeType; - options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*SelectedHash); - - Creator.reset (new VolumeCreator); - Creator->CreateVolume (options); - - page->SetKeyInfo (Creator->GetKeyInfo()); - - class Timer : public wxTimer - { - public: - Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { } - - void Notify() - { - Wizard->OnProgressTimer(); - } - - VolumeCreationWizard *Wizard; - }; - - page->SetProgressRange (options->Size); - page->SetProgressState (true); - ProgressTimer.reset (dynamic_cast (new Timer (this))); - ProgressTimer->Start (50); - } - catch (Exception &e) - { - CreationAborted = true; - OnVolumeCreatorFinished(); - Gui->ShowError (e); - } - } - - return GetCurrentStep(); - } - - case Step::VolumeCreatedInfo: - Creator.reset(); - SetCancelButtonText (L""); - - return Step::VolumeHostType; - - case Step::OuterVolumeContents: - try - { - // Determine maximum size of the hidden volume - wxBusyCursor busy; -#ifdef TC_UNIX - sync(); -#endif - VolumeInfoList ml = Core->GetMountedVolumes (MountedOuterVolume->Path); - MaxHiddenVolumeSize = 0; - - if (ml.empty()) - throw ParameterIncorrect (SRC_POS); - - if (ml.front()->TopWriteOffset == 0) - throw_err (_("The outer volume does not contain any files.")); - - Gui->SetActiveFrame (this); - shared_ptr dismountedOuterVolume = Core->DismountVolume (MountedOuterVolume, false, true); - - if (dismountedOuterVolume->Size > dismountedOuterVolume->TopWriteOffset) - MaxHiddenVolumeSize = dismountedOuterVolume->Size - dismountedOuterVolume->TopWriteOffset; - - // Add a reserve (in case the user mounts the outer volume and creates new files - // on it by accident or OS writes some new data behind his or her back, such as - // System Restore etc.) - - uint64 reservedSize = dismountedOuterVolume->Size / 200; - if (reservedSize > 10 * BYTES_PER_MB) - reservedSize = 10 * BYTES_PER_MB; - - if (MaxHiddenVolumeSize < reservedSize) - MaxHiddenVolumeSize = 0; - else - MaxHiddenVolumeSize -= reservedSize; - - MaxHiddenVolumeSize -= MaxHiddenVolumeSize % SECTOR_SIZE; // Must be a multiple of the sector size - } - catch (exception &e) - { - Gui->SetActiveFrame (this); - Gui->ShowError (e); - return GetCurrentStep(); - } - - return Step::HiddenVolume; - - case Step::HiddenVolume: - return Step::EncryptionOptions; - - default: - throw ParameterIncorrect (SRC_POS); - } - } - - void VolumeCreationWizard::UpdateControls () - { - VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); - if (page) - { - page->EnableAbort (IsWorkInProgress()); - } - } - - bool VolumeCreationWizard::DeviceWarningConfirmed; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Platform/SystemInfo.h" +#ifdef TC_UNIX +#include +#include "Platform/Unix/Process.h" +#endif +#include "Core/RandomNumberGenerator.h" +#include "Core/VolumeCreator.h" +#include "Main/Application.h" +#include "Main/GraphicUserInterface.h" +#include "Main/Resources.h" +#include "VolumeCreationWizard.h" +#include "EncryptionOptionsWizardPage.h" +#include "InfoWizardPage.h" +#include "ProgressWizardPage.h" +#include "SingleChoiceWizardPage.h" +#include "VolumeCreationProgressWizardPage.h" +#include "VolumeFormatOptionsWizardPage.h" +#include "VolumeLocationWizardPage.h" +#include "VolumePasswordWizardPage.h" +#include "VolumeSizeWizardPage.h" + +namespace TrueCrypt +{ + VolumeCreationWizard::VolumeCreationWizard (wxWindow* parent) + : WizardFrame (parent), + CrossPlatformSupport (true), + DisplayKeyInfo (true), + LargeFilesSupport (false), + QuickFormatEnabled (false), + SelectedFilesystemClusterSize (0), + SelectedFilesystemType (VolumeCreationOptions::FilesystemType::FAT), + SelectedVolumeHostType (VolumeHostType::File), + SelectedVolumeType (VolumeType::Normal), + VolumeSize (0) + { + RandomNumberGenerator::Start(); + + SetTitle (LangString["INTRO_TITLE"]); + SetImage (Resources::GetVolumeCreationWizardBitmap (Gui->GetCharHeight (this) * 21)); + SetMaxStaticTextWidth (55); + + SetStep (Step::VolumeHostType); + + class Timer : public wxTimer + { + public: + Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { } + + void Notify() + { + Wizard->OnRandomPoolUpdateTimer(); + } + + VolumeCreationWizard *Wizard; + }; + + RandomPoolUpdateTimer.reset (dynamic_cast (new Timer (this))); + RandomPoolUpdateTimer->Start (200); + } + + VolumeCreationWizard::~VolumeCreationWizard () + { + } + + WizardPage *VolumeCreationWizard::GetPage (WizardStep step) + { + switch (step) + { + case Step::VolumeHostType: + { + ClearHistory(); + + OuterVolume = false; + LargeFilesSupport = false; + QuickFormatEnabled = false; + + SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); + page->SetMinSize (wxSize (Gui->GetCharWidth (this) * 58, Gui->GetCharHeight (this) * 18 + 5)); + + page->SetPageTitle (LangString["INTRO_TITLE"]); + + page->AddChoice (VolumeHostType::File, LangString["IDC_FILE_CONTAINER"], LangString["IDT_FILE_CONTAINER"], L"introcontainer", LangString["IDC_MORE_INFO_ON_CONTAINERS"]); + page->AddChoice (VolumeHostType::Device, _("Create a volume within a partition/&drive"), _("Formats and encrypts a non-system partition, entire external or secondary drive, entire USB stick, etc.")); + + page->SetSelection (SelectedVolumeHostType); + return page; + } + + case Step::VolumeType: + { + SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); + page->SetPageTitle (LangString["VOLUME_TYPE_TITLE"]); + + page->AddChoice (VolumeType::Normal, LangString["IDC_STD_VOL"], LangString["NORMAL_VOLUME_TYPE_HELP"]); + page->AddChoice (VolumeType::Hidden, LangString["IDC_HIDDEN_VOL"], LangString["HIDDEN_VOLUME_TYPE_HELP"], L"hiddenvolume", LangString["IDC_HIDDEN_VOL_HELP"]); + + page->SetSelection (SelectedVolumeType); + return page; + } + + case Step::VolumeLocation: + { + VolumeLocationWizardPage *page = new VolumeLocationWizardPage (GetPageParent(), SelectedVolumeHostType); + page->SetPageTitle (LangString["VOLUME_LOCATION"]); + + if (SelectedVolumeType == VolumeType::Hidden) + page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP_HIDDEN_HOST_VOL" : "DEVICE_HELP_HIDDEN_HOST_VOL"]); + else + page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP" : "DEVICE_HELP_NO_INPLACE"]); + + page->SetVolumePath (SelectedVolumePath); + return page; + } + + case Step::EncryptionOptions: + { + EncryptionOptionsWizardPage *page = new EncryptionOptionsWizardPage (GetPageParent()); + + if (OuterVolume) + page->SetPageTitle (LangString["CIPHER_HIDVOL_HOST_TITLE"]); + else if (SelectedVolumeType == VolumeType::Hidden) + page->SetPageTitle (LangString["CIPHER_HIDVOL_TITLE"]); + else + page->SetPageTitle (LangString["CIPHER_TITLE"]); + + page->SetEncryptionAlgorithm (SelectedEncryptionAlgorithm); + page->SetHash (SelectedHash); + return page; + } + + case Step::VolumeSize: + { + wxString freeSpaceText; + wxString pageTitle; + wxString pageText; + + if (OuterVolume) + { + pageTitle = LangString["SIZE_HIDVOL_HOST_TITLE"]; + pageText = LangString["SIZE_HELP_HIDDEN_HOST_VOL"]; + } + else if (SelectedVolumeType == VolumeType::Hidden) + { + pageTitle = LangString["SIZE_HIDVOL_TITLE"]; + pageText = LangString["SIZE_HELP_HIDDEN_VOL"] + L"\n\n" + _("Please note that if your operating system does not allocate files from the beginning of the free space, the maximum possible hidden volume size may be much smaller than the size of the free space on the outer volume. This not a bug in TrueCrypt but a limitation of the operating system."); + freeSpaceText = StringFormatter (_("Maximum possible hidden volume size for this volume is {0}."), Gui->SizeToString (MaxHiddenVolumeSize)); + } + else + { + pageTitle = LangString["SIZE_TITLE"]; + pageText = LangString["VOLUME_SIZE_HELP"]; + } + + VolumeSizeWizardPage *page = new VolumeSizeWizardPage (GetPageParent(), SelectedVolumePath, freeSpaceText); + + page->SetPageTitle (pageTitle); + page->SetPageText (pageText); + + if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden) + page->SetMaxVolumeSize (MaxHiddenVolumeSize); + else + page->SetVolumeSize (VolumeSize); + + if (OuterVolume) + page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_HOST_SIZE); + else if (SelectedVolumeType == VolumeType::Hidden) + page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_SIZE); + else + page->SetMinVolumeSize (TC_MIN_VOLUME_SIZE); + + return page; + } + + case Step::VolumePassword: + { + VolumePasswordWizardPage *page = new VolumePasswordWizardPage (GetPageParent(), Password, Keyfiles); + + if (OuterVolume) + page->SetPageTitle (LangString["PASSWORD_HIDVOL_HOST_TITLE"]); + else if (SelectedVolumeType == VolumeType::Hidden) + page->SetPageTitle (LangString["PASSWORD_HIDVOL_TITLE"]); + else + page->SetPageTitle (LangString["PASSWORD_TITLE"]); + + page->SetPageText (LangString[OuterVolume ? "PASSWORD_HIDDENVOL_HOST_HELP" : "PASSWORD_HELP"]); + return page; + } + + case Step::LargeFilesSupport: + { + SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); + page->SetPageTitle (LangString["FILESYS_PAGE_TITLE"]); + + page->AddChoice (false, _("I will not store files larger than 4 GB on the volume"), + _("Choose this option if you do not need to store files larger than 4 GB (4,294,967,296 bytes) on the volume.")); + + page->AddChoice (true, _("I will store files larger than 4 GB on the volume"), + _("Choose this option if you need to store files larger than 4 GB (4,294,967,296 bytes) on the volume.")); + + page->SetSelection (LargeFilesSupport); + return page; + } + + case Step::FormatOptions: + { + VolumeFormatOptionsWizardPage *page = new VolumeFormatOptionsWizardPage (GetPageParent(), VolumeSize, + SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden), OuterVolume, LargeFilesSupport); + + page->SetPageTitle (_("Format Options")); + page->SetFilesystemType (SelectedFilesystemType); + + if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden) + QuickFormatEnabled = true; + page->SetQuickFormat (QuickFormatEnabled); + + return page; + } + + case Step::CrossPlatformSupport: + { + SingleChoiceWizardPage *page = new SingleChoiceWizardPage (GetPageParent(), wxEmptyString, true); + page->SetPageTitle (_("Cross-Platform Support")); + + page->AddChoice (true, _("I will mount the volume on other platforms"), + _("Choose this option if you need to use the volume on other platforms.")); + + page->AddChoice (false, StringFormatter (_("I will mount the volume only on {0}"), SystemInfo::GetPlatformName()), + _("Choose this option if you do not need to use the volume on other platforms.")); + + page->SetSelection (CrossPlatformSupport); + return page; + } + + case Step::CreationProgress: + { + VolumeCreationProgressWizardPage *page = new VolumeCreationProgressWizardPage (GetPageParent(), DisplayKeyInfo); + + if (OuterVolume) + page->SetPageTitle (LangString["FORMAT_HIDVOL_HOST_TITLE"]); + else if (SelectedVolumeType == VolumeType::Hidden) + page->SetPageTitle (LangString["FORMAT_HIDVOL_TITLE"]); + else + page->SetPageTitle (LangString["FORMAT_TITLE"]); + + page->SetPageText (LangString["FORMAT_HELP"]); + page->AbortEvent.Connect (EventConnector (this, &VolumeCreationWizard::OnAbortButtonClick)); + page->SetNextButtonText (LangString["FORMAT"]); + return page; + } + + case Step::VolumeCreatedInfo: + { + InfoWizardPage *page = new InfoWizardPage (GetPageParent()); + page->SetPageTitle (LangString["FORMAT_FINISHED_TITLE"]); + page->SetPageText (LangString["FORMAT_FINISHED_HELP"]); + + SetCancelButtonText (_("Exit")); + return page; + } + + case Step::OuterVolumeContents: + { + ClearHistory(); + + MountOptions mountOptions; + mountOptions.NoKernelCrypto = true; + mountOptions.Keyfiles = Keyfiles; + mountOptions.Password = Password; + mountOptions.Path = make_shared (SelectedVolumePath); + + try + { + wxBusyCursor busy; + Gui->SetActiveFrame (this); + MountedOuterVolume = Core->MountVolume (mountOptions); + } + catch (exception &e) + { + Gui->SetActiveFrame (this); + Gui->ShowError (e); + + Close(); + return new InfoWizardPage (GetPageParent()); + } + + struct OpenOuterVolumeFunctor : public Functor + { + OpenOuterVolumeFunctor (const DirectoryPath &outerVolumeMountPoint) : OuterVolumeMountPoint (outerVolumeMountPoint) { } + + virtual void operator() () + { + Gui->OpenExplorerWindow (OuterVolumeMountPoint); + } + + DirectoryPath OuterVolumeMountPoint; + }; + + InfoWizardPage *page = new InfoWizardPage (GetPageParent(), _("Open Outer Volume"), + shared_ptr (new OpenOuterVolumeFunctor (MountedOuterVolume->MountPoint))); + + page->SetPageTitle (LangString["HIDVOL_HOST_FILLING_TITLE"]); + + page->SetPageText (StringFormatter ( + _("Outer volume has been successfully created and mounted as '{0}'. To this volume you should now copy some sensitive-looking files that you actually do NOT want to hide. The files will be there for anyone forcing you to disclose your password. You will reveal only the password for this outer volume, not for the hidden one. The files that you really care about will be stored in the hidden volume, which will be created later on. When you finish copying, click Next. Do not dismount the volume.\n\nNote: After you click Next, the outer volume will be analyzed to determine the size of uninterrupted area of free space whose end is aligned with the end of the volume. This area will accommodate the hidden volume, so it will limit its maximum possible size. The procedure ensures no data on the outer volume are overwritten by the hidden volume."), + wstring (MountedOuterVolume->MountPoint))); + + return page; + } + + case Step::HiddenVolume: + { + ClearHistory(); + OuterVolume = false; + LargeFilesSupport = false; + + InfoWizardPage *page = new InfoWizardPage (GetPageParent()); + page->SetPageTitle (LangString["HIDVOL_PRE_CIPHER_TITLE"]); + page->SetPageText (LangString["HIDVOL_PRE_CIPHER_HELP"]); + + return page; + } + + default: + throw ParameterIncorrect (SRC_POS); + } + } + + void VolumeCreationWizard::OnAbortButtonClick (EventArgs &args) + { + AbortRequested = true; + } + + void VolumeCreationWizard::OnMouseMotion (wxMouseEvent& event) + { + event.Skip(); + if (!IsWorkInProgress() && RandomNumberGenerator::IsRunning()) + { + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&event), sizeof (event))); + + long coord = event.GetX(); + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); + coord = event.GetY(); + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&coord), sizeof (coord))); + } + } + + void VolumeCreationWizard::OnProgressTimer () + { + if (!IsWorkInProgress()) + return; + + if (AbortRequested && !AbortConfirmationPending) + { + AbortConfirmationPending = true; + if (Gui->AskYesNo (LangString ["FORMAT_ABORT"], true)) + { + if (IsWorkInProgress() && Creator.get() != nullptr) + { + CreationAborted = true; + Creator->Abort(); + } + } + AbortRequested = false; + AbortConfirmationPending = false; + } + + VolumeCreator::ProgressInfo progress = Creator->GetProgressInfo(); + + VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); + page->SetProgressValue (progress.SizeDone); + + if (!progress.CreationInProgress && !AbortConfirmationPending) + { + SetWorkInProgress (false); + OnVolumeCreatorFinished (); + } + } + + void VolumeCreationWizard::OnRandomPoolUpdateTimer () + { + if (!IsWorkInProgress()) + { + wxLongLong time = wxGetLocalTimeMillis(); + RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast (&time), sizeof (time))); + } + } + + void VolumeCreationWizard::OnVolumeCreatorFinished () + { + VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); + + ProgressTimer.reset(); + page->SetProgressState (false); + + Gui->EndInteractiveBusyState (this); + SetWorkInProgress (false); + UpdateControls(); + + try + { + if (!CreationAborted) + { + Creator->CheckResult(); + +#ifdef TC_UNIX + // Format non-FAT filesystem + const char *fsFormatter = nullptr; + + switch (SelectedFilesystemType) + { + case VolumeCreationOptions::FilesystemType::Ext2: fsFormatter = "mkfs.ext2"; break; + case VolumeCreationOptions::FilesystemType::Ext3: fsFormatter = "mkfs.ext3"; break; + case VolumeCreationOptions::FilesystemType::MacOsExt: fsFormatter = "newfs_hfs"; break; + case VolumeCreationOptions::FilesystemType::UFS: fsFormatter = "newfs" ; break; + default: break; + } + + if (fsFormatter) + { + wxBusyCursor busy; + + MountOptions mountOptions; + mountOptions.Path = make_shared (SelectedVolumePath); + mountOptions.NoFilesystem = true; + mountOptions.Password = Password; + mountOptions.Keyfiles = Keyfiles; + mountOptions.NoKernelCrypto = Gui->GetPreferences().DefaultMountOptions.NoKernelCrypto; + + shared_ptr volume = Core->MountVolume (mountOptions); + finally_do_arg (shared_ptr , volume, { Core->DismountVolume (finally_arg, true); }); + + Thread::Sleep (2000); // Try to prevent race conditions caused by OS + + // Temporarily take ownership of the device if the user is not an administrator + UserId origDeviceOwner ((uid_t) -1); + + DevicePath virtualDevice = volume->VirtualDevice; +#ifdef TC_MACOSX + string virtualDeviceStr = virtualDevice; + if (virtualDeviceStr.find ("/dev/rdisk") != 0) + virtualDevice = "/dev/r" + virtualDeviceStr.substr (5); +#endif + try + { + File file; + file.Open (virtualDevice, File::OpenReadWrite); + } + catch (...) + { + if (!Core->HasAdminPrivileges()) + { + origDeviceOwner = virtualDevice.GetOwner(); + Core->SetFileOwner (virtualDevice, UserId (getuid())); + } + } + + finally_do_arg2 (FilesystemPath, virtualDevice, UserId, origDeviceOwner, + { + if (finally_arg2.SystemId != (uid_t) -1) + Core->SetFileOwner (finally_arg, finally_arg2); + }); + + // Create filesystem + list args; + + if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::MacOsExt && VolumeSize >= 10 * BYTES_PER_MB) + args.push_back ("-J"); + + args.push_back (string (virtualDevice)); + + Process::Execute (fsFormatter, args); + } +#endif // TC_UNIX + + if (OuterVolume) + { + SetStep (Step::OuterVolumeContents); + } + else + { + Gui->ShowInfo (SelectedVolumeType == VolumeType::Hidden ? "HIDVOL_FORMAT_FINISHED_HELP" : "FORMAT_FINISHED_INFO"); + SetStep (Step::VolumeCreatedInfo); + } + + return; + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + + page->SetProgressValue (0); + if (SelectedVolumeType == VolumeType::Normal && !SelectedVolumePath.IsDevice()) + { + try + { + FilePath (wstring (SelectedVolumePath)).Delete(); + } + catch (...) { } + } + } + + WizardFrame::WizardStep VolumeCreationWizard::ProcessPageChangeRequest (bool forward) + { + switch (GetCurrentStep()) + { + case Step::VolumeHostType: + { + SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); + + try + { + SelectedVolumeHostType = page->GetSelection(); + } + catch (NoItemSelected &) + { + return GetCurrentStep(); + } + + return Step::VolumeType; + } + + case Step::VolumeType: + { + SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); + + try + { + SelectedVolumeType = page->GetSelection(); + } + catch (NoItemSelected &) + { + return GetCurrentStep(); + } + + if (SelectedVolumeType == VolumeType::Hidden) + OuterVolume = true; + + return Step::VolumeLocation; + } + + case Step::VolumeLocation: + { + VolumeLocationWizardPage *page = dynamic_cast (GetCurrentPage()); + SelectedVolumePath = page->GetVolumePath(); + VolumeSize = 0; + + if (forward) + { + if (Core->IsVolumeMounted (SelectedVolumePath)) + { + Gui->ShowInfo ("DISMOUNT_FIRST"); + return GetCurrentStep(); + } + + if (SelectedVolumePath.IsDevice()) + { + if (!DeviceWarningConfirmed && !Gui->AskYesNo (LangString["FORMAT_DEVICE_FOR_ADVANCED_ONLY"])) + return GetCurrentStep(); + + DeviceWarningConfirmed = true; + + foreach_ref (const HostDevice &drive, Core->GetHostDevices()) + { + if (drive.Path == SelectedVolumePath && !drive.Partitions.empty()) + { + Gui->ShowError ("DEVICE_PARTITIONS_ERR"); + return GetCurrentStep(); + } + } + + try + { + VolumeSize = Core->GetDeviceSize (SelectedVolumePath); + } + catch (UserAbort&) + { + return Step::VolumeLocation; + } + catch (exception &e) + { + Gui->ShowError (e); + Gui->ShowError ("CANNOT_CALC_SPACE"); + return GetCurrentStep(); + } + + DirectoryPath mountPoint; + try + { + mountPoint = Core->GetDeviceMountPoint (SelectedVolumePath); + + if (!mountPoint.IsEmpty()) + { + if (!Gui->AskYesNo (StringFormatter (_("WARNING: Formatting of the device will destroy all data on filesystem '{0}'.\n\nDo you want to continue?"), wstring (mountPoint)), false, true)) + return GetCurrentStep(); + + try + { + Core->DismountFilesystem (mountPoint, true); + } + catch (exception &e) + { + Gui->ShowError (e); + Gui->ShowError (StringFormatter (_("The filesystem of the selected device is currently mounted. Please dismount '{0}' before proceeding."), wstring (mountPoint))); + return GetCurrentStep(); + } + } + } + catch (...) { } + } + } + + return Step::EncryptionOptions; + } + + case Step::EncryptionOptions: + { + EncryptionOptionsWizardPage *page = dynamic_cast (GetCurrentPage()); + SelectedEncryptionAlgorithm = page->GetEncryptionAlgorithm (); + SelectedHash = page->GetHash (); + + if (forward) + RandomNumberGenerator::SetHash (SelectedHash); + + if (SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden)) + return Step::VolumePassword; + else + return Step::VolumeSize; + } + + case Step::VolumeSize: + { + VolumeSizeWizardPage *page = dynamic_cast (GetCurrentPage()); + + try + { + VolumeSize = page->GetVolumeSize(); + } + catch (Exception &e) + { + if (forward) + { + Gui->ShowError (e); + return GetCurrentStep(); + } + } + + if (forward + && !OuterVolume && SelectedVolumeType == VolumeType::Hidden + && (double) VolumeSize / MaxHiddenVolumeSize > 0.85) + { + if (!Gui->AskYesNo (LangString["FREE_SPACE_FOR_WRITING_TO_OUTER_VOLUME"])) + return GetCurrentStep(); + } + + if (forward + && SelectedVolumeHostType == VolumeHostType::File + && VolumeSize > 4 * BYTES_PER_GB + && (OuterVolume || SelectedVolumeType != VolumeType::Hidden) + && !Core->FilesystemSupportsLargeFiles (SelectedVolumePath)) + { + Gui->ShowWarning (LangString["VOLUME_TOO_LARGE_FOR_FAT32"]); + } + + return Step::VolumePassword; + } + + case Step::VolumePassword: + { + VolumePasswordWizardPage *page = dynamic_cast (GetCurrentPage()); + Password = page->GetPassword(); + Keyfiles = page->GetKeyfiles(); + + if (forward && Password && !Password->IsEmpty()) + { + try + { + Password->CheckPortability(); + } + catch (UnportablePassword &e) + { + Gui->ShowError (e); + return GetCurrentStep(); + } + + if (Password->Size() < VolumePassword::WarningSizeThreshold + && !Gui->AskYesNo (LangString["PASSWORD_LENGTH_WARNING"], false, true)) + { + return GetCurrentStep(); + } + } + + if (forward && OuterVolume) + { + // Use FAT to prevent problems with free space + QuickFormatEnabled = false; + SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT; + return Step::CreationProgress; + } + + if (VolumeSize > 4 * BYTES_PER_GB) + { + if (VolumeSize < TC_MAX_FAT_FS_SIZE) + return Step::LargeFilesSupport; + else + SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative(); + } + + return Step::FormatOptions; + } + + case Step::LargeFilesSupport: + { + SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); + + try + { + LargeFilesSupport = page->GetSelection(); + } + catch (NoItemSelected &) + { + return GetCurrentStep(); + } + + if (LargeFilesSupport) + SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative(); + else + SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT; + + return Step::FormatOptions; + } + + case Step::FormatOptions: + { + VolumeFormatOptionsWizardPage *page = dynamic_cast (GetCurrentPage()); + SelectedFilesystemType = page->GetFilesystemType(); + QuickFormatEnabled = page->IsQuickFormatEnabled(); + + if (OuterVolume && SelectedFilesystemType != VolumeCreationOptions::FilesystemType::FAT) + Gui->ShowInfo (_("Please note that the FAT filesystem usually offers the maximum free space available for the hidden volume.")); + + if (SelectedFilesystemType != VolumeCreationOptions::FilesystemType::None + && SelectedFilesystemType != VolumeCreationOptions::FilesystemType::FAT) + return Step::CrossPlatformSupport; + + return Step::CreationProgress; + } + + case Step::CrossPlatformSupport: + { + SingleChoiceWizardPage *page = dynamic_cast *> (GetCurrentPage()); + + try + { + CrossPlatformSupport = page->GetSelection(); + } + catch (NoItemSelected &) + { + return GetCurrentStep(); + } + + if (forward && CrossPlatformSupport) + Gui->ShowWarning (StringFormatter (_("Please note that the volume will not be formatted with a FAT filesystem and, therefore, you may be required to install additional filesystem drivers on platforms other than {0}, which will enable you to mount the volume."), SystemInfo::GetPlatformName())); + + return Step::CreationProgress; + } + + case Step::CreationProgress: + { + VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); + + DisplayKeyInfo = page->IsKeyInfoDisplayed(); + + if (forward) + { + if (SelectedVolumeType != VolumeType::Hidden || OuterVolume) + { + if (SelectedVolumePath.IsDevice()) + { + wxString confirmMsg = LangString["OVERWRITEPROMPT_DEVICE"]; + confirmMsg.Replace (L"%hs", L"%s"); + + if (!Gui->AskYesNo (wxString::Format (confirmMsg, wxString (_("DEVICE")).c_str(), wstring (SelectedVolumePath).c_str(), L""), false, true)) + return GetCurrentStep(); + } + else if (FilesystemPath (wstring (SelectedVolumePath)).IsFile()) + { + wxString confirmMsg = LangString["OVERWRITEPROMPT"]; + confirmMsg.Replace (L"%hs", L"%s"); + + if (!Gui->AskYesNo (wxString::Format (confirmMsg, wstring (SelectedVolumePath).c_str(), false, true))) + return GetCurrentStep(); + } + } + + AbortRequested = false; + AbortConfirmationPending = false; + CreationAborted = false; + SetWorkInProgress (true); + UpdateControls(); + + Gui->BeginInteractiveBusyState (this); + + try + { + make_shared_auto (VolumeCreationOptions, options); + + options->Filesystem = SelectedFilesystemType; + options->FilesystemClusterSize = SelectedFilesystemClusterSize; + + options->EA = SelectedEncryptionAlgorithm; + options->Password = Password; + options->Keyfiles = Keyfiles; + options->Path = SelectedVolumePath; + options->Quick = QuickFormatEnabled; + options->Size = VolumeSize; + options->Type = OuterVolume ? VolumeType::Normal : SelectedVolumeType; + options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*SelectedHash); + + Creator.reset (new VolumeCreator); + Creator->CreateVolume (options); + + page->SetKeyInfo (Creator->GetKeyInfo()); + + class Timer : public wxTimer + { + public: + Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { } + + void Notify() + { + Wizard->OnProgressTimer(); + } + + VolumeCreationWizard *Wizard; + }; + + page->SetProgressRange (options->Size); + page->SetProgressState (true); + ProgressTimer.reset (dynamic_cast (new Timer (this))); + ProgressTimer->Start (50); + } + catch (Exception &e) + { + CreationAborted = true; + OnVolumeCreatorFinished(); + Gui->ShowError (e); + } + } + + return GetCurrentStep(); + } + + case Step::VolumeCreatedInfo: + Creator.reset(); + SetCancelButtonText (L""); + + return Step::VolumeHostType; + + case Step::OuterVolumeContents: + try + { + // Determine maximum size of the hidden volume + wxBusyCursor busy; +#ifdef TC_UNIX + sync(); +#endif + VolumeInfoList ml = Core->GetMountedVolumes (MountedOuterVolume->Path); + MaxHiddenVolumeSize = 0; + + if (ml.empty()) + throw ParameterIncorrect (SRC_POS); + + if (ml.front()->TopWriteOffset == 0) + throw_err (_("The outer volume does not contain any files.")); + + Gui->SetActiveFrame (this); + shared_ptr dismountedOuterVolume = Core->DismountVolume (MountedOuterVolume, false, true); + + if (dismountedOuterVolume->Size > dismountedOuterVolume->TopWriteOffset) + MaxHiddenVolumeSize = dismountedOuterVolume->Size - dismountedOuterVolume->TopWriteOffset; + + // Add a reserve (in case the user mounts the outer volume and creates new files + // on it by accident or OS writes some new data behind his or her back, such as + // System Restore etc.) + + uint64 reservedSize = dismountedOuterVolume->Size / 200; + if (reservedSize > 10 * BYTES_PER_MB) + reservedSize = 10 * BYTES_PER_MB; + + if (MaxHiddenVolumeSize < reservedSize) + MaxHiddenVolumeSize = 0; + else + MaxHiddenVolumeSize -= reservedSize; + + MaxHiddenVolumeSize -= MaxHiddenVolumeSize % SECTOR_SIZE; // Must be a multiple of the sector size + } + catch (exception &e) + { + Gui->SetActiveFrame (this); + Gui->ShowError (e); + return GetCurrentStep(); + } + + return Step::HiddenVolume; + + case Step::HiddenVolume: + return Step::EncryptionOptions; + + default: + throw ParameterIncorrect (SRC_POS); + } + } + + void VolumeCreationWizard::UpdateControls () + { + VolumeCreationProgressWizardPage *page = dynamic_cast (GetCurrentPage()); + if (page) + { + page->EnableAbort (IsWorkInProgress()); + } + } + + bool VolumeCreationWizard::DeviceWarningConfirmed; +} diff --git a/Main/Forms/VolumeCreationWizard.h b/Main/Forms/VolumeCreationWizard.h index 481b0e1..a73a339 100644 --- a/Main/Forms/VolumeCreationWizard.h +++ b/Main/Forms/VolumeCreationWizard.h @@ -1,84 +1,84 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_VolumeCreationWizard -#define TC_HEADER_Main_Forms_VolumeCreationWizard - -#include "WizardFrame.h" -#include "Core/VolumeCreator.h" - -namespace TrueCrypt -{ - class VolumeCreationWizard : public WizardFrame - { - public: - VolumeCreationWizard (wxWindow* parent); - ~VolumeCreationWizard (); - - protected: - struct Step - { - enum Enum - { - VolumeHostType, - VolumeType, - VolumeLocation, - EncryptionOptions, - VolumeSize, - VolumePassword, - LargeFilesSupport, - FormatOptions, - CrossPlatformSupport, - CreationProgress, - VolumeCreatedInfo, - OuterVolumeContents, - HiddenVolume - }; - }; - - void CreateVolume (); - WizardPage *GetPage (WizardStep step); - void OnAbortButtonClick (EventArgs &args); - void OnMouseMotion (wxMouseEvent& event); - void OnProgressTimer (); - void OnRandomPoolUpdateTimer (); - void OnThreadExiting (wxCommandEvent& event); - void OnVolumeCreatorFinished (); - WizardStep ProcessPageChangeRequest (bool forward); - - volatile bool AbortConfirmationPending; - volatile bool AbortRequested; - volatile bool CreationAborted; - auto_ptr Creator; - bool CrossPlatformSupport; - static bool DeviceWarningConfirmed; - bool DisplayKeyInfo; - auto_ptr ProgressTimer; - auto_ptr RandomPoolUpdateTimer; - shared_ptr Keyfiles; - bool LargeFilesSupport; - uint64 MaxHiddenVolumeSize; - shared_ptr MountedOuterVolume; - bool OuterVolume; - bool QuickFormatEnabled; - shared_ptr SelectedEncryptionAlgorithm; - uint32 SelectedFilesystemClusterSize; - VolumeCreationOptions::FilesystemType::Enum SelectedFilesystemType; - VolumePath SelectedVolumePath; - VolumeHostType::Enum SelectedVolumeHostType; - VolumeType::Enum SelectedVolumeType; - shared_ptr Password; - shared_ptr SelectedHash; - uint64 VolumeSize; - - private: - void UpdateControls (); - }; -} - -#endif // TC_HEADER_Main_Forms_VolumeCreationWizard +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_VolumeCreationWizard +#define TC_HEADER_Main_Forms_VolumeCreationWizard + +#include "WizardFrame.h" +#include "Core/VolumeCreator.h" + +namespace TrueCrypt +{ + class VolumeCreationWizard : public WizardFrame + { + public: + VolumeCreationWizard (wxWindow* parent); + ~VolumeCreationWizard (); + + protected: + struct Step + { + enum Enum + { + VolumeHostType, + VolumeType, + VolumeLocation, + EncryptionOptions, + VolumeSize, + VolumePassword, + LargeFilesSupport, + FormatOptions, + CrossPlatformSupport, + CreationProgress, + VolumeCreatedInfo, + OuterVolumeContents, + HiddenVolume + }; + }; + + void CreateVolume (); + WizardPage *GetPage (WizardStep step); + void OnAbortButtonClick (EventArgs &args); + void OnMouseMotion (wxMouseEvent& event); + void OnProgressTimer (); + void OnRandomPoolUpdateTimer (); + void OnThreadExiting (wxCommandEvent& event); + void OnVolumeCreatorFinished (); + WizardStep ProcessPageChangeRequest (bool forward); + + volatile bool AbortConfirmationPending; + volatile bool AbortRequested; + volatile bool CreationAborted; + auto_ptr Creator; + bool CrossPlatformSupport; + static bool DeviceWarningConfirmed; + bool DisplayKeyInfo; + auto_ptr ProgressTimer; + auto_ptr RandomPoolUpdateTimer; + shared_ptr Keyfiles; + bool LargeFilesSupport; + uint64 MaxHiddenVolumeSize; + shared_ptr MountedOuterVolume; + bool OuterVolume; + bool QuickFormatEnabled; + shared_ptr SelectedEncryptionAlgorithm; + uint32 SelectedFilesystemClusterSize; + VolumeCreationOptions::FilesystemType::Enum SelectedFilesystemType; + VolumePath SelectedVolumePath; + VolumeHostType::Enum SelectedVolumeHostType; + VolumeType::Enum SelectedVolumeType; + shared_ptr Password; + shared_ptr SelectedHash; + uint64 VolumeSize; + + private: + void UpdateControls (); + }; +} + +#endif // TC_HEADER_Main_Forms_VolumeCreationWizard diff --git a/Main/Forms/VolumeFormatOptionsWizardPage.cpp b/Main/Forms/VolumeFormatOptionsWizardPage.cpp index 2ac5aef..93a0350 100644 --- a/Main/Forms/VolumeFormatOptionsWizardPage.cpp +++ b/Main/Forms/VolumeFormatOptionsWizardPage.cpp @@ -1,79 +1,79 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "VolumeFormatOptionsWizardPage.h" - -namespace TrueCrypt -{ - VolumeFormatOptionsWizardPage::VolumeFormatOptionsWizardPage (wxPanel* parent, uint64 volumeSize, bool enableQuickFormatButton, bool disableNoneFilesystem, bool disable32bitFilesystems) - : VolumeFormatOptionsWizardPageBase (parent) - { - InfoStaticText->SetLabel (_( - "In order to enable your operating system to mount your new volume, it has to be formatted with a filesystem. Please select a filesystem type.\n\nIf your volume is going to be hosted on a device or partition, you can use 'Quick format' to skip encryption of free space of the volume.")); - - if (!disableNoneFilesystem) - FilesystemTypeChoice->Append (LangString["NONE"], (void *) VolumeCreationOptions::FilesystemType::None); - - if (!disable32bitFilesystems && volumeSize <= TC_MAX_FAT_FS_SIZE) - FilesystemTypeChoice->Append (L"FAT", (void *) VolumeCreationOptions::FilesystemType::FAT); - -#ifdef TC_WINDOWS - FilesystemTypeChoice->Append (L"NTFS", (void *) VolumeCreationOptions::FilesystemType::NTFS); -#elif defined (TC_LINUX) - FilesystemTypeChoice->Append (L"Linux Ext2", (void *) VolumeCreationOptions::FilesystemType::Ext2); - FilesystemTypeChoice->Append (L"Linux Ext3", (void *) VolumeCreationOptions::FilesystemType::Ext3); -#elif defined (TC_MACOSX) - FilesystemTypeChoice->Append (L"Mac OS Extended", (void *) VolumeCreationOptions::FilesystemType::MacOsExt); -#elif defined (TC_FREEBSD) || defined (TC_SOLARIS) - FilesystemTypeChoice->Append (L"UFS", (void *) VolumeCreationOptions::FilesystemType::UFS); -#endif - - if (!disable32bitFilesystems && volumeSize <= TC_MAX_FAT_FS_SIZE) - SetFilesystemType (VolumeCreationOptions::FilesystemType::FAT); - else - SetFilesystemType (VolumeCreationOptions::FilesystemType::GetPlatformNative()); - - QuickFormatCheckBox->Enable (enableQuickFormatButton); - } - - VolumeCreationOptions::FilesystemType::Enum VolumeFormatOptionsWizardPage::GetFilesystemType () const - { - return (VolumeCreationOptions::FilesystemType::Enum) reinterpret_cast (Gui->GetSelectedData (FilesystemTypeChoice)); - } - - void VolumeFormatOptionsWizardPage::OnFilesystemTypeSelected (wxCommandEvent& event) - { - } - - void VolumeFormatOptionsWizardPage::OnQuickFormatCheckBoxClick (wxCommandEvent& event) - { - if (event.IsChecked()) - { - QuickFormatCheckBox->SetValue (Gui->AskYesNo (LangString["WARN_QUICK_FORMAT"], false, true)); - } - } - - void VolumeFormatOptionsWizardPage::SetFilesystemType (VolumeCreationOptions::FilesystemType::Enum type) - { - switch (type) - { - case VolumeCreationOptions::FilesystemType::None: FilesystemTypeChoice->SetStringSelection (LangString["NONE"]); break; - case VolumeCreationOptions::FilesystemType::FAT: FilesystemTypeChoice->SetStringSelection (L"FAT"); break; - case VolumeCreationOptions::FilesystemType::NTFS: FilesystemTypeChoice->SetStringSelection (L"NTFS"); break; - case VolumeCreationOptions::FilesystemType::Ext2: FilesystemTypeChoice->SetStringSelection (L"Linux Ext2"); break; - case VolumeCreationOptions::FilesystemType::Ext3: FilesystemTypeChoice->SetStringSelection (L"Linux Ext3"); break; - case VolumeCreationOptions::FilesystemType::MacOsExt: FilesystemTypeChoice->SetStringSelection (L"Mac OS Extended"); break; - case VolumeCreationOptions::FilesystemType::UFS: FilesystemTypeChoice->SetStringSelection (L"UFS"); break; - - default: - throw ParameterIncorrect (SRC_POS); - } - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "VolumeFormatOptionsWizardPage.h" + +namespace TrueCrypt +{ + VolumeFormatOptionsWizardPage::VolumeFormatOptionsWizardPage (wxPanel* parent, uint64 volumeSize, bool enableQuickFormatButton, bool disableNoneFilesystem, bool disable32bitFilesystems) + : VolumeFormatOptionsWizardPageBase (parent) + { + InfoStaticText->SetLabel (_( + "In order to enable your operating system to mount your new volume, it has to be formatted with a filesystem. Please select a filesystem type.\n\nIf your volume is going to be hosted on a device or partition, you can use 'Quick format' to skip encryption of free space of the volume.")); + + if (!disableNoneFilesystem) + FilesystemTypeChoice->Append (LangString["NONE"], (void *) VolumeCreationOptions::FilesystemType::None); + + if (!disable32bitFilesystems && volumeSize <= TC_MAX_FAT_FS_SIZE) + FilesystemTypeChoice->Append (L"FAT", (void *) VolumeCreationOptions::FilesystemType::FAT); + +#ifdef TC_WINDOWS + FilesystemTypeChoice->Append (L"NTFS", (void *) VolumeCreationOptions::FilesystemType::NTFS); +#elif defined (TC_LINUX) + FilesystemTypeChoice->Append (L"Linux Ext2", (void *) VolumeCreationOptions::FilesystemType::Ext2); + FilesystemTypeChoice->Append (L"Linux Ext3", (void *) VolumeCreationOptions::FilesystemType::Ext3); +#elif defined (TC_MACOSX) + FilesystemTypeChoice->Append (L"Mac OS Extended", (void *) VolumeCreationOptions::FilesystemType::MacOsExt); +#elif defined (TC_FREEBSD) || defined (TC_SOLARIS) + FilesystemTypeChoice->Append (L"UFS", (void *) VolumeCreationOptions::FilesystemType::UFS); +#endif + + if (!disable32bitFilesystems && volumeSize <= TC_MAX_FAT_FS_SIZE) + SetFilesystemType (VolumeCreationOptions::FilesystemType::FAT); + else + SetFilesystemType (VolumeCreationOptions::FilesystemType::GetPlatformNative()); + + QuickFormatCheckBox->Enable (enableQuickFormatButton); + } + + VolumeCreationOptions::FilesystemType::Enum VolumeFormatOptionsWizardPage::GetFilesystemType () const + { + return (VolumeCreationOptions::FilesystemType::Enum) reinterpret_cast (Gui->GetSelectedData (FilesystemTypeChoice)); + } + + void VolumeFormatOptionsWizardPage::OnFilesystemTypeSelected (wxCommandEvent& event) + { + } + + void VolumeFormatOptionsWizardPage::OnQuickFormatCheckBoxClick (wxCommandEvent& event) + { + if (event.IsChecked()) + { + QuickFormatCheckBox->SetValue (Gui->AskYesNo (LangString["WARN_QUICK_FORMAT"], false, true)); + } + } + + void VolumeFormatOptionsWizardPage::SetFilesystemType (VolumeCreationOptions::FilesystemType::Enum type) + { + switch (type) + { + case VolumeCreationOptions::FilesystemType::None: FilesystemTypeChoice->SetStringSelection (LangString["NONE"]); break; + case VolumeCreationOptions::FilesystemType::FAT: FilesystemTypeChoice->SetStringSelection (L"FAT"); break; + case VolumeCreationOptions::FilesystemType::NTFS: FilesystemTypeChoice->SetStringSelection (L"NTFS"); break; + case VolumeCreationOptions::FilesystemType::Ext2: FilesystemTypeChoice->SetStringSelection (L"Linux Ext2"); break; + case VolumeCreationOptions::FilesystemType::Ext3: FilesystemTypeChoice->SetStringSelection (L"Linux Ext3"); break; + case VolumeCreationOptions::FilesystemType::MacOsExt: FilesystemTypeChoice->SetStringSelection (L"Mac OS Extended"); break; + case VolumeCreationOptions::FilesystemType::UFS: FilesystemTypeChoice->SetStringSelection (L"UFS"); break; + + default: + throw ParameterIncorrect (SRC_POS); + } + } +} diff --git a/Main/Forms/VolumeFormatOptionsWizardPage.h b/Main/Forms/VolumeFormatOptionsWizardPage.h index a802735..f0efc57 100644 --- a/Main/Forms/VolumeFormatOptionsWizardPage.h +++ b/Main/Forms/VolumeFormatOptionsWizardPage.h @@ -1,36 +1,36 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_VolumeFormatOptionsWizardPage -#define TC_HEADER_Main_Forms_VolumeFormatOptionsWizardPage - -#include "Forms.h" -#include "Core/VolumeCreator.h" - -namespace TrueCrypt -{ - class VolumeFormatOptionsWizardPage : public VolumeFormatOptionsWizardPageBase - { - public: - VolumeFormatOptionsWizardPage (wxPanel* parent, uint64 volumeSize, bool enableQuickFormatButton = true, bool disableNoneFilesystem = false, bool disable32bitFilesystems = false); - - VolumeCreationOptions::FilesystemType::Enum GetFilesystemType () const; - bool IsValid () { return true; } - bool IsQuickFormatEnabled () const { return QuickFormatCheckBox->IsChecked(); } - void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } - void SetFilesystemType (VolumeCreationOptions::FilesystemType::Enum type); - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - void SetQuickFormat (bool enabled) { QuickFormatCheckBox->SetValue (enabled); } - - protected: - void OnFilesystemTypeSelected (wxCommandEvent& event); - void OnQuickFormatCheckBoxClick (wxCommandEvent& event); - }; -} - -#endif // TC_HEADER_Main_Forms_VolumeFormatOptionsWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_VolumeFormatOptionsWizardPage +#define TC_HEADER_Main_Forms_VolumeFormatOptionsWizardPage + +#include "Forms.h" +#include "Core/VolumeCreator.h" + +namespace TrueCrypt +{ + class VolumeFormatOptionsWizardPage : public VolumeFormatOptionsWizardPageBase + { + public: + VolumeFormatOptionsWizardPage (wxPanel* parent, uint64 volumeSize, bool enableQuickFormatButton = true, bool disableNoneFilesystem = false, bool disable32bitFilesystems = false); + + VolumeCreationOptions::FilesystemType::Enum GetFilesystemType () const; + bool IsValid () { return true; } + bool IsQuickFormatEnabled () const { return QuickFormatCheckBox->IsChecked(); } + void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } + void SetFilesystemType (VolumeCreationOptions::FilesystemType::Enum type); + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + void SetQuickFormat (bool enabled) { QuickFormatCheckBox->SetValue (enabled); } + + protected: + void OnFilesystemTypeSelected (wxCommandEvent& event); + void OnQuickFormatCheckBoxClick (wxCommandEvent& event); + }; +} + +#endif // TC_HEADER_Main_Forms_VolumeFormatOptionsWizardPage diff --git a/Main/Forms/VolumeLocationWizardPage.cpp b/Main/Forms/VolumeLocationWizardPage.cpp index bd15276..db28d65 100644 --- a/Main/Forms/VolumeLocationWizardPage.cpp +++ b/Main/Forms/VolumeLocationWizardPage.cpp @@ -1,98 +1,98 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "Main/VolumeHistory.h" -#include "VolumeLocationWizardPage.h" - -namespace TrueCrypt -{ - VolumeLocationWizardPage::VolumeLocationWizardPage (wxPanel* parent, VolumeHostType::Enum hostType, bool selectExisting) - : VolumeLocationWizardPageBase (parent), - SelectExisting (selectExisting) - { - switch (hostType) - { - case VolumeHostType::Device: - SelectFileButton->Show (false); - break; - - case VolumeHostType::File: - SelectDeviceButton->Show (false); - break; - - default: - break; - } - - Gui->PreferencesUpdatedEvent.Connect (EventConnector (this, &VolumeLocationWizardPage::OnPreferencesUpdated)); - VolumeHistory::ConnectComboBox (VolumePathComboBox); - - NoHistoryCheckBox->SetValue (!Gui->GetPreferences().SaveHistory); - } - - VolumeLocationWizardPage::~VolumeLocationWizardPage () - { - Gui->PreferencesUpdatedEvent.Disconnect (this); - VolumeHistory::DisconnectComboBox (VolumePathComboBox); - } - - void VolumeLocationWizardPage::OnNoHistoryCheckBoxClick (wxCommandEvent& event) - { - UserPreferences prefs = Gui->GetPreferences(); - prefs.SaveHistory = !event.IsChecked(); - Gui->SetPreferences (prefs); - - if (event.IsChecked()) - { - try - { - VolumeHistory::Clear(); - } - catch (exception &e) { Gui->ShowError (e); } - } - } - - void VolumeLocationWizardPage::OnPageChanging (bool forward) - { - if (forward) - { - VolumePath path = GetVolumePath(); - if (!path.IsEmpty()) - VolumeHistory::Add (path); - } - } - - void VolumeLocationWizardPage::OnPreferencesUpdated (EventArgs &args) - { - NoHistoryCheckBox->SetValue (!Gui->GetPreferences().SaveHistory); - } - - void VolumeLocationWizardPage::OnSelectFileButtonClick (wxCommandEvent& event) - { - FilePath path = Gui->SelectVolumeFile (this, !SelectExisting); - - if (!path.IsEmpty()) - SetVolumePath (path); - } - - void VolumeLocationWizardPage::OnSelectDeviceButtonClick (wxCommandEvent& event) - { - DevicePath path = Gui->SelectDevice (this); - - if (!path.IsEmpty()) - SetVolumePath (path); - } - - void VolumeLocationWizardPage::SetVolumePath (const VolumePath &path) - { - VolumePathComboBox->SetValue (wstring (path)); - PageUpdatedEvent.Raise(); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "Main/VolumeHistory.h" +#include "VolumeLocationWizardPage.h" + +namespace TrueCrypt +{ + VolumeLocationWizardPage::VolumeLocationWizardPage (wxPanel* parent, VolumeHostType::Enum hostType, bool selectExisting) + : VolumeLocationWizardPageBase (parent), + SelectExisting (selectExisting) + { + switch (hostType) + { + case VolumeHostType::Device: + SelectFileButton->Show (false); + break; + + case VolumeHostType::File: + SelectDeviceButton->Show (false); + break; + + default: + break; + } + + Gui->PreferencesUpdatedEvent.Connect (EventConnector (this, &VolumeLocationWizardPage::OnPreferencesUpdated)); + VolumeHistory::ConnectComboBox (VolumePathComboBox); + + NoHistoryCheckBox->SetValue (!Gui->GetPreferences().SaveHistory); + } + + VolumeLocationWizardPage::~VolumeLocationWizardPage () + { + Gui->PreferencesUpdatedEvent.Disconnect (this); + VolumeHistory::DisconnectComboBox (VolumePathComboBox); + } + + void VolumeLocationWizardPage::OnNoHistoryCheckBoxClick (wxCommandEvent& event) + { + UserPreferences prefs = Gui->GetPreferences(); + prefs.SaveHistory = !event.IsChecked(); + Gui->SetPreferences (prefs); + + if (event.IsChecked()) + { + try + { + VolumeHistory::Clear(); + } + catch (exception &e) { Gui->ShowError (e); } + } + } + + void VolumeLocationWizardPage::OnPageChanging (bool forward) + { + if (forward) + { + VolumePath path = GetVolumePath(); + if (!path.IsEmpty()) + VolumeHistory::Add (path); + } + } + + void VolumeLocationWizardPage::OnPreferencesUpdated (EventArgs &args) + { + NoHistoryCheckBox->SetValue (!Gui->GetPreferences().SaveHistory); + } + + void VolumeLocationWizardPage::OnSelectFileButtonClick (wxCommandEvent& event) + { + FilePath path = Gui->SelectVolumeFile (this, !SelectExisting); + + if (!path.IsEmpty()) + SetVolumePath (path); + } + + void VolumeLocationWizardPage::OnSelectDeviceButtonClick (wxCommandEvent& event) + { + DevicePath path = Gui->SelectDevice (this); + + if (!path.IsEmpty()) + SetVolumePath (path); + } + + void VolumeLocationWizardPage::SetVolumePath (const VolumePath &path) + { + VolumePathComboBox->SetValue (wstring (path)); + PageUpdatedEvent.Raise(); + } +} diff --git a/Main/Forms/VolumeLocationWizardPage.h b/Main/Forms/VolumeLocationWizardPage.h index ec6165b..64136ed 100644 --- a/Main/Forms/VolumeLocationWizardPage.h +++ b/Main/Forms/VolumeLocationWizardPage.h @@ -1,40 +1,40 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_VolumeLocationWizardPage -#define TC_HEADER_Main_Forms_VolumeLocationWizardPage - -#include "Forms.h" - -namespace TrueCrypt -{ - class VolumeLocationWizardPage : public VolumeLocationWizardPageBase - { - public: - VolumeLocationWizardPage (wxPanel* parent, VolumeHostType::Enum hostType = VolumeHostType::Unknown, bool selectExisting = false); - ~VolumeLocationWizardPage (); - - VolumePath GetVolumePath () const { return VolumePath (wstring (VolumePathComboBox->GetValue())); } - bool IsValid () { return !VolumePathComboBox->GetValue().IsEmpty(); } - void OnPageChanging (bool forward); - void SetVolumePath (const VolumePath &path); - void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - - protected: - void OnVolumePathTextChanged (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } - void OnNoHistoryCheckBoxClick (wxCommandEvent& event); - void OnSelectDeviceButtonClick (wxCommandEvent& event); - void OnSelectFileButtonClick (wxCommandEvent& event); - void OnPreferencesUpdated (EventArgs &args); - - bool SelectExisting; - }; -} - -#endif // TC_HEADER_Main_Forms_VolumeLocationWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_VolumeLocationWizardPage +#define TC_HEADER_Main_Forms_VolumeLocationWizardPage + +#include "Forms.h" + +namespace TrueCrypt +{ + class VolumeLocationWizardPage : public VolumeLocationWizardPageBase + { + public: + VolumeLocationWizardPage (wxPanel* parent, VolumeHostType::Enum hostType = VolumeHostType::Unknown, bool selectExisting = false); + ~VolumeLocationWizardPage (); + + VolumePath GetVolumePath () const { return VolumePath (wstring (VolumePathComboBox->GetValue())); } + bool IsValid () { return !VolumePathComboBox->GetValue().IsEmpty(); } + void OnPageChanging (bool forward); + void SetVolumePath (const VolumePath &path); + void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + + protected: + void OnVolumePathTextChanged (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } + void OnNoHistoryCheckBoxClick (wxCommandEvent& event); + void OnSelectDeviceButtonClick (wxCommandEvent& event); + void OnSelectFileButtonClick (wxCommandEvent& event); + void OnPreferencesUpdated (EventArgs &args); + + bool SelectExisting; + }; +} + +#endif // TC_HEADER_Main_Forms_VolumeLocationWizardPage diff --git a/Main/Forms/VolumePasswordPanel.cpp b/Main/Forms/VolumePasswordPanel.cpp index ef20e0d..c620904 100644 --- a/Main/Forms/VolumePasswordPanel.cpp +++ b/Main/Forms/VolumePasswordPanel.cpp @@ -1,310 +1,310 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "KeyfilesDialog.h" -#include "VolumePasswordPanel.h" -#include "SecurityTokenKeyfilesDialog.h" - -namespace TrueCrypt -{ - VolumePasswordPanel::VolumePasswordPanel (wxWindow* parent, shared_ptr password, shared_ptr keyfiles, bool enableCache, bool enablePassword, bool enableKeyfiles, bool enableConfirmation, bool enablePkcs5Prf, const wxString &passwordLabel) - : VolumePasswordPanelBase (parent), Keyfiles (new KeyfileList) - { - if (keyfiles) - { - *Keyfiles = *keyfiles; - UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); - } - else - { - *Keyfiles = Gui->GetPreferences().DefaultKeyfiles; - UseKeyfilesCheckBox->SetValue (Gui->GetPreferences().UseKeyfiles && !Keyfiles->empty()); - } - - PasswordTextCtrl->SetMaxLength (VolumePassword::MaxSize); - ConfirmPasswordTextCtrl->SetMaxLength (VolumePassword::MaxSize); - - if (!passwordLabel.empty()) - { - PasswordStaticText->SetLabel (passwordLabel); - GridBagSizer->Detach (PasswordStaticText); - GridBagSizer->Add (PasswordStaticText, wxGBPosition (0, 1), wxGBSpan (1, 1), wxALIGN_CENTER_VERTICAL | wxBOTTOM, Gui->GetDefaultBorderSize()); - } - - CacheCheckBox->Show (enableCache); - - if (!enablePassword && enableKeyfiles) - { - Layout(); - Fit(); - PasswordPlaceholderSizer->SetMinSize (wxSize (PasswordTextCtrl->GetSize().GetWidth(), -1)); - } - else if (!enablePkcs5Prf) - { - GridBagSizer->Remove (PasswordPlaceholderSizer); - } - - PasswordStaticText->Show (enablePassword); - PasswordTextCtrl->Show (enablePassword); - DisplayPasswordCheckBox->Show (enablePassword); - - ConfirmPasswordStaticText->Show (enableConfirmation); - ConfirmPasswordTextCtrl->Show (enableConfirmation); - - UseKeyfilesCheckBox->Show (enableKeyfiles); - KeyfilesButton->Show (enableKeyfiles); - - Pkcs5PrfStaticText->Show (enablePkcs5Prf); - Pkcs5PrfChoice->Show (enablePkcs5Prf); - - if (enablePkcs5Prf) - { - foreach_ref (const Pkcs5Kdf &kdf, Pkcs5Kdf::GetAvailableAlgorithms()) - { - if (!kdf.IsDeprecated()) - Pkcs5PrfChoice->Append (kdf.GetName()); - } - Pkcs5PrfChoice->Select (0); - } - - if (!enablePkcs5Prf || (!enablePassword && !enableKeyfiles)) - { - GridBagSizer->Remove (Pkcs5PrfSizer); - } - - // Keyfiles drag & drop - class FileDropTarget : public wxFileDropTarget - { - public: - FileDropTarget (VolumePasswordPanel *panel) : Panel (panel) { } - - wxDragResult OnDragOver (wxCoord x, wxCoord y, wxDragResult def) - { - return wxDragLink; - } - - bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString &filenames) - { - foreach (const wxString &f, filenames) - Panel->AddKeyfile (make_shared (wstring (f))); - - return true; - } - - protected: - VolumePasswordPanel *Panel; - }; - - if (enableKeyfiles) - { - SetDropTarget (new FileDropTarget (this)); -#ifdef TC_MACOSX - foreach (wxWindow *c, GetChildren()) - c->SetDropTarget (new FileDropTarget (this)); -#endif - } - - Layout(); - Fit(); - } - - VolumePasswordPanel::~VolumePasswordPanel () - { - WipeTextCtrl (PasswordTextCtrl); - WipeTextCtrl (ConfirmPasswordTextCtrl); - } - - void VolumePasswordPanel::AddKeyfile (shared_ptr keyfile) - { - if (!Keyfiles) - Keyfiles.reset (new KeyfileList); - - Keyfiles->push_back (keyfile); - UseKeyfilesCheckBox->SetValue (true); - } - - void VolumePasswordPanel::DisplayPassword (bool display, wxTextCtrl **textCtrl, int row) - { - FreezeScope freeze (this); - - wxTextCtrl *newTextCtrl = new wxTextCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, display ? 0 : wxTE_PASSWORD); - newTextCtrl->SetMaxLength (VolumePassword::MaxSize); - newTextCtrl->SetValue ((*textCtrl)->GetValue()); - newTextCtrl->SetMinSize ((*textCtrl)->GetSize()); - - GridBagSizer->Detach ((*textCtrl)); - GridBagSizer->Add (newTextCtrl, wxGBPosition (row, 1), wxGBSpan (1, 2), wxEXPAND|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 5); - (*textCtrl)->Show (false); - WipeTextCtrl (*textCtrl); - - Fit(); - Layout(); - newTextCtrl->SetMinSize ((*textCtrl)->GetMinSize()); - - newTextCtrl->Connect (wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (VolumePasswordPanel::OnTextChanged), nullptr, this); - *textCtrl = newTextCtrl; - } - - shared_ptr VolumePasswordPanel::GetPassword () const - { - return GetPassword (PasswordTextCtrl); - } - - shared_ptr VolumePasswordPanel::GetPassword (wxTextCtrl *textCtrl) const - { - shared_ptr password; - wchar_t passwordBuf[VolumePassword::MaxSize + 1]; - finally_do_arg (BufferPtr, BufferPtr (reinterpret_cast (passwordBuf), sizeof (passwordBuf)), { finally_arg.Erase(); }); - -#ifdef TC_WINDOWS - int len = GetWindowText (static_cast (textCtrl->GetHandle()), passwordBuf, VolumePassword::MaxSize + 1); - password.reset (new VolumePassword (passwordBuf, len)); -#else - wxString passwordStr (textCtrl->GetValue()); // A copy of the password is created here by wxWidgets, which cannot be erased - for (size_t i = 0; i < passwordStr.size() && i < VolumePassword::MaxSize; ++i) - { - passwordBuf[i] = (wchar_t) passwordStr[i]; - passwordStr[i] = L'X'; - } - password.reset (new VolumePassword (passwordBuf, passwordStr.size() <= VolumePassword::MaxSize ? passwordStr.size() : VolumePassword::MaxSize)); -#endif - return password; - } - - shared_ptr VolumePasswordPanel::GetPkcs5Kdf () const - { - try - { - return Pkcs5Kdf::GetAlgorithm (wstring (Pkcs5PrfChoice->GetStringSelection())); - } - catch (ParameterIncorrect&) - { - return shared_ptr (); - } - } - - void VolumePasswordPanel::OnAddKeyfileDirMenuItemSelected (wxCommandEvent& event) - { - try - { - DirectoryPath dir = Gui->SelectDirectory (this, LangString["SELECT_KEYFILE_PATH"]); - - if (!dir.IsEmpty()) - { - Keyfiles->push_back (make_shared (dir)); - - UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); - OnUpdate(); - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void VolumePasswordPanel::OnAddKeyfilesMenuItemSelected (wxCommandEvent& event) - { - try - { - FilePathList files = Gui->SelectFiles (this, LangString["SELECT_KEYFILES"], false, true); - - if (!files.empty()) - { - foreach_ref (const FilePath &f, files) - Keyfiles->push_back (make_shared (f)); - - UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); - OnUpdate(); - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void VolumePasswordPanel::OnAddSecurityTokenSignatureMenuItemSelected (wxCommandEvent& event) - { - try - { - SecurityTokenKeyfilesDialog dialog (this); - if (dialog.ShowModal() == wxID_OK) - { - foreach (const SecurityTokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) - { - Keyfiles->push_back (make_shared (wstring (path))); - } - - if (!dialog.GetSelectedSecurityTokenKeyfilePaths().empty()) - { - UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); - OnUpdate(); - } - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - } - - void VolumePasswordPanel::OnDisplayPasswordCheckBoxClick (wxCommandEvent& event) - { - DisplayPassword (event.IsChecked(), &PasswordTextCtrl, 1); - - if (ConfirmPasswordTextCtrl->IsShown()) - DisplayPassword (event.IsChecked(), &ConfirmPasswordTextCtrl, 2); - - OnUpdate(); - } - - void VolumePasswordPanel::OnKeyfilesButtonClick (wxCommandEvent& event) - { - KeyfilesDialog dialog (GetParent(), Keyfiles); - - if (dialog.ShowModal() == wxID_OK) - { - Keyfiles = dialog.GetKeyfiles(); - - UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); - OnUpdate(); - } - } - - void VolumePasswordPanel::OnKeyfilesButtonRightClick (wxMouseEvent& event) - { - wxMenu popup; - Gui->AppendToMenu (popup, LangString["IDC_KEYADD"], this, wxCommandEventHandler (VolumePasswordPanel::OnAddKeyfilesMenuItemSelected)); - Gui->AppendToMenu (popup, LangString["IDC_ADD_KEYFILE_PATH"], this, wxCommandEventHandler (VolumePasswordPanel::OnAddKeyfileDirMenuItemSelected)); - Gui->AppendToMenu (popup, LangString["IDC_TOKEN_FILES_ADD"], this, wxCommandEventHandler (VolumePasswordPanel::OnAddSecurityTokenSignatureMenuItemSelected)); - - PopupMenu (&popup, KeyfilesButton->GetPosition().x + 2, KeyfilesButton->GetPosition().y + 2); - } - - void VolumePasswordPanel::OnKeyfilesButtonRightDown (wxMouseEvent& event) - { -#ifndef TC_MACOSX - event.Skip(); -#endif - } - - bool VolumePasswordPanel::PasswordsMatch () const - { - assert (ConfirmPasswordStaticText->IsShown()); - return *GetPassword (PasswordTextCtrl) == *GetPassword (ConfirmPasswordTextCtrl); - } - - void VolumePasswordPanel::WipeTextCtrl (wxTextCtrl *textCtrl) - { - textCtrl->SetValue (wxString (L'X', textCtrl->GetLineLength(0))); - GetPassword (textCtrl); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "KeyfilesDialog.h" +#include "VolumePasswordPanel.h" +#include "SecurityTokenKeyfilesDialog.h" + +namespace TrueCrypt +{ + VolumePasswordPanel::VolumePasswordPanel (wxWindow* parent, shared_ptr password, shared_ptr keyfiles, bool enableCache, bool enablePassword, bool enableKeyfiles, bool enableConfirmation, bool enablePkcs5Prf, const wxString &passwordLabel) + : VolumePasswordPanelBase (parent), Keyfiles (new KeyfileList) + { + if (keyfiles) + { + *Keyfiles = *keyfiles; + UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); + } + else + { + *Keyfiles = Gui->GetPreferences().DefaultKeyfiles; + UseKeyfilesCheckBox->SetValue (Gui->GetPreferences().UseKeyfiles && !Keyfiles->empty()); + } + + PasswordTextCtrl->SetMaxLength (VolumePassword::MaxSize); + ConfirmPasswordTextCtrl->SetMaxLength (VolumePassword::MaxSize); + + if (!passwordLabel.empty()) + { + PasswordStaticText->SetLabel (passwordLabel); + GridBagSizer->Detach (PasswordStaticText); + GridBagSizer->Add (PasswordStaticText, wxGBPosition (0, 1), wxGBSpan (1, 1), wxALIGN_CENTER_VERTICAL | wxBOTTOM, Gui->GetDefaultBorderSize()); + } + + CacheCheckBox->Show (enableCache); + + if (!enablePassword && enableKeyfiles) + { + Layout(); + Fit(); + PasswordPlaceholderSizer->SetMinSize (wxSize (PasswordTextCtrl->GetSize().GetWidth(), -1)); + } + else if (!enablePkcs5Prf) + { + GridBagSizer->Remove (PasswordPlaceholderSizer); + } + + PasswordStaticText->Show (enablePassword); + PasswordTextCtrl->Show (enablePassword); + DisplayPasswordCheckBox->Show (enablePassword); + + ConfirmPasswordStaticText->Show (enableConfirmation); + ConfirmPasswordTextCtrl->Show (enableConfirmation); + + UseKeyfilesCheckBox->Show (enableKeyfiles); + KeyfilesButton->Show (enableKeyfiles); + + Pkcs5PrfStaticText->Show (enablePkcs5Prf); + Pkcs5PrfChoice->Show (enablePkcs5Prf); + + if (enablePkcs5Prf) + { + foreach_ref (const Pkcs5Kdf &kdf, Pkcs5Kdf::GetAvailableAlgorithms()) + { + if (!kdf.IsDeprecated()) + Pkcs5PrfChoice->Append (kdf.GetName()); + } + Pkcs5PrfChoice->Select (0); + } + + if (!enablePkcs5Prf || (!enablePassword && !enableKeyfiles)) + { + GridBagSizer->Remove (Pkcs5PrfSizer); + } + + // Keyfiles drag & drop + class FileDropTarget : public wxFileDropTarget + { + public: + FileDropTarget (VolumePasswordPanel *panel) : Panel (panel) { } + + wxDragResult OnDragOver (wxCoord x, wxCoord y, wxDragResult def) + { + return wxDragLink; + } + + bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString &filenames) + { + foreach (const wxString &f, filenames) + Panel->AddKeyfile (make_shared (wstring (f))); + + return true; + } + + protected: + VolumePasswordPanel *Panel; + }; + + if (enableKeyfiles) + { + SetDropTarget (new FileDropTarget (this)); +#ifdef TC_MACOSX + foreach (wxWindow *c, GetChildren()) + c->SetDropTarget (new FileDropTarget (this)); +#endif + } + + Layout(); + Fit(); + } + + VolumePasswordPanel::~VolumePasswordPanel () + { + WipeTextCtrl (PasswordTextCtrl); + WipeTextCtrl (ConfirmPasswordTextCtrl); + } + + void VolumePasswordPanel::AddKeyfile (shared_ptr keyfile) + { + if (!Keyfiles) + Keyfiles.reset (new KeyfileList); + + Keyfiles->push_back (keyfile); + UseKeyfilesCheckBox->SetValue (true); + } + + void VolumePasswordPanel::DisplayPassword (bool display, wxTextCtrl **textCtrl, int row) + { + FreezeScope freeze (this); + + wxTextCtrl *newTextCtrl = new wxTextCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, display ? 0 : wxTE_PASSWORD); + newTextCtrl->SetMaxLength (VolumePassword::MaxSize); + newTextCtrl->SetValue ((*textCtrl)->GetValue()); + newTextCtrl->SetMinSize ((*textCtrl)->GetSize()); + + GridBagSizer->Detach ((*textCtrl)); + GridBagSizer->Add (newTextCtrl, wxGBPosition (row, 1), wxGBSpan (1, 2), wxEXPAND|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 5); + (*textCtrl)->Show (false); + WipeTextCtrl (*textCtrl); + + Fit(); + Layout(); + newTextCtrl->SetMinSize ((*textCtrl)->GetMinSize()); + + newTextCtrl->Connect (wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (VolumePasswordPanel::OnTextChanged), nullptr, this); + *textCtrl = newTextCtrl; + } + + shared_ptr VolumePasswordPanel::GetPassword () const + { + return GetPassword (PasswordTextCtrl); + } + + shared_ptr VolumePasswordPanel::GetPassword (wxTextCtrl *textCtrl) const + { + shared_ptr password; + wchar_t passwordBuf[VolumePassword::MaxSize + 1]; + finally_do_arg (BufferPtr, BufferPtr (reinterpret_cast (passwordBuf), sizeof (passwordBuf)), { finally_arg.Erase(); }); + +#ifdef TC_WINDOWS + int len = GetWindowText (static_cast (textCtrl->GetHandle()), passwordBuf, VolumePassword::MaxSize + 1); + password.reset (new VolumePassword (passwordBuf, len)); +#else + wxString passwordStr (textCtrl->GetValue()); // A copy of the password is created here by wxWidgets, which cannot be erased + for (size_t i = 0; i < passwordStr.size() && i < VolumePassword::MaxSize; ++i) + { + passwordBuf[i] = (wchar_t) passwordStr[i]; + passwordStr[i] = L'X'; + } + password.reset (new VolumePassword (passwordBuf, passwordStr.size() <= VolumePassword::MaxSize ? passwordStr.size() : VolumePassword::MaxSize)); +#endif + return password; + } + + shared_ptr VolumePasswordPanel::GetPkcs5Kdf () const + { + try + { + return Pkcs5Kdf::GetAlgorithm (wstring (Pkcs5PrfChoice->GetStringSelection())); + } + catch (ParameterIncorrect&) + { + return shared_ptr (); + } + } + + void VolumePasswordPanel::OnAddKeyfileDirMenuItemSelected (wxCommandEvent& event) + { + try + { + DirectoryPath dir = Gui->SelectDirectory (this, LangString["SELECT_KEYFILE_PATH"]); + + if (!dir.IsEmpty()) + { + Keyfiles->push_back (make_shared (dir)); + + UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); + OnUpdate(); + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void VolumePasswordPanel::OnAddKeyfilesMenuItemSelected (wxCommandEvent& event) + { + try + { + FilePathList files = Gui->SelectFiles (this, LangString["SELECT_KEYFILES"], false, true); + + if (!files.empty()) + { + foreach_ref (const FilePath &f, files) + Keyfiles->push_back (make_shared (f)); + + UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); + OnUpdate(); + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void VolumePasswordPanel::OnAddSecurityTokenSignatureMenuItemSelected (wxCommandEvent& event) + { + try + { + SecurityTokenKeyfilesDialog dialog (this); + if (dialog.ShowModal() == wxID_OK) + { + foreach (const SecurityTokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) + { + Keyfiles->push_back (make_shared (wstring (path))); + } + + if (!dialog.GetSelectedSecurityTokenKeyfilePaths().empty()) + { + UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); + OnUpdate(); + } + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + } + + void VolumePasswordPanel::OnDisplayPasswordCheckBoxClick (wxCommandEvent& event) + { + DisplayPassword (event.IsChecked(), &PasswordTextCtrl, 1); + + if (ConfirmPasswordTextCtrl->IsShown()) + DisplayPassword (event.IsChecked(), &ConfirmPasswordTextCtrl, 2); + + OnUpdate(); + } + + void VolumePasswordPanel::OnKeyfilesButtonClick (wxCommandEvent& event) + { + KeyfilesDialog dialog (GetParent(), Keyfiles); + + if (dialog.ShowModal() == wxID_OK) + { + Keyfiles = dialog.GetKeyfiles(); + + UseKeyfilesCheckBox->SetValue (!Keyfiles->empty()); + OnUpdate(); + } + } + + void VolumePasswordPanel::OnKeyfilesButtonRightClick (wxMouseEvent& event) + { + wxMenu popup; + Gui->AppendToMenu (popup, LangString["IDC_KEYADD"], this, wxCommandEventHandler (VolumePasswordPanel::OnAddKeyfilesMenuItemSelected)); + Gui->AppendToMenu (popup, LangString["IDC_ADD_KEYFILE_PATH"], this, wxCommandEventHandler (VolumePasswordPanel::OnAddKeyfileDirMenuItemSelected)); + Gui->AppendToMenu (popup, LangString["IDC_TOKEN_FILES_ADD"], this, wxCommandEventHandler (VolumePasswordPanel::OnAddSecurityTokenSignatureMenuItemSelected)); + + PopupMenu (&popup, KeyfilesButton->GetPosition().x + 2, KeyfilesButton->GetPosition().y + 2); + } + + void VolumePasswordPanel::OnKeyfilesButtonRightDown (wxMouseEvent& event) + { +#ifndef TC_MACOSX + event.Skip(); +#endif + } + + bool VolumePasswordPanel::PasswordsMatch () const + { + assert (ConfirmPasswordStaticText->IsShown()); + return *GetPassword (PasswordTextCtrl) == *GetPassword (ConfirmPasswordTextCtrl); + } + + void VolumePasswordPanel::WipeTextCtrl (wxTextCtrl *textCtrl) + { + textCtrl->SetValue (wxString (L'X', textCtrl->GetLineLength(0))); + GetPassword (textCtrl); + } +} diff --git a/Main/Forms/VolumePasswordPanel.h b/Main/Forms/VolumePasswordPanel.h index ba82a27..b3ae803 100644 --- a/Main/Forms/VolumePasswordPanel.h +++ b/Main/Forms/VolumePasswordPanel.h @@ -1,54 +1,54 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_PasswordPanel -#define TC_HEADER_Main_Forms_PasswordPanel - -#include "Forms.h" -#include "Platform/Functor.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class VolumePasswordPanel : public VolumePasswordPanelBase - { - public: - VolumePasswordPanel (wxWindow* parent, shared_ptr password, shared_ptr keyfiles, bool enableCache = false, bool enablePassword = true, bool enableKeyfiles = true, bool enableConfirmation = false, bool enablePkcs5Prf = false, const wxString &passwordLabel = wxString()); - virtual ~VolumePasswordPanel (); - - void AddKeyfile (shared_ptr keyfile); - shared_ptr GetKeyfiles () const { return UseKeyfilesCheckBox->IsChecked() ? Keyfiles : shared_ptr (); } - shared_ptr GetPassword () const; - shared_ptr GetPkcs5Kdf () const; - void SetCacheCheckBoxValidator (const wxGenericValidator &validator) { CacheCheckBox->SetValidator (validator); } - void SetFocusToPasswordTextCtrl () { PasswordTextCtrl->SetSelection (-1, -1); PasswordTextCtrl->SetFocus(); } - bool PasswordsMatch () const; - - Event UpdateEvent; - - protected: - void DisplayPassword (bool display, wxTextCtrl **textCtrl, int row); - shared_ptr GetPassword (wxTextCtrl *textCtrl) const; - void OnAddKeyfileDirMenuItemSelected (wxCommandEvent& event); - void OnAddKeyfilesMenuItemSelected (wxCommandEvent& event); - void OnAddSecurityTokenSignatureMenuItemSelected (wxCommandEvent& event); - void OnDisplayPasswordCheckBoxClick (wxCommandEvent& event); - void OnKeyfilesButtonClick (wxCommandEvent& event); - void OnKeyfilesButtonRightClick (wxMouseEvent& event); - void OnKeyfilesButtonRightDown (wxMouseEvent& event); - void OnTextChanged (wxCommandEvent& event) { OnUpdate(); } - void OnUpdate () { UpdateEvent.Raise(); } - void OnUseKeyfilesCheckBoxClick (wxCommandEvent& event) { OnUpdate(); } - void WipeTextCtrl (wxTextCtrl *textCtrl); - - shared_ptr Keyfiles; - shared_ptr UpdateCallback; - }; -} - -#endif // TC_HEADER_Main_Forms_PasswordPanel +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_PasswordPanel +#define TC_HEADER_Main_Forms_PasswordPanel + +#include "Forms.h" +#include "Platform/Functor.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class VolumePasswordPanel : public VolumePasswordPanelBase + { + public: + VolumePasswordPanel (wxWindow* parent, shared_ptr password, shared_ptr keyfiles, bool enableCache = false, bool enablePassword = true, bool enableKeyfiles = true, bool enableConfirmation = false, bool enablePkcs5Prf = false, const wxString &passwordLabel = wxString()); + virtual ~VolumePasswordPanel (); + + void AddKeyfile (shared_ptr keyfile); + shared_ptr GetKeyfiles () const { return UseKeyfilesCheckBox->IsChecked() ? Keyfiles : shared_ptr (); } + shared_ptr GetPassword () const; + shared_ptr GetPkcs5Kdf () const; + void SetCacheCheckBoxValidator (const wxGenericValidator &validator) { CacheCheckBox->SetValidator (validator); } + void SetFocusToPasswordTextCtrl () { PasswordTextCtrl->SetSelection (-1, -1); PasswordTextCtrl->SetFocus(); } + bool PasswordsMatch () const; + + Event UpdateEvent; + + protected: + void DisplayPassword (bool display, wxTextCtrl **textCtrl, int row); + shared_ptr GetPassword (wxTextCtrl *textCtrl) const; + void OnAddKeyfileDirMenuItemSelected (wxCommandEvent& event); + void OnAddKeyfilesMenuItemSelected (wxCommandEvent& event); + void OnAddSecurityTokenSignatureMenuItemSelected (wxCommandEvent& event); + void OnDisplayPasswordCheckBoxClick (wxCommandEvent& event); + void OnKeyfilesButtonClick (wxCommandEvent& event); + void OnKeyfilesButtonRightClick (wxMouseEvent& event); + void OnKeyfilesButtonRightDown (wxMouseEvent& event); + void OnTextChanged (wxCommandEvent& event) { OnUpdate(); } + void OnUpdate () { UpdateEvent.Raise(); } + void OnUseKeyfilesCheckBoxClick (wxCommandEvent& event) { OnUpdate(); } + void WipeTextCtrl (wxTextCtrl *textCtrl); + + shared_ptr Keyfiles; + shared_ptr UpdateCallback; + }; +} + +#endif // TC_HEADER_Main_Forms_PasswordPanel diff --git a/Main/Forms/VolumePasswordWizardPage.cpp b/Main/Forms/VolumePasswordWizardPage.cpp index 22a42fb..c36a5b8 100644 --- a/Main/Forms/VolumePasswordWizardPage.cpp +++ b/Main/Forms/VolumePasswordWizardPage.cpp @@ -1,39 +1,39 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "VolumePasswordWizardPage.h" - -namespace TrueCrypt -{ - VolumePasswordWizardPage::VolumePasswordWizardPage (wxPanel* parent, shared_ptr password, shared_ptr keyfiles, bool enableConfirmation) - : VolumePasswordWizardPageBase (parent), ConfirmationMode (enableConfirmation) - { - PasswordPanel = new VolumePasswordPanel (this, password, keyfiles, false, true, true, enableConfirmation); - PasswordPanel->UpdateEvent.Connect (EventConnector (this, &VolumePasswordWizardPage::OnPasswordPanelUpdate)); - - PasswordPanelSizer->Add (PasswordPanel, 1, wxALL | wxEXPAND); - } - - VolumePasswordWizardPage::~VolumePasswordWizardPage () - { - PasswordPanel->UpdateEvent.Disconnect (this); - } - - bool VolumePasswordWizardPage::IsValid () - { - if (ConfirmationMode && !PasswordPanel->PasswordsMatch()) - return false; - - shared_ptr keyfiles (GetKeyfiles()); - shared_ptr password (GetPassword()); - - return (password && !GetPassword()->IsEmpty()) || (keyfiles && !keyfiles->empty()); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "VolumePasswordWizardPage.h" + +namespace TrueCrypt +{ + VolumePasswordWizardPage::VolumePasswordWizardPage (wxPanel* parent, shared_ptr password, shared_ptr keyfiles, bool enableConfirmation) + : VolumePasswordWizardPageBase (parent), ConfirmationMode (enableConfirmation) + { + PasswordPanel = new VolumePasswordPanel (this, password, keyfiles, false, true, true, enableConfirmation); + PasswordPanel->UpdateEvent.Connect (EventConnector (this, &VolumePasswordWizardPage::OnPasswordPanelUpdate)); + + PasswordPanelSizer->Add (PasswordPanel, 1, wxALL | wxEXPAND); + } + + VolumePasswordWizardPage::~VolumePasswordWizardPage () + { + PasswordPanel->UpdateEvent.Disconnect (this); + } + + bool VolumePasswordWizardPage::IsValid () + { + if (ConfirmationMode && !PasswordPanel->PasswordsMatch()) + return false; + + shared_ptr keyfiles (GetKeyfiles()); + shared_ptr password (GetPassword()); + + return (password && !GetPassword()->IsEmpty()) || (keyfiles && !keyfiles->empty()); + } +} diff --git a/Main/Forms/VolumePasswordWizardPage.h b/Main/Forms/VolumePasswordWizardPage.h index ce07501..3a6af85 100644 --- a/Main/Forms/VolumePasswordWizardPage.h +++ b/Main/Forms/VolumePasswordWizardPage.h @@ -1,37 +1,37 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_VolumePasswordWizardPage -#define TC_HEADER_Main_Forms_VolumePasswordWizardPage - -#include "Forms.h" -#include "VolumePasswordPanel.h" - -namespace TrueCrypt -{ - class VolumePasswordWizardPage : public VolumePasswordWizardPageBase - { - public: - VolumePasswordWizardPage (wxPanel* parent, shared_ptr password, shared_ptr keyfiles, bool enableConfirmation = true); - ~VolumePasswordWizardPage (); - - shared_ptr GetKeyfiles () const { return PasswordPanel->GetKeyfiles(); } - shared_ptr GetPassword () const { return PasswordPanel->GetPassword(); } - bool IsValid (); - void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - - protected: - void OnPasswordPanelUpdate (EventArgs &args) { PageUpdatedEvent.Raise(); } - - bool ConfirmationMode; - VolumePasswordPanel *PasswordPanel; - }; -} - -#endif // TC_HEADER_Main_Forms_VolumePasswordWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_VolumePasswordWizardPage +#define TC_HEADER_Main_Forms_VolumePasswordWizardPage + +#include "Forms.h" +#include "VolumePasswordPanel.h" + +namespace TrueCrypt +{ + class VolumePasswordWizardPage : public VolumePasswordWizardPageBase + { + public: + VolumePasswordWizardPage (wxPanel* parent, shared_ptr password, shared_ptr keyfiles, bool enableConfirmation = true); + ~VolumePasswordWizardPage (); + + shared_ptr GetKeyfiles () const { return PasswordPanel->GetKeyfiles(); } + shared_ptr GetPassword () const { return PasswordPanel->GetPassword(); } + bool IsValid (); + void SetMaxStaticTextWidth (int width) { InfoStaticText->Wrap (width); } + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + + protected: + void OnPasswordPanelUpdate (EventArgs &args) { PageUpdatedEvent.Raise(); } + + bool ConfirmationMode; + VolumePasswordPanel *PasswordPanel; + }; +} + +#endif // TC_HEADER_Main_Forms_VolumePasswordWizardPage diff --git a/Main/Forms/VolumePropertiesDialog.cpp b/Main/Forms/VolumePropertiesDialog.cpp index 7ee7a96..75ddcec 100644 --- a/Main/Forms/VolumePropertiesDialog.cpp +++ b/Main/Forms/VolumePropertiesDialog.cpp @@ -1,97 +1,97 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/Main.h" -#include "Main/GraphicUserInterface.h" -#include "VolumePropertiesDialog.h" - -namespace TrueCrypt -{ - VolumePropertiesDialog::VolumePropertiesDialog (wxWindow* parent, const VolumeInfo &volumeInfo) - : VolumePropertiesDialogBase (parent) - { - list colPermilles; - - PropertiesListCtrl->InsertColumn (0, LangString["PROPERTY"], wxLIST_FORMAT_LEFT, 208); - colPermilles.push_back (500); - PropertiesListCtrl->InsertColumn (1, LangString["VALUE"], wxLIST_FORMAT_LEFT, 192); - colPermilles.push_back (500); - - Gui->SetListCtrlWidth (PropertiesListCtrl, 70, false); - Gui->SetListCtrlHeight (PropertiesListCtrl, 17); - Gui->SetListCtrlColumnWidths (PropertiesListCtrl, colPermilles, false); - - AppendToList ("LOCATION", wstring (volumeInfo.Path)); -#ifndef TC_WINDOWS - AppendToList ("VIRTUAL_DEVICE", wstring (volumeInfo.VirtualDevice)); -#endif - AppendToList ("SIZE", Gui->SizeToString (volumeInfo.Size)); - AppendToList ("TYPE", Gui->VolumeTypeToString (volumeInfo.Type, volumeInfo.Protection)); - AppendToList ("READ_ONLY", LangString [volumeInfo.Protection == VolumeProtection::ReadOnly ? "UISTR_YES" : "UISTR_NO"]); - - wxString protection; - if (volumeInfo.Type == VolumeType::Hidden) - protection = LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"]; - else if (volumeInfo.HiddenVolumeProtectionTriggered) - protection = LangString["HID_VOL_DAMAGE_PREVENTED"]; - else - protection = LangString [volumeInfo.Protection == VolumeProtection::HiddenVolumeReadOnly ? "UISTR_YES" : "UISTR_NO"]; - - AppendToList ("HIDDEN_VOL_PROTECTION", protection); - AppendToList ("ENCRYPTION_ALGORITHM", volumeInfo.EncryptionAlgorithmName); - AppendToList ("KEY_SIZE", StringFormatter (L"{0} {1}", volumeInfo.EncryptionAlgorithmKeySize * 8, LangString ["BITS"])); - - if (volumeInfo.EncryptionModeName == L"XTS") - AppendToList ("SECONDARY_KEY_SIZE_XTS", StringFormatter (L"{0} {1}", volumeInfo.EncryptionAlgorithmKeySize * 8, LangString ["BITS"])); - - wstringstream blockSize; - blockSize << volumeInfo.EncryptionAlgorithmBlockSize * 8; - if (volumeInfo.EncryptionAlgorithmBlockSize != volumeInfo.EncryptionAlgorithmMinBlockSize) - blockSize << L"/" << volumeInfo.EncryptionAlgorithmMinBlockSize * 8; - - AppendToList ("BLOCK_SIZE", blockSize.str() + L" " + LangString ["BITS"]); - AppendToList ("MODE_OF_OPERATION", volumeInfo.EncryptionModeName); - AppendToList ("PKCS5_PRF", volumeInfo.Pkcs5PrfName); - -#if 0 - AppendToList ("PKCS5_ITERATIONS", StringConverter::FromNumber (volumeInfo.Pkcs5IterationCount)); - AppendToList ("VOLUME_CREATE_DATE", Gui->VolumeTimeToString (volumeInfo.VolumeCreationTime)); - AppendToList ("VOLUME_HEADER_DATE", Gui->VolumeTimeToString (volumeInfo.HeaderCreationTime)); -#endif - - AppendToList ("VOLUME_FORMAT_VERSION", StringConverter::ToWide (volumeInfo.MinRequiredProgramVersion < 0x600 ? 1 : 2)); - AppendToList ("BACKUP_HEADER", LangString[volumeInfo.MinRequiredProgramVersion >= 0x600 ? "UISTR_YES" : "UISTR_NO"]); - -#ifdef TC_LINUX - if (string (volumeInfo.VirtualDevice).find ("/dev/mapper/truecrypt") != 0) - { -#endif - AppendToList ("TOTAL_DATA_READ", Gui->SizeToString (volumeInfo.TotalDataRead)); - AppendToList ("TOTAL_DATA_WRITTEN", Gui->SizeToString (volumeInfo.TotalDataWritten)); -#ifdef TC_LINUX - } -#endif - - Layout(); - Fit(); - Center(); - - StdButtonsOK->SetDefault(); - } - - void VolumePropertiesDialog::AppendToList (const string &name, const wxString &value) - { - vector fields (PropertiesListCtrl->GetColumnCount()); - - fields[0] = LangString[name]; - fields[1] = value; - - Gui->AppendToListCtrl (PropertiesListCtrl, fields); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/Main.h" +#include "Main/GraphicUserInterface.h" +#include "VolumePropertiesDialog.h" + +namespace TrueCrypt +{ + VolumePropertiesDialog::VolumePropertiesDialog (wxWindow* parent, const VolumeInfo &volumeInfo) + : VolumePropertiesDialogBase (parent) + { + list colPermilles; + + PropertiesListCtrl->InsertColumn (0, LangString["PROPERTY"], wxLIST_FORMAT_LEFT, 208); + colPermilles.push_back (500); + PropertiesListCtrl->InsertColumn (1, LangString["VALUE"], wxLIST_FORMAT_LEFT, 192); + colPermilles.push_back (500); + + Gui->SetListCtrlWidth (PropertiesListCtrl, 70, false); + Gui->SetListCtrlHeight (PropertiesListCtrl, 17); + Gui->SetListCtrlColumnWidths (PropertiesListCtrl, colPermilles, false); + + AppendToList ("LOCATION", wstring (volumeInfo.Path)); +#ifndef TC_WINDOWS + AppendToList ("VIRTUAL_DEVICE", wstring (volumeInfo.VirtualDevice)); +#endif + AppendToList ("SIZE", Gui->SizeToString (volumeInfo.Size)); + AppendToList ("TYPE", Gui->VolumeTypeToString (volumeInfo.Type, volumeInfo.Protection)); + AppendToList ("READ_ONLY", LangString [volumeInfo.Protection == VolumeProtection::ReadOnly ? "UISTR_YES" : "UISTR_NO"]); + + wxString protection; + if (volumeInfo.Type == VolumeType::Hidden) + protection = LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"]; + else if (volumeInfo.HiddenVolumeProtectionTriggered) + protection = LangString["HID_VOL_DAMAGE_PREVENTED"]; + else + protection = LangString [volumeInfo.Protection == VolumeProtection::HiddenVolumeReadOnly ? "UISTR_YES" : "UISTR_NO"]; + + AppendToList ("HIDDEN_VOL_PROTECTION", protection); + AppendToList ("ENCRYPTION_ALGORITHM", volumeInfo.EncryptionAlgorithmName); + AppendToList ("KEY_SIZE", StringFormatter (L"{0} {1}", volumeInfo.EncryptionAlgorithmKeySize * 8, LangString ["BITS"])); + + if (volumeInfo.EncryptionModeName == L"XTS") + AppendToList ("SECONDARY_KEY_SIZE_XTS", StringFormatter (L"{0} {1}", volumeInfo.EncryptionAlgorithmKeySize * 8, LangString ["BITS"])); + + wstringstream blockSize; + blockSize << volumeInfo.EncryptionAlgorithmBlockSize * 8; + if (volumeInfo.EncryptionAlgorithmBlockSize != volumeInfo.EncryptionAlgorithmMinBlockSize) + blockSize << L"/" << volumeInfo.EncryptionAlgorithmMinBlockSize * 8; + + AppendToList ("BLOCK_SIZE", blockSize.str() + L" " + LangString ["BITS"]); + AppendToList ("MODE_OF_OPERATION", volumeInfo.EncryptionModeName); + AppendToList ("PKCS5_PRF", volumeInfo.Pkcs5PrfName); + +#if 0 + AppendToList ("PKCS5_ITERATIONS", StringConverter::FromNumber (volumeInfo.Pkcs5IterationCount)); + AppendToList ("VOLUME_CREATE_DATE", Gui->VolumeTimeToString (volumeInfo.VolumeCreationTime)); + AppendToList ("VOLUME_HEADER_DATE", Gui->VolumeTimeToString (volumeInfo.HeaderCreationTime)); +#endif + + AppendToList ("VOLUME_FORMAT_VERSION", StringConverter::ToWide (volumeInfo.MinRequiredProgramVersion < 0x600 ? 1 : 2)); + AppendToList ("BACKUP_HEADER", LangString[volumeInfo.MinRequiredProgramVersion >= 0x600 ? "UISTR_YES" : "UISTR_NO"]); + +#ifdef TC_LINUX + if (string (volumeInfo.VirtualDevice).find ("/dev/mapper/truecrypt") != 0) + { +#endif + AppendToList ("TOTAL_DATA_READ", Gui->SizeToString (volumeInfo.TotalDataRead)); + AppendToList ("TOTAL_DATA_WRITTEN", Gui->SizeToString (volumeInfo.TotalDataWritten)); +#ifdef TC_LINUX + } +#endif + + Layout(); + Fit(); + Center(); + + StdButtonsOK->SetDefault(); + } + + void VolumePropertiesDialog::AppendToList (const string &name, const wxString &value) + { + vector fields (PropertiesListCtrl->GetColumnCount()); + + fields[0] = LangString[name]; + fields[1] = value; + + Gui->AppendToListCtrl (PropertiesListCtrl, fields); + } +} diff --git a/Main/Forms/VolumePropertiesDialog.h b/Main/Forms/VolumePropertiesDialog.h index dc67bc4..a0c8425 100644 --- a/Main/Forms/VolumePropertiesDialog.h +++ b/Main/Forms/VolumePropertiesDialog.h @@ -1,26 +1,26 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_VolumePropertiesDialog -#define TC_HEADER_Main_Forms_VolumePropertiesDialog - -#include "Forms.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class VolumePropertiesDialog : public VolumePropertiesDialogBase - { - public: - VolumePropertiesDialog (wxWindow* parent, const VolumeInfo &volumeInfo); - - void AppendToList (const string &name, const wxString &value); - }; -} - -#endif // TC_HEADER_Main_Forms_VolumePropertiesDialog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_VolumePropertiesDialog +#define TC_HEADER_Main_Forms_VolumePropertiesDialog + +#include "Forms.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class VolumePropertiesDialog : public VolumePropertiesDialogBase + { + public: + VolumePropertiesDialog (wxWindow* parent, const VolumeInfo &volumeInfo); + + void AppendToList (const string &name, const wxString &value); + }; +} + +#endif // TC_HEADER_Main_Forms_VolumePropertiesDialog diff --git a/Main/Forms/VolumeSizeWizardPage.cpp b/Main/Forms/VolumeSizeWizardPage.cpp index 288944f..411cc68 100644 --- a/Main/Forms/VolumeSizeWizardPage.cpp +++ b/Main/Forms/VolumeSizeWizardPage.cpp @@ -1,126 +1,126 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "VolumeSizeWizardPage.h" - -namespace TrueCrypt -{ - VolumeSizeWizardPage::VolumeSizeWizardPage (wxPanel* parent, const VolumePath &volumePath, const wxString &freeSpaceText) - : VolumeSizeWizardPageBase (parent), - MaxVolumeSize (0), - MinVolumeSize (1) - { - VolumeSizePrefixChoice->Append (LangString["KB"], reinterpret_cast (1024)); - VolumeSizePrefixChoice->Append (LangString["MB"], reinterpret_cast (1024 * 1024)); - VolumeSizePrefixChoice->Append (LangString["GB"], reinterpret_cast (1024 * 1024 * 1024)); - VolumeSizePrefixChoice->Select (Prefix::MB); - - wxLongLong diskSpace = 0; - if (!wxGetDiskSpace (wxFileName (wstring (volumePath)).GetPath(), nullptr, &diskSpace)) - { - VolumeSizeTextCtrl->Disable(); - VolumeSizeTextCtrl->SetValue (L""); - } - - FreeSpaceStaticText->SetFont (Gui->GetDefaultBoldFont (this)); - - if (!freeSpaceText.empty()) - { - FreeSpaceStaticText->SetLabel (freeSpaceText); - } - else - { -#ifdef TC_WINDOWS - wxString drive = wxFileName (wstring (volumePath)).GetVolume(); - if (!drive.empty()) - { - FreeSpaceStaticText->SetLabel (StringFormatter (_("Free space on drive {0}: is {1}."), - drive, Gui->SizeToString (diskSpace.GetValue()))); - } - else -#endif - { - FreeSpaceStaticText->SetLabel (StringFormatter (_("Free space available: {0}"), - Gui->SizeToString (diskSpace.GetValue()))); - } - } - - VolumeSizeTextCtrl->SetMinSize (wxSize (Gui->GetCharWidth (VolumeSizeTextCtrl) * 20, -1)); - - wxTextValidator validator (wxFILTER_INCLUDE_CHAR_LIST); // wxFILTER_NUMERIC does not exclude - . , etc. - const wxChar *valArr[] = { L"0", L"1", L"2", L"3", L"4", L"5", L"6", L"7", L"8", L"9" }; - validator.SetIncludes (wxArrayString (array_capacity (valArr), (const wxChar **) &valArr)); - VolumeSizeTextCtrl->SetValidator (validator); - } - - uint64 VolumeSizeWizardPage::GetVolumeSize () const - { - uint64 prefixMult = 1; - int selection = VolumeSizePrefixChoice->GetSelection(); - if (selection == wxNOT_FOUND) - return 0; - - prefixMult = reinterpret_cast (VolumeSizePrefixChoice->GetClientData (selection)); - - uint64 val = StringConverter::ToUInt64 (wstring (VolumeSizeTextCtrl->GetValue())); - if (val <= 0x7fffFFFFffffFFFFull / prefixMult) - return val * prefixMult; - else - return 0; - } - - bool VolumeSizeWizardPage::IsValid () - { - if (!VolumeSizeTextCtrl->IsEmpty() && Validate()) - { - try - { - if (GetVolumeSize() >= MinVolumeSize && (MaxVolumeSize == 0 || GetVolumeSize() <= MaxVolumeSize)) - return true; - } - catch (...) { } - } - return false; - } - - void VolumeSizeWizardPage::SetMaxStaticTextWidth (int width) - { - FreeSpaceStaticText->Wrap (width); - InfoStaticText->Wrap (width); - } - - void VolumeSizeWizardPage::SetVolumeSize (uint64 size) - { - if (size == 0) - { - VolumeSizePrefixChoice->Select (Prefix::MB); - VolumeSizeTextCtrl->SetValue (L""); - return; - } - - if (size % (1024 * 1024 * 1024) == 0) - { - size /= 1024 * 1024 * 1024; - VolumeSizePrefixChoice->Select (Prefix::GB); - } - else if (size % (1024 * 1024) == 0) - { - size /= 1024 * 1024; - VolumeSizePrefixChoice->Select (Prefix::MB); - } - else - { - size /= 1024; - VolumeSizePrefixChoice->Select (Prefix::KB); - } - - VolumeSizeTextCtrl->SetValue (StringConverter::FromNumber (size)); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "VolumeSizeWizardPage.h" + +namespace TrueCrypt +{ + VolumeSizeWizardPage::VolumeSizeWizardPage (wxPanel* parent, const VolumePath &volumePath, const wxString &freeSpaceText) + : VolumeSizeWizardPageBase (parent), + MaxVolumeSize (0), + MinVolumeSize (1) + { + VolumeSizePrefixChoice->Append (LangString["KB"], reinterpret_cast (1024)); + VolumeSizePrefixChoice->Append (LangString["MB"], reinterpret_cast (1024 * 1024)); + VolumeSizePrefixChoice->Append (LangString["GB"], reinterpret_cast (1024 * 1024 * 1024)); + VolumeSizePrefixChoice->Select (Prefix::MB); + + wxLongLong diskSpace = 0; + if (!wxGetDiskSpace (wxFileName (wstring (volumePath)).GetPath(), nullptr, &diskSpace)) + { + VolumeSizeTextCtrl->Disable(); + VolumeSizeTextCtrl->SetValue (L""); + } + + FreeSpaceStaticText->SetFont (Gui->GetDefaultBoldFont (this)); + + if (!freeSpaceText.empty()) + { + FreeSpaceStaticText->SetLabel (freeSpaceText); + } + else + { +#ifdef TC_WINDOWS + wxString drive = wxFileName (wstring (volumePath)).GetVolume(); + if (!drive.empty()) + { + FreeSpaceStaticText->SetLabel (StringFormatter (_("Free space on drive {0}: is {1}."), + drive, Gui->SizeToString (diskSpace.GetValue()))); + } + else +#endif + { + FreeSpaceStaticText->SetLabel (StringFormatter (_("Free space available: {0}"), + Gui->SizeToString (diskSpace.GetValue()))); + } + } + + VolumeSizeTextCtrl->SetMinSize (wxSize (Gui->GetCharWidth (VolumeSizeTextCtrl) * 20, -1)); + + wxTextValidator validator (wxFILTER_INCLUDE_CHAR_LIST); // wxFILTER_NUMERIC does not exclude - . , etc. + const wxChar *valArr[] = { L"0", L"1", L"2", L"3", L"4", L"5", L"6", L"7", L"8", L"9" }; + validator.SetIncludes (wxArrayString (array_capacity (valArr), (const wxChar **) &valArr)); + VolumeSizeTextCtrl->SetValidator (validator); + } + + uint64 VolumeSizeWizardPage::GetVolumeSize () const + { + uint64 prefixMult = 1; + int selection = VolumeSizePrefixChoice->GetSelection(); + if (selection == wxNOT_FOUND) + return 0; + + prefixMult = reinterpret_cast (VolumeSizePrefixChoice->GetClientData (selection)); + + uint64 val = StringConverter::ToUInt64 (wstring (VolumeSizeTextCtrl->GetValue())); + if (val <= 0x7fffFFFFffffFFFFull / prefixMult) + return val * prefixMult; + else + return 0; + } + + bool VolumeSizeWizardPage::IsValid () + { + if (!VolumeSizeTextCtrl->IsEmpty() && Validate()) + { + try + { + if (GetVolumeSize() >= MinVolumeSize && (MaxVolumeSize == 0 || GetVolumeSize() <= MaxVolumeSize)) + return true; + } + catch (...) { } + } + return false; + } + + void VolumeSizeWizardPage::SetMaxStaticTextWidth (int width) + { + FreeSpaceStaticText->Wrap (width); + InfoStaticText->Wrap (width); + } + + void VolumeSizeWizardPage::SetVolumeSize (uint64 size) + { + if (size == 0) + { + VolumeSizePrefixChoice->Select (Prefix::MB); + VolumeSizeTextCtrl->SetValue (L""); + return; + } + + if (size % (1024 * 1024 * 1024) == 0) + { + size /= 1024 * 1024 * 1024; + VolumeSizePrefixChoice->Select (Prefix::GB); + } + else if (size % (1024 * 1024) == 0) + { + size /= 1024 * 1024; + VolumeSizePrefixChoice->Select (Prefix::MB); + } + else + { + size /= 1024; + VolumeSizePrefixChoice->Select (Prefix::KB); + } + + VolumeSizeTextCtrl->SetValue (StringConverter::FromNumber (size)); + } +} diff --git a/Main/Forms/VolumeSizeWizardPage.h b/Main/Forms/VolumeSizeWizardPage.h index afd21e6..ef7e9ff 100644 --- a/Main/Forms/VolumeSizeWizardPage.h +++ b/Main/Forms/VolumeSizeWizardPage.h @@ -1,49 +1,49 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_VolumeSizeWizardPage -#define TC_HEADER_Main_Forms_VolumeSizeWizardPage - -#include "Forms.h" - -namespace TrueCrypt -{ - class VolumeSizeWizardPage : public VolumeSizeWizardPageBase - { - public: - VolumeSizeWizardPage (wxPanel* parent, const VolumePath &volumePath, const wxString &freeSpaceText = wxEmptyString); - - uint64 GetVolumeSize () const; - bool IsValid (); - void SetMaxStaticTextWidth (int width); - void SetMaxVolumeSize (uint64 size) { MaxVolumeSize = size; } - void SetMinVolumeSize (uint64 size) { MinVolumeSize = size; } - void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } - void SetVolumeSize (uint64 size); - - protected: - struct Prefix - { - enum - { - KB = 0, - MB, - GB - }; - }; - - void OnBrowseButtonClick (wxCommandEvent& event); - void OnVolumeSizePrefixSelected (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } - void OnVolumeSizeTextChanged (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } - - uint64 MaxVolumeSize; - uint64 MinVolumeSize; - }; -} - -#endif // TC_HEADER_Main_Forms_VolumeSizeWizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_VolumeSizeWizardPage +#define TC_HEADER_Main_Forms_VolumeSizeWizardPage + +#include "Forms.h" + +namespace TrueCrypt +{ + class VolumeSizeWizardPage : public VolumeSizeWizardPageBase + { + public: + VolumeSizeWizardPage (wxPanel* parent, const VolumePath &volumePath, const wxString &freeSpaceText = wxEmptyString); + + uint64 GetVolumeSize () const; + bool IsValid (); + void SetMaxStaticTextWidth (int width); + void SetMaxVolumeSize (uint64 size) { MaxVolumeSize = size; } + void SetMinVolumeSize (uint64 size) { MinVolumeSize = size; } + void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); } + void SetVolumeSize (uint64 size); + + protected: + struct Prefix + { + enum + { + KB = 0, + MB, + GB + }; + }; + + void OnBrowseButtonClick (wxCommandEvent& event); + void OnVolumeSizePrefixSelected (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } + void OnVolumeSizeTextChanged (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } + + uint64 MaxVolumeSize; + uint64 MinVolumeSize; + }; +} + +#endif // TC_HEADER_Main_Forms_VolumeSizeWizardPage diff --git a/Main/Forms/WizardFrame.cpp b/Main/Forms/WizardFrame.cpp index cdf561d..c699b3f 100644 --- a/Main/Forms/WizardFrame.cpp +++ b/Main/Forms/WizardFrame.cpp @@ -1,189 +1,189 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/GraphicUserInterface.h" -#include "Main/Resources.h" -#include "WizardFrame.h" - -namespace TrueCrypt -{ - WizardFrame::WizardFrame (wxWindow* parent) - : WizardFrameBase (parent), - CurrentPage (nullptr), - CurrentStep (-1), - MaxStaticTextWidth (-1), - WorkInProgress (false) - { - SetIcon (Resources::GetTrueCryptIcon()); - - PageTitleStaticText->SetFont (wxFont ( -#ifdef TC_WINDOWS - 16 -#elif defined(TC_MACOSX) - 18 -#elif defined(__WXGTK__) - 14 -#endif - * Gui->GetCharHeight (this) / 13, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Times New Roman")); - - UpdateControls(); - this->SetDefaultItem (NextButton); - NextButton->SetFocus(); - - foreach (wxWindow *c, MainPanel->GetChildren()) - c->Connect (wxEVT_MOTION, wxMouseEventHandler (WizardFrame::OnMouseMotion), nullptr, this); - } - - WizardFrame::~WizardFrame () - { - if (CurrentPage) - CurrentPage->Destroy(); - } - - void WizardFrame::ClearHistory () - { - StepHistory.clear(); - UpdateControls(); - } - - void WizardFrame::OnActivate (wxActivateEvent& event) - { - Gui->SetActiveFrame (this); - event.Skip(); - } - - void WizardFrame::OnClose (wxCloseEvent& event) - { - if (WorkInProgress) - return; - - Gui->SetActiveFrame (nullptr); - event.Skip(); - } - - void WizardFrame::OnHelpButtonClick (wxCommandEvent& event) - { - Gui->OpenUserGuide (this); - } - - void WizardFrame::OnNextButtonClick (wxCommandEvent& event) - { - if (CurrentPage->IsValid()) - { - WizardStep nextStep = ProcessPageChangeRequest (true); - if (nextStep != CurrentStep) - SetStep (nextStep); - } - } - - void WizardFrame::OnPreviousButtonClick (wxCommandEvent& event) - { - ProcessPageChangeRequest (false); - - if (!StepHistory.empty()) - { - WizardStep prevStep = *StepHistory.rbegin(); - StepHistory.pop_back(); - SetStep (prevStep, false); - } - } - - void WizardFrame::SetCancelButtonText (const wxString &text) - { - CancelButton->SetLabel (text.empty() ? wxString (_("Cancel")) : text); - } - - void WizardFrame::SetImage (const wxBitmap &bitmap) - { - WizardBitmap->SetBitmap (bitmap); - } - - void WizardFrame::SetMaxStaticTextWidth (size_t charCount) - { - MaxStaticTextWidth = Gui->GetCharWidth (this) * charCount; - } - - void WizardFrame::SetStep (WizardStep newStep) - { - SetStep (newStep, true); - } - - void WizardFrame::SetStep (WizardStep newStep, bool forward) - { - bool init = false; - FreezeScope freeze (this); - -#ifdef TC_WINDOWS - HelpButton->Disable(); // Prevent Help button from getting default focus - NextButton->Enable(); -#endif - if (CurrentPage) - { - if (forward) - StepHistory.push_back (CurrentStep); - - CurrentPage->OnPageChanging (forward); - CurrentPage->Destroy(); - CurrentPage = nullptr; - } - else - init = true; - - CurrentStep = newStep; - CurrentPage = GetPage (newStep); - - CurrentPage->PageUpdatedEvent.Connect (EventConnector (this, &WizardFrame::OnPageUpdated)); - - CurrentPage->Connect (wxEVT_MOTION, wxMouseEventHandler (WizardFrame::OnMouseMotion), nullptr, this); - foreach (wxWindow *c, CurrentPage->GetChildren()) - c->Connect (wxEVT_MOTION, wxMouseEventHandler (WizardFrame::OnMouseMotion), nullptr, this); - - if (MaxStaticTextWidth > 0) - CurrentPage->SetMaxStaticTextWidth (MaxStaticTextWidth); - - PageTitleStaticText->SetLabel (CurrentPage->GetPageTitle()); - PageSizer->Add (CurrentPage, 1, wxALL | wxEXPAND); - - if (init) - { - Fit(); - Layout(); - Center(); - } - else - MainPanel->Layout(); - - CurrentPage->SetFocus(); - - wxString nextButtonText = CurrentPage->GetNextButtonText(); - if (nextButtonText.empty()) - NextButton->SetLabel (_("&Next >")); - else - NextButton->SetLabel (nextButtonText); - -#ifdef TC_WINDOWS - HelpButton->Enable(); -#endif - UpdateControls(); - } - - void WizardFrame::SetWorkInProgress (bool state) - { - WorkInProgress = state; - UpdateControls(); - } - - void WizardFrame::UpdateControls () - { - CancelButton->Enable (!WorkInProgress); - HelpButton->Enable (!WorkInProgress); - NextButton->Enable (!WorkInProgress && CurrentPage != nullptr && CurrentPage->IsValid()); - PreviousButton->Enable (!WorkInProgress && !StepHistory.empty()); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/GraphicUserInterface.h" +#include "Main/Resources.h" +#include "WizardFrame.h" + +namespace TrueCrypt +{ + WizardFrame::WizardFrame (wxWindow* parent) + : WizardFrameBase (parent), + CurrentPage (nullptr), + CurrentStep (-1), + MaxStaticTextWidth (-1), + WorkInProgress (false) + { + SetIcon (Resources::GetTrueCryptIcon()); + + PageTitleStaticText->SetFont (wxFont ( +#ifdef TC_WINDOWS + 16 +#elif defined(TC_MACOSX) + 18 +#elif defined(__WXGTK__) + 14 +#endif + * Gui->GetCharHeight (this) / 13, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Times New Roman")); + + UpdateControls(); + this->SetDefaultItem (NextButton); + NextButton->SetFocus(); + + foreach (wxWindow *c, MainPanel->GetChildren()) + c->Connect (wxEVT_MOTION, wxMouseEventHandler (WizardFrame::OnMouseMotion), nullptr, this); + } + + WizardFrame::~WizardFrame () + { + if (CurrentPage) + CurrentPage->Destroy(); + } + + void WizardFrame::ClearHistory () + { + StepHistory.clear(); + UpdateControls(); + } + + void WizardFrame::OnActivate (wxActivateEvent& event) + { + Gui->SetActiveFrame (this); + event.Skip(); + } + + void WizardFrame::OnClose (wxCloseEvent& event) + { + if (WorkInProgress) + return; + + Gui->SetActiveFrame (nullptr); + event.Skip(); + } + + void WizardFrame::OnHelpButtonClick (wxCommandEvent& event) + { + Gui->OpenUserGuide (this); + } + + void WizardFrame::OnNextButtonClick (wxCommandEvent& event) + { + if (CurrentPage->IsValid()) + { + WizardStep nextStep = ProcessPageChangeRequest (true); + if (nextStep != CurrentStep) + SetStep (nextStep); + } + } + + void WizardFrame::OnPreviousButtonClick (wxCommandEvent& event) + { + ProcessPageChangeRequest (false); + + if (!StepHistory.empty()) + { + WizardStep prevStep = *StepHistory.rbegin(); + StepHistory.pop_back(); + SetStep (prevStep, false); + } + } + + void WizardFrame::SetCancelButtonText (const wxString &text) + { + CancelButton->SetLabel (text.empty() ? wxString (_("Cancel")) : text); + } + + void WizardFrame::SetImage (const wxBitmap &bitmap) + { + WizardBitmap->SetBitmap (bitmap); + } + + void WizardFrame::SetMaxStaticTextWidth (size_t charCount) + { + MaxStaticTextWidth = Gui->GetCharWidth (this) * charCount; + } + + void WizardFrame::SetStep (WizardStep newStep) + { + SetStep (newStep, true); + } + + void WizardFrame::SetStep (WizardStep newStep, bool forward) + { + bool init = false; + FreezeScope freeze (this); + +#ifdef TC_WINDOWS + HelpButton->Disable(); // Prevent Help button from getting default focus + NextButton->Enable(); +#endif + if (CurrentPage) + { + if (forward) + StepHistory.push_back (CurrentStep); + + CurrentPage->OnPageChanging (forward); + CurrentPage->Destroy(); + CurrentPage = nullptr; + } + else + init = true; + + CurrentStep = newStep; + CurrentPage = GetPage (newStep); + + CurrentPage->PageUpdatedEvent.Connect (EventConnector (this, &WizardFrame::OnPageUpdated)); + + CurrentPage->Connect (wxEVT_MOTION, wxMouseEventHandler (WizardFrame::OnMouseMotion), nullptr, this); + foreach (wxWindow *c, CurrentPage->GetChildren()) + c->Connect (wxEVT_MOTION, wxMouseEventHandler (WizardFrame::OnMouseMotion), nullptr, this); + + if (MaxStaticTextWidth > 0) + CurrentPage->SetMaxStaticTextWidth (MaxStaticTextWidth); + + PageTitleStaticText->SetLabel (CurrentPage->GetPageTitle()); + PageSizer->Add (CurrentPage, 1, wxALL | wxEXPAND); + + if (init) + { + Fit(); + Layout(); + Center(); + } + else + MainPanel->Layout(); + + CurrentPage->SetFocus(); + + wxString nextButtonText = CurrentPage->GetNextButtonText(); + if (nextButtonText.empty()) + NextButton->SetLabel (_("&Next >")); + else + NextButton->SetLabel (nextButtonText); + +#ifdef TC_WINDOWS + HelpButton->Enable(); +#endif + UpdateControls(); + } + + void WizardFrame::SetWorkInProgress (bool state) + { + WorkInProgress = state; + UpdateControls(); + } + + void WizardFrame::UpdateControls () + { + CancelButton->Enable (!WorkInProgress); + HelpButton->Enable (!WorkInProgress); + NextButton->Enable (!WorkInProgress && CurrentPage != nullptr && CurrentPage->IsValid()); + PreviousButton->Enable (!WorkInProgress && !StepHistory.empty()); + } +} diff --git a/Main/Forms/WizardFrame.h b/Main/Forms/WizardFrame.h index cddbb3f..970e54e 100644 --- a/Main/Forms/WizardFrame.h +++ b/Main/Forms/WizardFrame.h @@ -1,58 +1,58 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_WizardFrame -#define TC_HEADER_Main_Forms_WizardFrame - -#include "Forms.h" -#include "Main/Main.h" - -namespace TrueCrypt -{ - class WizardFrame : public WizardFrameBase - { - public: - WizardFrame (wxWindow* parent); - virtual ~WizardFrame (); - - protected: - typedef int WizardStep; - - void ClearHistory (); - virtual WizardPage *GetPage (WizardStep step) = 0; - WizardPage *GetCurrentPage () const { return CurrentPage; } - WizardStep GetCurrentStep () const { return CurrentStep; } - wxPanel *GetPageParent () const { return MainPanel; } - bool IsWorkInProgress() const { return WorkInProgress; } - virtual void OnCancelButtonClick (wxCommandEvent& event) { Close(); } - virtual void OnClose (wxCloseEvent& event); - virtual void OnHelpButtonClick (wxCommandEvent& event); - virtual WizardStep ProcessPageChangeRequest (bool forward) = 0; - void SetCancelButtonText (const wxString &text); - void SetImage (const wxBitmap &bitmap); - void SetMaxStaticTextWidth (size_t charCount); - void SetStep (WizardStep newStep); - void SetWorkInProgress (bool state); - - private: - void OnActivate (wxActivateEvent& event); - void OnNextButtonClick (wxCommandEvent& event); - void OnPageUpdated (EventArgs &args) { UpdateControls(); } - void OnPreviousButtonClick (wxCommandEvent& event); - void SetStep (WizardStep newStep, bool forward); - void UpdateControls (); - - WizardPage *CurrentPage; - WizardStep CurrentStep; - int MaxStaticTextWidth; - list StepHistory; - bool WorkInProgress; - }; -} - -#endif // TC_HEADER_Main_Forms_WizardFrame +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_WizardFrame +#define TC_HEADER_Main_Forms_WizardFrame + +#include "Forms.h" +#include "Main/Main.h" + +namespace TrueCrypt +{ + class WizardFrame : public WizardFrameBase + { + public: + WizardFrame (wxWindow* parent); + virtual ~WizardFrame (); + + protected: + typedef int WizardStep; + + void ClearHistory (); + virtual WizardPage *GetPage (WizardStep step) = 0; + WizardPage *GetCurrentPage () const { return CurrentPage; } + WizardStep GetCurrentStep () const { return CurrentStep; } + wxPanel *GetPageParent () const { return MainPanel; } + bool IsWorkInProgress() const { return WorkInProgress; } + virtual void OnCancelButtonClick (wxCommandEvent& event) { Close(); } + virtual void OnClose (wxCloseEvent& event); + virtual void OnHelpButtonClick (wxCommandEvent& event); + virtual WizardStep ProcessPageChangeRequest (bool forward) = 0; + void SetCancelButtonText (const wxString &text); + void SetImage (const wxBitmap &bitmap); + void SetMaxStaticTextWidth (size_t charCount); + void SetStep (WizardStep newStep); + void SetWorkInProgress (bool state); + + private: + void OnActivate (wxActivateEvent& event); + void OnNextButtonClick (wxCommandEvent& event); + void OnPageUpdated (EventArgs &args) { UpdateControls(); } + void OnPreviousButtonClick (wxCommandEvent& event); + void SetStep (WizardStep newStep, bool forward); + void UpdateControls (); + + WizardPage *CurrentPage; + WizardStep CurrentStep; + int MaxStaticTextWidth; + list StepHistory; + bool WorkInProgress; + }; +} + +#endif // TC_HEADER_Main_Forms_WizardFrame diff --git a/Main/Forms/WizardPage.h b/Main/Forms/WizardPage.h index ad9d5c1..e7539ef 100644 --- a/Main/Forms/WizardPage.h +++ b/Main/Forms/WizardPage.h @@ -1,41 +1,41 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Forms_WizardPage -#define TC_HEADER_Main_Forms_WizardPage - -#include "Main/Main.h" - -namespace TrueCrypt -{ - class WizardPage : public wxPanel - { - public: - WizardPage (wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) - : wxPanel (parent, id, pos, size, style) - { } - virtual ~WizardPage () { } - - wxString GetPageTitle () const { return PageTitle; } - virtual bool IsValid () = 0; - virtual void OnPageChanging (bool forward) { } - wxString GetNextButtonText () const { return NextButtonText; } - void SetNextButtonText (const wxString &text) { NextButtonText = text; } - virtual void SetMaxStaticTextWidth (int width) { } - void SetPageTitle (const wxString &title) { PageTitle = title; } - virtual void SetPageText (const wxString &text) = 0; - - Event PageUpdatedEvent; - - protected: - wxString PageTitle; - wxString NextButtonText; - }; -} - -#endif // TC_HEADER_Main_Forms_WizardPage +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Forms_WizardPage +#define TC_HEADER_Main_Forms_WizardPage + +#include "Main/Main.h" + +namespace TrueCrypt +{ + class WizardPage : public wxPanel + { + public: + WizardPage (wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) + : wxPanel (parent, id, pos, size, style) + { } + virtual ~WizardPage () { } + + wxString GetPageTitle () const { return PageTitle; } + virtual bool IsValid () = 0; + virtual void OnPageChanging (bool forward) { } + wxString GetNextButtonText () const { return NextButtonText; } + void SetNextButtonText (const wxString &text) { NextButtonText = text; } + virtual void SetMaxStaticTextWidth (int width) { } + void SetPageTitle (const wxString &title) { PageTitle = title; } + virtual void SetPageText (const wxString &text) = 0; + + Event PageUpdatedEvent; + + protected: + wxString PageTitle; + wxString NextButtonText; + }; +} + +#endif // TC_HEADER_Main_Forms_WizardPage diff --git a/Main/GraphicUserInterface.cpp b/Main/GraphicUserInterface.cpp index 3343cab..ab43886 100644 --- a/Main/GraphicUserInterface.cpp +++ b/Main/GraphicUserInterface.cpp @@ -1,1652 +1,1653 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" - -#ifdef TC_UNIX -#include -#include -#include -#include -#include "Platform/Unix/Process.h" -#endif - -#include "Common/SecurityToken.h" -#include "Application.h" -#include "GraphicUserInterface.h" -#include "FatalErrorHandler.h" -#include "Forms/DeviceSelectionDialog.h" -#include "Forms/KeyfileGeneratorDialog.h" -#include "Forms/MainFrame.h" -#include "Forms/MountOptionsDialog.h" -#include "Forms/RandomPoolEnrichmentDialog.h" -#include "Forms/SecurityTokenKeyfilesDialog.h" - -namespace TrueCrypt -{ - GraphicUserInterface::GraphicUserInterface () : - ActiveFrame (nullptr), - BackgroundMode (false), - mMainFrame (nullptr) - { -#ifdef TC_UNIX - signal (SIGHUP, OnSignal); - signal (SIGINT, OnSignal); - signal (SIGQUIT, OnSignal); - signal (SIGTERM, OnSignal); -#endif - -#ifdef TC_MACOSX - wxApp::s_macHelpMenuTitleName = _("&Help"); -#endif - } - - GraphicUserInterface::~GraphicUserInterface () - { - try - { - if (RandomNumberGenerator::IsRunning()) - RandomNumberGenerator::Stop(); - } - catch (...) { } - - FatalErrorHandler::Deregister(); - -#ifdef TC_UNIX - signal (SIGHUP, SIG_DFL); - signal (SIGINT, SIG_DFL); - signal (SIGQUIT, SIG_DFL); - signal (SIGTERM, SIG_DFL); -#endif - } - - void GraphicUserInterface::AppendToListCtrl (wxListCtrl *listCtrl, const vector &itemFields, int imageIndex, void *itemDataPtr) const - { - InsertToListCtrl (listCtrl, listCtrl->GetItemCount(), itemFields, imageIndex, itemDataPtr); - } - - wxMenuItem *GraphicUserInterface::AppendToMenu (wxMenu &menu, const wxString &label, wxEvtHandler *handler, wxObjectEventFunction handlerFunction, int itemId) const - { - wxMenuItem *item = new wxMenuItem (&menu, itemId, label); - menu.Append (item); - - if (handler) - handler->Connect (item->GetId(), wxEVT_COMMAND_MENU_SELECTED, handlerFunction); - - return item; - } - - bool GraphicUserInterface::AskYesNo (const wxString &message, bool defaultYes, bool warning) const - { - return ShowMessage (message, - wxYES_NO | (warning ? wxICON_EXCLAMATION : wxICON_QUESTION) | (defaultYes ? wxYES_DEFAULT : wxNO_DEFAULT) - ) == wxYES; - } - - void GraphicUserInterface::AutoDismountVolumes (VolumeInfoList mountedVolumes, bool alwaysForce) - { - size_t mountedVolumeCount = Core->GetMountedVolumes().size(); - try - { - wxBusyCursor busy; - DismountVolumes (mountedVolumes, alwaysForce ? true : GetPreferences().ForceAutoDismount, false); - } - catch (...) { } - - if (Core->GetMountedVolumes().size() < mountedVolumeCount) - OnVolumesAutoDismounted(); - } - - void GraphicUserInterface::BackupVolumeHeaders (shared_ptr volumePath) const - { - wxWindow *parent = GetActiveWindow(); - - if (!volumePath || volumePath->IsEmpty()) - volumePath = make_shared (SelectVolumeFile (GetActiveWindow())); - - if (volumePath->IsEmpty()) - throw UserAbort (SRC_POS); - -#ifdef TC_WINDOWS - if (Core->IsVolumeMounted (*volumePath)) - { - ShowInfo ("DISMOUNT_FIRST"); - return; - } -#endif - -#ifdef TC_UNIX - // Temporarily take ownership of a device if the user is not an administrator - UserId origDeviceOwner ((uid_t) -1); - - if (!Core->HasAdminPrivileges() && volumePath->IsDevice()) - { - origDeviceOwner = FilesystemPath (wstring (*volumePath)).GetOwner(); - Core->SetFileOwner (*volumePath, UserId (getuid())); - } - - finally_do_arg2 (FilesystemPath, *volumePath, UserId, origDeviceOwner, - { - if (finally_arg2.SystemId != (uid_t) -1) - Core->SetFileOwner (finally_arg, finally_arg2); - }); -#endif - - ShowInfo ("EXTERNAL_VOL_HEADER_BAK_FIRST_INFO"); - - shared_ptr normalVolume; - shared_ptr hiddenVolume; - - MountOptions normalVolumeMountOptions; - MountOptions hiddenVolumeMountOptions; - - normalVolumeMountOptions.Path = volumePath; - hiddenVolumeMountOptions.Path = volumePath; - - VolumeType::Enum volumeType = VolumeType::Normal; - - // Open both types of volumes - while (true) - { - shared_ptr volume; - MountOptions *options = (volumeType == VolumeType::Hidden ? &hiddenVolumeMountOptions : &normalVolumeMountOptions); - - MountOptionsDialog dialog (parent, *options, - LangString[volumeType == VolumeType::Hidden ? "ENTER_HIDDEN_VOL_PASSWORD" : "ENTER_NORMAL_VOL_PASSWORD"], - true); - - while (!volume) - { - dialog.Hide(); - if (dialog.ShowModal() != wxID_OK) - return; - - try - { - wxBusyCursor busy; - volume = Core->OpenVolume ( - options->Path, - options->PreserveTimestamps, - options->Password, - options->Keyfiles, - options->Protection, - options->ProtectionPassword, - options->ProtectionKeyfiles, - true, - volumeType, - options->UseBackupHeaders - ); - } - catch (PasswordException &e) - { - ShowWarning (e); - } - } - - if (volumeType == VolumeType::Hidden) - hiddenVolume = volume; - else - normalVolume = volume; - - // Ask whether a hidden volume is present - if (volumeType == VolumeType::Normal) - { - wxArrayString choices; - choices.Add (LangString["VOLUME_CONTAINS_HIDDEN"]); - choices.Add (LangString["VOLUME_DOES_NOT_CONTAIN_HIDDEN"]); - - wxSingleChoiceDialog choiceDialog (parent, LangString["DOES_VOLUME_CONTAIN_HIDDEN"], Application::GetName(), choices); - choiceDialog.SetSize (wxSize (Gui->GetCharWidth (&choiceDialog) * 60, -1)); - choiceDialog.SetSelection (-1); - - if (choiceDialog.ShowModal() != wxID_OK) - return; - - switch (choiceDialog.GetSelection()) - { - case 0: - volumeType = VolumeType::Hidden; - continue; - - case 1: - break; - - default: - return; - } - } - - break; - } - - if (hiddenVolume) - { - if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV1Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV1Hidden)) - throw ParameterIncorrect (SRC_POS); - - if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV2Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV2Hidden)) - throw ParameterIncorrect (SRC_POS); - } - - // Ask user to select backup file path - wxString confirmMsg = LangString["CONFIRM_VOL_HEADER_BAK"]; - confirmMsg.Replace (L"%hs", L"%s"); - - if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true)) - return; - - FilePathList files = SelectFiles (parent, wxEmptyString, true, false); - if (files.empty()) - return; - - File backupFile; - backupFile.Open (*files.front(), File::CreateWrite); - - RandomNumberGenerator::Start(); - UserEnrichRandomPool (nullptr); - - { - wxBusyCursor busy; - - // Re-encrypt volume header - SecureBuffer newHeaderBuffer (normalVolume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Keyfiles); - - backupFile.Write (newHeaderBuffer); - - if (hiddenVolume) - { - // Re-encrypt hidden volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Keyfiles); - } - else - { - // Store random data in place of hidden volume header - shared_ptr ea = normalVolume->GetEncryptionAlgorithm(); - Core->RandomizeEncryptionAlgorithmKey (ea); - ea->Encrypt (newHeaderBuffer); - } - - backupFile.Write (newHeaderBuffer); - } - - ShowWarning ("VOL_HEADER_BACKED_UP"); - } - - void GraphicUserInterface::BeginInteractiveBusyState (wxWindow *window) - { - static auto_ptr arrowWaitCursor; - - if (arrowWaitCursor.get() == nullptr) - arrowWaitCursor.reset (new wxCursor (wxCURSOR_ARROWWAIT)); - - window->SetCursor (*arrowWaitCursor); - } - - void GraphicUserInterface::CreateKeyfile (shared_ptr keyfilePath) const - { - try - { - KeyfileGeneratorDialog dialog (GetActiveWindow()); - dialog.ShowModal(); - } - catch (exception &e) - { - ShowError (e); - } - } - - void GraphicUserInterface::ClearListCtrlSelection (wxListCtrl *listCtrl) const - { - foreach (long item, GetListCtrlSelectedItems (listCtrl)) - listCtrl->SetItemState (item, 0, wxLIST_STATE_SELECTED); - } - - wxHyperlinkCtrl *GraphicUserInterface::CreateHyperlink (wxWindow *parent, const wxString &linkUrl, const wxString &linkText) const - { - wxHyperlinkCtrl *hyperlink = new wxHyperlinkCtrl (parent, wxID_ANY, linkText, linkUrl, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); - - wxColour color = wxSystemSettings::GetColour (wxSYS_COLOUR_WINDOWTEXT); - hyperlink->SetHoverColour (color); - hyperlink->SetNormalColour (color); - hyperlink->SetVisitedColour (color); - - return hyperlink; - } - - void GraphicUserInterface::DoShowError (const wxString &message) const - { - ShowMessage (message, wxOK | wxICON_ERROR); - } - - void GraphicUserInterface::DoShowInfo (const wxString &message) const - { - ShowMessage (message, wxOK | wxICON_INFORMATION); - } - - void GraphicUserInterface::DoShowString (const wxString &str) const - { - ShowMessage (str, wxOK); - } - - void GraphicUserInterface::DoShowWarning (const wxString &message) const - { - ShowMessage (message, wxOK -#ifndef TC_MACOSX - | wxICON_EXCLAMATION -#endif - ); - } - - void GraphicUserInterface::EndInteractiveBusyState (wxWindow *window) const - { - static auto_ptr arrowCursor; - - if (arrowCursor.get() == nullptr) - arrowCursor.reset (new wxCursor (wxCURSOR_ARROW)); - - window->SetCursor (*arrowCursor); - } - - wxTopLevelWindow *GraphicUserInterface::GetActiveWindow () const - { -#ifdef TC_WINDOWS - return dynamic_cast (wxGetActiveWindow()); -#endif - -#ifdef __WXGTK__ - // GTK for some reason unhides a hidden window if it is a parent of a new window - if (IsInBackgroundMode()) - return nullptr; -#endif - if (wxTopLevelWindows.size() == 1) - return dynamic_cast (wxTopLevelWindows.front()); - -#ifdef __WXGTK__ - wxLongLong startTime = wxGetLocalTimeMillis(); - do - { -#endif - foreach (wxWindow *window, wxTopLevelWindows) - { - wxTopLevelWindow *topLevelWin = dynamic_cast (window); - if (topLevelWin && topLevelWin->IsActive() && topLevelWin->IsShown()) - return topLevelWin; - } -#ifdef __WXGTK__ - Yield(); // GTK does a lot of operations asynchronously, which makes it prone to many race conditions - } while (wxGetLocalTimeMillis() - startTime < 500); -#endif - - return dynamic_cast (ActiveFrame ? ActiveFrame : GetTopWindow()); - } - - shared_ptr GraphicUserInterface::GetAdminPasswordRequestHandler () - { - struct AdminPasswordRequestHandler : public GetStringFunctor - { - virtual void operator() (string &passwordStr) - { - wxPasswordEntryDialog dialog (Gui->GetActiveWindow(), _("Enter your user password or administrator password:"), _("Administrator privileges required")); - - if (dialog.ShowModal() != wxID_OK) - throw UserAbort (SRC_POS); - - wstring wPassword (dialog.GetValue()); // A copy of the password is created here by wxWidgets, which cannot be erased - finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); - - StringConverter::ToSingle (wPassword, passwordStr); - } - }; - - return shared_ptr (new AdminPasswordRequestHandler); - } - - int GraphicUserInterface::GetCharHeight (wxWindow *window) const - { - int width; - int height; - window->GetTextExtent (L"a", &width, &height); - - if (height < 1) - return 14; - - return height; - } - - int GraphicUserInterface::GetCharWidth (wxWindow *window) const - { - int width; - int height; - window->GetTextExtent (L"a", &width, &height); - - if (width < 1) - return 7; - - return width; - } - - wxFont GraphicUserInterface::GetDefaultBoldFont (wxWindow *window) const - { - return wxFont ( -#ifdef __WXGTK__ - 9 -#elif defined(TC_MACOSX) - 13 -#else - 10 -#endif - * GetCharHeight (window) / 13, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, -#ifdef __WXGTK__ - wxFONTWEIGHT_BOLD, false); -#elif defined(TC_MACOSX) - wxFONTWEIGHT_NORMAL, false); -#else - wxFONTWEIGHT_BOLD, false, L"Arial"); -#endif - } - - list GraphicUserInterface::GetListCtrlSelectedItems (wxListCtrl *listCtrl) const - { - list selectedItems; - - long item = -1; - while ((item = listCtrl->GetNextItem (item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED)) != -1) - selectedItems.push_back (item); - - return selectedItems; - } - - wxString GraphicUserInterface::GetListCtrlSubItemText (wxListCtrl *listCtrl, long itemIndex, int columnIndex) const - { - wxListItem item; - item.SetId (itemIndex); - item.SetColumn (columnIndex); - item.SetText (L""); - - if (!listCtrl->GetItem (item)) - throw ParameterIncorrect (SRC_POS); - - return item.GetText(); - } - - int GraphicUserInterface::GetScrollbarWidth (wxWindow *window, bool noScrollBar) const - { - int offset = 0; -#ifdef TC_WINDOWS - offset = 4; -#elif defined (__WXGTK__) - offset = 5; -#elif defined (TC_MACOSX) - offset = 9; -#endif - if (noScrollBar) - return offset; - - int width = wxSystemSettings::GetMetric (wxSYS_VSCROLL_X, window); - if (width == -1) - return 24; - - return width + offset; - } - - void GraphicUserInterface::InitSecurityTokenLibrary () const - { - if (Preferences.SecurityTokenModule.IsEmpty()) - throw_err (LangString ["NO_PKCS11_MODULE_SPECIFIED"]); - - struct PinRequestHandler : public GetPinFunctor - { - virtual void operator() (string &passwordStr) - { - if (Gui->GetPreferences().NonInteractive) - throw MissingArgument (SRC_POS); - - wxPasswordEntryDialog dialog (Gui->GetActiveWindow(), wxString::Format (LangString["ENTER_TOKEN_PASSWORD"], StringConverter::ToWide (passwordStr).c_str()), LangString["IDD_TOKEN_PASSWORD"]); - dialog.SetSize (wxSize (Gui->GetCharWidth (&dialog) * 50, -1)); - - if (dialog.ShowModal() != wxID_OK) - throw UserAbort (SRC_POS); - - wstring wPassword (dialog.GetValue()); // A copy of the password is created here by wxWidgets, which cannot be erased - finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); - - StringConverter::ToSingle (wPassword, passwordStr); - } - }; - - struct WarningHandler : public SendExceptionFunctor - { - virtual void operator() (const Exception &e) - { - Gui->ShowError (e); - } - }; - - try - { - SecurityToken::InitLibrary (Preferences.SecurityTokenModule, auto_ptr (new PinRequestHandler), auto_ptr (new WarningHandler)); - } - catch (Exception &e) - { - ShowError (e); - throw_err (LangString ["PKCS11_MODULE_INIT_FAILED"]); - } - } - - void GraphicUserInterface::InsertToListCtrl (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields, int imageIndex, void *itemDataPtr) const - { - wxListItem item; - item.SetData (itemDataPtr); - item.SetId (itemIndex); - item.SetImage (imageIndex); - int col = 0; - foreach (wxString field, itemFields) - { - item.SetColumn (col++); - item.SetText (field); - if (col == 1) - { - throw_sys_if (listCtrl->InsertItem (item) == -1); - item.SetImage (-1); - continue; - } - - listCtrl->SetItem (item); - } - } - - bool GraphicUserInterface::IsTheOnlyTopLevelWindow (const wxWindow *window) const - { - foreach (wxWindow *w, wxTopLevelWindows) - { - if (w != window - && (dynamic_cast (w) || dynamic_cast (w)) - && StringConverter::GetTypeName (typeid (*w)).find ("wxTaskBarIcon") == string::npos) - { - return false; - } - } - return true; - } - - void GraphicUserInterface::ListSecurityTokenKeyfiles () const - { - SecurityTokenKeyfilesDialog dialog (nullptr); - dialog.ShowModal(); - } - -#ifdef TC_MACOSX - void GraphicUserInterface::MacOpenFile (const wxString &fileName) - { - OpenVolumeSystemRequestEventArgs eventArgs (fileName); - OpenVolumeSystemRequestEvent.Raise (eventArgs); - } -#endif - - void GraphicUserInterface::MoveListCtrlItem (wxListCtrl *listCtrl, long itemIndex, long newItemIndex) const - { - if (itemIndex == newItemIndex || newItemIndex < 0 - || (newItemIndex > itemIndex && newItemIndex == listCtrl->GetItemCount())) - return; - - wxListItem item; - item.SetId (itemIndex); - item.SetData ((void *) nullptr); - item.SetImage (-1); - - if (!listCtrl->GetItem (item)) - throw ParameterIncorrect (SRC_POS); - - int itemState = listCtrl->GetItemState (itemIndex, wxLIST_STATE_SELECTED); - - vector itemFields (listCtrl->GetColumnCount()); - for (size_t col = 0; col < itemFields.size(); ++col) - { - itemFields[col] = GetListCtrlSubItemText (listCtrl, itemIndex, col); - } - - listCtrl->DeleteItem (itemIndex); - - if (newItemIndex > listCtrl->GetItemCount() - 1) - AppendToListCtrl (listCtrl, itemFields, item.GetImage(), (void *) item.GetData()); - else - InsertToListCtrl (listCtrl, newItemIndex, itemFields, item.GetImage(), (void *) item.GetData()); - - item.SetId (newItemIndex); - listCtrl->SetItemState (item, itemState, wxLIST_STATE_SELECTED); - } - - VolumeInfoList GraphicUserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const - { - MountOptionsDialog dialog (GetTopWindow(), options); - while (true) - { - options.Path.reset(); - - if (dialog.ShowModal() != wxID_OK) - return VolumeInfoList(); - - VolumeInfoList mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (options); - - if (!mountedVolumes.empty()) - return mountedVolumes; - } - } - - shared_ptr GraphicUserInterface::MountVolume (MountOptions &options) const - { - CheckRequirementsForMountingVolume(); - - shared_ptr volume; - - if (!options.Path || options.Path->IsEmpty()) - options.Path = make_shared (SelectVolumeFile (GetActiveWindow())); - - if (options.Path->IsEmpty()) - throw UserAbort (SRC_POS); - - if (Core->IsVolumeMounted (*options.Path)) - { - ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (*options.Path))); - return volume; - } - - try - { - if ((!options.Password || options.Password->IsEmpty()) - && (!options.Keyfiles || options.Keyfiles->empty()) - && !Core->IsPasswordCacheEmpty()) - { - // Cached password - try - { - wxBusyCursor busy; - return UserInterface::MountVolume (options); - } - catch (PasswordException&) { } - } - - if ((options.Password && !options.Password->IsEmpty()) - || (options.Keyfiles && !options.Keyfiles->empty())) - { - try - { - wxBusyCursor busy; - return UserInterface::MountVolume (options); - } - catch (PasswordException&) { } - } - - VolumePassword password; - KeyfileList keyfiles; - - MountOptionsDialog dialog (GetTopWindow(), options); - int incorrectPasswordCount = 0; - - while (!volume) - { - dialog.Hide(); - if (dialog.ShowModal() != wxID_OK) - return volume; - - try - { - wxBusyCursor busy; - volume = UserInterface::MountVolume (options); - } - catch (PasswordIncorrect &e) - { - if (++incorrectPasswordCount > 2 && !options.UseBackupHeaders) - { - // Try to mount the volume using the backup header - options.UseBackupHeaders = true; - - try - { - volume = UserInterface::MountVolume (options); - ShowWarning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); - } - catch (...) - { - options.UseBackupHeaders = false; - ShowWarning (e); - } - } - else - ShowWarning (e); - } - catch (PasswordException &e) - { - ShowWarning (e); - } - } - } - catch (exception &e) - { - ShowError (e); - } - -#ifdef TC_LINUX - if (volume && !Preferences.NonInteractive && !Preferences.DisableKernelEncryptionModeWarning - && volume->EncryptionModeName != L"XTS" - && (volume->EncryptionModeName != L"LRW" || volume->EncryptionAlgorithmMinBlockSize != 16 || volume->EncryptionAlgorithmKeySize != 32) - && !AskYesNo (LangString["ENCRYPTION_MODE_NOT_SUPPORTED_BY_KERNEL"] + _("\n\nDo you want to show this message next time you mount such a volume?"), true, true)) - { - UserPreferences prefs = GetPreferences(); - prefs.DisableKernelEncryptionModeWarning = true; - Gui->SetPreferences (prefs); - } -#endif - return volume; - } - - void GraphicUserInterface::OnAutoDismountAllEvent () - { - VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); - - if (!mountedVolumes.empty()) - { - wxBusyCursor busy; - AutoDismountVolumes (mountedVolumes); - } - } - - bool GraphicUserInterface::OnInit () - { - Gui = this; - InterfaceType = UserInterfaceType::Graphic; - try - { - FatalErrorHandler::Register(); - Init(); - - if (ProcessCommandLine() && !CmdLine->StartBackgroundTask) - { - Yield(); - Application::SetExitCode (0); - return false; - } - - // Check if another instance is already running and bring its windows to foreground -#ifndef TC_MACOSX -#ifdef TC_WINDOWS - const wxString serverName = Application::GetName() + L"-" + wxGetUserId(); - class Connection : public wxDDEConnection - { - public: - Connection () { } - - bool OnExecute (const wxString& topic, wxChar *data, int size, wxIPCFormat format) - { - if (topic == L"raise") - { - if (Gui->IsInBackgroundMode()) - Gui->SetBackgroundMode (false); - - Gui->mMainFrame->Show (true); - Gui->mMainFrame->Raise (); - return true; - } - return false; - } - }; -#endif - - SingleInstanceChecker.reset (new wxSingleInstanceChecker (wxString (L".") + Application::GetName() + L"-lock-" + wxGetUserId())); - - if (SingleInstanceChecker->IsAnotherRunning()) - { -#ifdef TC_WINDOWS - class Client: public wxDDEClient - { - public: - Client() {}; - wxConnectionBase *OnMakeConnection () { return new Connection; } - }; - - auto_ptr client (new Client); - auto_ptr connection (client->MakeConnection (L"localhost", serverName, L"raise")); - - if (connection.get() && connection->Execute (nullptr)) - { - connection->Disconnect(); - Application::SetExitCode (0); - return false; - } -#endif - wxLog::FlushActive(); - Application::SetExitCode (1); - Gui->ShowInfo (_("TrueCrypt is already running.")); - return false; - } - -#ifdef TC_WINDOWS - class Server : public wxDDEServer - { - public: - wxConnectionBase *OnAcceptConnection (const wxString &topic) - { - if (topic == L"raise") - return new Connection; - return nullptr; - } - }; - - DDEServer.reset (new Server); - if (!DDEServer->Create (serverName)) - wxLog::FlushActive(); -#endif -#endif // !TC_MACOSX - - Connect (wxEVT_END_SESSION, wxCloseEventHandler (GraphicUserInterface::OnEndSession)); -#ifdef wxHAS_POWER_EVENTS - Gui->Connect (wxEVT_POWER_SUSPENDING, wxPowerEventHandler (GraphicUserInterface::OnPowerSuspending)); -#endif - - mMainFrame = new MainFrame (nullptr); - - if (CmdLine->StartBackgroundTask) - { - UserPreferences prefs = GetPreferences (); - prefs.BackgroundTaskEnabled = true; - SetPreferences (prefs); - mMainFrame->Close(); - } - else - { - mMainFrame->Show (true); - } - - SetTopWindow (mMainFrame); - } - catch (exception &e) - { - ShowError (e); - return false; - } - - return true; - } - - void GraphicUserInterface::OnLogOff () - { - VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); - if (GetPreferences().BackgroundTaskEnabled && GetPreferences().DismountOnLogOff - && !mountedVolumes.empty()) - { - wxLongLong startTime = wxGetLocalTimeMillis(); - bool timeOver = false; - - wxBusyCursor busy; - while (!timeOver && !mountedVolumes.empty()) - { - try - { - timeOver = (wxGetLocalTimeMillis() - startTime >= 4000); - - DismountVolumes (mountedVolumes, !timeOver ? false : GetPreferences().ForceAutoDismount, timeOver); - OnVolumesAutoDismounted(); - - break; - } - catch (UserAbort&) - { - return; - } - catch (...) - { - Thread::Sleep (500); - } - - VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); - } - - } - } - -#ifdef wxHAS_POWER_EVENTS - void GraphicUserInterface::OnPowerSuspending (wxPowerEvent& event) - { - size_t volumeCount = Core->GetMountedVolumes().size(); - if (GetPreferences().BackgroundTaskEnabled && GetPreferences().DismountOnPowerSaving && volumeCount > 0) - { - OnAutoDismountAllEvent(); - - if (Core->GetMountedVolumes().size() < volumeCount) - ShowInfoTopMost (LangString["MOUNTED_VOLUMES_AUTO_DISMOUNTED"]); - } - } -#endif - - void GraphicUserInterface::OnSignal (int signal) - { -#ifdef TC_UNIX - Gui->SingleInstanceChecker.reset(); - _exit (1); -#endif - } - - void GraphicUserInterface::OnVolumesAutoDismounted () - { - if (GetPreferences().WipeCacheOnAutoDismount) - { - Core->WipePasswordCache(); - SecurityToken::CloseAllSessions(); - } - } - - void GraphicUserInterface::OpenDocument (wxWindow *parent, const wxFileName &document) - { - if (!document.FileExists()) - throw ParameterIncorrect (SRC_POS); - -#ifdef TC_WINDOWS - - if (int (ShellExecute (GetTopWindow() ? static_cast (GetTopWindow()->GetHandle()) : nullptr, L"open", - document.GetFullPath().c_str(), nullptr, nullptr, SW_SHOWNORMAL)) >= 32) - return; - -#else - wxMimeTypesManager mimeMgr; - wxFileType *fileType = mimeMgr.GetFileTypeFromExtension (document.GetExt()); - if (fileType) - { - try - { -#ifdef TC_MACOSX - if (wxExecute (fileType->GetOpenCommand (document.GetFullPath())) != 0) - return; -#else - if (wxExecute (fileType->GetOpenCommand (L"\"" + document.GetFullPath() + L"\"")) != 0) - return; -#endif - } - catch (TimeOut&) { } - } -#endif - } - - wxString GraphicUserInterface::GetHomepageLinkURL (const wxString &linkId, bool secure, const wxString &extraVars) const - { - wxString url = wxString (StringConverter::ToWide (secure ? TC_APPLINK_SECURE : TC_APPLINK)) + L"&dest=" + linkId; - wxString os, osVersion, architecture; - -#ifdef TC_WINDOWS - - os = L"Windows"; - -#elif defined (TC_UNIX) - struct utsname unameData; - if (uname (&unameData) != -1) - { - os = StringConverter::ToWide (unameData.sysname); - osVersion = StringConverter::ToWide (unameData.release); - architecture = StringConverter::ToWide (unameData.machine); - - if (os == L"Darwin") - os = L"MacOSX"; - } - else - os = L"Unknown"; -#else - os = L"Unknown"; -#endif - - os.Replace (L" ", L"-"); - url += L"&os="; - url += os; - - osVersion.Replace (L" ", L"-"); - url += L"&osver="; - url += osVersion; - - architecture.Replace (L" ", L"-"); - url += L"&arch="; - url += architecture; - - if (!extraVars.empty()) - { - url += L"&"; - url += extraVars; - } - - return url; - } - - void GraphicUserInterface::OpenHomepageLink (wxWindow *parent, const wxString &linkId, const wxString &extraVars) - { - wxString url; - - BeginInteractiveBusyState (parent); - wxLaunchDefaultBrowser (GetHomepageLinkURL (linkId, false, extraVars), wxBROWSER_NEW_WINDOW); - Thread::Sleep (200); - EndInteractiveBusyState (parent); - } - - void GraphicUserInterface::OpenOnlineHelp (wxWindow *parent) - { - OpenHomepageLink (parent, L"help"); - } - - void GraphicUserInterface::OpenUserGuide (wxWindow *parent) - { - try - { - wxString docPath = wstring (Application::GetExecutableDirectory()); - -#ifdef TC_RESOURCE_DIR - docPath = StringConverter::ToWide (string (TC_TO_STRING (TC_RESOURCE_DIR)) + "/doc/TrueCrypt User Guide.pdf"); -#elif defined (TC_WINDOWS) - docPath += L"\\TrueCrypt User Guide.pdf"; -#elif defined (TC_MACOSX) - docPath += L"/../Resources/TrueCrypt User Guide.pdf"; -#elif defined (TC_UNIX) - docPath = L"/usr/share/truecrypt/doc/TrueCrypt User Guide.pdf"; -#else -# error TC_RESOURCE_DIR undefined -#endif - - wxFileName docFile = docPath; - docFile.Normalize(); - - try - { - Gui->OpenDocument (parent, docFile); - } - catch (...) - { - if (Gui->AskYesNo (LangString ["HELP_READER_ERROR"], true)) - OpenOnlineHelp (parent); - } - } - catch (Exception &e) - { - Gui->ShowError (e); - } - } - - void GraphicUserInterface::RestoreVolumeHeaders (shared_ptr volumePath) const - { - wxWindow *parent = GetActiveWindow(); - - if (!volumePath || volumePath->IsEmpty()) - volumePath = make_shared (SelectVolumeFile (GetActiveWindow())); - - if (volumePath->IsEmpty()) - throw UserAbort (SRC_POS); - -#ifdef TC_WINDOWS - if (Core->IsVolumeMounted (*volumePath)) - { - ShowInfo ("DISMOUNT_FIRST"); - return; - } -#endif - -#ifdef TC_UNIX - // Temporarily take ownership of a device if the user is not an administrator - UserId origDeviceOwner ((uid_t) -1); - - if (!Core->HasAdminPrivileges() && volumePath->IsDevice()) - { - origDeviceOwner = FilesystemPath (wstring (*volumePath)).GetOwner(); - Core->SetFileOwner (*volumePath, UserId (getuid())); - } - - finally_do_arg2 (FilesystemPath, *volumePath, UserId, origDeviceOwner, - { - if (finally_arg2.SystemId != (uid_t) -1) - Core->SetFileOwner (finally_arg, finally_arg2); - }); -#endif - - // Ask whether to restore internal or external backup - bool restoreInternalBackup; - wxArrayString choices; - choices.Add (LangString["HEADER_RESTORE_INTERNAL"]); - choices.Add (LangString["HEADER_RESTORE_EXTERNAL"]); - - wxSingleChoiceDialog choiceDialog (parent, LangString["HEADER_RESTORE_EXTERNAL_INTERNAL"], Application::GetName(), choices); - choiceDialog.SetSize (wxSize (Gui->GetCharWidth (&choiceDialog) * 80, -1)); - choiceDialog.SetSelection (-1); - - if (choiceDialog.ShowModal() != wxID_OK) - return; - - switch (choiceDialog.GetSelection()) - { - case 0: - restoreInternalBackup = true; - break; - - case 1: - restoreInternalBackup = false; - break; - - default: - return; - } - - if (restoreInternalBackup) - { - // Restore header from the internal backup - shared_ptr volume; - MountOptions options; - options.Path = volumePath; - - MountOptionsDialog dialog (parent, options, wxEmptyString, true); - - while (!volume) - { - dialog.Hide(); - if (dialog.ShowModal() != wxID_OK) - return; - - try - { - wxBusyCursor busy; - volume = Core->OpenVolume ( - options.Path, - options.PreserveTimestamps, - options.Password, - options.Keyfiles, - options.Protection, - options.ProtectionPassword, - options.ProtectionKeyfiles, - options.SharedAccessAllowed, - VolumeType::Unknown, - true - ); - } - catch (PasswordException &e) - { - ShowWarning (e); - } - } - - shared_ptr layout = volume->GetLayout(); - if (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden)) - { - ShowError ("VOLUME_HAS_NO_BACKUP_HEADER"); - return; - } - - RandomNumberGenerator::Start(); - UserEnrichRandomPool (nullptr); - - // Re-encrypt volume header - SecureBuffer newHeaderBuffer (volume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Keyfiles); - - // Write volume header - int headerOffset = volume->GetLayout()->GetHeaderOffset(); - shared_ptr volumeFile = volume->GetFile(); - - if (headerOffset >= 0) - volumeFile->SeekAt (headerOffset); - else - volumeFile->SeekEnd (headerOffset); - - volumeFile->Write (newHeaderBuffer); - } - else - { - // Restore header from an external backup - - wxString confirmMsg = LangString["CONFIRM_VOL_HEADER_RESTORE"]; - confirmMsg.Replace (L"%hs", L"%s"); - - if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true, true)) - return; - - FilePathList files = SelectFiles (parent, wxEmptyString, false, false); - if (files.empty()) - return; - - File backupFile; - backupFile.Open (*files.front(), File::OpenRead); - - uint64 headerSize; - bool legacyBackup; - - // Determine the format of the backup file - switch (backupFile.Length()) - { - case TC_VOLUME_HEADER_GROUP_SIZE: - headerSize = TC_VOLUME_HEADER_SIZE; - legacyBackup = false; - break; - - case TC_VOLUME_HEADER_SIZE_LEGACY * 2: - headerSize = TC_VOLUME_HEADER_SIZE_LEGACY; - legacyBackup = true; - break; - - default: - ShowError ("HEADER_BACKUP_SIZE_INCORRECT"); - return; - } - - // Open the volume header stored in the backup file - MountOptions options; - - MountOptionsDialog dialog (parent, options, LangString["ENTER_HEADER_BACKUP_PASSWORD"], true); - shared_ptr decryptedLayout; - - while (!decryptedLayout) - { - dialog.Hide(); - if (dialog.ShowModal() != wxID_OK) - return; - - try - { - wxBusyCursor busy; - - // Test volume layouts - foreach (shared_ptr layout, VolumeLayout::GetAvailableLayouts ()) - { - if (layout->HasDriveHeader()) - continue; - - if (!legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden))) - continue; - - if (legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV2Normal) || typeid (*layout) == typeid (VolumeLayoutV2Hidden))) - continue; - - SecureBuffer headerBuffer (layout->GetHeaderSize()); - backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); - - // Decrypt header - shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); - if (layout->GetHeader()->Decrypt (headerBuffer, *passwordKey, layout->GetSupportedKeyDerivationFunctions(), layout->GetSupportedEncryptionAlgorithms(), layout->GetSupportedEncryptionModes())) - { - decryptedLayout = layout; - break; - } - } - - if (!decryptedLayout) - throw PasswordIncorrect (SRC_POS); - } - catch (PasswordException &e) - { - ShowWarning (e); - } - } - - File volumeFile; - volumeFile.Open (*volumePath, File::OpenReadWrite, File::ShareNone, File::PreserveTimestamps); - - RandomNumberGenerator::Start(); - UserEnrichRandomPool (nullptr); - - // Re-encrypt volume header - SecureBuffer newHeaderBuffer (decryptedLayout->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); - - // Write volume header - int headerOffset = decryptedLayout->GetHeaderOffset(); - if (headerOffset >= 0) - volumeFile.SeekAt (headerOffset); - else - volumeFile.SeekEnd (headerOffset); - - volumeFile.Write (newHeaderBuffer); - - if (decryptedLayout->HasBackupHeader()) - { - // Re-encrypt backup volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); - - // Write backup volume header - headerOffset = decryptedLayout->GetBackupHeaderOffset(); - if (headerOffset >= 0) - volumeFile.SeekAt (headerOffset); - else - volumeFile.SeekEnd (headerOffset); - - volumeFile.Write (newHeaderBuffer); - } - } - - ShowInfo ("VOL_HEADER_RESTORED"); - } - - DevicePath GraphicUserInterface::SelectDevice (wxWindow *parent) const - { - try - { - DeviceSelectionDialog dialog (parent); - if (dialog.ShowModal() == wxID_OK) - { - return dialog.SelectedDevice.Path; - } - } - catch (exception &e) - { - Gui->ShowError (e); - } - - return DevicePath(); - } - - DirectoryPath GraphicUserInterface::SelectDirectory (wxWindow *parent, const wxString &message, bool existingOnly) const - { - return DirectoryPath (::wxDirSelector (!message.empty() ? message : -#ifdef __WXGTK__ - wxDirSelectorPromptStr, -#else - L"", -#endif - L"", wxDD_DEFAULT_STYLE | (existingOnly ? wxDD_DIR_MUST_EXIST : 0), wxDefaultPosition, parent)); - } - - FilePathList GraphicUserInterface::SelectFiles (wxWindow *parent, const wxString &caption, bool saveMode, bool allowMultiple, const list < pair > &fileExtensions, const DirectoryPath &directory) const - { - FilePathList files; - - long style; - if (saveMode) - style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT; - else - style = wxFD_OPEN | wxFD_FILE_MUST_EXIST | (allowMultiple ? wxFD_MULTIPLE : 0); - - wxString wildcards = L"*.*"; - -#ifndef __WXGTK__ - if (!fileExtensions.empty()) -#endif - { - wildcards = LangString["ALL_FILES"] + -#ifdef TC_WINDOWS - L" (*.*)|*.*"; -#else - L"|*"; -#endif - typedef pair StringPair; - foreach (StringPair p, fileExtensions) - { - if (p.first == L"*" || p.first == L"*.*") - { - wildcards += L"|" + wildcards.substr (0, wildcards.find (L"*|") + 1); - wildcards = wildcards.substr (wildcards.find (L"*|") + 2); - continue; - } - - wildcards += wxString (L"|") + p.second + L" (*." + p.first + L")|*." + p.first; - } - } - - wxFileDialog dialog (parent, !caption.empty() ? caption : LangString ["OPEN_TITLE"], wstring (directory), wxString(), wildcards, style); - - if (dialog.ShowModal() == wxID_OK) - { - if (!allowMultiple) - files.push_back (make_shared (dialog.GetPath())); - else - { - wxArrayString paths; - dialog.GetPaths (paths); - - foreach (const wxString &path, paths) - files.push_back (make_shared (path)); - } - } - - return files; - } - - FilePath GraphicUserInterface::SelectVolumeFile (wxWindow *parent, bool saveMode, const DirectoryPath &directory) const - { - list < pair > extensions; - extensions.push_back (make_pair (L"tc", LangString["TC_VOLUMES"])); - - FilePathList selFiles = Gui->SelectFiles (parent, LangString[saveMode ? "OPEN_NEW_VOLUME" : "OPEN_VOL_TITLE"], saveMode, false, extensions, directory); - - if (!selFiles.empty()) - return *selFiles.front(); - else - return FilePath(); - } - - void GraphicUserInterface::SetBackgroundMode (bool state) - { -#ifdef TC_MACOSX - // Hiding an iconized window on OS X apparently cannot be reversed - if (state && mMainFrame->IsIconized()) - mMainFrame->Iconize (false); -#endif - mMainFrame->Show (!state); - if (!state) - { - if (mMainFrame->IsIconized()) - mMainFrame->Iconize (false); - - mMainFrame->Raise(); - } - - BackgroundMode = state; - } - - void GraphicUserInterface::SetListCtrlColumnWidths (wxListCtrl *listCtrl, list columnWidthPermilles, bool hasVerticalScrollbar) const - { -#ifdef TC_MACOSX - hasVerticalScrollbar = true; -#endif - int listWidth = listCtrl->GetSize().GetWidth(); - int minListWidth = listCtrl->GetMinSize().GetWidth(); - if (minListWidth > listWidth) - listWidth = minListWidth; - - listWidth -= GetScrollbarWidth (listCtrl, !hasVerticalScrollbar); - - int col = 0; - int totalColWidth = 0; - foreach (int colWidth, columnWidthPermilles) - { - int width = listWidth * colWidth / 1000; - totalColWidth += width; - - if (col == listCtrl->GetColumnCount() - 1) - width += listWidth - totalColWidth; - - listCtrl->SetColumnWidth (col++, width); - } - } - - void GraphicUserInterface::SetListCtrlHeight (wxListCtrl *listCtrl, size_t rowCount) const - { - wxRect itemRect; - if (listCtrl->GetItemCount() == 0) - { - bool addedCols = false; - if (listCtrl->GetColumnCount() == 0) - { - listCtrl->InsertColumn (0, L".", wxLIST_FORMAT_LEFT, 1); - addedCols = true; - } - vector f; - f.push_back (L"."); - AppendToListCtrl (listCtrl, f); - listCtrl->GetItemRect (0, itemRect); - - if (addedCols) - listCtrl->ClearAll(); - else - listCtrl->DeleteAllItems(); - } - else - listCtrl->GetItemRect (0, itemRect); - - int headerHeight = itemRect.y; -#ifdef TC_WINDOWS - headerHeight += 4; -#elif defined (TC_MACOSX) - headerHeight += 7; -#elif defined (__WXGTK__) - headerHeight += 5; -#endif - int rowHeight = itemRect.height; -#ifdef TC_MACOSX - rowHeight += 1; -#endif - listCtrl->SetMinSize (wxSize (listCtrl->GetMinSize().GetWidth(), rowHeight * rowCount + headerHeight)); - } - - void GraphicUserInterface::SetListCtrlWidth (wxListCtrl *listCtrl, size_t charCount, bool hasVerticalScrollbar) const - { - int width = GetCharWidth (listCtrl) * charCount; -#ifdef TC_MACOSX - if (!hasVerticalScrollbar) - width += GetScrollbarWidth (listCtrl); -#endif - listCtrl->SetMinSize (wxSize (width, listCtrl->GetMinSize().GetHeight())); - } - - void GraphicUserInterface::ShowErrorTopMost (const wxString &message) const - { - ShowMessage (message, wxOK | wxICON_ERROR, true); - } - - void GraphicUserInterface::ShowInfoTopMost (const wxString &message) const - { - ShowMessage (message, wxOK | wxICON_INFORMATION, true); - } - - int GraphicUserInterface::ShowMessage (const wxString &message, long style, bool topMost) const - { - wxString caption = Application::GetName(); - wxString subMessage = message; - -#ifdef TC_MACOSX - size_t p = message.find (L"\n"); - if (p != string::npos) - { - // Divide message to caption and info message - caption = message.substr (0, p); - - p = message.find_first_not_of (L'\n', p); - if (p != string::npos) - subMessage = message.substr (p); - else - subMessage.clear(); - - if (subMessage.EndsWith (L"?")) - { - // Move question to caption - caption += wstring (L" "); - p = subMessage.find_last_of (L".\n"); - if (p != string::npos) - { - if (caption.EndsWith (L": ")) - caption[caption.size() - 2] = L'.'; - - caption += subMessage.substr (subMessage.find_first_not_of (L"\n ", p + 1)); - subMessage = subMessage.substr (0, p + 1); - } - else - { - caption += subMessage.substr (subMessage.find_first_not_of (L"\n")); - subMessage.clear(); - } - } - } - else if (message.size() < 160) - { - caption = message; - subMessage.clear(); - } - else - { - if (style & wxICON_EXCLAMATION) - caption = wxString (_("Warning")) + L':'; - else if (style & wxICON_ERROR || style & wxICON_HAND) - caption = wxString (_("Error")) + L':'; - else - caption.clear(); - } -#endif - if (topMost) - { - if (!IsActive()) - mMainFrame->RequestUserAttention (wxUSER_ATTENTION_ERROR); - - style |= wxSTAY_ON_TOP; - } - - return wxMessageBox (subMessage, caption, style, GetActiveWindow()); - } - - void GraphicUserInterface::ShowWarningTopMost (const wxString &message) const - { - ShowMessage (message, wxOK -#ifndef TC_MACOSX - | wxICON_EXCLAMATION -#endif - , true); - } - - void GraphicUserInterface::ThrowTextModeRequired () const - { - Gui->ShowError (_("This feature is currently supported only in text mode.")); - throw UserAbort (SRC_POS); - } - - bool GraphicUserInterface::UpdateListCtrlItem (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields) const - { - bool changed = false; - wxListItem item; - item.SetId (itemIndex); - item.SetText (L""); - - int col = 0; - foreach (wxString field, itemFields) - { - item.SetColumn (col++); - - if (!listCtrl->GetItem (item)) - throw ParameterIncorrect (SRC_POS); - - if (item.GetText() != field) - { - item.SetText (field); - listCtrl->SetItem (item); - changed = true; - } - } - return changed; - } - - void GraphicUserInterface::UserEnrichRandomPool (wxWindow *parent, shared_ptr hash) const - { - RandomNumberGenerator::Start(); - - if (hash) - RandomNumberGenerator::SetHash (hash); - - if (!RandomNumberGenerator::IsEnrichedByUser()) - { - RandomPoolEnrichmentDialog dialog (parent); - RandomNumberGenerator::SetEnrichedByUserStatus (dialog.ShowModal() == wxID_OK); - } - } - - void GraphicUserInterface::Yield () const - { -#ifndef TC_WINDOWS - wxSafeYield (nullptr, true); -#endif - } - - DEFINE_EVENT_TYPE (TC_EVENT_THREAD_EXITING); - - GraphicUserInterface *Gui = nullptr; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" + +#ifdef TC_UNIX +#include +#include +#include +#include +#include "Platform/Unix/Process.h" +#endif + +#include "Common/SecurityToken.h" +#include "Application.h" +#include "GraphicUserInterface.h" +#include "FatalErrorHandler.h" +#include "Forms/DeviceSelectionDialog.h" +#include "Forms/KeyfileGeneratorDialog.h" +#include "Forms/MainFrame.h" +#include "Forms/MountOptionsDialog.h" +#include "Forms/RandomPoolEnrichmentDialog.h" +#include "Forms/SecurityTokenKeyfilesDialog.h" + +namespace TrueCrypt +{ + GraphicUserInterface::GraphicUserInterface () : + ActiveFrame (nullptr), + BackgroundMode (false), + mMainFrame (nullptr) + { +#ifdef TC_UNIX + signal (SIGHUP, OnSignal); + signal (SIGINT, OnSignal); + signal (SIGQUIT, OnSignal); + signal (SIGTERM, OnSignal); +#endif + +#ifdef TC_MACOSX + wxApp::s_macHelpMenuTitleName = _("&Help"); +#endif + } + + GraphicUserInterface::~GraphicUserInterface () + { + try + { + if (RandomNumberGenerator::IsRunning()) + RandomNumberGenerator::Stop(); + } + catch (...) { } + + FatalErrorHandler::Deregister(); + +#ifdef TC_UNIX + signal (SIGHUP, SIG_DFL); + signal (SIGINT, SIG_DFL); + signal (SIGQUIT, SIG_DFL); + signal (SIGTERM, SIG_DFL); +#endif + } + + void GraphicUserInterface::AppendToListCtrl (wxListCtrl *listCtrl, const vector &itemFields, int imageIndex, void *itemDataPtr) const + { + InsertToListCtrl (listCtrl, listCtrl->GetItemCount(), itemFields, imageIndex, itemDataPtr); + } + + wxMenuItem *GraphicUserInterface::AppendToMenu (wxMenu &menu, const wxString &label, wxEvtHandler *handler, wxObjectEventFunction handlerFunction, int itemId) const + { + wxMenuItem *item = new wxMenuItem (&menu, itemId, label); + menu.Append (item); + + if (handler) + handler->Connect (item->GetId(), wxEVT_COMMAND_MENU_SELECTED, handlerFunction); + + return item; + } + + bool GraphicUserInterface::AskYesNo (const wxString &message, bool defaultYes, bool warning) const + { + return ShowMessage (message, + wxYES_NO | (warning ? wxICON_EXCLAMATION : wxICON_QUESTION) | (defaultYes ? wxYES_DEFAULT : wxNO_DEFAULT) + ) == wxYES; + } + + void GraphicUserInterface::AutoDismountVolumes (VolumeInfoList mountedVolumes, bool alwaysForce) + { + size_t mountedVolumeCount = Core->GetMountedVolumes().size(); + try + { + wxBusyCursor busy; + DismountVolumes (mountedVolumes, alwaysForce ? true : GetPreferences().ForceAutoDismount, false); + } + catch (...) { } + + if (Core->GetMountedVolumes().size() < mountedVolumeCount) + OnVolumesAutoDismounted(); + } + + void GraphicUserInterface::BackupVolumeHeaders (shared_ptr volumePath) const + { + wxWindow *parent = GetActiveWindow(); + + if (!volumePath || volumePath->IsEmpty()) + volumePath = make_shared (SelectVolumeFile (GetActiveWindow())); + + if (volumePath->IsEmpty()) + throw UserAbort (SRC_POS); + +#ifdef TC_WINDOWS + if (Core->IsVolumeMounted (*volumePath)) + { + ShowInfo ("DISMOUNT_FIRST"); + return; + } +#endif + +#ifdef TC_UNIX + // Temporarily take ownership of a device if the user is not an administrator + UserId origDeviceOwner ((uid_t) -1); + + if (!Core->HasAdminPrivileges() && volumePath->IsDevice()) + { + origDeviceOwner = FilesystemPath (wstring (*volumePath)).GetOwner(); + Core->SetFileOwner (*volumePath, UserId (getuid())); + } + + finally_do_arg2 (FilesystemPath, *volumePath, UserId, origDeviceOwner, + { + if (finally_arg2.SystemId != (uid_t) -1) + Core->SetFileOwner (finally_arg, finally_arg2); + }); +#endif + + ShowInfo ("EXTERNAL_VOL_HEADER_BAK_FIRST_INFO"); + + shared_ptr normalVolume; + shared_ptr hiddenVolume; + + MountOptions normalVolumeMountOptions; + MountOptions hiddenVolumeMountOptions; + + normalVolumeMountOptions.Path = volumePath; + hiddenVolumeMountOptions.Path = volumePath; + + VolumeType::Enum volumeType = VolumeType::Normal; + + // Open both types of volumes + while (true) + { + shared_ptr volume; + MountOptions *options = (volumeType == VolumeType::Hidden ? &hiddenVolumeMountOptions : &normalVolumeMountOptions); + + MountOptionsDialog dialog (parent, *options, + LangString[volumeType == VolumeType::Hidden ? "ENTER_HIDDEN_VOL_PASSWORD" : "ENTER_NORMAL_VOL_PASSWORD"], + true); + + while (!volume) + { + dialog.Hide(); + if (dialog.ShowModal() != wxID_OK) + return; + + try + { + wxBusyCursor busy; + volume = Core->OpenVolume ( + options->Path, + options->PreserveTimestamps, + options->Password, + options->Keyfiles, + options->Protection, + options->ProtectionPassword, + options->ProtectionKeyfiles, + true, + volumeType, + options->UseBackupHeaders + ); + } + catch (PasswordException &e) + { + ShowWarning (e); + } + } + + if (volumeType == VolumeType::Hidden) + hiddenVolume = volume; + else + normalVolume = volume; + + // Ask whether a hidden volume is present + if (volumeType == VolumeType::Normal) + { + wxArrayString choices; + choices.Add (LangString["VOLUME_CONTAINS_HIDDEN"]); + choices.Add (LangString["VOLUME_DOES_NOT_CONTAIN_HIDDEN"]); + + wxSingleChoiceDialog choiceDialog (parent, LangString["DOES_VOLUME_CONTAIN_HIDDEN"], Application::GetName(), choices); + choiceDialog.SetSize (wxSize (Gui->GetCharWidth (&choiceDialog) * 60, -1)); + choiceDialog.SetSelection (-1); + + if (choiceDialog.ShowModal() != wxID_OK) + return; + + switch (choiceDialog.GetSelection()) + { + case 0: + volumeType = VolumeType::Hidden; + continue; + + case 1: + break; + + default: + return; + } + } + + break; + } + + if (hiddenVolume) + { + if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV1Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV1Hidden)) + throw ParameterIncorrect (SRC_POS); + + if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV2Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV2Hidden)) + throw ParameterIncorrect (SRC_POS); + } + + // Ask user to select backup file path + wxString confirmMsg = LangString["CONFIRM_VOL_HEADER_BAK"]; + confirmMsg.Replace (L"%hs", L"%s"); + + if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true)) + return; + + FilePathList files = SelectFiles (parent, wxEmptyString, true, false); + if (files.empty()) + return; + + File backupFile; + backupFile.Open (*files.front(), File::CreateWrite); + + RandomNumberGenerator::Start(); + UserEnrichRandomPool (nullptr); + + { + wxBusyCursor busy; + + // Re-encrypt volume header + SecureBuffer newHeaderBuffer (normalVolume->GetLayout()->GetHeaderSize()); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Keyfiles); + + backupFile.Write (newHeaderBuffer); + + if (hiddenVolume) + { + // Re-encrypt hidden volume header + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Keyfiles); + } + else + { + // Store random data in place of hidden volume header + shared_ptr ea = normalVolume->GetEncryptionAlgorithm(); + Core->RandomizeEncryptionAlgorithmKey (ea); + ea->Encrypt (newHeaderBuffer); + } + + backupFile.Write (newHeaderBuffer); + } + + ShowWarning ("VOL_HEADER_BACKED_UP"); + } + + void GraphicUserInterface::BeginInteractiveBusyState (wxWindow *window) + { + static auto_ptr arrowWaitCursor; + + if (arrowWaitCursor.get() == nullptr) + arrowWaitCursor.reset (new wxCursor (wxCURSOR_ARROWWAIT)); + + window->SetCursor (*arrowWaitCursor); + } + + void GraphicUserInterface::CreateKeyfile (shared_ptr keyfilePath) const + { + try + { + KeyfileGeneratorDialog dialog (GetActiveWindow()); + dialog.ShowModal(); + } + catch (exception &e) + { + ShowError (e); + } + } + + void GraphicUserInterface::ClearListCtrlSelection (wxListCtrl *listCtrl) const + { + foreach (long item, GetListCtrlSelectedItems (listCtrl)) + listCtrl->SetItemState (item, 0, wxLIST_STATE_SELECTED); + } + + wxHyperlinkCtrl *GraphicUserInterface::CreateHyperlink (wxWindow *parent, const wxString &linkUrl, const wxString &linkText) const + { + wxHyperlinkCtrl *hyperlink = new wxHyperlinkCtrl (parent, wxID_ANY, linkText, linkUrl, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); + + wxColour color = wxSystemSettings::GetColour (wxSYS_COLOUR_WINDOWTEXT); + hyperlink->SetHoverColour (color); + hyperlink->SetNormalColour (color); + hyperlink->SetVisitedColour (color); + + return hyperlink; + } + + void GraphicUserInterface::DoShowError (const wxString &message) const + { + ShowMessage (message, wxOK | wxICON_ERROR); + } + + void GraphicUserInterface::DoShowInfo (const wxString &message) const + { + ShowMessage (message, wxOK | wxICON_INFORMATION); + } + + void GraphicUserInterface::DoShowString (const wxString &str) const + { + ShowMessage (str, wxOK); + } + + void GraphicUserInterface::DoShowWarning (const wxString &message) const + { + ShowMessage (message, wxOK +#ifndef TC_MACOSX + | wxICON_EXCLAMATION +#endif + ); + } + + void GraphicUserInterface::EndInteractiveBusyState (wxWindow *window) const + { + static auto_ptr arrowCursor; + + if (arrowCursor.get() == nullptr) + arrowCursor.reset (new wxCursor (wxCURSOR_ARROW)); + + window->SetCursor (*arrowCursor); + } + + wxTopLevelWindow *GraphicUserInterface::GetActiveWindow () const + { +#ifdef TC_WINDOWS + return dynamic_cast (wxGetActiveWindow()); +#endif + +#ifdef __WXGTK__ + // GTK for some reason unhides a hidden window if it is a parent of a new window + if (IsInBackgroundMode()) + return nullptr; +#endif + if (wxTopLevelWindows.size() == 1) + return dynamic_cast (wxTopLevelWindows.front()); + +#ifdef __WXGTK__ + wxLongLong startTime = wxGetLocalTimeMillis(); + do + { +#endif + foreach (wxWindow *window, wxTopLevelWindows) + { + wxTopLevelWindow *topLevelWin = dynamic_cast (window); + if (topLevelWin && topLevelWin->IsActive() && topLevelWin->IsShown()) + return topLevelWin; + } +#ifdef __WXGTK__ + Yield(); // GTK does a lot of operations asynchronously, which makes it prone to many race conditions + } while (wxGetLocalTimeMillis() - startTime < 500); +#endif + + return dynamic_cast (ActiveFrame ? ActiveFrame : GetTopWindow()); + } + + shared_ptr GraphicUserInterface::GetAdminPasswordRequestHandler () + { + struct AdminPasswordRequestHandler : public GetStringFunctor + { + virtual void operator() (string &passwordStr) + { + wxPasswordEntryDialog dialog (Gui->GetActiveWindow(), _("Enter your user password or administrator password:"), _("Administrator privileges required")); + + if (dialog.ShowModal() != wxID_OK) + throw UserAbort (SRC_POS); + + wstring wPassword (dialog.GetValue()); // A copy of the password is created here by wxWidgets, which cannot be erased + finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); + + StringConverter::ToSingle (wPassword, passwordStr); + } + }; + + return shared_ptr (new AdminPasswordRequestHandler); + } + + int GraphicUserInterface::GetCharHeight (wxWindow *window) const + { + int width; + int height; + window->GetTextExtent (L"a", &width, &height); + + if (height < 1) + return 14; + + return height; + } + + int GraphicUserInterface::GetCharWidth (wxWindow *window) const + { + int width; + int height; + window->GetTextExtent (L"a", &width, &height); + + if (width < 1) + return 7; + + return width; + } + + wxFont GraphicUserInterface::GetDefaultBoldFont (wxWindow *window) const + { + return wxFont ( +#ifdef __WXGTK__ + 9 +#elif defined(TC_MACOSX) + 13 +#else + 10 +#endif + * GetCharHeight (window) / 13, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, +#ifdef __WXGTK__ + wxFONTWEIGHT_BOLD, false); +#elif defined(TC_MACOSX) + wxFONTWEIGHT_NORMAL, false); +#else + wxFONTWEIGHT_BOLD, false, L"Arial"); +#endif + } + + list GraphicUserInterface::GetListCtrlSelectedItems (wxListCtrl *listCtrl) const + { + list selectedItems; + + long item = -1; + while ((item = listCtrl->GetNextItem (item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED)) != -1) + selectedItems.push_back (item); + + return selectedItems; + } + + wxString GraphicUserInterface::GetListCtrlSubItemText (wxListCtrl *listCtrl, long itemIndex, int columnIndex) const + { + wxListItem item; + item.SetId (itemIndex); + item.SetColumn (columnIndex); + item.SetText (L""); + + if (!listCtrl->GetItem (item)) + throw ParameterIncorrect (SRC_POS); + + return item.GetText(); + } + + int GraphicUserInterface::GetScrollbarWidth (wxWindow *window, bool noScrollBar) const + { + int offset = 0; +#ifdef TC_WINDOWS + offset = 4; +#elif defined (__WXGTK__) + offset = 7; +#elif defined (TC_MACOSX) + offset = 9; +#endif + if (noScrollBar) + return offset; + + int width = wxSystemSettings::GetMetric (wxSYS_VSCROLL_X, window); + + if (width == -1) + return 24; + + return width + offset; + } + + void GraphicUserInterface::InitSecurityTokenLibrary () const + { + if (Preferences.SecurityTokenModule.IsEmpty()) + throw_err (LangString ["NO_PKCS11_MODULE_SPECIFIED"]); + + struct PinRequestHandler : public GetPinFunctor + { + virtual void operator() (string &passwordStr) + { + if (Gui->GetPreferences().NonInteractive) + throw MissingArgument (SRC_POS); + + wxPasswordEntryDialog dialog (Gui->GetActiveWindow(), wxString::Format (LangString["ENTER_TOKEN_PASSWORD"], StringConverter::ToWide (passwordStr).c_str()), LangString["IDD_TOKEN_PASSWORD"]); + dialog.SetSize (wxSize (Gui->GetCharWidth (&dialog) * 50, -1)); + + if (dialog.ShowModal() != wxID_OK) + throw UserAbort (SRC_POS); + + wstring wPassword (dialog.GetValue()); // A copy of the password is created here by wxWidgets, which cannot be erased + finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); + + StringConverter::ToSingle (wPassword, passwordStr); + } + }; + + struct WarningHandler : public SendExceptionFunctor + { + virtual void operator() (const Exception &e) + { + Gui->ShowError (e); + } + }; + + try + { + SecurityToken::InitLibrary (Preferences.SecurityTokenModule, auto_ptr (new PinRequestHandler), auto_ptr (new WarningHandler)); + } + catch (Exception &e) + { + ShowError (e); + throw_err (LangString ["PKCS11_MODULE_INIT_FAILED"]); + } + } + + void GraphicUserInterface::InsertToListCtrl (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields, int imageIndex, void *itemDataPtr) const + { + wxListItem item; + item.SetData (itemDataPtr); + item.SetId (itemIndex); + item.SetImage (imageIndex); + int col = 0; + foreach (wxString field, itemFields) + { + item.SetColumn (col++); + item.SetText (field); + if (col == 1) + { + throw_sys_if (listCtrl->InsertItem (item) == -1); + item.SetImage (-1); + continue; + } + + listCtrl->SetItem (item); + } + } + + bool GraphicUserInterface::IsTheOnlyTopLevelWindow (const wxWindow *window) const + { + foreach (wxWindow *w, wxTopLevelWindows) + { + if (w != window + && (dynamic_cast (w) || dynamic_cast (w)) + && StringConverter::GetTypeName (typeid (*w)).find ("wxTaskBarIcon") == string::npos) + { + return false; + } + } + return true; + } + + void GraphicUserInterface::ListSecurityTokenKeyfiles () const + { + SecurityTokenKeyfilesDialog dialog (nullptr); + dialog.ShowModal(); + } + +#ifdef TC_MACOSX + void GraphicUserInterface::MacOpenFile (const wxString &fileName) + { + OpenVolumeSystemRequestEventArgs eventArgs (fileName); + OpenVolumeSystemRequestEvent.Raise (eventArgs); + } +#endif + + void GraphicUserInterface::MoveListCtrlItem (wxListCtrl *listCtrl, long itemIndex, long newItemIndex) const + { + if (itemIndex == newItemIndex || newItemIndex < 0 + || (newItemIndex > itemIndex && newItemIndex == listCtrl->GetItemCount())) + return; + + wxListItem item; + item.SetId (itemIndex); + item.SetData ((void *) nullptr); + item.SetImage (-1); + + if (!listCtrl->GetItem (item)) + throw ParameterIncorrect (SRC_POS); + + int itemState = listCtrl->GetItemState (itemIndex, wxLIST_STATE_SELECTED); + + vector itemFields (listCtrl->GetColumnCount()); + for (size_t col = 0; col < itemFields.size(); ++col) + { + itemFields[col] = GetListCtrlSubItemText (listCtrl, itemIndex, col); + } + + listCtrl->DeleteItem (itemIndex); + + if (newItemIndex > listCtrl->GetItemCount() - 1) + AppendToListCtrl (listCtrl, itemFields, item.GetImage(), (void *) item.GetData()); + else + InsertToListCtrl (listCtrl, newItemIndex, itemFields, item.GetImage(), (void *) item.GetData()); + + item.SetId (newItemIndex); + listCtrl->SetItemState (item, itemState, wxLIST_STATE_SELECTED); + } + + VolumeInfoList GraphicUserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const + { + MountOptionsDialog dialog (GetTopWindow(), options); + while (true) + { + options.Path.reset(); + + if (dialog.ShowModal() != wxID_OK) + return VolumeInfoList(); + + VolumeInfoList mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (options); + + if (!mountedVolumes.empty()) + return mountedVolumes; + } + } + + shared_ptr GraphicUserInterface::MountVolume (MountOptions &options) const + { + CheckRequirementsForMountingVolume(); + + shared_ptr volume; + + if (!options.Path || options.Path->IsEmpty()) + options.Path = make_shared (SelectVolumeFile (GetActiveWindow())); + + if (options.Path->IsEmpty()) + throw UserAbort (SRC_POS); + + if (Core->IsVolumeMounted (*options.Path)) + { + ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (*options.Path))); + return volume; + } + + try + { + if ((!options.Password || options.Password->IsEmpty()) + && (!options.Keyfiles || options.Keyfiles->empty()) + && !Core->IsPasswordCacheEmpty()) + { + // Cached password + try + { + wxBusyCursor busy; + return UserInterface::MountVolume (options); + } + catch (PasswordException&) { } + } + + if ((options.Password && !options.Password->IsEmpty()) + || (options.Keyfiles && !options.Keyfiles->empty())) + { + try + { + wxBusyCursor busy; + return UserInterface::MountVolume (options); + } + catch (PasswordException&) { } + } + + VolumePassword password; + KeyfileList keyfiles; + + MountOptionsDialog dialog (GetTopWindow(), options); + int incorrectPasswordCount = 0; + + while (!volume) + { + dialog.Hide(); + if (dialog.ShowModal() != wxID_OK) + return volume; + + try + { + wxBusyCursor busy; + volume = UserInterface::MountVolume (options); + } + catch (PasswordIncorrect &e) + { + if (++incorrectPasswordCount > 2 && !options.UseBackupHeaders) + { + // Try to mount the volume using the backup header + options.UseBackupHeaders = true; + + try + { + volume = UserInterface::MountVolume (options); + ShowWarning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); + } + catch (...) + { + options.UseBackupHeaders = false; + ShowWarning (e); + } + } + else + ShowWarning (e); + } + catch (PasswordException &e) + { + ShowWarning (e); + } + } + } + catch (exception &e) + { + ShowError (e); + } + +#ifdef TC_LINUX + if (volume && !Preferences.NonInteractive && !Preferences.DisableKernelEncryptionModeWarning + && volume->EncryptionModeName != L"XTS" + && (volume->EncryptionModeName != L"LRW" || volume->EncryptionAlgorithmMinBlockSize != 16 || volume->EncryptionAlgorithmKeySize != 32) + && !AskYesNo (LangString["ENCRYPTION_MODE_NOT_SUPPORTED_BY_KERNEL"] + _("\n\nDo you want to show this message next time you mount such a volume?"), true, true)) + { + UserPreferences prefs = GetPreferences(); + prefs.DisableKernelEncryptionModeWarning = true; + Gui->SetPreferences (prefs); + } +#endif + return volume; + } + + void GraphicUserInterface::OnAutoDismountAllEvent () + { + VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); + + if (!mountedVolumes.empty()) + { + wxBusyCursor busy; + AutoDismountVolumes (mountedVolumes); + } + } + + bool GraphicUserInterface::OnInit () + { + Gui = this; + InterfaceType = UserInterfaceType::Graphic; + try + { + FatalErrorHandler::Register(); + Init(); + + if (ProcessCommandLine() && !CmdLine->StartBackgroundTask) + { + Yield(); + Application::SetExitCode (0); + return false; + } + + // Check if another instance is already running and bring its windows to foreground +#ifndef TC_MACOSX +#ifdef TC_WINDOWS + const wxString serverName = Application::GetName() + L"-" + wxGetUserId(); + class Connection : public wxDDEConnection + { + public: + Connection () { } + + bool OnExecute (const wxString& topic, wxChar *data, int size, wxIPCFormat format) + { + if (topic == L"raise") + { + if (Gui->IsInBackgroundMode()) + Gui->SetBackgroundMode (false); + + Gui->mMainFrame->Show (true); + Gui->mMainFrame->Raise (); + return true; + } + return false; + } + }; +#endif + + SingleInstanceChecker.reset (new wxSingleInstanceChecker (wxString (L".") + Application::GetName() + L"-lock-" + wxGetUserId())); + + if (SingleInstanceChecker->IsAnotherRunning()) + { +#ifdef TC_WINDOWS + class Client: public wxDDEClient + { + public: + Client() {}; + wxConnectionBase *OnMakeConnection () { return new Connection; } + }; + + auto_ptr client (new Client); + auto_ptr connection (client->MakeConnection (L"localhost", serverName, L"raise")); + + if (connection.get() && connection->Execute (nullptr)) + { + connection->Disconnect(); + Application::SetExitCode (0); + return false; + } +#endif + wxLog::FlushActive(); + Application::SetExitCode (1); + Gui->ShowInfo (_("TrueCrypt is already running.")); + return false; + } + +#ifdef TC_WINDOWS + class Server : public wxDDEServer + { + public: + wxConnectionBase *OnAcceptConnection (const wxString &topic) + { + if (topic == L"raise") + return new Connection; + return nullptr; + } + }; + + DDEServer.reset (new Server); + if (!DDEServer->Create (serverName)) + wxLog::FlushActive(); +#endif +#endif // !TC_MACOSX + + Connect (wxEVT_END_SESSION, wxCloseEventHandler (GraphicUserInterface::OnEndSession)); +#ifdef wxHAS_POWER_EVENTS + Gui->Connect (wxEVT_POWER_SUSPENDING, wxPowerEventHandler (GraphicUserInterface::OnPowerSuspending)); +#endif + + mMainFrame = new MainFrame (nullptr); + + if (CmdLine->StartBackgroundTask) + { + UserPreferences prefs = GetPreferences (); + prefs.BackgroundTaskEnabled = true; + SetPreferences (prefs); + mMainFrame->Close(); + } + else + { + mMainFrame->Show (true); + } + + SetTopWindow (mMainFrame); + } + catch (exception &e) + { + ShowError (e); + return false; + } + + return true; + } + + void GraphicUserInterface::OnLogOff () + { + VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); + if (GetPreferences().BackgroundTaskEnabled && GetPreferences().DismountOnLogOff + && !mountedVolumes.empty()) + { + wxLongLong startTime = wxGetLocalTimeMillis(); + bool timeOver = false; + + wxBusyCursor busy; + while (!timeOver && !mountedVolumes.empty()) + { + try + { + timeOver = (wxGetLocalTimeMillis() - startTime >= 4000); + + DismountVolumes (mountedVolumes, !timeOver ? false : GetPreferences().ForceAutoDismount, timeOver); + OnVolumesAutoDismounted(); + + break; + } + catch (UserAbort&) + { + return; + } + catch (...) + { + Thread::Sleep (500); + } + + VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); + } + + } + } + +#ifdef wxHAS_POWER_EVENTS + void GraphicUserInterface::OnPowerSuspending (wxPowerEvent& event) + { + size_t volumeCount = Core->GetMountedVolumes().size(); + if (GetPreferences().BackgroundTaskEnabled && GetPreferences().DismountOnPowerSaving && volumeCount > 0) + { + OnAutoDismountAllEvent(); + + if (Core->GetMountedVolumes().size() < volumeCount) + ShowInfoTopMost (LangString["MOUNTED_VOLUMES_AUTO_DISMOUNTED"]); + } + } +#endif + + void GraphicUserInterface::OnSignal (int signal) + { +#ifdef TC_UNIX + Gui->SingleInstanceChecker.reset(); + _exit (1); +#endif + } + + void GraphicUserInterface::OnVolumesAutoDismounted () + { + if (GetPreferences().WipeCacheOnAutoDismount) + { + Core->WipePasswordCache(); + SecurityToken::CloseAllSessions(); + } + } + + void GraphicUserInterface::OpenDocument (wxWindow *parent, const wxFileName &document) + { + if (!document.FileExists()) + throw ParameterIncorrect (SRC_POS); + +#ifdef TC_WINDOWS + + if (int (ShellExecute (GetTopWindow() ? static_cast (GetTopWindow()->GetHandle()) : nullptr, L"open", + document.GetFullPath().c_str(), nullptr, nullptr, SW_SHOWNORMAL)) >= 32) + return; + +#else + wxMimeTypesManager mimeMgr; + wxFileType *fileType = mimeMgr.GetFileTypeFromExtension (document.GetExt()); + if (fileType) + { + try + { +#ifdef TC_MACOSX + if (wxExecute (fileType->GetOpenCommand (document.GetFullPath())) != 0) + return; +#else + if (wxExecute (fileType->GetOpenCommand (L"\"" + document.GetFullPath() + L"\"")) != 0) + return; +#endif + } + catch (TimeOut&) { } + } +#endif + } + + wxString GraphicUserInterface::GetHomepageLinkURL (const wxString &linkId, bool secure, const wxString &extraVars) const + { + wxString url = wxString (StringConverter::ToWide (secure ? TC_APPLINK_SECURE : TC_APPLINK)) + L"&dest=" + linkId; + wxString os, osVersion, architecture; + +#ifdef TC_WINDOWS + + os = L"Windows"; + +#elif defined (TC_UNIX) + struct utsname unameData; + if (uname (&unameData) != -1) + { + os = StringConverter::ToWide (unameData.sysname); + osVersion = StringConverter::ToWide (unameData.release); + architecture = StringConverter::ToWide (unameData.machine); + + if (os == L"Darwin") + os = L"MacOSX"; + } + else + os = L"Unknown"; +#else + os = L"Unknown"; +#endif + + os.Replace (L" ", L"-"); + url += L"&os="; + url += os; + + osVersion.Replace (L" ", L"-"); + url += L"&osver="; + url += osVersion; + + architecture.Replace (L" ", L"-"); + url += L"&arch="; + url += architecture; + + if (!extraVars.empty()) + { + url += L"&"; + url += extraVars; + } + + return url; + } + + void GraphicUserInterface::OpenHomepageLink (wxWindow *parent, const wxString &linkId, const wxString &extraVars) + { + wxString url; + + BeginInteractiveBusyState (parent); + wxLaunchDefaultBrowser (GetHomepageLinkURL (linkId, false, extraVars), wxBROWSER_NEW_WINDOW); + Thread::Sleep (200); + EndInteractiveBusyState (parent); + } + + void GraphicUserInterface::OpenOnlineHelp (wxWindow *parent) + { + OpenHomepageLink (parent, L"help"); + } + + void GraphicUserInterface::OpenUserGuide (wxWindow *parent) + { + try + { + wxString docPath = wstring (Application::GetExecutableDirectory()); + +#ifdef TC_RESOURCE_DIR + docPath = StringConverter::ToWide (string (TC_TO_STRING (TC_RESOURCE_DIR)) + "/doc/TrueCrypt User Guide.pdf"); +#elif defined (TC_WINDOWS) + docPath += L"\\TrueCrypt User Guide.pdf"; +#elif defined (TC_MACOSX) + docPath += L"/../Resources/TrueCrypt User Guide.pdf"; +#elif defined (TC_UNIX) + docPath = L"/usr/share/truecrypt/doc/TrueCrypt User Guide.pdf"; +#else +# error TC_RESOURCE_DIR undefined +#endif + + wxFileName docFile = docPath; + docFile.Normalize(); + + try + { + Gui->OpenDocument (parent, docFile); + } + catch (...) + { + if (Gui->AskYesNo (LangString ["HELP_READER_ERROR"], true)) + OpenOnlineHelp (parent); + } + } + catch (Exception &e) + { + Gui->ShowError (e); + } + } + + void GraphicUserInterface::RestoreVolumeHeaders (shared_ptr volumePath) const + { + wxWindow *parent = GetActiveWindow(); + + if (!volumePath || volumePath->IsEmpty()) + volumePath = make_shared (SelectVolumeFile (GetActiveWindow())); + + if (volumePath->IsEmpty()) + throw UserAbort (SRC_POS); + +#ifdef TC_WINDOWS + if (Core->IsVolumeMounted (*volumePath)) + { + ShowInfo ("DISMOUNT_FIRST"); + return; + } +#endif + +#ifdef TC_UNIX + // Temporarily take ownership of a device if the user is not an administrator + UserId origDeviceOwner ((uid_t) -1); + + if (!Core->HasAdminPrivileges() && volumePath->IsDevice()) + { + origDeviceOwner = FilesystemPath (wstring (*volumePath)).GetOwner(); + Core->SetFileOwner (*volumePath, UserId (getuid())); + } + + finally_do_arg2 (FilesystemPath, *volumePath, UserId, origDeviceOwner, + { + if (finally_arg2.SystemId != (uid_t) -1) + Core->SetFileOwner (finally_arg, finally_arg2); + }); +#endif + + // Ask whether to restore internal or external backup + bool restoreInternalBackup; + wxArrayString choices; + choices.Add (LangString["HEADER_RESTORE_INTERNAL"]); + choices.Add (LangString["HEADER_RESTORE_EXTERNAL"]); + + wxSingleChoiceDialog choiceDialog (parent, LangString["HEADER_RESTORE_EXTERNAL_INTERNAL"], Application::GetName(), choices); + choiceDialog.SetSize (wxSize (Gui->GetCharWidth (&choiceDialog) * 80, -1)); + choiceDialog.SetSelection (-1); + + if (choiceDialog.ShowModal() != wxID_OK) + return; + + switch (choiceDialog.GetSelection()) + { + case 0: + restoreInternalBackup = true; + break; + + case 1: + restoreInternalBackup = false; + break; + + default: + return; + } + + if (restoreInternalBackup) + { + // Restore header from the internal backup + shared_ptr volume; + MountOptions options; + options.Path = volumePath; + + MountOptionsDialog dialog (parent, options, wxEmptyString, true); + + while (!volume) + { + dialog.Hide(); + if (dialog.ShowModal() != wxID_OK) + return; + + try + { + wxBusyCursor busy; + volume = Core->OpenVolume ( + options.Path, + options.PreserveTimestamps, + options.Password, + options.Keyfiles, + options.Protection, + options.ProtectionPassword, + options.ProtectionKeyfiles, + options.SharedAccessAllowed, + VolumeType::Unknown, + true + ); + } + catch (PasswordException &e) + { + ShowWarning (e); + } + } + + shared_ptr layout = volume->GetLayout(); + if (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden)) + { + ShowError ("VOLUME_HAS_NO_BACKUP_HEADER"); + return; + } + + RandomNumberGenerator::Start(); + UserEnrichRandomPool (nullptr); + + // Re-encrypt volume header + SecureBuffer newHeaderBuffer (volume->GetLayout()->GetHeaderSize()); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Keyfiles); + + // Write volume header + int headerOffset = volume->GetLayout()->GetHeaderOffset(); + shared_ptr volumeFile = volume->GetFile(); + + if (headerOffset >= 0) + volumeFile->SeekAt (headerOffset); + else + volumeFile->SeekEnd (headerOffset); + + volumeFile->Write (newHeaderBuffer); + } + else + { + // Restore header from an external backup + + wxString confirmMsg = LangString["CONFIRM_VOL_HEADER_RESTORE"]; + confirmMsg.Replace (L"%hs", L"%s"); + + if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true, true)) + return; + + FilePathList files = SelectFiles (parent, wxEmptyString, false, false); + if (files.empty()) + return; + + File backupFile; + backupFile.Open (*files.front(), File::OpenRead); + + uint64 headerSize; + bool legacyBackup; + + // Determine the format of the backup file + switch (backupFile.Length()) + { + case TC_VOLUME_HEADER_GROUP_SIZE: + headerSize = TC_VOLUME_HEADER_SIZE; + legacyBackup = false; + break; + + case TC_VOLUME_HEADER_SIZE_LEGACY * 2: + headerSize = TC_VOLUME_HEADER_SIZE_LEGACY; + legacyBackup = true; + break; + + default: + ShowError ("HEADER_BACKUP_SIZE_INCORRECT"); + return; + } + + // Open the volume header stored in the backup file + MountOptions options; + + MountOptionsDialog dialog (parent, options, LangString["ENTER_HEADER_BACKUP_PASSWORD"], true); + shared_ptr decryptedLayout; + + while (!decryptedLayout) + { + dialog.Hide(); + if (dialog.ShowModal() != wxID_OK) + return; + + try + { + wxBusyCursor busy; + + // Test volume layouts + foreach (shared_ptr layout, VolumeLayout::GetAvailableLayouts ()) + { + if (layout->HasDriveHeader()) + continue; + + if (!legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden))) + continue; + + if (legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV2Normal) || typeid (*layout) == typeid (VolumeLayoutV2Hidden))) + continue; + + SecureBuffer headerBuffer (layout->GetHeaderSize()); + backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); + + // Decrypt header + shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); + if (layout->GetHeader()->Decrypt (headerBuffer, *passwordKey, layout->GetSupportedKeyDerivationFunctions(), layout->GetSupportedEncryptionAlgorithms(), layout->GetSupportedEncryptionModes())) + { + decryptedLayout = layout; + break; + } + } + + if (!decryptedLayout) + throw PasswordIncorrect (SRC_POS); + } + catch (PasswordException &e) + { + ShowWarning (e); + } + } + + File volumeFile; + volumeFile.Open (*volumePath, File::OpenReadWrite, File::ShareNone, File::PreserveTimestamps); + + RandomNumberGenerator::Start(); + UserEnrichRandomPool (nullptr); + + // Re-encrypt volume header + SecureBuffer newHeaderBuffer (decryptedLayout->GetHeaderSize()); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); + + // Write volume header + int headerOffset = decryptedLayout->GetHeaderOffset(); + if (headerOffset >= 0) + volumeFile.SeekAt (headerOffset); + else + volumeFile.SeekEnd (headerOffset); + + volumeFile.Write (newHeaderBuffer); + + if (decryptedLayout->HasBackupHeader()) + { + // Re-encrypt backup volume header + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); + + // Write backup volume header + headerOffset = decryptedLayout->GetBackupHeaderOffset(); + if (headerOffset >= 0) + volumeFile.SeekAt (headerOffset); + else + volumeFile.SeekEnd (headerOffset); + + volumeFile.Write (newHeaderBuffer); + } + } + + ShowInfo ("VOL_HEADER_RESTORED"); + } + + DevicePath GraphicUserInterface::SelectDevice (wxWindow *parent) const + { + try + { + DeviceSelectionDialog dialog (parent); + if (dialog.ShowModal() == wxID_OK) + { + return dialog.SelectedDevice.Path; + } + } + catch (exception &e) + { + Gui->ShowError (e); + } + + return DevicePath(); + } + + DirectoryPath GraphicUserInterface::SelectDirectory (wxWindow *parent, const wxString &message, bool existingOnly) const + { + return DirectoryPath (::wxDirSelector (!message.empty() ? message : +#ifdef __WXGTK__ + wxDirSelectorPromptStr, +#else + L"", +#endif + L"", wxDD_DEFAULT_STYLE | (existingOnly ? wxDD_DIR_MUST_EXIST : 0), wxDefaultPosition, parent)); + } + + FilePathList GraphicUserInterface::SelectFiles (wxWindow *parent, const wxString &caption, bool saveMode, bool allowMultiple, const list < pair > &fileExtensions, const DirectoryPath &directory) const + { + FilePathList files; + + long style; + if (saveMode) + style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT; + else + style = wxFD_OPEN | wxFD_FILE_MUST_EXIST | (allowMultiple ? wxFD_MULTIPLE : 0); + + wxString wildcards = L"*.*"; + +#ifndef __WXGTK__ + if (!fileExtensions.empty()) +#endif + { + wildcards = LangString["ALL_FILES"] + +#ifdef TC_WINDOWS + L" (*.*)|*.*"; +#else + L"|*"; +#endif + typedef pair StringPair; + foreach (StringPair p, fileExtensions) + { + if (p.first == L"*" || p.first == L"*.*") + { + wildcards += L"|" + wildcards.substr (0, wildcards.find (L"*|") + 1); + wildcards = wildcards.substr (wildcards.find (L"*|") + 2); + continue; + } + + wildcards += wxString (L"|") + p.second + L" (*." + p.first + L")|*." + p.first; + } + } + + wxFileDialog dialog (parent, !caption.empty() ? caption : LangString ["OPEN_TITLE"], wstring (directory), wxString(), wildcards, style); + + if (dialog.ShowModal() == wxID_OK) + { + if (!allowMultiple) + files.push_back (make_shared (dialog.GetPath())); + else + { + wxArrayString paths; + dialog.GetPaths (paths); + + foreach (const wxString &path, paths) + files.push_back (make_shared (path)); + } + } + + return files; + } + + FilePath GraphicUserInterface::SelectVolumeFile (wxWindow *parent, bool saveMode, const DirectoryPath &directory) const + { + list < pair > extensions; + extensions.push_back (make_pair (L"tc", LangString["TC_VOLUMES"])); + + FilePathList selFiles = Gui->SelectFiles (parent, LangString[saveMode ? "OPEN_NEW_VOLUME" : "OPEN_VOL_TITLE"], saveMode, false, extensions, directory); + + if (!selFiles.empty()) + return *selFiles.front(); + else + return FilePath(); + } + + void GraphicUserInterface::SetBackgroundMode (bool state) + { +#ifdef TC_MACOSX + // Hiding an iconized window on OS X apparently cannot be reversed + if (state && mMainFrame->IsIconized()) + mMainFrame->Iconize (false); +#endif + mMainFrame->Show (!state); + if (!state) + { + if (mMainFrame->IsIconized()) + mMainFrame->Iconize (false); + + mMainFrame->Raise(); + } + + BackgroundMode = state; + } + + void GraphicUserInterface::SetListCtrlColumnWidths (wxListCtrl *listCtrl, list columnWidthPermilles, bool hasVerticalScrollbar) const + { +#ifdef TC_MACOSX + hasVerticalScrollbar = true; +#endif + int listWidth = listCtrl->GetSize().GetWidth(); + int minListWidth = listCtrl->GetMinSize().GetWidth(); + if (minListWidth > listWidth) + listWidth = minListWidth; + + listWidth -= GetScrollbarWidth (listCtrl, !hasVerticalScrollbar); + + int col = 0; + int totalColWidth = 0; + foreach (int colWidth, columnWidthPermilles) + { + int width = listWidth * colWidth / 1000; + totalColWidth += width; + + if (col == listCtrl->GetColumnCount() - 1) + width += listWidth - totalColWidth; + + listCtrl->SetColumnWidth (col++, width); + } + } + + void GraphicUserInterface::SetListCtrlHeight (wxListCtrl *listCtrl, size_t rowCount) const + { + wxRect itemRect; + if (listCtrl->GetItemCount() == 0) + { + bool addedCols = false; + if (listCtrl->GetColumnCount() == 0) + { + listCtrl->InsertColumn (0, L".", wxLIST_FORMAT_LEFT, 1); + addedCols = true; + } + vector f; + f.push_back (L"."); + AppendToListCtrl (listCtrl, f); + listCtrl->GetItemRect (0, itemRect); + + if (addedCols) + listCtrl->ClearAll(); + else + listCtrl->DeleteAllItems(); + } + else + listCtrl->GetItemRect (0, itemRect); + + int headerHeight = itemRect.y; +#ifdef TC_WINDOWS + headerHeight += 4; +#elif defined (TC_MACOSX) + headerHeight += 7; +#elif defined (__WXGTK__) + headerHeight += 5; +#endif + int rowHeight = itemRect.height; +#ifdef TC_MACOSX + rowHeight += 1; +#endif + listCtrl->SetMinSize (wxSize (listCtrl->GetMinSize().GetWidth(), rowHeight * rowCount + headerHeight)); + } + + void GraphicUserInterface::SetListCtrlWidth (wxListCtrl *listCtrl, size_t charCount, bool hasVerticalScrollbar) const + { + int width = GetCharWidth (listCtrl) * charCount; +#ifdef TC_MACOSX + if (!hasVerticalScrollbar) + width += GetScrollbarWidth (listCtrl); +#endif + listCtrl->SetMinSize (wxSize (width, listCtrl->GetMinSize().GetHeight())); + } + + void GraphicUserInterface::ShowErrorTopMost (const wxString &message) const + { + ShowMessage (message, wxOK | wxICON_ERROR, true); + } + + void GraphicUserInterface::ShowInfoTopMost (const wxString &message) const + { + ShowMessage (message, wxOK | wxICON_INFORMATION, true); + } + + int GraphicUserInterface::ShowMessage (const wxString &message, long style, bool topMost) const + { + wxString caption = Application::GetName(); + wxString subMessage = message; + +#ifdef TC_MACOSX + size_t p = message.find (L"\n"); + if (p != string::npos) + { + // Divide message to caption and info message + caption = message.substr (0, p); + + p = message.find_first_not_of (L'\n', p); + if (p != string::npos) + subMessage = message.substr (p); + else + subMessage.clear(); + + if (subMessage.EndsWith (L"?")) + { + // Move question to caption + caption += wstring (L" "); + p = subMessage.find_last_of (L".\n"); + if (p != string::npos) + { + if (caption.EndsWith (L": ")) + caption[caption.size() - 2] = L'.'; + + caption += subMessage.substr (subMessage.find_first_not_of (L"\n ", p + 1)); + subMessage = subMessage.substr (0, p + 1); + } + else + { + caption += subMessage.substr (subMessage.find_first_not_of (L"\n")); + subMessage.clear(); + } + } + } + else if (message.size() < 160) + { + caption = message; + subMessage.clear(); + } + else + { + if (style & wxICON_EXCLAMATION) + caption = wxString (_("Warning")) + L':'; + else if (style & wxICON_ERROR || style & wxICON_HAND) + caption = wxString (_("Error")) + L':'; + else + caption.clear(); + } +#endif + if (topMost) + { + if (!IsActive()) + mMainFrame->RequestUserAttention (wxUSER_ATTENTION_ERROR); + + style |= wxSTAY_ON_TOP; + } + + return wxMessageBox (subMessage, caption, style, GetActiveWindow()); + } + + void GraphicUserInterface::ShowWarningTopMost (const wxString &message) const + { + ShowMessage (message, wxOK +#ifndef TC_MACOSX + | wxICON_EXCLAMATION +#endif + , true); + } + + void GraphicUserInterface::ThrowTextModeRequired () const + { + Gui->ShowError (_("This feature is currently supported only in text mode.")); + throw UserAbort (SRC_POS); + } + + bool GraphicUserInterface::UpdateListCtrlItem (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields) const + { + bool changed = false; + wxListItem item; + item.SetId (itemIndex); + item.SetText (L""); + + int col = 0; + foreach (wxString field, itemFields) + { + item.SetColumn (col++); + + if (!listCtrl->GetItem (item)) + throw ParameterIncorrect (SRC_POS); + + if (item.GetText() != field) + { + item.SetText (field); + listCtrl->SetItem (item); + changed = true; + } + } + return changed; + } + + void GraphicUserInterface::UserEnrichRandomPool (wxWindow *parent, shared_ptr hash) const + { + RandomNumberGenerator::Start(); + + if (hash) + RandomNumberGenerator::SetHash (hash); + + if (!RandomNumberGenerator::IsEnrichedByUser()) + { + RandomPoolEnrichmentDialog dialog (parent); + RandomNumberGenerator::SetEnrichedByUserStatus (dialog.ShowModal() == wxID_OK); + } + } + + void GraphicUserInterface::Yield () const + { +#ifndef TC_WINDOWS + wxSafeYield (nullptr, true); +#endif + } + + DEFINE_EVENT_TYPE (TC_EVENT_THREAD_EXITING); + + GraphicUserInterface *Gui = nullptr; +} diff --git a/Main/GraphicUserInterface.h b/Main/GraphicUserInterface.h index eef4bcf..2acd508 100644 --- a/Main/GraphicUserInterface.h +++ b/Main/GraphicUserInterface.h @@ -1,159 +1,160 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_GraphicUserInterface -#define TC_HEADER_Main_GraphicUserInterface - -#include "System.h" -#include -#include "Main.h" -#include "UserInterface.h" - -namespace TrueCrypt -{ - class GraphicUserInterface : public UserInterface - { - public: - GraphicUserInterface (); - virtual ~GraphicUserInterface (); - - virtual void AppendToListCtrl (wxListCtrl *listCtrl, const vector &itemFields, int imageIndex = -1, void *itemDataPtr = nullptr) const; - virtual wxMenuItem *AppendToMenu (wxMenu &menu, const wxString &label, wxEvtHandler *handler = nullptr, wxObjectEventFunction handlerFunction = nullptr, int itemId = wxID_ANY) const; - virtual bool AskYesNo (const wxString &message, bool defaultYes = false, bool warning = false) const; - virtual void AutoDismountVolumes (VolumeInfoList mountedVolumes, bool alwaysForce = true); - virtual void BackupVolumeHeaders (shared_ptr volumePath) const; - virtual void BeginBusyState () const { wxBeginBusyCursor(); } - virtual void BeginInteractiveBusyState (wxWindow *window); - virtual void ChangePassword (shared_ptr volumePath = shared_ptr (), shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr (), shared_ptr newHash = shared_ptr ()) const { ThrowTextModeRequired(); } - wxHyperlinkCtrl *CreateHyperlink (wxWindow *parent, const wxString &linkUrl, const wxString &linkText) const; - virtual void CreateKeyfile (shared_ptr keyfilePath = shared_ptr ()) const; - virtual void CreateVolume (shared_ptr options) const { ThrowTextModeRequired(); } - virtual void ClearListCtrlSelection (wxListCtrl *listCtrl) const; - virtual void DeleteSecurityTokenKeyfiles () const { ThrowTextModeRequired(); } - virtual void DoShowError (const wxString &message) const; - virtual void DoShowInfo (const wxString &message) const; - virtual void DoShowString (const wxString &str) const; - virtual void DoShowWarning (const wxString &message) const; - virtual void EndBusyState () const { wxEndBusyCursor(); } - virtual void EndInteractiveBusyState (wxWindow *window) const; - virtual wxTopLevelWindow *GetActiveWindow () const; - virtual shared_ptr GetAdminPasswordRequestHandler (); - virtual int GetCharHeight (wxWindow *window) const; - virtual int GetCharWidth (wxWindow *window) const; - virtual int GetDefaultBorderSize () const { return 5; } - virtual wxFont GetDefaultBoldFont (wxWindow *window) const; - virtual wxString GetHomepageLinkURL (const wxString &linkId, bool secure = false, const wxString &extraVars = wxEmptyString) const; - virtual wxFrame *GetMainFrame () const { return mMainFrame; } - virtual int GetScrollbarWidth (wxWindow *window, bool noScrollBar = false) const; - virtual list GetListCtrlSelectedItems (wxListCtrl *listCtrl) const; - virtual wxString GetListCtrlSubItemText (wxListCtrl *listCtrl, long itemIndex, int columnIndex) const; - virtual void ImportSecurityTokenKeyfiles () const { ThrowTextModeRequired(); } - virtual void InitSecurityTokenLibrary () const; - virtual void InsertToListCtrl (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields, int imageIndex = -1, void *itemDataPtr = nullptr) const; - virtual bool IsInBackgroundMode () const { return BackgroundMode; } - virtual bool IsTheOnlyTopLevelWindow (const wxWindow *window) const; - virtual void ListSecurityTokenKeyfiles () const; - virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; - virtual shared_ptr MountVolume (MountOptions &options) const; - virtual void MoveListCtrlItem (wxListCtrl *listCtrl, long itemIndex, long newItemIndex) const; - virtual void OnAutoDismountAllEvent (); - virtual bool OnInit (); - virtual void OnLogOff (); - virtual void OpenDocument (wxWindow *parent, const wxFileName &document); - virtual void OpenHomepageLink (wxWindow *parent, const wxString &linkId, const wxString &extraVars = wxEmptyString); - virtual void OpenOnlineHelp (wxWindow *parent); - virtual void OpenUserGuide (wxWindow *parent); - virtual void RestoreVolumeHeaders (shared_ptr volumePath) const; - virtual DevicePath SelectDevice (wxWindow *parent) const; - virtual DirectoryPath SelectDirectory (wxWindow *parent, const wxString &message = wxEmptyString, bool existingOnly = true) const; - virtual FilePathList SelectFiles (wxWindow *parent, const wxString &caption, bool saveMode = false, bool allowMultiple = false, const list < pair > &fileExtensions = (list < pair > ()), const DirectoryPath &directory = DirectoryPath()) const; - virtual FilePath SelectVolumeFile (wxWindow *parent, bool saveMode = false, const DirectoryPath &directory = DirectoryPath()) const; - virtual void SetActiveFrame (wxFrame *frame) { ActiveFrame = frame; } - virtual void SetBackgroundMode (bool state); - virtual void SetListCtrlColumnWidths (wxListCtrl *listCtrl, list columnWidthPermilles, bool hasVerticalScrollbar = true) const; - virtual void SetListCtrlHeight (wxListCtrl *listCtrl, size_t rowCount) const; - virtual void SetListCtrlWidth (wxListCtrl *listCtrl, size_t charCount, bool hasVerticalScrollbar = true) const; - virtual void ShowErrorTopMost (char *langStringId) const { ShowErrorTopMost (LangString[langStringId]); } - virtual void ShowErrorTopMost (const wxString &message) const; - virtual void ShowInfoTopMost (char *langStringId) const { ShowInfoTopMost (LangString[langStringId]); } - virtual void ShowInfoTopMost (const wxString &message) const; - virtual void ShowWarningTopMost (char *langStringId) const { ShowWarningTopMost (LangString[langStringId]); } - virtual void ShowWarningTopMost (const wxString &message) const; - virtual bool UpdateListCtrlItem (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields) const; - virtual void UserEnrichRandomPool (wxWindow *parent, shared_ptr hash = shared_ptr ()) const; - virtual void Yield () const; - -#ifdef TC_MACOSX - virtual void MacOpenFile (const wxString &fileName); -#endif - - template - T *GetSelectedData (wxControlWithItems *control) const - { - int sel = control->GetSelection(); - if (sel == wxNOT_FOUND) - return nullptr; - - return reinterpret_cast (control->GetClientData (sel)); - } - - Event OpenVolumeSystemRequestEvent; - - protected: - virtual void OnEndSession (wxCloseEvent& event) { OnLogOff(); } -#ifdef wxHAS_POWER_EVENTS - virtual void OnPowerSuspending (wxPowerEvent& event); -#endif - static void OnSignal (int signal); - virtual void OnVolumesAutoDismounted (); - virtual int ShowMessage (const wxString &message, long style, bool topMost = false) const; - void ThrowTextModeRequired () const; - - wxFrame *ActiveFrame; - bool BackgroundMode; -#ifdef TC_WINDOWS - auto_ptr DDEServer; -#endif - wxFrame *mMainFrame; - auto_ptr SingleInstanceChecker; - - private: - GraphicUserInterface (const GraphicUserInterface &); - GraphicUserInterface &operator= (const GraphicUserInterface &); - }; - - - struct OpenVolumeSystemRequestEventArgs : public EventArgs - { - OpenVolumeSystemRequestEventArgs (const wxString &volumePath) : mVolumePath (volumePath) { } - wxString mVolumePath; - }; - - - class FreezeScope - { - public: - FreezeScope (wxWindow *window) : Window (window) - { - Window->Freeze(); - } - - ~FreezeScope () - { - Window->Thaw(); - } - - wxWindow *Window; - }; - - DECLARE_EVENT_TYPE (TC_EVENT_THREAD_EXITING, -1); - - extern GraphicUserInterface *Gui; -} - -#endif // TC_HEADER_Main_GraphicUserInterface +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_GraphicUserInterface +#define TC_HEADER_Main_GraphicUserInterface + +#include "System.h" +#include +#include "Main.h" +#include "UserInterface.h" + +namespace TrueCrypt +{ + class GraphicUserInterface : public UserInterface + { + public: + GraphicUserInterface (); + virtual ~GraphicUserInterface (); + + virtual void AppendToListCtrl (wxListCtrl *listCtrl, const vector &itemFields, int imageIndex = -1, void *itemDataPtr = nullptr) const; + virtual wxMenuItem *AppendToMenu (wxMenu &menu, const wxString &label, wxEvtHandler *handler = nullptr, wxObjectEventFunction handlerFunction = nullptr, int itemId = wxID_ANY) const; + virtual bool AskYesNo (const wxString &message, bool defaultYes = false, bool warning = false) const; + virtual void AutoDismountVolumes (VolumeInfoList mountedVolumes, bool alwaysForce = true); + virtual void BackupVolumeHeaders (shared_ptr volumePath) const; + virtual void BeginBusyState () const { wxBeginBusyCursor(); } + virtual void BeginInteractiveBusyState (wxWindow *window); + virtual void ChangePassword (shared_ptr volumePath = shared_ptr (), shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr (), shared_ptr newHash = shared_ptr ()) const { ThrowTextModeRequired(); } + wxHyperlinkCtrl *CreateHyperlink (wxWindow *parent, const wxString &linkUrl, const wxString &linkText) const; + virtual void CreateKeyfile (shared_ptr keyfilePath = shared_ptr ()) const; + virtual void CreateVolume (shared_ptr options) const { ThrowTextModeRequired(); } + virtual void ClearListCtrlSelection (wxListCtrl *listCtrl) const; + virtual void DeleteSecurityTokenKeyfiles () const { ThrowTextModeRequired(); } + virtual void DoShowError (const wxString &message) const; + virtual void DoShowInfo (const wxString &message) const; + virtual void DoShowString (const wxString &str) const; + virtual void DoShowWarning (const wxString &message) const; + virtual void EndBusyState () const { wxEndBusyCursor(); } + virtual void EndInteractiveBusyState (wxWindow *window) const; + virtual void ExportSecurityTokenKeyfile () const { ThrowTextModeRequired(); } + virtual wxTopLevelWindow *GetActiveWindow () const; + virtual shared_ptr GetAdminPasswordRequestHandler (); + virtual int GetCharHeight (wxWindow *window) const; + virtual int GetCharWidth (wxWindow *window) const; + virtual int GetDefaultBorderSize () const { return 5; } + virtual wxFont GetDefaultBoldFont (wxWindow *window) const; + virtual wxString GetHomepageLinkURL (const wxString &linkId, bool secure = false, const wxString &extraVars = wxEmptyString) const; + virtual wxFrame *GetMainFrame () const { return mMainFrame; } + virtual int GetScrollbarWidth (wxWindow *window, bool noScrollBar = false) const; + virtual list GetListCtrlSelectedItems (wxListCtrl *listCtrl) const; + virtual wxString GetListCtrlSubItemText (wxListCtrl *listCtrl, long itemIndex, int columnIndex) const; + virtual void ImportSecurityTokenKeyfiles () const { ThrowTextModeRequired(); } + virtual void InitSecurityTokenLibrary () const; + virtual void InsertToListCtrl (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields, int imageIndex = -1, void *itemDataPtr = nullptr) const; + virtual bool IsInBackgroundMode () const { return BackgroundMode; } + virtual bool IsTheOnlyTopLevelWindow (const wxWindow *window) const; + virtual void ListSecurityTokenKeyfiles () const; + virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; + virtual shared_ptr MountVolume (MountOptions &options) const; + virtual void MoveListCtrlItem (wxListCtrl *listCtrl, long itemIndex, long newItemIndex) const; + virtual void OnAutoDismountAllEvent (); + virtual bool OnInit (); + virtual void OnLogOff (); + virtual void OpenDocument (wxWindow *parent, const wxFileName &document); + virtual void OpenHomepageLink (wxWindow *parent, const wxString &linkId, const wxString &extraVars = wxEmptyString); + virtual void OpenOnlineHelp (wxWindow *parent); + virtual void OpenUserGuide (wxWindow *parent); + virtual void RestoreVolumeHeaders (shared_ptr volumePath) const; + virtual DevicePath SelectDevice (wxWindow *parent) const; + virtual DirectoryPath SelectDirectory (wxWindow *parent, const wxString &message = wxEmptyString, bool existingOnly = true) const; + virtual FilePathList SelectFiles (wxWindow *parent, const wxString &caption, bool saveMode = false, bool allowMultiple = false, const list < pair > &fileExtensions = (list < pair > ()), const DirectoryPath &directory = DirectoryPath()) const; + virtual FilePath SelectVolumeFile (wxWindow *parent, bool saveMode = false, const DirectoryPath &directory = DirectoryPath()) const; + virtual void SetActiveFrame (wxFrame *frame) { ActiveFrame = frame; } + virtual void SetBackgroundMode (bool state); + virtual void SetListCtrlColumnWidths (wxListCtrl *listCtrl, list columnWidthPermilles, bool hasVerticalScrollbar = true) const; + virtual void SetListCtrlHeight (wxListCtrl *listCtrl, size_t rowCount) const; + virtual void SetListCtrlWidth (wxListCtrl *listCtrl, size_t charCount, bool hasVerticalScrollbar = true) const; + virtual void ShowErrorTopMost (char *langStringId) const { ShowErrorTopMost (LangString[langStringId]); } + virtual void ShowErrorTopMost (const wxString &message) const; + virtual void ShowInfoTopMost (char *langStringId) const { ShowInfoTopMost (LangString[langStringId]); } + virtual void ShowInfoTopMost (const wxString &message) const; + virtual void ShowWarningTopMost (char *langStringId) const { ShowWarningTopMost (LangString[langStringId]); } + virtual void ShowWarningTopMost (const wxString &message) const; + virtual bool UpdateListCtrlItem (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields) const; + virtual void UserEnrichRandomPool (wxWindow *parent, shared_ptr hash = shared_ptr ()) const; + virtual void Yield () const; + +#ifdef TC_MACOSX + virtual void MacOpenFile (const wxString &fileName); +#endif + + template + T *GetSelectedData (wxControlWithItems *control) const + { + int sel = control->GetSelection(); + if (sel == wxNOT_FOUND) + return nullptr; + + return reinterpret_cast (control->GetClientData (sel)); + } + + Event OpenVolumeSystemRequestEvent; + + protected: + virtual void OnEndSession (wxCloseEvent& event) { OnLogOff(); } +#ifdef wxHAS_POWER_EVENTS + virtual void OnPowerSuspending (wxPowerEvent& event); +#endif + static void OnSignal (int signal); + virtual void OnVolumesAutoDismounted (); + virtual int ShowMessage (const wxString &message, long style, bool topMost = false) const; + void ThrowTextModeRequired () const; + + wxFrame *ActiveFrame; + bool BackgroundMode; +#ifdef TC_WINDOWS + auto_ptr DDEServer; +#endif + wxFrame *mMainFrame; + auto_ptr SingleInstanceChecker; + + private: + GraphicUserInterface (const GraphicUserInterface &); + GraphicUserInterface &operator= (const GraphicUserInterface &); + }; + + + struct OpenVolumeSystemRequestEventArgs : public EventArgs + { + OpenVolumeSystemRequestEventArgs (const wxString &volumePath) : mVolumePath (volumePath) { } + wxString mVolumePath; + }; + + + class FreezeScope + { + public: + FreezeScope (wxWindow *window) : Window (window) + { + Window->Freeze(); + } + + ~FreezeScope () + { + Window->Thaw(); + } + + wxWindow *Window; + }; + + DECLARE_EVENT_TYPE (TC_EVENT_THREAD_EXITING, -1); + + extern GraphicUserInterface *Gui; +} + +#endif // TC_HEADER_Main_GraphicUserInterface diff --git a/Main/Hotkey.cpp b/Main/Hotkey.cpp index a6fd93d..2317b86 100644 --- a/Main/Hotkey.cpp +++ b/Main/Hotkey.cpp @@ -1,241 +1,241 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Application.h" -#include "LanguageStrings.h" -#include "GraphicUserInterface.h" -#include "Hotkey.h" -#include "Xml.h" - -namespace TrueCrypt -{ - HotkeyList Hotkey::GetAvailableHotkeys () - { - HotkeyList hotkeys; -#ifdef TC_WINDOWS - -#define TC_HOTKEY(ID,LANG) hotkeys.push_back (shared_ptr (new Hotkey (Id::##ID, L###ID, LangString[LANG]))) - - TC_HOTKEY (CloseAllSecurityTokenSessions, "IDM_CLOSE_ALL_TOKEN_SESSIONS"); - TC_HOTKEY (DismountAll, "HK_DISMOUNT_ALL"); - TC_HOTKEY (DismountAllWipeCache, "HK_DISMOUNT_ALL_AND_WIPE"); - TC_HOTKEY (ForceDismountAllWipeCache, "HK_FORCE_DISMOUNT_ALL_AND_WIPE"); - TC_HOTKEY (ForceDismountAllWipeCacheExit, "HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT"); - TC_HOTKEY (MountAllDevices, "HK_AUTOMOUNT_DEVICES"); - TC_HOTKEY (MountAllFavorites, "HK_MOUNT_FAVORITE_VOLUMES"); - TC_HOTKEY (ShowHideApplication, "HK_SHOW_HIDE_MAIN_WINDOW"); - TC_HOTKEY (WipeCache, "HK_WIPE_CACHE"); - -#endif - return hotkeys; - } - - wxString Hotkey::GetShortcutString () const - { - wxString keyStr = Hotkey::GetVirtualKeyCodeString (VirtualKeyCode); - if (keyStr.empty()) - return L""; - - wxString str; - - if (VirtualKeyModifiers & wxMOD_SHIFT) - str += LangString["VK_SHIFT"] + L"+"; - - if (VirtualKeyModifiers & wxMOD_CONTROL) - str += LangString["VK_CONTROL"] + L"+"; - - if (VirtualKeyModifiers & wxMOD_ALT) - str += LangString["VK_ALT"] + L"+"; - - if (VirtualKeyModifiers & wxMOD_WIN ) - str += LangString["VK_WIN"] + L"+"; - - return str + keyStr; - } - - wxString Hotkey::GetVirtualKeyCodeString (int virtualKeyCode) - { -#ifdef TC_WINDOWS - // ASCII characters - if (virtualKeyCode >= 0x30 && virtualKeyCode <= 0x5a) - return StringFormatter (L"{0}", char (virtualKeyCode)); - - // OEM-specific - if (virtualKeyCode >= 0xE9 && virtualKeyCode <= 0xF5) - return StringFormatter (L"OEM-{0}", virtualKeyCode); - - // F1-F24 - if (virtualKeyCode >= VK_F1 && virtualKeyCode <= VK_F24) - return StringFormatter (L"F{0}", virtualKeyCode - VK_F1 + 1); - - // Numpad numbers - if (virtualKeyCode >= VK_NUMPAD0 && virtualKeyCode <= VK_NUMPAD9) - return StringFormatter (L"{0} {1}", LangString["VK_NUMPAD"], virtualKeyCode - VK_NUMPAD0); - - switch (virtualKeyCode) - { - case VK_MULTIPLY: return LangString["VK_NUMPAD"] + L" *"; - case VK_ADD: return LangString["VK_NUMPAD"] + L" +"; - case VK_SEPARATOR: return LangString["VK_NUMPAD"] + L" Separator"; - case VK_SUBTRACT: return LangString["VK_NUMPAD"] + L" -"; - case VK_DECIMAL: return LangString["VK_NUMPAD"] + L" ."; - case VK_DIVIDE: return LangString["VK_NUMPAD"] + L" /"; - case VK_OEM_1: return L"OEM 1 (';')"; - case VK_OEM_PLUS: return L"+"; - case VK_OEM_COMMA: return L","; - case VK_OEM_MINUS: return L"-"; - case VK_OEM_PERIOD: return L"."; - case VK_OEM_2: return L"OEM 2 ('/')"; - case VK_OEM_3: return L"OEM 3 (`)"; - case VK_OEM_4: return L"OEM 4 ('[')"; - case VK_OEM_5: return L"OEM 5 ('\\')"; - case VK_OEM_6: return L"OEM 6 (']')"; - case VK_OEM_7: return L"OEM 7 (')"; - case VK_OEM_8: return L"OEM 8"; - case VK_OEM_AX: return L"OEM AX"; - case VK_OEM_102: return L"OEM 102"; - case VK_ICO_HELP: return L"ICO_HELP"; - case VK_ICO_00: return L"ICO_00"; - case VK_ICO_CLEAR: return L"ICO_CLEAR"; - case VK_ATTN: return L"Attn"; - case VK_CRSEL: return L"CrSel"; - case VK_EXSEL: return L"ExSel"; - case VK_EREOF: return L"Erase EOF"; - case VK_PA1: return L"PA1"; - case VK_OEM_CLEAR: return L"OEM Clear"; - - case 0: - case 1: - case 0xFF: - break; - - default: - { - string langStrId = StringConverter::ToSingle (wstring (wxString::Format (L"VKEY_%02X", virtualKeyCode))); - if (LangString.Exists (langStrId)) - return LangString[langStrId]; - } - } -#endif // TC_WINDOWS - return L""; - } - - HotkeyList Hotkey::LoadList () - { - HotkeyList hotkeys = GetAvailableHotkeys(); - - FilePath path = Application::GetConfigFilePath (GetFileName()); - if (path.IsFile()) - { - foreach (XmlNode node, XmlParser (path).GetNodes (L"hotkey")) - { - wstring keyName (node.Attributes[L"name"]); - - foreach (shared_ptr hotkey, hotkeys) - { - if (hotkey->Name == keyName) - { - hotkey->VirtualKeyCode = StringConverter::ToUInt32 (wstring (node.Attributes[L"vkeycode"])); - hotkey->VirtualKeyModifiers = 0; - - if (node.Attributes[L"modshift"] == L"1") - hotkey->VirtualKeyModifiers |= wxMOD_SHIFT; - - if (node.Attributes[L"modcontrol"] == L"1") - hotkey->VirtualKeyModifiers |= wxMOD_CONTROL; - - if (node.Attributes[L"modalt"] == L"1") - hotkey->VirtualKeyModifiers |= wxMOD_ALT; - - if (node.Attributes[L"modwin"] == L"1") - hotkey->VirtualKeyModifiers |= wxMOD_WIN; - - break; - } - } - } - } - - return hotkeys; - } - - void Hotkey::RegisterList (wxWindow *handler, const HotkeyList &hotkeys) - { -#ifdef TC_WINDOWS - bool res = true; - foreach (shared_ptr hotkey, hotkeys) - { - if (hotkey->VirtualKeyCode != 0) - { - if (!handler->RegisterHotKey (hotkey->Id, hotkey->VirtualKeyModifiers, hotkey->VirtualKeyCode)) - res = false; - } - } - - if (!res) - Gui->ShowWarning ("HOTKEY_REGISTRATION_ERROR"); -#endif - } - - void Hotkey::SaveList (const HotkeyList &hotkeys) - { - FilePath hotkeysCfgPath = Application::GetConfigFilePath (GetFileName(), true); - - bool noHotkey = true; - XmlNode hotkeysXml (L"hotkeys"); - foreach_ref (const Hotkey &hotkey, hotkeys) - { - if (hotkey.VirtualKeyCode == 0) - continue; - - noHotkey = false; - XmlNode node (L"hotkey"); - node.Attributes[L"name"] = wstring (hotkey.Name); - - node.Attributes[L"vkeycode"] = StringConverter::FromNumber (hotkey.VirtualKeyCode); - - if (hotkey.VirtualKeyModifiers & wxMOD_SHIFT) - node.Attributes[L"modshift"] = L"1"; - - if (hotkey.VirtualKeyModifiers & wxMOD_CONTROL) - node.Attributes[L"modcontrol"] = L"1"; - - if (hotkey.VirtualKeyModifiers & wxMOD_ALT) - node.Attributes[L"modalt"] = L"1"; - - if (hotkey.VirtualKeyModifiers & wxMOD_WIN ) - node.Attributes[L"modwin"] = L"1"; - - hotkeysXml.InnerNodes.push_back (node); - } - - if (noHotkey) - { - if (hotkeysCfgPath.IsFile()) - hotkeysCfgPath.Delete(); - } - else - { - XmlWriter hotkeysWriter (hotkeysCfgPath); - hotkeysWriter.WriteNode (hotkeysXml); - hotkeysWriter.Close(); - } - } - - void Hotkey::UnregisterList (wxWindow *handler, const HotkeyList &hotkeys) - { -#ifdef TC_WINDOWS - foreach (shared_ptr hotkey, hotkeys) - { - if (hotkey->VirtualKeyCode != 0) - handler->UnregisterHotKey (hotkey->Id); - } -#endif - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Application.h" +#include "LanguageStrings.h" +#include "GraphicUserInterface.h" +#include "Hotkey.h" +#include "Xml.h" + +namespace TrueCrypt +{ + HotkeyList Hotkey::GetAvailableHotkeys () + { + HotkeyList hotkeys; +#ifdef TC_WINDOWS + +#define TC_HOTKEY(ID,LANG) hotkeys.push_back (shared_ptr (new Hotkey (Id::##ID, L###ID, LangString[LANG]))) + + TC_HOTKEY (CloseAllSecurityTokenSessions, "IDM_CLOSE_ALL_TOKEN_SESSIONS"); + TC_HOTKEY (DismountAll, "HK_DISMOUNT_ALL"); + TC_HOTKEY (DismountAllWipeCache, "HK_DISMOUNT_ALL_AND_WIPE"); + TC_HOTKEY (ForceDismountAllWipeCache, "HK_FORCE_DISMOUNT_ALL_AND_WIPE"); + TC_HOTKEY (ForceDismountAllWipeCacheExit, "HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT"); + TC_HOTKEY (MountAllDevices, "HK_AUTOMOUNT_DEVICES"); + TC_HOTKEY (MountAllFavorites, "HK_MOUNT_FAVORITE_VOLUMES"); + TC_HOTKEY (ShowHideApplication, "HK_SHOW_HIDE_MAIN_WINDOW"); + TC_HOTKEY (WipeCache, "HK_WIPE_CACHE"); + +#endif + return hotkeys; + } + + wxString Hotkey::GetShortcutString () const + { + wxString keyStr = Hotkey::GetVirtualKeyCodeString (VirtualKeyCode); + if (keyStr.empty()) + return L""; + + wxString str; + + if (VirtualKeyModifiers & wxMOD_SHIFT) + str += LangString["VK_SHIFT"] + L"+"; + + if (VirtualKeyModifiers & wxMOD_CONTROL) + str += LangString["VK_CONTROL"] + L"+"; + + if (VirtualKeyModifiers & wxMOD_ALT) + str += LangString["VK_ALT"] + L"+"; + + if (VirtualKeyModifiers & wxMOD_WIN ) + str += LangString["VK_WIN"] + L"+"; + + return str + keyStr; + } + + wxString Hotkey::GetVirtualKeyCodeString (int virtualKeyCode) + { +#ifdef TC_WINDOWS + // ASCII characters + if (virtualKeyCode >= 0x30 && virtualKeyCode <= 0x5a) + return StringFormatter (L"{0}", char (virtualKeyCode)); + + // OEM-specific + if (virtualKeyCode >= 0xE9 && virtualKeyCode <= 0xF5) + return StringFormatter (L"OEM-{0}", virtualKeyCode); + + // F1-F24 + if (virtualKeyCode >= VK_F1 && virtualKeyCode <= VK_F24) + return StringFormatter (L"F{0}", virtualKeyCode - VK_F1 + 1); + + // Numpad numbers + if (virtualKeyCode >= VK_NUMPAD0 && virtualKeyCode <= VK_NUMPAD9) + return StringFormatter (L"{0} {1}", LangString["VK_NUMPAD"], virtualKeyCode - VK_NUMPAD0); + + switch (virtualKeyCode) + { + case VK_MULTIPLY: return LangString["VK_NUMPAD"] + L" *"; + case VK_ADD: return LangString["VK_NUMPAD"] + L" +"; + case VK_SEPARATOR: return LangString["VK_NUMPAD"] + L" Separator"; + case VK_SUBTRACT: return LangString["VK_NUMPAD"] + L" -"; + case VK_DECIMAL: return LangString["VK_NUMPAD"] + L" ."; + case VK_DIVIDE: return LangString["VK_NUMPAD"] + L" /"; + case VK_OEM_1: return L"OEM 1 (';')"; + case VK_OEM_PLUS: return L"+"; + case VK_OEM_COMMA: return L","; + case VK_OEM_MINUS: return L"-"; + case VK_OEM_PERIOD: return L"."; + case VK_OEM_2: return L"OEM 2 ('/')"; + case VK_OEM_3: return L"OEM 3 (`)"; + case VK_OEM_4: return L"OEM 4 ('[')"; + case VK_OEM_5: return L"OEM 5 ('\\')"; + case VK_OEM_6: return L"OEM 6 (']')"; + case VK_OEM_7: return L"OEM 7 (')"; + case VK_OEM_8: return L"OEM 8"; + case VK_OEM_AX: return L"OEM AX"; + case VK_OEM_102: return L"OEM 102"; + case VK_ICO_HELP: return L"ICO_HELP"; + case VK_ICO_00: return L"ICO_00"; + case VK_ICO_CLEAR: return L"ICO_CLEAR"; + case VK_ATTN: return L"Attn"; + case VK_CRSEL: return L"CrSel"; + case VK_EXSEL: return L"ExSel"; + case VK_EREOF: return L"Erase EOF"; + case VK_PA1: return L"PA1"; + case VK_OEM_CLEAR: return L"OEM Clear"; + + case 0: + case 1: + case 0xFF: + break; + + default: + { + string langStrId = StringConverter::ToSingle (wstring (wxString::Format (L"VKEY_%02X", virtualKeyCode))); + if (LangString.Exists (langStrId)) + return LangString[langStrId]; + } + } +#endif // TC_WINDOWS + return L""; + } + + HotkeyList Hotkey::LoadList () + { + HotkeyList hotkeys = GetAvailableHotkeys(); + + FilePath path = Application::GetConfigFilePath (GetFileName()); + if (path.IsFile()) + { + foreach (XmlNode node, XmlParser (path).GetNodes (L"hotkey")) + { + wstring keyName (node.Attributes[L"name"]); + + foreach (shared_ptr hotkey, hotkeys) + { + if (hotkey->Name == keyName) + { + hotkey->VirtualKeyCode = StringConverter::ToUInt32 (wstring (node.Attributes[L"vkeycode"])); + hotkey->VirtualKeyModifiers = 0; + + if (node.Attributes[L"modshift"] == L"1") + hotkey->VirtualKeyModifiers |= wxMOD_SHIFT; + + if (node.Attributes[L"modcontrol"] == L"1") + hotkey->VirtualKeyModifiers |= wxMOD_CONTROL; + + if (node.Attributes[L"modalt"] == L"1") + hotkey->VirtualKeyModifiers |= wxMOD_ALT; + + if (node.Attributes[L"modwin"] == L"1") + hotkey->VirtualKeyModifiers |= wxMOD_WIN; + + break; + } + } + } + } + + return hotkeys; + } + + void Hotkey::RegisterList (wxWindow *handler, const HotkeyList &hotkeys) + { +#ifdef TC_WINDOWS + bool res = true; + foreach (shared_ptr hotkey, hotkeys) + { + if (hotkey->VirtualKeyCode != 0) + { + if (!handler->RegisterHotKey (hotkey->Id, hotkey->VirtualKeyModifiers, hotkey->VirtualKeyCode)) + res = false; + } + } + + if (!res) + Gui->ShowWarning ("HOTKEY_REGISTRATION_ERROR"); +#endif + } + + void Hotkey::SaveList (const HotkeyList &hotkeys) + { + FilePath hotkeysCfgPath = Application::GetConfigFilePath (GetFileName(), true); + + bool noHotkey = true; + XmlNode hotkeysXml (L"hotkeys"); + foreach_ref (const Hotkey &hotkey, hotkeys) + { + if (hotkey.VirtualKeyCode == 0) + continue; + + noHotkey = false; + XmlNode node (L"hotkey"); + node.Attributes[L"name"] = wstring (hotkey.Name); + + node.Attributes[L"vkeycode"] = StringConverter::FromNumber (hotkey.VirtualKeyCode); + + if (hotkey.VirtualKeyModifiers & wxMOD_SHIFT) + node.Attributes[L"modshift"] = L"1"; + + if (hotkey.VirtualKeyModifiers & wxMOD_CONTROL) + node.Attributes[L"modcontrol"] = L"1"; + + if (hotkey.VirtualKeyModifiers & wxMOD_ALT) + node.Attributes[L"modalt"] = L"1"; + + if (hotkey.VirtualKeyModifiers & wxMOD_WIN ) + node.Attributes[L"modwin"] = L"1"; + + hotkeysXml.InnerNodes.push_back (node); + } + + if (noHotkey) + { + if (hotkeysCfgPath.IsFile()) + hotkeysCfgPath.Delete(); + } + else + { + XmlWriter hotkeysWriter (hotkeysCfgPath); + hotkeysWriter.WriteNode (hotkeysXml); + hotkeysWriter.Close(); + } + } + + void Hotkey::UnregisterList (wxWindow *handler, const HotkeyList &hotkeys) + { +#ifdef TC_WINDOWS + foreach (shared_ptr hotkey, hotkeys) + { + if (hotkey->VirtualKeyCode != 0) + handler->UnregisterHotKey (hotkey->Id); + } +#endif + } +} diff --git a/Main/Hotkey.h b/Main/Hotkey.h index 0b48a7b..9e4ff8d 100644 --- a/Main/Hotkey.h +++ b/Main/Hotkey.h @@ -1,63 +1,63 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Hotkey -#define TC_HEADER_Main_Hotkey - -#include "System.h" -#include "Main.h" - -namespace TrueCrypt -{ - struct Hotkey; - typedef list < shared_ptr > HotkeyList; - - struct Hotkey - { - public: - struct Id - { - enum - { - CloseAllSecurityTokenSessions = 0, - DismountAll, - DismountAllWipeCache, - ForceDismountAllWipeCache, - ForceDismountAllWipeCacheExit, - MountAllDevices, - MountAllFavorites, - ShowHideApplication, - WipeCache - }; - }; - - Hotkey (int id, const wstring &name, const wxString &description, int virtualKeyCode = 0, int virtualKeyModifiers = 0) - : Description (description), Id (id), Name (name), VirtualKeyCode (virtualKeyCode), VirtualKeyModifiers (virtualKeyModifiers) { } - - virtual ~Hotkey () { } - - static HotkeyList GetAvailableHotkeys (); - wxString GetShortcutString () const; - static wxString GetVirtualKeyCodeString (int virtualKeyCode); - static HotkeyList LoadList (); - static void RegisterList (wxWindow *handler, const HotkeyList &hotkeys); - static void SaveList (const HotkeyList &hotkeys); - static void UnregisterList (wxWindow *handler, const HotkeyList &hotkeys); - - wxString Description; - int Id; - wstring Name; - int VirtualKeyCode; - int VirtualKeyModifiers; - - protected: - static wxString GetFileName () { return L"Hotkeys.xml"; } - }; -} - -#endif // TC_HEADER_Main_Hotkey +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Hotkey +#define TC_HEADER_Main_Hotkey + +#include "System.h" +#include "Main.h" + +namespace TrueCrypt +{ + struct Hotkey; + typedef list < shared_ptr > HotkeyList; + + struct Hotkey + { + public: + struct Id + { + enum + { + CloseAllSecurityTokenSessions = 0, + DismountAll, + DismountAllWipeCache, + ForceDismountAllWipeCache, + ForceDismountAllWipeCacheExit, + MountAllDevices, + MountAllFavorites, + ShowHideApplication, + WipeCache + }; + }; + + Hotkey (int id, const wstring &name, const wxString &description, int virtualKeyCode = 0, int virtualKeyModifiers = 0) + : Description (description), Id (id), Name (name), VirtualKeyCode (virtualKeyCode), VirtualKeyModifiers (virtualKeyModifiers) { } + + virtual ~Hotkey () { } + + static HotkeyList GetAvailableHotkeys (); + wxString GetShortcutString () const; + static wxString GetVirtualKeyCodeString (int virtualKeyCode); + static HotkeyList LoadList (); + static void RegisterList (wxWindow *handler, const HotkeyList &hotkeys); + static void SaveList (const HotkeyList &hotkeys); + static void UnregisterList (wxWindow *handler, const HotkeyList &hotkeys); + + wxString Description; + int Id; + wstring Name; + int VirtualKeyCode; + int VirtualKeyModifiers; + + protected: + static wxString GetFileName () { return L"Hotkeys.xml"; } + }; +} + +#endif // TC_HEADER_Main_Hotkey diff --git a/Main/LanguageStrings.cpp b/Main/LanguageStrings.cpp index bc2affc..31ac8fb 100644 --- a/Main/LanguageStrings.cpp +++ b/Main/LanguageStrings.cpp @@ -1,86 +1,86 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Resources.h" -#include "LanguageStrings.h" -#include "Xml.h" - -namespace TrueCrypt -{ - LanguageStrings::LanguageStrings () - { - } - - LanguageStrings::~LanguageStrings () - { - } - - wxString LanguageStrings::operator[] (const string &key) const - { - if (Map.count (key) > 0) - return wxString (Map.find (key)->second); - - return wxString (L"?") + StringConverter::ToWide (key) + L"?"; - } - - wstring LanguageStrings::Get (const string &key) const - { - return wstring (LangString[key]); - } - - void LanguageStrings::Init () - { - foreach (XmlNode node, XmlParser (Resources::GetLanguageXml()).GetNodes (L"string")) - { - wxString text = node.InnerText; - text.Replace (L"\\n", L"\n"); - Map[StringConverter::ToSingle (wstring (node.Attributes[L"key"]))] = text; - } - - foreach (XmlNode node, XmlParser (Resources::GetLanguageXml()).GetNodes (L"control")) - { - wxString text = node.InnerText; - text.Replace (L"\\n", L"\n"); - Map[StringConverter::ToSingle (wstring (node.Attributes[L"key"]))] = text; - } - - Map["EXCEPTION_OCCURRED"] = _("Exception occurred"); - Map["MOUNT"] = _("Mount"); - Map["MOUNT_POINT"] = _("Mount Directory"); - Map["NO"] = _("No"); - Map["NO_VOLUMES_MOUNTED"] = _("No volumes mounted."); - Map["OPEN_NEW_VOLUME"] = _("Specify a New TrueCrypt Volume"); - Map["PARAMETER_INCORRECT"] = _("Parameter incorrrect"); - Map["SELECT_KEYFILES"] = _("Select Keyfiles"); - Map["START_TC"] = _("Start TrueCrypt"); - Map["VOLUME_ALREADY_MOUNTED"] = _("The volume \"{0}\" is already mounted."); - Map["UNKNOWN_OPTION"] = _("Unknown option"); - Map["VOLUME_LOCATION"] = _("Volume Location"); - Map["YES"] = _("Yes"); - Map["VOLUME_HOST_IN_USE"] = _("WARNING: The host file/device \"{0}\" is already in use!\n\nIgnoring this can cause undesired results including system instability. All applications that might be using the host file/device should be closed before mounting the volume.\n\nContinue mounting?"); - Map["VIRTUAL_DEVICE"] = _("Virtual Device"); - Map["CONFIRM_BACKGROUND_TASK_DISABLED"] = _("WARNING: If the TrueCrypt Background Task is disabled, the following functions, depending on the platform, will be disabled whenever you exit TrueCrypt:\n\n1) Auto-dismount (e.g., upon log off, time-out, etc.)\n2) Notifications (e.g., when damage to hidden volume is prevented)\n3) Tray icon\n\nNote: You may shut down the Background Task anytime by right-clicking the TrueCrypt tray icon and selecting 'Exit'.\n\nAre you sure you want to disable the TrueCrypt Background Task?"); - Map["CONFIRM_EXIT"] = _("WARNING: If TrueCrypt exits now, the following functions, depending on the platform, will be disabled:\n\n1) Auto-dismount (e.g., upon log off, time-out, etc.)\n2) Notifications (e.g., when damage to hidden volume is prevented)\n3) Tray icon\n\nNote: If you do not wish TrueCrypt to continue running in background after you close its window, disable the Background Task in the Preferences.\n\nAre you sure you want TrueCrypt to exit?"); - Map["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"] = _("WARNING: Data were attempted to be saved to the hidden volume area of the volume \"{0}\"!\n\nTrueCrypt prevented these data from being saved in order to protect the hidden volume. This may have caused filesystem corruption on the outer volume and the operating system may have reported a write error (\"Delayed Write Failed\", \"The parameter is incorrect\", etc.). The entire volume (both the outer and the hidden part) will be write-protected until it is dismounted.\n\nWe strongly recommend that you restart the operating system now."); - Map["ENTER_PASSWORD"] = _("Enter password"); - Map["ENTER_PASSWORD_FOR"] = _("Enter password for \"{0}\""); - Map["ENTER_TC_VOL_PASSWORD"] = _("Enter TrueCrypt Volume Password"); - Map["SELECT_KEYFILE_PATH"] = _("Select Keyfile Search Path"); - Map["MORE_INFO_ABOUT"] = _("More information on {0}"); - Map["TWO_LAYER_CASCADE_HELP"] = _("Two ciphers in a cascade operating in XTS mode. Each block is first encrypted with {0} ({1}-bit key) and then with {2} ({3}-bit key). Each cipher uses its own key. All keys are mutually independent."); - Map["THREE_LAYER_CASCADE_HELP"] = _("Three ciphers in a cascade operating in XTS mode. Each block is first encrypted with {0} ({1}-bit key), then with {2} ({3}-bit key), and finally with {4} ({5}-bit key). Each cipher uses its own key. All keys are mutually independent."); - Map["CHECKING_FS"] = _("Checking the file system on the TrueCrypt volume mounted as {0}..."); - Map["REPAIRING_FS"] = _("Attempting to repair the file system on the TrueCrypt volume mounted as {0}..."); - Map["UNMOUNT_LOCK_FAILED"] = _("Volume \"{0}\" contains files or folders being used by applications or system.\n\nForce dismount?"); - Map["VOLUME_SIZE_HELP"] = _("Please specify the size of the container to create.\n\nIf you create a dynamic (sparse-file) container, this parameter will specify its maximum size.\n\nNote that the minimum possible size of a FAT volume is 275 KB. The minimum possible size of an NTFS volume is 2829 KB."); - Map["ENCRYPTION_MODE_NOT_SUPPORTED_BY_KERNEL"] = _("The volume you have mounted uses a mode of operation that is not supported by the Linux kernel. You may experience slow performance when using this volume. To achieve full performance, you should move the data from this volume to a new volume created by TrueCrypt 5.0 or later."); - } - - LanguageStrings LangString; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Resources.h" +#include "LanguageStrings.h" +#include "Xml.h" + +namespace TrueCrypt +{ + LanguageStrings::LanguageStrings () + { + } + + LanguageStrings::~LanguageStrings () + { + } + + wxString LanguageStrings::operator[] (const string &key) const + { + if (Map.count (key) > 0) + return wxString (Map.find (key)->second); + + return wxString (L"?") + StringConverter::ToWide (key) + L"?"; + } + + wstring LanguageStrings::Get (const string &key) const + { + return wstring (LangString[key]); + } + + void LanguageStrings::Init () + { + foreach (XmlNode node, XmlParser (Resources::GetLanguageXml()).GetNodes (L"string")) + { + wxString text = node.InnerText; + text.Replace (L"\\n", L"\n"); + Map[StringConverter::ToSingle (wstring (node.Attributes[L"key"]))] = text; + } + + foreach (XmlNode node, XmlParser (Resources::GetLanguageXml()).GetNodes (L"control")) + { + wxString text = node.InnerText; + text.Replace (L"\\n", L"\n"); + Map[StringConverter::ToSingle (wstring (node.Attributes[L"key"]))] = text; + } + + Map["EXCEPTION_OCCURRED"] = _("Exception occurred"); + Map["MOUNT"] = _("Mount"); + Map["MOUNT_POINT"] = _("Mount Directory"); + Map["NO"] = _("No"); + Map["NO_VOLUMES_MOUNTED"] = _("No volumes mounted."); + Map["OPEN_NEW_VOLUME"] = _("Specify a New TrueCrypt Volume"); + Map["PARAMETER_INCORRECT"] = _("Parameter incorrrect"); + Map["SELECT_KEYFILES"] = _("Select Keyfiles"); + Map["START_TC"] = _("Start TrueCrypt"); + Map["VOLUME_ALREADY_MOUNTED"] = _("The volume \"{0}\" is already mounted."); + Map["UNKNOWN_OPTION"] = _("Unknown option"); + Map["VOLUME_LOCATION"] = _("Volume Location"); + Map["YES"] = _("Yes"); + Map["VOLUME_HOST_IN_USE"] = _("WARNING: The host file/device \"{0}\" is already in use!\n\nIgnoring this can cause undesired results including system instability. All applications that might be using the host file/device should be closed before mounting the volume.\n\nContinue mounting?"); + Map["VIRTUAL_DEVICE"] = _("Virtual Device"); + Map["CONFIRM_BACKGROUND_TASK_DISABLED"] = _("WARNING: If the TrueCrypt Background Task is disabled, the following functions, depending on the platform, will be disabled whenever you exit TrueCrypt:\n\n1) Auto-dismount (e.g., upon log off, time-out, etc.)\n2) Notifications (e.g., when damage to hidden volume is prevented)\n3) Tray icon\n\nNote: You may shut down the Background Task anytime by right-clicking the TrueCrypt tray icon and selecting 'Exit'.\n\nAre you sure you want to disable the TrueCrypt Background Task?"); + Map["CONFIRM_EXIT"] = _("WARNING: If TrueCrypt exits now, the following functions, depending on the platform, will be disabled:\n\n1) Auto-dismount (e.g., upon log off, time-out, etc.)\n2) Notifications (e.g., when damage to hidden volume is prevented)\n3) Tray icon\n\nNote: If you do not wish TrueCrypt to continue running in background after you close its window, disable the Background Task in the Preferences.\n\nAre you sure you want TrueCrypt to exit?"); + Map["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"] = _("WARNING: Data were attempted to be saved to the hidden volume area of the volume \"{0}\"!\n\nTrueCrypt prevented these data from being saved in order to protect the hidden volume. This may have caused filesystem corruption on the outer volume and the operating system may have reported a write error (\"Delayed Write Failed\", \"The parameter is incorrect\", etc.). The entire volume (both the outer and the hidden part) will be write-protected until it is dismounted.\n\nWe strongly recommend that you restart the operating system now."); + Map["ENTER_PASSWORD"] = _("Enter password"); + Map["ENTER_PASSWORD_FOR"] = _("Enter password for \"{0}\""); + Map["ENTER_TC_VOL_PASSWORD"] = _("Enter TrueCrypt Volume Password"); + Map["SELECT_KEYFILE_PATH"] = _("Select Keyfile Search Path"); + Map["MORE_INFO_ABOUT"] = _("More information on {0}"); + Map["TWO_LAYER_CASCADE_HELP"] = _("Two ciphers in a cascade operating in XTS mode. Each block is first encrypted with {0} ({1}-bit key) and then with {2} ({3}-bit key). Each cipher uses its own key. All keys are mutually independent."); + Map["THREE_LAYER_CASCADE_HELP"] = _("Three ciphers in a cascade operating in XTS mode. Each block is first encrypted with {0} ({1}-bit key), then with {2} ({3}-bit key), and finally with {4} ({5}-bit key). Each cipher uses its own key. All keys are mutually independent."); + Map["CHECKING_FS"] = _("Checking the file system on the TrueCrypt volume mounted as {0}..."); + Map["REPAIRING_FS"] = _("Attempting to repair the file system on the TrueCrypt volume mounted as {0}..."); + Map["UNMOUNT_LOCK_FAILED"] = _("Volume \"{0}\" contains files or folders being used by applications or system.\n\nForce dismount?"); + Map["VOLUME_SIZE_HELP"] = _("Please specify the size of the container to create.\n\nIf you create a dynamic (sparse-file) container, this parameter will specify its maximum size.\n\nNote that the minimum possible size of a FAT volume is 275 KB. The minimum possible size of an NTFS volume is 2829 KB."); + Map["ENCRYPTION_MODE_NOT_SUPPORTED_BY_KERNEL"] = _("The volume you have mounted uses a mode of operation that is not supported by the Linux kernel. You may experience slow performance when using this volume. To achieve full performance, you should move the data from this volume to a new volume created by TrueCrypt 5.0 or later."); + } + + LanguageStrings LangString; +} diff --git a/Main/LanguageStrings.h b/Main/LanguageStrings.h index a4e1a9d..e11504a 100644 --- a/Main/LanguageStrings.h +++ b/Main/LanguageStrings.h @@ -1,40 +1,40 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_LanguageStrings -#define TC_HEADER_Main_LanguageStrings - -#include "System.h" -#include "Main.h" - -namespace TrueCrypt -{ - class LanguageStrings - { - public: - LanguageStrings (); - virtual ~LanguageStrings (); - - wxString operator[] (const string &key) const; - - bool Exists (const string &key) const { return Map.find (key) != Map.end(); } - wstring Get (const string &key) const; - void Init (); - - protected: - map Map; - - private: - LanguageStrings (const LanguageStrings &); - LanguageStrings &operator= (const LanguageStrings &); - }; - - extern LanguageStrings LangString; -} - -#endif // TC_HEADER_Main_LanguageStrings +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_LanguageStrings +#define TC_HEADER_Main_LanguageStrings + +#include "System.h" +#include "Main.h" + +namespace TrueCrypt +{ + class LanguageStrings + { + public: + LanguageStrings (); + virtual ~LanguageStrings (); + + wxString operator[] (const string &key) const; + + bool Exists (const string &key) const { return Map.find (key) != Map.end(); } + wstring Get (const string &key) const; + void Init (); + + protected: + map Map; + + private: + LanguageStrings (const LanguageStrings &); + LanguageStrings &operator= (const LanguageStrings &); + }; + + extern LanguageStrings LangString; +} + +#endif // TC_HEADER_Main_LanguageStrings diff --git a/Main/Main.h b/Main/Main.h index 68c322a..5bbc22d 100644 --- a/Main/Main.h +++ b/Main/Main.h @@ -1,17 +1,17 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Main -#define TC_HEADER_Main_Main - -#include "System.h" -#include "Platform/Platform.h" -#include "Core/Core.h" -#include "Main/StringFormatter.h" - -#endif // TC_HEADER_Main_Main +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Main +#define TC_HEADER_Main_Main + +#include "System.h" +#include "Platform/Platform.h" +#include "Core/Core.h" +#include "Main/StringFormatter.h" + +#endif // TC_HEADER_Main_Main diff --git a/Main/Main.make b/Main/Main.make index 2301816..87c1052 100644 --- a/Main/Main.make +++ b/Main/Main.make @@ -1,144 +1,144 @@ -# -# Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -OBJS := -OBJS += Application.o -OBJS += CommandLineInterface.o -OBJS += FavoriteVolume.o -OBJS += LanguageStrings.o -OBJS += StringFormatter.o -OBJS += TextUserInterface.o -OBJS += UserInterface.o -OBJS += UserPreferences.o -OBJS += Xml.o -OBJS += Unix/Main.o -OBJS += Resources.o - -ifndef TC_NO_GUI -OBJS += FatalErrorHandler.o -OBJS += GraphicUserInterface.o -OBJS += VolumeHistory.o -OBJS += Forms/AboutDialog.o -OBJS += Forms/ChangePasswordDialog.o -OBJS += Forms/DeviceSelectionDialog.o -OBJS += Forms/EncryptionOptionsWizardPage.o -OBJS += Forms/EncryptionTestDialog.o -OBJS += Forms/FavoriteVolumesDialog.o -OBJS += Forms/Forms.o -OBJS += Forms/InfoWizardPage.o -OBJS += Forms/KeyfileGeneratorDialog.o -OBJS += Forms/KeyfilesDialog.o -OBJS += Forms/KeyfilesPanel.o -OBJS += Forms/LegalNoticesDialog.o -OBJS += Forms/MainFrame.o -OBJS += Forms/MountOptionsDialog.o -OBJS += Forms/NewSecurityTokenKeyfileDialog.o -OBJS += Forms/PreferencesDialog.o -OBJS += Forms/ProgressWizardPage.o -OBJS += Forms/RandomPoolEnrichmentDialog.o -OBJS += Forms/SecurityTokenKeyfilesDialog.o -OBJS += Forms/SelectDirectoryWizardPage.o -OBJS += Forms/VolumePasswordPanel.o -OBJS += Forms/VolumePropertiesDialog.o -OBJS += Forms/VolumeCreationProgressWizardPage.o -OBJS += Forms/VolumeCreationWizard.o -OBJS += Forms/VolumeFormatOptionsWizardPage.o -OBJS += Forms/VolumeLocationWizardPage.o -OBJS += Forms/VolumePasswordWizardPage.o -OBJS += Forms/VolumeSizeWizardPage.o -OBJS += Forms/WizardFrame.o -endif - -ifndef DISABLE_PRECOMPILED_HEADERS -PCH := SystemPrecompiled.h.gch -endif - -RESOURCES := -RESOURCES += ../License.txt.h -RESOURCES += ../Common/Language.xml.h -ifndef TC_NO_GUI -RESOURCES += ../Common/Textual_logo_96dpi.bmp.h -RESOURCES += ../Format/TrueCrypt_Wizard.bmp.h -RESOURCES += ../Mount/Drive_icon_96dpi.bmp.h -RESOURCES += ../Mount/Drive_icon_mask_96dpi.bmp.h -RESOURCES += ../Mount/Logo_96dpi.bmp.h -endif - -CXXFLAGS += -I$(BASE_DIR)/Main - - -#------ wxWidgets configuration ------ - -ifdef TC_NO_GUI -WX_CONFIG_LIBS := base -else -WX_CONFIG_LIBS := adv,core,base -endif - -ifeq "$(TC_BUILD_CONFIG)" "Release" - -CXXFLAGS += $(shell $(WX_CONFIG) $(WX_CONFIG_ARGS) --cxxflags) -WX_LIBS = $(shell $(WX_CONFIG) $(WX_CONFIG_ARGS) --libs $(WX_CONFIG_LIBS)) - -else - -CXXFLAGS += $(shell $(WX_CONFIG) --debug $(WX_CONFIG_ARGS) --cxxflags) -WX_LIBS = $(shell $(WX_CONFIG) --debug $(WX_CONFIG_ARGS) --libs $(WX_CONFIG_LIBS)) - -endif - - -#------ FUSE configuration ------ - -FUSE_LIBS = $(shell pkg-config fuse --libs) - - -#------ Executable ------ - -TC_VERSION = $(shell grep VERSION_STRING ../Common/Tcdefs.h | head -n 1 | cut -d'"' -f 2) - -$(APPNAME): $(LIBS) $(OBJS) - @echo Linking $@ - $(CXX) -o $(APPNAME) $(LFLAGS) $(OBJS) $(LIBS) $(FUSE_LIBS) $(WX_LIBS) - -ifeq "$(TC_BUILD_CONFIG)" "Release" -ifndef NOSTRIP - strip $(APPNAME) -endif - -ifndef NOTEST - ./$(APPNAME) --text --test >/dev/null || exit 1 -endif - -ifeq "$(PLATFORM_UNSUPPORTED)" "1" - @echo; echo "WARNING: This platform may be unsupported. To avoid possible serious problems, please read the chapter pertaining to $(PLATFORM) in Readme.txt."; echo -endif -endif - -ifeq "$(PLATFORM)" "MacOSX" - mkdir -p $(APPNAME).app/Contents/MacOS $(APPNAME).app/Contents/Resources - -rm -f $(APPNAME).app/Contents/MacOS/$(APPNAME) - -ifeq "$(TC_BUILD_CONFIG)" "Release" - cp $(PWD)/Main/$(APPNAME) $(APPNAME).app/Contents/MacOS/$(APPNAME) -else - -ln -sf $(PWD)/Main/$(APPNAME) $(APPNAME).app/Contents/MacOS/$(APPNAME) -endif - - cp $(PWD)/Resources/Icons/TrueCrypt.icns $(APPNAME).app/Contents/Resources - - echo -n APPLTRUE >$(APPNAME).app/Contents/PkgInfo - sed -e 's/_VERSION_/$(patsubst %a,%.1,$(patsubst %b,%.2,$(TC_VERSION)))/' ../Build/Resources/MacOSX/Info.plist.xml >$(APPNAME).app/Contents/Info.plist -endif - - -$(OBJS): $(PCH) - -Resources.o: $(RESOURCES) - -include $(BUILD_INC)/Makefile.inc +# +# Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +OBJS := +OBJS += Application.o +OBJS += CommandLineInterface.o +OBJS += FavoriteVolume.o +OBJS += LanguageStrings.o +OBJS += StringFormatter.o +OBJS += TextUserInterface.o +OBJS += UserInterface.o +OBJS += UserPreferences.o +OBJS += Xml.o +OBJS += Unix/Main.o +OBJS += Resources.o + +ifndef TC_NO_GUI +OBJS += FatalErrorHandler.o +OBJS += GraphicUserInterface.o +OBJS += VolumeHistory.o +OBJS += Forms/AboutDialog.o +OBJS += Forms/ChangePasswordDialog.o +OBJS += Forms/DeviceSelectionDialog.o +OBJS += Forms/EncryptionOptionsWizardPage.o +OBJS += Forms/EncryptionTestDialog.o +OBJS += Forms/FavoriteVolumesDialog.o +OBJS += Forms/Forms.o +OBJS += Forms/InfoWizardPage.o +OBJS += Forms/KeyfileGeneratorDialog.o +OBJS += Forms/KeyfilesDialog.o +OBJS += Forms/KeyfilesPanel.o +OBJS += Forms/LegalNoticesDialog.o +OBJS += Forms/MainFrame.o +OBJS += Forms/MountOptionsDialog.o +OBJS += Forms/NewSecurityTokenKeyfileDialog.o +OBJS += Forms/PreferencesDialog.o +OBJS += Forms/ProgressWizardPage.o +OBJS += Forms/RandomPoolEnrichmentDialog.o +OBJS += Forms/SecurityTokenKeyfilesDialog.o +OBJS += Forms/SelectDirectoryWizardPage.o +OBJS += Forms/VolumePasswordPanel.o +OBJS += Forms/VolumePropertiesDialog.o +OBJS += Forms/VolumeCreationProgressWizardPage.o +OBJS += Forms/VolumeCreationWizard.o +OBJS += Forms/VolumeFormatOptionsWizardPage.o +OBJS += Forms/VolumeLocationWizardPage.o +OBJS += Forms/VolumePasswordWizardPage.o +OBJS += Forms/VolumeSizeWizardPage.o +OBJS += Forms/WizardFrame.o +endif + +ifndef DISABLE_PRECOMPILED_HEADERS +PCH := SystemPrecompiled.h.gch +endif + +RESOURCES := +RESOURCES += ../License.txt.h +RESOURCES += ../Common/Language.xml.h +ifndef TC_NO_GUI +RESOURCES += ../Common/Textual_logo_96dpi.bmp.h +RESOURCES += ../Format/TrueCrypt_Wizard.bmp.h +RESOURCES += ../Mount/Drive_icon_96dpi.bmp.h +RESOURCES += ../Mount/Drive_icon_mask_96dpi.bmp.h +RESOURCES += ../Mount/Logo_96dpi.bmp.h +endif + +CXXFLAGS += -I$(BASE_DIR)/Main + + +#------ wxWidgets configuration ------ + +ifdef TC_NO_GUI +WX_CONFIG_LIBS := base +else +WX_CONFIG_LIBS := adv,core,base +endif + +ifeq "$(TC_BUILD_CONFIG)" "Release" + +CXXFLAGS += $(shell $(WX_CONFIG) $(WX_CONFIG_ARGS) --cxxflags) +WX_LIBS = $(shell $(WX_CONFIG) $(WX_CONFIG_ARGS) --libs $(WX_CONFIG_LIBS)) + +else + +CXXFLAGS += $(shell $(WX_CONFIG) --debug $(WX_CONFIG_ARGS) --cxxflags) +WX_LIBS = $(shell $(WX_CONFIG) --debug $(WX_CONFIG_ARGS) --libs $(WX_CONFIG_LIBS)) + +endif + + +#------ FUSE configuration ------ + +FUSE_LIBS = $(shell pkg-config fuse --libs) + + +#------ Executable ------ + +TC_VERSION = $(shell grep VERSION_STRING ../Common/Tcdefs.h | head -n 1 | cut -d'"' -f 2) + +$(APPNAME): $(LIBS) $(OBJS) + @echo Linking $@ + $(CXX) -o $(APPNAME) $(LFLAGS) $(OBJS) $(LIBS) $(FUSE_LIBS) $(WX_LIBS) + +ifeq "$(TC_BUILD_CONFIG)" "Release" +ifndef NOSTRIP + strip $(APPNAME) +endif + +ifndef NOTEST + ./$(APPNAME) --text --test >/dev/null || exit 1 +endif + +ifeq "$(PLATFORM_UNSUPPORTED)" "1" + @echo; echo "WARNING: This platform may be unsupported. To avoid possible serious problems, please read the chapter pertaining to $(PLATFORM) in Readme.txt."; echo +endif +endif + +ifeq "$(PLATFORM)" "MacOSX" + mkdir -p $(APPNAME).app/Contents/MacOS $(APPNAME).app/Contents/Resources + -rm -f $(APPNAME).app/Contents/MacOS/$(APPNAME) + +ifeq "$(TC_BUILD_CONFIG)" "Release" + cp $(PWD)/Main/$(APPNAME) $(APPNAME).app/Contents/MacOS/$(APPNAME) +else + -ln -sf $(PWD)/Main/$(APPNAME) $(APPNAME).app/Contents/MacOS/$(APPNAME) +endif + + cp $(PWD)/Resources/Icons/TrueCrypt.icns $(APPNAME).app/Contents/Resources + + echo -n APPLTRUE >$(APPNAME).app/Contents/PkgInfo + sed -e 's/_VERSION_/$(patsubst %a,%.1,$(patsubst %b,%.2,$(TC_VERSION)))/' ../Build/Resources/MacOSX/Info.plist.xml >$(APPNAME).app/Contents/Info.plist +endif + + +$(OBJS): $(PCH) + +Resources.o: $(RESOURCES) + +include $(BUILD_INC)/Makefile.inc diff --git a/Main/Resources.cpp b/Main/Resources.cpp index 894a00e..6c2de73 100644 --- a/Main/Resources.cpp +++ b/Main/Resources.cpp @@ -1,184 +1,184 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Platform/Platform.h" -#include "Resources.h" - -#ifdef TC_WINDOWS -#include "Main/resource.h" -#endif - -namespace TrueCrypt -{ - -#ifdef TC_WINDOWS - static ConstBufferPtr GetWindowsResource (const wchar_t *resourceType, const wchar_t *resourceName) - { - HGLOBAL hResL; - HRSRC hRes; - - hRes = FindResource (NULL, resourceName, resourceType); - throw_sys_if (!hRes); - hResL = LoadResource (NULL, hRes); - throw_sys_if (!hResL); - - const byte *resPtr = (const byte *) LockResource (hResL); - throw_sys_if (!resPtr); - - return ConstBufferPtr (resPtr, SizeofResource (NULL, hRes)); - } -#endif // TC_WINDOWS - - - string Resources::GetLanguageXml () - { -#ifdef TC_WINDOWS - ConstBufferPtr res = GetWindowsResource (L"XML", L"IDR_LANGUAGE"); - Buffer strBuf (res.Size() + 1); - strBuf.Zero(); - strBuf.CopyFrom (res); - return string (reinterpret_cast (strBuf.Ptr())); -#else - static const char LanguageXml[] = - { -# include "Common/Language.xml.h" - , 0 - }; - - return string (LanguageXml); -#endif - } - - string Resources::GetLegalNotices () - { -#ifdef TC_WINDOWS - ConstBufferPtr res = GetWindowsResource (L"TEXT", L"IDR_LICENSE"); - Buffer strBuf (res.Size() + 1); - strBuf.Zero(); - strBuf.CopyFrom (res); - return string (reinterpret_cast (strBuf.Ptr())); -#else - static const char License[] = - { -# include "License.txt.h" - , 0 - }; - - return string (License); -#endif - } - - -#ifndef TC_NO_GUI - - wxBitmap Resources::GetDriveIconBitmap () - { -#ifdef TC_WINDOWS - return wxBitmap (L"IDB_DRIVE_ICON", wxBITMAP_TYPE_BMP_RESOURCE).ConvertToImage().Resize (wxSize (16, 12), wxPoint (0, 0)); -#else - static const byte DriveIcon[] = - { -# include "Mount/Drive_icon_96dpi.bmp.h" - }; - - wxMemoryInputStream stream (DriveIcon, sizeof (DriveIcon)); - return wxBitmap (wxImage (stream).Resize (wxSize (16, 12), wxPoint (0, 0))); -#endif - } - - wxBitmap Resources::GetDriveIconMaskBitmap () - { -#ifdef TC_WINDOWS - wxImage image = wxBitmap (L"IDB_DRIVE_ICON_MASK", wxBITMAP_TYPE_BMP_RESOURCE).ConvertToImage().Resize (wxSize (16, 12), wxPoint (0, 0)); - return wxBitmap (image.ConvertToMono (0, 0, 0), 1); -#else - static const byte DriveIconMask[] = - { -# include "Mount/Drive_icon_mask_96dpi.bmp.h" - }; - - wxMemoryInputStream stream (DriveIconMask, sizeof (DriveIconMask)); - wxImage image (stream); - image.Resize (wxSize (16, 12), wxPoint (0, 0)); - -# ifdef __WXGTK__ - return wxBitmap (image.ConvertToMono (0, 0, 0), 1); -# else - return wxBitmap (image); -# endif -#endif - } - - - wxBitmap Resources::GetLogoBitmap () - { -#ifdef TC_WINDOWS - return wxBitmap (L"IDB_LOGO", wxBITMAP_TYPE_BMP_RESOURCE); -#else - static const byte Logo[] = - { -# include "Mount/Logo_96dpi.bmp.h" - }; - - wxMemoryInputStream stream (Logo, sizeof (Logo)); - return wxBitmap (wxImage (stream)); -#endif - } - - wxBitmap Resources::GetTextualLogoBitmap () - { -#ifdef TC_WINDOWS - return wxBitmap (L"IDB_TEXTUAL_LOGO", wxBITMAP_TYPE_BMP_RESOURCE); -#else - static const byte Logo[] = - { -# include "Common/Textual_logo_96dpi.bmp.h" - }; - - wxMemoryInputStream stream (Logo, sizeof (Logo)); - return wxBitmap (wxImage (stream)); -#endif - } - - wxIcon Resources::GetTrueCryptIcon () - { -#ifdef TC_WINDOWS - return wxIcon (L"IDI_TRUECRYPT_ICON", wxBITMAP_TYPE_ICO_RESOURCE, 16, 16); -#else -# include "Resources/Icons/TrueCrypt-16x16.xpm" - return wxIcon (TrueCryptIcon16x16); -#endif - } - - wxBitmap Resources::GetVolumeCreationWizardBitmap (int height) - { -#ifdef TC_WINDOWS - return wxBitmap (L"IDB_VOLUME_WIZARD_BITMAP", wxBITMAP_TYPE_BMP_RESOURCE); -#else - static const byte VolumeWizardIcon[] = - { -# include "Format/TrueCrypt_Wizard.bmp.h" - }; - - wxMemoryInputStream stream (VolumeWizardIcon, sizeof (VolumeWizardIcon)); - - wxImage image (stream); - if (height != -1) - { - double scaleFactor = double (height) / double (image.GetHeight()); - image.Rescale (int (image.GetWidth() * scaleFactor), int (image.GetHeight() * scaleFactor), wxIMAGE_QUALITY_HIGH); - } - - return wxBitmap (image); -#endif - } - -#endif // !TC_NO_GUI - -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Platform/Platform.h" +#include "Resources.h" + +#ifdef TC_WINDOWS +#include "Main/resource.h" +#endif + +namespace TrueCrypt +{ + +#ifdef TC_WINDOWS + static ConstBufferPtr GetWindowsResource (const wchar_t *resourceType, const wchar_t *resourceName) + { + HGLOBAL hResL; + HRSRC hRes; + + hRes = FindResource (NULL, resourceName, resourceType); + throw_sys_if (!hRes); + hResL = LoadResource (NULL, hRes); + throw_sys_if (!hResL); + + const byte *resPtr = (const byte *) LockResource (hResL); + throw_sys_if (!resPtr); + + return ConstBufferPtr (resPtr, SizeofResource (NULL, hRes)); + } +#endif // TC_WINDOWS + + + string Resources::GetLanguageXml () + { +#ifdef TC_WINDOWS + ConstBufferPtr res = GetWindowsResource (L"XML", L"IDR_LANGUAGE"); + Buffer strBuf (res.Size() + 1); + strBuf.Zero(); + strBuf.CopyFrom (res); + return string (reinterpret_cast (strBuf.Ptr())); +#else + static const char LanguageXml[] = + { +# include "Common/Language.xml.h" + , 0 + }; + + return string (LanguageXml); +#endif + } + + string Resources::GetLegalNotices () + { +#ifdef TC_WINDOWS + ConstBufferPtr res = GetWindowsResource (L"TEXT", L"IDR_LICENSE"); + Buffer strBuf (res.Size() + 1); + strBuf.Zero(); + strBuf.CopyFrom (res); + return string (reinterpret_cast (strBuf.Ptr())); +#else + static const char License[] = + { +# include "License.txt.h" + , 0 + }; + + return string (License); +#endif + } + + +#ifndef TC_NO_GUI + + wxBitmap Resources::GetDriveIconBitmap () + { +#ifdef TC_WINDOWS + return wxBitmap (L"IDB_DRIVE_ICON", wxBITMAP_TYPE_BMP_RESOURCE).ConvertToImage().Resize (wxSize (16, 12), wxPoint (0, 0)); +#else + static const byte DriveIcon[] = + { +# include "Mount/Drive_icon_96dpi.bmp.h" + }; + + wxMemoryInputStream stream (DriveIcon, sizeof (DriveIcon)); + return wxBitmap (wxImage (stream).Resize (wxSize (16, 12), wxPoint (0, 0))); +#endif + } + + wxBitmap Resources::GetDriveIconMaskBitmap () + { +#ifdef TC_WINDOWS + wxImage image = wxBitmap (L"IDB_DRIVE_ICON_MASK", wxBITMAP_TYPE_BMP_RESOURCE).ConvertToImage().Resize (wxSize (16, 12), wxPoint (0, 0)); + return wxBitmap (image.ConvertToMono (0, 0, 0), 1); +#else + static const byte DriveIconMask[] = + { +# include "Mount/Drive_icon_mask_96dpi.bmp.h" + }; + + wxMemoryInputStream stream (DriveIconMask, sizeof (DriveIconMask)); + wxImage image (stream); + image.Resize (wxSize (16, 12), wxPoint (0, 0)); + +# ifdef __WXGTK__ + return wxBitmap (image.ConvertToMono (0, 0, 0), 1); +# else + return wxBitmap (image); +# endif +#endif + } + + + wxBitmap Resources::GetLogoBitmap () + { +#ifdef TC_WINDOWS + return wxBitmap (L"IDB_LOGO", wxBITMAP_TYPE_BMP_RESOURCE); +#else + static const byte Logo[] = + { +# include "Mount/Logo_96dpi.bmp.h" + }; + + wxMemoryInputStream stream (Logo, sizeof (Logo)); + return wxBitmap (wxImage (stream)); +#endif + } + + wxBitmap Resources::GetTextualLogoBitmap () + { +#ifdef TC_WINDOWS + return wxBitmap (L"IDB_TEXTUAL_LOGO", wxBITMAP_TYPE_BMP_RESOURCE); +#else + static const byte Logo[] = + { +# include "Common/Textual_logo_96dpi.bmp.h" + }; + + wxMemoryInputStream stream (Logo, sizeof (Logo)); + return wxBitmap (wxImage (stream)); +#endif + } + + wxIcon Resources::GetTrueCryptIcon () + { +#ifdef TC_WINDOWS + return wxIcon (L"IDI_TRUECRYPT_ICON", wxBITMAP_TYPE_ICO_RESOURCE, 16, 16); +#else +# include "Resources/Icons/TrueCrypt-16x16.xpm" + return wxIcon (TrueCryptIcon16x16); +#endif + } + + wxBitmap Resources::GetVolumeCreationWizardBitmap (int height) + { +#ifdef TC_WINDOWS + return wxBitmap (L"IDB_VOLUME_WIZARD_BITMAP", wxBITMAP_TYPE_BMP_RESOURCE); +#else + static const byte VolumeWizardIcon[] = + { +# include "Format/TrueCrypt_Wizard.bmp.h" + }; + + wxMemoryInputStream stream (VolumeWizardIcon, sizeof (VolumeWizardIcon)); + + wxImage image (stream); + if (height != -1) + { + double scaleFactor = double (height) / double (image.GetHeight()); + image.Rescale (int (image.GetWidth() * scaleFactor), int (image.GetHeight() * scaleFactor), wxIMAGE_QUALITY_HIGH); + } + + return wxBitmap (image); +#endif + } + +#endif // !TC_NO_GUI + +} diff --git a/Main/Resources.h b/Main/Resources.h index a936117..0ff44be 100644 --- a/Main/Resources.h +++ b/Main/Resources.h @@ -1,33 +1,33 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Resources -#define TC_HEADER_Main_Resources - -#include "System.h" -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - class Resources - { - public: - static string GetLanguageXml (); - static string GetLegalNotices (); -#ifndef TC_NO_GUI - static wxBitmap GetDriveIconBitmap (); - static wxBitmap GetDriveIconMaskBitmap (); - static wxBitmap GetLogoBitmap (); - static wxBitmap GetTextualLogoBitmap (); - static wxIcon GetTrueCryptIcon (); - static wxBitmap GetVolumeCreationWizardBitmap (int height = -1); -#endif - }; -} - -#endif // TC_HEADER_Main_Resources +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Resources +#define TC_HEADER_Main_Resources + +#include "System.h" +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + class Resources + { + public: + static string GetLanguageXml (); + static string GetLegalNotices (); +#ifndef TC_NO_GUI + static wxBitmap GetDriveIconBitmap (); + static wxBitmap GetDriveIconMaskBitmap (); + static wxBitmap GetLogoBitmap (); + static wxBitmap GetTextualLogoBitmap (); + static wxIcon GetTrueCryptIcon (); + static wxBitmap GetVolumeCreationWizardBitmap (int height = -1); +#endif + }; +} + +#endif // TC_HEADER_Main_Resources diff --git a/Main/StringFormatter.cpp b/Main/StringFormatter.cpp index 692b992..a48f78a 100644 --- a/Main/StringFormatter.cpp +++ b/Main/StringFormatter.cpp @@ -1,88 +1,88 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "StringFormatter.h" -#include "UserInterfaceException.h" - -namespace TrueCrypt -{ - StringFormatter::StringFormatter (const wxString &format, StringFormatterArg arg0, StringFormatterArg arg1, StringFormatterArg arg2, StringFormatterArg arg3, StringFormatterArg arg4, StringFormatterArg arg5, StringFormatterArg arg6, StringFormatterArg arg7, StringFormatterArg arg8, StringFormatterArg arg9) - { - bool numberExpected = false; - bool endTagExpected = false; - foreach (wchar_t c, wstring (format)) - { - if (numberExpected) - { - endTagExpected = true; - bool err = false; - - switch (c) - { - case L'{': FormattedString += L'{'; endTagExpected = false; break; // Escaped { - - case L'0': FormattedString += arg0; err = arg0.IsEmpty(); break; - case L'1': FormattedString += arg1; err = arg1.IsEmpty(); break; - case L'2': FormattedString += arg2; err = arg2.IsEmpty(); break; - case L'3': FormattedString += arg3; err = arg3.IsEmpty(); break; - case L'4': FormattedString += arg4; err = arg4.IsEmpty(); break; - case L'5': FormattedString += arg5; err = arg5.IsEmpty(); break; - case L'6': FormattedString += arg6; err = arg6.IsEmpty(); break; - case L'7': FormattedString += arg7; err = arg7.IsEmpty(); break; - case L'8': FormattedString += arg8; err = arg8.IsEmpty(); break; - case L'9': FormattedString += arg9; err = arg9.IsEmpty(); break; - - default: err = true; break; - } - - if (err) - throw StringFormatterException (SRC_POS, wstring (format)); - - numberExpected = false; - } - else if (endTagExpected) - { - if (c != L'}') - throw StringFormatterException (SRC_POS, wstring (format)); - - endTagExpected = false; - } - else if (c == L'{') - { - numberExpected = true; - } - else if (c == L'}') - { - FormattedString += c; - endTagExpected = true; - } - else - FormattedString += c; - } - - if (numberExpected - || endTagExpected - || (!arg0.WasReferenced() && !arg0.IsEmpty()) - || (!arg1.WasReferenced() && !arg1.IsEmpty()) - || (!arg2.WasReferenced() && !arg2.IsEmpty()) - || (!arg3.WasReferenced() && !arg3.IsEmpty()) - || (!arg4.WasReferenced() && !arg4.IsEmpty()) - || (!arg5.WasReferenced() && !arg5.IsEmpty()) - || (!arg6.WasReferenced() && !arg6.IsEmpty()) - || (!arg7.WasReferenced() && !arg7.IsEmpty()) - || (!arg8.WasReferenced() && !arg8.IsEmpty()) - || (!arg9.WasReferenced() && !arg9.IsEmpty()) - ) - throw StringFormatterException (SRC_POS, wstring (format)); - } - - StringFormatter::~StringFormatter () - { - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "StringFormatter.h" +#include "UserInterfaceException.h" + +namespace TrueCrypt +{ + StringFormatter::StringFormatter (const wxString &format, StringFormatterArg arg0, StringFormatterArg arg1, StringFormatterArg arg2, StringFormatterArg arg3, StringFormatterArg arg4, StringFormatterArg arg5, StringFormatterArg arg6, StringFormatterArg arg7, StringFormatterArg arg8, StringFormatterArg arg9) + { + bool numberExpected = false; + bool endTagExpected = false; + foreach (wchar_t c, wstring (format)) + { + if (numberExpected) + { + endTagExpected = true; + bool err = false; + + switch (c) + { + case L'{': FormattedString += L'{'; endTagExpected = false; break; // Escaped { + + case L'0': FormattedString += arg0; err = arg0.IsEmpty(); break; + case L'1': FormattedString += arg1; err = arg1.IsEmpty(); break; + case L'2': FormattedString += arg2; err = arg2.IsEmpty(); break; + case L'3': FormattedString += arg3; err = arg3.IsEmpty(); break; + case L'4': FormattedString += arg4; err = arg4.IsEmpty(); break; + case L'5': FormattedString += arg5; err = arg5.IsEmpty(); break; + case L'6': FormattedString += arg6; err = arg6.IsEmpty(); break; + case L'7': FormattedString += arg7; err = arg7.IsEmpty(); break; + case L'8': FormattedString += arg8; err = arg8.IsEmpty(); break; + case L'9': FormattedString += arg9; err = arg9.IsEmpty(); break; + + default: err = true; break; + } + + if (err) + throw StringFormatterException (SRC_POS, wstring (format)); + + numberExpected = false; + } + else if (endTagExpected) + { + if (c != L'}') + throw StringFormatterException (SRC_POS, wstring (format)); + + endTagExpected = false; + } + else if (c == L'{') + { + numberExpected = true; + } + else if (c == L'}') + { + FormattedString += c; + endTagExpected = true; + } + else + FormattedString += c; + } + + if (numberExpected + || endTagExpected + || (!arg0.WasReferenced() && !arg0.IsEmpty()) + || (!arg1.WasReferenced() && !arg1.IsEmpty()) + || (!arg2.WasReferenced() && !arg2.IsEmpty()) + || (!arg3.WasReferenced() && !arg3.IsEmpty()) + || (!arg4.WasReferenced() && !arg4.IsEmpty()) + || (!arg5.WasReferenced() && !arg5.IsEmpty()) + || (!arg6.WasReferenced() && !arg6.IsEmpty()) + || (!arg7.WasReferenced() && !arg7.IsEmpty()) + || (!arg8.WasReferenced() && !arg8.IsEmpty()) + || (!arg9.WasReferenced() && !arg9.IsEmpty()) + ) + throw StringFormatterException (SRC_POS, wstring (format)); + } + + StringFormatter::~StringFormatter () + { + } +} diff --git a/Main/StringFormatter.h b/Main/StringFormatter.h index 959edf3..238036b 100644 --- a/Main/StringFormatter.h +++ b/Main/StringFormatter.h @@ -1,64 +1,64 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_StringFormatter -#define TC_HEADER_Main_StringFormatter - -#include "System.h" -#include "Main.h" - -namespace TrueCrypt -{ - class StringFormatterArg - { - public: - StringFormatterArg () : Empty (true) { } - - StringFormatterArg (const char c) : Empty (false) { string s; s += c; StringArg = StringConverter::ToWide (s); } - StringFormatterArg (const wchar_t c) : Empty (false), Referenced (false), StringArg (c) { } - StringFormatterArg (const char *str) : Empty (false), Referenced (false), StringArg (StringConverter::ToWide (str)) { } - StringFormatterArg (const wchar_t *str) : Empty (false), Referenced (false), StringArg (str) { } - StringFormatterArg (const string &str) : Empty (false), Referenced (false), StringArg (StringConverter::ToWide (str)) { } - StringFormatterArg (const wstring &str) : Empty (false), Referenced (false), StringArg (str) { } - StringFormatterArg (const wxString &str) : Empty (false), Referenced (false), StringArg (str) { } - StringFormatterArg (int32 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } - StringFormatterArg (uint32 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } - StringFormatterArg (int64 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } - StringFormatterArg (uint64 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } - - operator wxString () { Referenced = true; return StringArg; } - - bool IsEmpty () const { return Empty; } - bool WasReferenced() const { return Referenced; } - - protected: - bool Empty; - bool Referenced; - wxString StringArg; - }; - - class StringFormatter - { - public: - StringFormatter (const wxString &format, StringFormatterArg arg0 = StringFormatterArg(), StringFormatterArg arg1 = StringFormatterArg(), StringFormatterArg arg2 = StringFormatterArg(), StringFormatterArg arg3 = StringFormatterArg(), StringFormatterArg arg4 = StringFormatterArg(), StringFormatterArg arg5 = StringFormatterArg(), StringFormatterArg arg6 = StringFormatterArg(), StringFormatterArg arg7 = StringFormatterArg(), StringFormatterArg arg8 = StringFormatterArg(), StringFormatterArg arg9 = StringFormatterArg()); - virtual ~StringFormatter (); - - operator wstring () const { return wstring (FormattedString); } - operator wxString () const { return FormattedString; } - operator StringFormatterArg () const { return FormattedString; } - - protected: - wxString FormattedString; - - private: - StringFormatter (const StringFormatter &); - StringFormatter &operator= (const StringFormatter &); - }; -} - -#endif // TC_HEADER_Main_StringFormatter +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_StringFormatter +#define TC_HEADER_Main_StringFormatter + +#include "System.h" +#include "Main.h" + +namespace TrueCrypt +{ + class StringFormatterArg + { + public: + StringFormatterArg () : Empty (true) { } + + StringFormatterArg (const char c) : Empty (false) { string s; s += c; StringArg = StringConverter::ToWide (s); } + StringFormatterArg (const wchar_t c) : Empty (false), Referenced (false), StringArg (c) { } + StringFormatterArg (const char *str) : Empty (false), Referenced (false), StringArg (StringConverter::ToWide (str)) { } + StringFormatterArg (const wchar_t *str) : Empty (false), Referenced (false), StringArg (str) { } + StringFormatterArg (const string &str) : Empty (false), Referenced (false), StringArg (StringConverter::ToWide (str)) { } + StringFormatterArg (const wstring &str) : Empty (false), Referenced (false), StringArg (str) { } + StringFormatterArg (const wxString &str) : Empty (false), Referenced (false), StringArg (str) { } + StringFormatterArg (int32 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } + StringFormatterArg (uint32 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } + StringFormatterArg (int64 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } + StringFormatterArg (uint64 number) : Empty (false), Referenced (false), StringArg (StringConverter::FromNumber (number)) { } + + operator wxString () { Referenced = true; return StringArg; } + + bool IsEmpty () const { return Empty; } + bool WasReferenced() const { return Referenced; } + + protected: + bool Empty; + bool Referenced; + wxString StringArg; + }; + + class StringFormatter + { + public: + StringFormatter (const wxString &format, StringFormatterArg arg0 = StringFormatterArg(), StringFormatterArg arg1 = StringFormatterArg(), StringFormatterArg arg2 = StringFormatterArg(), StringFormatterArg arg3 = StringFormatterArg(), StringFormatterArg arg4 = StringFormatterArg(), StringFormatterArg arg5 = StringFormatterArg(), StringFormatterArg arg6 = StringFormatterArg(), StringFormatterArg arg7 = StringFormatterArg(), StringFormatterArg arg8 = StringFormatterArg(), StringFormatterArg arg9 = StringFormatterArg()); + virtual ~StringFormatter (); + + operator wstring () const { return wstring (FormattedString); } + operator wxString () const { return FormattedString; } + operator StringFormatterArg () const { return FormattedString; } + + protected: + wxString FormattedString; + + private: + StringFormatter (const StringFormatter &); + StringFormatter &operator= (const StringFormatter &); + }; +} + +#endif // TC_HEADER_Main_StringFormatter diff --git a/Main/System.cpp b/Main/System.cpp index 98cbdf9..cf1eac3 100644 --- a/Main/System.cpp +++ b/Main/System.cpp @@ -1,10 +1,10 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -// Precompiled header +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +// Precompiled header #include "System.h" \ No newline at end of file diff --git a/Main/System.h b/Main/System.h index c16087d..914099a 100644 --- a/Main/System.h +++ b/Main/System.h @@ -1,69 +1,69 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_System -#define TC_HEADER_Main_System - -#ifndef TC_WINDOWS - -#include "SystemPrecompiled.h" - -#else - -#ifndef WINVER -#define WINVER 0x0501 -#endif - -#ifndef TC_LOCAL_WIN32_WINNT_OVERRIDE -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif -#endif - -#ifndef _WIN32_WINDOWS -#define _WIN32_WINDOWS 0x0410 -#endif - -#ifndef _WIN32_IE -#define _WIN32_IE 0x0600 -#endif - -#define WIN32_LEAN_AND_MEAN - -#ifndef UNICODE -#define UNICODE -#endif - -#ifndef _UNICODE -#define _UNICODE -#endif _UNICODE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#endif - -#endif // TC_HEADER_Main_System +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_System +#define TC_HEADER_Main_System + +#ifndef TC_WINDOWS + +#include "SystemPrecompiled.h" + +#else + +#ifndef WINVER +#define WINVER 0x0501 +#endif + +#ifndef TC_LOCAL_WIN32_WINNT_OVERRIDE +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 +# endif +#endif + +#ifndef _WIN32_WINDOWS +#define _WIN32_WINDOWS 0x0410 +#endif + +#ifndef _WIN32_IE +#define _WIN32_IE 0x0600 +#endif + +#define WIN32_LEAN_AND_MEAN + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef _UNICODE +#define _UNICODE +#endif _UNICODE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#endif + +#endif // TC_HEADER_Main_System diff --git a/Main/SystemPrecompiled.h b/Main/SystemPrecompiled.h index f783c5e..afb78f1 100644 --- a/Main/SystemPrecompiled.h +++ b/Main/SystemPrecompiled.h @@ -1,29 +1,29 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include -#include - -#ifndef TC_NO_GUI -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include +#include + +#ifndef TC_NO_GUI +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include diff --git a/Main/TextUserInterface.cpp b/Main/TextUserInterface.cpp index e742ef2..0d372d8 100644 --- a/Main/TextUserInterface.cpp +++ b/Main/TextUserInterface.cpp @@ -1,1437 +1,1462 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#ifdef TC_UNIX -#include -#include -#include -#include -#include -#endif - -#include "Common/SecurityToken.h" -#include "Core/RandomNumberGenerator.h" -#include "Application.h" -#include "TextUserInterface.h" - -namespace TrueCrypt -{ - TextUserInterface::TextUserInterface () - { -#ifdef TC_UNIX - signal (SIGHUP, OnSignal); - signal (SIGINT, OnSignal); - signal (SIGQUIT, OnSignal); - signal (SIGTERM, OnSignal); - - struct stat statBuf; - if (fstat (0, &statBuf) != -1) -#endif - { - FInputStream.reset (new wxFFileInputStream (stdin)); - TextInputStream.reset (new wxTextInputStream (*FInputStream)); - } - } - - TextUserInterface::~TextUserInterface () - { - try - { - if (RandomNumberGenerator::IsRunning()) - RandomNumberGenerator::Stop(); - } - catch (...) { } - -#ifdef TC_UNIX - signal (SIGHUP, SIG_DFL); - signal (SIGINT, SIG_DFL); - signal (SIGQUIT, SIG_DFL); - signal (SIGTERM, SIG_DFL); -#endif - } - - FilePath TextUserInterface::AskFilePath (const wxString &message) const - { - return AskString (!message.empty() ? message : wxString (_("Enter filename: "))); - } - - shared_ptr TextUserInterface::AskKeyfiles (const wxString &message) const - { - wxString msg = _("Enter keyfile"); - if (!message.empty()) - msg = message; - - make_shared_auto (KeyfileList, keyfiles); - - wxString s; - wxString m = msg + L" [" + _("none") + L"]: "; - while (!(s = AskString (m)).empty()) - { - keyfiles->push_back (make_shared (wstring (s))); - m = msg + L" [" + _("finish") + L"]: "; - } - - return keyfiles; - } - - shared_ptr TextUserInterface::AskPassword (const wxString &message, bool verify) const - { - wxString msg = LangString["ENTER_PASSWORD"] + L": "; - if (!message.empty()) - msg = message + L": "; - - SetTerminalEcho (false); - finally_do ({ TextUserInterface::SetTerminalEcho (true); }); - - wchar_t passwordBuf[4096]; - finally_do_arg (BufferPtr, BufferPtr (reinterpret_cast (passwordBuf), sizeof (passwordBuf)), { finally_arg.Erase(); }); - - make_shared_auto (VolumePassword, password); - - bool verPhase = false; - while (true) - { - ShowString (verPhase ? wxString (_("Re-enter password: ")) : msg); - - wxString passwordStr; - ReadInputStreamLine (passwordStr); - - size_t length = passwordStr.size(); - - ShowString (L"\n"); - - if (length < 1) - { - password->Set (passwordBuf, 0); - return password; - } - - for (size_t i = 0; i < length && i < VolumePassword::MaxSize; ++i) - { - passwordBuf[i] = (wchar_t) passwordStr[i]; - const_cast (passwordStr.c_str())[i] = L'X'; - } - - if (verify && verPhase) - { - make_shared_auto (VolumePassword, verPassword); - verPassword->Set (passwordBuf, length); - - if (*password != *verPassword) - { - ShowInfo (_("Passwords do not match.")); - ShowString (L"\n"); - verPhase = false; - continue; - } - } - - password->Set (passwordBuf, length); - - if (!verPhase) - { - try - { - password->CheckPortability(); - } - catch (UnportablePassword &e) - { - if (verify) - { - ShowError (e); - verPhase = false; - continue; - } - - ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); - } - - if (verify) - { - if (password->Size() < VolumePassword::WarningSizeThreshold) - { - SetTerminalEcho (true); - finally_do ({ TextUserInterface::SetTerminalEcho (false); }); - - if (!AskYesNo (LangString ["PASSWORD_LENGTH_WARNING"], false, true)) - { - ShowString (L"\n"); - continue; - } - ShowString (L"\n"); - } - } - } - - if (!verify || verPhase) - return password; - - if (!verPhase) - verPhase = true; - } - - return password; - } - - ssize_t TextUserInterface::AskSelection (ssize_t optionCount, ssize_t defaultOption) const - { - while (true) - { - wstring selectionStr = AskString (defaultOption == -1 ? wxString (_("Select: ")) : wxString (wstring (StringFormatter (_("Select [{0}]: "), (uint32) defaultOption)))); - ssize_t selection; - - if (selectionStr.empty() && defaultOption != -1) - return defaultOption; - - try - { - selection = StringConverter::ToUInt32 (selectionStr); - } - catch (...) - { - continue; - } - - if (selection > 0 && selection <= optionCount) - return selection; - } - } - - wstring TextUserInterface::AskString (const wxString &message) const - { - ShowString (message); - return wstring (ReadInputStreamLine()); - } - - bool TextUserInterface::AskYesNo (const wxString &message, bool defaultYes, bool warning) const - { - while (true) - { - wxString s = AskString (StringFormatter (L"{0} (y={1}/n={2}) [{3}]: ", - message, LangString["YES"], LangString["NO"], LangString[defaultYes ? "YES" : "NO"])); - - if (s.IsSameAs (L'n', false) || s.IsSameAs (L"no", false) || (!defaultYes && s.empty())) - return false; - - if (s.IsSameAs (L'y', false) || s.IsSameAs (L"yes", false) || (defaultYes && s.empty())) - return true; - }; - } - - shared_ptr TextUserInterface::AskVolumePath (const wxString &message) const - { - return make_shared (AskString (message.empty() ? wxString (_("Enter volume path: ")) : message)); - } - - void TextUserInterface::BackupVolumeHeaders (shared_ptr volumePath) const - { - if (!volumePath) - volumePath = AskVolumePath(); - - if (!volumePath) - throw UserAbort (SRC_POS); - -#ifdef TC_WINDOWS - if (Core->IsVolumeMounted (*volumePath)) - throw_err (LangString["DISMOUNT_FIRST"]); -#endif - - ShowInfo ("EXTERNAL_VOL_HEADER_BAK_FIRST_INFO"); - - shared_ptr normalVolume; - shared_ptr hiddenVolume; - - MountOptions normalVolumeMountOptions; - MountOptions hiddenVolumeMountOptions; - - normalVolumeMountOptions.Path = volumePath; - hiddenVolumeMountOptions.Path = volumePath; - - VolumeType::Enum volumeType = VolumeType::Normal; - - // Open both types of volumes - while (true) - { - shared_ptr volume; - MountOptions *options = (volumeType == VolumeType::Hidden ? &hiddenVolumeMountOptions : &normalVolumeMountOptions); - - while (!volume) - { - ShowString (L"\n"); - options->Password = AskPassword (LangString[volumeType == VolumeType::Hidden ? "ENTER_HIDDEN_VOL_PASSWORD" : "ENTER_NORMAL_VOL_PASSWORD"]); - options->Keyfiles = AskKeyfiles(); - - try - { - volume = Core->OpenVolume ( - options->Path, - options->PreserveTimestamps, - options->Password, - options->Keyfiles, - options->Protection, - options->ProtectionPassword, - options->ProtectionKeyfiles, - true, - volumeType, - options->UseBackupHeaders - ); - } - catch (PasswordException &e) - { - ShowInfo (e); - } - } - - if (volumeType == VolumeType::Hidden) - hiddenVolume = volume; - else - normalVolume = volume; - - // Ask whether a hidden volume is present - if (volumeType == VolumeType::Normal && AskYesNo (L"\n" + LangString["DOES_VOLUME_CONTAIN_HIDDEN"])) - { - volumeType = VolumeType::Hidden; - continue; - } - - break; - } - - if (hiddenVolume) - { - if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV1Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV1Hidden)) - throw ParameterIncorrect (SRC_POS); - - if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV2Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV2Hidden)) - throw ParameterIncorrect (SRC_POS); - } - - // Ask user to select backup file path - wxString confirmMsg = L"\n" + LangString["CONFIRM_VOL_HEADER_BAK"] + L"\n"; - confirmMsg.Replace (L"%hs", L"%s"); - - if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true)) - return; - - ShowString (L"\n"); - - FilePath filePath = AskFilePath(); - if (filePath.IsEmpty()) - throw UserAbort (SRC_POS); - - File backupFile; - backupFile.Open (filePath, File::CreateWrite); - - RandomNumberGenerator::Start(); - UserEnrichRandomPool(); - - // Re-encrypt volume header - SecureBuffer newHeaderBuffer (normalVolume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Keyfiles); - - backupFile.Write (newHeaderBuffer); - - if (hiddenVolume) - { - // Re-encrypt hidden volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Keyfiles); - } - else - { - // Store random data in place of hidden volume header - shared_ptr ea = normalVolume->GetEncryptionAlgorithm(); - Core->RandomizeEncryptionAlgorithmKey (ea); - ea->Encrypt (newHeaderBuffer); - } - - backupFile.Write (newHeaderBuffer); - - ShowString (L"\n"); - ShowInfo ("VOL_HEADER_BACKED_UP"); - } - - void TextUserInterface::ChangePassword (shared_ptr volumePath, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newHash) const - { - shared_ptr volume; - - // Volume path - if (!volumePath.get()) - { - if (Preferences.NonInteractive) - throw MissingArgument (SRC_POS); - - volumePath = AskVolumePath (); - } - - if (volumePath->IsEmpty()) - throw UserAbort (SRC_POS); - - bool passwordInteractive = !password.get(); - bool keyfilesInteractive = !keyfiles.get(); - - while (true) - { - // Current password - if (!passwordInteractive) - { - try - { - password->CheckPortability(); - } - catch (UnportablePassword &) - { - ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); - } - } - else if (!Preferences.NonInteractive) - { - password = AskPassword (); - } - - // Current keyfiles - try - { - if (keyfilesInteractive) - { - // Ask for keyfiles only if required - try - { - keyfiles.reset (new KeyfileList); - volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, keyfiles); - } - catch (PasswordException&) - { - if (!Preferences.NonInteractive) - keyfiles = AskKeyfiles (); - } - } - - if (!volume.get()) - volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, keyfiles); - } - catch (PasswordException &e) - { - if (Preferences.NonInteractive || !passwordInteractive || !keyfilesInteractive) - throw; - - ShowInfo (e); - continue; - } - - break; - } - - // New password - if (newPassword.get()) - newPassword->CheckPortability(); - else if (!Preferences.NonInteractive) - newPassword = AskPassword (_("Enter new password"), true); - - // New keyfiles - if (!newKeyfiles.get() && !Preferences.NonInteractive) - { - if (keyfiles.get() && keyfiles->size() > 0 && AskYesNo (_("Keep current keyfiles?"), true)) - newKeyfiles = keyfiles; - else - newKeyfiles = AskKeyfiles (_("Enter new keyfile")); - } - - UserEnrichRandomPool(); - - Core->ChangePassword (volume, newPassword, newKeyfiles, - newHash ? Pkcs5Kdf::GetAlgorithm (*newHash) : shared_ptr ()); - - ShowInfo ("PASSWORD_CHANGED"); - } - - void TextUserInterface::CreateKeyfile (shared_ptr keyfilePath) const - { - FilePath path; - - RandomNumberGenerator::Start(); - UserEnrichRandomPool(); - - if (keyfilePath) - { - Core->CreateKeyfile (*keyfilePath); - } - else - { - wstring fileName = AskFilePath(); - if (fileName.empty()) - return; - - Core->CreateKeyfile (fileName); - } - - ShowInfo ("KEYFILE_CREATED"); - } - - void TextUserInterface::CreateVolume (shared_ptr options) const - { - // Volume type - if (options->Type == VolumeType::Unknown) - { - if (Preferences.NonInteractive) - { - options->Type = VolumeType::Normal; - } - else - { - ShowString (_("Volume type:\n 1) Normal\n 2) Hidden\n")); - - switch (AskSelection (2, 1)) - { - case 1: - options->Type = VolumeType::Normal; - break; - - case 2: - options->Type = VolumeType::Hidden; - break; - } - } - } - - shared_ptr layout; - if (options->Type == VolumeType::Hidden) - layout.reset (new VolumeLayoutV2Hidden); - else - layout.reset (new VolumeLayoutV2Normal); - - if (!Preferences.NonInteractive && options->Type == VolumeType::Hidden) - ShowInfo (_("\nIMPORTANT: Inexperienced users should use the graphical user interface to create a hidden volume. When using the text interface, the procedure described in the command line help must be followed to create a hidden volume.")); - - // Volume path - if (options->Path.IsEmpty()) - { - if (Preferences.NonInteractive) - throw MissingArgument (SRC_POS); - - do - { - ShowString (L"\n"); - options->Path = VolumePath (*AskVolumePath()); - } while (options->Path.IsEmpty()); - } - - // Volume size - uint64 hostSize = 0; - - if (options->Type == VolumeType::Hidden) - { - FilesystemPath fsPath (wstring (options->Path)); - - if (fsPath.IsFile()) - { - File file; - file.Open (fsPath); - hostSize = file.Length(); - } - else if (fsPath.IsDevice()) - { - hostSize = Core->GetDeviceSize (fsPath); - } - else - { - throw_err (_("Hidden volume can be created only in an existing file or device.")); - } - - if (hostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE) - throw_err (StringFormatter (_("Minimum outer volume size is {0}."), SizeToString (TC_MIN_HIDDEN_VOLUME_HOST_SIZE + 512))); - } - - uint64 minVolumeSize = options->Type == VolumeType::Hidden ? TC_MIN_HIDDEN_VOLUME_SIZE : TC_MIN_VOLUME_SIZE; - - if (options->Path.IsDevice() && options->Type != VolumeType::Hidden) - { - if (options->Size != 0) - throw_err (_("Volume size cannot be changed for device-hosted volumes.")); - - options->Size = Core->GetDeviceSize (options->Path); - } - else - { - options->Quick = false; - - while (options->Size == 0) - { - if (Preferences.NonInteractive) - throw MissingArgument (SRC_POS); - - wstring sizeStr = AskString (options->Type == VolumeType::Hidden ? _("\nEnter hidden volume size (sizeK/size[M]/sizeG): ") : _("\nEnter volume size (sizeK/size[M]/sizeG): ")); - int multiplier = 1024 * 1024; - - if (sizeStr.find (L"K") != string::npos) - { - multiplier = 1024; - sizeStr.resize (sizeStr.size() - 1); - } - else if (sizeStr.find (L"M") != string::npos) - { - sizeStr.resize (sizeStr.size() - 1); - } - else if (sizeStr.find (L"G") != string::npos) - { - multiplier = 1024 * 1024 * 1024; - sizeStr.resize (sizeStr.size() - 1); - } - - try - { - options->Size = StringConverter::ToUInt64 (sizeStr); - options->Size *= multiplier; - } - catch (...) - { - continue; - } - - if (options->Size < minVolumeSize) - { - ShowError (StringFormatter (_("Minimum volume size is {0}."), SizeToString (minVolumeSize + 512))); - options->Size = 0; - } - - if (options->Type == VolumeType::Hidden) - { - uint64 maxHiddenVolumeSize = VolumeLayoutV2Normal().GetMaxDataSize (hostSize) - TC_MIN_FAT_FS_SIZE; - - if (options->Size > maxHiddenVolumeSize) - { - ShowError (StringFormatter (_("Maximum volume size is {0}."), SizeToString (maxHiddenVolumeSize))); - options->Size = 0; - } - } - } - } - - if (options->Size < minVolumeSize) - throw_err (_("Incorrect volume size")); - - if (options->Type == VolumeType::Hidden) - options->Quick = true; - - // Encryption algorithm - if (!options->EA) - { - if (Preferences.NonInteractive) - throw MissingArgument (SRC_POS); - - ShowInfo (wxString (L"\n") + LangString["ENCRYPTION_ALGORITHM_LV"] + L":"); - - vector < shared_ptr > encryptionAlgorithms; - foreach (shared_ptr ea, EncryptionAlgorithm::GetAvailableAlgorithms()) - { - if (!ea->IsDeprecated()) - { - ShowString (StringFormatter (L" {0}) {1}\n", (uint32) encryptionAlgorithms.size() + 1, ea->GetName())); - encryptionAlgorithms.push_back (ea); - } - } - - - options->EA = encryptionAlgorithms[AskSelection (encryptionAlgorithms.size(), 1) - 1]; - } - - // Hash algorithm - if (!options->VolumeHeaderKdf) - { - if (Preferences.NonInteractive) - throw MissingArgument (SRC_POS); - - ShowInfo (_("\nHash algorithm:")); - - vector < shared_ptr > hashes; - foreach (shared_ptr hash, Hash::GetAvailableAlgorithms()) - { - if (!hash->IsDeprecated()) - { - ShowString (StringFormatter (L" {0}) {1}\n", (uint32) hashes.size() + 1, hash->GetName())); - hashes.push_back (hash); - } - } - - shared_ptr selectedHash = hashes[AskSelection (hashes.size(), 1) - 1]; - RandomNumberGenerator::SetHash (selectedHash); - options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*selectedHash); - - } - - // Filesystem - options->FilesystemClusterSize = 0; - - if (options->Filesystem == VolumeCreationOptions::FilesystemType::Unknown) - { - if (Preferences.NonInteractive) - { - options->Filesystem = VolumeCreationOptions::FilesystemType::FAT; - } - else - { - ShowInfo (_("\nFilesystem:\n 1) FAT\n 2) None")); - - switch (AskSelection (2, 1)) - { - case 1: - options->Filesystem = VolumeCreationOptions::FilesystemType::FAT; - break; - - case 2: - options->Filesystem = VolumeCreationOptions::FilesystemType::None; - break; - } - } - } - - uint64 filesystemSize = layout->GetMaxDataSize (options->Size); - - if (options->Filesystem == VolumeCreationOptions::FilesystemType::FAT - && (filesystemSize < TC_MIN_FAT_FS_SIZE || filesystemSize > TC_MAX_FAT_FS_SIZE)) - { - throw_err (_("Specified volume size cannot be used with FAT filesystem.")); - } - - // Password - if (!options->Password && !Preferences.NonInteractive) - { - ShowString (L"\n"); - options->Password = AskPassword (_("Enter password"), true); - } - - if (options->Password) - options->Password->CheckPortability(); - - // Keyfiles - if (!options->Keyfiles && !Preferences.NonInteractive) - { - ShowString (L"\n"); - options->Keyfiles = AskKeyfiles (_("Enter keyfile path")); - } - - if ((!options->Keyfiles || options->Keyfiles->empty()) - && (!options->Password || options->Password->IsEmpty())) - { - throw_err (_("Password cannot be empty when no keyfile is specified")); - } - - // Random data - RandomNumberGenerator::Start(); - UserEnrichRandomPool(); - - ShowString (L"\n"); - wxLongLong startTime = wxGetLocalTimeMillis(); - - VolumeCreator creator; - creator.CreateVolume (options); - - bool volumeCreated = false; - while (!volumeCreated) - { - VolumeCreator::ProgressInfo progress = creator.GetProgressInfo(); - - wxLongLong timeDiff = wxGetLocalTimeMillis() - startTime; - if (timeDiff.GetValue() > 0) - { - uint64 speed = progress.SizeDone * 1000 / timeDiff.GetValue(); - - volumeCreated = !progress.CreationInProgress; - - ShowString (wxString::Format (L"\rDone: %7.3f%% Speed: %9s Left: %s ", - 100.0 - double (options->Size - progress.SizeDone) / (double (options->Size) / 100.0), - speed > 0 ? SpeedToString (speed).c_str() : L" ", - speed > 0 ? TimeSpanToString ((options->Size - progress.SizeDone) / speed).c_str() : L"")); - } - - Thread::Sleep (100); - } - - ShowString (L"\n\n"); - creator.CheckResult(); - - ShowInfo (options->Type == VolumeType::Hidden ? "HIDVOL_FORMAT_FINISHED_HELP" : "FORMAT_FINISHED_INFO"); - } - - void TextUserInterface::DeleteSecurityTokenKeyfiles () const - { - shared_ptr keyfiles = AskKeyfiles(); - if (keyfiles->empty()) - throw UserAbort(); - - foreach_ref (const Keyfile &keyfile, *keyfiles) - { - SecurityToken::DeleteKeyfile (SecurityTokenKeyfilePath (FilePath (keyfile))); - } - } - - void TextUserInterface::DoShowError (const wxString &message) const - { - wcerr << L"Error: " << static_cast (message) << endl; - } - - void TextUserInterface::DoShowInfo (const wxString &message) const - { - wcout << static_cast (message) << endl; - } - - void TextUserInterface::DoShowString (const wxString &str) const - { - wcout << str.c_str(); - } - - void TextUserInterface::DoShowWarning (const wxString &message) const - { - wcerr << L"Warning: " << static_cast (message) << endl; - } - - shared_ptr TextUserInterface::GetAdminPasswordRequestHandler () - { - struct AdminPasswordRequestHandler : public GetStringFunctor - { - AdminPasswordRequestHandler (TextUserInterface *userInterface) : UI (userInterface) { } - virtual void operator() (string &passwordStr) - { - UI->ShowString (_("Enter your user password or administrator password: ")); - - TextUserInterface::SetTerminalEcho (false); - finally_do ({ TextUserInterface::SetTerminalEcho (true); }); - - wstring wPassword (UI->ReadInputStreamLine()); - finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); - - UI->ShowString (L"\n"); - - StringConverter::ToSingle (wPassword, passwordStr); - } - TextUserInterface *UI; - }; - - return shared_ptr (new AdminPasswordRequestHandler (this)); - } - - void TextUserInterface::ImportSecurityTokenKeyfiles () const - { - list tokens = SecurityToken::GetAvailableTokens(); - - if (tokens.empty()) - throw_err (LangString ["NO_TOKENS_FOUND"]); - - CK_SLOT_ID slotId; - - if (tokens.size() == 1) - { - slotId = tokens.front().SlotId; - } - else - { - foreach (const SecurityTokenInfo &token, tokens) - { - wstringstream tokenLabel; - tokenLabel << L"[" << token.SlotId << L"] " << LangString["TOKEN_SLOT_ID"].c_str() << L" " << token.SlotId << L" " << token.Label; - - ShowInfo (tokenLabel.str()); - } - - slotId = (CK_SLOT_ID) AskSelection (tokens.back().SlotId, tokens.front().SlotId); - } - - shared_ptr keyfiles = AskKeyfiles(); - if (keyfiles->empty()) - throw UserAbort(); - - foreach_ref (const Keyfile &keyfilePath, *keyfiles) - { - File keyfile; - keyfile.Open (keyfilePath, File::OpenRead, File::ShareReadWrite, File::PreserveTimestamps); - - if (keyfile.Length() > 0) - { - vector keyfileData (keyfile.Length()); - BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); - - keyfile.ReadCompleteBuffer (keyfileDataBuf); - finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); - - SecurityToken::CreateKeyfile (slotId, keyfileData, string (FilePath (keyfilePath).ToBaseName())); - } - else - throw InsufficientData (SRC_POS, FilePath (keyfilePath)); - } - } - - void TextUserInterface::InitSecurityTokenLibrary () const - { - if (Preferences.SecurityTokenModule.IsEmpty()) - throw_err (LangString ["NO_PKCS11_MODULE_SPECIFIED"]); - - struct PinRequestHandler : public GetPinFunctor - { - PinRequestHandler (const TextUserInterface *userInterface) : UI (userInterface) { } - - virtual void operator() (string &passwordStr) - { - if (UI->GetPreferences().NonInteractive) - throw MissingArgument (SRC_POS); - - UI->ShowString (wxString::Format (LangString["ENTER_TOKEN_PASSWORD"], StringConverter::ToWide (passwordStr).c_str()) + L" "); - - TextUserInterface::SetTerminalEcho (false); - finally_do ({ TextUserInterface::SetTerminalEcho (true); }); - - wstring wPassword (UI->ReadInputStreamLine()); - finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); - - UI->ShowString (L"\n"); - - StringConverter::ToSingle (wPassword, passwordStr); - } - - const TextUserInterface *UI; - }; - - struct WarningHandler : public SendExceptionFunctor - { - WarningHandler (const TextUserInterface *userInterface) : UI (userInterface) { } - - virtual void operator() (const Exception &e) - { - UI->ShowError (e); - } - - const TextUserInterface *UI; - }; - - try - { - SecurityToken::InitLibrary (Preferences.SecurityTokenModule, auto_ptr (new PinRequestHandler (this)), auto_ptr (new WarningHandler (this))); - } - catch (Exception &e) - { - ShowError (e); - throw_err (LangString ["PKCS11_MODULE_INIT_FAILED"]); - } - } - - void TextUserInterface::ListSecurityTokenKeyfiles () const - { - foreach (const SecurityTokenKeyfile &keyfile, SecurityToken::GetAvailableKeyfiles()) - { - ShowString (wstring (SecurityTokenKeyfilePath (keyfile))); - ShowString (L"\n"); - } - } - - VolumeInfoList TextUserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const - { - while (true) - { - if (!options.Password) - options.Password = AskPassword(); - - if (!options.Keyfiles) - options.Keyfiles = AskKeyfiles(); - - VolumeInfoList mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (options); - - if (!mountedVolumes.empty()) - return mountedVolumes; - - options.Password.reset(); - } - } - - shared_ptr TextUserInterface::MountVolume (MountOptions &options) const - { - shared_ptr volume; - - CheckRequirementsForMountingVolume(); - - // Volume path - while (!options.Path || options.Path->IsEmpty()) - { - if (Preferences.NonInteractive) - throw MissingArgument (SRC_POS); - - options.Path = AskVolumePath (); - } - - if (Core->IsVolumeMounted (*options.Path)) - { - ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (*options.Path))); - return volume; - } - - // Mount point - if (!options.MountPoint && !options.NoFilesystem) - options.MountPoint.reset (new DirectoryPath (AskString (_("Enter mount directory [default]: ")))); - - VolumePassword password; - KeyfileList keyfiles; - - if ((!options.Password || options.Password->IsEmpty()) - && (!options.Keyfiles || options.Keyfiles->empty()) - && !Core->IsPasswordCacheEmpty()) - { - // Cached password - try - { - volume = UserInterface::MountVolume (options); - } - catch (PasswordException&) { } - } - - int incorrectPasswordCount = 0; - - while (!volume) - { - // Password - if (!options.Password) - { - options.Password = AskPassword (StringFormatter (_("Enter password for {0}"), wstring (*options.Path))); - } - else - { - try - { - if (options.Password) - options.Password->CheckPortability(); - } - catch (UnportablePassword &) - { - ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); - } - } - - // Keyfiles - if (!options.Keyfiles) - options.Keyfiles = AskKeyfiles(); - - // Hidden volume protection - if (options.Protection == VolumeProtection::None - && !CmdLine->ArgNoHiddenVolumeProtection - && AskYesNo (_("Protect hidden volume (if any)?"))) - options.Protection = VolumeProtection::HiddenVolumeReadOnly; - - if (options.Protection == VolumeProtection::HiddenVolumeReadOnly) - { - if (!options.ProtectionPassword) - options.ProtectionPassword = AskPassword (_("Enter password for hidden volume")); - if (!options.ProtectionKeyfiles) - options.ProtectionKeyfiles = AskKeyfiles (_("Enter keyfile for hidden volume")); - } - - try - { - volume = UserInterface::MountVolume (options); - } - catch (ProtectionPasswordIncorrect &e) - { - ShowInfo (e); - options.ProtectionPassword.reset(); - } - catch (PasswordIncorrect &e) - { - if (++incorrectPasswordCount > 2 && !options.UseBackupHeaders) - { - // Try to mount the volume using the backup header - options.UseBackupHeaders = true; - - try - { - volume = UserInterface::MountVolume (options); - ShowWarning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); - } - catch (...) - { - options.UseBackupHeaders = false; - ShowInfo (e); - options.Password.reset(); - } - } - else - { - ShowInfo (e); - options.Password.reset(); - } - - ShowString (L"\n"); - } - catch (PasswordException &e) - { - ShowInfo (e); - options.Password.reset(); - } - } - -#ifdef TC_LINUX - if (!Preferences.NonInteractive && !Preferences.DisableKernelEncryptionModeWarning - && volume->EncryptionModeName != L"XTS" - && (volume->EncryptionModeName != L"LRW" || volume->EncryptionAlgorithmMinBlockSize != 16 || volume->EncryptionAlgorithmKeySize != 32)) - { - ShowWarning (LangString["ENCRYPTION_MODE_NOT_SUPPORTED_BY_KERNEL"]); - } -#endif - - return volume; - } - - bool TextUserInterface::OnInit () - { - try - { - DefaultMessageOutput = new wxMessageOutputStderr; - wxMessageOutput::Set (DefaultMessageOutput); - - InterfaceType = UserInterfaceType::Text; - Init(); - } - catch (exception &e) - { - ShowError (e); - return false; - } - return true; - } - - int TextUserInterface::OnRun() - { - try - { - if (ProcessCommandLine ()) - { - Application::SetExitCode (0); - return 0; - } - } - catch (exception &e) - { - ShowError (e); - } - - Application::SetExitCode (1); - return 1; - } - - void TextUserInterface::OnSignal (int signal) - { -#ifdef TC_UNIX - try - { - SetTerminalEcho (true); - } - catch (...) { } - _exit (1); -#endif - } - - void TextUserInterface::ReadInputStreamLine (wxString &line) const - { - if (!TextInputStream.get() || feof (stdin) || ferror (stdin)) - throw UserAbort (SRC_POS); - - line = TextInputStream->ReadLine(); - - if (ferror (stdin) || (line.empty() && feof (stdin))) - throw UserAbort (SRC_POS); - } - - wxString TextUserInterface::ReadInputStreamLine () const - { - wxString line; - ReadInputStreamLine (line); - return line; - } - - void TextUserInterface::RestoreVolumeHeaders (shared_ptr volumePath) const - { - if (!volumePath) - volumePath = AskVolumePath(); - - if (!volumePath) - throw UserAbort (SRC_POS); - -#ifdef TC_WINDOWS - if (Core->IsVolumeMounted (*volumePath)) - throw_err (LangString["DISMOUNT_FIRST"]); -#endif - - // Ask whether to restore internal or external backup - bool restoreInternalBackup; - - ShowInfo (LangString["HEADER_RESTORE_EXTERNAL_INTERNAL"]); - ShowInfo (L"\n1) " + LangString["HEADER_RESTORE_INTERNAL"]); - ShowInfo (L"2) " + LangString["HEADER_RESTORE_EXTERNAL"] + L"\n"); - - switch (AskSelection (2)) - { - case 1: - restoreInternalBackup = true; - break; - - case 2: - restoreInternalBackup = false; - break; - - default: - throw UserAbort (SRC_POS); - } - - if (restoreInternalBackup) - { - // Restore header from the internal backup - shared_ptr volume; - MountOptions options; - options.Path = volumePath; - - while (!volume) - { - ShowString (L"\n"); - options.Password = AskPassword(); - options.Keyfiles = AskKeyfiles(); - - try - { - volume = Core->OpenVolume ( - options.Path, - options.PreserveTimestamps, - options.Password, - options.Keyfiles, - options.Protection, - options.ProtectionPassword, - options.ProtectionKeyfiles, - options.SharedAccessAllowed, - VolumeType::Unknown, - true - ); - } - catch (PasswordException &e) - { - ShowInfo (e); - } - } - - shared_ptr layout = volume->GetLayout(); - if (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden)) - { - throw_err (LangString ["VOLUME_HAS_NO_BACKUP_HEADER"]); - } - - RandomNumberGenerator::Start(); - UserEnrichRandomPool(); - - // Re-encrypt volume header - SecureBuffer newHeaderBuffer (volume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Keyfiles); - - // Write volume header - int headerOffset = volume->GetLayout()->GetHeaderOffset(); - shared_ptr volumeFile = volume->GetFile(); - - if (headerOffset >= 0) - volumeFile->SeekAt (headerOffset); - else - volumeFile->SeekEnd (headerOffset); - - volumeFile->Write (newHeaderBuffer); - } - else - { - // Restore header from an external backup - - wxString confirmMsg = L"\n\n" + LangString["CONFIRM_VOL_HEADER_RESTORE"]; - confirmMsg.Replace (L"%hs", L"%s"); - - if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true, true)) - return; - - ShowString (L"\n"); - - FilePath filePath = AskFilePath(); - if (filePath.IsEmpty()) - throw UserAbort (SRC_POS); - - File backupFile; - backupFile.Open (filePath, File::OpenRead); - - uint64 headerSize; - bool legacyBackup; - - // Determine the format of the backup file - switch (backupFile.Length()) - { - case TC_VOLUME_HEADER_GROUP_SIZE: - headerSize = TC_VOLUME_HEADER_SIZE; - legacyBackup = false; - break; - - case TC_VOLUME_HEADER_SIZE_LEGACY * 2: - headerSize = TC_VOLUME_HEADER_SIZE_LEGACY; - legacyBackup = true; - break; - - default: - throw_err (LangString ["HEADER_BACKUP_SIZE_INCORRECT"]); - } - - // Open the volume header stored in the backup file - MountOptions options; - - shared_ptr decryptedLayout; - - while (!decryptedLayout) - { - options.Password = AskPassword (L"\n" + LangString["ENTER_HEADER_BACKUP_PASSWORD"]); - options.Keyfiles = AskKeyfiles(); - - try - { - // Test volume layouts - foreach (shared_ptr layout, VolumeLayout::GetAvailableLayouts ()) - { - if (layout->HasDriveHeader()) - continue; - - if (!legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden))) - continue; - - if (legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV2Normal) || typeid (*layout) == typeid (VolumeLayoutV2Hidden))) - continue; - - SecureBuffer headerBuffer (layout->GetHeaderSize()); - backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); - - // Decrypt header - shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); - if (layout->GetHeader()->Decrypt (headerBuffer, *passwordKey, layout->GetSupportedKeyDerivationFunctions(), layout->GetSupportedEncryptionAlgorithms(), layout->GetSupportedEncryptionModes())) - { - decryptedLayout = layout; - break; - } - } - - if (!decryptedLayout) - throw PasswordIncorrect (SRC_POS); - } - catch (PasswordException &e) - { - ShowWarning (e); - } - } - - File volumeFile; - volumeFile.Open (*volumePath, File::OpenReadWrite, File::ShareNone, File::PreserveTimestamps); - - RandomNumberGenerator::Start(); - UserEnrichRandomPool(); - - // Re-encrypt volume header - SecureBuffer newHeaderBuffer (decryptedLayout->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); - - // Write volume header - int headerOffset = decryptedLayout->GetHeaderOffset(); - if (headerOffset >= 0) - volumeFile.SeekAt (headerOffset); - else - volumeFile.SeekEnd (headerOffset); - - volumeFile.Write (newHeaderBuffer); - - if (decryptedLayout->HasBackupHeader()) - { - // Re-encrypt backup volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); - - // Write backup volume header - headerOffset = decryptedLayout->GetBackupHeaderOffset(); - if (headerOffset >= 0) - volumeFile.SeekAt (headerOffset); - else - volumeFile.SeekEnd (headerOffset); - - volumeFile.Write (newHeaderBuffer); - } - } - - ShowString (L"\n"); - ShowInfo ("VOL_HEADER_RESTORED"); - } - - void TextUserInterface::SetTerminalEcho (bool enable) - { -#ifdef TC_UNIX - struct termios termAttr; - if (tcgetattr (0, &termAttr) == 0) - { - if (!enable) - { - termAttr.c_lflag &= ~ECHO; - throw_sys_if (tcsetattr (0, TCSANOW, &termAttr) != 0); - } - else - { - termAttr.c_lflag |= ECHO; - throw_sys_if (tcsetattr (0, TCSANOW, &termAttr) != 0); - } - } -#endif - } - - void TextUserInterface::UserEnrichRandomPool () const - { - RandomNumberGenerator::Start(); - - if (RandomNumberGenerator::IsEnrichedByUser()) - return; - - if (CmdLine->ArgHash) - RandomNumberGenerator::SetHash (CmdLine->ArgHash); - - if (!CmdLine->ArgRandomSourcePath.IsEmpty()) - { - SecureBuffer buffer (RandomNumberGenerator::PoolSize); - File randSourceFile; - - randSourceFile.Open (CmdLine->ArgRandomSourcePath, File::OpenRead); - - for (size_t i = 0; i < buffer.Size(); ++i) - { - if (randSourceFile.Read (buffer.GetRange (i, 1)) < 1) - break; - } - - RandomNumberGenerator::AddToPool (buffer); - RandomNumberGenerator::SetEnrichedByUserStatus (true); - } - else if (!Preferences.NonInteractive) - { - int randCharsRequired = RandomNumberGenerator::PoolSize / 2; - ShowInfo (StringFormatter (_("\nPlease type at least {0} randomly chosen characters and then press Enter:"), randCharsRequired)); - - SetTerminalEcho (false); - finally_do ({ TextUserInterface::SetTerminalEcho (true); }); - - while (randCharsRequired > 0) - { - wstring randStr = AskString(); - RandomNumberGenerator::AddToPool (ConstBufferPtr ((byte *) randStr.c_str(), randStr.size() * sizeof (wchar_t))); - - randCharsRequired -= randStr.size(); - - if (randCharsRequired > 0) - ShowInfo (StringFormatter (_("Characters remaining: {0}"), randCharsRequired)); - } - - ShowString (L"\n"); - RandomNumberGenerator::SetEnrichedByUserStatus (true); - } - } - - wxMessageOutput *DefaultMessageOutput; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#ifdef TC_UNIX +#include +#include +#include +#include +#include +#endif + +#include "Common/SecurityToken.h" +#include "Core/RandomNumberGenerator.h" +#include "Application.h" +#include "TextUserInterface.h" + +namespace TrueCrypt +{ + TextUserInterface::TextUserInterface () + { +#ifdef TC_UNIX + signal (SIGHUP, OnSignal); + signal (SIGINT, OnSignal); + signal (SIGQUIT, OnSignal); + signal (SIGTERM, OnSignal); + + struct stat statBuf; + if (fstat (0, &statBuf) != -1) +#endif + { + FInputStream.reset (new wxFFileInputStream (stdin)); + TextInputStream.reset (new wxTextInputStream (*FInputStream)); + } + } + + TextUserInterface::~TextUserInterface () + { + try + { + if (RandomNumberGenerator::IsRunning()) + RandomNumberGenerator::Stop(); + } + catch (...) { } + +#ifdef TC_UNIX + signal (SIGHUP, SIG_DFL); + signal (SIGINT, SIG_DFL); + signal (SIGQUIT, SIG_DFL); + signal (SIGTERM, SIG_DFL); +#endif + } + + FilePath TextUserInterface::AskFilePath (const wxString &message) const + { + return AskString (!message.empty() ? message : wxString (_("Enter filename: "))); + } + + shared_ptr TextUserInterface::AskKeyfiles (const wxString &message) const + { + wxString msg = _("Enter keyfile"); + if (!message.empty()) + msg = message; + + make_shared_auto (KeyfileList, keyfiles); + + wxString s; + wxString m = msg + L" [" + _("none") + L"]: "; + while (!(s = AskString (m)).empty()) + { + keyfiles->push_back (make_shared (wstring (s))); + m = msg + L" [" + _("finish") + L"]: "; + } + + return keyfiles; + } + + shared_ptr TextUserInterface::AskPassword (const wxString &message, bool verify) const + { + wxString msg = LangString["ENTER_PASSWORD"] + L": "; + if (!message.empty()) + msg = message + L": "; + + SetTerminalEcho (false); + finally_do ({ TextUserInterface::SetTerminalEcho (true); }); + + wchar_t passwordBuf[4096]; + finally_do_arg (BufferPtr, BufferPtr (reinterpret_cast (passwordBuf), sizeof (passwordBuf)), { finally_arg.Erase(); }); + + make_shared_auto (VolumePassword, password); + + bool verPhase = false; + while (true) + { + ShowString (verPhase ? wxString (_("Re-enter password: ")) : msg); + + wxString passwordStr; + ReadInputStreamLine (passwordStr); + + size_t length = passwordStr.size(); + + ShowString (L"\n"); + + if (length < 1) + { + password->Set (passwordBuf, 0); + return password; + } + + for (size_t i = 0; i < length && i < VolumePassword::MaxSize; ++i) + { + passwordBuf[i] = (wchar_t) passwordStr[i]; + const_cast (passwordStr.c_str())[i] = L'X'; + } + + if (verify && verPhase) + { + make_shared_auto (VolumePassword, verPassword); + verPassword->Set (passwordBuf, length); + + if (*password != *verPassword) + { + ShowInfo (_("Passwords do not match.")); + ShowString (L"\n"); + verPhase = false; + continue; + } + } + + password->Set (passwordBuf, length); + + if (!verPhase) + { + try + { + password->CheckPortability(); + } + catch (UnportablePassword &e) + { + if (verify) + { + ShowError (e); + verPhase = false; + continue; + } + + ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); + } + + if (verify) + { + if (password->Size() < VolumePassword::WarningSizeThreshold) + { + SetTerminalEcho (true); + finally_do ({ TextUserInterface::SetTerminalEcho (false); }); + + if (!AskYesNo (LangString ["PASSWORD_LENGTH_WARNING"], false, true)) + { + ShowString (L"\n"); + continue; + } + ShowString (L"\n"); + } + } + } + + if (!verify || verPhase) + return password; + + if (!verPhase) + verPhase = true; + } + + return password; + } + + ssize_t TextUserInterface::AskSelection (ssize_t optionCount, ssize_t defaultOption) const + { + while (true) + { + wstring selectionStr = AskString (defaultOption == -1 ? wxString (_("Select: ")) : wxString (wstring (StringFormatter (_("Select [{0}]: "), (uint32) defaultOption)))); + ssize_t selection; + + if (selectionStr.empty() && defaultOption != -1) + return defaultOption; + + try + { + selection = StringConverter::ToUInt32 (selectionStr); + } + catch (...) + { + continue; + } + + if (selection > 0 && selection <= optionCount) + return selection; + } + } + + wstring TextUserInterface::AskString (const wxString &message) const + { + ShowString (message); + return wstring (ReadInputStreamLine()); + } + + bool TextUserInterface::AskYesNo (const wxString &message, bool defaultYes, bool warning) const + { + while (true) + { + wxString s = AskString (StringFormatter (L"{0} (y={1}/n={2}) [{3}]: ", + message, LangString["YES"], LangString["NO"], LangString[defaultYes ? "YES" : "NO"])); + + if (s.IsSameAs (L'n', false) || s.IsSameAs (L"no", false) || (!defaultYes && s.empty())) + return false; + + if (s.IsSameAs (L'y', false) || s.IsSameAs (L"yes", false) || (defaultYes && s.empty())) + return true; + }; + } + + shared_ptr TextUserInterface::AskVolumePath (const wxString &message) const + { + return make_shared (AskString (message.empty() ? wxString (_("Enter volume path: ")) : message)); + } + + void TextUserInterface::BackupVolumeHeaders (shared_ptr volumePath) const + { + if (!volumePath) + volumePath = AskVolumePath(); + + if (!volumePath) + throw UserAbort (SRC_POS); + +#ifdef TC_WINDOWS + if (Core->IsVolumeMounted (*volumePath)) + throw_err (LangString["DISMOUNT_FIRST"]); +#endif + + ShowInfo ("EXTERNAL_VOL_HEADER_BAK_FIRST_INFO"); + + shared_ptr normalVolume; + shared_ptr hiddenVolume; + + MountOptions normalVolumeMountOptions; + MountOptions hiddenVolumeMountOptions; + + normalVolumeMountOptions.Path = volumePath; + hiddenVolumeMountOptions.Path = volumePath; + + VolumeType::Enum volumeType = VolumeType::Normal; + + // Open both types of volumes + while (true) + { + shared_ptr volume; + MountOptions *options = (volumeType == VolumeType::Hidden ? &hiddenVolumeMountOptions : &normalVolumeMountOptions); + + while (!volume) + { + ShowString (L"\n"); + options->Password = AskPassword (LangString[volumeType == VolumeType::Hidden ? "ENTER_HIDDEN_VOL_PASSWORD" : "ENTER_NORMAL_VOL_PASSWORD"]); + options->Keyfiles = AskKeyfiles(); + + try + { + volume = Core->OpenVolume ( + options->Path, + options->PreserveTimestamps, + options->Password, + options->Keyfiles, + options->Protection, + options->ProtectionPassword, + options->ProtectionKeyfiles, + true, + volumeType, + options->UseBackupHeaders + ); + } + catch (PasswordException &e) + { + ShowInfo (e); + } + } + + if (volumeType == VolumeType::Hidden) + hiddenVolume = volume; + else + normalVolume = volume; + + // Ask whether a hidden volume is present + if (volumeType == VolumeType::Normal && AskYesNo (L"\n" + LangString["DOES_VOLUME_CONTAIN_HIDDEN"])) + { + volumeType = VolumeType::Hidden; + continue; + } + + break; + } + + if (hiddenVolume) + { + if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV1Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV1Hidden)) + throw ParameterIncorrect (SRC_POS); + + if (typeid (*normalVolume->GetLayout()) == typeid (VolumeLayoutV2Normal) && typeid (*hiddenVolume->GetLayout()) != typeid (VolumeLayoutV2Hidden)) + throw ParameterIncorrect (SRC_POS); + } + + // Ask user to select backup file path + wxString confirmMsg = L"\n" + LangString["CONFIRM_VOL_HEADER_BAK"] + L"\n"; + confirmMsg.Replace (L"%hs", L"%s"); + + if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true)) + return; + + ShowString (L"\n"); + + FilePath filePath = AskFilePath(); + if (filePath.IsEmpty()) + throw UserAbort (SRC_POS); + + File backupFile; + backupFile.Open (filePath, File::CreateWrite); + + RandomNumberGenerator::Start(); + UserEnrichRandomPool(); + + // Re-encrypt volume header + SecureBuffer newHeaderBuffer (normalVolume->GetLayout()->GetHeaderSize()); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Keyfiles); + + backupFile.Write (newHeaderBuffer); + + if (hiddenVolume) + { + // Re-encrypt hidden volume header + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Keyfiles); + } + else + { + // Store random data in place of hidden volume header + shared_ptr ea = normalVolume->GetEncryptionAlgorithm(); + Core->RandomizeEncryptionAlgorithmKey (ea); + ea->Encrypt (newHeaderBuffer); + } + + backupFile.Write (newHeaderBuffer); + + ShowString (L"\n"); + ShowInfo ("VOL_HEADER_BACKED_UP"); + } + + void TextUserInterface::ChangePassword (shared_ptr volumePath, shared_ptr password, shared_ptr keyfiles, shared_ptr newPassword, shared_ptr newKeyfiles, shared_ptr newHash) const + { + shared_ptr volume; + + // Volume path + if (!volumePath.get()) + { + if (Preferences.NonInteractive) + throw MissingArgument (SRC_POS); + + volumePath = AskVolumePath (); + } + + if (volumePath->IsEmpty()) + throw UserAbort (SRC_POS); + + bool passwordInteractive = !password.get(); + bool keyfilesInteractive = !keyfiles.get(); + + while (true) + { + // Current password + if (!passwordInteractive) + { + try + { + password->CheckPortability(); + } + catch (UnportablePassword &) + { + ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); + } + } + else if (!Preferences.NonInteractive) + { + password = AskPassword (); + } + + // Current keyfiles + try + { + if (keyfilesInteractive) + { + // Ask for keyfiles only if required + try + { + keyfiles.reset (new KeyfileList); + volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, keyfiles); + } + catch (PasswordException&) + { + if (!Preferences.NonInteractive) + keyfiles = AskKeyfiles (); + } + } + + if (!volume.get()) + volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, keyfiles); + } + catch (PasswordException &e) + { + if (Preferences.NonInteractive || !passwordInteractive || !keyfilesInteractive) + throw; + + ShowInfo (e); + continue; + } + + break; + } + + // New password + if (newPassword.get()) + newPassword->CheckPortability(); + else if (!Preferences.NonInteractive) + newPassword = AskPassword (_("Enter new password"), true); + + // New keyfiles + if (!newKeyfiles.get() && !Preferences.NonInteractive) + { + if (keyfiles.get() && keyfiles->size() > 0 && AskYesNo (_("Keep current keyfiles?"), true)) + newKeyfiles = keyfiles; + else + newKeyfiles = AskKeyfiles (_("Enter new keyfile")); + } + + UserEnrichRandomPool(); + + Core->ChangePassword (volume, newPassword, newKeyfiles, + newHash ? Pkcs5Kdf::GetAlgorithm (*newHash) : shared_ptr ()); + + ShowInfo ("PASSWORD_CHANGED"); + } + + void TextUserInterface::CreateKeyfile (shared_ptr keyfilePath) const + { + FilePath path; + + RandomNumberGenerator::Start(); + UserEnrichRandomPool(); + + if (keyfilePath) + { + Core->CreateKeyfile (*keyfilePath); + } + else + { + wstring fileName = AskFilePath(); + if (fileName.empty()) + return; + + Core->CreateKeyfile (fileName); + } + + ShowInfo ("KEYFILE_CREATED"); + } + + void TextUserInterface::CreateVolume (shared_ptr options) const + { + // Volume type + if (options->Type == VolumeType::Unknown) + { + if (Preferences.NonInteractive) + { + options->Type = VolumeType::Normal; + } + else + { + ShowString (_("Volume type:\n 1) Normal\n 2) Hidden\n")); + + switch (AskSelection (2, 1)) + { + case 1: + options->Type = VolumeType::Normal; + break; + + case 2: + options->Type = VolumeType::Hidden; + break; + } + } + } + + shared_ptr layout; + if (options->Type == VolumeType::Hidden) + layout.reset (new VolumeLayoutV2Hidden); + else + layout.reset (new VolumeLayoutV2Normal); + + if (!Preferences.NonInteractive && options->Type == VolumeType::Hidden) + ShowInfo (_("\nIMPORTANT: Inexperienced users should use the graphical user interface to create a hidden volume. When using the text interface, the procedure described in the command line help must be followed to create a hidden volume.")); + + // Volume path + if (options->Path.IsEmpty()) + { + if (Preferences.NonInteractive) + throw MissingArgument (SRC_POS); + + do + { + ShowString (L"\n"); + options->Path = VolumePath (*AskVolumePath()); + } while (options->Path.IsEmpty()); + } + + // Volume size + uint64 hostSize = 0; + + if (options->Type == VolumeType::Hidden) + { + FilesystemPath fsPath (wstring (options->Path)); + + if (fsPath.IsFile()) + { + File file; + file.Open (fsPath); + hostSize = file.Length(); + } + else if (fsPath.IsDevice()) + { + hostSize = Core->GetDeviceSize (fsPath); + } + else + { + throw_err (_("Hidden volume can be created only in an existing file or device.")); + } + + if (hostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE) + throw_err (StringFormatter (_("Minimum outer volume size is {0}."), SizeToString (TC_MIN_HIDDEN_VOLUME_HOST_SIZE + 512))); + } + + uint64 minVolumeSize = options->Type == VolumeType::Hidden ? TC_MIN_HIDDEN_VOLUME_SIZE : TC_MIN_VOLUME_SIZE; + + if (options->Path.IsDevice() && options->Type != VolumeType::Hidden) + { + if (options->Size != 0) + throw_err (_("Volume size cannot be changed for device-hosted volumes.")); + + options->Size = Core->GetDeviceSize (options->Path); + } + else + { + options->Quick = false; + + while (options->Size == 0) + { + if (Preferences.NonInteractive) + throw MissingArgument (SRC_POS); + + wstring sizeStr = AskString (options->Type == VolumeType::Hidden ? _("\nEnter hidden volume size (sizeK/size[M]/sizeG): ") : _("\nEnter volume size (sizeK/size[M]/sizeG): ")); + int multiplier = 1024 * 1024; + + if (sizeStr.find (L"K") != string::npos) + { + multiplier = 1024; + sizeStr.resize (sizeStr.size() - 1); + } + else if (sizeStr.find (L"M") != string::npos) + { + sizeStr.resize (sizeStr.size() - 1); + } + else if (sizeStr.find (L"G") != string::npos) + { + multiplier = 1024 * 1024 * 1024; + sizeStr.resize (sizeStr.size() - 1); + } + + try + { + options->Size = StringConverter::ToUInt64 (sizeStr); + options->Size *= multiplier; + } + catch (...) + { + continue; + } + + if (options->Size < minVolumeSize) + { + ShowError (StringFormatter (_("Minimum volume size is {0}."), SizeToString (minVolumeSize + 512))); + options->Size = 0; + } + + if (options->Type == VolumeType::Hidden) + { + uint64 maxHiddenVolumeSize = VolumeLayoutV2Normal().GetMaxDataSize (hostSize) - TC_MIN_FAT_FS_SIZE; + + if (options->Size > maxHiddenVolumeSize) + { + ShowError (StringFormatter (_("Maximum volume size is {0}."), SizeToString (maxHiddenVolumeSize))); + options->Size = 0; + } + } + } + } + + if (options->Size < minVolumeSize) + throw_err (_("Incorrect volume size")); + + if (options->Type == VolumeType::Hidden) + options->Quick = true; + + // Encryption algorithm + if (!options->EA) + { + if (Preferences.NonInteractive) + throw MissingArgument (SRC_POS); + + ShowInfo (wxString (L"\n") + LangString["ENCRYPTION_ALGORITHM_LV"] + L":"); + + vector < shared_ptr > encryptionAlgorithms; + foreach (shared_ptr ea, EncryptionAlgorithm::GetAvailableAlgorithms()) + { + if (!ea->IsDeprecated()) + { + ShowString (StringFormatter (L" {0}) {1}\n", (uint32) encryptionAlgorithms.size() + 1, ea->GetName())); + encryptionAlgorithms.push_back (ea); + } + } + + + options->EA = encryptionAlgorithms[AskSelection (encryptionAlgorithms.size(), 1) - 1]; + } + + // Hash algorithm + if (!options->VolumeHeaderKdf) + { + if (Preferences.NonInteractive) + throw MissingArgument (SRC_POS); + + ShowInfo (_("\nHash algorithm:")); + + vector < shared_ptr > hashes; + foreach (shared_ptr hash, Hash::GetAvailableAlgorithms()) + { + if (!hash->IsDeprecated()) + { + ShowString (StringFormatter (L" {0}) {1}\n", (uint32) hashes.size() + 1, hash->GetName())); + hashes.push_back (hash); + } + } + + shared_ptr selectedHash = hashes[AskSelection (hashes.size(), 1) - 1]; + RandomNumberGenerator::SetHash (selectedHash); + options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*selectedHash); + + } + + // Filesystem + options->FilesystemClusterSize = 0; + + if (options->Filesystem == VolumeCreationOptions::FilesystemType::Unknown) + { + if (Preferences.NonInteractive) + { + options->Filesystem = VolumeCreationOptions::FilesystemType::FAT; + } + else + { + ShowInfo (_("\nFilesystem:\n 1) FAT\n 2) None")); + + switch (AskSelection (2, 1)) + { + case 1: + options->Filesystem = VolumeCreationOptions::FilesystemType::FAT; + break; + + case 2: + options->Filesystem = VolumeCreationOptions::FilesystemType::None; + break; + } + } + } + + uint64 filesystemSize = layout->GetMaxDataSize (options->Size); + + if (options->Filesystem == VolumeCreationOptions::FilesystemType::FAT + && (filesystemSize < TC_MIN_FAT_FS_SIZE || filesystemSize > TC_MAX_FAT_FS_SIZE)) + { + throw_err (_("Specified volume size cannot be used with FAT filesystem.")); + } + + // Password + if (!options->Password && !Preferences.NonInteractive) + { + ShowString (L"\n"); + options->Password = AskPassword (_("Enter password"), true); + } + + if (options->Password) + options->Password->CheckPortability(); + + // Keyfiles + if (!options->Keyfiles && !Preferences.NonInteractive) + { + ShowString (L"\n"); + options->Keyfiles = AskKeyfiles (_("Enter keyfile path")); + } + + if ((!options->Keyfiles || options->Keyfiles->empty()) + && (!options->Password || options->Password->IsEmpty())) + { + throw_err (_("Password cannot be empty when no keyfile is specified")); + } + + // Random data + RandomNumberGenerator::Start(); + UserEnrichRandomPool(); + + ShowString (L"\n"); + wxLongLong startTime = wxGetLocalTimeMillis(); + + VolumeCreator creator; + creator.CreateVolume (options); + + bool volumeCreated = false; + while (!volumeCreated) + { + VolumeCreator::ProgressInfo progress = creator.GetProgressInfo(); + + wxLongLong timeDiff = wxGetLocalTimeMillis() - startTime; + if (timeDiff.GetValue() > 0) + { + uint64 speed = progress.SizeDone * 1000 / timeDiff.GetValue(); + + volumeCreated = !progress.CreationInProgress; + + ShowString (wxString::Format (L"\rDone: %7.3f%% Speed: %9s Left: %s ", + 100.0 - double (options->Size - progress.SizeDone) / (double (options->Size) / 100.0), + speed > 0 ? SpeedToString (speed).c_str() : L" ", + speed > 0 ? TimeSpanToString ((options->Size - progress.SizeDone) / speed).c_str() : L"")); + } + + Thread::Sleep (100); + } + + ShowString (L"\n\n"); + creator.CheckResult(); + + ShowInfo (options->Type == VolumeType::Hidden ? "HIDVOL_FORMAT_FINISHED_HELP" : "FORMAT_FINISHED_INFO"); + } + + void TextUserInterface::DeleteSecurityTokenKeyfiles () const + { + shared_ptr keyfiles = AskKeyfiles(); + if (keyfiles->empty()) + throw UserAbort(); + + foreach_ref (const Keyfile &keyfile, *keyfiles) + { + SecurityToken::DeleteKeyfile (SecurityTokenKeyfilePath (FilePath (keyfile))); + } + } + + void TextUserInterface::DoShowError (const wxString &message) const + { + wcerr << L"Error: " << static_cast (message) << endl; + } + + void TextUserInterface::DoShowInfo (const wxString &message) const + { + wcout << static_cast (message) << endl; + } + + void TextUserInterface::DoShowString (const wxString &str) const + { + wcout << str.c_str(); + } + + void TextUserInterface::DoShowWarning (const wxString &message) const + { + wcerr << L"Warning: " << static_cast (message) << endl; + } + + void TextUserInterface::ExportSecurityTokenKeyfile () const + { + wstring keyfilePath = AskString (_("Enter security token keyfile path: ")); + + if (keyfilePath.empty()) + throw UserAbort (SRC_POS); + + SecurityTokenKeyfile tokenKeyfile (keyfilePath); + + vector keyfileData; + SecurityToken::GetKeyfileData (tokenKeyfile, keyfileData); + + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); + finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); + + FilePath exportFilePath = AskFilePath(); + + if (exportFilePath.IsEmpty()) + throw UserAbort (SRC_POS); + + File keyfile; + keyfile.Open (exportFilePath, File::CreateWrite); + keyfile.Write (keyfileDataBuf); + } + + shared_ptr TextUserInterface::GetAdminPasswordRequestHandler () + { + struct AdminPasswordRequestHandler : public GetStringFunctor + { + AdminPasswordRequestHandler (TextUserInterface *userInterface) : UI (userInterface) { } + virtual void operator() (string &passwordStr) + { + UI->ShowString (_("Enter your user password or administrator password: ")); + + TextUserInterface::SetTerminalEcho (false); + finally_do ({ TextUserInterface::SetTerminalEcho (true); }); + + wstring wPassword (UI->ReadInputStreamLine()); + finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); + + UI->ShowString (L"\n"); + + StringConverter::ToSingle (wPassword, passwordStr); + } + TextUserInterface *UI; + }; + + return shared_ptr (new AdminPasswordRequestHandler (this)); + } + + void TextUserInterface::ImportSecurityTokenKeyfiles () const + { + list tokens = SecurityToken::GetAvailableTokens(); + + if (tokens.empty()) + throw_err (LangString ["NO_TOKENS_FOUND"]); + + CK_SLOT_ID slotId; + + if (tokens.size() == 1) + { + slotId = tokens.front().SlotId; + } + else + { + foreach (const SecurityTokenInfo &token, tokens) + { + wstringstream tokenLabel; + tokenLabel << L"[" << token.SlotId << L"] " << LangString["TOKEN_SLOT_ID"].c_str() << L" " << token.SlotId << L" " << token.Label; + + ShowInfo (tokenLabel.str()); + } + + slotId = (CK_SLOT_ID) AskSelection (tokens.back().SlotId, tokens.front().SlotId); + } + + shared_ptr keyfiles = AskKeyfiles(); + if (keyfiles->empty()) + throw UserAbort(); + + foreach_ref (const Keyfile &keyfilePath, *keyfiles) + { + File keyfile; + keyfile.Open (keyfilePath, File::OpenRead, File::ShareReadWrite, File::PreserveTimestamps); + + if (keyfile.Length() > 0) + { + vector keyfileData (keyfile.Length()); + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); + + keyfile.ReadCompleteBuffer (keyfileDataBuf); + finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); + + SecurityToken::CreateKeyfile (slotId, keyfileData, string (FilePath (keyfilePath).ToBaseName())); + } + else + throw InsufficientData (SRC_POS, FilePath (keyfilePath)); + } + } + + void TextUserInterface::InitSecurityTokenLibrary () const + { + if (Preferences.SecurityTokenModule.IsEmpty()) + throw_err (LangString ["NO_PKCS11_MODULE_SPECIFIED"]); + + struct PinRequestHandler : public GetPinFunctor + { + PinRequestHandler (const TextUserInterface *userInterface) : UI (userInterface) { } + + virtual void operator() (string &passwordStr) + { + if (UI->GetPreferences().NonInteractive) + throw MissingArgument (SRC_POS); + + UI->ShowString (wxString::Format (LangString["ENTER_TOKEN_PASSWORD"], StringConverter::ToWide (passwordStr).c_str()) + L" "); + + TextUserInterface::SetTerminalEcho (false); + finally_do ({ TextUserInterface::SetTerminalEcho (true); }); + + wstring wPassword (UI->ReadInputStreamLine()); + finally_do_arg (wstring *, &wPassword, { StringConverter::Erase (*finally_arg); }); + + UI->ShowString (L"\n"); + + StringConverter::ToSingle (wPassword, passwordStr); + } + + const TextUserInterface *UI; + }; + + struct WarningHandler : public SendExceptionFunctor + { + WarningHandler (const TextUserInterface *userInterface) : UI (userInterface) { } + + virtual void operator() (const Exception &e) + { + UI->ShowError (e); + } + + const TextUserInterface *UI; + }; + + try + { + SecurityToken::InitLibrary (Preferences.SecurityTokenModule, auto_ptr (new PinRequestHandler (this)), auto_ptr (new WarningHandler (this))); + } + catch (Exception &e) + { + ShowError (e); + throw_err (LangString ["PKCS11_MODULE_INIT_FAILED"]); + } + } + + void TextUserInterface::ListSecurityTokenKeyfiles () const + { + foreach (const SecurityTokenKeyfile &keyfile, SecurityToken::GetAvailableKeyfiles()) + { + ShowString (wstring (SecurityTokenKeyfilePath (keyfile))); + ShowString (L"\n"); + } + } + + VolumeInfoList TextUserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const + { + while (true) + { + if (!options.Password) + options.Password = AskPassword(); + + if (!options.Keyfiles) + options.Keyfiles = AskKeyfiles(); + + VolumeInfoList mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (options); + + if (!mountedVolumes.empty()) + return mountedVolumes; + + options.Password.reset(); + } + } + + shared_ptr TextUserInterface::MountVolume (MountOptions &options) const + { + shared_ptr volume; + + CheckRequirementsForMountingVolume(); + + // Volume path + while (!options.Path || options.Path->IsEmpty()) + { + if (Preferences.NonInteractive) + throw MissingArgument (SRC_POS); + + options.Path = AskVolumePath (); + } + + if (Core->IsVolumeMounted (*options.Path)) + { + ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (*options.Path))); + return volume; + } + + // Mount point + if (!options.MountPoint && !options.NoFilesystem) + options.MountPoint.reset (new DirectoryPath (AskString (_("Enter mount directory [default]: ")))); + + VolumePassword password; + KeyfileList keyfiles; + + if ((!options.Password || options.Password->IsEmpty()) + && (!options.Keyfiles || options.Keyfiles->empty()) + && !Core->IsPasswordCacheEmpty()) + { + // Cached password + try + { + volume = UserInterface::MountVolume (options); + } + catch (PasswordException&) { } + } + + int incorrectPasswordCount = 0; + + while (!volume) + { + // Password + if (!options.Password) + { + options.Password = AskPassword (StringFormatter (_("Enter password for {0}"), wstring (*options.Path))); + } + else + { + try + { + if (options.Password) + options.Password->CheckPortability(); + } + catch (UnportablePassword &) + { + ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); + } + } + + // Keyfiles + if (!options.Keyfiles) + options.Keyfiles = AskKeyfiles(); + + // Hidden volume protection + if (options.Protection == VolumeProtection::None + && !CmdLine->ArgNoHiddenVolumeProtection + && AskYesNo (_("Protect hidden volume (if any)?"))) + options.Protection = VolumeProtection::HiddenVolumeReadOnly; + + if (options.Protection == VolumeProtection::HiddenVolumeReadOnly) + { + if (!options.ProtectionPassword) + options.ProtectionPassword = AskPassword (_("Enter password for hidden volume")); + if (!options.ProtectionKeyfiles) + options.ProtectionKeyfiles = AskKeyfiles (_("Enter keyfile for hidden volume")); + } + + try + { + volume = UserInterface::MountVolume (options); + } + catch (ProtectionPasswordIncorrect &e) + { + ShowInfo (e); + options.ProtectionPassword.reset(); + } + catch (PasswordIncorrect &e) + { + if (++incorrectPasswordCount > 2 && !options.UseBackupHeaders) + { + // Try to mount the volume using the backup header + options.UseBackupHeaders = true; + + try + { + volume = UserInterface::MountVolume (options); + ShowWarning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); + } + catch (...) + { + options.UseBackupHeaders = false; + ShowInfo (e); + options.Password.reset(); + } + } + else + { + ShowInfo (e); + options.Password.reset(); + } + + ShowString (L"\n"); + } + catch (PasswordException &e) + { + ShowInfo (e); + options.Password.reset(); + } + } + +#ifdef TC_LINUX + if (!Preferences.NonInteractive && !Preferences.DisableKernelEncryptionModeWarning + && volume->EncryptionModeName != L"XTS" + && (volume->EncryptionModeName != L"LRW" || volume->EncryptionAlgorithmMinBlockSize != 16 || volume->EncryptionAlgorithmKeySize != 32)) + { + ShowWarning (LangString["ENCRYPTION_MODE_NOT_SUPPORTED_BY_KERNEL"]); + } +#endif + + return volume; + } + + bool TextUserInterface::OnInit () + { + try + { + DefaultMessageOutput = new wxMessageOutputStderr; + wxMessageOutput::Set (DefaultMessageOutput); + + InterfaceType = UserInterfaceType::Text; + Init(); + } + catch (exception &e) + { + ShowError (e); + return false; + } + return true; + } + + int TextUserInterface::OnRun() + { + try + { + if (ProcessCommandLine ()) + { + Application::SetExitCode (0); + return 0; + } + } + catch (exception &e) + { + ShowError (e); + } + + Application::SetExitCode (1); + return 1; + } + + void TextUserInterface::OnSignal (int signal) + { +#ifdef TC_UNIX + try + { + SetTerminalEcho (true); + } + catch (...) { } + _exit (1); +#endif + } + + void TextUserInterface::ReadInputStreamLine (wxString &line) const + { + if (!TextInputStream.get() || feof (stdin) || ferror (stdin)) + throw UserAbort (SRC_POS); + + line = TextInputStream->ReadLine(); + + if (ferror (stdin) || (line.empty() && feof (stdin))) + throw UserAbort (SRC_POS); + } + + wxString TextUserInterface::ReadInputStreamLine () const + { + wxString line; + ReadInputStreamLine (line); + return line; + } + + void TextUserInterface::RestoreVolumeHeaders (shared_ptr volumePath) const + { + if (!volumePath) + volumePath = AskVolumePath(); + + if (!volumePath) + throw UserAbort (SRC_POS); + +#ifdef TC_WINDOWS + if (Core->IsVolumeMounted (*volumePath)) + throw_err (LangString["DISMOUNT_FIRST"]); +#endif + + // Ask whether to restore internal or external backup + bool restoreInternalBackup; + + ShowInfo (LangString["HEADER_RESTORE_EXTERNAL_INTERNAL"]); + ShowInfo (L"\n1) " + LangString["HEADER_RESTORE_INTERNAL"]); + ShowInfo (L"2) " + LangString["HEADER_RESTORE_EXTERNAL"] + L"\n"); + + switch (AskSelection (2)) + { + case 1: + restoreInternalBackup = true; + break; + + case 2: + restoreInternalBackup = false; + break; + + default: + throw UserAbort (SRC_POS); + } + + if (restoreInternalBackup) + { + // Restore header from the internal backup + shared_ptr volume; + MountOptions options; + options.Path = volumePath; + + while (!volume) + { + ShowString (L"\n"); + options.Password = AskPassword(); + options.Keyfiles = AskKeyfiles(); + + try + { + volume = Core->OpenVolume ( + options.Path, + options.PreserveTimestamps, + options.Password, + options.Keyfiles, + options.Protection, + options.ProtectionPassword, + options.ProtectionKeyfiles, + options.SharedAccessAllowed, + VolumeType::Unknown, + true + ); + } + catch (PasswordException &e) + { + ShowInfo (e); + } + } + + shared_ptr layout = volume->GetLayout(); + if (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden)) + { + throw_err (LangString ["VOLUME_HAS_NO_BACKUP_HEADER"]); + } + + RandomNumberGenerator::Start(); + UserEnrichRandomPool(); + + // Re-encrypt volume header + SecureBuffer newHeaderBuffer (volume->GetLayout()->GetHeaderSize()); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Keyfiles); + + // Write volume header + int headerOffset = volume->GetLayout()->GetHeaderOffset(); + shared_ptr volumeFile = volume->GetFile(); + + if (headerOffset >= 0) + volumeFile->SeekAt (headerOffset); + else + volumeFile->SeekEnd (headerOffset); + + volumeFile->Write (newHeaderBuffer); + } + else + { + // Restore header from an external backup + + wxString confirmMsg = L"\n\n" + LangString["CONFIRM_VOL_HEADER_RESTORE"]; + confirmMsg.Replace (L"%hs", L"%s"); + + if (!AskYesNo (wxString::Format (confirmMsg, wstring (*volumePath).c_str()), true, true)) + return; + + ShowString (L"\n"); + + FilePath filePath = AskFilePath(); + if (filePath.IsEmpty()) + throw UserAbort (SRC_POS); + + File backupFile; + backupFile.Open (filePath, File::OpenRead); + + uint64 headerSize; + bool legacyBackup; + + // Determine the format of the backup file + switch (backupFile.Length()) + { + case TC_VOLUME_HEADER_GROUP_SIZE: + headerSize = TC_VOLUME_HEADER_SIZE; + legacyBackup = false; + break; + + case TC_VOLUME_HEADER_SIZE_LEGACY * 2: + headerSize = TC_VOLUME_HEADER_SIZE_LEGACY; + legacyBackup = true; + break; + + default: + throw_err (LangString ["HEADER_BACKUP_SIZE_INCORRECT"]); + } + + // Open the volume header stored in the backup file + MountOptions options; + + shared_ptr decryptedLayout; + + while (!decryptedLayout) + { + options.Password = AskPassword (L"\n" + LangString["ENTER_HEADER_BACKUP_PASSWORD"]); + options.Keyfiles = AskKeyfiles(); + + try + { + // Test volume layouts + foreach (shared_ptr layout, VolumeLayout::GetAvailableLayouts ()) + { + if (layout->HasDriveHeader()) + continue; + + if (!legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV1Normal) || typeid (*layout) == typeid (VolumeLayoutV1Hidden))) + continue; + + if (legacyBackup && (typeid (*layout) == typeid (VolumeLayoutV2Normal) || typeid (*layout) == typeid (VolumeLayoutV2Hidden))) + continue; + + SecureBuffer headerBuffer (layout->GetHeaderSize()); + backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); + + // Decrypt header + shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); + if (layout->GetHeader()->Decrypt (headerBuffer, *passwordKey, layout->GetSupportedKeyDerivationFunctions(), layout->GetSupportedEncryptionAlgorithms(), layout->GetSupportedEncryptionModes())) + { + decryptedLayout = layout; + break; + } + } + + if (!decryptedLayout) + throw PasswordIncorrect (SRC_POS); + } + catch (PasswordException &e) + { + ShowWarning (e); + } + } + + File volumeFile; + volumeFile.Open (*volumePath, File::OpenReadWrite, File::ShareNone, File::PreserveTimestamps); + + RandomNumberGenerator::Start(); + UserEnrichRandomPool(); + + // Re-encrypt volume header + SecureBuffer newHeaderBuffer (decryptedLayout->GetHeaderSize()); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); + + // Write volume header + int headerOffset = decryptedLayout->GetHeaderOffset(); + if (headerOffset >= 0) + volumeFile.SeekAt (headerOffset); + else + volumeFile.SeekEnd (headerOffset); + + volumeFile.Write (newHeaderBuffer); + + if (decryptedLayout->HasBackupHeader()) + { + // Re-encrypt backup volume header + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Keyfiles); + + // Write backup volume header + headerOffset = decryptedLayout->GetBackupHeaderOffset(); + if (headerOffset >= 0) + volumeFile.SeekAt (headerOffset); + else + volumeFile.SeekEnd (headerOffset); + + volumeFile.Write (newHeaderBuffer); + } + } + + ShowString (L"\n"); + ShowInfo ("VOL_HEADER_RESTORED"); + } + + void TextUserInterface::SetTerminalEcho (bool enable) + { +#ifdef TC_UNIX + struct termios termAttr; + if (tcgetattr (0, &termAttr) == 0) + { + if (!enable) + { + termAttr.c_lflag &= ~ECHO; + throw_sys_if (tcsetattr (0, TCSANOW, &termAttr) != 0); + } + else + { + termAttr.c_lflag |= ECHO; + throw_sys_if (tcsetattr (0, TCSANOW, &termAttr) != 0); + } + } +#endif + } + + void TextUserInterface::UserEnrichRandomPool () const + { + RandomNumberGenerator::Start(); + + if (RandomNumberGenerator::IsEnrichedByUser()) + return; + + if (CmdLine->ArgHash) + RandomNumberGenerator::SetHash (CmdLine->ArgHash); + + if (!CmdLine->ArgRandomSourcePath.IsEmpty()) + { + SecureBuffer buffer (RandomNumberGenerator::PoolSize); + File randSourceFile; + + randSourceFile.Open (CmdLine->ArgRandomSourcePath, File::OpenRead); + + for (size_t i = 0; i < buffer.Size(); ++i) + { + if (randSourceFile.Read (buffer.GetRange (i, 1)) < 1) + break; + } + + RandomNumberGenerator::AddToPool (buffer); + RandomNumberGenerator::SetEnrichedByUserStatus (true); + } + else if (!Preferences.NonInteractive) + { + int randCharsRequired = RandomNumberGenerator::PoolSize / 2; + ShowInfo (StringFormatter (_("\nPlease type at least {0} randomly chosen characters and then press Enter:"), randCharsRequired)); + + SetTerminalEcho (false); + finally_do ({ TextUserInterface::SetTerminalEcho (true); }); + + while (randCharsRequired > 0) + { + wstring randStr = AskString(); + RandomNumberGenerator::AddToPool (ConstBufferPtr ((byte *) randStr.c_str(), randStr.size() * sizeof (wchar_t))); + + randCharsRequired -= randStr.size(); + + if (randCharsRequired > 0) + ShowInfo (StringFormatter (_("Characters remaining: {0}"), randCharsRequired)); + } + + ShowString (L"\n"); + RandomNumberGenerator::SetEnrichedByUserStatus (true); + } + } + + wxMessageOutput *DefaultMessageOutput; +} diff --git a/Main/TextUserInterface.h b/Main/TextUserInterface.h index 5a2c7ae..9333b39 100644 --- a/Main/TextUserInterface.h +++ b/Main/TextUserInterface.h @@ -1,77 +1,78 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_TextUserInterface -#define TC_HEADER_Main_TextUserInterface - -#include "System.h" -#include "Main.h" -#include "UserInterface.h" - -namespace TrueCrypt -{ - class TextUserInterface : public UserInterface - { - public: - TextUserInterface (); - virtual ~TextUserInterface (); - - virtual FilePath AskFilePath (const wxString &message = wxEmptyString) const; - virtual shared_ptr AskKeyfiles (const wxString &message = L"") const; - virtual shared_ptr AskPassword (const wxString &message = L"", bool verify = false) const; - virtual ssize_t AskSelection (ssize_t optionCount, ssize_t defaultOption = -1) const; - virtual wstring AskString (const wxString &message = wxEmptyString) const; - virtual shared_ptr AskVolumePath (const wxString &message = L"") const; - virtual bool AskYesNo (const wxString &message, bool defaultYes = false, bool warning = false) const; - virtual void BackupVolumeHeaders (shared_ptr volumePath) const; - virtual void BeginBusyState () const { } - virtual void ChangePassword (shared_ptr volumePath = shared_ptr (), shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr (), shared_ptr newHash = shared_ptr ()) const; - virtual void CreateKeyfile (shared_ptr keyfilePath = shared_ptr ()) const; - virtual void CreateVolume (shared_ptr options) const; - virtual void DeleteSecurityTokenKeyfiles () const; - virtual void DoShowError (const wxString &message) const; - virtual void DoShowInfo (const wxString &message) const; - virtual void DoShowString (const wxString &str) const; - virtual void DoShowWarning (const wxString &message) const; - virtual void EndBusyState () const { } - virtual shared_ptr GetAdminPasswordRequestHandler (); - virtual void ImportSecurityTokenKeyfiles () const; -#ifndef TC_NO_GUI - virtual bool Initialize (int &argc, wxChar **argv) { return wxAppBase::Initialize(argc, argv); } -#endif - virtual void InitSecurityTokenLibrary () const; - virtual void ListSecurityTokenKeyfiles () const; - virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; - virtual shared_ptr MountVolume (MountOptions &options) const; - virtual bool OnInit (); -#ifndef TC_NO_GUI - virtual bool OnInitGui () { return true; } -#endif - virtual int OnRun(); - virtual void RestoreVolumeHeaders (shared_ptr volumePath) const; - static void SetTerminalEcho (bool enable); - virtual void UserEnrichRandomPool () const; - virtual void Yield () const { } - - protected: - static void OnSignal (int signal); - virtual void ReadInputStreamLine (wxString &line) const; - virtual wxString ReadInputStreamLine () const; - - auto_ptr FInputStream; - auto_ptr TextInputStream; - - private: - TextUserInterface (const TextUserInterface &); - TextUserInterface &operator= (const TextUserInterface &); - }; - - extern wxMessageOutput *DefaultMessageOutput; -} - -#endif // TC_HEADER_Main_TextUserInterface +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_TextUserInterface +#define TC_HEADER_Main_TextUserInterface + +#include "System.h" +#include "Main.h" +#include "UserInterface.h" + +namespace TrueCrypt +{ + class TextUserInterface : public UserInterface + { + public: + TextUserInterface (); + virtual ~TextUserInterface (); + + virtual FilePath AskFilePath (const wxString &message = wxEmptyString) const; + virtual shared_ptr AskKeyfiles (const wxString &message = L"") const; + virtual shared_ptr AskPassword (const wxString &message = L"", bool verify = false) const; + virtual ssize_t AskSelection (ssize_t optionCount, ssize_t defaultOption = -1) const; + virtual wstring AskString (const wxString &message = wxEmptyString) const; + virtual shared_ptr AskVolumePath (const wxString &message = L"") const; + virtual bool AskYesNo (const wxString &message, bool defaultYes = false, bool warning = false) const; + virtual void BackupVolumeHeaders (shared_ptr volumePath) const; + virtual void BeginBusyState () const { } + virtual void ChangePassword (shared_ptr volumePath = shared_ptr (), shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr (), shared_ptr newHash = shared_ptr ()) const; + virtual void CreateKeyfile (shared_ptr keyfilePath = shared_ptr ()) const; + virtual void CreateVolume (shared_ptr options) const; + virtual void DeleteSecurityTokenKeyfiles () const; + virtual void DoShowError (const wxString &message) const; + virtual void DoShowInfo (const wxString &message) const; + virtual void DoShowString (const wxString &str) const; + virtual void DoShowWarning (const wxString &message) const; + virtual void EndBusyState () const { } + virtual void ExportSecurityTokenKeyfile () const; + virtual shared_ptr GetAdminPasswordRequestHandler (); + virtual void ImportSecurityTokenKeyfiles () const; +#ifndef TC_NO_GUI + virtual bool Initialize (int &argc, wxChar **argv) { return wxAppBase::Initialize(argc, argv); } +#endif + virtual void InitSecurityTokenLibrary () const; + virtual void ListSecurityTokenKeyfiles () const; + virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; + virtual shared_ptr MountVolume (MountOptions &options) const; + virtual bool OnInit (); +#ifndef TC_NO_GUI + virtual bool OnInitGui () { return true; } +#endif + virtual int OnRun(); + virtual void RestoreVolumeHeaders (shared_ptr volumePath) const; + static void SetTerminalEcho (bool enable); + virtual void UserEnrichRandomPool () const; + virtual void Yield () const { } + + protected: + static void OnSignal (int signal); + virtual void ReadInputStreamLine (wxString &line) const; + virtual wxString ReadInputStreamLine () const; + + auto_ptr FInputStream; + auto_ptr TextInputStream; + + private: + TextUserInterface (const TextUserInterface &); + TextUserInterface &operator= (const TextUserInterface &); + }; + + extern wxMessageOutput *DefaultMessageOutput; +} + +#endif // TC_HEADER_Main_TextUserInterface diff --git a/Main/Unix/Main.cpp b/Main/Unix/Main.cpp index d2f3714..7868cf6 100644 --- a/Main/Unix/Main.cpp +++ b/Main/Unix/Main.cpp @@ -1,127 +1,127 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include - -#include "Platform/Platform.h" -#include "Platform/SystemLog.h" -#include "Volume/EncryptionThreadPool.h" -#include "Core/Unix/CoreService.h" -#include "Main/Application.h" -#include "Main/Main.h" -#include "Main/UserInterface.h" - -#if defined (TC_MACOSX) && !defined (TC_NO_GUI) -#include -#endif - -using namespace TrueCrypt; - -int main (int argc, char **argv) -{ - try - { - // Make sure all required commands can be executed via default search path - string sysPathStr = "/usr/sbin:/sbin:/usr/bin:/bin"; - - char *sysPath = getenv ("PATH"); - if (sysPath) - { - sysPathStr += ":"; - sysPathStr += sysPath; - } - - setenv ("PATH", sysPathStr.c_str(), 1); - - if (argc > 1 && strcmp (argv[1], TC_CORE_SERVICE_CMDLINE_OPTION) == 0) - { - // Process elevated requests - try - { - CoreService::ProcessElevatedRequests(); - return 0; - } - catch (exception &e) - { -#ifdef DEBUG - SystemLog::WriteException (e); -#endif - } - catch (...) { } - return 1; - } - - // Start core service - CoreService::Start(); - finally_do ({ CoreService::Stop(); }); - - // Start encryption thread pool - EncryptionThreadPool::Start(); - finally_do ({ EncryptionThreadPool::Stop(); }); - -#ifdef TC_NO_GUI - bool forceTextUI = true; -#else - bool forceTextUI = false; -#endif - -#ifdef __WXGTK__ - if (!getenv ("DISPLAY")) - forceTextUI = true; -#endif - - // Initialize application - if (forceTextUI || (argc > 1 && (strcmp (argv[1], "-t") == 0 || strcmp (argv[1], "--text") == 0))) - { - Application::Initialize (UserInterfaceType::Text); - } - else - { -#if defined (TC_MACOSX) && !defined (TC_NO_GUI) - if (argc > 1 && !(argc == 2 && strstr (argv[1], "-psn_") == argv[1])) - { - ProcessSerialNumber p; - if (GetCurrentProcess (&p) == noErr) - { - TransformProcessType (&p, kProcessTransformToForegroundApplication); - SetFrontProcess (&p); - } - } -#endif - Application::Initialize (UserInterfaceType::Graphic); - } - - Application::SetExitCode (1); - - // Start application - if (::wxEntry (argc, argv) == 0) - Application::SetExitCode (0); - } - catch (ErrorMessage &e) - { - wcerr << wstring (e) << endl; - } - catch (SystemException &e) - { - wstringstream s; - if (e.GetSubject().empty()) - s << e.what() << endl << e.SystemText(); - else - s << e.what() << endl << e.SystemText() << endl << e.GetSubject(); - wcerr << s.str() << endl; - } - catch (exception &e) - { - stringstream s; - s << StringConverter::GetTypeName (typeid (e)) << endl << e.what(); - cerr << s.str() << endl; - } - - return Application::GetExitCode(); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include + +#include "Platform/Platform.h" +#include "Platform/SystemLog.h" +#include "Volume/EncryptionThreadPool.h" +#include "Core/Unix/CoreService.h" +#include "Main/Application.h" +#include "Main/Main.h" +#include "Main/UserInterface.h" + +#if defined (TC_MACOSX) && !defined (TC_NO_GUI) +#include +#endif + +using namespace TrueCrypt; + +int main (int argc, char **argv) +{ + try + { + // Make sure all required commands can be executed via default search path + string sysPathStr = "/usr/sbin:/sbin:/usr/bin:/bin"; + + char *sysPath = getenv ("PATH"); + if (sysPath) + { + sysPathStr += ":"; + sysPathStr += sysPath; + } + + setenv ("PATH", sysPathStr.c_str(), 1); + + if (argc > 1 && strcmp (argv[1], TC_CORE_SERVICE_CMDLINE_OPTION) == 0) + { + // Process elevated requests + try + { + CoreService::ProcessElevatedRequests(); + return 0; + } + catch (exception &e) + { +#ifdef DEBUG + SystemLog::WriteException (e); +#endif + } + catch (...) { } + return 1; + } + + // Start core service + CoreService::Start(); + finally_do ({ CoreService::Stop(); }); + + // Start encryption thread pool + EncryptionThreadPool::Start(); + finally_do ({ EncryptionThreadPool::Stop(); }); + +#ifdef TC_NO_GUI + bool forceTextUI = true; +#else + bool forceTextUI = false; +#endif + +#ifdef __WXGTK__ + if (!getenv ("DISPLAY")) + forceTextUI = true; +#endif + + // Initialize application + if (forceTextUI || (argc > 1 && (strcmp (argv[1], "-t") == 0 || strcmp (argv[1], "--text") == 0))) + { + Application::Initialize (UserInterfaceType::Text); + } + else + { +#if defined (TC_MACOSX) && !defined (TC_NO_GUI) + if (argc > 1 && !(argc == 2 && strstr (argv[1], "-psn_") == argv[1])) + { + ProcessSerialNumber p; + if (GetCurrentProcess (&p) == noErr) + { + TransformProcessType (&p, kProcessTransformToForegroundApplication); + SetFrontProcess (&p); + } + } +#endif + Application::Initialize (UserInterfaceType::Graphic); + } + + Application::SetExitCode (1); + + // Start application + if (::wxEntry (argc, argv) == 0) + Application::SetExitCode (0); + } + catch (ErrorMessage &e) + { + wcerr << wstring (e) << endl; + } + catch (SystemException &e) + { + wstringstream s; + if (e.GetSubject().empty()) + s << e.what() << endl << e.SystemText(); + else + s << e.what() << endl << e.SystemText() << endl << e.GetSubject(); + wcerr << s.str() << endl; + } + catch (exception &e) + { + stringstream s; + s << StringConverter::GetTypeName (typeid (e)) << endl << e.what(); + cerr << s.str() << endl; + } + + return Application::GetExitCode(); +} diff --git a/Main/UserInterface.cpp b/Main/UserInterface.cpp index 481828f..b5acf28 100644 --- a/Main/UserInterface.cpp +++ b/Main/UserInterface.cpp @@ -1,1438 +1,1453 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include -#include -#include -#include -#include "Platform/PlatformTest.h" -#ifdef TC_UNIX -#include -#include "Platform/Unix/Process.h" -#endif -#include "Platform/SystemInfo.h" -#include "Common/SecurityToken.h" -#include "Volume/EncryptionTest.h" -#include "Application.h" -#include "FavoriteVolume.h" -#include "UserInterface.h" - -namespace TrueCrypt -{ - UserInterface::UserInterface () - { - } - - UserInterface::~UserInterface () - { - Core->WarningEvent.Disconnect (this); - Core->VolumeMountedEvent.Disconnect (this); - - try - { - if (SecurityToken::IsInitialized()) - SecurityToken::CloseLibrary(); - } - catch (...) { } - } - - void UserInterface::CheckRequirementsForMountingVolume () const - { -#ifdef TC_LINUX - if (!Preferences.NonInteractive) - { - vector osVersion = SystemInfo::GetVersion(); - - if (osVersion.size() >= 3 && osVersion[0] == 2 && osVersion[1] == 6 && osVersion[2] < 24) - ShowWarning (_("Your system uses an old version of the Linux kernel.\n\nDue to a bug in the Linux kernel, your system may stop responding when writing data to a TrueCrypt volume. This problem can be solved by upgrading the kernel to version 2.6.24 or later.")); - } -#endif // TC_LINUX - } - - void UserInterface::CloseExplorerWindows (shared_ptr mountedVolume) const - { -#ifdef TC_WINDOWS - struct Args - { - HWND ExplorerWindow; - string DriveRootPath; - }; - - struct Enumerator - { - static BOOL CALLBACK ChildWindows (HWND hwnd, LPARAM argsLP) - { - Args *args = reinterpret_cast (argsLP); - - char s[4096]; - SendMessageA (hwnd, WM_GETTEXT, sizeof (s), (LPARAM) s); - - if (strstr (s, args->DriveRootPath.c_str()) != NULL) - { - PostMessage (args->ExplorerWindow, WM_CLOSE, 0, 0); - return FALSE; - } - - return TRUE; - } - - static BOOL CALLBACK TopLevelWindows (HWND hwnd, LPARAM argsLP) - { - Args *args = reinterpret_cast (argsLP); - - char s[4096]; - GetClassNameA (hwnd, s, sizeof s); - if (strcmp (s, "CabinetWClass") == 0) - { - GetWindowTextA (hwnd, s, sizeof s); - if (strstr (s, args->DriveRootPath.c_str()) != NULL) - { - PostMessage (hwnd, WM_CLOSE, 0, 0); - return TRUE; - } - - args->ExplorerWindow = hwnd; - EnumChildWindows (hwnd, ChildWindows, argsLP); - } - - return TRUE; - } - }; - - Args args; - - string mountPoint = mountedVolume->MountPoint; - if (mountPoint.size() < 2 || mountPoint[1] != ':') - return; - - args.DriveRootPath = string() + mountPoint[0] + string (":\\"); - - EnumWindows (Enumerator::TopLevelWindows, (LPARAM) &args); -#endif - } - - void UserInterface::DismountAllVolumes (bool ignoreOpenFiles, bool interactive) const - { - try - { - VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); - - if (mountedVolumes.size() < 1) - ShowInfo (LangString["NO_VOLUMES_MOUNTED"]); - - BusyScope busy (this); - DismountVolumes (mountedVolumes, ignoreOpenFiles, interactive); - } - catch (exception &e) - { - ShowError (e); - } - } - - void UserInterface::DismountVolume (shared_ptr volume, bool ignoreOpenFiles, bool interactive) const - { - VolumeInfoList volumes; - volumes.push_back (volume); - - DismountVolumes (volumes, ignoreOpenFiles, interactive); - } - - void UserInterface::DismountVolumes (VolumeInfoList volumes, bool ignoreOpenFiles, bool interactive) const - { - BusyScope busy (this); - - volumes.sort (VolumeInfo::FirstVolumeMountedAfterSecond); - - wxString message; - bool twoPassMode = volumes.size() > 1; - bool volumesInUse = false; - bool firstPass = true; - -#ifdef TC_WINDOWS - if (Preferences.CloseExplorerWindowsOnDismount) - { - foreach (shared_ptr volume, volumes) - CloseExplorerWindows (volume); - } -#endif - while (!volumes.empty()) - { - VolumeInfoList volumesLeft; - foreach (shared_ptr volume, volumes) - { - try - { - BusyScope busy (this); - volume = Core->DismountVolume (volume, ignoreOpenFiles); - } - catch (MountedVolumeInUse&) - { - if (!firstPass) - throw; - - if (twoPassMode || !interactive) - { - volumesInUse = true; - volumesLeft.push_back (volume); - continue; - } - else - { - if (AskYesNo (StringFormatter (LangString["UNMOUNT_LOCK_FAILED"], wstring (volume->Path)), true, true)) - { - BusyScope busy (this); - volume = Core->DismountVolume (volume, true); - } - else - throw UserAbort (SRC_POS); - } - } - catch (...) - { - if (twoPassMode && firstPass) - volumesLeft.push_back (volume); - else - throw; - } - - if (volume->HiddenVolumeProtectionTriggered) - ShowWarning (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (volume->Path))); - - if (Preferences.Verbose) - { - if (!message.IsEmpty()) - message += L'\n'; - message += StringFormatter (_("Volume \"{0}\" has been dismounted."), wstring (volume->Path)); - } - } - - if (twoPassMode && firstPass) - { - volumes = volumesLeft; - - if (volumesInUse && interactive) - { - if (AskYesNo (LangString["UNMOUNTALL_LOCK_FAILED"], true, true)) - ignoreOpenFiles = true; - else - throw UserAbort (SRC_POS); - } - } - else - break; - - firstPass = false; - } - - if (Preferences.Verbose && !message.IsEmpty()) - ShowInfo (message); - } - - void UserInterface::DisplayVolumeProperties (const VolumeInfoList &volumes) const - { - if (volumes.size() < 1) - throw_err (LangString["NO_VOLUMES_MOUNTED"]); - - wxString prop; - - foreach_ref (const VolumeInfo &volume, volumes) - { - prop << _("Slot") << L": " << StringConverter::FromNumber (volume.SlotNumber) << L'\n'; - prop << LangString["VOLUME"] << L": " << wstring (volume.Path) << L'\n'; -#ifndef TC_WINDOWS - prop << LangString["VIRTUAL_DEVICE"] << L": " << wstring (volume.VirtualDevice) << L'\n'; -#endif - prop << LangString["MOUNT_POINT"] << L": " << wstring (volume.MountPoint) << L'\n'; - prop << LangString["SIZE"] << L": " << SizeToString (volume.Size) << L'\n'; - prop << LangString["TYPE"] << L": " << VolumeTypeToString (volume.Type, volume.Protection) << L'\n'; - - prop << LangString["READ_ONLY"] << L": " << LangString [volume.Protection == VolumeProtection::ReadOnly ? "UISTR_YES" : "UISTR_NO"] << L'\n'; - - wxString protection; - if (volume.Type == VolumeType::Hidden) - protection = LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"]; - else if (volume.HiddenVolumeProtectionTriggered) - protection = LangString["HID_VOL_DAMAGE_PREVENTED"]; - else - protection = LangString [volume.Protection == VolumeProtection::HiddenVolumeReadOnly ? "UISTR_YES" : "UISTR_NO"]; - - prop << LangString["HIDDEN_VOL_PROTECTION"] << L": " << protection << L'\n'; - prop << LangString["ENCRYPTION_ALGORITHM"] << L": " << volume.EncryptionAlgorithmName << L'\n'; - prop << LangString["KEY_SIZE"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n'; - - if (volume.EncryptionModeName == L"XTS") - prop << LangString["SECONDARY_KEY_SIZE_XTS"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n';; - - wstringstream blockSize; - blockSize << volume.EncryptionAlgorithmBlockSize * 8; - if (volume.EncryptionAlgorithmBlockSize != volume.EncryptionAlgorithmMinBlockSize) - blockSize << L"/" << volume.EncryptionAlgorithmMinBlockSize * 8; - - prop << LangString["BLOCK_SIZE"] << L": " << blockSize.str() + L" " + LangString ["BITS"] << L'\n'; - prop << LangString["MODE_OF_OPERATION"] << L": " << volume.EncryptionModeName << L'\n'; - prop << LangString["PKCS5_PRF"] << L": " << volume.Pkcs5PrfName << L'\n'; - - prop << LangString["VOLUME_FORMAT_VERSION"] << L": " << (volume.MinRequiredProgramVersion < 0x600 ? 1 : 2) << L'\n'; - prop << LangString["BACKUP_HEADER"] << L": " << LangString[volume.MinRequiredProgramVersion >= 0x600 ? "UISTR_YES" : "UISTR_NO"] << L'\n'; - -#ifdef TC_LINUX - if (string (volume.VirtualDevice).find ("/dev/mapper/truecrypt") != 0) - { -#endif - prop << LangString["TOTAL_DATA_READ"] << L": " << SizeToString (volume.TotalDataRead) << L'\n'; - prop << LangString["TOTAL_DATA_WRITTEN"] << L": " << SizeToString (volume.TotalDataWritten) << L'\n'; -#ifdef TC_LINUX - } -#endif - - prop << L'\n'; - } - - ShowString (prop); - } - - wxString UserInterface::ExceptionToMessage (const exception &ex) const - { - wxString message; - - const Exception *e = dynamic_cast (&ex); - if (e) - { - message = ExceptionToString (*e); - - // System exception - const SystemException *sysEx = dynamic_cast (&ex); - if (sysEx) - { - if (!message.IsEmpty()) - { - message += L"\n\n"; - } - - message += wxString (sysEx->SystemText()).Trim (true); - } - - if (!message.IsEmpty()) - { - // Subject - if (!e->GetSubject().empty()) - { - message = message.Trim (true); - - if (message.EndsWith (L".")) - message.Truncate (message.size() - 1); - - if (!message.EndsWith (L":")) - message << L":\n"; - else - message << L"\n"; - - message << e->GetSubject(); - } - -#ifdef TC_UNIX - if (sysEx && sysEx->GetErrorCode() == EIO) - message << L"\n\n" << LangString["ERR_HARDWARE_ERROR"]; -#endif - -#ifdef DEBUG - if (sysEx && sysEx->what()) - message << L"\n\n" << StringConverter::ToWide (sysEx->what()); -#endif - return message; - } - } - - // bad_alloc - const bad_alloc *outOfMemory = dynamic_cast (&ex); - if (outOfMemory) - return _("Out of memory."); - - // Unresolved exceptions - string typeName (StringConverter::GetTypeName (typeid (ex))); - size_t pos = typeName.find ("TrueCrypt::"); - if (pos != string::npos) - { - return StringConverter::ToWide (typeName.substr (pos + string ("TrueCrypt::").size())) - + L" at " + StringConverter::ToWide (ex.what()); - } - - return StringConverter::ToWide (typeName) + L" at " + StringConverter::ToWide (ex.what()); - } - - wxString UserInterface::ExceptionToString (const Exception &ex) const - { - // Error messages - const ErrorMessage *errMsgEx = dynamic_cast (&ex); - if (errMsgEx) - return wstring (*errMsgEx).c_str(); - - // ExecutedProcessFailed - const ExecutedProcessFailed *execEx = dynamic_cast (&ex); - if (execEx) - { - wstring errOutput; - - // ElevationFailed - if (dynamic_cast (&ex)) - errOutput += wxString (_("Failed to obtain administrator privileges")) + (StringConverter::Trim (execEx->GetErrorOutput()).empty() ? L". " : L": "); - - errOutput += StringConverter::ToWide (execEx->GetErrorOutput()); - - if (errOutput.empty()) - return errOutput + StringFormatter (_("Command \"{0}\" returned error {1}."), execEx->GetCommand(), execEx->GetExitCode()); - - return wxString (errOutput).Trim (true); - } - - // PasswordIncorrect - if (dynamic_cast (&ex)) - { - wxString message = ExceptionTypeToString (typeid (ex)); - -#ifndef TC_NO_GUI - if (Application::GetUserInterfaceType() == UserInterfaceType::Graphic && wxGetKeyState (WXK_CAPITAL)) - message += wxString (L"\n\n") + LangString["CAPSLOCK_ON"]; -#endif - return message; - } - - // PKCS#11 Exception - if (dynamic_cast (&ex)) - { - string errorString = string (dynamic_cast (ex)); - - if (LangString.Exists (errorString)) - return LangString[errorString]; - - if (errorString.find ("CKR_") == 0) - { - errorString = errorString.substr (4); - for (size_t i = 0; i < errorString.size(); ++i) - { - if (errorString[i] == '_') - errorString[i] = ' '; - } - } - - return LangString["SECURITY_TOKEN_ERROR"] + L":\n\n" + StringConverter::ToWide (errorString); - } - - // Other library exceptions - return ExceptionTypeToString (typeid (ex)); - } - - wxString UserInterface::ExceptionTypeToString (const std::type_info &ex) const - { -#define EX2MSG(exception, message) do { if (ex == typeid (exception)) return (message); } while (false) - EX2MSG (DriveLetterUnavailable, LangString["DRIVE_LETTER_UNAVAILABLE"]); - EX2MSG (EncryptedSystemRequired, _("This operation must be performed only when the system hosted on the volume is running.")); - EX2MSG (ExternalException, LangString["EXCEPTION_OCCURRED"]); - EX2MSG (InsufficientData, _("Not enough data available.")); - EX2MSG (InvalidSecurityTokenKeyfilePath, LangString["INVALID_TOKEN_KEYFILE_PATH"]); - EX2MSG (HigherVersionRequired, LangString["NEW_VERSION_REQUIRED"]); - EX2MSG (KernelCryptoServiceTestFailed, _("Kernel cryptographic service test failed. The cryptographic service of your kernel most likely does not support volumes larger than 2 TB.\n\nPossible solutions:\n- Try upgrading your kernel.\n- Disable use of the kernel cryptographic services (Settings > Preferences > System Integration) or use 'nokernelcrypto' mount option on the command line.")); - EX2MSG (LoopDeviceSetupFailed, _("Failed to set up a loop device.")); - EX2MSG (MissingArgument, _("A required argument is missing.")); - EX2MSG (MissingVolumeData, _("Volume data missing.")); - EX2MSG (MountPointRequired, _("Mount point required.")); - EX2MSG (MountPointUnavailable, _("Mount point is already in use.")); - EX2MSG (NoDriveLetterAvailable, LangString["NO_FREE_DRIVES"]); - EX2MSG (PasswordEmpty, _("No password or keyfile specified.")); - EX2MSG (PasswordIncorrect, LangString["PASSWORD_WRONG"]); - EX2MSG (PasswordKeyfilesIncorrect, LangString["PASSWORD_OR_KEYFILE_WRONG"]); - EX2MSG (PasswordOrKeyboardLayoutIncorrect, LangString["PASSWORD_OR_KEYFILE_WRONG"] + _("\n\nNote that pre-boot authentication passwords need to be typed in the pre-boot environment where non-US keyboard layouts are not available. Therefore, pre-boot authentication passwords must always be typed using the standard US keyboard layout (otherwise, the password will be typed incorrectly in most cases). However, note that you do NOT need a real US keyboard; you just need to change the keyboard layout in your operating system.")); - EX2MSG (PasswordOrMountOptionsIncorrect, LangString["PASSWORD_OR_KEYFILE_OR_MODE_WRONG"] + _("\n\nNote: If you are attempting to mount a partition located on an encrypted system drive without pre-boot authentication or to mount the encrypted system partition of an operating system that is not running, you can do so by selecting 'Options >' > 'Mount partition using system encryption'.")); - EX2MSG (PasswordTooLong, StringFormatter (_("Password is longer than {0} characters."), (int) VolumePassword::MaxSize)); - EX2MSG (PartitionDeviceRequired, _("Partition device required.")); - EX2MSG (ProtectionPasswordIncorrect, _("Incorrect password to the protected hidden volume or the hidden volume does not exist.")); - EX2MSG (ProtectionPasswordKeyfilesIncorrect,_("Incorrect keyfile(s) and/or password to the protected hidden volume or the hidden volume does not exist.")); - EX2MSG (RootDeviceUnavailable, LangString["NODRIVER"]); - EX2MSG (SecurityTokenKeyfileAlreadyExists, LangString["TOKEN_KEYFILE_ALREADY_EXISTS"]); - EX2MSG (SecurityTokenKeyfileNotFound, LangString["TOKEN_KEYFILE_NOT_FOUND"]); - EX2MSG (SecurityTokenLibraryNotInitialized, LangString["PKCS11_MODULE_INIT_FAILED"]); - EX2MSG (StringConversionFailed, _("Invalid characters encountered.")); - EX2MSG (StringFormatterException, _("Error while parsing formatted string.")); - EX2MSG (UnportablePassword, LangString["UNSUPPORTED_CHARS_IN_PWD"]); - EX2MSG (UnsupportedSectorSize, LangString["LARGE_SECTOR_UNSUPPORTED"]); - EX2MSG (VolumeAlreadyMounted, LangString["VOL_ALREADY_MOUNTED"]); - EX2MSG (VolumeEncryptionNotCompleted, LangString["ERR_ENCRYPTION_NOT_COMPLETED"]); - EX2MSG (VolumeHostInUse, _("The host file/device is already in use.")); - EX2MSG (VolumeSlotUnavailable, _("Volume slot unavailable.")); - -#ifdef TC_MACOSX - EX2MSG (HigherFuseVersionRequired, _("TrueCrypt requires MacFUSE 1.3 or later.")); -#endif - -#undef EX2MSG - return L""; - } - - void UserInterface::Init () - { - SetAppName (Application::GetName()); - SetClassName (Application::GetName()); - - LangString.Init(); - Core->Init(); - - wxCmdLineParser parser; - parser.SetCmdLine (argc, argv); - CmdLine.reset (new CommandLineInterface (parser, InterfaceType)); - SetPreferences (CmdLine->Preferences); - - Core->SetApplicationExecutablePath (Application::GetExecutablePath()); - - if (!Preferences.NonInteractive) - { - Core->SetAdminPasswordCallback (GetAdminPasswordRequestHandler()); - } - else - { - struct AdminPasswordRequestHandler : public GetStringFunctor - { - virtual void operator() (string &str) - { - throw ElevationFailed (SRC_POS, "sudo", 1, ""); - } - }; - - Core->SetAdminPasswordCallback (shared_ptr (new AdminPasswordRequestHandler)); - } - - Core->WarningEvent.Connect (EventConnector (this, &UserInterface::OnWarning)); - Core->VolumeMountedEvent.Connect (EventConnector (this, &UserInterface::OnVolumeMounted)); - - if (!CmdLine->Preferences.SecurityTokenModule.IsEmpty() && !SecurityToken::IsInitialized()) - { - try - { - InitSecurityTokenLibrary(); - } - catch (exception &e) - { - if (Preferences.NonInteractive) - throw; - - ShowError (e); - } - } - } - - void UserInterface::ListMountedVolumes (const VolumeInfoList &volumes) const - { - if (volumes.size() < 1) - throw_err (LangString["NO_VOLUMES_MOUNTED"]); - - wxString message; - - foreach_ref (const VolumeInfo &volume, volumes) - { - message << volume.SlotNumber << L": " << StringConverter::QuoteSpaces (volume.Path); - - if (!volume.VirtualDevice.IsEmpty()) - message << L' ' << wstring (volume.VirtualDevice); - else - message << L" - "; - - if (!volume.MountPoint.IsEmpty()) - message << L' ' << StringConverter::QuoteSpaces (volume.MountPoint); - else - message << L" - "; - - message << L'\n'; - } - - ShowString (message); - } - - VolumeInfoList UserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const - { - BusyScope busy (this); - - VolumeInfoList newMountedVolumes; - - if (!options.MountPoint) - options.MountPoint.reset (new DirectoryPath); - - Core->CoalesceSlotNumberAndMountPoint (options); - - bool sharedAccessAllowed = options.SharedAccessAllowed; - bool someVolumesShared = false; - - HostDeviceList devices; - foreach (shared_ptr device, Core->GetHostDevices (true)) - { - devices.push_back (device); - - foreach (shared_ptr partition, device->Partitions) - devices.push_back (partition); - } - - set mountedVolumes; - foreach_ref (const VolumeInfo &v, Core->GetMountedVolumes()) - mountedVolumes.insert (v.Path); - - bool protectedVolumeMounted = false; - bool legacyVolumeMounted = false; - - foreach_ref (const HostDevice &device, devices) - { - if (mountedVolumes.find (wstring (device.Path)) != mountedVolumes.end()) - continue; - - Yield(); - options.SlotNumber = Core->GetFirstFreeSlotNumber (options.SlotNumber); - options.MountPoint.reset (new DirectoryPath); - options.Path.reset (new VolumePath (device.Path)); - - try - { - try - { - options.SharedAccessAllowed = sharedAccessAllowed; - newMountedVolumes.push_back (Core->MountVolume (options)); - } - catch (VolumeHostInUse&) - { - if (!sharedAccessAllowed) - { - try - { - options.SharedAccessAllowed = true; - newMountedVolumes.push_back (Core->MountVolume (options)); - someVolumesShared = true; - } - catch (VolumeHostInUse&) - { - continue; - } - } - else - continue; - } - - if (newMountedVolumes.back()->Protection == VolumeProtection::HiddenVolumeReadOnly) - protectedVolumeMounted = true; - - if (newMountedVolumes.back()->EncryptionAlgorithmMinBlockSize == 8) - legacyVolumeMounted = true; - } - catch (DriverError&) { } - catch (MissingVolumeData&) { } - catch (PasswordException&) { } - catch (SystemException&) { } - } - - if (newMountedVolumes.empty()) - { - ShowWarning (LangString [options.Keyfiles && !options.Keyfiles->empty() ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT"]); - } - else - { - if (someVolumesShared) - ShowWarning ("DEVICE_IN_USE_INFO"); - - if (legacyVolumeMounted) - ShowWarning ("WARN_64_BIT_BLOCK_CIPHER"); - - if (protectedVolumeMounted) - ShowInfo (LangString[newMountedVolumes.size() > 1 ? "HIDVOL_PROT_WARN_AFTER_MOUNT_PLURAL" : "HIDVOL_PROT_WARN_AFTER_MOUNT"]); - } - - if (!newMountedVolumes.empty() && GetPreferences().CloseSecurityTokenSessionsAfterMount) - SecurityToken::CloseAllSessions(); - - return newMountedVolumes; - } - - VolumeInfoList UserInterface::MountAllFavoriteVolumes (MountOptions &options) - { - BusyScope busy (this); - - VolumeInfoList newMountedVolumes; - foreach_ref (const FavoriteVolume &favorite, FavoriteVolume::LoadList()) - { - shared_ptr mountedVolume = Core->GetMountedVolume (favorite.Path); - if (mountedVolume) - { - if (mountedVolume->MountPoint != favorite.MountPoint) - ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (favorite.Path))); - continue; - } - - favorite.ToMountOptions (options); - - if (Preferences.NonInteractive) - { - BusyScope busy (this); - newMountedVolumes.push_back (Core->MountVolume (options)); - } - else - { - try - { - BusyScope busy (this); - newMountedVolumes.push_back (Core->MountVolume (options)); - } - catch (...) - { - UserPreferences prefs = GetPreferences(); - if (prefs.CloseSecurityTokenSessionsAfterMount) - Preferences.CloseSecurityTokenSessionsAfterMount = false; - - shared_ptr volume = MountVolume (options); - - if (prefs.CloseSecurityTokenSessionsAfterMount) - Preferences.CloseSecurityTokenSessionsAfterMount = true; - - if (!volume) - break; - newMountedVolumes.push_back (volume); - } - } - } - - if (!newMountedVolumes.empty() && GetPreferences().CloseSecurityTokenSessionsAfterMount) - SecurityToken::CloseAllSessions(); - - return newMountedVolumes; - } - - shared_ptr UserInterface::MountVolume (MountOptions &options) const - { - shared_ptr volume; - - try - { - volume = Core->MountVolume (options); - } - catch (VolumeHostInUse&) - { - if (options.SharedAccessAllowed) - throw_err (LangString["FILE_IN_USE_FAILED"]); - - if (!AskYesNo (StringFormatter (LangString["VOLUME_HOST_IN_USE"], wstring (*options.Path)), false, true)) - throw UserAbort (SRC_POS); - - try - { - options.SharedAccessAllowed = true; - volume = Core->MountVolume (options); - } - catch (VolumeHostInUse&) - { - throw_err (LangString["FILE_IN_USE_FAILED"]); - } - } - - if (volume->EncryptionAlgorithmMinBlockSize == 8) - ShowWarning ("WARN_64_BIT_BLOCK_CIPHER"); - - if (VolumeHasUnrecommendedExtension (*options.Path)) - ShowWarning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); - - if (options.Protection == VolumeProtection::HiddenVolumeReadOnly) - ShowInfo ("HIDVOL_PROT_WARN_AFTER_MOUNT"); - - if (GetPreferences().CloseSecurityTokenSessionsAfterMount) - SecurityToken::CloseAllSessions(); - - return volume; - } - - void UserInterface::OnUnhandledException () - { - try - { - throw; - } - catch (UserAbort&) - { - } - catch (exception &e) - { - ShowError (e); - } - catch (...) - { - ShowError (_("Unknown exception occurred.")); - } - - Yield(); - Application::SetExitCode (1); - } - - void UserInterface::OnVolumeMounted (EventArgs &args) - { - shared_ptr mountedVolume = (dynamic_cast (args)).mVolume; - - if (Preferences.OpenExplorerWindowAfterMount && !mountedVolume->MountPoint.IsEmpty()) - OpenExplorerWindow (mountedVolume->MountPoint); - } - - void UserInterface::OnWarning (EventArgs &args) - { - ExceptionEventArgs &e = dynamic_cast (args); - ShowWarning (e.mException); - } - - void UserInterface::OpenExplorerWindow (const DirectoryPath &path) - { - if (path.IsEmpty()) - return; - - list args; - -#ifdef TC_WINDOWS - - wstring p (Directory::AppendSeparator (path)); - SHFILEINFO fInfo; - SHGetFileInfo (p.c_str(), 0, &fInfo, sizeof (fInfo), 0); // Force explorer to discover the drive - ShellExecute (GetTopWindow() ? static_cast (GetTopWindow()->GetHandle()) : nullptr, L"open", p.c_str(), nullptr, nullptr, SW_SHOWNORMAL); - -#elif defined (TC_MACOSX) - - args.push_back (string (path)); - try - { - Process::Execute ("open", args); - } - catch (exception &e) { ShowError (e); } - -#else - // MIME handler for directory seems to be unavailable through wxWidgets - wxString desktop = GetTraits()->GetDesktopEnvironment(); - - if (desktop == L"GNOME" || desktop.empty()) - { - args.push_back ("--no-default-window"); - args.push_back ("--no-desktop"); - args.push_back (string (path)); - try - { - Process::Execute ("nautilus", args, 2000); - } - catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } - } - else if (desktop == L"KDE") - { - try - { - args.push_back (string (path)); - Process::Execute ("dolphin", args, 2000); - } - catch (TimeOut&) { } - catch (exception&) - { - args.clear(); - args.push_back ("openURL"); - args.push_back (string (path)); - try - { - Process::Execute ("kfmclient", args, 2000); - } - catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } - } - } -#endif - } - - bool UserInterface::ProcessCommandLine () - { - CommandLineInterface &cmdLine = *CmdLine; - - switch (cmdLine.ArgCommand) - { - case CommandId::None: - return false; - - case CommandId::AutoMountDevices: - case CommandId::AutoMountFavorites: - case CommandId::AutoMountDevicesFavorites: - case CommandId::MountVolume: - { - cmdLine.ArgMountOptions.Path = cmdLine.ArgVolumePath; - cmdLine.ArgMountOptions.MountPoint = cmdLine.ArgMountPoint; - cmdLine.ArgMountOptions.Password = cmdLine.ArgPassword; - cmdLine.ArgMountOptions.Keyfiles = cmdLine.ArgKeyfiles; - cmdLine.ArgMountOptions.SharedAccessAllowed = cmdLine.ArgForce; - - VolumeInfoList mountedVolumes; - switch (cmdLine.ArgCommand) - { - case CommandId::AutoMountDevices: - case CommandId::AutoMountFavorites: - case CommandId::AutoMountDevicesFavorites: - { - if (cmdLine.ArgCommand == CommandId::AutoMountDevices || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites) - { - if (Preferences.NonInteractive) - mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions); - else - mountedVolumes = MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions); - } - - if (cmdLine.ArgCommand == CommandId::AutoMountFavorites || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites) - { - foreach (shared_ptr v, MountAllFavoriteVolumes(cmdLine.ArgMountOptions)) - mountedVolumes.push_back (v); - } - } - break; - - - break; - - case CommandId::MountVolume: - if (Preferences.OpenExplorerWindowAfterMount) - { - // Open explorer window for an already mounted volume - shared_ptr mountedVolume = Core->GetMountedVolume (*cmdLine.ArgMountOptions.Path); - if (mountedVolume && !mountedVolume->MountPoint.IsEmpty()) - { - OpenExplorerWindow (mountedVolume->MountPoint); - break; - } - } - - if (Preferences.NonInteractive) - { - // Volume path - if (!cmdLine.ArgMountOptions.Path) - throw MissingArgument (SRC_POS); - - mountedVolumes.push_back (Core->MountVolume (cmdLine.ArgMountOptions)); - } - else - { - shared_ptr volume = MountVolume (cmdLine.ArgMountOptions); - if (!volume) - { - Application::SetExitCode (1); - throw UserAbort (SRC_POS); - } - mountedVolumes.push_back (volume); - } - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - - if (Preferences.Verbose && !mountedVolumes.empty()) - { - wxString message; - foreach_ref (const VolumeInfo &volume, mountedVolumes) - { - if (!message.IsEmpty()) - message += L'\n'; - message += StringFormatter (_("Volume \"{0}\" has been mounted."), wstring (volume.Path)); - } - ShowInfo (message); - } - } - return true; - - case CommandId::BackupHeaders: - BackupVolumeHeaders (cmdLine.ArgVolumePath); - return true; - - case CommandId::ChangePassword: - ChangePassword (cmdLine.ArgVolumePath, cmdLine.ArgPassword, cmdLine.ArgKeyfiles, cmdLine.ArgNewPassword, cmdLine.ArgNewKeyfiles, cmdLine.ArgHash); - return true; - - case CommandId::CreateKeyfile: - CreateKeyfile (cmdLine.ArgFilePath); - return true; - - case CommandId::CreateVolume: - { - make_shared_auto (VolumeCreationOptions, options); - - if (cmdLine.ArgHash) - { - options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*cmdLine.ArgHash); - RandomNumberGenerator::SetHash (cmdLine.ArgHash); - } - - options->EA = cmdLine.ArgEncryptionAlgorithm; - options->Filesystem = cmdLine.ArgFilesystem; - options->Keyfiles = cmdLine.ArgKeyfiles; - options->Password = cmdLine.ArgPassword; - options->Quick = cmdLine.ArgQuick; - options->Size = (cmdLine.ArgSize + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1); - options->Type = cmdLine.ArgVolumeType; - - if (cmdLine.ArgVolumePath) - options->Path = VolumePath (*cmdLine.ArgVolumePath); - - CreateVolume (options); - return true; - } - - case CommandId::DeleteSecurityTokenKeyfiles: - DeleteSecurityTokenKeyfiles(); - return true; - - case CommandId::DismountVolumes: - DismountVolumes (cmdLine.ArgVolumes, cmdLine.ArgForce, !Preferences.NonInteractive); - return true; - - case CommandId::DisplayVersion: - ShowString (Application::GetName() + L" " + StringConverter::ToWide (Version::String()) + L"\n"); - return true; - - case CommandId::DisplayVolumeProperties: - DisplayVolumeProperties (cmdLine.ArgVolumes); - return true; - - case CommandId::Help: - { - wstring helpText = StringConverter::ToWide ( - "Synopsis:\n" - "\n" - "truecrypt [OPTIONS] COMMAND\n" - "truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n" - "\n" - "\n" - "Commands:\n" - "\n" - "--auto-mount=devices|favorites\n" - " Auto mount device-hosted or favorite volumes.\n" - "\n" - "--backup-headers[=VOLUME_PATH]\n" - " Backup volume headers to a file. All required options are requested from the\n" - " user.\n" - "\n" - "-c, --create[=VOLUME_PATH]\n" - " Create a new volume. Most options are requested from the user if not specified\n" - " on command line. See also options --encryption, -k, --filesystem, --hash, -p,\n" - " --random-source, --quick, --size, --volume-type. Note that passing some of the\n" - " options may affect security of the volume (see option -p for more information).\n" - "\n" - " Inexperienced users should use the graphical user interface to create a hidden\n" - " volume. When using the text user interface, the following procedure must be\n" - " followed to create a hidden volume:\n" - " 1) Create an outer volume with no filesystem.\n" - " 2) Create a hidden volume within the outer volume.\n" - " 3) Mount the outer volume using hidden volume protection.\n" - " 4) Create a filesystem on the virtual device of the outer volume.\n" - " 5) Mount the new filesystem and fill it with data.\n" - " 6) Dismount the outer volume.\n" - " If at any step the hidden volume protection is triggered, start again from 1).\n" - "\n" - "--create-keyfile[=FILE_PATH]\n" - " Create a new keyfile containing pseudo-random data.\n" - "\n" - "-C, --change[=VOLUME_PATH]\n" - " Change a password and/or keyfile(s) of a volume. Most options are requested\n" - " from the user if not specified on command line. PKCS-5 PRF HMAC hash\n" - " algorithm can be changed with option --hash. See also options -k,\n" - " --new-keyfiles, --new-password, -p, --random-source, -v.\n" - "\n" - "-d, --dismount[=MOUNTED_VOLUME]\n" - " Dismount a mounted volume. If MOUNTED_VOLUME is not specified, all\n" - " volumes are dismounted. See below for description of MOUNTED_VOLUME.\n" - "\n" - "--delete-token-keyfiles\n" - " Delete keyfiles from security tokens. See also command --list-token-keyfiles.\n" - "\n" - "--import-token-keyfiles\n" - " Import keyfiles to a security token. See also option --token-lib.\n" - "\n" - "-l, --list[=MOUNTED_VOLUME]\n" - " Display a list of mounted volumes. If MOUNTED_VOLUME is not specified, all\n" - " volumes are listed. By default, the list contains only volume path, virtual\n" - " device, and mount point. A more detailed list can be enabled by verbose\n" - " output option (-v). See below for description of MOUNTED_VOLUME.\n" - "\n" - "--list-token-keyfiles\n" - " Display a list of all available security token keyfiles. See also command\n" - " --import-token-keyfiles.\n" - "\n" - "--mount[=VOLUME_PATH]\n" - " Mount a volume. Volume path and other options are requested from the user\n" - " if not specified on command line.\n" - "\n" - "--restore-headers[=VOLUME_PATH]\n" - " Restore volume headers from the embedded or an external backup. All required\n" - " options are requested from the user.\n" - "\n" - "--test\n" - " Test internal algorithms used in the process of encryption and decryption.\n" - "\n" - "--version\n" - " Display program version.\n" - "\n" - "--volume-properties[=MOUNTED_VOLUME]\n" - " Display properties of a mounted volume. See below for description of\n" - " MOUNTED_VOLUME.\n" - "\n" - "MOUNTED_VOLUME:\n" - " Specifies a mounted volume. One of the following forms can be used:\n" - " 1) Path to the encrypted TrueCrypt volume.\n" - " 2) Mount directory of the volume's filesystem (if mounted).\n" - " 3) Slot number of the mounted volume (requires --slot).\n" - "\n" - "\n" - "Options:\n" - "\n" - "--encryption=ENCRYPTION_ALGORITHM\n" - " Use specified encryption algorithm when creating a new volume.\n" - "\n" - "--filesystem=TYPE\n" - " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n" - " with option -t. Default type is 'auto'. When creating a new volume, this\n" - " option specifies the filesystem to be created on the new volume.\n" - " Filesystem type 'none' disables mounting or creating a filesystem.\n" - "\n" - "--force\n" - " Force mounting of a volume in use, dismounting of a volume in use, or\n" - " overwriting a file. Note that this option has no effect on some platforms.\n" - "\n" - "--fs-options=OPTIONS\n" - " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n" - " command with option -o when a filesystem on a TrueCrypt volume is mounted.\n" - " This option is not available on some platforms.\n" - "\n" - "--hash=HASH\n" - " Use specified hash algorithm when creating a new volume or changing password\n" - " and/or keyfiles. This option also specifies the mixing PRF of the random\n" - " number generator.\n" - "\n" - "-k, --keyfiles=KEYFILE1,KEYFILE2,KEYFILE3,..\n" - " Use specified keyfiles when mounting a volume or when changing password\n" - " and/or keyfiles. When a directory is specified, all files inside it will be\n" - " used (non-recursively). Multiple keyfiles must be separated by comma.\n" - " Use double comma (,,) to specify a comma contained in keyfile's name.\n" - " Keyfile stored on a security token must be specified as\n" - " token://slot/SLOT_NUMBER/file/FILENAME. An empty keyfile (-k \"\") disables\n" - " interactive requests for keyfiles. See also options --import-token-keyfiles,\n" - " --list-token-keyfiles, --new-keyfiles, --protection-keyfiles.\n" - "\n" - "-m, --mount-options=headerbak|nokernelcrypto|readonly|ro|system|timestamp|ts\n" - " Specify comma-separated mount options for a TrueCrypt volume:\n" - " headerbak: Use backup headers when mounting a volume.\n" - " nokernelcrypto: Do not use kernel cryptographic services.\n" - " readonly|ro: Mount volume as read-only.\n" - " system: Mount partition using system encryption.\n" - " timestamp|ts: Do not preserve host-file timestamps (note that the operating\n" - " system under certain circumstances does not alter host-file timestamps, which\n" - " may be mistakenly interpreted to mean that this option does not work).\n" - " See also option --fs-options.\n" - "\n" - "-p, --password=PASSWORD\n" - " Use specified password to mount/open a volume. An empty password can also be\n" - " specified (-p \"\"). Note that passing a password on the command line is\n" - " potentially insecure as the password may be visible in the process list\n" - " (see ps(1)) and/or stored in a command history file or system logs.\n" - "\n" - "--protect-hidden=yes|no\n" - " Write-protect a hidden volume when mounting an outer volume. Before mounting\n" - " the outer volume, the user will be prompted for a password to open the hidden\n" - " volume. The size and position of the hidden volume is then determined and the\n" - " outer volume is mounted with all sectors belonging to the hidden volume\n" - " protected against write operations. When a write to the protected area is\n" - " prevented, the whole volume is switched to read-only mode. Verbose list\n" - " (-v -l) can be used to query the state of the hidden volume protection.\n" - " Warning message is displayed when a volume switched to read-only is being\n" - " dismounted.\n" - "\n" - "--protection-keyfiles=KEYFILE1,KEYFILE2,KEYFILE3,..\n" - " Use specified keyfiles to open a hidden volume to be protected. This option\n" - " may be used only when mounting an outer volume with hidden volume protected.\n" - " See also options -k and --protect-hidden.\n" - "\n" - "--protection-password=PASSWORD\n" - " Use specified password to open a hidden volume to be protected. This option\n" - " may be used only when mounting an outer volume with hidden volume protected.\n" - " See also options -p and --protect-hidden.\n" - "\n" - "--quick\n" - " Use quick format when creating a new volume. This option can be used only\n" - " when creating a device-hosted volume and must not be used when creating an\n" - " outer volume.\n" - "\n" - "--random-source=FILE\n" - " Use FILE as a source of random data (e.g., when creating a volume) instead\n" - " of requiring the user to type random characters.\n" - "\n" - "--slot=SLOT\n" - " Use specified slot number when mounting, dismounting, or listing a volume.\n" - "\n" - "--size=SIZE\n" - " Use specified size in bytes when creating a new volume.\n" - "\n" - "-t, --text\n" - " Use text user interface. Graphical user interface is used by default if\n" - " available.\n" - "\n" - "--token-lib=LIB_PATH\n" - " Use specified PKCS #11 security token library.\n" - "\n" - "--volume-type=TYPE\n" - " Use specified volume type when creating a new volume. TYPE can be 'normal'\n" - " or 'hidden'. See option -c for more information on creating hidden volumes.\n" - "\n" - "-v, --verbose\n" - " Enable verbose output.\n" - "\n" - "\nExamples:\n\n" - "Create a new volume:\n" - "truecrypt -t -c\n" - "\n" - "Mount a volume:\n" - "truecrypt volume.tc /media/truecrypt1\n" - "\n" - "Mount a volume as read-only, using keyfiles:\n" - "truecrypt -m ro -k keyfile1,keyfile2 volume.tc\n" - "\n" - "Mount a volume without mounting its filesystem:\n" - "truecrypt --filesystem=none volume.tc\n" - "\n" - "Mount a volume prompting only for its password:\n" - "truecrypt -t -k \"\" --protect-hidden=no volume.tc /media/truecrypt1\n" - "\n" - "Dismount a volume:\n" - "truecrypt -d volume.tc\n" - "\n" - "Dismount all mounted volumes:\n" - "truecrypt -d\n" - ); - -#ifndef TC_NO_GUI - if (Application::GetUserInterfaceType() == UserInterfaceType::Graphic) - { - wxDialog dialog (nullptr, wxID_ANY, _("TrueCrypt Command Line Help"), wxDefaultPosition); - - wxTextCtrl *textCtrl = new wxTextCtrl (&dialog, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY); - textCtrl->SetFont (wxFont (wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Courier")); - textCtrl->SetValue (helpText); - - int fontWidth, fontHeight; - textCtrl->GetTextExtent (L"A", &fontWidth, &fontHeight); - dialog.SetSize (wxSize (fontWidth * 85, fontHeight * 29)); - - wxBoxSizer *sizer = new wxBoxSizer (wxVERTICAL); - sizer->Add (textCtrl, 1, wxALL | wxEXPAND, 5); - sizer->Add (new wxButton (&dialog, wxID_OK, _("OK")), 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 5); - - dialog.SetSizer (sizer); - dialog.Layout(); - dialog.ShowModal(); - } - else -#endif // !TC_NO_GUI - { - ShowString (L"\n\n"); - ShowString (helpText); - } - } - return true; - - case CommandId::ImportSecurityTokenKeyfiles: - ImportSecurityTokenKeyfiles(); - return true; - - case CommandId::ListSecurityTokenKeyfiles: - ListSecurityTokenKeyfiles(); - return true; - - case CommandId::ListVolumes: - if (Preferences.Verbose) - DisplayVolumeProperties (cmdLine.ArgVolumes); - else - ListMountedVolumes (cmdLine.ArgVolumes); - return true; - - case CommandId::RestoreHeaders: - RestoreVolumeHeaders (cmdLine.ArgVolumePath); - return true; - - case CommandId::Test: - Test(); - return true; - - default: - throw ParameterIncorrect (SRC_POS); - } - - return false; - } - - void UserInterface::SetPreferences (const UserPreferences &preferences) - { - Preferences = preferences; - PreferencesUpdatedEvent.Raise(); - } - - void UserInterface::ShowError (const exception &ex) const - { - if (!dynamic_cast (&ex)) - DoShowError (ExceptionToMessage (ex)); - } - - wxString UserInterface::SizeToString (uint64 size) const - { - wstringstream s; - if (size > 1024ULL*1024*1024*1024*1024*99) - s << size/1024/1024/1024/1024/1024 << L" " << LangString["PB"].c_str(); - else if (size > 1024ULL*1024*1024*1024*1024) - return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024/1024), LangString["PB"].c_str()); - else if (size > 1024ULL*1024*1024*1024*99) - s << size/1024/1024/1024/1024 << L" " << LangString["TB"].c_str(); - else if (size > 1024ULL*1024*1024*1024) - return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024), LangString["TB"].c_str()); - else if (size > 1024ULL*1024*1024*99) - s << size/1024/1024/1024 << L" " << LangString["GB"].c_str(); - else if (size > 1024ULL*1024*1024) - return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024), LangString["GB"].c_str()); - else if (size > 1024ULL*1024*99) - s << size/1024/1024 << L" " << LangString["MB"].c_str(); - else if (size > 1024ULL*1024) - return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024), LangString["MB"].c_str()); - else if (size > 1024ULL) - s << size/1024 << L" " << LangString["KB"].c_str(); - else - s << size << L" " << LangString["BYTE"].c_str(); - - return s.str(); - } - - wxString UserInterface::SpeedToString (uint64 speed) const - { - wstringstream s; - - if (speed > 1024ULL*1024*1024*1024*1024*99) - s << speed/1024/1024/1024/1024/1024 << L" " << LangString["PB_PER_SEC"].c_str(); - else if (speed > 1024ULL*1024*1024*1024*1024) - return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024/1024), LangString["PB_PER_SEC"].c_str()); - else if (speed > 1024ULL*1024*1024*1024*99) - s << speed/1024/1024/1024/1024 << L" " << LangString["TB_PER_SEC"].c_str(); - else if (speed > 1024ULL*1024*1024*1024) - return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024), LangString["TB_PER_SEC"].c_str()); - else if (speed > 1024ULL*1024*1024*99) - s << speed/1024/1024/1024 << L" " << LangString["GB_PER_SEC"].c_str(); - else if (speed > 1024ULL*1024*999) - return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024), LangString["GB_PER_SEC"].c_str()); - else if (speed > 1024ULL*1024*9) - s << speed/1024/1024 << L" " << LangString["MB_PER_SEC"].c_str(); - else if (speed > 1024ULL*999) - return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024), LangString["MB_PER_SEC"].c_str()); - else if (speed > 1024ULL) - s << speed/1024 << L" " << LangString["KB_PER_SEC"].c_str(); - else - s << speed << L" " << LangString["B_PER_SEC"].c_str(); - - return s.str(); - } - - void UserInterface::Test () const - { - if (!PlatformTest::TestAll()) - throw TestFailed (SRC_POS); - - EncryptionTest::TestAll(); - - // StringFormatter - if (StringFormatter (L"{9} {8} {7} {6} {5} {4} {3} {2} {1} {0} {{0}}", "1", L"2", '3', L'4', 5, 6, 7, 8, 9, 10) != L"10 9 8 7 6 5 4 3 2 1 {0}") - throw TestFailed (SRC_POS); - try - { - StringFormatter (L"{0} {1}", 1); - throw TestFailed (SRC_POS); - } - catch (StringFormatterException&) { } - - try - { - StringFormatter (L"{0} {1} {1}", 1, 2, 3); - throw TestFailed (SRC_POS); - } - catch (StringFormatterException&) { } - - try - { - StringFormatter (L"{0} 1}", 1, 2); - throw TestFailed (SRC_POS); - } - catch (StringFormatterException&) { } - - try - { - StringFormatter (L"{0} {1", 1, 2); - throw TestFailed (SRC_POS); - } - catch (StringFormatterException&) { } - - ShowInfo ("TESTS_PASSED"); - } - - wxString UserInterface::TimeSpanToString (uint64 seconds) const - { - wstringstream s; - - if (seconds >= 60 * 60 * 24 * 2) - s << seconds / (60 * 24 * 60) << L" " << LangString["DAYS"].c_str(); - else if (seconds >= 120 * 60) - s << seconds / (60 * 60) << L" " << LangString["HOURS"].c_str(); - else if (seconds >= 120) - s << seconds / 60 << L" " << LangString["MINUTES"].c_str(); - else - s << seconds << L" " << LangString["SECONDS"].c_str(); - - return s.str(); - } - - bool UserInterface::VolumeHasUnrecommendedExtension (const VolumePath &path) const - { - wxString ext = wxFileName (wxString (wstring (path)).Lower()).GetExt(); - return ext.IsSameAs (L"exe") || ext.IsSameAs (L"sys") || ext.IsSameAs (L"dll"); - } - - wxString UserInterface::VolumeTimeToString (VolumeTime volumeTime) const - { - wxString dateStr = VolumeTimeToDateTime (volumeTime).Format(); - -#ifdef TC_WINDOWS - - FILETIME ft; - *(unsigned __int64 *)(&ft) = volumeTime; - SYSTEMTIME st; - FileTimeToSystemTime (&ft, &st); - - wchar_t wstr[1024]; - if (GetDateFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr)) != 0) - { - dateStr = wstr; - GetTimeFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr)); - dateStr += wxString (L" ") + wstr; - } -#endif - return dateStr; - } - - wxString UserInterface::VolumeTypeToString (VolumeType::Enum type, VolumeProtection::Enum protection) const - { - switch (type) - { - case VolumeType::Normal: - return LangString[protection == VolumeProtection::HiddenVolumeReadOnly ? "OUTER" : "NORMAL"]; - - case VolumeType::Hidden: - return LangString["HIDDEN"]; - - default: - return L"?"; - } - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include +#include +#include +#include +#include "Platform/PlatformTest.h" +#ifdef TC_UNIX +#include +#include "Platform/Unix/Process.h" +#endif +#include "Platform/SystemInfo.h" +#include "Common/SecurityToken.h" +#include "Volume/EncryptionTest.h" +#include "Application.h" +#include "FavoriteVolume.h" +#include "UserInterface.h" + +namespace TrueCrypt +{ + UserInterface::UserInterface () + { + } + + UserInterface::~UserInterface () + { + Core->WarningEvent.Disconnect (this); + Core->VolumeMountedEvent.Disconnect (this); + + try + { + if (SecurityToken::IsInitialized()) + SecurityToken::CloseLibrary(); + } + catch (...) { } + } + + void UserInterface::CheckRequirementsForMountingVolume () const + { +#ifdef TC_LINUX + if (!Preferences.NonInteractive) + { + vector osVersion = SystemInfo::GetVersion(); + + if (osVersion.size() >= 3 && osVersion[0] == 2 && osVersion[1] == 6 && osVersion[2] < 24) + ShowWarning (_("Your system uses an old version of the Linux kernel.\n\nDue to a bug in the Linux kernel, your system may stop responding when writing data to a TrueCrypt volume. This problem can be solved by upgrading the kernel to version 2.6.24 or later.")); + } +#endif // TC_LINUX + } + + void UserInterface::CloseExplorerWindows (shared_ptr mountedVolume) const + { +#ifdef TC_WINDOWS + struct Args + { + HWND ExplorerWindow; + string DriveRootPath; + }; + + struct Enumerator + { + static BOOL CALLBACK ChildWindows (HWND hwnd, LPARAM argsLP) + { + Args *args = reinterpret_cast (argsLP); + + char s[4096]; + SendMessageA (hwnd, WM_GETTEXT, sizeof (s), (LPARAM) s); + + if (strstr (s, args->DriveRootPath.c_str()) != NULL) + { + PostMessage (args->ExplorerWindow, WM_CLOSE, 0, 0); + return FALSE; + } + + return TRUE; + } + + static BOOL CALLBACK TopLevelWindows (HWND hwnd, LPARAM argsLP) + { + Args *args = reinterpret_cast (argsLP); + + char s[4096]; + GetClassNameA (hwnd, s, sizeof s); + if (strcmp (s, "CabinetWClass") == 0) + { + GetWindowTextA (hwnd, s, sizeof s); + if (strstr (s, args->DriveRootPath.c_str()) != NULL) + { + PostMessage (hwnd, WM_CLOSE, 0, 0); + return TRUE; + } + + args->ExplorerWindow = hwnd; + EnumChildWindows (hwnd, ChildWindows, argsLP); + } + + return TRUE; + } + }; + + Args args; + + string mountPoint = mountedVolume->MountPoint; + if (mountPoint.size() < 2 || mountPoint[1] != ':') + return; + + args.DriveRootPath = string() + mountPoint[0] + string (":\\"); + + EnumWindows (Enumerator::TopLevelWindows, (LPARAM) &args); +#endif + } + + void UserInterface::DismountAllVolumes (bool ignoreOpenFiles, bool interactive) const + { + try + { + VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); + + if (mountedVolumes.size() < 1) + ShowInfo (LangString["NO_VOLUMES_MOUNTED"]); + + BusyScope busy (this); + DismountVolumes (mountedVolumes, ignoreOpenFiles, interactive); + } + catch (exception &e) + { + ShowError (e); + } + } + + void UserInterface::DismountVolume (shared_ptr volume, bool ignoreOpenFiles, bool interactive) const + { + VolumeInfoList volumes; + volumes.push_back (volume); + + DismountVolumes (volumes, ignoreOpenFiles, interactive); + } + + void UserInterface::DismountVolumes (VolumeInfoList volumes, bool ignoreOpenFiles, bool interactive) const + { + BusyScope busy (this); + + volumes.sort (VolumeInfo::FirstVolumeMountedAfterSecond); + + wxString message; + bool twoPassMode = volumes.size() > 1; + bool volumesInUse = false; + bool firstPass = true; + +#ifdef TC_WINDOWS + if (Preferences.CloseExplorerWindowsOnDismount) + { + foreach (shared_ptr volume, volumes) + CloseExplorerWindows (volume); + } +#endif + while (!volumes.empty()) + { + VolumeInfoList volumesLeft; + foreach (shared_ptr volume, volumes) + { + try + { + BusyScope busy (this); + volume = Core->DismountVolume (volume, ignoreOpenFiles); + } + catch (MountedVolumeInUse&) + { + if (!firstPass) + throw; + + if (twoPassMode || !interactive) + { + volumesInUse = true; + volumesLeft.push_back (volume); + continue; + } + else + { + if (AskYesNo (StringFormatter (LangString["UNMOUNT_LOCK_FAILED"], wstring (volume->Path)), true, true)) + { + BusyScope busy (this); + volume = Core->DismountVolume (volume, true); + } + else + throw UserAbort (SRC_POS); + } + } + catch (...) + { + if (twoPassMode && firstPass) + volumesLeft.push_back (volume); + else + throw; + } + + if (volume->HiddenVolumeProtectionTriggered) + ShowWarning (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (volume->Path))); + + if (Preferences.Verbose) + { + if (!message.IsEmpty()) + message += L'\n'; + message += StringFormatter (_("Volume \"{0}\" has been dismounted."), wstring (volume->Path)); + } + } + + if (twoPassMode && firstPass) + { + volumes = volumesLeft; + + if (volumesInUse && interactive) + { + if (AskYesNo (LangString["UNMOUNTALL_LOCK_FAILED"], true, true)) + ignoreOpenFiles = true; + else + throw UserAbort (SRC_POS); + } + } + else + break; + + firstPass = false; + } + + if (Preferences.Verbose && !message.IsEmpty()) + ShowInfo (message); + } + + void UserInterface::DisplayVolumeProperties (const VolumeInfoList &volumes) const + { + if (volumes.size() < 1) + throw_err (LangString["NO_VOLUMES_MOUNTED"]); + + wxString prop; + + foreach_ref (const VolumeInfo &volume, volumes) + { + prop << _("Slot") << L": " << StringConverter::FromNumber (volume.SlotNumber) << L'\n'; + prop << LangString["VOLUME"] << L": " << wstring (volume.Path) << L'\n'; +#ifndef TC_WINDOWS + prop << LangString["VIRTUAL_DEVICE"] << L": " << wstring (volume.VirtualDevice) << L'\n'; +#endif + prop << LangString["MOUNT_POINT"] << L": " << wstring (volume.MountPoint) << L'\n'; + prop << LangString["SIZE"] << L": " << SizeToString (volume.Size) << L'\n'; + prop << LangString["TYPE"] << L": " << VolumeTypeToString (volume.Type, volume.Protection) << L'\n'; + + prop << LangString["READ_ONLY"] << L": " << LangString [volume.Protection == VolumeProtection::ReadOnly ? "UISTR_YES" : "UISTR_NO"] << L'\n'; + + wxString protection; + if (volume.Type == VolumeType::Hidden) + protection = LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"]; + else if (volume.HiddenVolumeProtectionTriggered) + protection = LangString["HID_VOL_DAMAGE_PREVENTED"]; + else + protection = LangString [volume.Protection == VolumeProtection::HiddenVolumeReadOnly ? "UISTR_YES" : "UISTR_NO"]; + + prop << LangString["HIDDEN_VOL_PROTECTION"] << L": " << protection << L'\n'; + prop << LangString["ENCRYPTION_ALGORITHM"] << L": " << volume.EncryptionAlgorithmName << L'\n'; + prop << LangString["KEY_SIZE"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n'; + + if (volume.EncryptionModeName == L"XTS") + prop << LangString["SECONDARY_KEY_SIZE_XTS"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n';; + + wstringstream blockSize; + blockSize << volume.EncryptionAlgorithmBlockSize * 8; + if (volume.EncryptionAlgorithmBlockSize != volume.EncryptionAlgorithmMinBlockSize) + blockSize << L"/" << volume.EncryptionAlgorithmMinBlockSize * 8; + + prop << LangString["BLOCK_SIZE"] << L": " << blockSize.str() + L" " + LangString ["BITS"] << L'\n'; + prop << LangString["MODE_OF_OPERATION"] << L": " << volume.EncryptionModeName << L'\n'; + prop << LangString["PKCS5_PRF"] << L": " << volume.Pkcs5PrfName << L'\n'; + + prop << LangString["VOLUME_FORMAT_VERSION"] << L": " << (volume.MinRequiredProgramVersion < 0x600 ? 1 : 2) << L'\n'; + prop << LangString["BACKUP_HEADER"] << L": " << LangString[volume.MinRequiredProgramVersion >= 0x600 ? "UISTR_YES" : "UISTR_NO"] << L'\n'; + +#ifdef TC_LINUX + if (string (volume.VirtualDevice).find ("/dev/mapper/truecrypt") != 0) + { +#endif + prop << LangString["TOTAL_DATA_READ"] << L": " << SizeToString (volume.TotalDataRead) << L'\n'; + prop << LangString["TOTAL_DATA_WRITTEN"] << L": " << SizeToString (volume.TotalDataWritten) << L'\n'; +#ifdef TC_LINUX + } +#endif + + prop << L'\n'; + } + + ShowString (prop); + } + + wxString UserInterface::ExceptionToMessage (const exception &ex) const + { + wxString message; + + const Exception *e = dynamic_cast (&ex); + if (e) + { + message = ExceptionToString (*e); + + // System exception + const SystemException *sysEx = dynamic_cast (&ex); + if (sysEx) + { + if (!message.IsEmpty()) + { + message += L"\n\n"; + } + + message += wxString (sysEx->SystemText()).Trim (true); + } + + if (!message.IsEmpty()) + { + // Subject + if (!e->GetSubject().empty()) + { + message = message.Trim (true); + + if (message.EndsWith (L".")) + message.Truncate (message.size() - 1); + + if (!message.EndsWith (L":")) + message << L":\n"; + else + message << L"\n"; + + message << e->GetSubject(); + } + +#ifdef TC_UNIX + if (sysEx && sysEx->GetErrorCode() == EIO) + message << L"\n\n" << LangString["ERR_HARDWARE_ERROR"]; +#endif + +#ifdef DEBUG + if (sysEx && sysEx->what()) + message << L"\n\n" << StringConverter::ToWide (sysEx->what()); +#endif + return message; + } + } + + // bad_alloc + const bad_alloc *outOfMemory = dynamic_cast (&ex); + if (outOfMemory) + return _("Out of memory."); + + // Unresolved exceptions + string typeName (StringConverter::GetTypeName (typeid (ex))); + size_t pos = typeName.find ("TrueCrypt::"); + if (pos != string::npos) + { + return StringConverter::ToWide (typeName.substr (pos + string ("TrueCrypt::").size())) + + L" at " + StringConverter::ToWide (ex.what()); + } + + return StringConverter::ToWide (typeName) + L" at " + StringConverter::ToWide (ex.what()); + } + + wxString UserInterface::ExceptionToString (const Exception &ex) const + { + // Error messages + const ErrorMessage *errMsgEx = dynamic_cast (&ex); + if (errMsgEx) + return wstring (*errMsgEx).c_str(); + + // ExecutedProcessFailed + const ExecutedProcessFailed *execEx = dynamic_cast (&ex); + if (execEx) + { + wstring errOutput; + + // ElevationFailed + if (dynamic_cast (&ex)) + errOutput += wxString (_("Failed to obtain administrator privileges")) + (StringConverter::Trim (execEx->GetErrorOutput()).empty() ? L". " : L": "); + + errOutput += StringConverter::ToWide (execEx->GetErrorOutput()); + + if (errOutput.empty()) + return errOutput + StringFormatter (_("Command \"{0}\" returned error {1}."), execEx->GetCommand(), execEx->GetExitCode()); + + return wxString (errOutput).Trim (true); + } + + // PasswordIncorrect + if (dynamic_cast (&ex)) + { + wxString message = ExceptionTypeToString (typeid (ex)); + +#ifndef TC_NO_GUI + if (Application::GetUserInterfaceType() == UserInterfaceType::Graphic && wxGetKeyState (WXK_CAPITAL)) + message += wxString (L"\n\n") + LangString["CAPSLOCK_ON"]; +#endif + return message; + } + + // PKCS#11 Exception + if (dynamic_cast (&ex)) + { + string errorString = string (dynamic_cast (ex)); + + if (LangString.Exists (errorString)) + return LangString[errorString]; + + if (errorString.find ("CKR_") == 0) + { + errorString = errorString.substr (4); + for (size_t i = 0; i < errorString.size(); ++i) + { + if (errorString[i] == '_') + errorString[i] = ' '; + } + } + + return LangString["SECURITY_TOKEN_ERROR"] + L":\n\n" + StringConverter::ToWide (errorString); + } + + // Other library exceptions + return ExceptionTypeToString (typeid (ex)); + } + + wxString UserInterface::ExceptionTypeToString (const std::type_info &ex) const + { +#define EX2MSG(exception, message) do { if (ex == typeid (exception)) return (message); } while (false) + EX2MSG (DriveLetterUnavailable, LangString["DRIVE_LETTER_UNAVAILABLE"]); + EX2MSG (EncryptedSystemRequired, _("This operation must be performed only when the system hosted on the volume is running.")); + EX2MSG (ExternalException, LangString["EXCEPTION_OCCURRED"]); + EX2MSG (InsufficientData, _("Not enough data available.")); + EX2MSG (InvalidSecurityTokenKeyfilePath, LangString["INVALID_TOKEN_KEYFILE_PATH"]); + EX2MSG (HigherVersionRequired, LangString["NEW_VERSION_REQUIRED"]); + EX2MSG (KernelCryptoServiceTestFailed, _("Kernel cryptographic service test failed. The cryptographic service of your kernel most likely does not support volumes larger than 2 TB.\n\nPossible solutions:\n- Try upgrading your kernel.\n- Disable use of the kernel cryptographic services (Settings > Preferences > System Integration) or use 'nokernelcrypto' mount option on the command line.")); + EX2MSG (LoopDeviceSetupFailed, _("Failed to set up a loop device.")); + EX2MSG (MissingArgument, _("A required argument is missing.")); + EX2MSG (MissingVolumeData, _("Volume data missing.")); + EX2MSG (MountPointRequired, _("Mount point required.")); + EX2MSG (MountPointUnavailable, _("Mount point is already in use.")); + EX2MSG (NoDriveLetterAvailable, LangString["NO_FREE_DRIVES"]); + EX2MSG (PasswordEmpty, _("No password or keyfile specified.")); + EX2MSG (PasswordIncorrect, LangString["PASSWORD_WRONG"]); + EX2MSG (PasswordKeyfilesIncorrect, LangString["PASSWORD_OR_KEYFILE_WRONG"]); + EX2MSG (PasswordOrKeyboardLayoutIncorrect, LangString["PASSWORD_OR_KEYFILE_WRONG"] + _("\n\nNote that pre-boot authentication passwords need to be typed in the pre-boot environment where non-US keyboard layouts are not available. Therefore, pre-boot authentication passwords must always be typed using the standard US keyboard layout (otherwise, the password will be typed incorrectly in most cases). However, note that you do NOT need a real US keyboard; you just need to change the keyboard layout in your operating system.")); + EX2MSG (PasswordOrMountOptionsIncorrect, LangString["PASSWORD_OR_KEYFILE_OR_MODE_WRONG"] + _("\n\nNote: If you are attempting to mount a partition located on an encrypted system drive without pre-boot authentication or to mount the encrypted system partition of an operating system that is not running, you can do so by selecting 'Options >' > 'Mount partition using system encryption'.")); + EX2MSG (PasswordTooLong, StringFormatter (_("Password is longer than {0} characters."), (int) VolumePassword::MaxSize)); + EX2MSG (PartitionDeviceRequired, _("Partition device required.")); + EX2MSG (ProtectionPasswordIncorrect, _("Incorrect password to the protected hidden volume or the hidden volume does not exist.")); + EX2MSG (ProtectionPasswordKeyfilesIncorrect,_("Incorrect keyfile(s) and/or password to the protected hidden volume or the hidden volume does not exist.")); + EX2MSG (RootDeviceUnavailable, LangString["NODRIVER"]); + EX2MSG (SecurityTokenKeyfileAlreadyExists, LangString["TOKEN_KEYFILE_ALREADY_EXISTS"]); + EX2MSG (SecurityTokenKeyfileNotFound, LangString["TOKEN_KEYFILE_NOT_FOUND"]); + EX2MSG (SecurityTokenLibraryNotInitialized, LangString["PKCS11_MODULE_INIT_FAILED"]); + EX2MSG (StringConversionFailed, _("Invalid characters encountered.")); + EX2MSG (StringFormatterException, _("Error while parsing formatted string.")); + EX2MSG (TemporaryDirectoryFailure, _("Failed to create a file or directory in a temporary directory.\n\nPlease make sure that the temporary directory exists, its security permissions allow you to access it, and there is sufficient disk space.")); + EX2MSG (UnportablePassword, LangString["UNSUPPORTED_CHARS_IN_PWD"]); + EX2MSG (UnsupportedSectorSize, LangString["LARGE_SECTOR_UNSUPPORTED"]); + EX2MSG (VolumeAlreadyMounted, LangString["VOL_ALREADY_MOUNTED"]); + EX2MSG (VolumeEncryptionNotCompleted, LangString["ERR_ENCRYPTION_NOT_COMPLETED"]); + EX2MSG (VolumeHostInUse, _("The host file/device is already in use.")); + EX2MSG (VolumeSlotUnavailable, _("Volume slot unavailable.")); + +#ifdef TC_MACOSX + EX2MSG (HigherFuseVersionRequired, _("TrueCrypt requires MacFUSE 1.3 or later.")); +#endif + +#undef EX2MSG + return L""; + } + + void UserInterface::Init () + { + SetAppName (Application::GetName()); + SetClassName (Application::GetName()); + + LangString.Init(); + Core->Init(); + + wxCmdLineParser parser; + parser.SetCmdLine (argc, argv); + CmdLine.reset (new CommandLineInterface (parser, InterfaceType)); + SetPreferences (CmdLine->Preferences); + + Core->SetApplicationExecutablePath (Application::GetExecutablePath()); + + if (!Preferences.NonInteractive) + { + Core->SetAdminPasswordCallback (GetAdminPasswordRequestHandler()); + } + else + { + struct AdminPasswordRequestHandler : public GetStringFunctor + { + virtual void operator() (string &str) + { + throw ElevationFailed (SRC_POS, "sudo", 1, ""); + } + }; + + Core->SetAdminPasswordCallback (shared_ptr (new AdminPasswordRequestHandler)); + } + + Core->WarningEvent.Connect (EventConnector (this, &UserInterface::OnWarning)); + Core->VolumeMountedEvent.Connect (EventConnector (this, &UserInterface::OnVolumeMounted)); + + if (!CmdLine->Preferences.SecurityTokenModule.IsEmpty() && !SecurityToken::IsInitialized()) + { + try + { + InitSecurityTokenLibrary(); + } + catch (exception &e) + { + if (Preferences.NonInteractive) + throw; + + ShowError (e); + } + } + } + + void UserInterface::ListMountedVolumes (const VolumeInfoList &volumes) const + { + if (volumes.size() < 1) + throw_err (LangString["NO_VOLUMES_MOUNTED"]); + + wxString message; + + foreach_ref (const VolumeInfo &volume, volumes) + { + message << volume.SlotNumber << L": " << StringConverter::QuoteSpaces (volume.Path); + + if (!volume.VirtualDevice.IsEmpty()) + message << L' ' << wstring (volume.VirtualDevice); + else + message << L" - "; + + if (!volume.MountPoint.IsEmpty()) + message << L' ' << StringConverter::QuoteSpaces (volume.MountPoint); + else + message << L" - "; + + message << L'\n'; + } + + ShowString (message); + } + + VolumeInfoList UserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const + { + BusyScope busy (this); + + VolumeInfoList newMountedVolumes; + + if (!options.MountPoint) + options.MountPoint.reset (new DirectoryPath); + + Core->CoalesceSlotNumberAndMountPoint (options); + + bool sharedAccessAllowed = options.SharedAccessAllowed; + bool someVolumesShared = false; + + HostDeviceList devices; + foreach (shared_ptr device, Core->GetHostDevices (true)) + { + devices.push_back (device); + + foreach (shared_ptr partition, device->Partitions) + devices.push_back (partition); + } + + set mountedVolumes; + foreach_ref (const VolumeInfo &v, Core->GetMountedVolumes()) + mountedVolumes.insert (v.Path); + + bool protectedVolumeMounted = false; + bool legacyVolumeMounted = false; + + foreach_ref (const HostDevice &device, devices) + { + if (mountedVolumes.find (wstring (device.Path)) != mountedVolumes.end()) + continue; + + Yield(); + options.SlotNumber = Core->GetFirstFreeSlotNumber (options.SlotNumber); + options.MountPoint.reset (new DirectoryPath); + options.Path.reset (new VolumePath (device.Path)); + + try + { + try + { + options.SharedAccessAllowed = sharedAccessAllowed; + newMountedVolumes.push_back (Core->MountVolume (options)); + } + catch (VolumeHostInUse&) + { + if (!sharedAccessAllowed) + { + try + { + options.SharedAccessAllowed = true; + newMountedVolumes.push_back (Core->MountVolume (options)); + someVolumesShared = true; + } + catch (VolumeHostInUse&) + { + continue; + } + } + else + continue; + } + + if (newMountedVolumes.back()->Protection == VolumeProtection::HiddenVolumeReadOnly) + protectedVolumeMounted = true; + + if (newMountedVolumes.back()->EncryptionAlgorithmMinBlockSize == 8) + legacyVolumeMounted = true; + } + catch (DriverError&) { } + catch (MissingVolumeData&) { } + catch (PasswordException&) { } + catch (SystemException&) { } + } + + if (newMountedVolumes.empty()) + { + ShowWarning (LangString [options.Keyfiles && !options.Keyfiles->empty() ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT"]); + } + else + { + if (someVolumesShared) + ShowWarning ("DEVICE_IN_USE_INFO"); + + if (legacyVolumeMounted) + ShowWarning ("WARN_64_BIT_BLOCK_CIPHER"); + + if (protectedVolumeMounted) + ShowInfo (LangString[newMountedVolumes.size() > 1 ? "HIDVOL_PROT_WARN_AFTER_MOUNT_PLURAL" : "HIDVOL_PROT_WARN_AFTER_MOUNT"]); + } + + if (!newMountedVolumes.empty() && GetPreferences().CloseSecurityTokenSessionsAfterMount) + SecurityToken::CloseAllSessions(); + + return newMountedVolumes; + } + + VolumeInfoList UserInterface::MountAllFavoriteVolumes (MountOptions &options) + { + BusyScope busy (this); + + VolumeInfoList newMountedVolumes; + foreach_ref (const FavoriteVolume &favorite, FavoriteVolume::LoadList()) + { + shared_ptr mountedVolume = Core->GetMountedVolume (favorite.Path); + if (mountedVolume) + { + if (mountedVolume->MountPoint != favorite.MountPoint) + ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (favorite.Path))); + continue; + } + + favorite.ToMountOptions (options); + + if (Preferences.NonInteractive) + { + BusyScope busy (this); + newMountedVolumes.push_back (Core->MountVolume (options)); + } + else + { + try + { + BusyScope busy (this); + newMountedVolumes.push_back (Core->MountVolume (options)); + } + catch (...) + { + UserPreferences prefs = GetPreferences(); + if (prefs.CloseSecurityTokenSessionsAfterMount) + Preferences.CloseSecurityTokenSessionsAfterMount = false; + + shared_ptr volume = MountVolume (options); + + if (prefs.CloseSecurityTokenSessionsAfterMount) + Preferences.CloseSecurityTokenSessionsAfterMount = true; + + if (!volume) + break; + newMountedVolumes.push_back (volume); + } + } + } + + if (!newMountedVolumes.empty() && GetPreferences().CloseSecurityTokenSessionsAfterMount) + SecurityToken::CloseAllSessions(); + + return newMountedVolumes; + } + + shared_ptr UserInterface::MountVolume (MountOptions &options) const + { + shared_ptr volume; + + try + { + volume = Core->MountVolume (options); + } + catch (VolumeHostInUse&) + { + if (options.SharedAccessAllowed) + throw_err (LangString["FILE_IN_USE_FAILED"]); + + if (!AskYesNo (StringFormatter (LangString["VOLUME_HOST_IN_USE"], wstring (*options.Path)), false, true)) + throw UserAbort (SRC_POS); + + try + { + options.SharedAccessAllowed = true; + volume = Core->MountVolume (options); + } + catch (VolumeHostInUse&) + { + throw_err (LangString["FILE_IN_USE_FAILED"]); + } + } + + if (volume->EncryptionAlgorithmMinBlockSize == 8) + ShowWarning ("WARN_64_BIT_BLOCK_CIPHER"); + + if (VolumeHasUnrecommendedExtension (*options.Path)) + ShowWarning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); + + if (options.Protection == VolumeProtection::HiddenVolumeReadOnly) + ShowInfo ("HIDVOL_PROT_WARN_AFTER_MOUNT"); + + if (GetPreferences().CloseSecurityTokenSessionsAfterMount) + SecurityToken::CloseAllSessions(); + + return volume; + } + + void UserInterface::OnUnhandledException () + { + try + { + throw; + } + catch (UserAbort&) + { + } + catch (exception &e) + { + ShowError (e); + } + catch (...) + { + ShowError (_("Unknown exception occurred.")); + } + + Yield(); + Application::SetExitCode (1); + } + + void UserInterface::OnVolumeMounted (EventArgs &args) + { + shared_ptr mountedVolume = (dynamic_cast (args)).mVolume; + + if (Preferences.OpenExplorerWindowAfterMount && !mountedVolume->MountPoint.IsEmpty()) + OpenExplorerWindow (mountedVolume->MountPoint); + } + + void UserInterface::OnWarning (EventArgs &args) + { + ExceptionEventArgs &e = dynamic_cast (args); + ShowWarning (e.mException); + } + + void UserInterface::OpenExplorerWindow (const DirectoryPath &path) + { + if (path.IsEmpty()) + return; + + list args; + +#ifdef TC_WINDOWS + + wstring p (Directory::AppendSeparator (path)); + SHFILEINFO fInfo; + SHGetFileInfo (p.c_str(), 0, &fInfo, sizeof (fInfo), 0); // Force explorer to discover the drive + ShellExecute (GetTopWindow() ? static_cast (GetTopWindow()->GetHandle()) : nullptr, L"open", p.c_str(), nullptr, nullptr, SW_SHOWNORMAL); + +#elif defined (TC_MACOSX) + + args.push_back (string (path)); + try + { + Process::Execute ("open", args); + } + catch (exception &e) { ShowError (e); } + +#else + // MIME handler for directory seems to be unavailable through wxWidgets + wxString desktop = GetTraits()->GetDesktopEnvironment(); + + if (desktop == L"GNOME" || desktop.empty()) + { + args.push_back ("--no-default-window"); + args.push_back ("--no-desktop"); + args.push_back (string (path)); + try + { + Process::Execute ("nautilus", args, 2000); + } + catch (TimeOut&) { } + catch (exception &e) { ShowError (e); } + } + else if (desktop == L"KDE") + { + try + { + args.push_back (string (path)); + Process::Execute ("dolphin", args, 2000); + } + catch (TimeOut&) { } + catch (exception&) + { + args.clear(); + args.push_back ("openURL"); + args.push_back (string (path)); + try + { + Process::Execute ("kfmclient", args, 2000); + } + catch (TimeOut&) { } + catch (exception &e) { ShowError (e); } + } + } +#endif + } + + bool UserInterface::ProcessCommandLine () + { + CommandLineInterface &cmdLine = *CmdLine; + + switch (cmdLine.ArgCommand) + { + case CommandId::None: + return false; + + case CommandId::AutoMountDevices: + case CommandId::AutoMountFavorites: + case CommandId::AutoMountDevicesFavorites: + case CommandId::MountVolume: + { + cmdLine.ArgMountOptions.Path = cmdLine.ArgVolumePath; + cmdLine.ArgMountOptions.MountPoint = cmdLine.ArgMountPoint; + cmdLine.ArgMountOptions.Password = cmdLine.ArgPassword; + cmdLine.ArgMountOptions.Keyfiles = cmdLine.ArgKeyfiles; + cmdLine.ArgMountOptions.SharedAccessAllowed = cmdLine.ArgForce; + + VolumeInfoList mountedVolumes; + switch (cmdLine.ArgCommand) + { + case CommandId::AutoMountDevices: + case CommandId::AutoMountFavorites: + case CommandId::AutoMountDevicesFavorites: + { + if (cmdLine.ArgCommand == CommandId::AutoMountDevices || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites) + { + if (Preferences.NonInteractive) + mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions); + else + mountedVolumes = MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions); + } + + if (cmdLine.ArgCommand == CommandId::AutoMountFavorites || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites) + { + foreach (shared_ptr v, MountAllFavoriteVolumes(cmdLine.ArgMountOptions)) + mountedVolumes.push_back (v); + } + } + break; + + + break; + + case CommandId::MountVolume: + if (Preferences.OpenExplorerWindowAfterMount) + { + // Open explorer window for an already mounted volume + shared_ptr mountedVolume = Core->GetMountedVolume (*cmdLine.ArgMountOptions.Path); + if (mountedVolume && !mountedVolume->MountPoint.IsEmpty()) + { + OpenExplorerWindow (mountedVolume->MountPoint); + break; + } + } + + if (Preferences.NonInteractive) + { + // Volume path + if (!cmdLine.ArgMountOptions.Path) + throw MissingArgument (SRC_POS); + + mountedVolumes.push_back (Core->MountVolume (cmdLine.ArgMountOptions)); + } + else + { + shared_ptr volume = MountVolume (cmdLine.ArgMountOptions); + if (!volume) + { + Application::SetExitCode (1); + throw UserAbort (SRC_POS); + } + mountedVolumes.push_back (volume); + } + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + + if (Preferences.Verbose && !mountedVolumes.empty()) + { + wxString message; + foreach_ref (const VolumeInfo &volume, mountedVolumes) + { + if (!message.IsEmpty()) + message += L'\n'; + message += StringFormatter (_("Volume \"{0}\" has been mounted."), wstring (volume.Path)); + } + ShowInfo (message); + } + } + return true; + + case CommandId::BackupHeaders: + BackupVolumeHeaders (cmdLine.ArgVolumePath); + return true; + + case CommandId::ChangePassword: + ChangePassword (cmdLine.ArgVolumePath, cmdLine.ArgPassword, cmdLine.ArgKeyfiles, cmdLine.ArgNewPassword, cmdLine.ArgNewKeyfiles, cmdLine.ArgHash); + return true; + + case CommandId::CreateKeyfile: + CreateKeyfile (cmdLine.ArgFilePath); + return true; + + case CommandId::CreateVolume: + { + make_shared_auto (VolumeCreationOptions, options); + + if (cmdLine.ArgHash) + { + options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*cmdLine.ArgHash); + RandomNumberGenerator::SetHash (cmdLine.ArgHash); + } + + options->EA = cmdLine.ArgEncryptionAlgorithm; + options->Filesystem = cmdLine.ArgFilesystem; + options->Keyfiles = cmdLine.ArgKeyfiles; + options->Password = cmdLine.ArgPassword; + options->Quick = cmdLine.ArgQuick; + options->Size = (cmdLine.ArgSize + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1); + options->Type = cmdLine.ArgVolumeType; + + if (cmdLine.ArgVolumePath) + options->Path = VolumePath (*cmdLine.ArgVolumePath); + + CreateVolume (options); + return true; + } + + case CommandId::DeleteSecurityTokenKeyfiles: + DeleteSecurityTokenKeyfiles(); + return true; + + case CommandId::DismountVolumes: + DismountVolumes (cmdLine.ArgVolumes, cmdLine.ArgForce, !Preferences.NonInteractive); + return true; + + case CommandId::DisplayVersion: + ShowString (Application::GetName() + L" " + StringConverter::ToWide (Version::String()) + L"\n"); + return true; + + case CommandId::DisplayVolumeProperties: + DisplayVolumeProperties (cmdLine.ArgVolumes); + return true; + + case CommandId::Help: + { + wstring helpText = StringConverter::ToWide ( + "Synopsis:\n" + "\n" + "truecrypt [OPTIONS] COMMAND\n" + "truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n" + "\n" + "\n" + "Commands:\n" + "\n" + "--auto-mount=devices|favorites\n" + " Auto mount device-hosted or favorite volumes.\n" + "\n" + "--backup-headers[=VOLUME_PATH]\n" + " Backup volume headers to a file. All required options are requested from the\n" + " user.\n" + "\n" + "-c, --create[=VOLUME_PATH]\n" + " Create a new volume. Most options are requested from the user if not specified\n" + " on command line. See also options --encryption, -k, --filesystem, --hash, -p,\n" + " --random-source, --quick, --size, --volume-type. Note that passing some of the\n" + " options may affect security of the volume (see option -p for more information).\n" + "\n" + " Inexperienced users should use the graphical user interface to create a hidden\n" + " volume. When using the text user interface, the following procedure must be\n" + " followed to create a hidden volume:\n" + " 1) Create an outer volume with no filesystem.\n" + " 2) Create a hidden volume within the outer volume.\n" + " 3) Mount the outer volume using hidden volume protection.\n" + " 4) Create a filesystem on the virtual device of the outer volume.\n" + " 5) Mount the new filesystem and fill it with data.\n" + " 6) Dismount the outer volume.\n" + " If at any step the hidden volume protection is triggered, start again from 1).\n" + "\n" + "--create-keyfile[=FILE_PATH]\n" + " Create a new keyfile containing pseudo-random data.\n" + "\n" + "-C, --change[=VOLUME_PATH]\n" + " Change a password and/or keyfile(s) of a volume. Most options are requested\n" + " from the user if not specified on command line. PKCS-5 PRF HMAC hash\n" + " algorithm can be changed with option --hash. See also options -k,\n" + " --new-keyfiles, --new-password, -p, --random-source.\n" + "\n" + "-d, --dismount[=MOUNTED_VOLUME]\n" + " Dismount a mounted volume. If MOUNTED_VOLUME is not specified, all\n" + " volumes are dismounted. See below for description of MOUNTED_VOLUME.\n" + "\n" + "--delete-token-keyfiles\n" + " Delete keyfiles from security tokens. See also command --list-token-keyfiles.\n" + "\n" + "--export-token-keyfile\n" + " Export a keyfile from a security token. See also command --list-token-keyfiles.\n" + "\n" + "--import-token-keyfiles\n" + " Import keyfiles to a security token. See also option --token-lib.\n" + "\n" + "-l, --list[=MOUNTED_VOLUME]\n" + " Display a list of mounted volumes. If MOUNTED_VOLUME is not specified, all\n" + " volumes are listed. By default, the list contains only volume path, virtual\n" + " device, and mount point. A more detailed list can be enabled by verbose\n" + " output option (-v). See below for description of MOUNTED_VOLUME.\n" + "\n" + "--list-token-keyfiles\n" + " Display a list of all available security token keyfiles. See also command\n" + " --import-token-keyfiles.\n" + "\n" + "--mount[=VOLUME_PATH]\n" + " Mount a volume. Volume path and other options are requested from the user\n" + " if not specified on command line.\n" + "\n" + "--restore-headers[=VOLUME_PATH]\n" + " Restore volume headers from the embedded or an external backup. All required\n" + " options are requested from the user.\n" + "\n" + "--test\n" + " Test internal algorithms used in the process of encryption and decryption.\n" + "\n" + "--version\n" + " Display program version.\n" + "\n" + "--volume-properties[=MOUNTED_VOLUME]\n" + " Display properties of a mounted volume. See below for description of\n" + " MOUNTED_VOLUME.\n" + "\n" + "MOUNTED_VOLUME:\n" + " Specifies a mounted volume. One of the following forms can be used:\n" + " 1) Path to the encrypted TrueCrypt volume.\n" + " 2) Mount directory of the volume's filesystem (if mounted).\n" + " 3) Slot number of the mounted volume (requires --slot).\n" + "\n" + "\n" + "Options:\n" + "\n" + "--encryption=ENCRYPTION_ALGORITHM\n" + " Use specified encryption algorithm when creating a new volume.\n" + "\n" + "--filesystem=TYPE\n" + " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n" + " with option -t. Default type is 'auto'. When creating a new volume, this\n" + " option specifies the filesystem to be created on the new volume.\n" + " Filesystem type 'none' disables mounting or creating a filesystem.\n" + "\n" + "--force\n" + " Force mounting of a volume in use, dismounting of a volume in use, or\n" + " overwriting a file. Note that this option has no effect on some platforms.\n" + "\n" + "--fs-options=OPTIONS\n" + " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n" + " command with option -o when a filesystem on a TrueCrypt volume is mounted.\n" + " This option is not available on some platforms.\n" + "\n" + "--hash=HASH\n" + " Use specified hash algorithm when creating a new volume or changing password\n" + " and/or keyfiles. This option also specifies the mixing PRF of the random\n" + " number generator.\n" + "\n" + "-k, --keyfiles=KEYFILE1,KEYFILE2,KEYFILE3,..\n" + " Use specified keyfiles when mounting a volume or when changing password\n" + " and/or keyfiles. When a directory is specified, all files inside it will be\n" + " used (non-recursively). Multiple keyfiles must be separated by comma.\n" + " Use double comma (,,) to specify a comma contained in keyfile's name.\n" + " Keyfile stored on a security token must be specified as\n" + " token://slot/SLOT_NUMBER/file/FILENAME. An empty keyfile (-k \"\") disables\n" + " interactive requests for keyfiles. See also options --import-token-keyfiles,\n" + " --list-token-keyfiles, --new-keyfiles, --protection-keyfiles.\n" + "\n" + "-m, --mount-options=headerbak|nokernelcrypto|readonly|ro|system|timestamp|ts\n" + " Specify comma-separated mount options for a TrueCrypt volume:\n" + " headerbak: Use backup headers when mounting a volume.\n" + " nokernelcrypto: Do not use kernel cryptographic services.\n" + " readonly|ro: Mount volume as read-only.\n" + " system: Mount partition using system encryption.\n" + " timestamp|ts: Do not preserve host-file timestamps (note that the operating\n" + " system under certain circumstances does not alter host-file timestamps, which\n" + " may be mistakenly interpreted to mean that this option does not work).\n" + " See also option --fs-options.\n" + "\n" + "--new-keyfiles=KEYFILE1,KEYFILE2,KEYFILE3,..\n" + " Add specified keyfiles to a volume. This option can only be used with command\n" + " -C.\n" + "\n" + "--new-password=PASSWORD\n" + " Specifies a new password. This option can only be used with command -C.\n" + "\n" + "-p, --password=PASSWORD\n" + " Use specified password to mount/open a volume. An empty password can also be\n" + " specified (-p \"\"). Note that passing a password on the command line is\n" + " potentially insecure as the password may be visible in the process list\n" + " (see ps(1)) and/or stored in a command history file or system logs.\n" + "\n" + "--protect-hidden=yes|no\n" + " Write-protect a hidden volume when mounting an outer volume. Before mounting\n" + " the outer volume, the user will be prompted for a password to open the hidden\n" + " volume. The size and position of the hidden volume is then determined and the\n" + " outer volume is mounted with all sectors belonging to the hidden volume\n" + " protected against write operations. When a write to the protected area is\n" + " prevented, the whole volume is switched to read-only mode. Verbose list\n" + " (-v -l) can be used to query the state of the hidden volume protection.\n" + " Warning message is displayed when a volume switched to read-only is being\n" + " dismounted.\n" + "\n" + "--protection-keyfiles=KEYFILE1,KEYFILE2,KEYFILE3,..\n" + " Use specified keyfiles to open a hidden volume to be protected. This option\n" + " may be used only when mounting an outer volume with hidden volume protected.\n" + " See also options -k and --protect-hidden.\n" + "\n" + "--protection-password=PASSWORD\n" + " Use specified password to open a hidden volume to be protected. This option\n" + " may be used only when mounting an outer volume with hidden volume protected.\n" + " See also options -p and --protect-hidden.\n" + "\n" + "--quick\n" + " Use quick format when creating a new volume. This option can be used only\n" + " when creating a device-hosted volume and must not be used when creating an\n" + " outer volume.\n" + "\n" + "--random-source=FILE\n" + " Use FILE as a source of random data (e.g., when creating a volume) instead\n" + " of requiring the user to type random characters.\n" + "\n" + "--slot=SLOT\n" + " Use specified slot number when mounting, dismounting, or listing a volume.\n" + "\n" + "--size=SIZE\n" + " Use specified size in bytes when creating a new volume.\n" + "\n" + "-t, --text\n" + " Use text user interface. Graphical user interface is used by default if\n" + " available.\n" + "\n" + "--token-lib=LIB_PATH\n" + " Use specified PKCS #11 security token library.\n" + "\n" + "--volume-type=TYPE\n" + " Use specified volume type when creating a new volume. TYPE can be 'normal'\n" + " or 'hidden'. See option -c for more information on creating hidden volumes.\n" + "\n" + "-v, --verbose\n" + " Enable verbose output.\n" + "\n" + "\nExamples:\n\n" + "Create a new volume:\n" + "truecrypt -t -c\n" + "\n" + "Mount a volume:\n" + "truecrypt volume.tc /media/truecrypt1\n" + "\n" + "Mount a volume as read-only, using keyfiles:\n" + "truecrypt -m ro -k keyfile1,keyfile2 volume.tc\n" + "\n" + "Mount a volume without mounting its filesystem:\n" + "truecrypt --filesystem=none volume.tc\n" + "\n" + "Mount a volume prompting only for its password:\n" + "truecrypt -t -k \"\" --protect-hidden=no volume.tc /media/truecrypt1\n" + "\n" + "Dismount a volume:\n" + "truecrypt -d volume.tc\n" + "\n" + "Dismount all mounted volumes:\n" + "truecrypt -d\n" + ); + +#ifndef TC_NO_GUI + if (Application::GetUserInterfaceType() == UserInterfaceType::Graphic) + { + wxDialog dialog (nullptr, wxID_ANY, _("TrueCrypt Command Line Help"), wxDefaultPosition); + + wxTextCtrl *textCtrl = new wxTextCtrl (&dialog, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY); + textCtrl->SetFont (wxFont (wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Courier")); + textCtrl->SetValue (helpText); + + int fontWidth, fontHeight; + textCtrl->GetTextExtent (L"A", &fontWidth, &fontHeight); + dialog.SetSize (wxSize (fontWidth * 85, fontHeight * 29)); + + wxBoxSizer *sizer = new wxBoxSizer (wxVERTICAL); + sizer->Add (textCtrl, 1, wxALL | wxEXPAND, 5); + sizer->Add (new wxButton (&dialog, wxID_OK, _("OK")), 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 5); + + dialog.SetSizer (sizer); + dialog.Layout(); + dialog.ShowModal(); + } + else +#endif // !TC_NO_GUI + { + ShowString (L"\n\n"); + ShowString (helpText); + } + } + return true; + + case CommandId::ExportSecurityTokenKeyfile: + ExportSecurityTokenKeyfile(); + return true; + + case CommandId::ImportSecurityTokenKeyfiles: + ImportSecurityTokenKeyfiles(); + return true; + + case CommandId::ListSecurityTokenKeyfiles: + ListSecurityTokenKeyfiles(); + return true; + + case CommandId::ListVolumes: + if (Preferences.Verbose) + DisplayVolumeProperties (cmdLine.ArgVolumes); + else + ListMountedVolumes (cmdLine.ArgVolumes); + return true; + + case CommandId::RestoreHeaders: + RestoreVolumeHeaders (cmdLine.ArgVolumePath); + return true; + + case CommandId::Test: + Test(); + return true; + + default: + throw ParameterIncorrect (SRC_POS); + } + + return false; + } + + void UserInterface::SetPreferences (const UserPreferences &preferences) + { + Preferences = preferences; + PreferencesUpdatedEvent.Raise(); + } + + void UserInterface::ShowError (const exception &ex) const + { + if (!dynamic_cast (&ex)) + DoShowError (ExceptionToMessage (ex)); + } + + wxString UserInterface::SizeToString (uint64 size) const + { + wstringstream s; + if (size > 1024ULL*1024*1024*1024*1024*99) + s << size/1024/1024/1024/1024/1024 << L" " << LangString["PB"].c_str(); + else if (size > 1024ULL*1024*1024*1024*1024) + return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024/1024), LangString["PB"].c_str()); + else if (size > 1024ULL*1024*1024*1024*99) + s << size/1024/1024/1024/1024 << L" " << LangString["TB"].c_str(); + else if (size > 1024ULL*1024*1024*1024) + return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024), LangString["TB"].c_str()); + else if (size > 1024ULL*1024*1024*99) + s << size/1024/1024/1024 << L" " << LangString["GB"].c_str(); + else if (size > 1024ULL*1024*1024) + return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024), LangString["GB"].c_str()); + else if (size > 1024ULL*1024*99) + s << size/1024/1024 << L" " << LangString["MB"].c_str(); + else if (size > 1024ULL*1024) + return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024), LangString["MB"].c_str()); + else if (size > 1024ULL) + s << size/1024 << L" " << LangString["KB"].c_str(); + else + s << size << L" " << LangString["BYTE"].c_str(); + + return s.str(); + } + + wxString UserInterface::SpeedToString (uint64 speed) const + { + wstringstream s; + + if (speed > 1024ULL*1024*1024*1024*1024*99) + s << speed/1024/1024/1024/1024/1024 << L" " << LangString["PB_PER_SEC"].c_str(); + else if (speed > 1024ULL*1024*1024*1024*1024) + return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024/1024), LangString["PB_PER_SEC"].c_str()); + else if (speed > 1024ULL*1024*1024*1024*99) + s << speed/1024/1024/1024/1024 << L" " << LangString["TB_PER_SEC"].c_str(); + else if (speed > 1024ULL*1024*1024*1024) + return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024), LangString["TB_PER_SEC"].c_str()); + else if (speed > 1024ULL*1024*1024*99) + s << speed/1024/1024/1024 << L" " << LangString["GB_PER_SEC"].c_str(); + else if (speed > 1024ULL*1024*999) + return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024), LangString["GB_PER_SEC"].c_str()); + else if (speed > 1024ULL*1024*9) + s << speed/1024/1024 << L" " << LangString["MB_PER_SEC"].c_str(); + else if (speed > 1024ULL*999) + return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024), LangString["MB_PER_SEC"].c_str()); + else if (speed > 1024ULL) + s << speed/1024 << L" " << LangString["KB_PER_SEC"].c_str(); + else + s << speed << L" " << LangString["B_PER_SEC"].c_str(); + + return s.str(); + } + + void UserInterface::Test () const + { + if (!PlatformTest::TestAll()) + throw TestFailed (SRC_POS); + + EncryptionTest::TestAll(); + + // StringFormatter + if (StringFormatter (L"{9} {8} {7} {6} {5} {4} {3} {2} {1} {0} {{0}}", "1", L"2", '3', L'4', 5, 6, 7, 8, 9, 10) != L"10 9 8 7 6 5 4 3 2 1 {0}") + throw TestFailed (SRC_POS); + try + { + StringFormatter (L"{0} {1}", 1); + throw TestFailed (SRC_POS); + } + catch (StringFormatterException&) { } + + try + { + StringFormatter (L"{0} {1} {1}", 1, 2, 3); + throw TestFailed (SRC_POS); + } + catch (StringFormatterException&) { } + + try + { + StringFormatter (L"{0} 1}", 1, 2); + throw TestFailed (SRC_POS); + } + catch (StringFormatterException&) { } + + try + { + StringFormatter (L"{0} {1", 1, 2); + throw TestFailed (SRC_POS); + } + catch (StringFormatterException&) { } + + ShowInfo ("TESTS_PASSED"); + } + + wxString UserInterface::TimeSpanToString (uint64 seconds) const + { + wstringstream s; + + if (seconds >= 60 * 60 * 24 * 2) + s << seconds / (60 * 24 * 60) << L" " << LangString["DAYS"].c_str(); + else if (seconds >= 120 * 60) + s << seconds / (60 * 60) << L" " << LangString["HOURS"].c_str(); + else if (seconds >= 120) + s << seconds / 60 << L" " << LangString["MINUTES"].c_str(); + else + s << seconds << L" " << LangString["SECONDS"].c_str(); + + return s.str(); + } + + bool UserInterface::VolumeHasUnrecommendedExtension (const VolumePath &path) const + { + wxString ext = wxFileName (wxString (wstring (path)).Lower()).GetExt(); + return ext.IsSameAs (L"exe") || ext.IsSameAs (L"sys") || ext.IsSameAs (L"dll"); + } + + wxString UserInterface::VolumeTimeToString (VolumeTime volumeTime) const + { + wxString dateStr = VolumeTimeToDateTime (volumeTime).Format(); + +#ifdef TC_WINDOWS + + FILETIME ft; + *(unsigned __int64 *)(&ft) = volumeTime; + SYSTEMTIME st; + FileTimeToSystemTime (&ft, &st); + + wchar_t wstr[1024]; + if (GetDateFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr)) != 0) + { + dateStr = wstr; + GetTimeFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr)); + dateStr += wxString (L" ") + wstr; + } +#endif + return dateStr; + } + + wxString UserInterface::VolumeTypeToString (VolumeType::Enum type, VolumeProtection::Enum protection) const + { + switch (type) + { + case VolumeType::Normal: + return LangString[protection == VolumeProtection::HiddenVolumeReadOnly ? "OUTER" : "NORMAL"]; + + case VolumeType::Hidden: + return LangString["HIDDEN"]; + + default: + return L"?"; + } + } +} diff --git a/Main/UserInterface.h b/Main/UserInterface.h index 2f6d087..6bc5fa0 100644 --- a/Main/UserInterface.h +++ b/Main/UserInterface.h @@ -1,110 +1,111 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_UserInterface -#define TC_HEADER_Main_UserInterface - -#include "System.h" -#include "Core/Core.h" -#include "Main.h" -#include "CommandLineInterface.h" -#include "FavoriteVolume.h" -#include "LanguageStrings.h" -#include "UserPreferences.h" -#include "UserInterfaceException.h" -#include "UserInterfaceType.h" - -namespace TrueCrypt -{ - class UserInterface : public wxApp - { - public: - virtual ~UserInterface (); - - virtual bool AskYesNo (const wxString &message, bool defaultYes = false, bool warning = false) const = 0; - virtual void BackupVolumeHeaders (shared_ptr volumePath) const = 0; - virtual void BeginBusyState () const = 0; - virtual void ChangePassword (shared_ptr volumePath = shared_ptr (), shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr (), shared_ptr newHash = shared_ptr ()) const = 0; - virtual void CheckRequirementsForMountingVolume () const; - virtual void CloseExplorerWindows (shared_ptr mountedVolume) const; - virtual void CreateKeyfile (shared_ptr keyfilePath = shared_ptr ()) const = 0; - virtual void CreateVolume (shared_ptr options) const = 0; - virtual void DeleteSecurityTokenKeyfiles () const = 0; - virtual void DismountAllVolumes (bool ignoreOpenFiles = false, bool interactive = true) const; - virtual void DismountVolume (shared_ptr volume, bool ignoreOpenFiles = false, bool interactive = true) const; - virtual void DismountVolumes (VolumeInfoList volumes, bool ignoreOpenFiles = false, bool interactive = true) const; - virtual void DisplayVolumeProperties (const VolumeInfoList &volumes) const; - virtual void DoShowError (const wxString &message) const = 0; - virtual void DoShowInfo (const wxString &message) const = 0; - virtual void DoShowString (const wxString &str) const = 0; - virtual void DoShowWarning (const wxString &message) const = 0; - virtual void EndBusyState () const = 0; - virtual wxString ExceptionToMessage (const exception &ex) const; - virtual shared_ptr GetAdminPasswordRequestHandler () = 0; - virtual const UserPreferences &GetPreferences () const { return Preferences; } - virtual void ImportSecurityTokenKeyfiles () const = 0; - virtual void Init (); - virtual void InitSecurityTokenLibrary () const = 0; - virtual void ListMountedVolumes (const VolumeInfoList &volumes) const; - virtual void ListSecurityTokenKeyfiles () const = 0; - virtual shared_ptr MountVolume (MountOptions &options) const; - virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; - virtual VolumeInfoList MountAllFavoriteVolumes (MountOptions &options); - virtual void OpenExplorerWindow (const DirectoryPath &path); - virtual void RestoreVolumeHeaders (shared_ptr volumePath) const = 0; - virtual void SetPreferences (const UserPreferences &preferences); - virtual void ShowError (const exception &ex) const; - virtual void ShowError (const char *langStringId) const { DoShowError (LangString[langStringId]); } - virtual void ShowError (const wxString &message) const { DoShowError (message); } - virtual void ShowInfo (const exception &ex) const { DoShowInfo (ExceptionToMessage (ex)); } - virtual void ShowInfo (const char *langStringId) const { DoShowInfo (LangString[langStringId]); } - virtual void ShowInfo (const wxString &message) const { DoShowInfo (message); } - virtual void ShowWarning (const exception &ex) const { DoShowWarning (ExceptionToMessage (ex)); } - virtual void ShowWarning (const char *langStringId) const { DoShowWarning (LangString[langStringId]); } - virtual void ShowString (const wxString &str) const { DoShowString (str); } - virtual void ShowWarning (const wxString &message) const { DoShowWarning (message); } - virtual wxString SizeToString (uint64 size) const; - virtual wxString SpeedToString (uint64 speed) const; - virtual void Test () const; - virtual wxString TimeSpanToString (uint64 seconds) const; - virtual bool VolumeHasUnrecommendedExtension (const VolumePath &path) const; - virtual void Yield () const = 0; - virtual wxDateTime VolumeTimeToDateTime (VolumeTime volumeTime) const { return wxDateTime ((time_t) (volumeTime / 1000ULL / 1000 / 10 - 134774ULL * 24 * 3600)); } - virtual wxString VolumeTimeToString (VolumeTime volumeTime) const; - virtual wxString VolumeTypeToString (VolumeType::Enum type, VolumeProtection::Enum protection) const; - - Event PreferencesUpdatedEvent; - - struct BusyScope - { - BusyScope (const UserInterface *userInterface) : UI (userInterface) { UI->BeginBusyState (); } - ~BusyScope () { UI->EndBusyState (); } - const UserInterface *UI; - }; - - protected: - UserInterface (); - virtual bool OnExceptionInMainLoop () { throw; } - virtual void OnUnhandledException (); - virtual void OnVolumeMounted (EventArgs &args); - virtual void OnWarning (EventArgs &args); - virtual bool ProcessCommandLine (); - - virtual wxString ExceptionToString (const Exception &ex) const; - virtual wxString ExceptionTypeToString (const std::type_info &ex) const; - - UserPreferences Preferences; - UserInterfaceType::Enum InterfaceType; - - private: - UserInterface (const UserInterface &); - UserInterface &operator= (const UserInterface &); - }; -} - -#endif // TC_HEADER_Main_UserInterface +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_UserInterface +#define TC_HEADER_Main_UserInterface + +#include "System.h" +#include "Core/Core.h" +#include "Main.h" +#include "CommandLineInterface.h" +#include "FavoriteVolume.h" +#include "LanguageStrings.h" +#include "UserPreferences.h" +#include "UserInterfaceException.h" +#include "UserInterfaceType.h" + +namespace TrueCrypt +{ + class UserInterface : public wxApp + { + public: + virtual ~UserInterface (); + + virtual bool AskYesNo (const wxString &message, bool defaultYes = false, bool warning = false) const = 0; + virtual void BackupVolumeHeaders (shared_ptr volumePath) const = 0; + virtual void BeginBusyState () const = 0; + virtual void ChangePassword (shared_ptr volumePath = shared_ptr (), shared_ptr password = shared_ptr (), shared_ptr keyfiles = shared_ptr (), shared_ptr newPassword = shared_ptr (), shared_ptr newKeyfiles = shared_ptr (), shared_ptr newHash = shared_ptr ()) const = 0; + virtual void CheckRequirementsForMountingVolume () const; + virtual void CloseExplorerWindows (shared_ptr mountedVolume) const; + virtual void CreateKeyfile (shared_ptr keyfilePath = shared_ptr ()) const = 0; + virtual void CreateVolume (shared_ptr options) const = 0; + virtual void DeleteSecurityTokenKeyfiles () const = 0; + virtual void DismountAllVolumes (bool ignoreOpenFiles = false, bool interactive = true) const; + virtual void DismountVolume (shared_ptr volume, bool ignoreOpenFiles = false, bool interactive = true) const; + virtual void DismountVolumes (VolumeInfoList volumes, bool ignoreOpenFiles = false, bool interactive = true) const; + virtual void DisplayVolumeProperties (const VolumeInfoList &volumes) const; + virtual void DoShowError (const wxString &message) const = 0; + virtual void DoShowInfo (const wxString &message) const = 0; + virtual void DoShowString (const wxString &str) const = 0; + virtual void DoShowWarning (const wxString &message) const = 0; + virtual void EndBusyState () const = 0; + virtual wxString ExceptionToMessage (const exception &ex) const; + virtual void ExportSecurityTokenKeyfile () const = 0; + virtual shared_ptr GetAdminPasswordRequestHandler () = 0; + virtual const UserPreferences &GetPreferences () const { return Preferences; } + virtual void ImportSecurityTokenKeyfiles () const = 0; + virtual void Init (); + virtual void InitSecurityTokenLibrary () const = 0; + virtual void ListMountedVolumes (const VolumeInfoList &volumes) const; + virtual void ListSecurityTokenKeyfiles () const = 0; + virtual shared_ptr MountVolume (MountOptions &options) const; + virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; + virtual VolumeInfoList MountAllFavoriteVolumes (MountOptions &options); + virtual void OpenExplorerWindow (const DirectoryPath &path); + virtual void RestoreVolumeHeaders (shared_ptr volumePath) const = 0; + virtual void SetPreferences (const UserPreferences &preferences); + virtual void ShowError (const exception &ex) const; + virtual void ShowError (const char *langStringId) const { DoShowError (LangString[langStringId]); } + virtual void ShowError (const wxString &message) const { DoShowError (message); } + virtual void ShowInfo (const exception &ex) const { DoShowInfo (ExceptionToMessage (ex)); } + virtual void ShowInfo (const char *langStringId) const { DoShowInfo (LangString[langStringId]); } + virtual void ShowInfo (const wxString &message) const { DoShowInfo (message); } + virtual void ShowWarning (const exception &ex) const { DoShowWarning (ExceptionToMessage (ex)); } + virtual void ShowWarning (const char *langStringId) const { DoShowWarning (LangString[langStringId]); } + virtual void ShowString (const wxString &str) const { DoShowString (str); } + virtual void ShowWarning (const wxString &message) const { DoShowWarning (message); } + virtual wxString SizeToString (uint64 size) const; + virtual wxString SpeedToString (uint64 speed) const; + virtual void Test () const; + virtual wxString TimeSpanToString (uint64 seconds) const; + virtual bool VolumeHasUnrecommendedExtension (const VolumePath &path) const; + virtual void Yield () const = 0; + virtual wxDateTime VolumeTimeToDateTime (VolumeTime volumeTime) const { return wxDateTime ((time_t) (volumeTime / 1000ULL / 1000 / 10 - 134774ULL * 24 * 3600)); } + virtual wxString VolumeTimeToString (VolumeTime volumeTime) const; + virtual wxString VolumeTypeToString (VolumeType::Enum type, VolumeProtection::Enum protection) const; + + Event PreferencesUpdatedEvent; + + struct BusyScope + { + BusyScope (const UserInterface *userInterface) : UI (userInterface) { UI->BeginBusyState (); } + ~BusyScope () { UI->EndBusyState (); } + const UserInterface *UI; + }; + + protected: + UserInterface (); + virtual bool OnExceptionInMainLoop () { throw; } + virtual void OnUnhandledException (); + virtual void OnVolumeMounted (EventArgs &args); + virtual void OnWarning (EventArgs &args); + virtual bool ProcessCommandLine (); + + virtual wxString ExceptionToString (const Exception &ex) const; + virtual wxString ExceptionTypeToString (const std::type_info &ex) const; + + UserPreferences Preferences; + UserInterfaceType::Enum InterfaceType; + + private: + UserInterface (const UserInterface &); + UserInterface &operator= (const UserInterface &); + }; +} + +#endif // TC_HEADER_Main_UserInterface diff --git a/Main/UserInterfaceException.h b/Main/UserInterfaceException.h index cca7ed4..37a7076 100644 --- a/Main/UserInterfaceException.h +++ b/Main/UserInterfaceException.h @@ -1,36 +1,36 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_UserInterfaceException -#define TC_HEADER_Main_UserInterfaceException - -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - TC_EXCEPTION_DECL (UserInterfaceException, Exception); - TC_EXCEPTION_DECL (MissingArgument, UserInterfaceException); - TC_EXCEPTION_DECL (NoItemSelected, UserInterfaceException); - TC_EXCEPTION_DECL (StringFormatterException, UserInterfaceException); - - struct ErrorMessage : public UserInterfaceException - { - ErrorMessage (const string &exceptionMessage, const wxString &errorMessage) : UserInterfaceException (exceptionMessage), Text (errorMessage) { } - virtual ~ErrorMessage () throw () { } - - operator wstring () const { return wstring (Text); } - operator wxString () const { return Text; } - - protected: - wxString Text; - }; - -#define throw_err(message) throw ErrorMessage (SRC_POS, (message)) -} - -#endif // TC_HEADER_Main_UserInterfaceException +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_UserInterfaceException +#define TC_HEADER_Main_UserInterfaceException + +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + TC_EXCEPTION_DECL (UserInterfaceException, Exception); + TC_EXCEPTION_DECL (MissingArgument, UserInterfaceException); + TC_EXCEPTION_DECL (NoItemSelected, UserInterfaceException); + TC_EXCEPTION_DECL (StringFormatterException, UserInterfaceException); + + struct ErrorMessage : public UserInterfaceException + { + ErrorMessage (const string &exceptionMessage, const wxString &errorMessage) : UserInterfaceException (exceptionMessage), Text (errorMessage) { } + virtual ~ErrorMessage () throw () { } + + operator wstring () const { return wstring (Text); } + operator wxString () const { return Text; } + + protected: + wxString Text; + }; + +#define throw_err(message) throw ErrorMessage (SRC_POS, (message)) +} + +#endif // TC_HEADER_Main_UserInterfaceException diff --git a/Main/UserInterfaceType.h b/Main/UserInterfaceType.h index 39fffeb..573b543 100644 --- a/Main/UserInterfaceType.h +++ b/Main/UserInterfaceType.h @@ -1,25 +1,25 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_UserInterfaceType -#define TC_HEADER_Main_UserInterfaceType - -namespace TrueCrypt -{ - struct UserInterfaceType - { - enum Enum - { - Unknown, - Graphic, - Text - }; - }; -} - -#endif // TC_HEADER_Main_UserInterfaceType +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_UserInterfaceType +#define TC_HEADER_Main_UserInterfaceType + +namespace TrueCrypt +{ + struct UserInterfaceType + { + enum Enum + { + Unknown, + Graphic, + Text + }; + }; +} + +#endif // TC_HEADER_Main_UserInterfaceType diff --git a/Main/UserPreferences.cpp b/Main/UserPreferences.cpp index f367961..3003d9d 100644 --- a/Main/UserPreferences.cpp +++ b/Main/UserPreferences.cpp @@ -1,233 +1,233 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Main/Application.h" -#include "UserPreferences.h" -#include "Xml.h" - -namespace TrueCrypt -{ - void UserPreferences::SetValue (const wxString &cfgText, bool &cfgVar) - { - if (cfgText == L"0") - cfgVar = false; - else if (cfgText == L"1") - cfgVar = true; - } - - void UserPreferences::SetValue (const wxString &cfgText, int &cfgVar) - { - if (cfgText.empty()) - cfgVar = 0; - else - cfgVar = StringConverter::ToUInt32 (wstring (cfgText)); - } - - void UserPreferences::SetValue (const wxString &cfgText, uint64 &cfgVar) - { - if (cfgText.empty()) - cfgVar = 0; - else - cfgVar = StringConverter::ToUInt64 (wstring (cfgText)); - } - - void UserPreferences::SetValue (const wxString &cfgText, wstring &cfgVar) - { - cfgVar = cfgText; - } - - void UserPreferences::SetValue (const wxString &cfgText, wxString &cfgVar) - { - cfgVar = cfgText; - } - - void UserPreferences::SetValue (const wxString &cfgText, FilesystemPath &cfgVar) - { - cfgVar = wstring (cfgText); - } - - void UserPreferences::Load() - { - // Preferences - FilePath cfgPath = Application::GetConfigFilePath (GetPreferencesFileName()); - if (cfgPath.IsFile()) - { - map configMap; - foreach (XmlNode node, XmlParser (cfgPath).GetNodes (L"config")) - { - configMap[node.Attributes[L"key"]] = node.InnerText; - } - -#define TC_CONFIG_SET(NAME) SetValue (configMap[L###NAME], NAME) - - TC_CONFIG_SET (BackgroundTaskEnabled); - TC_CONFIG_SET (BackgroundTaskMenuDismountItemsEnabled); - TC_CONFIG_SET (BackgroundTaskMenuMountItemsEnabled); - TC_CONFIG_SET (BackgroundTaskMenuOpenItemsEnabled); - TC_CONFIG_SET (BeepAfterHotkeyMountDismount); - SetValue (configMap[L"CachePasswords"], DefaultMountOptions.CachePassword); - TC_CONFIG_SET (CloseBackgroundTaskOnNoVolumes); - TC_CONFIG_SET (CloseExplorerWindowsOnDismount); - TC_CONFIG_SET (CloseSecurityTokenSessionsAfterMount); - TC_CONFIG_SET (DisableKernelEncryptionModeWarning); - TC_CONFIG_SET (DismountOnInactivity); - TC_CONFIG_SET (DismountOnLogOff); - TC_CONFIG_SET (DismountOnPowerSaving); - TC_CONFIG_SET (DismountOnScreenSaver); - TC_CONFIG_SET (DisplayMessageAfterHotkeyDismount); - TC_CONFIG_SET (BackgroundTaskEnabled); - SetValue (configMap[L"FilesystemOptions"], DefaultMountOptions.FilesystemOptions); - TC_CONFIG_SET (ForceAutoDismount); - TC_CONFIG_SET (LastSelectedSlotNumber); - TC_CONFIG_SET (MaxVolumeIdleTime); - TC_CONFIG_SET (MountDevicesOnLogon); - TC_CONFIG_SET (MountFavoritesOnLogon); - - bool readOnly; - SetValue (configMap[L"MountVolumesReadOnly"], readOnly); - DefaultMountOptions.Protection = readOnly ? VolumeProtection::ReadOnly : VolumeProtection::None; - - SetValue (configMap[L"MountVolumesRemovable"], DefaultMountOptions.Removable); - SetValue (configMap[L"NoKernelCrypto"], DefaultMountOptions.NoKernelCrypto); - TC_CONFIG_SET (OpenExplorerWindowAfterMount); - SetValue (configMap[L"PreserveTimestamps"], DefaultMountOptions.PreserveTimestamps); - TC_CONFIG_SET (SaveHistory); - SetValue (configMap[L"SecurityTokenLibrary"], SecurityTokenModule); - TC_CONFIG_SET (StartOnLogon); - TC_CONFIG_SET (UseKeyfiles); - TC_CONFIG_SET (WipeCacheOnAutoDismount); - TC_CONFIG_SET (WipeCacheOnClose); - } - - // Default keyfiles - cfgPath = Application::GetConfigFilePath (GetDefaultKeyfilesFileName()); - if (cfgPath.IsFile()) - { - foreach (const XmlNode &node, XmlParser (cfgPath).GetNodes (L"keyfile")) - { - DefaultKeyfiles.push_back (make_shared ((wstring) node.InnerText)); - } - } - -#ifdef TC_WINDOWS - // Hotkeys - Hotkeys = Hotkey::LoadList(); -#endif - } - - void UserPreferences::Save() const - { - // Preferences - class ConfigXmlFormatter - { - public: - void AddEntry (const wchar_t *key, const wxString &value) - { - if (!value.empty()) - { - XmlNode config (L"config"); - config.Attributes[L"key"] = key; - config.InnerText = value; - XmlConfig.InnerNodes.push_back (config); - } - } - - void AddEntry (const wchar_t *key, bool value) - { - AddEntry (key, wxString (value ? L"1" : L"0")); - } - - void AddEntry (const wchar_t *key, int value) - { - wstringstream s; - s << value; - AddEntry (key, s.str()); - } - - void AddEntry (const wchar_t *key, uint64 value) - { - wstringstream s; - s << value; - AddEntry (key, s.str()); - } - - XmlNode XmlConfig; - }; - - ConfigXmlFormatter formatter; - formatter.XmlConfig.Name = L"configuration"; - -#define TC_CONFIG_ADD(NAME) formatter.AddEntry (L###NAME, NAME) - - TC_CONFIG_ADD (BackgroundTaskEnabled); - TC_CONFIG_ADD (BackgroundTaskMenuDismountItemsEnabled); - TC_CONFIG_ADD (BackgroundTaskMenuMountItemsEnabled); - TC_CONFIG_ADD (BackgroundTaskMenuOpenItemsEnabled); - TC_CONFIG_ADD (BeepAfterHotkeyMountDismount); - formatter.AddEntry (L"CachePasswords", DefaultMountOptions.CachePassword); - TC_CONFIG_ADD (CloseBackgroundTaskOnNoVolumes); - TC_CONFIG_ADD (CloseExplorerWindowsOnDismount); - TC_CONFIG_ADD (CloseSecurityTokenSessionsAfterMount); - TC_CONFIG_ADD (DisableKernelEncryptionModeWarning); - TC_CONFIG_ADD (DismountOnInactivity); - TC_CONFIG_ADD (DismountOnLogOff); - TC_CONFIG_ADD (DismountOnPowerSaving); - TC_CONFIG_ADD (DismountOnScreenSaver); - TC_CONFIG_ADD (DisplayMessageAfterHotkeyDismount); - TC_CONFIG_ADD (BackgroundTaskEnabled); - formatter.AddEntry (L"FilesystemOptions", DefaultMountOptions.FilesystemOptions); - TC_CONFIG_ADD (ForceAutoDismount); - TC_CONFIG_ADD (LastSelectedSlotNumber); - TC_CONFIG_ADD (MaxVolumeIdleTime); - TC_CONFIG_ADD (MountDevicesOnLogon); - TC_CONFIG_ADD (MountFavoritesOnLogon); - formatter.AddEntry (L"MountVolumesReadOnly", DefaultMountOptions.Protection == VolumeProtection::ReadOnly); - formatter.AddEntry (L"MountVolumesRemovable", DefaultMountOptions.Removable); - formatter.AddEntry (L"NoKernelCrypto", DefaultMountOptions.NoKernelCrypto); - TC_CONFIG_ADD (OpenExplorerWindowAfterMount); - formatter.AddEntry (L"PreserveTimestamps", DefaultMountOptions.PreserveTimestamps); - TC_CONFIG_ADD (SaveHistory); - formatter.AddEntry (L"SecurityTokenLibrary", wstring (SecurityTokenModule)); - TC_CONFIG_ADD (StartOnLogon); - TC_CONFIG_ADD (UseKeyfiles); - TC_CONFIG_ADD (WipeCacheOnAutoDismount); - TC_CONFIG_ADD (WipeCacheOnClose); - - XmlWriter writer (Application::GetConfigFilePath (GetPreferencesFileName(), true)); - writer.WriteNode (formatter.XmlConfig); - writer.Close(); - - // Default keyfiles - FilePath keyfilesCfgPath = Application::GetConfigFilePath (GetDefaultKeyfilesFileName(), true); - - if (DefaultKeyfiles.empty()) - { - if (keyfilesCfgPath.IsFile()) - keyfilesCfgPath.Delete(); - } - else - { - XmlNode keyfilesXml (L"defaultkeyfiles"); - - foreach_ref (const Keyfile &keyfile, DefaultKeyfiles) - { - keyfilesXml.InnerNodes.push_back (XmlNode (L"keyfile", wxString (FilesystemPath (keyfile)))); - } - - XmlWriter keyfileWriter (keyfilesCfgPath); - keyfileWriter.WriteNode (keyfilesXml); - keyfileWriter.Close(); - } - -#ifdef TC_WINDOWS - // Hotkeys - Hotkey::SaveList (Hotkeys); -#endif - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Main/Application.h" +#include "UserPreferences.h" +#include "Xml.h" + +namespace TrueCrypt +{ + void UserPreferences::SetValue (const wxString &cfgText, bool &cfgVar) + { + if (cfgText == L"0") + cfgVar = false; + else if (cfgText == L"1") + cfgVar = true; + } + + void UserPreferences::SetValue (const wxString &cfgText, int &cfgVar) + { + if (cfgText.empty()) + cfgVar = 0; + else + cfgVar = StringConverter::ToUInt32 (wstring (cfgText)); + } + + void UserPreferences::SetValue (const wxString &cfgText, uint64 &cfgVar) + { + if (cfgText.empty()) + cfgVar = 0; + else + cfgVar = StringConverter::ToUInt64 (wstring (cfgText)); + } + + void UserPreferences::SetValue (const wxString &cfgText, wstring &cfgVar) + { + cfgVar = cfgText; + } + + void UserPreferences::SetValue (const wxString &cfgText, wxString &cfgVar) + { + cfgVar = cfgText; + } + + void UserPreferences::SetValue (const wxString &cfgText, FilesystemPath &cfgVar) + { + cfgVar = wstring (cfgText); + } + + void UserPreferences::Load() + { + // Preferences + FilePath cfgPath = Application::GetConfigFilePath (GetPreferencesFileName()); + if (cfgPath.IsFile()) + { + map configMap; + foreach (XmlNode node, XmlParser (cfgPath).GetNodes (L"config")) + { + configMap[node.Attributes[L"key"]] = node.InnerText; + } + +#define TC_CONFIG_SET(NAME) SetValue (configMap[L###NAME], NAME) + + TC_CONFIG_SET (BackgroundTaskEnabled); + TC_CONFIG_SET (BackgroundTaskMenuDismountItemsEnabled); + TC_CONFIG_SET (BackgroundTaskMenuMountItemsEnabled); + TC_CONFIG_SET (BackgroundTaskMenuOpenItemsEnabled); + TC_CONFIG_SET (BeepAfterHotkeyMountDismount); + SetValue (configMap[L"CachePasswords"], DefaultMountOptions.CachePassword); + TC_CONFIG_SET (CloseBackgroundTaskOnNoVolumes); + TC_CONFIG_SET (CloseExplorerWindowsOnDismount); + TC_CONFIG_SET (CloseSecurityTokenSessionsAfterMount); + TC_CONFIG_SET (DisableKernelEncryptionModeWarning); + TC_CONFIG_SET (DismountOnInactivity); + TC_CONFIG_SET (DismountOnLogOff); + TC_CONFIG_SET (DismountOnPowerSaving); + TC_CONFIG_SET (DismountOnScreenSaver); + TC_CONFIG_SET (DisplayMessageAfterHotkeyDismount); + TC_CONFIG_SET (BackgroundTaskEnabled); + SetValue (configMap[L"FilesystemOptions"], DefaultMountOptions.FilesystemOptions); + TC_CONFIG_SET (ForceAutoDismount); + TC_CONFIG_SET (LastSelectedSlotNumber); + TC_CONFIG_SET (MaxVolumeIdleTime); + TC_CONFIG_SET (MountDevicesOnLogon); + TC_CONFIG_SET (MountFavoritesOnLogon); + + bool readOnly; + SetValue (configMap[L"MountVolumesReadOnly"], readOnly); + DefaultMountOptions.Protection = readOnly ? VolumeProtection::ReadOnly : VolumeProtection::None; + + SetValue (configMap[L"MountVolumesRemovable"], DefaultMountOptions.Removable); + SetValue (configMap[L"NoKernelCrypto"], DefaultMountOptions.NoKernelCrypto); + TC_CONFIG_SET (OpenExplorerWindowAfterMount); + SetValue (configMap[L"PreserveTimestamps"], DefaultMountOptions.PreserveTimestamps); + TC_CONFIG_SET (SaveHistory); + SetValue (configMap[L"SecurityTokenLibrary"], SecurityTokenModule); + TC_CONFIG_SET (StartOnLogon); + TC_CONFIG_SET (UseKeyfiles); + TC_CONFIG_SET (WipeCacheOnAutoDismount); + TC_CONFIG_SET (WipeCacheOnClose); + } + + // Default keyfiles + cfgPath = Application::GetConfigFilePath (GetDefaultKeyfilesFileName()); + if (cfgPath.IsFile()) + { + foreach (const XmlNode &node, XmlParser (cfgPath).GetNodes (L"keyfile")) + { + DefaultKeyfiles.push_back (make_shared ((wstring) node.InnerText)); + } + } + +#ifdef TC_WINDOWS + // Hotkeys + Hotkeys = Hotkey::LoadList(); +#endif + } + + void UserPreferences::Save() const + { + // Preferences + class ConfigXmlFormatter + { + public: + void AddEntry (const wchar_t *key, const wxString &value) + { + if (!value.empty()) + { + XmlNode config (L"config"); + config.Attributes[L"key"] = key; + config.InnerText = value; + XmlConfig.InnerNodes.push_back (config); + } + } + + void AddEntry (const wchar_t *key, bool value) + { + AddEntry (key, wxString (value ? L"1" : L"0")); + } + + void AddEntry (const wchar_t *key, int value) + { + wstringstream s; + s << value; + AddEntry (key, s.str()); + } + + void AddEntry (const wchar_t *key, uint64 value) + { + wstringstream s; + s << value; + AddEntry (key, s.str()); + } + + XmlNode XmlConfig; + }; + + ConfigXmlFormatter formatter; + formatter.XmlConfig.Name = L"configuration"; + +#define TC_CONFIG_ADD(NAME) formatter.AddEntry (L###NAME, NAME) + + TC_CONFIG_ADD (BackgroundTaskEnabled); + TC_CONFIG_ADD (BackgroundTaskMenuDismountItemsEnabled); + TC_CONFIG_ADD (BackgroundTaskMenuMountItemsEnabled); + TC_CONFIG_ADD (BackgroundTaskMenuOpenItemsEnabled); + TC_CONFIG_ADD (BeepAfterHotkeyMountDismount); + formatter.AddEntry (L"CachePasswords", DefaultMountOptions.CachePassword); + TC_CONFIG_ADD (CloseBackgroundTaskOnNoVolumes); + TC_CONFIG_ADD (CloseExplorerWindowsOnDismount); + TC_CONFIG_ADD (CloseSecurityTokenSessionsAfterMount); + TC_CONFIG_ADD (DisableKernelEncryptionModeWarning); + TC_CONFIG_ADD (DismountOnInactivity); + TC_CONFIG_ADD (DismountOnLogOff); + TC_CONFIG_ADD (DismountOnPowerSaving); + TC_CONFIG_ADD (DismountOnScreenSaver); + TC_CONFIG_ADD (DisplayMessageAfterHotkeyDismount); + TC_CONFIG_ADD (BackgroundTaskEnabled); + formatter.AddEntry (L"FilesystemOptions", DefaultMountOptions.FilesystemOptions); + TC_CONFIG_ADD (ForceAutoDismount); + TC_CONFIG_ADD (LastSelectedSlotNumber); + TC_CONFIG_ADD (MaxVolumeIdleTime); + TC_CONFIG_ADD (MountDevicesOnLogon); + TC_CONFIG_ADD (MountFavoritesOnLogon); + formatter.AddEntry (L"MountVolumesReadOnly", DefaultMountOptions.Protection == VolumeProtection::ReadOnly); + formatter.AddEntry (L"MountVolumesRemovable", DefaultMountOptions.Removable); + formatter.AddEntry (L"NoKernelCrypto", DefaultMountOptions.NoKernelCrypto); + TC_CONFIG_ADD (OpenExplorerWindowAfterMount); + formatter.AddEntry (L"PreserveTimestamps", DefaultMountOptions.PreserveTimestamps); + TC_CONFIG_ADD (SaveHistory); + formatter.AddEntry (L"SecurityTokenLibrary", wstring (SecurityTokenModule)); + TC_CONFIG_ADD (StartOnLogon); + TC_CONFIG_ADD (UseKeyfiles); + TC_CONFIG_ADD (WipeCacheOnAutoDismount); + TC_CONFIG_ADD (WipeCacheOnClose); + + XmlWriter writer (Application::GetConfigFilePath (GetPreferencesFileName(), true)); + writer.WriteNode (formatter.XmlConfig); + writer.Close(); + + // Default keyfiles + FilePath keyfilesCfgPath = Application::GetConfigFilePath (GetDefaultKeyfilesFileName(), true); + + if (DefaultKeyfiles.empty()) + { + if (keyfilesCfgPath.IsFile()) + keyfilesCfgPath.Delete(); + } + else + { + XmlNode keyfilesXml (L"defaultkeyfiles"); + + foreach_ref (const Keyfile &keyfile, DefaultKeyfiles) + { + keyfilesXml.InnerNodes.push_back (XmlNode (L"keyfile", wxString (FilesystemPath (keyfile)))); + } + + XmlWriter keyfileWriter (keyfilesCfgPath); + keyfileWriter.WriteNode (keyfilesXml); + keyfileWriter.Close(); + } + +#ifdef TC_WINDOWS + // Hotkeys + Hotkey::SaveList (Hotkeys); +#endif + } +} diff --git a/Main/UserPreferences.h b/Main/UserPreferences.h index c6e49d9..65dd238 100644 --- a/Main/UserPreferences.h +++ b/Main/UserPreferences.h @@ -1,103 +1,103 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_UserPreferences -#define TC_HEADER_Main_UserPreferences - -#include "System.h" -#include "Main.h" -#include "Hotkey.h" - -namespace TrueCrypt -{ - struct UserPreferences - { - UserPreferences () - : - BackgroundTaskEnabled (true), - BackgroundTaskMenuDismountItemsEnabled (true), - BackgroundTaskMenuMountItemsEnabled (true), - BackgroundTaskMenuOpenItemsEnabled (true), - BeepAfterHotkeyMountDismount (false), - CloseBackgroundTaskOnNoVolumes (true), - CloseExplorerWindowsOnDismount (true), - CloseSecurityTokenSessionsAfterMount (false), - DisableKernelEncryptionModeWarning (false), - DismountOnInactivity (false), - DismountOnLogOff (true), - DismountOnPowerSaving (false), - DismountOnScreenSaver (false), - DisplayMessageAfterHotkeyDismount (false), - ForceAutoDismount (true), - LastSelectedSlotNumber (0), - MaxVolumeIdleTime (60), - MountDevicesOnLogon (false), - MountFavoritesOnLogon (false), - NonInteractive (false), - OpenExplorerWindowAfterMount (false), - SaveHistory (false), - StartOnLogon (false), - UseKeyfiles (false), - Verbose (false), - WipeCacheOnAutoDismount (true), - WipeCacheOnClose (false) - { - } - - virtual ~UserPreferences () - { - } - void Load(); - void Save() const; - - HotkeyList Hotkeys; - KeyfileList DefaultKeyfiles; - MountOptions DefaultMountOptions; - - bool BackgroundTaskEnabled; - bool BackgroundTaskMenuDismountItemsEnabled; - bool BackgroundTaskMenuMountItemsEnabled; - bool BackgroundTaskMenuOpenItemsEnabled; - bool BeepAfterHotkeyMountDismount; - bool CloseBackgroundTaskOnNoVolumes; - bool CloseExplorerWindowsOnDismount; - bool CloseSecurityTokenSessionsAfterMount; - bool DisableKernelEncryptionModeWarning; - bool DismountOnInactivity; - bool DismountOnLogOff; - bool DismountOnPowerSaving; - bool DismountOnScreenSaver; - bool DisplayMessageAfterHotkeyDismount; - bool ForceAutoDismount; - uint64 LastSelectedSlotNumber; - int32 MaxVolumeIdleTime; - bool MountDevicesOnLogon; - bool MountFavoritesOnLogon; - bool NonInteractive; - bool OpenExplorerWindowAfterMount; - bool SaveHistory; - FilePath SecurityTokenModule; - bool StartOnLogon; - bool UseKeyfiles; - bool Verbose; - bool WipeCacheOnAutoDismount; - bool WipeCacheOnClose; - - protected: - wxString GetDefaultKeyfilesFileName () const { return L"Default Keyfiles.xml"; } - wxString GetPreferencesFileName () const { return L"Configuration.xml"; } - void SetValue (const wxString &cfgText, bool &cfgVar); - void SetValue (const wxString &cfgText, int &cfgVar); - void SetValue (const wxString &cfgText, uint64 &cfgVar); - void SetValue (const wxString &cfgText, wstring &cfgVar); - void SetValue (const wxString &cfgText, wxString &cfgVar); - void SetValue (const wxString &cfgText, FilesystemPath &cfgVar); - }; -} - -#endif // TC_HEADER_Main_UserPreferences +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_UserPreferences +#define TC_HEADER_Main_UserPreferences + +#include "System.h" +#include "Main.h" +#include "Hotkey.h" + +namespace TrueCrypt +{ + struct UserPreferences + { + UserPreferences () + : + BackgroundTaskEnabled (true), + BackgroundTaskMenuDismountItemsEnabled (true), + BackgroundTaskMenuMountItemsEnabled (true), + BackgroundTaskMenuOpenItemsEnabled (true), + BeepAfterHotkeyMountDismount (false), + CloseBackgroundTaskOnNoVolumes (true), + CloseExplorerWindowsOnDismount (true), + CloseSecurityTokenSessionsAfterMount (false), + DisableKernelEncryptionModeWarning (false), + DismountOnInactivity (false), + DismountOnLogOff (true), + DismountOnPowerSaving (false), + DismountOnScreenSaver (false), + DisplayMessageAfterHotkeyDismount (false), + ForceAutoDismount (true), + LastSelectedSlotNumber (0), + MaxVolumeIdleTime (60), + MountDevicesOnLogon (false), + MountFavoritesOnLogon (false), + NonInteractive (false), + OpenExplorerWindowAfterMount (false), + SaveHistory (false), + StartOnLogon (false), + UseKeyfiles (false), + Verbose (false), + WipeCacheOnAutoDismount (true), + WipeCacheOnClose (false) + { + } + + virtual ~UserPreferences () + { + } + void Load(); + void Save() const; + + HotkeyList Hotkeys; + KeyfileList DefaultKeyfiles; + MountOptions DefaultMountOptions; + + bool BackgroundTaskEnabled; + bool BackgroundTaskMenuDismountItemsEnabled; + bool BackgroundTaskMenuMountItemsEnabled; + bool BackgroundTaskMenuOpenItemsEnabled; + bool BeepAfterHotkeyMountDismount; + bool CloseBackgroundTaskOnNoVolumes; + bool CloseExplorerWindowsOnDismount; + bool CloseSecurityTokenSessionsAfterMount; + bool DisableKernelEncryptionModeWarning; + bool DismountOnInactivity; + bool DismountOnLogOff; + bool DismountOnPowerSaving; + bool DismountOnScreenSaver; + bool DisplayMessageAfterHotkeyDismount; + bool ForceAutoDismount; + uint64 LastSelectedSlotNumber; + int32 MaxVolumeIdleTime; + bool MountDevicesOnLogon; + bool MountFavoritesOnLogon; + bool NonInteractive; + bool OpenExplorerWindowAfterMount; + bool SaveHistory; + FilePath SecurityTokenModule; + bool StartOnLogon; + bool UseKeyfiles; + bool Verbose; + bool WipeCacheOnAutoDismount; + bool WipeCacheOnClose; + + protected: + wxString GetDefaultKeyfilesFileName () const { return L"Default Keyfiles.xml"; } + wxString GetPreferencesFileName () const { return L"Configuration.xml"; } + void SetValue (const wxString &cfgText, bool &cfgVar); + void SetValue (const wxString &cfgText, int &cfgVar); + void SetValue (const wxString &cfgText, uint64 &cfgVar); + void SetValue (const wxString &cfgText, wstring &cfgVar); + void SetValue (const wxString &cfgText, wxString &cfgVar); + void SetValue (const wxString &cfgText, FilesystemPath &cfgVar); + }; +} + +#endif // TC_HEADER_Main_UserPreferences diff --git a/Main/VolumeHistory.cpp b/Main/VolumeHistory.cpp index 49eb46f..cedd5ea 100644 --- a/Main/VolumeHistory.cpp +++ b/Main/VolumeHistory.cpp @@ -1,152 +1,152 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include "Application.h" -#include "GraphicUserInterface.h" -#include "Xml.h" -#include "VolumeHistory.h" - -namespace TrueCrypt -{ - VolumeHistory::VolumeHistory () - { - } - - VolumeHistory::~VolumeHistory () - { - } - - void VolumeHistory::Add (const VolumePath &newPath) - { - if (Gui->GetPreferences().SaveHistory) - { - ScopeLock lock (AccessMutex); - - VolumePathList::iterator iter = VolumePaths.begin(); - foreach (const VolumePath &path, VolumePaths) - { - if (newPath == path) - { - VolumePaths.erase (iter); - break; - } - iter++; - } - - VolumePaths.push_front (newPath); - if (VolumePaths.size() > MaxSize) - VolumePaths.pop_back(); - - foreach (wxComboBox *comboBox, ConnectedComboBoxes) - { - UpdateComboBox (comboBox); - } - } - } - - void VolumeHistory::Clear () - { - VolumePaths.clear(); - foreach (wxComboBox *comboBox, ConnectedComboBoxes) - { - UpdateComboBox (comboBox); - } - - Save(); - } - - void VolumeHistory::ConnectComboBox (wxComboBox *comboBox) - { - ScopeLock lock (AccessMutex); - ConnectedComboBoxes.push_back (comboBox); - - UpdateComboBox (comboBox); - } - - void VolumeHistory::DisconnectComboBox (wxComboBox *comboBox) - { - ScopeLock lock (AccessMutex); - - for (list::iterator iter = ConnectedComboBoxes.begin(); iter != ConnectedComboBoxes.end(); ++iter) - { - if (comboBox == *iter) - { - ConnectedComboBoxes.erase (iter); - break; - } - } - } - - void VolumeHistory::Load () - { - ScopeLock lock (AccessMutex); - FilePath historyCfgPath = Application::GetConfigFilePath (GetFileName()); - - if (historyCfgPath.IsFile()) - { - if (!Gui->GetPreferences().SaveHistory) - { - historyCfgPath.Delete(); - } - else - { - foreach_reverse (const XmlNode &node, XmlParser (historyCfgPath).GetNodes (L"volume")) - { - Add (wstring (node.InnerText)); - } - } - } - } - - void VolumeHistory::Save () - { - ScopeLock lock (AccessMutex); - FilePath historyCfgPath = Application::GetConfigFilePath (GetFileName(), true); - - if (!Gui->GetPreferences().SaveHistory || VolumePaths.empty()) - { - if (historyCfgPath.IsFile()) - historyCfgPath.Delete(); - } - else - { - XmlNode historyXml (L"history"); - - foreach (const VolumePath &path, VolumePaths) - { - historyXml.InnerNodes.push_back (XmlNode (L"volume", wstring (path))); - } - - XmlWriter historyWriter (historyCfgPath); - historyWriter.WriteNode (historyXml); - historyWriter.Close(); - } - } - - void VolumeHistory::UpdateComboBox (wxComboBox *comboBox) - { - wxString curValue = comboBox->GetValue(); - - comboBox->Freeze(); - comboBox->Clear(); - - foreach (const VolumePath &path, VolumePaths) - { - comboBox->Append (wstring (path)); - } - - comboBox->SetValue (curValue); - comboBox->Thaw(); - } - - list VolumeHistory::ConnectedComboBoxes; - VolumePathList VolumeHistory::VolumePaths; - Mutex VolumeHistory::AccessMutex; - -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include "Application.h" +#include "GraphicUserInterface.h" +#include "Xml.h" +#include "VolumeHistory.h" + +namespace TrueCrypt +{ + VolumeHistory::VolumeHistory () + { + } + + VolumeHistory::~VolumeHistory () + { + } + + void VolumeHistory::Add (const VolumePath &newPath) + { + if (Gui->GetPreferences().SaveHistory) + { + ScopeLock lock (AccessMutex); + + VolumePathList::iterator iter = VolumePaths.begin(); + foreach (const VolumePath &path, VolumePaths) + { + if (newPath == path) + { + VolumePaths.erase (iter); + break; + } + iter++; + } + + VolumePaths.push_front (newPath); + if (VolumePaths.size() > MaxSize) + VolumePaths.pop_back(); + + foreach (wxComboBox *comboBox, ConnectedComboBoxes) + { + UpdateComboBox (comboBox); + } + } + } + + void VolumeHistory::Clear () + { + VolumePaths.clear(); + foreach (wxComboBox *comboBox, ConnectedComboBoxes) + { + UpdateComboBox (comboBox); + } + + Save(); + } + + void VolumeHistory::ConnectComboBox (wxComboBox *comboBox) + { + ScopeLock lock (AccessMutex); + ConnectedComboBoxes.push_back (comboBox); + + UpdateComboBox (comboBox); + } + + void VolumeHistory::DisconnectComboBox (wxComboBox *comboBox) + { + ScopeLock lock (AccessMutex); + + for (list::iterator iter = ConnectedComboBoxes.begin(); iter != ConnectedComboBoxes.end(); ++iter) + { + if (comboBox == *iter) + { + ConnectedComboBoxes.erase (iter); + break; + } + } + } + + void VolumeHistory::Load () + { + ScopeLock lock (AccessMutex); + FilePath historyCfgPath = Application::GetConfigFilePath (GetFileName()); + + if (historyCfgPath.IsFile()) + { + if (!Gui->GetPreferences().SaveHistory) + { + historyCfgPath.Delete(); + } + else + { + foreach_reverse (const XmlNode &node, XmlParser (historyCfgPath).GetNodes (L"volume")) + { + Add (wstring (node.InnerText)); + } + } + } + } + + void VolumeHistory::Save () + { + ScopeLock lock (AccessMutex); + FilePath historyCfgPath = Application::GetConfigFilePath (GetFileName(), true); + + if (!Gui->GetPreferences().SaveHistory || VolumePaths.empty()) + { + if (historyCfgPath.IsFile()) + historyCfgPath.Delete(); + } + else + { + XmlNode historyXml (L"history"); + + foreach (const VolumePath &path, VolumePaths) + { + historyXml.InnerNodes.push_back (XmlNode (L"volume", wstring (path))); + } + + XmlWriter historyWriter (historyCfgPath); + historyWriter.WriteNode (historyXml); + historyWriter.Close(); + } + } + + void VolumeHistory::UpdateComboBox (wxComboBox *comboBox) + { + wxString curValue = comboBox->GetValue(); + + comboBox->Freeze(); + comboBox->Clear(); + + foreach (const VolumePath &path, VolumePaths) + { + comboBox->Append (wstring (path)); + } + + comboBox->SetValue (curValue); + comboBox->Thaw(); + } + + list VolumeHistory::ConnectedComboBoxes; + VolumePathList VolumeHistory::VolumePaths; + Mutex VolumeHistory::AccessMutex; + +} diff --git a/Main/VolumeHistory.h b/Main/VolumeHistory.h index eef9282..2082ab2 100644 --- a/Main/VolumeHistory.h +++ b/Main/VolumeHistory.h @@ -1,45 +1,45 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_VolumeHistory -#define TC_HEADER_Main_VolumeHistory - -#include "System.h" -#include "Main.h" - -namespace TrueCrypt -{ - class VolumeHistory - { - public: - VolumeHistory (); - virtual ~VolumeHistory (); - - static void Add (const VolumePath &path); - static void Clear (); - static void ConnectComboBox (wxComboBox *comboBox); - static void DisconnectComboBox (wxComboBox *comboBox); - static void Load (); - static void Save (); - - protected: - static void UpdateComboBox (wxComboBox *comboBox); - static wxString GetFileName () { return L"History.xml"; } - - static const unsigned int MaxSize = 10; - static list ConnectedComboBoxes; - static VolumePathList VolumePaths; - static Mutex AccessMutex; - - private: - VolumeHistory (const VolumeHistory &); - VolumeHistory &operator= (const VolumeHistory &); - }; -} - -#endif // TC_HEADER_Main_VolumeHistory +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_VolumeHistory +#define TC_HEADER_Main_VolumeHistory + +#include "System.h" +#include "Main.h" + +namespace TrueCrypt +{ + class VolumeHistory + { + public: + VolumeHistory (); + virtual ~VolumeHistory (); + + static void Add (const VolumePath &path); + static void Clear (); + static void ConnectComboBox (wxComboBox *comboBox); + static void DisconnectComboBox (wxComboBox *comboBox); + static void Load (); + static void Save (); + + protected: + static void UpdateComboBox (wxComboBox *comboBox); + static wxString GetFileName () { return L"History.xml"; } + + static const unsigned int MaxSize = 10; + static list ConnectedComboBoxes; + static VolumePathList VolumePaths; + static Mutex AccessMutex; + + private: + VolumeHistory (const VolumeHistory &); + VolumeHistory &operator= (const VolumeHistory &); + }; +} + +#endif // TC_HEADER_Main_VolumeHistory diff --git a/Main/Xml.cpp b/Main/Xml.cpp index 3f50f8b..f1755b0 100644 --- a/Main/Xml.cpp +++ b/Main/Xml.cpp @@ -1,178 +1,178 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "System.h" -#include -#include "Platform/FileStream.h" -#include "Xml.h" - -namespace TrueCrypt -{ - XmlParser::XmlParser (const FilePath &fileName) - { - make_shared_auto (File, file); - file->Open (fileName); - FileStream stream (file); - - XmlText = wxString::FromUTF8 (stream.ReadToEnd().c_str()); - } - - wxString XmlParser::ConvertEscapedChars (wxString xmlString) const - { - xmlString.Replace (L"<", L"<"); - xmlString.Replace (L">", L">"); - xmlString.Replace (L"&", L"&"); - xmlString.Replace (L""", L"\""); - return xmlString; - } - - XmlNodeList XmlParser::GetNodes (const wxString &nodeName) const - { - XmlNodeList nodeList; - - size_t nodePos = 0; - while ((nodePos = XmlText.find (L"<" + nodeName, nodePos)) != string::npos) - { - XmlNode xmlNode; - xmlNode.Name = nodeName; - - size_t nodeEnd = XmlText.find (L">", nodePos); - if (nodeEnd == string::npos) - throw ParameterIncorrect (SRC_POS); - - wxString nodeTagText = XmlText.substr (nodePos + 1, nodeEnd - nodePos - 1); - nodePos = nodeEnd; - - if (nodeTagText.size() > nodeName.size() && nodeTagText[nodeName.size()] != L' ' && nodeTagText[nodeName.size()] != L'/') - continue; - - nodeTagText = nodeTagText.substr (nodeName.size()); - - - // Attributes - wxStringTokenizer tokenizer (nodeTagText, L"\"", wxTOKEN_RET_EMPTY); - while (tokenizer.HasMoreTokens()) - { - wxString attributeName = tokenizer.GetNextToken(); - attributeName.Replace (L" ", L"", true); - attributeName.Replace (L"=", L""); - - if (!attributeName.empty() && tokenizer.HasMoreTokens()) - { - wxString attributeText = tokenizer.GetNextToken(); - xmlNode.Attributes[attributeName] = ConvertEscapedChars (attributeText); - } - } - - // Inner text - if (!nodeTagText.EndsWith (L"/")) - { - size_t innerTextPos = nodeEnd + 1; - size_t innerTextEnd = XmlText.find (L"", innerTextPos); - if (innerTextEnd == string::npos) - throw ParameterIncorrect (SRC_POS); - - xmlNode.InnerText = ConvertEscapedChars (XmlText.substr (innerTextPos, innerTextEnd - innerTextPos)); - nodePos = innerTextEnd; - } - - nodeList.push_back (xmlNode); - } - - return nodeList; - } - - XmlWriter::XmlWriter (const FilePath &fileName) - { - MemOutStream.reset (new wxMemoryOutputStream); - TextOutStream.reset (new wxTextOutputStream (*MemOutStream)); - OutFile.Open (fileName, File::CreateWrite); - - *TextOutStream << L"" << endl << L"" << endl; - CurrentIndentLevel = 0; - } - - void XmlWriter::Close() - { - if (MemOutStream.get()) - { - *TextOutStream << L"" << endl; - - wxStreamBuffer *buf = MemOutStream->GetOutputStreamBuffer(); - OutFile.Write (ConstBufferPtr (reinterpret_cast (buf->GetBufferStart()), buf->GetBufferSize())); - OutFile.Close(); - - TextOutStream.reset(); - MemOutStream.reset(); - } - } - - wxString XmlWriter::EscapeChars (wxString rawString) const - { - rawString.Replace (L"<", L"<"); - rawString.Replace (L">", L">"); - rawString.Replace (L"&", L"&"); - rawString.Replace (L"\"", L"""); - return rawString; - } - - void XmlWriter::WriteNode (const XmlNode &xmlNode) - { - XmlNodeList nodes; - nodes.push_back (xmlNode); - WriteNodes (nodes); - } - - void XmlWriter::WriteNodes (const XmlNodeList &xmlNodes) - { - CurrentIndentLevel++; - wxString indent; - for (int i = 0; i < CurrentIndentLevel; ++i) - indent += L"\t"; - - foreach (const XmlNode &node, xmlNodes) - { - *TextOutStream << indent << L"<" << node.Name; - - typedef pair AttribPair; - foreach (AttribPair attrib, node.Attributes) - { - *TextOutStream << L" " << attrib.first << L"=\"" << EscapeChars (attrib.second) << L"\""; - } - - if (!node.InnerNodes.empty()) - { - *TextOutStream << L">" << endl; - WriteNodes (node.InnerNodes); - *TextOutStream << indent; - } - else if (!node.InnerText.empty()) - { - *TextOutStream << L">" << EscapeChars (node.InnerText); - } - else - { - *TextOutStream << L"/>" << endl; - continue; - } - - *TextOutStream << L"" << endl; - } - - CurrentIndentLevel--; - } - - XmlWriter::~XmlWriter () - { - try - { - Close(); - } - catch (...) { } - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "System.h" +#include +#include "Platform/FileStream.h" +#include "Xml.h" + +namespace TrueCrypt +{ + XmlParser::XmlParser (const FilePath &fileName) + { + make_shared_auto (File, file); + file->Open (fileName); + FileStream stream (file); + + XmlText = wxString::FromUTF8 (stream.ReadToEnd().c_str()); + } + + wxString XmlParser::ConvertEscapedChars (wxString xmlString) const + { + xmlString.Replace (L"<", L"<"); + xmlString.Replace (L">", L">"); + xmlString.Replace (L"&", L"&"); + xmlString.Replace (L""", L"\""); + return xmlString; + } + + XmlNodeList XmlParser::GetNodes (const wxString &nodeName) const + { + XmlNodeList nodeList; + + size_t nodePos = 0; + while ((nodePos = XmlText.find (L"<" + nodeName, nodePos)) != string::npos) + { + XmlNode xmlNode; + xmlNode.Name = nodeName; + + size_t nodeEnd = XmlText.find (L">", nodePos); + if (nodeEnd == string::npos) + throw ParameterIncorrect (SRC_POS); + + wxString nodeTagText = XmlText.substr (nodePos + 1, nodeEnd - nodePos - 1); + nodePos = nodeEnd; + + if (nodeTagText.size() > nodeName.size() && nodeTagText[nodeName.size()] != L' ' && nodeTagText[nodeName.size()] != L'/') + continue; + + nodeTagText = nodeTagText.substr (nodeName.size()); + + + // Attributes + wxStringTokenizer tokenizer (nodeTagText, L"\"", wxTOKEN_RET_EMPTY); + while (tokenizer.HasMoreTokens()) + { + wxString attributeName = tokenizer.GetNextToken(); + attributeName.Replace (L" ", L"", true); + attributeName.Replace (L"=", L""); + + if (!attributeName.empty() && tokenizer.HasMoreTokens()) + { + wxString attributeText = tokenizer.GetNextToken(); + xmlNode.Attributes[attributeName] = ConvertEscapedChars (attributeText); + } + } + + // Inner text + if (!nodeTagText.EndsWith (L"/")) + { + size_t innerTextPos = nodeEnd + 1; + size_t innerTextEnd = XmlText.find (L"", innerTextPos); + if (innerTextEnd == string::npos) + throw ParameterIncorrect (SRC_POS); + + xmlNode.InnerText = ConvertEscapedChars (XmlText.substr (innerTextPos, innerTextEnd - innerTextPos)); + nodePos = innerTextEnd; + } + + nodeList.push_back (xmlNode); + } + + return nodeList; + } + + XmlWriter::XmlWriter (const FilePath &fileName) + { + MemOutStream.reset (new wxMemoryOutputStream); + TextOutStream.reset (new wxTextOutputStream (*MemOutStream)); + OutFile.Open (fileName, File::CreateWrite); + + *TextOutStream << L"" << endl << L"" << endl; + CurrentIndentLevel = 0; + } + + void XmlWriter::Close() + { + if (MemOutStream.get()) + { + *TextOutStream << L"" << endl; + + wxStreamBuffer *buf = MemOutStream->GetOutputStreamBuffer(); + OutFile.Write (ConstBufferPtr (reinterpret_cast (buf->GetBufferStart()), buf->GetBufferSize())); + OutFile.Close(); + + TextOutStream.reset(); + MemOutStream.reset(); + } + } + + wxString XmlWriter::EscapeChars (wxString rawString) const + { + rawString.Replace (L"<", L"<"); + rawString.Replace (L">", L">"); + rawString.Replace (L"&", L"&"); + rawString.Replace (L"\"", L"""); + return rawString; + } + + void XmlWriter::WriteNode (const XmlNode &xmlNode) + { + XmlNodeList nodes; + nodes.push_back (xmlNode); + WriteNodes (nodes); + } + + void XmlWriter::WriteNodes (const XmlNodeList &xmlNodes) + { + CurrentIndentLevel++; + wxString indent; + for (int i = 0; i < CurrentIndentLevel; ++i) + indent += L"\t"; + + foreach (const XmlNode &node, xmlNodes) + { + *TextOutStream << indent << L"<" << node.Name; + + typedef pair AttribPair; + foreach (AttribPair attrib, node.Attributes) + { + *TextOutStream << L" " << attrib.first << L"=\"" << EscapeChars (attrib.second) << L"\""; + } + + if (!node.InnerNodes.empty()) + { + *TextOutStream << L">" << endl; + WriteNodes (node.InnerNodes); + *TextOutStream << indent; + } + else if (!node.InnerText.empty()) + { + *TextOutStream << L">" << EscapeChars (node.InnerText); + } + else + { + *TextOutStream << L"/>" << endl; + continue; + } + + *TextOutStream << L"" << endl; + } + + CurrentIndentLevel--; + } + + XmlWriter::~XmlWriter () + { + try + { + Close(); + } + catch (...) { } + } +} diff --git a/Main/Xml.h b/Main/Xml.h index 4bed14a..1fe3380 100644 --- a/Main/Xml.h +++ b/Main/Xml.h @@ -1,75 +1,75 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Main_Xml -#define TC_HEADER_Main_Xml - -#include "System.h" -#include "Main.h" - -namespace TrueCrypt -{ - struct XmlNode; - typedef list XmlNodeList; - - struct XmlNode - { - XmlNode () { } - XmlNode (const wxString &name) : Name (name) { } - XmlNode (const wxString &name, const wxString &innerText) : InnerText (innerText), Name (name) { } - XmlNode (const wxString &name, const XmlNodeList &innerNodes) : InnerNodes (innerNodes), Name (name) { } - - map Attributes; - XmlNodeList InnerNodes; - wxString InnerText; - wxString Name; - }; - - class XmlParser - { - public: - XmlParser (const FilePath &fileName); - XmlParser (const string &xmlTextUtf8) : XmlText (wxString::FromUTF8 (xmlTextUtf8.c_str())) { } - XmlParser (const wxString &xmlText) : XmlText (xmlText) { } - virtual ~XmlParser () { } - - wxString ConvertEscapedChars (wxString xmlString) const; - XmlNodeList GetNodes (const wxString &nodeName) const; - - protected: - wxString XmlText; - - private: - XmlParser (const XmlParser &); - XmlParser &operator= (const XmlParser &); - }; - - class XmlWriter - { - public: - XmlWriter (const FilePath &fileName); - virtual ~XmlWriter (); - - void Close(); - wxString EscapeChars (wxString rawString) const; - void WriteNode (const XmlNode &xmlNode); - void WriteNodes (const XmlNodeList &xmlNodes); - - protected: - int CurrentIndentLevel; - auto_ptr MemOutStream; - auto_ptr TextOutStream; - File OutFile; - - private: - XmlWriter (const XmlWriter &); - XmlWriter &operator= (const XmlWriter &); - }; -} - -#endif // TC_HEADER_Main_Xml +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Main_Xml +#define TC_HEADER_Main_Xml + +#include "System.h" +#include "Main.h" + +namespace TrueCrypt +{ + struct XmlNode; + typedef list XmlNodeList; + + struct XmlNode + { + XmlNode () { } + XmlNode (const wxString &name) : Name (name) { } + XmlNode (const wxString &name, const wxString &innerText) : InnerText (innerText), Name (name) { } + XmlNode (const wxString &name, const XmlNodeList &innerNodes) : InnerNodes (innerNodes), Name (name) { } + + map Attributes; + XmlNodeList InnerNodes; + wxString InnerText; + wxString Name; + }; + + class XmlParser + { + public: + XmlParser (const FilePath &fileName); + XmlParser (const string &xmlTextUtf8) : XmlText (wxString::FromUTF8 (xmlTextUtf8.c_str())) { } + XmlParser (const wxString &xmlText) : XmlText (xmlText) { } + virtual ~XmlParser () { } + + wxString ConvertEscapedChars (wxString xmlString) const; + XmlNodeList GetNodes (const wxString &nodeName) const; + + protected: + wxString XmlText; + + private: + XmlParser (const XmlParser &); + XmlParser &operator= (const XmlParser &); + }; + + class XmlWriter + { + public: + XmlWriter (const FilePath &fileName); + virtual ~XmlWriter (); + + void Close(); + wxString EscapeChars (wxString rawString) const; + void WriteNode (const XmlNode &xmlNode); + void WriteNodes (const XmlNodeList &xmlNodes); + + protected: + int CurrentIndentLevel; + auto_ptr MemOutStream; + auto_ptr TextOutStream; + File OutFile; + + private: + XmlWriter (const XmlWriter &); + XmlWriter &operator= (const XmlWriter &); + }; +} + +#endif // TC_HEADER_Main_Xml diff --git a/Makefile b/Makefile index 06cce5a..e0714c0 100644 --- a/Makefile +++ b/Makefile @@ -1,260 +1,263 @@ -# -# Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -#------ Command line arguments ------ -# DEBUG: Disable optimizations and enable debugging checks -# DEBUGGER: Enable debugging information for use by debuggers -# NOGUI: Disable graphical user interface (build console-only application) -# NOSTRIP: Do not strip release binary -# NOTEST: Do not test release binary -# RESOURCEDIR: Run-time resource directory -# VERBOSE: Enable verbose messages -# WXSTATIC: Use static wxWidgets library - -#------ Targets ------ -# all -# clean -# wxbuild: Configure and build wxWidgets - source code must be located at $(WX_ROOT) - - -#------ Build configuration ------ - -export APPNAME := truecrypt -export BASE_DIR := $(CURDIR) -export BUILD_INC := $(BASE_DIR)/Build/Include - -export AR ?= ar -export CC ?= gcc -export CXX ?= g++ -export RANLIB ?= ranlib - -export CFLAGS := -Wall -export CXXFLAGS := -Wall -Wno-sign-compare -Wno-unused-parameter -C_CXX_FLAGS := -MMD -I$(BASE_DIR) -I$(BASE_DIR)/Crypto - -export LFLAGS := - -export PKG_CONFIG_PATH ?= /usr/local/lib/pkgconfig - -export WX_CONFIG ?= wx-config -export WX_CONFIG_ARGS := --unicode -WX_CONFIGURE_FLAGS := -export WXCONFIG_CFLAGS := -export WXCONFIG_CXXFLAGS := -WX_ROOT ?= .. - - -export TC_BUILD_CONFIG := Release - -ifeq "$(origin DEBUG)" "command line" -ifneq "$(DEBUG)" "0" -TC_BUILD_CONFIG := Debug -endif -endif - -ifeq "$(origin NOGUI)" "command line" -export TC_NO_GUI := 1 -C_CXX_FLAGS += -DTC_NO_GUI -WX_CONFIGURE_FLAGS += --disable-gui -endif - -ifdef PKCS11_INC -C_CXX_FLAGS += -I$(PKCS11_INC) -endif - -ifeq "$(origin RESOURCEDIR)" "command line" -C_CXX_FLAGS += -DTC_RESOURCE_DIR="$(RESOURCEDIR)" -endif - -ifneq "$(origin VERBOSE)" "command line" -MAKEFLAGS += -s -endif - -ifeq "$(origin WXSTATIC)" "command line" -WX_CONFIG = $(WX_BUILD_DIR)/wx-config -WX_CONFIG_ARGS += --static -endif - - -#------ Release configuration ------ - -ifeq "$(TC_BUILD_CONFIG)" "Release" - -C_CXX_FLAGS += -O2 -fno-strict-aliasing # Do not enable strict aliasing -export WX_BUILD_DIR ?= $(BASE_DIR)/wxrelease -WX_CONFIGURE_FLAGS += --disable-debug_flag --disable-debug_gdb --disable-debug_info - -else - -#------ Debug configuration ------ - -C_CXX_FLAGS += -DDEBUG -CXXFLAGS += -fno-default-inline -Wno-unused-function -Wno-unused-variable -export WX_BUILD_DIR ?= $(BASE_DIR)/wxdebug -WX_CONFIGURE_FLAGS += --enable-debug_flag --disable-debug_gdb --disable-debug_info - -endif - - -#------ Debugger configuration ------ - -ifeq "$(origin DEBUGGER)" "command line" - -C_CXX_FLAGS += -ggdb -WX_CONFIGURE_FLAGS += --enable-debug_gdb --enable-debug_info - -endif - - -#------ Platform configuration ------ - -export PLATFORM := "Unknown" -export PLATFORM_UNSUPPORTED := 0 - - -#------ Linux configuration ------ - -ifeq "$(shell uname -s)" "Linux" - -PLATFORM := Linux -C_CXX_FLAGS += -DTC_UNIX -DTC_LINUX - -ifeq "$(TC_BUILD_CONFIG)" "Release" -C_CXX_FLAGS += -fdata-sections -ffunction-sections -LFLAGS += -Wl,--gc-sections - -ifneq "$(shell ld --help 2>&1 | grep sysv | wc -l)" "0" -LFLAGS += -Wl,--hash-style=sysv -endif - -WXCONFIG_CFLAGS += -fdata-sections -ffunction-sections -WXCONFIG_CXXFLAGS += -fdata-sections -ffunction-sections -endif - -endif - - -#------ Mac OS X configuration ------ - -ifeq "$(shell uname -s)" "Darwin" - -PLATFORM := MacOSX -APPNAME := TrueCrypt -TC_OSX_SDK ?= /Developer/SDKs/MacOSX10.4u.sdk - -C_CXX_FLAGS += -DTC_UNIX -DTC_BSD -DTC_MACOSX -mmacosx-version-min=10.4 -isysroot $(TC_OSX_SDK) -LFLAGS += -mmacosx-version-min=10.4 -Wl,-syslibroot $(TC_OSX_SDK) -WX_CONFIGURE_FLAGS += --with-macosx-version-min=10.4 --with-macosx-sdk=$(TC_OSX_SDK) - -ifeq "$(TC_BUILD_CONFIG)" "Release" - -export DISABLE_PRECOMPILED_HEADERS := 1 - -S := $(C_CXX_FLAGS) -C_CXX_FLAGS = $(subst -MMD,,$(S)) - -C_CXX_FLAGS += -gfull -arch i386 -arch ppc -LFLAGS += -Wl,-dead_strip -arch i386 -arch ppc - -WX_CONFIGURE_FLAGS += --enable-universal_binary -WXCONFIG_CFLAGS += -gfull -WXCONFIG_CXXFLAGS += -gfull - -else - -WX_CONFIGURE_FLAGS += --disable-universal_binary - -endif - -endif - - -#------ FreeBSD configuration ------ - -ifeq "$(shell uname -s)" "FreeBSD" - -PLATFORM := FreeBSD -PLATFORM_UNSUPPORTED := 1 -C_CXX_FLAGS += -DTC_UNIX -DTC_BSD -DTC_FREEBSD - -endif - - -#------ Solaris configuration ------ - -ifeq "$(shell uname -s)" "SunOS" - -PLATFORM := Solaris -PLATFORM_UNSUPPORTED := 1 -C_CXX_FLAGS += -DTC_UNIX -DTC_SOLARIS -WX_CONFIGURE_FLAGS += --with-gtk - -endif - - -#------ Common configuration ------ - -CFLAGS := $(C_CXX_FLAGS) $(CFLAGS) $(TC_EXTRA_CFLAGS) -CXXFLAGS := $(C_CXX_FLAGS) $(CXXFLAGS) $(TC_EXTRA_CXXFLAGS) -LFLAGS := $(LFLAGS) $(TC_EXTRA_LFLAGS) - -WX_CONFIGURE_FLAGS += --enable-unicode -disable-shared --disable-dependency-tracking --disable-compat26 --enable-exceptions --enable-std_string --enable-dataobj --enable-mimetype \ - --disable-protocol --disable-protocols --disable-url --disable-ipc --disable-sockets --disable-fs_inet --disable-ole --disable-docview --disable-clipboard \ - --disable-help --disable-html --disable-mshtmlhelp --disable-htmlhelp --disable-mdi --disable-metafile --disable-webkit \ - --disable-xrc --disable-aui --disable-postscript --disable-printarch \ - --disable-arcstream --disable-fs_archive --disable-fs_zip --disable-tarstream --disable-zipstream \ - --disable-animatectrl --disable-bmpcombobox --disable-calendar --disable-caret --disable-checklst --disable-collpane --disable-colourpicker --disable-comboctrl \ - --disable-datepick --disable-display --disable-dirpicker --disable-filepicker --disable-fontpicker --disable-grid --disable-dataviewctrl \ - --disable-listbook --disable-odcombobox --disable-sash --disable-searchctrl --disable-slider --disable-splitter --disable-togglebtn \ - --disable-toolbar --disable-tbarnative --disable-treebook --disable-toolbook --disable-tipwindow --disable-popupwin \ - --disable-commondlg --disable-aboutdlg --disable-coldlg --disable-finddlg --disable-fontdlg --disable-numberdlg --disable-splash \ - --disable-tipdlg --disable-progressdlg --disable-wizarddlg --disable-miniframe --disable-tooltips --disable-splines --disable-palette \ - --disable-richtext --disable-dialupman --disable-debugreport --disable-filesystem \ - --disable-graphics_ctx --disable-sound --disable-mediactrl --disable-joystick --disable-apple_ieee \ - --disable-gif --disable-pcx --disable-tga --disable-iff --disable-gif --disable-pnm \ - --without-expat --without-libtiff --without-libjpeg --without-libpng -without-regex --without-zlib - - -#------ Project build ------ - -PROJ_DIRS := Platform Volume Driver/Fuse Core Main - -.PHONY: all clean wxbuild - -all clean: - @if pwd | grep -q ' '; then echo 'Error: source code is stored in a path containing spaces' >&2; exit 1; fi - - @for DIR in $(PROJ_DIRS); do \ - PROJ=$$(echo $$DIR | cut -d/ -f1); \ - $(MAKE) -C $$DIR -f $$PROJ.make NAME=$$PROJ $(MAKECMDGOALS) || exit $?; \ - export LIBS="$(BASE_DIR)/$$DIR/$$PROJ.a $$LIBS"; \ - done - - -#------ wxWidgets build ------ - -ifeq "$(MAKECMDGOALS)" "wxbuild" -CFLAGS := -CXXFLAGS := -LFLAGS := -endif - -wxbuild: - -ifneq "$(shell test -f $(WX_ROOT)/configure || test -f $(WX_BUILD_DIR)/../configure && echo 1)" "1" - @echo 'Error: WX_ROOT must point to wxWidgets source code directory' >&2 - @exit 1 -endif - - rm -rf "$(WX_BUILD_DIR)" - mkdir -p "$(WX_BUILD_DIR)" - @echo Configuring wxWidgets library... - cd "$(WX_BUILD_DIR)" && "$(WX_ROOT)/configure" $(WX_CONFIGURE_FLAGS) >/dev/null - - @echo Building wxWidgets library... - cd "$(WX_BUILD_DIR)" && $(MAKE) +# +# Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +#------ Command line arguments ------ +# DEBUG: Disable optimizations and enable debugging checks +# DEBUGGER: Enable debugging information for use by debuggers +# NOGUI: Disable graphical user interface (build console-only application) +# NOSTRIP: Do not strip release binary +# NOTEST: Do not test release binary +# RESOURCEDIR: Run-time resource directory +# VERBOSE: Enable verbose messages +# WXSTATIC: Use static wxWidgets library + +#------ Targets ------ +# all +# clean +# wxbuild: Configure and build wxWidgets - source code must be located at $(WX_ROOT) + + +#------ Build configuration ------ + +export APPNAME := truecrypt +export BASE_DIR := $(CURDIR) +export BUILD_INC := $(BASE_DIR)/Build/Include + +export AR ?= ar +export CC ?= gcc +export CXX ?= g++ +export RANLIB ?= ranlib + +export CFLAGS := -Wall +export CXXFLAGS := -Wall -Wno-unused-parameter +C_CXX_FLAGS := -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES -I$(BASE_DIR) -I$(BASE_DIR)/Crypto + +export LFLAGS := + +export PKG_CONFIG_PATH ?= /usr/local/lib/pkgconfig + +export WX_CONFIG ?= wx-config +export WX_CONFIG_ARGS := --unicode +WX_CONFIGURE_FLAGS := +export WXCONFIG_CFLAGS := +export WXCONFIG_CXXFLAGS := +WX_ROOT ?= .. + + +export TC_BUILD_CONFIG := Release + +ifeq "$(origin DEBUG)" "command line" +ifneq "$(DEBUG)" "0" +TC_BUILD_CONFIG := Debug +endif +endif + +ifeq "$(origin NOGUI)" "command line" +export TC_NO_GUI := 1 +C_CXX_FLAGS += -DTC_NO_GUI +WX_CONFIGURE_FLAGS += --disable-gui +endif + +ifdef PKCS11_INC +C_CXX_FLAGS += -I$(PKCS11_INC) +endif + +ifeq "$(origin RESOURCEDIR)" "command line" +C_CXX_FLAGS += -DTC_RESOURCE_DIR="$(RESOURCEDIR)" +endif + +ifneq "$(origin VERBOSE)" "command line" +MAKEFLAGS += -s +endif + +ifeq "$(origin WXSTATIC)" "command line" +WX_CONFIG = $(WX_BUILD_DIR)/wx-config +WX_CONFIG_ARGS += --static +endif + + +#------ Release configuration ------ + +ifeq "$(TC_BUILD_CONFIG)" "Release" + +C_CXX_FLAGS += -O2 -fno-strict-aliasing # Do not enable strict aliasing +export WX_BUILD_DIR ?= $(BASE_DIR)/wxrelease +WX_CONFIGURE_FLAGS += --disable-debug_flag --disable-debug_gdb --disable-debug_info + +else + +#------ Debug configuration ------ + +C_CXX_FLAGS += -DDEBUG +CXXFLAGS += -fno-default-inline -Wno-unused-function -Wno-unused-variable +export WX_BUILD_DIR ?= $(BASE_DIR)/wxdebug +WX_CONFIGURE_FLAGS += --enable-debug_flag --disable-debug_gdb --disable-debug_info + +endif + + +#------ Debugger configuration ------ + +ifeq "$(origin DEBUGGER)" "command line" + +C_CXX_FLAGS += -ggdb +WX_CONFIGURE_FLAGS += --enable-debug_gdb --enable-debug_info + +endif + + +#------ Platform configuration ------ + +export PLATFORM := "Unknown" +export PLATFORM_UNSUPPORTED := 0 + + +#------ Linux configuration ------ + +ifeq "$(shell uname -s)" "Linux" + +PLATFORM := Linux +C_CXX_FLAGS += -DTC_UNIX -DTC_LINUX + +ifeq "$(TC_BUILD_CONFIG)" "Release" +C_CXX_FLAGS += -fdata-sections -ffunction-sections +LFLAGS += -Wl,--gc-sections + +ifneq "$(shell ld --help 2>&1 | grep sysv | wc -l)" "0" +LFLAGS += -Wl,--hash-style=sysv +endif + +WXCONFIG_CFLAGS += -fdata-sections -ffunction-sections +WXCONFIG_CXXFLAGS += -fdata-sections -ffunction-sections +endif + +endif + + +#------ Mac OS X configuration ------ + +ifeq "$(shell uname -s)" "Darwin" + +PLATFORM := MacOSX +APPNAME := TrueCrypt + +TC_OSX_SDK ?= /Developer/SDKs/MacOSX10.4u.sdk +CC := gcc-4.0 +CXX := g++-4.0 + +C_CXX_FLAGS += -DTC_UNIX -DTC_BSD -DTC_MACOSX -mmacosx-version-min=10.4 -isysroot $(TC_OSX_SDK) +LFLAGS += -mmacosx-version-min=10.4 -Wl,-syslibroot $(TC_OSX_SDK) +WX_CONFIGURE_FLAGS += --with-macosx-version-min=10.4 --with-macosx-sdk=$(TC_OSX_SDK) + +ifeq "$(TC_BUILD_CONFIG)" "Release" + +export DISABLE_PRECOMPILED_HEADERS := 1 + +S := $(C_CXX_FLAGS) +C_CXX_FLAGS = $(subst -MMD,,$(S)) + +C_CXX_FLAGS += -gfull -arch i386 -arch ppc +LFLAGS += -Wl,-dead_strip -arch i386 -arch ppc + +WX_CONFIGURE_FLAGS += --enable-universal_binary +WXCONFIG_CFLAGS += -gfull +WXCONFIG_CXXFLAGS += -gfull + +else + +WX_CONFIGURE_FLAGS += --disable-universal_binary + +endif + +endif + + +#------ FreeBSD configuration ------ + +ifeq "$(shell uname -s)" "FreeBSD" + +PLATFORM := FreeBSD +PLATFORM_UNSUPPORTED := 1 +C_CXX_FLAGS += -DTC_UNIX -DTC_BSD -DTC_FREEBSD + +endif + + +#------ Solaris configuration ------ + +ifeq "$(shell uname -s)" "SunOS" + +PLATFORM := Solaris +PLATFORM_UNSUPPORTED := 1 +C_CXX_FLAGS += -DTC_UNIX -DTC_SOLARIS +WX_CONFIGURE_FLAGS += --with-gtk + +endif + + +#------ Common configuration ------ + +CFLAGS := $(C_CXX_FLAGS) $(CFLAGS) $(TC_EXTRA_CFLAGS) +CXXFLAGS := $(C_CXX_FLAGS) $(CXXFLAGS) $(TC_EXTRA_CXXFLAGS) +LFLAGS := $(LFLAGS) $(TC_EXTRA_LFLAGS) + +WX_CONFIGURE_FLAGS += --enable-unicode -disable-shared --disable-dependency-tracking --disable-compat26 --enable-exceptions --enable-std_string --enable-dataobj --enable-mimetype \ + --disable-protocol --disable-protocols --disable-url --disable-ipc --disable-sockets --disable-fs_inet --disable-ole --disable-docview --disable-clipboard \ + --disable-help --disable-html --disable-mshtmlhelp --disable-htmlhelp --disable-mdi --disable-metafile --disable-webkit \ + --disable-xrc --disable-aui --disable-postscript --disable-printarch \ + --disable-arcstream --disable-fs_archive --disable-fs_zip --disable-tarstream --disable-zipstream \ + --disable-animatectrl --disable-bmpcombobox --disable-calendar --disable-caret --disable-checklst --disable-collpane --disable-colourpicker --disable-comboctrl \ + --disable-datepick --disable-display --disable-dirpicker --disable-filepicker --disable-fontpicker --disable-grid --disable-dataviewctrl \ + --disable-listbook --disable-odcombobox --disable-sash --disable-searchctrl --disable-slider --disable-splitter --disable-togglebtn \ + --disable-toolbar --disable-tbarnative --disable-treebook --disable-toolbook --disable-tipwindow --disable-popupwin \ + --disable-commondlg --disable-aboutdlg --disable-coldlg --disable-finddlg --disable-fontdlg --disable-numberdlg --disable-splash \ + --disable-tipdlg --disable-progressdlg --disable-wizarddlg --disable-miniframe --disable-tooltips --disable-splines --disable-palette \ + --disable-richtext --disable-dialupman --disable-debugreport --disable-filesystem \ + --disable-graphics_ctx --disable-sound --disable-mediactrl --disable-joystick --disable-apple_ieee \ + --disable-gif --disable-pcx --disable-tga --disable-iff --disable-gif --disable-pnm \ + --without-expat --without-libtiff --without-libjpeg --without-libpng -without-regex --without-zlib + + +#------ Project build ------ + +PROJ_DIRS := Platform Volume Driver/Fuse Core Main + +.PHONY: all clean wxbuild + +all clean: + @if pwd | grep -q ' '; then echo 'Error: source code is stored in a path containing spaces' >&2; exit 1; fi + + @for DIR in $(PROJ_DIRS); do \ + PROJ=$$(echo $$DIR | cut -d/ -f1); \ + $(MAKE) -C $$DIR -f $$PROJ.make NAME=$$PROJ $(MAKECMDGOALS) || exit $?; \ + export LIBS="$(BASE_DIR)/$$DIR/$$PROJ.a $$LIBS"; \ + done + + +#------ wxWidgets build ------ + +ifeq "$(MAKECMDGOALS)" "wxbuild" +CFLAGS := +CXXFLAGS := +LFLAGS := +endif + +wxbuild: + +ifneq "$(shell test -f $(WX_ROOT)/configure || test -f $(WX_BUILD_DIR)/../configure && echo 1)" "1" + @echo 'Error: WX_ROOT must point to wxWidgets source code directory' >&2 + @exit 1 +endif + + rm -rf "$(WX_BUILD_DIR)" + mkdir -p "$(WX_BUILD_DIR)" + @echo Configuring wxWidgets library... + cd "$(WX_BUILD_DIR)" && "$(WX_ROOT)/configure" $(WX_CONFIGURE_FLAGS) >/dev/null + + @echo Building wxWidgets library... + cd "$(WX_BUILD_DIR)" && $(MAKE) diff --git a/Mount/Hotkeys.c b/Mount/Hotkeys.c index 06fe8a7..f4ff5d8 100644 --- a/Mount/Hotkeys.c +++ b/Mount/Hotkeys.c @@ -1,525 +1,525 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include "Dlgcode.h" -#include "Hotkeys.h" -#include "Language.h" -#include "Mount.h" -#include "Resource.h" - -#define MAX_KEY_COMB_NAME_LEN 260 - -TCHOTKEY Hotkeys [NBR_HOTKEYS]; -static TCHOTKEY tmpHotkeys [NBR_HOTKEYS]; - -static int nSelectedHotkeyId; -static UINT currentVKeyCode; - - -static void ScanAndProcessKey (UINT *vKeyCode, wchar_t *keyName) -{ - UINT vKey; - *vKeyCode = 0; - - for (vKey = 0; vKey <= 0xFF; vKey++) - { - if (GetAsyncKeyState (vKey) < 0) - { - if (GetKeyName (vKey, keyName)) // If the key is allowed and its name has been resolved - *vKeyCode = vKey; - } - } -} - - -/* Returns TRUE if the key is allowed and its name is resolved. */ -BOOL GetKeyName (UINT vKey, wchar_t *keyName) -{ - BOOL result = TRUE; - - if (vKey >= 0x30 && vKey <= 0x5a) - { - // ASCII characters - wsprintfW (keyName, L"%hc", (char) vKey); - } - else if (vKey >= 0xE9 && vKey <= 0xF5) - { - // OEM-specific - wsprintfW (keyName, L"OEM-%d", vKey); - } - else if (vKey >= VK_F1 && vKey <= VK_F24) - { - // F1-F24 - wsprintfW (keyName, L"F%d", vKey - VK_F1 + 1); - } - else if (vKey >= VK_NUMPAD0 && vKey <= VK_NUMPAD9) - { - // Numpad numbers - wsprintfW (keyName, L"%s %d", GetString ("VK_NUMPAD"), vKey - VK_NUMPAD0); - } - else - { - switch (vKey) - { - case VK_MULTIPLY: wsprintfW (keyName, L"%s *", GetString ("VK_NUMPAD")); break; - case VK_ADD: wsprintfW (keyName, L"%s +", GetString ("VK_NUMPAD")); break; - case VK_SEPARATOR: wsprintfW (keyName, L"%s Separator", GetString ("VK_NUMPAD")); break; - case VK_SUBTRACT: wsprintfW (keyName, L"%s -", GetString ("VK_NUMPAD")); break; - case VK_DECIMAL: wsprintfW (keyName, L"%s .", GetString ("VK_NUMPAD")); break; - case VK_DIVIDE: wsprintfW (keyName, L"%s /", GetString ("VK_NUMPAD")); break; - case VK_OEM_1: wcscpy (keyName, L"OEM 1 (';')"); break; - case VK_OEM_PLUS: wcscpy (keyName, L"+"); break; - case VK_OEM_COMMA: wcscpy (keyName, L","); break; - case VK_OEM_MINUS: wcscpy (keyName, L"-"); break; - case VK_OEM_PERIOD: wcscpy (keyName, L"."); break; - case VK_OEM_2: wcscpy (keyName, L"OEM 2 ('/')"); break; - case VK_OEM_3: wcscpy (keyName, L"OEM 3 (`)"); break; - case VK_OEM_4: wcscpy (keyName, L"OEM 4 ('[')"); break; - case VK_OEM_5: wcscpy (keyName, L"OEM 5 ('\\')"); break; - case VK_OEM_6: wcscpy (keyName, L"OEM 6 (']')"); break; - case VK_OEM_7: wcscpy (keyName, L"OEM 7 (')"); break; - case VK_OEM_8: wcscpy (keyName, L"OEM 8"); break; - case VK_OEM_AX: wcscpy (keyName, L"OEM AX"); break; - case VK_OEM_102: wcscpy (keyName, L"OEM 102"); break; - case VK_ICO_HELP: wcscpy (keyName, L"ICO_HELP"); break; - case VK_ICO_00: wcscpy (keyName, L"ICO_00"); break; - case VK_ICO_CLEAR: wcscpy (keyName, L"ICO_CLEAR"); break; - case VK_ATTN: wcscpy (keyName, L"Attn"); break; - case VK_CRSEL: wcscpy (keyName, L"CrSel"); break; - case VK_EXSEL: wcscpy (keyName, L"ExSel"); break; - case VK_EREOF: wcscpy (keyName, L"Erase EOF"); break; - case VK_PA1: wcscpy (keyName, L"PA1"); break; - case VK_OEM_CLEAR: wcscpy (keyName, L"OEM Clear"); break; - - case 0: - case 1: - case 0xFF: - result = FALSE; - break; - - default: - { - char key[16]; - wchar_t *desc; - sprintf (key, "VKEY_%02X", vKey); - desc = GetString (key); - if (desc == UnknownString) - result = FALSE; - else - wcsncpy (keyName, desc, MAX_KEY_COMB_NAME_LEN); - } - } - } - return result; -} - - -static BOOL ShortcutInUse (UINT vKeyCode, UINT modifiers, TCHOTKEY hotkeys[]) -{ - int i; - - for (i = 0; i < NBR_HOTKEYS; i++) - { - if (hotkeys[i].vKeyCode == vKeyCode && hotkeys[i].vKeyModifiers == modifiers) - return TRUE; - } - return FALSE; -} - - -void UnregisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]) -{ - int i; - - for (i = 0; i < NBR_HOTKEYS; i++) - { - if (hotkeys[i].vKeyCode != 0) - UnregisterHotKey (hwndDlg, i); - - } -} - - -BOOL RegisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]) -{ - BOOL result = TRUE; - int i; - - for (i = 0; i < NBR_HOTKEYS; i++) - { - if (hotkeys[i].vKeyCode != 0 - && !RegisterHotKey (hwndDlg, i, hotkeys[i].vKeyModifiers, hotkeys[i].vKeyCode)) - result = FALSE; - } - - return result; -} - - -static void DisplayHotkeyList (HWND hwndDlg) -{ - LVITEMW item; - HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST); - int i; - wchar_t ShortcutMod [MAX_KEY_COMB_NAME_LEN]; - wchar_t ShortcutFinal [MAX_KEY_COMB_NAME_LEN*2]; - wchar_t Shortcut [MAX_KEY_COMB_NAME_LEN]; - - SendMessage (hList, LVM_DELETEALLITEMS,0, (LPARAM)&item); - - for (i = 0; i < NBR_HOTKEYS; i++) - { - memset (&item,0,sizeof(item)); - item.mask = LVIF_TEXT; - item.iItem = i; - item.iSubItem = 0; - - switch (i) - { - - case HK_AUTOMOUNT_DEVICES: - item.pszText = GetString ("HK_AUTOMOUNT_DEVICES"); - break; - - case HK_DISMOUNT_ALL: - item.pszText = GetString ("HK_DISMOUNT_ALL"); - break; - - case HK_WIPE_CACHE: - item.pszText = GetString ("HK_WIPE_CACHE"); - break; - - case HK_DISMOUNT_ALL_AND_WIPE: - item.pszText = GetString ("HK_DISMOUNT_ALL_AND_WIPE"); - break; - - case HK_FORCE_DISMOUNT_ALL_AND_WIPE: - item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE"); - break; - - case HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT: - item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT"); - break; - - case HK_MOUNT_FAVORITE_VOLUMES: - item.pszText = GetString ("HK_MOUNT_FAVORITE_VOLUMES"); - break; - - case HK_SHOW_HIDE_MAIN_WINDOW: - item.pszText = GetString ("HK_SHOW_HIDE_MAIN_WINDOW"); - break; - - case HK_CLOSE_SECURITY_TOKEN_SESSIONS: - item.pszText = GetString ("IDM_CLOSE_ALL_TOKEN_SESSIONS"); - break; - - default: - item.pszText = L"[?]"; - } - - SendMessageW (hList,LVM_INSERTITEMW,0,(LPARAM)&item); - - item.iSubItem = 1; - wcscpy (Shortcut, L""); - wcscpy (ShortcutMod, L""); - - if (GetKeyName (tmpHotkeys[i].vKeyCode, Shortcut)) - { - if (tmpHotkeys[i].vKeyModifiers & MOD_CONTROL) - { - wcscat (ShortcutMod, GetString ("VK_CONTROL")); - wcscat (ShortcutMod, L"+"); - } - - if (tmpHotkeys[i].vKeyModifiers & MOD_SHIFT) - { - wcscat (ShortcutMod, GetString ("VK_SHIFT")); - wcscat (ShortcutMod, L"+"); - } - - if (tmpHotkeys[i].vKeyModifiers & MOD_ALT) - { - wcscat (ShortcutMod, GetString ("VK_ALT")); - wcscat (ShortcutMod, L"+"); - } - - if (tmpHotkeys[i].vKeyModifiers & MOD_WIN) - { - wcscat (ShortcutMod, GetString ("VK_WIN")); - wcscat (ShortcutMod, L"+"); - } - - wsprintfW (ShortcutFinal, L"%s%s", ShortcutMod, Shortcut); - item.pszText = ShortcutFinal; - } - else - item.pszText = L""; - - SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&item); - } -} - - - -BOOL CALLBACK HotkeysDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST); - HWND hwndMainDlg = hwndDlg; - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - static BOOL bKeyScanOn; - static BOOL bTPlaySoundOnHotkeyMountDismount; - static BOOL bTDisplayMsgBoxOnHotkeyDismount; - - while (GetParent (hwndMainDlg) != NULL) - { - hwndMainDlg = GetParent (hwndMainDlg); - } - - switch (msg) - { - case WM_INITDIALOG: - { - LVCOLUMNW col; - - bKeyScanOn = FALSE; - nSelectedHotkeyId = -1; - currentVKeyCode = 0; - memcpy (tmpHotkeys, Hotkeys, sizeof(tmpHotkeys)); - - SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP - ); - - memset (&col,0,sizeof(col)); - col.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - col.pszText = GetString ("ACTION"); - col.cx = CompensateXDPI (341); - col.fmt = LVCFMT_LEFT; - SendMessageW (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&col); - - col.pszText = GetString ("SHORTCUT"); - col.cx = CompensateXDPI (190); - col.fmt = LVCFMT_LEFT; - SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&col); - - LocalizeDialog (hwndDlg, "IDD_HOTKEYS_DLG"); - - SetCheckBox (hwndDlg, IDC_HK_MOD_CTRL, TRUE); - SetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT, FALSE); - SetCheckBox (hwndDlg, IDC_HK_MOD_ALT, TRUE); - SetCheckBox (hwndDlg, IDC_HK_MOD_WIN, FALSE); - - SetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_PLAY_SOUND, bPlaySoundOnHotkeyMountDismount); - SetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_MSG_BOX, bDisplayMsgBoxOnHotkeyDismount); - - bTPlaySoundOnHotkeyMountDismount = bPlaySoundOnHotkeyMountDismount; - bTDisplayMsgBoxOnHotkeyDismount = bDisplayMsgBoxOnHotkeyDismount; - - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); - - DisplayHotkeyList(hwndDlg); - - SetTimer (hwndDlg, 0xfe, 10, NULL); - return 1; - } - - case WM_TIMER: - { - if (nSelectedHotkeyId > -1) - { - wchar_t keyName [MAX_KEY_COMB_NAME_LEN]; - UINT tmpVKeyCode; - - keyName[0] = 0; - - ScanAndProcessKey (&tmpVKeyCode, &keyName[0]); - - if (keyName[0] != 0) - { - currentVKeyCode = tmpVKeyCode; - SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), TRUE); - } - } - return 1; - } - - case WM_COMMAND: - case WM_NOTIFY: - - if (lw == IDC_HOTKEY_KEY && hw == EN_CHANGE) - { - if (!bKeyScanOn && nSelectedHotkeyId < 0 && GetWindowTextLengthW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY))) - SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); - } - - if (msg == WM_NOTIFY && wParam == IDC_HOTKEY_LIST) - { - if (((LPNMHDR) lParam)->code == LVN_ITEMACTIVATE - || ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED)) - { - LVITEM item; - memset(&item,0,sizeof(item)); - nSelectedHotkeyId = ((LPNMLISTVIEW) lParam)->iItem; - SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), GetString ("PRESS_A_KEY_TO_ASSIGN")); - - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), (tmpHotkeys[nSelectedHotkeyId].vKeyCode > 0)); - - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); - bKeyScanOn = TRUE; - return 1; - } - } - - if (lw == IDC_HOTKEY_ASSIGN) - { - BOOL bOwnActiveShortcut = FALSE; - - if (nSelectedHotkeyId >= 0 && currentVKeyCode != 0) - { - UINT modifiers = 0; - if (GetCheckBox (hwndDlg, IDC_HK_MOD_CTRL)) - modifiers = MOD_CONTROL; - - if (GetCheckBox (hwndDlg, IDC_HK_MOD_ALT)) - modifiers |= MOD_ALT; - - if (GetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT)) - modifiers |= MOD_SHIFT; - - if (GetCheckBox (hwndDlg, IDC_HK_MOD_WIN)) - modifiers |= MOD_WIN; - - // Check if it's not already assigned - if (ShortcutInUse (currentVKeyCode, modifiers, tmpHotkeys)) - { - Error ("SHORTCUT_ALREADY_IN_USE"); - return 1; - } - - // Check for reserved system keys - switch (currentVKeyCode) - { - case VK_F1: - case VK_F12: - /* F1 is help and F12 is reserved for use by the debugger at all times */ - if (modifiers == 0) - { - Error ("CANNOT_USE_RESERVED_KEY"); - return 1; - } - break; - } - - bOwnActiveShortcut = ShortcutInUse (currentVKeyCode, modifiers, Hotkeys); - - // Test if the shortcut can be assigned without errors - if (!bOwnActiveShortcut - && !RegisterHotKey (hwndDlg, nSelectedHotkeyId, modifiers, currentVKeyCode)) - { - handleWin32Error(hwndDlg); - return 1; - } - else - { - if (!bOwnActiveShortcut && !UnregisterHotKey (hwndDlg, nSelectedHotkeyId)) - handleWin32Error(hwndDlg); - - tmpHotkeys[nSelectedHotkeyId].vKeyCode = currentVKeyCode; - tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = modifiers; - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); - nSelectedHotkeyId = -1; - bKeyScanOn = FALSE; - } - } - DisplayHotkeyList(hwndDlg); - return 1; - } - - if (lw == IDC_HOTKEY_REMOVE) - { - if (nSelectedHotkeyId >= 0) - { - tmpHotkeys[nSelectedHotkeyId].vKeyCode = 0; - tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = 0; - SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); - nSelectedHotkeyId = -1; - bKeyScanOn = FALSE; - DisplayHotkeyList(hwndDlg); - } - return 1; - } - - if (lw == IDC_RESET_HOTKEYS) - { - int i; - - for (i = 0; i < NBR_HOTKEYS; i++) - { - tmpHotkeys[i].vKeyCode = 0; - tmpHotkeys[i].vKeyModifiers = 0; - } - SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); - nSelectedHotkeyId = -1; - bKeyScanOn = FALSE; - DisplayHotkeyList(hwndDlg); - return 1; - } - - if (lw == IDC_DISMOUNT_CONFIRM_PLAY_SOUND) - { - bTPlaySoundOnHotkeyMountDismount = GetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_PLAY_SOUND); - } - - if (lw == IDC_DISMOUNT_CONFIRM_MSG_BOX) - { - bTDisplayMsgBoxOnHotkeyDismount = GetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_MSG_BOX); - } - - if (lw == IDCANCEL || lw == IDCLOSE) - { - KillTimer (hwndDlg, 0xfe); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - if (lw == IDOK) - { - UnregisterAllHotkeys (hwndMainDlg, Hotkeys); - memcpy (Hotkeys, tmpHotkeys, sizeof(Hotkeys)); - RegisterAllHotkeys (hwndMainDlg, Hotkeys); - KillTimer (hwndDlg, 0xfe); - bPlaySoundOnHotkeyMountDismount = bTPlaySoundOnHotkeyMountDismount; - bDisplayMsgBoxOnHotkeyDismount = bTDisplayMsgBoxOnHotkeyDismount; - - SaveSettings (hwndDlg); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - return 0; - - case WM_CLOSE: - - KillTimer (hwndDlg, 0xfe); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - return 0; -} - - +/* + Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include "Dlgcode.h" +#include "Hotkeys.h" +#include "Language.h" +#include "Mount.h" +#include "Resource.h" + +#define MAX_KEY_COMB_NAME_LEN 260 + +TCHOTKEY Hotkeys [NBR_HOTKEYS]; +static TCHOTKEY tmpHotkeys [NBR_HOTKEYS]; + +static int nSelectedHotkeyId; +static UINT currentVKeyCode; + + +static void ScanAndProcessKey (UINT *vKeyCode, wchar_t *keyName) +{ + UINT vKey; + *vKeyCode = 0; + + for (vKey = 0; vKey <= 0xFF; vKey++) + { + if (GetAsyncKeyState (vKey) < 0) + { + if (GetKeyName (vKey, keyName)) // If the key is allowed and its name has been resolved + *vKeyCode = vKey; + } + } +} + + +/* Returns TRUE if the key is allowed and its name is resolved. */ +BOOL GetKeyName (UINT vKey, wchar_t *keyName) +{ + BOOL result = TRUE; + + if (vKey >= 0x30 && vKey <= 0x5a) + { + // ASCII characters + wsprintfW (keyName, L"%hc", (char) vKey); + } + else if (vKey >= 0xE9 && vKey <= 0xF5) + { + // OEM-specific + wsprintfW (keyName, L"OEM-%d", vKey); + } + else if (vKey >= VK_F1 && vKey <= VK_F24) + { + // F1-F24 + wsprintfW (keyName, L"F%d", vKey - VK_F1 + 1); + } + else if (vKey >= VK_NUMPAD0 && vKey <= VK_NUMPAD9) + { + // Numpad numbers + wsprintfW (keyName, L"%s %d", GetString ("VK_NUMPAD"), vKey - VK_NUMPAD0); + } + else + { + switch (vKey) + { + case VK_MULTIPLY: wsprintfW (keyName, L"%s *", GetString ("VK_NUMPAD")); break; + case VK_ADD: wsprintfW (keyName, L"%s +", GetString ("VK_NUMPAD")); break; + case VK_SEPARATOR: wsprintfW (keyName, L"%s Separator", GetString ("VK_NUMPAD")); break; + case VK_SUBTRACT: wsprintfW (keyName, L"%s -", GetString ("VK_NUMPAD")); break; + case VK_DECIMAL: wsprintfW (keyName, L"%s .", GetString ("VK_NUMPAD")); break; + case VK_DIVIDE: wsprintfW (keyName, L"%s /", GetString ("VK_NUMPAD")); break; + case VK_OEM_1: wcscpy (keyName, L"OEM 1 (';')"); break; + case VK_OEM_PLUS: wcscpy (keyName, L"+"); break; + case VK_OEM_COMMA: wcscpy (keyName, L","); break; + case VK_OEM_MINUS: wcscpy (keyName, L"-"); break; + case VK_OEM_PERIOD: wcscpy (keyName, L"."); break; + case VK_OEM_2: wcscpy (keyName, L"OEM 2 ('/')"); break; + case VK_OEM_3: wcscpy (keyName, L"OEM 3 (`)"); break; + case VK_OEM_4: wcscpy (keyName, L"OEM 4 ('[')"); break; + case VK_OEM_5: wcscpy (keyName, L"OEM 5 ('\\')"); break; + case VK_OEM_6: wcscpy (keyName, L"OEM 6 (']')"); break; + case VK_OEM_7: wcscpy (keyName, L"OEM 7 (')"); break; + case VK_OEM_8: wcscpy (keyName, L"OEM 8"); break; + case VK_OEM_AX: wcscpy (keyName, L"OEM AX"); break; + case VK_OEM_102: wcscpy (keyName, L"OEM 102"); break; + case VK_ICO_HELP: wcscpy (keyName, L"ICO_HELP"); break; + case VK_ICO_00: wcscpy (keyName, L"ICO_00"); break; + case VK_ICO_CLEAR: wcscpy (keyName, L"ICO_CLEAR"); break; + case VK_ATTN: wcscpy (keyName, L"Attn"); break; + case VK_CRSEL: wcscpy (keyName, L"CrSel"); break; + case VK_EXSEL: wcscpy (keyName, L"ExSel"); break; + case VK_EREOF: wcscpy (keyName, L"Erase EOF"); break; + case VK_PA1: wcscpy (keyName, L"PA1"); break; + case VK_OEM_CLEAR: wcscpy (keyName, L"OEM Clear"); break; + + case 0: + case 1: + case 0xFF: + result = FALSE; + break; + + default: + { + char key[16]; + wchar_t *desc; + sprintf (key, "VKEY_%02X", vKey); + desc = GetString (key); + if (desc == UnknownString) + result = FALSE; + else + wcsncpy (keyName, desc, MAX_KEY_COMB_NAME_LEN); + } + } + } + return result; +} + + +static BOOL ShortcutInUse (UINT vKeyCode, UINT modifiers, TCHOTKEY hotkeys[]) +{ + int i; + + for (i = 0; i < NBR_HOTKEYS; i++) + { + if (hotkeys[i].vKeyCode == vKeyCode && hotkeys[i].vKeyModifiers == modifiers) + return TRUE; + } + return FALSE; +} + + +void UnregisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]) +{ + int i; + + for (i = 0; i < NBR_HOTKEYS; i++) + { + if (hotkeys[i].vKeyCode != 0) + UnregisterHotKey (hwndDlg, i); + + } +} + + +BOOL RegisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]) +{ + BOOL result = TRUE; + int i; + + for (i = 0; i < NBR_HOTKEYS; i++) + { + if (hotkeys[i].vKeyCode != 0 + && !RegisterHotKey (hwndDlg, i, hotkeys[i].vKeyModifiers, hotkeys[i].vKeyCode)) + result = FALSE; + } + + return result; +} + + +static void DisplayHotkeyList (HWND hwndDlg) +{ + LVITEMW item; + HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST); + int i; + wchar_t ShortcutMod [MAX_KEY_COMB_NAME_LEN]; + wchar_t ShortcutFinal [MAX_KEY_COMB_NAME_LEN*2]; + wchar_t Shortcut [MAX_KEY_COMB_NAME_LEN]; + + SendMessage (hList, LVM_DELETEALLITEMS,0, (LPARAM)&item); + + for (i = 0; i < NBR_HOTKEYS; i++) + { + memset (&item,0,sizeof(item)); + item.mask = LVIF_TEXT; + item.iItem = i; + item.iSubItem = 0; + + switch (i) + { + + case HK_AUTOMOUNT_DEVICES: + item.pszText = GetString ("HK_AUTOMOUNT_DEVICES"); + break; + + case HK_DISMOUNT_ALL: + item.pszText = GetString ("HK_DISMOUNT_ALL"); + break; + + case HK_WIPE_CACHE: + item.pszText = GetString ("HK_WIPE_CACHE"); + break; + + case HK_DISMOUNT_ALL_AND_WIPE: + item.pszText = GetString ("HK_DISMOUNT_ALL_AND_WIPE"); + break; + + case HK_FORCE_DISMOUNT_ALL_AND_WIPE: + item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE"); + break; + + case HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT: + item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT"); + break; + + case HK_MOUNT_FAVORITE_VOLUMES: + item.pszText = GetString ("HK_MOUNT_FAVORITE_VOLUMES"); + break; + + case HK_SHOW_HIDE_MAIN_WINDOW: + item.pszText = GetString ("HK_SHOW_HIDE_MAIN_WINDOW"); + break; + + case HK_CLOSE_SECURITY_TOKEN_SESSIONS: + item.pszText = GetString ("IDM_CLOSE_ALL_TOKEN_SESSIONS"); + break; + + default: + item.pszText = L"[?]"; + } + + SendMessageW (hList,LVM_INSERTITEMW,0,(LPARAM)&item); + + item.iSubItem = 1; + wcscpy (Shortcut, L""); + wcscpy (ShortcutMod, L""); + + if (GetKeyName (tmpHotkeys[i].vKeyCode, Shortcut)) + { + if (tmpHotkeys[i].vKeyModifiers & MOD_CONTROL) + { + wcscat (ShortcutMod, GetString ("VK_CONTROL")); + wcscat (ShortcutMod, L"+"); + } + + if (tmpHotkeys[i].vKeyModifiers & MOD_SHIFT) + { + wcscat (ShortcutMod, GetString ("VK_SHIFT")); + wcscat (ShortcutMod, L"+"); + } + + if (tmpHotkeys[i].vKeyModifiers & MOD_ALT) + { + wcscat (ShortcutMod, GetString ("VK_ALT")); + wcscat (ShortcutMod, L"+"); + } + + if (tmpHotkeys[i].vKeyModifiers & MOD_WIN) + { + wcscat (ShortcutMod, GetString ("VK_WIN")); + wcscat (ShortcutMod, L"+"); + } + + wsprintfW (ShortcutFinal, L"%s%s", ShortcutMod, Shortcut); + item.pszText = ShortcutFinal; + } + else + item.pszText = L""; + + SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&item); + } +} + + + +BOOL CALLBACK HotkeysDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST); + HWND hwndMainDlg = hwndDlg; + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + static BOOL bKeyScanOn; + static BOOL bTPlaySoundOnHotkeyMountDismount; + static BOOL bTDisplayMsgBoxOnHotkeyDismount; + + while (GetParent (hwndMainDlg) != NULL) + { + hwndMainDlg = GetParent (hwndMainDlg); + } + + switch (msg) + { + case WM_INITDIALOG: + { + LVCOLUMNW col; + + bKeyScanOn = FALSE; + nSelectedHotkeyId = -1; + currentVKeyCode = 0; + memcpy (tmpHotkeys, Hotkeys, sizeof(tmpHotkeys)); + + SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP + ); + + memset (&col,0,sizeof(col)); + col.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + col.pszText = GetString ("ACTION"); + col.cx = CompensateXDPI (341); + col.fmt = LVCFMT_LEFT; + SendMessageW (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&col); + + col.pszText = GetString ("SHORTCUT"); + col.cx = CompensateXDPI (190); + col.fmt = LVCFMT_LEFT; + SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&col); + + LocalizeDialog (hwndDlg, "IDD_HOTKEYS_DLG"); + + SetCheckBox (hwndDlg, IDC_HK_MOD_CTRL, TRUE); + SetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT, FALSE); + SetCheckBox (hwndDlg, IDC_HK_MOD_ALT, TRUE); + SetCheckBox (hwndDlg, IDC_HK_MOD_WIN, FALSE); + + SetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_PLAY_SOUND, bPlaySoundOnHotkeyMountDismount); + SetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_MSG_BOX, bDisplayMsgBoxOnHotkeyDismount); + + bTPlaySoundOnHotkeyMountDismount = bPlaySoundOnHotkeyMountDismount; + bTDisplayMsgBoxOnHotkeyDismount = bDisplayMsgBoxOnHotkeyDismount; + + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); + + DisplayHotkeyList(hwndDlg); + + SetTimer (hwndDlg, 0xfe, 10, NULL); + return 1; + } + + case WM_TIMER: + { + if (nSelectedHotkeyId > -1) + { + wchar_t keyName [MAX_KEY_COMB_NAME_LEN]; + UINT tmpVKeyCode; + + keyName[0] = 0; + + ScanAndProcessKey (&tmpVKeyCode, &keyName[0]); + + if (keyName[0] != 0) + { + currentVKeyCode = tmpVKeyCode; + SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), TRUE); + } + } + return 1; + } + + case WM_COMMAND: + case WM_NOTIFY: + + if (lw == IDC_HOTKEY_KEY && hw == EN_CHANGE) + { + if (!bKeyScanOn && nSelectedHotkeyId < 0 && GetWindowTextLengthW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY))) + SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); + } + + if (msg == WM_NOTIFY && wParam == IDC_HOTKEY_LIST) + { + if (((LPNMHDR) lParam)->code == LVN_ITEMACTIVATE + || ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED)) + { + LVITEM item; + memset(&item,0,sizeof(item)); + nSelectedHotkeyId = ((LPNMLISTVIEW) lParam)->iItem; + SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), GetString ("PRESS_A_KEY_TO_ASSIGN")); + + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), (tmpHotkeys[nSelectedHotkeyId].vKeyCode > 0)); + + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); + bKeyScanOn = TRUE; + return 1; + } + } + + if (lw == IDC_HOTKEY_ASSIGN) + { + BOOL bOwnActiveShortcut = FALSE; + + if (nSelectedHotkeyId >= 0 && currentVKeyCode != 0) + { + UINT modifiers = 0; + if (GetCheckBox (hwndDlg, IDC_HK_MOD_CTRL)) + modifiers = MOD_CONTROL; + + if (GetCheckBox (hwndDlg, IDC_HK_MOD_ALT)) + modifiers |= MOD_ALT; + + if (GetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT)) + modifiers |= MOD_SHIFT; + + if (GetCheckBox (hwndDlg, IDC_HK_MOD_WIN)) + modifiers |= MOD_WIN; + + // Check if it's not already assigned + if (ShortcutInUse (currentVKeyCode, modifiers, tmpHotkeys)) + { + Error ("SHORTCUT_ALREADY_IN_USE"); + return 1; + } + + // Check for reserved system keys + switch (currentVKeyCode) + { + case VK_F1: + case VK_F12: + /* F1 is help and F12 is reserved for use by the debugger at all times */ + if (modifiers == 0) + { + Error ("CANNOT_USE_RESERVED_KEY"); + return 1; + } + break; + } + + bOwnActiveShortcut = ShortcutInUse (currentVKeyCode, modifiers, Hotkeys); + + // Test if the shortcut can be assigned without errors + if (!bOwnActiveShortcut + && !RegisterHotKey (hwndDlg, nSelectedHotkeyId, modifiers, currentVKeyCode)) + { + handleWin32Error(hwndDlg); + return 1; + } + else + { + if (!bOwnActiveShortcut && !UnregisterHotKey (hwndDlg, nSelectedHotkeyId)) + handleWin32Error(hwndDlg); + + tmpHotkeys[nSelectedHotkeyId].vKeyCode = currentVKeyCode; + tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = modifiers; + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); + nSelectedHotkeyId = -1; + bKeyScanOn = FALSE; + } + } + DisplayHotkeyList(hwndDlg); + return 1; + } + + if (lw == IDC_HOTKEY_REMOVE) + { + if (nSelectedHotkeyId >= 0) + { + tmpHotkeys[nSelectedHotkeyId].vKeyCode = 0; + tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = 0; + SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); + nSelectedHotkeyId = -1; + bKeyScanOn = FALSE; + DisplayHotkeyList(hwndDlg); + } + return 1; + } + + if (lw == IDC_RESET_HOTKEYS) + { + int i; + + for (i = 0; i < NBR_HOTKEYS; i++) + { + tmpHotkeys[i].vKeyCode = 0; + tmpHotkeys[i].vKeyModifiers = 0; + } + SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L""); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE); + nSelectedHotkeyId = -1; + bKeyScanOn = FALSE; + DisplayHotkeyList(hwndDlg); + return 1; + } + + if (lw == IDC_DISMOUNT_CONFIRM_PLAY_SOUND) + { + bTPlaySoundOnHotkeyMountDismount = GetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_PLAY_SOUND); + } + + if (lw == IDC_DISMOUNT_CONFIRM_MSG_BOX) + { + bTDisplayMsgBoxOnHotkeyDismount = GetCheckBox (hwndDlg, IDC_DISMOUNT_CONFIRM_MSG_BOX); + } + + if (lw == IDCANCEL || lw == IDCLOSE) + { + KillTimer (hwndDlg, 0xfe); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + if (lw == IDOK) + { + UnregisterAllHotkeys (hwndMainDlg, Hotkeys); + memcpy (Hotkeys, tmpHotkeys, sizeof(Hotkeys)); + RegisterAllHotkeys (hwndMainDlg, Hotkeys); + KillTimer (hwndDlg, 0xfe); + bPlaySoundOnHotkeyMountDismount = bTPlaySoundOnHotkeyMountDismount; + bDisplayMsgBoxOnHotkeyDismount = bTDisplayMsgBoxOnHotkeyDismount; + + SaveSettings (hwndDlg); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + return 0; + + case WM_CLOSE: + + KillTimer (hwndDlg, 0xfe); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + return 0; +} + + diff --git a/Mount/Hotkeys.h b/Mount/Hotkeys.h index 3acbbd7..b3f5254 100644 --- a/Mount/Hotkeys.h +++ b/Mount/Hotkeys.h @@ -1,48 +1,48 @@ -/* - Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -enum -{ - /* When adding/removing hot keys, update the following functions in Mount.c: - DisplayHotkeyList() - SaveSettings() - LoadSettings() - HandleHotKey() */ - - HK_AUTOMOUNT_DEVICES = 0, - HK_CLOSE_SECURITY_TOKEN_SESSIONS, - HK_DISMOUNT_ALL, - HK_DISMOUNT_ALL_AND_WIPE, - HK_FORCE_DISMOUNT_ALL_AND_WIPE, - HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT, - HK_MOUNT_FAVORITE_VOLUMES, - HK_SHOW_HIDE_MAIN_WINDOW, - HK_WIPE_CACHE, - NBR_HOTKEYS -}; - -typedef struct -{ - UINT vKeyCode; - UINT vKeyModifiers; -} TCHOTKEY; - -extern TCHOTKEY Hotkeys [NBR_HOTKEYS]; - -BOOL CALLBACK HotkeysDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -BOOL GetKeyName (UINT vKey, wchar_t *keyName); -void UnregisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]); -BOOL RegisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]); - -#ifdef __cplusplus -} -#endif +/* + Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + /* When adding/removing hot keys, update the following functions in Mount.c: + DisplayHotkeyList() + SaveSettings() + LoadSettings() + HandleHotKey() */ + + HK_AUTOMOUNT_DEVICES = 0, + HK_CLOSE_SECURITY_TOKEN_SESSIONS, + HK_DISMOUNT_ALL, + HK_DISMOUNT_ALL_AND_WIPE, + HK_FORCE_DISMOUNT_ALL_AND_WIPE, + HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT, + HK_MOUNT_FAVORITE_VOLUMES, + HK_SHOW_HIDE_MAIN_WINDOW, + HK_WIPE_CACHE, + NBR_HOTKEYS +}; + +typedef struct +{ + UINT vKeyCode; + UINT vKeyModifiers; +} TCHOTKEY; + +extern TCHOTKEY Hotkeys [NBR_HOTKEYS]; + +BOOL CALLBACK HotkeysDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL GetKeyName (UINT vKey, wchar_t *keyName); +void UnregisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]); +BOOL RegisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[]); + +#ifdef __cplusplus +} +#endif diff --git a/Mount/MainCom.cpp b/Mount/MainCom.cpp index 40cbad0..c25679d 100644 --- a/Mount/MainCom.cpp +++ b/Mount/MainCom.cpp @@ -1,229 +1,244 @@ -/* - Copyright (c) 2007-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include "BaseCom.h" -#include "BootEncryption.h" -#include "Dlgcode.h" -#include "MainCom.h" -#include "MainCom_h.h" -#include "MainCom_i.c" -#include "Mount.h" -#include "Password.h" - -using namespace TrueCrypt; - -static volatile LONG ObjectCount = 0; - -class TrueCryptMainCom : public ITrueCryptMainCom -{ - -public: - TrueCryptMainCom (DWORD messageThreadId) : RefCount (0), MessageThreadId (messageThreadId) - { - InterlockedIncrement (&ObjectCount); - } - - ~TrueCryptMainCom () - { - if (InterlockedDecrement (&ObjectCount) == 0) - PostThreadMessage (MessageThreadId, WM_APP, 0, 0); - } - - virtual ULONG STDMETHODCALLTYPE AddRef () - { - return InterlockedIncrement (&RefCount); - } - - virtual ULONG STDMETHODCALLTYPE Release () - { - if (!InterlockedDecrement (&RefCount)) - { - delete this; - return 0; - } - - return RefCount; - } - - virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) - { - if (riid == IID_IUnknown || riid == IID_ITrueCryptMainCom) - *ppvObject = this; - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - AddRef (); - return S_OK; - } - - virtual int STDMETHODCALLTYPE BackupVolumeHeader (LONG_PTR hwndDlg, BOOL bRequireConfirmation, BSTR lpszVolume) - { - USES_CONVERSION; - MainDlg = (HWND) hwndDlg; - return ::BackupVolumeHeader ((HWND) hwndDlg, bRequireConfirmation, CW2A (lpszVolume)); - } - - virtual int STDMETHODCALLTYPE RestoreVolumeHeader (LONG_PTR hwndDlg, BSTR lpszVolume) - { - USES_CONVERSION; - MainDlg = (HWND) hwndDlg; - return ::RestoreVolumeHeader ((HWND) hwndDlg, CW2A (lpszVolume)); - } - - virtual DWORD STDMETHODCALLTYPE CallDriver (DWORD ioctl, BSTR input, BSTR *output) - { - return BaseCom::CallDriver (ioctl, input, output); - } - - virtual int STDMETHODCALLTYPE ChangePassword (BSTR volumePath, Password *oldPassword, Password *newPassword, int pkcs5, LONG_PTR hWnd) - { - USES_CONVERSION; - MainDlg = (HWND) hWnd; - return ::ChangePwd (CW2A (volumePath), oldPassword, newPassword, pkcs5, (HWND) hWnd); - } - - virtual BOOL STDMETHODCALLTYPE IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) - { - return BaseCom::IsPagingFileActive (checkNonWindowsPartitionsOnly); - } - - virtual DWORD STDMETHODCALLTYPE ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone) - { - return BaseCom::ReadWriteFile (write, device, filePath, bufferBstr, offset, size, sizeDone); - } - - virtual DWORD STDMETHODCALLTYPE RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass) - { - return BaseCom::RegisterFilterDriver (registerDriver, volumeClass); - } - - virtual DWORD STDMETHODCALLTYPE SetDriverServiceStartType (DWORD startType) - { - return BaseCom::SetDriverServiceStartType (startType); - } - - virtual DWORD STDMETHODCALLTYPE WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value) - { - return BaseCom::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value); - } - -protected: - DWORD MessageThreadId; - LONG RefCount; -}; - - -extern "C" BOOL ComServerMain () -{ - SetProcessShutdownParameters (0x100, 0); - - TrueCryptFactory factory (GetCurrentThreadId ()); - DWORD cookie; - - if (IsUacSupported ()) - UacElevated = TRUE; - - if (CoRegisterClassObject (CLSID_TrueCryptMainCom, (LPUNKNOWN) &factory, - CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie) != S_OK) - return FALSE; - - MSG msg; - while (int r = GetMessage (&msg, NULL, 0, 0)) - { - if (r == -1) - return FALSE; - - TranslateMessage (&msg); - DispatchMessage (&msg); - - if (msg.message == WM_APP - && ObjectCount < 1 - && !factory.IsServerLocked ()) - break; - } - CoRevokeClassObject (cookie); - - return TRUE; -} - - -static BOOL ComGetInstance (HWND hWnd, ITrueCryptMainCom **tcServer) -{ - return ComGetInstanceBase (hWnd, CLSID_TrueCryptMainCom, IID_ITrueCryptMainCom, (void **) tcServer); -} - - -ITrueCryptMainCom *GetElevatedInstance (HWND parent) -{ - ITrueCryptMainCom *instance; - - if (!ComGetInstance (parent, &instance)) - throw UserAbort (SRC_POS); - - return instance; -} - - -extern "C" int UacBackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume) -{ - CComPtr tc; - int r; - - CoInitialize (NULL); - - if (ComGetInstance (hwndDlg, &tc)) - r = tc->BackupVolumeHeader ((LONG_PTR) hwndDlg, bRequireConfirmation, CComBSTR (lpszVolume)); - else - r = -1; - - CoUninitialize (); - - return r; -} - - -extern "C" int UacRestoreVolumeHeader (HWND hwndDlg, char *lpszVolume) -{ - CComPtr tc; - int r; - - CoInitialize (NULL); - - if (ComGetInstance (hwndDlg, &tc)) - r = tc->RestoreVolumeHeader ((LONG_PTR) hwndDlg, CComBSTR (lpszVolume)); - else - r = -1; - - CoUninitialize (); - - return r; -} - - -extern "C" int UacChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg) -{ - CComPtr tc; - int r; - - if (ComGetInstance (hwndDlg, &tc)) - { - WaitCursor (); - r = tc->ChangePassword (CComBSTR (lpszVolume), oldPassword, newPassword, pkcs5, (LONG_PTR) hwndDlg); - NormalCursor (); - } - else - r = -1; - - return r; -} +/* + Copyright (c) 2007-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include "BaseCom.h" +#include "BootEncryption.h" +#include "Dlgcode.h" +#include "MainCom.h" +#include "MainCom_h.h" +#include "MainCom_i.c" +#include "Mount.h" +#include "Password.h" + +using namespace TrueCrypt; + +static volatile LONG ObjectCount = 0; + +class TrueCryptMainCom : public ITrueCryptMainCom +{ + +public: + TrueCryptMainCom (DWORD messageThreadId) : RefCount (0), MessageThreadId (messageThreadId) + { + InterlockedIncrement (&ObjectCount); + } + + ~TrueCryptMainCom () + { + if (InterlockedDecrement (&ObjectCount) == 0) + PostThreadMessage (MessageThreadId, WM_APP, 0, 0); + } + + virtual ULONG STDMETHODCALLTYPE AddRef () + { + return InterlockedIncrement (&RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release () + { + if (!InterlockedDecrement (&RefCount)) + { + delete this; + return 0; + } + + return RefCount; + } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) + { + if (riid == IID_IUnknown || riid == IID_ITrueCryptMainCom) + *ppvObject = this; + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + AddRef (); + return S_OK; + } + + virtual int STDMETHODCALLTYPE BackupVolumeHeader (LONG_PTR hwndDlg, BOOL bRequireConfirmation, BSTR lpszVolume) + { + USES_CONVERSION; + MainDlg = (HWND) hwndDlg; + return ::BackupVolumeHeader ((HWND) hwndDlg, bRequireConfirmation, CW2A (lpszVolume)); + } + + virtual int STDMETHODCALLTYPE RestoreVolumeHeader (LONG_PTR hwndDlg, BSTR lpszVolume) + { + USES_CONVERSION; + MainDlg = (HWND) hwndDlg; + return ::RestoreVolumeHeader ((HWND) hwndDlg, CW2A (lpszVolume)); + } + + virtual DWORD STDMETHODCALLTYPE CallDriver (DWORD ioctl, BSTR input, BSTR *output) + { + return BaseCom::CallDriver (ioctl, input, output); + } + + virtual int STDMETHODCALLTYPE ChangePassword (BSTR volumePath, Password *oldPassword, Password *newPassword, int pkcs5, LONG_PTR hWnd) + { + USES_CONVERSION; + MainDlg = (HWND) hWnd; + return ::ChangePwd (CW2A (volumePath), oldPassword, newPassword, pkcs5, (HWND) hWnd); + } + + virtual DWORD STDMETHODCALLTYPE CopyFile (BSTR sourceFile, BSTR destinationFile) + { + return BaseCom::CopyFile (sourceFile, destinationFile); + } + + virtual DWORD STDMETHODCALLTYPE DeleteFile (BSTR file) + { + return BaseCom::DeleteFile (file); + } + + virtual BOOL STDMETHODCALLTYPE IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) + { + return BaseCom::IsPagingFileActive (checkNonWindowsPartitionsOnly); + } + + virtual DWORD STDMETHODCALLTYPE ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone) + { + return BaseCom::ReadWriteFile (write, device, filePath, bufferBstr, offset, size, sizeDone); + } + + virtual DWORD STDMETHODCALLTYPE RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass) + { + return BaseCom::RegisterFilterDriver (registerDriver, volumeClass); + } + + virtual DWORD STDMETHODCALLTYPE RegisterSystemFavoritesService (BOOL registerService) + { + return BaseCom::RegisterSystemFavoritesService (registerService); + } + + virtual DWORD STDMETHODCALLTYPE SetDriverServiceStartType (DWORD startType) + { + return BaseCom::SetDriverServiceStartType (startType); + } + + virtual DWORD STDMETHODCALLTYPE WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value) + { + return BaseCom::WriteLocalMachineRegistryDwordValue (keyPath, valueName, value); + } + +protected: + DWORD MessageThreadId; + LONG RefCount; +}; + + +extern "C" BOOL ComServerMain () +{ + SetProcessShutdownParameters (0x100, 0); + + TrueCryptFactory factory (GetCurrentThreadId ()); + DWORD cookie; + + if (IsUacSupported ()) + UacElevated = TRUE; + + if (CoRegisterClassObject (CLSID_TrueCryptMainCom, (LPUNKNOWN) &factory, + CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie) != S_OK) + return FALSE; + + MSG msg; + while (int r = GetMessage (&msg, NULL, 0, 0)) + { + if (r == -1) + return FALSE; + + TranslateMessage (&msg); + DispatchMessage (&msg); + + if (msg.message == WM_APP + && ObjectCount < 1 + && !factory.IsServerLocked ()) + break; + } + CoRevokeClassObject (cookie); + + return TRUE; +} + + +static BOOL ComGetInstance (HWND hWnd, ITrueCryptMainCom **tcServer) +{ + return ComGetInstanceBase (hWnd, CLSID_TrueCryptMainCom, IID_ITrueCryptMainCom, (void **) tcServer); +} + + +ITrueCryptMainCom *GetElevatedInstance (HWND parent) +{ + ITrueCryptMainCom *instance; + + if (!ComGetInstance (parent, &instance)) + throw UserAbort (SRC_POS); + + return instance; +} + + +extern "C" int UacBackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume) +{ + CComPtr tc; + int r; + + CoInitialize (NULL); + + if (ComGetInstance (hwndDlg, &tc)) + r = tc->BackupVolumeHeader ((LONG_PTR) hwndDlg, bRequireConfirmation, CComBSTR (lpszVolume)); + else + r = -1; + + CoUninitialize (); + + return r; +} + + +extern "C" int UacRestoreVolumeHeader (HWND hwndDlg, char *lpszVolume) +{ + CComPtr tc; + int r; + + CoInitialize (NULL); + + if (ComGetInstance (hwndDlg, &tc)) + r = tc->RestoreVolumeHeader ((LONG_PTR) hwndDlg, CComBSTR (lpszVolume)); + else + r = -1; + + CoUninitialize (); + + return r; +} + + +extern "C" int UacChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg) +{ + CComPtr tc; + int r; + + if (ComGetInstance (hwndDlg, &tc)) + { + WaitCursor (); + r = tc->ChangePassword (CComBSTR (lpszVolume), oldPassword, newPassword, pkcs5, (LONG_PTR) hwndDlg); + NormalCursor (); + } + else + r = -1; + + return r; +} diff --git a/Mount/MainCom.h b/Mount/MainCom.h index 7dd3d05..e5dbe93 100644 --- a/Mount/MainCom.h +++ b/Mount/MainCom.h @@ -1,31 +1,31 @@ -/* - Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_MAIN_COM -#define TC_HEADER_MAIN_COM - -#include - -#ifdef __cplusplus - -#include "MainCom_h.h" -ITrueCryptMainCom *GetElevatedInstance (HWND parent); - -extern "C" { -#endif - -BOOL ComServerMain (); -int UacBackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume); -int UacRestoreVolumeHeader (HWND hwndDlg, char *lpszVolume); -int UacChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg); - -#ifdef __cplusplus -} -#endif - -#endif // TC_HEADER_MAIN_COM +/* + Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_MAIN_COM +#define TC_HEADER_MAIN_COM + +#include + +#ifdef __cplusplus + +#include "MainCom_h.h" +ITrueCryptMainCom *GetElevatedInstance (HWND parent); + +extern "C" { +#endif + +BOOL ComServerMain (); +int UacBackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume); +int UacRestoreVolumeHeader (HWND hwndDlg, char *lpszVolume); +int UacChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg); + +#ifdef __cplusplus +} +#endif + +#endif // TC_HEADER_MAIN_COM diff --git a/Mount/MainCom.idl b/Mount/MainCom.idl index 1722bcb..db3b3eb 100644 --- a/Mount/MainCom.idl +++ b/Mount/MainCom.idl @@ -1,7 +1,7 @@ /* - Copyright (c) 2007-2008 TrueCrypt Foundation. All rights reserved. + Copyright (c) 2007-2009 TrueCrypt Foundation. All rights reserved. - Governed by the TrueCrypt License 2.7 the full text of which is contained + Governed by the TrueCrypt License 2.8 the full text of which is contained in the file License.txt included in TrueCrypt binary and source code distribution packages. */ @@ -12,7 +12,7 @@ import "..\Common\Password.h"; [ uuid(1770F56C-7881-4591-A179-79B8001C7D42), helpstring("TrueCrypt Main UAC Support Library"), - version(2.2) + version(2.3) ] library TrueCryptMainCom { @@ -27,9 +27,12 @@ library TrueCryptMainCom int BackupVolumeHeader (LONG_PTR hwndDlg, BOOL bRequireConfirmation, BSTR lpszVolume); DWORD CallDriver (DWORD ioctl, BSTR input, BSTR *output); int ChangePassword (BSTR volumePath, Password *oldPassword, Password *newPassword, int pkcs5, LONG_PTR hWnd); + DWORD CopyFile (BSTR sourceFile, BSTR destinationFile); + DWORD DeleteFile (BSTR file); BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly); DWORD ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *bufferBstr, unsigned __int64 offset, unsigned __int32 size, DWORD *sizeDone); DWORD RegisterFilterDriver (BOOL registerDriver, BOOL volumeClass); + DWORD RegisterSystemFavoritesService (BOOL registerService); int RestoreVolumeHeader (LONG_PTR hwndDlg, BSTR lpszVolume); DWORD SetDriverServiceStartType (DWORD startType); DWORD WriteLocalMachineRegistryDwordValue (BSTR keyPath, BSTR valueName, DWORD value); diff --git a/Mount/Mount.c b/Mount/Mount.c index d19e3db..ff89f2e 100644 --- a/Mount/Mount.c +++ b/Mount/Mount.c @@ -1,7728 +1,8082 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#include "Tcdefs.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "Apidrvr.h" -#include "BootEncryption.h" -#include "Cmdline.h" -#include "Crypto.h" -#include "Dlgcode.h" -#include "Combo.h" -#include "Hotkeys.h" -#include "Keyfiles.h" -#include "Language.h" -#include "MainCom.h" -#include "Mount.h" -#include "Pkcs5.h" -#include "Random.h" -#include "Registry.h" -#include "Resource.h" -#include "Password.h" -#include "Xml.h" -#include "../Boot/Windows/BootCommon.h" -#include "../Common/Dictionary.h" -#include "../Common/Common.h" -#include "../Common/Resource.h" -#include "../Common/SecurityToken.h" -#include "../Platform/Finally.h" -#include "../Platform/ForEach.h" - -using namespace TrueCrypt; - -enum timer_ids -{ - TIMER_ID_MAIN = 0xff, - TIMER_ID_KEYB_LAYOUT_GUARD -}; - -enum hidden_os_read_only_notif_mode -{ - TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE = 0, - TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_COMPACT, - TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_DISABLED -}; - -#define TIMER_INTERVAL_MAIN 500 -#define TIMER_INTERVAL_KEYB_LAYOUT_GUARD 10 - -BootEncryption *BootEncObj = NULL; -BootEncryptionStatus BootEncStatus; -BootEncryptionStatus RecentBootEncStatus; - -BOOL bExplore = FALSE; /* Display explorer window after mount */ -BOOL bBeep = FALSE; /* Donot beep after mount */ -char szFileName[TC_MAX_PATH+1]; /* Volume to mount */ -char szDriveLetter[3]; /* Drive Letter to mount */ -char commandLineDrive = 0; -BOOL bCacheInDriver = FALSE; /* Cache any passwords we see */ -BOOL bCacheInDriverDefault = FALSE; -BOOL bHistoryCmdLine = FALSE; /* History control is always disabled */ -BOOL bCloseDismountedWindows=TRUE; /* Close all open explorer windows of dismounted volume */ -BOOL bWipeCacheOnExit = FALSE; /* Wipe password from chace on exit */ -BOOL bWipeCacheOnAutoDismount = TRUE; -BOOL bEnableBkgTask = FALSE; -BOOL bCloseBkgTaskWhenNoVolumes = FALSE; -BOOL bDismountOnLogOff = TRUE; -BOOL bDismountOnScreenSaver = TRUE; -BOOL bDismountOnPowerSaving = FALSE; -BOOL bForceAutoDismount = TRUE; -BOOL bForceMount = FALSE; /* Mount volume even if host file/device already in use */ -BOOL bForceUnmount = FALSE; /* Unmount volume even if it cannot be locked */ -BOOL bWipe = FALSE; /* Wipe driver passwords */ -BOOL bAuto = FALSE; /* Do everything without user input */ -BOOL bAutoMountDevices = FALSE; /* Auto-mount devices */ -BOOL bAutoMountFavorites = FALSE; -BOOL bPlaySoundOnHotkeyMountDismount = TRUE; -BOOL bDisplayMsgBoxOnHotkeyDismount = FALSE; -BOOL bHibernationPreventionNotified = FALSE; /* TRUE if the user has been notified that hibernation was prevented (system encryption) during the session. */ -BOOL bHiddenSysLeakProtNotifiedDuringSession = FALSE; /* TRUE if the user has been notified during the session that unencrypted filesystems and non-hidden TrueCrypt volumes are mounted as read-only under hidden OS. */ -BOOL CloseSecurityTokenSessionsAfterMount = FALSE; - -BOOL MultipleMountOperationInProgress = FALSE; - -BOOL Quit = FALSE; /* Exit after processing command line */ -BOOL ComServerMode = FALSE; -BOOL UsePreferences = TRUE; - -int HiddenSysLeakProtectionNotificationStatus = TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE; -int MaxVolumeIdleTime = -120; -int nCurrentShowType = 0; /* current display mode, mount, unmount etc */ -int nSelectedDriveIndex = -1; /* Item number of selected drive */ - -int cmdUnmountDrive = 0; /* Volume drive letter to unmount (-1 = all) */ -Password VolumePassword; /* Password used for mounting volumes */ -Password CmdVolumePassword; /* Password passed from command line */ -BOOL CmdVolumePasswordValid = FALSE; -MountOptions mountOptions; -MountOptions defaultMountOptions; -KeyFile *FirstCmdKeyFile; - -HBITMAP hbmLogoBitmapRescaled = NULL; -char OrigKeyboardLayout [8+1] = "00000409"; -BOOL bKeyboardLayoutChanged = FALSE; /* TRUE if the keyboard layout was changed to the standard US keyboard layout (from any other layout). */ -BOOL bKeybLayoutAltKeyWarningShown = FALSE; /* TRUE if the user has been informed that it is not possible to type characters by pressing keys while the right Alt key is held down. */ - -static KeyFilesDlgParam hidVolProtKeyFilesParam; - -static MOUNT_LIST_STRUCT LastKnownMountList; -VOLUME_NOTIFICATIONS_LIST VolumeNotificationsList; -static DWORD LastKnownLogicalDrives; - -static HANDLE TaskBarIconMutex = NULL; -static BOOL MainWindowHidden = FALSE; -static int pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; -static int bSysEncPwdChangeDlgMode = FALSE; -static int bPrebootPasswordDlgMode = FALSE; -static int NoCmdLineArgs; -static BOOL CmdLineVolumeSpecified; - -static void localcleanup (void) -{ - // Wipe command line - char *c = GetCommandLineA (); - wchar_t *wc = GetCommandLineW (); - burn(c, strlen (c)); - burn(wc, wcslen (wc) * sizeof (wchar_t)); - - /* Delete buffered bitmaps (if any) */ - if (hbmLogoBitmapRescaled != NULL) - { - DeleteObject ((HGDIOBJ) hbmLogoBitmapRescaled); - hbmLogoBitmapRescaled = NULL; - } - - /* These items should have already been cleared by the functions that used them, but we're going to - clear them for extra security. */ - burn (&VolumePassword, sizeof (VolumePassword)); - burn (&CmdVolumePassword, sizeof (CmdVolumePassword)); - burn (&mountOptions, sizeof (mountOptions)); - burn (&defaultMountOptions, sizeof (defaultMountOptions)); - burn (&szFileName, sizeof(szFileName)); - - /* Cleanup common code resources */ - cleanup (); - - if (BootEncObj != NULL) - { - delete BootEncObj; - BootEncObj = NULL; - } - - RandStop (TRUE); -} - -void RefreshMainDlg (HWND hwndDlg) -{ - int drive = (char) (HIWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)))); - - MoveEditToCombo (GetDlgItem (hwndDlg, IDC_VOLUME), bHistory); - LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), drive); - EnableDisableButtons (hwndDlg); -} - -void EndMainDlg (HWND hwndDlg) -{ - MoveEditToCombo (GetDlgItem (hwndDlg, IDC_VOLUME), bHistory); - - if (UsePreferences) - SaveSettings (hwndDlg); - - if (bWipeCacheOnExit) - { - DWORD dwResult; - DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - } - - if (!bHistory) - { - SetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), ""); - ClearHistory (GetDlgItem (hwndDlg, IDC_VOLUME)); - } - - if (TaskBarIconMutex != NULL) - { - MainWindowHidden = TRUE; - ShowWindow (hwndDlg, SW_HIDE); - } - else - { - TaskBarIconRemove (hwndDlg); - EndDialog (hwndDlg, 0); - } -} - -static void InitMainDialog (HWND hwndDlg) -{ - MENUITEMINFOW info; - char *popupTexts[] = {"MENU_VOLUMES", "MENU_SYSTEM_ENCRYPTION", "MENU_KEYFILES", "MENU_TOOLS", "MENU_SETTINGS", "MENU_HELP", "MENU_WEBSITE", 0}; - wchar_t *str; - int i; - - /* Call the common dialog init code */ - InitDialog (hwndDlg); - LocalizeDialog (hwndDlg, NULL); - - DragAcceptFiles (hwndDlg, TRUE); - - SendMessage (GetDlgItem (hwndDlg, IDC_VOLUME), CB_LIMITTEXT, TC_MAX_PATH, 0); - SetWindowTextW (hwndDlg, lpszTitle); - - // Help file name - InitHelpFileName(); - - // Localize menu strings - for (i = 40001; str = (wchar_t *)GetDictionaryValueByInt (i); i++) - { - info.cbSize = sizeof (info); - info.fMask = MIIM_TYPE; - info.fType = MFT_STRING; - info.dwTypeData = str; - info.cch = wcslen (str); - - SetMenuItemInfoW (GetMenu (hwndDlg), i, FALSE, &info); - } - - for (i = 0; popupTexts[i] != 0; i++) - { - str = GetString (popupTexts[i]); - - info.cbSize = sizeof (info); - info.fMask = MIIM_TYPE; - - if (memcmp (popupTexts[i], "MENU_WEBSITE", 6) == 0) - info.fType = MFT_STRING | MFT_RIGHTJUSTIFY; - else - info.fType = MFT_STRING; - - info.dwTypeData = str; - info.cch = wcslen (str); - - SetMenuItemInfoW (GetMenu (hwndDlg), i, TRUE, &info); - } - - // Resize the logo bitmap if the user has a non-default DPI - if (ScreenDPI != USER_DEFAULT_SCREEN_DPI - && hbmLogoBitmapRescaled == NULL) // If not re-called (e.g. after language pack change) - { - hbmLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_LOGO_288DPI), - GetDlgItem (hwndDlg, IDC_LOGO), - 0, 0, 0, 0, FALSE, TRUE); - } - - BuildTree (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - - if (*szDriveLetter != 0) - { - SelectItem (GetDlgItem (hwndDlg, IDC_DRIVELIST), *szDriveLetter); - - if(nSelectedDriveIndex > SendMessage (GetDlgItem (hwndDlg, IDC_DRIVELIST), LVM_GETITEMCOUNT, 0, 0)/2) - SendMessage(GetDlgItem (hwndDlg, IDC_DRIVELIST), LVM_SCROLL, 0, 1000); - } - - SendMessage (GetDlgItem (hwndDlg, IDC_NO_HISTORY), BM_SETCHECK, bHistory ? BST_UNCHECKED : BST_CHECKED, 0); - EnableDisableButtons (hwndDlg); -} - -void EnableDisableButtons (HWND hwndDlg) -{ - HWND hOKButton = GetDlgItem (hwndDlg, IDOK); - WORD x; - - x = LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))); - - EnableMenuItem (GetMenu (hwndDlg), IDM_MOUNT_VOLUME, MF_ENABLED); - EnableMenuItem (GetMenu (hwndDlg), IDM_MOUNT_VOLUME_OPTIONS, MF_ENABLED); - EnableMenuItem (GetMenu (hwndDlg), IDM_BACKUP_VOL_HEADER, MF_ENABLED); - EnableMenuItem (GetMenu (hwndDlg), IDM_RESTORE_VOL_HEADER, MF_ENABLED); - EnableMenuItem (GetMenu (hwndDlg), IDM_CHANGE_PASSWORD, MF_ENABLED); - EnableWindow (hOKButton, TRUE); - - switch (x) - { - case TC_MLIST_ITEM_NONSYS_VOL: - { - SetWindowTextW (hOKButton, GetString ("UNMOUNT_BUTTON")); - EnableWindow (hOKButton, TRUE); - EnableMenuItem (GetMenu (hwndDlg), IDM_UNMOUNT_VOLUME, MF_ENABLED); - - EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES), TRUE); - EnableMenuItem (GetMenu (hwndDlg), IDM_VOLUME_PROPERTIES, MF_ENABLED); - } - break; - - case TC_MLIST_ITEM_SYS_PARTITION: - case TC_MLIST_ITEM_SYS_DRIVE: - EnableWindow (hOKButton, FALSE); - SetWindowTextW (hOKButton, GetString ("MOUNT_BUTTON")); - EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES), TRUE); - EnableMenuItem (GetMenu (hwndDlg), IDM_UNMOUNT_VOLUME, MF_GRAYED); - break; - - case TC_MLIST_ITEM_FREE: - default: - SetWindowTextW (hOKButton, GetString ("MOUNT_BUTTON")); - EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES), FALSE); - EnableMenuItem (GetMenu (hwndDlg), IDM_VOLUME_PROPERTIES, MF_GRAYED); - EnableMenuItem (GetMenu (hwndDlg), IDM_UNMOUNT_VOLUME, MF_GRAYED); - } - - EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_CACHE), !IsPasswordCacheEmpty()); - EnableMenuItem (GetMenu (hwndDlg), IDM_WIPE_CACHE, IsPasswordCacheEmpty() ? MF_GRAYED:MF_ENABLED); - EnableMenuItem (GetMenu (hwndDlg), IDM_CLEAR_HISTORY, IsComboEmpty (GetDlgItem (hwndDlg, IDC_VOLUME)) ? MF_GRAYED:MF_ENABLED); -} - -BOOL VolumeSelected (HWND hwndDlg) -{ - return (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_VOLUME)) > 0); -} - -/* Returns TRUE if the last partition/drive selected via the Select Device dialog box was the system -partition/drive and if it is encrypted. - WARNING: This function is very fast but not always reliable (for example, if the user manually types - a device path before Select Device is invoked during the session; after the Select Device dialog - has been invoked at least once, the correct system device paths are cached). Therefore, it must NOT - be used before performing any dangerous operations (such as header backup restore or formatting a - supposedly non-system device) -- instead use IsSystemDevicePath(path, hwndDlg, TRUE) for such - purposes. This function can be used only for preliminary GUI checks requiring very fast responses. */ -BOOL ActiveSysEncDeviceSelected (void) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - - if (BootEncStatus.DriveEncrypted) - { - int retCode = 0; - - GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szFileName, sizeof (szFileName)); - - retCode = IsSystemDevicePath (szFileName, MainDlg, FALSE); - - return (WholeSysDriveEncryption(FALSE) ? (retCode == 2 || retCode == 1) : (retCode == 1)); - } - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - return FALSE; -} - -void LoadSettings (HWND hwndDlg) -{ - WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; - - LoadSysEncSettings (hwndDlg); - - if (LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) != 0) - bInPlaceEncNonSysPending = TRUE; - - // If the config file has already been loaded during this session - if (ConfigBuffer != NULL) - { - free (ConfigBuffer); - ConfigBuffer = NULL; - } - - // Options - bExplore = ConfigReadInt ("OpenExplorerWindowAfterMount", FALSE); - bCloseDismountedWindows = ConfigReadInt ("CloseExplorerWindowsOnDismount", TRUE); - - bHistory = ConfigReadInt ("SaveVolumeHistory", FALSE); - - bCacheInDriverDefault = bCacheInDriver = ConfigReadInt ("CachePasswords", FALSE); - bWipeCacheOnExit = ConfigReadInt ("WipePasswordCacheOnExit", FALSE); - bWipeCacheOnAutoDismount = ConfigReadInt ("WipeCacheOnAutoDismount", TRUE); - - bStartOnLogon = ConfigReadInt ("StartOnLogon", FALSE); - bMountDevicesOnLogon = ConfigReadInt ("MountDevicesOnLogon", FALSE); - bMountFavoritesOnLogon = ConfigReadInt ("MountFavoritesOnLogon", FALSE); - - bEnableBkgTask = ConfigReadInt ("EnableBackgroundTask", TRUE); - bCloseBkgTaskWhenNoVolumes = ConfigReadInt ("CloseBackgroundTaskOnNoVolumes", FALSE); - - bDismountOnLogOff = ConfigReadInt ("DismountOnLogOff", TRUE); - bDismountOnPowerSaving = ConfigReadInt ("DismountOnPowerSaving", FALSE); - bDismountOnScreenSaver = ConfigReadInt ("DismountOnScreenSaver", FALSE); - bForceAutoDismount = ConfigReadInt ("ForceAutoDismount", TRUE); - MaxVolumeIdleTime = ConfigReadInt ("MaxVolumeIdleTime", -60); - - HiddenSectorDetectionStatus = ConfigReadInt ("HiddenSectorDetectionStatus", 0); - - defaultKeyFilesParam.EnableKeyFiles = ConfigReadInt ("UseKeyfiles", FALSE); - - bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = ConfigReadInt ("PreserveTimestamps", TRUE); - defaultMountOptions.Removable = ConfigReadInt ("MountVolumesRemovable", FALSE); - defaultMountOptions.ReadOnly = ConfigReadInt ("MountVolumesReadOnly", FALSE); - defaultMountOptions.ProtectHiddenVolume = FALSE; - defaultMountOptions.PartitionInInactiveSysEncScope = FALSE; - defaultMountOptions.RecoveryMode = FALSE; - defaultMountOptions.UseBackupHeader = FALSE; - - mountOptions = defaultMountOptions; - - CloseSecurityTokenSessionsAfterMount = ConfigReadInt ("CloseSecurityTokenSessionsAfterMount", 0); - - if (IsHiddenOSRunning()) - HiddenSysLeakProtectionNotificationStatus = ConfigReadInt ("HiddenSystemLeakProtNotifStatus", TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE); - - // Drive letter - command line arg overrides registry - if (szDriveLetter[0] == 0) - ConfigReadString ("LastSelectedDrive", "", szDriveLetter, sizeof (szDriveLetter)); - - ConfigReadString ("SecurityTokenLibrary", "", SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath) - 1); - if (SecurityTokenLibraryPath[0]) - InitSecurityTokenLibrary(); - - // Hotkeys - bPlaySoundOnHotkeyMountDismount = ConfigReadInt ("PlaySoundOnHotkeyMountDismount", TRUE); - bDisplayMsgBoxOnHotkeyDismount = ConfigReadInt ("DisplayMsgBoxOnHotkeyDismount", FALSE); - Hotkeys [HK_AUTOMOUNT_DEVICES].vKeyModifiers = ConfigReadInt ("HotkeyModAutoMountDevices", 0); - Hotkeys [HK_AUTOMOUNT_DEVICES].vKeyCode = ConfigReadInt ("HotkeyCodeAutoMountDevices", 0); - Hotkeys [HK_DISMOUNT_ALL].vKeyModifiers = ConfigReadInt ("HotkeyModDismountAll", 0); - Hotkeys [HK_DISMOUNT_ALL].vKeyCode = ConfigReadInt ("HotkeyCodeDismountAll", 0); - Hotkeys [HK_WIPE_CACHE].vKeyModifiers = ConfigReadInt ("HotkeyModWipeCache", 0); - Hotkeys [HK_WIPE_CACHE].vKeyCode = ConfigReadInt ("HotkeyCodeWipeCache", 0); - Hotkeys [HK_DISMOUNT_ALL_AND_WIPE].vKeyModifiers = ConfigReadInt ("HotkeyModDismountAllWipe", 0); - Hotkeys [HK_DISMOUNT_ALL_AND_WIPE].vKeyCode = ConfigReadInt ("HotkeyCodeDismountAllWipe", 0); - Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyModifiers = ConfigReadInt ("HotkeyModForceDismountAllWipe", 0); - Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyCode = ConfigReadInt ("HotkeyCodeForceDismountAllWipe", 0); - Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyModifiers = ConfigReadInt ("HotkeyModForceDismountAllWipeExit", 0); - Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyCode = ConfigReadInt ("HotkeyCodeForceDismountAllWipeExit", 0); - Hotkeys [HK_MOUNT_FAVORITE_VOLUMES].vKeyModifiers = ConfigReadInt ("HotkeyModMountFavoriteVolumes", 0); - Hotkeys [HK_MOUNT_FAVORITE_VOLUMES].vKeyCode = ConfigReadInt ("HotkeyCodeMountFavoriteVolumes", 0); - Hotkeys [HK_SHOW_HIDE_MAIN_WINDOW].vKeyModifiers = ConfigReadInt ("HotkeyModShowHideMainWindow", 0); - Hotkeys [HK_SHOW_HIDE_MAIN_WINDOW].vKeyCode = ConfigReadInt ("HotkeyCodeShowHideMainWindow", 0); - Hotkeys [HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyModifiers = ConfigReadInt ("HotkeyModCloseSecurityTokenSessions", 0); - Hotkeys [HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyCode = ConfigReadInt ("HotkeyCodeCloseSecurityTokenSessions", 0); - - // History - if (bHistoryCmdLine != TRUE) - { - LoadCombo (GetDlgItem (hwndDlg, IDC_VOLUME)); - if (CmdLineVolumeSpecified) - SetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName); - } -} - -void SaveSettings (HWND hwndDlg) -{ - WaitCursor (); - - char szTmp[32] = {0}; - LPARAM lLetter; - - // Options - ConfigWriteBegin (); - - ConfigWriteInt ("OpenExplorerWindowAfterMount", bExplore); - ConfigWriteInt ("CloseExplorerWindowsOnDismount", bCloseDismountedWindows); - ConfigWriteInt ("SaveVolumeHistory", !IsButtonChecked (GetDlgItem (hwndDlg, IDC_NO_HISTORY))); - - ConfigWriteInt ("CachePasswords", bCacheInDriverDefault); - ConfigWriteInt ("WipePasswordCacheOnExit", bWipeCacheOnExit); - ConfigWriteInt ("WipeCacheOnAutoDismount", bWipeCacheOnAutoDismount); - - ConfigWriteInt ("StartOnLogon", bStartOnLogon); - ConfigWriteInt ("MountDevicesOnLogon", bMountDevicesOnLogon); - ConfigWriteInt ("MountFavoritesOnLogon", bMountFavoritesOnLogon); - - ConfigWriteInt ("MountVolumesReadOnly", defaultMountOptions.ReadOnly); - ConfigWriteInt ("MountVolumesRemovable", defaultMountOptions.Removable); - ConfigWriteInt ("PreserveTimestamps", defaultMountOptions.PreserveTimestamp); - - ConfigWriteInt ("EnableBackgroundTask", bEnableBkgTask); - ConfigWriteInt ("CloseBackgroundTaskOnNoVolumes", bCloseBkgTaskWhenNoVolumes); - - ConfigWriteInt ("DismountOnLogOff", bDismountOnLogOff); - ConfigWriteInt ("DismountOnPowerSaving", bDismountOnPowerSaving); - ConfigWriteInt ("DismountOnScreenSaver", bDismountOnScreenSaver); - ConfigWriteInt ("ForceAutoDismount", bForceAutoDismount); - ConfigWriteInt ("MaxVolumeIdleTime", MaxVolumeIdleTime); - - ConfigWriteInt ("HiddenSectorDetectionStatus", HiddenSectorDetectionStatus); - - ConfigWriteInt ("UseKeyfiles", defaultKeyFilesParam.EnableKeyFiles); - - if (IsHiddenOSRunning()) - ConfigWriteInt ("HiddenSystemLeakProtNotifStatus", HiddenSysLeakProtectionNotificationStatus); - - // Drive Letter - lLetter = GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - if (LOWORD (lLetter) != 0xffff) - sprintf (szTmp, "%c:", (char) HIWORD (lLetter)); - ConfigWriteString ("LastSelectedDrive", szTmp); - - ConfigWriteInt ("CloseSecurityTokenSessionsAfterMount", CloseSecurityTokenSessionsAfterMount); - - // Hotkeys - ConfigWriteInt ("HotkeyModAutoMountDevices", Hotkeys[HK_AUTOMOUNT_DEVICES].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeAutoMountDevices", Hotkeys[HK_AUTOMOUNT_DEVICES].vKeyCode); - ConfigWriteInt ("HotkeyModDismountAll", Hotkeys[HK_DISMOUNT_ALL].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeDismountAll", Hotkeys[HK_DISMOUNT_ALL].vKeyCode); - ConfigWriteInt ("HotkeyModWipeCache", Hotkeys[HK_WIPE_CACHE].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeWipeCache", Hotkeys[HK_WIPE_CACHE].vKeyCode); - ConfigWriteInt ("HotkeyModDismountAllWipe", Hotkeys[HK_DISMOUNT_ALL_AND_WIPE].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeDismountAllWipe", Hotkeys[HK_DISMOUNT_ALL_AND_WIPE].vKeyCode); - ConfigWriteInt ("HotkeyModForceDismountAllWipe", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeForceDismountAllWipe", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyCode); - ConfigWriteInt ("HotkeyModForceDismountAllWipeExit", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeForceDismountAllWipeExit", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyCode); - ConfigWriteInt ("HotkeyModMountFavoriteVolumes", Hotkeys[HK_MOUNT_FAVORITE_VOLUMES].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeMountFavoriteVolumes", Hotkeys[HK_MOUNT_FAVORITE_VOLUMES].vKeyCode); - ConfigWriteInt ("HotkeyModShowHideMainWindow", Hotkeys[HK_SHOW_HIDE_MAIN_WINDOW].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeShowHideMainWindow", Hotkeys[HK_SHOW_HIDE_MAIN_WINDOW].vKeyCode); - ConfigWriteInt ("HotkeyModCloseSecurityTokenSessions", Hotkeys[HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyModifiers); - ConfigWriteInt ("HotkeyCodeCloseSecurityTokenSessions", Hotkeys[HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyCode); - ConfigWriteInt ("PlaySoundOnHotkeyMountDismount", bPlaySoundOnHotkeyMountDismount); - ConfigWriteInt ("DisplayMsgBoxOnHotkeyDismount", bDisplayMsgBoxOnHotkeyDismount); - - // Language - if (GetPreferredLangId () != NULL) - ConfigWriteString ("Language", GetPreferredLangId ()); - - // PKCS#11 Library Path - ConfigWriteString ("SecurityTokenLibrary", SecurityTokenLibraryPath[0] ? SecurityTokenLibraryPath : ""); - - ConfigWriteEnd (); - - // History - DumpCombo (GetDlgItem (hwndDlg, IDC_VOLUME), IsButtonChecked (GetDlgItem (hwndDlg, IDC_NO_HISTORY))); - - NormalCursor (); -} - -// Returns TRUE if system encryption or decryption had been or is in progress and has not been completed -static BOOL SysEncryptionOrDecryptionRequired (void) -{ - /* If you update this function, revise SysEncryptionOrDecryptionRequired() in Tcformat.c as well. */ - - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - return (SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING - || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING - || - ( - BootEncStatus.DriveMounted - && - ( - BootEncStatus.ConfiguredEncryptedAreaStart != BootEncStatus.EncryptedAreaStart - || BootEncStatus.ConfiguredEncryptedAreaEnd != BootEncStatus.EncryptedAreaEnd - ) - ) - ); -} - -// Returns TRUE if the system partition/drive is completely encrypted -static BOOL SysDriveOrPartitionFullyEncrypted (BOOL bSilent) -{ - /* If you update this function, revise SysDriveOrPartitionFullyEncrypted() in Tcformat.c as well. */ - - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - if (!bSilent) - e.Show (MainDlg); - } - - return (!BootEncStatus.SetupInProgress - && BootEncStatus.ConfiguredEncryptedAreaEnd != 0 - && BootEncStatus.ConfiguredEncryptedAreaEnd != -1 - && BootEncStatus.ConfiguredEncryptedAreaStart == BootEncStatus.EncryptedAreaStart - && BootEncStatus.ConfiguredEncryptedAreaEnd == BootEncStatus.EncryptedAreaEnd); -} - -// Returns TRUE if the system partition/drive is being filtered by the TrueCrypt driver and the key data -// was successfully decrypted (the device is fully ready to be encrypted or decrypted). Note that this -// function does not examine whether the system device is encrypted or not (or to what extent). -static BOOL SysEncDeviceActive (BOOL bSilent) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - if (!bSilent) - e.Show (MainDlg); - - return FALSE; - } - - return (BootEncStatus.DriveMounted); -} - -// Returns TRUE if the entire system drive (as opposed to the system partition only) is (or is to be) encrypted -BOOL WholeSysDriveEncryption (BOOL bSilent) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - - return (BootEncStatus.ConfiguredEncryptedAreaStart == TC_BOOT_LOADER_AREA_SIZE - && BootEncStatus.ConfiguredEncryptedAreaEnd >= BootEncStatus.BootDriveLength.QuadPart - 1); - } - catch (Exception &e) - { - if (!bSilent) - e.Show (MainDlg); - - return FALSE; - } -} - -// Returns the size of the system drive/partition (if encrypted) in bytes -unsigned __int64 GetSysEncDeviceSize (BOOL bSilent) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - if (!bSilent) - e.Show (MainDlg); - } - - return (BootEncStatus.ConfiguredEncryptedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1); -} - -// Returns the current size of the encrypted area of the system drive/partition in bytes -unsigned __int64 GetSysEncDeviceEncryptedPartSize (BOOL bSilent) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - if (!bSilent) - e.Show (MainDlg); - } - - return (BootEncStatus.EncryptedAreaEnd - BootEncStatus.EncryptedAreaStart + 1); -} - - -static void PopulateSysEncContextMenu (HMENU popup, BOOL bToolsOnly) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - if (!bToolsOnly && !IsHiddenOSRunning()) - { - if (SysEncryptionOrDecryptionRequired ()) - { - if (!BootEncStatus.SetupInProgress) - AppendMenuW (popup, MF_STRING, IDM_SYSENC_RESUME, GetString ("IDM_SYSENC_RESUME")); - - if (SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) - AppendMenuW (popup, MF_STRING, IDM_PERMANENTLY_DECRYPT_SYS, GetString ("PERMANENTLY_DECRYPT")); - - AppendMenuW (popup, MF_STRING, IDM_ENCRYPT_SYSTEM_DEVICE, GetString ("ENCRYPT")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - } - } - - AppendMenuW (popup, MF_STRING, IDM_CHANGE_SYS_PASSWORD, GetString ("IDM_CHANGE_SYS_PASSWORD")); - AppendMenuW (popup, MF_STRING, IDM_CHANGE_SYS_HEADER_KEY_DERIV_ALGO, GetString ("IDM_CHANGE_SYS_HEADER_KEY_DERIV_ALGO")); - - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDM_SYS_ENC_SETTINGS, GetString ("IDM_SYS_ENC_SETTINGS")); - - if (!IsHiddenOSRunning()) - { - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDM_CREATE_RESCUE_DISK, GetString ("IDM_CREATE_RESCUE_DISK")); - AppendMenuW (popup, MF_STRING, IDM_VERIFY_RESCUE_DISK, GetString ("IDM_VERIFY_RESCUE_DISK")); - } - - if (!bToolsOnly) - { - if (SysDriveOrPartitionFullyEncrypted (FALSE) && !IsHiddenOSRunning()) - { - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDM_PERMANENTLY_DECRYPT_SYS, GetString ("PERMANENTLY_DECRYPT")); - } - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDM_VOLUME_PROPERTIES, GetString ("IDPM_PROPERTIES")); - } -} - - -// WARNING: This function may take a long time to complete. To prevent data corruption, it MUST be called before -// mounting a partition (as a regular volume) that is within key scope of system encryption. -// Returns TRUE if the partition can be mounted as a partition within key scope of inactive system encryption. -// If devicePath is empty, the currently selected partition in the GUI is checked. -BOOL CheckSysEncMountWithoutPBA (const char *devicePath, BOOL quiet) -{ - BOOL tmpbDevice; - char szDevicePath [TC_MAX_PATH+1]; - char szDiskFile [TC_MAX_PATH+1]; - - if (strlen (devicePath) < 2) - { - GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, sizeof (szDevicePath)); - CreateFullVolumePath (szDiskFile, szDevicePath, &tmpbDevice); - - if (!tmpbDevice) - { - if (!quiet) - Warning ("NO_SYSENC_PARTITION_SELECTED"); - - return FALSE; - } - - if (LOWORD (GetSelectedLong (GetDlgItem (MainDlg, IDC_DRIVELIST))) != TC_MLIST_ITEM_FREE) - { - if (!quiet) - Warning ("SELECT_FREE_DRIVE"); - - return FALSE; - } - } - else - strncpy (szDevicePath, devicePath, sizeof (szDevicePath)); - - char *partionPortion = strrchr (szDevicePath, '\\'); - - if (!partionPortion - || !_stricmp (partionPortion, "\\Partition0")) - { - // Only partitions are supported (not whole drives) - if (!quiet) - Warning ("NO_SYSENC_PARTITION_SELECTED"); - - return FALSE; - } - - try - { - BootEncStatus = BootEncObj->GetStatus(); - - if (BootEncStatus.DriveMounted) - { - int retCode = 0; - int driveNo; - char parentDrivePath [TC_MAX_PATH+1]; - - if (sscanf (szDevicePath, "\\Device\\Harddisk%d\\Partition", &driveNo) != 1) - { - if (!quiet) - Error ("INVALID_PATH"); - - return FALSE; - } - - _snprintf (parentDrivePath, - sizeof (parentDrivePath), - "\\Device\\Harddisk%d\\Partition0", - driveNo); - - WaitCursor (); - - // This is critical (re-mounting a mounted system volume as a normal volume could cause data corruption) - // so we force the slower but reliable method - retCode = IsSystemDevicePath (parentDrivePath, MainDlg, TRUE); - - NormalCursor(); - - if (retCode != 2) - return TRUE; - else - { - // The partition is located on active system drive - - if (!quiet) - Warning ("MOUNT_WITHOUT_PBA_VOL_ON_ACTIVE_SYSENC_DRIVE"); - - return FALSE; - } - } - else - return TRUE; - } - catch (Exception &e) - { - NormalCursor(); - e.Show (MainDlg); - } - - return FALSE; -} - - -// Returns TRUE if the host drive of the specified partition contains a portion of the TrueCrypt Boot Loader -// and if the drive is not within key scope of active system encryption (e.g. the system drive of the running OS). -// If bPrebootPasswordDlgMode is TRUE, this function returns FALSE (because the check would be redundant). -BOOL TCBootLoaderOnInactiveSysEncDrive (void) -{ - try - { - int driveNo; - char szDevicePath [TC_MAX_PATH+1]; - char parentDrivePath [TC_MAX_PATH+1]; - - if (bPrebootPasswordDlgMode) - return FALSE; - - GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, sizeof (szDevicePath)); - - if (sscanf (szDevicePath, "\\Device\\Harddisk%d\\Partition", &driveNo) != 1) - return FALSE; - - _snprintf (parentDrivePath, - sizeof (parentDrivePath), - "\\Device\\Harddisk%d\\Partition0", - driveNo); - - BootEncStatus = BootEncObj->GetStatus(); - - if (BootEncStatus.DriveMounted - && IsSystemDevicePath (parentDrivePath, MainDlg, FALSE) == 2) - { - // The partition is within key scope of active system encryption - return FALSE; - } - - return ((BOOL) BootEncObj->IsBootLoaderOnDrive (parentDrivePath)); - } - catch (...) - { - return FALSE; - } - -} - - -BOOL SelectItem (HWND hTree, char nLetter) -{ - int i; - LVITEM item; - - for (i = 0; i < ListView_GetItemCount(hTree); i++) - { - memset(&item, 0, sizeof(LVITEM)); - item.mask = LVIF_PARAM; - item.iItem = i; - - if (ListView_GetItem (hTree, &item) == FALSE) - return FALSE; - else - { - if (HIWORD (item.lParam) == nLetter) - { - memset(&item, 0, sizeof(LVITEM)); - item.state = LVIS_FOCUSED|LVIS_SELECTED; - item.stateMask = LVIS_FOCUSED|LVIS_SELECTED; - item.mask = LVIF_STATE; - item.iItem = i; - SendMessage(hTree, LVM_SETITEMSTATE, i, (LPARAM) &item); - return TRUE; - } - } - } - - return TRUE; -} - - -static void LaunchVolCreationWizard (HWND hwndDlg, const char *arg) -{ - char t[TC_MAX_PATH] = {'"',0}; - char *tmp; - - GetModuleFileName (NULL, t+1, sizeof(t)-1); - - tmp = strrchr (t, '\\'); - if (tmp) - { - STARTUPINFO si; - PROCESS_INFORMATION pi; - ZeroMemory (&si, sizeof (si)); - - strcpy (++tmp, "TrueCrypt Format.exe\""); - - if (!FileExists(t)) - Error ("VOL_CREATION_WIZARD_NOT_FOUND"); // Display a user-friendly error message and advise what to do - - if (strlen (arg) > 0) - { - strcat (t, " "); - strcat (t, arg); - } - - if (!CreateProcess (NULL, (LPSTR) t, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) - { - handleWin32Error (hwndDlg); - } - else - { - CloseHandle (pi.hProcess); - CloseHandle (pi.hThread); - } - } -} - - -// Fills drive list -// drive>0 = update only the corresponding drive subitems -void LoadDriveLetters (HWND hTree, int drive) -{ - char *szDriveLetters[]= - {"A:", "B:", "C:", "D:", - "E:", "F:", "G:", "H:", "I:", "J:", "K:", - "L:", "M:", "N:", "O:", "P:", "Q:", "R:", - "S:", "T:", "U:", "V:", "W:", "X:", "Y:", - "Z:"}; - - DWORD dwResult; - BOOL bResult; - DWORD dwUsedDrives; - MOUNT_LIST_STRUCT driver; - VOLUME_PROPERTIES_STRUCT propSysEnc; - char sysDriveLetter = 0; - - BOOL bSysEnc = FALSE; - BOOL bWholeSysDriveEncryption = FALSE; - - LVITEM listItem; - int item = 0; - char i; - - try - { - BootEncStatus = BootEncObj->GetStatus(); - if (bSysEnc = BootEncStatus.DriveMounted) - { - BootEncObj->GetVolumeProperties (&propSysEnc); - } - } - catch (...) - { - bSysEnc = FALSE; - } - - ZeroMemory (&driver, sizeof (driver)); - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &driver, - sizeof (driver), &driver, sizeof (driver), &dwResult, - NULL); - memcpy (&LastKnownMountList, &driver, sizeof (driver)); - - if (bResult == FALSE) - { - handleWin32Error (hTree); - driver.ulMountedDrives = 0; - } - - LastKnownLogicalDrives = dwUsedDrives = GetLogicalDrives (); - if (dwUsedDrives == 0) - Warning ("DRIVELETTERS"); - - if(drive == 0) - ListView_DeleteAllItems(hTree); - - if (bSysEnc) - { - bWholeSysDriveEncryption = WholeSysDriveEncryption (TRUE); - - sysDriveLetter = GetSystemDriveLetter (); - } - - /* System drive */ - - if (bWholeSysDriveEncryption) - { - i = ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER; - int curDrive = 0; - - if (drive > 0) - { - LVITEM tmp; - memset(&tmp, 0, sizeof(LVITEM)); - tmp.mask = LVIF_PARAM; - tmp.iItem = item; - if (ListView_GetItem (hTree, &tmp)) - curDrive = HIWORD(tmp.lParam); - } - - { - char szTmp[1024]; - wchar_t szTmpW[1024]; - - memset(&listItem, 0, sizeof(listItem)); - - listItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; - listItem.iImage = 2; - listItem.iItem = item++; - - listItem.pszText = szTmp; - strcpy (szTmp, " "); - - listItem.lParam = MAKELONG (TC_MLIST_ITEM_SYS_DRIVE, ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER); - - if(drive == 0) - ListView_InsertItem (hTree, &listItem); - else - ListView_SetItem (hTree, &listItem); - - listItem.mask=LVIF_TEXT; - - // Fully encrypted - if (SysDriveOrPartitionFullyEncrypted (TRUE)) - { - wcscpy (szTmpW, GetString ("SYSTEM_DRIVE")); - } - else - { - // Partially encrypted - - if (BootEncStatus.SetupInProgress) - { - // Currently encrypting/decrypting - - if (BootEncStatus.SetupMode != SetupDecryption) - { - _snwprintf (szTmpW, - sizeof szTmpW/2, - GetString ("SYSTEM_DRIVE_ENCRYPTING"), - (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); - } - else - { - _snwprintf (szTmpW, - sizeof szTmpW/2, - GetString ("SYSTEM_DRIVE_DECRYPTING"), - 100.0 - ((double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0)); - } - } - else - { - _snwprintf (szTmpW, - sizeof szTmpW/2, - GetString ("SYSTEM_DRIVE_PARTIALLY_ENCRYPTED"), - (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); - } - } - - ListSubItemSetW (hTree, listItem.iItem, 1, szTmpW); - - GetSizeString (GetSysEncDeviceSize(TRUE), szTmpW); - ListSubItemSetW (hTree, listItem.iItem, 2, szTmpW); - - EAGetName (szTmp, propSysEnc.ea); - listItem.iSubItem = 3; - ListView_SetItem (hTree, &listItem); - - ListSubItemSetW (hTree, listItem.iItem, 4, GetString (IsHiddenOSRunning() ? "HIDDEN" : "SYSTEM_VOLUME_TYPE_ADJECTIVE")); - - VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; - } - } - - /* Drive letters */ - - for (i = 2; i < 26; i++) - { - int curDrive = 0; - - BOOL bSysEncPartition = (bSysEnc && !bWholeSysDriveEncryption && sysDriveLetter == *((char *) szDriveLetters[i])); - - if (drive > 0) - { - LVITEM tmp; - memset(&tmp, 0, sizeof(LVITEM)); - tmp.mask = LVIF_PARAM; - tmp.iItem = item; - if (ListView_GetItem (hTree, &tmp)) - curDrive = HIWORD(tmp.lParam); - } - - if (driver.ulMountedDrives & (1 << i) - || bSysEncPartition) - { - char szTmp[1024]; - wchar_t szTmpW[1024]; - wchar_t *ws; - - memset(&listItem, 0, sizeof(listItem)); - - listItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; - listItem.iImage = bSysEncPartition ? 2 : 1; - listItem.iItem = item++; - - if (drive > 0 && drive != curDrive) - continue; - - listItem.lParam = MAKELONG ( - bSysEncPartition ? TC_MLIST_ITEM_SYS_PARTITION : TC_MLIST_ITEM_NONSYS_VOL, - i + 'A'); - - listItem.pszText = szDriveLetters[i]; - - if (drive == 0) - ListView_InsertItem (hTree, &listItem); - else - ListView_SetItem (hTree, &listItem); - - listItem.mask=LVIF_TEXT; - listItem.pszText = szTmp; - - if (bSysEncPartition) - { - // Fully encrypted - if (SysDriveOrPartitionFullyEncrypted (TRUE)) - { - wcscpy (szTmpW, GetString (IsHiddenOSRunning() ? "HIDDEN_SYSTEM_PARTITION" : "SYSTEM_PARTITION")); - } - else - { - // Partially encrypted - - if (BootEncStatus.SetupInProgress) - { - // Currently encrypting/decrypting - - if (BootEncStatus.SetupMode != SetupDecryption) - { - _snwprintf (szTmpW, - sizeof szTmpW/2, - GetString ("SYSTEM_PARTITION_ENCRYPTING"), - (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); - } - else - { - _snwprintf (szTmpW, - sizeof szTmpW/2, - GetString ("SYSTEM_PARTITION_DECRYPTING"), - 100.0 - ((double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0)); - } - } - else - { - _snwprintf (szTmpW, - sizeof szTmpW/2, - GetString ("SYSTEM_PARTITION_PARTIALLY_ENCRYPTED"), - (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); - } - } - - ListSubItemSetW (hTree, listItem.iItem, 1, szTmpW); - } - else - { - ToSBCS ((LPWSTR) driver.wszVolume[i]); - - if (memcmp (driver.wszVolume[i], "\\Device", 7) == 0) - sprintf (szTmp, "%s", ((char *) driver.wszVolume[i])); - else - sprintf (szTmp, "%s", ((char *) driver.wszVolume[i]) + 4); - - listItem.iSubItem = 1; - ListView_SetItem (hTree, &listItem); - } - - GetSizeString (bSysEncPartition ? GetSysEncDeviceSize(TRUE) : driver.diskLength[i], szTmpW); - ListSubItemSetW (hTree, listItem.iItem, 2, szTmpW); - - EAGetName (szTmp, bSysEncPartition ? propSysEnc.ea : driver.ea[i]); - listItem.iSubItem = 3; - ListView_SetItem (hTree, &listItem); - - if (bSysEncPartition) - { - ws = GetString (IsHiddenOSRunning() ? "HIDDEN" : "SYSTEM_VOLUME_TYPE_ADJECTIVE"); - VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; - ListSubItemSetW (hTree, listItem.iItem, 4, ws); - } - else - { - switch (driver.volumeType[i]) - { - case PROP_VOL_TYPE_NORMAL: - ws = GetString ("NORMAL"); - break; - case PROP_VOL_TYPE_HIDDEN: - ws = GetString ("HIDDEN"); - break; - case PROP_VOL_TYPE_OUTER: - ws = GetString ("OUTER"); // Normal/outer volume (hidden volume protected) - break; - case PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED: - ws = GetString ("OUTER_VOL_WRITE_PREVENTED"); // Normal/outer volume (hidden volume protected AND write denied) - break; - default: - ws = L"?"; - } - ListSubItemSetW (hTree, listItem.iItem, 4, ws); - - if (driver.volumeType[i] == PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED) // Normal/outer volume (hidden volume protected AND write denied) - { - if (!VolumeNotificationsList.bHidVolDamagePrevReported[i]) - { - wchar_t szTmp[4096]; - - VolumeNotificationsList.bHidVolDamagePrevReported[i] = TRUE; - swprintf (szTmp, GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), i+'A'); - SetForegroundWindow (GetParent(hTree)); - MessageBoxW (GetParent(hTree), szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - } - } - else - { - VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; - } - } - } - else - { - VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; - - if (!(dwUsedDrives & 1 << i)) - { - if(drive > 0 && drive != HIWORD (GetSelectedLong (hTree))) - { - item++; - continue; - } - - memset(&listItem,0,sizeof(listItem)); - - listItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; - listItem.iImage = 0; - listItem.iItem = item++; - listItem.pszText = szDriveLetters[i]; - listItem.lParam = MAKELONG (TC_MLIST_ITEM_FREE, i + 'A'); - - if(drive == 0) - ListView_InsertItem (hTree, &listItem); - else - ListView_SetItem (hTree, &listItem); - - listItem.mask=LVIF_TEXT; - listItem.pszText = ""; - listItem.iSubItem = 1; - ListView_SetItem (hTree, &listItem); - listItem.iSubItem = 2; - ListView_SetItem (hTree, &listItem); - listItem.iSubItem = 3; - ListView_SetItem (hTree, &listItem); - listItem.iSubItem = 4; - ListView_SetItem (hTree, &listItem); - - } - } - } -} - - -static void PasswordChangeEnable (HWND hwndDlg, int button, int passwordId, BOOL keyFilesEnabled, - int newPasswordId, int newVerifyId, BOOL newKeyFilesEnabled) -{ - char password[MAX_PASSWORD + 1]; - char newPassword[MAX_PASSWORD + 1]; - char newVerify[MAX_PASSWORD + 1]; - BOOL bEnable = TRUE; - - GetWindowText (GetDlgItem (hwndDlg, passwordId), password, sizeof (password)); - - if (pwdChangeDlgMode == PCDM_CHANGE_PKCS5_PRF) - newKeyFilesEnabled = keyFilesEnabled; - - switch (pwdChangeDlgMode) - { - case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: - case PCDM_ADD_REMOVE_VOL_KEYFILES: - case PCDM_CHANGE_PKCS5_PRF: - memcpy (newPassword, password, sizeof (newPassword)); - memcpy (newVerify, password, sizeof (newVerify)); - break; - - default: - GetWindowText (GetDlgItem (hwndDlg, newPasswordId), newPassword, sizeof (newPassword)); - GetWindowText (GetDlgItem (hwndDlg, newVerifyId), newVerify, sizeof (newVerify)); - } - - if (!keyFilesEnabled && strlen (password) < MIN_PASSWORD) - bEnable = FALSE; - else if (strcmp (newPassword, newVerify) != 0) - bEnable = FALSE; - else if (!newKeyFilesEnabled && strlen (newPassword) < MIN_PASSWORD) - bEnable = FALSE; - - burn (password, sizeof (password)); - burn (newPassword, sizeof (newPassword)); - burn (newVerify, sizeof (newVerify)); - - EnableWindow (GetDlgItem (hwndDlg, button), bEnable); -} - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK PasswordChangeDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static KeyFilesDlgParam newKeyFilesParam; - - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - LPARAM nIndex; - HWND hComboBox = GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID); - int i; - - ZeroMemory (&newKeyFilesParam, sizeof (newKeyFilesParam)); - - SetWindowTextW (hwndDlg, GetString ("IDD_PASSWORDCHANGE_DLG")); - LocalizeDialog (hwndDlg, "IDD_PASSWORDCHANGE_DLG"); - - SendMessage (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), EM_LIMITTEXT, MAX_PASSWORD, 0); - EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); - - SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, KeyFilesEnable); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEW_KEYFILES), TRUE); - - SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); - - nIndex = SendMessageW (hComboBox, CB_ADDSTRING, 0, (LPARAM) GetString ("UNCHANGED")); - SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) 0); - - for (i = FIRST_PRF_ID; i <= LAST_PRF_ID; i++) - { - if (!HashIsDeprecated (i)) - { - nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) get_pkcs5_prf_name(i)); - SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) i); - } - } - - SendMessage (hComboBox, CB_SETCURSEL, 0, 0); - - switch (pwdChangeDlgMode) - { - case PCDM_CHANGE_PKCS5_PRF: - SetWindowTextW (hwndDlg, GetString ("IDD_PCDM_CHANGE_PKCS5_PRF")); - LocalizeDialog (hwndDlg, "IDD_PCDM_CHANGE_PKCS5_PRF"); - EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_VERIFY), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_NEW_KEYFILES), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEW_KEYFILES), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_NEW_PASSWORD), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_CONFIRM_PASSWORD), FALSE); - break; - - case PCDM_ADD_REMOVE_VOL_KEYFILES: - SetWindowTextW (hwndDlg, GetString ("IDD_PCDM_ADD_REMOVE_VOL_KEYFILES")); - LocalizeDialog (hwndDlg, "IDD_PCDM_ADD_REMOVE_VOL_KEYFILES"); - newKeyFilesParam.EnableKeyFiles = TRUE; - EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_VERIFY), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_NEW_PASSWORD), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_CONFIRM_PASSWORD), FALSE); - break; - - case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: - newKeyFilesParam.EnableKeyFiles = FALSE; - SetWindowTextW (hwndDlg, GetString ("IDD_PCDM_REMOVE_ALL_KEYFILES_FROM_VOL")); - LocalizeDialog (hwndDlg, "IDD_PCDM_REMOVE_ALL_KEYFILES_FROM_VOL"); - KeyFilesEnable = TRUE; - SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_KEYFILES), TRUE); - EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_VERIFY), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_NEW_KEYFILES), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_NEW_KEYFILES), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_NEW_PASSWORD), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_CONFIRM_PASSWORD), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDT_PKCS5_PRF), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), FALSE); - break; - - case PCDM_CHANGE_PASSWORD: - default: - // NOP - break; - }; - - if (bSysEncPwdChangeDlgMode) - { - ToBootPwdField (hwndDlg, IDC_PASSWORD); - ToBootPwdField (hwndDlg, IDC_VERIFY); - ToBootPwdField (hwndDlg, IDC_OLD_PASSWORD); - - if ((DWORD) GetKeyboardLayout (NULL) != 0x00000409 && (DWORD) GetKeyboardLayout (NULL) != 0x04090409) - { - DWORD keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); - EndDialog (hwndDlg, IDCANCEL); - return 0; - } - - bKeyboardLayoutChanged = TRUE; - } - - ShowWindow(GetDlgItem(hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_SHOW_PASSWORD_CHPWD_ORI), SW_HIDE); - - if (SetTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD, TIMER_INTERVAL_KEYB_LAYOUT_GUARD, NULL) == 0) - { - Error ("CANNOT_SET_TIMER"); - EndDialog (hwndDlg, IDCANCEL); - return 0; - } - - newKeyFilesParam.EnableKeyFiles = FALSE; - KeyFilesEnable = FALSE; - SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_KEYFILES), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_NEW_KEYFILES), FALSE); - } - - CheckCapsLock (hwndDlg, FALSE); - - return 0; - } - - case WM_TIMER: - switch (wParam) - { - case TIMER_ID_KEYB_LAYOUT_GUARD: - if (bSysEncPwdChangeDlgMode) - { - DWORD keybLayout = (DWORD) GetKeyboardLayout (NULL); - - /* Watch the keyboard layout */ - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - // Keyboard layout is not standard US - - // Attempt to wipe passwords stored in the input field buffers - char tmp[MAX_PASSWORD+1]; - memset (tmp, 'X', MAX_PASSWORD); - tmp [MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), tmp); - - SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), ""); - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), ""); - SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), ""); - - keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); - Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - bKeyboardLayoutChanged = TRUE; - - wchar_t szTmp [4096]; - wcscpy (szTmp, GetString ("KEYB_LAYOUT_CHANGE_PREVENTED")); - wcscat (szTmp, L"\n\n"); - wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); - MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - } - - - /* Watch the right Alt key (which is used to enter various characters on non-US keyboards) */ - - if (bKeyboardLayoutChanged && !bKeybLayoutAltKeyWarningShown) - { - if (GetAsyncKeyState (VK_RMENU) < 0) - { - bKeybLayoutAltKeyWarningShown = TRUE; - - wchar_t szTmp [4096]; - wcscpy (szTmp, GetString ("ALT_KEY_CHARS_NOT_FOR_SYS_ENCRYPTION")); - wcscat (szTmp, L"\n\n"); - wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); - MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); - } - } - } - return 1; - } - return 0; - - case WM_COMMAND: - if (lw == IDCANCEL) - { - // Attempt to wipe passwords stored in the input field buffers - char tmp[MAX_PASSWORD+1]; - memset (tmp, 'X', MAX_PASSWORD); - tmp[MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), tmp); - RestoreDefaultKeyFilesParam (); - - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - if (hw == EN_CHANGE) - { - PasswordChangeEnable (hwndDlg, IDOK, - IDC_OLD_PASSWORD, - KeyFilesEnable && FirstKeyFile != NULL, - IDC_PASSWORD, IDC_VERIFY, - newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); - - return 1; - } - - if (lw == IDC_KEYFILES) - { - if (bSysEncPwdChangeDlgMode) - { - Warning ("KEYFILES_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); - return 1; - } - - KeyFilesDlgParam param; - param.EnableKeyFiles = KeyFilesEnable; - param.FirstKeyFile = FirstKeyFile; - - if (IDOK == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, - (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m)) - { - KeyFilesEnable = param.EnableKeyFiles; - FirstKeyFile = param.FirstKeyFile; - - SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, KeyFilesEnable); - } - - PasswordChangeEnable (hwndDlg, IDOK, - IDC_OLD_PASSWORD, - KeyFilesEnable && FirstKeyFile != NULL, - IDC_PASSWORD, IDC_VERIFY, - newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); - - return 1; - } - - - if (lw == IDC_NEW_KEYFILES) - { - if (bSysEncPwdChangeDlgMode) - { - Warning ("KEYFILES_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); - return 1; - } - - if (IDOK == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, - (DLGPROC) KeyFilesDlgProc, (LPARAM) &newKeyFilesParam)) - { - SetCheckBox (hwndDlg, IDC_ENABLE_NEW_KEYFILES, newKeyFilesParam.EnableKeyFiles); - - VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (hwndDlg, IDOK), GetDlgItem (hwndDlg, IDC_PASSWORD), - GetDlgItem (hwndDlg, IDC_VERIFY), NULL, NULL, - newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); - } - - PasswordChangeEnable (hwndDlg, IDOK, - IDC_OLD_PASSWORD, - KeyFilesEnable && FirstKeyFile != NULL, - IDC_PASSWORD, IDC_VERIFY, - newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); - - return 1; - } - - if (lw == IDC_ENABLE_KEYFILES) - { - KeyFilesEnable = GetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES); - - PasswordChangeEnable (hwndDlg, IDOK, - IDC_OLD_PASSWORD, - KeyFilesEnable && FirstKeyFile != NULL, - IDC_PASSWORD, IDC_VERIFY, - newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); - - return 1; - } - - if (lw == IDC_ENABLE_NEW_KEYFILES) - { - newKeyFilesParam.EnableKeyFiles = GetCheckBox (hwndDlg, IDC_ENABLE_NEW_KEYFILES); - - PasswordChangeEnable (hwndDlg, IDOK, - IDC_OLD_PASSWORD, - KeyFilesEnable && FirstKeyFile != NULL, - IDC_PASSWORD, IDC_VERIFY, - newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); - - return 1; - } - - if (hw == CBN_SELCHANGE) - { - switch (lw) - { - case IDC_PKCS5_PRF_ID: - if (bSysEncPwdChangeDlgMode) - { - int new_hash_algo_id = SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETITEMDATA, - SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETCURSEL, 0, 0), 0); - - if (new_hash_algo_id != 0 && new_hash_algo_id != DEFAULT_HASH_ALGORITHM_BOOT) - { - int new_hash_algo_id = DEFAULT_HASH_ALGORITHM_BOOT; - Info ("ALGO_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); - SelectAlgo (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), &new_hash_algo_id); - } - } - break; - } - return 1; - - } - - if (lw == IDC_SHOW_PASSWORD_CHPWD_ORI) - { - SendMessage (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_ORI) ? 0 : '*', - 0); - InvalidateRect (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), NULL, TRUE); - return 1; - } - - if (lw == IDC_SHOW_PASSWORD_CHPWD_NEW) - { - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW) ? 0 : '*', - 0); - SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW) ? 0 : '*', - 0); - InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); - InvalidateRect (GetDlgItem (hwndDlg, IDC_VERIFY), NULL, TRUE); - return 1; - } - - if (lw == IDOK) - { - HWND hParent = GetParent (hwndDlg); - Password oldPassword; - Password newPassword; - int nStatus; - int pkcs5 = SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETITEMDATA, - SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETCURSEL, 0, 0), 0); - - if (!CheckPasswordCharEncoding (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL)) - { - Error ("UNSUPPORTED_CHARS_IN_PWD"); - return 1; - } - - if (pwdChangeDlgMode == PCDM_CHANGE_PKCS5_PRF) - { - newKeyFilesParam.EnableKeyFiles = KeyFilesEnable; - } - else if (!(newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL) - && pwdChangeDlgMode == PCDM_CHANGE_PASSWORD) - { - if (!CheckPasswordLength (hwndDlg, GetDlgItem (hwndDlg, IDC_PASSWORD))) - return 1; - } - - GetWindowText (GetDlgItem (hParent, IDC_VOLUME), szFileName, sizeof (szFileName)); - - GetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), (LPSTR) oldPassword.Text, sizeof (oldPassword.Text)); - oldPassword.Length = strlen ((char *) oldPassword.Text); - - switch (pwdChangeDlgMode) - { - case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: - case PCDM_ADD_REMOVE_VOL_KEYFILES: - case PCDM_CHANGE_PKCS5_PRF: - memcpy (newPassword.Text, oldPassword.Text, sizeof (newPassword.Text)); - newPassword.Length = strlen ((char *) oldPassword.Text); - break; - - default: - GetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), (LPSTR) newPassword.Text, sizeof (newPassword.Text)); - newPassword.Length = strlen ((char *) newPassword.Text); - } - - WaitCursor (); - - if (KeyFilesEnable) - KeyFilesApply (&oldPassword, FirstKeyFile); - - if (newKeyFilesParam.EnableKeyFiles) - KeyFilesApply (&newPassword, - pwdChangeDlgMode==PCDM_CHANGE_PKCS5_PRF ? FirstKeyFile : newKeyFilesParam.FirstKeyFile); - - if (bSysEncPwdChangeDlgMode) - { - // System - - pkcs5 = 0; // PKCS-5 PRF unchanged (currently system encryption supports only RIPEMD-160) - - try - { - nStatus = BootEncObj->ChangePassword (&oldPassword, &newPassword, pkcs5); - } - catch (Exception &e) - { - e.Show (MainDlg); - nStatus = ERR_OS_ERROR; - } - } - else - { - // Non-system - - nStatus = ChangePwd (szFileName, &oldPassword, &newPassword, pkcs5, hwndDlg); - - if (nStatus == ERR_OS_ERROR - && GetLastError () == ERROR_ACCESS_DENIED - && IsUacSupported () - && IsVolumeDeviceHosted (szFileName)) - { - nStatus = UacChangePwd (szFileName, &oldPassword, &newPassword, pkcs5, hwndDlg); - } - } - - burn (&oldPassword, sizeof (oldPassword)); - burn (&newPassword, sizeof (newPassword)); - - NormalCursor (); - - if (nStatus == 0) - { - // Attempt to wipe passwords stored in the input field buffers - char tmp[MAX_PASSWORD+1]; - memset (tmp, 'X', MAX_PASSWORD); - tmp[MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), tmp); - - KeyFileRemoveAll (&newKeyFilesParam.FirstKeyFile); - RestoreDefaultKeyFilesParam (); - - if (bSysEncPwdChangeDlgMode) - { - KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); - } - - EndDialog (hwndDlg, IDOK); - } - return 1; - } - return 0; - } - - return 0; -} - -static char PasswordDlgVolume[MAX_PATH]; -static BOOL PasswordDialogDisableMountOptions; -static char *PasswordDialogTitleStringId; - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK PasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - static Password *szXPwd; - - switch (msg) - { - case WM_INITDIALOG: - { - szXPwd = (Password *) lParam; - LocalizeDialog (hwndDlg, "IDD_PASSWORD_DLG"); - DragAcceptFiles (hwndDlg, TRUE); - - if (PasswordDialogTitleStringId) - { - SetWindowTextW (hwndDlg, GetString (PasswordDialogTitleStringId)); - } - else if (strlen (PasswordDlgVolume) > 0) - { - wchar_t s[1024]; - const int maxVisibleLen = 40; - - if (strlen (PasswordDlgVolume) > maxVisibleLen) - { - string volStr = PasswordDlgVolume; - wsprintfW (s, GetString ("ENTER_PASSWORD_FOR"), ("..." + volStr.substr (volStr.size() - maxVisibleLen - 1)).c_str()); - } - else - wsprintfW (s, GetString ("ENTER_PASSWORD_FOR"), PasswordDlgVolume); - - SetWindowTextW (hwndDlg, s); - } - - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); - SendMessage (GetDlgItem (hwndDlg, IDC_CACHE), BM_SETCHECK, bCacheInDriver ? BST_CHECKED:BST_UNCHECKED, 0); - - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); - - mountOptions.PartitionInInactiveSysEncScope = bPrebootPasswordDlgMode; - - if (bPrebootPasswordDlgMode) - { - SendMessage (hwndDlg, TC_APPMSG_PREBOOT_PASSWORD_MODE, 0, 0); - } - - if (PasswordDialogDisableMountOptions) - { - EnableWindow (GetDlgItem (hwndDlg, IDC_CACHE), FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_MOUNT_OPTIONS), FALSE); - } - - SetForegroundWindow (hwndDlg); - } - return 0; - - case TC_APPMSG_PREBOOT_PASSWORD_MODE: - { - ToBootPwdField (hwndDlg, IDC_PASSWORD); - - // Attempt to wipe the password stored in the input field buffer - char tmp[MAX_PASSWORD+1]; - memset (tmp, 'X', MAX_PASSWORD); - tmp [MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), ""); - - sprintf (OrigKeyboardLayout, "%08X", (DWORD) GetKeyboardLayout (NULL) & 0xFFFF); - - DWORD keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - if (SetTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD, TIMER_INTERVAL_KEYB_LAYOUT_GUARD, NULL) == 0) - { - Error ("CANNOT_SET_TIMER"); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - SetCheckBox (hwndDlg, IDC_SHOW_PASSWORD, FALSE); - EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD), FALSE); - - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_SETPASSWORDCHAR, '*', 0); - InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); - - bPrebootPasswordDlgMode = TRUE; - } - return 1; - - case WM_TIMER: - switch (wParam) - { - case TIMER_ID_KEYB_LAYOUT_GUARD: - if (bPrebootPasswordDlgMode) - { - DWORD keybLayout = (DWORD) GetKeyboardLayout (NULL); - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - // Keyboard layout is not standard US - - // Attempt to wipe the password stored in the input field buffer - char tmp[MAX_PASSWORD+1]; - memset (tmp, 'X', MAX_PASSWORD); - tmp [MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), ""); - - keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); - - if (keybLayout != 0x00000409 && keybLayout != 0x04090409) - { - KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); - Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - wchar_t szTmp [4096]; - wcscpy (szTmp, GetString ("KEYB_LAYOUT_CHANGE_PREVENTED")); - wcscat (szTmp, L"\n\n"); - wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); - MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - } - } - return 1; - } - return 0; - - case WM_COMMAND: - - if (lw == IDC_MOUNT_OPTIONS) - { - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg, - (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions); - - if (!bPrebootPasswordDlgMode && mountOptions.PartitionInInactiveSysEncScope) - SendMessage (hwndDlg, TC_APPMSG_PREBOOT_PASSWORD_MODE, 0, 0); - - return 1; - } - - if (lw == IDC_SHOW_PASSWORD) - { - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD) ? 0 : '*', - 0); - InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); - return 1; - } - - if (lw == IDC_KEY_FILES) - { - KeyFilesDlgParam param; - param.EnableKeyFiles = KeyFilesEnable; - param.FirstKeyFile = FirstKeyFile; - - if (IDOK == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, - (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m)) - { - KeyFilesEnable = param.EnableKeyFiles; - FirstKeyFile = param.FirstKeyFile; - - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); - } - - return 1; - } - - if (lw == IDC_KEYFILES_ENABLE) - { - KeyFilesEnable = GetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE); - - return 1; - } - - if (lw == IDCANCEL || lw == IDOK) - { - char tmp[MAX_PASSWORD+1]; - - if (lw == IDOK) - { - if (mountOptions.ProtectHiddenVolume && hidVolProtKeyFilesParam.EnableKeyFiles) - KeyFilesApply (&mountOptions.ProtectedHidVolPassword, hidVolProtKeyFilesParam.FirstKeyFile); - - GetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), (LPSTR) szXPwd->Text, MAX_PASSWORD + 1); - szXPwd->Length = strlen ((char *) szXPwd->Text); - - bCacheInDriver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_CACHE)); - } - - // Attempt to wipe password stored in the input field buffer - memset (tmp, 'X', MAX_PASSWORD); - tmp[MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), tmp); - - if (hidVolProtKeyFilesParam.FirstKeyFile != NULL) - { - KeyFileRemoveAll (&hidVolProtKeyFilesParam.FirstKeyFile); - hidVolProtKeyFilesParam.EnableKeyFiles = FALSE; - } - - if (bPrebootPasswordDlgMode) - { - KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); - - // Restore the original keyboard layout - if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) - Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); - } - - EndDialog (hwndDlg, lw); - return 1; - } - return 0; - - case WM_CONTEXTMENU: - { - RECT buttonRect; - GetWindowRect (GetDlgItem (hwndDlg, IDC_KEY_FILES), &buttonRect); - - if (LOWORD (lParam) >= buttonRect.left && LOWORD (lParam) <= buttonRect.right - && HIWORD (lParam) >= buttonRect.top && HIWORD (lParam) <= buttonRect.bottom) - { - // The "Keyfiles" button has been right-clicked - - KeyFilesDlgParam param; - param.EnableKeyFiles = KeyFilesEnable; - param.FirstKeyFile = FirstKeyFile; - - POINT popupPos; - popupPos.x = buttonRect.left + 2; - popupPos.y = buttonRect.top + 2; - - if (KeyfilesPopupMenu (hwndDlg, popupPos, ¶m)) - { - KeyFilesEnable = param.EnableKeyFiles; - FirstKeyFile = param.FirstKeyFile; - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); - } - } - } - break; - - case WM_DROPFILES: - { - HDROP hdrop = (HDROP) wParam; - int i = 0, count = DragQueryFile (hdrop, -1, NULL, 0); - - while (count-- > 0) - { - KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); - DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName)); - FirstKeyFile = KeyFileAdd (FirstKeyFile, kf); - KeyFilesEnable = TRUE; - } - - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); - DragFinish (hdrop); - } - return 1; - } - - return 0; -} - -static void PreferencesDlgEnableButtons (HWND hwndDlg) -{ - BOOL back = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE)); - BOOL idle = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE)); - BOOL installed = !IsNonInstallMode(); - - EnableWindow (GetDlgItem (hwndDlg, IDC_CLOSE_BKG_TASK_WHEN_NOVOL), back && installed); - EnableWindow (GetDlgItem (hwndDlg, IDT_LOGON), installed); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_LOGON_START), back && installed); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_DEVICES), installed); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_FAVORITES), installed); - EnableWindow (GetDlgItem (hwndDlg, IDT_AUTO_DISMOUNT), back); - EnableWindow (GetDlgItem (hwndDlg, IDT_AUTO_DISMOUNT_ON), back); - EnableWindow (GetDlgItem (hwndDlg, IDT_MINUTES), back); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_LOGOFF), back); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING), back); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER), back); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE), back); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE_TIME), back && idle); - EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT), back); -} - -BOOL CALLBACK PreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static BOOL PreferencesDialogActive = FALSE; - static HWND ActivePreferencesDialogWindow; - - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - if (PreferencesDialogActive) - { - ShowWindow (ActivePreferencesDialogWindow, SW_SHOW); - SetForegroundWindow (ActivePreferencesDialogWindow); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - ActivePreferencesDialogWindow = hwndDlg; - PreferencesDialogActive = TRUE; - - LocalizeDialog (hwndDlg, "IDD_PREFERENCES_DLG"); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_OPEN_EXPLORER), BM_SETCHECK, - bExplore ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_CLOSE_DISMOUNTED_WINDOWS), BM_SETCHECK, - bCloseDismountedWindows ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PRESERVE_TIMESTAMPS), BM_SETCHECK, - defaultMountOptions.PreserveTimestamp ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_EXIT), BM_SETCHECK, - bWipeCacheOnExit ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_AUTODISMOUNT), BM_SETCHECK, - bWipeCacheOnAutoDismount ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_CACHE_PASSWORDS), BM_SETCHECK, - bCacheInDriver ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_READONLY), BM_SETCHECK, - defaultMountOptions.ReadOnly ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_REMOVABLE), BM_SETCHECK, - defaultMountOptions.Removable ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_LOGON_START), BM_SETCHECK, - bStartOnLogon ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_DEVICES), BM_SETCHECK, - bMountDevicesOnLogon ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_FAVORITES), BM_SETCHECK, - bMountFavoritesOnLogon ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE), BM_SETCHECK, - bEnableBkgTask ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_CLOSE_BKG_TASK_WHEN_NOVOL), BM_SETCHECK, - bCloseBkgTaskWhenNoVolumes || IsNonInstallMode() ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_LOGOFF), BM_SETCHECK, - bDismountOnLogOff ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING), BM_SETCHECK, - bDismountOnPowerSaving ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER), BM_SETCHECK, - bDismountOnScreenSaver ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT), BM_SETCHECK, - bForceAutoDismount ? BST_CHECKED:BST_UNCHECKED, 0); - - SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE), BM_SETCHECK, - MaxVolumeIdleTime > 0 ? BST_CHECKED:BST_UNCHECKED, 0); - - SetDlgItemInt (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE_TIME, abs (MaxVolumeIdleTime), FALSE); - - PreferencesDlgEnableButtons (hwndDlg); - } - return 0; - - case WM_COMMAND: - - if (lw == IDC_PRESERVE_TIMESTAMPS && !IsButtonChecked (GetDlgItem (hwndDlg, IDC_PRESERVE_TIMESTAMPS))) - { - if (AskWarnNoYes ("CONFIRM_TIMESTAMP_UPDATING") == IDNO) - SetCheckBox (hwndDlg, IDC_PRESERVE_TIMESTAMPS, TRUE); - } - - if (lw == IDC_PREF_BKG_TASK_ENABLE && !IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE))) - { - if (AskWarnNoYes ("CONFIRM_BACKGROUND_TASK_DISABLED") == IDNO) - SetCheckBox (hwndDlg, IDC_PREF_BKG_TASK_ENABLE, TRUE); - } - - // Forced dismount disabled warning - if (lw == IDC_PREF_DISMOUNT_INACTIVE - || lw == IDC_PREF_DISMOUNT_POWERSAVING - || lw == IDC_PREF_DISMOUNT_SCREENSAVER - || lw == IDC_PREF_FORCE_AUTO_DISMOUNT) - { - BOOL i = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE)); - BOOL p = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING)); - BOOL s = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER)); - BOOL q = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT)); - - if (!q) - { - if (lw == IDC_PREF_FORCE_AUTO_DISMOUNT && (i || p || s)) - { - if (AskWarnNoYes ("CONFIRM_NO_FORCED_AUTODISMOUNT") == IDNO) - SetCheckBox (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT, TRUE); - } - else if ((lw == IDC_PREF_DISMOUNT_INACTIVE && i - || lw == IDC_PREF_DISMOUNT_POWERSAVING && p - || lw == IDC_PREF_DISMOUNT_SCREENSAVER && s)) - Warning ("WARN_PREF_AUTO_DISMOUNT"); - } - - if (p && lw == IDC_PREF_DISMOUNT_POWERSAVING) - Warning ("WARN_PREF_AUTO_DISMOUNT_ON_POWER"); - } - - if (lw == IDCANCEL) - { - PreferencesDialogActive = FALSE; - EndDialog (hwndDlg, lw); - return 1; - } - - if (lw == IDOK) - { - bExplore = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_OPEN_EXPLORER)); - bCloseDismountedWindows = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_CLOSE_DISMOUNTED_WINDOWS)); - bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PRESERVE_TIMESTAMPS)); - bWipeCacheOnExit = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_EXIT)); - bWipeCacheOnAutoDismount = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_AUTODISMOUNT)); - bCacheInDriverDefault = bCacheInDriver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_CACHE_PASSWORDS)); - defaultMountOptions.ReadOnly = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_READONLY)); - defaultMountOptions.Removable = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_REMOVABLE)); - bEnableBkgTask = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE)); - bCloseBkgTaskWhenNoVolumes = IsNonInstallMode() ? bCloseBkgTaskWhenNoVolumes : IsButtonChecked (GetDlgItem (hwndDlg, IDC_CLOSE_BKG_TASK_WHEN_NOVOL)); - bDismountOnLogOff = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_LOGOFF)); - bDismountOnPowerSaving = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING)); - bDismountOnScreenSaver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER)); - bForceAutoDismount = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT)); - MaxVolumeIdleTime = GetDlgItemInt (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE_TIME, NULL, FALSE) - * (IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE)) ? 1 : -1); - bStartOnLogon = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_LOGON_START)); - bMountDevicesOnLogon = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_DEVICES)); - bMountFavoritesOnLogon = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_FAVORITES)); - - ManageStartupSeq (); - - WaitCursor (); - SaveSettings (hwndDlg); - NormalCursor (); - - PreferencesDialogActive = FALSE; - EndDialog (hwndDlg, lw); - return 1; - } - - if (lw == IDC_MORE_SETTINGS) - { - HMENU popup = CreatePopupMenu (); - - AppendMenuW (popup, MF_STRING, IDM_LANGUAGE, GetString ("IDM_LANGUAGE")); - AppendMenuW (popup, MF_STRING, IDM_HOTKEY_SETTINGS, GetString ("IDM_HOTKEY_SETTINGS")); - AppendMenuW (popup, MF_STRING, IDM_SYSENC_SETTINGS, GetString ("IDM_SYSENC_SETTINGS")); - AppendMenuW (popup, MF_STRING, IDM_DEFAULT_KEYFILES, GetString ("IDM_DEFAULT_KEYFILES")); - AppendMenuW (popup, MF_STRING, IDM_TOKEN_PREFERENCES, GetString ("IDM_TOKEN_PREFERENCES")); - - RECT rect; - GetWindowRect (GetDlgItem (hwndDlg, IDC_MORE_SETTINGS), &rect); - - int menuItem = TrackPopupMenu (popup, TPM_RETURNCMD | TPM_LEFTBUTTON, rect.left + 2, rect.top + 2, 0, hwndDlg, NULL); - DestroyMenu (popup); - - SendMessage (MainDlg, WM_COMMAND, menuItem, NULL); - return 1; - } - - if (HIWORD (wParam) == BN_CLICKED) - { - PreferencesDlgEnableButtons (hwndDlg); - return 1; - } - - return 0; - } - - return 0; -} - - -BOOL CALLBACK MountOptionsDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static MountOptions *mountOptions; - - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - BOOL protect; - - mountOptions = (MountOptions *) lParam; - - LocalizeDialog (hwndDlg, "IDD_MOUNT_OPTIONS"); - - SendDlgItemMessage (hwndDlg, IDC_MOUNT_READONLY, BM_SETCHECK, - mountOptions->ReadOnly ? BST_CHECKED : BST_UNCHECKED, 0); - SendDlgItemMessage (hwndDlg, IDC_MOUNT_REMOVABLE, BM_SETCHECK, - mountOptions->Removable ? BST_CHECKED : BST_UNCHECKED, 0); - SendDlgItemMessage (hwndDlg, IDC_PROTECT_HIDDEN_VOL, BM_SETCHECK, - mountOptions->ProtectHiddenVolume ? BST_CHECKED : BST_UNCHECKED, 0); - - SendDlgItemMessage (hwndDlg, IDC_PROTECT_HIDDEN_VOL, BM_SETCHECK, - mountOptions->ProtectHiddenVolume ? BST_CHECKED : BST_UNCHECKED, 0); - - mountOptions->PartitionInInactiveSysEncScope = bPrebootPasswordDlgMode; - - SendDlgItemMessage (hwndDlg, IDC_MOUNT_SYSENC_PART_WITHOUT_PBA, BM_SETCHECK, - bPrebootPasswordDlgMode ? BST_CHECKED : BST_UNCHECKED, 0); - - SendDlgItemMessage (hwndDlg, IDC_USE_EMBEDDED_HEADER_BAK, BM_SETCHECK, - mountOptions->UseBackupHeader ? BST_CHECKED : BST_UNCHECKED, 0); - - EnableWindow (GetDlgItem (hwndDlg, IDC_MOUNT_SYSENC_PART_WITHOUT_PBA), !bPrebootPasswordDlgMode); - - protect = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)); - - EnableWindow (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); - EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_VOL_PROTECTION), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); - EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), protect); - EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_MO), protect); - EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_PROT_PASSWD), protect); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_HIDVOL_PROT), protect); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT), protect); - - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT, hidVolProtKeyFilesParam.EnableKeyFiles); - - SendDlgItemMessage (hwndDlg, IDC_PASSWORD_PROT_HIDVOL, EM_LIMITTEXT, MAX_PASSWORD, 0); - - if (mountOptions->ProtectedHidVolPassword.Length > 0) - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), (LPSTR) mountOptions->ProtectedHidVolPassword.Text); - - ToHyperlink (hwndDlg, IDC_LINK_HIDVOL_PROTECTION_INFO); - - } - return 0; - - case WM_CONTEXTMENU: - { - RECT buttonRect; - GetWindowRect (GetDlgItem (hwndDlg, IDC_KEYFILES_HIDVOL_PROT), &buttonRect); - - if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)) - && LOWORD (lParam) >= buttonRect.left && LOWORD (lParam) <= buttonRect.right - && HIWORD (lParam) >= buttonRect.top && HIWORD (lParam) <= buttonRect.bottom) - { - // The "Keyfiles" button has been right-clicked - - POINT popupPos; - popupPos.x = buttonRect.left + 2; - popupPos.y = buttonRect.top + 2; - - if (KeyfilesPopupMenu (hwndDlg, popupPos, &hidVolProtKeyFilesParam)) - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT, hidVolProtKeyFilesParam.EnableKeyFiles); - } - } - break; - - case WM_COMMAND: - - if (lw == IDC_KEYFILES_HIDVOL_PROT) - { - if (IDOK == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, - (DLGPROC) KeyFilesDlgProc, (LPARAM) &hidVolProtKeyFilesParam)) - { - SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT, hidVolProtKeyFilesParam.EnableKeyFiles); - } - } - - if (lw == IDC_KEYFILES_ENABLE_HIDVOL_PROT) - { - hidVolProtKeyFilesParam.EnableKeyFiles = GetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT); - - return 0; - } - - if (lw == IDC_SHOW_PASSWORD_MO) - { - SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), - EM_SETPASSWORDCHAR, - GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_MO) ? 0 : '*', - 0); - InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), NULL, TRUE); - return 1; - } - - if (lw == IDC_LINK_HIDVOL_PROTECTION_INFO) - { - Applink ("hiddenvolprotection", TRUE, ""); - } - - if (lw == IDCANCEL) - { - char tmp[MAX_PASSWORD+1]; - - // Cleanup - memset (tmp, 'X', MAX_PASSWORD); - tmp[MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), tmp); - - EndDialog (hwndDlg, lw); - return 1; - } - - if (lw == IDOK) - { - char tmp[MAX_PASSWORD+1]; - - mountOptions->ReadOnly = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY)); - mountOptions->Removable = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_REMOVABLE)); - mountOptions->ProtectHiddenVolume = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)); - mountOptions->PartitionInInactiveSysEncScope = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_SYSENC_PART_WITHOUT_PBA)); - mountOptions->UseBackupHeader = IsButtonChecked (GetDlgItem (hwndDlg, IDC_USE_EMBEDDED_HEADER_BAK)); - - if (mountOptions->ProtectHiddenVolume) - { - GetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), - (LPSTR) mountOptions->ProtectedHidVolPassword.Text, - sizeof (mountOptions->ProtectedHidVolPassword.Text)); - - mountOptions->ProtectedHidVolPassword.Length = strlen ((char *) mountOptions->ProtectedHidVolPassword.Text); - } - - // Cleanup - memset (tmp, 'X', MAX_PASSWORD); - tmp[MAX_PASSWORD] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), tmp); - - if ((mountOptions->ProtectHiddenVolume && !bEnableBkgTask) - && (AskWarnYesNo ("HIDVOL_PROT_BKG_TASK_WARNING") == IDYES)) - { - bEnableBkgTask = TRUE; - TaskBarIconAdd (MainDlg); - } - - EndDialog (hwndDlg, lw); - return 1; - } - - if (lw == IDC_MOUNT_READONLY || lw == IDC_PROTECT_HIDDEN_VOL) - { - BOOL protect; - - if (lw == IDC_MOUNT_READONLY) - { - SendDlgItemMessage (hwndDlg, IDC_PROTECT_HIDDEN_VOL, BM_SETCHECK, BST_UNCHECKED, 0); - EnableWindow (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); - EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_VOL_PROTECTION), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); - } - - protect = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)); - - EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), protect); - EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_PROT_PASSWD), protect); - EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_MO), protect); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_HIDVOL_PROT), protect); - EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT), protect); - - return 1; - } - - return 0; - } - - return 0; -} - - -// Returns the block size (in bits) of the cipher with which the volume mounted as the -// specified drive letter is encrypted. In case of a cascade of ciphers with different -// block sizes the function returns the smallest block size. -int GetCipherBlockSizeByDriveNo (int nDosDriveNo) -{ - VOLUME_PROPERTIES_STRUCT prop; - DWORD dwResult; - - int blockSize = 0, cipherID; - - memset (&prop, 0, sizeof(prop)); - prop.driveNo = nDosDriveNo; - - if (DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL)) - { - for (cipherID = EAGetLastCipher (prop.ea); - cipherID != 0; - cipherID = EAGetPreviousCipher (prop.ea, cipherID)) - { - if (blockSize > 0) - blockSize = min (blockSize, CipherGetBlockSize (cipherID) * 8); - else - blockSize = CipherGetBlockSize (cipherID) * 8; - } - } - - return blockSize; -} - - -// Returns the mode of operation in which the volume mounted as the specified drive letter is encrypted. -int GetModeOfOperationByDriveNo (int nDosDriveNo) -{ - VOLUME_PROPERTIES_STRUCT prop; - DWORD dwResult; - - memset (&prop, 0, sizeof(prop)); - prop.driveNo = nDosDriveNo; - - if (DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL)) - { - return prop.mode; - } - - return 0; -} - - -BOOL CALLBACK VolumePropertiesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - BOOL bSysEnc = (BOOL) lParam; - BOOL bSysEncWholeDrive = FALSE; - WORD lw = LOWORD (wParam); - int i = 0; - - switch (msg) - { - case WM_INITDIALOG: - { - VOLUME_PROPERTIES_STRUCT prop; - DWORD dwResult; - - LVCOLUMNW lvCol; - HWND list = GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES_LIST); - char szTmp[1024]; - wchar_t sw[1024]; - wchar_t *s; - - if (bSysEnc) - { - try - { - BootEncStatus = BootEncObj->GetStatus(); - bSysEncWholeDrive = WholeSysDriveEncryption(FALSE); - } - catch (Exception &e) - { - e.Show (MainDlg); - return 0; - } - - if (!BootEncStatus.DriveEncrypted && !BootEncStatus.DriveMounted) - return 0; - } - else - { - switch (LOWORD (GetSelectedLong (GetDlgItem (GetParent(hwndDlg), IDC_DRIVELIST)))) - { - case TC_MLIST_ITEM_FREE: - - // No mounted volume - EndDialog (hwndDlg, IDOK); - return 0; - - case TC_MLIST_ITEM_NONSYS_VOL: - // NOP - break; - - case TC_MLIST_ITEM_SYS_DRIVE: - // Encrypted system drive - bSysEnc = TRUE; - bSysEncWholeDrive = TRUE; - break; - - case TC_MLIST_ITEM_SYS_PARTITION: - // Encrypted system partition - bSysEnc = TRUE; - bSysEncWholeDrive = FALSE; - break; - } - } - - LocalizeDialog (hwndDlg, "IDD_VOLUME_PROPERTIES"); - - SendMessage (list,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, - LVS_EX_FULLROWSELECT - |LVS_EX_HEADERDRAGDROP - |LVS_EX_LABELTIP - ); - - memset (&lvCol,0,sizeof(lvCol)); - lvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - lvCol.pszText = GetString ("VALUE"); - lvCol.cx = CompensateXDPI (208); - lvCol.fmt = LVCFMT_LEFT ; - SendMessage (list,LVM_INSERTCOLUMNW,0,(LPARAM)&lvCol); - - lvCol.pszText = GetString ("PROPERTY"); - lvCol.cx = CompensateXDPI (192); - lvCol.fmt = LVCFMT_LEFT; - SendMessage (list,LVM_INSERTCOLUMNW,0,(LPARAM)&lvCol); - - memset (&prop, 0, sizeof(prop)); - prop.driveNo = HIWORD (GetSelectedLong (GetDlgItem (GetParent(hwndDlg), IDC_DRIVELIST))) - 'A'; - - if (bSysEnc) - { - try - { - BootEncStatus = BootEncObj->GetStatus(); - if (!BootEncStatus.DriveEncrypted && !BootEncStatus.DriveMounted) - return 0; - - BootEncObj->GetVolumeProperties (&prop); - } - catch (Exception &e) - { - e.Show (MainDlg); - return 0; - } - } - else - { - if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL) || dwResult == 0) - return 0; - } - - // Location - ListItemAddW (list, i, GetString ("LOCATION")); - if (bSysEnc) - ListSubItemSetW (list, i++, 1, GetString (bSysEncWholeDrive ? "SYSTEM_DRIVE" : IsHiddenOSRunning() ? "HIDDEN_SYSTEM_PARTITION" : "SYSTEM_PARTITION")); - else - ListSubItemSetW (list, i++, 1, (wchar_t *) (prop.wszVolume[1] != L'?' ? prop.wszVolume : prop.wszVolume + 4)); - - // Size - ListItemAddW (list, i, GetString ("SIZE")); - swprintf (sw, L"%I64u %s", prop.diskLength, GetString ("BYTES")); - ListSubItemSetW (list, i++, 1, sw); - - // Type - ListItemAddW (list, i, GetString ("TYPE")); - if (bSysEnc) - ListSubItemSetW (list, i++, 1, GetString (IsHiddenOSRunning() ? "TYPE_HIDDEN_SYSTEM_ADJECTIVE" : "SYSTEM_VOLUME_TYPE_ADJECTIVE")); - else - { - ListSubItemSetW (list, i++, 1, - prop.hiddenVolume ? GetString ("HIDDEN") : - (prop.hiddenVolProtection != HIDVOL_PROT_STATUS_NONE ? GetString ("OUTER") : GetString ("NORMAL"))); - } - - if (!bSysEnc) - { - // Write protection - ListItemAddW (list, i, GetString ("READ_ONLY")); - - if (prop.readOnly || prop.hiddenVolProtection == HIDVOL_PROT_STATUS_ACTION_TAKEN) - s = GetString ("UISTR_YES"); - else - s = GetString ("UISTR_NO"); - - ListSubItemSetW (list, i++, 1, s); - - // Hidden Volume Protection - ListItemAddW (list, i, GetString ("HIDDEN_VOL_PROTECTION")); - if (prop.hiddenVolume) - s = GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"); - else if (prop.hiddenVolProtection == HIDVOL_PROT_STATUS_NONE) - s = GetString ("UISTR_NO"); - else if (prop.hiddenVolProtection == HIDVOL_PROT_STATUS_ACTIVE) - s = GetString ("UISTR_YES"); - else if (prop.hiddenVolProtection == HIDVOL_PROT_STATUS_ACTION_TAKEN) - s = GetString ("HID_VOL_DAMAGE_PREVENTED"); - - ListSubItemSetW (list, i++, 1, s); - } - - // Encryption algorithm - ListItemAddW (list, i, GetString ("ENCRYPTION_ALGORITHM")); - - if (prop.ea == 0 || prop.ea > EAGetCount ()) - { - ListSubItemSet (list, i, 1, "?"); - return 1; - } - - EAGetName (szTmp, prop.ea); - ListSubItemSet (list, i++, 1, szTmp); - - // Key size(s) - { - char name[128]; - int size = EAGetKeySize (prop.ea); - EAGetName (name, prop.ea); - - if (strcmp (name, "Triple DES") == 0) /* Deprecated/legacy */ - size -= 3; // Compensate for parity bytes - - // Primary key - ListItemAddW (list, i, GetString ("KEY_SIZE")); - wsprintfW (sw, L"%d %s", size * 8, GetString ("BITS")); - ListSubItemSetW (list, i++, 1, sw); - - if (strcmp (EAGetModeName (prop.ea, prop.mode, TRUE), "XTS") == 0) - { - // Secondary key (XTS) - - ListItemAddW (list, i, GetString ("SECONDARY_KEY_SIZE_XTS")); - ListSubItemSetW (list, i++, 1, sw); - } - else if (strcmp (EAGetModeName (prop.ea, prop.mode, TRUE), "LRW") == 0) - { - // Tweak key (LRW) - - ListItemAddW (list, i, GetString ("SECONDARY_KEY_SIZE_LRW")); - swprintf (sw, L"%d %s", CipherGetBlockSize (EAGetFirstCipher(prop.ea))*8, GetString ("BITS")); - ListSubItemSetW (list, i++, 1, sw); - } - } - - // Block size - ListItemAddW (list, i, GetString ("BLOCK_SIZE")); - if (EAGetFirstMode (prop.ea) == INNER_CBC) - { - // Cascaded ciphers with non-equal block sizes (deprecated/legacy) - wchar_t tmpstr[64]; - int i = EAGetLastCipher(prop.ea); - - swprintf (sw, L"%d", CipherGetBlockSize(i)*8); - - while (i = EAGetPreviousCipher(prop.ea, i)) - { - swprintf (tmpstr, L"/%d", CipherGetBlockSize(i)*8); - wcscat (sw, tmpstr); - } - wcscat (sw, L" "); - } - else - { - swprintf (sw, L"%d ", CipherGetBlockSize (EAGetFirstCipher(prop.ea))*8); - } - wcscat (sw, GetString ("BITS")); - ListSubItemSetW (list, i++, 1, sw); - - // Mode - ListItemAddW (list, i, GetString ("MODE_OF_OPERATION")); - ListSubItemSet (list, i++, 1, EAGetModeName (prop.ea, prop.mode, TRUE)); - - // PKCS 5 PRF - ListItemAddW (list, i, GetString ("PKCS5_PRF")); - ListSubItemSet (list, i++, 1, get_pkcs5_prf_name (prop.pkcs5)); - -#if 0 - // PCKS 5 iterations - ListItemAddW (list, i, GetString ("PKCS5_ITERATIONS")); - sprintf (szTmp, "%d", prop.pkcs5Iterations); - ListSubItemSet (list, i++, 1, szTmp); -#endif - -#if 0 - { - // Legacy - - FILETIME ft, curFt; - LARGE_INTEGER ft64, curFt64; - SYSTEMTIME st; - wchar_t date[128]; - memset (date, 0, sizeof (date)); - - // Volume date - ListItemAddW (list, i, GetString ("VOLUME_CREATE_DATE")); - *(unsigned __int64 *)(&ft) = prop.volumeCreationTime; - FileTimeToSystemTime (&ft, &st); - GetDateFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); - swprintf (date, L"%s ", sw); - GetTimeFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); - wcscat (date, sw); - ListSubItemSetW (list, i++, 1, date); - - // Header date - ListItemAddW (list, i, GetString ("VOLUME_HEADER_DATE")); - *(unsigned __int64 *)(&ft) = prop.headerCreationTime; - FileTimeToSystemTime (&ft, &st); - GetDateFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); - swprintf (date, L"%s ", sw); - GetTimeFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); - wcscat (date, sw); - - GetLocalTime (&st); - SystemTimeToFileTime (&st, &curFt); - curFt64.HighPart = curFt.dwHighDateTime; - curFt64.LowPart = curFt.dwLowDateTime; - ft64.HighPart = ft.dwHighDateTime; - ft64.LowPart = ft.dwLowDateTime; - swprintf (date + wcslen (date), GetString ("VOLUME_HEADER_DAYS") - , (curFt64.QuadPart - ft64.QuadPart)/(24LL*3600*10000000)); - ListSubItemSetW (list, i++, 1, date); - } -#endif // 0 - - if (!bSysEnc || IsHiddenOSRunning()) - { - // Volume format version - ListItemAddW (list, i, GetString ("VOLUME_FORMAT_VERSION")); - sprintf (szTmp, "%d", prop.volFormatVersion); - ListSubItemSet (list, i++, 1, szTmp); - - // Backup header - ListItemAddW (list, i, GetString ("BACKUP_HEADER")); - ListSubItemSetW (list, i++, 1, GetString (prop.volFormatVersion > 1 ? "UISTR_YES" : "UISTR_NO")); - } - - // Total data read - ListItemAddW (list, i, GetString ("TOTAL_DATA_READ")); - GetSizeString (prop.totalBytesRead, sw); - ListSubItemSetW (list, i++, 1, sw); - - // Total data written - ListItemAddW (list, i, GetString ("TOTAL_DATA_WRITTEN")); - GetSizeString (prop.totalBytesWritten, sw); - ListSubItemSetW (list, i++, 1, sw); - - if (bSysEnc) - { - // Encrypted portion - ListItemAddW (list, i, GetString ("ENCRYPTED_PORTION")); - if (GetSysEncDeviceEncryptedPartSize (FALSE) == GetSysEncDeviceSize (FALSE)) - ListSubItemSetW (list, i++, 1, GetString ("ENCRYPTED_PORTION_FULLY_ENCRYPTED")); - else if (GetSysEncDeviceEncryptedPartSize (FALSE) <= 1) - ListSubItemSetW (list, i++, 1, GetString ("ENCRYPTED_PORTION_NOT_ENCRYPTED")); - else - { - - _snwprintf (sw, - sizeof sw/2, - GetString ("PROCESSED_PORTION_X_PERCENT"), - (double) GetSysEncDeviceEncryptedPartSize (FALSE) / (double) GetSysEncDeviceSize (FALSE) * 100.0); - - ListSubItemSetW (list, i++, 1, sw); - } - } - - return 0; - } - - case WM_COMMAND: - if (lw == IDOK) - { - EndDialog (hwndDlg, lw); - return 1; - } - return 0; - - case WM_CLOSE: - EndDialog (hwndDlg, lw); - return 1; - } - - return 0; -} - - -BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - static BOOL bAutoRunWarningDisplayed = FALSE; - - switch (msg) - { - case WM_INITDIALOG: - { - int i, index; - char drive[] = { 0, ':', 0 }; - - LocalizeDialog (hwndDlg, "IDD_TRAVELER_DLG"); - - SendDlgItemMessage (hwndDlg, IDC_COPY_WIZARD, BM_SETCHECK, - BST_CHECKED, 0); - - SendDlgItemMessage (hwndDlg, IDC_TRAVEL_OPEN_EXPLORER, BM_SETCHECK, - BST_CHECKED, 0); - - SendDlgItemMessage (hwndDlg, IDC_AUTORUN_DISABLE, BM_SETCHECK, - BST_CHECKED, 0); - - SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_RESETCONTENT, 0, 0); - - index = SendDlgItemMessageW (hwndDlg, IDC_DRIVELIST, CB_ADDSTRING, 0, (LPARAM) GetString ("FIRST_AVAILABLE")); - SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_SETITEMDATA, index, (LPARAM) 0); - - for (i = 'D'; i <= 'Z'; i++) - { - drive[0] = i; - index = SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_ADDSTRING, 0, (LPARAM) drive); - SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_SETITEMDATA, index, (LPARAM) i); - } - - SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_SETCURSEL, 0, 0); - - return 0; - } - - - case WM_COMMAND: - - if (HIWORD (wParam) == BN_CLICKED - && (lw == IDC_AUTORUN_DISABLE || lw == IDC_AUTORUN_MOUNT || lw == IDC_AUTORUN_START )) - { - BOOL enabled = IsButtonChecked (GetDlgItem (hwndDlg, IDC_AUTORUN_MOUNT)); - - EnableWindow (GetDlgItem (hwndDlg, IDC_BROWSE_FILES), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_NAME), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TRAVEL_OPEN_EXPLORER), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TRAV_CACHE_PASSWORDS), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_DRIVELIST), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TRAVELER_MOUNT), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_MOUNT_LETTER), enabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_MOUNT_SETTINGS), enabled); - - if (!bAutoRunWarningDisplayed - && (lw == IDC_AUTORUN_MOUNT || lw == IDC_AUTORUN_START)) - { - bAutoRunWarningDisplayed = TRUE; - Warning ("AUTORUN_MAY_NOT_ALWAYS_WORK"); - } - - return 1; - } - - if (lw == IDC_BROWSE_FILES) - { - char dstDir[MAX_PATH]; - char volName[MAX_PATH] = { 0 }; - - GetDlgItemText (hwndDlg, IDC_DIRECTORY, dstDir, sizeof dstDir); - - if (BrowseFilesInDir (hwndDlg, "OPEN_TITLE", dstDir, volName, bHistory, FALSE, NULL)) - SetDlgItemText (hwndDlg, IDC_VOLUME_NAME, strchr (volName, '\\') + 1); - - return 1; - } - - if (lw == IDC_BROWSE_DIRS) - { - char dstPath[MAX_PATH * 2]; - GetDlgItemText (hwndDlg, IDC_DIRECTORY, dstPath, sizeof dstPath); - - if (BrowseDirectories (hwndDlg, "SELECT_DEST_DIR", dstPath)) - SetDlgItemText (hwndDlg, IDC_DIRECTORY, dstPath); - - return 1; - } - - if (lw == IDCANCEL || lw == IDCLOSE) - { - EndDialog (hwndDlg, lw); - return 1; - } - - if (lw == IDC_CREATE) - { - - BOOL copyWizard, bExplore, bCacheInDriver, bAutoRun, bAutoMount, bMountReadOnly; - char dstDir[MAX_PATH]; - char srcPath[MAX_PATH * 2]; - char dstPath[MAX_PATH * 2]; - char appDir[MAX_PATH]; - char sysDir[MAX_PATH]; - char volName[MAX_PATH]; - int drive; - - GetDlgItemText (hwndDlg, IDC_DIRECTORY, dstDir, sizeof dstDir); - volName[0] = 0; - GetDlgItemText (hwndDlg, IDC_VOLUME_NAME, volName + 1, sizeof volName); - - drive = SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_GETCURSEL, 0, 0); - drive = SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_GETITEMDATA, drive, 0); - - copyWizard = IsButtonChecked (GetDlgItem (hwndDlg, IDC_COPY_WIZARD)); - bExplore = IsButtonChecked (GetDlgItem (hwndDlg, IDC_TRAVEL_OPEN_EXPLORER)); - bCacheInDriver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_TRAV_CACHE_PASSWORDS)); - bMountReadOnly = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY)); - bAutoRun = !IsButtonChecked (GetDlgItem (hwndDlg, IDC_AUTORUN_DISABLE)); - bAutoMount = IsButtonChecked (GetDlgItem (hwndDlg, IDC_AUTORUN_MOUNT)); - - if (dstDir[0] == 0) - { - SetFocus (GetDlgItem (hwndDlg, IDC_DIRECTORY)); - MessageBoxW (hwndDlg, GetString ("NO_PATH_SELECTED"), lpszTitle, MB_ICONEXCLAMATION); - return 1; - } - - - if (bAutoMount && volName[1] == 0) - { - SetFocus (GetDlgItem (hwndDlg, IDC_VOLUME_NAME)); - MessageBoxW (hwndDlg, GetString ("NO_FILE_SELECTED"), lpszTitle, MB_ICONEXCLAMATION); - return 1; - } - - if (volName[1] != 0) - { - volName[0] = '"'; - strcat (volName, "\""); - } - - GetModuleFileName (NULL, appDir, sizeof (appDir)); - strrchr (appDir, '\\')[0] = 0; - - WaitCursor (); - GetSystemDirectory (sysDir, sizeof (sysDir)); - - sprintf (dstPath, "%s\\TrueCrypt", dstDir); - CreateDirectory (dstPath, NULL); - - // Main app - sprintf (srcPath, "%s\\TrueCrypt.exe", appDir); - sprintf (dstPath, "%s\\TrueCrypt\\TrueCrypt.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) - { - handleWin32Error (hwndDlg); - goto stop; - } - - // Wizard - if (copyWizard) - { - sprintf (srcPath, "%s\\TrueCrypt Format.exe", appDir); - sprintf (dstPath, "%s\\TrueCrypt\\TrueCrypt Format.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) - { - handleWin32Error (hwndDlg); - goto stop; - } - } - - // Driver - sprintf (srcPath, "%s\\truecrypt.sys", appDir); - sprintf (dstPath, "%s\\TrueCrypt\\truecrypt.sys", dstDir); - if (!TCCopyFile (srcPath, dstPath)) - { - handleWin32Error (hwndDlg); - goto stop; - } - - // Driver x64 - sprintf (srcPath, "%s\\truecrypt-x64.sys", appDir); - sprintf (dstPath, "%s\\TrueCrypt\\truecrypt-x64.sys", dstDir); - if (!TCCopyFile (srcPath, dstPath)) - { - handleWin32Error (hwndDlg); - goto stop; - } - - if (GetPreferredLangId () && strcmp (GetPreferredLangId (), "en") != 0) - { - // Language pack - sprintf (srcPath, "%s\\Language.%s.xml", appDir, GetPreferredLangId ()); - sprintf (dstPath, "%s\\TrueCrypt\\Language.%s.xml", dstDir, GetPreferredLangId ()); - TCCopyFile (srcPath, dstPath); - } - - // AutoRun - sprintf (dstPath, "%s\\autorun.inf", dstDir); - DeleteFile (dstPath); - if (bAutoRun) - { - FILE *af; - char autoMount[100]; - char driveLetter[] = { ' ', '/', 'l', drive, 0 }; - - af = fopen (dstPath, "w,ccs=UNICODE"); - - if (af == NULL) - { - MessageBoxW (hwndDlg, GetString ("CANT_CREATE_AUTORUN"), lpszTitle, MB_ICONERROR); - goto stop; - } - - sprintf (autoMount, "TrueCrypt\\TrueCrypt.exe /q background%s%s%s%s /m rm /v %s", - drive > 0 ? driveLetter : "", - bExplore ? " /e" : "", - bCacheInDriver ? " /c y" : "", - bMountReadOnly ? " /m ro" : "", - volName); - - fwprintf (af, L"[autorun]\nlabel=%s\nicon=TrueCrypt\\TrueCrypt.exe\n", GetString ("TC_TRAVELER_DISK")); - fwprintf (af, L"action=%s\n", bAutoMount ? GetString ("MOUNT_TC_VOLUME") : GetString ("IDC_PREF_LOGON_START")); - fwprintf (af, L"open=%hs\n", bAutoMount ? autoMount : "TrueCrypt\\TrueCrypt.exe"); - fwprintf (af, L"shell\\start=%s\nshell\\start\\command=TrueCrypt\\TrueCrypt.exe\n", GetString ("IDC_PREF_LOGON_START")); - fwprintf (af, L"shell\\dismount=%s\nshell\\dismount\\command=TrueCrypt\\TrueCrypt.exe /q /d\n", GetString ("DISMOUNT_ALL_TC_VOLUMES")); - - fclose (af); - } - MessageBoxW (hwndDlg, GetString ("TRAVELER_DISK_CREATED"), lpszTitle, MB_ICONINFORMATION); - -stop: - NormalCursor (); - return 1; - } - return 0; - } - - return 0; -} - - -void -BuildTree (HWND hTree) -{ - HIMAGELIST hList; - HBITMAP hBitmap, hBitmapMask; - LVCOLUMNW lvCol; - - ListView_DeleteColumn (hTree,0); - ListView_DeleteColumn (hTree,0); - ListView_DeleteColumn (hTree,0); - ListView_DeleteColumn (hTree,0); - ListView_DeleteColumn (hTree,0); - ListView_DeleteColumn (hTree,0); - - SendMessage(hTree,LVM_SETEXTENDEDLISTVIEWSTYLE,0, - LVS_EX_FULLROWSELECT - |LVS_EX_HEADERDRAGDROP - ); - - memset(&lvCol,0,sizeof(lvCol)); - - lvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - lvCol.pszText = GetString ("DRIVE"); - lvCol.cx = CompensateXDPI (38); - lvCol.fmt = LVCFMT_COL_HAS_IMAGES|LVCFMT_LEFT ; - SendMessage (hTree,LVM_INSERTCOLUMNW,0,(LPARAM)&lvCol); - - lvCol.pszText = GetString ("VOLUME"); - lvCol.cx = CompensateXDPI (253); - lvCol.fmt = LVCFMT_LEFT; - SendMessage (hTree,LVM_INSERTCOLUMNW,1,(LPARAM)&lvCol); - - lvCol.pszText = GetString ("SIZE"); - lvCol.cx = CompensateXDPI (55); - lvCol.fmt = LVCFMT_RIGHT; - SendMessage (hTree,LVM_INSERTCOLUMNW,2,(LPARAM)&lvCol); - - lvCol.pszText = GetString ("ENCRYPTION_ALGORITHM_LV"); - lvCol.cx = CompensateXDPI (121); - lvCol.fmt = LVCFMT_LEFT; - SendMessage (hTree,LVM_INSERTCOLUMNW,3,(LPARAM)&lvCol); - - lvCol.pszText = GetString ("TYPE"); - lvCol.cx = CompensateXDPI (52); - lvCol.fmt = LVCFMT_LEFT; - SendMessage (hTree,LVM_INSERTCOLUMNW,4,(LPARAM)&lvCol); - - // Regular drive icon - - hBitmap = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_DRIVEICON)); - if (hBitmap == NULL) - return; - hBitmapMask = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_DRIVEICON_MASK)); - - hList = ImageList_Create (16, 12, ILC_COLOR8|ILC_MASK, 2, 2); - if (ImageList_Add (hList, hBitmap, hBitmapMask) == -1) - { - DeleteObject (hBitmap); - DeleteObject (hBitmapMask); - return; - } - else - { - DeleteObject (hBitmap); - DeleteObject (hBitmapMask); - } - - // System drive icon - - hBitmap = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_SYS_DRIVEICON)); - if (hBitmap == NULL) - return; - hBitmapMask = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_SYS_DRIVEICON_MASK)); - - if (ImageList_Add (hList, hBitmap, hBitmapMask) == -1) - { - DeleteObject (hBitmap); - DeleteObject (hBitmapMask); - return; - } - else - { - DeleteObject (hBitmap); - DeleteObject (hBitmapMask); - } - - ListView_SetImageList (hTree, hList, LVSIL_NORMAL); - ListView_SetImageList (hTree, hList, LVSIL_SMALL); - - LoadDriveLetters (hTree, 0); -} - -LPARAM -GetSelectedLong (HWND hTree) -{ - int hItem = ListView_GetSelectionMark (hTree); - LVITEM item; - - if (nSelectedDriveIndex >= 0) - hItem = nSelectedDriveIndex; - - memset(&item, 0, sizeof(LVITEM)); - item.mask = LVIF_PARAM; - item.iItem = hItem; - - if (ListView_GetItem (hTree, &item) == FALSE) - return MAKELONG (0xffff, 0xffff); - else - return item.lParam; -} - -LPARAM -GetItemLong (HWND hTree, int itemNo) -{ - LVITEM item; - - memset(&item, 0, sizeof(LVITEM)); - item.mask = LVIF_PARAM; - item.iItem = itemNo; - - if (ListView_GetItem (hTree, &item) == FALSE) - return MAKELONG (0xffff, 0xffff); - else - return item.lParam; -} - -static int AskVolumePassword (HWND hwndDlg, Password *password, char *titleStringId, BOOL enableMountOptions) -{ - int result; - - PasswordDialogTitleStringId = titleStringId; - PasswordDialogDisableMountOptions = !enableMountOptions; - - result = DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_PASSWORD_DLG), hwndDlg, - (DLGPROC) PasswordDlgProc, (LPARAM) password); - - if (result != IDOK) - { - password->Length = 0; - burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); - } - - return result == IDOK; -} - -// GUI actions - -static BOOL Mount (HWND hwndDlg, int nDosDriveNo, char *szFileName) -{ - BOOL status = FALSE; - char fileName[MAX_PATH]; - int mounted = 0, modeOfOperation; - if (nDosDriveNo == 0) - nDosDriveNo = HIWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) - 'A'; - - VolumePassword.Length = 0; - - if (szFileName == NULL) - { - GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), fileName, sizeof (fileName)); - szFileName = fileName; - } - - if (strlen(szFileName) == 0) - { - status = FALSE; - goto ret; - } - - if (IsMountedVolume (szFileName)) - { - Warning ("VOL_ALREADY_MOUNTED"); - status = FALSE; - goto ret; - } - - ResetWrongPwdRetryCount (); - - // First try cached passwords and if they fail ask user for a new one - WaitCursor (); - - mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, NULL, bCacheInDriver, bForceMount, &mountOptions, FALSE, FALSE); - - // If keyfiles are enabled, test empty password first - if (!mounted && KeyFilesEnable) - { - KeyFilesApply (&VolumePassword, FirstKeyFile); - mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, FALSE, FALSE); - } - - NormalCursor (); - - if (mounted) - { - // Check for deprecated CBC mode - modeOfOperation = GetModeOfOperationByDriveNo (nDosDriveNo); - if (modeOfOperation == CBC || modeOfOperation == OUTER_CBC) - Warning("WARN_CBC_MODE"); - - // Check for deprecated 64-bit-block ciphers - if (GetCipherBlockSizeByDriveNo (nDosDriveNo) == 64) - Warning("WARN_64_BIT_BLOCK_CIPHER"); - - // Check for problematic file extensions (exe, dll, sys) - if (CheckFileExtension(szFileName)) - Warning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); - } - - while (mounted == 0) - { - if (CmdVolumePassword.Length > 0) - { - VolumePassword = CmdVolumePassword; - } - else if (!Silent) - { - strcpy (PasswordDlgVolume, szFileName); - if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, TRUE)) - goto ret; - } - - WaitCursor (); - - if (KeyFilesEnable) - KeyFilesApply (&VolumePassword, FirstKeyFile); - - mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, FALSE, TRUE); - NormalCursor (); - - // Check for deprecated CBC mode - modeOfOperation = GetModeOfOperationByDriveNo (nDosDriveNo); - if (modeOfOperation == CBC || modeOfOperation == OUTER_CBC) - Warning("WARN_CBC_MODE"); - - // Check for deprecated 64-bit-block ciphers - if (GetCipherBlockSizeByDriveNo (nDosDriveNo) == 64) - Warning("WARN_64_BIT_BLOCK_CIPHER"); - - // Check for legacy non-ASCII passwords - if (mounted > 0 && !KeyFilesEnable && !CheckPasswordCharEncoding (NULL, &VolumePassword)) - Warning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); - - // Check for problematic file extensions (exe, dll, sys) - if (mounted > 0 && CheckFileExtension (szFileName)) - Warning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); - - burn (&VolumePassword, sizeof (VolumePassword)); - burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); - - if (CmdVolumePassword.Length > 0 || Silent) - break; - } - - if (mounted > 0) - { - status = TRUE; - - if (bBeep) - MessageBeep (-1); - - RefreshMainDlg(hwndDlg); - - if (bExplore) - { - WaitCursor(); - OpenVolumeExplorerWindow (nDosDriveNo); - NormalCursor(); - } - - if (mountOptions.ProtectHiddenVolume) - Info ("HIDVOL_PROT_WARN_AFTER_MOUNT"); - } - -ret: - burn (&VolumePassword, sizeof (VolumePassword)); - burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); - - RestoreDefaultKeyFilesParam (); - - if (UsePreferences) - bCacheInDriver = bCacheInDriverDefault; - - if (status && CloseSecurityTokenSessionsAfterMount && !MultipleMountOperationInProgress) - SecurityToken::CloseAllSessions(); - - return status; -} - - -static BOOL Dismount (HWND hwndDlg, int nDosDriveNo) -{ - BOOL status = FALSE; - WaitCursor (); - - if (nDosDriveNo == 0) - nDosDriveNo = (char) (HIWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) - 'A'); - - if (bCloseDismountedWindows) - { - CloseVolumeExplorerWindows (hwndDlg, nDosDriveNo); - } - - if (UnmountVolume (hwndDlg, nDosDriveNo, bForceUnmount)) - { - status = TRUE; - - if (bBeep) - MessageBeep (-1); - RefreshMainDlg (hwndDlg); - - if (nCurrentOS == WIN_2000 && RemoteSession && !IsAdmin ()) - LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), 0); - } - - NormalCursor (); - return status; -} - -static BOOL DismountAll (HWND hwndDlg, BOOL forceUnmount, BOOL interact, int dismountMaxRetries, int dismountAutoRetryDelay) -{ - BOOL status = TRUE; - MOUNT_LIST_STRUCT mountList; - DWORD dwResult; - UNMOUNT_STRUCT unmount; - BOOL bResult; - unsigned __int32 prevMountedDrives = 0; - int i; - -retry: - WaitCursor(); - - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mountList, sizeof (mountList), &mountList, sizeof (mountList), &dwResult, NULL); - - if (mountList.ulMountedDrives == 0) - { - NormalCursor(); - return TRUE; - } - - BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, 0, mountList.ulMountedDrives); - - prevMountedDrives = mountList.ulMountedDrives; - - for (i = 0; i < 26; i++) - { - if (mountList.ulMountedDrives & (1 << i)) - { - if (bCloseDismountedWindows) - CloseVolumeExplorerWindows (hwndDlg, i); - } - } - - unmount.nDosDriveNo = 0; - unmount.ignoreOpenFiles = forceUnmount; - - do - { - bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_ALL_VOLUMES, &unmount, - sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); - - if (bResult == FALSE) - { - NormalCursor(); - handleWin32Error (hwndDlg); - return FALSE; - } - - if (unmount.nReturnCode == ERR_SUCCESS - && unmount.HiddenVolumeProtectionTriggered - && !VolumeNotificationsList.bHidVolDamagePrevReported [unmount.nDosDriveNo]) - { - wchar_t msg[4096]; - - VolumeNotificationsList.bHidVolDamagePrevReported [unmount.nDosDriveNo] = TRUE; - swprintf (msg, GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), unmount.nDosDriveNo + 'A'); - SetForegroundWindow (hwndDlg); - MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - - unmount.HiddenVolumeProtectionTriggered = FALSE; - continue; - } - - if (unmount.nReturnCode == ERR_FILES_OPEN) - Sleep (dismountAutoRetryDelay); - else - break; - - } while (--dismountMaxRetries > 0); - - memset (&mountList, 0, sizeof (mountList)); - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mountList, sizeof (mountList), &mountList, sizeof (mountList), &dwResult, NULL); - BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, 0, prevMountedDrives & ~mountList.ulMountedDrives); - - RefreshMainDlg (hwndDlg); - - if (nCurrentOS == WIN_2000 && RemoteSession && !IsAdmin ()) - LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), 0); - - NormalCursor(); - - if (unmount.nReturnCode != 0) - { - if (forceUnmount) - status = FALSE; - - if (unmount.nReturnCode == ERR_FILES_OPEN) - { - if (interact && IDYES == AskWarnNoYes ("UNMOUNTALL_LOCK_FAILED")) - { - forceUnmount = TRUE; - goto retry; - } - - return FALSE; - } - - if (interact) - MessageBoxW (hwndDlg, GetString ("UNMOUNT_FAILED"), lpszTitle, MB_ICONERROR); - } - else - { - if (bBeep) - MessageBeep (-1); - } - - return status; -} - -static BOOL MountAllDevices (HWND hwndDlg, BOOL bPasswordPrompt) -{ - HWND driveList = GetDlgItem (hwndDlg, IDC_DRIVELIST); - int selDrive = ListView_GetSelectionMark (driveList); - BOOL shared = FALSE, status = FALSE, b64BitBlockCipher = FALSE, bCBCMode = FALSE, bHeaderBakRetry = FALSE; - int mountedVolCount = 0, modeOfOperation; - vector devices; - - VolumePassword.Length = 0; - mountOptions = defaultMountOptions; - bPrebootPasswordDlgMode = FALSE; - - if (selDrive == -1) - selDrive = 0; - - ResetWrongPwdRetryCount (); - - MultipleMountOperationInProgress = TRUE; - - do - { - if (!bHeaderBakRetry) - { - if (!CmdVolumePasswordValid && bPasswordPrompt) - { - PasswordDlgVolume[0] = '\0'; - if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, TRUE)) - goto ret; - } - else if (CmdVolumePasswordValid) - { - bPasswordPrompt = FALSE; - VolumePassword = CmdVolumePassword; - } - - WaitCursor(); - - if (FirstCmdKeyFile) - KeyFilesApply (&VolumePassword, FirstCmdKeyFile); - else if (KeyFilesEnable) - KeyFilesApply (&VolumePassword, FirstKeyFile); - - } - - if (devices.empty()) - devices = GetAvailableHostDevices (true, false, true, true); - - foreach (const HostDevice &drive, devices) - { - vector partitions = drive.Partitions; - partitions.insert (partitions.begin(), drive); - - foreach (const HostDevice &device, partitions) - { - char szFileName[TC_MAX_PATH]; - strcpy_s (szFileName, sizeof (szFileName), device.Path.c_str()); - BOOL mounted = IsMountedVolume (szFileName); - - // Skip other partitions of the disk if partition0 (whole disk) is mounted - if (!device.IsPartition && mounted) - break; - - if (device.Floppy) - break; - - if (device.HasUnencryptedFilesystem && !mountOptions.UseBackupHeader && !bHeaderBakRetry) - continue; - - if (!mounted) - { - int nDosDriveNo; - - while (LOWORD (GetItemLong (driveList, selDrive)) != 0xffff) - { - if(LOWORD (GetItemLong (driveList, selDrive)) != TC_MLIST_ITEM_FREE) - { - selDrive++; - continue; - } - nDosDriveNo = HIWORD(GetItemLong (driveList, selDrive)) - 'A'; - break; - } - - if (LOWORD (GetItemLong (driveList, selDrive)) == 0xffff) - goto ret; - - // First try user password then cached passwords - if ((mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, TRUE, FALSE)) > 0 - || (mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, NULL, bCacheInDriver, bForceMount, &mountOptions, TRUE, FALSE)) > 0) - { - // A volume has been successfully mounted - - ResetWrongPwdRetryCount (); - - if (mounted == 2) - shared = TRUE; - - LoadDriveLetters (driveList, (HIWORD (GetItemLong (GetDlgItem (hwndDlg, IDC_DRIVELIST), selDrive)))); - selDrive++; - - if (bExplore) - { - WaitCursor(); - OpenVolumeExplorerWindow (nDosDriveNo); - NormalCursor(); - } - - if (bBeep) - MessageBeep (-1); - - status = TRUE; - - // Check for deprecated CBC mode - modeOfOperation = GetModeOfOperationByDriveNo (nDosDriveNo); - bCBCMode = (modeOfOperation == CBC || modeOfOperation == OUTER_CBC); - - if (GetCipherBlockSizeByDriveNo(nDosDriveNo) == 64) - b64BitBlockCipher = TRUE; - - mountedVolCount++; - - // Skip other partitions of the disk if partition0 (whole disk) has been mounted - if (!device.IsPartition) - break; - } - } - } - } - - if (mountedVolCount < 1) - { - // Failed to mount any volume - - IncreaseWrongPwdRetryCount (1); - - if (WrongPwdRetryCountOverLimit () - && !mountOptions.UseBackupHeader - && !bHeaderBakRetry) - { - // Retry using embedded header backup (if any) - mountOptions.UseBackupHeader = TRUE; - bHeaderBakRetry = TRUE; - } - else if (bHeaderBakRetry) - { - mountOptions.UseBackupHeader = defaultMountOptions.UseBackupHeader; - bHeaderBakRetry = FALSE; - } - - if (!Silent && !bHeaderBakRetry) - { - WCHAR szTmp[4096]; - - swprintf (szTmp, GetString (KeyFilesEnable || FirstCmdKeyFile ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT")); - if (CheckCapsLock (hwndDlg, TRUE)) - wcscat (szTmp, GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); - - MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONWARNING); - } - } - else if (bHeaderBakRetry) - { - // We have successfully mounted a volume using the header backup embedded in the volume (the header is damaged) - mountOptions.UseBackupHeader = defaultMountOptions.UseBackupHeader; - bHeaderBakRetry = FALSE; - - if (!Silent) - Warning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); - } - - if (!bHeaderBakRetry) - { - burn (&VolumePassword, sizeof (VolumePassword)); - burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); - } - - } while (bPasswordPrompt && mountedVolCount < 1); - - /* One or more volumes successfully mounted */ - - ResetWrongPwdRetryCount (); - - if (shared) - Warning ("DEVICE_IN_USE_INFO"); - - if (mountOptions.ProtectHiddenVolume) - { - if (mountedVolCount > 1) - Info ("HIDVOL_PROT_WARN_AFTER_MOUNT_PLURAL"); - else if (mountedVolCount == 1) - Info ("HIDVOL_PROT_WARN_AFTER_MOUNT"); - } - - // Check for deprecated CBC mode - if (bCBCMode) - Warning("WARN_CBC_MODE"); - - // Check for deprecated 64-bit-block ciphers - if (b64BitBlockCipher) - Warning("WARN_64_BIT_BLOCK_CIPHER"); - - // Check for legacy non-ASCII passwords - if (!KeyFilesEnable - && !FirstCmdKeyFile - && mountedVolCount > 0 - && !CheckPasswordCharEncoding (NULL, &VolumePassword)) - Warning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); - - if (status && CloseSecurityTokenSessionsAfterMount) - SecurityToken::CloseAllSessions(); - -ret: - MultipleMountOperationInProgress = FALSE; - - burn (&VolumePassword, sizeof (VolumePassword)); - burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); - - mountOptions.UseBackupHeader = defaultMountOptions.UseBackupHeader; - - RestoreDefaultKeyFilesParam (); - - if (UsePreferences) - bCacheInDriver = bCacheInDriverDefault; - - EnableDisableButtons (hwndDlg); - - NormalCursor(); - - return status; -} - -static void ChangePassword (HWND hwndDlg) -{ - int result; - - GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, sizeof (szFileName)); - if (IsMountedVolume (szFileName)) - { - Warning (pwdChangeDlgMode == PCDM_CHANGE_PKCS5_PRF ? "MOUNTED_NO_PKCS5_PRF_CHANGE" : "MOUNTED_NOPWCHANGE"); - return; - } - - bSysEncPwdChangeDlgMode = FALSE; - - result = DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_PASSWORDCHANGE_DLG), hwndDlg, - (DLGPROC) PasswordChangeDlgProc); - - if (result == IDOK) - { - switch (pwdChangeDlgMode) - { - case PCDM_CHANGE_PKCS5_PRF: - Info ("PKCS5_PRF_CHANGED"); - break; - - case PCDM_ADD_REMOVE_VOL_KEYFILES: - case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: - Info ("KEYFILE_CHANGED"); - break; - - case PCDM_CHANGE_PASSWORD: - default: - Info ("PASSWORD_CHANGED"); - } - } -} - -// Change password of the system partition/drive -static void ChangeSysEncPassword (HWND hwndDlg, BOOL bOnlyChangeKDF) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - if (!BootEncStatus.DriveEncrypted - && !BootEncStatus.DriveMounted - && !BootEncStatus.VolumeHeaderPresent - && !SysEncryptionOrDecryptionRequired ()) - { - Warning ("SYS_DRIVE_NOT_ENCRYPTED"); - return; - } - - if (SysEncryptionOrDecryptionRequired () - || BootEncStatus.SetupInProgress) - { - Warning ("SYSTEM_ENCRYPTION_NOT_COMPLETED"); - return; - } - - if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption - { - sprintf (OrigKeyboardLayout, "%08X", (DWORD) GetKeyboardLayout (NULL) & 0xFFFF); - - bSysEncPwdChangeDlgMode = TRUE; - - if (bOnlyChangeKDF) - pwdChangeDlgMode = PCDM_CHANGE_PKCS5_PRF; - else - pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; - - - if (DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_PASSWORDCHANGE_DLG), hwndDlg, - (DLGPROC) PasswordChangeDlgProc) == IDOK) - { - switch (pwdChangeDlgMode) - { - case PCDM_CHANGE_PKCS5_PRF: - Info ("PKCS5_PRF_CHANGED"); - - if (!IsHiddenOSRunning()) - { - if (AskWarnYesNo ("SYS_HKD_ALGO_CHANGED_ASK_RESCUE_DISK") == IDYES) - CreateRescueDisk (); - } - - break; - - case PCDM_ADD_REMOVE_VOL_KEYFILES: - case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: - // NOP - Keyfiles are not supported for system encryption - break; - - case PCDM_CHANGE_PASSWORD: - default: - Info ("PASSWORD_CHANGED"); - - if (!IsHiddenOSRunning()) - { - if (AskWarnYesNo ("SYS_PASSWORD_CHANGED_ASK_RESCUE_DISK") == IDYES) - CreateRescueDisk (); - } - } - } - - bSysEncPwdChangeDlgMode = FALSE; - - if (bKeyboardLayoutChanged) - { - // Restore the original keyboard layout - if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) - Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); - else - bKeyboardLayoutChanged = FALSE; - } - - bKeybLayoutAltKeyWarningShown = FALSE; - - CloseSysEncMutex (); - } - else - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); -} - -// Initiates or resumes encryption of the system partition/drive -static void EncryptSystemDevice (void) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - if (!BootEncStatus.DriveEncrypted - && !BootEncStatus.DriveMounted - && !SysEncryptionOrDecryptionRequired ()) - { - // System partition/drive is not encrypted (nothing to resume). Initiate the process. - - if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption - { - LaunchVolCreationWizard (MainDlg, "/sysenc"); - } - else - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - - return; - } - else if (SysEncryptionOrDecryptionRequired ()) - { - // System partition/drive encryption already initiated but is incomplete -- attempt to resume the process. - // Note that this also covers the pretest phase and paused decryption (reverses decrypting and starts encrypting) - - if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption - { - LaunchVolCreationWizard (MainDlg, "/sysenc"); - } - else - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); - } - else if (SysDriveOrPartitionFullyEncrypted (FALSE)) - { - // System partition/drive appears to be fully encrypted - Info ("SYS_PARTITION_OR_DRIVE_APPEARS_FULLY_ENCRYPTED"); - return; - } -} - -// Initiates decryption of the system partition/drive -static void DecryptSystemDevice (void) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - if (!BootEncStatus.DriveEncrypted - && !BootEncStatus.DriveMounted - && !BootEncStatus.DeviceFilterActive - && !BootEncStatus.VolumeHeaderPresent - && !SysEncryptionOrDecryptionRequired ()) - { - Warning ("SYS_DRIVE_NOT_ENCRYPTED"); - return; - } - - if (IsHiddenOSRunning()) - { - Warning ("CANNOT_DECRYPT_HIDDEN_OS"); - return; - } - - if (AskNoYes ("CONFIRM_DECRYPT_SYS_DEVICE") == IDNO) - return; - - if (AskWarnNoYes ("CONFIRM_DECRYPT_SYS_DEVICE_CAUTION") == IDNO) - return; - - if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption - { - try - { - // User-mode app may have crashed and its mutex may have gotten lost, so we need to check the driver status too - if (BootEncStatus.SetupInProgress) - { - int attempts = 20; - - BootEncObj->AbortSetup (); - while (BootEncStatus.SetupInProgress && attempts > 0) - { - Sleep (100); - BootEncStatus = BootEncObj->GetStatus(); - attempts--; - WaitCursor(); - } - } - } - catch (Exception &e) - { - e.Show (MainDlg); - } - NormalCursor (); - - if (BootEncStatus.SetupInProgress) - { - CloseSysEncMutex (); - Error ("SYS_ENCRYPTION_OR_DECRYPTION_IN_PROGRESS"); - return; - } - - CloseSysEncMutex (); - LaunchVolCreationWizard (MainDlg, "/dsysenc"); - } - else - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); -} - -// Initiates the process of creation of a hidden operating system -static void CreateHiddenOS (void) -{ - - // Display brief information as to what a hidden operating system is and what it's good for. This needs to be - // done, because if the system partition/drive is currently encrypted, the wizard will not display any - // such information, but will exit (displaying only an error meessage). - Info("HIDDEN_OS_PREINFO"); - - LaunchVolCreationWizard (MainDlg, "/isysenc"); -} - -// Blindly attempts (without any checks) to instruct the wizard to resume whatever system encryption process -// had been interrupted or not started but scheduled or exptected to start. -static void ResumeInterruptedSysEncProcess (void) -{ - if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption - { - LaunchVolCreationWizard (MainDlg, "/csysenc"); - } - else - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); -} - -void CreateRescueDisk (void) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - if (IsHiddenOSRunning()) - { - Warning ("CANNOT_CREATE_RESCUE_DISK_ON_HIDDEN_OS"); - return; - } - - if (!BootEncStatus.DriveEncrypted - && !BootEncStatus.DriveMounted - && !BootEncStatus.VolumeHeaderPresent - && !SysEncryptionOrDecryptionRequired ()) - { - Warning ("SYS_DRIVE_NOT_ENCRYPTED"); - return; - } - - if (SysEncryptionOrDecryptionRequired () - || BootEncStatus.SetupInProgress) - { - Warning ("SYSTEM_ENCRYPTION_NOT_COMPLETED"); - return; - } - - if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption - { - try - { - wchar_t szTmp [8096]; - char szRescueDiskISO [TC_MAX_PATH+1]; - - if (AskOkCancel ("RESCUE_DISK_NON_WIZARD_CREATION_SELECT_PATH") != IDOK) - { - CloseSysEncMutex (); - return; - } - - if (BrowseFiles (MainDlg, "OPEN_TITLE", szRescueDiskISO, FALSE, TRUE, NULL) == FALSE) - { - CloseSysEncMutex (); - return; - } - - WaitCursor(); - BootEncObj->CreateRescueIsoImage (false, szRescueDiskISO); - - _snwprintf (szTmp, sizeof szTmp / 2, - GetString ("RESCUE_DISK_NON_WIZARD_CREATION_BURN"), - szRescueDiskISO); - - MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); - } - catch (Exception &e) - { - e.Show (MainDlg); - Error ("ERROR_CREATING_RESCUE_DISK"); - } - CloseSysEncMutex (); - - NormalCursor (); - } - else - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); -} - -static void VerifyRescueDisk (void) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - if (!BootEncStatus.DriveEncrypted - && !BootEncStatus.DriveMounted - && !BootEncStatus.VolumeHeaderPresent - && !SysEncryptionOrDecryptionRequired ()) - { - Warning ("SYS_DRIVE_NOT_ENCRYPTED"); - return; - } - - if (SysEncryptionOrDecryptionRequired () - || BootEncStatus.SetupInProgress) - { - Warning ("SYSTEM_ENCRYPTION_NOT_COMPLETED"); - return; - } - - if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption - { - try - { - if (AskOkCancel ("RESCUE_DISK_NON_WIZARD_CHECK_INSERT") != IDOK) - { - CloseSysEncMutex (); - return; - } - - // Create a temporary up-to-date rescue disk image in RAM (with it the CD/DVD content will be compared) - BootEncObj->CreateRescueIsoImage (false, ""); - - WaitCursor(); - if (!BootEncObj->VerifyRescueDisk ()) - Error ("RESCUE_DISK_NON_WIZARD_CHECK_FAILED"); - else - Info ("RESCUE_DISK_NON_WIZARD_CHECK_PASSED"); - } - catch (Exception &e) - { - e.Show (MainDlg); - Error ("RESCUE_DISK_NON_WIZARD_CHECK_FAILED"); - } - CloseSysEncMutex (); - - NormalCursor (); - } - else - Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); -} - -static void ShowSystemEncryptionStatus (void) -{ - try - { - BootEncStatus = BootEncObj->GetStatus(); - } - catch (Exception &e) - { - e.Show (MainDlg); - } - - if (GetAsyncKeyState (VK_SHIFT) < 0 && GetAsyncKeyState (VK_CONTROL) < 0) - { - // Ctrl+Shift held (for debugging purposes) - - DebugMsgBox ("Debugging information for system encryption:\n\nDeviceFilterActive: %d\nBootLoaderVersion: %x\nSetupInProgress: %d\nSetupMode: %d\nVolumeHeaderPresent: %d\nDriveMounted: %d\nDriveEncrypted: %d\n" - "HiddenSystem: %d\nHiddenSystemPartitionStart: %I64d\n" - "ConfiguredEncryptedAreaStart: %I64d\nConfiguredEncryptedAreaEnd: %I64d\nEncryptedAreaStart: %I64d\nEncryptedAreaEnd: %I64d\nEncrypted: %I64d%%", - BootEncStatus.DeviceFilterActive, - BootEncStatus.BootLoaderVersion, - BootEncStatus.SetupInProgress, - BootEncStatus.SetupMode, - BootEncStatus.VolumeHeaderPresent, - BootEncStatus.DriveMounted, - BootEncStatus.DriveEncrypted, - BootEncStatus.HiddenSystem ? 1 : 0, - BootEncStatus.HiddenSystemPartitionStart, - BootEncStatus.ConfiguredEncryptedAreaStart, - BootEncStatus.ConfiguredEncryptedAreaEnd, - BootEncStatus.EncryptedAreaStart, - BootEncStatus.EncryptedAreaEnd, - !BootEncStatus.DriveEncrypted ? 0 : (BootEncStatus.EncryptedAreaEnd + 1 - BootEncStatus.EncryptedAreaStart) * 100I64 / (BootEncStatus.ConfiguredEncryptedAreaEnd + 1 - BootEncStatus.ConfiguredEncryptedAreaStart)); - } - - if (!BootEncStatus.DriveEncrypted && !BootEncStatus.DriveMounted) - { - Info ("SYS_DRIVE_NOT_ENCRYPTED"); - return; - } - - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_VOLUME_PROPERTIES), MainDlg, - (DLGPROC) VolumePropertiesDlgProc, (LPARAM) TRUE); - -} - -static void ResumeInterruptedNonSysInplaceEncProcess (void) -{ - // IMPORTANT: This function must not check any config files! Otherwise, if a config file was lost or corrupt, - // the user would not be able resume encryption and the data on the volume would be inaccessible. - - LaunchVolCreationWizard (MainDlg, "/zinplace"); -} - -static BOOL SelectContainer (HWND hwndDlg) -{ - if (BrowseFiles (hwndDlg, "OPEN_VOL_TITLE", szFileName, bHistory, FALSE, NULL) == FALSE) - return FALSE; - - AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); - EnableDisableButtons (hwndDlg); - SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - return TRUE; -} - -static BOOL SelectPartition (HWND hwndDlg) -{ - int nResult = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RAWDEVICES_DLG), hwndDlg, - (DLGPROC) RawDevicesDlgProc, (LPARAM) & szFileName[0]); - if (nResult == IDOK) - { - AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); - EnableDisableButtons (hwndDlg); - SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - return TRUE; - } - - return FALSE; -} - -static void WipeCache (HWND hwndDlg, BOOL silent) -{ - DWORD dwResult; - BOOL bResult; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - if (hwndDlg == NULL) - return; - - if (bResult == FALSE) - handleWin32Error (hwndDlg); - else - { - EnableDisableButtons (hwndDlg); - - if (!silent) - Info ("PASSWORD_CACHE_WIPED"); - } -} - -static void Benchmark (HWND hwndDlg) -{ - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_BENCHMARK_DLG), hwndDlg, - (DLGPROC) BenchmarkDlgProc, (LPARAM) NULL); -} - - -static BOOL CheckMountList () -{ - MOUNT_LIST_STRUCT current; - GetMountList (¤t); - static BootEncryptionStatus newBootEncStatus; - - if (LastKnownLogicalDrives != GetLogicalDrives() - || memcmp (&LastKnownMountList, ¤t, sizeof (current)) != 0) - { - int selDrive; - - WaitCursor (); - LastKnownMountList = current; - - selDrive = HIWORD (GetSelectedLong (GetDlgItem (MainDlg, IDC_DRIVELIST))); - LoadDriveLetters (GetDlgItem (MainDlg, IDC_DRIVELIST), 0); - NormalCursor (); - - if ((current.ulMountedDrives & (1 << (selDrive - 'A'))) == 0 && !IsDriveAvailable (selDrive - 'A')) - { - nSelectedDriveIndex = -1; - return FALSE; - } - - if (nSelectedDriveIndex >= 0) - { - SelectItem (GetDlgItem (MainDlg, IDC_DRIVELIST),selDrive); - - if(nSelectedDriveIndex > SendMessage (GetDlgItem (MainDlg, IDC_DRIVELIST), LVM_GETITEMCOUNT, 0, 0)/2) - SendMessage(GetDlgItem (MainDlg, IDC_DRIVELIST), LVM_SCROLL, 0, 1000); - } - } - - try - { - newBootEncStatus = BootEncObj->GetStatus(); - - if (newBootEncStatus.SetupInProgress != RecentBootEncStatus.SetupInProgress - || newBootEncStatus.EncryptedAreaEnd != RecentBootEncStatus.EncryptedAreaEnd - || newBootEncStatus.DriveEncrypted != RecentBootEncStatus.DriveEncrypted - || newBootEncStatus.DriveMounted != RecentBootEncStatus.DriveMounted - || newBootEncStatus.SetupMode != RecentBootEncStatus.SetupMode - || newBootEncStatus.EncryptedAreaStart != RecentBootEncStatus.EncryptedAreaStart) - { - /* System encryption status change */ - - int selDrive; - int driveLetterToRefresh; - - if (RecentBootEncStatus.DriveMounted == newBootEncStatus.DriveMounted) // If an icon (and whole new line) for a system device isn't to be added/removed - { - // Partial refresh - if (WholeSysDriveEncryption (TRUE)) - { - // System drive (not just partition) - driveLetterToRefresh = ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER; - } - else - { - // System partition - driveLetterToRefresh = GetSystemDriveLetter (); - } - } - else - { - // Full rebuild of the mount list - driveLetterToRefresh = 0; - } - - WaitCursor (); - - selDrive = HIWORD (GetSelectedLong (GetDlgItem (MainDlg, IDC_DRIVELIST))); - LoadDriveLetters (GetDlgItem (MainDlg, IDC_DRIVELIST), driveLetterToRefresh); - - memcpy (&RecentBootEncStatus, &newBootEncStatus, sizeof (RecentBootEncStatus)); - - NormalCursor (); - - if ((current.ulMountedDrives & (1 << (selDrive - 'A'))) == 0 && !IsDriveAvailable (selDrive - 'A')) - { - nSelectedDriveIndex = -1; - } - - if (nSelectedDriveIndex >= 0) - { - SelectItem (GetDlgItem (MainDlg, IDC_DRIVELIST),selDrive); - - //if(nSelectedDriveIndex > SendMessage (GetDlgItem (MainDlg, IDC_DRIVELIST), LVM_GETITEMCOUNT, 0, 0)/2) - // SendMessage(GetDlgItem (MainDlg, IDC_DRIVELIST), LVM_SCROLL, 0, 1000); - } - } - - /* Miscellaneous notifications */ - - // Hibernation prevention notifications - if (newBootEncStatus.HibernationPreventionCount != RecentBootEncStatus.HibernationPreventionCount - && !bHibernationPreventionNotified) - { - bHibernationPreventionNotified = TRUE; - RecentBootEncStatus.HibernationPreventionCount = newBootEncStatus.HibernationPreventionCount; - Warning ("SYS_ENC_HIBERNATION_PREVENTED"); - } - - // Write mode prevention (hidden OS leak protection) - if (IsHiddenOSRunning()) - { - if (newBootEncStatus.HiddenSysLeakProtectionCount != RecentBootEncStatus.HiddenSysLeakProtectionCount - && !bHiddenSysLeakProtNotifiedDuringSession) - { - bHiddenSysLeakProtNotifiedDuringSession = TRUE; - - switch (HiddenSysLeakProtectionNotificationStatus) - { - case TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_COMPACT: - { - char *tmp[] = {0, "HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO", "SHOW_MORE_INFORMATION", "DO_NOT_SHOW_THIS_AGAIN", "CONTINUE", 0}; - switch (AskMultiChoice ((void **) tmp, FALSE)) - { - case 1: - InfoDirect ((wstring (GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO")) - + L"\n\n" - + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION") - + L"\n\n\n" - + GetString ("DECOY_TO_HIDDEN_OS_DATA_TRANSFER_HOWTO")).c_str()); - break; - - case 2: - // No more warnings will be shown - if (ConfigBuffer == NULL) - { - // We need to load the config file because it is not done automatically when - // launched from the sys startup sequence (and SaveSettings would start by _loading_ - // the settings to cache). - LoadSettings (MainDlg); - } - HiddenSysLeakProtectionNotificationStatus = TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_DISABLED; - SaveSettings (MainDlg); - break; - - default: - // NOP - break; - } - } - break; - - case TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_DISABLED: - // NOP - break; - - case TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE: - default: - { - // First time warning -- include technical explanation - InfoDirect ((wstring (GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO")) - + L"\n\n" - + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION") - + L"\n\n\n" - + GetString ("DECOY_TO_HIDDEN_OS_DATA_TRANSFER_HOWTO")).c_str()); - - // Further warnings will not include the explanation (and will allow disabling) - - if (ConfigBuffer == NULL) - { - // We need to load the config file because it is not done automatically when - // launched from the sys startup sequence (and SaveSettings would start by _loading_ - // the settings to cache). - LoadSettings (MainDlg); - } - HiddenSysLeakProtectionNotificationStatus = TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_COMPACT; - SaveSettings (MainDlg); - } - break; - } - } - } - } - catch (...) - { - // NOP - } - - return TRUE; -} - - -/* Except in response to the WM_INITDIALOG and WM_ENDSESSION messages, the dialog box procedure - should return nonzero if it processes a message, and zero if it does not. */ -BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static UINT taskBarCreatedMsg; - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - DWORD mPos; - - switch (uMsg) - { - case WM_HOTKEY: - - HandleHotKey (hwndDlg, wParam); - return 1; - - case WM_INITDIALOG: - { - int exitCode = 0; - int modeOfOperation; - - MainDlg = hwndDlg; - - if (IsTrueCryptInstallerRunning()) - AbortProcess ("TC_INSTALLER_IS_RUNNING"); - - // Set critical default options in case UsePreferences is false - bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = TRUE; - - ResetWrongPwdRetryCount (); - - ExtractCommandLine (hwndDlg, (char *) lParam); - - if (ComServerMode) - { - InitDialog (hwndDlg); - - if (!ComServerMain ()) - { - handleWin32Error (hwndDlg); - exit (1); - } - exit (0); - } - - try - { - BootEncStatus = BootEncObj->GetStatus(); - memcpy (&RecentBootEncStatus, &BootEncStatus, sizeof (RecentBootEncStatus)); - } - catch (...) - { - // NOP - } - - if (UsePreferences) - { - // General preferences - LoadSettings (hwndDlg); - - // Keyfiles - LoadDefaultKeyFilesParam (); - RestoreDefaultKeyFilesParam (); - } - - InitMainDialog (hwndDlg); - - if (IsHiddenOSRunning()) - { - try - { - if (BootEncObj->GetInstalledBootLoaderVersion() > VERSION_NUM) - Warning ("UPDATE_TC_IN_HIDDEN_OS_TOO"); - } - catch (...) { } - } - - // Wipe cache - if (bWipe) - WipeCache (hwndDlg, Silent); - - // Automount - if (bAuto || (Quit && szFileName[0] != 0)) - { - // No drive letter specified on command line - if (commandLineDrive == 0) - szDriveLetter[0] = GetFirstAvailableDrive () + 'A'; - - if (bAutoMountDevices) - { - defaultMountOptions = mountOptions; - if (FirstCmdKeyFile) - { - KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles = TRUE; - FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); - defaultKeyFilesParam.FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); - } - - if (!MountAllDevices (hwndDlg, !Silent && !CmdVolumePasswordValid && !FirstCmdKeyFile && IsPasswordCacheEmpty())) - exitCode = 1; - } - - if (bAutoMountFavorites) - { - defaultMountOptions = mountOptions; - if (FirstCmdKeyFile) - { - KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles = TRUE; - FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); - defaultKeyFilesParam.FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); - } - - if (!MountFavoriteVolumes ()) - exitCode = 1; - } - - if (szFileName[0] != 0 && !IsMountedVolume (szFileName)) - { - BOOL mounted; - - // Cached password - mounted = MountVolume (hwndDlg, szDriveLetter[0] - 'A', szFileName, NULL, bCacheInDriver, bForceMount, &mountOptions, Silent, FALSE); - - // Command line password or keyfiles - if (!mounted && (CmdVolumePassword.Length != 0 || FirstCmdKeyFile)) - { - BOOL reportBadPasswd = CmdVolumePassword.Length > 0; - - if (FirstCmdKeyFile) - KeyFilesApply (&CmdVolumePassword, FirstCmdKeyFile); - - mounted = MountVolume (hwndDlg, szDriveLetter[0] - 'A', - szFileName, &CmdVolumePassword, bCacheInDriver, bForceMount, - &mountOptions, Silent, reportBadPasswd); - - burn (&CmdVolumePassword, sizeof (CmdVolumePassword)); - } - - if (FirstCmdKeyFile) - { - FirstKeyFile = FirstCmdKeyFile; - KeyFilesEnable = TRUE; - } - - // Ask user for password - while (!mounted && !Silent) - { - VolumePassword.Length = 0; - - strcpy (PasswordDlgVolume, szFileName); - if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, TRUE)) - break; - - WaitCursor (); - - if (KeyFilesEnable && FirstKeyFile) - KeyFilesApply (&VolumePassword, FirstKeyFile); - - mounted = MountVolume (hwndDlg, szDriveLetter[0] - 'A', szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, FALSE, TRUE); - - burn (&VolumePassword, sizeof (VolumePassword)); - burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); - - NormalCursor (); - } - - if (UsePreferences) - { - RestoreDefaultKeyFilesParam (); - bCacheInDriver = bCacheInDriverDefault; - } - - if (mounted > 0) - { - if (bBeep) - MessageBeep (-1); - - if (bExplore) - OpenVolumeExplorerWindow (szDriveLetter[0] - 'A'); - - RefreshMainDlg(hwndDlg); - - if(!Silent) - { - // Check for deprecated CBC mode - modeOfOperation = GetModeOfOperationByDriveNo (szDriveLetter[0] - 'A'); - if (modeOfOperation == CBC || modeOfOperation == OUTER_CBC) - Warning("WARN_CBC_MODE"); - - // Check for deprecated 64-bit-block ciphers - if (GetCipherBlockSizeByDriveNo (szDriveLetter[0] - 'A') == 64) - Warning("WARN_64_BIT_BLOCK_CIPHER"); - - // Check for problematic file extensions (exe, dll, sys) - if (CheckFileExtension (szFileName)) - Warning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); - } - } - else - exitCode = 1; - } - else if (bExplore && GetMountedVolumeDriveNo (szFileName) != -1) - OpenVolumeExplorerWindow (GetMountedVolumeDriveNo (szFileName)); - else if (szFileName[0] != 0 && IsMountedVolume (szFileName)) - Warning ("VOL_ALREADY_MOUNTED"); - - if (!Quit) - RefreshMainDlg(hwndDlg); - } - - // Wipe command line password - if (CmdVolumePassword.Length != 0) - { - burn (&CmdVolumePassword, sizeof (CmdVolumePassword)); - CmdVolumePassword.Length = 0; - } - - // Wipe command line keyfiles - if (FirstCmdKeyFile) - { - if (defaultKeyFilesParam.FirstKeyFile) - KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); - - defaultKeyFilesParam.EnableKeyFiles = FALSE; - - if (!Quit) - { - LoadSettings (hwndDlg); - LoadDefaultKeyFilesParam (); - RestoreDefaultKeyFilesParam (); - } - } - - // Dismount - if (cmdUnmountDrive > 0) - { - if (!Dismount (hwndDlg, (char)toupper(szDriveLetter[0]) - 'A')) - exitCode = 1; - } - else if (cmdUnmountDrive == -1) - { - if (!DismountAll (hwndDlg, bForceUnmount, !Silent, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY)) - exitCode = 1; - } - - // TaskBar icon - if (bEnableBkgTask) - TaskBarIconAdd (hwndDlg); - - // Quit - if (Quit) - { - if (TaskBarIconMutex == NULL) - exit (exitCode); - - MainWindowHidden = TRUE; - - LoadSettings (hwndDlg); - LoadDefaultKeyFilesParam (); - RestoreDefaultKeyFilesParam (); - - if (!bEnableBkgTask) - { - if (TaskBarIconMutex) - TaskBarIconRemove (hwndDlg); - exit (exitCode); - } - } - - // No command line arguments or only /volume => bring active instance - // to foreground if available - if (NoCmdLineArgs == 0 || (CmdLineVolumeSpecified && NoCmdLineArgs <= 2)) - { - HWND h = hwndDlg; - EnumWindows (FindTCWindowEnum, (LPARAM) &h); - - if (h != hwndDlg) - { - if (CmdLineVolumeSpecified) - { - COPYDATASTRUCT cd; - memcpy (&cd.dwData, WM_COPY_SET_VOLUME_NAME, 4); - cd.lpData = szFileName; - cd.cbData = strlen (szFileName) + 1; - - SendMessage (h, WM_COPYDATA, (WPARAM)hwndDlg, (LPARAM)&cd); - } - - SendMessage (h, TC_APPMSG_MOUNT_SHOW_WINDOW, 0, 0); - - ShowWindow (h, SW_SHOW); - SetForegroundWindow (h); - - if (TaskBarIconMutex == NULL) - exit (0); - } - } - - // Register hot keys - if (!RegisterAllHotkeys (hwndDlg, Hotkeys) - && TaskBarIconMutex != NULL) // Warn only if we are the first instance of TrueCrypt - Warning("HOTKEY_REGISTRATION_ERROR"); - - Silent = FALSE; - - GetMountList (&LastKnownMountList); - SetTimer (hwndDlg, TIMER_ID_MAIN, TIMER_INTERVAL_MAIN, NULL); - - taskBarCreatedMsg = RegisterWindowMessage ("TaskbarCreated"); - - SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - - /* Check system encryption status */ - - if (!Quit) // Do not care about system encryption or in-place encryption if we were launched from the system startup sequence (the wizard was added to it too). - { - if (SysEncryptionOrDecryptionRequired ()) - { - if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption - { - // We shouldn't block the mutex at this point - - if (SystemEncryptionStatus == SYSENC_STATUS_PRETEST - || AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) - { - // The wizard was not launched during the system startup seq, or the user may have forgotten - // to resume the encryption/decryption process. - - - LaunchVolCreationWizard (hwndDlg, "/csysenc"); - } - } - } - - if (bInPlaceEncNonSysPending && !NonSysInplaceEncInProgressElsewhere()) - { - if (AskNonSysInPlaceEncryptionResume() == IDYES) - ResumeInterruptedNonSysInplaceEncProcess (); - } - } - - DoPostInstallTasks (); - } - return 0; - - case WM_WINDOWPOSCHANGING: - if (MainWindowHidden) - { - // Prevent window from being shown - PWINDOWPOS wp = (PWINDOWPOS)lParam; - wp->flags &= ~SWP_SHOWWINDOW; - return 0; - } - return 1; - - case WM_SYSCOMMAND: - if (lw == IDC_ABOUT) - { - DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc); - return 1; - } - return 0; - - case WM_HELP: - OpenPageHelp (hwndDlg, 0); - return 1; - - case WM_ENDSESSION: - if (TaskBarIconMutex != NULL) - { - if (bDismountOnLogOff) - { - // Auto-dismount when user logs off - DWORD dwResult; - - if (bWipeCacheOnAutoDismount) - DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - - DismountAll (hwndDlg, bForceAutoDismount, !bForceAutoDismount, 1, 0); - } - - TaskBarIconRemove (hwndDlg); - } - EndMainDlg (hwndDlg); - localcleanup (); - return 0; - - case WM_POWERBROADCAST: - if (wParam == PBT_APMSUSPEND - && TaskBarIconMutex != NULL && bDismountOnPowerSaving) - { - // Auto-dismount when entering power-saving mode - DWORD dwResult; - BOOL volumesMounted = LastKnownMountList.ulMountedDrives != 0; - - if (bWipeCacheOnAutoDismount) - { - DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - SecurityToken::CloseAllSessions(); - } - - if (DismountAll (hwndDlg, bForceAutoDismount, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY) && volumesMounted) - PostMessage (hwndDlg, TC_APPMSG_VOLUMES_DISMOUNTED_ON_POWER, 0, NULL); - } - return 0; - - case WM_TIMER: - { - // Check mount list and update GUI if needed - CheckMountList (); - - // Cache status - if (IsPasswordCacheEmpty() == IsWindowEnabled (GetDlgItem (hwndDlg, IDC_WIPE_CACHE))) - EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_CACHE), !IsPasswordCacheEmpty()); - - if (TaskBarIconMutex != NULL) - { - // Idle auto-dismount - if (MaxVolumeIdleTime > 0) - DismountIdleVolumes (); - - // Screen saver auto-dismount - if (bDismountOnScreenSaver) - { - static BOOL previousState = FALSE; - BOOL running = FALSE; - SystemParametersInfo (SPI_GETSCREENSAVERRUNNING, 0, &running, 0); - - if (running && !previousState) - { - DWORD dwResult; - previousState = TRUE; - - if (bWipeCacheOnAutoDismount) - { - DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - SecurityToken::CloseAllSessions(); - } - - DismountAll (hwndDlg, bForceAutoDismount, FALSE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); - } - else - { - previousState = running; - } - } - } - - // Exit background process in non-install mode or if no volume mounted - // and no other instance active - if (LastKnownMountList.ulMountedDrives == 0 - && MainWindowHidden -#ifndef _DEBUG - && (bCloseBkgTaskWhenNoVolumes || IsNonInstallMode ()) -#endif - && !SysEncDeviceActive (TRUE) - && GetDriverRefCount () < 2) - { - TaskBarIconRemove (hwndDlg); - EndMainDlg (hwndDlg); - } - - return 1; - } - return 1; - - case TC_APPMSG_TASKBAR_ICON: - { - switch (lParam) - { - case WM_LBUTTONDOWN: - SetForegroundWindow (hwndDlg); - MainWindowHidden = FALSE; - ShowWindow (hwndDlg, SW_SHOW); - ShowWindow (hwndDlg, SW_RESTORE); - return 1; - - case WM_RBUTTONUP: - { - POINT pos; - HMENU popup = CreatePopupMenu (); - int sel, i, n; - - if (MainWindowHidden) - { - AppendMenuW (popup, MF_STRING, IDM_SHOW_HIDE, GetString ("SHOW_TC")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - } - else if (bEnableBkgTask - && (!(LastKnownMountList.ulMountedDrives == 0 - && (bCloseBkgTaskWhenNoVolumes || IsNonInstallMode ()) - && !SysEncDeviceActive (TRUE) - && GetDriverRefCount () < 2))) - { - AppendMenuW (popup, MF_STRING, IDM_SHOW_HIDE, GetString ("HIDE_TC")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - } - AppendMenuW (popup, MF_STRING, IDM_MOUNTALL, GetString ("IDC_MOUNTALL")); - AppendMenuW (popup, MF_STRING, IDM_MOUNT_FAVORITE_VOLUMES, GetString ("IDM_MOUNT_FAVORITE_VOLUMES")); - AppendMenuW (popup, MF_STRING, IDM_UNMOUNTALL, GetString ("IDM_UNMOUNTALL")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - - for (n = 0; n < 2; n++) - { - for (i = 0; i < 26; i++) - { - if (LastKnownMountList.ulMountedDrives & (1 << i)) - { - wchar_t s[1024]; - wchar_t *vol = (wchar_t *) LastKnownMountList.wszVolume[i]; - - if (wcsstr (vol, L"\\??\\")) vol += 4; - - wsprintfW (s, L"%s %c: (%s)", - GetString (n==0 ? "OPEN" : "DISMOUNT"), - i + L'A', - vol); - AppendMenuW (popup, MF_STRING, n*26 + TRAYICON_MENU_DRIVE_OFFSET + i, s); - } - } - if (LastKnownMountList.ulMountedDrives != 0) - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - } - - AppendMenuW (popup, MF_STRING, IDM_HELP, GetString ("MENU_HELP")); - AppendMenuW (popup, MF_STRING, IDM_HOMEPAGE_SYSTRAY, GetString ("HOMEPAGE")); - AppendMenuW (popup, MF_STRING, IDM_PREFERENCES, GetString ("IDM_PREFERENCES")); - AppendMenuW (popup, MF_STRING, IDM_ABOUT, GetString ("IDM_ABOUT")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDCANCEL, GetString ("EXIT")); - - GetCursorPos (&pos); - - SetForegroundWindow(hwndDlg); - - sel = TrackPopupMenu (popup, - TPM_RETURNCMD | TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON, - pos.x, - pos.y, - 0, - hwndDlg, - NULL); - - if (sel >= TRAYICON_MENU_DRIVE_OFFSET && sel < TRAYICON_MENU_DRIVE_OFFSET + 26) - { - OpenVolumeExplorerWindow (sel - TRAYICON_MENU_DRIVE_OFFSET); - } - else if (sel >= TRAYICON_MENU_DRIVE_OFFSET + 26 && sel < TRAYICON_MENU_DRIVE_OFFSET + 26*2) - { - if (CheckMountList ()) - Dismount (hwndDlg, sel - TRAYICON_MENU_DRIVE_OFFSET - 26); - } - else if (sel == IDM_SHOW_HIDE) - { - ChangeMainWindowVisibility (); - } - else if (sel == IDM_HOMEPAGE_SYSTRAY) - { - Applink ("home", TRUE, ""); - } - else if (sel == IDCANCEL) - { - if ((LastKnownMountList.ulMountedDrives == 0 - && !SysEncDeviceActive (TRUE)) - || AskWarnNoYes ("CONFIRM_EXIT") == IDYES) - { - // Close all other TC windows - EnumWindows (CloseTCWindowsEnum, 0); - - TaskBarIconRemove (hwndDlg); - SendMessage (hwndDlg, WM_COMMAND, sel, 0); - } - } - else - { - SendMessage (hwndDlg, WM_COMMAND, sel, 0); - } - - PostMessage(hwndDlg, WM_NULL, 0, 0); - DestroyMenu (popup); - } - return 1; - } - } - - return 0; - - case TC_APPMSG_CLOSE_BKG_TASK: - if (TaskBarIconMutex != NULL) - TaskBarIconRemove (hwndDlg); - - return 1; - - case TC_APPMSG_SYSENC_CONFIG_UPDATE: - LoadSysEncSettings (hwndDlg); - - // The wizard added TrueCrypt.exe to the system startup sequence or performed other operations that - // require us to update our cached settings. - LoadSettings (hwndDlg); - - return 1; - - case TC_APPMSG_VOLUMES_DISMOUNTED_ON_POWER: - Info ("MOUNTED_VOLUMES_AUTO_DISMOUNTED"); - return 1; - - case WM_DEVICECHANGE: - if (!IgnoreWmDeviceChange && wParam != DBT_DEVICEARRIVAL) - { - // Check if any host device has been removed and force dismount of volumes accordingly - PDEV_BROADCAST_HDR hdr = (PDEV_BROADCAST_HDR) lParam; - int m; - - GetMountList (&LastKnownMountList); - - if (wParam == DBT_DEVICEREMOVECOMPLETE && hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) - { - // File-hosted volumes - PDEV_BROADCAST_VOLUME vol = (PDEV_BROADCAST_VOLUME) lParam; - int i; - - for (i = 0; i < 26; i++) - { - if (vol->dbcv_unitmask & (1 << i)) - { - for (m = 0; m < 26; m++) - { - if (LastKnownMountList.ulMountedDrives & (1 << m)) - { - wchar_t *vol = (wchar_t *) LastKnownMountList.wszVolume[m]; - - if (wcsstr (vol, L"\\??\\") == vol) - vol += 4; - - if (vol[1] == L':' && i == (vol[0] - (vol[0] <= L'Z' ? L'A' : L'a'))) - { - UnmountVolume (hwndDlg, m, TRUE); - if (bWipeCacheOnAutoDismount || bWipeCacheOnExit) - { - WipeCache (NULL, TRUE); - SecurityToken::CloseAllSessions(); - } - } - } - } - } - } - } - - // Device-hosted volumes - for (m = 0; m < 26; m++) - { - if (LastKnownMountList.ulMountedDrives & (1 << m)) - { - wchar_t *vol = (wchar_t *) LastKnownMountList.wszVolume[m]; - char volp[MAX_PATH]; - - if (wcsstr (vol, L"\\??\\") == vol) - vol += 4; - - _snprintf (volp, sizeof(volp), "%ls", vol); - - if (IsVolumeDeviceHosted (volp)) - { - OPEN_TEST_STRUCT ots; - - if (!OpenDevice (volp, &ots, FALSE)) - { - UnmountVolume (hwndDlg, m, TRUE); - if (bWipeCacheOnAutoDismount || bWipeCacheOnExit) - { - WipeCache (NULL, TRUE); - SecurityToken::CloseAllSessions(); - } - } - } - } - } - return 1; - } - return 0; - - case WM_NOTIFY: - - if(wParam == IDC_DRIVELIST) - { - /* Single click within drive list */ - if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED )) - { - nSelectedDriveIndex = ((LPNMLISTVIEW) lParam)->iItem; - EnableDisableButtons (hwndDlg); - return 1; - } - - /* Double click within drive list */ - if (((LPNMHDR) lParam)->code == LVN_ITEMACTIVATE) - { - int state = GetItemLong (GetDlgItem (hwndDlg, IDC_DRIVELIST), ((LPNMITEMACTIVATE)lParam)->iItem ); - nSelectedDriveIndex = ((LPNMITEMACTIVATE)lParam)->iItem; - if (LOWORD(state) == TC_MLIST_ITEM_NONSYS_VOL || LOWORD(state) == TC_MLIST_ITEM_SYS_PARTITION) - { - // Open explorer window for mounted volume - WaitCursor (); - OpenVolumeExplorerWindow (HIWORD(state) - 'A'); - NormalCursor (); - } - else if (LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == TC_MLIST_ITEM_FREE) - { - mountOptions = defaultMountOptions; - bPrebootPasswordDlgMode = FALSE; - - if (GetAsyncKeyState (VK_CONTROL) < 0) - { - if (IDCANCEL == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg, - (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions)) - return 1; - - if (mountOptions.ProtectHiddenVolume && hidVolProtKeyFilesParam.EnableKeyFiles) - KeyFilesApply (&mountOptions.ProtectedHidVolPassword, hidVolProtKeyFilesParam.FirstKeyFile); - } - - if (CheckMountList ()) - Mount (hwndDlg, 0, 0); - } - return 1; - } - - /* Right click and drag&drop operations */ - - switch (((NM_LISTVIEW *) lParam)->hdr.code) - { - case NM_RCLICK: - case LVN_BEGINRDRAG: - /* If the mouse was moving while the right mouse button is pressed, popup menu would - not open, because drag&drop operation would be initiated. Therefore, we're handling - RMB drag-and-drop operations as well. */ - { - - /* Drive list context menu */ - - int menuItem; - HMENU popup = CreatePopupMenu (); - - SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - - switch (LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)))) - { - case TC_MLIST_ITEM_FREE: - - // No mounted volume at this drive letter - - AppendMenuW (popup, MF_STRING, IDM_MOUNT_VOLUME, GetString ("IDM_MOUNT_VOLUME")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDPM_SELECT_FILE_AND_MOUNT, GetString ("SELECT_FILE_AND_MOUNT")); - AppendMenuW (popup, MF_STRING, IDPM_SELECT_DEVICE_AND_MOUNT, GetString ("SELECT_DEVICE_AND_MOUNT")); - break; - - case TC_MLIST_ITEM_NONSYS_VOL: - - // There's a mounted non-system volume at this drive letter - - AppendMenuW (popup, MF_STRING, IDM_UNMOUNT_VOLUME, GetString ("DISMOUNT")); - AppendMenuW (popup, MF_STRING, IDPM_OPEN_VOLUME, GetString ("OPEN")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDPM_CHECK_FILESYS, GetString ("IDPM_CHECK_FILESYS")); - AppendMenuW (popup, MF_STRING, IDPM_REPAIR_FILESYS, GetString ("IDPM_REPAIR_FILESYS")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDM_VOLUME_PROPERTIES, GetString ("IDPM_PROPERTIES")); - break; - - case TC_MLIST_ITEM_SYS_PARTITION: - case TC_MLIST_ITEM_SYS_DRIVE: - - // System partition/drive - - PopulateSysEncContextMenu (popup, FALSE); - break; - } - - mPos=GetMessagePos(); - - menuItem = TrackPopupMenu (popup, - TPM_RETURNCMD | TPM_LEFTBUTTON, - GET_X_LPARAM(mPos), - GET_Y_LPARAM(mPos), - 0, - hwndDlg, - NULL); - - DestroyMenu (popup); - - switch (menuItem) - { - case IDPM_SELECT_FILE_AND_MOUNT: - if (SelectContainer (hwndDlg)) - MountSelectedVolume (hwndDlg, FALSE); - break; - - case IDPM_SELECT_DEVICE_AND_MOUNT: - if (SelectPartition (hwndDlg)) - MountSelectedVolume (hwndDlg, FALSE); - break; - - case IDPM_CHECK_FILESYS: - case IDPM_REPAIR_FILESYS: - { - LPARAM lLetter = GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - - if (LOWORD (lLetter) != 0xffff) - CheckFilesystem ((char) HIWORD (lLetter) - 'A', menuItem == IDPM_REPAIR_FILESYS); - } - break; - - case IDM_UNMOUNT_VOLUME: - if (CheckMountList ()) - Dismount (hwndDlg, 0); - break; - - case IDPM_OPEN_VOLUME: - { - int state = GetItemLong(GetDlgItem (hwndDlg, IDC_DRIVELIST), ((LPNMITEMACTIVATE)lParam)->iItem ); - nSelectedDriveIndex = ((LPNMITEMACTIVATE)lParam)->iItem; - - WaitCursor (); - OpenVolumeExplorerWindow (HIWORD(state) - 'A'); - NormalCursor (); - } - break; - - case IDM_VOLUME_PROPERTIES: - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_VOLUME_PROPERTIES), hwndDlg, - (DLGPROC) VolumePropertiesDlgProc, (LPARAM) FALSE); - break; - - case IDM_MOUNT_VOLUME: - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - mountOptions = defaultMountOptions; - bPrebootPasswordDlgMode = FALSE; - - if (CheckMountList ()) - Mount (hwndDlg, 0, 0); - } - break; - - default: - SendMessage (MainDlg, WM_COMMAND, menuItem, NULL); - break; - } - return 1; - } - } - } - return 0; - - case WM_ERASEBKGND: - return 0; - - case WM_COMMAND: - - if (lw == IDCANCEL || lw == IDC_EXIT) - { - EndMainDlg (hwndDlg); - return 1; - } - - if (lw == IDHELP || lw == IDM_HELP) - { - OpenPageHelp (hwndDlg, 0); - return 1; - } - - if (lw == IDM_ABOUT || lw == IDC_LOGO) - { - DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc); - return 1; - } - - if (lw == IDOK && LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == TC_MLIST_ITEM_NONSYS_VOL - || lw == IDM_UNMOUNT_VOLUME) - { - if (lw == IDM_UNMOUNT_VOLUME && LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) != TC_MLIST_ITEM_NONSYS_VOL) - { - Warning ("SELECT_A_MOUNTED_VOLUME"); - return 1; - } - - if (CheckMountList ()) - Dismount (hwndDlg, 0); - return 1; - } - - if ((lw == IDOK || lw == IDM_MOUNT_VOLUME || lw == IDM_MOUNT_VOLUME_OPTIONS || lw == IDC_MOUNTALL || lw == IDM_MOUNTALL) - && LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == 0xffff) - { - MessageBoxW (hwndDlg, GetString ("SELECT_FREE_DRIVE"), L"TrueCrypt", MB_ICONEXCLAMATION); - return 1; - } - - if ((lw == IDOK || lw == IDM_MOUNT_VOLUME || lw == IDM_MOUNT_VOLUME_OPTIONS)) - { - MountSelectedVolume (hwndDlg, lw == IDM_MOUNT_VOLUME_OPTIONS); - return 1; - } - - if (lw == IDC_UNMOUNTALL || lw == IDM_UNMOUNTALL) - { - DismountAll (hwndDlg, bForceUnmount, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); - return 1; - } - - if (lw == IDC_MOUNTALL || lw == IDM_MOUNTALL) - { - // If Shift key is down and the password cache isn't empty, bypass password prompt - MountAllDevices (hwndDlg, !(GetAsyncKeyState (VK_SHIFT) < 0 && !IsPasswordCacheEmpty())); - return 1; - } - - if (lw == IDC_SELECT_FILE || lw == IDM_SELECT_FILE) - { - SelectContainer (hwndDlg); - return 1; - } - - if (lw == IDC_SELECT_DEVICE || lw == IDM_SELECT_DEVICE) - { - SelectPartition (hwndDlg); - return 1; - } - - // System Encryption menu - switch (lw) - { - case IDM_ENCRYPT_SYSTEM_DEVICE: - EncryptSystemDevice (); - break; - case IDM_PERMANENTLY_DECRYPT_SYS: - DecryptSystemDevice (); - break; - case IDM_CREATE_HIDDEN_OS: - CreateHiddenOS (); - break; - case IDM_SYSENC_RESUME: - ResumeInterruptedSysEncProcess (); - break; - case IDM_SYSTEM_ENCRYPTION_STATUS: - ShowSystemEncryptionStatus (); - break; - case IDM_CHANGE_SYS_PASSWORD: - ChangeSysEncPassword (hwndDlg, FALSE); - break; - case IDM_CHANGE_SYS_HEADER_KEY_DERIV_ALGO: - ChangeSysEncPassword (hwndDlg, TRUE); - break; - case IDM_CREATE_RESCUE_DISK: - CreateRescueDisk (); - break; - case IDM_VERIFY_RESCUE_DISK: - VerifyRescueDisk (); - break; - case IDM_MOUNT_SYSENC_PART_WITHOUT_PBA: - - if (CheckSysEncMountWithoutPBA ("", FALSE)) - { - mountOptions = defaultMountOptions; - bPrebootPasswordDlgMode = TRUE; - - if (CheckMountList ()) - Mount (hwndDlg, 0, 0); - - bPrebootPasswordDlgMode = FALSE; - } - break; - } - - if (lw == IDC_VOLUME_TOOLS) - { - /* Volume Tools popup menu */ - - int menuItem; - char volPath[TC_MAX_PATH]; /* Volume to mount */ - HMENU popup = CreatePopupMenu (); - RECT rect; - - if (ActiveSysEncDeviceSelected ()) - { - PopulateSysEncContextMenu (popup, TRUE); - } - else - { - AppendMenuW (popup, MF_STRING, IDM_CHANGE_PASSWORD, GetString ("IDM_CHANGE_PASSWORD")); - AppendMenuW (popup, MF_STRING, IDM_CHANGE_HEADER_KEY_DERIV_ALGO, GetString ("IDM_CHANGE_HEADER_KEY_DERIV_ALGO")); - AppendMenu (popup, MF_SEPARATOR, 0, NULL); - AppendMenuW (popup, MF_STRING, IDM_BACKUP_VOL_HEADER, GetString ("IDM_BACKUP_VOL_HEADER")); - AppendMenuW (popup, MF_STRING, IDM_RESTORE_VOL_HEADER, GetString ("IDM_RESTORE_VOL_HEADER")); - } - - GetWindowRect (GetDlgItem (hwndDlg, IDC_VOLUME_TOOLS), &rect); - - menuItem = TrackPopupMenu (popup, - TPM_RETURNCMD | TPM_LEFTBUTTON, - rect.left + 2, - rect.top + 2, - 0, - hwndDlg, - NULL); - - DestroyMenu (popup); - - switch (menuItem) - { - case IDM_CHANGE_PASSWORD: - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; - ChangePassword (hwndDlg); - } - break; - - case IDM_CHANGE_HEADER_KEY_DERIV_ALGO: - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - pwdChangeDlgMode = PCDM_CHANGE_PKCS5_PRF; - ChangePassword (hwndDlg); - } - break; - - case IDM_BACKUP_VOL_HEADER: - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); - - WaitCursor (); - - if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) - UacBackupVolumeHeader (hwndDlg, TRUE, volPath); - else - BackupVolumeHeader (hwndDlg, TRUE, volPath); - - NormalCursor (); - } - break; - - case IDM_RESTORE_VOL_HEADER: - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); - - WaitCursor (); - - if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) - UacRestoreVolumeHeader (hwndDlg, volPath); - else - RestoreVolumeHeader (hwndDlg, volPath); - - NormalCursor (); - } - break; - - default: - SendMessage (MainDlg, WM_COMMAND, menuItem, NULL); - break; - } - return 1; - } - - if (lw == IDM_CHANGE_PASSWORD) - { - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - if (ActiveSysEncDeviceSelected ()) - { - ChangeSysEncPassword (hwndDlg, FALSE); - } - else - { - pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; - ChangePassword (hwndDlg); - } - } - return 1; - } - - if (lw == IDM_CHANGE_HEADER_KEY_DERIV_ALGO) - { - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - if (ActiveSysEncDeviceSelected ()) - { - ChangeSysEncPassword (hwndDlg, TRUE); - } - else - { - pwdChangeDlgMode = PCDM_CHANGE_PKCS5_PRF; - ChangePassword (hwndDlg); - } - } - return 1; - } - - if (lw == IDC_WIPE_CACHE || lw == IDM_WIPE_CACHE) - { - WipeCache (hwndDlg, FALSE); - return 1; - } - - if (lw == IDM_CLEAR_HISTORY) - { - ClearHistory (GetDlgItem (hwndDlg, IDC_VOLUME)); - EnableDisableButtons (hwndDlg); - return 1; - } - - if (lw == IDC_CREATE_VOLUME || lw == IDM_CREATE_VOLUME || lw == IDM_VOLUME_WIZARD) - { - LaunchVolCreationWizard (hwndDlg, ""); - return 1; - } - - if (lw == IDM_ADD_REMOVE_VOL_KEYFILES) - { - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - pwdChangeDlgMode = PCDM_ADD_REMOVE_VOL_KEYFILES; - ChangePassword (hwndDlg); - } - return 1; - } - - if (lw == IDM_REMOVE_ALL_KEYFILES_FROM_VOL) - { - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - pwdChangeDlgMode = PCDM_REMOVE_ALL_KEYFILES_FROM_VOL; - ChangePassword (hwndDlg); - } - return 1; - } - - if (lw == IDM_MANAGE_TOKEN_KEYFILES) - { - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, NULL); - return 1; - } - - if (lw == IDM_CLOSE_ALL_TOKEN_SESSIONS) - { - try - { - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - SecurityToken::CloseAllSessions(); - } - Info ("ALL_TOKEN_SESSIONS_CLOSED"); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - return 1; - } - - if (lw == IDM_GENERATE_KEYFILE || lw == IDM_KEYFILE_GENERATOR) - { - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg, - (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0); - - return 1; - } - - if (lw == IDM_LICENSE) - { - TextInfoDialogBox (TC_TBXID_LEGAL_NOTICES); - return 1; - } - - if (lw == IDM_WEBSITE) - { - Applink ("website", TRUE, ""); - return 1; - } - else if (lw == IDM_HOMEPAGE) - { - Applink ("homepage", TRUE, ""); - return 1; - } - else if (lw == IDM_FORUMS) - { - Applink ("forum", TRUE, ""); - return 1; - } - else if (lw == IDM_ONLINE_TUTORIAL) - { - Applink ("tutorial", TRUE, ""); - return 1; - } - else if (lw == IDM_ONLINE_HELP) - { - OpenOnlineHelp (); - return 1; - } - else if (lw == IDM_FAQ) - { - Applink ("faq", TRUE, ""); - return 1; - } - else if (lw == IDM_TC_DOWNLOADS) - { - Applink ("downloads", TRUE, ""); - return 1; - } - else if (lw == IDM_NEWS) - { - Applink ("news", TRUE, ""); - return 1; - } - else if (lw == IDM_VERSION_HISTORY) - { - Applink ("history", TRUE, ""); - return 1; - } - else if (lw == IDM_BUGREPORT) - { - Applink ("bugreport", TRUE, ""); - return 1; - } - else if (lw == IDM_DONATIONS) - { - Applink ("donations", FALSE, ""); - return 1; - } - else if (lw == IDM_CONTACT) - { - Applink ("contact", FALSE, ""); - return 1; - } - - if (lw == IDM_PREFERENCES) - { - if (IDOK == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_PREFERENCES_DLG), hwndDlg, - (DLGPROC) PreferencesDlgProc, (LPARAM) 0)) - { - if (bEnableBkgTask) - { - TaskBarIconAdd (hwndDlg); - } - else - { - TaskBarIconRemove (hwndDlg); - if (MainWindowHidden) - EndMainDlg (hwndDlg); - } - } - return 1; - } - - if (lw == IDM_HOTKEY_SETTINGS) - { - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_HOTKEYS_DLG), hwndDlg, - (DLGPROC) HotkeysDlgProc, (LPARAM) 0); - return 1; - } - - if (lw == IDM_DEFAULT_KEYFILES || lw == IDM_SET_DEFAULT_KEYFILES) - { - KeyfileDefaultsDlg (hwndDlg); - return 1; - } - - if (lw == IDM_TOKEN_PREFERENCES) - { - SecurityTokenPreferencesDialog (hwndDlg); - return 1; - } - - if (lw == IDM_SYSENC_SETTINGS || lw == IDM_SYS_ENC_SETTINGS) - { - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_SETTINGS), hwndDlg, (DLGPROC) BootLoaderPreferencesDlgProc, 0); - return 1; - } - - if (lw == IDM_BENCHMARK) - { - Benchmark (hwndDlg); - return 1; - } - - if (lw == IDM_TRAVELER) - { - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_TRAVELER_DLG), hwndDlg, - (DLGPROC) TravelerDlgProc, (LPARAM) 0); - return 1; - } - - if (lw == IDM_BACKUP_VOL_HEADER) - { - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - char volPath[TC_MAX_PATH]; /* Volume to mount */ - - GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); - - WaitCursor (); - - if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) - UacBackupVolumeHeader (hwndDlg, TRUE, volPath); - else - BackupVolumeHeader (hwndDlg, TRUE, volPath); - - NormalCursor (); - } - return 1; - } - - if (lw == IDM_RESTORE_VOL_HEADER) - { - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else - { - char volPath[TC_MAX_PATH]; /* Volume to mount */ - - GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); - - WaitCursor (); - - if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) - UacRestoreVolumeHeader (hwndDlg, volPath); - else - RestoreVolumeHeader (hwndDlg, volPath); - - NormalCursor (); - } - return 1; - } - - if (lw == IDM_LANGUAGE) - { - BOOL p; - if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), hwndDlg, - (DLGPROC) LanguageDlgProc, (LPARAM) 0) == IDOK) - { - LoadLanguageFile (); - SaveSettings (hwndDlg); - - p = LocalizationActive; - LocalizationActive = TRUE; - InitMainDialog (hwndDlg); - InvalidateRect (hwndDlg, NULL, FALSE); - LocalizationActive = p; - DrawMenuBar (hwndDlg); - } - return 1; - } - - if (lw == IDM_TEST_VECTORS) - { - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_CIPHER_TEST_DLG), hwndDlg, (DLGPROC) CipherTestDialogProc, (LPARAM) 1); - return 1; - } - - if (lw == IDM_REFRESH_DRIVE_LETTERS) - { - DWORD driveMap = GetLogicalDrives (); - - WaitCursor (); - - if (!(nCurrentOS == WIN_2000 && RemoteSession)) - { - BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, 0, ~driveMap); - Sleep (100); - BroadcastDeviceChange (DBT_DEVICEARRIVAL, 0, driveMap); - } - - LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), 0); - - if (nSelectedDriveIndex >= 0) - { - SelectItem (GetDlgItem (hwndDlg, IDC_DRIVELIST), - (char) HIWORD (GetItemLong (GetDlgItem (hwndDlg, IDC_DRIVELIST), nSelectedDriveIndex))); - } - - NormalCursor (); - return 1; - } - - if (lw == IDM_MOUNT_FAVORITE_VOLUMES) - { - MountFavoriteVolumes (); - return 1; - } - - if (lw == IDM_RESUME_INTERRUPTED_PROC) - { - ResumeInterruptedNonSysInplaceEncProcess (); - return 1; - } - - if (lw == IDM_SAVE_FAVORITE_VOLUMES) - { - SaveFavoriteVolumes (); - return 1; - } - - if (lw == IDC_VOLUME_PROPERTIES || lw == IDM_VOLUME_PROPERTIES) - { - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_VOLUME_PROPERTIES), hwndDlg, - (DLGPROC) VolumePropertiesDlgProc, (LPARAM) 0); - return 1; - } - - if (lw == IDC_VOLUME && hw == CBN_EDITCHANGE) - { - EnableDisableButtons (hwndDlg); - return 1; - } - - if (lw == IDC_VOLUME && hw == CBN_SELCHANGE) - { - UpdateComboOrder (GetDlgItem (hwndDlg, IDC_VOLUME)); - MoveEditToCombo ((HWND) lParam, bHistory); - PostMessage (hwndDlg, TC_APPMSG_MOUNT_ENABLE_DISABLE_CONTROLS, 0, 0); - return 1; - } - - if (lw == IDC_NO_HISTORY) - { - if (!(bHistory = !IsButtonChecked (GetDlgItem (hwndDlg, IDC_NO_HISTORY)))) - ClearHistory (GetDlgItem (hwndDlg, IDC_VOLUME)); - - return 1; - } - - return 0; - - case WM_DROPFILES: - { - HDROP hdrop = (HDROP) wParam; - DragQueryFile (hdrop, 0, szFileName, sizeof szFileName); - DragFinish (hdrop); - - AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); - EnableDisableButtons (hwndDlg); - SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - } - return 1; - - case TC_APPMSG_MOUNT_ENABLE_DISABLE_CONTROLS: - EnableDisableButtons (hwndDlg); - return 1; - - case TC_APPMSG_MOUNT_SHOW_WINDOW: - MainWindowHidden = FALSE; - ShowWindow (hwndDlg, SW_SHOW); - ShowWindow (hwndDlg, SW_RESTORE); - return 1; - - case WM_COPYDATA: - { - PCOPYDATASTRUCT cd = (PCOPYDATASTRUCT)lParam; - if (memcmp (&cd->dwData, WM_COPY_SET_VOLUME_NAME, 4) == 0) - { - if (cd->cbData > 0) - AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), (char *)cd->lpData, bHistory); - - EnableDisableButtons (hwndDlg); - SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); - } - } - return 1; - - case WM_CLOSE: - EndMainDlg (hwndDlg); - return 1; - - default: - // Recreate tray icon if Explorer restarted - if (taskBarCreatedMsg != 0 && uMsg == taskBarCreatedMsg && TaskBarIconMutex != NULL) - { - TaskBarIconRemove (hwndDlg); - TaskBarIconAdd (hwndDlg); - return 1; - } - } - - return 0; -} - -void ExtractCommandLine (HWND hwndDlg, char *lpszCommandLine) -{ - char **lpszCommandLineArgs; /* Array of command line arguments */ - int nNoCommandLineArgs; /* The number of arguments in the array */ - char tmpPath[MAX_PATH * 2]; - - /* Defaults */ - mountOptions.PreserveTimestamp = TRUE; - - if (_stricmp (lpszCommandLine, "-Embedding") == 0) - { - ComServerMode = TRUE; - return; - } - - /* Extract command line arguments */ - NoCmdLineArgs = nNoCommandLineArgs = Win32CommandLine (lpszCommandLine, &lpszCommandLineArgs); - - if (nNoCommandLineArgs > 0) - { - int i; - - for (i = 0; i < nNoCommandLineArgs; i++) - { - enum - { - OptionAuto, - OptionBeep, - OptionCache, - CommandDismount, - OptionExplore, - OptionForce, - CommandHelp, - OptionHistory, - OptionKeyfile, - OptionLetter, - OptionMountOption, - OptionPassword, - OptionQuit, - OptionSilent, - OptionTokenLib, - OptionVolume, - CommandWipeCache - }; - - argument args[]= - { - { OptionAuto, "/auto", "/a", FALSE }, - { OptionBeep, "/beep", "/b", FALSE }, - { OptionCache, "/cache", "/c", FALSE }, - { CommandDismount, "/dismount", "/d", FALSE }, - { OptionExplore, "/explore", "/e", FALSE }, - { OptionForce, "/force", "/f", FALSE }, - { CommandHelp, "/help", "/?", FALSE }, - { OptionHistory, "/history", "/h", FALSE }, - { OptionKeyfile, "/keyfile", "/k", FALSE }, - { OptionLetter, "/letter", "/l", FALSE }, - { OptionMountOption, "/mountoption", "/m", FALSE }, - { OptionPassword, "/password", "/p", FALSE }, - { OptionQuit, "/quit", "/q", FALSE }, - { OptionSilent, "/silent", "/s", FALSE }, - { OptionTokenLib, "/tokenlib", NULL, FALSE }, - { OptionVolume, "/volume", "/v", FALSE }, - { CommandWipeCache, "/wipecache", "/w", FALSE } - }; - - argumentspec as; - - int nArgPos; - - as.args = args; - as.arg_cnt = sizeof(args)/ sizeof(args[0]); - - switch (GetArgumentID (&as, lpszCommandLineArgs[i], &nArgPos)) - { - case OptionAuto: - { - char szTmp[32]; - bAuto = TRUE; - - if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, - nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp))) - { - if (!_stricmp (szTmp, "devices")) - bAutoMountDevices = TRUE; - else if (!_stricmp (szTmp, "favorites")) - bAutoMountFavorites = TRUE; - } - } - break; - - case OptionBeep: - bBeep = TRUE; - break; - - case OptionCache: - { - char szTmp[8]; - bCacheInDriver = TRUE; - - GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, - szTmp, sizeof (szTmp)); - - if (!_stricmp(szTmp,"n") || !_stricmp(szTmp,"no")) - bCacheInDriver = FALSE; - } - break; - - case CommandDismount: - - if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, - szDriveLetter, sizeof (szDriveLetter))) - cmdUnmountDrive = toupper(szDriveLetter[0]) - 'A'; - else - cmdUnmountDrive = -1; - - break; - - case OptionExplore: - bExplore = TRUE; - break; - - case OptionForce: - bForceMount = TRUE; - bForceUnmount = TRUE; - break; - - case OptionKeyfile: - if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, - nNoCommandLineArgs, tmpPath, sizeof (tmpPath))) - { - KeyFile *kf; - RelativePath2Absolute (tmpPath); - kf = (KeyFile *) malloc (sizeof (KeyFile)); - strncpy (kf->FileName, tmpPath, sizeof (kf->FileName)); - FirstCmdKeyFile = KeyFileAdd (FirstCmdKeyFile, kf); - } - break; - - case OptionLetter: - GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, - szDriveLetter, sizeof (szDriveLetter)); - commandLineDrive = *szDriveLetter = (char) toupper (*szDriveLetter); - break; - - case OptionHistory: - { - char szTmp[8]; - bHistory = bHistoryCmdLine = TRUE; - - GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, - szTmp, sizeof (szTmp)); - - if (!_stricmp(szTmp,"n") || !_stricmp(szTmp,"no")) - bHistory = FALSE; - } - break; - - case OptionMountOption: - { - char szTmp[16]; - if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, - nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp))) - { - if (!_stricmp (szTmp, "ro") || !_stricmp (szTmp, "readonly")) - mountOptions.ReadOnly = TRUE; - - if (!_stricmp (szTmp, "rm") || !_stricmp (szTmp, "removable")) - mountOptions.Removable = TRUE; - - if (!_stricmp (szTmp, "ts") || !_stricmp (szTmp, "timestamp")) - mountOptions.PreserveTimestamp = FALSE; - - if (!_stricmp (szTmp, "sm") || !_stricmp (szTmp, "system")) - mountOptions.PartitionInInactiveSysEncScope = bPrebootPasswordDlgMode = TRUE; - - if (!_stricmp (szTmp, "bk") || !_stricmp (szTmp, "headerbak")) - mountOptions.UseBackupHeader = TRUE; - - if (!_stricmp (szTmp, "recovery")) - mountOptions.RecoveryMode = TRUE; - } - } - break; - - case OptionPassword: - GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, - (char *) CmdVolumePassword.Text, sizeof (CmdVolumePassword.Text)); - CmdVolumePassword.Length = strlen ((char *) CmdVolumePassword.Text); - CmdVolumePasswordValid = TRUE; - break; - - case OptionVolume: - if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, - nNoCommandLineArgs, szFileName, sizeof (szFileName))) - { - RelativePath2Absolute (szFileName); - AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); - CmdLineVolumeSpecified = TRUE; - } - break; - - case OptionQuit: - { - char szTmp[32]; - - if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, - nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp))) - { - if (!_stricmp (szTmp, "UAC")) // Used to indicate non-install elevation - break; - - if (!_stricmp (szTmp, "preferences")) - { - Quit = TRUE; - UsePreferences = TRUE; - break; - } - - if (!_stricmp (szTmp, "background")) - bEnableBkgTask = TRUE; - } - - Quit = TRUE; - UsePreferences = FALSE; - } - break; - - case OptionSilent: - Silent = TRUE; - break; - - case OptionTokenLib: - if (GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath)) == HAS_ARGUMENT) - InitSecurityTokenLibrary(); - else - Error ("COMMAND_LINE_ERROR"); - - break; - - case CommandWipeCache: - bWipe = TRUE; - break; - - case CommandHelp: - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_COMMANDHELP_DLG), hwndDlg, (DLGPROC) - CommandHelpDlgProc, (LPARAM) &as); - exit(0); - break; - - // no option = file name - default: - { - strncpy (szFileName, lpszCommandLineArgs[i], MAX_PATH-1); - if (szFileName[0] != '\\' && strchr (szFileName, ':') == 0) - { - char path[MAX_PATH*2]; - GetCurrentDirectory (MAX_PATH, path); - strcat (path, "\\"); - strcat (path, szFileName); - strncpy (szFileName, path, MAX_PATH-1); - } - - if (nNoCommandLineArgs == 1) - CmdLineVolumeSpecified = TRUE; - AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); - } - } - } - } - - /* Free up the command line arguments */ - while (--nNoCommandLineArgs >= 0) - { - free (lpszCommandLineArgs[nNoCommandLineArgs]); - } -} - - -int WINAPI WINMAIN (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCommandLine, int nCmdShow) -{ - int status; - atexit (localcleanup); - SetProcessShutdownParameters (0x100, 0); - - VirtualLock (&VolumePassword, sizeof (VolumePassword)); - VirtualLock (&CmdVolumePassword, sizeof (CmdVolumePassword)); - VirtualLock (&mountOptions, sizeof (mountOptions)); - VirtualLock (&defaultMountOptions, sizeof (defaultMountOptions)); - VirtualLock (&szFileName, sizeof(szFileName)); - - try - { - BootEncObj = new BootEncryption (NULL); - } - catch (Exception &e) - { - e.Show (NULL); - } - - if (BootEncObj == NULL) - AbortProcess ("INIT_SYS_ENC"); - - InitCommonControls (); - InitApp (hInstance, lpszCommandLine); - - RegisterRedTick(hInstance); - - /* Allocate, dup, then store away the application title */ - lpszTitle = L"TrueCrypt"; - - status = DriverAttach (); - if (status != 0) - { - if (status == ERR_OS_ERROR) - handleWin32Error (NULL); - else - handleError (NULL, status); - - AbortProcess ("NODRIVER"); - } - - /* Create the main dialog box */ - DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_MOUNT_DLG), NULL, (DLGPROC) MainDialogProc, - (LPARAM) lpszCommandLine); - - /* Terminate */ - return 0; -} - - -BOOL TaskBarIconAdd (HWND hwnd) -{ - BOOL res; - NOTIFYICONDATAW tnid; - - // Only one icon may be created - if (TaskBarIconMutex != NULL) return TRUE; - - TaskBarIconMutex = CreateMutex (NULL, TRUE, "TrueCryptTaskBarIcon"); - if (TaskBarIconMutex == NULL || GetLastError () == ERROR_ALREADY_EXISTS) - { - TaskBarIconMutex = NULL; - return FALSE; - } - - tnid.cbSize = sizeof (NOTIFYICONDATAW); - tnid.hWnd = hwnd; - tnid.uID = IDI_TRUECRYPT_ICON; - tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - tnid.uCallbackMessage = TC_APPMSG_TASKBAR_ICON; - tnid.hIcon = (HICON) LoadImage (hInst, MAKEINTRESOURCE (IDI_TRUECRYPT_ICON), - IMAGE_ICON, - ScreenDPI >= 120 ? 0 : 16, - ScreenDPI >= 120 ? 0 : 16, - (ScreenDPI >= 120 ? LR_DEFAULTSIZE : 0) - | (nCurrentOS != WIN_2000 ? LR_DEFAULTCOLOR : LR_VGACOLOR)); // Windows 2000 cannot display more than 16 fixed colors in notification tray - - wcscpy (tnid.szTip, L"TrueCrypt"); - - res = Shell_NotifyIconW (NIM_ADD, &tnid); - - if (tnid.hIcon) - DestroyIcon (tnid.hIcon); - - return res; -} - - -BOOL TaskBarIconRemove (HWND hwnd) -{ - if (TaskBarIconMutex != NULL) - { - NOTIFYICONDATA tnid; - BOOL res; - - ZeroMemory (&tnid, sizeof (tnid)); - tnid.cbSize = sizeof(NOTIFYICONDATA); - tnid.hWnd = hwnd; - tnid.uID = IDI_TRUECRYPT_ICON; - - res = Shell_NotifyIcon (NIM_DELETE, &tnid); - if (TaskBarIconMutex) - { - CloseHandle (TaskBarIconMutex); - TaskBarIconMutex = NULL; - } - return res; - } - else - return FALSE; -} - - -void DismountIdleVolumes () -{ - static DWORD lastMinTickCount; - static int InactivityTime[26]; - static unsigned __int64 LastRead[26], LastWritten[26]; - static int LastId[26]; - - VOLUME_PROPERTIES_STRUCT prop; - DWORD dwResult; - BOOL bResult; - int i; - - if (GetTickCount() > lastMinTickCount && GetTickCount() - lastMinTickCount < 60 * 1000) - return; - - lastMinTickCount = GetTickCount(); - - for (i = 0; i < 26; i++) - { - if (LastKnownMountList.ulMountedDrives & (1 << i)) - { - memset (&prop, 0, sizeof(prop)); - prop.driveNo = i; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, - sizeof (prop), &prop, sizeof (prop), &dwResult, NULL); - - if (bResult) - { - if (LastRead[i] == prop.totalBytesRead - && LastWritten[i] == prop.totalBytesWritten - && LastId[i] == prop.uniqueId) - { - if (++InactivityTime[i] >= MaxVolumeIdleTime) - { - BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, i, 0); - - if (bCloseDismountedWindows && CloseVolumeExplorerWindows (MainDlg, i)) - Sleep (250); - - if (DriverUnmountVolume (MainDlg, i, bForceAutoDismount) == 0) - { - InactivityTime[i] = 0; - BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, i, 0); - - if (bWipeCacheOnAutoDismount) - { - DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - SecurityToken::CloseAllSessions(); - } - } - } - } - else - { - InactivityTime[i] = 0; - LastRead[i] = prop.totalBytesRead; - LastWritten[i] = prop.totalBytesWritten; - LastId[i] = prop.uniqueId; - } - } - } - } -} - - -BOOL MountFavoriteVolumes () -{ - BOOL status = TRUE; - DWORD size; - char *favorites = LoadFile (GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES), &size); - char *xml = favorites; - char mountPoint[MAX_PATH], volume[MAX_PATH]; - - if (xml == NULL) return FALSE; - - mountOptions = defaultMountOptions; - bPrebootPasswordDlgMode = FALSE; - - MultipleMountOperationInProgress = TRUE; - - while (xml = XmlFindElement (xml, "volume")) - { - int drive; - XmlGetAttributeText (xml, "mountpoint", mountPoint, sizeof (mountPoint)); - XmlGetNodeText (xml, volume, sizeof (volume)); - drive = toupper (mountPoint[0]) - 'A'; - - char boolVal[2]; - XmlGetAttributeText (xml, "readonly", boolVal, sizeof (boolVal)); - if (boolVal[0]) - mountOptions.ReadOnly = (boolVal[0] == '1' ? TRUE : FALSE); - - XmlGetAttributeText (xml, "removable", boolVal, sizeof (boolVal)); - if (boolVal[0]) - mountOptions.Removable = (boolVal[0] == '1' ? TRUE : FALSE); - - if ((LastKnownMountList.ulMountedDrives & (1 << drive)) == 0) - { - if (!Mount (MainDlg, drive, volume)) - status = FALSE; - LoadDriveLetters (GetDlgItem (MainDlg, IDC_DRIVELIST), 0); - } - - xml++; - } - - MultipleMountOperationInProgress = FALSE; - - if (status && CloseSecurityTokenSessionsAfterMount) - SecurityToken::CloseAllSessions(); - - free (favorites); - return status; -} - - -void SaveFavoriteVolumes () -{ - if (AskNoYes("CONFIRM_SAVE_FAVORITE_VOL") == IDYES) - { - FILE *f; - int i, cnt = 0; - - f = fopen (GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES), "w"); - if (f == NULL) - { - handleWin32Error (MainDlg); - return; - } - - XmlWriteHeader (f); - fputs ("\n\t", f); - - for (i = 0; i < 26; i++) - { - if (LastKnownMountList.ulMountedDrives & (1 << i)) - { - char t[2048], tq[2048]; - - sprintf_s (t, sizeof (t), "%ls", &LastKnownMountList.wszVolume[i][(LastKnownMountList.wszVolume[i][1] == L'?') ? 4 : 0]); - XmlQuoteText (t, tq, sizeof (tq)); - - VOLUME_PROPERTIES_STRUCT prop; - DWORD bytesReturned; - - memset (&prop, 0, sizeof(prop)); - prop.driveNo = i; - - if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &bytesReturned, NULL)) - { - handleWin32Error (NULL); - continue; - } - - fprintf (f, "\n\t\t%s", i + 'A', - (int) prop.readOnly, (int) prop.removable, tq); - - cnt++; - } - } - - fputs ("\n\t", f); - XmlWriteFooter (f); - fclose (f); - - if (cnt == 0) - remove (GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES)); // No volumes to save as favorite - - Info ("FAVORITE_VOLUMES_SAVED"); - } -} - - -static void SaveDefaultKeyFilesParam (void) -{ - if (defaultKeyFilesParam.FirstKeyFile == NULL) - { - /* No keyfiles selected */ - remove (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES)); - } - else - { - FILE *f; - KeyFile *kf = FirstKeyFile; - - f = fopen (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES), "w"); - if (f == NULL) - { - handleWin32Error (MainDlg); - return; - } - - XmlWriteHeader (f); - - fputs ("\n\t", f); - - while (kf != NULL) - { - char q[TC_MAX_PATH * 2]; - - XmlQuoteText (kf->FileName, q, sizeof (q)); - fprintf (f, "\n\t\t%s", q); - - kf = kf->Next; - } - - fputs ("\n\t", f); - - XmlWriteFooter (f); - - fclose (f); - return; - } -} - - -static void KeyfileDefaultsDlg (HWND hwndDlg) -{ - KeyFilesDlgParam param; - - param.EnableKeyFiles = defaultKeyFilesParam.EnableKeyFiles; - param.FirstKeyFile = defaultKeyFilesParam.FirstKeyFile; - - if (DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, - (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m) == IDOK) - { - if (!param.EnableKeyFiles || AskWarnYesNo ("CONFIRM_SAVE_DEFAULT_KEYFILES") == IDYES) - { - KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); - defaultKeyFilesParam.EnableKeyFiles = param.EnableKeyFiles; - defaultKeyFilesParam.FirstKeyFile = param.FirstKeyFile; - - RestoreDefaultKeyFilesParam (); - SaveDefaultKeyFilesParam (); - } - } -} - - -static void HandleHotKey (HWND hwndDlg, WPARAM wParam) -{ - DWORD dwResult; - BOOL success = TRUE; - - switch (wParam) - { - case HK_AUTOMOUNT_DEVICES: - MountAllDevices (hwndDlg, TRUE); - - if (bPlaySoundOnHotkeyMountDismount) - MessageBeep(-1); - - break; - - case HK_DISMOUNT_ALL: - case HK_DISMOUNT_ALL_AND_WIPE: - - if (wParam == HK_DISMOUNT_ALL_AND_WIPE) - WipeCache (hwndDlg, TRUE); - - if (DismountAll (hwndDlg, FALSE, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY) && bDisplayMsgBoxOnHotkeyDismount) - InfoTopMost (wParam == HK_DISMOUNT_ALL_AND_WIPE ? "VOLUMES_DISMOUNTED_CACHE_WIPED" : "MOUNTED_VOLUMES_DISMOUNTED"); - else if (bDisplayMsgBoxOnHotkeyDismount) - InfoTopMost (wParam == HK_DISMOUNT_ALL_AND_WIPE ? "PASSWORD_CACHE_WIPED" : "DISMOUNT_ALL_ATTEMPT_COMPLETED"); - - if (!bDisplayMsgBoxOnHotkeyDismount && bPlaySoundOnHotkeyMountDismount) - MessageBeep(-1); - - break; - - case HK_WIPE_CACHE: - WipeCache (hwndDlg, FALSE); - break; - - case HK_FORCE_DISMOUNT_ALL_AND_WIPE: - success = DismountAll (hwndDlg, TRUE, FALSE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); - success &= DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - if (success) - { - if (bPlaySoundOnHotkeyMountDismount) - MessageBeep(-1); - - if (bDisplayMsgBoxOnHotkeyDismount) - InfoTopMost ("VOLUMES_DISMOUNTED_CACHE_WIPED"); - } - break; - - case HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT: - success = DismountAll (hwndDlg, TRUE, FALSE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); - success &= DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - if (success) - { - if (bPlaySoundOnHotkeyMountDismount) - MessageBeep(-1); - - if (bDisplayMsgBoxOnHotkeyDismount) - InfoTopMost ("VOLUMES_DISMOUNTED_CACHE_WIPED"); - } - TaskBarIconRemove (hwndDlg); - EndMainDlg (hwndDlg); - break; - - case HK_MOUNT_FAVORITE_VOLUMES: - MountFavoriteVolumes (); - - if (bPlaySoundOnHotkeyMountDismount) - MessageBeep(-1); - - break; - - case HK_SHOW_HIDE_MAIN_WINDOW: - ChangeMainWindowVisibility (); - break; - - case HK_CLOSE_SECURITY_TOKEN_SESSIONS: - try - { - SecurityToken::CloseAllSessions(); - InfoTopMost ("ALL_TOKEN_SESSIONS_CLOSED"); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - break; - } -} - - -void ChangeMainWindowVisibility () -{ - MainWindowHidden = !MainWindowHidden; - - if (!MainWindowHidden) - SetForegroundWindow (MainDlg); - - ShowWindow (MainDlg, !MainWindowHidden ? SW_SHOW : SW_HIDE); - - if (!MainWindowHidden) - ShowWindow (MainDlg, SW_RESTORE); -} - - -int BackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume) -{ - int nStatus = ERR_OS_ERROR; - wchar_t szTmp[4096]; - int fBackup = -1; - OpenVolumeContext volume; - OpenVolumeContext hiddenVolume; - Password hiddenVolPassword; - byte temporaryKey[MASTER_KEYDATA_SIZE]; - byte originalK2[MASTER_KEYDATA_SIZE]; - - volume.VolumeIsOpen = FALSE; - hiddenVolume.VolumeIsOpen = FALSE; - - switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE)) - { - case 1: - case 2: - if (AskErrNoYes ("BACKUP_HEADER_NOT_FOR_SYS_DEVICE") == IDYES) - CreateRescueDisk (); - - return 0; - } - - if (IsMountedVolume (lpszVolume)) - { - Warning ("DISMOUNT_FIRST"); - goto ret; - } - - Info ("EXTERNAL_VOL_HEADER_BAK_FIRST_INFO"); - - - WaitCursor(); - - // Open both types of volumes - for (int type = TC_VOLUME_TYPE_NORMAL; type <= TC_VOLUME_TYPE_HIDDEN; ++type) - { - OpenVolumeContext *askVol = (type == TC_VOLUME_TYPE_HIDDEN ? &hiddenVolume : &volume); - Password *askPassword = (type == TC_VOLUME_TYPE_HIDDEN ? &hiddenVolPassword : &VolumePassword); - - while (TRUE) - { - if (!AskVolumePassword (hwndDlg, askPassword, type == TC_VOLUME_TYPE_HIDDEN ? "ENTER_HIDDEN_VOL_PASSWORD" : "ENTER_NORMAL_VOL_PASSWORD", FALSE)) - { - nStatus = ERR_SUCCESS; - goto ret; - } - - WaitCursor(); - - if (KeyFilesEnable && FirstKeyFile) - KeyFilesApply (askPassword, FirstKeyFile); - - nStatus = OpenVolume (askVol, lpszVolume, askPassword, FALSE, bPreserveTimestamp, FALSE); - - NormalCursor(); - - if (nStatus == ERR_SUCCESS) - { - if ((type == TC_VOLUME_TYPE_NORMAL && askVol->CryptoInfo->hiddenVolume) - || (type == TC_VOLUME_TYPE_HIDDEN && !askVol->CryptoInfo->hiddenVolume)) - { - CloseVolume (askVol); - handleError (hwndDlg, ERR_PASSWORD_WRONG); - continue; - } - - RandSetHashFunction (askVol->CryptoInfo->pkcs5); - - if (type == TC_VOLUME_TYPE_NORMAL) - { - // Ask the user if there is a hidden volume - char *volTypeChoices[] = {0, "DOES_VOLUME_CONTAIN_HIDDEN", "VOLUME_CONTAINS_HIDDEN", "VOLUME_DOES_NOT_CONTAIN_HIDDEN", "IDCANCEL", 0}; - switch (AskMultiChoice ((void **) volTypeChoices, FALSE)) - { - case 1: - break; - case 2: - goto noHidden; - - default: - nStatus = ERR_SUCCESS; - goto ret; - } - } - - break; - } - - if (nStatus != ERR_PASSWORD_WRONG) - goto error; - - handleError (hwndDlg, nStatus); - } - } -noHidden: - - if (hiddenVolume.VolumeIsOpen && volume.CryptoInfo->LegacyVolume != hiddenVolume.CryptoInfo->LegacyVolume) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto error; - } - - swprintf (szTmp, GetString ("CONFIRM_VOL_HEADER_BAK"), lpszVolume); - - if (bRequireConfirmation - && (MessageBoxW (hwndDlg, szTmp, lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON1) == IDNO)) - goto ret; - - /* Select backup file */ - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, TRUE, NULL)) - goto ret; - - /* Conceive the backup file */ - if ((fBackup = _open(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - // Backup headers - - byte backup[TC_VOLUME_HEADER_GROUP_SIZE]; - - bool legacyVolume = volume.CryptoInfo->LegacyVolume ? true : false; - int backupFileSize = legacyVolume ? TC_VOLUME_HEADER_SIZE_LEGACY * 2 : TC_VOLUME_HEADER_GROUP_SIZE; - - // Fill backup buffer with random data - memcpy (originalK2, volume.CryptoInfo->k2, sizeof (volume.CryptoInfo->k2)); - - if (Randinit() != ERR_SUCCESS) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto error; - } - - NormalCursor(); - UserEnrichRandomPool (hwndDlg); - WaitCursor(); - - // Temporary keys - if (!RandgetBytes (temporaryKey, EAGetKeySize (volume.CryptoInfo->ea), TRUE) - || !RandgetBytes (volume.CryptoInfo->k2, sizeof (volume.CryptoInfo->k2), FALSE)) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto error; - } - - if (EAInit (volume.CryptoInfo->ea, temporaryKey, volume.CryptoInfo->ks) != ERR_SUCCESS || !EAInitMode (volume.CryptoInfo)) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto error; - } - - EncryptBuffer (backup, backupFileSize, volume.CryptoInfo); - - memcpy (volume.CryptoInfo->k2, originalK2, sizeof (volume.CryptoInfo->k2)); - if (EAInit (volume.CryptoInfo->ea, volume.CryptoInfo->master_keydata, volume.CryptoInfo->ks) != ERR_SUCCESS || !EAInitMode (volume.CryptoInfo)) - { - nStatus = ERR_PARAMETER_INCORRECT; - goto error; - } - - // Store header encrypted with a new key - nStatus = ReEncryptVolumeHeader ((char *) backup, FALSE, volume.CryptoInfo, &VolumePassword, FALSE); - if (nStatus != ERR_SUCCESS) - goto error; - - if (hiddenVolume.VolumeIsOpen) - { - nStatus = ReEncryptVolumeHeader ((char *) backup + (legacyVolume ? TC_VOLUME_HEADER_SIZE_LEGACY : TC_VOLUME_HEADER_SIZE), - FALSE, hiddenVolume.CryptoInfo, &hiddenVolPassword, FALSE); - - if (nStatus != ERR_SUCCESS) - goto error; - } - - if (_write (fBackup, backup, backupFileSize) == -1) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - /* Backup has been successfully created */ - Warning("VOL_HEADER_BACKED_UP"); - -ret: - nStatus = ERR_SUCCESS; - -error: - DWORD dwError = GetLastError (); - - CloseVolume (&volume); - CloseVolume (&hiddenVolume); - - if (fBackup != -1) - _close (fBackup); - - SetLastError (dwError); - if (nStatus != 0) - handleError (hwndDlg, nStatus); - - burn (&VolumePassword, sizeof (VolumePassword)); - burn (&hiddenVolPassword, sizeof (hiddenVolPassword)); - burn (temporaryKey, sizeof (temporaryKey)); - burn (originalK2, sizeof (originalK2)); - - RestoreDefaultKeyFilesParam(); - RandStop (FALSE); - NormalCursor(); - - return nStatus; -} - - -int RestoreVolumeHeader (HWND hwndDlg, char *lpszVolume) -{ - int nDosLinkCreated = -1, nStatus = ERR_OS_ERROR; - char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; - char szFileName[TC_MAX_PATH]; - char szDosDevice[TC_MAX_PATH]; - void *dev = INVALID_HANDLE_VALUE; - DWORD dwError; - BOOL bDevice; - unsigned __int64 hostSize = 0; - FILETIME ftCreationTime; - FILETIME ftLastWriteTime; - FILETIME ftLastAccessTime; - wchar_t szTmp[4096]; - BOOL bTimeStampValid = FALSE; - HANDLE fBackup = INVALID_HANDLE_VALUE; - LARGE_INTEGER headerOffset; - CRYPTO_INFO *restoredCryptoInfo = NULL; - - switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE)) - { - case 1: - case 2: - if (AskErrNoYes ("RESTORE_HEADER_NOT_FOR_SYS_DEVICE") == IDYES) - CreateRescueDisk (); - - return 0; - - case -1: - // In some environments (such as PE), the system volume is not located on a hard drive. - // Therefore, we must interpret this return code as "Not a system device path" (otherwise, - // it would not be possible to restore headers on non-system devices in such environments). - // Note that this is rather safe, because bReliableRequired is set to TRUE. - - // NOP - break; - } - - if (IsMountedVolume (lpszVolume)) - { - Warning ("DISMOUNT_FIRST"); - return 0; - } - - - BOOL restoreInternalBackup; - - // Ask the user to select the type of backup (internal/external) - char *volTypeChoices[] = {0, "HEADER_RESTORE_EXTERNAL_INTERNAL", "HEADER_RESTORE_INTERNAL", "HEADER_RESTORE_EXTERNAL", "IDCANCEL", 0}; - switch (AskMultiChoice ((void **) volTypeChoices, FALSE)) - { - case 1: - restoreInternalBackup = TRUE; - break; - case 2: - restoreInternalBackup = FALSE; - break; - default: - return 0; - } - - OpenVolumeContext volume; - volume.VolumeIsOpen = FALSE; - - WaitCursor(); - - if (restoreInternalBackup) - { - // Restore header from the internal backup - - // Open the volume using backup header - while (TRUE) - { - strncpy (PasswordDlgVolume, lpszVolume, sizeof (PasswordDlgVolume)); - if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, FALSE)) - { - nStatus = ERR_SUCCESS; - goto ret; - } - - WaitCursor(); - - if (KeyFilesEnable && FirstKeyFile) - KeyFilesApply (&VolumePassword, FirstKeyFile); - - nStatus = OpenVolume (&volume, lpszVolume, &VolumePassword, TRUE, bPreserveTimestamp, TRUE); - - NormalCursor(); - - if (nStatus == ERR_SUCCESS) - break; - - if (nStatus != ERR_PASSWORD_WRONG) - goto error; - - handleError (hwndDlg, nStatus); - } - - if (volume.CryptoInfo->LegacyVolume) - { - Error ("VOLUME_HAS_NO_BACKUP_HEADER"); - nStatus = ERROR_SUCCESS; - goto error; - } - - // Create a new header with a new salt - char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - - nStatus = ReEncryptVolumeHeader (buffer, FALSE, volume.CryptoInfo, &VolumePassword, FALSE); - if (nStatus != 0) - goto error; - - headerOffset.QuadPart = volume.CryptoInfo->hiddenVolume ? TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_VOLUME_HEADER_OFFSET; - if (!SetFilePointerEx (volume.HostFileHandle, headerOffset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - DWORD bytesWritten; - if (!WriteFile (volume.HostFileHandle, buffer, sizeof (buffer), &bytesWritten, NULL)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - } - else - { - // Restore header from an external backup - - swprintf (szTmp, GetString ("CONFIRM_VOL_HEADER_RESTORE"), lpszVolume); - - if (MessageBoxW (hwndDlg, szTmp, lpszTitle, YES_NO|MB_ICONWARNING|MB_DEFBUTTON2) == IDNO) - { - nStatus = ERR_SUCCESS; - goto ret; - } - - /* Select backup file */ - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, FALSE, NULL)) - { - nStatus = ERR_SUCCESS; - goto ret; - } - - /* Open the backup file */ - fBackup = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (fBackup == INVALID_HANDLE_VALUE) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - // Determine size of the backup file - LARGE_INTEGER backupSize; - if (!GetFileSizeEx (fBackup, &backupSize)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice); - - if (bDevice == FALSE) - strcpy (szCFDevice, szDiskFile); - else - { - nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE); - if (nDosLinkCreated != 0) - goto error; - } - - // Open the volume - dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - - if (dev == INVALID_HANDLE_VALUE) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - // Determine volume host size - if (bDevice) - { - PARTITION_INFORMATION diskInfo; - DWORD dwResult; - BOOL bResult; - - bResult = GetPartitionInfo (lpszVolume, &diskInfo); - - if (bResult) - { - hostSize = diskInfo.PartitionLength.QuadPart; - } - else - { - DISK_GEOMETRY driveInfo; - - bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, - &driveInfo, sizeof (driveInfo), &dwResult, NULL); - - if (!bResult) - goto error; - - hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * - driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; - } - - if (hostSize == 0) - { - nStatus = ERR_VOL_SIZE_WRONG; - goto error; - } - } - else - { - LARGE_INTEGER fileSize; - if (!GetFileSizeEx (dev, &fileSize)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - hostSize = fileSize.QuadPart; - } - - if (!bDevice && bPreserveTimestamp) - { - /* Remember the container modification/creation date and time. */ - - if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) - { - bTimeStampValid = FALSE; - Warning ("GETFILETIME_FAILED_GENERIC"); - } - else - bTimeStampValid = TRUE; - } - - /* Read the volume header from the backup file */ - char buffer[TC_VOLUME_HEADER_GROUP_SIZE]; - - DWORD bytesRead; - if (!ReadFile (fBackup, buffer, sizeof (buffer), &bytesRead, NULL)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - if (bytesRead != backupSize.QuadPart) - { - nStatus = ERR_VOL_SIZE_WRONG; - goto error; - } - - LARGE_INTEGER headerOffset; - LARGE_INTEGER headerBackupOffset; - bool legacyBackup; - int headerOffsetBackupFile; - int headerSize; - - // Determine the format of the backup file - switch (backupSize.QuadPart) - { - case TC_VOLUME_HEADER_GROUP_SIZE: - headerSize = TC_VOLUME_HEADER_EFFECTIVE_SIZE; - legacyBackup = false; - break; - - case TC_VOLUME_HEADER_SIZE_LEGACY * 2: - headerSize = TC_VOLUME_HEADER_SIZE_LEGACY; - legacyBackup = true; - break; - - default: - Error ("HEADER_BACKUP_SIZE_INCORRECT"); - nStatus = ERR_SUCCESS; - goto error; - } - - // Open the header - while (TRUE) - { - if (!AskVolumePassword (hwndDlg, &VolumePassword, "ENTER_HEADER_BACKUP_PASSWORD", FALSE)) - { - nStatus = ERR_SUCCESS; - goto ret; - } - - if (KeyFilesEnable && FirstKeyFile) - KeyFilesApply (&VolumePassword, FirstKeyFile); - - // Decrypt volume header - headerOffsetBackupFile = 0; - for (int type = TC_VOLUME_TYPE_NORMAL; type <= TC_VOLUME_TYPE_HIDDEN; ++type) - { - if (type == TC_VOLUME_TYPE_HIDDEN) - headerOffsetBackupFile += (legacyBackup ? TC_VOLUME_HEADER_SIZE_LEGACY : TC_VOLUME_HEADER_SIZE); - - nStatus = ReadVolumeHeader (FALSE, buffer + headerOffsetBackupFile, &VolumePassword, &restoredCryptoInfo, NULL); - if (nStatus == ERR_SUCCESS) - break; - } - - if (nStatus == ERR_SUCCESS) - break; - - if (nStatus != ERR_PASSWORD_WRONG) - goto error; - - handleError (hwndDlg, nStatus); - } - - BOOL hiddenVol = restoredCryptoInfo->hiddenVolume; - - if (legacyBackup) - { - headerOffset.QuadPart = hiddenVol ? hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY : TC_VOLUME_HEADER_OFFSET; - } - else - { - headerOffset.QuadPart = hiddenVol ? TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_VOLUME_HEADER_OFFSET; - headerBackupOffset.QuadPart = hiddenVol ? hostSize - TC_VOLUME_HEADER_SIZE : hostSize - TC_VOLUME_HEADER_GROUP_SIZE; - } - - WaitCursor(); - - // Restore header encrypted with a new key - ReEncryptVolumeHeader (buffer, FALSE, restoredCryptoInfo, &VolumePassword, FALSE); - - if (!SetFilePointerEx (dev, headerOffset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - DWORD bytesWritten; - if (!WriteFile (dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &bytesWritten, NULL)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - if (!restoredCryptoInfo->LegacyVolume) - { - // Restore backup header encrypted with a new key - ReEncryptVolumeHeader (buffer, FALSE, restoredCryptoInfo, &VolumePassword, FALSE); - - if (!SetFilePointerEx (dev, headerBackupOffset, NULL, FILE_BEGIN)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - - if (!WriteFile (dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &bytesWritten, NULL)) - { - nStatus = ERR_OS_ERROR; - goto error; - } - } - } - - - /* Volume header has been successfully restored */ - - Info("VOL_HEADER_RESTORED"); -ret: - nStatus = ERR_SUCCESS; - -error: - dwError = GetLastError (); - NormalCursor(); - - if (restoreInternalBackup) - { - CloseVolume (&volume); - } - else - { - if (restoredCryptoInfo) - crypto_close (restoredCryptoInfo); - - if (bTimeStampValid) - { - // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). - if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) - MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); - } - - if (dev != INVALID_HANDLE_VALUE) - CloseHandle (dev); - - if (fBackup != INVALID_HANDLE_VALUE) - CloseHandle (fBackup); - - if (nDosLinkCreated == 0) - RemoveFakeDosName (szDiskFile, szDosDevice); - } - - SetLastError (dwError); - if (nStatus != 0) - handleError (hwndDlg, nStatus); - - burn (&VolumePassword, sizeof (VolumePassword)); - RestoreDefaultKeyFilesParam(); - RandStop (FALSE); - NormalCursor(); - - return nStatus; -} - - -void ReadDriverConfiguration (DriverConfiguration *configuration) -{ - DWORD configMap; - memset (configuration, 0, sizeof (*configuration)); - - if (ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, &configMap)) - { - if (configMap & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD) - configuration->CacheBootPassword = TRUE; - } -} - - -void WriteDriverConfiguration (DriverConfiguration *configuration) -{ - DWORD configMap = 0; - - if (configuration->CacheBootPassword) - configMap |= TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD; - - BootEncObj->WriteLocalMachineRegistryDwordValue ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, configMap); -} - - -static BOOL CALLBACK SecurityTokenPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - LocalizeDialog (hwndDlg, "IDD_TOKEN_PREFERENCES"); - SetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, SecurityTokenLibraryPath); - CheckDlgButton (hwndDlg, IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT, CloseSecurityTokenSessionsAfterMount ? BST_CHECKED : BST_UNCHECKED); - - SetWindowTextW (GetDlgItem (hwndDlg, IDT_PKCS11_LIB_HELP), GetString("PKCS11_LIB_LOCATION_HELP")); - - return 0; - - case WM_COMMAND: - - switch (lw) - { - case IDCANCEL: - EndDialog (hwndDlg, lw); - return 1; - - case IDOK: - { - char securityTokenLibraryPath[MAX_PATH]; - GetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, securityTokenLibraryPath, sizeof (securityTokenLibraryPath)); - - if (securityTokenLibraryPath[0] == 0) - { - try - { - SecurityToken::CloseLibrary(); - } - catch (...) { } - - SecurityTokenLibraryPath[0] = 0; - } - else - { - char prevSecurityTokenLibraryPath[MAX_PATH]; - strcpy (prevSecurityTokenLibraryPath, SecurityTokenLibraryPath); - strcpy (SecurityTokenLibraryPath, securityTokenLibraryPath); - - if (!InitSecurityTokenLibrary()) - { - strcpy (SecurityTokenLibraryPath, prevSecurityTokenLibraryPath); - return 1; - } - } - - CloseSecurityTokenSessionsAfterMount = (IsDlgButtonChecked (hwndDlg, IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT) == BST_CHECKED); - - WaitCursor (); - SaveSettings (hwndDlg); - NormalCursor (); - - EndDialog (hwndDlg, lw); - return 1; - } - - case IDC_AUTO_DETECT_PKCS11_MODULE: - { - char systemDir[MAX_PATH]; - GetSystemDirectory (systemDir, sizeof (systemDir)); - WIN32_FIND_DATA findData; - bool found = false; - - WaitCursor(); - - HANDLE find = FindFirstFile ((string (systemDir) + "\\*.dll").c_str(), &findData); - while (!found && find != INVALID_HANDLE_VALUE) - { - string dllPathname = string (systemDir) + "\\" + findData.cFileName; - DWORD fileSize; - - char *file = LoadFile (dllPathname.c_str(), &fileSize); - if (file) - { - const char *functionName = "C_GetFunctionList"; - size_t strLen = strlen (functionName); - - if (fileSize > strLen) - { - for (size_t i = 0; i < fileSize - strLen; ++i) - { - if (memcmp (file + i, functionName, strLen) == 0) - { - HMODULE module = LoadLibrary (dllPathname.c_str()); - if (module) - { - if (GetProcAddress (module, functionName)) - { - SetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, dllPathname.c_str()); - found = true; - - FreeLibrary (module); - break; - } - - FreeLibrary (module); - } - } - } - } - - free (file); - } - - if (!FindNextFile (find, &findData)) - break; - } - - if (find != INVALID_HANDLE_VALUE) - FindClose (find); - - NormalCursor(); - - if (!found) - Warning ("PKCS11_MODULE_AUTO_DETECTION_FAILED"); - - return 1; - } - - case IDC_SELECT_PKCS11_MODULE: - { - char securityTokenLibraryPath[MAX_PATH]; - char systemDir[MAX_PATH]; - wchar_t browseFilter[1024]; - - Info ("SELECT_PKCS11_MODULE_HELP"); - - wsprintfW (browseFilter, L"%ls (*.dll)%c*.dll%c%c", GetString ("DLL_FILES"), 0, 0, 0); - GetSystemDirectory (systemDir, sizeof (systemDir)); - - if (BrowseFilesInDir (hwndDlg, "SELECT_PKCS11_MODULE", systemDir, securityTokenLibraryPath, TRUE, FALSE, browseFilter)) - SetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, securityTokenLibraryPath); - return 1; - } - } - return 0; - } - - return 0; -} - - -void SecurityTokenPreferencesDialog (HWND hwndDlg) -{ - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PREFERENCES), hwndDlg, (DLGPROC) SecurityTokenPreferencesDlgProc, 0); -} - - -static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - if (!BootEncStatus.DriveMounted) - { - Warning ("SYS_DRIVE_NOT_ENCRYPTED"); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - try - { - LocalizeDialog (hwndDlg, "IDD_SYSENC_SETTINGS"); - - byte userConfig; - string customUserMessage; - DriverConfiguration driverConfig; - uint16 bootLoaderVersion; - - BootEncObj->ReadBootSectorConfig (nullptr, 0, &userConfig, &customUserMessage, &bootLoaderVersion); - - if (bootLoaderVersion != VERSION_NUM) - Warning ("BOOT_LOADER_VERSION_INCORRECT_PREFERENCES"); - - ReadDriverConfiguration (&driverConfig); - - SendMessage (GetDlgItem (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE), EM_LIMITTEXT, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, 0); - SetDlgItemText (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE, customUserMessage.c_str()); - - CheckDlgButton (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT, (userConfig & TC_BOOT_USER_CFG_FLAG_SILENT_MODE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton (hwndDlg, IDC_ALLOW_ESC_PBA_BYPASS, (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_ESC) ? BST_UNCHECKED : BST_CHECKED); - CheckDlgButton (hwndDlg, IDC_BOOT_LOADER_CACHE_PASSWORD, driverConfig.CacheBootPassword ? BST_CHECKED : BST_UNCHECKED); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE_HELP), GetString("CUSTOM_BOOT_LOADER_MESSAGE_HELP")); - } - catch (Exception &e) - { - e.Show (hwndDlg); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - } - return 0; - - case WM_COMMAND: - - switch (lw) - { - case IDCANCEL: - EndDialog (hwndDlg, lw); - return 1; - - case IDOK: - { - char customUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; - GetDlgItemText (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE, customUserMessage, sizeof (customUserMessage)); - - byte userConfig = 0; - if (IsDlgButtonChecked (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT)) - userConfig |= TC_BOOT_USER_CFG_FLAG_SILENT_MODE; - - if (!IsDlgButtonChecked (hwndDlg, IDC_ALLOW_ESC_PBA_BYPASS)) - userConfig |= TC_BOOT_USER_CFG_FLAG_DISABLE_ESC; - - DriverConfiguration driverConfig; - driverConfig.CacheBootPassword = IsDlgButtonChecked (hwndDlg, IDC_BOOT_LOADER_CACHE_PASSWORD); - - try - { - BootEncObj->WriteBootSectorUserConfig (userConfig, customUserMessage); - WriteDriverConfiguration (&driverConfig); - } - catch (Exception &e) - { - e.Show (hwndDlg); - return 1; - } - - EndDialog (hwndDlg, lw); - return 1; - } - - case IDC_DISABLE_BOOT_LOADER_OUTPUT: - if ((IsDlgButtonChecked (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT)) - && AskWarnYesNo ("CUSTOM_BOOT_LOADER_MESSAGE_PROMPT") == IDNO) - { - CheckDlgButton (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT, BST_UNCHECKED); - } - - break; - - case IDC_BOOT_LOADER_CACHE_PASSWORD: - if (IsDlgButtonChecked (hwndDlg, IDC_BOOT_LOADER_CACHE_PASSWORD)) - Warning ("BOOT_PASSWORD_CACHE_KEYBOARD_WARNING"); - - break; - } - return 0; - } - - return 0; -} - - -void MountSelectedVolume (HWND hwndDlg, BOOL mountWithOptions) -{ - if (!VolumeSelected(hwndDlg)) - { - Warning ("NO_VOLUME_SELECTED"); - } - else if (LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == TC_MLIST_ITEM_FREE) - { - mountOptions = defaultMountOptions; - bPrebootPasswordDlgMode = FALSE; - - if (mountWithOptions || GetAsyncKeyState (VK_CONTROL) < 0) - { - if (IDCANCEL == DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg, - (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions)) - return; - - if (mountOptions.ProtectHiddenVolume && hidVolProtKeyFilesParam.EnableKeyFiles) - KeyFilesApply (&mountOptions.ProtectedHidVolPassword, hidVolProtKeyFilesParam.FirstKeyFile); - } - - if (CheckMountList ()) - Mount (hwndDlg, 0, 0); - } - else - Warning ("SELECT_FREE_DRIVE"); -} +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "Tcdefs.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Apidrvr.h" +#include "BootEncryption.h" +#include "Cmdline.h" +#include "Crypto.h" +#include "Dlgcode.h" +#include "Combo.h" +#include "Hotkeys.h" +#include "Keyfiles.h" +#include "Language.h" +#include "MainCom.h" +#include "Mount.h" +#include "Pkcs5.h" +#include "Random.h" +#include "Registry.h" +#include "Resource.h" +#include "Password.h" +#include "Xml.h" +#include "../Boot/Windows/BootCommon.h" +#include "../Common/Dictionary.h" +#include "../Common/Common.h" +#include "../Common/Resource.h" +#include "../Common/SecurityToken.h" +#include "../Platform/Finally.h" +#include "../Platform/ForEach.h" + +using namespace TrueCrypt; + +enum timer_ids +{ + TIMER_ID_MAIN = 0xff, + TIMER_ID_KEYB_LAYOUT_GUARD +}; + +enum hidden_os_read_only_notif_mode +{ + TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE = 0, + TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_COMPACT, + TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_DISABLED +}; + +#define TIMER_INTERVAL_MAIN 500 +#define TIMER_INTERVAL_KEYB_LAYOUT_GUARD 10 + +BootEncryption *BootEncObj = NULL; +BootEncryptionStatus BootEncStatus; +BootEncryptionStatus RecentBootEncStatus; + +BOOL bExplore = FALSE; /* Display explorer window after mount */ +BOOL bBeep = FALSE; /* Donot beep after mount */ +char szFileName[TC_MAX_PATH+1]; /* Volume to mount */ +char szDriveLetter[3]; /* Drive Letter to mount */ +char commandLineDrive = 0; +BOOL bCacheInDriver = FALSE; /* Cache any passwords we see */ +BOOL bCacheInDriverDefault = FALSE; +BOOL bHistoryCmdLine = FALSE; /* History control is always disabled */ +BOOL bCloseDismountedWindows=TRUE; /* Close all open explorer windows of dismounted volume */ +BOOL bWipeCacheOnExit = FALSE; /* Wipe password from chace on exit */ +BOOL bWipeCacheOnAutoDismount = TRUE; +BOOL bEnableBkgTask = FALSE; +BOOL bCloseBkgTaskWhenNoVolumes = FALSE; +BOOL bDismountOnLogOff = TRUE; +BOOL bDismountOnScreenSaver = TRUE; +BOOL bDismountOnPowerSaving = FALSE; +BOOL bForceAutoDismount = TRUE; +BOOL bForceMount = FALSE; /* Mount volume even if host file/device already in use */ +BOOL bForceUnmount = FALSE; /* Unmount volume even if it cannot be locked */ +BOOL bWipe = FALSE; /* Wipe driver passwords */ +BOOL bAuto = FALSE; /* Do everything without user input */ +BOOL bAutoMountDevices = FALSE; /* Auto-mount devices */ +BOOL bAutoMountFavorites = FALSE; +BOOL bPlaySoundOnHotkeyMountDismount = TRUE; +BOOL bDisplayMsgBoxOnHotkeyDismount = FALSE; +BOOL bHibernationPreventionNotified = FALSE; /* TRUE if the user has been notified that hibernation was prevented (system encryption) during the session. */ +BOOL bHiddenSysLeakProtNotifiedDuringSession = FALSE; /* TRUE if the user has been notified during the session that unencrypted filesystems and non-hidden TrueCrypt volumes are mounted as read-only under hidden OS. */ +BOOL CloseSecurityTokenSessionsAfterMount = FALSE; + +BOOL MultipleMountOperationInProgress = FALSE; + +BOOL Quit = FALSE; /* Exit after processing command line */ +BOOL ComServerMode = FALSE; +BOOL ServiceMode = FALSE; +BOOL UsePreferences = TRUE; + +int HiddenSysLeakProtectionNotificationStatus = TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE; +int MaxVolumeIdleTime = -120; +int nCurrentShowType = 0; /* current display mode, mount, unmount etc */ +int nSelectedDriveIndex = -1; /* Item number of selected drive */ + +int cmdUnmountDrive = 0; /* Volume drive letter to unmount (-1 = all) */ +Password VolumePassword; /* Password used for mounting volumes */ +Password CmdVolumePassword; /* Password passed from command line */ +BOOL CmdVolumePasswordValid = FALSE; +MountOptions CmdMountOptions; +BOOL CmdMountOptionsValid = FALSE; +MountOptions mountOptions; +MountOptions defaultMountOptions; +KeyFile *FirstCmdKeyFile; + +HBITMAP hbmLogoBitmapRescaled = NULL; +char OrigKeyboardLayout [8+1] = "00000409"; +BOOL bKeyboardLayoutChanged = FALSE; /* TRUE if the keyboard layout was changed to the standard US keyboard layout (from any other layout). */ +BOOL bKeybLayoutAltKeyWarningShown = FALSE; /* TRUE if the user has been informed that it is not possible to type characters by pressing keys while the right Alt key is held down. */ + +static KeyFilesDlgParam hidVolProtKeyFilesParam; + +static MOUNT_LIST_STRUCT LastKnownMountList; +VOLUME_NOTIFICATIONS_LIST VolumeNotificationsList; +static DWORD LastKnownLogicalDrives; + +static HANDLE TaskBarIconMutex = NULL; +static BOOL MainWindowHidden = FALSE; +static int pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; +static int bSysEncPwdChangeDlgMode = FALSE; +static int bPrebootPasswordDlgMode = FALSE; +static int NoCmdLineArgs; +static BOOL CmdLineVolumeSpecified; +static int LastDriveListVolumeColumnWidth; + +static void localcleanup (void) +{ + // Wipe command line + char *c = GetCommandLineA (); + wchar_t *wc = GetCommandLineW (); + burn(c, strlen (c)); + burn(wc, wcslen (wc) * sizeof (wchar_t)); + + /* Delete buffered bitmaps (if any) */ + if (hbmLogoBitmapRescaled != NULL) + { + DeleteObject ((HGDIOBJ) hbmLogoBitmapRescaled); + hbmLogoBitmapRescaled = NULL; + } + + /* These items should have already been cleared by the functions that used them, but we're going to + clear them for extra security. */ + burn (&VolumePassword, sizeof (VolumePassword)); + burn (&CmdVolumePassword, sizeof (CmdVolumePassword)); + burn (&mountOptions, sizeof (mountOptions)); + burn (&defaultMountOptions, sizeof (defaultMountOptions)); + burn (&szFileName, sizeof(szFileName)); + + /* Cleanup common code resources */ + cleanup (); + + if (BootEncObj != NULL) + { + delete BootEncObj; + BootEncObj = NULL; + } + + RandStop (TRUE); +} + +void RefreshMainDlg (HWND hwndDlg) +{ + int drive = (char) (HIWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)))); + + MoveEditToCombo (GetDlgItem (hwndDlg, IDC_VOLUME), bHistory); + LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), drive); + EnableDisableButtons (hwndDlg); +} + +void EndMainDlg (HWND hwndDlg) +{ + MoveEditToCombo (GetDlgItem (hwndDlg, IDC_VOLUME), bHistory); + + if (UsePreferences) + SaveSettings (hwndDlg); + + if (bWipeCacheOnExit) + { + DWORD dwResult; + DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + } + + if (!bHistory) + { + SetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), ""); + ClearHistory (GetDlgItem (hwndDlg, IDC_VOLUME)); + } + + if (TaskBarIconMutex != NULL) + { + MainWindowHidden = TRUE; + ShowWindow (hwndDlg, SW_HIDE); + } + else + { + TaskBarIconRemove (hwndDlg); + EndDialog (hwndDlg, 0); + } +} + +static void InitMainDialog (HWND hwndDlg) +{ + MENUITEMINFOW info; + char *popupTexts[] = {"MENU_VOLUMES", "MENU_SYSTEM_ENCRYPTION", "MENU_KEYFILES", "MENU_TOOLS", "MENU_SETTINGS", "MENU_HELP", "MENU_WEBSITE", 0}; + wchar_t *str; + int i; + + /* Call the common dialog init code */ + InitDialog (hwndDlg); + LocalizeDialog (hwndDlg, NULL); + + SetWindowLongPtr (hwndDlg, DWLP_USER, (LONG_PTR) (IsAdmin() ? TC_MAIN_WINDOW_FLAG_ADMIN_PRIVILEGES : 0)); + + DragAcceptFiles (hwndDlg, TRUE); + + SendMessage (GetDlgItem (hwndDlg, IDC_VOLUME), CB_LIMITTEXT, TC_MAX_PATH, 0); + SetWindowTextW (hwndDlg, (IsAdmin() && !IsBuiltInAdmin() && IsUacSupported() && !IsNonInstallMode()) ? (wstring (lpszTitle) + L" [" + GetString ("ADMINISTRATOR") + L"]").c_str() : lpszTitle); + + // Help file name + InitHelpFileName(); + + // Localize menu strings + for (i = 40001; str = (wchar_t *)GetDictionaryValueByInt (i); i++) + { + info.cbSize = sizeof (info); + info.fMask = MIIM_TYPE; + info.fType = MFT_STRING; + info.dwTypeData = str; + info.cch = wcslen (str); + + SetMenuItemInfoW (GetMenu (hwndDlg), i, FALSE, &info); + } + + for (i = 0; popupTexts[i] != 0; i++) + { + str = GetString (popupTexts[i]); + + info.cbSize = sizeof (info); + info.fMask = MIIM_TYPE; + + if (memcmp (popupTexts[i], "MENU_WEBSITE", 6) == 0) + info.fType = MFT_STRING | MFT_RIGHTJUSTIFY; + else + info.fType = MFT_STRING; + + info.dwTypeData = str; + info.cch = wcslen (str); + + SetMenuItemInfoW (GetMenu (hwndDlg), i, TRUE, &info); + } + + // Resize the logo bitmap if the user has a non-default DPI + if (ScreenDPI != USER_DEFAULT_SCREEN_DPI + && hbmLogoBitmapRescaled == NULL) // If not re-called (e.g. after language pack change) + { + hbmLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_LOGO_288DPI), + GetDlgItem (hwndDlg, IDC_LOGO), + 0, 0, 0, 0, FALSE, TRUE); + } + + BuildTree (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + + if (*szDriveLetter != 0) + { + SelectItem (GetDlgItem (hwndDlg, IDC_DRIVELIST), *szDriveLetter); + + if(nSelectedDriveIndex > SendMessage (GetDlgItem (hwndDlg, IDC_DRIVELIST), LVM_GETITEMCOUNT, 0, 0)/2) + SendMessage(GetDlgItem (hwndDlg, IDC_DRIVELIST), LVM_SCROLL, 0, 1000); + } + + SendMessage (GetDlgItem (hwndDlg, IDC_NO_HISTORY), BM_SETCHECK, bHistory ? BST_UNCHECKED : BST_CHECKED, 0); + EnableDisableButtons (hwndDlg); +} + +void EnableDisableButtons (HWND hwndDlg) +{ + HWND hOKButton = GetDlgItem (hwndDlg, IDOK); + WORD x; + + x = LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))); + + EnableMenuItem (GetMenu (hwndDlg), IDM_MOUNT_VOLUME, MF_ENABLED); + EnableMenuItem (GetMenu (hwndDlg), IDM_MOUNT_VOLUME_OPTIONS, MF_ENABLED); + EnableMenuItem (GetMenu (hwndDlg), IDM_BACKUP_VOL_HEADER, MF_ENABLED); + EnableMenuItem (GetMenu (hwndDlg), IDM_RESTORE_VOL_HEADER, MF_ENABLED); + EnableMenuItem (GetMenu (hwndDlg), IDM_CHANGE_PASSWORD, MF_ENABLED); + EnableWindow (hOKButton, TRUE); + + switch (x) + { + case TC_MLIST_ITEM_NONSYS_VOL: + { + SetWindowTextW (hOKButton, GetString ("UNMOUNT_BUTTON")); + EnableWindow (hOKButton, TRUE); + EnableMenuItem (GetMenu (hwndDlg), IDM_UNMOUNT_VOLUME, MF_ENABLED); + + EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES), TRUE); + EnableMenuItem (GetMenu (hwndDlg), IDM_VOLUME_PROPERTIES, MF_ENABLED); + } + break; + + case TC_MLIST_ITEM_SYS_PARTITION: + case TC_MLIST_ITEM_SYS_DRIVE: + EnableWindow (hOKButton, FALSE); + SetWindowTextW (hOKButton, GetString ("MOUNT_BUTTON")); + EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES), TRUE); + EnableMenuItem (GetMenu (hwndDlg), IDM_UNMOUNT_VOLUME, MF_GRAYED); + break; + + case TC_MLIST_ITEM_FREE: + default: + SetWindowTextW (hOKButton, GetString ("MOUNT_BUTTON")); + EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES), FALSE); + EnableMenuItem (GetMenu (hwndDlg), IDM_VOLUME_PROPERTIES, MF_GRAYED); + EnableMenuItem (GetMenu (hwndDlg), IDM_UNMOUNT_VOLUME, MF_GRAYED); + } + + EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_CACHE), !IsPasswordCacheEmpty()); + EnableMenuItem (GetMenu (hwndDlg), IDM_WIPE_CACHE, IsPasswordCacheEmpty() ? MF_GRAYED:MF_ENABLED); + EnableMenuItem (GetMenu (hwndDlg), IDM_CLEAR_HISTORY, IsComboEmpty (GetDlgItem (hwndDlg, IDC_VOLUME)) ? MF_GRAYED:MF_ENABLED); +} + +BOOL VolumeSelected (HWND hwndDlg) +{ + return (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_VOLUME)) > 0); +} + +/* Returns TRUE if the last partition/drive selected via the Select Device dialog box was the system +partition/drive and if it is encrypted. + WARNING: This function is very fast but not always reliable (for example, if the user manually types + a device path before Select Device is invoked during the session; after the Select Device dialog + has been invoked at least once, the correct system device paths are cached). Therefore, it must NOT + be used before performing any dangerous operations (such as header backup restore or formatting a + supposedly non-system device) -- instead use IsSystemDevicePath(path, hwndDlg, TRUE) for such + purposes. This function can be used only for preliminary GUI checks requiring very fast responses. */ +BOOL ActiveSysEncDeviceSelected (void) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + + if (BootEncStatus.DriveEncrypted) + { + int retCode = 0; + + GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szFileName, sizeof (szFileName)); + + retCode = IsSystemDevicePath (szFileName, MainDlg, FALSE); + + return (WholeSysDriveEncryption(FALSE) ? (retCode == 2 || retCode == 1) : (retCode == 1)); + } + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + return FALSE; +} + +void LoadSettings (HWND hwndDlg) +{ + WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE; + + LoadSysEncSettings (hwndDlg); + + if (LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) != 0) + bInPlaceEncNonSysPending = TRUE; + + // If the config file has already been loaded during this session + if (ConfigBuffer != NULL) + { + free (ConfigBuffer); + ConfigBuffer = NULL; + } + + // Options + bExplore = ConfigReadInt ("OpenExplorerWindowAfterMount", FALSE); + bCloseDismountedWindows = ConfigReadInt ("CloseExplorerWindowsOnDismount", TRUE); + + bHistory = ConfigReadInt ("SaveVolumeHistory", FALSE); + + bCacheInDriverDefault = bCacheInDriver = ConfigReadInt ("CachePasswords", FALSE); + bWipeCacheOnExit = ConfigReadInt ("WipePasswordCacheOnExit", FALSE); + bWipeCacheOnAutoDismount = ConfigReadInt ("WipeCacheOnAutoDismount", TRUE); + + bStartOnLogon = ConfigReadInt ("StartOnLogon", FALSE); + bMountDevicesOnLogon = ConfigReadInt ("MountDevicesOnLogon", FALSE); + bMountFavoritesOnLogon = ConfigReadInt ("MountFavoritesOnLogon", FALSE); + + bEnableBkgTask = ConfigReadInt ("EnableBackgroundTask", TRUE); + bCloseBkgTaskWhenNoVolumes = ConfigReadInt ("CloseBackgroundTaskOnNoVolumes", FALSE); + + bDismountOnLogOff = ConfigReadInt ("DismountOnLogOff", !(IsServerOS() && IsAdmin())); + bDismountOnPowerSaving = ConfigReadInt ("DismountOnPowerSaving", FALSE); + bDismountOnScreenSaver = ConfigReadInt ("DismountOnScreenSaver", FALSE); + bForceAutoDismount = ConfigReadInt ("ForceAutoDismount", TRUE); + MaxVolumeIdleTime = ConfigReadInt ("MaxVolumeIdleTime", -60); + + HiddenSectorDetectionStatus = ConfigReadInt ("HiddenSectorDetectionStatus", 0); + + defaultKeyFilesParam.EnableKeyFiles = ConfigReadInt ("UseKeyfiles", FALSE); + + bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = ConfigReadInt ("PreserveTimestamps", TRUE); + defaultMountOptions.Removable = ConfigReadInt ("MountVolumesRemovable", FALSE); + defaultMountOptions.ReadOnly = ConfigReadInt ("MountVolumesReadOnly", FALSE); + defaultMountOptions.ProtectHiddenVolume = FALSE; + defaultMountOptions.PartitionInInactiveSysEncScope = FALSE; + defaultMountOptions.RecoveryMode = FALSE; + defaultMountOptions.UseBackupHeader = FALSE; + + mountOptions = defaultMountOptions; + + CloseSecurityTokenSessionsAfterMount = ConfigReadInt ("CloseSecurityTokenSessionsAfterMount", 0); + + if (IsHiddenOSRunning()) + HiddenSysLeakProtectionNotificationStatus = ConfigReadInt ("HiddenSystemLeakProtNotifStatus", TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE); + + // Drive letter - command line arg overrides registry + if (szDriveLetter[0] == 0) + ConfigReadString ("LastSelectedDrive", "", szDriveLetter, sizeof (szDriveLetter)); + + ConfigReadString ("SecurityTokenLibrary", "", SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath) - 1); + if (SecurityTokenLibraryPath[0]) + InitSecurityTokenLibrary(); + + // Hotkeys + bPlaySoundOnHotkeyMountDismount = ConfigReadInt ("PlaySoundOnHotkeyMountDismount", TRUE); + bDisplayMsgBoxOnHotkeyDismount = ConfigReadInt ("DisplayMsgBoxOnHotkeyDismount", FALSE); + Hotkeys [HK_AUTOMOUNT_DEVICES].vKeyModifiers = ConfigReadInt ("HotkeyModAutoMountDevices", 0); + Hotkeys [HK_AUTOMOUNT_DEVICES].vKeyCode = ConfigReadInt ("HotkeyCodeAutoMountDevices", 0); + Hotkeys [HK_DISMOUNT_ALL].vKeyModifiers = ConfigReadInt ("HotkeyModDismountAll", 0); + Hotkeys [HK_DISMOUNT_ALL].vKeyCode = ConfigReadInt ("HotkeyCodeDismountAll", 0); + Hotkeys [HK_WIPE_CACHE].vKeyModifiers = ConfigReadInt ("HotkeyModWipeCache", 0); + Hotkeys [HK_WIPE_CACHE].vKeyCode = ConfigReadInt ("HotkeyCodeWipeCache", 0); + Hotkeys [HK_DISMOUNT_ALL_AND_WIPE].vKeyModifiers = ConfigReadInt ("HotkeyModDismountAllWipe", 0); + Hotkeys [HK_DISMOUNT_ALL_AND_WIPE].vKeyCode = ConfigReadInt ("HotkeyCodeDismountAllWipe", 0); + Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyModifiers = ConfigReadInt ("HotkeyModForceDismountAllWipe", 0); + Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyCode = ConfigReadInt ("HotkeyCodeForceDismountAllWipe", 0); + Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyModifiers = ConfigReadInt ("HotkeyModForceDismountAllWipeExit", 0); + Hotkeys [HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyCode = ConfigReadInt ("HotkeyCodeForceDismountAllWipeExit", 0); + Hotkeys [HK_MOUNT_FAVORITE_VOLUMES].vKeyModifiers = ConfigReadInt ("HotkeyModMountFavoriteVolumes", 0); + Hotkeys [HK_MOUNT_FAVORITE_VOLUMES].vKeyCode = ConfigReadInt ("HotkeyCodeMountFavoriteVolumes", 0); + Hotkeys [HK_SHOW_HIDE_MAIN_WINDOW].vKeyModifiers = ConfigReadInt ("HotkeyModShowHideMainWindow", 0); + Hotkeys [HK_SHOW_HIDE_MAIN_WINDOW].vKeyCode = ConfigReadInt ("HotkeyCodeShowHideMainWindow", 0); + Hotkeys [HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyModifiers = ConfigReadInt ("HotkeyModCloseSecurityTokenSessions", 0); + Hotkeys [HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyCode = ConfigReadInt ("HotkeyCodeCloseSecurityTokenSessions", 0); + + // History + if (bHistoryCmdLine != TRUE) + { + LoadCombo (GetDlgItem (hwndDlg, IDC_VOLUME)); + if (CmdLineVolumeSpecified) + SetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName); + } +} + +void SaveSettings (HWND hwndDlg) +{ + WaitCursor (); + + char szTmp[32] = {0}; + LPARAM lLetter; + + // Options + ConfigWriteBegin (); + + ConfigWriteInt ("OpenExplorerWindowAfterMount", bExplore); + ConfigWriteInt ("CloseExplorerWindowsOnDismount", bCloseDismountedWindows); + ConfigWriteInt ("SaveVolumeHistory", !IsButtonChecked (GetDlgItem (hwndDlg, IDC_NO_HISTORY))); + + ConfigWriteInt ("CachePasswords", bCacheInDriverDefault); + ConfigWriteInt ("WipePasswordCacheOnExit", bWipeCacheOnExit); + ConfigWriteInt ("WipeCacheOnAutoDismount", bWipeCacheOnAutoDismount); + + ConfigWriteInt ("StartOnLogon", bStartOnLogon); + ConfigWriteInt ("MountDevicesOnLogon", bMountDevicesOnLogon); + ConfigWriteInt ("MountFavoritesOnLogon", bMountFavoritesOnLogon); + + ConfigWriteInt ("MountVolumesReadOnly", defaultMountOptions.ReadOnly); + ConfigWriteInt ("MountVolumesRemovable", defaultMountOptions.Removable); + ConfigWriteInt ("PreserveTimestamps", defaultMountOptions.PreserveTimestamp); + + ConfigWriteInt ("EnableBackgroundTask", bEnableBkgTask); + ConfigWriteInt ("CloseBackgroundTaskOnNoVolumes", bCloseBkgTaskWhenNoVolumes); + + ConfigWriteInt ("DismountOnLogOff", bDismountOnLogOff); + ConfigWriteInt ("DismountOnPowerSaving", bDismountOnPowerSaving); + ConfigWriteInt ("DismountOnScreenSaver", bDismountOnScreenSaver); + ConfigWriteInt ("ForceAutoDismount", bForceAutoDismount); + ConfigWriteInt ("MaxVolumeIdleTime", MaxVolumeIdleTime); + + ConfigWriteInt ("HiddenSectorDetectionStatus", HiddenSectorDetectionStatus); + + ConfigWriteInt ("UseKeyfiles", defaultKeyFilesParam.EnableKeyFiles); + + if (IsHiddenOSRunning()) + ConfigWriteInt ("HiddenSystemLeakProtNotifStatus", HiddenSysLeakProtectionNotificationStatus); + + // Drive Letter + lLetter = GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + if (LOWORD (lLetter) != 0xffff) + sprintf (szTmp, "%c:", (char) HIWORD (lLetter)); + ConfigWriteString ("LastSelectedDrive", szTmp); + + ConfigWriteInt ("CloseSecurityTokenSessionsAfterMount", CloseSecurityTokenSessionsAfterMount); + + // Hotkeys + ConfigWriteInt ("HotkeyModAutoMountDevices", Hotkeys[HK_AUTOMOUNT_DEVICES].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeAutoMountDevices", Hotkeys[HK_AUTOMOUNT_DEVICES].vKeyCode); + ConfigWriteInt ("HotkeyModDismountAll", Hotkeys[HK_DISMOUNT_ALL].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeDismountAll", Hotkeys[HK_DISMOUNT_ALL].vKeyCode); + ConfigWriteInt ("HotkeyModWipeCache", Hotkeys[HK_WIPE_CACHE].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeWipeCache", Hotkeys[HK_WIPE_CACHE].vKeyCode); + ConfigWriteInt ("HotkeyModDismountAllWipe", Hotkeys[HK_DISMOUNT_ALL_AND_WIPE].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeDismountAllWipe", Hotkeys[HK_DISMOUNT_ALL_AND_WIPE].vKeyCode); + ConfigWriteInt ("HotkeyModForceDismountAllWipe", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeForceDismountAllWipe", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE].vKeyCode); + ConfigWriteInt ("HotkeyModForceDismountAllWipeExit", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeForceDismountAllWipeExit", Hotkeys[HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT].vKeyCode); + ConfigWriteInt ("HotkeyModMountFavoriteVolumes", Hotkeys[HK_MOUNT_FAVORITE_VOLUMES].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeMountFavoriteVolumes", Hotkeys[HK_MOUNT_FAVORITE_VOLUMES].vKeyCode); + ConfigWriteInt ("HotkeyModShowHideMainWindow", Hotkeys[HK_SHOW_HIDE_MAIN_WINDOW].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeShowHideMainWindow", Hotkeys[HK_SHOW_HIDE_MAIN_WINDOW].vKeyCode); + ConfigWriteInt ("HotkeyModCloseSecurityTokenSessions", Hotkeys[HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyModifiers); + ConfigWriteInt ("HotkeyCodeCloseSecurityTokenSessions", Hotkeys[HK_CLOSE_SECURITY_TOKEN_SESSIONS].vKeyCode); + ConfigWriteInt ("PlaySoundOnHotkeyMountDismount", bPlaySoundOnHotkeyMountDismount); + ConfigWriteInt ("DisplayMsgBoxOnHotkeyDismount", bDisplayMsgBoxOnHotkeyDismount); + + // Language + if (GetPreferredLangId () != NULL) + ConfigWriteString ("Language", GetPreferredLangId ()); + + // PKCS#11 Library Path + ConfigWriteString ("SecurityTokenLibrary", SecurityTokenLibraryPath[0] ? SecurityTokenLibraryPath : ""); + + ConfigWriteEnd (); + + // History + DumpCombo (GetDlgItem (hwndDlg, IDC_VOLUME), IsButtonChecked (GetDlgItem (hwndDlg, IDC_NO_HISTORY))); + + NormalCursor (); +} + +// Returns TRUE if system encryption or decryption had been or is in progress and has not been completed +static BOOL SysEncryptionOrDecryptionRequired (void) +{ + /* If you update this function, revise SysEncryptionOrDecryptionRequired() in Tcformat.c as well. */ + + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + return (SystemEncryptionStatus == SYSENC_STATUS_ENCRYPTING + || SystemEncryptionStatus == SYSENC_STATUS_DECRYPTING + || + ( + BootEncStatus.DriveMounted + && + ( + BootEncStatus.ConfiguredEncryptedAreaStart != BootEncStatus.EncryptedAreaStart + || BootEncStatus.ConfiguredEncryptedAreaEnd != BootEncStatus.EncryptedAreaEnd + ) + ) + ); +} + +// Returns TRUE if the system partition/drive is completely encrypted +static BOOL SysDriveOrPartitionFullyEncrypted (BOOL bSilent) +{ + /* If you update this function, revise SysDriveOrPartitionFullyEncrypted() in Tcformat.c as well. */ + + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + if (!bSilent) + e.Show (MainDlg); + } + + return (!BootEncStatus.SetupInProgress + && BootEncStatus.ConfiguredEncryptedAreaEnd != 0 + && BootEncStatus.ConfiguredEncryptedAreaEnd != -1 + && BootEncStatus.ConfiguredEncryptedAreaStart == BootEncStatus.EncryptedAreaStart + && BootEncStatus.ConfiguredEncryptedAreaEnd == BootEncStatus.EncryptedAreaEnd); +} + +// Returns TRUE if the system partition/drive is being filtered by the TrueCrypt driver and the key data +// was successfully decrypted (the device is fully ready to be encrypted or decrypted). Note that this +// function does not examine whether the system device is encrypted or not (or to what extent). +static BOOL SysEncDeviceActive (BOOL bSilent) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + if (!bSilent) + e.Show (MainDlg); + + return FALSE; + } + + return (BootEncStatus.DriveMounted); +} + +// Returns TRUE if the entire system drive (as opposed to the system partition only) is (or is to be) encrypted +BOOL WholeSysDriveEncryption (BOOL bSilent) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + + return (BootEncStatus.ConfiguredEncryptedAreaStart == TC_BOOT_LOADER_AREA_SIZE + && BootEncStatus.ConfiguredEncryptedAreaEnd >= BootEncStatus.BootDriveLength.QuadPart - 1); + } + catch (Exception &e) + { + if (!bSilent) + e.Show (MainDlg); + + return FALSE; + } +} + +// Returns the size of the system drive/partition (if encrypted) in bytes +unsigned __int64 GetSysEncDeviceSize (BOOL bSilent) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + if (!bSilent) + e.Show (MainDlg); + } + + return (BootEncStatus.ConfiguredEncryptedAreaEnd - BootEncStatus.ConfiguredEncryptedAreaStart + 1); +} + +// Returns the current size of the encrypted area of the system drive/partition in bytes +unsigned __int64 GetSysEncDeviceEncryptedPartSize (BOOL bSilent) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + if (!bSilent) + e.Show (MainDlg); + } + + return (BootEncStatus.EncryptedAreaEnd - BootEncStatus.EncryptedAreaStart + 1); +} + + +static void PopulateSysEncContextMenu (HMENU popup, BOOL bToolsOnly) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + if (!bToolsOnly && !IsHiddenOSRunning()) + { + if (SysEncryptionOrDecryptionRequired ()) + { + if (!BootEncStatus.SetupInProgress) + AppendMenuW (popup, MF_STRING, IDM_SYSENC_RESUME, GetString ("IDM_SYSENC_RESUME")); + + if (SystemEncryptionStatus != SYSENC_STATUS_DECRYPTING) + AppendMenuW (popup, MF_STRING, IDM_PERMANENTLY_DECRYPT_SYS, GetString ("PERMANENTLY_DECRYPT")); + + AppendMenuW (popup, MF_STRING, IDM_ENCRYPT_SYSTEM_DEVICE, GetString ("ENCRYPT")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + } + } + + AppendMenuW (popup, MF_STRING, IDM_CHANGE_SYS_PASSWORD, GetString ("IDM_CHANGE_SYS_PASSWORD")); + AppendMenuW (popup, MF_STRING, IDM_CHANGE_SYS_HEADER_KEY_DERIV_ALGO, GetString ("IDM_CHANGE_SYS_HEADER_KEY_DERIV_ALGO")); + + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDM_SYS_ENC_SETTINGS, GetString ("IDM_SYS_ENC_SETTINGS")); + + if (!IsHiddenOSRunning()) + { + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDM_CREATE_RESCUE_DISK, GetString ("IDM_CREATE_RESCUE_DISK")); + AppendMenuW (popup, MF_STRING, IDM_VERIFY_RESCUE_DISK, GetString ("IDM_VERIFY_RESCUE_DISK")); + } + + if (!bToolsOnly) + { + if (SysDriveOrPartitionFullyEncrypted (FALSE) && !IsHiddenOSRunning()) + { + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDM_PERMANENTLY_DECRYPT_SYS, GetString ("PERMANENTLY_DECRYPT")); + } + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDM_VOLUME_PROPERTIES, GetString ("IDPM_PROPERTIES")); + } +} + + +// WARNING: This function may take a long time to complete. To prevent data corruption, it MUST be called before +// mounting a partition (as a regular volume) that is within key scope of system encryption. +// Returns TRUE if the partition can be mounted as a partition within key scope of inactive system encryption. +// If devicePath is empty, the currently selected partition in the GUI is checked. +BOOL CheckSysEncMountWithoutPBA (const char *devicePath, BOOL quiet) +{ + BOOL tmpbDevice; + char szDevicePath [TC_MAX_PATH+1]; + char szDiskFile [TC_MAX_PATH+1]; + + if (strlen (devicePath) < 2) + { + GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, sizeof (szDevicePath)); + CreateFullVolumePath (szDiskFile, szDevicePath, &tmpbDevice); + + if (!tmpbDevice) + { + if (!quiet) + Warning ("NO_SYSENC_PARTITION_SELECTED"); + + return FALSE; + } + + if (LOWORD (GetSelectedLong (GetDlgItem (MainDlg, IDC_DRIVELIST))) != TC_MLIST_ITEM_FREE) + { + if (!quiet) + Warning ("SELECT_FREE_DRIVE"); + + return FALSE; + } + } + else + strncpy (szDevicePath, devicePath, sizeof (szDevicePath)); + + char *partionPortion = strrchr (szDevicePath, '\\'); + + if (!partionPortion + || !_stricmp (partionPortion, "\\Partition0")) + { + // Only partitions are supported (not whole drives) + if (!quiet) + Warning ("NO_SYSENC_PARTITION_SELECTED"); + + return FALSE; + } + + try + { + BootEncStatus = BootEncObj->GetStatus(); + + if (BootEncStatus.DriveMounted) + { + int retCode = 0; + int driveNo; + char parentDrivePath [TC_MAX_PATH+1]; + + if (sscanf (szDevicePath, "\\Device\\Harddisk%d\\Partition", &driveNo) != 1) + { + if (!quiet) + Error ("INVALID_PATH"); + + return FALSE; + } + + _snprintf (parentDrivePath, + sizeof (parentDrivePath), + "\\Device\\Harddisk%d\\Partition0", + driveNo); + + WaitCursor (); + + // This is critical (re-mounting a mounted system volume as a normal volume could cause data corruption) + // so we force the slower but reliable method + retCode = IsSystemDevicePath (parentDrivePath, MainDlg, TRUE); + + NormalCursor(); + + if (retCode != 2) + return TRUE; + else + { + // The partition is located on active system drive + + if (!quiet) + Warning ("MOUNT_WITHOUT_PBA_VOL_ON_ACTIVE_SYSENC_DRIVE"); + + return FALSE; + } + } + else + return TRUE; + } + catch (Exception &e) + { + NormalCursor(); + e.Show (MainDlg); + } + + return FALSE; +} + + +// Returns TRUE if the host drive of the specified partition contains a portion of the TrueCrypt Boot Loader +// and if the drive is not within key scope of active system encryption (e.g. the system drive of the running OS). +// If bPrebootPasswordDlgMode is TRUE, this function returns FALSE (because the check would be redundant). +BOOL TCBootLoaderOnInactiveSysEncDrive (void) +{ + try + { + int driveNo; + char szDevicePath [TC_MAX_PATH+1]; + char parentDrivePath [TC_MAX_PATH+1]; + + if (bPrebootPasswordDlgMode) + return FALSE; + + GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, sizeof (szDevicePath)); + + if (sscanf (szDevicePath, "\\Device\\Harddisk%d\\Partition", &driveNo) != 1) + return FALSE; + + _snprintf (parentDrivePath, + sizeof (parentDrivePath), + "\\Device\\Harddisk%d\\Partition0", + driveNo); + + BootEncStatus = BootEncObj->GetStatus(); + + if (BootEncStatus.DriveMounted + && IsSystemDevicePath (parentDrivePath, MainDlg, FALSE) == 2) + { + // The partition is within key scope of active system encryption + return FALSE; + } + + return ((BOOL) BootEncObj->IsBootLoaderOnDrive (parentDrivePath)); + } + catch (...) + { + return FALSE; + } + +} + + +BOOL SelectItem (HWND hTree, char nLetter) +{ + int i; + LVITEM item; + + for (i = 0; i < ListView_GetItemCount(hTree); i++) + { + memset(&item, 0, sizeof(LVITEM)); + item.mask = LVIF_PARAM; + item.iItem = i; + + if (ListView_GetItem (hTree, &item) == FALSE) + return FALSE; + else + { + if (HIWORD (item.lParam) == nLetter) + { + memset(&item, 0, sizeof(LVITEM)); + item.state = LVIS_FOCUSED|LVIS_SELECTED; + item.stateMask = LVIS_FOCUSED|LVIS_SELECTED; + item.mask = LVIF_STATE; + item.iItem = i; + SendMessage(hTree, LVM_SETITEMSTATE, i, (LPARAM) &item); + return TRUE; + } + } + } + + return TRUE; +} + + +static void LaunchVolCreationWizard (HWND hwndDlg, const char *arg) +{ + char t[TC_MAX_PATH] = {'"',0}; + char *tmp; + + GetModuleFileName (NULL, t+1, sizeof(t)-1); + + tmp = strrchr (t, '\\'); + if (tmp) + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory (&si, sizeof (si)); + + strcpy (++tmp, "TrueCrypt Format.exe\""); + + if (!FileExists(t)) + Error ("VOL_CREATION_WIZARD_NOT_FOUND"); // Display a user-friendly error message and advise what to do + + if (strlen (arg) > 0) + { + strcat (t, " "); + strcat (t, arg); + } + + if (!CreateProcess (NULL, (LPSTR) t, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) + { + handleWin32Error (hwndDlg); + } + else + { + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + } + } +} + + +// Fills drive list +// drive>0 = update only the corresponding drive subitems +void LoadDriveLetters (HWND hTree, int drive) +{ + char *szDriveLetters[]= + {"A:", "B:", "C:", "D:", + "E:", "F:", "G:", "H:", "I:", "J:", "K:", + "L:", "M:", "N:", "O:", "P:", "Q:", "R:", + "S:", "T:", "U:", "V:", "W:", "X:", "Y:", + "Z:"}; + + DWORD dwResult; + BOOL bResult; + DWORD dwUsedDrives; + MOUNT_LIST_STRUCT driver; + VOLUME_PROPERTIES_STRUCT propSysEnc; + char sysDriveLetter = 0; + + BOOL bSysEnc = FALSE; + BOOL bWholeSysDriveEncryption = FALSE; + + LVITEM listItem; + int item = 0; + char i; + + try + { + BootEncStatus = BootEncObj->GetStatus(); + if (bSysEnc = BootEncStatus.DriveMounted) + { + BootEncObj->GetVolumeProperties (&propSysEnc); + } + } + catch (...) + { + bSysEnc = FALSE; + } + + ZeroMemory (&driver, sizeof (driver)); + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &driver, + sizeof (driver), &driver, sizeof (driver), &dwResult, + NULL); + memcpy (&LastKnownMountList, &driver, sizeof (driver)); + + if (bResult == FALSE) + { + handleWin32Error (hTree); + driver.ulMountedDrives = 0; + } + + LastKnownLogicalDrives = dwUsedDrives = GetLogicalDrives (); + if (dwUsedDrives == 0) + Warning ("DRIVELETTERS"); + + if(drive == 0) + ListView_DeleteAllItems(hTree); + + if (bSysEnc) + { + bWholeSysDriveEncryption = WholeSysDriveEncryption (TRUE); + + sysDriveLetter = GetSystemDriveLetter (); + } + + /* System drive */ + + if (bWholeSysDriveEncryption) + { + i = ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER; + int curDrive = 0; + + if (drive > 0) + { + LVITEM tmp; + memset(&tmp, 0, sizeof(LVITEM)); + tmp.mask = LVIF_PARAM; + tmp.iItem = item; + if (ListView_GetItem (hTree, &tmp)) + curDrive = HIWORD(tmp.lParam); + } + + { + char szTmp[1024]; + wchar_t szTmpW[1024]; + + memset(&listItem, 0, sizeof(listItem)); + + listItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; + listItem.iImage = 2; + listItem.iItem = item++; + + listItem.pszText = szTmp; + strcpy (szTmp, " "); + + listItem.lParam = MAKELONG (TC_MLIST_ITEM_SYS_DRIVE, ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER); + + if(drive == 0) + ListView_InsertItem (hTree, &listItem); + else + ListView_SetItem (hTree, &listItem); + + listItem.mask=LVIF_TEXT; + + // Fully encrypted + if (SysDriveOrPartitionFullyEncrypted (TRUE)) + { + wcscpy (szTmpW, GetString ("SYSTEM_DRIVE")); + } + else + { + // Partially encrypted + + if (BootEncStatus.SetupInProgress) + { + // Currently encrypting/decrypting + + if (BootEncStatus.SetupMode != SetupDecryption) + { + _snwprintf (szTmpW, + sizeof szTmpW/2, + GetString ("SYSTEM_DRIVE_ENCRYPTING"), + (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); + } + else + { + _snwprintf (szTmpW, + sizeof szTmpW/2, + GetString ("SYSTEM_DRIVE_DECRYPTING"), + 100.0 - ((double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0)); + } + } + else + { + _snwprintf (szTmpW, + sizeof szTmpW/2, + GetString ("SYSTEM_DRIVE_PARTIALLY_ENCRYPTED"), + (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); + } + } + + ListSubItemSetW (hTree, listItem.iItem, 1, szTmpW); + + GetSizeString (GetSysEncDeviceSize(TRUE), szTmpW); + ListSubItemSetW (hTree, listItem.iItem, 2, szTmpW); + + EAGetName (szTmp, propSysEnc.ea); + listItem.iSubItem = 3; + ListView_SetItem (hTree, &listItem); + + ListSubItemSetW (hTree, listItem.iItem, 4, GetString (IsHiddenOSRunning() ? "HIDDEN" : "SYSTEM_VOLUME_TYPE_ADJECTIVE")); + + VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; + } + } + + /* Drive letters */ + + for (i = 2; i < 26; i++) + { + int curDrive = 0; + + BOOL bSysEncPartition = (bSysEnc && !bWholeSysDriveEncryption && sysDriveLetter == *((char *) szDriveLetters[i])); + + if (drive > 0) + { + LVITEM tmp; + memset(&tmp, 0, sizeof(LVITEM)); + tmp.mask = LVIF_PARAM; + tmp.iItem = item; + if (ListView_GetItem (hTree, &tmp)) + curDrive = HIWORD(tmp.lParam); + } + + if (driver.ulMountedDrives & (1 << i) + || bSysEncPartition) + { + char szTmp[1024]; + wchar_t szTmpW[1024]; + wchar_t *ws; + + memset(&listItem, 0, sizeof(listItem)); + + listItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; + listItem.iImage = bSysEncPartition ? 2 : 1; + listItem.iItem = item++; + + if (drive > 0 && drive != curDrive) + continue; + + listItem.lParam = MAKELONG ( + bSysEncPartition ? TC_MLIST_ITEM_SYS_PARTITION : TC_MLIST_ITEM_NONSYS_VOL, + i + 'A'); + + listItem.pszText = szDriveLetters[i]; + + if (drive == 0) + ListView_InsertItem (hTree, &listItem); + else + ListView_SetItem (hTree, &listItem); + + listItem.mask=LVIF_TEXT; + listItem.pszText = szTmp; + + if (bSysEncPartition) + { + // Fully encrypted + if (SysDriveOrPartitionFullyEncrypted (TRUE)) + { + wcscpy (szTmpW, GetString (IsHiddenOSRunning() ? "HIDDEN_SYSTEM_PARTITION" : "SYSTEM_PARTITION")); + } + else + { + // Partially encrypted + + if (BootEncStatus.SetupInProgress) + { + // Currently encrypting/decrypting + + if (BootEncStatus.SetupMode != SetupDecryption) + { + _snwprintf (szTmpW, + sizeof szTmpW/2, + GetString ("SYSTEM_PARTITION_ENCRYPTING"), + (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); + } + else + { + _snwprintf (szTmpW, + sizeof szTmpW/2, + GetString ("SYSTEM_PARTITION_DECRYPTING"), + 100.0 - ((double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0)); + } + } + else + { + _snwprintf (szTmpW, + sizeof szTmpW/2, + GetString ("SYSTEM_PARTITION_PARTIALLY_ENCRYPTED"), + (double) GetSysEncDeviceEncryptedPartSize (TRUE) / (double) GetSysEncDeviceSize (TRUE) * 100.0); + } + } + + ListSubItemSetW (hTree, listItem.iItem, 1, szTmpW); + } + else + { + ToSBCS ((LPWSTR) driver.wszVolume[i]); + + if (memcmp (driver.wszVolume[i], "\\Device", 7) == 0) + sprintf (szTmp, "%s", ((char *) driver.wszVolume[i])); + else + sprintf (szTmp, "%s", ((char *) driver.wszVolume[i]) + 4); + + strcpy_s (szTmp, sizeof (szTmp), FitPathInGfxWidth (hTree, hUserFont, ListView_GetColumnWidth (hTree, 1) - GetTextGfxWidth (hTree, L"___", hUserFont), szTmp).c_str()); + listItem.iSubItem = 1; + ListView_SetItem (hTree, &listItem); + } + + GetSizeString (bSysEncPartition ? GetSysEncDeviceSize(TRUE) : driver.diskLength[i], szTmpW); + ListSubItemSetW (hTree, listItem.iItem, 2, szTmpW); + + EAGetName (szTmp, bSysEncPartition ? propSysEnc.ea : driver.ea[i]); + listItem.iSubItem = 3; + ListView_SetItem (hTree, &listItem); + + if (bSysEncPartition) + { + ws = GetString (IsHiddenOSRunning() ? "HIDDEN" : "SYSTEM_VOLUME_TYPE_ADJECTIVE"); + VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; + ListSubItemSetW (hTree, listItem.iItem, 4, ws); + } + else + { + switch (driver.volumeType[i]) + { + case PROP_VOL_TYPE_NORMAL: + ws = GetString ("NORMAL"); + break; + case PROP_VOL_TYPE_HIDDEN: + ws = GetString ("HIDDEN"); + break; + case PROP_VOL_TYPE_OUTER: + ws = GetString ("OUTER"); // Normal/outer volume (hidden volume protected) + break; + case PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED: + ws = GetString ("OUTER_VOL_WRITE_PREVENTED"); // Normal/outer volume (hidden volume protected AND write denied) + break; + default: + ws = L"?"; + } + ListSubItemSetW (hTree, listItem.iItem, 4, ws); + + if (driver.volumeType[i] == PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED) // Normal/outer volume (hidden volume protected AND write denied) + { + if (!VolumeNotificationsList.bHidVolDamagePrevReported[i]) + { + wchar_t szTmp[4096]; + + VolumeNotificationsList.bHidVolDamagePrevReported[i] = TRUE; + swprintf (szTmp, GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), i+'A'); + SetForegroundWindow (GetParent(hTree)); + MessageBoxW (GetParent(hTree), szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + } + } + else + { + VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; + } + } + } + else + { + VolumeNotificationsList.bHidVolDamagePrevReported[i] = FALSE; + + if (!(dwUsedDrives & 1 << i)) + { + if(drive > 0 && drive != HIWORD (GetSelectedLong (hTree))) + { + item++; + continue; + } + + memset(&listItem,0,sizeof(listItem)); + + listItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; + listItem.iImage = 0; + listItem.iItem = item++; + listItem.pszText = szDriveLetters[i]; + listItem.lParam = MAKELONG (TC_MLIST_ITEM_FREE, i + 'A'); + + if(drive == 0) + ListView_InsertItem (hTree, &listItem); + else + ListView_SetItem (hTree, &listItem); + + listItem.mask=LVIF_TEXT; + listItem.pszText = ""; + listItem.iSubItem = 1; + ListView_SetItem (hTree, &listItem); + listItem.iSubItem = 2; + ListView_SetItem (hTree, &listItem); + listItem.iSubItem = 3; + ListView_SetItem (hTree, &listItem); + listItem.iSubItem = 4; + ListView_SetItem (hTree, &listItem); + + } + } + } +} + + +static void PasswordChangeEnable (HWND hwndDlg, int button, int passwordId, BOOL keyFilesEnabled, + int newPasswordId, int newVerifyId, BOOL newKeyFilesEnabled) +{ + char password[MAX_PASSWORD + 1]; + char newPassword[MAX_PASSWORD + 1]; + char newVerify[MAX_PASSWORD + 1]; + BOOL bEnable = TRUE; + + GetWindowText (GetDlgItem (hwndDlg, passwordId), password, sizeof (password)); + + if (pwdChangeDlgMode == PCDM_CHANGE_PKCS5_PRF) + newKeyFilesEnabled = keyFilesEnabled; + + switch (pwdChangeDlgMode) + { + case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: + case PCDM_ADD_REMOVE_VOL_KEYFILES: + case PCDM_CHANGE_PKCS5_PRF: + memcpy (newPassword, password, sizeof (newPassword)); + memcpy (newVerify, password, sizeof (newVerify)); + break; + + default: + GetWindowText (GetDlgItem (hwndDlg, newPasswordId), newPassword, sizeof (newPassword)); + GetWindowText (GetDlgItem (hwndDlg, newVerifyId), newVerify, sizeof (newVerify)); + } + + if (!keyFilesEnabled && strlen (password) < MIN_PASSWORD) + bEnable = FALSE; + else if (strcmp (newPassword, newVerify) != 0) + bEnable = FALSE; + else if (!newKeyFilesEnabled && strlen (newPassword) < MIN_PASSWORD) + bEnable = FALSE; + + burn (password, sizeof (password)); + burn (newPassword, sizeof (newPassword)); + burn (newVerify, sizeof (newVerify)); + + EnableWindow (GetDlgItem (hwndDlg, button), bEnable); +} + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK PasswordChangeDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static KeyFilesDlgParam newKeyFilesParam; + + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + LPARAM nIndex; + HWND hComboBox = GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID); + int i; + + ZeroMemory (&newKeyFilesParam, sizeof (newKeyFilesParam)); + + SetWindowTextW (hwndDlg, GetString ("IDD_PASSWORDCHANGE_DLG")); + LocalizeDialog (hwndDlg, "IDD_PASSWORDCHANGE_DLG"); + + SendMessage (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), EM_LIMITTEXT, MAX_PASSWORD, 0); + EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); + + SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, KeyFilesEnable); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEW_KEYFILES), TRUE); + + SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); + + nIndex = SendMessageW (hComboBox, CB_ADDSTRING, 0, (LPARAM) GetString ("UNCHANGED")); + SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) 0); + + for (i = FIRST_PRF_ID; i <= LAST_PRF_ID; i++) + { + if (!HashIsDeprecated (i)) + { + nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) get_pkcs5_prf_name(i)); + SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) i); + } + } + + SendMessage (hComboBox, CB_SETCURSEL, 0, 0); + + switch (pwdChangeDlgMode) + { + case PCDM_CHANGE_PKCS5_PRF: + SetWindowTextW (hwndDlg, GetString ("IDD_PCDM_CHANGE_PKCS5_PRF")); + LocalizeDialog (hwndDlg, "IDD_PCDM_CHANGE_PKCS5_PRF"); + EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_VERIFY), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_NEW_KEYFILES), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEW_KEYFILES), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_NEW_PASSWORD), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_CONFIRM_PASSWORD), FALSE); + break; + + case PCDM_ADD_REMOVE_VOL_KEYFILES: + SetWindowTextW (hwndDlg, GetString ("IDD_PCDM_ADD_REMOVE_VOL_KEYFILES")); + LocalizeDialog (hwndDlg, "IDD_PCDM_ADD_REMOVE_VOL_KEYFILES"); + newKeyFilesParam.EnableKeyFiles = TRUE; + EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_VERIFY), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_NEW_PASSWORD), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_CONFIRM_PASSWORD), FALSE); + break; + + case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: + newKeyFilesParam.EnableKeyFiles = FALSE; + SetWindowTextW (hwndDlg, GetString ("IDD_PCDM_REMOVE_ALL_KEYFILES_FROM_VOL")); + LocalizeDialog (hwndDlg, "IDD_PCDM_REMOVE_ALL_KEYFILES_FROM_VOL"); + KeyFilesEnable = TRUE; + SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_KEYFILES), TRUE); + EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_VERIFY), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_NEW_KEYFILES), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_NEW_KEYFILES), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_NEW_PASSWORD), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_CONFIRM_PASSWORD), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDT_PKCS5_PRF), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), FALSE); + break; + + case PCDM_CHANGE_PASSWORD: + default: + // NOP + break; + }; + + if (bSysEncPwdChangeDlgMode) + { + ToBootPwdField (hwndDlg, IDC_PASSWORD); + ToBootPwdField (hwndDlg, IDC_VERIFY); + ToBootPwdField (hwndDlg, IDC_OLD_PASSWORD); + + if ((DWORD) GetKeyboardLayout (NULL) != 0x00000409 && (DWORD) GetKeyboardLayout (NULL) != 0x04090409) + { + DWORD keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); + EndDialog (hwndDlg, IDCANCEL); + return 0; + } + + bKeyboardLayoutChanged = TRUE; + } + + ShowWindow(GetDlgItem(hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SHOW_PASSWORD_CHPWD_ORI), SW_HIDE); + + if (SetTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD, TIMER_INTERVAL_KEYB_LAYOUT_GUARD, NULL) == 0) + { + Error ("CANNOT_SET_TIMER"); + EndDialog (hwndDlg, IDCANCEL); + return 0; + } + + newKeyFilesParam.EnableKeyFiles = FALSE; + KeyFilesEnable = FALSE; + SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_KEYFILES), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_NEW_KEYFILES), FALSE); + } + + CheckCapsLock (hwndDlg, FALSE); + + return 0; + } + + case WM_TIMER: + switch (wParam) + { + case TIMER_ID_KEYB_LAYOUT_GUARD: + if (bSysEncPwdChangeDlgMode) + { + DWORD keybLayout = (DWORD) GetKeyboardLayout (NULL); + + /* Watch the keyboard layout */ + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + // Keyboard layout is not standard US + + // Attempt to wipe passwords stored in the input field buffers + char tmp[MAX_PASSWORD+1]; + memset (tmp, 'X', MAX_PASSWORD); + tmp [MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), tmp); + + SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), ""); + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), ""); + SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), ""); + + keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); + Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + bKeyboardLayoutChanged = TRUE; + + wchar_t szTmp [4096]; + wcscpy (szTmp, GetString ("KEYB_LAYOUT_CHANGE_PREVENTED")); + wcscat (szTmp, L"\n\n"); + wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); + MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + } + + + /* Watch the right Alt key (which is used to enter various characters on non-US keyboards) */ + + if (bKeyboardLayoutChanged && !bKeybLayoutAltKeyWarningShown) + { + if (GetAsyncKeyState (VK_RMENU) < 0) + { + bKeybLayoutAltKeyWarningShown = TRUE; + + wchar_t szTmp [4096]; + wcscpy (szTmp, GetString ("ALT_KEY_CHARS_NOT_FOR_SYS_ENCRYPTION")); + wcscat (szTmp, L"\n\n"); + wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); + MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); + } + } + } + return 1; + } + return 0; + + case WM_COMMAND: + if (lw == IDCANCEL) + { + // Attempt to wipe passwords stored in the input field buffers + char tmp[MAX_PASSWORD+1]; + memset (tmp, 'X', MAX_PASSWORD); + tmp[MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), tmp); + RestoreDefaultKeyFilesParam (); + + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + if (hw == EN_CHANGE) + { + PasswordChangeEnable (hwndDlg, IDOK, + IDC_OLD_PASSWORD, + KeyFilesEnable && FirstKeyFile != NULL, + IDC_PASSWORD, IDC_VERIFY, + newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); + + return 1; + } + + if (lw == IDC_KEYFILES) + { + if (bSysEncPwdChangeDlgMode) + { + Warning ("KEYFILES_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); + return 1; + } + + KeyFilesDlgParam param; + param.EnableKeyFiles = KeyFilesEnable; + param.FirstKeyFile = FirstKeyFile; + + if (IDOK == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, + (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m)) + { + KeyFilesEnable = param.EnableKeyFiles; + FirstKeyFile = param.FirstKeyFile; + + SetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES, KeyFilesEnable); + } + + PasswordChangeEnable (hwndDlg, IDOK, + IDC_OLD_PASSWORD, + KeyFilesEnable && FirstKeyFile != NULL, + IDC_PASSWORD, IDC_VERIFY, + newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); + + return 1; + } + + + if (lw == IDC_NEW_KEYFILES) + { + if (bSysEncPwdChangeDlgMode) + { + Warning ("KEYFILES_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); + return 1; + } + + if (IDOK == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, + (DLGPROC) KeyFilesDlgProc, (LPARAM) &newKeyFilesParam)) + { + SetCheckBox (hwndDlg, IDC_ENABLE_NEW_KEYFILES, newKeyFilesParam.EnableKeyFiles); + + VerifyPasswordAndUpdate (hwndDlg, GetDlgItem (hwndDlg, IDOK), GetDlgItem (hwndDlg, IDC_PASSWORD), + GetDlgItem (hwndDlg, IDC_VERIFY), NULL, NULL, + newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); + } + + PasswordChangeEnable (hwndDlg, IDOK, + IDC_OLD_PASSWORD, + KeyFilesEnable && FirstKeyFile != NULL, + IDC_PASSWORD, IDC_VERIFY, + newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); + + return 1; + } + + if (lw == IDC_ENABLE_KEYFILES) + { + KeyFilesEnable = GetCheckBox (hwndDlg, IDC_ENABLE_KEYFILES); + + PasswordChangeEnable (hwndDlg, IDOK, + IDC_OLD_PASSWORD, + KeyFilesEnable && FirstKeyFile != NULL, + IDC_PASSWORD, IDC_VERIFY, + newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); + + return 1; + } + + if (lw == IDC_ENABLE_NEW_KEYFILES) + { + newKeyFilesParam.EnableKeyFiles = GetCheckBox (hwndDlg, IDC_ENABLE_NEW_KEYFILES); + + PasswordChangeEnable (hwndDlg, IDOK, + IDC_OLD_PASSWORD, + KeyFilesEnable && FirstKeyFile != NULL, + IDC_PASSWORD, IDC_VERIFY, + newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL); + + return 1; + } + + if (hw == CBN_SELCHANGE) + { + switch (lw) + { + case IDC_PKCS5_PRF_ID: + if (bSysEncPwdChangeDlgMode) + { + int new_hash_algo_id = SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETITEMDATA, + SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETCURSEL, 0, 0), 0); + + if (new_hash_algo_id != 0 && new_hash_algo_id != DEFAULT_HASH_ALGORITHM_BOOT) + { + int new_hash_algo_id = DEFAULT_HASH_ALGORITHM_BOOT; + Info ("ALGO_NOT_SUPPORTED_FOR_SYS_ENCRYPTION"); + SelectAlgo (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), &new_hash_algo_id); + } + } + break; + } + return 1; + + } + + if (lw == IDC_SHOW_PASSWORD_CHPWD_ORI) + { + SendMessage (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_ORI) ? 0 : '*', + 0); + InvalidateRect (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), NULL, TRUE); + return 1; + } + + if (lw == IDC_SHOW_PASSWORD_CHPWD_NEW) + { + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW) ? 0 : '*', + 0); + SendMessage (GetDlgItem (hwndDlg, IDC_VERIFY), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_CHPWD_NEW) ? 0 : '*', + 0); + InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); + InvalidateRect (GetDlgItem (hwndDlg, IDC_VERIFY), NULL, TRUE); + return 1; + } + + if (lw == IDOK) + { + HWND hParent = GetParent (hwndDlg); + Password oldPassword; + Password newPassword; + int nStatus; + int pkcs5 = SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETITEMDATA, + SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETCURSEL, 0, 0), 0); + + if (!CheckPasswordCharEncoding (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL)) + { + Error ("UNSUPPORTED_CHARS_IN_PWD"); + return 1; + } + + if (pwdChangeDlgMode == PCDM_CHANGE_PKCS5_PRF) + { + newKeyFilesParam.EnableKeyFiles = KeyFilesEnable; + } + else if (!(newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL) + && pwdChangeDlgMode == PCDM_CHANGE_PASSWORD) + { + if (!CheckPasswordLength (hwndDlg, GetDlgItem (hwndDlg, IDC_PASSWORD))) + return 1; + } + + GetWindowText (GetDlgItem (hParent, IDC_VOLUME), szFileName, sizeof (szFileName)); + + GetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), (LPSTR) oldPassword.Text, sizeof (oldPassword.Text)); + oldPassword.Length = strlen ((char *) oldPassword.Text); + + switch (pwdChangeDlgMode) + { + case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: + case PCDM_ADD_REMOVE_VOL_KEYFILES: + case PCDM_CHANGE_PKCS5_PRF: + memcpy (newPassword.Text, oldPassword.Text, sizeof (newPassword.Text)); + newPassword.Length = strlen ((char *) oldPassword.Text); + break; + + default: + GetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), (LPSTR) newPassword.Text, sizeof (newPassword.Text)); + newPassword.Length = strlen ((char *) newPassword.Text); + } + + WaitCursor (); + + if (KeyFilesEnable) + KeyFilesApply (&oldPassword, FirstKeyFile); + + if (newKeyFilesParam.EnableKeyFiles) + KeyFilesApply (&newPassword, + pwdChangeDlgMode==PCDM_CHANGE_PKCS5_PRF ? FirstKeyFile : newKeyFilesParam.FirstKeyFile); + + if (bSysEncPwdChangeDlgMode) + { + // System + + pkcs5 = 0; // PKCS-5 PRF unchanged (currently system encryption supports only RIPEMD-160) + + try + { + nStatus = BootEncObj->ChangePassword (&oldPassword, &newPassword, pkcs5); + } + catch (Exception &e) + { + e.Show (MainDlg); + nStatus = ERR_OS_ERROR; + } + } + else + { + // Non-system + + nStatus = ChangePwd (szFileName, &oldPassword, &newPassword, pkcs5, hwndDlg); + + if (nStatus == ERR_OS_ERROR + && GetLastError () == ERROR_ACCESS_DENIED + && IsUacSupported () + && IsVolumeDeviceHosted (szFileName)) + { + nStatus = UacChangePwd (szFileName, &oldPassword, &newPassword, pkcs5, hwndDlg); + } + } + + burn (&oldPassword, sizeof (oldPassword)); + burn (&newPassword, sizeof (newPassword)); + + NormalCursor (); + + if (nStatus == 0) + { + // Attempt to wipe passwords stored in the input field buffers + char tmp[MAX_PASSWORD+1]; + memset (tmp, 'X', MAX_PASSWORD); + tmp[MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_OLD_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_VERIFY), tmp); + + KeyFileRemoveAll (&newKeyFilesParam.FirstKeyFile); + RestoreDefaultKeyFilesParam (); + + if (bSysEncPwdChangeDlgMode) + { + KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); + } + + EndDialog (hwndDlg, IDOK); + } + return 1; + } + return 0; + } + + return 0; +} + +static char PasswordDlgVolume[MAX_PATH]; +static BOOL PasswordDialogDisableMountOptions; +static char *PasswordDialogTitleStringId; + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK PasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + static Password *szXPwd; + + switch (msg) + { + case WM_INITDIALOG: + { + szXPwd = (Password *) lParam; + LocalizeDialog (hwndDlg, "IDD_PASSWORD_DLG"); + DragAcceptFiles (hwndDlg, TRUE); + + if (PasswordDialogTitleStringId) + { + SetWindowTextW (hwndDlg, GetString (PasswordDialogTitleStringId)); + } + else if (strlen (PasswordDlgVolume) > 0) + { + wchar_t s[1024]; + RECT rect; + GetWindowRect (hwndDlg, &rect); + + wsprintfW (s, GetString ("ENTER_PASSWORD_FOR"), "___"); + wsprintfW (s, GetString ("ENTER_PASSWORD_FOR"), FitPathInGfxWidth (hwndDlg, WindowTitleBarFont, rect.right - rect.left - GetTextGfxWidth (hwndDlg, s, WindowTitleBarFont), PasswordDlgVolume).c_str()); + + SetWindowTextW (hwndDlg, s); + } + + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); + SendMessage (GetDlgItem (hwndDlg, IDC_CACHE), BM_SETCHECK, bCacheInDriver ? BST_CHECKED:BST_UNCHECKED, 0); + + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); + + mountOptions.PartitionInInactiveSysEncScope = bPrebootPasswordDlgMode; + + if (bPrebootPasswordDlgMode) + { + SendMessage (hwndDlg, TC_APPMSG_PREBOOT_PASSWORD_MODE, 0, 0); + } + + if (PasswordDialogDisableMountOptions) + { + EnableWindow (GetDlgItem (hwndDlg, IDC_CACHE), FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_MOUNT_OPTIONS), FALSE); + } + + SetForegroundWindow (hwndDlg); + } + return 0; + + case TC_APPMSG_PREBOOT_PASSWORD_MODE: + { + ToBootPwdField (hwndDlg, IDC_PASSWORD); + + // Attempt to wipe the password stored in the input field buffer + char tmp[MAX_PASSWORD+1]; + memset (tmp, 'X', MAX_PASSWORD); + tmp [MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), ""); + + sprintf (OrigKeyboardLayout, "%08X", (DWORD) GetKeyboardLayout (NULL) & 0xFFFF); + + DWORD keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + if (SetTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD, TIMER_INTERVAL_KEYB_LAYOUT_GUARD, NULL) == 0) + { + Error ("CANNOT_SET_TIMER"); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + SetCheckBox (hwndDlg, IDC_SHOW_PASSWORD, FALSE); + EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD), FALSE); + + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_SETPASSWORDCHAR, '*', 0); + InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); + + bPrebootPasswordDlgMode = TRUE; + } + return 1; + + case WM_TIMER: + switch (wParam) + { + case TIMER_ID_KEYB_LAYOUT_GUARD: + if (bPrebootPasswordDlgMode) + { + DWORD keybLayout = (DWORD) GetKeyboardLayout (NULL); + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + // Keyboard layout is not standard US + + // Attempt to wipe the password stored in the input field buffer + char tmp[MAX_PASSWORD+1]; + memset (tmp, 'X', MAX_PASSWORD); + tmp [MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), ""); + + keybLayout = (DWORD) LoadKeyboardLayout ("00000409", KLF_ACTIVATE); + + if (keybLayout != 0x00000409 && keybLayout != 0x04090409) + { + KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); + Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION"); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + wchar_t szTmp [4096]; + wcscpy (szTmp, GetString ("KEYB_LAYOUT_CHANGE_PREVENTED")); + wcscat (szTmp, L"\n\n"); + wcscat (szTmp, GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION")); + MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + } + } + return 1; + } + return 0; + + case WM_COMMAND: + + if (lw == IDC_MOUNT_OPTIONS) + { + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg, + (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions); + + if (!bPrebootPasswordDlgMode && mountOptions.PartitionInInactiveSysEncScope) + SendMessage (hwndDlg, TC_APPMSG_PREBOOT_PASSWORD_MODE, 0, 0); + + return 1; + } + + if (lw == IDC_SHOW_PASSWORD) + { + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD) ? 0 : '*', + 0); + InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD), NULL, TRUE); + return 1; + } + + if (lw == IDC_KEY_FILES) + { + KeyFilesDlgParam param; + param.EnableKeyFiles = KeyFilesEnable; + param.FirstKeyFile = FirstKeyFile; + + if (IDOK == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, + (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m)) + { + KeyFilesEnable = param.EnableKeyFiles; + FirstKeyFile = param.FirstKeyFile; + + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); + } + + return 1; + } + + if (lw == IDC_KEYFILES_ENABLE) + { + KeyFilesEnable = GetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE); + + return 1; + } + + if (lw == IDCANCEL || lw == IDOK) + { + char tmp[MAX_PASSWORD+1]; + + if (lw == IDOK) + { + if (mountOptions.ProtectHiddenVolume && hidVolProtKeyFilesParam.EnableKeyFiles) + KeyFilesApply (&mountOptions.ProtectedHidVolPassword, hidVolProtKeyFilesParam.FirstKeyFile); + + GetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), (LPSTR) szXPwd->Text, MAX_PASSWORD + 1); + szXPwd->Length = strlen ((char *) szXPwd->Text); + + bCacheInDriver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_CACHE)); + } + + // Attempt to wipe password stored in the input field buffer + memset (tmp, 'X', MAX_PASSWORD); + tmp[MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp); + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), tmp); + + if (hidVolProtKeyFilesParam.FirstKeyFile != NULL) + { + KeyFileRemoveAll (&hidVolProtKeyFilesParam.FirstKeyFile); + hidVolProtKeyFilesParam.EnableKeyFiles = FALSE; + } + + if (bPrebootPasswordDlgMode) + { + KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD); + + // Restore the original keyboard layout + if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) + Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); + } + + EndDialog (hwndDlg, lw); + return 1; + } + return 0; + + case WM_CONTEXTMENU: + { + RECT buttonRect; + GetWindowRect (GetDlgItem (hwndDlg, IDC_KEY_FILES), &buttonRect); + + if (LOWORD (lParam) >= buttonRect.left && LOWORD (lParam) <= buttonRect.right + && HIWORD (lParam) >= buttonRect.top && HIWORD (lParam) <= buttonRect.bottom) + { + // The "Keyfiles" button has been right-clicked + + KeyFilesDlgParam param; + param.EnableKeyFiles = KeyFilesEnable; + param.FirstKeyFile = FirstKeyFile; + + POINT popupPos; + popupPos.x = buttonRect.left + 2; + popupPos.y = buttonRect.top + 2; + + if (KeyfilesPopupMenu (hwndDlg, popupPos, ¶m)) + { + KeyFilesEnable = param.EnableKeyFiles; + FirstKeyFile = param.FirstKeyFile; + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); + } + } + } + break; + + case WM_DROPFILES: + { + HDROP hdrop = (HDROP) wParam; + int i = 0, count = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0); + + while (count-- > 0) + { + KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); + DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName)); + FirstKeyFile = KeyFileAdd (FirstKeyFile, kf); + KeyFilesEnable = TRUE; + } + + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable); + DragFinish (hdrop); + } + return 1; + } + + return 0; +} + +static void PreferencesDlgEnableButtons (HWND hwndDlg) +{ + BOOL back = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE)); + BOOL idle = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE)); + BOOL installed = !IsNonInstallMode(); + + EnableWindow (GetDlgItem (hwndDlg, IDC_CLOSE_BKG_TASK_WHEN_NOVOL), back && installed); + EnableWindow (GetDlgItem (hwndDlg, IDT_LOGON), installed); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_LOGON_START), back && installed); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_DEVICES), installed); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_FAVORITES), installed); + EnableWindow (GetDlgItem (hwndDlg, IDT_AUTO_DISMOUNT), back); + EnableWindow (GetDlgItem (hwndDlg, IDT_AUTO_DISMOUNT_ON), back); + EnableWindow (GetDlgItem (hwndDlg, IDT_MINUTES), back); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_LOGOFF), back); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING), back); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER), back); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE), back); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE_TIME), back && idle); + EnableWindow (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT), back); +} + +BOOL CALLBACK PreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static BOOL PreferencesDialogActive = FALSE; + static HWND ActivePreferencesDialogWindow; + + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + if (PreferencesDialogActive) + { + ShowWindow (ActivePreferencesDialogWindow, SW_SHOW); + SetForegroundWindow (ActivePreferencesDialogWindow); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + ActivePreferencesDialogWindow = hwndDlg; + PreferencesDialogActive = TRUE; + + LocalizeDialog (hwndDlg, "IDD_PREFERENCES_DLG"); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_OPEN_EXPLORER), BM_SETCHECK, + bExplore ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_CLOSE_DISMOUNTED_WINDOWS), BM_SETCHECK, + bCloseDismountedWindows ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PRESERVE_TIMESTAMPS), BM_SETCHECK, + defaultMountOptions.PreserveTimestamp ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_EXIT), BM_SETCHECK, + bWipeCacheOnExit ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_AUTODISMOUNT), BM_SETCHECK, + bWipeCacheOnAutoDismount ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_CACHE_PASSWORDS), BM_SETCHECK, + bCacheInDriver ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_READONLY), BM_SETCHECK, + defaultMountOptions.ReadOnly ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_REMOVABLE), BM_SETCHECK, + defaultMountOptions.Removable ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_LOGON_START), BM_SETCHECK, + bStartOnLogon ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_DEVICES), BM_SETCHECK, + bMountDevicesOnLogon ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_FAVORITES), BM_SETCHECK, + bMountFavoritesOnLogon ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE), BM_SETCHECK, + bEnableBkgTask ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_CLOSE_BKG_TASK_WHEN_NOVOL), BM_SETCHECK, + bCloseBkgTaskWhenNoVolumes || IsNonInstallMode() ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_LOGOFF), BM_SETCHECK, + bDismountOnLogOff ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING), BM_SETCHECK, + bDismountOnPowerSaving ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER), BM_SETCHECK, + bDismountOnScreenSaver ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT), BM_SETCHECK, + bForceAutoDismount ? BST_CHECKED:BST_UNCHECKED, 0); + + SendMessage (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE), BM_SETCHECK, + MaxVolumeIdleTime > 0 ? BST_CHECKED:BST_UNCHECKED, 0); + + SetDlgItemInt (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE_TIME, abs (MaxVolumeIdleTime), FALSE); + + PreferencesDlgEnableButtons (hwndDlg); + } + return 0; + + case WM_COMMAND: + + if (lw == IDC_PRESERVE_TIMESTAMPS && !IsButtonChecked (GetDlgItem (hwndDlg, IDC_PRESERVE_TIMESTAMPS))) + { + if (AskWarnNoYes ("CONFIRM_TIMESTAMP_UPDATING") == IDNO) + SetCheckBox (hwndDlg, IDC_PRESERVE_TIMESTAMPS, TRUE); + } + + if (lw == IDC_PREF_BKG_TASK_ENABLE && !IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE))) + { + if (AskWarnNoYes ("CONFIRM_BACKGROUND_TASK_DISABLED") == IDNO) + SetCheckBox (hwndDlg, IDC_PREF_BKG_TASK_ENABLE, TRUE); + } + + // Forced dismount disabled warning + if (lw == IDC_PREF_DISMOUNT_INACTIVE + || lw == IDC_PREF_DISMOUNT_LOGOFF + || lw == IDC_PREF_DISMOUNT_POWERSAVING + || lw == IDC_PREF_DISMOUNT_SCREENSAVER + || lw == IDC_PREF_FORCE_AUTO_DISMOUNT) + { + BOOL i = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE)); + BOOL l = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_LOGOFF)); + BOOL p = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING)); + BOOL s = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER)); + BOOL q = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT)); + + if (!q) + { + if (lw == IDC_PREF_FORCE_AUTO_DISMOUNT && (i || l || p || s)) + { + if (AskWarnNoYes ("CONFIRM_NO_FORCED_AUTODISMOUNT") == IDNO) + SetCheckBox (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT, TRUE); + } + else if ((lw == IDC_PREF_DISMOUNT_INACTIVE && i + || lw == IDC_PREF_DISMOUNT_LOGOFF && l + || lw == IDC_PREF_DISMOUNT_POWERSAVING && p + || lw == IDC_PREF_DISMOUNT_SCREENSAVER && s)) + Warning ("WARN_PREF_AUTO_DISMOUNT"); + } + + if (p && lw == IDC_PREF_DISMOUNT_POWERSAVING) + Warning ("WARN_PREF_AUTO_DISMOUNT_ON_POWER"); + } + + if (lw == IDCANCEL) + { + PreferencesDialogActive = FALSE; + EndDialog (hwndDlg, lw); + return 1; + } + + if (lw == IDOK) + { + bExplore = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_OPEN_EXPLORER)); + bCloseDismountedWindows = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_CLOSE_DISMOUNTED_WINDOWS)); + bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PRESERVE_TIMESTAMPS)); + bWipeCacheOnExit = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_EXIT)); + bWipeCacheOnAutoDismount = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_WIPE_CACHE_ON_AUTODISMOUNT)); + bCacheInDriverDefault = bCacheInDriver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_CACHE_PASSWORDS)); + defaultMountOptions.ReadOnly = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_READONLY)); + defaultMountOptions.Removable = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_MOUNT_REMOVABLE)); + bEnableBkgTask = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_BKG_TASK_ENABLE)); + bCloseBkgTaskWhenNoVolumes = IsNonInstallMode() ? bCloseBkgTaskWhenNoVolumes : IsButtonChecked (GetDlgItem (hwndDlg, IDC_CLOSE_BKG_TASK_WHEN_NOVOL)); + bDismountOnLogOff = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_LOGOFF)); + bDismountOnPowerSaving = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_POWERSAVING)); + bDismountOnScreenSaver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_SCREENSAVER)); + bForceAutoDismount = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_FORCE_AUTO_DISMOUNT)); + MaxVolumeIdleTime = GetDlgItemInt (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE_TIME, NULL, FALSE) + * (IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_DISMOUNT_INACTIVE)) ? 1 : -1); + bStartOnLogon = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_LOGON_START)); + bMountDevicesOnLogon = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_DEVICES)); + bMountFavoritesOnLogon = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PREF_LOGON_MOUNT_FAVORITES)); + + ManageStartupSeq (); + + WaitCursor (); + SaveSettings (hwndDlg); + NormalCursor (); + + PreferencesDialogActive = FALSE; + EndDialog (hwndDlg, lw); + return 1; + } + + if (lw == IDC_MORE_SETTINGS) + { + HMENU popup = CreatePopupMenu (); + + AppendMenuW (popup, MF_STRING, IDM_LANGUAGE, GetString ("IDM_LANGUAGE")); + AppendMenuW (popup, MF_STRING, IDM_HOTKEY_SETTINGS, GetString ("IDM_HOTKEY_SETTINGS")); + AppendMenuW (popup, MF_STRING, IDM_SYSENC_SETTINGS, GetString ("IDM_SYSENC_SETTINGS")); + AppendMenuW (popup, MF_STRING, IDM_SYS_FAVORITES_SETTINGS, GetString ("IDM_SYS_FAVORITES_SETTINGS")); + AppendMenuW (popup, MF_STRING, IDM_DEFAULT_KEYFILES, GetString ("IDM_DEFAULT_KEYFILES")); + AppendMenuW (popup, MF_STRING, IDM_TOKEN_PREFERENCES, GetString ("IDM_TOKEN_PREFERENCES")); + + RECT rect; + GetWindowRect (GetDlgItem (hwndDlg, IDC_MORE_SETTINGS), &rect); + + int menuItem = TrackPopupMenu (popup, TPM_RETURNCMD | TPM_LEFTBUTTON, rect.left + 2, rect.top + 2, 0, hwndDlg, NULL); + DestroyMenu (popup); + + SendMessage (MainDlg, WM_COMMAND, menuItem, NULL); + return 1; + } + + if (HIWORD (wParam) == BN_CLICKED) + { + PreferencesDlgEnableButtons (hwndDlg); + return 1; + } + + return 0; + } + + return 0; +} + + +BOOL CALLBACK MountOptionsDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static MountOptions *mountOptions; + + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + BOOL protect; + + mountOptions = (MountOptions *) lParam; + + LocalizeDialog (hwndDlg, "IDD_MOUNT_OPTIONS"); + + SendDlgItemMessage (hwndDlg, IDC_MOUNT_READONLY, BM_SETCHECK, + mountOptions->ReadOnly ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage (hwndDlg, IDC_MOUNT_REMOVABLE, BM_SETCHECK, + mountOptions->Removable ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage (hwndDlg, IDC_PROTECT_HIDDEN_VOL, BM_SETCHECK, + mountOptions->ProtectHiddenVolume ? BST_CHECKED : BST_UNCHECKED, 0); + + SendDlgItemMessage (hwndDlg, IDC_PROTECT_HIDDEN_VOL, BM_SETCHECK, + mountOptions->ProtectHiddenVolume ? BST_CHECKED : BST_UNCHECKED, 0); + + mountOptions->PartitionInInactiveSysEncScope = bPrebootPasswordDlgMode; + + SendDlgItemMessage (hwndDlg, IDC_MOUNT_SYSENC_PART_WITHOUT_PBA, BM_SETCHECK, + bPrebootPasswordDlgMode ? BST_CHECKED : BST_UNCHECKED, 0); + + SendDlgItemMessage (hwndDlg, IDC_USE_EMBEDDED_HEADER_BAK, BM_SETCHECK, + mountOptions->UseBackupHeader ? BST_CHECKED : BST_UNCHECKED, 0); + + EnableWindow (GetDlgItem (hwndDlg, IDC_MOUNT_SYSENC_PART_WITHOUT_PBA), !bPrebootPasswordDlgMode); + + protect = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)); + + EnableWindow (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); + EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_VOL_PROTECTION), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); + EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), protect); + EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_MO), protect); + EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_PROT_PASSWD), protect); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_HIDVOL_PROT), protect); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT), protect); + + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT, hidVolProtKeyFilesParam.EnableKeyFiles); + + SendDlgItemMessage (hwndDlg, IDC_PASSWORD_PROT_HIDVOL, EM_LIMITTEXT, MAX_PASSWORD, 0); + + if (mountOptions->ProtectedHidVolPassword.Length > 0) + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), (LPSTR) mountOptions->ProtectedHidVolPassword.Text); + + ToHyperlink (hwndDlg, IDC_LINK_HIDVOL_PROTECTION_INFO); + + } + return 0; + + case WM_CONTEXTMENU: + { + RECT buttonRect; + GetWindowRect (GetDlgItem (hwndDlg, IDC_KEYFILES_HIDVOL_PROT), &buttonRect); + + if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)) + && LOWORD (lParam) >= buttonRect.left && LOWORD (lParam) <= buttonRect.right + && HIWORD (lParam) >= buttonRect.top && HIWORD (lParam) <= buttonRect.bottom) + { + // The "Keyfiles" button has been right-clicked + + POINT popupPos; + popupPos.x = buttonRect.left + 2; + popupPos.y = buttonRect.top + 2; + + if (KeyfilesPopupMenu (hwndDlg, popupPos, &hidVolProtKeyFilesParam)) + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT, hidVolProtKeyFilesParam.EnableKeyFiles); + } + } + break; + + case WM_COMMAND: + + if (lw == IDC_KEYFILES_HIDVOL_PROT) + { + if (IDOK == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, + (DLGPROC) KeyFilesDlgProc, (LPARAM) &hidVolProtKeyFilesParam)) + { + SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT, hidVolProtKeyFilesParam.EnableKeyFiles); + } + } + + if (lw == IDC_KEYFILES_ENABLE_HIDVOL_PROT) + { + hidVolProtKeyFilesParam.EnableKeyFiles = GetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT); + + return 0; + } + + if (lw == IDC_SHOW_PASSWORD_MO) + { + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), + EM_SETPASSWORDCHAR, + GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD_MO) ? 0 : '*', + 0); + InvalidateRect (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), NULL, TRUE); + return 1; + } + + if (lw == IDC_LINK_HIDVOL_PROTECTION_INFO) + { + Applink ("hiddenvolprotection", TRUE, ""); + } + + if (lw == IDCANCEL) + { + char tmp[MAX_PASSWORD+1]; + + // Cleanup + memset (tmp, 'X', MAX_PASSWORD); + tmp[MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), tmp); + + EndDialog (hwndDlg, lw); + return 1; + } + + if (lw == IDOK) + { + char tmp[MAX_PASSWORD+1]; + + mountOptions->ReadOnly = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY)); + mountOptions->Removable = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_REMOVABLE)); + mountOptions->ProtectHiddenVolume = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)); + mountOptions->PartitionInInactiveSysEncScope = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_SYSENC_PART_WITHOUT_PBA)); + mountOptions->UseBackupHeader = IsButtonChecked (GetDlgItem (hwndDlg, IDC_USE_EMBEDDED_HEADER_BAK)); + + if (mountOptions->ProtectHiddenVolume) + { + GetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), + (LPSTR) mountOptions->ProtectedHidVolPassword.Text, + sizeof (mountOptions->ProtectedHidVolPassword.Text)); + + mountOptions->ProtectedHidVolPassword.Length = strlen ((char *) mountOptions->ProtectedHidVolPassword.Text); + } + + // Cleanup + memset (tmp, 'X', MAX_PASSWORD); + tmp[MAX_PASSWORD] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), tmp); + + if ((mountOptions->ProtectHiddenVolume && !bEnableBkgTask) + && (AskWarnYesNo ("HIDVOL_PROT_BKG_TASK_WARNING") == IDYES)) + { + bEnableBkgTask = TRUE; + TaskBarIconAdd (MainDlg); + } + + EndDialog (hwndDlg, lw); + return 1; + } + + if (lw == IDC_MOUNT_READONLY || lw == IDC_PROTECT_HIDDEN_VOL) + { + BOOL protect; + + if (lw == IDC_MOUNT_READONLY) + { + SendDlgItemMessage (hwndDlg, IDC_PROTECT_HIDDEN_VOL, BM_SETCHECK, BST_UNCHECKED, 0); + EnableWindow (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); + EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_VOL_PROTECTION), !IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY))); + } + + protect = IsButtonChecked (GetDlgItem (hwndDlg, IDC_PROTECT_HIDDEN_VOL)); + + EnableWindow (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), protect); + EnableWindow (GetDlgItem (hwndDlg, IDT_HIDDEN_PROT_PASSWD), protect); + EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PASSWORD_MO), protect); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_HIDVOL_PROT), protect); + EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE_HIDVOL_PROT), protect); + + return 1; + } + + return 0; + } + + return 0; +} + + +// Returns the block size (in bits) of the cipher with which the volume mounted as the +// specified drive letter is encrypted. In case of a cascade of ciphers with different +// block sizes the function returns the smallest block size. +int GetCipherBlockSizeByDriveNo (int nDosDriveNo) +{ + VOLUME_PROPERTIES_STRUCT prop; + DWORD dwResult; + + int blockSize = 0, cipherID; + + memset (&prop, 0, sizeof(prop)); + prop.driveNo = nDosDriveNo; + + if (DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL)) + { + for (cipherID = EAGetLastCipher (prop.ea); + cipherID != 0; + cipherID = EAGetPreviousCipher (prop.ea, cipherID)) + { + if (blockSize > 0) + blockSize = min (blockSize, CipherGetBlockSize (cipherID) * 8); + else + blockSize = CipherGetBlockSize (cipherID) * 8; + } + } + + return blockSize; +} + + +// Returns the mode of operation in which the volume mounted as the specified drive letter is encrypted. +int GetModeOfOperationByDriveNo (int nDosDriveNo) +{ + VOLUME_PROPERTIES_STRUCT prop; + DWORD dwResult; + + memset (&prop, 0, sizeof(prop)); + prop.driveNo = nDosDriveNo; + + if (DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL)) + { + return prop.mode; + } + + return 0; +} + + +BOOL CALLBACK VolumePropertiesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + BOOL bSysEnc = (BOOL) lParam; + BOOL bSysEncWholeDrive = FALSE; + WORD lw = LOWORD (wParam); + int i = 0; + + switch (msg) + { + case WM_INITDIALOG: + { + VOLUME_PROPERTIES_STRUCT prop; + DWORD dwResult; + + LVCOLUMNW lvCol; + HWND list = GetDlgItem (hwndDlg, IDC_VOLUME_PROPERTIES_LIST); + char szTmp[1024]; + wchar_t sw[1024]; + wchar_t *s; + + if (bSysEnc) + { + try + { + BootEncStatus = BootEncObj->GetStatus(); + bSysEncWholeDrive = WholeSysDriveEncryption(FALSE); + } + catch (Exception &e) + { + e.Show (MainDlg); + return 0; + } + + if (!BootEncStatus.DriveEncrypted && !BootEncStatus.DriveMounted) + return 0; + } + else + { + switch (LOWORD (GetSelectedLong (GetDlgItem (GetParent(hwndDlg), IDC_DRIVELIST)))) + { + case TC_MLIST_ITEM_FREE: + + // No mounted volume + EndDialog (hwndDlg, IDOK); + return 0; + + case TC_MLIST_ITEM_NONSYS_VOL: + // NOP + break; + + case TC_MLIST_ITEM_SYS_DRIVE: + // Encrypted system drive + bSysEnc = TRUE; + bSysEncWholeDrive = TRUE; + break; + + case TC_MLIST_ITEM_SYS_PARTITION: + // Encrypted system partition + bSysEnc = TRUE; + bSysEncWholeDrive = FALSE; + break; + } + } + + LocalizeDialog (hwndDlg, "IDD_VOLUME_PROPERTIES"); + + SendMessage (list,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, + LVS_EX_FULLROWSELECT + |LVS_EX_HEADERDRAGDROP + |LVS_EX_LABELTIP + ); + + memset (&lvCol,0,sizeof(lvCol)); + lvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + lvCol.pszText = GetString ("VALUE"); + lvCol.cx = CompensateXDPI (208); + lvCol.fmt = LVCFMT_LEFT ; + SendMessage (list,LVM_INSERTCOLUMNW,0,(LPARAM)&lvCol); + + lvCol.pszText = GetString ("PROPERTY"); + lvCol.cx = CompensateXDPI (192); + lvCol.fmt = LVCFMT_LEFT; + SendMessage (list,LVM_INSERTCOLUMNW,0,(LPARAM)&lvCol); + + memset (&prop, 0, sizeof(prop)); + prop.driveNo = HIWORD (GetSelectedLong (GetDlgItem (GetParent(hwndDlg), IDC_DRIVELIST))) - 'A'; + + if (bSysEnc) + { + try + { + BootEncStatus = BootEncObj->GetStatus(); + if (!BootEncStatus.DriveEncrypted && !BootEncStatus.DriveMounted) + return 0; + + BootEncObj->GetVolumeProperties (&prop); + } + catch (Exception &e) + { + e.Show (MainDlg); + return 0; + } + } + else + { + if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL) || dwResult == 0) + return 0; + } + + // Location + ListItemAddW (list, i, GetString ("LOCATION")); + if (bSysEnc) + ListSubItemSetW (list, i++, 1, GetString (bSysEncWholeDrive ? "SYSTEM_DRIVE" : IsHiddenOSRunning() ? "HIDDEN_SYSTEM_PARTITION" : "SYSTEM_PARTITION")); + else + ListSubItemSetW (list, i++, 1, (wchar_t *) (prop.wszVolume[1] != L'?' ? prop.wszVolume : prop.wszVolume + 4)); + + // Size + ListItemAddW (list, i, GetString ("SIZE")); + swprintf (sw, L"%I64u %s", prop.diskLength, GetString ("BYTES")); + ListSubItemSetW (list, i++, 1, sw); + + // Type + ListItemAddW (list, i, GetString ("TYPE")); + if (bSysEnc) + ListSubItemSetW (list, i++, 1, GetString (IsHiddenOSRunning() ? "TYPE_HIDDEN_SYSTEM_ADJECTIVE" : "SYSTEM_VOLUME_TYPE_ADJECTIVE")); + else + { + ListSubItemSetW (list, i++, 1, + prop.hiddenVolume ? GetString ("HIDDEN") : + (prop.hiddenVolProtection != HIDVOL_PROT_STATUS_NONE ? GetString ("OUTER") : GetString ("NORMAL"))); + } + + if (!bSysEnc) + { + // Write protection + ListItemAddW (list, i, GetString ("READ_ONLY")); + + if (prop.readOnly || prop.hiddenVolProtection == HIDVOL_PROT_STATUS_ACTION_TAKEN) + s = GetString ("UISTR_YES"); + else + s = GetString ("UISTR_NO"); + + ListSubItemSetW (list, i++, 1, s); + + // Hidden Volume Protection + ListItemAddW (list, i, GetString ("HIDDEN_VOL_PROTECTION")); + if (prop.hiddenVolume) + s = GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"); + else if (prop.hiddenVolProtection == HIDVOL_PROT_STATUS_NONE) + s = GetString ("UISTR_NO"); + else if (prop.hiddenVolProtection == HIDVOL_PROT_STATUS_ACTIVE) + s = GetString ("UISTR_YES"); + else if (prop.hiddenVolProtection == HIDVOL_PROT_STATUS_ACTION_TAKEN) + s = GetString ("HID_VOL_DAMAGE_PREVENTED"); + + ListSubItemSetW (list, i++, 1, s); + } + + // Encryption algorithm + ListItemAddW (list, i, GetString ("ENCRYPTION_ALGORITHM")); + + if (prop.ea == 0 || prop.ea > EAGetCount ()) + { + ListSubItemSet (list, i, 1, "?"); + return 1; + } + + EAGetName (szTmp, prop.ea); + ListSubItemSet (list, i++, 1, szTmp); + + // Key size(s) + { + char name[128]; + int size = EAGetKeySize (prop.ea); + EAGetName (name, prop.ea); + + if (strcmp (name, "Triple DES") == 0) /* Deprecated/legacy */ + size -= 3; // Compensate for parity bytes + + // Primary key + ListItemAddW (list, i, GetString ("KEY_SIZE")); + wsprintfW (sw, L"%d %s", size * 8, GetString ("BITS")); + ListSubItemSetW (list, i++, 1, sw); + + if (strcmp (EAGetModeName (prop.ea, prop.mode, TRUE), "XTS") == 0) + { + // Secondary key (XTS) + + ListItemAddW (list, i, GetString ("SECONDARY_KEY_SIZE_XTS")); + ListSubItemSetW (list, i++, 1, sw); + } + else if (strcmp (EAGetModeName (prop.ea, prop.mode, TRUE), "LRW") == 0) + { + // Tweak key (LRW) + + ListItemAddW (list, i, GetString ("SECONDARY_KEY_SIZE_LRW")); + swprintf (sw, L"%d %s", CipherGetBlockSize (EAGetFirstCipher(prop.ea))*8, GetString ("BITS")); + ListSubItemSetW (list, i++, 1, sw); + } + } + + // Block size + ListItemAddW (list, i, GetString ("BLOCK_SIZE")); + if (EAGetFirstMode (prop.ea) == INNER_CBC) + { + // Cascaded ciphers with non-equal block sizes (deprecated/legacy) + wchar_t tmpstr[64]; + int i = EAGetLastCipher(prop.ea); + + swprintf (sw, L"%d", CipherGetBlockSize(i)*8); + + while (i = EAGetPreviousCipher(prop.ea, i)) + { + swprintf (tmpstr, L"/%d", CipherGetBlockSize(i)*8); + wcscat (sw, tmpstr); + } + wcscat (sw, L" "); + } + else + { + swprintf (sw, L"%d ", CipherGetBlockSize (EAGetFirstCipher(prop.ea))*8); + } + wcscat (sw, GetString ("BITS")); + ListSubItemSetW (list, i++, 1, sw); + + // Mode + ListItemAddW (list, i, GetString ("MODE_OF_OPERATION")); + ListSubItemSet (list, i++, 1, EAGetModeName (prop.ea, prop.mode, TRUE)); + + // PKCS 5 PRF + ListItemAddW (list, i, GetString ("PKCS5_PRF")); + ListSubItemSet (list, i++, 1, get_pkcs5_prf_name (prop.pkcs5)); + +#if 0 + // PCKS 5 iterations + ListItemAddW (list, i, GetString ("PKCS5_ITERATIONS")); + sprintf (szTmp, "%d", prop.pkcs5Iterations); + ListSubItemSet (list, i++, 1, szTmp); +#endif + +#if 0 + { + // Legacy + + FILETIME ft, curFt; + LARGE_INTEGER ft64, curFt64; + SYSTEMTIME st; + wchar_t date[128]; + memset (date, 0, sizeof (date)); + + // Volume date + ListItemAddW (list, i, GetString ("VOLUME_CREATE_DATE")); + *(unsigned __int64 *)(&ft) = prop.volumeCreationTime; + FileTimeToSystemTime (&ft, &st); + GetDateFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); + swprintf (date, L"%s ", sw); + GetTimeFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); + wcscat (date, sw); + ListSubItemSetW (list, i++, 1, date); + + // Header date + ListItemAddW (list, i, GetString ("VOLUME_HEADER_DATE")); + *(unsigned __int64 *)(&ft) = prop.headerCreationTime; + FileTimeToSystemTime (&ft, &st); + GetDateFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); + swprintf (date, L"%s ", sw); + GetTimeFormatW (LOCALE_USER_DEFAULT, 0, &st, 0, sw, sizeof (sw)/2); + wcscat (date, sw); + + GetLocalTime (&st); + SystemTimeToFileTime (&st, &curFt); + curFt64.HighPart = curFt.dwHighDateTime; + curFt64.LowPart = curFt.dwLowDateTime; + ft64.HighPart = ft.dwHighDateTime; + ft64.LowPart = ft.dwLowDateTime; + swprintf (date + wcslen (date), GetString ("VOLUME_HEADER_DAYS") + , (curFt64.QuadPart - ft64.QuadPart)/(24LL*3600*10000000)); + ListSubItemSetW (list, i++, 1, date); + } +#endif // 0 + + if (!bSysEnc || IsHiddenOSRunning()) + { + // Volume format version + ListItemAddW (list, i, GetString ("VOLUME_FORMAT_VERSION")); + sprintf (szTmp, "%d", prop.volFormatVersion); + ListSubItemSet (list, i++, 1, szTmp); + + // Backup header + ListItemAddW (list, i, GetString ("BACKUP_HEADER")); + ListSubItemSetW (list, i++, 1, GetString (prop.volFormatVersion > 1 ? "UISTR_YES" : "UISTR_NO")); + } + + // Total data read + ListItemAddW (list, i, GetString ("TOTAL_DATA_READ")); + GetSizeString (prop.totalBytesRead, sw); + ListSubItemSetW (list, i++, 1, sw); + + // Total data written + ListItemAddW (list, i, GetString ("TOTAL_DATA_WRITTEN")); + GetSizeString (prop.totalBytesWritten, sw); + ListSubItemSetW (list, i++, 1, sw); + + if (bSysEnc) + { + // Encrypted portion + ListItemAddW (list, i, GetString ("ENCRYPTED_PORTION")); + if (GetSysEncDeviceEncryptedPartSize (FALSE) == GetSysEncDeviceSize (FALSE)) + ListSubItemSetW (list, i++, 1, GetString ("ENCRYPTED_PORTION_FULLY_ENCRYPTED")); + else if (GetSysEncDeviceEncryptedPartSize (FALSE) <= 1) + ListSubItemSetW (list, i++, 1, GetString ("ENCRYPTED_PORTION_NOT_ENCRYPTED")); + else + { + + _snwprintf (sw, + sizeof sw/2, + GetString ("PROCESSED_PORTION_X_PERCENT"), + (double) GetSysEncDeviceEncryptedPartSize (FALSE) / (double) GetSysEncDeviceSize (FALSE) * 100.0); + + ListSubItemSetW (list, i++, 1, sw); + } + } + + return 0; + } + + case WM_COMMAND: + if (lw == IDOK) + { + EndDialog (hwndDlg, lw); + return 1; + } + return 0; + + case WM_CLOSE: + EndDialog (hwndDlg, lw); + return 1; + } + + return 0; +} + + +BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + static BOOL bAutoRunWarningDisplayed = FALSE; + + switch (msg) + { + case WM_INITDIALOG: + { + char i; + int index; + char drive[] = { 0, ':', 0 }; + + LocalizeDialog (hwndDlg, "IDD_TRAVELER_DLG"); + + SendDlgItemMessage (hwndDlg, IDC_COPY_WIZARD, BM_SETCHECK, + BST_CHECKED, 0); + + SendDlgItemMessage (hwndDlg, IDC_TRAVEL_OPEN_EXPLORER, BM_SETCHECK, + BST_CHECKED, 0); + + SendDlgItemMessage (hwndDlg, IDC_AUTORUN_DISABLE, BM_SETCHECK, + BST_CHECKED, 0); + + SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_RESETCONTENT, 0, 0); + + index = SendDlgItemMessageW (hwndDlg, IDC_DRIVELIST, CB_ADDSTRING, 0, (LPARAM) GetString ("FIRST_AVAILABLE")); + SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_SETITEMDATA, index, (LPARAM) 0); + + for (i = 'D'; i <= 'Z'; i++) + { + drive[0] = i; + index = SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_ADDSTRING, 0, (LPARAM) drive); + SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_SETITEMDATA, index, (LPARAM) i); + } + + SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_SETCURSEL, 0, 0); + + return 0; + } + + + case WM_COMMAND: + + if (HIWORD (wParam) == BN_CLICKED + && (lw == IDC_AUTORUN_DISABLE || lw == IDC_AUTORUN_MOUNT || lw == IDC_AUTORUN_START )) + { + BOOL enabled = IsButtonChecked (GetDlgItem (hwndDlg, IDC_AUTORUN_MOUNT)); + + EnableWindow (GetDlgItem (hwndDlg, IDC_BROWSE_FILES), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_VOLUME_NAME), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TRAVEL_OPEN_EXPLORER), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TRAV_CACHE_PASSWORDS), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_DRIVELIST), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TRAVELER_MOUNT), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_MOUNT_LETTER), enabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_MOUNT_SETTINGS), enabled); + + if (!bAutoRunWarningDisplayed + && (lw == IDC_AUTORUN_MOUNT || lw == IDC_AUTORUN_START)) + { + bAutoRunWarningDisplayed = TRUE; + Warning ("AUTORUN_MAY_NOT_ALWAYS_WORK"); + } + + return 1; + } + + if (lw == IDC_BROWSE_FILES) + { + char dstDir[MAX_PATH]; + char volName[MAX_PATH] = { 0 }; + + GetDlgItemText (hwndDlg, IDC_DIRECTORY, dstDir, sizeof dstDir); + + if (BrowseFilesInDir (hwndDlg, "OPEN_TITLE", dstDir, volName, bHistory, FALSE, NULL)) + SetDlgItemText (hwndDlg, IDC_VOLUME_NAME, strchr (volName, '\\') + 1); + + return 1; + } + + if (lw == IDC_BROWSE_DIRS) + { + char dstPath[MAX_PATH * 2]; + GetDlgItemText (hwndDlg, IDC_DIRECTORY, dstPath, sizeof dstPath); + + if (BrowseDirectories (hwndDlg, "SELECT_DEST_DIR", dstPath)) + SetDlgItemText (hwndDlg, IDC_DIRECTORY, dstPath); + + return 1; + } + + if (lw == IDCANCEL || lw == IDCLOSE) + { + EndDialog (hwndDlg, lw); + return 1; + } + + if (lw == IDC_CREATE) + { + + BOOL copyWizard, bExplore, bCacheInDriver, bAutoRun, bAutoMount, bMountReadOnly; + char dstDir[MAX_PATH]; + char srcPath[MAX_PATH * 2]; + char dstPath[MAX_PATH * 2]; + char appDir[MAX_PATH]; + char sysDir[MAX_PATH]; + char volName[MAX_PATH]; + int drive; + + GetDlgItemText (hwndDlg, IDC_DIRECTORY, dstDir, sizeof dstDir); + volName[0] = 0; + GetDlgItemText (hwndDlg, IDC_VOLUME_NAME, volName + 1, sizeof volName); + + drive = SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_GETCURSEL, 0, 0); + drive = SendDlgItemMessage (hwndDlg, IDC_DRIVELIST, CB_GETITEMDATA, drive, 0); + + copyWizard = IsButtonChecked (GetDlgItem (hwndDlg, IDC_COPY_WIZARD)); + bExplore = IsButtonChecked (GetDlgItem (hwndDlg, IDC_TRAVEL_OPEN_EXPLORER)); + bCacheInDriver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_TRAV_CACHE_PASSWORDS)); + bMountReadOnly = IsButtonChecked (GetDlgItem (hwndDlg, IDC_MOUNT_READONLY)); + bAutoRun = !IsButtonChecked (GetDlgItem (hwndDlg, IDC_AUTORUN_DISABLE)); + bAutoMount = IsButtonChecked (GetDlgItem (hwndDlg, IDC_AUTORUN_MOUNT)); + + if (dstDir[0] == 0) + { + SetFocus (GetDlgItem (hwndDlg, IDC_DIRECTORY)); + MessageBoxW (hwndDlg, GetString ("NO_PATH_SELECTED"), lpszTitle, MB_ICONEXCLAMATION); + return 1; + } + + + if (bAutoMount && volName[1] == 0) + { + SetFocus (GetDlgItem (hwndDlg, IDC_VOLUME_NAME)); + MessageBoxW (hwndDlg, GetString ("NO_FILE_SELECTED"), lpszTitle, MB_ICONEXCLAMATION); + return 1; + } + + if (volName[1] != 0) + { + volName[0] = '"'; + strcat (volName, "\""); + } + + GetModuleFileName (NULL, appDir, sizeof (appDir)); + strrchr (appDir, '\\')[0] = 0; + + WaitCursor (); + GetSystemDirectory (sysDir, sizeof (sysDir)); + + sprintf (dstPath, "%s\\TrueCrypt", dstDir); + CreateDirectory (dstPath, NULL); + + // Main app + sprintf (srcPath, "%s\\TrueCrypt.exe", appDir); + sprintf (dstPath, "%s\\TrueCrypt\\TrueCrypt.exe", dstDir); + if (!TCCopyFile (srcPath, dstPath)) + { + handleWin32Error (hwndDlg); + goto stop; + } + + // Wizard + if (copyWizard) + { + sprintf (srcPath, "%s\\TrueCrypt Format.exe", appDir); + sprintf (dstPath, "%s\\TrueCrypt\\TrueCrypt Format.exe", dstDir); + if (!TCCopyFile (srcPath, dstPath)) + { + handleWin32Error (hwndDlg); + goto stop; + } + } + + // Driver + sprintf (srcPath, "%s\\truecrypt.sys", appDir); + sprintf (dstPath, "%s\\TrueCrypt\\truecrypt.sys", dstDir); + if (!TCCopyFile (srcPath, dstPath)) + { + handleWin32Error (hwndDlg); + goto stop; + } + + // Driver x64 + sprintf (srcPath, "%s\\truecrypt-x64.sys", appDir); + sprintf (dstPath, "%s\\TrueCrypt\\truecrypt-x64.sys", dstDir); + if (!TCCopyFile (srcPath, dstPath)) + { + handleWin32Error (hwndDlg); + goto stop; + } + + if (GetPreferredLangId () && strcmp (GetPreferredLangId (), "en") != 0) + { + // Language pack + sprintf (srcPath, "%s\\Language.%s.xml", appDir, GetPreferredLangId ()); + sprintf (dstPath, "%s\\TrueCrypt\\Language.%s.xml", dstDir, GetPreferredLangId ()); + TCCopyFile (srcPath, dstPath); + } + + // AutoRun + sprintf (dstPath, "%s\\autorun.inf", dstDir); + DeleteFile (dstPath); + if (bAutoRun) + { + FILE *af; + char autoMount[100]; + char driveLetter[] = { ' ', '/', 'l', (char) drive, 0 }; + + af = fopen (dstPath, "w,ccs=UNICODE"); + + if (af == NULL) + { + MessageBoxW (hwndDlg, GetString ("CANT_CREATE_AUTORUN"), lpszTitle, MB_ICONERROR); + goto stop; + } + + sprintf (autoMount, "TrueCrypt\\TrueCrypt.exe /q background%s%s%s%s /m rm /v %s", + drive > 0 ? driveLetter : "", + bExplore ? " /e" : "", + bCacheInDriver ? " /c y" : "", + bMountReadOnly ? " /m ro" : "", + volName); + + fwprintf (af, L"[autorun]\nlabel=%s\nicon=TrueCrypt\\TrueCrypt.exe\n", GetString ("TC_TRAVELER_DISK")); + fwprintf (af, L"action=%s\n", bAutoMount ? GetString ("MOUNT_TC_VOLUME") : GetString ("IDC_PREF_LOGON_START")); + fwprintf (af, L"open=%hs\n", bAutoMount ? autoMount : "TrueCrypt\\TrueCrypt.exe"); + fwprintf (af, L"shell\\start=%s\nshell\\start\\command=TrueCrypt\\TrueCrypt.exe\n", GetString ("IDC_PREF_LOGON_START")); + fwprintf (af, L"shell\\dismount=%s\nshell\\dismount\\command=TrueCrypt\\TrueCrypt.exe /q /d\n", GetString ("DISMOUNT_ALL_TC_VOLUMES")); + + fclose (af); + } + MessageBoxW (hwndDlg, GetString ("TRAVELER_DISK_CREATED"), lpszTitle, MB_ICONINFORMATION); + +stop: + NormalCursor (); + return 1; + } + return 0; + } + + return 0; +} + + +void +BuildTree (HWND hTree) +{ + HIMAGELIST hList; + HBITMAP hBitmap, hBitmapMask; + LVCOLUMNW lvCol; + + ListView_DeleteColumn (hTree,0); + ListView_DeleteColumn (hTree,0); + ListView_DeleteColumn (hTree,0); + ListView_DeleteColumn (hTree,0); + ListView_DeleteColumn (hTree,0); + ListView_DeleteColumn (hTree,0); + + SendMessage(hTree,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT + |LVS_EX_HEADERDRAGDROP + ); + + memset(&lvCol,0,sizeof(lvCol)); + + lvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + lvCol.pszText = GetString ("DRIVE"); + lvCol.cx = CompensateXDPI (38); + lvCol.fmt = LVCFMT_COL_HAS_IMAGES|LVCFMT_LEFT ; + SendMessage (hTree,LVM_INSERTCOLUMNW,0,(LPARAM)&lvCol); + + lvCol.pszText = GetString ("VOLUME"); + lvCol.cx = CompensateXDPI (253); + lvCol.fmt = LVCFMT_LEFT; + SendMessage (hTree,LVM_INSERTCOLUMNW,1,(LPARAM)&lvCol); + LastDriveListVolumeColumnWidth = ListView_GetColumnWidth (hTree, 1); + + lvCol.pszText = GetString ("SIZE"); + lvCol.cx = CompensateXDPI (55); + lvCol.fmt = LVCFMT_RIGHT; + SendMessage (hTree,LVM_INSERTCOLUMNW,2,(LPARAM)&lvCol); + + lvCol.pszText = GetString ("ENCRYPTION_ALGORITHM_LV"); + lvCol.cx = CompensateXDPI (121); + lvCol.fmt = LVCFMT_LEFT; + SendMessage (hTree,LVM_INSERTCOLUMNW,3,(LPARAM)&lvCol); + + lvCol.pszText = GetString ("TYPE"); + lvCol.cx = CompensateXDPI (52); + lvCol.fmt = LVCFMT_LEFT; + SendMessage (hTree,LVM_INSERTCOLUMNW,4,(LPARAM)&lvCol); + + // Regular drive icon + + hBitmap = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_DRIVEICON)); + if (hBitmap == NULL) + return; + hBitmapMask = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_DRIVEICON_MASK)); + + hList = ImageList_Create (16, 12, ILC_COLOR8|ILC_MASK, 2, 2); + if (ImageList_Add (hList, hBitmap, hBitmapMask) == -1) + { + DeleteObject (hBitmap); + DeleteObject (hBitmapMask); + return; + } + else + { + DeleteObject (hBitmap); + DeleteObject (hBitmapMask); + } + + // System drive icon + + hBitmap = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_SYS_DRIVEICON)); + if (hBitmap == NULL) + return; + hBitmapMask = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_SYS_DRIVEICON_MASK)); + + if (ImageList_Add (hList, hBitmap, hBitmapMask) == -1) + { + DeleteObject (hBitmap); + DeleteObject (hBitmapMask); + return; + } + else + { + DeleteObject (hBitmap); + DeleteObject (hBitmapMask); + } + + ListView_SetImageList (hTree, hList, LVSIL_NORMAL); + ListView_SetImageList (hTree, hList, LVSIL_SMALL); + + LoadDriveLetters (hTree, 0); +} + +LPARAM +GetSelectedLong (HWND hTree) +{ + int hItem = ListView_GetSelectionMark (hTree); + LVITEM item; + + if (nSelectedDriveIndex >= 0) + hItem = nSelectedDriveIndex; + + memset(&item, 0, sizeof(LVITEM)); + item.mask = LVIF_PARAM; + item.iItem = hItem; + + if (ListView_GetItem (hTree, &item) == FALSE) + return MAKELONG (0xffff, 0xffff); + else + return item.lParam; +} + +LPARAM +GetItemLong (HWND hTree, int itemNo) +{ + LVITEM item; + + memset(&item, 0, sizeof(LVITEM)); + item.mask = LVIF_PARAM; + item.iItem = itemNo; + + if (ListView_GetItem (hTree, &item) == FALSE) + return MAKELONG (0xffff, 0xffff); + else + return item.lParam; +} + +static int AskVolumePassword (HWND hwndDlg, Password *password, char *titleStringId, BOOL enableMountOptions) +{ + int result; + + PasswordDialogTitleStringId = titleStringId; + PasswordDialogDisableMountOptions = !enableMountOptions; + + result = DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_PASSWORD_DLG), hwndDlg, + (DLGPROC) PasswordDlgProc, (LPARAM) password); + + if (result != IDOK) + { + password->Length = 0; + burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); + } + + return result == IDOK; +} + +// GUI actions + +static BOOL Mount (HWND hwndDlg, int nDosDriveNo, char *szFileName) +{ + BOOL status = FALSE; + char fileName[MAX_PATH]; + int mounted = 0, modeOfOperation; + if (nDosDriveNo == 0) + nDosDriveNo = HIWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) - 'A'; + + if (!MultipleMountOperationInProgress) + VolumePassword.Length = 0; + + if (szFileName == NULL) + { + GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), fileName, sizeof (fileName)); + szFileName = fileName; + } + + if (strlen(szFileName) == 0) + { + status = FALSE; + goto ret; + } + + if (IsMountedVolume (szFileName)) + { + Warning ("VOL_ALREADY_MOUNTED"); + status = FALSE; + goto ret; + } + + if (!VolumePathExists (szFileName)) + { + if (!MultipleMountOperationInProgress) + handleWin32Error (hwndDlg); + + status = FALSE; + goto ret; + } + + ResetWrongPwdRetryCount (); + + // First try cached passwords and if they fail ask user for a new one + WaitCursor (); + + mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, NULL, bCacheInDriver, bForceMount, &mountOptions, Silent, FALSE); + + // If keyfiles are enabled, test empty password first + if (!mounted && KeyFilesEnable) + { + KeyFilesApply (&VolumePassword, FirstKeyFile); + mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, Silent, FALSE); + } + + if (!mounted && !KeyFilesEnable && MultipleMountOperationInProgress && VolumePassword.Length != 0) + mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, Silent, FALSE); + + NormalCursor (); + + if (mounted) + { + // Check for deprecated CBC mode + modeOfOperation = GetModeOfOperationByDriveNo (nDosDriveNo); + if (modeOfOperation == CBC || modeOfOperation == OUTER_CBC) + Warning("WARN_CBC_MODE"); + + // Check for deprecated 64-bit-block ciphers + if (GetCipherBlockSizeByDriveNo (nDosDriveNo) == 64) + Warning("WARN_64_BIT_BLOCK_CIPHER"); + + // Check for problematic file extensions (exe, dll, sys) + if (CheckFileExtension(szFileName)) + Warning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); + } + + while (mounted == 0) + { + if (CmdVolumePassword.Length > 0) + { + VolumePassword = CmdVolumePassword; + } + else if (!Silent) + { + strcpy (PasswordDlgVolume, szFileName); + if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, TRUE)) + goto ret; + } + + WaitCursor (); + + if (KeyFilesEnable) + KeyFilesApply (&VolumePassword, FirstKeyFile); + + mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, Silent, !Silent); + NormalCursor (); + + // Check for deprecated CBC mode + modeOfOperation = GetModeOfOperationByDriveNo (nDosDriveNo); + if (modeOfOperation == CBC || modeOfOperation == OUTER_CBC) + Warning("WARN_CBC_MODE"); + + // Check for deprecated 64-bit-block ciphers + if (GetCipherBlockSizeByDriveNo (nDosDriveNo) == 64) + Warning("WARN_64_BIT_BLOCK_CIPHER"); + + // Check for legacy non-ASCII passwords + if (mounted > 0 && !KeyFilesEnable && !CheckPasswordCharEncoding (NULL, &VolumePassword)) + Warning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); + + // Check for problematic file extensions (exe, dll, sys) + if (mounted > 0 && CheckFileExtension (szFileName)) + Warning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); + + if (!MultipleMountOperationInProgress) + burn (&VolumePassword, sizeof (VolumePassword)); + + burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); + + if (CmdVolumePassword.Length > 0 || Silent) + break; + } + + if (mounted > 0) + { + status = TRUE; + + if (bBeep) + MessageBeep (0xFFFFFFFF); + + RefreshMainDlg(hwndDlg); + + if (bExplore) + { + WaitCursor(); + OpenVolumeExplorerWindow (nDosDriveNo); + NormalCursor(); + } + + if (mountOptions.ProtectHiddenVolume) + Info ("HIDVOL_PROT_WARN_AFTER_MOUNT"); + } + +ret: + if (!MultipleMountOperationInProgress) + burn (&VolumePassword, sizeof (VolumePassword)); + + burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); + + RestoreDefaultKeyFilesParam (); + + if (UsePreferences) + bCacheInDriver = bCacheInDriverDefault; + + if (status && CloseSecurityTokenSessionsAfterMount && !MultipleMountOperationInProgress) + SecurityToken::CloseAllSessions(); + + return status; +} + + +static BOOL Dismount (HWND hwndDlg, int nDosDriveNo) +{ + BOOL status = FALSE; + WaitCursor (); + + if (nDosDriveNo == 0) + nDosDriveNo = (char) (HIWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) - 'A'); + + if (bCloseDismountedWindows) + { + CloseVolumeExplorerWindows (hwndDlg, nDosDriveNo); + } + + if (UnmountVolume (hwndDlg, nDosDriveNo, bForceUnmount)) + { + status = TRUE; + + if (bBeep) + MessageBeep (0xFFFFFFFF); + RefreshMainDlg (hwndDlg); + + if (nCurrentOS == WIN_2000 && RemoteSession && !IsAdmin ()) + LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), 0); + } + + NormalCursor (); + return status; +} + +static BOOL DismountAll (HWND hwndDlg, BOOL forceUnmount, BOOL interact, int dismountMaxRetries, int dismountAutoRetryDelay) +{ + BOOL status = TRUE; + MOUNT_LIST_STRUCT mountList; + DWORD dwResult; + UNMOUNT_STRUCT unmount; + BOOL bResult; + unsigned __int32 prevMountedDrives = 0; + int i; + +retry: + WaitCursor(); + + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mountList, sizeof (mountList), &mountList, sizeof (mountList), &dwResult, NULL); + + if (mountList.ulMountedDrives == 0) + { + NormalCursor(); + return TRUE; + } + + BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, 0, mountList.ulMountedDrives); + + prevMountedDrives = mountList.ulMountedDrives; + + for (i = 0; i < 26; i++) + { + if (mountList.ulMountedDrives & (1 << i)) + { + if (bCloseDismountedWindows) + CloseVolumeExplorerWindows (hwndDlg, i); + } + } + + unmount.nDosDriveNo = 0; + unmount.ignoreOpenFiles = forceUnmount; + + do + { + bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_ALL_VOLUMES, &unmount, + sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); + + if (bResult == FALSE) + { + NormalCursor(); + handleWin32Error (hwndDlg); + return FALSE; + } + + if (unmount.nReturnCode == ERR_SUCCESS + && unmount.HiddenVolumeProtectionTriggered + && !VolumeNotificationsList.bHidVolDamagePrevReported [unmount.nDosDriveNo]) + { + wchar_t msg[4096]; + + VolumeNotificationsList.bHidVolDamagePrevReported [unmount.nDosDriveNo] = TRUE; + swprintf (msg, GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), unmount.nDosDriveNo + 'A'); + SetForegroundWindow (hwndDlg); + MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + + unmount.HiddenVolumeProtectionTriggered = FALSE; + continue; + } + + if (unmount.nReturnCode == ERR_FILES_OPEN) + Sleep (dismountAutoRetryDelay); + else + break; + + } while (--dismountMaxRetries > 0); + + memset (&mountList, 0, sizeof (mountList)); + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mountList, sizeof (mountList), &mountList, sizeof (mountList), &dwResult, NULL); + BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, 0, prevMountedDrives & ~mountList.ulMountedDrives); + + RefreshMainDlg (hwndDlg); + + if (nCurrentOS == WIN_2000 && RemoteSession && !IsAdmin ()) + LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), 0); + + NormalCursor(); + + if (unmount.nReturnCode != 0) + { + if (forceUnmount) + status = FALSE; + + if (unmount.nReturnCode == ERR_FILES_OPEN) + { + if (interact && IDYES == AskWarnNoYes ("UNMOUNTALL_LOCK_FAILED")) + { + forceUnmount = TRUE; + goto retry; + } + + if (IsOSAtLeast (WIN_7)) + { + // Undo SHCNE_DRIVEREMOVED + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, NULL, 0, &mountList, sizeof (mountList), &dwResult, NULL); + + for (i = 0; i < 26; i++) + { + if (mountList.ulMountedDrives & (1 << i)) + { + char root[] = { (char) i + 'A', ':', '\\', 0 }; + SHChangeNotify (SHCNE_DRIVEADD, SHCNF_PATH, root, NULL); + } + } + } + + return FALSE; + } + + if (interact) + MessageBoxW (hwndDlg, GetString ("UNMOUNT_FAILED"), lpszTitle, MB_ICONERROR); + } + else + { + if (bBeep) + MessageBeep (0xFFFFFFFF); + } + + return status; +} + +static BOOL MountAllDevices (HWND hwndDlg, BOOL bPasswordPrompt) +{ + HWND driveList = GetDlgItem (hwndDlg, IDC_DRIVELIST); + int selDrive = ListView_GetSelectionMark (driveList); + BOOL shared = FALSE, status = FALSE, b64BitBlockCipher = FALSE, bCBCMode = FALSE, bHeaderBakRetry = FALSE; + int mountedVolCount = 0, modeOfOperation; + vector devices; + + VolumePassword.Length = 0; + mountOptions = defaultMountOptions; + bPrebootPasswordDlgMode = FALSE; + + if (selDrive == -1) + selDrive = 0; + + ResetWrongPwdRetryCount (); + + MultipleMountOperationInProgress = TRUE; + + do + { + if (!bHeaderBakRetry) + { + if (!CmdVolumePasswordValid && bPasswordPrompt) + { + PasswordDlgVolume[0] = '\0'; + if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, TRUE)) + goto ret; + } + else if (CmdVolumePasswordValid) + { + bPasswordPrompt = FALSE; + VolumePassword = CmdVolumePassword; + } + + WaitCursor(); + + if (FirstCmdKeyFile) + KeyFilesApply (&VolumePassword, FirstCmdKeyFile); + else if (KeyFilesEnable) + KeyFilesApply (&VolumePassword, FirstKeyFile); + + } + + if (devices.empty()) + devices = GetAvailableHostDevices (true, false, true, true); + foreach (const HostDevice &drive, devices) + { + vector partitions = drive.Partitions; + partitions.insert (partitions.begin(), drive); + + foreach (const HostDevice &device, partitions) + { + char szFileName[TC_MAX_PATH]; + strcpy_s (szFileName, sizeof (szFileName), device.Path.c_str()); + BOOL mounted = IsMountedVolume (szFileName); + + // Skip other partitions of the disk if partition0 (whole disk) is mounted + if (!device.IsPartition && mounted) + break; + + if (device.Floppy) + break; + + if (device.HasUnencryptedFilesystem && !mountOptions.UseBackupHeader && !bHeaderBakRetry) + continue; + + if (!mounted) + { + int nDosDriveNo; + + while (LOWORD (GetItemLong (driveList, selDrive)) != 0xffff) + { + if(LOWORD (GetItemLong (driveList, selDrive)) != TC_MLIST_ITEM_FREE) + { + selDrive++; + continue; + } + nDosDriveNo = HIWORD(GetItemLong (driveList, selDrive)) - 'A'; + break; + } + + if (LOWORD (GetItemLong (driveList, selDrive)) == 0xffff) + goto ret; + + // First try user password then cached passwords + if ((mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, TRUE, FALSE)) > 0 + || (mounted = MountVolume (hwndDlg, nDosDriveNo, szFileName, NULL, bCacheInDriver, bForceMount, &mountOptions, TRUE, FALSE)) > 0) + { + // A volume has been successfully mounted + + ResetWrongPwdRetryCount (); + + if (mounted == 2) + shared = TRUE; + + LoadDriveLetters (driveList, (HIWORD (GetItemLong (GetDlgItem (hwndDlg, IDC_DRIVELIST), selDrive)))); + selDrive++; + + if (bExplore) + { + WaitCursor(); + OpenVolumeExplorerWindow (nDosDriveNo); + NormalCursor(); + } + + if (bBeep) + MessageBeep (0xFFFFFFFF); + + status = TRUE; + + // Check for deprecated CBC mode + modeOfOperation = GetModeOfOperationByDriveNo (nDosDriveNo); + bCBCMode = (modeOfOperation == CBC || modeOfOperation == OUTER_CBC); + + if (GetCipherBlockSizeByDriveNo(nDosDriveNo) == 64) + b64BitBlockCipher = TRUE; + + mountedVolCount++; + + // Skip other partitions of the disk if partition0 (whole disk) has been mounted + if (!device.IsPartition) + break; + } + } + } + } + + if (mountedVolCount < 1) + { + // Failed to mount any volume + + IncreaseWrongPwdRetryCount (1); + + if (WrongPwdRetryCountOverLimit () + && !mountOptions.UseBackupHeader + && !bHeaderBakRetry) + { + // Retry using embedded header backup (if any) + mountOptions.UseBackupHeader = TRUE; + bHeaderBakRetry = TRUE; + } + else if (bHeaderBakRetry) + { + mountOptions.UseBackupHeader = defaultMountOptions.UseBackupHeader; + bHeaderBakRetry = FALSE; + } + + if (!Silent && !bHeaderBakRetry) + { + WCHAR szTmp[4096]; + + swprintf (szTmp, GetString (KeyFilesEnable || FirstCmdKeyFile ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT")); + if (CheckCapsLock (hwndDlg, TRUE)) + wcscat (szTmp, GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); + + MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONWARNING); + } + } + else if (bHeaderBakRetry) + { + // We have successfully mounted a volume using the header backup embedded in the volume (the header is damaged) + mountOptions.UseBackupHeader = defaultMountOptions.UseBackupHeader; + bHeaderBakRetry = FALSE; + + if (!Silent) + Warning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK"); + } + + if (!bHeaderBakRetry) + { + burn (&VolumePassword, sizeof (VolumePassword)); + burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); + } + + } while (bPasswordPrompt && mountedVolCount < 1); + + /* One or more volumes successfully mounted */ + + ResetWrongPwdRetryCount (); + + if (shared) + Warning ("DEVICE_IN_USE_INFO"); + + if (mountOptions.ProtectHiddenVolume) + { + if (mountedVolCount > 1) + Info ("HIDVOL_PROT_WARN_AFTER_MOUNT_PLURAL"); + else if (mountedVolCount == 1) + Info ("HIDVOL_PROT_WARN_AFTER_MOUNT"); + } + + // Check for deprecated CBC mode + if (bCBCMode) + Warning("WARN_CBC_MODE"); + + // Check for deprecated 64-bit-block ciphers + if (b64BitBlockCipher) + Warning("WARN_64_BIT_BLOCK_CIPHER"); + + // Check for legacy non-ASCII passwords + if (!KeyFilesEnable + && !FirstCmdKeyFile + && mountedVolCount > 0 + && !CheckPasswordCharEncoding (NULL, &VolumePassword)) + Warning ("UNSUPPORTED_CHARS_IN_PWD_RECOM"); + + if (status && CloseSecurityTokenSessionsAfterMount) + SecurityToken::CloseAllSessions(); + +ret: + MultipleMountOperationInProgress = FALSE; + + burn (&VolumePassword, sizeof (VolumePassword)); + burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); + + mountOptions.UseBackupHeader = defaultMountOptions.UseBackupHeader; + + RestoreDefaultKeyFilesParam (); + + if (UsePreferences) + bCacheInDriver = bCacheInDriverDefault; + + EnableDisableButtons (hwndDlg); + + NormalCursor(); + + return status; +} + +static void ChangePassword (HWND hwndDlg) +{ + int result; + + GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, sizeof (szFileName)); + if (IsMountedVolume (szFileName)) + { + Warning (pwdChangeDlgMode == PCDM_CHANGE_PKCS5_PRF ? "MOUNTED_NO_PKCS5_PRF_CHANGE" : "MOUNTED_NOPWCHANGE"); + return; + } + + if (!VolumePathExists (szFileName)) + { + handleWin32Error (hwndDlg); + return; + } + + bSysEncPwdChangeDlgMode = FALSE; + + result = DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_PASSWORDCHANGE_DLG), hwndDlg, + (DLGPROC) PasswordChangeDlgProc); + + if (result == IDOK) + { + switch (pwdChangeDlgMode) + { + case PCDM_CHANGE_PKCS5_PRF: + Info ("PKCS5_PRF_CHANGED"); + break; + + case PCDM_ADD_REMOVE_VOL_KEYFILES: + case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: + Info ("KEYFILE_CHANGED"); + break; + + case PCDM_CHANGE_PASSWORD: + default: + Info ("PASSWORD_CHANGED"); + } + } +} + +// Change password of the system partition/drive +static void ChangeSysEncPassword (HWND hwndDlg, BOOL bOnlyChangeKDF) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + if (!BootEncStatus.DriveEncrypted + && !BootEncStatus.DriveMounted + && !BootEncStatus.VolumeHeaderPresent + && !SysEncryptionOrDecryptionRequired ()) + { + Warning ("SYS_DRIVE_NOT_ENCRYPTED"); + return; + } + + if (SysEncryptionOrDecryptionRequired () + || BootEncStatus.SetupInProgress) + { + Warning ("SYSTEM_ENCRYPTION_NOT_COMPLETED"); + return; + } + + if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption + { + sprintf (OrigKeyboardLayout, "%08X", (DWORD) GetKeyboardLayout (NULL) & 0xFFFF); + + bSysEncPwdChangeDlgMode = TRUE; + + if (bOnlyChangeKDF) + pwdChangeDlgMode = PCDM_CHANGE_PKCS5_PRF; + else + pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; + + + if (DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_PASSWORDCHANGE_DLG), hwndDlg, + (DLGPROC) PasswordChangeDlgProc) == IDOK) + { + switch (pwdChangeDlgMode) + { + case PCDM_CHANGE_PKCS5_PRF: + Info ("PKCS5_PRF_CHANGED"); + + if (!IsHiddenOSRunning()) + { + if (AskWarnYesNo ("SYS_HKD_ALGO_CHANGED_ASK_RESCUE_DISK") == IDYES) + CreateRescueDisk (); + } + + break; + + case PCDM_ADD_REMOVE_VOL_KEYFILES: + case PCDM_REMOVE_ALL_KEYFILES_FROM_VOL: + // NOP - Keyfiles are not supported for system encryption + break; + + case PCDM_CHANGE_PASSWORD: + default: + Info ("PASSWORD_CHANGED"); + + if (!IsHiddenOSRunning()) + { + if (AskWarnYesNo ("SYS_PASSWORD_CHANGED_ASK_RESCUE_DISK") == IDYES) + CreateRescueDisk (); + } + } + } + + bSysEncPwdChangeDlgMode = FALSE; + + if (bKeyboardLayoutChanged) + { + // Restore the original keyboard layout + if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL) + Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT"); + else + bKeyboardLayoutChanged = FALSE; + } + + bKeybLayoutAltKeyWarningShown = FALSE; + + CloseSysEncMutex (); + } + else + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); +} + +// Initiates or resumes encryption of the system partition/drive +static void EncryptSystemDevice (void) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + if (!BootEncStatus.DriveEncrypted + && !BootEncStatus.DriveMounted + && !SysEncryptionOrDecryptionRequired ()) + { + // System partition/drive is not encrypted (nothing to resume). Initiate the process. + + if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption + { + LaunchVolCreationWizard (MainDlg, "/sysenc"); + } + else + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + + return; + } + else if (SysEncryptionOrDecryptionRequired ()) + { + // System partition/drive encryption already initiated but is incomplete -- attempt to resume the process. + // Note that this also covers the pretest phase and paused decryption (reverses decrypting and starts encrypting) + + if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption + { + LaunchVolCreationWizard (MainDlg, "/sysenc"); + } + else + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); + } + else if (SysDriveOrPartitionFullyEncrypted (FALSE)) + { + // System partition/drive appears to be fully encrypted + Info ("SYS_PARTITION_OR_DRIVE_APPEARS_FULLY_ENCRYPTED"); + return; + } +} + +// Initiates decryption of the system partition/drive +static void DecryptSystemDevice (void) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + if (!BootEncStatus.DriveEncrypted + && !BootEncStatus.DriveMounted + && !BootEncStatus.DeviceFilterActive + && !BootEncStatus.VolumeHeaderPresent + && !SysEncryptionOrDecryptionRequired ()) + { + Warning ("SYS_DRIVE_NOT_ENCRYPTED"); + return; + } + + if (IsHiddenOSRunning()) + { + Warning ("CANNOT_DECRYPT_HIDDEN_OS"); + return; + } + + if (AskNoYes ("CONFIRM_DECRYPT_SYS_DEVICE") == IDNO) + return; + + if (AskWarnNoYes ("CONFIRM_DECRYPT_SYS_DEVICE_CAUTION") == IDNO) + return; + + if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption + { + try + { + // User-mode app may have crashed and its mutex may have gotten lost, so we need to check the driver status too + if (BootEncStatus.SetupInProgress) + { + int attempts = 20; + + BootEncObj->AbortSetup (); + while (BootEncStatus.SetupInProgress && attempts > 0) + { + Sleep (100); + BootEncStatus = BootEncObj->GetStatus(); + attempts--; + WaitCursor(); + } + } + } + catch (Exception &e) + { + e.Show (MainDlg); + } + NormalCursor (); + + if (BootEncStatus.SetupInProgress) + { + CloseSysEncMutex (); + Error ("SYS_ENCRYPTION_OR_DECRYPTION_IN_PROGRESS"); + return; + } + + CloseSysEncMutex (); + LaunchVolCreationWizard (MainDlg, "/dsysenc"); + } + else + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); +} + +// Initiates the process of creation of a hidden operating system +static void CreateHiddenOS (void) +{ + + // Display brief information as to what a hidden operating system is and what it's good for. This needs to be + // done, because if the system partition/drive is currently encrypted, the wizard will not display any + // such information, but will exit (displaying only an error meessage). + Info("HIDDEN_OS_PREINFO"); + + LaunchVolCreationWizard (MainDlg, "/isysenc"); +} + +// Blindly attempts (without any checks) to instruct the wizard to resume whatever system encryption process +// had been interrupted or not started but scheduled or exptected to start. +static void ResumeInterruptedSysEncProcess (void) +{ + if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption + { + LaunchVolCreationWizard (MainDlg, "/csysenc"); + } + else + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); +} + +void CreateRescueDisk (void) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + if (IsHiddenOSRunning()) + { + Warning ("CANNOT_CREATE_RESCUE_DISK_ON_HIDDEN_OS"); + return; + } + + if (!BootEncStatus.DriveEncrypted + && !BootEncStatus.DriveMounted + && !BootEncStatus.VolumeHeaderPresent + && !SysEncryptionOrDecryptionRequired ()) + { + Warning ("SYS_DRIVE_NOT_ENCRYPTED"); + return; + } + + if (SysEncryptionOrDecryptionRequired () + || BootEncStatus.SetupInProgress) + { + Warning ("SYSTEM_ENCRYPTION_NOT_COMPLETED"); + return; + } + + if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption + { + try + { + wchar_t szTmp [8096]; + char szRescueDiskISO [TC_MAX_PATH+1]; + + if (AskOkCancel ("RESCUE_DISK_NON_WIZARD_CREATION_SELECT_PATH") != IDOK) + { + CloseSysEncMutex (); + return; + } + + char initialDir[MAX_PATH]; + SHGetFolderPath (NULL, CSIDL_MYDOCUMENTS, NULL, 0, initialDir); + + if (!BrowseFilesInDir (MainDlg, "OPEN_TITLE", initialDir, szRescueDiskISO, FALSE, TRUE, NULL, L"TrueCrypt Rescue Disk.iso", L"iso")) + { + CloseSysEncMutex (); + return; + } + + WaitCursor(); + BootEncObj->CreateRescueIsoImage (false, szRescueDiskISO); + + _snwprintf (szTmp, sizeof szTmp / 2, + GetString (IsWindowsIsoBurnerAvailable() ? "RESCUE_DISK_NON_WIZARD_CREATION_WIN_ISOBURN" : "RESCUE_DISK_NON_WIZARD_CREATION_BURN"), + szRescueDiskISO); + + if (IsWindowsIsoBurnerAvailable()) + { + if (AskYesNoString (szTmp) == IDYES) + LaunchWindowsIsoBurner (MainDlg, szRescueDiskISO); + } + else + InfoDirect (szTmp); + } + catch (Exception &e) + { + e.Show (MainDlg); + Error ("ERROR_CREATING_RESCUE_DISK"); + } + CloseSysEncMutex (); + + NormalCursor (); + } + else + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); +} + +static void VerifyRescueDisk (void) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + if (!BootEncStatus.DriveEncrypted + && !BootEncStatus.DriveMounted + && !BootEncStatus.VolumeHeaderPresent + && !SysEncryptionOrDecryptionRequired ()) + { + Warning ("SYS_DRIVE_NOT_ENCRYPTED"); + return; + } + + if (SysEncryptionOrDecryptionRequired () + || BootEncStatus.SetupInProgress) + { + Warning ("SYSTEM_ENCRYPTION_NOT_COMPLETED"); + return; + } + + if (CreateSysEncMutex ()) // If no instance of the wizard is currently taking care of system encryption + { + try + { + if (AskOkCancel ("RESCUE_DISK_NON_WIZARD_CHECK_INSERT") != IDOK) + { + CloseSysEncMutex (); + return; + } + + // Create a temporary up-to-date rescue disk image in RAM (with it the CD/DVD content will be compared) + BootEncObj->CreateRescueIsoImage (false, ""); + + WaitCursor(); + if (!BootEncObj->VerifyRescueDisk ()) + Error ("RESCUE_DISK_NON_WIZARD_CHECK_FAILED"); + else + Info ("RESCUE_DISK_NON_WIZARD_CHECK_PASSED"); + } + catch (Exception &e) + { + e.Show (MainDlg); + Error ("RESCUE_DISK_NON_WIZARD_CHECK_FAILED"); + } + CloseSysEncMutex (); + + NormalCursor (); + } + else + Warning ("SYSTEM_ENCRYPTION_IN_PROGRESS_ELSEWHERE"); +} + +static void ShowSystemEncryptionStatus (void) +{ + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + } + + if (GetAsyncKeyState (VK_SHIFT) < 0 && GetAsyncKeyState (VK_CONTROL) < 0) + { + // Ctrl+Shift held (for debugging purposes) + + DebugMsgBox ("Debugging information for system encryption:\n\nDeviceFilterActive: %d\nBootLoaderVersion: %x\nSetupInProgress: %d\nSetupMode: %d\nVolumeHeaderPresent: %d\nDriveMounted: %d\nDriveEncrypted: %d\n" + "HiddenSystem: %d\nHiddenSystemPartitionStart: %I64d\n" + "ConfiguredEncryptedAreaStart: %I64d\nConfiguredEncryptedAreaEnd: %I64d\nEncryptedAreaStart: %I64d\nEncryptedAreaEnd: %I64d\nEncrypted: %I64d%%", + BootEncStatus.DeviceFilterActive, + BootEncStatus.BootLoaderVersion, + BootEncStatus.SetupInProgress, + BootEncStatus.SetupMode, + BootEncStatus.VolumeHeaderPresent, + BootEncStatus.DriveMounted, + BootEncStatus.DriveEncrypted, + BootEncStatus.HiddenSystem ? 1 : 0, + BootEncStatus.HiddenSystemPartitionStart, + BootEncStatus.ConfiguredEncryptedAreaStart, + BootEncStatus.ConfiguredEncryptedAreaEnd, + BootEncStatus.EncryptedAreaStart, + BootEncStatus.EncryptedAreaEnd, + !BootEncStatus.DriveEncrypted ? 0 : (BootEncStatus.EncryptedAreaEnd + 1 - BootEncStatus.EncryptedAreaStart) * 100I64 / (BootEncStatus.ConfiguredEncryptedAreaEnd + 1 - BootEncStatus.ConfiguredEncryptedAreaStart)); + } + + if (!BootEncStatus.DriveEncrypted && !BootEncStatus.DriveMounted) + { + Info ("SYS_DRIVE_NOT_ENCRYPTED"); + return; + } + + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_VOLUME_PROPERTIES), MainDlg, + (DLGPROC) VolumePropertiesDlgProc, (LPARAM) TRUE); + +} + +static void ResumeInterruptedNonSysInplaceEncProcess (void) +{ + // IMPORTANT: This function must not check any config files! Otherwise, if a config file was lost or corrupt, + // the user would not be able resume encryption and the data on the volume would be inaccessible. + + LaunchVolCreationWizard (MainDlg, "/zinplace"); +} + +static BOOL SelectContainer (HWND hwndDlg) +{ + if (BrowseFiles (hwndDlg, "OPEN_VOL_TITLE", szFileName, bHistory, FALSE, NULL) == FALSE) + return FALSE; + + AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); + EnableDisableButtons (hwndDlg); + SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + return TRUE; +} + +static BOOL SelectPartition (HWND hwndDlg) +{ + int nResult = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RAWDEVICES_DLG), hwndDlg, + (DLGPROC) RawDevicesDlgProc, (LPARAM) & szFileName[0]); + if (nResult == IDOK) + { + AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); + EnableDisableButtons (hwndDlg); + SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + return TRUE; + } + + return FALSE; +} + +static void WipeCache (HWND hwndDlg, BOOL silent) +{ + DWORD dwResult; + BOOL bResult; + + bResult = DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + if (hwndDlg == NULL) + return; + + if (bResult == FALSE) + handleWin32Error (hwndDlg); + else + { + EnableDisableButtons (hwndDlg); + + if (!silent) + Info ("PASSWORD_CACHE_WIPED"); + } +} + +static void Benchmark (HWND hwndDlg) +{ + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_BENCHMARK_DLG), hwndDlg, + (DLGPROC) BenchmarkDlgProc, (LPARAM) NULL); +} + + +static BOOL CheckMountList () +{ + MOUNT_LIST_STRUCT current; + GetMountList (¤t); + static BootEncryptionStatus newBootEncStatus; + + if (LastKnownLogicalDrives != GetLogicalDrives() + || memcmp (&LastKnownMountList, ¤t, sizeof (current)) != 0) + { + char selDrive; + + WaitCursor (); + LastKnownMountList = current; + + selDrive = (char) HIWORD (GetSelectedLong (GetDlgItem (MainDlg, IDC_DRIVELIST))); + LoadDriveLetters (GetDlgItem (MainDlg, IDC_DRIVELIST), 0); + NormalCursor (); + + if ((current.ulMountedDrives & (1 << (selDrive - 'A'))) == 0 && !IsDriveAvailable (selDrive - 'A')) + { + nSelectedDriveIndex = -1; + return FALSE; + } + + if (nSelectedDriveIndex >= 0) + { + SelectItem (GetDlgItem (MainDlg, IDC_DRIVELIST),selDrive); + + if(nSelectedDriveIndex > SendMessage (GetDlgItem (MainDlg, IDC_DRIVELIST), LVM_GETITEMCOUNT, 0, 0)/2) + SendMessage(GetDlgItem (MainDlg, IDC_DRIVELIST), LVM_SCROLL, 0, 1000); + } + } + + try + { + newBootEncStatus = BootEncObj->GetStatus(); + + if (newBootEncStatus.SetupInProgress != RecentBootEncStatus.SetupInProgress + || newBootEncStatus.EncryptedAreaEnd != RecentBootEncStatus.EncryptedAreaEnd + || newBootEncStatus.DriveEncrypted != RecentBootEncStatus.DriveEncrypted + || newBootEncStatus.DriveMounted != RecentBootEncStatus.DriveMounted + || newBootEncStatus.SetupMode != RecentBootEncStatus.SetupMode + || newBootEncStatus.EncryptedAreaStart != RecentBootEncStatus.EncryptedAreaStart) + { + /* System encryption status change */ + + char selDrive; + int driveLetterToRefresh; + + if (RecentBootEncStatus.DriveMounted == newBootEncStatus.DriveMounted) // If an icon (and whole new line) for a system device isn't to be added/removed + { + // Partial refresh + if (WholeSysDriveEncryption (TRUE)) + { + // System drive (not just partition) + driveLetterToRefresh = ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER; + } + else + { + // System partition + driveLetterToRefresh = GetSystemDriveLetter (); + } + } + else + { + // Full rebuild of the mount list + driveLetterToRefresh = 0; + } + + selDrive = (char) HIWORD (GetSelectedLong (GetDlgItem (MainDlg, IDC_DRIVELIST))); + LoadDriveLetters (GetDlgItem (MainDlg, IDC_DRIVELIST), driveLetterToRefresh); + + RecentBootEncStatus = newBootEncStatus; + + if ((current.ulMountedDrives & (1 << (selDrive - 'A'))) == 0 && !IsDriveAvailable (selDrive - 'A')) + { + nSelectedDriveIndex = -1; + } + + if (nSelectedDriveIndex >= 0) + { + SelectItem (GetDlgItem (MainDlg, IDC_DRIVELIST),selDrive); + } + } + + /* Miscellaneous notifications */ + + // Hibernation prevention notifications + if (newBootEncStatus.HibernationPreventionCount != RecentBootEncStatus.HibernationPreventionCount + && !bHibernationPreventionNotified) + { + bHibernationPreventionNotified = TRUE; + RecentBootEncStatus.HibernationPreventionCount = newBootEncStatus.HibernationPreventionCount; + + if (IsHiddenOSRunning() && BootEncObj->GetSystemDriveConfiguration().ExtraBootPartitionPresent) + WarningTopMost ("HIDDEN_OS_HIBERNATION_PREVENTED"); + else + WarningTopMost ("SYS_ENC_HIBERNATION_PREVENTED"); + } + + // Write mode prevention (hidden OS leak protection) + if (IsHiddenOSRunning()) + { + if (newBootEncStatus.HiddenSysLeakProtectionCount != RecentBootEncStatus.HiddenSysLeakProtectionCount + && !bHiddenSysLeakProtNotifiedDuringSession) + { + bHiddenSysLeakProtNotifiedDuringSession = TRUE; + + switch (HiddenSysLeakProtectionNotificationStatus) + { + case TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_COMPACT: + { + char *tmp[] = {0, "HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO", "SHOW_MORE_INFORMATION", "DO_NOT_SHOW_THIS_AGAIN", "CONTINUE", 0}; + switch (AskMultiChoice ((void **) tmp, FALSE)) + { + case 1: + InfoDirect ((wstring (GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO")) + + L"\n\n" + + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION") + + L"\n\n\n" + + GetString ("DECOY_TO_HIDDEN_OS_DATA_TRANSFER_HOWTO")).c_str()); + break; + + case 2: + // No more warnings will be shown + if (ConfigBuffer == NULL) + { + // We need to load the config file because it is not done automatically when + // launched from the sys startup sequence (and SaveSettings would start by _loading_ + // the settings to cache). + LoadSettings (MainDlg); + } + HiddenSysLeakProtectionNotificationStatus = TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_DISABLED; + SaveSettings (MainDlg); + break; + + default: + // NOP + break; + } + } + break; + + case TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_DISABLED: + // NOP + break; + + case TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE: + default: + { + // First time warning -- include technical explanation + InfoDirect ((wstring (GetString ("HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO")) + + L"\n\n" + + GetString ("HIDDEN_OS_WRITE_PROTECTION_EXPLANATION") + + L"\n\n\n" + + GetString ("DECOY_TO_HIDDEN_OS_DATA_TRANSFER_HOWTO")).c_str()); + + // Further warnings will not include the explanation (and will allow disabling) + + if (ConfigBuffer == NULL) + { + // We need to load the config file because it is not done automatically when + // launched from the sys startup sequence (and SaveSettings would start by _loading_ + // the settings to cache). + LoadSettings (MainDlg); + } + HiddenSysLeakProtectionNotificationStatus = TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_COMPACT; + SaveSettings (MainDlg); + } + break; + } + } + } + } + catch (...) + { + // NOP + } + + return TRUE; +} + + +/* Except in response to the WM_INITDIALOG and WM_ENDSESSION messages, the dialog box procedure + should return nonzero if it processes a message, and zero if it does not. */ +BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static UINT taskBarCreatedMsg; + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + DWORD mPos; + + switch (uMsg) + { + case WM_HOTKEY: + + HandleHotKey (hwndDlg, wParam); + return 1; + + case WM_INITDIALOG: + { + int exitCode = 0; + int modeOfOperation; + + MainDlg = hwndDlg; + + if (IsTrueCryptInstallerRunning()) + AbortProcess ("TC_INSTALLER_IS_RUNNING"); + + // Set critical default options in case UsePreferences is false + bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = TRUE; + + ResetWrongPwdRetryCount (); + + ExtractCommandLine (hwndDlg, (char *) lParam); + + if (ComServerMode) + { + InitDialog (hwndDlg); + + if (!ComServerMain ()) + { + handleWin32Error (hwndDlg); + exit (1); + } + exit (0); + } + + try + { + BootEncStatus = BootEncObj->GetStatus(); + RecentBootEncStatus = BootEncStatus; + } + catch (...) + { + // NOP + } + + if (UsePreferences) + { + // General preferences + LoadSettings (hwndDlg); + + // Keyfiles + LoadDefaultKeyFilesParam (); + RestoreDefaultKeyFilesParam (); + } + + if (CmdMountOptionsValid) + mountOptions = CmdMountOptions; + + InitMainDialog (hwndDlg); + + if (IsHiddenOSRunning()) + { + try + { + if (BootEncObj->GetInstalledBootLoaderVersion() > VERSION_NUM) + Warning ("UPDATE_TC_IN_HIDDEN_OS_TOO"); + } + catch (...) { } + } + + // Automount + if (bAuto || (Quit && szFileName[0] != 0)) + { + // No drive letter specified on command line + if (commandLineDrive == 0) + szDriveLetter[0] = (char) GetFirstAvailableDrive () + 'A'; + + if (bAutoMountDevices) + { + defaultMountOptions = mountOptions; + if (FirstCmdKeyFile) + { + KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles = TRUE; + FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); + defaultKeyFilesParam.FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); + } + + if (!MountAllDevices (hwndDlg, !Silent && !CmdVolumePasswordValid && IsPasswordCacheEmpty())) + exitCode = 1; + } + + if (bAutoMountFavorites) + { + defaultMountOptions = mountOptions; + if (FirstCmdKeyFile) + { + KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles = TRUE; + FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); + defaultKeyFilesParam.FirstKeyFile = KeyFileCloneAll (FirstCmdKeyFile); + } + + if (!MountFavoriteVolumes (FALSE)) + exitCode = 1; + } + + if (szFileName[0] != 0 && !IsMountedVolume (szFileName)) + { + BOOL mounted; + + // Cached password + mounted = MountVolume (hwndDlg, szDriveLetter[0] - 'A', szFileName, NULL, bCacheInDriver, bForceMount, &mountOptions, Silent, FALSE); + + // Command line password or keyfiles + if (!mounted && (CmdVolumePassword.Length != 0 || FirstCmdKeyFile)) + { + BOOL reportBadPasswd = CmdVolumePassword.Length > 0; + + if (FirstCmdKeyFile) + KeyFilesApply (&CmdVolumePassword, FirstCmdKeyFile); + + mounted = MountVolume (hwndDlg, szDriveLetter[0] - 'A', + szFileName, &CmdVolumePassword, bCacheInDriver, bForceMount, + &mountOptions, Silent, reportBadPasswd); + + burn (&CmdVolumePassword, sizeof (CmdVolumePassword)); + } + + if (FirstCmdKeyFile) + { + FirstKeyFile = FirstCmdKeyFile; + KeyFilesEnable = TRUE; + } + + // Ask user for password + while (!mounted && !Silent) + { + VolumePassword.Length = 0; + + strcpy (PasswordDlgVolume, szFileName); + if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, TRUE)) + break; + + WaitCursor (); + + if (KeyFilesEnable && FirstKeyFile) + KeyFilesApply (&VolumePassword, FirstKeyFile); + + mounted = MountVolume (hwndDlg, szDriveLetter[0] - 'A', szFileName, &VolumePassword, bCacheInDriver, bForceMount, &mountOptions, FALSE, TRUE); + + burn (&VolumePassword, sizeof (VolumePassword)); + burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword)); + + NormalCursor (); + } + + if (UsePreferences) + { + RestoreDefaultKeyFilesParam (); + bCacheInDriver = bCacheInDriverDefault; + } + + if (mounted > 0) + { + if (bBeep) + MessageBeep (0xFFFFFFFF); + + if (bExplore) + OpenVolumeExplorerWindow (szDriveLetter[0] - 'A'); + + RefreshMainDlg(hwndDlg); + + if(!Silent) + { + // Check for deprecated CBC mode + modeOfOperation = GetModeOfOperationByDriveNo (szDriveLetter[0] - 'A'); + if (modeOfOperation == CBC || modeOfOperation == OUTER_CBC) + Warning("WARN_CBC_MODE"); + + // Check for deprecated 64-bit-block ciphers + if (GetCipherBlockSizeByDriveNo (szDriveLetter[0] - 'A') == 64) + Warning("WARN_64_BIT_BLOCK_CIPHER"); + + // Check for problematic file extensions (exe, dll, sys) + if (CheckFileExtension (szFileName)) + Warning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); + } + } + else + exitCode = 1; + } + else if (bExplore && GetMountedVolumeDriveNo (szFileName) != -1) + OpenVolumeExplorerWindow (GetMountedVolumeDriveNo (szFileName)); + else if (szFileName[0] != 0 && IsMountedVolume (szFileName)) + Warning ("VOL_ALREADY_MOUNTED"); + + if (!Quit) + RefreshMainDlg(hwndDlg); + } + + // Wipe cache + if (bWipe) + WipeCache (hwndDlg, Silent); + + // Wipe command line password + if (CmdVolumePassword.Length != 0) + { + burn (&CmdVolumePassword, sizeof (CmdVolumePassword)); + CmdVolumePassword.Length = 0; + } + + // Wipe command line keyfiles + if (FirstCmdKeyFile) + { + if (defaultKeyFilesParam.FirstKeyFile) + KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); + + defaultKeyFilesParam.EnableKeyFiles = FALSE; + + if (!Quit) + { + LoadSettings (hwndDlg); + LoadDefaultKeyFilesParam (); + RestoreDefaultKeyFilesParam (); + } + } + + // Dismount + if (cmdUnmountDrive > 0) + { + if (!Dismount (hwndDlg, (char)toupper(szDriveLetter[0]) - 'A')) + exitCode = 1; + } + else if (cmdUnmountDrive == -1) + { + if (!DismountAll (hwndDlg, bForceUnmount, !Silent, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY)) + exitCode = 1; + } + + // TaskBar icon + if (bEnableBkgTask) + TaskBarIconAdd (hwndDlg); + + // Quit + if (Quit) + { + if (TaskBarIconMutex == NULL) + exit (exitCode); + + MainWindowHidden = TRUE; + + LoadSettings (hwndDlg); + LoadDefaultKeyFilesParam (); + RestoreDefaultKeyFilesParam (); + + if (!bEnableBkgTask) + { + if (TaskBarIconMutex) + TaskBarIconRemove (hwndDlg); + exit (exitCode); + } + } + + // No command line arguments or only /volume => bring active instance + // to foreground if available + if (NoCmdLineArgs == 0 || (CmdLineVolumeSpecified && NoCmdLineArgs <= 2)) + { + HWND h = hwndDlg; + EnumWindows (FindTCWindowEnum, (LPARAM) &h); + + if (h != hwndDlg + && (!IsAdmin() || (GetWindowLongPtr (h, DWLP_USER) & TC_MAIN_WINDOW_FLAG_ADMIN_PRIVILEGES) != 0)) + { + if (CmdLineVolumeSpecified) + { + COPYDATASTRUCT cd; + memcpy (&cd.dwData, WM_COPY_SET_VOLUME_NAME, 4); + cd.lpData = szFileName; + cd.cbData = strlen (szFileName) + 1; + + SendMessage (h, WM_COPYDATA, (WPARAM)hwndDlg, (LPARAM)&cd); + } + + SendMessage (h, TC_APPMSG_MOUNT_SHOW_WINDOW, 0, 0); + + ShowWindow (h, SW_SHOW); + SetForegroundWindow (h); + + if (TaskBarIconMutex == NULL) + exit (0); + } + } + + // Register hot keys + if (!RegisterAllHotkeys (hwndDlg, Hotkeys) + && TaskBarIconMutex != NULL) // Warn only if we are the first instance of TrueCrypt + Warning("HOTKEY_REGISTRATION_ERROR"); + + Silent = FALSE; + + GetMountList (&LastKnownMountList); + SetTimer (hwndDlg, TIMER_ID_MAIN, TIMER_INTERVAL_MAIN, NULL); + + taskBarCreatedMsg = RegisterWindowMessage ("TaskbarCreated"); + + SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + + DWORD bytesOut; + int dirty; + if (DeviceIoControl (hDriver, TC_IOCTL_IS_SYSTEM_FAVORITE_VOLUME_DIRTY, NULL, 0, &dirty, sizeof (dirty), &bytesOut, NULL) && dirty) + WarningTopMost ("SYS_FAVORITE_VOLUME_DIRTY"); + + /* Check system encryption status */ + + if (!Quit) // Do not care about system encryption or in-place encryption if we were launched from the system startup sequence (the wizard was added to it too). + { + if (SysEncryptionOrDecryptionRequired ()) + { + if (!MutexExistsOnSystem (TC_MUTEX_NAME_SYSENC)) // If no instance of the wizard is currently taking care of system encryption + { + // We shouldn't block the mutex at this point + + if (SystemEncryptionStatus == SYSENC_STATUS_PRETEST + || AskWarnYesNo ("SYSTEM_ENCRYPTION_RESUME_PROMPT") == IDYES) + { + // The wizard was not launched during the system startup seq, or the user may have forgotten + // to resume the encryption/decryption process. + + + LaunchVolCreationWizard (hwndDlg, "/csysenc"); + } + } + } + + if (bInPlaceEncNonSysPending && !NonSysInplaceEncInProgressElsewhere()) + { + if (AskNonSysInPlaceEncryptionResume() == IDYES) + ResumeInterruptedNonSysInplaceEncProcess (); + } + } + + DoPostInstallTasks (); + ResetCurrentDirectory (); + } + return 0; + + case WM_WINDOWPOSCHANGING: + if (MainWindowHidden) + { + // Prevent window from being shown + PWINDOWPOS wp = (PWINDOWPOS)lParam; + wp->flags &= ~SWP_SHOWWINDOW; + return 0; + } + return 1; + + case WM_SYSCOMMAND: + if (lw == IDC_ABOUT) + { + DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc); + return 1; + } + return 0; + + case WM_HELP: + OpenPageHelp (hwndDlg, 0); + return 1; + + case WM_ENDSESSION: + if (TaskBarIconMutex != NULL) + { + if (bDismountOnLogOff) + { + // Auto-dismount when user logs off + DWORD dwResult; + + if (bWipeCacheOnAutoDismount) + DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + + DismountAll (hwndDlg, bForceAutoDismount, FALSE, 1, 0); + } + + TaskBarIconRemove (hwndDlg); + } + EndMainDlg (hwndDlg); + localcleanup (); + return 0; + + case WM_POWERBROADCAST: + if (wParam == PBT_APMSUSPEND + && TaskBarIconMutex != NULL && bDismountOnPowerSaving) + { + // Auto-dismount when entering power-saving mode + DWORD dwResult; + + if (bWipeCacheOnAutoDismount) + { + DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + SecurityToken::CloseAllSessions(); + } + + DismountAll (hwndDlg, bForceAutoDismount, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); + } + return 0; + + case WM_TIMER: + { + // Check mount list and update GUI if needed + CheckMountList (); + + // Cache status + if (IsPasswordCacheEmpty() == IsWindowEnabled (GetDlgItem (hwndDlg, IDC_WIPE_CACHE))) + EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_CACHE), !IsPasswordCacheEmpty()); + + if (TaskBarIconMutex != NULL) + { + // Idle auto-dismount + if (MaxVolumeIdleTime > 0) + DismountIdleVolumes (); + + // Screen saver auto-dismount + if (bDismountOnScreenSaver) + { + static BOOL previousState = FALSE; + BOOL running = FALSE; + SystemParametersInfo (SPI_GETSCREENSAVERRUNNING, 0, &running, 0); + + if (running && !previousState) + { + DWORD dwResult; + previousState = TRUE; + + if (bWipeCacheOnAutoDismount) + { + DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + SecurityToken::CloseAllSessions(); + } + + DismountAll (hwndDlg, bForceAutoDismount, FALSE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); + } + else + { + previousState = running; + } + } + } + + // Exit background process in non-install mode or if no volume mounted + // and no other instance active + if (LastKnownMountList.ulMountedDrives == 0 + && MainWindowHidden +#ifndef _DEBUG + && (bCloseBkgTaskWhenNoVolumes || IsNonInstallMode ()) +#endif + && !SysEncDeviceActive (TRUE) + && GetDriverRefCount () < 2) + { + TaskBarIconRemove (hwndDlg); + EndMainDlg (hwndDlg); + } + } + return 1; + + case TC_APPMSG_TASKBAR_ICON: + { + switch (lParam) + { + case WM_LBUTTONDOWN: + SetForegroundWindow (hwndDlg); + MainWindowHidden = FALSE; + ShowWindow (hwndDlg, SW_SHOW); + ShowWindow (hwndDlg, SW_RESTORE); + return 1; + + case WM_RBUTTONUP: + { + POINT pos; + HMENU popup = CreatePopupMenu (); + int sel, i, n; + + if (MainWindowHidden) + { + AppendMenuW (popup, MF_STRING, IDM_SHOW_HIDE, GetString ("SHOW_TC")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + } + else if (bEnableBkgTask + && (!(LastKnownMountList.ulMountedDrives == 0 + && (bCloseBkgTaskWhenNoVolumes || IsNonInstallMode ()) + && !SysEncDeviceActive (TRUE) + && GetDriverRefCount () < 2))) + { + AppendMenuW (popup, MF_STRING, IDM_SHOW_HIDE, GetString ("HIDE_TC")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + } + AppendMenuW (popup, MF_STRING, IDM_MOUNTALL, GetString ("IDC_MOUNTALL")); + AppendMenuW (popup, MF_STRING, IDM_MOUNT_FAVORITE_VOLUMES, GetString ("IDM_MOUNT_FAVORITE_VOLUMES")); + AppendMenuW (popup, MF_STRING, IDM_UNMOUNTALL, GetString ("IDM_UNMOUNTALL")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + + for (n = 0; n < 2; n++) + { + for (i = 0; i < 26; i++) + { + if (LastKnownMountList.ulMountedDrives & (1 << i)) + { + wchar_t s[1024]; + wchar_t *vol = (wchar_t *) LastKnownMountList.wszVolume[i]; + + if (wcsstr (vol, L"\\??\\")) vol += 4; + + wsprintfW (s, L"%s %c: (%s)", + GetString (n==0 ? "OPEN" : "DISMOUNT"), + i + L'A', + vol); + AppendMenuW (popup, MF_STRING, n*26 + TRAYICON_MENU_DRIVE_OFFSET + i, s); + } + } + if (LastKnownMountList.ulMountedDrives != 0) + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + } + + AppendMenuW (popup, MF_STRING, IDM_HELP, GetString ("MENU_HELP")); + AppendMenuW (popup, MF_STRING, IDM_HOMEPAGE_SYSTRAY, GetString ("HOMEPAGE")); + AppendMenuW (popup, MF_STRING, IDM_PREFERENCES, GetString ("IDM_PREFERENCES")); + AppendMenuW (popup, MF_STRING, IDM_ABOUT, GetString ("IDM_ABOUT")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDCANCEL, GetString ("EXIT")); + + GetCursorPos (&pos); + + SetForegroundWindow(hwndDlg); + + sel = TrackPopupMenu (popup, + TPM_RETURNCMD | TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON, + pos.x, + pos.y, + 0, + hwndDlg, + NULL); + + if (sel >= TRAYICON_MENU_DRIVE_OFFSET && sel < TRAYICON_MENU_DRIVE_OFFSET + 26) + { + OpenVolumeExplorerWindow (sel - TRAYICON_MENU_DRIVE_OFFSET); + } + else if (sel >= TRAYICON_MENU_DRIVE_OFFSET + 26 && sel < TRAYICON_MENU_DRIVE_OFFSET + 26*2) + { + if (CheckMountList ()) + Dismount (hwndDlg, sel - TRAYICON_MENU_DRIVE_OFFSET - 26); + } + else if (sel == IDM_SHOW_HIDE) + { + ChangeMainWindowVisibility (); + } + else if (sel == IDM_HOMEPAGE_SYSTRAY) + { + Applink ("home", TRUE, ""); + } + else if (sel == IDCANCEL) + { + if ((LastKnownMountList.ulMountedDrives == 0 + && !SysEncDeviceActive (TRUE)) + || AskWarnNoYes ("CONFIRM_EXIT") == IDYES) + { + // Close all other TC windows + EnumWindows (CloseTCWindowsEnum, 0); + + TaskBarIconRemove (hwndDlg); + SendMessage (hwndDlg, WM_COMMAND, sel, 0); + } + } + else + { + SendMessage (hwndDlg, WM_COMMAND, sel, 0); + } + + PostMessage(hwndDlg, WM_NULL, 0, 0); + DestroyMenu (popup); + } + return 1; + } + } + + return 0; + + case TC_APPMSG_CLOSE_BKG_TASK: + if (TaskBarIconMutex != NULL) + TaskBarIconRemove (hwndDlg); + + return 1; + + case TC_APPMSG_SYSENC_CONFIG_UPDATE: + LoadSysEncSettings (hwndDlg); + + // The wizard added TrueCrypt.exe to the system startup sequence or performed other operations that + // require us to update our cached settings. + LoadSettings (hwndDlg); + + return 1; + + case WM_DEVICECHANGE: + if (!IgnoreWmDeviceChange && wParam != DBT_DEVICEARRIVAL) + { + // Check if any host device has been removed and force dismount of volumes accordingly + PDEV_BROADCAST_HDR hdr = (PDEV_BROADCAST_HDR) lParam; + int m; + + GetMountList (&LastKnownMountList); + + if (wParam == DBT_DEVICEREMOVECOMPLETE && hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) + { + // File-hosted volumes + PDEV_BROADCAST_VOLUME vol = (PDEV_BROADCAST_VOLUME) lParam; + int i; + + for (i = 0; i < 26; i++) + { + if (vol->dbcv_unitmask & (1 << i)) + { + for (m = 0; m < 26; m++) + { + if (LastKnownMountList.ulMountedDrives & (1 << m)) + { + wchar_t *vol = (wchar_t *) LastKnownMountList.wszVolume[m]; + + if (wcsstr (vol, L"\\??\\") == vol) + vol += 4; + + if (vol[1] == L':' && i == (vol[0] - (vol[0] <= L'Z' ? L'A' : L'a'))) + UnmountVolume (hwndDlg, m, TRUE); + } + } + } + } + } + + // Device-hosted volumes + for (m = 0; m < 26; m++) + { + if (LastKnownMountList.ulMountedDrives & (1 << m)) + { + wchar_t *vol = (wchar_t *) LastKnownMountList.wszVolume[m]; + char volp[MAX_PATH]; + + if (wcsstr (vol, L"\\??\\") == vol) + vol += 4; + + _snprintf (volp, sizeof(volp), "%ls", vol); + + if (IsVolumeDeviceHosted (volp)) + { + OPEN_TEST_STRUCT ots; + + if (!OpenDevice (volp, &ots, FALSE)) + UnmountVolume (hwndDlg, m, TRUE); + } + } + } + return 1; + } + return 0; + + case WM_NOTIFY: + + if(wParam == IDC_DRIVELIST) + { + if (((LPNMHDR) lParam)->code == NM_CUSTOMDRAW) + { + int width = ListView_GetColumnWidth (GetDlgItem (hwndDlg, IDC_DRIVELIST), 1); + if (width != LastDriveListVolumeColumnWidth) + { + LastDriveListVolumeColumnWidth = width; + LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), 0); + } + return 0; + } + + /* Single click within drive list */ + if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED )) + { + nSelectedDriveIndex = ((LPNMLISTVIEW) lParam)->iItem; + EnableDisableButtons (hwndDlg); + return 1; + } + + /* Double click within drive list */ + if (((LPNMHDR) lParam)->code == LVN_ITEMACTIVATE) + { + int state = GetItemLong (GetDlgItem (hwndDlg, IDC_DRIVELIST), ((LPNMITEMACTIVATE)lParam)->iItem ); + nSelectedDriveIndex = ((LPNMITEMACTIVATE)lParam)->iItem; + if (LOWORD(state) == TC_MLIST_ITEM_NONSYS_VOL || LOWORD(state) == TC_MLIST_ITEM_SYS_PARTITION) + { + // Open explorer window for mounted volume + WaitCursor (); + OpenVolumeExplorerWindow (HIWORD(state) - 'A'); + NormalCursor (); + } + else if (LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == TC_MLIST_ITEM_FREE) + { + mountOptions = defaultMountOptions; + bPrebootPasswordDlgMode = FALSE; + + if (GetAsyncKeyState (VK_CONTROL) < 0) + { + if (IDCANCEL == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg, + (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions)) + return 1; + + if (mountOptions.ProtectHiddenVolume && hidVolProtKeyFilesParam.EnableKeyFiles) + KeyFilesApply (&mountOptions.ProtectedHidVolPassword, hidVolProtKeyFilesParam.FirstKeyFile); + } + + if (CheckMountList ()) + Mount (hwndDlg, 0, 0); + } + return 1; + } + + /* Right click and drag&drop operations */ + + switch (((NM_LISTVIEW *) lParam)->hdr.code) + { + case NM_RCLICK: + case LVN_BEGINRDRAG: + /* If the mouse was moving while the right mouse button is pressed, popup menu would + not open, because drag&drop operation would be initiated. Therefore, we're handling + RMB drag-and-drop operations as well. */ + { + + /* Drive list context menu */ + + int menuItem; + HMENU popup = CreatePopupMenu (); + + SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + + switch (LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)))) + { + case TC_MLIST_ITEM_FREE: + + // No mounted volume at this drive letter + + AppendMenuW (popup, MF_STRING, IDM_MOUNT_VOLUME, GetString ("IDM_MOUNT_VOLUME")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDPM_SELECT_FILE_AND_MOUNT, GetString ("SELECT_FILE_AND_MOUNT")); + AppendMenuW (popup, MF_STRING, IDPM_SELECT_DEVICE_AND_MOUNT, GetString ("SELECT_DEVICE_AND_MOUNT")); + break; + + case TC_MLIST_ITEM_NONSYS_VOL: + + // There's a mounted non-system volume at this drive letter + + AppendMenuW (popup, MF_STRING, IDM_UNMOUNT_VOLUME, GetString ("DISMOUNT")); + AppendMenuW (popup, MF_STRING, IDPM_OPEN_VOLUME, GetString ("OPEN")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDPM_CHECK_FILESYS, GetString ("IDPM_CHECK_FILESYS")); + AppendMenuW (popup, MF_STRING, IDPM_REPAIR_FILESYS, GetString ("IDPM_REPAIR_FILESYS")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDM_VOLUME_PROPERTIES, GetString ("IDPM_PROPERTIES")); + break; + + case TC_MLIST_ITEM_SYS_PARTITION: + case TC_MLIST_ITEM_SYS_DRIVE: + + // System partition/drive + + PopulateSysEncContextMenu (popup, FALSE); + break; + } + + mPos=GetMessagePos(); + + menuItem = TrackPopupMenu (popup, + TPM_RETURNCMD | TPM_LEFTBUTTON, + GET_X_LPARAM(mPos), + GET_Y_LPARAM(mPos), + 0, + hwndDlg, + NULL); + + DestroyMenu (popup); + + switch (menuItem) + { + case IDPM_SELECT_FILE_AND_MOUNT: + if (SelectContainer (hwndDlg)) + MountSelectedVolume (hwndDlg, FALSE); + break; + + case IDPM_SELECT_DEVICE_AND_MOUNT: + if (SelectPartition (hwndDlg)) + MountSelectedVolume (hwndDlg, FALSE); + break; + + case IDPM_CHECK_FILESYS: + case IDPM_REPAIR_FILESYS: + { + LPARAM lLetter = GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + + if (LOWORD (lLetter) != 0xffff) + CheckFilesystem ((char) HIWORD (lLetter) - 'A', menuItem == IDPM_REPAIR_FILESYS); + } + break; + + case IDM_UNMOUNT_VOLUME: + if (CheckMountList ()) + Dismount (hwndDlg, 0); + break; + + case IDPM_OPEN_VOLUME: + { + int state = GetItemLong(GetDlgItem (hwndDlg, IDC_DRIVELIST), ((LPNMITEMACTIVATE)lParam)->iItem ); + nSelectedDriveIndex = ((LPNMITEMACTIVATE)lParam)->iItem; + + WaitCursor (); + OpenVolumeExplorerWindow (HIWORD(state) - 'A'); + NormalCursor (); + } + break; + + case IDM_VOLUME_PROPERTIES: + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_VOLUME_PROPERTIES), hwndDlg, + (DLGPROC) VolumePropertiesDlgProc, (LPARAM) FALSE); + break; + + case IDM_MOUNT_VOLUME: + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + mountOptions = defaultMountOptions; + bPrebootPasswordDlgMode = FALSE; + + if (CheckMountList ()) + Mount (hwndDlg, 0, 0); + } + break; + + default: + SendMessage (MainDlg, WM_COMMAND, menuItem, NULL); + break; + } + return 1; + } + } + } + return 0; + + case WM_ERASEBKGND: + return 0; + + case WM_COMMAND: + + if (lw == IDCANCEL || lw == IDC_EXIT) + { + EndMainDlg (hwndDlg); + return 1; + } + + if (lw == IDHELP || lw == IDM_HELP) + { + OpenPageHelp (hwndDlg, 0); + return 1; + } + + if (lw == IDM_ABOUT || lw == IDC_LOGO) + { + DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc); + return 1; + } + + if (lw == IDOK && LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == TC_MLIST_ITEM_NONSYS_VOL + || lw == IDM_UNMOUNT_VOLUME) + { + if (lw == IDM_UNMOUNT_VOLUME && LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) != TC_MLIST_ITEM_NONSYS_VOL) + { + Warning ("SELECT_A_MOUNTED_VOLUME"); + return 1; + } + + if (CheckMountList ()) + Dismount (hwndDlg, 0); + return 1; + } + + if ((lw == IDOK || lw == IDM_MOUNT_VOLUME || lw == IDM_MOUNT_VOLUME_OPTIONS || lw == IDC_MOUNTALL || lw == IDM_MOUNTALL) + && LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == 0xffff) + { + MessageBoxW (hwndDlg, GetString ("SELECT_FREE_DRIVE"), L"TrueCrypt", MB_ICONEXCLAMATION); + return 1; + } + + if ((lw == IDOK || lw == IDM_MOUNT_VOLUME || lw == IDM_MOUNT_VOLUME_OPTIONS)) + { + MountSelectedVolume (hwndDlg, lw == IDM_MOUNT_VOLUME_OPTIONS); + return 1; + } + + if (lw == IDC_UNMOUNTALL || lw == IDM_UNMOUNTALL) + { + DismountAll (hwndDlg, bForceUnmount, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); + return 1; + } + + if (lw == IDC_MOUNTALL || lw == IDM_MOUNTALL) + { + // If Shift key is down and the password cache isn't empty, bypass password prompt + MountAllDevices (hwndDlg, !(GetAsyncKeyState (VK_SHIFT) < 0 && !IsPasswordCacheEmpty())); + return 1; + } + + if (lw == IDC_SELECT_FILE || lw == IDM_SELECT_FILE) + { + SelectContainer (hwndDlg); + return 1; + } + + if (lw == IDC_SELECT_DEVICE || lw == IDM_SELECT_DEVICE) + { + SelectPartition (hwndDlg); + return 1; + } + + // System Encryption menu + switch (lw) + { + case IDM_ENCRYPT_SYSTEM_DEVICE: + EncryptSystemDevice (); + break; + case IDM_PERMANENTLY_DECRYPT_SYS: + DecryptSystemDevice (); + break; + case IDM_CREATE_HIDDEN_OS: + CreateHiddenOS (); + break; + case IDM_SYSENC_RESUME: + ResumeInterruptedSysEncProcess (); + break; + case IDM_SYSTEM_ENCRYPTION_STATUS: + ShowSystemEncryptionStatus (); + break; + case IDM_CHANGE_SYS_PASSWORD: + ChangeSysEncPassword (hwndDlg, FALSE); + break; + case IDM_CHANGE_SYS_HEADER_KEY_DERIV_ALGO: + ChangeSysEncPassword (hwndDlg, TRUE); + break; + case IDM_CREATE_RESCUE_DISK: + CreateRescueDisk (); + break; + case IDM_VERIFY_RESCUE_DISK: + VerifyRescueDisk (); + break; + case IDM_MOUNT_SYSENC_PART_WITHOUT_PBA: + + if (CheckSysEncMountWithoutPBA ("", FALSE)) + { + mountOptions = defaultMountOptions; + bPrebootPasswordDlgMode = TRUE; + + if (CheckMountList ()) + Mount (hwndDlg, 0, 0); + + bPrebootPasswordDlgMode = FALSE; + } + break; + } + + if (lw == IDC_VOLUME_TOOLS) + { + /* Volume Tools popup menu */ + + int menuItem; + char volPath[TC_MAX_PATH]; /* Volume to mount */ + HMENU popup = CreatePopupMenu (); + RECT rect; + + if (ActiveSysEncDeviceSelected ()) + { + PopulateSysEncContextMenu (popup, TRUE); + } + else + { + AppendMenuW (popup, MF_STRING, IDM_CHANGE_PASSWORD, GetString ("IDM_CHANGE_PASSWORD")); + AppendMenuW (popup, MF_STRING, IDM_CHANGE_HEADER_KEY_DERIV_ALGO, GetString ("IDM_CHANGE_HEADER_KEY_DERIV_ALGO")); + AppendMenu (popup, MF_SEPARATOR, 0, NULL); + AppendMenuW (popup, MF_STRING, IDM_BACKUP_VOL_HEADER, GetString ("IDM_BACKUP_VOL_HEADER")); + AppendMenuW (popup, MF_STRING, IDM_RESTORE_VOL_HEADER, GetString ("IDM_RESTORE_VOL_HEADER")); + } + + GetWindowRect (GetDlgItem (hwndDlg, IDC_VOLUME_TOOLS), &rect); + + menuItem = TrackPopupMenu (popup, + TPM_RETURNCMD | TPM_LEFTBUTTON, + rect.left + 2, + rect.top + 2, + 0, + hwndDlg, + NULL); + + DestroyMenu (popup); + + switch (menuItem) + { + case IDM_CHANGE_PASSWORD: + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; + ChangePassword (hwndDlg); + } + break; + + case IDM_CHANGE_HEADER_KEY_DERIV_ALGO: + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + pwdChangeDlgMode = PCDM_CHANGE_PKCS5_PRF; + ChangePassword (hwndDlg); + } + break; + + case IDM_BACKUP_VOL_HEADER: + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); + + WaitCursor (); + + if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) + UacBackupVolumeHeader (hwndDlg, TRUE, volPath); + else + BackupVolumeHeader (hwndDlg, TRUE, volPath); + + NormalCursor (); + } + break; + + case IDM_RESTORE_VOL_HEADER: + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); + + WaitCursor (); + + if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) + UacRestoreVolumeHeader (hwndDlg, volPath); + else + RestoreVolumeHeader (hwndDlg, volPath); + + NormalCursor (); + } + break; + + default: + SendMessage (MainDlg, WM_COMMAND, menuItem, NULL); + break; + } + return 1; + } + + if (lw == IDM_CHANGE_PASSWORD) + { + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + if (ActiveSysEncDeviceSelected ()) + { + ChangeSysEncPassword (hwndDlg, FALSE); + } + else + { + pwdChangeDlgMode = PCDM_CHANGE_PASSWORD; + ChangePassword (hwndDlg); + } + } + return 1; + } + + if (lw == IDM_CHANGE_HEADER_KEY_DERIV_ALGO) + { + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + if (ActiveSysEncDeviceSelected ()) + { + ChangeSysEncPassword (hwndDlg, TRUE); + } + else + { + pwdChangeDlgMode = PCDM_CHANGE_PKCS5_PRF; + ChangePassword (hwndDlg); + } + } + return 1; + } + + if (lw == IDC_WIPE_CACHE || lw == IDM_WIPE_CACHE) + { + WipeCache (hwndDlg, FALSE); + return 1; + } + + if (lw == IDM_CLEAR_HISTORY) + { + ClearHistory (GetDlgItem (hwndDlg, IDC_VOLUME)); + EnableDisableButtons (hwndDlg); + return 1; + } + + if (lw == IDC_CREATE_VOLUME || lw == IDM_CREATE_VOLUME || lw == IDM_VOLUME_WIZARD) + { + LaunchVolCreationWizard (hwndDlg, ""); + return 1; + } + + if (lw == IDM_ADD_REMOVE_VOL_KEYFILES) + { + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + pwdChangeDlgMode = PCDM_ADD_REMOVE_VOL_KEYFILES; + ChangePassword (hwndDlg); + } + return 1; + } + + if (lw == IDM_REMOVE_ALL_KEYFILES_FROM_VOL) + { + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + pwdChangeDlgMode = PCDM_REMOVE_ALL_KEYFILES_FROM_VOL; + ChangePassword (hwndDlg); + } + return 1; + } + + if (lw == IDM_MANAGE_TOKEN_KEYFILES) + { + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, NULL); + return 1; + } + + if (lw == IDM_CLOSE_ALL_TOKEN_SESSIONS) + { + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + SecurityToken::CloseAllSessions(); + } + Info ("ALL_TOKEN_SESSIONS_CLOSED"); + + return 1; + } + + if (lw == IDM_GENERATE_KEYFILE || lw == IDM_KEYFILE_GENERATOR) + { + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg, + (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0); + + return 1; + } + + if (lw == IDM_LICENSE) + { + TextInfoDialogBox (TC_TBXID_LEGAL_NOTICES); + return 1; + } + + if (lw == IDM_WEBSITE) + { + Applink ("website", TRUE, ""); + return 1; + } + else if (lw == IDM_HOMEPAGE) + { + Applink ("homepage", TRUE, ""); + return 1; + } + else if (lw == IDM_FORUMS) + { + Applink ("forum", TRUE, ""); + return 1; + } + else if (lw == IDM_ONLINE_TUTORIAL) + { + Applink ("tutorial", TRUE, ""); + return 1; + } + else if (lw == IDM_ONLINE_HELP) + { + OpenOnlineHelp (); + return 1; + } + else if (lw == IDM_FAQ) + { + Applink ("faq", TRUE, ""); + return 1; + } + else if (lw == IDM_TC_DOWNLOADS) + { + Applink ("downloads", TRUE, ""); + return 1; + } + else if (lw == IDM_NEWS) + { + Applink ("news", TRUE, ""); + return 1; + } + else if (lw == IDM_VERSION_HISTORY) + { + Applink ("history", TRUE, ""); + return 1; + } + else if (lw == IDM_BUGREPORT) + { + Applink ("bugreport", TRUE, ""); + return 1; + } + else if (lw == IDM_DONATIONS) + { + Applink ("donations", FALSE, ""); + return 1; + } + else if (lw == IDM_CONTACT) + { + Applink ("contact", FALSE, ""); + return 1; + } + + if (lw == IDM_PREFERENCES) + { + if (IDOK == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_PREFERENCES_DLG), hwndDlg, + (DLGPROC) PreferencesDlgProc, (LPARAM) 0)) + { + if (bEnableBkgTask) + { + TaskBarIconAdd (hwndDlg); + } + else + { + TaskBarIconRemove (hwndDlg); + if (MainWindowHidden) + EndMainDlg (hwndDlg); + } + } + return 1; + } + + if (lw == IDM_HOTKEY_SETTINGS) + { + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_HOTKEYS_DLG), hwndDlg, + (DLGPROC) HotkeysDlgProc, (LPARAM) 0); + return 1; + } + + if (lw == IDM_DEFAULT_KEYFILES || lw == IDM_SET_DEFAULT_KEYFILES) + { + KeyfileDefaultsDlg (hwndDlg); + return 1; + } + + if (lw == IDM_TOKEN_PREFERENCES) + { + SecurityTokenPreferencesDialog (hwndDlg); + return 1; + } + + if (lw == IDM_SYSENC_SETTINGS || lw == IDM_SYS_ENC_SETTINGS) + { + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_SYSENC_SETTINGS), hwndDlg, (DLGPROC) BootLoaderPreferencesDlgProc, 0); + return 1; + } + + if (lw == IDM_SYS_FAVORITES_SETTINGS) + { + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_SYS_FAVORITES_SETTINGS), hwndDlg, (DLGPROC) SystemFavoritesSettingsDlgProc, 0); + return 1; + } + + if (lw == IDM_BENCHMARK) + { + Benchmark (hwndDlg); + return 1; + } + + if (lw == IDM_TRAVELER) + { + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_TRAVELER_DLG), hwndDlg, + (DLGPROC) TravelerDlgProc, (LPARAM) 0); + return 1; + } + + if (lw == IDM_BACKUP_VOL_HEADER) + { + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + char volPath[TC_MAX_PATH]; /* Volume to mount */ + + GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); + + WaitCursor (); + + if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) + UacBackupVolumeHeader (hwndDlg, TRUE, volPath); + else + BackupVolumeHeader (hwndDlg, TRUE, volPath); + + NormalCursor (); + } + return 1; + } + + if (lw == IDM_RESTORE_VOL_HEADER) + { + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else + { + char volPath[TC_MAX_PATH]; /* Volume to mount */ + + GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), volPath, sizeof (volPath)); + + WaitCursor (); + + if (!IsAdmin () && IsUacSupported () && IsVolumeDeviceHosted (volPath)) + UacRestoreVolumeHeader (hwndDlg, volPath); + else + RestoreVolumeHeader (hwndDlg, volPath); + + NormalCursor (); + } + return 1; + } + + if (lw == IDM_LANGUAGE) + { + BOOL p; + if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), hwndDlg, + (DLGPROC) LanguageDlgProc, (LPARAM) 0) == IDOK) + { + LoadLanguageFile (); + SaveSettings (hwndDlg); + + p = LocalizationActive; + LocalizationActive = TRUE; + InitMainDialog (hwndDlg); + InvalidateRect (hwndDlg, NULL, FALSE); + LocalizationActive = p; + DrawMenuBar (hwndDlg); + } + return 1; + } + + if (lw == IDM_TEST_VECTORS) + { + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_CIPHER_TEST_DLG), hwndDlg, (DLGPROC) CipherTestDialogProc, (LPARAM) 1); + return 1; + } + + if (lw == IDM_REFRESH_DRIVE_LETTERS) + { + DWORD driveMap = GetLogicalDrives (); + + WaitCursor (); + + if (!(nCurrentOS == WIN_2000 && RemoteSession)) + { + BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, 0, ~driveMap); + Sleep (100); + BroadcastDeviceChange (DBT_DEVICEARRIVAL, 0, driveMap); + } + + LoadDriveLetters (GetDlgItem (hwndDlg, IDC_DRIVELIST), 0); + + if (nSelectedDriveIndex >= 0) + { + SelectItem (GetDlgItem (hwndDlg, IDC_DRIVELIST), + (char) HIWORD (GetItemLong (GetDlgItem (hwndDlg, IDC_DRIVELIST), nSelectedDriveIndex))); + } + + NormalCursor (); + return 1; + } + + if (lw == IDM_MOUNT_FAVORITE_VOLUMES) + { + MountFavoriteVolumes (FALSE); + return 1; + } + + if (lw == IDM_RESUME_INTERRUPTED_PROC) + { + ResumeInterruptedNonSysInplaceEncProcess (); + return 1; + } + + if (lw == IDM_SAVE_FAVORITE_VOLUMES) + { + SaveFavoriteVolumes (FALSE); + return 1; + } + + if (lw == IDM_SAVE_SYSTEM_FAVORITE_VOLUMES) + { + try + { + BootEncStatus = BootEncObj->GetStatus(); + } + catch (Exception &e) + { + e.Show (MainDlg); + return 1; + } + + if (BootEncStatus.DriveMounted) + SaveFavoriteVolumes (TRUE); + else + Error ("SYS_FAVORITES_REQUIRE_PBA"); + + return 1; + } + + if (lw == IDC_VOLUME_PROPERTIES || lw == IDM_VOLUME_PROPERTIES) + { + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_VOLUME_PROPERTIES), hwndDlg, + (DLGPROC) VolumePropertiesDlgProc, (LPARAM) 0); + return 1; + } + + if (lw == IDC_VOLUME && hw == CBN_EDITCHANGE) + { + EnableDisableButtons (hwndDlg); + return 1; + } + + if (lw == IDC_VOLUME && hw == CBN_SELCHANGE) + { + UpdateComboOrder (GetDlgItem (hwndDlg, IDC_VOLUME)); + MoveEditToCombo ((HWND) lParam, bHistory); + PostMessage (hwndDlg, TC_APPMSG_MOUNT_ENABLE_DISABLE_CONTROLS, 0, 0); + return 1; + } + + if (lw == IDC_NO_HISTORY) + { + if (!(bHistory = !IsButtonChecked (GetDlgItem (hwndDlg, IDC_NO_HISTORY)))) + ClearHistory (GetDlgItem (hwndDlg, IDC_VOLUME)); + + return 1; + } + + return 0; + + case WM_DROPFILES: + { + HDROP hdrop = (HDROP) wParam; + DragQueryFile (hdrop, 0, szFileName, sizeof szFileName); + DragFinish (hdrop); + + AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); + EnableDisableButtons (hwndDlg); + SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + } + return 1; + + case TC_APPMSG_MOUNT_ENABLE_DISABLE_CONTROLS: + EnableDisableButtons (hwndDlg); + return 1; + + case TC_APPMSG_MOUNT_SHOW_WINDOW: + MainWindowHidden = FALSE; + ShowWindow (hwndDlg, SW_SHOW); + ShowWindow (hwndDlg, SW_RESTORE); + return 1; + + case WM_COPYDATA: + { + PCOPYDATASTRUCT cd = (PCOPYDATASTRUCT)lParam; + if (memcmp (&cd->dwData, WM_COPY_SET_VOLUME_NAME, 4) == 0) + { + if (cd->cbData > 0) + { + ((char *) cd->lpData)[cd->cbData - 1] = 0; + AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), (char *)cd->lpData, bHistory); + } + + EnableDisableButtons (hwndDlg); + SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST)); + } + } + return 1; + + case WM_CLOSE: + EndMainDlg (hwndDlg); + return 1; + + default: + // Recreate tray icon if Explorer restarted + if (taskBarCreatedMsg != 0 && uMsg == taskBarCreatedMsg && TaskBarIconMutex != NULL) + { + TaskBarIconRemove (hwndDlg); + TaskBarIconAdd (hwndDlg); + return 1; + } + } + + return 0; +} + +void ExtractCommandLine (HWND hwndDlg, char *lpszCommandLine) +{ + char **lpszCommandLineArgs; /* Array of command line arguments */ + int nNoCommandLineArgs; /* The number of arguments in the array */ + char tmpPath[MAX_PATH * 2]; + + /* Defaults */ + mountOptions.PreserveTimestamp = TRUE; + + if (_stricmp (lpszCommandLine, "-Embedding") == 0) + { + ComServerMode = TRUE; + return; + } + + /* Extract command line arguments */ + NoCmdLineArgs = nNoCommandLineArgs = Win32CommandLine (lpszCommandLine, &lpszCommandLineArgs); + + if (nNoCommandLineArgs > 0) + { + int i; + + for (i = 0; i < nNoCommandLineArgs; i++) + { + enum + { + OptionAuto, + OptionBeep, + OptionCache, + CommandDismount, + OptionExplore, + OptionForce, + CommandHelp, + OptionHistory, + OptionKeyfile, + OptionLetter, + OptionMountOption, + OptionPassword, + OptionQuit, + OptionSilent, + OptionTokenLib, + OptionVolume, + CommandWipeCache + }; + + argument args[]= + { + { OptionAuto, "/auto", "/a", FALSE }, + { OptionBeep, "/beep", "/b", FALSE }, + { OptionCache, "/cache", "/c", FALSE }, + { CommandDismount, "/dismount", "/d", FALSE }, + { OptionExplore, "/explore", "/e", FALSE }, + { OptionForce, "/force", "/f", FALSE }, + { CommandHelp, "/help", "/?", FALSE }, + { OptionHistory, "/history", "/h", FALSE }, + { OptionKeyfile, "/keyfile", "/k", FALSE }, + { OptionLetter, "/letter", "/l", FALSE }, + { OptionMountOption, "/mountoption", "/m", FALSE }, + { OptionPassword, "/password", "/p", FALSE }, + { OptionQuit, "/quit", "/q", FALSE }, + { OptionSilent, "/silent", "/s", FALSE }, + { OptionTokenLib, "/tokenlib", NULL, FALSE }, + { OptionVolume, "/volume", "/v", FALSE }, + { CommandWipeCache, "/wipecache", "/w", FALSE } + }; + + argumentspec as; + + int nArgPos; + + as.args = args; + as.arg_cnt = sizeof(args)/ sizeof(args[0]); + + switch (GetArgumentID (&as, lpszCommandLineArgs[i], &nArgPos)) + { + case OptionAuto: + { + char szTmp[32]; + bAuto = TRUE; + + if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, + nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp))) + { + if (!_stricmp (szTmp, "devices")) + bAutoMountDevices = TRUE; + else if (!_stricmp (szTmp, "favorites")) + bAutoMountFavorites = TRUE; + } + } + break; + + case OptionBeep: + bBeep = TRUE; + break; + + case OptionCache: + { + char szTmp[8]; + bCacheInDriver = TRUE; + + GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, + szTmp, sizeof (szTmp)); + + if (!_stricmp(szTmp,"n") || !_stricmp(szTmp,"no")) + bCacheInDriver = FALSE; + } + break; + + case CommandDismount: + + if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, + szDriveLetter, sizeof (szDriveLetter))) + cmdUnmountDrive = toupper(szDriveLetter[0]) - 'A'; + else + cmdUnmountDrive = -1; + + break; + + case OptionExplore: + bExplore = TRUE; + break; + + case OptionForce: + bForceMount = TRUE; + bForceUnmount = TRUE; + break; + + case OptionKeyfile: + if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, + nNoCommandLineArgs, tmpPath, sizeof (tmpPath))) + { + KeyFile *kf; + RelativePath2Absolute (tmpPath); + kf = (KeyFile *) malloc (sizeof (KeyFile)); + strncpy (kf->FileName, tmpPath, sizeof (kf->FileName)); + FirstCmdKeyFile = KeyFileAdd (FirstCmdKeyFile, kf); + } + break; + + case OptionLetter: + GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, + szDriveLetter, sizeof (szDriveLetter)); + commandLineDrive = *szDriveLetter = (char) toupper (*szDriveLetter); + + if (commandLineDrive < 'C' || commandLineDrive > 'Z') + AbortProcess ("BAD_DRIVE_LETTER"); + + break; + + case OptionHistory: + { + char szTmp[8]; + bHistory = bHistoryCmdLine = TRUE; + + GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, + szTmp, sizeof (szTmp)); + + if (!_stricmp(szTmp,"n") || !_stricmp(szTmp,"no")) + bHistory = FALSE; + } + break; + + case OptionMountOption: + { + char szTmp[16]; + if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, + nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp))) + { + if (!_stricmp (szTmp, "ro") || !_stricmp (szTmp, "readonly")) + mountOptions.ReadOnly = TRUE; + + if (!_stricmp (szTmp, "rm") || !_stricmp (szTmp, "removable")) + mountOptions.Removable = TRUE; + + if (!_stricmp (szTmp, "ts") || !_stricmp (szTmp, "timestamp")) + mountOptions.PreserveTimestamp = FALSE; + + if (!_stricmp (szTmp, "sm") || !_stricmp (szTmp, "system")) + mountOptions.PartitionInInactiveSysEncScope = bPrebootPasswordDlgMode = TRUE; + + if (!_stricmp (szTmp, "bk") || !_stricmp (szTmp, "headerbak")) + mountOptions.UseBackupHeader = TRUE; + + if (!_stricmp (szTmp, "recovery")) + mountOptions.RecoveryMode = TRUE; + + CmdMountOptions = mountOptions; + CmdMountOptionsValid = TRUE; + } + } + break; + + case OptionPassword: + GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, + (char *) CmdVolumePassword.Text, sizeof (CmdVolumePassword.Text)); + CmdVolumePassword.Length = strlen ((char *) CmdVolumePassword.Text); + CmdVolumePasswordValid = TRUE; + break; + + case OptionVolume: + if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, + nNoCommandLineArgs, szFileName, sizeof (szFileName))) + { + RelativePath2Absolute (szFileName); + AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); + CmdLineVolumeSpecified = TRUE; + } + break; + + case OptionQuit: + { + char szTmp[32]; + + if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, + nArgPos, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp))) + { + if (!_stricmp (szTmp, "UAC")) // Used to indicate non-install elevation + break; + + if (!_stricmp (szTmp, "preferences")) + { + Quit = TRUE; + UsePreferences = TRUE; + break; + } + + if (!_stricmp (szTmp, "background")) + bEnableBkgTask = TRUE; + } + + Quit = TRUE; + UsePreferences = FALSE; + } + break; + + case OptionSilent: + Silent = TRUE; + break; + + case OptionTokenLib: + if (GetArgumentValue (lpszCommandLineArgs, nArgPos, &i, nNoCommandLineArgs, SecurityTokenLibraryPath, sizeof (SecurityTokenLibraryPath)) == HAS_ARGUMENT) + InitSecurityTokenLibrary(); + else + Error ("COMMAND_LINE_ERROR"); + + break; + + case CommandWipeCache: + bWipe = TRUE; + break; + + case CommandHelp: + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_COMMANDHELP_DLG), hwndDlg, (DLGPROC) + CommandHelpDlgProc, (LPARAM) &as); + exit(0); + break; + + // no option = file name + default: + { + strcpy_s (szFileName, array_capacity (szFileName), lpszCommandLineArgs[i]); + RelativePath2Absolute (szFileName); + + if (nNoCommandLineArgs == 1) + CmdLineVolumeSpecified = TRUE; + AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory); + } + } + } + } + + /* Free up the command line arguments */ + while (--nNoCommandLineArgs >= 0) + { + free (lpszCommandLineArgs[nNoCommandLineArgs]); + } +} + + +static SERVICE_STATUS SystemFavoritesServiceStatus; +static SERVICE_STATUS_HANDLE SystemFavoritesServiceStatusHandle; + + +static void SystemFavoritesServiceLogError (const string &errorMessage) +{ + HANDLE eventSource = RegisterEventSource (NULL, TC_SYSTEM_FAVORITES_SERVICE_NAME); + + if (eventSource) + { + LPCTSTR strings[] = { TC_SYSTEM_FAVORITES_SERVICE_NAME, errorMessage.c_str() }; + ReportEvent (eventSource, EVENTLOG_ERROR_TYPE, 0, 0xC0000001, NULL, array_capacity (strings), 0, strings, NULL); + + DeregisterEventSource (eventSource); + } +} + + +static void SystemFavoritesServiceSetStatus (DWORD status, DWORD waitHint = 0) +{ + SystemFavoritesServiceStatus.dwCurrentState = status; + SystemFavoritesServiceStatus.dwWaitHint = waitHint; + SystemFavoritesServiceStatus.dwWin32ExitCode = NO_ERROR; + + SetServiceStatus (SystemFavoritesServiceStatusHandle, &SystemFavoritesServiceStatus); +} + + +static VOID WINAPI SystemFavoritesServiceCtrlHandler (DWORD control) +{ + if (control == SERVICE_CONTROL_STOP) + SystemFavoritesServiceSetStatus (SERVICE_STOP_PENDING); + else + SystemFavoritesServiceSetStatus (SystemFavoritesServiceStatus.dwCurrentState); +} + + +static VOID WINAPI SystemFavoritesServiceMain (DWORD argc, LPTSTR *argv) +{ + memset (&SystemFavoritesServiceStatus, 0, sizeof (SystemFavoritesServiceStatus)); + SystemFavoritesServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + + SystemFavoritesServiceStatusHandle = RegisterServiceCtrlHandler (TC_SYSTEM_FAVORITES_SERVICE_NAME, SystemFavoritesServiceCtrlHandler); + if (!SystemFavoritesServiceStatusHandle) + return; + + SystemFavoritesServiceSetStatus (SERVICE_START_PENDING, 60000); + + MountFavoriteVolumes (TRUE); + + SystemFavoritesServiceSetStatus (SERVICE_RUNNING); + SystemFavoritesServiceSetStatus (SERVICE_STOPPED); +} + + +static BOOL StartSystemFavoritesService () +{ + ServiceMode = TRUE; + Silent = TRUE; + DeviceChangeBroadcastDisabled = TRUE; + + if (DriverAttach() != ERR_SUCCESS) + return FALSE; + + SERVICE_TABLE_ENTRY serviceTable[2]; + serviceTable[0].lpServiceName = TC_SYSTEM_FAVORITES_SERVICE_NAME; + serviceTable[0].lpServiceProc = SystemFavoritesServiceMain; + + serviceTable[1].lpServiceName = NULL; + serviceTable[1].lpServiceProc = NULL; + + BOOL result = StartServiceCtrlDispatcher (serviceTable); + + if (!(ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD)) + WipeCache (NULL, TRUE); + + return result; +} + + +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCommandLine, int nCmdShow) +{ + int argc; + LPWSTR *argv = CommandLineToArgvW (GetCommandLineW(), &argc); + + if (argv && argc == 2 && SingleStringToWide (TC_SYSTEM_FAVORITES_SERVICE_CMDLINE_OPTION) == argv[1]) + return StartSystemFavoritesService() ? 0 : 1; + + int status; + atexit (localcleanup); + SetProcessShutdownParameters (0x100, 0); + + VirtualLock (&VolumePassword, sizeof (VolumePassword)); + VirtualLock (&CmdVolumePassword, sizeof (CmdVolumePassword)); + VirtualLock (&mountOptions, sizeof (mountOptions)); + VirtualLock (&defaultMountOptions, sizeof (defaultMountOptions)); + VirtualLock (&szFileName, sizeof(szFileName)); + + try + { + BootEncObj = new BootEncryption (NULL); + } + catch (Exception &e) + { + e.Show (NULL); + } + + if (BootEncObj == NULL) + AbortProcess ("INIT_SYS_ENC"); + + InitCommonControls (); + InitApp (hInstance, lpszCommandLine); + + RegisterRedTick(hInstance); + + /* Allocate, dup, then store away the application title */ + lpszTitle = L"TrueCrypt"; + + status = DriverAttach (); + if (status != 0) + { + if (status == ERR_OS_ERROR) + handleWin32Error (NULL); + else + handleError (NULL, status); + + AbortProcess ("NODRIVER"); + } + + /* Create the main dialog box */ + DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_MOUNT_DLG), NULL, (DLGPROC) MainDialogProc, + (LPARAM) lpszCommandLine); + + /* Terminate */ + return 0; +} + + +BOOL TaskBarIconAdd (HWND hwnd) +{ + BOOL res; + NOTIFYICONDATAW tnid; + + // Only one icon may be created + if (TaskBarIconMutex != NULL) return TRUE; + + TaskBarIconMutex = CreateMutex (NULL, TRUE, "TrueCryptTaskBarIcon"); + if (TaskBarIconMutex == NULL || GetLastError () == ERROR_ALREADY_EXISTS) + { + TaskBarIconMutex = NULL; + return FALSE; + } + + tnid.cbSize = sizeof (NOTIFYICONDATAW); + tnid.hWnd = hwnd; + tnid.uID = IDI_TRUECRYPT_ICON; + tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + tnid.uCallbackMessage = TC_APPMSG_TASKBAR_ICON; + tnid.hIcon = (HICON) LoadImage (hInst, MAKEINTRESOURCE (IDI_TRUECRYPT_ICON), + IMAGE_ICON, + ScreenDPI >= 120 ? 0 : 16, + ScreenDPI >= 120 ? 0 : 16, + (ScreenDPI >= 120 ? LR_DEFAULTSIZE : 0) + | (nCurrentOS != WIN_2000 ? LR_DEFAULTCOLOR : LR_VGACOLOR)); // Windows 2000 cannot display more than 16 fixed colors in notification tray + + wcscpy (tnid.szTip, L"TrueCrypt"); + + res = Shell_NotifyIconW (NIM_ADD, &tnid); + + if (tnid.hIcon) + DestroyIcon (tnid.hIcon); + + return res; +} + + +BOOL TaskBarIconRemove (HWND hwnd) +{ + if (TaskBarIconMutex != NULL) + { + NOTIFYICONDATA tnid; + BOOL res; + + ZeroMemory (&tnid, sizeof (tnid)); + tnid.cbSize = sizeof(NOTIFYICONDATA); + tnid.hWnd = hwnd; + tnid.uID = IDI_TRUECRYPT_ICON; + + res = Shell_NotifyIcon (NIM_DELETE, &tnid); + if (TaskBarIconMutex) + { + CloseHandle (TaskBarIconMutex); + TaskBarIconMutex = NULL; + } + return res; + } + else + return FALSE; +} + + +void DismountIdleVolumes () +{ + static DWORD lastMinTickCount; + static int InactivityTime[26]; + static unsigned __int64 LastRead[26], LastWritten[26]; + static int LastId[26]; + + VOLUME_PROPERTIES_STRUCT prop; + DWORD dwResult; + BOOL bResult; + int i; + + if (GetTickCount() > lastMinTickCount && GetTickCount() - lastMinTickCount < 60 * 1000) + return; + + lastMinTickCount = GetTickCount(); + + for (i = 0; i < 26; i++) + { + if (LastKnownMountList.ulMountedDrives & (1 << i)) + { + memset (&prop, 0, sizeof(prop)); + prop.driveNo = i; + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, + sizeof (prop), &prop, sizeof (prop), &dwResult, NULL); + + if (bResult) + { + if (LastRead[i] == prop.totalBytesRead + && LastWritten[i] == prop.totalBytesWritten + && LastId[i] == prop.uniqueId) + { + if (++InactivityTime[i] >= MaxVolumeIdleTime) + { + BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, i, 0); + + if (bCloseDismountedWindows && CloseVolumeExplorerWindows (MainDlg, i)) + Sleep (250); + + if (DriverUnmountVolume (MainDlg, i, bForceAutoDismount) == 0) + { + InactivityTime[i] = 0; + BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, i, 0); + + if (bWipeCacheOnAutoDismount) + { + DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + SecurityToken::CloseAllSessions(); + } + } + } + } + else + { + InactivityTime[i] = 0; + LastRead[i] = prop.totalBytesRead; + LastWritten[i] = prop.totalBytesWritten; + LastId[i] = prop.uniqueId; + } + } + } + } +} + + +BOOL MountFavoriteVolumes (BOOL systemFavorites) +{ + BOOL status = TRUE; + DWORD size; + char *favorites = LoadFile (systemFavorites ? GetProgramConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES) : GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES), &size); + char *xml = favorites; + char mountPoint[MAX_PATH], volume[MAX_PATH]; + + if (xml == NULL) return FALSE; + + mountOptions = defaultMountOptions; + + VolumePassword.Length = 0; + MultipleMountOperationInProgress = TRUE; + + while (xml = XmlFindElement (xml, "volume")) + { + int drive; + XmlGetAttributeText (xml, "mountpoint", mountPoint, sizeof (mountPoint)); + XmlGetNodeText (xml, volume, sizeof (volume)); + drive = toupper (mountPoint[0]) - 'A'; + + char boolVal[2]; + XmlGetAttributeText (xml, "readonly", boolVal, sizeof (boolVal)); + if (boolVal[0]) + mountOptions.ReadOnly = (boolVal[0] == '1' ? TRUE : FALSE); + + XmlGetAttributeText (xml, "removable", boolVal, sizeof (boolVal)); + if (boolVal[0]) + mountOptions.Removable = (boolVal[0] == '1' ? TRUE : FALSE); + + XmlGetAttributeText (xml, "system", boolVal, sizeof (boolVal)); + if (boolVal[0] == '1') + { + mountOptions.PartitionInInactiveSysEncScope = TRUE; + bPrebootPasswordDlgMode = TRUE; + } + else + { + mountOptions.PartitionInInactiveSysEncScope = FALSE; + bPrebootPasswordDlgMode = FALSE; + } + + string path = volume; + if (path.find ("\\\\?\\Volume{") == 0 && path.rfind ("}\\") == path.size() - 2) + { + // Resolve volume name + char volDevPath[TC_MAX_PATH]; + if (QueryDosDevice (path.substr (4, path.size() - 5).c_str(), volDevPath, TC_MAX_PATH) != 0) + { + foreach (const HostDevice &device, GetAvailableHostDevices (true, true)) + { + if (!device.DynamicVolume) + { + wchar_t resolvedVolumePath[TC_MAX_PATH]; + + if (ResolveSymbolicLink (SingleStringToWide (device.Path).c_str(), resolvedVolumePath) + && SingleStringToWide (volDevPath) == resolvedVolumePath) + { + strcpy_s (volume, TC_MAX_PATH, device.Path.c_str()); + break; + } + } + } + } + } + + if ((LastKnownMountList.ulMountedDrives & (1 << drive)) == 0) + { + MountVolumesAsSystemFavorite = systemFavorites; + + if (!Mount (MainDlg, drive, volume)) + status = FALSE; + LoadDriveLetters (GetDlgItem (MainDlg, IDC_DRIVELIST), 0); + + MountVolumesAsSystemFavorite = FALSE; + + if (ServiceMode && LastMountedVolumeDirty) + { + DWORD bytesOut; + DeviceIoControl (hDriver, TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY, NULL, 0, NULL, 0, &bytesOut, NULL); + + SystemFavoritesServiceLogError (string ("The filesystem of the volume mounted as ") + (char) (drive + 'A') + ": was not cleanly dismounted and needs to be checked for errors."); + } + } + + xml++; + } + + MultipleMountOperationInProgress = FALSE; + burn (&VolumePassword, sizeof (VolumePassword)); + + if (status && CloseSecurityTokenSessionsAfterMount) + SecurityToken::CloseAllSessions(); + + free (favorites); + return status; +} + + +void SaveFavoriteVolumes (BOOL systemFavorites) +{ + if (AskYesNo (systemFavorites ? "CONFIRM_SAVE_SYS_FAVORITE_VOL" : "CONFIRM_SAVE_FAVORITE_VOL") == IDYES) + { + FILE *f; + int i, cnt = 0; + + f = fopen (GetConfigPath (systemFavorites ? TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES : TC_APPD_FILENAME_FAVORITE_VOLUMES), "w"); + if (f == NULL) + { + handleWin32Error (MainDlg); + return; + } + + XmlWriteHeader (f); + fputs ("\n\t", f); + + for (i = 0; i < 26; i++) + { + if (LastKnownMountList.ulMountedDrives & (1 << i)) + { + char t[2048], tq[2048]; + + sprintf_s (t, sizeof (t), "%ls", &LastKnownMountList.wszVolume[i][(LastKnownMountList.wszVolume[i][1] == L'?') ? 4 : 0]); + + if (strstr (t, "\\Device\\") == t) + { + // Convert device path to GUID path + string volumeDevPath = t; + + wchar_t resolvedVolumeDevPath[TC_MAX_PATH]; + if (ResolveSymbolicLink (SingleStringToWide (volumeDevPath).c_str(), resolvedVolumeDevPath)) + volumeDevPath = WideToSingleString (resolvedVolumeDevPath); + + char volumeName[TC_MAX_PATH]; + HANDLE find = FindFirstVolume (volumeName, sizeof (volumeName)); + + if (find != INVALID_HANDLE_VALUE) + { + do + { + char findVolumeDevPath[TC_MAX_PATH]; + string vn = volumeName; + + if (QueryDosDevice (vn.substr (4, vn.size() - 5).c_str(), findVolumeDevPath, sizeof (findVolumeDevPath)) != 0 + && volumeDevPath == findVolumeDevPath) + { + strcpy_s (t, array_capacity (t), volumeName); + break; + } + + } while (FindNextVolume (find, volumeName, sizeof (volumeName))); + + FindVolumeClose (find); + } + } + + XmlQuoteText (t, tq, sizeof (tq)); + + VOLUME_PROPERTIES_STRUCT prop; + DWORD bytesReturned; + + memset (&prop, 0, sizeof(prop)); + prop.driveNo = i; + + if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &bytesReturned, NULL)) + { + handleWin32Error (NULL); + continue; + } + + fprintf (f, "\n\t\t%s", + i + 'A', + prop.readOnly ? 1 : 0, + prop.removable ? 1 : 0, + prop.partitionInInactiveSysEncScope ? 1 : 0, + tq); + + cnt++; + } + } + + fputs ("\n\t", f); + XmlWriteFooter (f); + fclose (f); + + if (systemFavorites) + { + finally_do ({ remove (GetConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES)); }); + + try + { + BootEncObj->DeleteFileAdmin (GetProgramConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES)); + } + catch (UserAbort&) { return; } + catch (...) { } + + try + { + if (cnt != 0) + BootEncObj->CopyFileAdmin (GetConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES), GetProgramConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES)); + + Info ("SYS_FAVORITE_VOLUMES_SAVED"); + } + catch (Exception &e) + { + e.Show (NULL); + } + + } + else + Info ("FAVORITE_VOLUMES_SAVED"); + + if (cnt == 0) + { + if (systemFavorites) + { + try + { + BootEncObj->DeleteFileAdmin (GetProgramConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES)); + } + catch (...) { } + } + else + remove (GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES)); + } + } +} + + +static void SaveDefaultKeyFilesParam (void) +{ + if (defaultKeyFilesParam.FirstKeyFile == NULL) + { + /* No keyfiles selected */ + remove (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES)); + } + else + { + FILE *f; + KeyFile *kf = FirstKeyFile; + + f = fopen (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES), "w"); + if (f == NULL) + { + handleWin32Error (MainDlg); + return; + } + + XmlWriteHeader (f); + + fputs ("\n\t", f); + + while (kf != NULL) + { + char q[TC_MAX_PATH * 2]; + + XmlQuoteText (kf->FileName, q, sizeof (q)); + fprintf (f, "\n\t\t%s", q); + + kf = kf->Next; + } + + fputs ("\n\t", f); + + XmlWriteFooter (f); + + fclose (f); + return; + } +} + + +static void KeyfileDefaultsDlg (HWND hwndDlg) +{ + KeyFilesDlgParam param; + + param.EnableKeyFiles = defaultKeyFilesParam.EnableKeyFiles; + param.FirstKeyFile = defaultKeyFilesParam.FirstKeyFile; + + if (DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg, + (DLGPROC) KeyFilesDlgProc, (LPARAM) ¶m) == IDOK) + { + if (!param.EnableKeyFiles || AskWarnYesNo ("CONFIRM_SAVE_DEFAULT_KEYFILES") == IDYES) + { + KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); + defaultKeyFilesParam.EnableKeyFiles = param.EnableKeyFiles; + defaultKeyFilesParam.FirstKeyFile = param.FirstKeyFile; + + RestoreDefaultKeyFilesParam (); + SaveDefaultKeyFilesParam (); + } + } +} + + +static void HandleHotKey (HWND hwndDlg, WPARAM wParam) +{ + DWORD dwResult; + BOOL success = TRUE; + + switch (wParam) + { + case HK_AUTOMOUNT_DEVICES: + MountAllDevices (hwndDlg, TRUE); + + if (bPlaySoundOnHotkeyMountDismount) + MessageBeep (0xFFFFFFFF); + + break; + + case HK_DISMOUNT_ALL: + case HK_DISMOUNT_ALL_AND_WIPE: + + if (wParam == HK_DISMOUNT_ALL_AND_WIPE) + WipeCache (hwndDlg, TRUE); + + if (DismountAll (hwndDlg, FALSE, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY) && bDisplayMsgBoxOnHotkeyDismount) + InfoTopMost (wParam == HK_DISMOUNT_ALL_AND_WIPE ? "VOLUMES_DISMOUNTED_CACHE_WIPED" : "MOUNTED_VOLUMES_DISMOUNTED"); + else if (bDisplayMsgBoxOnHotkeyDismount) + InfoTopMost (wParam == HK_DISMOUNT_ALL_AND_WIPE ? "PASSWORD_CACHE_WIPED" : "DISMOUNT_ALL_ATTEMPT_COMPLETED"); + + if (!bDisplayMsgBoxOnHotkeyDismount && bPlaySoundOnHotkeyMountDismount) + MessageBeep (0xFFFFFFFF); + + break; + + case HK_WIPE_CACHE: + WipeCache (hwndDlg, FALSE); + break; + + case HK_FORCE_DISMOUNT_ALL_AND_WIPE: + success = DismountAll (hwndDlg, TRUE, FALSE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); + success &= DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + if (success) + { + if (bPlaySoundOnHotkeyMountDismount) + MessageBeep (0xFFFFFFFF); + + if (bDisplayMsgBoxOnHotkeyDismount) + InfoTopMost ("VOLUMES_DISMOUNTED_CACHE_WIPED"); + } + break; + + case HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT: + success = DismountAll (hwndDlg, TRUE, FALSE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); + success &= DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); + if (success) + { + if (bPlaySoundOnHotkeyMountDismount) + MessageBeep (0xFFFFFFFF); + + if (bDisplayMsgBoxOnHotkeyDismount) + InfoTopMost ("VOLUMES_DISMOUNTED_CACHE_WIPED"); + } + TaskBarIconRemove (hwndDlg); + EndMainDlg (hwndDlg); + break; + + case HK_MOUNT_FAVORITE_VOLUMES: + MountFavoriteVolumes (FALSE); + + if (bPlaySoundOnHotkeyMountDismount) + MessageBeep (0xFFFFFFFF); + + break; + + case HK_SHOW_HIDE_MAIN_WINDOW: + ChangeMainWindowVisibility (); + break; + + case HK_CLOSE_SECURITY_TOKEN_SESSIONS: + SecurityToken::CloseAllSessions(); + InfoTopMost ("ALL_TOKEN_SESSIONS_CLOSED"); + break; + } +} + + +void ChangeMainWindowVisibility () +{ + MainWindowHidden = !MainWindowHidden; + + if (!MainWindowHidden) + SetForegroundWindow (MainDlg); + + ShowWindow (MainDlg, !MainWindowHidden ? SW_SHOW : SW_HIDE); + + if (!MainWindowHidden) + ShowWindow (MainDlg, SW_RESTORE); +} + + +int BackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume) +{ + int nStatus = ERR_OS_ERROR; + wchar_t szTmp[4096]; + int fBackup = -1; + OpenVolumeContext volume; + OpenVolumeContext hiddenVolume; + Password hiddenVolPassword; + byte temporaryKey[MASTER_KEYDATA_SIZE]; + byte originalK2[MASTER_KEYDATA_SIZE]; + + volume.VolumeIsOpen = FALSE; + hiddenVolume.VolumeIsOpen = FALSE; + + switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE)) + { + case 1: + case 2: + if (AskErrNoYes ("BACKUP_HEADER_NOT_FOR_SYS_DEVICE") == IDYES) + CreateRescueDisk (); + + return 0; + } + + if (IsMountedVolume (lpszVolume)) + { + Warning ("DISMOUNT_FIRST"); + goto ret; + } + + if (!VolumePathExists (lpszVolume)) + { + handleWin32Error (hwndDlg); + goto ret; + } + + Info ("EXTERNAL_VOL_HEADER_BAK_FIRST_INFO"); + + + WaitCursor(); + + // Open both types of volumes + for (int type = TC_VOLUME_TYPE_NORMAL; type <= TC_VOLUME_TYPE_HIDDEN; ++type) + { + OpenVolumeContext *askVol = (type == TC_VOLUME_TYPE_HIDDEN ? &hiddenVolume : &volume); + Password *askPassword = (type == TC_VOLUME_TYPE_HIDDEN ? &hiddenVolPassword : &VolumePassword); + + while (TRUE) + { + if (!AskVolumePassword (hwndDlg, askPassword, type == TC_VOLUME_TYPE_HIDDEN ? "ENTER_HIDDEN_VOL_PASSWORD" : "ENTER_NORMAL_VOL_PASSWORD", FALSE)) + { + nStatus = ERR_SUCCESS; + goto ret; + } + + WaitCursor(); + + if (KeyFilesEnable && FirstKeyFile) + KeyFilesApply (askPassword, FirstKeyFile); + + nStatus = OpenVolume (askVol, lpszVolume, askPassword, FALSE, bPreserveTimestamp, FALSE); + + NormalCursor(); + + if (nStatus == ERR_SUCCESS) + { + if ((type == TC_VOLUME_TYPE_NORMAL && askVol->CryptoInfo->hiddenVolume) + || (type == TC_VOLUME_TYPE_HIDDEN && !askVol->CryptoInfo->hiddenVolume)) + { + CloseVolume (askVol); + handleError (hwndDlg, ERR_PASSWORD_WRONG); + continue; + } + + RandSetHashFunction (askVol->CryptoInfo->pkcs5); + + if (type == TC_VOLUME_TYPE_NORMAL) + { + // Ask the user if there is a hidden volume + char *volTypeChoices[] = {0, "DOES_VOLUME_CONTAIN_HIDDEN", "VOLUME_CONTAINS_HIDDEN", "VOLUME_DOES_NOT_CONTAIN_HIDDEN", "IDCANCEL", 0}; + switch (AskMultiChoice ((void **) volTypeChoices, FALSE)) + { + case 1: + break; + case 2: + goto noHidden; + + default: + nStatus = ERR_SUCCESS; + goto ret; + } + } + + break; + } + + if (nStatus != ERR_PASSWORD_WRONG) + goto error; + + handleError (hwndDlg, nStatus); + } + } +noHidden: + + if (hiddenVolume.VolumeIsOpen && volume.CryptoInfo->LegacyVolume != hiddenVolume.CryptoInfo->LegacyVolume) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto error; + } + + swprintf (szTmp, GetString ("CONFIRM_VOL_HEADER_BAK"), lpszVolume); + + if (bRequireConfirmation + && (MessageBoxW (hwndDlg, szTmp, lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON1) == IDNO)) + goto ret; + + /* Select backup file */ + if (!BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, TRUE, NULL)) + goto ret; + + /* Conceive the backup file */ + if ((fBackup = _open(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + // Backup headers + + byte backup[TC_VOLUME_HEADER_GROUP_SIZE]; + + bool legacyVolume = volume.CryptoInfo->LegacyVolume ? true : false; + int backupFileSize = legacyVolume ? TC_VOLUME_HEADER_SIZE_LEGACY * 2 : TC_VOLUME_HEADER_GROUP_SIZE; + + // Fill backup buffer with random data + memcpy (originalK2, volume.CryptoInfo->k2, sizeof (volume.CryptoInfo->k2)); + + if (Randinit() != ERR_SUCCESS) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto error; + } + + NormalCursor(); + UserEnrichRandomPool (hwndDlg); + WaitCursor(); + + // Temporary keys + if (!RandgetBytes (temporaryKey, EAGetKeySize (volume.CryptoInfo->ea), TRUE) + || !RandgetBytes (volume.CryptoInfo->k2, sizeof (volume.CryptoInfo->k2), FALSE)) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto error; + } + + if (EAInit (volume.CryptoInfo->ea, temporaryKey, volume.CryptoInfo->ks) != ERR_SUCCESS || !EAInitMode (volume.CryptoInfo)) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto error; + } + + EncryptBuffer (backup, backupFileSize, volume.CryptoInfo); + + memcpy (volume.CryptoInfo->k2, originalK2, sizeof (volume.CryptoInfo->k2)); + if (EAInit (volume.CryptoInfo->ea, volume.CryptoInfo->master_keydata, volume.CryptoInfo->ks) != ERR_SUCCESS || !EAInitMode (volume.CryptoInfo)) + { + nStatus = ERR_PARAMETER_INCORRECT; + goto error; + } + + // Store header encrypted with a new key + nStatus = ReEncryptVolumeHeader ((char *) backup, FALSE, volume.CryptoInfo, &VolumePassword, FALSE); + if (nStatus != ERR_SUCCESS) + goto error; + + if (hiddenVolume.VolumeIsOpen) + { + nStatus = ReEncryptVolumeHeader ((char *) backup + (legacyVolume ? TC_VOLUME_HEADER_SIZE_LEGACY : TC_VOLUME_HEADER_SIZE), + FALSE, hiddenVolume.CryptoInfo, &hiddenVolPassword, FALSE); + + if (nStatus != ERR_SUCCESS) + goto error; + } + + if (_write (fBackup, backup, backupFileSize) == -1) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + /* Backup has been successfully created */ + Warning("VOL_HEADER_BACKED_UP"); + +ret: + nStatus = ERR_SUCCESS; + +error: + DWORD dwError = GetLastError (); + + CloseVolume (&volume); + CloseVolume (&hiddenVolume); + + if (fBackup != -1) + _close (fBackup); + + SetLastError (dwError); + if (nStatus != 0) + handleError (hwndDlg, nStatus); + + burn (&VolumePassword, sizeof (VolumePassword)); + burn (&hiddenVolPassword, sizeof (hiddenVolPassword)); + burn (temporaryKey, sizeof (temporaryKey)); + burn (originalK2, sizeof (originalK2)); + + RestoreDefaultKeyFilesParam(); + RandStop (FALSE); + NormalCursor(); + + return nStatus; +} + + +int RestoreVolumeHeader (HWND hwndDlg, char *lpszVolume) +{ + int nDosLinkCreated = -1, nStatus = ERR_OS_ERROR; + char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; + char szFileName[TC_MAX_PATH]; + char szDosDevice[TC_MAX_PATH]; + void *dev = INVALID_HANDLE_VALUE; + DWORD dwError; + BOOL bDevice; + unsigned __int64 hostSize = 0; + FILETIME ftCreationTime; + FILETIME ftLastWriteTime; + FILETIME ftLastAccessTime; + wchar_t szTmp[4096]; + BOOL bTimeStampValid = FALSE; + HANDLE fBackup = INVALID_HANDLE_VALUE; + LARGE_INTEGER headerOffset; + CRYPTO_INFO *restoredCryptoInfo = NULL; + + switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE)) + { + case 1: + case 2: + if (AskErrNoYes ("RESTORE_HEADER_NOT_FOR_SYS_DEVICE") == IDYES) + CreateRescueDisk (); + + return 0; + + case -1: + // In some environments (such as PE), the system volume is not located on a hard drive. + // Therefore, we must interpret this return code as "Not a system device path" (otherwise, + // it would not be possible to restore headers on non-system devices in such environments). + // Note that this is rather safe, because bReliableRequired is set to TRUE. + + // NOP + break; + } + + if (IsMountedVolume (lpszVolume)) + { + Warning ("DISMOUNT_FIRST"); + return 0; + } + + if (!VolumePathExists (lpszVolume)) + { + handleWin32Error (hwndDlg); + return 0; + } + + BOOL restoreInternalBackup; + + // Ask the user to select the type of backup (internal/external) + char *volTypeChoices[] = {0, "HEADER_RESTORE_EXTERNAL_INTERNAL", "HEADER_RESTORE_INTERNAL", "HEADER_RESTORE_EXTERNAL", "IDCANCEL", 0}; + switch (AskMultiChoice ((void **) volTypeChoices, FALSE)) + { + case 1: + restoreInternalBackup = TRUE; + break; + case 2: + restoreInternalBackup = FALSE; + break; + default: + return 0; + } + + OpenVolumeContext volume; + volume.VolumeIsOpen = FALSE; + + WaitCursor(); + + if (restoreInternalBackup) + { + // Restore header from the internal backup + + // Open the volume using backup header + while (TRUE) + { + strncpy (PasswordDlgVolume, lpszVolume, sizeof (PasswordDlgVolume)); + if (!AskVolumePassword (hwndDlg, &VolumePassword, NULL, FALSE)) + { + nStatus = ERR_SUCCESS; + goto ret; + } + + WaitCursor(); + + if (KeyFilesEnable && FirstKeyFile) + KeyFilesApply (&VolumePassword, FirstKeyFile); + + nStatus = OpenVolume (&volume, lpszVolume, &VolumePassword, TRUE, bPreserveTimestamp, TRUE); + + NormalCursor(); + + if (nStatus == ERR_SUCCESS) + break; + + if (nStatus != ERR_PASSWORD_WRONG) + goto error; + + handleError (hwndDlg, nStatus); + } + + if (volume.CryptoInfo->LegacyVolume) + { + Error ("VOLUME_HAS_NO_BACKUP_HEADER"); + nStatus = ERROR_SUCCESS; + goto error; + } + + // Create a new header with a new salt + char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + + nStatus = ReEncryptVolumeHeader (buffer, FALSE, volume.CryptoInfo, &VolumePassword, FALSE); + if (nStatus != 0) + goto error; + + headerOffset.QuadPart = volume.CryptoInfo->hiddenVolume ? TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_VOLUME_HEADER_OFFSET; + if (!SetFilePointerEx (volume.HostFileHandle, headerOffset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + DWORD bytesWritten; + if (!WriteFile (volume.HostFileHandle, buffer, sizeof (buffer), &bytesWritten, NULL)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + } + else + { + // Restore header from an external backup + + swprintf (szTmp, GetString ("CONFIRM_VOL_HEADER_RESTORE"), lpszVolume); + + if (MessageBoxW (hwndDlg, szTmp, lpszTitle, YES_NO|MB_ICONWARNING|MB_DEFBUTTON2) == IDNO) + { + nStatus = ERR_SUCCESS; + goto ret; + } + + /* Select backup file */ + if (!BrowseFiles (hwndDlg, "OPEN_TITLE", szFileName, bHistory, FALSE, NULL)) + { + nStatus = ERR_SUCCESS; + goto ret; + } + + /* Open the backup file */ + fBackup = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (fBackup == INVALID_HANDLE_VALUE) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + // Determine size of the backup file + LARGE_INTEGER backupSize; + if (!GetFileSizeEx (fBackup, &backupSize)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice); + + if (bDevice == FALSE) + strcpy (szCFDevice, szDiskFile); + else + { + nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE); + if (nDosLinkCreated != 0) + goto error; + } + + // Open the volume + dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if (dev == INVALID_HANDLE_VALUE) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + // Determine volume host size + if (bDevice) + { + PARTITION_INFORMATION diskInfo; + DWORD dwResult; + BOOL bResult; + + bResult = GetPartitionInfo (lpszVolume, &diskInfo); + + if (bResult) + { + hostSize = diskInfo.PartitionLength.QuadPart; + } + else + { + DISK_GEOMETRY driveInfo; + + bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, + &driveInfo, sizeof (driveInfo), &dwResult, NULL); + + if (!bResult) + goto error; + + hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * + driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; + } + + if (hostSize == 0) + { + nStatus = ERR_VOL_SIZE_WRONG; + goto error; + } + } + else + { + LARGE_INTEGER fileSize; + if (!GetFileSizeEx (dev, &fileSize)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + hostSize = fileSize.QuadPart; + } + + if (!bDevice && bPreserveTimestamp) + { + /* Remember the container modification/creation date and time. */ + + if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) + { + bTimeStampValid = FALSE; + Warning ("GETFILETIME_FAILED_GENERIC"); + } + else + bTimeStampValid = TRUE; + } + + /* Read the volume header from the backup file */ + char buffer[TC_VOLUME_HEADER_GROUP_SIZE]; + + DWORD bytesRead; + if (!ReadFile (fBackup, buffer, sizeof (buffer), &bytesRead, NULL)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + if (bytesRead != backupSize.QuadPart) + { + nStatus = ERR_VOL_SIZE_WRONG; + goto error; + } + + LARGE_INTEGER headerOffset; + LARGE_INTEGER headerBackupOffset; + bool legacyBackup; + int headerOffsetBackupFile; + int headerSize; + + // Determine the format of the backup file + switch (backupSize.QuadPart) + { + case TC_VOLUME_HEADER_GROUP_SIZE: + headerSize = TC_VOLUME_HEADER_EFFECTIVE_SIZE; + legacyBackup = false; + break; + + case TC_VOLUME_HEADER_SIZE_LEGACY * 2: + headerSize = TC_VOLUME_HEADER_SIZE_LEGACY; + legacyBackup = true; + break; + + default: + Error ("HEADER_BACKUP_SIZE_INCORRECT"); + nStatus = ERR_SUCCESS; + goto error; + } + + // Open the header + while (TRUE) + { + if (!AskVolumePassword (hwndDlg, &VolumePassword, "ENTER_HEADER_BACKUP_PASSWORD", FALSE)) + { + nStatus = ERR_SUCCESS; + goto ret; + } + + if (KeyFilesEnable && FirstKeyFile) + KeyFilesApply (&VolumePassword, FirstKeyFile); + + // Decrypt volume header + headerOffsetBackupFile = 0; + for (int type = TC_VOLUME_TYPE_NORMAL; type <= TC_VOLUME_TYPE_HIDDEN; ++type) + { + if (type == TC_VOLUME_TYPE_HIDDEN) + headerOffsetBackupFile += (legacyBackup ? TC_VOLUME_HEADER_SIZE_LEGACY : TC_VOLUME_HEADER_SIZE); + + nStatus = ReadVolumeHeader (FALSE, buffer + headerOffsetBackupFile, &VolumePassword, &restoredCryptoInfo, NULL); + if (nStatus == ERR_SUCCESS) + break; + } + + if (nStatus == ERR_SUCCESS) + break; + + if (nStatus != ERR_PASSWORD_WRONG) + goto error; + + handleError (hwndDlg, nStatus); + } + + BOOL hiddenVol = restoredCryptoInfo->hiddenVolume; + + if (legacyBackup) + { + headerOffset.QuadPart = hiddenVol ? hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY : TC_VOLUME_HEADER_OFFSET; + } + else + { + headerOffset.QuadPart = hiddenVol ? TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_VOLUME_HEADER_OFFSET; + headerBackupOffset.QuadPart = hiddenVol ? hostSize - TC_VOLUME_HEADER_SIZE : hostSize - TC_VOLUME_HEADER_GROUP_SIZE; + } + + WaitCursor(); + + // Restore header encrypted with a new key + ReEncryptVolumeHeader (buffer, FALSE, restoredCryptoInfo, &VolumePassword, FALSE); + + if (!SetFilePointerEx (dev, headerOffset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + DWORD bytesWritten; + if (!WriteFile (dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &bytesWritten, NULL)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + if (!restoredCryptoInfo->LegacyVolume) + { + // Restore backup header encrypted with a new key + ReEncryptVolumeHeader (buffer, FALSE, restoredCryptoInfo, &VolumePassword, FALSE); + + if (!SetFilePointerEx (dev, headerBackupOffset, NULL, FILE_BEGIN)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + + if (!WriteFile (dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE, &bytesWritten, NULL)) + { + nStatus = ERR_OS_ERROR; + goto error; + } + } + } + + + /* Volume header has been successfully restored */ + + Info("VOL_HEADER_RESTORED"); +ret: + nStatus = ERR_SUCCESS; + +error: + dwError = GetLastError (); + NormalCursor(); + + if (restoreInternalBackup) + { + CloseVolume (&volume); + } + else + { + if (restoredCryptoInfo) + crypto_close (restoredCryptoInfo); + + if (bTimeStampValid) + { + // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). + if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) + MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); + } + + if (dev != INVALID_HANDLE_VALUE) + CloseHandle (dev); + + if (fBackup != INVALID_HANDLE_VALUE) + CloseHandle (fBackup); + + if (nDosLinkCreated == 0) + RemoveFakeDosName (szDiskFile, szDosDevice); + } + + SetLastError (dwError); + if (nStatus != 0) + handleError (hwndDlg, nStatus); + + burn (&VolumePassword, sizeof (VolumePassword)); + RestoreDefaultKeyFilesParam(); + RandStop (FALSE); + NormalCursor(); + + return nStatus; +} + + +uint32 ReadDriverConfigurationFlags () +{ + return BootEncObj->ReadDriverConfigurationFlags(); +} + + +void SetDriverConfigurationFlag (uint32 flag, BOOL state) +{ + BootEncObj->SetDriverConfigurationFlag (flag, state ? true : false); +} + + +static BOOL CALLBACK SecurityTokenPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + LocalizeDialog (hwndDlg, "IDD_TOKEN_PREFERENCES"); + SetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, SecurityTokenLibraryPath); + CheckDlgButton (hwndDlg, IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT, CloseSecurityTokenSessionsAfterMount ? BST_CHECKED : BST_UNCHECKED); + + SetWindowTextW (GetDlgItem (hwndDlg, IDT_PKCS11_LIB_HELP), GetString("PKCS11_LIB_LOCATION_HELP")); + + return 0; + + case WM_COMMAND: + + switch (lw) + { + case IDCANCEL: + EndDialog (hwndDlg, lw); + return 1; + + case IDOK: + { + char securityTokenLibraryPath[MAX_PATH]; + GetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, securityTokenLibraryPath, sizeof (securityTokenLibraryPath)); + + if (securityTokenLibraryPath[0] == 0) + { + try + { + SecurityToken::CloseLibrary(); + } + catch (...) { } + + SecurityTokenLibraryPath[0] = 0; + } + else + { + char prevSecurityTokenLibraryPath[MAX_PATH]; + strcpy (prevSecurityTokenLibraryPath, SecurityTokenLibraryPath); + strcpy (SecurityTokenLibraryPath, securityTokenLibraryPath); + + if (!InitSecurityTokenLibrary()) + { + strcpy (SecurityTokenLibraryPath, prevSecurityTokenLibraryPath); + return 1; + } + } + + CloseSecurityTokenSessionsAfterMount = (IsDlgButtonChecked (hwndDlg, IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT) == BST_CHECKED); + + WaitCursor (); + SaveSettings (hwndDlg); + NormalCursor (); + + EndDialog (hwndDlg, lw); + return 1; + } + + case IDC_AUTO_DETECT_PKCS11_MODULE: + { + char systemDir[MAX_PATH]; + GetSystemDirectory (systemDir, sizeof (systemDir)); + WIN32_FIND_DATA findData; + bool found = false; + + WaitCursor(); + + HANDLE find = FindFirstFile ((string (systemDir) + "\\*.dll").c_str(), &findData); + while (!found && find != INVALID_HANDLE_VALUE) + { + string dllPathname = string (systemDir) + "\\" + findData.cFileName; + DWORD fileSize; + + char *file = LoadFile (dllPathname.c_str(), &fileSize); + if (file) + { + const char *functionName = "C_GetFunctionList"; + size_t strLen = strlen (functionName); + + if (fileSize > strLen) + { + for (size_t i = 0; i < fileSize - strLen; ++i) + { + if (memcmp (file + i, functionName, strLen) == 0) + { + HMODULE module = LoadLibrary (dllPathname.c_str()); + if (module) + { + if (GetProcAddress (module, functionName)) + { + SetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, dllPathname.c_str()); + found = true; + + FreeLibrary (module); + break; + } + + FreeLibrary (module); + } + } + } + } + + free (file); + } + + if (!FindNextFile (find, &findData)) + break; + } + + if (find != INVALID_HANDLE_VALUE) + FindClose (find); + + NormalCursor(); + + if (!found) + Warning ("PKCS11_MODULE_AUTO_DETECTION_FAILED"); + + return 1; + } + + case IDC_SELECT_PKCS11_MODULE: + { + char securityTokenLibraryPath[MAX_PATH]; + char systemDir[MAX_PATH]; + wchar_t browseFilter[1024]; + + Info ("SELECT_PKCS11_MODULE_HELP"); + + wsprintfW (browseFilter, L"%ls (*.dll)%c*.dll%c%c", GetString ("DLL_FILES"), 0, 0, 0); + GetSystemDirectory (systemDir, sizeof (systemDir)); + + if (BrowseFilesInDir (hwndDlg, "SELECT_PKCS11_MODULE", systemDir, securityTokenLibraryPath, TRUE, FALSE, browseFilter)) + SetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, securityTokenLibraryPath); + return 1; + } + } + return 0; + } + + return 0; +} + + +void SecurityTokenPreferencesDialog (HWND hwndDlg) +{ + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PREFERENCES), hwndDlg, (DLGPROC) SecurityTokenPreferencesDlgProc, 0); +} + + +static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + if (!BootEncObj->GetStatus().DriveMounted) + { + Warning ("SYS_DRIVE_NOT_ENCRYPTED"); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + try + { + LocalizeDialog (hwndDlg, "IDD_SYSENC_SETTINGS"); + + uint32 driverConfig = ReadDriverConfigurationFlags(); + byte userConfig; + string customUserMessage; + uint16 bootLoaderVersion; + + BootEncObj->ReadBootSectorConfig (nullptr, 0, &userConfig, &customUserMessage, &bootLoaderVersion); + + if (bootLoaderVersion != VERSION_NUM) + Warning ("BOOT_LOADER_VERSION_INCORRECT_PREFERENCES"); + + SendMessage (GetDlgItem (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE), EM_LIMITTEXT, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, 0); + SetDlgItemText (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE, customUserMessage.c_str()); + + CheckDlgButton (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT, (userConfig & TC_BOOT_USER_CFG_FLAG_SILENT_MODE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hwndDlg, IDC_ALLOW_ESC_PBA_BYPASS, (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_ESC) ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton (hwndDlg, IDC_BOOT_LOADER_CACHE_PASSWORD, (driverConfig & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD) ? BST_CHECKED : BST_UNCHECKED); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE_HELP), GetString("CUSTOM_BOOT_LOADER_MESSAGE_HELP")); + } + catch (Exception &e) + { + e.Show (hwndDlg); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + } + return 0; + + case WM_COMMAND: + + switch (lw) + { + case IDCANCEL: + EndDialog (hwndDlg, lw); + return 1; + + case IDOK: + { + if (!BootEncObj->GetStatus().DriveMounted) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + char customUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH + 1]; + GetDlgItemText (hwndDlg, IDC_CUSTOM_BOOT_LOADER_MESSAGE, customUserMessage, sizeof (customUserMessage)); + + byte userConfig = 0; + if (IsDlgButtonChecked (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT)) + userConfig |= TC_BOOT_USER_CFG_FLAG_SILENT_MODE; + + if (!IsDlgButtonChecked (hwndDlg, IDC_ALLOW_ESC_PBA_BYPASS)) + userConfig |= TC_BOOT_USER_CFG_FLAG_DISABLE_ESC; + + try + { + BootEncObj->WriteBootSectorUserConfig (userConfig, customUserMessage); + SetDriverConfigurationFlag (TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD, IsDlgButtonChecked (hwndDlg, IDC_BOOT_LOADER_CACHE_PASSWORD)); + } + catch (Exception &e) + { + e.Show (hwndDlg); + return 1; + } + + EndDialog (hwndDlg, lw); + return 1; + } + + case IDC_DISABLE_BOOT_LOADER_OUTPUT: + if ((IsDlgButtonChecked (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT)) + && AskWarnYesNo ("CUSTOM_BOOT_LOADER_MESSAGE_PROMPT") == IDNO) + { + CheckDlgButton (hwndDlg, IDC_DISABLE_BOOT_LOADER_OUTPUT, BST_UNCHECKED); + } + + break; + + case IDC_BOOT_LOADER_CACHE_PASSWORD: + if (IsDlgButtonChecked (hwndDlg, IDC_BOOT_LOADER_CACHE_PASSWORD)) + Warning ("BOOT_PASSWORD_CACHE_KEYBOARD_WARNING"); + + break; + } + return 0; + } + + return 0; +} + + +static BOOL CALLBACK SystemFavoritesSettingsDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + if (!BootEncObj->GetStatus().DriveMounted) + { + Warning ("SYS_FAVORITES_REQUIRE_PBA"); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + LocalizeDialog (hwndDlg, "IDD_SYS_FAVORITES_SETTINGS"); + + uint32 driverConfig = ReadDriverConfigurationFlags(); + + CheckDlgButton (hwndDlg, IDC_MOUNT_SYSTEM_FAVORITES_ON_BOOT, (driverConfig & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hwndDlg, IDC_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS, (driverConfig & TC_DRIVER_CONFIG_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS) ? BST_CHECKED : BST_UNCHECKED); + } + return 0; + + case WM_COMMAND: + + switch (lw) + { + case IDCANCEL: + EndDialog (hwndDlg, lw); + return 1; + + case IDOK: + { + if (!BootEncObj->GetStatus().DriveMounted) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + try + { + uint32 reqConfig = IsDlgButtonChecked (hwndDlg, IDC_MOUNT_SYSTEM_FAVORITES_ON_BOOT) ? TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES : 0; + if (reqConfig != (ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES)) + BootEncObj->RegisterSystemFavoritesService (reqConfig ? TRUE : FALSE); + + SetDriverConfigurationFlag (TC_DRIVER_CONFIG_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS, IsDlgButtonChecked (hwndDlg, IDC_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS)); + } + catch (Exception &e) + { + e.Show (hwndDlg); + return 1; + } + + EndDialog (hwndDlg, lw); + return 1; + } + + case IDC_MOUNT_SYSTEM_FAVORITES_ON_BOOT: + if (IsDlgButtonChecked (hwndDlg, IDC_MOUNT_SYSTEM_FAVORITES_ON_BOOT)) + WarningDirect ((wstring (GetString ("SYS_FAVORITES_KEYBOARD_WARNING")) + L"\n\n" + GetString ("BOOT_PASSWORD_CACHE_KEYBOARD_WARNING")).c_str()); + + break; + + case IDC_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS: + if (IsDlgButtonChecked (hwndDlg, IDC_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS)) + WarningDirect ((wstring (GetString ("SYS_FAVORITES_ADMIN_ONLY_WARNING")) + L"\n\n" + GetString ("SETTING_REQUIRES_REBOOT")).c_str()); + else + Warning ("SETTING_REQUIRES_REBOOT"); + + break; + } + return 0; + } + + return 0; +} + + +void MountSelectedVolume (HWND hwndDlg, BOOL mountWithOptions) +{ + if (!VolumeSelected(hwndDlg)) + { + Warning ("NO_VOLUME_SELECTED"); + } + else if (LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST))) == TC_MLIST_ITEM_FREE) + { + mountOptions = defaultMountOptions; + bPrebootPasswordDlgMode = FALSE; + + if (mountWithOptions || GetAsyncKeyState (VK_CONTROL) < 0) + { + if (IDCANCEL == DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg, + (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions)) + return; + + if (mountOptions.ProtectHiddenVolume && hidVolProtKeyFilesParam.EnableKeyFiles) + KeyFilesApply (&mountOptions.ProtectedHidVolPassword, hidVolProtKeyFilesParam.FirstKeyFile); + } + + if (CheckMountList ()) + Mount (hwndDlg, 0, 0); + } + else + Warning ("SELECT_FREE_DRIVE"); +} diff --git a/Mount/Mount.h b/Mount/Mount.h index fd5dfe8..819ae3c 100644 --- a/Mount/Mount.h +++ b/Mount/Mount.h @@ -1,107 +1,102 @@ -/* - Legal Notice: Some portions of the source code contained in this file were - derived from the source code of Encryption for the Masses 2.02a, which is - Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License - Agreement for Encryption for the Masses'. Modifications and additions to - the original source code (contained in this file) and all other portions of - this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed - by the TrueCrypt License 2.7 the full text of which is contained in the - file License.txt included in TrueCrypt binary and source code distribution - packages. */ - -#ifdef __cplusplus -extern "C" { -#endif - -enum mount_list_item_types -{ - TC_MLIST_ITEM_FREE = 0, - TC_MLIST_ITEM_NONSYS_VOL, - TC_MLIST_ITEM_SYS_PARTITION, - TC_MLIST_ITEM_SYS_DRIVE -}; - -#define TRAYICON_MENU_DRIVE_OFFSET 9000 - -#define WM_COPY_SET_VOLUME_NAME "VNAM" - -#define ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER ('A' - 1) - -/* Password Change dialog modes */ -enum -{ - PCDM_CHANGE_PASSWORD = 0, - PCDM_CHANGE_PKCS5_PRF, - PCDM_ADD_REMOVE_VOL_KEYFILES, - PCDM_REMOVE_ALL_KEYFILES_FROM_VOL -}; - -typedef struct -{ - BOOL bHidVolDamagePrevReported[26]; -} VOLUME_NOTIFICATIONS_LIST; - - -typedef struct -{ - BOOL CacheBootPassword; -} DriverConfiguration; - - -extern VOLUME_NOTIFICATIONS_LIST VolumeNotificationsList; - -extern BOOL bPlaySoundOnHotkeyMountDismount; -extern BOOL bDisplayMsgBoxOnHotkeyDismount; - -void localcleanup ( void ); -void EndMainDlg ( HWND hwndDlg ); -void EnableDisableButtons ( HWND hwndDlg ); -BOOL VolumeSelected (HWND hwndDlg ); -void LoadSettings ( HWND hwndDlg ); -void SaveSettings ( HWND hwndDlg ); -BOOL SelectItem ( HWND hTree , char nLetter ); -void LoadDriveLetters ( HWND hTree, int drive ); -BOOL CALLBACK PasswordChangeDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); -BOOL CALLBACK PasswordDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); -BOOL CALLBACK MountOptionsDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -void BuildTree ( HWND hTree ); -LPARAM GetSelectedLong ( HWND hTree ); -LPARAM GetItemLong ( HWND hTree, int itemNo ); -BOOL CALLBACK CommandHelpDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); -BOOL CALLBACK MainDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); -void ExtractCommandLine ( HWND hwndDlg , char *lpszCommandLine ); -int WINAPI WINMAIN ( HINSTANCE hInstance , HINSTANCE hPrevInstance , char *lpszCommandLine , int nCmdShow ); -void WipeCache (HWND hwndDlg, BOOL silent); -void OpenVolumeExplorerWindow (int driveNo); -BOOL TaskBarIconAdd (HWND hwnd); -BOOL TaskBarIconRemove (HWND hwnd); -void DismountIdleVolumes (); -BOOL MountFavoriteVolumes (); -void SaveFavoriteVolumes (); -static void SaveDefaultKeyFilesParam (void); -static BOOL Dismount (HWND hwndDlg, int nDosDriveNo); -static BOOL DismountAll (HWND hwndDlg, BOOL forceUnmount, BOOL interact, int dismountMaxRetries, int dismountAutoRetryDelay); -static void KeyfileDefaultsDlg (HWND hwndDlg); -static void HandleHotKey (HWND hwndDlg, WPARAM wParam); -static BOOL CheckMountList (); -int GetCipherBlockSizeByDriveNo (int nDosDriveNo); -int GetModeOfOperationByDriveNo (int nDosDriveNo); -void ChangeMainWindowVisibility (); -void LaunchVolCreationWizard (HWND hwndDlg); -BOOL WholeSysDriveEncryption (BOOL bSilent); -BOOL CheckSysEncMountWithoutPBA (const char *devicePath, BOOL quiet); -BOOL TCBootLoaderOnInactiveSysEncDrive (void); -void CreateRescueDisk (void); -int BackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume); -int RestoreVolumeHeader (HWND hwndDlg, char *lpszVolume); -void SecurityTokenPreferencesDialog (HWND hwndDlg); -static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -void MountSelectedVolume (HWND hwndDlg, BOOL mountWithOptions); - -#ifdef __cplusplus -} - -void ReadDriverConfiguration (DriverConfiguration *configuration); -void WriteDriverConfiguration (DriverConfiguration *configuration); - -#endif +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.8 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum mount_list_item_types +{ + TC_MLIST_ITEM_FREE = 0, + TC_MLIST_ITEM_NONSYS_VOL, + TC_MLIST_ITEM_SYS_PARTITION, + TC_MLIST_ITEM_SYS_DRIVE +}; + +#define TC_MAIN_WINDOW_FLAG_ADMIN_PRIVILEGES 0x1 + +#define TRAYICON_MENU_DRIVE_OFFSET 9000 + +#define WM_COPY_SET_VOLUME_NAME "VNAM" + +#define ENC_SYSDRIVE_PSEUDO_DRIVE_LETTER ('A' - 1) + +/* Password Change dialog modes */ +enum +{ + PCDM_CHANGE_PASSWORD = 0, + PCDM_CHANGE_PKCS5_PRF, + PCDM_ADD_REMOVE_VOL_KEYFILES, + PCDM_REMOVE_ALL_KEYFILES_FROM_VOL +}; + +typedef struct +{ + BOOL bHidVolDamagePrevReported[26]; +} VOLUME_NOTIFICATIONS_LIST; + + +extern VOLUME_NOTIFICATIONS_LIST VolumeNotificationsList; + +extern BOOL bPlaySoundOnHotkeyMountDismount; +extern BOOL bDisplayMsgBoxOnHotkeyDismount; + +static void localcleanup ( void ); +void EndMainDlg ( HWND hwndDlg ); +void EnableDisableButtons ( HWND hwndDlg ); +BOOL VolumeSelected (HWND hwndDlg ); +void LoadSettings ( HWND hwndDlg ); +void SaveSettings ( HWND hwndDlg ); +BOOL SelectItem ( HWND hTree , char nLetter ); +void LoadDriveLetters ( HWND hTree, int drive ); +BOOL CALLBACK PasswordChangeDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); +BOOL CALLBACK PasswordDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); +BOOL CALLBACK MountOptionsDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +void BuildTree ( HWND hTree ); +LPARAM GetSelectedLong ( HWND hTree ); +LPARAM GetItemLong ( HWND hTree, int itemNo ); +BOOL CALLBACK CommandHelpDlgProc ( HWND hwndDlg , UINT msg , WPARAM wParam , LPARAM lParam ); +BOOL CALLBACK MainDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ); +void ExtractCommandLine ( HWND hwndDlg , char *lpszCommandLine ); +static void WipeCache (HWND hwndDlg, BOOL silent); +void OpenVolumeExplorerWindow (int driveNo); +BOOL TaskBarIconAdd (HWND hwnd); +BOOL TaskBarIconRemove (HWND hwnd); +void DismountIdleVolumes (); +BOOL MountFavoriteVolumes (BOOL systemFavorites); +void SaveFavoriteVolumes (BOOL systemFavorites); +static void SaveDefaultKeyFilesParam (void); +static BOOL Dismount (HWND hwndDlg, int nDosDriveNo); +static BOOL DismountAll (HWND hwndDlg, BOOL forceUnmount, BOOL interact, int dismountMaxRetries, int dismountAutoRetryDelay); +static void KeyfileDefaultsDlg (HWND hwndDlg); +static void HandleHotKey (HWND hwndDlg, WPARAM wParam); +static BOOL CheckMountList (); +int GetCipherBlockSizeByDriveNo (int nDosDriveNo); +int GetModeOfOperationByDriveNo (int nDosDriveNo); +void ChangeMainWindowVisibility (); +void LaunchVolCreationWizard (HWND hwndDlg); +BOOL WholeSysDriveEncryption (BOOL bSilent); +BOOL CheckSysEncMountWithoutPBA (const char *devicePath, BOOL quiet); +BOOL TCBootLoaderOnInactiveSysEncDrive (void); +void CreateRescueDisk (void); +int BackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume); +int RestoreVolumeHeader (HWND hwndDlg, char *lpszVolume); +void SecurityTokenPreferencesDialog (HWND hwndDlg); +static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK SystemFavoritesSettingsDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +void MountSelectedVolume (HWND hwndDlg, BOOL mountWithOptions); +uint32 ReadDriverConfigurationFlags (); +void SetDriverConfigurationFlag (uint32 flag, BOOL state); + +#ifdef __cplusplus +} + +#endif diff --git a/Mount/Mount.manifest b/Mount/Mount.manifest index 13d7582..48616cf 100644 --- a/Mount/Mount.manifest +++ b/Mount/Mount.manifest @@ -1,5 +1,5 @@ - + @@ -7,4 +7,15 @@ + + + true + + + + + + + + \ No newline at end of file diff --git a/Mount/Mount.rc b/Mount/Mount.rc index c53274d..09fc1ef 100644 --- a/Mount/Mount.rc +++ b/Mount/Mount.rc @@ -271,6 +271,20 @@ BEGIN LTEXT "",IDC_CUSTOM_BOOT_LOADER_MESSAGE_HELP,18,74,337,73 END +IDD_SYS_FAVORITES_SETTINGS DIALOGEX 0, 0, 370, 87 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "TrueCrypt - System Favorite Volumes - Options" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Mount system favorite volumes when Windows starts (in the initial phase of the start procedure)",IDC_MOUNT_SYSTEM_FAVORITES_ON_BOOT, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,23,339,10 + CONTROL "Allow only administrators to view and dismount system favorite volumes in TrueCrypt",IDC_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,39,339,10 + DEFPUSHBUTTON "OK",IDOK,257,66,50,14 + PUSHBUTTON "Cancel",IDCANCEL,313,66,50,14 + GROUPBOX "System Favorite Volumes Options",IDT_SYSTEM_FAVORITES_OPTIONS,7,6,355,53 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -344,7 +358,14 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 363 TOPMARGIN, 7 - BOTTOMMARGIN, 235 + END + + IDD_SYS_FAVORITES_SETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 363 + TOPMARGIN, 7 + BOTTOMMARGIN, 80 END END #endif // APSTUDIO_INVOKED @@ -356,8 +377,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,2,1,0 - PRODUCTVERSION 6,2,1,0 + FILEVERSION 6,3,0,0 + PRODUCTVERSION 6,3,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -374,12 +395,11 @@ BEGIN BEGIN VALUE "CompanyName", "TrueCrypt Foundation" VALUE "FileDescription", "TrueCrypt" - VALUE "FileVersion", "6.2a" - VALUE "LegalCopyright", "TrueCrypt Foundation" + VALUE "FileVersion", "6.3" VALUE "LegalTrademarks", "TrueCrypt" VALUE "OriginalFilename", "TrueCrypt.exe" VALUE "ProductName", "TrueCrypt" - VALUE "ProductVersion", "6.2a" + VALUE "ProductVersion", "6.3" END END BLOCK "VarFileInfo" @@ -441,7 +461,8 @@ BEGIN MENUITEM "Select Device...", IDM_SELECT_DEVICE MENUITEM SEPARATOR MENUITEM "Mount Favorite Volumes", IDM_MOUNT_FAVORITE_VOLUMES - MENUITEM "Save Currently Mounted Volumes as Favorite", IDM_SAVE_FAVORITE_VOLUMES + MENUITEM "Save Currently Mounted Volumes as Favorites", IDM_SAVE_FAVORITE_VOLUMES + MENUITEM "Save Currently Mounted Volumes as System Favorites", IDM_SAVE_SYSTEM_FAVORITE_VOLUMES MENUITEM SEPARATOR MENUITEM "Resume Interrupted Process", IDM_RESUME_INTERRUPTED_PROC MENUITEM SEPARATOR @@ -511,7 +532,10 @@ BEGIN BEGIN MENUITEM "Language...", IDM_LANGUAGE MENUITEM "Hot Keys...", IDM_HOTKEY_SETTINGS + MENUITEM SEPARATOR MENUITEM "System Encryption...", IDM_SYSENC_SETTINGS + MENUITEM "System Favorite Volumes...", IDM_SYS_FAVORITES_SETTINGS + MENUITEM SEPARATOR MENUITEM "Default Keyfiles...", IDM_DEFAULT_KEYFILES MENUITEM "Security Tokens...", IDM_TOKEN_PREFERENCES MENUITEM SEPARATOR diff --git a/Mount/Mount.vcproj b/Mount/Mount.vcproj index d28fcdf..68aa617 100644 --- a/Mount/Mount.vcproj +++ b/Mount/Mount.vcproj @@ -56,9 +56,9 @@ UsePrecompiledHeader="0" BrowseInformation="0" BrowseInformationFile="" - WarningLevel="3" + WarningLevel="4" DebugInformationFormat="4" - DisableSpecificWarnings="4311" + DisableSpecificWarnings="4057;4100;4127;4201;4701;4706" /> + + + + + + (Memory::Allocate (size)); - DataSize = size; - } - catch (...) - { - DataPtr = nullptr; - DataSize = 0; - throw; - } - } - - void Buffer::CopyFrom (const ConstBufferPtr &bufferPtr) - { - if (!IsAllocated ()) - Allocate (bufferPtr.Size()); - else if (bufferPtr.Size() > DataSize) - throw ParameterTooLarge (SRC_POS); - - Memory::Copy (DataPtr, bufferPtr.Get(), bufferPtr.Size()); - } - - void Buffer::Erase () - { - if (DataSize > 0) - Memory::Erase (DataPtr, DataSize); - } - - void Buffer::Free () - { - if (DataPtr == nullptr) - throw NotInitialized (SRC_POS); - - Memory::Free (DataPtr); - DataPtr = nullptr; - DataSize = 0; - } - - BufferPtr Buffer::GetRange (size_t offset, size_t size) const - { - if (offset + size > DataSize) - throw ParameterIncorrect (SRC_POS); - - return BufferPtr (DataPtr + offset, size); - } - - void Buffer::Zero () - { - if (DataSize > 0) - Memory::Zero (DataPtr, DataSize); - } - - SecureBuffer::SecureBuffer (size_t size) - { - Allocate (size); - } - - SecureBuffer::~SecureBuffer () - { - if (DataPtr != nullptr && DataSize != 0) - Free (); - } - - void SecureBuffer::Allocate (size_t size) - { - Buffer::Allocate (size); - } - - void SecureBuffer::Free () - { - if (DataPtr == nullptr) - throw NotInitialized (SRC_POS); - - Erase (); - Buffer::Free (); - } - - void BufferPtr::CopyFrom (const ConstBufferPtr &bufferPtr) const - { - if (bufferPtr.Size() > DataSize) - throw ParameterTooLarge (SRC_POS); - - Memory::Copy (DataPtr, bufferPtr.Get(), bufferPtr.Size()); - } - - BufferPtr BufferPtr::GetRange (size_t offset, size_t size) const - { - if (offset + size > DataSize) - throw ParameterIncorrect (SRC_POS); - - return BufferPtr (DataPtr + offset, size); - } - - ConstBufferPtr ConstBufferPtr::GetRange (size_t offset, size_t size) const - { - if (offset + size > DataSize) - throw ParameterIncorrect (SRC_POS); - - return ConstBufferPtr (DataPtr + offset, size); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Buffer.h" +#include "Exception.h" + +namespace TrueCrypt +{ + Buffer::Buffer () : DataPtr (nullptr), DataSize (0) + { + } + + Buffer::Buffer (size_t size) : DataPtr (nullptr), DataSize (0) + { + Allocate (size); + } + + Buffer::~Buffer () + { + if (DataPtr != nullptr) + Free (); + } + + void Buffer::Allocate (size_t size) + { + if (size < 1) + throw ParameterIncorrect (SRC_POS); + + if (DataPtr != nullptr) + { + if (DataSize == size) + return; + Free(); + } + + try + { + DataPtr = static_cast (Memory::Allocate (size)); + DataSize = size; + } + catch (...) + { + DataPtr = nullptr; + DataSize = 0; + throw; + } + } + + void Buffer::CopyFrom (const ConstBufferPtr &bufferPtr) + { + if (!IsAllocated ()) + Allocate (bufferPtr.Size()); + else if (bufferPtr.Size() > DataSize) + throw ParameterTooLarge (SRC_POS); + + Memory::Copy (DataPtr, bufferPtr.Get(), bufferPtr.Size()); + } + + void Buffer::Erase () + { + if (DataSize > 0) + Memory::Erase (DataPtr, DataSize); + } + + void Buffer::Free () + { + if (DataPtr == nullptr) + throw NotInitialized (SRC_POS); + + Memory::Free (DataPtr); + DataPtr = nullptr; + DataSize = 0; + } + + BufferPtr Buffer::GetRange (size_t offset, size_t size) const + { + if (offset + size > DataSize) + throw ParameterIncorrect (SRC_POS); + + return BufferPtr (DataPtr + offset, size); + } + + void Buffer::Zero () + { + if (DataSize > 0) + Memory::Zero (DataPtr, DataSize); + } + + SecureBuffer::SecureBuffer (size_t size) + { + Allocate (size); + } + + SecureBuffer::~SecureBuffer () + { + if (DataPtr != nullptr && DataSize != 0) + Free (); + } + + void SecureBuffer::Allocate (size_t size) + { + Buffer::Allocate (size); + } + + void SecureBuffer::Free () + { + if (DataPtr == nullptr) + throw NotInitialized (SRC_POS); + + Erase (); + Buffer::Free (); + } + + void BufferPtr::CopyFrom (const ConstBufferPtr &bufferPtr) const + { + if (bufferPtr.Size() > DataSize) + throw ParameterTooLarge (SRC_POS); + + Memory::Copy (DataPtr, bufferPtr.Get(), bufferPtr.Size()); + } + + BufferPtr BufferPtr::GetRange (size_t offset, size_t size) const + { + if (offset + size > DataSize) + throw ParameterIncorrect (SRC_POS); + + return BufferPtr (DataPtr + offset, size); + } + + ConstBufferPtr ConstBufferPtr::GetRange (size_t offset, size_t size) const + { + if (offset + size > DataSize) + throw ParameterIncorrect (SRC_POS); + + return ConstBufferPtr (DataPtr + offset, size); + } +} diff --git a/Platform/Buffer.h b/Platform/Buffer.h index 855e5d6..3336f57 100644 --- a/Platform/Buffer.h +++ b/Platform/Buffer.h @@ -1,115 +1,115 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Buffer -#define TC_HEADER_Platform_Buffer - -#include "PlatformBase.h" -#include "Memory.h" - -namespace TrueCrypt -{ - - class ConstBufferPtr - { - public: - ConstBufferPtr () - : DataPtr (nullptr), DataSize (0) { } - ConstBufferPtr (const byte *data, size_t size) - : DataPtr (data), DataSize (size) { } - virtual ~ConstBufferPtr () { } - - operator const byte * () const { return DataPtr; } - - bool IsDataEqual (const ConstBufferPtr &other) const { return Memory::Compare (DataPtr, DataSize, other.DataPtr, other.DataSize) == 0; } - const byte *Get () const { return DataPtr; } - ConstBufferPtr GetRange (size_t offset, size_t size) const; - void Set (const byte *data, size_t size) { DataPtr = data; DataSize = size; } - size_t Size () const { return DataSize; } - - protected: - const byte *DataPtr; - size_t DataSize; - }; - - - class BufferPtr - { - public: - BufferPtr () - : DataPtr (nullptr), DataSize (0) { } - BufferPtr (byte *data, size_t size) - : DataPtr (data), DataSize (size) { } - virtual ~BufferPtr () { } - - operator byte * () const { return DataPtr; } - void CopyFrom (const ConstBufferPtr &bufferPtr) const; - void Erase () const { Zero(); } - byte *Get () const { return DataPtr; } - BufferPtr GetRange (size_t offset, size_t size) const; - void Set (byte *data, size_t size) { DataPtr = data; DataSize = size; } - size_t Size () const { return DataSize; } - void Zero () const { Memory::Zero (DataPtr, DataSize); } - - operator ConstBufferPtr () const { return ConstBufferPtr (DataPtr, DataSize); } - - protected: - byte *DataPtr; - size_t DataSize; - }; - - class Buffer - { - public: - Buffer (); - Buffer (size_t size); - Buffer (const ConstBufferPtr &bufferPtr) { CopyFrom (bufferPtr); } - virtual ~Buffer (); - - virtual void Allocate (size_t size); - virtual void CopyFrom (const ConstBufferPtr &bufferPtr); - virtual byte *Ptr () const { return DataPtr; } - virtual void Erase (); - virtual void Free (); - virtual BufferPtr GetRange (size_t offset, size_t size) const; - virtual size_t Size () const { return DataSize; } - virtual bool IsAllocated () const { return DataSize != 0; } - virtual void Zero (); - - virtual operator byte * () const { return DataPtr; } - virtual operator BufferPtr () const { return BufferPtr (DataPtr, DataSize); } - virtual operator ConstBufferPtr () const { return ConstBufferPtr (DataPtr, DataSize); } - - protected: - byte *DataPtr; - size_t DataSize; - - private: - Buffer (const Buffer &); - Buffer &operator= (const Buffer &); - }; - - class SecureBuffer : public Buffer - { - public: - SecureBuffer () { } - SecureBuffer (size_t size); - SecureBuffer (const ConstBufferPtr &bufferPtr) { CopyFrom (bufferPtr); } - virtual ~SecureBuffer (); - - virtual void Allocate (size_t size); - virtual void Free (); - - private: - SecureBuffer (const SecureBuffer &); - SecureBuffer &operator= (const SecureBuffer &); - }; - -} - -#endif // TC_HEADER_Platform_Buffer +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Buffer +#define TC_HEADER_Platform_Buffer + +#include "PlatformBase.h" +#include "Memory.h" + +namespace TrueCrypt +{ + + class ConstBufferPtr + { + public: + ConstBufferPtr () + : DataPtr (nullptr), DataSize (0) { } + ConstBufferPtr (const byte *data, size_t size) + : DataPtr (data), DataSize (size) { } + virtual ~ConstBufferPtr () { } + + operator const byte * () const { return DataPtr; } + + bool IsDataEqual (const ConstBufferPtr &other) const { return Memory::Compare (DataPtr, DataSize, other.DataPtr, other.DataSize) == 0; } + const byte *Get () const { return DataPtr; } + ConstBufferPtr GetRange (size_t offset, size_t size) const; + void Set (const byte *data, size_t size) { DataPtr = data; DataSize = size; } + size_t Size () const { return DataSize; } + + protected: + const byte *DataPtr; + size_t DataSize; + }; + + + class BufferPtr + { + public: + BufferPtr () + : DataPtr (nullptr), DataSize (0) { } + BufferPtr (byte *data, size_t size) + : DataPtr (data), DataSize (size) { } + virtual ~BufferPtr () { } + + operator byte * () const { return DataPtr; } + void CopyFrom (const ConstBufferPtr &bufferPtr) const; + void Erase () const { Zero(); } + byte *Get () const { return DataPtr; } + BufferPtr GetRange (size_t offset, size_t size) const; + void Set (byte *data, size_t size) { DataPtr = data; DataSize = size; } + size_t Size () const { return DataSize; } + void Zero () const { Memory::Zero (DataPtr, DataSize); } + + operator ConstBufferPtr () const { return ConstBufferPtr (DataPtr, DataSize); } + + protected: + byte *DataPtr; + size_t DataSize; + }; + + class Buffer + { + public: + Buffer (); + Buffer (size_t size); + Buffer (const ConstBufferPtr &bufferPtr) { CopyFrom (bufferPtr); } + virtual ~Buffer (); + + virtual void Allocate (size_t size); + virtual void CopyFrom (const ConstBufferPtr &bufferPtr); + virtual byte *Ptr () const { return DataPtr; } + virtual void Erase (); + virtual void Free (); + virtual BufferPtr GetRange (size_t offset, size_t size) const; + virtual size_t Size () const { return DataSize; } + virtual bool IsAllocated () const { return DataSize != 0; } + virtual void Zero (); + + virtual operator byte * () const { return DataPtr; } + virtual operator BufferPtr () const { return BufferPtr (DataPtr, DataSize); } + virtual operator ConstBufferPtr () const { return ConstBufferPtr (DataPtr, DataSize); } + + protected: + byte *DataPtr; + size_t DataSize; + + private: + Buffer (const Buffer &); + Buffer &operator= (const Buffer &); + }; + + class SecureBuffer : public Buffer + { + public: + SecureBuffer () { } + SecureBuffer (size_t size); + SecureBuffer (const ConstBufferPtr &bufferPtr) { CopyFrom (bufferPtr); } + virtual ~SecureBuffer (); + + virtual void Allocate (size_t size); + virtual void Free (); + + private: + SecureBuffer (const SecureBuffer &); + SecureBuffer &operator= (const SecureBuffer &); + }; + +} + +#endif // TC_HEADER_Platform_Buffer diff --git a/Platform/Directory.h b/Platform/Directory.h index 259448a..5453194 100644 --- a/Platform/Directory.h +++ b/Platform/Directory.h @@ -1,29 +1,29 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Directory -#define TC_HEADER_Platform_Directory - -#include "PlatformBase.h" -#include "FilesystemPath.h" - -namespace TrueCrypt -{ - class Directory - { - public: - static void Create (const DirectoryPath &path); - static DirectoryPath AppendSeparator (const DirectoryPath &path); - static FilePathList GetFilePaths (const DirectoryPath &path = L".", bool regularFilesOnly = true); - - private: - Directory (); - }; -} - -#endif // TC_HEADER_Platform_Directory +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Directory +#define TC_HEADER_Platform_Directory + +#include "PlatformBase.h" +#include "FilesystemPath.h" + +namespace TrueCrypt +{ + class Directory + { + public: + static void Create (const DirectoryPath &path); + static DirectoryPath AppendSeparator (const DirectoryPath &path); + static FilePathList GetFilePaths (const DirectoryPath &path = L".", bool regularFilesOnly = true); + + private: + Directory (); + }; +} + +#endif // TC_HEADER_Platform_Directory diff --git a/Platform/Event.cpp b/Platform/Event.cpp index 8b0787a..d29b06f 100644 --- a/Platform/Event.cpp +++ b/Platform/Event.cpp @@ -1,47 +1,47 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Event.h" - -namespace TrueCrypt -{ - void Event::Connect (const EventConnectorBase &connector) - { - ScopeLock lock (HandlersMutex); - ConnectedHandlers.push_back (shared_ptr (connector.CloneNew())); - } - - void Event::Disconnect (void *handler) - { - ScopeLock lock (HandlersMutex); - - EventHandlerList newConnectedHandlers; - foreach (shared_ptr h, ConnectedHandlers) - { - if (h->GetHandler() != handler) - newConnectedHandlers.push_back (h); - } - - ConnectedHandlers = newConnectedHandlers; - } - - void Event::Raise () - { - EventArgs args; - Raise (args); - } - - void Event::Raise (EventArgs &args) - { - ScopeLock lock (HandlersMutex); - foreach_ref (EventConnectorBase &handler, ConnectedHandlers) - { - handler (args); - } - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Event.h" + +namespace TrueCrypt +{ + void Event::Connect (const EventConnectorBase &connector) + { + ScopeLock lock (HandlersMutex); + ConnectedHandlers.push_back (shared_ptr (connector.CloneNew())); + } + + void Event::Disconnect (void *handler) + { + ScopeLock lock (HandlersMutex); + + EventHandlerList newConnectedHandlers; + foreach (shared_ptr h, ConnectedHandlers) + { + if (h->GetHandler() != handler) + newConnectedHandlers.push_back (h); + } + + ConnectedHandlers = newConnectedHandlers; + } + + void Event::Raise () + { + EventArgs args; + Raise (args); + } + + void Event::Raise (EventArgs &args) + { + ScopeLock lock (HandlersMutex); + foreach_ref (EventConnectorBase &handler, ConnectedHandlers) + { + handler (args); + } + } +} diff --git a/Platform/Event.h b/Platform/Event.h index 7648579..29c0a7c 100644 --- a/Platform/Event.h +++ b/Platform/Event.h @@ -1,86 +1,86 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Event -#define TC_HEADER_Platform_Event - -#include "PlatformBase.h" -#include "ForEach.h" -#include "Mutex.h" -#include "SharedPtr.h" - -namespace TrueCrypt -{ - struct EventArgs - { - virtual ~EventArgs () { } - }; - - class EventConnectorBase - { - public: - virtual ~EventConnectorBase () { } - virtual void operator() (EventArgs &args) = 0; - - virtual EventConnectorBase *CloneNew () const = 0; - virtual void *GetHandler () const = 0; - }; - - typedef list < shared_ptr > EventHandlerList; - - template - class EventConnector : public EventConnectorBase - { - public: - typedef void (T::*EventHandlerFunction) (EventArgs &); - - EventConnector (T *handler, EventHandlerFunction function) - : Handler (handler), Function (function) { } - - virtual void operator() (EventArgs &args) { (Handler->*Function) (args); } - - virtual EventConnectorBase *CloneNew () const { return new EventConnector (*this); } - virtual void *GetHandler () const { return Handler; } - - protected: - T *Handler; - EventHandlerFunction Function; - }; - - class Event - { - public: - Event () { } - virtual ~Event () { } - - void Connect (const EventConnectorBase &connector); - void Disconnect (void *handler); - void Raise (); - void Raise (EventArgs &args); - - protected: - EventHandlerList ConnectedHandlers; - Mutex HandlersMutex; - - private: - Event (const Event &); - Event &operator= (const Event &); - }; - - struct ExceptionEventArgs : public EventArgs - { - ExceptionEventArgs (exception &ex) : mException (ex) { } - exception &mException; - - private: - ExceptionEventArgs (const ExceptionEventArgs &); - ExceptionEventArgs &operator= (const ExceptionEventArgs &); - }; -} - -#endif // TC_HEADER_Platform_Event +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Event +#define TC_HEADER_Platform_Event + +#include "PlatformBase.h" +#include "ForEach.h" +#include "Mutex.h" +#include "SharedPtr.h" + +namespace TrueCrypt +{ + struct EventArgs + { + virtual ~EventArgs () { } + }; + + class EventConnectorBase + { + public: + virtual ~EventConnectorBase () { } + virtual void operator() (EventArgs &args) = 0; + + virtual EventConnectorBase *CloneNew () const = 0; + virtual void *GetHandler () const = 0; + }; + + typedef list < shared_ptr > EventHandlerList; + + template + class EventConnector : public EventConnectorBase + { + public: + typedef void (T::*EventHandlerFunction) (EventArgs &); + + EventConnector (T *handler, EventHandlerFunction function) + : Handler (handler), Function (function) { } + + virtual void operator() (EventArgs &args) { (Handler->*Function) (args); } + + virtual EventConnectorBase *CloneNew () const { return new EventConnector (*this); } + virtual void *GetHandler () const { return Handler; } + + protected: + T *Handler; + EventHandlerFunction Function; + }; + + class Event + { + public: + Event () { } + virtual ~Event () { } + + void Connect (const EventConnectorBase &connector); + void Disconnect (void *handler); + void Raise (); + void Raise (EventArgs &args); + + protected: + EventHandlerList ConnectedHandlers; + Mutex HandlersMutex; + + private: + Event (const Event &); + Event &operator= (const Event &); + }; + + struct ExceptionEventArgs : public EventArgs + { + ExceptionEventArgs (exception &ex) : mException (ex) { } + exception &mException; + + private: + ExceptionEventArgs (const ExceptionEventArgs &); + ExceptionEventArgs &operator= (const ExceptionEventArgs &); + }; +} + +#endif // TC_HEADER_Platform_Event diff --git a/Platform/Exception.cpp b/Platform/Exception.cpp index 0e7875c..59a32f8 100644 --- a/Platform/Exception.cpp +++ b/Platform/Exception.cpp @@ -1,52 +1,52 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Exception.h" -#include "SerializerFactory.h" - -namespace TrueCrypt -{ - void Exception::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - sr.Deserialize ("Message", Message); - sr.Deserialize ("Subject", Subject); - } - - void Exception::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("Message", Message); - sr.Serialize ("Subject", Subject); - } - - void ExecutedProcessFailed::Deserialize (shared_ptr stream) - { - Exception::Deserialize (stream); - Serializer sr (stream); - sr.Deserialize ("Command", Command); - sr.Deserialize ("ExitCode", ExitCode); - sr.Deserialize ("ErrorOutput", ErrorOutput); - } - - void ExecutedProcessFailed::Serialize (shared_ptr stream) const - { - Exception::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("Command", Command); - sr.Serialize ("ExitCode", ExitCode); - sr.Serialize ("ErrorOutput", ErrorOutput); - } - -#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -#undef TC_EXCEPTION_NODECL -#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (Exception); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Exception.h" +#include "SerializerFactory.h" + +namespace TrueCrypt +{ + void Exception::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + sr.Deserialize ("Message", Message); + sr.Deserialize ("Subject", Subject); + } + + void Exception::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("Message", Message); + sr.Serialize ("Subject", Subject); + } + + void ExecutedProcessFailed::Deserialize (shared_ptr stream) + { + Exception::Deserialize (stream); + Serializer sr (stream); + sr.Deserialize ("Command", Command); + sr.Deserialize ("ExitCode", ExitCode); + sr.Deserialize ("ErrorOutput", ErrorOutput); + } + + void ExecutedProcessFailed::Serialize (shared_ptr stream) const + { + Exception::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("Command", Command); + sr.Serialize ("ExitCode", ExitCode); + sr.Serialize ("ErrorOutput", ErrorOutput); + } + +#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +#undef TC_EXCEPTION_NODECL +#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (Exception); +} diff --git a/Platform/Exception.h b/Platform/Exception.h index f56782c..f0e1b35 100644 --- a/Platform/Exception.h +++ b/Platform/Exception.h @@ -1,110 +1,110 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Exception -#define TC_HEADER_Platform_Exception - -#include -#include "PlatformBase.h" -#include "Serializable.h" - -namespace TrueCrypt -{ -#define TC_SERIALIZABLE_EXCEPTION(TYPE) TC_SERIALIZABLE (TYPE); \ - virtual Exception *CloneNew () { return new TYPE (*this); } \ - virtual void Throw () const { throw *this; } - - struct Exception : public exception, public Serializable - { - public: - Exception () { } - Exception (const string &message) : Message (message) { } - Exception (const string &message, const wstring &subject) : Message (message), Subject (subject) { } - virtual ~Exception () throw () { } - - TC_SERIALIZABLE_EXCEPTION (Exception); - - virtual const char *what () const throw () { return Message.c_str(); } - virtual const wstring &GetSubject() const { return Subject; } - - protected: - string Message; - wstring Subject; - }; - - struct ExecutedProcessFailed : public Exception - { - ExecutedProcessFailed () { } - ExecutedProcessFailed (const string &message, const string &command, int exitCode, const string &errorOutput) - : Exception (message), Command (command), ExitCode (exitCode), ErrorOutput (errorOutput) { } - virtual ~ExecutedProcessFailed () throw () { } - - TC_SERIALIZABLE_EXCEPTION (ExecutedProcessFailed); - - string GetCommand () const { return Command; } - int64 GetExitCode () const { return ExitCode; } - string GetErrorOutput () const { return ErrorOutput; } - - protected: - string Command; - int64 ExitCode; - string ErrorOutput; - }; - -#define TC_EXCEPTION_DECL(NAME,BASE) \ - struct NAME : public BASE \ - { \ - NAME () { } \ - NAME (const string &message) : BASE (message) { } \ - NAME (const string &message, const wstring &subject) : BASE (message, subject) { } \ - virtual Exception *CloneNew () { return new NAME (*this); } \ - static Serializable *GetNewSerializable () { return new NAME (); } \ - virtual void Throw () const { throw *this; } \ - } - -#define TC_EXCEPTION_NODECL(dummy) // -#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) - -#ifdef TC_EXCEPTION_SET -#undef TC_EXCEPTION_SET -#endif -#define TC_EXCEPTION_SET \ - TC_EXCEPTION_NODECL (Exception); \ - TC_EXCEPTION_NODECL (ExecutedProcessFailed); \ - TC_EXCEPTION (AlreadyInitialized); \ - TC_EXCEPTION (AssertionFailed); \ - TC_EXCEPTION (ExternalException); \ - TC_EXCEPTION (InsufficientData); \ - TC_EXCEPTION (NotApplicable); \ - TC_EXCEPTION (NotImplemented); \ - TC_EXCEPTION (NotInitialized); \ - TC_EXCEPTION (ParameterIncorrect); \ - TC_EXCEPTION (ParameterTooLarge); \ - TC_EXCEPTION (PartitionDeviceRequired); \ - TC_EXCEPTION (StringConversionFailed); \ - TC_EXCEPTION (TestFailed); \ - TC_EXCEPTION (TimeOut); \ - TC_EXCEPTION (UnknownException); \ - TC_EXCEPTION (UserAbort) - - TC_EXCEPTION_SET; - -#undef TC_EXCEPTION -} - -#ifdef assert -# undef assert -#endif - -#ifdef DEBUG -# define assert(condition) do { if (!(condition)) throw AssertionFailed (SRC_POS); } while (false) -#else -# define assert(condition) ((void) 0) -#endif - -#endif // TC_HEADER_Platform_Exception +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Exception +#define TC_HEADER_Platform_Exception + +#include +#include "PlatformBase.h" +#include "Serializable.h" + +namespace TrueCrypt +{ +#define TC_SERIALIZABLE_EXCEPTION(TYPE) TC_SERIALIZABLE (TYPE); \ + virtual Exception *CloneNew () { return new TYPE (*this); } \ + virtual void Throw () const { throw *this; } + + struct Exception : public exception, public Serializable + { + public: + Exception () { } + Exception (const string &message) : Message (message) { } + Exception (const string &message, const wstring &subject) : Message (message), Subject (subject) { } + virtual ~Exception () throw () { } + + TC_SERIALIZABLE_EXCEPTION (Exception); + + virtual const char *what () const throw () { return Message.c_str(); } + virtual const wstring &GetSubject() const { return Subject; } + + protected: + string Message; + wstring Subject; + }; + + struct ExecutedProcessFailed : public Exception + { + ExecutedProcessFailed () { } + ExecutedProcessFailed (const string &message, const string &command, int exitCode, const string &errorOutput) + : Exception (message), Command (command), ExitCode (exitCode), ErrorOutput (errorOutput) { } + virtual ~ExecutedProcessFailed () throw () { } + + TC_SERIALIZABLE_EXCEPTION (ExecutedProcessFailed); + + string GetCommand () const { return Command; } + int64 GetExitCode () const { return ExitCode; } + string GetErrorOutput () const { return ErrorOutput; } + + protected: + string Command; + int64 ExitCode; + string ErrorOutput; + }; + +#define TC_EXCEPTION_DECL(NAME,BASE) \ + struct NAME : public BASE \ + { \ + NAME () { } \ + NAME (const string &message) : BASE (message) { } \ + NAME (const string &message, const wstring &subject) : BASE (message, subject) { } \ + virtual Exception *CloneNew () { return new NAME (*this); } \ + static Serializable *GetNewSerializable () { return new NAME (); } \ + virtual void Throw () const { throw *this; } \ + } + +#define TC_EXCEPTION_NODECL(dummy) // +#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) + +#ifdef TC_EXCEPTION_SET +#undef TC_EXCEPTION_SET +#endif +#define TC_EXCEPTION_SET \ + TC_EXCEPTION_NODECL (Exception); \ + TC_EXCEPTION_NODECL (ExecutedProcessFailed); \ + TC_EXCEPTION (AlreadyInitialized); \ + TC_EXCEPTION (AssertionFailed); \ + TC_EXCEPTION (ExternalException); \ + TC_EXCEPTION (InsufficientData); \ + TC_EXCEPTION (NotApplicable); \ + TC_EXCEPTION (NotImplemented); \ + TC_EXCEPTION (NotInitialized); \ + TC_EXCEPTION (ParameterIncorrect); \ + TC_EXCEPTION (ParameterTooLarge); \ + TC_EXCEPTION (PartitionDeviceRequired); \ + TC_EXCEPTION (StringConversionFailed); \ + TC_EXCEPTION (TestFailed); \ + TC_EXCEPTION (TimeOut); \ + TC_EXCEPTION (UnknownException); \ + TC_EXCEPTION (UserAbort) + + TC_EXCEPTION_SET; + +#undef TC_EXCEPTION +} + +#ifdef assert +# undef assert +#endif + +#ifdef DEBUG +# define assert(condition) do { if (!(condition)) throw AssertionFailed (SRC_POS); } while (false) +#else +# define assert(condition) ((void) 0) +#endif + +#endif // TC_HEADER_Platform_Exception diff --git a/Platform/File.h b/Platform/File.h index 4341978..507a6a2 100644 --- a/Platform/File.h +++ b/Platform/File.h @@ -1,110 +1,110 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_File -#define TC_HEADER_Platform_File - -#include "PlatformBase.h" -#include "Buffer.h" -#include "FilesystemPath.h" -#include "SystemException.h" - -namespace TrueCrypt -{ - class File - { - public: - enum FileOpenMode - { - CreateReadWrite, - CreateWrite, - OpenRead, - OpenWrite, - OpenReadWrite - }; - - enum FileShareMode - { - ShareNone, - ShareRead, - ShareReadWrite, - ShareReadWriteIgnoreLock - }; - - enum FileOpenFlags - { - // Bitmap - FlagsNone = 0, - PreserveTimestamps = 1 << 0, - DisableWriteCaching = 1 << 1 - }; - -#ifdef TC_WINDOWS - typedef FILE* SystemFileHandleType; -#else - typedef int SystemFileHandleType; -#endif - - File () : FileIsOpen (false), SharedHandle (false) { } - virtual ~File (); - - void AssignSystemHandle (SystemFileHandleType openFileHandle, bool sharedHandle = true) - { - if (FileIsOpen) - Close(); - FileHandle = openFileHandle; - FileIsOpen = true; - SharedHandle = sharedHandle; - } - - void Close (); - static void Copy (const FilePath &sourcePath, const FilePath &destinationPath, bool preserveTimestamps = true); - void Delete (); - void Flush () const; - uint32 GetDeviceSectorSize () const; - static size_t GetOptimalReadSize () { return OptimalReadSize; } - static size_t GetOptimalWriteSize () { return OptimalWriteSize; } - uint64 GetPartitionDeviceStartOffset () const; - bool IsOpen () const { return FileIsOpen; } - FilePath GetPath () const; - uint64 Length () const; - void Open (const FilePath &path, FileOpenMode mode = OpenRead, FileShareMode shareMode = ShareReadWrite, FileOpenFlags flags = FlagsNone); - uint64 Read (const BufferPtr &buffer) const; - void ReadCompleteBuffer (const BufferPtr &buffer) const; - uint64 ReadAt (const BufferPtr &buffer, uint64 position) const; - void SeekAt (uint64 position) const; - void SeekEnd (int ofset) const; - void Write (const ConstBufferPtr &buffer) const; - void Write (const ConstBufferPtr &buffer, size_t length) const { Write (buffer.GetRange (0, length)); } - void WriteAt (const ConstBufferPtr &buffer, uint64 position) const; - - protected: - void ValidateState () const; - - static const size_t OptimalReadSize = 256 * 1024; - static const size_t OptimalWriteSize = 256 * 1024; - - bool FileIsOpen; - FileOpenFlags mFileOpenFlags; - bool SharedHandle; - FilePath Path; - SystemFileHandleType FileHandle; - -#ifdef TC_WINDOWS -#else - time_t AccTime; - time_t ModTime; -#endif - - private: - File (const File &); - File &operator= (const File &); - }; -} - -#endif // TC_HEADER_Platform_File +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_File +#define TC_HEADER_Platform_File + +#include "PlatformBase.h" +#include "Buffer.h" +#include "FilesystemPath.h" +#include "SystemException.h" + +namespace TrueCrypt +{ + class File + { + public: + enum FileOpenMode + { + CreateReadWrite, + CreateWrite, + OpenRead, + OpenWrite, + OpenReadWrite + }; + + enum FileShareMode + { + ShareNone, + ShareRead, + ShareReadWrite, + ShareReadWriteIgnoreLock + }; + + enum FileOpenFlags + { + // Bitmap + FlagsNone = 0, + PreserveTimestamps = 1 << 0, + DisableWriteCaching = 1 << 1 + }; + +#ifdef TC_WINDOWS + typedef FILE* SystemFileHandleType; +#else + typedef int SystemFileHandleType; +#endif + + File () : FileIsOpen (false), SharedHandle (false) { } + virtual ~File (); + + void AssignSystemHandle (SystemFileHandleType openFileHandle, bool sharedHandle = true) + { + if (FileIsOpen) + Close(); + FileHandle = openFileHandle; + FileIsOpen = true; + SharedHandle = sharedHandle; + } + + void Close (); + static void Copy (const FilePath &sourcePath, const FilePath &destinationPath, bool preserveTimestamps = true); + void Delete (); + void Flush () const; + uint32 GetDeviceSectorSize () const; + static size_t GetOptimalReadSize () { return OptimalReadSize; } + static size_t GetOptimalWriteSize () { return OptimalWriteSize; } + uint64 GetPartitionDeviceStartOffset () const; + bool IsOpen () const { return FileIsOpen; } + FilePath GetPath () const; + uint64 Length () const; + void Open (const FilePath &path, FileOpenMode mode = OpenRead, FileShareMode shareMode = ShareReadWrite, FileOpenFlags flags = FlagsNone); + uint64 Read (const BufferPtr &buffer) const; + void ReadCompleteBuffer (const BufferPtr &buffer) const; + uint64 ReadAt (const BufferPtr &buffer, uint64 position) const; + void SeekAt (uint64 position) const; + void SeekEnd (int ofset) const; + void Write (const ConstBufferPtr &buffer) const; + void Write (const ConstBufferPtr &buffer, size_t length) const { Write (buffer.GetRange (0, length)); } + void WriteAt (const ConstBufferPtr &buffer, uint64 position) const; + + protected: + void ValidateState () const; + + static const size_t OptimalReadSize = 256 * 1024; + static const size_t OptimalWriteSize = 256 * 1024; + + bool FileIsOpen; + FileOpenFlags mFileOpenFlags; + bool SharedHandle; + FilePath Path; + SystemFileHandleType FileHandle; + +#ifdef TC_WINDOWS +#else + time_t AccTime; + time_t ModTime; +#endif + + private: + File (const File &); + File &operator= (const File &); + }; +} + +#endif // TC_HEADER_Platform_File diff --git a/Platform/FileCommon.cpp b/Platform/FileCommon.cpp index 862a97a..036c9a6 100644 --- a/Platform/FileCommon.cpp +++ b/Platform/FileCommon.cpp @@ -1,87 +1,87 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "File.h" -#ifdef TC_UNIX -#include -#include -#include -#include -#endif - -namespace TrueCrypt -{ - File::~File () - { - try - { - if (FileIsOpen) - Close(); - } - catch (...) { } - } - - void File::Copy (const FilePath &sourcePath, const FilePath &destinationPath, bool preserveTimestamps) - { - File source; - source.Open (sourcePath); - - File destination; - destination.Open (destinationPath, CreateWrite); - - SecureBuffer buffer (OptimalReadSize); - uint64 len; - - while ((len = source.Read (buffer)) > 0) - { - destination.Write (buffer, static_cast (len)); - } - - if (preserveTimestamps) - { - destination.Flush(); -#ifndef TC_WINDOWS - struct stat statData; - throw_sys_sub_if (stat (string (sourcePath).c_str(), &statData) == -1, wstring (sourcePath)); - - struct utimbuf u; - u.actime = statData.st_atime; - u.modtime = statData.st_mtime; - throw_sys_sub_if (utime (string (destinationPath).c_str(), &u) == -1, wstring (destinationPath)); -#endif - } - } - - FilePath File::GetPath () const - { - if_debug (ValidateState()); - return Path; - } - - void File::ReadCompleteBuffer (const BufferPtr &buffer) const - { - size_t dataLeft = buffer.Size(); - size_t offset = 0; - - while (dataLeft > 0) - { - size_t dataRead = static_cast (Read (buffer.GetRange (offset, dataLeft))); - if (dataRead == 0) - throw InsufficientData (SRC_POS); - - dataLeft -= dataRead; - offset += dataRead; - } - } - - void File::ValidateState () const - { - if (!FileIsOpen) - throw NotInitialized (SRC_POS); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "File.h" +#ifdef TC_UNIX +#include +#include +#include +#include +#endif + +namespace TrueCrypt +{ + File::~File () + { + try + { + if (FileIsOpen) + Close(); + } + catch (...) { } + } + + void File::Copy (const FilePath &sourcePath, const FilePath &destinationPath, bool preserveTimestamps) + { + File source; + source.Open (sourcePath); + + File destination; + destination.Open (destinationPath, CreateWrite); + + SecureBuffer buffer (OptimalReadSize); + uint64 len; + + while ((len = source.Read (buffer)) > 0) + { + destination.Write (buffer, static_cast (len)); + } + + if (preserveTimestamps) + { + destination.Flush(); +#ifndef TC_WINDOWS + struct stat statData; + throw_sys_sub_if (stat (string (sourcePath).c_str(), &statData) == -1, wstring (sourcePath)); + + struct utimbuf u; + u.actime = statData.st_atime; + u.modtime = statData.st_mtime; + throw_sys_sub_if (utime (string (destinationPath).c_str(), &u) == -1, wstring (destinationPath)); +#endif + } + } + + FilePath File::GetPath () const + { + if_debug (ValidateState()); + return Path; + } + + void File::ReadCompleteBuffer (const BufferPtr &buffer) const + { + size_t dataLeft = buffer.Size(); + size_t offset = 0; + + while (dataLeft > 0) + { + size_t dataRead = static_cast (Read (buffer.GetRange (offset, dataLeft))); + if (dataRead == 0) + throw InsufficientData (SRC_POS); + + dataLeft -= dataRead; + offset += dataRead; + } + } + + void File::ValidateState () const + { + if (!FileIsOpen) + throw NotInitialized (SRC_POS); + } +} diff --git a/Platform/FileStream.h b/Platform/FileStream.h index 6ef7458..04e7796 100644 --- a/Platform/FileStream.h +++ b/Platform/FileStream.h @@ -1,58 +1,58 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_FileStream -#define TC_HEADER_Platform_FileStream - -#include "PlatformBase.h" -#include "File.h" -#include "SharedPtr.h" -#include "Stream.h" - -namespace TrueCrypt -{ - class FileStream : public Stream - { - public: - FileStream (shared_ptr file) : DataFile (file) { } - FileStream (File::SystemFileHandleType openFileHandle) { DataFile.reset (new File ()); DataFile->AssignSystemHandle (openFileHandle); } - virtual ~FileStream () { } - - virtual uint64 Read (const BufferPtr &buffer) - { - return DataFile->Read (buffer); - } - - virtual void ReadCompleteBuffer (const BufferPtr &buffer) - { - DataFile->ReadCompleteBuffer (buffer); - } - - virtual string ReadToEnd () - { - string str; - vector buffer (4096); - uint64 len; - - while ((len = DataFile->Read (BufferPtr (reinterpret_cast (&buffer[0]), buffer.size()))) > 0) - str.insert (str.end(), buffer.begin(), buffer.begin() + static_cast (len)); - - return str; - } - - virtual void Write (const ConstBufferPtr &data) - { - DataFile->Write (data); - } - - protected: - shared_ptr DataFile; - }; -} - -#endif // TC_HEADER_Platform_FileStream +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_FileStream +#define TC_HEADER_Platform_FileStream + +#include "PlatformBase.h" +#include "File.h" +#include "SharedPtr.h" +#include "Stream.h" + +namespace TrueCrypt +{ + class FileStream : public Stream + { + public: + FileStream (shared_ptr file) : DataFile (file) { } + FileStream (File::SystemFileHandleType openFileHandle) { DataFile.reset (new File ()); DataFile->AssignSystemHandle (openFileHandle); } + virtual ~FileStream () { } + + virtual uint64 Read (const BufferPtr &buffer) + { + return DataFile->Read (buffer); + } + + virtual void ReadCompleteBuffer (const BufferPtr &buffer) + { + DataFile->ReadCompleteBuffer (buffer); + } + + virtual string ReadToEnd () + { + string str; + vector buffer (4096); + uint64 len; + + while ((len = DataFile->Read (BufferPtr (reinterpret_cast (&buffer[0]), buffer.size()))) > 0) + str.insert (str.end(), buffer.begin(), buffer.begin() + static_cast (len)); + + return str; + } + + virtual void Write (const ConstBufferPtr &data) + { + DataFile->Write (data); + } + + protected: + shared_ptr DataFile; + }; +} + +#endif // TC_HEADER_Platform_FileStream diff --git a/Platform/FilesystemPath.h b/Platform/FilesystemPath.h index 4049643..6aaad6e 100644 --- a/Platform/FilesystemPath.h +++ b/Platform/FilesystemPath.h @@ -1,73 +1,73 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_FilesystemPath -#define TC_HEADER_Platform_FilesystemPath - -#include "PlatformBase.h" -#include "Platform/User.h" -#include "SharedPtr.h" -#include "StringConverter.h" - -namespace TrueCrypt -{ - struct FilesystemPathType - { - enum Enum - { - Unknown, - File, - Directory, - SymbolickLink, - BlockDevice, - CharacterDevice - }; - }; - - class FilesystemPath - { - public: - FilesystemPath () { } - FilesystemPath (const char *path) : Path (StringConverter::ToWide (path)) { } - FilesystemPath (string path) : Path (StringConverter::ToWide (path)) { } - FilesystemPath (const wchar_t *path) : Path (path) { } - FilesystemPath (wstring path) : Path (path) { } - virtual ~FilesystemPath () { } - - bool operator== (const FilesystemPath &other) const { return Path == other.Path; } - bool operator!= (const FilesystemPath &other) const { return Path != other.Path; } - operator string () const { return StringConverter::ToSingle (Path); } - operator wstring () const { return Path; } - - void Delete () const; - UserId GetOwner () const; - FilesystemPathType::Enum GetType () const; - bool IsBlockDevice () const throw () { try { return GetType() == FilesystemPathType::BlockDevice; } catch (...) { return false; }; } - bool IsCharacterDevice () const throw () { try { return GetType() == FilesystemPathType::CharacterDevice; } catch (...) { return false; }; } - bool IsDevice () const throw () { return IsBlockDevice() || IsCharacterDevice(); } - bool IsDirectory () const throw () { try { return GetType() == FilesystemPathType::Directory; } catch (...) { return false; } } - bool IsEmpty () const throw () { try { return Path.empty(); } catch (...) { return false; } } - bool IsFile () const throw () { try { return GetType() == FilesystemPathType::File; } catch (...) { return false; } } - FilesystemPath ToBaseName () const; - FilesystemPath ToHostDriveOfPartition () const; - - static const int MaxSize = 260; - - protected: - wstring Path; - }; - - typedef FilesystemPath DevicePath; - typedef FilesystemPath DirectoryPath; - typedef FilesystemPath FilePath; - - typedef list < shared_ptr > DirectoryPathList; - typedef list < shared_ptr > FilePathList; -} - -#endif // TC_HEADER_Platform_FilesystemPath +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_FilesystemPath +#define TC_HEADER_Platform_FilesystemPath + +#include "PlatformBase.h" +#include "Platform/User.h" +#include "SharedPtr.h" +#include "StringConverter.h" + +namespace TrueCrypt +{ + struct FilesystemPathType + { + enum Enum + { + Unknown, + File, + Directory, + SymbolickLink, + BlockDevice, + CharacterDevice + }; + }; + + class FilesystemPath + { + public: + FilesystemPath () { } + FilesystemPath (const char *path) : Path (StringConverter::ToWide (path)) { } + FilesystemPath (string path) : Path (StringConverter::ToWide (path)) { } + FilesystemPath (const wchar_t *path) : Path (path) { } + FilesystemPath (wstring path) : Path (path) { } + virtual ~FilesystemPath () { } + + bool operator== (const FilesystemPath &other) const { return Path == other.Path; } + bool operator!= (const FilesystemPath &other) const { return Path != other.Path; } + operator string () const { return StringConverter::ToSingle (Path); } + operator wstring () const { return Path; } + + void Delete () const; + UserId GetOwner () const; + FilesystemPathType::Enum GetType () const; + bool IsBlockDevice () const throw () { try { return GetType() == FilesystemPathType::BlockDevice; } catch (...) { return false; }; } + bool IsCharacterDevice () const throw () { try { return GetType() == FilesystemPathType::CharacterDevice; } catch (...) { return false; }; } + bool IsDevice () const throw () { return IsBlockDevice() || IsCharacterDevice(); } + bool IsDirectory () const throw () { try { return GetType() == FilesystemPathType::Directory; } catch (...) { return false; } } + bool IsEmpty () const throw () { try { return Path.empty(); } catch (...) { return false; } } + bool IsFile () const throw () { try { return GetType() == FilesystemPathType::File; } catch (...) { return false; } } + FilesystemPath ToBaseName () const; + FilesystemPath ToHostDriveOfPartition () const; + + static const int MaxSize = 260; + + protected: + wstring Path; + }; + + typedef FilesystemPath DevicePath; + typedef FilesystemPath DirectoryPath; + typedef FilesystemPath FilePath; + + typedef list < shared_ptr > DirectoryPathList; + typedef list < shared_ptr > FilePathList; +} + +#endif // TC_HEADER_Platform_FilesystemPath diff --git a/Platform/Finally.h b/Platform/Finally.h index 4cac00f..00c734e 100644 --- a/Platform/Finally.h +++ b/Platform/Finally.h @@ -1,46 +1,46 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Finally -#define TC_HEADER_Platform_Finally - -#include "PlatformBase.h" - -// Execute code when leaving scope -#define finally_do(code) \ -struct TC_JOIN(Finally,__LINE__) \ -{ \ - TC_JOIN(~Finally,__LINE__) () { try { code } catch (...) { } } \ -} \ -TC_UNUSED_VAR \ -TC_JOIN(finally,__LINE__) - -// Execute code with argument 'finally_arg' when leaving scope -#define finally_do_arg(argType, arg, code) \ -struct TC_JOIN(Finally,__LINE__) \ -{ \ - TC_JOIN(Finally,__LINE__) (argType a) : finally_arg (a) { } \ - TC_JOIN(~Finally,__LINE__) () { try { code } catch (...) { } } \ - argType finally_arg; \ -} \ -TC_UNUSED_VAR \ -TC_JOIN(finally,__LINE__) (arg) - -#define finally_do_arg2(argType, arg, argType2, arg2, code) \ -struct TC_JOIN(Finally,__LINE__) \ -{ \ - TC_JOIN(Finally,__LINE__) (argType a, argType2 a2) : finally_arg (a), finally_arg2 (a2) { } \ - TC_JOIN(~Finally,__LINE__) () { try { code } catch (...) { } } \ - argType finally_arg; \ - argType2 finally_arg2; \ -} \ -TC_UNUSED_VAR \ -TC_JOIN(finally,__LINE__) (arg, arg2) - - -#endif // TC_HEADER_Platform_Finally +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Finally +#define TC_HEADER_Platform_Finally + +#include "PlatformBase.h" + +// Execute code when leaving scope +#define finally_do(code) \ +struct TC_JOIN(Finally,__LINE__) \ +{ \ + TC_JOIN(~Finally,__LINE__) () { try { code } catch (...) { } } \ +} \ +TC_UNUSED_VAR \ +TC_JOIN(finally,__LINE__) + +// Execute code with argument 'finally_arg' when leaving scope +#define finally_do_arg(argType, arg, code) \ +struct TC_JOIN(Finally,__LINE__) \ +{ \ + TC_JOIN(Finally,__LINE__) (argType a) : finally_arg (a) { } \ + TC_JOIN(~Finally,__LINE__) () { try { code } catch (...) { } } \ + argType finally_arg; \ +} \ +TC_UNUSED_VAR \ +TC_JOIN(finally,__LINE__) (arg) + +#define finally_do_arg2(argType, arg, argType2, arg2, code) \ +struct TC_JOIN(Finally,__LINE__) \ +{ \ + TC_JOIN(Finally,__LINE__) (argType a, argType2 a2) : finally_arg (a), finally_arg2 (a2) { } \ + TC_JOIN(~Finally,__LINE__) () { try { code } catch (...) { } } \ + argType finally_arg; \ + argType2 finally_arg2; \ +} \ +TC_UNUSED_VAR \ +TC_JOIN(finally,__LINE__) (arg, arg2) + + +#endif // TC_HEADER_Platform_Finally diff --git a/Platform/ForEach.h b/Platform/ForEach.h index fc537aa..c1c82b4 100644 --- a/Platform/ForEach.h +++ b/Platform/ForEach.h @@ -1,118 +1,118 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_ForEach -#define TC_HEADER_Platform_ForEach - -namespace TrueCrypt -{ - class ForEach - { - public: - struct Container - { - Container () : InnerContinue (true), InnerEndCondition (false) { } - virtual ~Container () { } - - void Continue () const { InnerContinue = true; } - bool InnerIsNotEnd () const { return InnerEndCondition = !InnerEndCondition; } - virtual bool IsNotEnd () const = 0; - virtual void Next () const = 0; - - mutable bool InnerContinue; - mutable bool InnerEndCondition; - }; - - protected: - template - struct ContainerForward : Container - { - ContainerForward (const T &container) - : ContainerCopy (container), EndIterator (ContainerCopy.end()), Iterator (ContainerCopy.begin()) { } - - virtual bool IsNotEnd () const { bool r = InnerContinue && Iterator != EndIterator; InnerContinue = false; return r; } - virtual void Next () const { ++Iterator; } - - const T ContainerCopy; // Support for temporary objects - typename T::const_iterator EndIterator; - mutable typename T::const_iterator Iterator; - - private: - ContainerForward &operator= (const ContainerForward &); - }; - - template - struct ContainerReverse : Container - { - ContainerReverse (const T &container) - : ContainerCopy (container), EndIterator (ContainerCopy.rend()), Iterator (ContainerCopy.rbegin()) { } - - virtual bool IsNotEnd () const { bool r = InnerContinue && Iterator != EndIterator; InnerContinue = false; return r; } - virtual void Next () const { ++Iterator; } - - const T ContainerCopy; - typename T::const_reverse_iterator EndIterator; - mutable typename T::const_reverse_iterator Iterator; - - private: - ContainerReverse &operator= (const ContainerReverse &); - }; - - public: - template - static ContainerForward GetContainerForward (const T &container) - { - return ContainerForward (container); - } - - template - static ContainerReverse GetContainerReverse (const T &container) - { - return ContainerReverse (container); - } - - protected: - template - struct TypeWrapper { }; - - public: - template - static TypeWrapper ToTypeWrapper (const T &x) { return TypeWrapper (); } - - struct TypeWrapperDummy - { - template - operator TypeWrapper () const { return TypeWrapper (); } - }; - - template - static const ContainerForward &GetContainerForward (const Container &forEachContainer, const TypeWrapper &) - { - return static_cast &> (forEachContainer); - } - - template - static const ContainerReverse &GetContainerReverse (const Container &forEachContainer, const TypeWrapper &) - { - return static_cast &> (forEachContainer); - } - }; -} - - -#define FOREACH_TEMPLATE(dereference,listType,variable,listInstance) \ - for (const ForEach::Container &forEachContainer = ForEach::GetContainer##listType (listInstance); forEachContainer.IsNotEnd(); forEachContainer.Next()) \ - for (variable = dereference(ForEach::GetContainer##listType (forEachContainer, (true ? ForEach::TypeWrapperDummy() : ForEach::ToTypeWrapper (listInstance))).Iterator); forEachContainer.InnerIsNotEnd(); forEachContainer.Continue()) - -#define foreach(variable,listInstance) FOREACH_TEMPLATE(*, Forward, variable, listInstance) -#define foreach_ref(variable,listInstance) FOREACH_TEMPLATE(**, Forward, variable, listInstance) -#define foreach_reverse(variable,listInstance) FOREACH_TEMPLATE(*, Reverse, variable, listInstance) -#define foreach_reverse_ref(variable,listInstance) FOREACH_TEMPLATE(**, Reverse, variable, listInstance) - - -#endif // TC_HEADER_Platform_ForEach +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_ForEach +#define TC_HEADER_Platform_ForEach + +namespace TrueCrypt +{ + class ForEach + { + public: + struct Container + { + Container () : InnerContinue (true), InnerEndCondition (false) { } + virtual ~Container () { } + + void Continue () const { InnerContinue = true; } + bool InnerIsNotEnd () const { return InnerEndCondition = !InnerEndCondition; } + virtual bool IsNotEnd () const = 0; + virtual void Next () const = 0; + + mutable bool InnerContinue; + mutable bool InnerEndCondition; + }; + + protected: + template + struct ContainerForward : Container + { + ContainerForward (const T &container) + : ContainerCopy (container), EndIterator (ContainerCopy.end()), Iterator (ContainerCopy.begin()) { } + + virtual bool IsNotEnd () const { bool r = InnerContinue && Iterator != EndIterator; InnerContinue = false; return r; } + virtual void Next () const { ++Iterator; } + + const T ContainerCopy; // Support for temporary objects + typename T::const_iterator EndIterator; + mutable typename T::const_iterator Iterator; + + private: + ContainerForward &operator= (const ContainerForward &); + }; + + template + struct ContainerReverse : Container + { + ContainerReverse (const T &container) + : ContainerCopy (container), EndIterator (ContainerCopy.rend()), Iterator (ContainerCopy.rbegin()) { } + + virtual bool IsNotEnd () const { bool r = InnerContinue && Iterator != EndIterator; InnerContinue = false; return r; } + virtual void Next () const { ++Iterator; } + + const T ContainerCopy; + typename T::const_reverse_iterator EndIterator; + mutable typename T::const_reverse_iterator Iterator; + + private: + ContainerReverse &operator= (const ContainerReverse &); + }; + + public: + template + static ContainerForward GetContainerForward (const T &container) + { + return ContainerForward (container); + } + + template + static ContainerReverse GetContainerReverse (const T &container) + { + return ContainerReverse (container); + } + + protected: + template + struct TypeWrapper { }; + + public: + template + static TypeWrapper ToTypeWrapper (const T &x) { return TypeWrapper (); } + + struct TypeWrapperDummy + { + template + operator TypeWrapper () const { return TypeWrapper (); } + }; + + template + static const ContainerForward &GetContainerForward (const Container &forEachContainer, const TypeWrapper &) + { + return static_cast &> (forEachContainer); + } + + template + static const ContainerReverse &GetContainerReverse (const Container &forEachContainer, const TypeWrapper &) + { + return static_cast &> (forEachContainer); + } + }; +} + + +#define FOREACH_TEMPLATE(dereference,listType,variable,listInstance) \ + for (const ForEach::Container &forEachContainer = ForEach::GetContainer##listType (listInstance); forEachContainer.IsNotEnd(); forEachContainer.Next()) \ + for (variable = dereference(ForEach::GetContainer##listType (forEachContainer, (true ? ForEach::TypeWrapperDummy() : ForEach::ToTypeWrapper (listInstance))).Iterator); forEachContainer.InnerIsNotEnd(); forEachContainer.Continue()) + +#define foreach(variable,listInstance) FOREACH_TEMPLATE(*, Forward, variable, listInstance) +#define foreach_ref(variable,listInstance) FOREACH_TEMPLATE(**, Forward, variable, listInstance) +#define foreach_reverse(variable,listInstance) FOREACH_TEMPLATE(*, Reverse, variable, listInstance) +#define foreach_reverse_ref(variable,listInstance) FOREACH_TEMPLATE(**, Reverse, variable, listInstance) + + +#endif // TC_HEADER_Platform_ForEach diff --git a/Platform/Functor.h b/Platform/Functor.h index a558be8..b3e1dc2 100644 --- a/Platform/Functor.h +++ b/Platform/Functor.h @@ -1,29 +1,29 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Functor -#define TC_HEADER_Platform_Functor - -#include "PlatformBase.h" - -namespace TrueCrypt -{ - struct Functor - { - virtual ~Functor () { } - virtual void operator() () = 0; - }; - - struct GetStringFunctor - { - virtual ~GetStringFunctor () { } - virtual void operator() (string &str) = 0; - }; -} - -#endif // TC_HEADER_Platform_Functor +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Functor +#define TC_HEADER_Platform_Functor + +#include "PlatformBase.h" + +namespace TrueCrypt +{ + struct Functor + { + virtual ~Functor () { } + virtual void operator() () = 0; + }; + + struct GetStringFunctor + { + virtual ~GetStringFunctor () { } + virtual void operator() (string &str) = 0; + }; +} + +#endif // TC_HEADER_Platform_Functor diff --git a/Platform/Memory.cpp b/Platform/Memory.cpp index 290495e..372b273 100644 --- a/Platform/Memory.cpp +++ b/Platform/Memory.cpp @@ -1,57 +1,57 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Memory.h" -#include "Exception.h" - -namespace TrueCrypt -{ - void *Memory::Allocate (std::size_t size) - { - if (size < 1) - throw ParameterIncorrect (SRC_POS); - - void *bufPtr = malloc (size); - if (!bufPtr) - throw bad_alloc(); - - return bufPtr; - } - - int Memory::Compare (const void *memory1, size_t size1, const void *memory2, size_t size2) - { - if (size1 > size2) - return 1; - else if (size1 < size2) - return -1; - - return memcmp (memory1, memory2, size1); - } - - void Memory::Copy (void *memoryDestination, const void *memorySource, size_t size) - { - assert (memoryDestination != nullptr && memorySource != nullptr); - memcpy (memoryDestination, memorySource, size); - } - - void Memory::Erase (void *memory, size_t size) - { - Zero (memory, size); - } - - void Memory::Zero (void *memory, size_t size) - { - memset (memory, 0, size); - } - - void Memory::Free (void *memory) - { - assert (memory != nullptr); - free (memory); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Memory.h" +#include "Exception.h" + +namespace TrueCrypt +{ + void *Memory::Allocate (std::size_t size) + { + if (size < 1) + throw ParameterIncorrect (SRC_POS); + + void *bufPtr = malloc (size); + if (!bufPtr) + throw bad_alloc(); + + return bufPtr; + } + + int Memory::Compare (const void *memory1, size_t size1, const void *memory2, size_t size2) + { + if (size1 > size2) + return 1; + else if (size1 < size2) + return -1; + + return memcmp (memory1, memory2, size1); + } + + void Memory::Copy (void *memoryDestination, const void *memorySource, size_t size) + { + assert (memoryDestination != nullptr && memorySource != nullptr); + memcpy (memoryDestination, memorySource, size); + } + + void Memory::Erase (void *memory, size_t size) + { + Zero (memory, size); + } + + void Memory::Zero (void *memory, size_t size) + { + memset (memory, 0, size); + } + + void Memory::Free (void *memory) + { + assert (memory != nullptr); + free (memory); + } +} diff --git a/Platform/Memory.h b/Platform/Memory.h index dc30837..cdf8524 100644 --- a/Platform/Memory.h +++ b/Platform/Memory.h @@ -1,174 +1,174 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Memory -#define TC_HEADER_Platform_Memory - -#include -#include -#include "PlatformBase.h" - -#ifdef TC_WINDOWS - -# ifndef LITTLE_ENDIAN -# define LITTLE_ENDIAN 1234 -# endif -# ifndef BYTE_ORDER -# define BYTE_ORDER LITTLE_ENDIAN -# endif - -#elif !defined(BYTE_ORDER) - -# ifdef TC_MACOSX -# include -# elif defined (TC_BSD) -# include -# elif defined (TC_SOLARIS) -# include -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -# ifdef _BIG_ENDIAN -# define BYTE_ORDER BIG_ENDIAN -# else -# define BYTE_ORDER LITTLE_ENDIAN -# endif -# else -# include -# endif - -# ifndef BYTE_ORDER -# ifndef __BYTE_ORDER -# error Byte ordering cannot be determined (BYTE_ORDER undefined). -# endif - -# define BYTE_ORDER __BYTE_ORDER -# endif - -# ifndef LITTLE_ENDIAN -# define LITTLE_ENDIAN __LITTLE_ENDIAN -# endif - -# ifndef BIG_ENDIAN -# define BIG_ENDIAN __BIG_ENDIAN -# endif - -#endif // !BYTE_ORDER - -#if BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN -# error Unsupported byte ordering detected. -#endif - -namespace TrueCrypt -{ - class Memory - { - public: - static void *Allocate (size_t size); - static int Compare (const void *memory1, size_t size1, const void *memory2, size_t size2); - static void Copy (void *memoryDestination, const void *memorySource, size_t size); - static void Erase (void *memory, size_t size); - static void Free (void *memory); - static void Zero (void *memory, size_t size); - }; - - class Endian - { - public: - static byte Big (const byte &x) - { - return x; - } - - static uint16 Big (const uint16 &x) - { -#if BYTE_ORDER == BIG_ENDIAN - return x; -#else - return MirrorBytes (x); -#endif - } - - static uint32 Big (const uint32 &x) - { -#if BYTE_ORDER == BIG_ENDIAN - return x; -#else - return MirrorBytes (x); -#endif - } - - static uint64 Big (const uint64 &x) - { -#if BYTE_ORDER == BIG_ENDIAN - return x; -#else - return MirrorBytes (x); -#endif - } - - static byte Little (const byte &x) - { - return x; - } - - static uint16 Little (const uint16 &x) - { -#if BYTE_ORDER == LITTLE_ENDIAN - return x; -#else - return MirrorBytes (x); -#endif - } - - static uint32 Little (const uint32 &x) - { -#if BYTE_ORDER == LITTLE_ENDIAN - return x; -#else - return MirrorBytes (x); -#endif - } - - static uint64 Little (const uint64 &x) - { -#if BYTE_ORDER == LITTLE_ENDIAN - return x; -#else - return MirrorBytes (x); -#endif - } - - protected: - static uint16 MirrorBytes (const uint16 &x) - { - return (x << 8) | (x >> 8); - } - - static uint32 MirrorBytes (const uint32 &x) - { - uint32 n = (byte) x; - n <<= 8; n |= (byte) (x >> 8); - n <<= 8; n |= (byte) (x >> 16); - return (n << 8) | (byte) (x >> 24); - } - - static uint64 MirrorBytes (const uint64 &x) - { - uint64 n = (byte) x; - n <<= 8; n |= (byte) (x >> 8); - n <<= 8; n |= (byte) (x >> 16); - n <<= 8; n |= (byte) (x >> 24); - n <<= 8; n |= (byte) (x >> 32); - n <<= 8; n |= (byte) (x >> 40); - n <<= 8; n |= (byte) (x >> 48); - return (n << 8) | (byte) (x >> 56); - } - }; -} - -#endif // TC_HEADER_Platform_Memory +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Memory +#define TC_HEADER_Platform_Memory + +#include +#include +#include "PlatformBase.h" + +#ifdef TC_WINDOWS + +# ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN 1234 +# endif +# ifndef BYTE_ORDER +# define BYTE_ORDER LITTLE_ENDIAN +# endif + +#elif !defined(BYTE_ORDER) + +# ifdef TC_MACOSX +# include +# elif defined (TC_BSD) +# include +# elif defined (TC_SOLARIS) +# include +# define LITTLE_ENDIAN 1234 +# define BIG_ENDIAN 4321 +# ifdef _BIG_ENDIAN +# define BYTE_ORDER BIG_ENDIAN +# else +# define BYTE_ORDER LITTLE_ENDIAN +# endif +# else +# include +# endif + +# ifndef BYTE_ORDER +# ifndef __BYTE_ORDER +# error Byte ordering cannot be determined (BYTE_ORDER undefined). +# endif + +# define BYTE_ORDER __BYTE_ORDER +# endif + +# ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# endif + +# ifndef BIG_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# endif + +#endif // !BYTE_ORDER + +#if BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN +# error Unsupported byte ordering detected. +#endif + +namespace TrueCrypt +{ + class Memory + { + public: + static void *Allocate (size_t size); + static int Compare (const void *memory1, size_t size1, const void *memory2, size_t size2); + static void Copy (void *memoryDestination, const void *memorySource, size_t size); + static void Erase (void *memory, size_t size); + static void Free (void *memory); + static void Zero (void *memory, size_t size); + }; + + class Endian + { + public: + static byte Big (const byte &x) + { + return x; + } + + static uint16 Big (const uint16 &x) + { +#if BYTE_ORDER == BIG_ENDIAN + return x; +#else + return MirrorBytes (x); +#endif + } + + static uint32 Big (const uint32 &x) + { +#if BYTE_ORDER == BIG_ENDIAN + return x; +#else + return MirrorBytes (x); +#endif + } + + static uint64 Big (const uint64 &x) + { +#if BYTE_ORDER == BIG_ENDIAN + return x; +#else + return MirrorBytes (x); +#endif + } + + static byte Little (const byte &x) + { + return x; + } + + static uint16 Little (const uint16 &x) + { +#if BYTE_ORDER == LITTLE_ENDIAN + return x; +#else + return MirrorBytes (x); +#endif + } + + static uint32 Little (const uint32 &x) + { +#if BYTE_ORDER == LITTLE_ENDIAN + return x; +#else + return MirrorBytes (x); +#endif + } + + static uint64 Little (const uint64 &x) + { +#if BYTE_ORDER == LITTLE_ENDIAN + return x; +#else + return MirrorBytes (x); +#endif + } + + protected: + static uint16 MirrorBytes (const uint16 &x) + { + return (x << 8) | (x >> 8); + } + + static uint32 MirrorBytes (const uint32 &x) + { + uint32 n = (byte) x; + n <<= 8; n |= (byte) (x >> 8); + n <<= 8; n |= (byte) (x >> 16); + return (n << 8) | (byte) (x >> 24); + } + + static uint64 MirrorBytes (const uint64 &x) + { + uint64 n = (byte) x; + n <<= 8; n |= (byte) (x >> 8); + n <<= 8; n |= (byte) (x >> 16); + n <<= 8; n |= (byte) (x >> 24); + n <<= 8; n |= (byte) (x >> 32); + n <<= 8; n |= (byte) (x >> 40); + n <<= 8; n |= (byte) (x >> 48); + return (n << 8) | (byte) (x >> 56); + } + }; +} + +#endif // TC_HEADER_Platform_Memory diff --git a/Platform/MemoryStream.cpp b/Platform/MemoryStream.cpp index 0a7c5f6..1a5a29d 100644 --- a/Platform/MemoryStream.cpp +++ b/Platform/MemoryStream.cpp @@ -1,47 +1,47 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Exception.h" -#include "MemoryStream.h" - -namespace TrueCrypt -{ - MemoryStream::MemoryStream (const ConstBufferPtr &data) : - ReadPosition (0) - { - Data = vector (data.Size()); - BufferPtr (&Data[0], Data.size()).CopyFrom (data); - } - - uint64 MemoryStream::Read (const BufferPtr &buffer) - { - if (Data.size() == 0) - throw ParameterIncorrect (SRC_POS); - - ConstBufferPtr streamBuf (*this); - size_t len = buffer.Size(); - if (streamBuf.Size() - ReadPosition < len) - len = streamBuf.Size() - ReadPosition; - - BufferPtr(buffer).CopyFrom (streamBuf.GetRange (ReadPosition, len)); - ReadPosition += len; - return len; - } - - void MemoryStream::ReadCompleteBuffer (const BufferPtr &buffer) - { - if (Read (buffer) != buffer.Size()) - throw InsufficientData (SRC_POS); - } - - void MemoryStream::Write (const ConstBufferPtr &data) - { - for (uint64 i = 0; i < data.Size(); i++) - Data.push_back (data[i]); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Exception.h" +#include "MemoryStream.h" + +namespace TrueCrypt +{ + MemoryStream::MemoryStream (const ConstBufferPtr &data) : + ReadPosition (0) + { + Data = vector (data.Size()); + BufferPtr (&Data[0], Data.size()).CopyFrom (data); + } + + uint64 MemoryStream::Read (const BufferPtr &buffer) + { + if (Data.size() == 0) + throw ParameterIncorrect (SRC_POS); + + ConstBufferPtr streamBuf (*this); + size_t len = buffer.Size(); + if (streamBuf.Size() - ReadPosition < len) + len = streamBuf.Size() - ReadPosition; + + BufferPtr(buffer).CopyFrom (streamBuf.GetRange (ReadPosition, len)); + ReadPosition += len; + return len; + } + + void MemoryStream::ReadCompleteBuffer (const BufferPtr &buffer) + { + if (Read (buffer) != buffer.Size()) + throw InsufficientData (SRC_POS); + } + + void MemoryStream::Write (const ConstBufferPtr &data) + { + for (uint64 i = 0; i < data.Size(); i++) + Data.push_back (data[i]); + } +} diff --git a/Platform/MemoryStream.h b/Platform/MemoryStream.h index 1d1fdf3..39074ba 100644 --- a/Platform/MemoryStream.h +++ b/Platform/MemoryStream.h @@ -1,36 +1,36 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_MemoryStream -#define TC_HEADER_Platform_MemoryStream - -#include "PlatformBase.h" -#include "Stream.h" - -namespace TrueCrypt -{ - class MemoryStream : public Stream - { - public: - MemoryStream () : ReadPosition (0) { } - MemoryStream (const ConstBufferPtr &data); - virtual ~MemoryStream () { } - - operator ConstBufferPtr () const { return ConstBufferPtr (&Data[0], Data.size()); } - - virtual uint64 Read (const BufferPtr &buffer); - virtual void ReadCompleteBuffer (const BufferPtr &buffer); - virtual void Write (const ConstBufferPtr &data); - - protected: - vector Data; - size_t ReadPosition; - }; -} - -#endif // TC_HEADER_Platform_MemoryStream +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_MemoryStream +#define TC_HEADER_Platform_MemoryStream + +#include "PlatformBase.h" +#include "Stream.h" + +namespace TrueCrypt +{ + class MemoryStream : public Stream + { + public: + MemoryStream () : ReadPosition (0) { } + MemoryStream (const ConstBufferPtr &data); + virtual ~MemoryStream () { } + + operator ConstBufferPtr () const { return ConstBufferPtr (&Data[0], Data.size()); } + + virtual uint64 Read (const BufferPtr &buffer); + virtual void ReadCompleteBuffer (const BufferPtr &buffer); + virtual void Write (const ConstBufferPtr &data); + + protected: + vector Data; + size_t ReadPosition; + }; +} + +#endif // TC_HEADER_Platform_MemoryStream diff --git a/Platform/Mutex.h b/Platform/Mutex.h index 260564e..803dd0c 100644 --- a/Platform/Mutex.h +++ b/Platform/Mutex.h @@ -1,61 +1,61 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Mutex -#define TC_HEADER_Platform_Mutex - -#ifdef TC_WINDOWS -# include "System.h" -#else -# include -#endif -#include "PlatformBase.h" - -namespace TrueCrypt -{ - class Mutex - { -#ifdef TC_WINDOWS - typedef CRITICAL_SECTION SystemMutex_t; -#else - typedef pthread_mutex_t SystemMutex_t; -#endif - - public: - Mutex (); - ~Mutex (); - - SystemMutex_t *GetSystemHandle () { return &SystemMutex; } - void Lock (); - void Unlock (); - - protected: - bool Initialized; - SystemMutex_t SystemMutex; - - private: - Mutex (const Mutex &); - Mutex &operator= (const Mutex &); - }; - - class ScopeLock - { - public: - ScopeLock (Mutex &mutex) : ScopeMutex (mutex) { mutex.Lock(); } - ~ScopeLock () { ScopeMutex.Unlock(); } - - protected: - Mutex &ScopeMutex; - - private: - ScopeLock (const ScopeLock &); - ScopeLock &operator= (const ScopeLock &); - }; -} - -#endif // TC_HEADER_Platform_Mutex +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Mutex +#define TC_HEADER_Platform_Mutex + +#ifdef TC_WINDOWS +# include "System.h" +#else +# include +#endif +#include "PlatformBase.h" + +namespace TrueCrypt +{ + class Mutex + { +#ifdef TC_WINDOWS + typedef CRITICAL_SECTION SystemMutex_t; +#else + typedef pthread_mutex_t SystemMutex_t; +#endif + + public: + Mutex (); + ~Mutex (); + + SystemMutex_t *GetSystemHandle () { return &SystemMutex; } + void Lock (); + void Unlock (); + + protected: + bool Initialized; + SystemMutex_t SystemMutex; + + private: + Mutex (const Mutex &); + Mutex &operator= (const Mutex &); + }; + + class ScopeLock + { + public: + ScopeLock (Mutex &mutex) : ScopeMutex (mutex) { mutex.Lock(); } + ~ScopeLock () { ScopeMutex.Unlock(); } + + protected: + Mutex &ScopeMutex; + + private: + ScopeLock (const ScopeLock &); + ScopeLock &operator= (const ScopeLock &); + }; +} + +#endif // TC_HEADER_Platform_Mutex diff --git a/Platform/Platform.h b/Platform/Platform.h index 3ffb6f5..9c89087 100644 --- a/Platform/Platform.h +++ b/Platform/Platform.h @@ -1,28 +1,28 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform -#define TC_HEADER_Platform - -#include "PlatformBase.h" -#include "Buffer.h" -#include "Exception.h" -#include "Directory.h" -#include "Event.h" -#include "File.h" -#include "FilesystemPath.h" -#include "Finally.h" -#include "ForEach.h" -#include "Functor.h" -#include "Memory.h" -#include "Mutex.h" -#include "SharedPtr.h" -#include "SystemException.h" -#include "Thread.h" - -#endif // TC_HEADER_Platform +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform +#define TC_HEADER_Platform + +#include "PlatformBase.h" +#include "Buffer.h" +#include "Exception.h" +#include "Directory.h" +#include "Event.h" +#include "File.h" +#include "FilesystemPath.h" +#include "Finally.h" +#include "ForEach.h" +#include "Functor.h" +#include "Memory.h" +#include "Mutex.h" +#include "SharedPtr.h" +#include "SystemException.h" +#include "Thread.h" + +#endif // TC_HEADER_Platform diff --git a/Platform/Platform.make b/Platform/Platform.make index e78a056..14e62f0 100644 --- a/Platform/Platform.make +++ b/Platform/Platform.make @@ -1,35 +1,35 @@ -# -# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -OBJS := Buffer.o -OBJS += Exception.o -OBJS += Event.o -OBJS += FileCommon.o -OBJS += MemoryStream.o -OBJS += Memory.o -OBJS += PlatformTest.o -OBJS += Serializable.o -OBJS += Serializer.o -OBJS += SerializerFactory.o -OBJS += StringConverter.o -OBJS += TextReader.o -OBJS += Unix/Directory.o -OBJS += Unix/File.o -OBJS += Unix/FilesystemPath.o -OBJS += Unix/Mutex.o -OBJS += Unix/Pipe.o -OBJS += Unix/Poller.o -OBJS += Unix/Process.o -OBJS += Unix/SyncEvent.o -OBJS += Unix/SystemException.o -OBJS += Unix/SystemInfo.o -OBJS += Unix/SystemLog.o -OBJS += Unix/Thread.o -OBJS += Unix/Time.o - -include $(BUILD_INC)/Makefile.inc +# +# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +OBJS := Buffer.o +OBJS += Exception.o +OBJS += Event.o +OBJS += FileCommon.o +OBJS += MemoryStream.o +OBJS += Memory.o +OBJS += PlatformTest.o +OBJS += Serializable.o +OBJS += Serializer.o +OBJS += SerializerFactory.o +OBJS += StringConverter.o +OBJS += TextReader.o +OBJS += Unix/Directory.o +OBJS += Unix/File.o +OBJS += Unix/FilesystemPath.o +OBJS += Unix/Mutex.o +OBJS += Unix/Pipe.o +OBJS += Unix/Poller.o +OBJS += Unix/Process.o +OBJS += Unix/SyncEvent.o +OBJS += Unix/SystemException.o +OBJS += Unix/SystemInfo.o +OBJS += Unix/SystemLog.o +OBJS += Unix/Thread.o +OBJS += Unix/Time.o + +include $(BUILD_INC)/Makefile.inc diff --git a/Platform/PlatformBase.h b/Platform/PlatformBase.h index 302725f..1fb371d 100644 --- a/Platform/PlatformBase.h +++ b/Platform/PlatformBase.h @@ -1,130 +1,130 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_PlatformBase -#define TC_HEADER_Platform_PlatformBase - -#include -#include -#include -#include -#include -#include -#include - -#ifndef _MSC_VER -#include -#endif - -using namespace std; - -#ifndef nullptr -#define nullptr 0 -#endif - -namespace TrueCrypt -{ -#ifdef _MSC_VER -# ifndef TC_INT_TYPES_DEFINED - typedef __int8 int8; - typedef __int16 int16; - typedef __int32 int32; - typedef __int64 int64; - typedef unsigned __int8 byte; - typedef unsigned __int16 uint16; - typedef unsigned __int32 uint32; - typedef unsigned __int64 uint64; -# endif -#else - typedef int8_t int8; - typedef int16_t int16; - typedef int32_t int32; - typedef int64_t int64; - typedef uint8_t byte; - typedef uint16_t uint16; - typedef uint32_t uint32; - typedef uint64_t uint64; -#endif -} - -#if (defined(_WIN32) || defined(_WIN64)) && !defined(TC_WINDOWS) -# define TC_WINDOWS -#endif - -#if defined(_DEBUG) && !defined(DEBUG) -# define DEBUG -#endif - -#ifndef TC_TO_STRING -# define TC_TO_STRING2(n) #n -# define TC_TO_STRING(n) TC_TO_STRING2(n) -#endif - -#define TC_JOIN_ARGS(a,b) a##b -#define TC_JOIN(a,b) TC_JOIN_ARGS(a,b) - -#ifdef __GNUC__ - template string GetFunctionName (T pos) - { - string s (pos); - size_t p = s.find ('('); - if (p == string::npos) - return s; - s = s.substr (0, p); - p = s.find_last_of (" "); - if (p == string::npos) - return s; - return s.substr (p + 1); - } -# define SRC_POS (GetFunctionName (__PRETTY_FUNCTION__) += ":" TC_TO_STRING(__LINE__)) -# define TC_UNUSED_VAR __attribute__ ((unused)) -#else -# define SRC_POS (__FUNCTION__ ":" TC_TO_STRING(__LINE__)) -# define TC_UNUSED_VAR -#endif - -#ifdef trace_point -# undef trace_point -#endif - -#ifdef trace_msg -# undef trace_msg -#endif - -#ifdef DEBUG -# define if_debug(...) __VA_ARGS__ - -# ifdef TC_WINDOWS -# define trace_point OutputDebugStringA ((string (SRC_POS) + "\n").c_str()) -# define trace_msg(stream_args) do { stringstream s; s << (SRC_POS) << ": " << stream_args << endl; OutputDebugStringA (s.str().c_str()); } while (0) -# define trace_msgw(stream_args) do { wstringstream s; s << (SRC_POS) << L": " << stream_args << endl; OutputDebugStringW (s.str().c_str()); } while (0) -# else -# include -# define trace_point cerr << (SRC_POS) << endl -# define trace_msg(stream_args) cerr << (SRC_POS) << ": " << stream_args << endl -# define trace_msgw(stream_args) cerr << (SRC_POS); wcerr << L": " << stream_args << endl -# endif - -# include "Platform/SystemLog.h" -# define trace_log_point SystemLog::WriteError (SRC_POS) -# define trace_log_msg(stream_args) do { stringstream s; s << (SRC_POS) << ": " << stream_args; SystemLog::WriteError (s.str()); } while (0) - -#else -# define if_debug(...) -# define trace_point -# define trace_msg(...) -# define trace_msgw(...) -# define trace_log_point -# define trace_log_msg(...) -#endif - -#define trace_val(VAL) trace_msg (#VAL << '=' << (VAL)); - -#define array_capacity(arr) (sizeof (arr) / sizeof ((arr)[0])) - -#endif // TC_HEADER_Platform_PlatformBase +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_PlatformBase +#define TC_HEADER_Platform_PlatformBase + +#include +#include +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#endif + +using namespace std; + +#ifndef nullptr +#define nullptr 0 +#endif + +namespace TrueCrypt +{ +#ifdef _MSC_VER +# ifndef TC_INT_TYPES_DEFINED + typedef __int8 int8; + typedef __int16 int16; + typedef __int32 int32; + typedef __int64 int64; + typedef unsigned __int8 byte; + typedef unsigned __int16 uint16; + typedef unsigned __int32 uint32; + typedef unsigned __int64 uint64; +# endif +#else + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + typedef uint8_t byte; + typedef uint16_t uint16; + typedef uint32_t uint32; + typedef uint64_t uint64; +#endif +} + +#if (defined(_WIN32) || defined(_WIN64)) && !defined(TC_WINDOWS) +# define TC_WINDOWS +#endif + +#if defined(_DEBUG) && !defined(DEBUG) +# define DEBUG +#endif + +#ifndef TC_TO_STRING +# define TC_TO_STRING2(n) #n +# define TC_TO_STRING(n) TC_TO_STRING2(n) +#endif + +#define TC_JOIN_ARGS(a,b) a##b +#define TC_JOIN(a,b) TC_JOIN_ARGS(a,b) + +#ifdef __GNUC__ + template string GetFunctionName (T pos) + { + string s (pos); + size_t p = s.find ('('); + if (p == string::npos) + return s; + s = s.substr (0, p); + p = s.find_last_of (" "); + if (p == string::npos) + return s; + return s.substr (p + 1); + } +# define SRC_POS (GetFunctionName (__PRETTY_FUNCTION__) += ":" TC_TO_STRING(__LINE__)) +# define TC_UNUSED_VAR __attribute__ ((unused)) +#else +# define SRC_POS (__FUNCTION__ ":" TC_TO_STRING(__LINE__)) +# define TC_UNUSED_VAR +#endif + +#ifdef trace_point +# undef trace_point +#endif + +#ifdef trace_msg +# undef trace_msg +#endif + +#ifdef DEBUG +# define if_debug(...) __VA_ARGS__ + +# ifdef TC_WINDOWS +# define trace_point OutputDebugStringA ((string (SRC_POS) + "\n").c_str()) +# define trace_msg(stream_args) do { stringstream s; s << (SRC_POS) << ": " << stream_args << endl; OutputDebugStringA (s.str().c_str()); } while (0) +# define trace_msgw(stream_args) do { wstringstream s; s << (SRC_POS) << L": " << stream_args << endl; OutputDebugStringW (s.str().c_str()); } while (0) +# else +# include +# define trace_point cerr << (SRC_POS) << endl +# define trace_msg(stream_args) cerr << (SRC_POS) << ": " << stream_args << endl +# define trace_msgw(stream_args) cerr << (SRC_POS); wcerr << L": " << stream_args << endl +# endif + +# include "Platform/SystemLog.h" +# define trace_log_point SystemLog::WriteError (SRC_POS) +# define trace_log_msg(stream_args) do { stringstream s; s << (SRC_POS) << ": " << stream_args; SystemLog::WriteError (s.str()); } while (0) + +#else +# define if_debug(...) +# define trace_point +# define trace_msg(...) +# define trace_msgw(...) +# define trace_log_point +# define trace_log_msg(...) +#endif + +#define trace_val(VAL) trace_msg (#VAL << '=' << (VAL)); + +#define array_capacity(arr) (sizeof (arr) / sizeof ((arr)[0])) + +#endif // TC_HEADER_Platform_PlatformBase diff --git a/Platform/PlatformTest.cpp b/Platform/PlatformTest.cpp index c03a9bd..1c30931 100644 --- a/Platform/PlatformTest.cpp +++ b/Platform/PlatformTest.cpp @@ -1,350 +1,350 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "PlatformTest.h" -#include "Exception.h" -#include "FileStream.h" -#include "Finally.h" -#include "ForEach.h" -#include "MemoryStream.h" -#include "Mutex.h" -#include "Serializable.h" -#include "SharedPtr.h" -#include "StringConverter.h" -#include "SyncEvent.h" -#include "Thread.h" -#include "Common/Tcdefs.h" - -namespace TrueCrypt -{ - // make_shared_auto, File, Stream, MemoryStream, Endian, Serializer, Serializable - void PlatformTest::SerializerTest () - { - shared_ptr stream (new MemoryStream); - -#if 0 - make_shared_auto (File, file); - finally_do_arg (File&, *file, { if (finally_arg.IsOpen()) finally_arg.Delete(); }); - - try - { - file->Open ("truecrypt-serializer-test.tmp", File::CreateReadWrite); - stream = shared_ptr (new FileStream (file)); - } - catch (...) { } -#endif - - Serializer ser (stream); - - uint32 i32 = 0x12345678; - uint64 i64 = 0x0123456789abcdefULL; - string str = "string test"; - wstring wstr = L"wstring test"; - - string convStr = "test"; - StringConverter::ToSingle (wstr, convStr); - if (convStr != "wstring test") - throw TestFailed (SRC_POS); - - StringConverter::Erase (convStr); - if (convStr != " ") - throw TestFailed (SRC_POS); - - wstring wEraseTest = L"erase test"; - StringConverter::Erase (wEraseTest); - if (wEraseTest != L" ") - throw TestFailed (SRC_POS); - - list stringList; - stringList.push_back (str + "1"); - stringList.push_back (str + "2"); - stringList.push_back (str + "3"); - - list wstringList; - wstringList.push_back (wstr + L"1"); - wstringList.push_back (wstr + L"2"); - wstringList.push_back (wstr + L"3"); - - Buffer buffer (10); - for (size_t i = 0; i < buffer.Size(); i++) - buffer[i] = (byte) i; - - ser.Serialize ("int32", i32); - ser.Serialize ("int64", i64); - ser.Serialize ("string", str); - ser.Serialize ("wstring", wstr); - ser.Serialize ("stringList", stringList); - ser.Serialize ("wstringList", wstringList); - ser.Serialize ("buffer", ConstBufferPtr (buffer)); - - ExecutedProcessFailed ex (SRC_POS, "cmd", -123, "error output"); - ex.Serialize (stream); - - list < shared_ptr > exList; - exList.push_back (make_shared (ExecutedProcessFailed (SRC_POS, "cmd", -123, "error output1"))); - exList.push_back (make_shared (ExecutedProcessFailed (SRC_POS, "cmd", -234, "error output2"))); - exList.push_back (make_shared (ExecutedProcessFailed (SRC_POS, "cmd", -567, "error output3"))); - Serializable::SerializeList (stream, exList); - -#if 0 - if (file->IsOpen()) - file->SeekAt (0); -#endif - - uint32 di32; - ser.Deserialize ("int32", di32); - if (i32 != di32) - throw TestFailed (SRC_POS); - - uint64 di64; - ser.Deserialize ("int64", di64); - if (i64 != di64) - throw TestFailed (SRC_POS); - - string dstr; - ser.Deserialize ("string", dstr); - if (str != dstr) - throw TestFailed (SRC_POS); - - wstring dwstr; - ser.Deserialize ("wstring", dwstr); - if (str != dstr) - throw TestFailed (SRC_POS); - - int i = 1; - foreach (string item, ser.DeserializeStringList ("stringList")) - { - stringstream s; - s << str << i++; - if (item != s.str()) - throw TestFailed (SRC_POS); - } - - i = 1; - foreach (wstring item, ser.DeserializeWStringList ("wstringList")) - { - wstringstream s; - s << wstr << i++; - if (item != s.str()) - throw TestFailed (SRC_POS); - } - - Buffer dbuffer (10); - ser.Deserialize ("buffer", buffer); - for (size_t i = 0; i < buffer.Size(); i++) - if (buffer[i] != (byte) i) - throw TestFailed (SRC_POS); - - shared_ptr dex = Serializable::DeserializeNew (stream); - if (!dex - || dex->GetCommand() != "cmd" - || dex->GetExitCode() != -123 - || dex->GetErrorOutput() != "error output") - throw TestFailed (SRC_POS); - - list < shared_ptr > dexList; - Serializable::DeserializeList (stream, dexList); - i = 1; - foreach_ref (const ExecutedProcessFailed &ex, dexList) - { - stringstream s; - s << "error output" << i++; - if (ex.GetErrorOutput() != s.str()) - throw TestFailed (SRC_POS); - } - } - - // shared_ptr, Mutex, ScopeLock, SyncEvent, Thread - static struct - { - shared_ptr SharedIntPtr; - Mutex IntMutex; - SyncEvent ExitAllowedEvent; - } ThreadTestData; - - void PlatformTest::ThreadTest () - { - Mutex mutex; - mutex.Lock(); - mutex.Unlock(); - - const int maxThreads = 3; - ThreadTestData.SharedIntPtr.reset (new int (0)); - - for (int i = 0; i < maxThreads; i++) - { - Thread t; - t.Start (&ThreadTestProc, (void *) &ThreadTestData); - } - - for (int i = 0; i < 50; i++) - { - { - ScopeLock sl (ThreadTestData.IntMutex); - if (*ThreadTestData.SharedIntPtr == maxThreads) - break; - } - - Thread::Sleep(100); - } - - if (*ThreadTestData.SharedIntPtr != maxThreads) - throw TestFailed (SRC_POS); - - for (int i = 0; i < 60000; i++) - { - ThreadTestData.ExitAllowedEvent.Signal(); - Thread::Sleep(1); - - ScopeLock sl (ThreadTestData.IntMutex); - if (*ThreadTestData.SharedIntPtr == 0) - break; - } - - if (*ThreadTestData.SharedIntPtr != 0) - throw TestFailed (SRC_POS); - } - - TC_THREAD_PROC PlatformTest::ThreadTestProc (void *arg) - { - - if (arg != (void *) &ThreadTestData) - return 0; - - { - ScopeLock sl (ThreadTestData.IntMutex); - ++(*ThreadTestData.SharedIntPtr); - } - - ThreadTestData.ExitAllowedEvent.Wait(); - - { - ScopeLock sl (ThreadTestData.IntMutex); - --(*ThreadTestData.SharedIntPtr); - } - - return 0; - } - - bool PlatformTest::TestAll () - { - // Integer types - if (sizeof (byte) != 1 || sizeof (int8) != 1 || sizeof (__int8) != 1) throw TestFailed (SRC_POS); - if (sizeof (uint16) != 2 || sizeof (int16) != 2 || sizeof (__int16) != 2) throw TestFailed (SRC_POS); - if (sizeof (uint32) != 4 || sizeof (int32) != 4 || sizeof (__int32) != 4) throw TestFailed (SRC_POS); - if (sizeof (uint64) != 8 || sizeof (int64) != 8) throw TestFailed (SRC_POS); - - // Exception handling - TestFlag = false; - try - { - try - { - throw TestFailed (SRC_POS); - } - catch (...) - { - throw; - } - return false; - } - catch (Exception &) - { - TestFlag = true; - } - if (!TestFlag) - return false; - - // RTTI - RttiTest rtti; - RttiTestBase &rttiBaseRef = rtti; - RttiTestBase *rttiBasePtr = &rtti; - - if (typeid (rttiBaseRef) != typeid (rtti)) - throw TestFailed (SRC_POS); - - if (typeid (*rttiBasePtr) != typeid (rtti)) - throw TestFailed (SRC_POS); - - if (dynamic_cast (rttiBasePtr) == nullptr) - throw TestFailed (SRC_POS); - - try - { - dynamic_cast (rttiBaseRef); - } - catch (...) - { - throw TestFailed (SRC_POS); - } - - // finally - TestFlag = false; - { - finally_do ({ TestFlag = true; }); - if (TestFlag) - throw TestFailed (SRC_POS); - } - if (!TestFlag) - throw TestFailed (SRC_POS); - - TestFlag = false; - { - finally_do_arg (bool&, TestFlag, { finally_arg = true; }); - if (TestFlag) - throw TestFailed (SRC_POS); - } - if (!TestFlag) - throw TestFailed (SRC_POS); - - TestFlag = false; - int tesFlag2 = 0; - { - finally_do_arg2 (bool&, TestFlag, int&, tesFlag2, { finally_arg = true; finally_arg2 = 2; }); - if (TestFlag || tesFlag2 != 0) - throw TestFailed (SRC_POS); - } - if (!TestFlag || tesFlag2 != 2) - throw TestFailed (SRC_POS); - - // uint64, vector, list, string, wstring, stringstream, wstringstream - // shared_ptr, make_shared, StringConverter, foreach - list > numList; - - numList.push_front (make_shared (StringConverter::ToUInt64 (StringConverter::FromNumber ((uint64) 0xFFFFffffFFFFfffeULL)))); - numList.push_front (make_shared (StringConverter::ToUInt32 (StringConverter::GetTrailingNumber ("str2")))); - numList.push_front (make_shared (3)); - - list testList; - wstringstream wstream (L"test"); - foreach_reverse_ref (uint64 n, numList) - { - wstream.str (L""); - wstream << L"str" << n; - testList.push_back (wstream.str()); - } - - stringstream sstream; - sstream << "dummy"; - sstream.str (""); - sstream << "str18446744073709551614,str2" << " str" << StringConverter::Trim (StringConverter::ToSingle (L"\t 3 \r\n")); - foreach (const string &s, StringConverter::Split (sstream.str(), ", ")) - { - if (testList.front() != StringConverter::ToWide (s)) - throw TestFailed (SRC_POS); - testList.pop_front(); - } - - SerializerTest(); - ThreadTest(); - - return true; - } - - bool PlatformTest::TestFlag; -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "PlatformTest.h" +#include "Exception.h" +#include "FileStream.h" +#include "Finally.h" +#include "ForEach.h" +#include "MemoryStream.h" +#include "Mutex.h" +#include "Serializable.h" +#include "SharedPtr.h" +#include "StringConverter.h" +#include "SyncEvent.h" +#include "Thread.h" +#include "Common/Tcdefs.h" + +namespace TrueCrypt +{ + // make_shared_auto, File, Stream, MemoryStream, Endian, Serializer, Serializable + void PlatformTest::SerializerTest () + { + shared_ptr stream (new MemoryStream); + +#if 0 + make_shared_auto (File, file); + finally_do_arg (File&, *file, { if (finally_arg.IsOpen()) finally_arg.Delete(); }); + + try + { + file->Open ("truecrypt-serializer-test.tmp", File::CreateReadWrite); + stream = shared_ptr (new FileStream (file)); + } + catch (...) { } +#endif + + Serializer ser (stream); + + uint32 i32 = 0x12345678; + uint64 i64 = 0x0123456789abcdefULL; + string str = "string test"; + wstring wstr = L"wstring test"; + + string convStr = "test"; + StringConverter::ToSingle (wstr, convStr); + if (convStr != "wstring test") + throw TestFailed (SRC_POS); + + StringConverter::Erase (convStr); + if (convStr != " ") + throw TestFailed (SRC_POS); + + wstring wEraseTest = L"erase test"; + StringConverter::Erase (wEraseTest); + if (wEraseTest != L" ") + throw TestFailed (SRC_POS); + + list stringList; + stringList.push_back (str + "1"); + stringList.push_back (str + "2"); + stringList.push_back (str + "3"); + + list wstringList; + wstringList.push_back (wstr + L"1"); + wstringList.push_back (wstr + L"2"); + wstringList.push_back (wstr + L"3"); + + Buffer buffer (10); + for (size_t i = 0; i < buffer.Size(); i++) + buffer[i] = (byte) i; + + ser.Serialize ("int32", i32); + ser.Serialize ("int64", i64); + ser.Serialize ("string", str); + ser.Serialize ("wstring", wstr); + ser.Serialize ("stringList", stringList); + ser.Serialize ("wstringList", wstringList); + ser.Serialize ("buffer", ConstBufferPtr (buffer)); + + ExecutedProcessFailed ex (SRC_POS, "cmd", -123, "error output"); + ex.Serialize (stream); + + list < shared_ptr > exList; + exList.push_back (make_shared (ExecutedProcessFailed (SRC_POS, "cmd", -123, "error output1"))); + exList.push_back (make_shared (ExecutedProcessFailed (SRC_POS, "cmd", -234, "error output2"))); + exList.push_back (make_shared (ExecutedProcessFailed (SRC_POS, "cmd", -567, "error output3"))); + Serializable::SerializeList (stream, exList); + +#if 0 + if (file->IsOpen()) + file->SeekAt (0); +#endif + + uint32 di32; + ser.Deserialize ("int32", di32); + if (i32 != di32) + throw TestFailed (SRC_POS); + + uint64 di64; + ser.Deserialize ("int64", di64); + if (i64 != di64) + throw TestFailed (SRC_POS); + + string dstr; + ser.Deserialize ("string", dstr); + if (str != dstr) + throw TestFailed (SRC_POS); + + wstring dwstr; + ser.Deserialize ("wstring", dwstr); + if (str != dstr) + throw TestFailed (SRC_POS); + + int i = 1; + foreach (string item, ser.DeserializeStringList ("stringList")) + { + stringstream s; + s << str << i++; + if (item != s.str()) + throw TestFailed (SRC_POS); + } + + i = 1; + foreach (wstring item, ser.DeserializeWStringList ("wstringList")) + { + wstringstream s; + s << wstr << i++; + if (item != s.str()) + throw TestFailed (SRC_POS); + } + + Buffer dbuffer (10); + ser.Deserialize ("buffer", buffer); + for (size_t i = 0; i < buffer.Size(); i++) + if (buffer[i] != (byte) i) + throw TestFailed (SRC_POS); + + shared_ptr dex = Serializable::DeserializeNew (stream); + if (!dex + || dex->GetCommand() != "cmd" + || dex->GetExitCode() != -123 + || dex->GetErrorOutput() != "error output") + throw TestFailed (SRC_POS); + + list < shared_ptr > dexList; + Serializable::DeserializeList (stream, dexList); + i = 1; + foreach_ref (const ExecutedProcessFailed &ex, dexList) + { + stringstream s; + s << "error output" << i++; + if (ex.GetErrorOutput() != s.str()) + throw TestFailed (SRC_POS); + } + } + + // shared_ptr, Mutex, ScopeLock, SyncEvent, Thread + static struct + { + shared_ptr SharedIntPtr; + Mutex IntMutex; + SyncEvent ExitAllowedEvent; + } ThreadTestData; + + void PlatformTest::ThreadTest () + { + Mutex mutex; + mutex.Lock(); + mutex.Unlock(); + + const int maxThreads = 3; + ThreadTestData.SharedIntPtr.reset (new int (0)); + + for (int i = 0; i < maxThreads; i++) + { + Thread t; + t.Start (&ThreadTestProc, (void *) &ThreadTestData); + } + + for (int i = 0; i < 50; i++) + { + { + ScopeLock sl (ThreadTestData.IntMutex); + if (*ThreadTestData.SharedIntPtr == maxThreads) + break; + } + + Thread::Sleep(100); + } + + if (*ThreadTestData.SharedIntPtr != maxThreads) + throw TestFailed (SRC_POS); + + for (int i = 0; i < 60000; i++) + { + ThreadTestData.ExitAllowedEvent.Signal(); + Thread::Sleep(1); + + ScopeLock sl (ThreadTestData.IntMutex); + if (*ThreadTestData.SharedIntPtr == 0) + break; + } + + if (*ThreadTestData.SharedIntPtr != 0) + throw TestFailed (SRC_POS); + } + + TC_THREAD_PROC PlatformTest::ThreadTestProc (void *arg) + { + + if (arg != (void *) &ThreadTestData) + return 0; + + { + ScopeLock sl (ThreadTestData.IntMutex); + ++(*ThreadTestData.SharedIntPtr); + } + + ThreadTestData.ExitAllowedEvent.Wait(); + + { + ScopeLock sl (ThreadTestData.IntMutex); + --(*ThreadTestData.SharedIntPtr); + } + + return 0; + } + + bool PlatformTest::TestAll () + { + // Integer types + if (sizeof (byte) != 1 || sizeof (int8) != 1 || sizeof (__int8) != 1) throw TestFailed (SRC_POS); + if (sizeof (uint16) != 2 || sizeof (int16) != 2 || sizeof (__int16) != 2) throw TestFailed (SRC_POS); + if (sizeof (uint32) != 4 || sizeof (int32) != 4 || sizeof (__int32) != 4) throw TestFailed (SRC_POS); + if (sizeof (uint64) != 8 || sizeof (int64) != 8) throw TestFailed (SRC_POS); + + // Exception handling + TestFlag = false; + try + { + try + { + throw TestFailed (SRC_POS); + } + catch (...) + { + throw; + } + return false; + } + catch (Exception &) + { + TestFlag = true; + } + if (!TestFlag) + return false; + + // RTTI + RttiTest rtti; + RttiTestBase &rttiBaseRef = rtti; + RttiTestBase *rttiBasePtr = &rtti; + + if (typeid (rttiBaseRef) != typeid (rtti)) + throw TestFailed (SRC_POS); + + if (typeid (*rttiBasePtr) != typeid (rtti)) + throw TestFailed (SRC_POS); + + if (dynamic_cast (rttiBasePtr) == nullptr) + throw TestFailed (SRC_POS); + + try + { + dynamic_cast (rttiBaseRef); + } + catch (...) + { + throw TestFailed (SRC_POS); + } + + // finally + TestFlag = false; + { + finally_do ({ TestFlag = true; }); + if (TestFlag) + throw TestFailed (SRC_POS); + } + if (!TestFlag) + throw TestFailed (SRC_POS); + + TestFlag = false; + { + finally_do_arg (bool*, &TestFlag, { *finally_arg = true; }); + if (TestFlag) + throw TestFailed (SRC_POS); + } + if (!TestFlag) + throw TestFailed (SRC_POS); + + TestFlag = false; + int tesFlag2 = 0; + { + finally_do_arg2 (bool*, &TestFlag, int*, &tesFlag2, { *finally_arg = true; *finally_arg2 = 2; }); + if (TestFlag || tesFlag2 != 0) + throw TestFailed (SRC_POS); + } + if (!TestFlag || tesFlag2 != 2) + throw TestFailed (SRC_POS); + + // uint64, vector, list, string, wstring, stringstream, wstringstream + // shared_ptr, make_shared, StringConverter, foreach + list > numList; + + numList.push_front (make_shared (StringConverter::ToUInt64 (StringConverter::FromNumber ((uint64) 0xFFFFffffFFFFfffeULL)))); + numList.push_front (make_shared (StringConverter::ToUInt32 (StringConverter::GetTrailingNumber ("str2")))); + numList.push_front (make_shared (3)); + + list testList; + wstringstream wstream (L"test"); + foreach_reverse_ref (uint64 n, numList) + { + wstream.str (L""); + wstream << L"str" << n; + testList.push_back (wstream.str()); + } + + stringstream sstream; + sstream << "dummy"; + sstream.str (""); + sstream << "str18446744073709551614,str2" << " str" << StringConverter::Trim (StringConverter::ToSingle (L"\t 3 \r\n")); + foreach (const string &s, StringConverter::Split (sstream.str(), ", ")) + { + if (testList.front() != StringConverter::ToWide (s)) + throw TestFailed (SRC_POS); + testList.pop_front(); + } + + SerializerTest(); + ThreadTest(); + + return true; + } + + bool PlatformTest::TestFlag; +} diff --git a/Platform/PlatformTest.h b/Platform/PlatformTest.h index 077b50d..0ae2f67 100644 --- a/Platform/PlatformTest.h +++ b/Platform/PlatformTest.h @@ -1,43 +1,43 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_PlatformTest -#define TC_HEADER_Platform_PlatformTest - -#include "PlatformBase.h" -#include "Thread.h" - -namespace TrueCrypt -{ - class PlatformTest - { - public: - static bool TestAll (); - - protected: - class RttiTestBase - { - public: - virtual ~RttiTestBase () { }; - }; - - class RttiTest : public RttiTestBase { - public: - virtual ~RttiTest () { }; - }; - - PlatformTest (); - static void SerializerTest (); - static void ThreadTest (); - static TC_THREAD_PROC ThreadTestProc (void *param); - - static bool TestFlag; - }; -} - -#endif // TC_HEADER_Platform_PlatformTest +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_PlatformTest +#define TC_HEADER_Platform_PlatformTest + +#include "PlatformBase.h" +#include "Thread.h" + +namespace TrueCrypt +{ + class PlatformTest + { + public: + static bool TestAll (); + + protected: + class RttiTestBase + { + public: + virtual ~RttiTestBase () { }; + }; + + class RttiTest : public RttiTestBase { + public: + virtual ~RttiTest () { }; + }; + + PlatformTest (); + static void SerializerTest (); + static void ThreadTest (); + static TC_THREAD_PROC ThreadTestProc (void *param); + + static bool TestFlag; + }; +} + +#endif // TC_HEADER_Platform_PlatformTest diff --git a/Platform/Serializable.cpp b/Platform/Serializable.cpp index 9d83cf6..05769ff 100644 --- a/Platform/Serializable.cpp +++ b/Platform/Serializable.cpp @@ -1,39 +1,39 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Serializable.h" -#include "SerializerFactory.h" - -namespace TrueCrypt -{ - string Serializable::DeserializeHeader (shared_ptr stream) - { - Serializer sr (stream); - return sr.DeserializeString ("SerializableName"); - } - - Serializable *Serializable::DeserializeNew (shared_ptr stream) - { - string name = Serializable::DeserializeHeader (stream); - Serializable *serializable = SerializerFactory::GetNewSerializable (name); - serializable->Deserialize (stream); - - return serializable; - } - - void Serializable::Serialize (shared_ptr stream) const - { - Serializer sr (stream); - Serializable::SerializeHeader (sr, SerializerFactory::GetName (typeid (*this))); - } - - void Serializable::SerializeHeader (Serializer &serializer, const string &name) - { - serializer.Serialize ("SerializableName", name); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Serializable.h" +#include "SerializerFactory.h" + +namespace TrueCrypt +{ + string Serializable::DeserializeHeader (shared_ptr stream) + { + Serializer sr (stream); + return sr.DeserializeString ("SerializableName"); + } + + Serializable *Serializable::DeserializeNew (shared_ptr stream) + { + string name = Serializable::DeserializeHeader (stream); + Serializable *serializable = SerializerFactory::GetNewSerializable (name); + serializable->Deserialize (stream); + + return serializable; + } + + void Serializable::Serialize (shared_ptr stream) const + { + Serializer sr (stream); + Serializable::SerializeHeader (sr, SerializerFactory::GetName (typeid (*this))); + } + + void Serializable::SerializeHeader (Serializer &serializer, const string &name) + { + serializer.Serialize ("SerializableName", name); + } +} diff --git a/Platform/Serializable.h b/Platform/Serializable.h index b84535b..9e0fa31 100644 --- a/Platform/Serializable.h +++ b/Platform/Serializable.h @@ -1,82 +1,82 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Serializable -#define TC_HEADER_Platform_Serializable - -#include -#include "PlatformBase.h" -#include "ForEach.h" -#include "Serializer.h" -#include "SerializerFactory.h" - -namespace TrueCrypt -{ - class Serializable - { - public: - virtual ~Serializable () { } - - virtual void Deserialize (shared_ptr stream) = 0; - static string DeserializeHeader (shared_ptr stream); - static Serializable *DeserializeNew (shared_ptr stream); - - template - static shared_ptr DeserializeNew (shared_ptr stream) - { - shared_ptr p (dynamic_cast (DeserializeNew (stream))); - if (!p) - throw std::runtime_error (SRC_POS); - return p; - } - - template - static void DeserializeList (shared_ptr stream, list < shared_ptr > &dataList) - { - if (DeserializeHeader (stream) != string ("list<") + SerializerFactory::GetName (typeid (T)) + ">") - throw std::runtime_error (SRC_POS); - - Serializer sr (stream); - uint64 listSize; - sr.Deserialize ("ListSize", listSize); - - for (int i = 0; i < listSize; i++) - { - shared_ptr p (dynamic_cast (DeserializeNew (stream))); - if (!p) - throw std::runtime_error (SRC_POS); - dataList.push_back (p); - } - } - - virtual void Serialize (shared_ptr stream) const; - - template - static void SerializeList (shared_ptr stream, const list < shared_ptr > &dataList) - { - Serializer sr (stream); - SerializeHeader (sr, string ("list<") + SerializerFactory::GetName (typeid (T)) + ">"); - - sr.Serialize ("ListSize", (uint64) dataList.size()); - foreach_ref (const T &item, dataList) - item.Serialize (stream); - } - - static void SerializeHeader (Serializer &serializer, const string &name); - - protected: - Serializable () { } - }; -} - -#define TC_SERIALIZABLE(TYPE) \ - static Serializable *GetNewSerializable () { return new TYPE(); } \ - virtual void Deserialize (shared_ptr stream); \ - virtual void Serialize (shared_ptr stream) const - -#endif // TC_HEADER_Platform_Serializable +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Serializable +#define TC_HEADER_Platform_Serializable + +#include +#include "PlatformBase.h" +#include "ForEach.h" +#include "Serializer.h" +#include "SerializerFactory.h" + +namespace TrueCrypt +{ + class Serializable + { + public: + virtual ~Serializable () { } + + virtual void Deserialize (shared_ptr stream) = 0; + static string DeserializeHeader (shared_ptr stream); + static Serializable *DeserializeNew (shared_ptr stream); + + template + static shared_ptr DeserializeNew (shared_ptr stream) + { + shared_ptr p (dynamic_cast (DeserializeNew (stream))); + if (!p) + throw std::runtime_error (SRC_POS); + return p; + } + + template + static void DeserializeList (shared_ptr stream, list < shared_ptr > &dataList) + { + if (DeserializeHeader (stream) != string ("list<") + SerializerFactory::GetName (typeid (T)) + ">") + throw std::runtime_error (SRC_POS); + + Serializer sr (stream); + uint64 listSize; + sr.Deserialize ("ListSize", listSize); + + for (size_t i = 0; i < listSize; i++) + { + shared_ptr p (dynamic_cast (DeserializeNew (stream))); + if (!p) + throw std::runtime_error (SRC_POS); + dataList.push_back (p); + } + } + + virtual void Serialize (shared_ptr stream) const; + + template + static void SerializeList (shared_ptr stream, const list < shared_ptr > &dataList) + { + Serializer sr (stream); + SerializeHeader (sr, string ("list<") + SerializerFactory::GetName (typeid (T)) + ">"); + + sr.Serialize ("ListSize", (uint64) dataList.size()); + foreach_ref (const T &item, dataList) + item.Serialize (stream); + } + + static void SerializeHeader (Serializer &serializer, const string &name); + + protected: + Serializable () { } + }; +} + +#define TC_SERIALIZABLE(TYPE) \ + static Serializable *GetNewSerializable () { return new TYPE(); } \ + virtual void Deserialize (shared_ptr stream); \ + virtual void Serialize (shared_ptr stream) const + +#endif // TC_HEADER_Platform_Serializable diff --git a/Platform/Serializer.cpp b/Platform/Serializer.cpp index 72d45e9..70a5d79 100644 --- a/Platform/Serializer.cpp +++ b/Platform/Serializer.cpp @@ -1,299 +1,299 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Exception.h" -#include "ForEach.h" -#include "Memory.h" -#include "Serializer.h" - -namespace TrueCrypt -{ - template - T Serializer::Deserialize () - { - uint64 size; - DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &size, sizeof (size))); - - if (Endian::Big (size) != sizeof (T)) - throw ParameterIncorrect (SRC_POS); - - T data; - DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data, sizeof (data))); - - return Endian::Big (data); - } - - void Serializer::Deserialize (const string &name, bool &data) - { - ValidateName (name); - data = Deserialize () == 1; - } - - void Serializer::Deserialize (const string &name, byte &data) - { - ValidateName (name); - data = Deserialize (); - } - - void Serializer::Deserialize (const string &name, int32 &data) - { - ValidateName (name); - data = (int32) Deserialize (); - } - - void Serializer::Deserialize (const string &name, int64 &data) - { - ValidateName (name); - data = (int64) Deserialize (); - } - - void Serializer::Deserialize (const string &name, uint32 &data) - { - ValidateName (name); - data = Deserialize (); - } - - void Serializer::Deserialize (const string &name, uint64 &data) - { - ValidateName (name); - data = Deserialize (); - } - - void Serializer::Deserialize (const string &name, string &data) - { - ValidateName (name); - data = DeserializeString (); - } - - void Serializer::Deserialize (const string &name, wstring &data) - { - ValidateName (name); - data = DeserializeWString (); - } - - void Serializer::Deserialize (const string &name, const BufferPtr &data) - { - ValidateName (name); - - uint64 size = Deserialize (); - if (data.Size() != size) - throw ParameterIncorrect (SRC_POS); - - DataStream->ReadCompleteBuffer (data); - } - - bool Serializer::DeserializeBool (const string &name) - { - bool data; - Deserialize (name, data); - return data; - } - - int32 Serializer::DeserializeInt32 (const string &name) - { - ValidateName (name); - return Deserialize (); - } - - int64 Serializer::DeserializeInt64 (const string &name) - { - ValidateName (name); - return Deserialize (); - } - - uint32 Serializer::DeserializeUInt32 (const string &name) - { - ValidateName (name); - return Deserialize (); - } - - uint64 Serializer::DeserializeUInt64 (const string &name) - { - ValidateName (name); - return Deserialize (); - } - - string Serializer::DeserializeString () - { - uint64 size = Deserialize (); - - vector data ((size_t) size); - DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data[0], (size_t) size)); - - return string (&data[0]); - } - - string Serializer::DeserializeString (const string &name) - { - ValidateName (name); - return DeserializeString (); - } - - list Serializer::DeserializeStringList (const string &name) - { - ValidateName (name); - list deserializedList; - uint64 listSize = Deserialize (); - - for (int i = 0; i < listSize; i++) - deserializedList.push_back (DeserializeString ()); - - return deserializedList; - } - - wstring Serializer::DeserializeWString () - { - uint64 size = Deserialize (); - - vector data ((size_t) size / sizeof (wchar_t)); - DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data[0], (size_t) size)); - - return wstring (&data[0]); - } - - list Serializer::DeserializeWStringList (const string &name) - { - ValidateName (name); - list deserializedList; - uint64 listSize = Deserialize (); - - for (int i = 0; i < listSize; i++) - deserializedList.push_back (DeserializeWString ()); - - return deserializedList; - } - - wstring Serializer::DeserializeWString (const string &name) - { - ValidateName (name); - return DeserializeWString (); - } - - template - void Serializer::Serialize (T data) - { - uint64 size = Endian::Big (uint64 (sizeof (data))); - DataStream->Write (ConstBufferPtr ((byte *) &size, sizeof (size))); - - data = Endian::Big (data); - DataStream->Write (ConstBufferPtr ((byte *) &data, sizeof (data))); - } - - void Serializer::Serialize (const string &name, bool data) - { - SerializeString (name); - byte d = data ? 1 : 0; - Serialize (d); - } - - void Serializer::Serialize (const string &name, byte data) - { - SerializeString (name); - Serialize (data); - } - - void Serializer::Serialize (const string &name, const char *data) - { - Serialize (name, string (data)); - } - - void Serializer::Serialize (const string &name, int32 data) - { - SerializeString (name); - Serialize ((uint32) data); - } - - void Serializer::Serialize (const string &name, int64 data) - { - SerializeString (name); - Serialize ((uint64) data); - } - - void Serializer::Serialize (const string &name, uint32 data) - { - SerializeString (name); - Serialize (data); - } - - void Serializer::Serialize (const string &name, uint64 data) - { - SerializeString (name); - Serialize (data); - } - - void Serializer::Serialize (const string &name, const string &data) - { - SerializeString (name); - SerializeString (data); - } - - void Serializer::Serialize (const string &name, const wchar_t *data) - { - Serialize (name, wstring (data)); - } - - void Serializer::Serialize (const string &name, const wstring &data) - { - SerializeString (name); - SerializeWString (data); - } - - void Serializer::Serialize (const string &name, const list &stringList) - { - SerializeString (name); - - uint64 listSize = stringList.size(); - Serialize (listSize); - - foreach (const string &item, stringList) - SerializeString (item); - } - - void Serializer::Serialize (const string &name, const list &stringList) - { - SerializeString (name); - - uint64 listSize = stringList.size(); - Serialize (listSize); - - foreach (const wstring &item, stringList) - SerializeWString (item); - } - - void Serializer::Serialize (const string &name, const ConstBufferPtr &data) - { - SerializeString (name); - - uint64 size = data.Size(); - Serialize (size); - - DataStream->Write (data); - } - - void Serializer::SerializeString (const string &data) - { - Serialize ((uint64) data.size() + 1); - DataStream->Write (ConstBufferPtr ((byte *) (data.data() ? data.data() : data.c_str()), data.size() + 1)); - } - - void Serializer::SerializeWString (const wstring &data) - { - uint64 size = (data.size() + 1) * sizeof (wchar_t); - Serialize (size); - DataStream->Write (ConstBufferPtr ((byte *) (data.data() ? data.data() : data.c_str()), (size_t) size)); - } - - void Serializer::ValidateName (const string &name) - { - string dName = DeserializeString(); - if (dName != name) - { - throw ParameterIncorrect (SRC_POS); - } - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Exception.h" +#include "ForEach.h" +#include "Memory.h" +#include "Serializer.h" + +namespace TrueCrypt +{ + template + T Serializer::Deserialize () + { + uint64 size; + DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &size, sizeof (size))); + + if (Endian::Big (size) != sizeof (T)) + throw ParameterIncorrect (SRC_POS); + + T data; + DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data, sizeof (data))); + + return Endian::Big (data); + } + + void Serializer::Deserialize (const string &name, bool &data) + { + ValidateName (name); + data = Deserialize () == 1; + } + + void Serializer::Deserialize (const string &name, byte &data) + { + ValidateName (name); + data = Deserialize (); + } + + void Serializer::Deserialize (const string &name, int32 &data) + { + ValidateName (name); + data = (int32) Deserialize (); + } + + void Serializer::Deserialize (const string &name, int64 &data) + { + ValidateName (name); + data = (int64) Deserialize (); + } + + void Serializer::Deserialize (const string &name, uint32 &data) + { + ValidateName (name); + data = Deserialize (); + } + + void Serializer::Deserialize (const string &name, uint64 &data) + { + ValidateName (name); + data = Deserialize (); + } + + void Serializer::Deserialize (const string &name, string &data) + { + ValidateName (name); + data = DeserializeString (); + } + + void Serializer::Deserialize (const string &name, wstring &data) + { + ValidateName (name); + data = DeserializeWString (); + } + + void Serializer::Deserialize (const string &name, const BufferPtr &data) + { + ValidateName (name); + + uint64 size = Deserialize (); + if (data.Size() != size) + throw ParameterIncorrect (SRC_POS); + + DataStream->ReadCompleteBuffer (data); + } + + bool Serializer::DeserializeBool (const string &name) + { + bool data; + Deserialize (name, data); + return data; + } + + int32 Serializer::DeserializeInt32 (const string &name) + { + ValidateName (name); + return Deserialize (); + } + + int64 Serializer::DeserializeInt64 (const string &name) + { + ValidateName (name); + return Deserialize (); + } + + uint32 Serializer::DeserializeUInt32 (const string &name) + { + ValidateName (name); + return Deserialize (); + } + + uint64 Serializer::DeserializeUInt64 (const string &name) + { + ValidateName (name); + return Deserialize (); + } + + string Serializer::DeserializeString () + { + uint64 size = Deserialize (); + + vector data ((size_t) size); + DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data[0], (size_t) size)); + + return string (&data[0]); + } + + string Serializer::DeserializeString (const string &name) + { + ValidateName (name); + return DeserializeString (); + } + + list Serializer::DeserializeStringList (const string &name) + { + ValidateName (name); + list deserializedList; + uint64 listSize = Deserialize (); + + for (size_t i = 0; i < listSize; i++) + deserializedList.push_back (DeserializeString ()); + + return deserializedList; + } + + wstring Serializer::DeserializeWString () + { + uint64 size = Deserialize (); + + vector data ((size_t) size / sizeof (wchar_t)); + DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data[0], (size_t) size)); + + return wstring (&data[0]); + } + + list Serializer::DeserializeWStringList (const string &name) + { + ValidateName (name); + list deserializedList; + uint64 listSize = Deserialize (); + + for (size_t i = 0; i < listSize; i++) + deserializedList.push_back (DeserializeWString ()); + + return deserializedList; + } + + wstring Serializer::DeserializeWString (const string &name) + { + ValidateName (name); + return DeserializeWString (); + } + + template + void Serializer::Serialize (T data) + { + uint64 size = Endian::Big (uint64 (sizeof (data))); + DataStream->Write (ConstBufferPtr ((byte *) &size, sizeof (size))); + + data = Endian::Big (data); + DataStream->Write (ConstBufferPtr ((byte *) &data, sizeof (data))); + } + + void Serializer::Serialize (const string &name, bool data) + { + SerializeString (name); + byte d = data ? 1 : 0; + Serialize (d); + } + + void Serializer::Serialize (const string &name, byte data) + { + SerializeString (name); + Serialize (data); + } + + void Serializer::Serialize (const string &name, const char *data) + { + Serialize (name, string (data)); + } + + void Serializer::Serialize (const string &name, int32 data) + { + SerializeString (name); + Serialize ((uint32) data); + } + + void Serializer::Serialize (const string &name, int64 data) + { + SerializeString (name); + Serialize ((uint64) data); + } + + void Serializer::Serialize (const string &name, uint32 data) + { + SerializeString (name); + Serialize (data); + } + + void Serializer::Serialize (const string &name, uint64 data) + { + SerializeString (name); + Serialize (data); + } + + void Serializer::Serialize (const string &name, const string &data) + { + SerializeString (name); + SerializeString (data); + } + + void Serializer::Serialize (const string &name, const wchar_t *data) + { + Serialize (name, wstring (data)); + } + + void Serializer::Serialize (const string &name, const wstring &data) + { + SerializeString (name); + SerializeWString (data); + } + + void Serializer::Serialize (const string &name, const list &stringList) + { + SerializeString (name); + + uint64 listSize = stringList.size(); + Serialize (listSize); + + foreach (const string &item, stringList) + SerializeString (item); + } + + void Serializer::Serialize (const string &name, const list &stringList) + { + SerializeString (name); + + uint64 listSize = stringList.size(); + Serialize (listSize); + + foreach (const wstring &item, stringList) + SerializeWString (item); + } + + void Serializer::Serialize (const string &name, const ConstBufferPtr &data) + { + SerializeString (name); + + uint64 size = data.Size(); + Serialize (size); + + DataStream->Write (data); + } + + void Serializer::SerializeString (const string &data) + { + Serialize ((uint64) data.size() + 1); + DataStream->Write (ConstBufferPtr ((byte *) (data.data() ? data.data() : data.c_str()), data.size() + 1)); + } + + void Serializer::SerializeWString (const wstring &data) + { + uint64 size = (data.size() + 1) * sizeof (wchar_t); + Serialize (size); + DataStream->Write (ConstBufferPtr ((byte *) (data.data() ? data.data() : data.c_str()), (size_t) size)); + } + + void Serializer::ValidateName (const string &name) + { + string dName = DeserializeString(); + if (dName != name) + { + throw ParameterIncorrect (SRC_POS); + } + } +} diff --git a/Platform/Serializer.h b/Platform/Serializer.h index 0f8c36d..6687bb7 100644 --- a/Platform/Serializer.h +++ b/Platform/Serializer.h @@ -1,74 +1,74 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Serializer -#define TC_HEADER_Platform_Serializer - -#include "PlatformBase.h" -#include "Buffer.h" -#include "SharedPtr.h" -#include "Stream.h" - -namespace TrueCrypt -{ - class Serializer - { - public: - Serializer (shared_ptr stream) : DataStream (stream) { } - virtual ~Serializer () { } - - void Deserialize (const string &name, bool &data); - void Deserialize (const string &name, byte &data); - void Deserialize (const string &name, int32 &data); - void Deserialize (const string &name, int64 &data); - void Deserialize (const string &name, uint32 &data); - void Deserialize (const string &name, uint64 &data); - void Deserialize (const string &name, string &data); - void Deserialize (const string &name, wstring &data); - void Deserialize (const string &name, const BufferPtr &data); - bool DeserializeBool (const string &name); - int32 DeserializeInt32 (const string &name); - int64 DeserializeInt64 (const string &name); - uint32 DeserializeUInt32 (const string &name); - uint64 DeserializeUInt64 (const string &name); - string DeserializeString (const string &name); - list DeserializeStringList (const string &name); - wstring DeserializeWString (const string &name); - list DeserializeWStringList (const string &name); - void Serialize (const string &name, bool data); - void Serialize (const string &name, byte data); - void Serialize (const string &name, const char *data); - void Serialize (const string &name, int32 data); - void Serialize (const string &name, int64 data); - void Serialize (const string &name, uint32 data); - void Serialize (const string &name, uint64 data); - void Serialize (const string &name, const string &data); - void Serialize (const string &name, const wstring &data); - void Serialize (const string &name, const wchar_t *data); - void Serialize (const string &name, const list &stringList); - void Serialize (const string &name, const list &stringList); - void Serialize (const string &name, const ConstBufferPtr &data); - - protected: - template T Deserialize (); - string DeserializeString (); - wstring DeserializeWString (); - template void Serialize (T data); - void SerializeString (const string &data); - void SerializeWString (const wstring &data); - void ValidateName (const string &name); - - shared_ptr DataStream; - - private: - Serializer (const Serializer &); - Serializer &operator= (const Serializer &); - }; -} - -#endif // TC_HEADER_Platform_Serializer +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Serializer +#define TC_HEADER_Platform_Serializer + +#include "PlatformBase.h" +#include "Buffer.h" +#include "SharedPtr.h" +#include "Stream.h" + +namespace TrueCrypt +{ + class Serializer + { + public: + Serializer (shared_ptr stream) : DataStream (stream) { } + virtual ~Serializer () { } + + void Deserialize (const string &name, bool &data); + void Deserialize (const string &name, byte &data); + void Deserialize (const string &name, int32 &data); + void Deserialize (const string &name, int64 &data); + void Deserialize (const string &name, uint32 &data); + void Deserialize (const string &name, uint64 &data); + void Deserialize (const string &name, string &data); + void Deserialize (const string &name, wstring &data); + void Deserialize (const string &name, const BufferPtr &data); + bool DeserializeBool (const string &name); + int32 DeserializeInt32 (const string &name); + int64 DeserializeInt64 (const string &name); + uint32 DeserializeUInt32 (const string &name); + uint64 DeserializeUInt64 (const string &name); + string DeserializeString (const string &name); + list DeserializeStringList (const string &name); + wstring DeserializeWString (const string &name); + list DeserializeWStringList (const string &name); + void Serialize (const string &name, bool data); + void Serialize (const string &name, byte data); + void Serialize (const string &name, const char *data); + void Serialize (const string &name, int32 data); + void Serialize (const string &name, int64 data); + void Serialize (const string &name, uint32 data); + void Serialize (const string &name, uint64 data); + void Serialize (const string &name, const string &data); + void Serialize (const string &name, const wstring &data); + void Serialize (const string &name, const wchar_t *data); + void Serialize (const string &name, const list &stringList); + void Serialize (const string &name, const list &stringList); + void Serialize (const string &name, const ConstBufferPtr &data); + + protected: + template T Deserialize (); + string DeserializeString (); + wstring DeserializeWString (); + template void Serialize (T data); + void SerializeString (const string &data); + void SerializeWString (const wstring &data); + void ValidateName (const string &name); + + shared_ptr DataStream; + + private: + Serializer (const Serializer &); + Serializer &operator= (const Serializer &); + }; +} + +#endif // TC_HEADER_Platform_Serializer diff --git a/Platform/SerializerFactory.cpp b/Platform/SerializerFactory.cpp index 7733d5b..3585ddc 100644 --- a/Platform/SerializerFactory.cpp +++ b/Platform/SerializerFactory.cpp @@ -1,54 +1,54 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include "SerializerFactory.h" - -namespace TrueCrypt -{ - void SerializerFactory::Deinitialize () - { - if (--UseCount == 0) - { - delete NameToTypeMap; - delete TypeToNameMap; - } - } - - string SerializerFactory::GetName (const type_info &typeInfo) - { - string typeName = StringConverter::GetTypeName (typeInfo); - if (TypeToNameMap->find (typeName) == TypeToNameMap->end()) - throw std::runtime_error (SRC_POS); - - return (*TypeToNameMap)[typeName]; - } - - Serializable *SerializerFactory::GetNewSerializable (const string &typeName) - { - if (NameToTypeMap->find (typeName) == NameToTypeMap->end()) - throw std::runtime_error (SRC_POS); - - return (*NameToTypeMap)[typeName].GetNewPtr(); - } - - void SerializerFactory::Initialize () - { - if (UseCount == 0) - { - NameToTypeMap = new map ; - TypeToNameMap = new map ; - } - - ++UseCount; - } - - map *SerializerFactory::NameToTypeMap; - map *SerializerFactory::TypeToNameMap; - int SerializerFactory::UseCount; -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include "SerializerFactory.h" + +namespace TrueCrypt +{ + void SerializerFactory::Deinitialize () + { + if (--UseCount == 0) + { + delete NameToTypeMap; + delete TypeToNameMap; + } + } + + string SerializerFactory::GetName (const type_info &typeInfo) + { + string typeName = StringConverter::GetTypeName (typeInfo); + if (TypeToNameMap->find (typeName) == TypeToNameMap->end()) + throw std::runtime_error (SRC_POS); + + return (*TypeToNameMap)[typeName]; + } + + Serializable *SerializerFactory::GetNewSerializable (const string &typeName) + { + if (NameToTypeMap->find (typeName) == NameToTypeMap->end()) + throw std::runtime_error (SRC_POS); + + return (*NameToTypeMap)[typeName].GetNewPtr(); + } + + void SerializerFactory::Initialize () + { + if (UseCount == 0) + { + NameToTypeMap = new map ; + TypeToNameMap = new map ; + } + + ++UseCount; + } + + map *SerializerFactory::NameToTypeMap; + map *SerializerFactory::TypeToNameMap; + int SerializerFactory::UseCount; +} diff --git a/Platform/SerializerFactory.h b/Platform/SerializerFactory.h index f37cd07..bbfb258 100644 --- a/Platform/SerializerFactory.h +++ b/Platform/SerializerFactory.h @@ -1,93 +1,93 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_SerializerFactory -#define TC_HEADER_Platform_SerializerFactory - -#include -#include "PlatformBase.h" -#include "StringConverter.h" - -namespace TrueCrypt -{ - class Serializable; - - class SerializerFactory - { - public: - ~SerializerFactory (); - - static void Deinitialize (); - static string GetName (const type_info &typeInfo); - static Serializable *GetNewSerializable (const string &typeName); - static void Initialize (); - - struct MapEntry - { - MapEntry () { } - MapEntry (const string &typeName, Serializable* (*getNewPtr) ()) - : TypeName (typeName), GetNewPtr (getNewPtr) { } - - MapEntry &operator= (const MapEntry &right) - { - TypeName = right.TypeName; - GetNewPtr = right.GetNewPtr; - return *this; - } - - string TypeName; - Serializable* (*GetNewPtr) (); - }; - - static map *NameToTypeMap; - static map *TypeToNameMap; - - protected: - SerializerFactory (); - - static int UseCount; - }; - -} - -#define TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(TYPE) \ - struct TYPE##SerializerFactoryInitializer \ - { \ - TYPE##SerializerFactoryInitializer () \ - { \ - SerializerFactory::Initialize(); \ - TC_EXCEPTION_SET; \ - } \ - ~TYPE##SerializerFactoryInitializer () \ - { \ - SerializerFactory::Deinitialize(); \ - } \ - }; \ - static TYPE##SerializerFactoryInitializer TYPE##SerializerFactoryInitializer - -#define TC_SERIALIZER_FACTORY_ADD_CLASS(TYPE) \ - struct TYPE##SerializerFactoryInitializer \ - { \ - TYPE##SerializerFactoryInitializer () \ - { \ - SerializerFactory::Initialize(); \ - TC_SERIALIZER_FACTORY_ADD (TYPE); \ - } \ - ~TYPE##SerializerFactoryInitializer () \ - { \ - SerializerFactory::Deinitialize(); \ - } \ - }; \ - static TYPE##SerializerFactoryInitializer TYPE##SerializerFactoryInitializerInst - -#define TC_SERIALIZER_FACTORY_ADD(TYPE) \ - (*SerializerFactory::NameToTypeMap)[#TYPE] = SerializerFactory::MapEntry (StringConverter::GetTypeName (typeid (TYPE)), &TYPE::GetNewSerializable); \ - (*SerializerFactory::TypeToNameMap)[StringConverter::GetTypeName (typeid (TYPE))] = #TYPE - - -#endif // TC_HEADER_Platform_SerializerFactory +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_SerializerFactory +#define TC_HEADER_Platform_SerializerFactory + +#include +#include "PlatformBase.h" +#include "StringConverter.h" + +namespace TrueCrypt +{ + class Serializable; + + class SerializerFactory + { + public: + ~SerializerFactory (); + + static void Deinitialize (); + static string GetName (const type_info &typeInfo); + static Serializable *GetNewSerializable (const string &typeName); + static void Initialize (); + + struct MapEntry + { + MapEntry () { } + MapEntry (const string &typeName, Serializable* (*getNewPtr) ()) + : TypeName (typeName), GetNewPtr (getNewPtr) { } + + MapEntry &operator= (const MapEntry &right) + { + TypeName = right.TypeName; + GetNewPtr = right.GetNewPtr; + return *this; + } + + string TypeName; + Serializable* (*GetNewPtr) (); + }; + + static map *NameToTypeMap; + static map *TypeToNameMap; + + protected: + SerializerFactory (); + + static int UseCount; + }; + +} + +#define TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(TYPE) \ + struct TYPE##SerializerFactoryInitializer \ + { \ + TYPE##SerializerFactoryInitializer () \ + { \ + SerializerFactory::Initialize(); \ + TC_EXCEPTION_SET; \ + } \ + ~TYPE##SerializerFactoryInitializer () \ + { \ + SerializerFactory::Deinitialize(); \ + } \ + }; \ + static TYPE##SerializerFactoryInitializer TYPE##SerializerFactoryInitializer + +#define TC_SERIALIZER_FACTORY_ADD_CLASS(TYPE) \ + struct TYPE##SerializerFactoryInitializer \ + { \ + TYPE##SerializerFactoryInitializer () \ + { \ + SerializerFactory::Initialize(); \ + TC_SERIALIZER_FACTORY_ADD (TYPE); \ + } \ + ~TYPE##SerializerFactoryInitializer () \ + { \ + SerializerFactory::Deinitialize(); \ + } \ + }; \ + static TYPE##SerializerFactoryInitializer TYPE##SerializerFactoryInitializerInst + +#define TC_SERIALIZER_FACTORY_ADD(TYPE) \ + (*SerializerFactory::NameToTypeMap)[#TYPE] = SerializerFactory::MapEntry (StringConverter::GetTypeName (typeid (TYPE)), &TYPE::GetNewSerializable); \ + (*SerializerFactory::TypeToNameMap)[StringConverter::GetTypeName (typeid (TYPE))] = #TYPE + + +#endif // TC_HEADER_Platform_SerializerFactory diff --git a/Platform/SharedPtr.h b/Platform/SharedPtr.h index 60ec64b..9c0a05b 100644 --- a/Platform/SharedPtr.h +++ b/Platform/SharedPtr.h @@ -1,151 +1,151 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_SharedPtr -#define TC_HEADER_Platform_SharedPtr - -#include -#include "SharedVal.h" - -namespace TrueCrypt -{ - template - class SharedPtr - { - public: - explicit SharedPtr () - : Pointer (nullptr), UseCount (nullptr) { } - - explicit SharedPtr (T *pointer) - : Pointer (pointer), UseCount (new SharedVal (1)) { } - - SharedPtr (const SharedPtr &source) - { - CopyFrom (source); - } - - ~SharedPtr () - { - Release(); - } - - SharedPtr &operator= (const SharedPtr &source) - { - if (&source == this) - return *this; - - Release(); - CopyFrom (source); - return *this; - } - - bool operator == (const SharedPtr &other) - { - return get() == other.get(); - } - - bool operator != (const SharedPtr &other) - { - return get() != other.get(); - } - - T &operator* () const - { -#ifdef DEBUG - if (Pointer == nullptr) - throw std::runtime_error (SRC_POS); -#endif - return *Pointer; - } - - T *operator-> () const - { -#ifdef DEBUG - if (Pointer == nullptr) - throw std::runtime_error (SRC_POS); -#endif - return Pointer; - } - - operator bool () const - { - return Pointer != nullptr; - } - - T *get () const - { - return Pointer; - } - - void reset () - { - Release(); - } - - void reset (T *pointer) - { - *this = SharedPtr (pointer); - } - - uint64 use_count () const - { - if (!UseCount) - return 0; - - return *UseCount; - } - - protected: - void CopyFrom (const SharedPtr &source) - { - Pointer = source.Pointer; - UseCount = source.UseCount; - - if (UseCount) - UseCount->Increment(); - } - - void Release () - { - if (UseCount != nullptr) - { - if (UseCount->Decrement() == 0) - { - if (Pointer != nullptr) - delete Pointer; - delete UseCount; - } - - Pointer = nullptr; - UseCount = nullptr; - } - } - - T *Pointer; - SharedVal *UseCount; - }; - -#ifdef shared_ptr -#undef shared_ptr -#endif -#define shared_ptr TrueCrypt::SharedPtr - -#define make_shared_auto(typeName,instanceName) shared_ptr instanceName (new typeName ()) - - template shared_ptr make_shared () - { - return shared_ptr (new T ()); - } - - template shared_ptr make_shared (const A &arg) - { - return shared_ptr (new T (arg)); - } -} - -#endif +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_SharedPtr +#define TC_HEADER_Platform_SharedPtr + +#include +#include "SharedVal.h" + +namespace TrueCrypt +{ + template + class SharedPtr + { + public: + explicit SharedPtr () + : Pointer (nullptr), UseCount (nullptr) { } + + explicit SharedPtr (T *pointer) + : Pointer (pointer), UseCount (new SharedVal (1)) { } + + SharedPtr (const SharedPtr &source) + { + CopyFrom (source); + } + + ~SharedPtr () + { + Release(); + } + + SharedPtr &operator= (const SharedPtr &source) + { + if (&source == this) + return *this; + + Release(); + CopyFrom (source); + return *this; + } + + bool operator == (const SharedPtr &other) + { + return get() == other.get(); + } + + bool operator != (const SharedPtr &other) + { + return get() != other.get(); + } + + T &operator* () const + { +#ifdef DEBUG + if (Pointer == nullptr) + throw std::runtime_error (SRC_POS); +#endif + return *Pointer; + } + + T *operator-> () const + { +#ifdef DEBUG + if (Pointer == nullptr) + throw std::runtime_error (SRC_POS); +#endif + return Pointer; + } + + operator bool () const + { + return Pointer != nullptr; + } + + T *get () const + { + return Pointer; + } + + void reset () + { + Release(); + } + + void reset (T *pointer) + { + *this = SharedPtr (pointer); + } + + uint64 use_count () const + { + if (!UseCount) + return 0; + + return *UseCount; + } + + protected: + void CopyFrom (const SharedPtr &source) + { + Pointer = source.Pointer; + UseCount = source.UseCount; + + if (UseCount) + UseCount->Increment(); + } + + void Release () + { + if (UseCount != nullptr) + { + if (UseCount->Decrement() == 0) + { + if (Pointer != nullptr) + delete Pointer; + delete UseCount; + } + + Pointer = nullptr; + UseCount = nullptr; + } + } + + T *Pointer; + SharedVal *UseCount; + }; + +#ifdef shared_ptr +#undef shared_ptr +#endif +#define shared_ptr TrueCrypt::SharedPtr + +#define make_shared_auto(typeName,instanceName) shared_ptr instanceName (new typeName ()) + + template shared_ptr make_shared () + { + return shared_ptr (new T ()); + } + + template shared_ptr make_shared (const A &arg) + { + return shared_ptr (new T (arg)); + } +} + +#endif diff --git a/Platform/SharedVal.h b/Platform/SharedVal.h index ecfd13b..0204eef 100644 --- a/Platform/SharedVal.h +++ b/Platform/SharedVal.h @@ -1,71 +1,71 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_SharedVal -#define TC_HEADER_Platform_SharedVal - -#include "PlatformBase.h" -#include "Mutex.h" - -namespace TrueCrypt -{ - template - class SharedVal - { - public: - SharedVal () { } - explicit SharedVal (T value) : Value (value) { } - virtual ~SharedVal () { } - - operator T () - { - return Get (); - } - - T Decrement () - { - ValMutex.Lock(); - T r = --Value; - ValMutex.Unlock(); - return r; - } - - T Get () - { - ValMutex.Lock(); - T r = Value; - ValMutex.Unlock(); - return r; - } - - T Increment () - { - ValMutex.Lock(); - T r = ++Value; - ValMutex.Unlock(); - return r; - } - - void Set (T value) - { - ValMutex.Lock(); - Value = value; - ValMutex.Unlock(); - } - - protected: - volatile T Value; - Mutex ValMutex; - - private: - SharedVal (const SharedVal &); - SharedVal &operator= (const SharedVal &); - }; -} - -#endif // TC_HEADER_Platform_SharedVal +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_SharedVal +#define TC_HEADER_Platform_SharedVal + +#include "PlatformBase.h" +#include "Mutex.h" + +namespace TrueCrypt +{ + template + class SharedVal + { + public: + SharedVal () { } + explicit SharedVal (T value) : Value (value) { } + virtual ~SharedVal () { } + + operator T () + { + return Get (); + } + + T Decrement () + { + ValMutex.Lock(); + T r = --Value; + ValMutex.Unlock(); + return r; + } + + T Get () + { + ValMutex.Lock(); + T r = Value; + ValMutex.Unlock(); + return r; + } + + T Increment () + { + ValMutex.Lock(); + T r = ++Value; + ValMutex.Unlock(); + return r; + } + + void Set (T value) + { + ValMutex.Lock(); + Value = value; + ValMutex.Unlock(); + } + + protected: + volatile T Value; + Mutex ValMutex; + + private: + SharedVal (const SharedVal &); + SharedVal &operator= (const SharedVal &); + }; +} + +#endif // TC_HEADER_Platform_SharedVal diff --git a/Platform/Stream.h b/Platform/Stream.h index 97c6994..b2f1a58 100644 --- a/Platform/Stream.h +++ b/Platform/Stream.h @@ -1,34 +1,34 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Stream -#define TC_HEADER_Platform_Stream - -#include "PlatformBase.h" -#include "Buffer.h" - -namespace TrueCrypt -{ - class Stream - { - public: - virtual ~Stream () { } - virtual uint64 Read (const BufferPtr &buffer) = 0; - virtual void ReadCompleteBuffer (const BufferPtr &buffer) = 0; - virtual void Write (const ConstBufferPtr &data) = 0; - - protected: - Stream () { }; - - private: - Stream (const Stream &); - Stream &operator= (const Stream &); - }; -} - -#endif // TC_HEADER_Platform_Stream +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Stream +#define TC_HEADER_Platform_Stream + +#include "PlatformBase.h" +#include "Buffer.h" + +namespace TrueCrypt +{ + class Stream + { + public: + virtual ~Stream () { } + virtual uint64 Read (const BufferPtr &buffer) = 0; + virtual void ReadCompleteBuffer (const BufferPtr &buffer) = 0; + virtual void Write (const ConstBufferPtr &data) = 0; + + protected: + Stream () { }; + + private: + Stream (const Stream &); + Stream &operator= (const Stream &); + }; +} + +#endif // TC_HEADER_Platform_Stream diff --git a/Platform/StringConverter.cpp b/Platform/StringConverter.cpp index 29dd8f8..6b46846 100644 --- a/Platform/StringConverter.cpp +++ b/Platform/StringConverter.cpp @@ -1,367 +1,367 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifdef __GNUC__ -# include -#endif -#include -#include -#include "Buffer.h" -#include "Exception.h" -#include "ForEach.h" -#include "StringConverter.h" -#include "SystemException.h" - -namespace TrueCrypt -{ - void StringConverter::Erase (string &str) - { - for (size_t i = 0; i < str.size(); ++i) - { - str[i] = ' '; - } - } - - void StringConverter::Erase (wstring &str) - { - for (size_t i = 0; i < str.size(); ++i) - { - str[i] = ' '; - } - } - - wstring StringConverter::FromNumber (double number) - { - wstringstream s; - s << number; - return s.str(); - } - - wstring StringConverter::FromNumber (int32 number) - { - wstringstream s; - s << number; - return s.str(); - } - - wstring StringConverter::FromNumber (uint32 number) - { - wstringstream s; - s << number; - return s.str(); - } - - wstring StringConverter::FromNumber (int64 number) - { - wstringstream s; - s << number; - return s.str(); - } - - wstring StringConverter::FromNumber (uint64 number) - { - wstringstream s; - s << number; - return s.str(); - } - - string StringConverter::GetTrailingNumber (const string &str) - { - size_t start = str.find_last_not_of ("0123456789"); - if (start == string::npos) - return str; - - string s = str.substr (start + 1); - if (s.empty ()) - throw ParameterIncorrect (SRC_POS); - - return s; - } - - string StringConverter::GetTypeName (const type_info &typeInfo) - { - try - { -#ifdef _MSC_VER - // type_info::name() leaks memory as of MS VC++ 8.0 - string rawName (typeInfo.raw_name()); - - int cut1 = (rawName.find (".?A") != string::npos) ? 4 : string::npos; - int cut2 = rawName.find ("@"); - int cut3 = rawName.find ("@@"); - - if (cut1 == string::npos || cut2 == string::npos || cut3 == string::npos) - return typeInfo.name(); - - return rawName.substr (cut2 + 1, cut3 - cut2 - 1) + "::" + rawName.substr (cut1, cut2 - cut1); - -#elif defined (__GNUC__) - int status; - char *name = abi::__cxa_demangle (typeInfo.name(), nullptr, nullptr, &status); - - if (name) - { - string s (name); - free (name); - return s; - } -#endif - } - catch (...) { } - - return typeInfo.name(); - } - - wstring StringConverter::QuoteSpaces (const wstring &str) - { - if (str.find (L' ') == string::npos) - return str; - - wstring escaped (L"'"); - foreach (wchar_t c, str) - { - if (c == L'\'') - escaped += L'\''; - escaped += c; - } - return escaped + L'\''; - } - - vector StringConverter::Split (const string &str, const string &separators, bool returnEmptyFields) - { - vector elements; - - if (!returnEmptyFields) - { - size_t p = 0; - while ((p = str.find_first_not_of (separators, p)) != string::npos) - { - size_t end = str.find_first_of (separators, p); - if (end == string::npos) - { - elements.push_back (str.substr (p)); - break; - } - - elements.push_back (str.substr (p, end - p)); - p = end; - } - } - else - { - string element; - elements.push_back (element); - foreach (char c, str) - { - if (separators.find (c) != string::npos) - { - element.erase(); - elements.push_back (element); - } - else - { - elements.back() += c; - } - } - } - - return elements; - } - - string StringConverter::StripTrailingNumber (const string &str) - { - size_t start = str.find_last_not_of ("0123456789"); - if (start == string::npos) - return ""; - - return str.substr (0, start + 1); - } - - wstring StringConverter::ToExceptionString (const exception &ex) - { - const SystemException *sysEx = dynamic_cast (&ex); - if (sysEx) - return ToWide (sysEx->what()) + L": " + sysEx->SystemText() + L": " + sysEx->GetSubject(); - - if (ex.what() && !string (ex.what()).empty()) - return ToWide (GetTypeName (typeid (ex)) + ": " + ex.what()); - - return ToWide (GetTypeName (typeid (ex))); - } - - string StringConverter::ToLower (const string &str) - { - string s; - foreach (char c, str) - s += tolower (c, locale()); - return s; - } - - string StringConverter::ToSingle (const wstring &wstr, bool noThrow) - { - string str; - ToSingle (wstr, str, noThrow); - return str; - } - - void StringConverter::ToSingle (const wstring &wstr, string &str, bool noThrow) - { - try - { - mbstate_t mbState; - Memory::Zero (&mbState, sizeof (mbState)); - const wchar_t *src = wstr.c_str(); - - size_t size = wcsrtombs (nullptr, &src, 0, &mbState); - if (size == -1) - throw StringConversionFailed (SRC_POS, wstr); - - vector buf (size + 1); - Memory::Zero (&mbState, sizeof (mbState)); - - if ((size = wcsrtombs (&buf[0], &src, buf.size(), &mbState)) == -1) - throw StringConversionFailed (SRC_POS, wstr); - - str.clear(); - str.insert (0, &buf.front(), size); - Memory::Erase (&buf.front(), buf.size()); - } - catch (...) - { - if (!noThrow) - throw; - } - } - - uint32 StringConverter::ToUInt32 (const string &str) - { - uint32 n; - stringstream ss (str); - - ss >> n; - if (ss.fail() || n == 0xffffFFFFU) - throw ParameterIncorrect (SRC_POS); - - return n; - } - - uint32 StringConverter::ToUInt32 (const wstring &str) - { - uint32 n; - wstringstream ss (str); - - ss >> n; - if (ss.fail() || n == 0xffffFFFFU) - throw ParameterIncorrect (SRC_POS); - - return n; - } - - uint64 StringConverter::ToUInt64 (const string &str) - { - uint64 n; - stringstream ss (str); - - ss >> n; - if (ss.fail() || n == 0xffffFFFFffffFFFFULL) - throw ParameterIncorrect (SRC_POS); - - return n; - } - - uint64 StringConverter::ToUInt64 (const wstring &str) - { - uint64 n; - wstringstream ss (str); - - ss >> n; - if (ss.fail() || n == 0xffffFFFFffffFFFFULL) - throw ParameterIncorrect (SRC_POS); - - return n; - } - - string StringConverter::ToUpper (const string &str) - { - string s; - foreach (char c, str) - s += toupper (c, locale()); - return s; - } - - wstring StringConverter::ToWide (const string &str, bool noThrow) - { - try - { - mbstate_t mbState; - Memory::Zero (&mbState, sizeof (mbState)); - const char *src = str.c_str(); - - size_t size = mbsrtowcs (nullptr, &src, 0, &mbState); - if (size == -1) - throw StringConversionFailed (SRC_POS); - - vector buf (size + 1); - Memory::Zero (&mbState, sizeof (mbState)); - - if ((size = mbsrtowcs (&buf[0], &src, buf.size(), &mbState)) == -1) - throw StringConversionFailed (SRC_POS); - - wstring s; - s.insert (s.begin(), buf.begin(), buf.begin() + size); - return s; - } - catch (...) - { - if (noThrow) - return L""; - throw; - } - } - - void StringConverter::ToWideBuffer (const wstring &str, wchar_t *buffer, size_t bufferSize) - { - if (str.length() < 1) - { - buffer[0] = 0; - return; - } - - BufferPtr ( - (byte *) buffer, - bufferSize).CopyFrom ( - ConstBufferPtr ((byte *) (wstring (str).c_str()), - (str.length() + 1) * sizeof (wchar_t) - ) - ); - } - - string StringConverter::Trim (const string &str) - { - size_t start = 0; - size_t end = str.size(); - if (end < 1) - return str; - - foreach (char c, str) - { - if (c > ' ') - break; - ++start; - } - - foreach_reverse (char c, str) - { - if (c > ' ') - break; - --end; - } - - return str.substr (start, end - start); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifdef __GNUC__ +# include +#endif +#include +#include +#include "Buffer.h" +#include "Exception.h" +#include "ForEach.h" +#include "StringConverter.h" +#include "SystemException.h" + +namespace TrueCrypt +{ + void StringConverter::Erase (string &str) + { + for (size_t i = 0; i < str.size(); ++i) + { + str[i] = ' '; + } + } + + void StringConverter::Erase (wstring &str) + { + for (size_t i = 0; i < str.size(); ++i) + { + str[i] = ' '; + } + } + + wstring StringConverter::FromNumber (double number) + { + wstringstream s; + s << number; + return s.str(); + } + + wstring StringConverter::FromNumber (int32 number) + { + wstringstream s; + s << number; + return s.str(); + } + + wstring StringConverter::FromNumber (uint32 number) + { + wstringstream s; + s << number; + return s.str(); + } + + wstring StringConverter::FromNumber (int64 number) + { + wstringstream s; + s << number; + return s.str(); + } + + wstring StringConverter::FromNumber (uint64 number) + { + wstringstream s; + s << number; + return s.str(); + } + + string StringConverter::GetTrailingNumber (const string &str) + { + size_t start = str.find_last_not_of ("0123456789"); + if (start == string::npos) + return str; + + string s = str.substr (start + 1); + if (s.empty ()) + throw ParameterIncorrect (SRC_POS); + + return s; + } + + string StringConverter::GetTypeName (const type_info &typeInfo) + { + try + { +#ifdef _MSC_VER + // type_info::name() leaks memory as of MS VC++ 8.0 + string rawName (typeInfo.raw_name()); + + size_t cut1 = (rawName.find (".?A") != string::npos) ? 4 : string::npos; + size_t cut2 = rawName.find ("@"); + size_t cut3 = rawName.find ("@@"); + + if (cut1 == string::npos || cut2 == string::npos || cut3 == string::npos) + return typeInfo.name(); + + return rawName.substr (cut2 + 1, cut3 - cut2 - 1) + "::" + rawName.substr (cut1, cut2 - cut1); + +#elif defined (__GNUC__) + int status; + char *name = abi::__cxa_demangle (typeInfo.name(), nullptr, nullptr, &status); + + if (name) + { + string s (name); + free (name); + return s; + } +#endif + } + catch (...) { } + + return typeInfo.name(); + } + + wstring StringConverter::QuoteSpaces (const wstring &str) + { + if (str.find (L' ') == string::npos) + return str; + + wstring escaped (L"'"); + foreach (wchar_t c, str) + { + if (c == L'\'') + escaped += L'\''; + escaped += c; + } + return escaped + L'\''; + } + + vector StringConverter::Split (const string &str, const string &separators, bool returnEmptyFields) + { + vector elements; + + if (!returnEmptyFields) + { + size_t p = 0; + while ((p = str.find_first_not_of (separators, p)) != string::npos) + { + size_t end = str.find_first_of (separators, p); + if (end == string::npos) + { + elements.push_back (str.substr (p)); + break; + } + + elements.push_back (str.substr (p, end - p)); + p = end; + } + } + else + { + string element; + elements.push_back (element); + foreach (char c, str) + { + if (separators.find (c) != string::npos) + { + element.erase(); + elements.push_back (element); + } + else + { + elements.back() += c; + } + } + } + + return elements; + } + + string StringConverter::StripTrailingNumber (const string &str) + { + size_t start = str.find_last_not_of ("0123456789"); + if (start == string::npos) + return ""; + + return str.substr (0, start + 1); + } + + wstring StringConverter::ToExceptionString (const exception &ex) + { + const SystemException *sysEx = dynamic_cast (&ex); + if (sysEx) + return ToWide (sysEx->what()) + L": " + sysEx->SystemText() + L": " + sysEx->GetSubject(); + + if (ex.what() && !string (ex.what()).empty()) + return ToWide (GetTypeName (typeid (ex)) + ": " + ex.what()); + + return ToWide (GetTypeName (typeid (ex))); + } + + string StringConverter::ToLower (const string &str) + { + string s; + foreach (char c, str) + s += tolower (c, locale()); + return s; + } + + string StringConverter::ToSingle (const wstring &wstr, bool noThrow) + { + string str; + ToSingle (wstr, str, noThrow); + return str; + } + + void StringConverter::ToSingle (const wstring &wstr, string &str, bool noThrow) + { + try + { + mbstate_t mbState; + Memory::Zero (&mbState, sizeof (mbState)); + const wchar_t *src = wstr.c_str(); + + size_t size = wcsrtombs (nullptr, &src, 0, &mbState); + if (size == (size_t) -1) + throw StringConversionFailed (SRC_POS, wstr); + + vector buf (size + 1); + Memory::Zero (&mbState, sizeof (mbState)); + + if ((size = wcsrtombs (&buf[0], &src, buf.size(), &mbState)) == (size_t) -1) + throw StringConversionFailed (SRC_POS, wstr); + + str.clear(); + str.insert (0, &buf.front(), size); + Memory::Erase (&buf.front(), buf.size()); + } + catch (...) + { + if (!noThrow) + throw; + } + } + + uint32 StringConverter::ToUInt32 (const string &str) + { + uint32 n; + stringstream ss (str); + + ss >> n; + if (ss.fail() || n == 0xffffFFFFU) + throw ParameterIncorrect (SRC_POS); + + return n; + } + + uint32 StringConverter::ToUInt32 (const wstring &str) + { + uint32 n; + wstringstream ss (str); + + ss >> n; + if (ss.fail() || n == 0xffffFFFFU) + throw ParameterIncorrect (SRC_POS); + + return n; + } + + uint64 StringConverter::ToUInt64 (const string &str) + { + uint64 n; + stringstream ss (str); + + ss >> n; + if (ss.fail() || n == 0xffffFFFFffffFFFFULL) + throw ParameterIncorrect (SRC_POS); + + return n; + } + + uint64 StringConverter::ToUInt64 (const wstring &str) + { + uint64 n; + wstringstream ss (str); + + ss >> n; + if (ss.fail() || n == 0xffffFFFFffffFFFFULL) + throw ParameterIncorrect (SRC_POS); + + return n; + } + + string StringConverter::ToUpper (const string &str) + { + string s; + foreach (char c, str) + s += toupper (c, locale()); + return s; + } + + wstring StringConverter::ToWide (const string &str, bool noThrow) + { + try + { + mbstate_t mbState; + Memory::Zero (&mbState, sizeof (mbState)); + const char *src = str.c_str(); + + size_t size = mbsrtowcs (nullptr, &src, 0, &mbState); + if (size == (size_t) -1) + throw StringConversionFailed (SRC_POS); + + vector buf (size + 1); + Memory::Zero (&mbState, sizeof (mbState)); + + if ((size = mbsrtowcs (&buf[0], &src, buf.size(), &mbState)) == (size_t) -1) + throw StringConversionFailed (SRC_POS); + + wstring s; + s.insert (s.begin(), buf.begin(), buf.begin() + size); + return s; + } + catch (...) + { + if (noThrow) + return L""; + throw; + } + } + + void StringConverter::ToWideBuffer (const wstring &str, wchar_t *buffer, size_t bufferSize) + { + if (str.length() < 1) + { + buffer[0] = 0; + return; + } + + BufferPtr ( + (byte *) buffer, + bufferSize).CopyFrom ( + ConstBufferPtr ((byte *) (wstring (str).c_str()), + (str.length() + 1) * sizeof (wchar_t) + ) + ); + } + + string StringConverter::Trim (const string &str) + { + size_t start = 0; + size_t end = str.size(); + if (end < 1) + return str; + + foreach (char c, str) + { + if (c > ' ') + break; + ++start; + } + + foreach_reverse (char c, str) + { + if (c > ' ') + break; + --end; + } + + return str.substr (start, end - start); + } +} diff --git a/Platform/StringConverter.h b/Platform/StringConverter.h index 792d455..a0d481f 100644 --- a/Platform/StringConverter.h +++ b/Platform/StringConverter.h @@ -1,60 +1,60 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_StringConverter -#define TC_HEADER_Platform_StringConverter - -#include -#include "PlatformBase.h" - -namespace TrueCrypt -{ - class StringConverter - { - public: - static void Erase (string &str); - static void Erase (wstring &str); - static wstring FromNumber (double number); - static wstring FromNumber (int32 number); - static wstring FromNumber (uint32 number); - static wstring FromNumber (int64 number); - static wstring FromNumber (uint64 number); - static string GetTrailingNumber (const string &str); - static string GetTypeName (const type_info &typeInfo); - static wstring QuoteSpaces (const wstring &str); - static vector Split (const string &str, const string &separators = " \t\r\n", bool returnEmptyFields = false); - static string StripTrailingNumber (const string &str); - static wstring ToExceptionString (const exception &ex); - static string ToLower (const string &str); - static uint32 ToUInt32 (const string &str); - static uint32 ToUInt32 (const wstring &str); - static uint64 ToUInt64 (const string &str); - static uint64 ToUInt64 (const wstring &str); - static string ToSingle (double number) { return ToSingle (FromNumber (number)); } - static string ToSingle (int32 number) { return ToSingle (FromNumber (number)); } - static string ToSingle (uint32 number) { return ToSingle (FromNumber (number)); } - static string ToSingle (int64 number) { return ToSingle (FromNumber (number)); } - static string ToSingle (uint64 number) { return ToSingle (FromNumber (number)); } - static string ToSingle (const wstring &wstr, bool noThrow = false); - static void ToSingle (const wstring &wstr, string &str, bool noThrow = false); - static string ToUpper (const string &str); - static wstring ToWide (double number) { return FromNumber (number); } - static wstring ToWide (int32 number) { return FromNumber (number); } - static wstring ToWide (uint32 number) { return FromNumber (number); } - static wstring ToWide (int64 number) { return FromNumber (number); } - static wstring ToWide (uint64 number) { return FromNumber (number); } - static wstring ToWide (const string &str, bool noThrow = false); - static void ToWideBuffer (const wstring &str, wchar_t *buffer, size_t bufferSize); - static string Trim (const string &str); - - private: - StringConverter (); - }; -} - -#endif // TC_HEADER_Platform_StringConverter +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_StringConverter +#define TC_HEADER_Platform_StringConverter + +#include +#include "PlatformBase.h" + +namespace TrueCrypt +{ + class StringConverter + { + public: + static void Erase (string &str); + static void Erase (wstring &str); + static wstring FromNumber (double number); + static wstring FromNumber (int32 number); + static wstring FromNumber (uint32 number); + static wstring FromNumber (int64 number); + static wstring FromNumber (uint64 number); + static string GetTrailingNumber (const string &str); + static string GetTypeName (const type_info &typeInfo); + static wstring QuoteSpaces (const wstring &str); + static vector Split (const string &str, const string &separators = " \t\r\n", bool returnEmptyFields = false); + static string StripTrailingNumber (const string &str); + static wstring ToExceptionString (const exception &ex); + static string ToLower (const string &str); + static uint32 ToUInt32 (const string &str); + static uint32 ToUInt32 (const wstring &str); + static uint64 ToUInt64 (const string &str); + static uint64 ToUInt64 (const wstring &str); + static string ToSingle (double number) { return ToSingle (FromNumber (number)); } + static string ToSingle (int32 number) { return ToSingle (FromNumber (number)); } + static string ToSingle (uint32 number) { return ToSingle (FromNumber (number)); } + static string ToSingle (int64 number) { return ToSingle (FromNumber (number)); } + static string ToSingle (uint64 number) { return ToSingle (FromNumber (number)); } + static string ToSingle (const wstring &wstr, bool noThrow = false); + static void ToSingle (const wstring &wstr, string &str, bool noThrow = false); + static string ToUpper (const string &str); + static wstring ToWide (double number) { return FromNumber (number); } + static wstring ToWide (int32 number) { return FromNumber (number); } + static wstring ToWide (uint32 number) { return FromNumber (number); } + static wstring ToWide (int64 number) { return FromNumber (number); } + static wstring ToWide (uint64 number) { return FromNumber (number); } + static wstring ToWide (const string &str, bool noThrow = false); + static void ToWideBuffer (const wstring &str, wchar_t *buffer, size_t bufferSize); + static string Trim (const string &str); + + private: + StringConverter (); + }; +} + +#endif // TC_HEADER_Platform_StringConverter diff --git a/Platform/SyncEvent.h b/Platform/SyncEvent.h index 1bd7990..cb44b69 100644 --- a/Platform/SyncEvent.h +++ b/Platform/SyncEvent.h @@ -1,47 +1,47 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_SyncEvent -#define TC_HEADER_Platform_SyncEvent - -#ifdef TC_WINDOWS -# include "System.h" -#else -# include -#endif -#include "PlatformBase.h" -#include "Mutex.h" - -namespace TrueCrypt -{ - class SyncEvent - { - public: - SyncEvent (); - ~SyncEvent (); - - void Signal (); - void Wait (); - - protected: - bool Initialized; -#ifdef TC_WINDOWS - HANDLE SystemSyncEvent; -#else - volatile bool Signaled; - pthread_cond_t SystemSyncEvent; - Mutex EventMutex; -#endif - - private: - SyncEvent (const SyncEvent &); - SyncEvent &operator= (const SyncEvent &); - }; -} - -#endif // TC_HEADER_Platform_SyncEvent +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_SyncEvent +#define TC_HEADER_Platform_SyncEvent + +#ifdef TC_WINDOWS +# include "System.h" +#else +# include +#endif +#include "PlatformBase.h" +#include "Mutex.h" + +namespace TrueCrypt +{ + class SyncEvent + { + public: + SyncEvent (); + ~SyncEvent (); + + void Signal (); + void Wait (); + + protected: + bool Initialized; +#ifdef TC_WINDOWS + HANDLE SystemSyncEvent; +#else + volatile bool Signaled; + pthread_cond_t SystemSyncEvent; + Mutex EventMutex; +#endif + + private: + SyncEvent (const SyncEvent &); + SyncEvent &operator= (const SyncEvent &); + }; +} + +#endif // TC_HEADER_Platform_SyncEvent diff --git a/Platform/System.h b/Platform/System.h index ea83d4e..2e6a1e9 100644 --- a/Platform/System.h +++ b/Platform/System.h @@ -1,16 +1,16 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_System -#define TC_HEADER_Platform_System - -#ifdef TC_WINDOWS -#include "Windows/System.h" -#endif - -#endif // TC_HEADER_Platform_System +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_System +#define TC_HEADER_Platform_System + +#ifdef TC_WINDOWS +#include "Windows/System.h" +#endif + +#endif // TC_HEADER_Platform_System diff --git a/Platform/SystemException.h b/Platform/SystemException.h index 668a93d..76af35b 100644 --- a/Platform/SystemException.h +++ b/Platform/SystemException.h @@ -1,46 +1,46 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_SystemException -#define TC_HEADER_Platform_SystemException - -#include "PlatformBase.h" -#include "Exception.h" - -namespace TrueCrypt -{ - class SystemException : public Exception - { - public: - SystemException (); - SystemException (const string &message); - SystemException (const string &message, const string &subject); - SystemException (const string &message, const wstring &subject); - SystemException (const string &message, int64 errorCode) - : Exception (message), ErrorCode (errorCode) { } - virtual ~SystemException () throw () { } - - TC_SERIALIZABLE_EXCEPTION (SystemException); - - int64 GetErrorCode () const { return ErrorCode; } - bool IsError () const; - wstring SystemText () const; - - protected: - int64 ErrorCode; - }; - -#undef TC_EXCEPTION_SET -#define TC_EXCEPTION_SET \ - TC_EXCEPTION_NODECL (SystemException); -} - -#define throw_sys_if(condition) do { if (condition) throw SystemException (SRC_POS); } while (false) -#define throw_sys_sub_if(condition,subject) do { if (condition) throw SystemException (SRC_POS, (subject)); } while (false) - -#endif // TC_HEADER_Platform_SystemException +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_SystemException +#define TC_HEADER_Platform_SystemException + +#include "PlatformBase.h" +#include "Exception.h" + +namespace TrueCrypt +{ + class SystemException : public Exception + { + public: + SystemException (); + SystemException (const string &message); + SystemException (const string &message, const string &subject); + SystemException (const string &message, const wstring &subject); + SystemException (const string &message, int64 errorCode) + : Exception (message), ErrorCode (errorCode) { } + virtual ~SystemException () throw () { } + + TC_SERIALIZABLE_EXCEPTION (SystemException); + + int64 GetErrorCode () const { return ErrorCode; } + bool IsError () const; + wstring SystemText () const; + + protected: + int64 ErrorCode; + }; + +#undef TC_EXCEPTION_SET +#define TC_EXCEPTION_SET \ + TC_EXCEPTION_NODECL (SystemException); +} + +#define throw_sys_if(condition) do { if (condition) throw SystemException (SRC_POS); } while (false) +#define throw_sys_sub_if(condition,subject) do { if (condition) throw SystemException (SRC_POS, (subject)); } while (false) + +#endif // TC_HEADER_Platform_SystemException diff --git a/Platform/SystemInfo.h b/Platform/SystemInfo.h index 3df8dfd..1fc4fe1 100644 --- a/Platform/SystemInfo.h +++ b/Platform/SystemInfo.h @@ -1,27 +1,27 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_SystemInfo -#define TC_HEADER_Platform_SystemInfo - -#include "PlatformBase.h" - -namespace TrueCrypt -{ - class SystemInfo - { - public: - static wstring GetPlatformName (); - static vector GetVersion (); - - protected: - SystemInfo (); - }; -} - -#endif // TC_HEADER_Platform_SystemInfo +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_SystemInfo +#define TC_HEADER_Platform_SystemInfo + +#include "PlatformBase.h" + +namespace TrueCrypt +{ + class SystemInfo + { + public: + static wstring GetPlatformName (); + static vector GetVersion (); + + protected: + SystemInfo (); + }; +} + +#endif // TC_HEADER_Platform_SystemInfo diff --git a/Platform/SystemLog.h b/Platform/SystemLog.h index c4a8117..cd1c9ef 100644 --- a/Platform/SystemLog.h +++ b/Platform/SystemLog.h @@ -1,42 +1,42 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_SystemLog -#define TC_HEADER_Platform_SystemLog - -#include "Platform/PlatformBase.h" -#include "Platform/StringConverter.h" - -namespace TrueCrypt -{ - class SystemLog - { - public: - static void WriteDebug (const string &debugMessage); - static void WriteError (const string &errorMessage); - - static void WriteException (const exception &ex) - { - WriteError (string ("exception: ") + StringConverter::ToSingle (StringConverter::ToExceptionString (ex))); - } - - protected: - SystemLog (); - }; - -#ifdef DEBUG -# define tracelog_point do { stringstream s; s << (SRC_POS); SystemLog::WriteError (s.str()); } while (false) -# define tracelog_msg(stream_args) do { stringstream s; s << (SRC_POS) << ": " << stream_args; SystemLog::WriteError (s.str()); } while (false) -#else -# define tracelog_point -# define tracelog_msg(stream_args) while (false) { stringstream s; s << stream_args; } -#endif - -} - -#endif // TC_HEADER_Platform_SystemLog +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_SystemLog +#define TC_HEADER_Platform_SystemLog + +#include "Platform/PlatformBase.h" +#include "Platform/StringConverter.h" + +namespace TrueCrypt +{ + class SystemLog + { + public: + static void WriteDebug (const string &debugMessage); + static void WriteError (const string &errorMessage); + + static void WriteException (const exception &ex) + { + WriteError (string ("exception: ") + StringConverter::ToSingle (StringConverter::ToExceptionString (ex))); + } + + protected: + SystemLog (); + }; + +#ifdef DEBUG +# define tracelog_point do { stringstream s; s << (SRC_POS); SystemLog::WriteError (s.str()); } while (false) +# define tracelog_msg(stream_args) do { stringstream s; s << (SRC_POS) << ": " << stream_args; SystemLog::WriteError (s.str()); } while (false) +#else +# define tracelog_point +# define tracelog_msg(stream_args) while (false) { stringstream s; s << stream_args; } +#endif + +} + +#endif // TC_HEADER_Platform_SystemLog diff --git a/Platform/TextReader.cpp b/Platform/TextReader.cpp index 3f6823c..c9c61d9 100644 --- a/Platform/TextReader.cpp +++ b/Platform/TextReader.cpp @@ -1,37 +1,37 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "TextReader.h" - -namespace TrueCrypt -{ - TextReader::TextReader (const FilePath &path) - { - InputFile.reset (new File); - InputFile->Open (path); - InputStream = shared_ptr (new FileStream (InputFile)); - } - - bool TextReader::ReadLine (string &outputString) - { - outputString.erase(); - - char c; - while (InputStream->Read (BufferPtr ((byte *) &c, sizeof (c))) == sizeof (c)) - { - if (c == '\r') - continue; - - if (c == '\n') - return true; - - outputString += c; - } - return !outputString.empty(); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "TextReader.h" + +namespace TrueCrypt +{ + TextReader::TextReader (const FilePath &path) + { + InputFile.reset (new File); + InputFile->Open (path); + InputStream = shared_ptr (new FileStream (InputFile)); + } + + bool TextReader::ReadLine (string &outputString) + { + outputString.erase(); + + char c; + while (InputStream->Read (BufferPtr ((byte *) &c, sizeof (c))) == sizeof (c)) + { + if (c == '\r') + continue; + + if (c == '\n') + return true; + + outputString += c; + } + return !outputString.empty(); + } +} diff --git a/Platform/TextReader.h b/Platform/TextReader.h index 47a9aab..c388e36 100644 --- a/Platform/TextReader.h +++ b/Platform/TextReader.h @@ -1,35 +1,35 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_TextReader -#define TC_HEADER_Platform_TextReader - -#include "PlatformBase.h" -#include "FileStream.h" -#include "FilesystemPath.h" -#include "SharedPtr.h" -#include "Stream.h" - -namespace TrueCrypt -{ - class TextReader - { - public: - TextReader (const FilePath &path); - TextReader (shared_ptr stream) : InputStream (stream) { } - virtual ~TextReader () { } - - virtual bool ReadLine (string &outputString); - - protected: - shared_ptr InputFile; - shared_ptr InputStream; - }; -} - -#endif // TC_HEADER_Platform_TextReader +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_TextReader +#define TC_HEADER_Platform_TextReader + +#include "PlatformBase.h" +#include "FileStream.h" +#include "FilesystemPath.h" +#include "SharedPtr.h" +#include "Stream.h" + +namespace TrueCrypt +{ + class TextReader + { + public: + TextReader (const FilePath &path); + TextReader (shared_ptr stream) : InputStream (stream) { } + virtual ~TextReader () { } + + virtual bool ReadLine (string &outputString); + + protected: + shared_ptr InputFile; + shared_ptr InputStream; + }; +} + +#endif // TC_HEADER_Platform_TextReader diff --git a/Platform/Thread.h b/Platform/Thread.h index 3157bfd..ea5283c 100644 --- a/Platform/Thread.h +++ b/Platform/Thread.h @@ -1,74 +1,74 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Thread -#define TC_HEADER_Platform_Thread - -#ifdef TC_WINDOWS -# include "System.h" -# define TC_THREAD_PROC DWORD WINAPI -#else -# include -# define TC_THREAD_PROC void* -#endif -#include "PlatformBase.h" -#include "Functor.h" -#include "SharedPtr.h" -#include "SyncEvent.h" - -namespace TrueCrypt -{ - class Thread - { - public: -#ifdef TC_WINDOWS - typedef HANDLE ThreadSystemHandle; - typedef LPTHREAD_START_ROUTINE ThreadProcPtr; -#else - typedef pthread_t ThreadSystemHandle; - typedef void* (*ThreadProcPtr) (void *); -#endif - Thread () { }; - virtual ~Thread () { }; - - void Join () const; - void Start (ThreadProcPtr threadProc, void *parameter = nullptr); - - void Start (Functor *functor) - { - Start (Thread::FunctorEntry, (void *)functor); - } - - static void Sleep (uint32 milliSeconds); - - protected: - static TC_THREAD_PROC FunctorEntry (void *functorArg) - { - Functor *functor = (Functor *) functorArg; - try - { - (*functor) (); - } - catch (...) { } - - delete functor; - return 0; - } - - static const size_t MinThreadStackSize = 1024 * 1024; - - ThreadSystemHandle SystemHandle; - - private: - Thread (const Thread &); - Thread &operator= (const Thread &); - }; - -} - -#endif // TC_HEADER_Platform_Thread +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Thread +#define TC_HEADER_Platform_Thread + +#ifdef TC_WINDOWS +# include "System.h" +# define TC_THREAD_PROC DWORD WINAPI +#else +# include +# define TC_THREAD_PROC void* +#endif +#include "PlatformBase.h" +#include "Functor.h" +#include "SharedPtr.h" +#include "SyncEvent.h" + +namespace TrueCrypt +{ + class Thread + { + public: +#ifdef TC_WINDOWS + typedef HANDLE ThreadSystemHandle; + typedef LPTHREAD_START_ROUTINE ThreadProcPtr; +#else + typedef pthread_t ThreadSystemHandle; + typedef void* (*ThreadProcPtr) (void *); +#endif + Thread () { }; + virtual ~Thread () { }; + + void Join () const; + void Start (ThreadProcPtr threadProc, void *parameter = nullptr); + + void Start (Functor *functor) + { + Start (Thread::FunctorEntry, (void *)functor); + } + + static void Sleep (uint32 milliSeconds); + + protected: + static TC_THREAD_PROC FunctorEntry (void *functorArg) + { + Functor *functor = (Functor *) functorArg; + try + { + (*functor) (); + } + catch (...) { } + + delete functor; + return 0; + } + + static const size_t MinThreadStackSize = 1024 * 1024; + + ThreadSystemHandle SystemHandle; + + private: + Thread (const Thread &); + Thread &operator= (const Thread &); + }; + +} + +#endif // TC_HEADER_Platform_Thread diff --git a/Platform/Time.h b/Platform/Time.h index 446eb8a..ccdd597 100644 --- a/Platform/Time.h +++ b/Platform/Time.h @@ -1,30 +1,30 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Time -#define TC_HEADER_Platform_Time - -#include "PlatformBase.h" - -namespace TrueCrypt -{ - class Time - { - public: - Time () { } - virtual ~Time () { } - - static uint64 GetCurrent (); // Returns time in hundreds of nanoseconds since 1601/01/01 - - private: - Time (const Time &); - Time &operator= (const Time &); - }; -} - -#endif // TC_HEADER_Platform_Time +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Time +#define TC_HEADER_Platform_Time + +#include "PlatformBase.h" + +namespace TrueCrypt +{ + class Time + { + public: + Time () { } + virtual ~Time () { } + + static uint64 GetCurrent (); // Returns time in hundreds of nanoseconds since 1601/01/01 + + private: + Time (const Time &); + Time &operator= (const Time &); + }; +} + +#endif // TC_HEADER_Platform_Time diff --git a/Platform/Unix/Directory.cpp b/Platform/Unix/Directory.cpp index 23afb24..0ea987b 100644 --- a/Platform/Unix/Directory.cpp +++ b/Platform/Unix/Directory.cpp @@ -1,62 +1,62 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include "System.h" -#include "Platform/Directory.h" -#include "Platform/Finally.h" -#include "Platform/SystemException.h" - -namespace TrueCrypt -{ - static Mutex ReadDirMutex; // readdir_r() may be unsafe on some systems - - void Directory::Create (const DirectoryPath &path) - { - string p = path; - throw_sys_sub_if (mkdir (p.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == -1, p); - } - - DirectoryPath Directory::AppendSeparator (const DirectoryPath &path) - { - wstring p (path); - - if (p.find_last_of (L'/') + 1 != p.size()) - return p + L'/'; - - return p; - } - - FilePathList Directory::GetFilePaths (const DirectoryPath &path, bool regularFilesOnly) - { - DIR *dir = opendir (string (path).c_str()); - throw_sys_sub_if (!dir, wstring (path)); - finally_do_arg (DIR*, dir, { closedir (finally_arg); }); - - ScopeLock lock (ReadDirMutex); - - FilePathList files; - struct dirent *dirEntry; - errno = 0; - while ((dirEntry = readdir (dir)) != nullptr) - { - shared_ptr filePath (new FilePath (string (AppendSeparator (path)) + string (dirEntry->d_name))); - - if (!regularFilesOnly || filePath->IsFile()) - files.push_back (filePath); - - errno = 0; - } - - throw_sys_sub_if (errno != 0, wstring (path)); - return files; - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include "System.h" +#include "Platform/Directory.h" +#include "Platform/Finally.h" +#include "Platform/SystemException.h" + +namespace TrueCrypt +{ + static Mutex ReadDirMutex; // readdir_r() may be unsafe on some systems + + void Directory::Create (const DirectoryPath &path) + { + string p = path; + throw_sys_sub_if (mkdir (p.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == -1, p); + } + + DirectoryPath Directory::AppendSeparator (const DirectoryPath &path) + { + wstring p (path); + + if (p.find_last_of (L'/') + 1 != p.size()) + return p + L'/'; + + return p; + } + + FilePathList Directory::GetFilePaths (const DirectoryPath &path, bool regularFilesOnly) + { + DIR *dir = opendir (string (path).c_str()); + throw_sys_sub_if (!dir, wstring (path)); + finally_do_arg (DIR*, dir, { closedir (finally_arg); }); + + ScopeLock lock (ReadDirMutex); + + FilePathList files; + struct dirent *dirEntry; + errno = 0; + while ((dirEntry = readdir (dir)) != nullptr) + { + shared_ptr filePath (new FilePath (string (AppendSeparator (path)) + string (dirEntry->d_name))); + + if (!regularFilesOnly || filePath->IsFile()) + files.push_back (filePath); + + errno = 0; + } + + throw_sys_sub_if (errno != 0, wstring (path)); + return files; + } +} diff --git a/Platform/Unix/File.cpp b/Platform/Unix/File.cpp index 9246011..4b51718 100644 --- a/Platform/Unix/File.cpp +++ b/Platform/Unix/File.cpp @@ -1,346 +1,345 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 - -#include -#include -#include -#include - -#ifdef TC_LINUX -#include -#endif - -#ifdef TC_BSD -#include -#endif - -#ifdef TC_SOLARIS -#include -#include -#endif - -#include -#include -#include - -#include "Platform/File.h" -#include "Platform/TextReader.h" - -namespace TrueCrypt -{ -#if 0 -# define TC_TRACE_FILE_OPERATIONS - - static void TraceFileOperation (int fileHandle, FilePath filePath, bool write, uint64 length, int64 position = -1) - { - string path = filePath; - if (path.empty() || path.find ("truecrypt_aux_mnt") != string::npos) - return; - - stringstream s; - s << path << ": " << (write ? "W " : "R ") << (position == -1 ? lseek (fileHandle, 0, SEEK_CUR) : position) << " (" << length << ")"; - SystemLog::WriteError (s.str()); - } -#endif - - void File::Close () - { - if_debug (ValidateState()); - - if (!SharedHandle) - { - close (FileHandle); - FileIsOpen = false; - - if ((mFileOpenFlags & File::PreserveTimestamps) && Path.IsFile()) - { - struct utimbuf u; - u.actime = AccTime; - u.modtime = ModTime; - - try - { - throw_sys_sub_if (utime (string (Path).c_str(), &u) == -1, wstring (Path)); - } - catch (...) // Suppress errors to allow using read-only files - { -#ifdef DEBUG - throw; -#endif - } - } - } - } - - void File::Delete () - { - Close(); - Path.Delete(); - } - - - void File::Flush () const - { - if_debug (ValidateState()); - throw_sys_sub_if (fsync (FileHandle) != 0, wstring (Path)); - } - - uint32 File::GetDeviceSectorSize () const - { - if (Path.IsDevice()) - { -#ifdef TC_LINUX - int blockSize; - throw_sys_sub_if (ioctl (FileHandle, BLKSSZGET, &blockSize) == -1, wstring (Path)); - return blockSize; - -#elif defined (TC_MACOSX) - uint32 blockSize; - throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path)); - return blockSize; - -#elif defined (TC_FREEBSD) - u_int sectorSize; - throw_sys_sub_if (ioctl (FileHandle, DIOCGSECTORSIZE, §orSize) == -1, wstring (Path)); - return (uint32) sectorSize; - -#elif defined (TC_SOLARIS) - struct dk_minfo mediaInfo; - throw_sys_sub_if (ioctl (FileHandle, DKIOCGMEDIAINFO, &mediaInfo) == -1, wstring (Path)); - return mediaInfo.dki_lbsize; -#endif - } - - return 512; - } - - uint64 File::GetPartitionDeviceStartOffset () const - { -#ifdef TC_LINUX - - // HDIO_GETGEO ioctl is limited by the size of long - TextReader tr ("/sys/block/" + string (Path.ToHostDriveOfPartition().ToBaseName()) + "/" + string (Path.ToBaseName()) + "/start"); - - string line; - tr.ReadLine (line); - return StringConverter::ToUInt64 (line) * GetDeviceSectorSize(); - -#elif defined (TC_MACOSX) - -#ifndef DKIOCGETBASE -# define DKIOCGETBASE _IOR('d', 73, uint64) -#endif - uint64 offset; - throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBASE, &offset) == -1, wstring (Path)); - return offset; - -#elif defined (TC_SOLARIS) - - struct extpart_info partInfo; - throw_sys_sub_if (ioctl (FileHandle, DKIOCEXTPARTINFO, &partInfo) == -1, wstring (Path)); - return partInfo.p_start * GetDeviceSectorSize(); - -#else - throw NotImplemented (SRC_POS); -#endif - } - - uint64 File::Length () const - { - if_debug (ValidateState()); - - // BSD does not support seeking to the end of a device -#ifdef TC_BSD - if (Path.IsBlockDevice() || Path.IsCharacterDevice()) - { -# ifdef TC_MACOSX - uint32 blockSize; - uint64 blockCount; - throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path)); - throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKCOUNT, &blockCount) == -1, wstring (Path)); - return blockCount * blockSize; -# else - uint64 mediaSize; - throw_sys_sub_if (ioctl (FileHandle, DIOCGMEDIASIZE, &mediaSize) == -1, wstring (Path)); - return mediaSize; -# endif - } -#endif - off_t current = lseek (FileHandle, 0, SEEK_CUR); - throw_sys_sub_if (current == -1, wstring (Path)); - SeekEnd (0); - uint64 length = lseek (FileHandle, 0, SEEK_CUR); - SeekAt (current); - return length; - } - - void File::Open (const FilePath &path, FileOpenMode mode, FileShareMode shareMode, FileOpenFlags flags) - { -#ifdef TC_LINUX - int sysFlags = O_LARGEFILE; -#else - int sysFlags = 0; -#endif - - switch (mode) - { - case CreateReadWrite: - sysFlags |= O_CREAT | O_TRUNC | O_RDWR; - break; - - case CreateWrite: - sysFlags |= O_CREAT | O_TRUNC | O_WRONLY; - break; - - case OpenRead: - sysFlags |= O_RDONLY; - break; - - case OpenWrite: - sysFlags |= O_WRONLY; - break; - - case OpenReadWrite: - sysFlags |= O_RDWR; - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - - if ((flags & File::PreserveTimestamps) && path.IsFile()) - { - struct stat statData; - throw_sys_sub_if (stat (string (path).c_str(), &statData) == -1, wstring (path)); - AccTime = statData.st_atime; - ModTime = statData.st_mtime; - } - - FileHandle = open (string (path).c_str(), sysFlags, S_IRUSR | S_IWUSR); - throw_sys_sub_if (FileHandle == -1, wstring (path)); - - try - { - struct flock fl; - memset (&fl, 0, sizeof (fl)); - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - - switch (shareMode) - { - case ShareNone: - fl.l_type = F_WRLCK; - if (fcntl (FileHandle, F_SETLK, &fl) == -1) - throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path)); - break; - - case ShareRead: - fl.l_type = F_RDLCK; - if (fcntl (FileHandle, F_SETLK, &fl) == -1) - throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path)); - break; - - case ShareReadWrite: - fl.l_type = (mode == OpenRead ? F_RDLCK : F_WRLCK); - if (fcntl (FileHandle, F_GETLK, &fl) != -1 && fl.l_type != F_UNLCK) - { - errno = EAGAIN; - throw SystemException (SRC_POS, wstring (path)); - } - break; - - case ShareReadWriteIgnoreLock: - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - } - catch (...) - { - close (FileHandle); - throw; - } - - Path = path; - mFileOpenFlags = flags; - FileIsOpen = true; - } - - uint64 File::Read (const BufferPtr &buffer) const - { - if_debug (ValidateState()); - -#ifdef TC_TRACE_FILE_OPERATIONS - TraceFileOperation (FileHandle, Path, false, buffer.Size()); -#endif - ssize_t bytesRead = read (FileHandle, buffer, buffer.Size()); - throw_sys_sub_if (bytesRead == -1, wstring (Path)); - - return bytesRead; - } - - uint64 File::ReadAt (const BufferPtr &buffer, uint64 position) const - { - if_debug (ValidateState()); - -#ifdef TC_TRACE_FILE_OPERATIONS - TraceFileOperation (FileHandle, Path, false, buffer.Size(), position); -#endif - ssize_t bytesRead = pread (FileHandle, buffer, buffer.Size(), position); - throw_sys_sub_if (bytesRead == -1, wstring (Path)); - - return bytesRead; - } - - void File::SeekAt (uint64 position) const - { - if_debug (ValidateState()); - throw_sys_sub_if (lseek (FileHandle, position, SEEK_SET) == -1, wstring (Path)); - } - - void File::SeekEnd (int offset) const - { - if_debug (ValidateState()); - - // BSD does not support seeking to the end of a device -#ifdef TC_BSD - if (Path.IsBlockDevice() || Path.IsCharacterDevice()) - { - SeekAt (Length() + offset); - return; - } -#endif - - throw_sys_sub_if (lseek (FileHandle, offset, SEEK_END) == -1, wstring (Path)); - } - - void File::Write (const ConstBufferPtr &buffer) const - { - if_debug (ValidateState()); - -#ifdef TC_TRACE_FILE_OPERATIONS - TraceFileOperation (FileHandle, Path, true, buffer.Size()); -#endif - throw_sys_sub_if (write (FileHandle, buffer, buffer.Size()) != buffer.Size(), wstring (Path)); - } - - void File::WriteAt (const ConstBufferPtr &buffer, uint64 position) const - { - if_debug (ValidateState()); - -#ifdef TC_TRACE_FILE_OPERATIONS - TraceFileOperation (FileHandle, Path, true, buffer.Size(), position); -#endif - throw_sys_sub_if (pwrite (FileHandle, buffer, buffer.Size(), position) != buffer.Size(), wstring (Path)); - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include + +#ifdef TC_LINUX +#include +#endif + +#ifdef TC_BSD +#include +#endif + +#ifdef TC_SOLARIS +#include +#include +#endif + +#include +#include +#include + +#include "Platform/File.h" +#include "Platform/TextReader.h" + +namespace TrueCrypt +{ +#if 0 +# define TC_TRACE_FILE_OPERATIONS + + static void TraceFileOperation (int fileHandle, FilePath filePath, bool write, uint64 length, int64 position = -1) + { + string path = filePath; + if (path.empty() || path.find ("truecrypt_aux_mnt") != string::npos) + return; + + stringstream s; + s << path << ": " << (write ? "W " : "R ") << (position == -1 ? lseek (fileHandle, 0, SEEK_CUR) : position) << " (" << length << ")"; + SystemLog::WriteError (s.str()); + } +#endif + + void File::Close () + { + if_debug (ValidateState()); + + if (!SharedHandle) + { + close (FileHandle); + FileIsOpen = false; + + if ((mFileOpenFlags & File::PreserveTimestamps) && Path.IsFile()) + { + struct utimbuf u; + u.actime = AccTime; + u.modtime = ModTime; + + try + { + throw_sys_sub_if (utime (string (Path).c_str(), &u) == -1, wstring (Path)); + } + catch (...) // Suppress errors to allow using read-only files + { +#ifdef DEBUG + throw; +#endif + } + } + } + } + + void File::Delete () + { + Close(); + Path.Delete(); + } + + + void File::Flush () const + { + if_debug (ValidateState()); + throw_sys_sub_if (fsync (FileHandle) != 0, wstring (Path)); + } + + uint32 File::GetDeviceSectorSize () const + { + if (Path.IsDevice()) + { +#ifdef TC_LINUX + int blockSize; + throw_sys_sub_if (ioctl (FileHandle, BLKSSZGET, &blockSize) == -1, wstring (Path)); + return blockSize; + +#elif defined (TC_MACOSX) + uint32 blockSize; + throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path)); + return blockSize; + +#elif defined (TC_FREEBSD) + u_int sectorSize; + throw_sys_sub_if (ioctl (FileHandle, DIOCGSECTORSIZE, §orSize) == -1, wstring (Path)); + return (uint32) sectorSize; + +#elif defined (TC_SOLARIS) + struct dk_minfo mediaInfo; + throw_sys_sub_if (ioctl (FileHandle, DKIOCGMEDIAINFO, &mediaInfo) == -1, wstring (Path)); + return mediaInfo.dki_lbsize; +#endif + } + + return 512; + } + + uint64 File::GetPartitionDeviceStartOffset () const + { +#ifdef TC_LINUX + + // HDIO_GETGEO ioctl is limited by the size of long + TextReader tr ("/sys/block/" + string (Path.ToHostDriveOfPartition().ToBaseName()) + "/" + string (Path.ToBaseName()) + "/start"); + + string line; + tr.ReadLine (line); + return StringConverter::ToUInt64 (line) * GetDeviceSectorSize(); + +#elif defined (TC_MACOSX) + +#ifndef DKIOCGETBASE +# define DKIOCGETBASE _IOR('d', 73, uint64) +#endif + uint64 offset; + throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBASE, &offset) == -1, wstring (Path)); + return offset; + +#elif defined (TC_SOLARIS) + + struct extpart_info partInfo; + throw_sys_sub_if (ioctl (FileHandle, DKIOCEXTPARTINFO, &partInfo) == -1, wstring (Path)); + return partInfo.p_start * GetDeviceSectorSize(); + +#else + throw NotImplemented (SRC_POS); +#endif + } + + uint64 File::Length () const + { + if_debug (ValidateState()); + + // BSD does not support seeking to the end of a device +#ifdef TC_BSD + if (Path.IsBlockDevice() || Path.IsCharacterDevice()) + { +# ifdef TC_MACOSX + uint32 blockSize; + uint64 blockCount; + throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path)); + throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKCOUNT, &blockCount) == -1, wstring (Path)); + return blockCount * blockSize; +# else + uint64 mediaSize; + throw_sys_sub_if (ioctl (FileHandle, DIOCGMEDIASIZE, &mediaSize) == -1, wstring (Path)); + return mediaSize; +# endif + } +#endif + off_t current = lseek (FileHandle, 0, SEEK_CUR); + throw_sys_sub_if (current == -1, wstring (Path)); + SeekEnd (0); + uint64 length = lseek (FileHandle, 0, SEEK_CUR); + SeekAt (current); + return length; + } + + void File::Open (const FilePath &path, FileOpenMode mode, FileShareMode shareMode, FileOpenFlags flags) + { +#ifdef TC_LINUX + int sysFlags = O_LARGEFILE; +#else + int sysFlags = 0; +#endif + + switch (mode) + { + case CreateReadWrite: + sysFlags |= O_CREAT | O_TRUNC | O_RDWR; + break; + + case CreateWrite: + sysFlags |= O_CREAT | O_TRUNC | O_WRONLY; + break; + + case OpenRead: + sysFlags |= O_RDONLY; + break; + + case OpenWrite: + sysFlags |= O_WRONLY; + break; + + case OpenReadWrite: + sysFlags |= O_RDWR; + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + + if ((flags & File::PreserveTimestamps) && path.IsFile()) + { + struct stat statData; + throw_sys_sub_if (stat (string (path).c_str(), &statData) == -1, wstring (path)); + AccTime = statData.st_atime; + ModTime = statData.st_mtime; + } + + FileHandle = open (string (path).c_str(), sysFlags, S_IRUSR | S_IWUSR); + throw_sys_sub_if (FileHandle == -1, wstring (path)); + +#if 0 // File locking is disabled to avoid remote filesystem locking issues + try + { + struct flock fl; + memset (&fl, 0, sizeof (fl)); + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + + switch (shareMode) + { + case ShareNone: + fl.l_type = F_WRLCK; + if (fcntl (FileHandle, F_SETLK, &fl) == -1) + throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path)); + break; + + case ShareRead: + fl.l_type = F_RDLCK; + if (fcntl (FileHandle, F_SETLK, &fl) == -1) + throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path)); + break; + + case ShareReadWrite: + fl.l_type = (mode == OpenRead ? F_RDLCK : F_WRLCK); + if (fcntl (FileHandle, F_GETLK, &fl) != -1 && fl.l_type != F_UNLCK) + { + errno = EAGAIN; + throw SystemException (SRC_POS, wstring (path)); + } + break; + + case ShareReadWriteIgnoreLock: + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + } + catch (...) + { + close (FileHandle); + throw; + } +#endif // 0 + + Path = path; + mFileOpenFlags = flags; + FileIsOpen = true; + } + + uint64 File::Read (const BufferPtr &buffer) const + { + if_debug (ValidateState()); + +#ifdef TC_TRACE_FILE_OPERATIONS + TraceFileOperation (FileHandle, Path, false, buffer.Size()); +#endif + ssize_t bytesRead = read (FileHandle, buffer, buffer.Size()); + throw_sys_sub_if (bytesRead == -1, wstring (Path)); + + return bytesRead; + } + + uint64 File::ReadAt (const BufferPtr &buffer, uint64 position) const + { + if_debug (ValidateState()); + +#ifdef TC_TRACE_FILE_OPERATIONS + TraceFileOperation (FileHandle, Path, false, buffer.Size(), position); +#endif + ssize_t bytesRead = pread (FileHandle, buffer, buffer.Size(), position); + throw_sys_sub_if (bytesRead == -1, wstring (Path)); + + return bytesRead; + } + + void File::SeekAt (uint64 position) const + { + if_debug (ValidateState()); + throw_sys_sub_if (lseek (FileHandle, position, SEEK_SET) == -1, wstring (Path)); + } + + void File::SeekEnd (int offset) const + { + if_debug (ValidateState()); + + // BSD does not support seeking to the end of a device +#ifdef TC_BSD + if (Path.IsBlockDevice() || Path.IsCharacterDevice()) + { + SeekAt (Length() + offset); + return; + } +#endif + + throw_sys_sub_if (lseek (FileHandle, offset, SEEK_END) == -1, wstring (Path)); + } + + void File::Write (const ConstBufferPtr &buffer) const + { + if_debug (ValidateState()); + +#ifdef TC_TRACE_FILE_OPERATIONS + TraceFileOperation (FileHandle, Path, true, buffer.Size()); +#endif + throw_sys_sub_if (write (FileHandle, buffer, buffer.Size()) != (ssize_t) buffer.Size(), wstring (Path)); + } + + void File::WriteAt (const ConstBufferPtr &buffer, uint64 position) const + { + if_debug (ValidateState()); + +#ifdef TC_TRACE_FILE_OPERATIONS + TraceFileOperation (FileHandle, Path, true, buffer.Size(), position); +#endif + throw_sys_sub_if (pwrite (FileHandle, buffer, buffer.Size(), position) != (ssize_t) buffer.Size(), wstring (Path)); + } +} diff --git a/Platform/Unix/FilesystemPath.cpp b/Platform/Unix/FilesystemPath.cpp index a762b53..84178e2 100644 --- a/Platform/Unix/FilesystemPath.cpp +++ b/Platform/Unix/FilesystemPath.cpp @@ -1,96 +1,96 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/FilesystemPath.h" -#include "Platform/SystemException.h" -#include "Platform/StringConverter.h" -#include -#include - -namespace TrueCrypt -{ - void FilesystemPath::Delete () const - { - throw_sys_sub_if (remove (string (*this).c_str()) == -1, Path); - } - - UserId FilesystemPath::GetOwner () const - { - struct stat statData; - throw_sys_if (stat (StringConverter::ToSingle (Path).c_str(), &statData) == -1); - - UserId owner; - owner.SystemId = statData.st_uid; - return owner; - } - - FilesystemPathType::Enum FilesystemPath::GetType () const - { - // Strip trailing directory separator - wstring path = Path; - size_t pos = path.find_last_not_of (L'/'); - if (path.size() > 2 && pos != path.size() - 1) - path = path.substr (0, pos + 1); - - struct stat statData; - throw_sys_sub_if (stat (StringConverter::ToSingle (path).c_str(), &statData) != 0, Path); - - if (S_ISREG (statData.st_mode)) return FilesystemPathType::File; - if (S_ISDIR (statData.st_mode)) return FilesystemPathType::Directory; - if (S_ISCHR (statData.st_mode)) return FilesystemPathType::CharacterDevice; - if (S_ISBLK (statData.st_mode)) return FilesystemPathType::BlockDevice; - if (S_ISLNK (statData.st_mode)) return FilesystemPathType::SymbolickLink; - - return FilesystemPathType::Unknown; - } - - FilesystemPath FilesystemPath::ToBaseName () const - { - wstring path = Path; - size_t pos = path.find_last_of (L'/'); - - if (pos == string::npos) - return Path; - - return Path.substr (pos + 1); - } - - FilesystemPath FilesystemPath::ToHostDriveOfPartition () const - { - DevicePath path; - -#ifdef TC_LINUX - - path = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path)); - -#elif defined (TC_MACOSX) - - string pathStr = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path)); - path = pathStr.substr (0, pathStr.size() - 1); - -#elif defined (TC_FREEBSD) - - string pathStr = StringConverter::ToSingle (Path); - size_t p = pathStr.rfind ("s"); - if (p == string::npos) - throw PartitionDeviceRequired (SRC_POS); - path = pathStr.substr (0, p); - -#elif defined (TC_SOLARIS) - - path = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path)) + "0"; - -#else - throw NotImplemented (SRC_POS); -#endif - if (!path.IsDevice()) - throw PartitionDeviceRequired (SRC_POS); - - return path; - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/FilesystemPath.h" +#include "Platform/SystemException.h" +#include "Platform/StringConverter.h" +#include +#include + +namespace TrueCrypt +{ + void FilesystemPath::Delete () const + { + throw_sys_sub_if (remove (string (*this).c_str()) == -1, Path); + } + + UserId FilesystemPath::GetOwner () const + { + struct stat statData; + throw_sys_if (stat (StringConverter::ToSingle (Path).c_str(), &statData) == -1); + + UserId owner; + owner.SystemId = statData.st_uid; + return owner; + } + + FilesystemPathType::Enum FilesystemPath::GetType () const + { + // Strip trailing directory separator + wstring path = Path; + size_t pos = path.find_last_not_of (L'/'); + if (path.size() > 2 && pos != path.size() - 1) + path = path.substr (0, pos + 1); + + struct stat statData; + throw_sys_sub_if (stat (StringConverter::ToSingle (path).c_str(), &statData) != 0, Path); + + if (S_ISREG (statData.st_mode)) return FilesystemPathType::File; + if (S_ISDIR (statData.st_mode)) return FilesystemPathType::Directory; + if (S_ISCHR (statData.st_mode)) return FilesystemPathType::CharacterDevice; + if (S_ISBLK (statData.st_mode)) return FilesystemPathType::BlockDevice; + if (S_ISLNK (statData.st_mode)) return FilesystemPathType::SymbolickLink; + + return FilesystemPathType::Unknown; + } + + FilesystemPath FilesystemPath::ToBaseName () const + { + wstring path = Path; + size_t pos = path.find_last_of (L'/'); + + if (pos == string::npos) + return Path; + + return Path.substr (pos + 1); + } + + FilesystemPath FilesystemPath::ToHostDriveOfPartition () const + { + DevicePath path; + +#ifdef TC_LINUX + + path = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path)); + +#elif defined (TC_MACOSX) + + string pathStr = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path)); + path = pathStr.substr (0, pathStr.size() - 1); + +#elif defined (TC_FREEBSD) + + string pathStr = StringConverter::ToSingle (Path); + size_t p = pathStr.rfind ("s"); + if (p == string::npos) + throw PartitionDeviceRequired (SRC_POS); + path = pathStr.substr (0, p); + +#elif defined (TC_SOLARIS) + + path = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path)) + "0"; + +#else + throw NotImplemented (SRC_POS); +#endif + if (!path.IsDevice()) + throw PartitionDeviceRequired (SRC_POS); + + return path; + } +} diff --git a/Platform/Unix/Mutex.cpp b/Platform/Unix/Mutex.cpp index b14d4b8..8f4e4ca 100644 --- a/Platform/Unix/Mutex.cpp +++ b/Platform/Unix/Mutex.cpp @@ -1,62 +1,62 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include "Platform/Mutex.h" -#include "Platform/SystemException.h" - -namespace TrueCrypt -{ - Mutex::Mutex () - { - pthread_mutexattr_t attributes; - - int status = pthread_mutexattr_init (&attributes); - if (status != 0) - throw SystemException (SRC_POS, status); - - status = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); - if (status != 0) - throw SystemException (SRC_POS, status); - - status = pthread_mutex_init (&SystemMutex, &attributes); - if (status != 0) - throw SystemException (SRC_POS, status); - - Initialized = true; - } - - Mutex::~Mutex () - { - Initialized = false; -#ifdef DEBUG - int status = -#endif - pthread_mutex_destroy (&SystemMutex); - -#ifdef DEBUG - if (status != 0) - SystemLog::WriteException (SystemException (SRC_POS, status)); -#endif - } - - void Mutex::Lock () - { - assert (Initialized); - int status = pthread_mutex_lock (&SystemMutex); - if (status != 0) - throw SystemException (SRC_POS, status); - } - - void Mutex::Unlock () - { - int status = pthread_mutex_unlock (&SystemMutex); - if (status != 0) - throw SystemException (SRC_POS, status); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include "Platform/Mutex.h" +#include "Platform/SystemException.h" + +namespace TrueCrypt +{ + Mutex::Mutex () + { + pthread_mutexattr_t attributes; + + int status = pthread_mutexattr_init (&attributes); + if (status != 0) + throw SystemException (SRC_POS, status); + + status = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (status != 0) + throw SystemException (SRC_POS, status); + + status = pthread_mutex_init (&SystemMutex, &attributes); + if (status != 0) + throw SystemException (SRC_POS, status); + + Initialized = true; + } + + Mutex::~Mutex () + { + Initialized = false; +#ifdef DEBUG + int status = +#endif + pthread_mutex_destroy (&SystemMutex); + +#ifdef DEBUG + if (status != 0) + SystemLog::WriteException (SystemException (SRC_POS, status)); +#endif + } + + void Mutex::Lock () + { + assert (Initialized); + int status = pthread_mutex_lock (&SystemMutex); + if (status != 0) + throw SystemException (SRC_POS, status); + } + + void Mutex::Unlock () + { + int status = pthread_mutex_unlock (&SystemMutex); + if (status != 0) + throw SystemException (SRC_POS, status); + } +} diff --git a/Platform/Unix/Pipe.cpp b/Platform/Unix/Pipe.cpp index ad6ff64..176c820 100644 --- a/Platform/Unix/Pipe.cpp +++ b/Platform/Unix/Pipe.cpp @@ -1,65 +1,65 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include "Pipe.h" -#include "Platform/SystemException.h" - -namespace TrueCrypt -{ - Pipe::Pipe () - { - int fd[2]; - throw_sys_if (pipe (fd) == -1); - ReadFileDescriptor = fd[0]; - WriteFileDescriptor = fd[1]; - } - - Pipe::~Pipe () - { - try - { - Close(); - } - catch (...) { } - } - - void Pipe::Close () - { - if (ReadFileDescriptor != -1) - close (ReadFileDescriptor); - if (WriteFileDescriptor != -1) - close (WriteFileDescriptor); - } - - int Pipe::GetReadFD () - { - assert (ReadFileDescriptor != -1); - - if (WriteFileDescriptor != -1) - { - close (WriteFileDescriptor); - WriteFileDescriptor = -1; - } - - return ReadFileDescriptor; - } - - int Pipe::GetWriteFD () - { - assert (WriteFileDescriptor != -1); - - if (ReadFileDescriptor != -1) - { - close (ReadFileDescriptor); - ReadFileDescriptor = -1; - } - - return WriteFileDescriptor; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include "Pipe.h" +#include "Platform/SystemException.h" + +namespace TrueCrypt +{ + Pipe::Pipe () + { + int fd[2]; + throw_sys_if (pipe (fd) == -1); + ReadFileDescriptor = fd[0]; + WriteFileDescriptor = fd[1]; + } + + Pipe::~Pipe () + { + try + { + Close(); + } + catch (...) { } + } + + void Pipe::Close () + { + if (ReadFileDescriptor != -1) + close (ReadFileDescriptor); + if (WriteFileDescriptor != -1) + close (WriteFileDescriptor); + } + + int Pipe::GetReadFD () + { + assert (ReadFileDescriptor != -1); + + if (WriteFileDescriptor != -1) + { + close (WriteFileDescriptor); + WriteFileDescriptor = -1; + } + + return ReadFileDescriptor; + } + + int Pipe::GetWriteFD () + { + assert (WriteFileDescriptor != -1); + + if (ReadFileDescriptor != -1) + { + close (ReadFileDescriptor); + ReadFileDescriptor = -1; + } + + return WriteFileDescriptor; + } +} diff --git a/Platform/Unix/Pipe.h b/Platform/Unix/Pipe.h index 2dfad2e..de8dcf6 100644 --- a/Platform/Unix/Pipe.h +++ b/Platform/Unix/Pipe.h @@ -1,38 +1,38 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Unix_Pipe -#define TC_HEADER_Platform_Unix_Pipe - -#include "Platform/PlatformBase.h" - -namespace TrueCrypt -{ - class Pipe - { - public: - Pipe (); - virtual ~Pipe (); - - void Close (); - int GetReadFD (); - int GetWriteFD (); - int PeekReadFD () const { return ReadFileDescriptor; } - int PeekWriteFD () const { return WriteFileDescriptor; } - - protected: - int ReadFileDescriptor; - int WriteFileDescriptor; - - private: - Pipe (const Pipe &); - Pipe &operator= (const Pipe &); - }; -} - -#endif // TC_HEADER_Platform_Unix_Pipe +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Unix_Pipe +#define TC_HEADER_Platform_Unix_Pipe + +#include "Platform/PlatformBase.h" + +namespace TrueCrypt +{ + class Pipe + { + public: + Pipe (); + virtual ~Pipe (); + + void Close (); + int GetReadFD (); + int GetWriteFD (); + int PeekReadFD () const { return ReadFileDescriptor; } + int PeekWriteFD () const { return WriteFileDescriptor; } + + protected: + int ReadFileDescriptor; + int WriteFileDescriptor; + + private: + Pipe (const Pipe &); + Pipe &operator= (const Pipe &); + }; +} + +#endif // TC_HEADER_Platform_Unix_Pipe diff --git a/Platform/Unix/Poller.cpp b/Platform/Unix/Poller.cpp index 1cda024..9692c4f 100644 --- a/Platform/Unix/Poller.cpp +++ b/Platform/Unix/Poller.cpp @@ -1,57 +1,57 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include "Poller.h" -#include "Platform/SystemException.h" - -namespace TrueCrypt -{ - Poller::Poller (int fileDescriptor1, int fileDescriptor2, int fileDescriptor3, int fileDescriptor4) - { - FileDescriptors.push_back (fileDescriptor1); - - if (fileDescriptor2 != -1) - FileDescriptors.push_back (fileDescriptor2); - - if (fileDescriptor3 != -1) - FileDescriptors.push_back (fileDescriptor3); - - if (fileDescriptor4 != -1) - FileDescriptors.push_back (fileDescriptor4); - } - - list Poller::WaitForData (int timeOut) const - { - vector pfd (FileDescriptors.size()); - for (int i = 0; i < FileDescriptors.size(); i++) - { - pfd[i].fd = FileDescriptors[i]; - pfd[i].events = POLLIN; - } - - list descList; - - int pollRes = poll (&pfd[0], pfd.size(), timeOut); - - if (pollRes == 0 && timeOut != -1) - throw TimeOut (SRC_POS); - - if (pollRes > 0) - { - for (int i = 0; i < pfd.size(); i++) - { - if (pfd[i].revents & POLLIN) - descList.push_back (pfd[i].fd); - } - } - - return descList; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include "Poller.h" +#include "Platform/SystemException.h" + +namespace TrueCrypt +{ + Poller::Poller (int fileDescriptor1, int fileDescriptor2, int fileDescriptor3, int fileDescriptor4) + { + FileDescriptors.push_back (fileDescriptor1); + + if (fileDescriptor2 != -1) + FileDescriptors.push_back (fileDescriptor2); + + if (fileDescriptor3 != -1) + FileDescriptors.push_back (fileDescriptor3); + + if (fileDescriptor4 != -1) + FileDescriptors.push_back (fileDescriptor4); + } + + list Poller::WaitForData (int timeOut) const + { + vector pfd (FileDescriptors.size()); + for (size_t i = 0; i < FileDescriptors.size(); i++) + { + pfd[i].fd = FileDescriptors[i]; + pfd[i].events = POLLIN; + } + + list descList; + + int pollRes = poll (&pfd[0], pfd.size(), timeOut); + + if (pollRes == 0 && timeOut != -1) + throw TimeOut (SRC_POS); + + if (pollRes > 0) + { + for (size_t i = 0; i < pfd.size(); i++) + { + if (pfd[i].revents & POLLIN) + descList.push_back (pfd[i].fd); + } + } + + return descList; + } +} diff --git a/Platform/Unix/Poller.h b/Platform/Unix/Poller.h index 10b35dd..aad4b35 100644 --- a/Platform/Unix/Poller.h +++ b/Platform/Unix/Poller.h @@ -1,33 +1,33 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Unix_Poller -#define TC_HEADER_Platform_Unix_Poller - -#include "Platform/PlatformBase.h" - -namespace TrueCrypt -{ - class Poller - { - public: - Poller (int fileDescriptor1, int fileDescriptor2 = -1, int fileDescriptor3 = -1, int fileDescriptor4 = -1); - virtual ~Poller () { } - - list WaitForData (int timeOut = -1) const; - - protected: - vector FileDescriptors; - - private: - Poller (const Poller &); - Poller &operator= (const Poller &); - }; -} - -#endif // TC_HEADER_Platform_Unix_Poller +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Unix_Poller +#define TC_HEADER_Platform_Unix_Poller + +#include "Platform/PlatformBase.h" + +namespace TrueCrypt +{ + class Poller + { + public: + Poller (int fileDescriptor1, int fileDescriptor2 = -1, int fileDescriptor3 = -1, int fileDescriptor4 = -1); + virtual ~Poller () { } + + list WaitForData (int timeOut = -1) const; + + protected: + vector FileDescriptors; + + private: + Poller (const Poller &); + Poller &operator= (const Poller &); + }; +} + +#endif // TC_HEADER_Platform_Unix_Poller diff --git a/Platform/Unix/Process.cpp b/Platform/Unix/Process.cpp index 37cc570..c374961 100644 --- a/Platform/Unix/Process.cpp +++ b/Platform/Unix/Process.cpp @@ -1,199 +1,199 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include -#include -#include -#include "Process.h" -#include "Platform/Exception.h" -#include "Platform/FileStream.h" -#include "Platform/ForEach.h" -#include "Platform/MemoryStream.h" -#include "Platform/SystemException.h" -#include "Platform/StringConverter.h" -#include "Platform/Unix/Pipe.h" -#include "Platform/Unix/Poller.h" - -namespace TrueCrypt -{ - string Process::Execute (const string &processName, const list &arguments, int timeOut, ProcessExecFunctor *execFunctor, const Buffer *inputData) - { - char *args[32]; - if (array_capacity (args) <= arguments.size()) - throw ParameterTooLarge (SRC_POS); - -#if 0 - stringstream dbg; - dbg << "exec " << processName; - foreach (const string &at, arguments) - dbg << " " << at; - trace_msg (dbg.str()); -#endif - - Pipe inPipe, outPipe, errPipe, exceptionPipe; - - int forkedPid = fork(); - throw_sys_if (forkedPid == -1); - - if (forkedPid == 0) - { - try - { - try - { - int argIndex = 0; - if (!execFunctor) - args[argIndex++] = const_cast (processName.c_str()); - - foreach (const string &arg, arguments) - { - args[argIndex++] = const_cast (arg.c_str()); - } - args[argIndex] = nullptr; - - if (inputData) - { - throw_sys_if (dup2 (inPipe.GetReadFD(), STDIN_FILENO) == -1); - } - else - { - inPipe.Close(); - int nullDev = open ("/dev/null", 0); - throw_sys_sub_if (nullDev == -1, "/dev/null"); - throw_sys_if (dup2 (nullDev, STDIN_FILENO) == -1); - } - - throw_sys_if (dup2 (outPipe.GetWriteFD(), STDOUT_FILENO) == -1); - throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1); - exceptionPipe.GetWriteFD(); - - if (execFunctor) - { - (*execFunctor)(argIndex, args); - } - else - { - execvp (args[0], args); - throw SystemException (SRC_POS, args[0]); - } - } - catch (Exception &) - { - throw; - } - catch (exception &e) - { - throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e)); - } - catch (...) - { - throw UnknownException (SRC_POS); - } - } - catch (Exception &e) - { - try - { - shared_ptr outputStream (new FileStream (exceptionPipe.GetWriteFD())); - e.Serialize (outputStream); - } - catch (...) { } - } - - _exit (1); - } - - throw_sys_if (fcntl (outPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); - throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); - throw_sys_if (fcntl (exceptionPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); - - vector buffer (4096), stdOutput (4096), errOutput (4096), exOutput (4096); - buffer.clear (); - stdOutput.clear (); - errOutput.clear (); - exOutput.clear (); - - Poller poller (outPipe.GetReadFD(), errPipe.GetReadFD(), exceptionPipe.GetReadFD()); - int status, waitRes; - - if (inputData) - throw_sys_if (write (inPipe.GetWriteFD(), inputData->Ptr(), inputData->Size()) == -1 && errno != EPIPE); - - inPipe.Close(); - - int timeTaken = 0; - do - { - const int pollTimeout = 200; - try - { - ssize_t bytesRead = 0; - foreach (int fd, poller.WaitForData (pollTimeout)) - { - bytesRead = read (fd, &buffer[0], buffer.capacity()); - if (bytesRead > 0) - { - if (fd == outPipe.GetReadFD()) - stdOutput.insert (stdOutput.end(), buffer.begin(), buffer.begin() + bytesRead); - else if (fd == errPipe.GetReadFD()) - errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead); - else if (fd == exceptionPipe.GetReadFD()) - exOutput.insert (exOutput.end(), buffer.begin(), buffer.begin() + bytesRead); - } - } - - if (bytesRead == 0) - { - waitRes = waitpid (forkedPid, &status, 0); - break; - } - } - catch (TimeOut&) - { - timeTaken += pollTimeout; - if (timeOut >= 0 && timeTaken >= timeOut) - throw; - } - } while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0); - throw_sys_if (waitRes == -1); - - stdOutput.push_back (0); - errOutput.push_back (0); - - if (!exOutput.empty()) - { - auto_ptr deserializedObject; - Exception *deserializedException = nullptr; - - try - { - shared_ptr stream (new MemoryStream (ConstBufferPtr ((byte *) &exOutput[0], exOutput.size()))); - deserializedObject.reset (Serializable::DeserializeNew (stream)); - deserializedException = dynamic_cast (deserializedObject.get()); - } - catch (...) { } - - if (deserializedException) - deserializedException->Throw(); - } - - int exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1); - if (exitCode != 0) - { - string strErrOutput; - strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end()); - throw ExecutedProcessFailed (SRC_POS, processName, exitCode, strErrOutput); - } - - string strOutput; - strOutput.insert (strOutput.begin(), stdOutput.begin(), stdOutput.end()); - return strOutput; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include +#include +#include +#include "Process.h" +#include "Platform/Exception.h" +#include "Platform/FileStream.h" +#include "Platform/ForEach.h" +#include "Platform/MemoryStream.h" +#include "Platform/SystemException.h" +#include "Platform/StringConverter.h" +#include "Platform/Unix/Pipe.h" +#include "Platform/Unix/Poller.h" + +namespace TrueCrypt +{ + string Process::Execute (const string &processName, const list &arguments, int timeOut, ProcessExecFunctor *execFunctor, const Buffer *inputData) + { + char *args[32]; + if (array_capacity (args) <= arguments.size()) + throw ParameterTooLarge (SRC_POS); + +#if 0 + stringstream dbg; + dbg << "exec " << processName; + foreach (const string &at, arguments) + dbg << " " << at; + trace_msg (dbg.str()); +#endif + + Pipe inPipe, outPipe, errPipe, exceptionPipe; + + int forkedPid = fork(); + throw_sys_if (forkedPid == -1); + + if (forkedPid == 0) + { + try + { + try + { + int argIndex = 0; + if (!execFunctor) + args[argIndex++] = const_cast (processName.c_str()); + + foreach (const string &arg, arguments) + { + args[argIndex++] = const_cast (arg.c_str()); + } + args[argIndex] = nullptr; + + if (inputData) + { + throw_sys_if (dup2 (inPipe.GetReadFD(), STDIN_FILENO) == -1); + } + else + { + inPipe.Close(); + int nullDev = open ("/dev/null", 0); + throw_sys_sub_if (nullDev == -1, "/dev/null"); + throw_sys_if (dup2 (nullDev, STDIN_FILENO) == -1); + } + + throw_sys_if (dup2 (outPipe.GetWriteFD(), STDOUT_FILENO) == -1); + throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1); + exceptionPipe.GetWriteFD(); + + if (execFunctor) + { + (*execFunctor)(argIndex, args); + } + else + { + execvp (args[0], args); + throw SystemException (SRC_POS, args[0]); + } + } + catch (Exception &) + { + throw; + } + catch (exception &e) + { + throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e)); + } + catch (...) + { + throw UnknownException (SRC_POS); + } + } + catch (Exception &e) + { + try + { + shared_ptr outputStream (new FileStream (exceptionPipe.GetWriteFD())); + e.Serialize (outputStream); + } + catch (...) { } + } + + _exit (1); + } + + throw_sys_if (fcntl (outPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); + throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); + throw_sys_if (fcntl (exceptionPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1); + + vector buffer (4096), stdOutput (4096), errOutput (4096), exOutput (4096); + buffer.clear (); + stdOutput.clear (); + errOutput.clear (); + exOutput.clear (); + + Poller poller (outPipe.GetReadFD(), errPipe.GetReadFD(), exceptionPipe.GetReadFD()); + int status, waitRes; + + if (inputData) + throw_sys_if (write (inPipe.GetWriteFD(), inputData->Ptr(), inputData->Size()) == -1 && errno != EPIPE); + + inPipe.Close(); + + int timeTaken = 0; + do + { + const int pollTimeout = 200; + try + { + ssize_t bytesRead = 0; + foreach (int fd, poller.WaitForData (pollTimeout)) + { + bytesRead = read (fd, &buffer[0], buffer.capacity()); + if (bytesRead > 0) + { + if (fd == outPipe.GetReadFD()) + stdOutput.insert (stdOutput.end(), buffer.begin(), buffer.begin() + bytesRead); + else if (fd == errPipe.GetReadFD()) + errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead); + else if (fd == exceptionPipe.GetReadFD()) + exOutput.insert (exOutput.end(), buffer.begin(), buffer.begin() + bytesRead); + } + } + + if (bytesRead == 0) + { + waitRes = waitpid (forkedPid, &status, 0); + break; + } + } + catch (TimeOut&) + { + timeTaken += pollTimeout; + if (timeOut >= 0 && timeTaken >= timeOut) + throw; + } + } while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0); + throw_sys_if (waitRes == -1); + + stdOutput.push_back (0); + errOutput.push_back (0); + + if (!exOutput.empty()) + { + auto_ptr deserializedObject; + Exception *deserializedException = nullptr; + + try + { + shared_ptr stream (new MemoryStream (ConstBufferPtr ((byte *) &exOutput[0], exOutput.size()))); + deserializedObject.reset (Serializable::DeserializeNew (stream)); + deserializedException = dynamic_cast (deserializedObject.get()); + } + catch (...) { } + + if (deserializedException) + deserializedException->Throw(); + } + + int exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1); + if (exitCode != 0) + { + string strErrOutput; + strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end()); + throw ExecutedProcessFailed (SRC_POS, processName, exitCode, strErrOutput); + } + + string strOutput; + strOutput.insert (strOutput.begin(), stdOutput.begin(), stdOutput.end()); + return strOutput; + } +} diff --git a/Platform/Unix/Process.h b/Platform/Unix/Process.h index 99972f8..caeb9c4 100644 --- a/Platform/Unix/Process.h +++ b/Platform/Unix/Process.h @@ -1,40 +1,40 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Unix_Process -#define TC_HEADER_Platform_Unix_Process - -#include "Platform/PlatformBase.h" -#include "Platform/Buffer.h" -#include "Platform/Functor.h" - -namespace TrueCrypt -{ - struct ProcessExecFunctor - { - virtual ~ProcessExecFunctor () { } - virtual void operator() (int argc, char *argv[]) = 0; - }; - - class Process - { - public: - Process (); - virtual ~Process (); - - static string Execute (const string &processName, const list &arguments, int timeOut = -1, ProcessExecFunctor *execFunctor = nullptr, const Buffer *inputData = nullptr); - - protected: - - private: - Process (const Process &); - Process &operator= (const Process &); - }; -} - -#endif // TC_HEADER_Platform_Unix_Process +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Unix_Process +#define TC_HEADER_Platform_Unix_Process + +#include "Platform/PlatformBase.h" +#include "Platform/Buffer.h" +#include "Platform/Functor.h" + +namespace TrueCrypt +{ + struct ProcessExecFunctor + { + virtual ~ProcessExecFunctor () { } + virtual void operator() (int argc, char *argv[]) = 0; + }; + + class Process + { + public: + Process (); + virtual ~Process (); + + static string Execute (const string &processName, const list &arguments, int timeOut = -1, ProcessExecFunctor *execFunctor = nullptr, const Buffer *inputData = nullptr); + + protected: + + private: + Process (const Process &); + Process &operator= (const Process &); + }; +} + +#endif // TC_HEADER_Platform_Unix_Process diff --git a/Platform/Unix/SyncEvent.cpp b/Platform/Unix/SyncEvent.cpp index 762cd6a..cb7aa0c 100644 --- a/Platform/Unix/SyncEvent.cpp +++ b/Platform/Unix/SyncEvent.cpp @@ -1,68 +1,68 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/Exception.h" -#include "Platform/SyncEvent.h" -#include "Platform/SystemException.h" - -namespace TrueCrypt -{ - SyncEvent::SyncEvent () - { - int status = pthread_cond_init (&SystemSyncEvent, nullptr); - if (status != 0) - throw SystemException (SRC_POS, status); - - Signaled = false; - Initialized = true; - } - - SyncEvent::~SyncEvent () - { -#ifdef DEBUG - int status = -#endif - pthread_cond_destroy (&SystemSyncEvent); - -#ifdef DEBUG - if (status != 0) - SystemLog::WriteException (SystemException (SRC_POS, status)); -#endif - - Initialized = false; - } - - void SyncEvent::Signal () - { - assert (Initialized); - - ScopeLock lock (EventMutex); - - Signaled = true; - - int status = pthread_cond_signal (&SystemSyncEvent); - if (status != 0) - throw SystemException (SRC_POS, status); - } - - void SyncEvent::Wait () - { - assert (Initialized); - - ScopeLock lock (EventMutex); - - while (!Signaled) - { - int status = pthread_cond_wait (&SystemSyncEvent, EventMutex.GetSystemHandle()); - if (status != 0) - throw SystemException (SRC_POS, status); - } - - Signaled = false; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/Exception.h" +#include "Platform/SyncEvent.h" +#include "Platform/SystemException.h" + +namespace TrueCrypt +{ + SyncEvent::SyncEvent () + { + int status = pthread_cond_init (&SystemSyncEvent, nullptr); + if (status != 0) + throw SystemException (SRC_POS, status); + + Signaled = false; + Initialized = true; + } + + SyncEvent::~SyncEvent () + { +#ifdef DEBUG + int status = +#endif + pthread_cond_destroy (&SystemSyncEvent); + +#ifdef DEBUG + if (status != 0) + SystemLog::WriteException (SystemException (SRC_POS, status)); +#endif + + Initialized = false; + } + + void SyncEvent::Signal () + { + assert (Initialized); + + ScopeLock lock (EventMutex); + + Signaled = true; + + int status = pthread_cond_signal (&SystemSyncEvent); + if (status != 0) + throw SystemException (SRC_POS, status); + } + + void SyncEvent::Wait () + { + assert (Initialized); + + ScopeLock lock (EventMutex); + + while (!Signaled) + { + int status = pthread_cond_wait (&SystemSyncEvent, EventMutex.GetSystemHandle()); + if (status != 0) + throw SystemException (SRC_POS, status); + } + + Signaled = false; + } +} diff --git a/Platform/Unix/System.h b/Platform/Unix/System.h index 78e3d50..2611d1c 100644 --- a/Platform/Unix/System.h +++ b/Platform/Unix/System.h @@ -1,12 +1,12 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_Unix_System -#define TC_HEADER_Platform_Unix_System - -#endif // TC_HEADER_Platform_Unix_System +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_Unix_System +#define TC_HEADER_Platform_Unix_System + +#endif // TC_HEADER_Platform_Unix_System diff --git a/Platform/Unix/SystemException.cpp b/Platform/Unix/SystemException.cpp index 2051182..26dc812 100644 --- a/Platform/Unix/SystemException.cpp +++ b/Platform/Unix/SystemException.cpp @@ -1,66 +1,66 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include "Platform/SerializerFactory.h" -#include "Platform/SystemException.h" -#include "Platform/StringConverter.h" - -namespace TrueCrypt -{ - SystemException::SystemException () - : ErrorCode (errno) - { - } - - SystemException::SystemException (const string &message) - : Exception (message), ErrorCode (errno) - { - } - - SystemException::SystemException (const string &message, const string &subject) - : Exception (message, StringConverter::ToWide (subject)), ErrorCode (errno) - { - } - - SystemException::SystemException (const string &message, const wstring &subject) - : Exception (message, subject), ErrorCode (errno) - { - } - - void SystemException::Deserialize (shared_ptr stream) - { - Exception::Deserialize (stream); - Serializer sr (stream); - sr.Deserialize ("ErrorCode", ErrorCode); - } - - bool SystemException::IsError () const - { - return ErrorCode != 0; - } - - void SystemException::Serialize (shared_ptr stream) const - { - Exception::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("ErrorCode", ErrorCode); - } - - wstring SystemException::SystemText () const - { - return StringConverter::ToWide (strerror ((int) ErrorCode)); - } - -#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -#undef TC_EXCEPTION_NODECL -#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SystemException); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include "Platform/SerializerFactory.h" +#include "Platform/SystemException.h" +#include "Platform/StringConverter.h" + +namespace TrueCrypt +{ + SystemException::SystemException () + : ErrorCode (errno) + { + } + + SystemException::SystemException (const string &message) + : Exception (message), ErrorCode (errno) + { + } + + SystemException::SystemException (const string &message, const string &subject) + : Exception (message, StringConverter::ToWide (subject)), ErrorCode (errno) + { + } + + SystemException::SystemException (const string &message, const wstring &subject) + : Exception (message, subject), ErrorCode (errno) + { + } + + void SystemException::Deserialize (shared_ptr stream) + { + Exception::Deserialize (stream); + Serializer sr (stream); + sr.Deserialize ("ErrorCode", ErrorCode); + } + + bool SystemException::IsError () const + { + return ErrorCode != 0; + } + + void SystemException::Serialize (shared_ptr stream) const + { + Exception::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("ErrorCode", ErrorCode); + } + + wstring SystemException::SystemText () const + { + return StringConverter::ToWide (strerror ((int) ErrorCode)); + } + +#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +#undef TC_EXCEPTION_NODECL +#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SystemException); +} diff --git a/Platform/Unix/SystemInfo.cpp b/Platform/Unix/SystemInfo.cpp index 7770ba0..df84f9c 100644 --- a/Platform/Unix/SystemInfo.cpp +++ b/Platform/Unix/SystemInfo.cpp @@ -1,55 +1,55 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/SystemException.h" -#include "Platform/SystemInfo.h" -#include - -namespace TrueCrypt -{ - wstring SystemInfo::GetPlatformName () - { -#ifdef TC_LINUX - return L"Linux"; -#elif defined (TC_MACOSX) - return L"Mac OS X"; -#elif defined (TC_FREEBSD) - return L"FreeBSD"; -#elif defined (TC_SOLARIS) - return L"Solaris"; -#else -# error GetPlatformName() undefined -#endif - - } - - vector SystemInfo::GetVersion () - { - struct utsname unameData; - throw_sys_if (uname (&unameData) == -1); - - vector versionStrings = StringConverter::Split (unameData.release, "."); - vector version; - - for (int i = 0; i < versionStrings.size(); ++i) - { - string s = versionStrings[i]; - - size_t p = s.find_first_not_of ("0123456789"); - if (p != string::npos) - s = s.substr (0, p); - - if (s.empty()) - break; - - version.push_back (StringConverter::ToUInt32 (s)); - } - - return version; - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/SystemException.h" +#include "Platform/SystemInfo.h" +#include + +namespace TrueCrypt +{ + wstring SystemInfo::GetPlatformName () + { +#ifdef TC_LINUX + return L"Linux"; +#elif defined (TC_MACOSX) + return L"Mac OS X"; +#elif defined (TC_FREEBSD) + return L"FreeBSD"; +#elif defined (TC_SOLARIS) + return L"Solaris"; +#else +# error GetPlatformName() undefined +#endif + + } + + vector SystemInfo::GetVersion () + { + struct utsname unameData; + throw_sys_if (uname (&unameData) == -1); + + vector versionStrings = StringConverter::Split (unameData.release, "."); + vector version; + + for (size_t i = 0; i < versionStrings.size(); ++i) + { + string s = versionStrings[i]; + + size_t p = s.find_first_not_of ("0123456789"); + if (p != string::npos) + s = s.substr (0, p); + + if (s.empty()) + break; + + version.push_back (StringConverter::ToUInt32 (s)); + } + + return version; + } +} diff --git a/Platform/Unix/SystemLog.cpp b/Platform/Unix/SystemLog.cpp index fde5f91..0bc7785 100644 --- a/Platform/Unix/SystemLog.cpp +++ b/Platform/Unix/SystemLog.cpp @@ -1,27 +1,27 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include "Platform/SystemLog.h" - -namespace TrueCrypt -{ - void SystemLog::WriteDebug (const string &debugMessage) - { - openlog ("truecrypt", LOG_PID, LOG_USER); - syslog (LOG_DEBUG, "%s", debugMessage.c_str()); - closelog(); - } - - void SystemLog::WriteError (const string &errorMessage) - { - openlog ("truecrypt", LOG_PID, LOG_USER); - syslog (LOG_ERR, "%s", errorMessage.c_str()); - closelog(); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include "Platform/SystemLog.h" + +namespace TrueCrypt +{ + void SystemLog::WriteDebug (const string &debugMessage) + { + openlog ("truecrypt", LOG_PID, LOG_USER); + syslog (LOG_DEBUG, "%s", debugMessage.c_str()); + closelog(); + } + + void SystemLog::WriteError (const string &errorMessage) + { + openlog ("truecrypt", LOG_PID, LOG_USER); + syslog (LOG_ERR, "%s", errorMessage.c_str()); + closelog(); + } +} diff --git a/Platform/Unix/Thread.cpp b/Platform/Unix/Thread.cpp index f0c9cb6..582a0b4 100644 --- a/Platform/Unix/Thread.cpp +++ b/Platform/Unix/Thread.cpp @@ -1,54 +1,54 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include -#include -#include "Platform/SystemException.h" -#include "Platform/Thread.h" -#include "Platform/SystemLog.h" - -namespace TrueCrypt -{ - void Thread::Join () const - { - int status = pthread_join (SystemHandle, nullptr); - if (status != 0) - throw SystemException (SRC_POS, status); - } - - void Thread::Start (ThreadProcPtr threadProc, void *parameter) - { - pthread_attr_t attr; - size_t stackSize = 0; - int status; - - status = pthread_attr_init (&attr); - if (status != 0) - throw SystemException (SRC_POS, status); - - status = pthread_attr_getstacksize (&attr, &stackSize); - if (status != 0) - throw SystemException (SRC_POS, status); - - if (stackSize < MinThreadStackSize) - { - status = pthread_attr_setstacksize (&attr, MinThreadStackSize); - if (status != 0) - throw SystemException (SRC_POS, status); - } - - status = pthread_create (&SystemHandle, nullptr, threadProc, parameter); - if (status != 0) - throw SystemException (SRC_POS, status); - } - - void Thread::Sleep (uint32 milliSeconds) - { - ::usleep (milliSeconds * 1000); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include +#include +#include "Platform/SystemException.h" +#include "Platform/Thread.h" +#include "Platform/SystemLog.h" + +namespace TrueCrypt +{ + void Thread::Join () const + { + int status = pthread_join (SystemHandle, nullptr); + if (status != 0) + throw SystemException (SRC_POS, status); + } + + void Thread::Start (ThreadProcPtr threadProc, void *parameter) + { + pthread_attr_t attr; + size_t stackSize = 0; + int status; + + status = pthread_attr_init (&attr); + if (status != 0) + throw SystemException (SRC_POS, status); + + status = pthread_attr_getstacksize (&attr, &stackSize); + if (status != 0) + throw SystemException (SRC_POS, status); + + if (stackSize < MinThreadStackSize) + { + status = pthread_attr_setstacksize (&attr, MinThreadStackSize); + if (status != 0) + throw SystemException (SRC_POS, status); + } + + status = pthread_create (&SystemHandle, nullptr, threadProc, parameter); + if (status != 0) + throw SystemException (SRC_POS, status); + } + + void Thread::Sleep (uint32 milliSeconds) + { + ::usleep (milliSeconds * 1000); + } +} diff --git a/Platform/Unix/Time.cpp b/Platform/Unix/Time.cpp index 96495fb..a5efd4e 100644 --- a/Platform/Unix/Time.cpp +++ b/Platform/Unix/Time.cpp @@ -1,23 +1,23 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/Time.h" -#include -#include - -namespace TrueCrypt -{ - uint64 Time::GetCurrent () - { - struct timeval tv; - gettimeofday (&tv, NULL); - - // Unix time => Windows file time - return ((uint64) tv.tv_sec + 134774LL * 24 * 3600) * 1000LL * 1000 * 10; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/Time.h" +#include +#include + +namespace TrueCrypt +{ + uint64 Time::GetCurrent () + { + struct timeval tv; + gettimeofday (&tv, NULL); + + // Unix time => Windows file time + return ((uint64) tv.tv_sec + 134774LL * 24 * 3600) * 1000LL * 1000 * 10; + } +} diff --git a/Platform/User.h b/Platform/User.h index 6b151b9..aa97814 100644 --- a/Platform/User.h +++ b/Platform/User.h @@ -1,32 +1,32 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Platform_User -#define TC_HEADER_Platform_User - -#include "PlatformBase.h" - -#ifdef TC_UNIX -#include -#include -#endif - -namespace TrueCrypt -{ - struct UserId - { - UserId () { } -#ifdef TC_UNIX - UserId (uid_t systemId) : SystemId (systemId) { } - - uid_t SystemId; -#endif - }; -} - -#endif // TC_HEADER_Platform_User +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Platform_User +#define TC_HEADER_Platform_User + +#include "PlatformBase.h" + +#ifdef TC_UNIX +#include +#include +#endif + +namespace TrueCrypt +{ + struct UserId + { + UserId () { } +#ifdef TC_UNIX + UserId (uid_t systemId) : SystemId (systemId) { } + + uid_t SystemId; +#endif + }; +} + +#endif // TC_HEADER_Platform_User diff --git a/Readme.txt b/Readme.txt index df1b62f..dbfe49d 100644 --- a/Readme.txt +++ b/Readme.txt @@ -1,190 +1,223 @@ -This archive contains the source code of TrueCrypt 6.2a. - - -Important -========= - -You may use the source code contained in this archive only if you accept and -agree to be bound by the license terms contained in the file 'License.txt', -which is included in this archive. Note that the license specifies, for -example, that a derived work must not be called 'TrueCrypt'. - - - -Contents -======== - -I. Windows - Requirements for Building TrueCrypt for Windows - Instructions for Building TrueCrypt for Windows - -II. Linux and Mac OS X - Requirements for Building TrueCrypt for Linux and Mac OS X - Instructions for Building TrueCrypt for Linux and Mac OS X - Requirements for Running TrueCrypt on Linux - Requirements for Running TrueCrypt on Mac OS X - -III. OpenSolaris and FreeBSD - -IV. Third-Party Developers (Contributors) - -V. Further Information - - - -I. Windows -========== - -Requirements for Building TrueCrypt for Windows: ------------------------------------------------- - -- Microsoft Visual C++ 2008 SP1 (Professional Edition or compatible) -- Microsoft Visual C++ 1.52 (available from MSDN Subscriber Downloads) -- Microsoft Windows Driver Kit for Windows Server 2008 (build 6001.18002) -- RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki) 2.20 - header files (available at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20) -- NASM 0.99 assembler -- Yasm assembler -- gzip compressor - -IMPORTANT: - -The 64-bit editions of Windows Vista and later versions of Windows, and in -some cases (e.g. playback of HD DVD content) also the 32-bit editions, do not -allow the TrueCrypt driver to run without an appropriate digital signature. -Therefore, all .sys files in official TrueCrypt binary packages are digitally -signed with the digital certificate of the TrueCrypt Foundation, which was -issued by a certification authority. At the end of each official .exe and -.sys file, there are embedded digital signatures and all related certificates -(i.e. all certificates in the relevant certification chain, such as the -certification authority certificates, CA-MS cross-certificate, and the -TrueCrypt Foundation certificate). Keep this in mind if you compile TrueCrypt -and compare your binaries with the official binaries. If your binaries are -unsigned, the sizes of the official binaries will usually be approximately -10 KB greater than sizes of your binaries (if you use a different version of -compiler or if you install a different or no service pack for Visual Studio, -there may be further differences). - - -Instructions for Building TrueCrypt for Windows: ------------------------------------------------- - -1) Create an environment variable 'MSVC16_ROOT' pointing to the installation - directory of MS Visual C++ 1.52. - -2) If you have installed the Windows Driver Development Kit in another - directory than '%SYSTEMDRIVE%\WinDDK', create an environment variable - 'WINDDK_ROOT' pointing to the DDK installation directory. - -3) Copy the PKCS #11 header files to a standard include path or create an - environment variable 'PKCS11_INC' pointing to the directory where - the PKCS #11 header files are installed. - -4) Open the 'TrueCrypt.sln' solution in Microsoft Visual Studio 2008. - -5) Select 'All' as the active solution configuration. - -6) Build the solution. - -7) If successful, there should be newly built TrueCrypt binaries in the - 'Release' folder. - - - -II. Linux and Mac OS X -====================== - -Requirements for Building TrueCrypt for Linux and Mac OS X: ------------------------------------------------------------ - -- GNU Make -- GNU C++ Compiler 4.0 or compatible -- Apple XCode (Mac OS X only) -- pkg-config -- wxWidgets 2.8 shared library and header files installed or - wxWidgets 2.8 library source code (available at http://www.wxwidgets.org) -- FUSE library and header files (available at http://fuse.sourceforge.net - and http://code.google.com/p/macfuse) -- RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki) 2.20 - header files (available at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20) - located in a standard include path or in a directory defined by the - environment variable 'PKCS11_INC'. - - -Instructions for Building TrueCrypt for Linux and Mac OS X: ------------------------------------------------------------ - -1) Change the current directory to the root of the TrueCrypt source code. - -2) If you have no wxWidgets shared library installed, run the following - command to configure the wxWidgets static library for TrueCrypt and to - build it: - - $ make WX_ROOT=/usr/src/wxWidgets wxbuild - - The variable WX_ROOT must point to the location of the source code of the - wxWidgets library. Output files will be placed in the './wxrelease/' - directory. - -3) To build TrueCrypt, run the following command: - - $ make - - or if you have no wxWidgets shared library installed: - - $ make WXSTATIC=1 - -4) If successful, the TrueCrypt executable should be located in the directory - 'Main'. - -By default, a universal executable supporting both graphical and text user -interface is built. To build a console-only executable, which requires no GUI -library, use the 'NOGUI' parameter: - - $ make NOGUI=1 WX_ROOT=/usr/src/wxWidgets wxbuild - $ make NOGUI=1 WXSTATIC=1 - - -Requirements for Running TrueCrypt on Linux: --------------------------------------------- - -- Kernel including FUSE, device mapper, and encryption modules -- FUSE library (available at http://fuse.sourceforge.net) -- device mapper tools (available at http://sources.redhat.com/dm) - - -Requirements for Running TrueCrypt on Mac OS X: ------------------------------------------------ - -- Mac OS X 10.4 or later -- MacFUSE 1.3 or later (available at http://code.google.com/p/macfuse) - - - -III. OpenSolaris and FreeBSD -============================ - -Support status for OpenSolaris: http://www.truecrypt.org/misc/opensolaris -Support status for FreeBSD: http://www.truecrypt.org/misc/freebsd - - - -IV. Third-Party Developers (Contributors) -========================================= - -If you intend to implement a feature, please contact us first to make sure: - -1) That the feature has not been implemented (we may have already implemented - it, but haven't released the code yet). -2) That the feature is acceptable. -3) Whether we need help of third-party developers with implementing the feature. - -Information on how to contact us can be found at: -http://www.truecrypt.org/contact - - - -V. Further Information -====================== - -http://www.truecrypt.org +This archive contains the source code of TrueCrypt 6.3. + + +Important +========= + +You may use the source code contained in this archive only if you accept and +agree to be bound by the license terms contained in the file 'License.txt', +which is included in this archive. Note that the license specifies, for +example, that a derived work must not be called 'TrueCrypt'. + + + +Contents +======== + +I. Windows + Requirements for Building TrueCrypt for Windows + Instructions for Building TrueCrypt for Windows + +II. Linux and Mac OS X + Requirements for Building TrueCrypt for Linux and Mac OS X + Instructions for Building TrueCrypt for Linux and Mac OS X + Requirements for Running TrueCrypt on Linux + Requirements for Running TrueCrypt on Mac OS X + +III. OpenSolaris and FreeBSD + +IV. Third-Party Developers (Contributors) + +V. Legal Information + +VI. Further Information + + + +I. Windows +========== + +Requirements for Building TrueCrypt for Windows: +------------------------------------------------ + +- Microsoft Visual C++ 2008 SP1 (Professional Edition or compatible) +- Microsoft Visual C++ 1.52 (available from MSDN Subscriber Downloads) +- Microsoft Windows SDK for Windows 7 +- Microsoft Windows Driver Kit 7.0.0 (build 7600.16385.0) +- RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki) 2.20 + header files (available at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20) +- NASM assembler (2.06 or compatible) +- gzip compressor + +IMPORTANT: + +The 64-bit editions of Windows Vista and later versions of Windows, and in +some cases (e.g. playback of HD DVD content) also the 32-bit editions, do not +allow the TrueCrypt driver to run without an appropriate digital signature. +Therefore, all .sys files in official TrueCrypt binary packages are digitally +signed with the digital certificate of the TrueCrypt Foundation, which was +issued by a certification authority. At the end of each official .exe and +.sys file, there are embedded digital signatures and all related certificates +(i.e. all certificates in the relevant certification chain, such as the +certification authority certificates, CA-MS cross-certificate, and the +TrueCrypt Foundation certificate). Keep this in mind if you compile TrueCrypt +and compare your binaries with the official binaries. If your binaries are +unsigned, the sizes of the official binaries will usually be approximately +10 KB greater than sizes of your binaries (if you use a different version of +compiler or if you install a different or no service pack for Visual Studio, +there may be further differences). + + +Instructions for Building TrueCrypt for Windows: +------------------------------------------------ + +1) Create an environment variable 'MSVC16_ROOT' pointing to the installation + directory of MS Visual C++ 1.52. + +2) If you have installed the Windows Driver Development Kit in another + directory than '%SYSTEMDRIVE%\WinDDK', create an environment variable + 'WINDDK_ROOT' pointing to the DDK installation directory. + +3) Copy the PKCS #11 header files to a standard include path or create an + environment variable 'PKCS11_INC' pointing to the directory where + the PKCS #11 header files are installed. + +4) Open the 'TrueCrypt.sln' solution in Microsoft Visual Studio 2008. + +5) Select 'All' as the active solution configuration. + +6) Build the solution. + +7) If successful, there should be newly built TrueCrypt binaries in the + 'Release' folder. + + + +II. Linux and Mac OS X +====================== + +Requirements for Building TrueCrypt for Linux and Mac OS X: +----------------------------------------------------------- + +- GNU Make +- GNU C++ Compiler 4.0 or compatible +- Apple Xcode (Mac OS X only) +- pkg-config +- wxWidgets 2.8 shared library and header files installed or + wxWidgets 2.8 library source code (available at http://www.wxwidgets.org) +- FUSE library and header files (available at http://fuse.sourceforge.net + and http://code.google.com/p/macfuse) +- RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki) 2.20 + header files (available at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20) + located in a standard include path or in a directory defined by the + environment variable 'PKCS11_INC'. + + +Instructions for Building TrueCrypt for Linux and Mac OS X: +----------------------------------------------------------- + +1) Change the current directory to the root of the TrueCrypt source code. + +2) If you have no wxWidgets shared library installed, run the following + command to configure the wxWidgets static library for TrueCrypt and to + build it: + + $ make WX_ROOT=/usr/src/wxWidgets wxbuild + + The variable WX_ROOT must point to the location of the source code of the + wxWidgets library. Output files will be placed in the './wxrelease/' + directory. + +3) To build TrueCrypt, run the following command: + + $ make + + or if you have no wxWidgets shared library installed: + + $ make WXSTATIC=1 + +4) If successful, the TrueCrypt executable should be located in the directory + 'Main'. + +By default, a universal executable supporting both graphical and text user +interface is built. To build a console-only executable, which requires no GUI +library, use the 'NOGUI' parameter: + + $ make NOGUI=1 WX_ROOT=/usr/src/wxWidgets wxbuild + $ make NOGUI=1 WXSTATIC=1 + + +Requirements for Running TrueCrypt on Linux: +-------------------------------------------- + +- Kernel including FUSE, device mapper, and encryption modules +- FUSE library (available at http://fuse.sourceforge.net) +- device mapper tools (available at http://sources.redhat.com/dm) + + +Requirements for Running TrueCrypt on Mac OS X: +----------------------------------------------- + +- Mac OS X 10.4 or later +- MacFUSE 1.3 or later (available at http://code.google.com/p/macfuse) + + + +III. OpenSolaris and FreeBSD +============================ + +Support status for OpenSolaris: http://www.truecrypt.org/misc/opensolaris +Support status for FreeBSD: http://www.truecrypt.org/misc/freebsd + + + +IV. Third-Party Developers (Contributors) +========================================= + +If you intend to implement a feature, please contact us first to make sure: + +1) That the feature has not been implemented (we may have already implemented + it, but haven't released the code yet). +2) That the feature is acceptable. +3) Whether we need help of third-party developers with implementing the feature. + +Information on how to contact us can be found at: +http://www.truecrypt.org/contact + + + +V. Legal Information +==================== + +Copyright Information +--------------------- + +This software as a whole: +Copyright (c) 2009 TrueCrypt Foundation. All rights reserved. + +Portions of this software: +Copyright (c) 2003-2009 TrueCrypt Foundation. All rights reserved. +Copyright (c) 1998-2000 Paul Le Roux. All rights reserved. +Copyright (c) 1998-2008 Brian Gladman, Worcester, UK. All rights reserved. +Copyright (c) 2002-2004 Mark Adler. All rights reserved. +For more information, please see the legal notices attached to parts of the +source code. + +Trademark Information +--------------------- + +TrueCrypt and the TrueCrypt logos are trademarks of the TrueCrypt Foundation. +Note: The goal is not to monetize the name or the product, but to protect +the reputation of TrueCrypt, and to prevent support issues and other kinds +of issues that might arise from the existence of similar products with +the same or similar name. Even though TrueCrypt is a trademark, TrueCrypt +is and will remain open-source and free software. + +Any other trademarks are the sole property of their respective owners. + + + +VI. Further Information +======================= + +http://www.truecrypt.org diff --git a/Release/Setup Files/License.txt b/Release/Setup Files/License.txt index 0bb3c64..52c0dd9 100644 --- a/Release/Setup Files/License.txt +++ b/Release/Setup Files/License.txt @@ -1,531 +1,533 @@ -TrueCrypt License Version 2.7 - -Software distributed under this license is distributed on an "AS -IS" BASIS WITHOUT WARRANTIES OF ANY KIND. THE AUTHORS AND -DISTRIBUTORS OF THE SOFTWARE DISCLAIM ANY LIABILITY. ANYONE WHO -USES, COPIES, MODIFIES, OR (RE)DISTRIBUTES ANY PART OF THE -SOFTWARE IS, BY SUCH ACTION(S), ACCEPTING AND AGREEING TO BE -BOUND BY ALL TERMS AND CONDITIONS OF THIS LICENSE. IF YOU DO NOT -ACCEPT THEM, DO NOT USE, COPY, MODIFY, NOR (RE)DISTRIBUTE THE -SOFTWARE, NOR ANY PART(S) THEREOF. - - -I. Definitions - -1. "This Product" means the work (including, but not limited to, -source code, graphics, texts, and accompanying files) made -available under and governed by this version of this license -("License"), as may be indicated by, but is not limited to, -copyright notice(s) attached to or included in the work. - -2. "You" means (and "Your" refers to) an individual or a legal -entity (e.g., a non-profit organization, commercial -organization, government agency, etc.) exercising permissions -granted by this License. - -3. "Modification" means (and "modify" refers to) any alteration -of This Product, including, but not limited to, addition to or -deletion from the substance or structure of This Product, -translation into another language, repackaging, alteration or -removal of any file included with This Product, and addition of -any new files to This Product. - -4. "Your Product" means This Product modified by You, or any -work You derive from (or base on) any part of This Product. In -addition, "Your Product" means any work in which You include any -(modified or unmodified) portion of This Product. However, if -the work in which you include it is an aggregate software -distribution (such as an operating system distribution or a -cover CD-ROM of a magazine) containing multiple separate -products, then the term "Your Product" includes only those -products (in the aggregate software distribution) that use, -include, or depend on a modified or unmodified version of This -Product (and the term "Your Product" does not include the whole -aggregate software distribution). For the purposes of this -License, a product suite consisting of two or more products is -considered a single product (operating system distributions and -cover media of magazines are not considered product suites). - -5. "Distribution" means (and "distribute" refers to), regardless -of means or methods, conveyance, transfer, providing, or making -available of This/Your Product or portions thereof to third -parties (including, but not limited to, making This/Your -Product, or portions thereof, available for download to third -parties, whether or not any third party has downloaded the -product, or any portion thereof, made available for download). - - - -II. Terms and Conditions for Use, Copying, and Distribution - -1. Provided that You comply with all applicable terms and -conditions of this License, You may make copies of This Product -(unmodified) and distribute copies of This Product (unmodified) -that are not included in another product forming Your Product -(except as permitted under Chapter III). Note: For terms and -conditions for copying and distribution of modified versions of -This Product, see Chapter III. - -2. Provided that You comply with all applicable terms and -conditions of this License, You may use This Product freely (see -also Chapter III) on any number of computers/systems for non- -commercial and/or commercial purposes. - - - -III. Terms and Conditions for Modification and Derivation of New -Products - -1. If all conditions specified in the following paragraphs in -this Chapter (III) are met (for exceptions, see Section III.2) -and if You comply with all other applicable terms and conditions -of this License, You may modify This Product (thus forming Your -Product), derive new works from This Product or portions thereof -(thus forming Your Product), include This Product or portions -thereof in another product (thus forming Your Product, unless -defined otherwise in Chapter I), and You may use (for non- -commercial and/or commercial purposes), copy, and/or distribute -Your Product. - - a. The name of Your Product (or of Your modified version of - This Product) must not contain the name TrueCrypt (for - example, the following names are not allowed: TrueCrypt, - TrueCrypt+, TrueCrypt Professional, iTrueCrypt, etc.) nor - any other names confusingly similar to the name TrueCrypt - (e.g., True-Crypt, True Crypt, TruKrypt, etc.) - - Note: TrueCrypt and the TrueCrypt logos are trademarks of - the TrueCrypt Foundation. The goal is not to monetize the - name or the product, but to protect the reputation of - TrueCrypt, and to prevent support issues and other kinds of - issues that might arise from the existence of similar - products with the same or similar name. Even though - TrueCrypt and the TrueCrypt logos are trademarks, TrueCrypt - is and will remain open-source and free software. - - All occurrences of the name TrueCrypt that could reasonably - be considered to identify Your Product must be removed from - Your Product and from any associated materials. Logo(s) - included in (or attached to) Your Product (and in/to - associated materials) must not incorporate and must not be - confusingly similar to any of the TrueCrypt logos (including - the non-textual logo consisting primarily of a key in - stylized form) or portion(s) thereof. All graphics contained - in This Product (logos, icons, etc.) must be removed from - Your Product (or from Your modified version of This Product) - and from any associated materials. - - b. The following phrases must be removed from Your Product - and from any associated materials, except the text of this - License: "A TrueCrypt Foundation Release", "Released by - TrueCrypt Foundation", "This is a TrueCrypt Foundation - release." - - c. Phrase "Based on TrueCrypt, freely available at - http://www.truecrypt.org/" must be displayed by Your Product - (if technically feasible) and contained in its - documentation. Alternatively, if This Product or its portion - You included in Your Product constitutes only a minor - portion of Your Product, phrase "Portions of this product - are based in part on TrueCrypt, freely available at - http://www.truecrypt.org/" may be displayed instead. In each - of the cases mentioned above in this paragraph, - "http://www.truecrypt.org/" must be a hyperlink (if - technically feasible) pointing to http://www.truecrypt.org/ - and You may freely choose the location within the user - interface (if there is any) of Your Product (e.g., an - "About" window, etc.) and the way in which Your Product will - display the respective phrase. - - Your Product (and any associated materials, e.g., the - documentation, the content of the official web site of Your - Product, etc.) must not present any Internet address - containing the domain name truecrypt.org (or any domain name - that forwards to the domain name truecrypt.org) in a manner - that might suggest that it is where information about Your - Product may be obtained or where bugs found in Your Product - may be reported or where support for Your Product may be - available or otherwise attempt to indicate that the domain - name truecrypt.org is associated with Your Product. - - d. The complete source code of Your Product must be freely - and publicly available (for exceptions, see Section III.2) - at least until You cease to distribute Your Product and - there must be a well-publicized means of obtaining the - source code free of charge or for a reasonable reproduction - fee (at least until You cease to distribute Your Product). - Examples of possible ways to meet these conditions: (i) You - include the source code with every copy of Your Product that - You make and distribute (see also below in this Subsection - III.1.d for conditions that licenses governing the source - code must meet) provided that You make the copies available - to the general public free of charge or for a reasonable - reproduction fee, or (ii) You include information (valid and - correct at least until You cease to distribute Your Product) - about where the source code can be freely obtained (e.g., an - Internet address, etc.) with every copy of Your Product that - You make and distribute (see also below in this Subsection - III.1.d for conditions that licenses governing the source - code must meet) provided that You make the copies available - to the general public free of charge or for a reasonable - reproduction fee. - - Portions of the source code of Your Product not contained in - This Product (e.g., portions added by You in creating Your - Product, whether created by You or by third parties) must be - available under license(s) that (however, see also - Subsection III.1.e) allow(s) anyone to modify and derive new - works from the portions of the source code that are not - contained in This Product and to use, copy, and redistribute - such modifications and/or derivative works. The license(s) - must be perpetual, non-exclusive, royalty-free, no-charge, - and worldwide, and must not invalidate, weaken, restrict, - interpret, amend, modify, interfere with or otherwise affect - any part, term, provision, or clause of this License. The - text(s) of the license(s) must be included with every copy - of Your Product that You make and distribute. The source - code must not be deliberately obfuscated, and it must not be - in an intermediate form (e.g., the output of a - preprocessor). Source code means the preferred form in which - a programmer would usually modify the program. - - Note: If you cannot comply with the above requirements, we - may grant an exception under certain conditions. You may - request an exception at: licensing@truecrypt.org - - e. You must not change the license terms of This Product in - any way (adding any new terms is considered changing the - license terms even if the original terms are retained), - which means, e.g., that no part of This Product may be put - under another license. You must keep intact all the legal - notices contained in the source code files. You must include - the following items with every copy of Your Product that You - make and distribute: a clear and conspicuous notice stating - that Your Product or portion(s) thereof is/are governed by - this version of the TrueCrypt License, a verbatim copy of - this version of the TrueCrypt License (as contained herein), - a clear and conspicuous notice containing information about - where the included copy of the License can be found, and an - appropriate copyright notice. - - -2. You are not obligated to comply with Subsection III.1.d if -Your Product is not distributed (i.e., Your Product is available -only to You). - -Note: If you cannot comply with Subsection III.1.d, we may grant -an exception under certain conditions. You may request an -exception at: licensing@truecrypt.org - - - -IV. Disclaimer of Liability, Disclaimer of Warranty, -Indemnification - -You expressly acknowledge and agree to the following: - -1. IN NO EVENT WILL ANY (CO)AUTHOR OF THIS PRODUCT, OR ANY -APPLICABLE COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY WHO MAY -COPY AND/OR (RE)DISTRIBUTE THIS PRODUCT OR PORTIONS THEREOF, AS -MAY BE PERMITTED HEREIN, BE LIABLE TO YOU OR TO ANY OTHER PARTY -FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, ANY DIRECT, -INDIRECT, GENERAL, SPECIAL, INCIDENTAL, PUNITIVE, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, CORRUPTION -OR LOSS OF DATA, ANY LOSSES SUSTAINED BY YOU OR THIRD PARTIES, A -FAILURE OF THIS PRODUCT TO OPERATE WITH ANY OTHER PRODUCT, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR BUSINESS -INTERRUPTION), WHETHER IN CONTRACT, STRICT LIABILITY, TORT -(INCLUDING NEGLIGENCE) OR OTHERWISE, ARISING OUT OF THE USE, -COPYING, MODIFICATION, OR (RE)DISTRIBUTION OF THIS PRODUCT (OR A -PORTION THEREOF) OR OF YOUR PRODUCT (OR A PORTION THEREOF), OR -INABILITY TO USE THIS PRODUCT (OR A PORTION THEREOF), EVEN IF -ANY (CO)AUTHOR, COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY -HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -2. THIS PRODUCT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY -KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT -LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE ENTIRE RISK AS TO -THE QUALITY AND PERFORMANCE OF THIS PRODUCT IS WITH YOU. SHOULD -THIS PRODUCT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL -NECESSARY SERVICING, REPAIR, OR CORRECTION. - -3. THIS PRODUCT MAY INCORPORATE IMPLEMENTATIONS OF CRYPTOGRAPHIC -ALGORITHMS THAT ARE REGULATED (E.G., SUBJECT TO EXPORT/IMPORT -CONTROL REGULATIONS) OR ILLEGAL IN SOME COUNTRIES. IT IS SOLELY -YOUR RESPONSIBILITY TO VERIFY THAT IT IS LEGAL TO IMPORT AND/OR -(RE)EXPORT AND/OR USE THIS PRODUCT (OR PORTIONS THEREOF) IN -COUNTRIES WHERE YOU INTEND TO USE IT AND/OR TO WHICH YOU INTEND -TO IMPORT IT AND/OR FROM WHICH YOU INTEND TO EXPORT IT, AND IT -IS SOLELY YOUR RESPONSIBILITY TO COMPLY WITH ANY APPLICABLE -REGULATIONS, RESTRICTIONS, AND LAWS. - -4. YOU SHALL INDEMNIFY, DEFEND AND HOLD ALL (CO)AUTHORS OF THIS -PRODUCT, AND APPLICABLE COPYRIGHT/TRADEMARK OWNERS, HARMLESS -FROM AND AGAINST ANY AND ALL LIABILITY, DAMAGES, LOSSES, -SETTLEMENTS, PENALTIES, FINES, COSTS, EXPENSES (INCLUDING -REASONABLE ATTORNEYS' FEES), DEMANDS, CAUSES OF ACTION, CLAIMS, -ACTIONS, PROCEEDINGS, AND SUITS, DIRECTLY RELATED TO OR ARISING -OUT OF YOUR USE, INABILITY TO USE, COPYING, (RE)DISTRIBUTION, -IMPORT AND/OR (RE)EXPORT OF THIS PRODUCT (OR PORTIONS THEREOF) -AND/OR YOUR BREACH OF ANY TERM OF THIS LICENSE. - - - -V. Trademarks - -This License does not grant permission to use trademarks -associated with (or applying to) This Product, except for fair -use as defined by applicable law and except for use expressly -permitted or required by this License. Any attempt otherwise to -use trademarks associated with (or applying to) This Product -automatically and immediately terminates Your rights under This -License and may constitute trademark infringement (which may be -prosecuted). - -TrueCrypt is a registered trademark of the TrueCrypt Foundation -registered with the World Intellectual Property Organization, an -agency of the United Nations, (international trademark -registration), in the U.S. Patent and Trademark Office, and in -the trademark offices of other countries. All TrueCrypt logos -(including the non-textual logo consisting primarily of a key in -stylized form) are trademarks of the TrueCrypt Foundation. - -Note: The goal is not to monetize the name or the product, but -to protect the reputation of TrueCrypt. TrueCrypt is and will -remain open-source and free software. - - - -VI. General Terms and Conditions, Miscellaneous Provisions - -1. ANYONE WHO USES AND/OR COPIES AND/OR MODIFIES AND/OR CREATES -DERIVATIVE WORKS OF AND/OR (RE)DISTRIBUTES THIS PRODUCT, OR ANY -PORTION(S) THEREOF, IS, BY SUCH ACTION(S), AGREEING TO BE BOUND -BY AND ACCEPTING ALL TERMS AND CONDITIONS OF THIS LICENSE (AND -THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS LICENSE). -IF YOU DO NOT ACCEPT (AND AGREE TO BE BOUND BY) ALL TERMS AND -CONDITIONS OF THIS LICENSE, DO NOT USE, COPY, MODIFY, CREATE -DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY -PORTION(S) THEREOF. - -2. YOU MAY NOT USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, -(RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) -THEREOF, EXCEPT AS EXPRESSLY PROVIDED IN THIS LICENSE (EVEN IF -APPLICABLE LAW GIVES YOU MORE RIGHTS). ANY ATTEMPT (EVEN IF -PERMITTED BY APPLICABLE LAW) OTHERWISE TO USE, MODIFY, COPY, -CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS -PRODUCT, OR PORTION(S) THEREOF, AUTOMATICALLY AND IMMEDIATELY -TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CONSTITUTE -COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). ANY -RESTRICTIONS CONTAINED IN THIS LICENSE ARE ALSO LIMITATIONS ON -THE SCOPE OF THIS LICENSE AND ALSO DEFINE THE SCOPE OF YOUR -RIGHTS UNDER THIS LICENSE. YOUR FAILURE TO COMPLY WITH THE TERMS -AND CONDITIONS OF THIS LICENSE OR FAILURE TO PERFORM ANY -APPLICABLE OBLIGATION IMPOSED BY THIS LICENSE AUTOMATICALLY AND -IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN -CAUSE OR BE CONSIDERED COPYRIGHT INFRINGEMENT (WHICH MAY BE -PROSECUTED). NOTHING IN THIS LICENSE SHALL IMPLY OR BE CONSTRUED -AS A PROMISE, OBLIGATION, OR COVENANT NOT TO SUE FOR COPYRIGHT -OR TRADEMARK INFRINGEMENT IF YOU DO NOT COMPLY WITH THE TERMS -AND CONDITIONS OF THIS LICENSE. - -3. This license does not constitute or imply a waiver of any -intellectual property rights except as may be otherwise -expressly provided in this License. This license does not -transfer, assign, or convey any intellectual property rights -(e.g., it does not transfer ownership of copyrights or -trademarks). - -4. Subject to the terms and conditions of this License, You may -allow a third party to use Your copy of This Product (or a copy -that You make and distribute, or Your Product) provided that the -third party overtly accepts and agrees to be bound by all terms -and conditions of this License and the third party is not -prohibited from using This Product (or portions thereof) by this -License (see, e.g., Section VI.7) or by applicable law. However, -You are not obligated to ensure that the third party accepts -(and agrees to be bound by all terms of) this License if You -distribute only the self-extracting package (containing This -Product) that does not allow the user to install (nor extract) -the files contained in the package until he or she accepts and -agrees to be bound by all terms and conditions of this License. - -5. Without specific prior written permission from the authors of -This Product (or from their common representative), You must not -use the name of This Product, the names of the authors of This -Product, or the names of the legal entities (or informal groups) -of which the authors were/are members/employees, to endorse or -promote Your Product or any work in which You include a modified -or unmodified version of This Product, or to endorse or promote -You or Your affiliates, or in a way that might suggest that Your -Product (or any work in which You include a modified or -unmodified version of This Product), You, or Your affiliates -is/are endorsed by one or more authors of This Product, or in a -way that might suggest that one or more authors of This Product -is/are affiliated with You (or Your affiliates) or directly -participated in the creation of Your Product or of any work in -which You include a modified or unmodified version of This -Product. - -6. IF YOU ARE NOT SURE WHETHER YOU UNDERSTAND ALL PARTS OF THIS -LICENSE OR IF YOU ARE NOT SURE WHETHER YOU CAN COMPLY WITH ALL -TERMS AND CONDITIONS OF THIS LICENSE, YOU MUST NOT USE, COPY, -MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS -PRODUCT, NOR ANY PORTION(S) OF IT. YOU SHOULD CONSULT WITH A -LAWYER. - -7. IF (IN RELEVANT CONTEXT) ANY PROVISION OF CHAPTER IV OF THIS -LICENSE IS UNENFORCEABLE, INVALID, OR PROHIBITED UNDER -APPLICABLE LAW IN YOUR JURISDICTION, YOU HAVE NO RIGHTS UNDER -THIS LICENSE AND YOU MUST NOT USE, COPY, MODIFY, CREATE -DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY -PORTION(S) THEREOF. - -8. Except as otherwise provided in this License, if any -provision of this License, or a portion thereof, is found to be -invalid or unenforceable under applicable law, it shall not -affect the validity or enforceability of the remainder of this -License, and such invalid or unenforceable provision shall be -construed to reflect the original intent of the provision and -shall be enforced to the maximum extent permitted by applicable -law so as to effect the original intent of the provision as -closely as possible. - -____________________________________________________________ - - -Third-Party Licenses - -This Product contains components that were created by third -parties and that are governed by third-party licenses, which are -contained hereinafter (separated by lines consisting of -underscores). Each of the third-party licenses applies only to -(portions of) the source code file(s) in which the third-party -license is contained or in which it is explicitly referenced, -and to compiled or otherwise processed forms of such source -code. None of the third-party licenses applies to This Product -as a whole, even when it uses terms such as "product", -"program", or any other equivalent terms/phrases. This Product -as a whole is governed by the TrueCrypt License (see above). -Some of the third-party components have been modified by the -authors of This Product. Unless otherwise stated, such -modifications and additions are governed by the TrueCrypt -License (see above). Note: Unless otherwise stated, graphics and -files that are not part of the source code are governed by the -TrueCrypt License. - -____________________________________________________________ - -License agreement for Encryption for the Masses. - -Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved. - -This product can be copied and distributed free of charge, -including source code. - -You may modify this product and source code, and distribute such -modifications, and you may derive new works based on this -product, provided that: - -1. Any product which is simply derived from this product cannot -be called E4M, or Encryption for the Masses. - -2. If you use any of the source code in your product, and your -product is distributed with source code, you must include this -notice with those portions of this source code that you use. - -Or, - -If your product is distributed in binary form only, you must -display on any packaging, and marketing materials which -reference your product, a notice which states: - -"This product uses components written by Paul Le Roux -" - -3. If you use any of the source code originally by Eric Young, -you must in addition follow his terms and conditions. - -4. Nothing requires that you accept this License, as you have -not signed it. However, nothing else grants you permission to -modify or distribute the product or its derivative works. - -These actions are prohibited by law if you do not accept this -License. - -5. If any of these license terms is found to be to broad in -scope, and declared invalid by any court or legal process, you -agree that all other terms shall not be so affected, and shall -remain valid and enforceable. - -6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE THERE -IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED -"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR -IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE -ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS -WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE -COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -7. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY -MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, -INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS -OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH -ANY OTHER PROGRAMS, EVEN IF SUCH HOLDER OR OTHER PARTY HAD -PREVIOUSLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -____________________________________________________________ - -Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. -All rights reserved. - -LICENSE TERMS - -The free distribution and use of this software is allowed (with -or without changes) provided that: - - 1. source code distributions include the above copyright - notice, this list of conditions and the following - disclaimer; - - 2. binary distributions include the above copyright notice, - this list of conditions and the following disclaimer in - their documentation; - - 3. the name of the copyright holder is not used to endorse - products built using this software without specific written - permission. - -DISCLAIMER - -This software is provided 'as is' with no explicit or implied -warranties in respect of its properties, including, but not -limited to, correctness and/or fitness for purpose. -____________________________________________________________ - -Copyright (C) 2002-2004 Mark Adler, all rights reserved -version 1.8, 9 Jan 2004 - -This software is provided 'as-is', without any express or -implied warranty. In no event will the author be held liable -for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you - must not claim that you wrote the original software. If you - use this software in a product, an acknowledgment in the - product documentation would be appreciated but is not - required. -2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source - distribution. -____________________________________________________________ +TrueCrypt License Version 2.8 + +Software distributed under this license is distributed on an "AS +IS" BASIS WITHOUT WARRANTIES OF ANY KIND. THE AUTHORS AND +DISTRIBUTORS OF THE SOFTWARE DISCLAIM ANY LIABILITY. ANYONE WHO +USES, COPIES, MODIFIES, OR (RE)DISTRIBUTES ANY PART OF THE +SOFTWARE IS, BY SUCH ACTION(S), ACCEPTING AND AGREEING TO BE +BOUND BY ALL TERMS AND CONDITIONS OF THIS LICENSE. IF YOU DO NOT +ACCEPT THEM, DO NOT USE, COPY, MODIFY, NOR (RE)DISTRIBUTE THE +SOFTWARE, NOR ANY PART(S) THEREOF. + + +I. Definitions + +1. "This Product" means the work (including, but not limited to, +source code, graphics, texts, and accompanying files) made +available under and governed by this version of this license +("License"), as may be indicated by, but is not limited to, +copyright notice(s) attached to or included in the work. + +2. "You" means (and "Your" refers to) an individual or a legal +entity (e.g., a non-profit organization, commercial +organization, government agency, etc.) exercising permissions +granted by this License. + +3. "Modification" means (and "modify" refers to) any alteration +of This Product, including, but not limited to, addition to or +deletion from the substance or structure of This Product, +translation into another language, repackaging, alteration or +removal of any file included with This Product, and addition of +any new files to This Product. + +4. "Your Product" means This Product modified by You, or any +work You derive from (or base on) any part of This Product. In +addition, "Your Product" means any work in which You include any +(modified or unmodified) portion of This Product. However, if +the work in which you include it is an aggregate software +distribution (such as an operating system distribution or a +cover CD-ROM of a magazine) containing multiple separate +products, then the term "Your Product" includes only those +products (in the aggregate software distribution) that use, +include, or depend on a modified or unmodified version of This +Product (and the term "Your Product" does not include the whole +aggregate software distribution). For the purposes of this +License, a product suite consisting of two or more products is +considered a single product (operating system distributions and +cover media of magazines are not considered product suites). + +5. "Distribution" means (and "distribute" refers to), regardless +of means or methods, conveyance, transfer, providing, or making +available of This/Your Product or portions thereof to third +parties (including, but not limited to, making This/Your +Product, or portions thereof, available for download to third +parties, whether or not any third party has downloaded the +product, or any portion thereof, made available for download). + + + +II. Terms and Conditions for Use, Copying, and Distribution + +1. Provided that You comply with all applicable terms and +conditions of this License, You may make copies of This Product +(unmodified) and distribute copies of This Product (unmodified) +that are not included in another product forming Your Product +(except as permitted under Chapter III). Note: For terms and +conditions for copying and distribution of modified versions of +This Product, see Chapter III. + +2. Provided that You comply with all applicable terms and +conditions of this License, You may use This Product freely (see +also Chapter III) on any number of computers/systems for non- +commercial and/or commercial purposes. + + + +III. Terms and Conditions for Modification and Derivation of New +Products + +1. If all conditions specified in the following paragraphs in +this Chapter (III) are met (for exceptions, see Section III.2) +and if You comply with all other applicable terms and conditions +of this License, You may modify This Product (thus forming Your +Product), derive new works from This Product or portions thereof +(thus forming Your Product), include This Product or portions +thereof in another product (thus forming Your Product, unless +defined otherwise in Chapter I), and You may use (for non- +commercial and/or commercial purposes), copy, and/or distribute +Your Product. + + a. The name of Your Product (or of Your modified version of + This Product) must not contain the name TrueCrypt (for + example, the following names are not allowed: TrueCrypt, + TrueCrypt+, TrueCrypt Professional, iTrueCrypt, etc.) nor + any other names confusingly similar to the name TrueCrypt + (e.g., True-Crypt, True Crypt, TruKrypt, etc.) + + Note: TrueCrypt and the TrueCrypt logos are trademarks of + the TrueCrypt Foundation. The goal is not to monetize the + name or the product, but to protect the reputation of + TrueCrypt, and to prevent support issues and other kinds of + issues that might arise from the existence of similar + products with the same or similar name. Even though + TrueCrypt and the TrueCrypt logos are trademarks, TrueCrypt + is and will remain open-source and free software. + + All occurrences of the name TrueCrypt that could reasonably + be considered to identify Your Product must be removed from + Your Product and from any associated materials. Logo(s) + included in (or attached to) Your Product (and in/to + associated materials) must not incorporate and must not be + confusingly similar to any of the TrueCrypt logos + (including, but not limited to, the non-textual logo + consisting primarily of a key in stylized form) or + portion(s) thereof. All graphics contained in This Product + (logos, icons, etc.) must be removed from Your Product (or + from Your modified version of This Product) and from any + associated materials. + + b. The following phrases must be removed from Your Product + and from any associated materials, except the text of this + License: "A TrueCrypt Foundation Release", "Released by + TrueCrypt Foundation", "This is a TrueCrypt Foundation + release." + + c. Phrase "Based on TrueCrypt, freely available at + http://www.truecrypt.org/" must be displayed by Your Product + (if technically feasible) and contained in its + documentation. Alternatively, if This Product or its portion + You included in Your Product constitutes only a minor + portion of Your Product, phrase "Portions of this product + are based in part on TrueCrypt, freely available at + http://www.truecrypt.org/" may be displayed instead. In each + of the cases mentioned above in this paragraph, + "http://www.truecrypt.org/" must be a hyperlink (if + technically feasible) pointing to http://www.truecrypt.org/ + and You may freely choose the location within the user + interface (if there is any) of Your Product (e.g., an + "About" window, etc.) and the way in which Your Product will + display the respective phrase. + + Your Product (and any associated materials, e.g., the + documentation, the content of the official web site of Your + Product, etc.) must not present any Internet address + containing the domain name truecrypt.org (or any domain name + that forwards to the domain name truecrypt.org) in a manner + that might suggest that it is where information about Your + Product may be obtained or where bugs found in Your Product + may be reported or where support for Your Product may be + available or otherwise attempt to indicate that the domain + name truecrypt.org is associated with Your Product. + + d. The complete source code of Your Product must be freely + and publicly available (for exceptions, see Section III.2) + at least until You cease to distribute Your Product and + there must be a well-publicized means of obtaining the + source code free of charge or for a reasonable reproduction + fee (at least until You cease to distribute Your Product). + Examples of possible ways to meet these conditions: (i) You + include the source code with every copy of Your Product that + You make and distribute (see also below in this Subsection + III.1.d for conditions that licenses governing the source + code must meet) provided that You make the copies available + to the general public free of charge or for a reasonable + reproduction fee, or (ii) You include information (valid and + correct at least until You cease to distribute Your Product) + about where the source code can be freely obtained (e.g., an + Internet address, etc.) with every copy of Your Product that + You make and distribute (see also below in this Subsection + III.1.d for conditions that licenses governing the source + code must meet) provided that You make the copies available + to the general public free of charge or for a reasonable + reproduction fee. + + Portions of the source code of Your Product not contained in + This Product (e.g., portions added by You in creating Your + Product, whether created by You or by third parties) must be + available under license(s) that (however, see also + Subsection III.1.e) allow(s) anyone to modify and derive new + works from the portions of the source code that are not + contained in This Product and to use, copy, and redistribute + such modifications and/or derivative works. The license(s) + must be perpetual, non-exclusive, royalty-free, no-charge, + and worldwide, and must not invalidate, weaken, restrict, + interpret, amend, modify, interfere with or otherwise affect + any part, term, provision, or clause of this License. The + text(s) of the license(s) must be included with every copy + of Your Product that You make and distribute. The source + code must not be deliberately obfuscated, and it must not be + in an intermediate form (e.g., the output of a + preprocessor). Source code means the preferred form in which + a programmer would usually modify the program. + + Note: If you cannot comply with the above requirements, we + may grant an exception under certain conditions. You may + request an exception at: licensing@truecrypt.org + + e. You must not change the license terms of This Product in + any way (adding any new terms is considered changing the + license terms even if the original terms are retained), + which means, e.g., that no part of This Product may be put + under another license. You must keep intact all the legal + notices contained in the source code files. You must include + the following items with every copy of Your Product that You + make and distribute: a clear and conspicuous notice stating + that Your Product or portion(s) thereof is/are governed by + this version of the TrueCrypt License, a verbatim copy of + this version of the TrueCrypt License (as contained herein), + a clear and conspicuous notice containing information about + where the included copy of the License can be found, and an + appropriate copyright notice. + + +2. You are not obligated to comply with Subsection III.1.d if +Your Product is not distributed (i.e., Your Product is available +only to You). + +Note: If you cannot comply with Subsection III.1.d, we may grant +an exception under certain conditions. You may request an +exception at: licensing@truecrypt.org + + + +IV. Disclaimer of Liability, Disclaimer of Warranty, +Indemnification + +You expressly acknowledge and agree to the following: + +1. IN NO EVENT WILL ANY (CO)AUTHOR OF THIS PRODUCT, OR ANY +APPLICABLE COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY WHO MAY +COPY AND/OR (RE)DISTRIBUTE THIS PRODUCT OR PORTIONS THEREOF, AS +MAY BE PERMITTED HEREIN, BE LIABLE TO YOU OR TO ANY OTHER PARTY +FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, ANY DIRECT, +INDIRECT, GENERAL, SPECIAL, INCIDENTAL, PUNITIVE, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, CORRUPTION +OR LOSS OF DATA, ANY LOSSES SUSTAINED BY YOU OR THIRD PARTIES, A +FAILURE OF THIS PRODUCT TO OPERATE WITH ANY OTHER PRODUCT, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR BUSINESS +INTERRUPTION), WHETHER IN CONTRACT, STRICT LIABILITY, TORT +(INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE) OR OTHERWISE, +ARISING OUT OF THE USE, COPYING, MODIFICATION, OR +(RE)DISTRIBUTION OF THIS PRODUCT (OR A PORTION THEREOF) OR OF +YOUR PRODUCT (OR A PORTION THEREOF), OR INABILITY TO USE THIS +PRODUCT (OR A PORTION THEREOF), EVEN IF ANY (CO)AUTHOR, +COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY HAS BEEN ADVISED +OF THE POSSIBILITY OF SUCH DAMAGES. + +2. THIS PRODUCT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY +KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT +LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE ENTIRE RISK AS TO +THE QUALITY AND PERFORMANCE OF THIS PRODUCT IS WITH YOU. SHOULD +THIS PRODUCT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL +NECESSARY SERVICING, REPAIR, OR CORRECTION. + +3. THIS PRODUCT MAY INCORPORATE IMPLEMENTATIONS OF CRYPTOGRAPHIC +ALGORITHMS THAT ARE REGULATED (E.G., SUBJECT TO EXPORT/IMPORT +CONTROL REGULATIONS) OR ILLEGAL IN SOME COUNTRIES. IT IS SOLELY +YOUR RESPONSIBILITY TO VERIFY THAT IT IS LEGAL TO IMPORT AND/OR +(RE)EXPORT AND/OR USE THIS PRODUCT (OR PORTIONS THEREOF) IN +COUNTRIES WHERE YOU INTEND TO USE IT AND/OR TO WHICH YOU INTEND +TO IMPORT IT AND/OR FROM WHICH YOU INTEND TO EXPORT IT, AND IT +IS SOLELY YOUR RESPONSIBILITY TO COMPLY WITH ANY APPLICABLE +REGULATIONS, RESTRICTIONS, AND LAWS. + +4. YOU SHALL INDEMNIFY, DEFEND AND HOLD ALL (CO)AUTHORS OF THIS +PRODUCT, AND APPLICABLE COPYRIGHT/TRADEMARK OWNERS, HARMLESS +FROM AND AGAINST ANY AND ALL LIABILITY, DAMAGES, LOSSES, +SETTLEMENTS, PENALTIES, FINES, COSTS, EXPENSES (INCLUDING +REASONABLE ATTORNEYS' FEES), DEMANDS, CAUSES OF ACTION, CLAIMS, +ACTIONS, PROCEEDINGS, AND SUITS, DIRECTLY RELATED TO OR ARISING +OUT OF YOUR USE, INABILITY TO USE, COPYING, (RE)DISTRIBUTION, +IMPORT AND/OR (RE)EXPORT OF THIS PRODUCT (OR PORTIONS THEREOF) +AND/OR YOUR BREACH OF ANY TERM OF THIS LICENSE. + + + +V. Trademarks + +This License does not grant permission to use trademarks +associated with (or applying to) This Product, except for fair +use as defined by applicable law and except for use expressly +permitted or required by this License. Any attempt otherwise to +use trademarks associated with (or applying to) This Product +automatically and immediately terminates Your rights under This +License and may constitute trademark infringement (which may be +prosecuted). + +TrueCrypt is a registered trademark of the TrueCrypt Foundation +registered with the World Intellectual Property Organization, an +agency of the United Nations, (international trademark +registration), in the U.S. Patent and Trademark Office, and in +the trademark offices of other countries. All TrueCrypt logos +(including the non-textual logo consisting primarily of a key in +stylized form) are trademarks of the TrueCrypt Foundation. + +Note: The goal is not to monetize the name or the product, but +to protect the reputation of TrueCrypt. TrueCrypt is and will +remain open-source and free software. + + + +VI. General Terms and Conditions, Miscellaneous Provisions + +1. ANYONE WHO USES AND/OR COPIES AND/OR MODIFIES AND/OR CREATES +DERIVATIVE WORKS OF AND/OR (RE)DISTRIBUTES THIS PRODUCT, OR ANY +PORTION(S) THEREOF, IS, BY SUCH ACTION(S), AGREEING TO BE BOUND +BY AND ACCEPTING ALL TERMS AND CONDITIONS OF THIS LICENSE (AND +THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS LICENSE). +IF YOU DO NOT ACCEPT (AND AGREE TO BE BOUND BY) ALL TERMS AND +CONDITIONS OF THIS LICENSE, DO NOT USE, COPY, MODIFY, CREATE +DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY +PORTION(S) THEREOF. + +2. YOU MAY NOT USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, +(RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) +THEREOF, EXCEPT AS EXPRESSLY PROVIDED IN THIS LICENSE (EVEN IF +APPLICABLE LAW GIVES YOU MORE RIGHTS). ANY ATTEMPT (EVEN IF +PERMITTED BY APPLICABLE LAW) OTHERWISE TO USE, MODIFY, COPY, +CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS +PRODUCT, OR PORTION(S) THEREOF, AUTOMATICALLY AND IMMEDIATELY +TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CONSTITUTE +COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). ANY CONDITIONS +AND RESTRICTIONS CONTAINED IN THIS LICENSE ARE ALSO LIMITATIONS +ON THE SCOPE OF THIS LICENSE AND ALSO DEFINE THE SCOPE OF YOUR +RIGHTS UNDER THIS LICENSE. YOUR FAILURE TO COMPLY WITH THE TERMS +AND CONDITIONS OF THIS LICENSE OR FAILURE TO PERFORM ANY +APPLICABLE OBLIGATION IMPOSED BY THIS LICENSE AUTOMATICALLY AND +IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN +CAUSE OR BE CONSIDERED COPYRIGHT INFRINGEMENT (WHICH MAY BE +PROSECUTED). NOTHING IN THIS LICENSE SHALL IMPLY OR BE CONSTRUED +AS A PROMISE, OBLIGATION, OR COVENANT NOT TO SUE FOR COPYRIGHT +OR TRADEMARK INFRINGEMENT IF YOU DO NOT COMPLY WITH THE TERMS +AND CONDITIONS OF THIS LICENSE. + +3. This license does not constitute or imply a waiver of any +intellectual property rights except as may be otherwise +expressly provided in this License. This license does not +transfer, assign, or convey any intellectual property rights +(e.g., it does not transfer ownership of copyrights or +trademarks). + +4. Subject to the terms and conditions of this License, You may +allow a third party to use Your copy of This Product (or a copy +that You make and distribute, or Your Product) provided that the +third party overtly accepts and agrees to be bound by all terms +and conditions of this License and the third party is not +prohibited from using This Product (or portions thereof) by this +License (see, e.g., Section VI.7) or by applicable law. However, +You are not obligated to ensure that the third party accepts +(and agrees to be bound by all terms of) this License if You +distribute only the self-extracting package (containing This +Product) that does not allow the user to install (nor extract) +the files contained in the package until he or she accepts and +agrees to be bound by all terms and conditions of this License. + +5. Without specific prior written permission from the authors of +This Product (or from their common representative), You must not +use the name of This Product, the names of the authors of This +Product, or the names of the legal entities (or informal groups) +of which the authors were/are members/employees, to endorse or +promote Your Product or any work in which You include a modified +or unmodified version of This Product, or to endorse or promote +You or Your affiliates, or in a way that might suggest that Your +Product (or any work in which You include a modified or +unmodified version of This Product), You, or Your affiliates +is/are endorsed by one or more authors of This Product, or in a +way that might suggest that one or more authors of This Product +is/are affiliated with You (or Your affiliates) or directly +participated in the creation of Your Product or of any work in +which You include a modified or unmodified version of This +Product. + +6. IF YOU ARE NOT SURE WHETHER YOU UNDERSTAND ALL PARTS OF THIS +LICENSE OR IF YOU ARE NOT SURE WHETHER YOU CAN COMPLY WITH ALL +TERMS AND CONDITIONS OF THIS LICENSE, YOU MUST NOT USE, COPY, +MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS +PRODUCT, NOR ANY PORTION(S) OF IT. YOU SHOULD CONSULT WITH A +LAWYER. + +7. IF (IN RELEVANT CONTEXT) ANY PROVISION OF CHAPTER IV OF THIS +LICENSE IS UNENFORCEABLE, INVALID, OR PROHIBITED UNDER +APPLICABLE LAW IN YOUR JURISDICTION, YOU HAVE NO RIGHTS UNDER +THIS LICENSE AND YOU MUST NOT USE, COPY, MODIFY, CREATE +DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY +PORTION(S) THEREOF. + +8. Except as otherwise provided in this License, if any +provision of this License, or a portion thereof, is found to be +invalid or unenforceable under applicable law, it shall not +affect the validity or enforceability of the remainder of this +License, and such invalid or unenforceable provision shall be +construed to reflect the original intent of the provision and +shall be enforced to the maximum extent permitted by applicable +law so as to effect the original intent of the provision as +closely as possible. + +____________________________________________________________ + + +Third-Party Licenses + +This Product contains components that were created by third +parties and that are governed by third-party licenses, which are +contained hereinafter (separated by lines consisting of +underscores). Each of the third-party licenses applies only to +(portions of) the source code file(s) in which the third-party +license is contained or in which it is explicitly referenced, +and to compiled or otherwise processed forms of such source +code. None of the third-party licenses applies to This Product +as a whole, even when it uses terms such as "product", +"program", or any other equivalent terms/phrases. This Product +as a whole is governed by the TrueCrypt License (see above). +Some of the third-party components have been modified by the +authors of This Product. Unless otherwise stated, such +modifications and additions are governed by the TrueCrypt +License (see above). Note: Unless otherwise stated, graphics and +files that are not part of the source code are governed by the +TrueCrypt License. + +____________________________________________________________ + +License agreement for Encryption for the Masses. + +Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved. + +This product can be copied and distributed free of charge, +including source code. + +You may modify this product and source code, and distribute such +modifications, and you may derive new works based on this +product, provided that: + +1. Any product which is simply derived from this product cannot +be called E4M, or Encryption for the Masses. + +2. If you use any of the source code in your product, and your +product is distributed with source code, you must include this +notice with those portions of this source code that you use. + +Or, + +If your product is distributed in binary form only, you must +display on any packaging, and marketing materials which +reference your product, a notice which states: + +"This product uses components written by Paul Le Roux +" + +3. If you use any of the source code originally by Eric Young, +you must in addition follow his terms and conditions. + +4. Nothing requires that you accept this License, as you have +not signed it. However, nothing else grants you permission to +modify or distribute the product or its derivative works. + +These actions are prohibited by law if you do not accept this +License. + +5. If any of these license terms is found to be to broad in +scope, and declared invalid by any court or legal process, you +agree that all other terms shall not be so affected, and shall +remain valid and enforceable. + +6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE THERE +IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR +IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS +WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE +COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +7. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY +MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE +LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS +OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH +ANY OTHER PROGRAMS, EVEN IF SUCH HOLDER OR OTHER PARTY HAD +PREVIOUSLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +____________________________________________________________ + +Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. +All rights reserved. + +LICENSE TERMS + +The free distribution and use of this software is allowed (with +or without changes) provided that: + + 1. source code distributions include the above copyright + notice, this list of conditions and the following + disclaimer; + + 2. binary distributions include the above copyright notice, + this list of conditions and the following disclaimer in + their documentation; + + 3. the name of the copyright holder is not used to endorse + products built using this software without specific written + permission. + +DISCLAIMER + +This software is provided 'as is' with no explicit or implied +warranties in respect of its properties, including, but not +limited to, correctness and/or fitness for purpose. +____________________________________________________________ + +Copyright (C) 2002-2004 Mark Adler, all rights reserved +version 1.8, 9 Jan 2004 + +This software is provided 'as-is', without any express or +implied warranty. In no event will the author be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you + use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not + required. +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source + distribution. +____________________________________________________________ diff --git a/Release/Setup Files/TrueCrypt User Guide.pdf b/Release/Setup Files/TrueCrypt User Guide.pdf index 2b0c6d67170d3ed63742b833f474e4535834e016..99b117fda11e2e65e5d9d34e41b9a099b54d824e 100644 GIT binary patch delta 629984 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

Cz)$%t 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 z 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

sK(}`%h?3yTEVXW(1dvu^1s=&7Wn0(2} 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

%m8gh?!L`j89qbLSJiadZOpm!tb_5j02? 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⩔fy8b95R*Jc)C%jXoyFpcMtnDy@G> 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

22Td@f*?JpS>Gj^#+L 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 delta 444257 zcmc$H37k*W`~TQVG-XR=9b0xYpM6FmJ6SVhry650j2ULe8s8hTMd{nn5E5mHkQOac zq+Nw1N{S+qL@H&;|5?tx_uTur+syC#di}q>`c5;(=Q-y&&+~rvb7stI{qwgWrC!f= z9h&-@`D5$-@Z+BSv1NR5331s&Mz&}X-#RNRJ1=*j--kcyH8{R)c2-_`R$gvgIMI(k ziBFj{COy7q>TvwO9QYIXgGBm+Ug^2n<8so{@mB-*la?)G)3b)c$HwB{%(i`NL=U4e?+yj#B70-K!MASWW$jHeBj?*IP5G7{z;F?iBoQm$&HDNNr5fr!FF@tk5XeYrA;FR^}ukEK6R1IKjN}sg@HuD zWnLjm1g((&Q(H@B<}T#{C#%k3Wi7 zLcb~w%^!*gmKgUA%g=SK2mwr9*|Ubk6XVHV0p6XK~>WeJ`^zVxz?toJ`cTSYcQoiIv4HQ57?z zE-(peUGTB8lc@Pv)<_%td={h)EVSA&^o&t5fr;Zl$TDJv#AK4FAq%tM`&9Tz2K)@! zJ4s?D;h}+>VK`ur3}6b8m6>7(l`2ydNxsZjNgI-xA^`-_izi8Ac(%a@AFC$wgvFB) zLe)h@pkF80=1}+tw;mVM2c$9+*fQE6MLr#DbpTBCe(Fiusf$C0#VJM&5@*O8V+AxH zHm{%eA{`_GH$sO7+^~)8m|^h$wp&BwQ({^J9x{65!Ux2G2BpHjQ{ktw2KflBWxE)p zAN7h0`h;fqSO|hFdy)_&vTj8iiNpk-LI{1+)h2GDx$`Fk!%=Kp7Zj<`;{<#4jC{*{TM0B%!~{d}B=L*Iz-; zAQDP4*epNWPtqFk-^@|wyv9)@D|&!QLbjm^Q(2Y_d`7WKj~Oj9N5|vq7?2BYJ5jur zqPtj$LJ>T1fb>M?0IgVtjey1h)_UfE45hwM0x&>9--xZYU&2y<6lkKZfq{XYq3^(2 zrkihao3x)7f=7yhNq#(PlLQG30~dqfHcYED2#yUJSqKgvti(1y>Y_o@#Mu+SXgSet z7+V-dDorkW0(g3|D!?Vx(E->|NaNySx&mucV@AOrf`Xc1O%fx&j>iHTY!@5=7?FHm zaik>F;;3Qq3Om9*fh3-+ZV}tZOa$4+J!QeaGEfYI-_3!A;%{WY-$6;wBH2*oA|+-5 z{EoHrW^iB{wp8>e0nL`_?CE6Vf+E;TwsJ%PuCKA;kVM@w>9WhNS(Z6uK{pmxj=(tWE{E#@K3`ExLf5M7D*Dx=fR_E5O`m1ZHHG zxUJzUNg>K!4qz?@2j=jN_Q7m1#aqHdR9MmFMFtX#(G1(Lcv>UbFX`kB$01Cng#UE7 z$#B|Z;2+c))D;YIR2@oIbYtPZ8Qp}aE`5-28qQYuBSAt-!x`J5BOkF6FP$;(R6k?- z-iVHpHSzN&n@^U{&tx^N!nj_*i(CZ`592%Z!4OPFNit1NgGr{@3IsXcm-opYh9^r|PffXD8ARy{RWFjC6FU zK!z7LWnT#H2A~13y(J8;yhD=b+~h43YJKuL2iC$a3&SgCU{- zUxhMpm<8r;D_;nFcKw^ho)e9#mE>Li}ZtGz+^8-V3CBEyhoA! z5sOr?V@;W1`yDJzJz0N?yi0bT9#4EJWAhS}Fu}&b;xiKSPO|3!1hZA&T zN??S+TcwXM=vaU^98KK^Stv=q*)*dAA^flQY53Rh9rlD62V1n;31+nNgDe zMQgI%4ZB`y#zBjn2rk&cVBr&N)i`-CpgU%!(6jA8e8f0APm?)iWGwx4Z-m3(?8+k%{6N(l`-I>*Tb zjIwT#sgByFqNa2Vg#9MM5*)G@r~95RN<$t9rU@}^+K#?c{nK`k@@WVDr_3A+^d!|V zSX!ag9)yggK?gx{PYgUz49qt`A4Fd=^I1ii`6h%zbeCh}tkX4D}~* zF}*;QI|B!r04MsA*%%7H1G#7nXAQyv-)ry)r)l7ij*r5q*)BiiQ#GEKEHqPv!q${| z%ZO3b$O1d{1T_^ZbVyX4L(o!Fj)mPt*-28kiemu~>{9AyM<#~P zPPoz<=o$@}sKp4sP=g9K4{U_lfMK2#<)1(#k$u2y>7KahN@p)t>&Y zycW%*(kg+zz8G~aVaNm-)*ipN51qx<{0}H}INNUHv zkxs4~2~P^s~@0=9{OMCDxgpo5clDJ(^FtR-+l z%3JUjq+RMh9-AtkmYk9e0Im=1kF})=vy(vvfNPh+P{}7vA*C+koV(S{Q#TO3teA1K zgyE-32cSSbpDhZR0a1YF6@|5|Bf$vsOeZEE0Qw6}V_K3jTcIYYIQ*%Mo=u@jmW}?8 znv^nppuFZNJRHXG&RJne`@iM{yf#f#|q&g0HDm3r48y0^cFKQCzS+WIX(t>Zm%$#K1Fk z@tV#PT*U=>b?{Z>VIrtVn12DEfD$wjQUv&3fCRT`!1n?pAcE)LqYpG-g>cHELJ|wC zpbyuuLW!ki*|VFmRzQT&uJcCN@GyS4DQ8=-dKi8|omof#^dj(?pl^%Pn@hD5h-M^- zAVS`j7=U&xSt2B`64Ieb1m&r*{se_eSPiS6afJ>`!VmVgBwvyN6Zn*wYY|ZkH?GOF zBw3BniNG`rI-w}G2)OC6^fqLE@F(mwf^$KrfvE>gbY+gB$l>x8t>-PsARiY@6!OV! z9Pqsm&qN`fi9$R%Vljvz$1t8u7RhwWmYV-VY_Vl1tB9~v*m5GDF|9{1l+Rn^r)HL= z1IB0t<7I*%1%Oo*Kulf>x5(fXkv@7`S_m3~ER11M!C*)+uuC#AYLA-gL`E;F4G_n~8djH7bD|%m2Iun9qAiOeIUmNg z8LP*_1LBi3nU?6KQE3N`3r(J9w$tzJ) zi3>siXUf&6fxZWu#$KbeQyrX5RZrRdWt>Ay!64jRX<*b7i5eCX_A7*`Rav2)*)8}9r;pmfxu7@0;DX*c2HvJ1 zkUrQTC$>upL;ry!CW2=g#Ob_=i@{2<>O#pWMYJYrL!2u1NhJ0l6eM==l|87CXy6R< zdCO{{W~ICci_rm!1v3UpVA!uQpU3u2jgpKm5GyF#9wA%W?y=VwEi!|rVb3~5l6)$0 zT7u4jbQm;(navqG(S^tX8oOzP?LN^kM&c^cirS)#NG=woP@6h6vNIp_ii+y#dtoe{ znxuueCiU~Mjatk639hk-!x`HLq1-;nTBvr+tD0xp3UC^&CFYT{sdZ1va!VRVpJ+Jk z#3W9_Y0J?<;t=%YNg4;?C}5PXafpIgy+@tm))%w{qu{4mgo$dQAsMucyOufkgQh(@NpA6Yl<*%8fRQAMO8v6YcrAW zYgG~PN!vTg0~GRTr|^|5zsv&>szd`tG!NLn)PaIG!7LD&V+2NM(lU4H_(Xrd01b^7 z?3w`INW956QNIz+i4+p6o{Gk&=l~d9$f3q29sWGiIWYtiY#Wyr(7a}eipbS#Iv-8f z5O`yf$QXJ1NCZ_zi5bB};VF9JJh4IMd{iv23!j2xeN56;`dIKuFI7?0HjD#hPSJ@u ztAxdQ>>I)MGE9gl+~AMVET^0>hTvQPX7Y^cs-v~;MXLJXK`nWlQf5q|i+}Fp@hsJT zX`;yTCeH=>7%+4X&MH(>(+XI{;94)p9~OAfvyj^}eWZFU1429fJi=hmM)u6T$OQXW z($>`pG1Pxa9j&yHsR(V<3RglK#kdq}qxeQ}M{@6c3@JKyx{?7I9y3mX|KOA@A~fb) z3`b6%Xw*l+b)k>);xKq)8={G4XY!YE@&=nKEz*@rtdAIL;59num<|u|hGd=#Ptp_5 z$)}fjt~;sBa)??)lZdX6q>p^os@O>t+}Kmc%@l2N8UNQ5rAW120VN+&r*lYQr;~ z01{Kt2tzHsHH8M)w6QskU|387(D%S6p^6DZvk(*hh8CvatZ-`>cu1BU2VeAf7$zC{ zNJy;UXov|g?LA<7qf`G|}LYf=Q4ZQlFU7)Q+1cMKCgfc1r^l#B)`r6q+=5AQOPb zCYg+wiD7HNGkUsO(?LSbz@9ehtE_9vz>paH3-MOrWQ7~T8-nji$Dx=ml#)k>;Cmqv z%wPDPB*GvG%r7TNP{d??B0KStBoH~3O;%izp+_Hi6N<F9`n zZRpEsk|7@%ZQ1Ku!p6oCpO{GEwTR=>q(m{$gf&FzBK>u*w1dWiluyXMpv_FtXd`K` z|3VYYVq>`$9YL)XL_U)M^yjeT3i6Cl8hH{@#S{B=3{-t(Mp_U$!ZP?uLTeB{#(-$y z6CoJK3kqKAkjU9cS@=+LnduBeT9<{%Qiv%n8|%!g;~bYye8U1NrYm}a{*RCI2_)B8 zxlVD(+|;I$pmeNx_(`_o-WJ;>(=Trq*DDK$ zE}w?U5T9WZDWYiG7XFJEnq%n@-w2Mds4z#&GfQ}##%TCQP1kmXv&P~kU&IkL6i?W~x^{t1ob{p-kO_VUHN9m}aYv&17yeyCcg3QGDZ#!|%gCHD=zH*9v`J3}TK z4pW9O5ymEoc*+G7(}t4l5@+Sj=)ReX{^BUaCYVu-g&`kR z7*87lN@}KOMbH9DP!=eU#D!RD;Vao^_)6s9D`^vaH9J;GBGB{182T`YG16#H+iZpI zz>)405DnAfKxK1ouA=(HSO*KG_=a^-)OQ8*SV1+&H6+Y%MpSKeF$@nI%^ZEY3?q8i zqfeZa#fn3a6*H)jm~0U%M()D-YYW2wnC}w8+aWr@>4KQb8YPVpscr~Q&A|}~H-u-& z;CtFML`U>H<38c03V01h{ALnCJZnchsmle-~|P&27%OFFZUIh%5FY&MufGLM`HA|=nWK+ zo}RGau2j5E2Gcoe+X2oVbu+9<$6fVYSTf;U7}vs5L$tzIuqCO1Y*ZG}LMceK%nn!G(7kHl_6-;L%~oJlKTnl*2!#AIdTM8nee+l!hw=8|s!fXKI(>u# z78>aL!Ovm(f}{!k?g9IUtvKk8h!cjrE2>+7Y|yVwF|a`&M$(F`Oc@SeC?hjIF2tLL zucV9yp%5G}DIs)rS->MLT@nguD#m>wV*xNKL#Rq?65NZZAjWb4~XlIOfPZ~+1t{Xultk6-% zg`!bgMD|`#ghM=8UZUaBxJL#-P+Y8>grJ8@)*Q80QsuDRIbxW>mJyoVWW(lAA*t8{ zV#r@bM9PgytQ^=m0KS9B0C?K088Jz8jVNJ^(b%Rya zd<`bvc!B9X(bsI)z7CbbK={?lhnU*IR0gwwWGF67Y*FMZ{*u&dHcTK9mn7!WB}2{T zUpjNzha(#p5E-r2I9w4I|N6KkP#8&p1{xbWlMjzsurXvfFtkH|3ELVo0Ll$wPWv)R z0+E*CP<7fA4_jr=M&2q45>qh4it*%G@}f>&1h6QF7&En z8*noM{C^xIwQ(W|FK9v!273uHJBYmz7~fd+Gy8~;x_VBXXw^w^3XDXC)ngKXl~i3l zdl_Q!!sSp^)@F&a#PU3ip|hNqrq+TDLkfxqhv0mjYiL>n5rIz2^G^uePTvIsI=;j zs#pDDrUJcwJT-Qb)!;Fz1xQvR+K&P2!ff?qNmi#GqM#1;Y>vNpXhYt#j&*80U_4#p z2#86N#S92~LMK&`#)*1`|Cf*HWgCO!Eo;9#W51ys-7ygsR z3a9fYv6We&yKW5oHbW6U!EmFcQ*Uwgi6%S(PNTGXD}-?j3Je-UgApVmEEwvsiL+pASC=TRmxD~N3_xl-oO)7x>y2hl3~bh+PB>vyuc^RSc7L6oMsE3#-M>s0Uvf zmGIF3fYZq`*Yusq8xx!p8)IB%%c4LHj(SAcua+x_UEQ&y3 zQ3MKegdiU-k5K76P*fkpiU+hM>2zru4m=QpAT~Upgo&`OVw@r+Lj_{*bM{T>)KL%f z=+Y{+Jlh$*$GU^2F7SI;!W{>iE8j8VlcrvvhNTuaMXuN&9N179%@=6*Ch(9Mql2EM z*o)B=3&vm#g=I}}M(t5l#opMh-yOCyS`=8E$8CKi?M53FRSWbbD54|V+rCL9<$dE1 zoCJb3&SKxVZPbHqYW7?V6lwmJVJ^W4veMX!ihZJVRxouwvGc z0r*NV1Yb!N;VVfxd^HCwaMqsD5Pp~bx-`1Wdvs!u84nGpA;X~%5{*Am{t1Y?;pz-5 zePJaT8yIk^A{i_=TCxmkn&M1gl=nuxOa`IxM^)CLJ71Vc&77-3pMYKv##XwGfZry? zm!$^x<-`;RDD?}&%}}bMnW`+*vY`l91%UwvjpHC@!?+BG&ywLQ0|usSVB8LVrUHm9 zgACHg3vgP!A}>D(sX;zdv0^?`?HKVwK1@&YLUH{=4VKJLO+dyI5hZ_|#m3BnpV3}J zc_kNaP8BV#QECl;!a8Xl(0Pk{ucLXDFn06Os_^ES<7oi0OFpfj=8=n%D46+nbE@#O*!>u~*j2UNXef*-q z9yg}MsVAl#QfrWlQE*I{@4@=uP?~cP;%UMI9nDmCjO{EaCYu|-Xz=h0E9Dmr9)7+g zGfwe~rUSnycKe0>@(cUr7v)&LD98G_9II(OD!kgL?nz3xqf_N2+%?PWaAYO}mzkMD zFc|VQ_F=}r{lQ5vRxT)3V^qWV4{)L?BHUtBb}-0ZlM)bNKl8tI0gX6!~U=rqH#)EZhWiUyK>Xh#^q$> zO=>zOCp|57TwX?YR<83(P;+&ToA(bZ!PnaYpr;X^6TeGo438_Qnp@%)#hI$^9;&J# zf>S?(nk2zVY7>cBfUT0?q}X`8DdHtP`dIt@!SUileSRq3hLb|BoL)Y(M7`Vni7-o< z6d%38f}O>SRqOzxS5{~02Lptpg3u}9kyH~GA<|*ailBOQfM?D}C!O5o!6j~WA*zF# z6Hx##&qN=|DN)T?NhwQge~1BS&W-?b1))$C2}E2^5m6y)SnAm56O@2~Y>+)oKa^(t z;BN(CZGgsJXf|-x327oj)d?{J<7ZTk3vn6cBbvL>N$QAyFaWBQAM#7X6jmA&gxD|uJtO!cNg(VF_O%kq)N)o)+K0X5 z0^|i?i#~8A0zP-h^FYrThY(_+AmfLS8hVjDon!v!A>~~5=nO-+M{pB-kP8nadIJP! zdK6hX@-zb7)95V%5P8{Sje@5q-*BA^QFMbHiK48cvj{0(Peh?Hba-lJd}c;kdRA__ zBmPnB=tvx!yRfDYqkL|}(f?{NA}_Dt`31!)D``;YN=?giChv?%evl{}+YbUH!km*= z`eT~M$4@BOw4hi;0w`ywAZOj40|3I<3mgEP3McvswSox~nx$ps<~Ga!XlM3Q-zbX)5<%G1BJu(gwbaRfb)ct z{;&c!Mqrp2hc+j}dAH7?BJLJ^Z76jBBzPw2vQK9e48TGAA*Mk8!Jp)M;Q2dKA*BE{ z@@9Dxoza)l3ikYkt)g4whhAXFP`K??7XJzPpQl!JmT^jDIMT-6qyYTuOLX0`fi}W! zZnM;J`PbT1RmSC}XJt%GN^CY}=rHGFcZNS7$eIrW0gyEq!SKqA{MxDYUHE{pEb~E) z2Sls4U$lDrMXR@8w0dI{OL<>zL5B08w44+tfXSrH6X!Xg)~*iX0t`4IX46wGe`4DT&g&pX+ix3_vv_p{&f10i ziC$%Zyb&Rk`Tw?Y!G1bq`!#?vkT*moFu@zz3T8~eHDoqR%YU&=H5Wd(LSPVH3<*LN z4PIv`3>!38z{)K4Zqv|ZS2@|+M z$T@=l>b8#jv8_7{cSI&>6hlP_?tFufr$iWhrAz^QMMdfr=NJ9xer{@p?-?-)Vjn72 zGYP&Ge~sf>_+I=q?s$Y4P8627Hw3;%#zVu%!N-f$hh#ZdNx>vh863WfU*}dU_?~~= z&z&#uJ%JH?C76M)f;=1;t(Kbs;PAxfaS0s07dXeIVfY?#4lc&`b1hT?ys+9&U``%} znTAx43^NreFG9?;*Ej?@$kK+u8HxBKgB6qKOMN}GQ0g~@-^Mq*xg2CjR9j@F>G&Ke zhk;i_SyT1qS{j@v6ZET;_1-s2$_1(aDOPcqP2v)mj45{{21LzLYe7rvU9zE7vNRR8 ztTY5^frt{VNR%xlS|lRszEIA+ag+pK4Hkxg`<)bk*aBw zh27K6owC+!Hy z3X%?i8WZX0P=!get0G8a%aX^Vc1|n;ze5Tj6_SQY2TOq#l~r}ufSw*nJBRClQ&yc)xcJ|iv_Z`H&3Sxs-cp%lF>`iPku-P^wCQjNy8MlmGh(h$cP4E>O8wz-SJHS;_PYi} z4MC3qk@lHgLPd}!yH|Kfkw!agP&5c87D>a6=vGIqKqVDc&wU!OQvC&Qw_TG5V83fn zYkanbNJrOancu)S>;x*bn32=rOd2dUk&ezY6KU>?0m=#iDHb)n={5N|_N0M>K`7-D z>5w&!a{Gq5X~jE+^H>Hw3vG4QNE*xok@iO=fqB>Db*ZH3;b>)?7f7L|ILBQFz#}8l z2{xn+Ql@WOaTPOXG(%4w>Iq01mS82}1I6VwLdx_zh`fKf#K$E1KaIjI`^pwc#@ET7N`YCry-L$^ZdSG9To+JMUUZIFth| z84e7Q5JkT_&qSIiD>7+mjKfO8k>OAqrCkT2q9&4XBWeB3V=K}`SrOd<(zu2lY3Oqz z(*CG)h6QPT(%hCbQC4CxZRcb@VAmMU5a|SKPrY< z{iR)3hC6_ng26`+I=vaq{LvLW3)1>SyRM|2U9%*(9~RSPwCe;LG&7vF{tB-fX-XnE z;wWaX6(ntuzNTG^i$V(RA4x+PHoAp3Ul3&&?y=NsBWeAST-RN@f|(D}`b0W}VAjge zwr8F~YyJkcl^;20f# zE_^ zr80{f9#kALBr&M7n%ZP7+)!!O!xBgWaS`Z0Cek4rNi&2T`m?;6kSo}sYem`xxq-A$ z?TC$P8+RRsdY6@@yk2wy7u@@i1CRhUkUH9^-`WQ=Qqv#6)i!Fq&ww<%(J9^vNPsl- zGZ5+Meg?uYBWe9%TUXLiSZx9lND4x7oJc2Fn+Xs;+12-&D8iRDbokU=Fx?x$R5N=c zumo$NHjvgIZ*|?ZjNCeD@`K15!OSxUvoI>+fwcZet1Ia!G`HfoYrMG> z86GmFOcW40CT&nI{Yg)^vnJDRPZ~4s*d2zXtx_fmJXRy!T7bTZXGn3G-@q~h6z_?2 z*gBR?lwPw#(g0E(8E%bcl7!<0u0+}yH2oSI5~0}n1%i7lfJIIc11IM`5Z|HO%kpOxG4IXTq3B3 zxRQ27vmn@GA|0{DQ6p*np-7;twU``Nr3~D8qktjZ26$Vgg$-q65s6Tjikr&w&4 zwDQd)Gz*BNAS}UJ%nW+1zfkBznkdtg+RnQcNx^_kQqZ_-{nbHN(gbFF=ap5c185cy zu35mwHIv`?L-XO;a_Ms+ie)YoX$ujDK2J-IV+VYZ9C71_NOU&@s29fTC}^+-FSPYn z^IUlzl@~O|AFyw11R~m6bBnRJMSj_?a6Gqk&y*}x%8@p-L?LZ|#JbiXKOR>o+LUjw zlyZfdF_1QTNJu+mcisjE&2t8aa~zhmku-E;UXQD=c$UWw&V-5@5~ z`eS9TJa=)^Ff%N2q*Ayms-fz0Yz8?mgpNhwnlaYK)G!CUum*#uY4I2Sf`sQTNpL+c z%{fSCo{K&&pGBV+zZPnwtv~tY#ⅇ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 z%0D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%0A& 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
KIz%7WWdcad>@ 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"\line \line 3. If you use any of the source code originally by Eric Young, you must in addition follow his terms and conditions.\line \line 4. Nothing requires that you accept this License, as yo -u have not signed it. However, nothing else grants you permission to modify or distribute the product or its derivative works.\line \line These actions are prohibited by law if you do not accept this License.\line \line 5. If any of these license terms is found to be to broad - in scope, and declared invalid by any court or legal process, you agree that all other terms shall not be so affected, and shall remain valid and enforceable.\line \line 6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE THERE IS NO WARRANTY FOR THE PROGRAM, -TO THE EXTENT PERMITTED BY APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICU -LAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\line \line 7. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED - TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INAB -ILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS, EVEN IF SUCH HOLDER OR OTHER PARTY HAD PREVIOU -SLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\line ____________________________________________________________\line \line Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.\line \line LICENSE TERMS\line \line The free distribution and use of this software is - allowed (with or without changes) provided that:} -\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 1.\tab}\ilvl0 \ltrpar\s3\cf0\ls1\aspalpha\li707\ri0\lin707\rin0\fi-283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 source code distributions include the above copyright notice, this list of conditions and the following disclaimer;} -\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 2.\tab}\ilvl0 \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation;} -\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\sa283\f3\fs16\f3\fs16\f3\fs16 3.\tab}\ilvl0 \ltrpar\s3\cf0\ls1\aspalpha\li707\ri0\lin707\rin0\fi-283\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 the name of the copyright holder is not used to endorse products built using this software without specific written permission. } -\par \pard\plain \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 DISCLAIMER\line \line This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose.\line ____________________________________________________________\line \line Copyrigh +ODS OR SERVICES, OR BUSINESS INTERRUPTION), WHETHER IN CONTRACT, STRICT LIABILITY, TORT (INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE) OR OTHERWISE, ARISING OUT OF THE USE, COPYING, MODIFICATION, OR (RE)DISTRIBUTION OF THIS PRODUCT (OR A PORTION THEREOF) OR O +F YOUR PRODUCT (OR A PORTION THEREOF), OR INABILITY TO USE THIS PRODUCT (OR A PORTION THEREOF), EVEN IF ANY (CO)AUTHOR, COPYRIGHT/TRADEMARK OWNER, OR ANY OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.}\line \line {\ltrch\hich\b\loch\b 2. THIS PRODUCT IS PROVIDED "AS IS" +WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THIS PRODUC +T IS WITH YOU. SHOULD THIS PRODUCT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.}\line \line {\ltrch\hich\b\loch\b 3}. THIS PRODUCT MAY INCORPORATE IMPLEMENTATIONS OF CRYPTOGRAPHIC ALGORITHMS THAT ARE REGULATED (E.G., SUBJECT TO EXPORT/IMPORT CONTR +OL REGULATIONS) OR ILLEGAL IN SOME COUNTRIES. IT IS SOLELY YOUR RESPONSIBILITY TO VERIFY THAT IT IS LEGAL TO IMPORT AND/OR (RE)EXPORT AND/OR USE THIS PRODUCT (OR PORTIONS THEREOF) IN COUNTRIES WHERE YOU INTEND TO USE IT AND/OR TO WHICH YOU INTEND TO IMPORT + IT AND/OR FROM WHICH YOU INTEND TO EXPORT IT, AND IT IS SOLELY YOUR RESPONSIBILITY TO COMPLY WITH ANY APPLICABLE REGULATIONS, RESTRICTIONS, AND LAWS.\line \line {\ltrch\hich\b\loch\b 4}. YOU SHALL INDEMNIFY, DEFEND AND HOLD ALL (CO)AUTHORS OF THIS PRODUCT, AND APPLICABLE COPYRIGHT/TRADEM +ARK OWNERS, HARMLESS FROM AND AGAINST ANY AND ALL LIABILITY, DAMAGES, LOSSES, SETTLEMENTS, PENALTIES, FINES, COSTS, EXPENSES (INCLUDING REASONABLE ATTORNEYS' FEES), DEMANDS, CAUSES OF ACTION, CLAIMS, ACTIONS, PROCEEDINGS, AND SUITS, DIRECTLY RELATED TO OR +ARISING OUT OF YOUR USE, INABILITY TO USE, COPYING, (RE)DISTRIBUTION, IMPORT AND/OR (RE)EXPORT OF THIS PRODUCT (OR PORTIONS THEREOF) AND/OR YOUR BREACH OF ANY TERM OF THIS LICENSE.\line \line \line \line {\ltrch\hich\b\loch\b V. Trademarks}\line \line This License does not grant permission to use trademarks +associated with (or applying to) This Product, except for fair use as defined by applicable law and except for use expressly permitted or required by this License. Any attempt otherwise to use trademarks associated with (or applying to) This Product automa +tically and immediately terminates Your rights under This License and may constitute trademark infringement (which may be prosecuted).\line \line TrueCrypt is a registered trademark of the TrueCrypt Foundation registered with the World Intellectual Property Organiza +tion, an agency of the United Nations, (international trademark registration), in the U.S. Patent and Trademark Office, and in the trademark offices of other countries. All TrueCrypt logos (including the non-textual logo consisting primarily of a key in st +ylized form) are trademarks of the TrueCrypt Foundation.\line \line Note: The goal is not to monetize the name or the product, but to protect the reputation of TrueCrypt. TrueCrypt is and will remain open-source and free software.\line \line \line \line {\ltrch\hich\b\loch\b VI. General Terms and Conditions +, Miscellaneous Provisions}\line \line {\ltrch\hich\b\loch\b 1}. ANYONE WHO USES AND/OR COPIES AND/OR MODIFIES AND/OR CREATES DERIVATIVE WORKS OF AND/OR (RE)DISTRIBUTES THIS PRODUCT, OR ANY PORTION(S) THEREOF, IS, BY SUCH ACTION(S), AGREEING TO BE BOUND BY AND ACCEPTING ALL TERMS AND CONDI +TIONS OF THIS LICENSE (AND THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS LICENSE). IF YOU DO NOT ACCEPT (AND AGREE TO BE BOUND BY) ALL TERMS AND CONDITIONS OF THIS LICENSE, DO NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE T +HIS PRODUCT, NOR ANY PORTION(S) THEREOF.\line \line {\ltrch\hich\b\loch\b 2}. YOU MAY NOT USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) THEREOF, EXCEPT AS EXPRESSLY PROVIDED IN THIS LICENSE (EVEN IF APPLICABLE LAW GIVES YOU MORE R +IGHTS). ANY ATTEMPT (EVEN IF PERMITTED BY APPLICABLE LAW) OTHERWISE TO USE, MODIFY, COPY, CREATE DERIVATIVE WORKS OF, (RE)DISTRIBUTE, OR SUBLICENSE THIS PRODUCT, OR PORTION(S) THEREOF, AUTOMATICALLY AND IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE + AND CAN CONSTITUTE COPYRIGHT INFRINGEMENT (WHICH MAY BE PROSECUTED). ANY CONDITIONS AND RESTRICTIONS CONTAINED IN THIS LICENSE ARE ALSO LIMITATIONS ON THE SCOPE OF THIS LICENSE AND ALSO DEFINE THE SCOPE OF YOUR RIGHTS UNDER THIS LICENSE. YOUR FAILURE TO C +OMPLY WITH THE TERMS AND CONDITIONS OF THIS LICENSE OR FAILURE TO PERFORM ANY APPLICABLE OBLIGATION IMPOSED BY THIS LICENSE AUTOMATICALLY AND IMMEDIATELY TERMINATES YOUR RIGHTS UNDER THIS LICENSE AND CAN CAUSE OR BE CONSIDERED COPYRIGHT INFRINGEMENT (WHICH + MAY BE PROSECUTED). NOTHING IN THIS LICENSE SHALL IMPLY OR BE CONSTRUED AS A PROMISE, OBLIGATION, OR COVENANT NOT TO SUE FOR COPYRIGHT OR TRADEMARK INFRINGEMENT IF YOU DO NOT COMPLY WITH THE TERMS AND CONDITIONS OF THIS LICENSE.\line \line {\ltrch\hich\b\loch\b 3}. This license does not +constitute or imply a waiver of any intellectual property rights except as may be otherwise expressly provided in this License. This license does not transfer, assign, or convey any intellectual property rights (e.g., it does not transfer ownership of copy +rights or trademarks).\line \line {\ltrch\hich\b\loch\b 4}. Subject to the terms and conditions of this License, You may allow a third party to use Your copy of This Product (or a copy that You make and distribute, or Your Product) provided that the third party overtly accepts and agrees +to be bound by all terms and conditions of this License and the third party is not prohibited from using This Product (or portions thereof) by this License (see, e.g., Section VI.7) or by applicable law. However, You are not obligated to ensure that the th +ird party accepts (and agrees to be bound by all terms of) this License if You distribute only the self-extracting package (containing This Product) that does not allow the user to install (nor extract) the files contained in the package until he or she ac +cepts and agrees to be bound by all terms and conditions of this License.\line \line {\ltrch\hich\b\loch\b 5}. Without specific prior written permission from the authors of This Product (or from their common representative), You must not use the name of This Product, the names of the auth +ors of This Product, or the names of the legal entities (or informal groups) of which the authors were/are members/employees, to endorse or promote Your Product or any work in which You include a modified or unmodified version of This Product, or to endors +e or promote You or Your affiliates, or in a way that might suggest that Your Product (or any work in which You include a modified or unmodified version of This Product), You, or Your affiliates is/are endorsed by one or more authors of This Product, or in + a way that might suggest that one or more authors of This Product is/are affiliated with You (or Your affiliates) or directly participated in the creation of Your Product or of any work in which You include a modified or unmodified version of This Product +.\line \line {\ltrch\hich\b\loch\b 6}. {\ltrch\hich\b\loch\b IF YOU ARE NOT SURE WHETHER YOU UNDERSTAND ALL PARTS OF THIS LICENSE OR IF YOU ARE NOT SURE WHETHER YOU CAN COMPLY WITH ALL TERMS AND CONDITIONS OF THIS LICENSE, YOU MUST NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PROD +UCT, NOR ANY PORTION(S) OF IT. YOU SHOULD CONSULT WITH A LAWYER.}\line \line {\ltrch\hich\b\loch\b 7}. IF (IN RELEVANT CONTEXT) ANY PROVISION OF CHAPTER IV OF THIS LICENSE IS UNENFORCEABLE, INVALID, OR PROHIBITED UNDER APPLICABLE LAW IN YOUR JURISDICTION, YOU HAVE NO RIGHTS UNDER THIS LICE +NSE AND YOU MUST NOT USE, COPY, MODIFY, CREATE DERIVATIVE WORKS OF, NOR (RE)DISTRIBUTE THIS PRODUCT, NOR ANY PORTION(S) THEREOF.\line \line {\ltrch\hich\b\loch\b 8}. Except as otherwise provided in this License, if any provision of this License, or a portion thereof, is found to be invali +d or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of this License, and such invalid or unenforceable provision shall be construed to reflect the original intent of the provision and shall be enforc +ed to the maximum extent permitted by applicable law so as to effect the original intent of the provision as closely as possible.\line \line ____________________________________________________________\line \line \line {\ltrch\hich\b\loch\b Third-Party Licenses}\line \line This Product contains components that we +re created by third parties and that are governed by third-party licenses, which are contained hereinafter (separated by lines consisting of underscores). Each of the third-party licenses applies only to (portions of) the source code file(s) in which the t +hird-party license is contained or in which it is explicitly referenced, and to compiled or otherwise processed forms of such source code. {\ltrch\hich\b\loch\b None of the third-party licenses applies to This Product as a whole, even when it uses terms such as "product", "prog +ram", or any other equivalent terms/phrases. This Product as a whole is governed by the TrueCrypt License (see above).} Some of the third-party components have been modified by the authors of This Product. Unless otherwise stated, such modifications and add +itions are governed by the TrueCrypt License (see above). Note: Unless otherwise stated, graphics and files that are not part of the source code are governed by the TrueCrypt License.\line \line ____________________________________________________________\line \line \line License +agreement for Encryption for the Masses.\line \line Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\line \line This product can be copied and distributed free of charge, including source code.\line \line You may modify this product and source code, and distribute such modifi +cations, and you may derive new works based on this product, provided that:\line \line 1. Any product which is simply derived from this product cannot be called E4M, or Encryption for the Masses.\line \line 2. If you use any of the source code in your product, and your produc +t is distributed with source code, you must include this notice with those portions of this source code that you use.\line \line Or,\line \line If your product is distributed in binary form only, you must display on any packaging, and marketing materials which reference your +product, a notice which states:\line \line "This product uses components written by Paul Le Roux "\line \line 3. If you use any of the source code originally by Eric Young, you must in addition follow his terms and conditions.\line \line 4. Nothing requires + that you accept this License, as you have not signed it. However, nothing else grants you permission to modify or distribute the product or its derivative works.\line \line These actions are prohibited by law if you do not accept this License.\line \line 5. If any of these l +icense terms is found to be to broad in scope, and declared invalid by any court or legal process, you agree that all other terms shall not be so affected, and shall remain valid and enforceable.\line \line 6. THIS PROGRAM IS DISTRIBUTED FREE OF CHARGE, THEREFORE TH +ERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. UNLESS OTHERWISE STATED THE PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCH +ANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\line \line 7. IN NO EVENT UNLESS +REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DA +MAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM, INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS, EVEN IF SU +CH HOLDER OR OTHER PARTY HAD PREVIOUSLY BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\line ____________________________________________________________\line \line Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.\line \line LICENSE TERMS\line \line The free dist +ribution and use of this software is allowed (with or without changes) provided that:} +\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 1.\tab}\ilvl0 \ltrpar\s3\cf0\ls1\aspalpha\li707\ri0\lin707\rin0\fi-283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 source code distributions include the above copyright notice, this list of conditions and the following disclaimer;} +\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 2.\tab}\ilvl0 \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation;} +\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\sa283\f3\fs16\f3\fs16\f3\fs16 3.\tab}\ilvl0 \ltrpar\s3\cf0\ls1\aspalpha\li707\ri0\lin707\rin0\fi-283\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 the name of the copyright holder is not used to endorse products built using this software without specific written permission. } +\par \pard\plain \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 DISCLAIMER\line \line This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose.\line ____________________________________________________________\line \line Copyrigh t (C) 2002-2004 Mark Adler, all rights reserved\line version 1.8, 9 Jan 2004\line \line This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software.\line \line Permissi on is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:} -\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 1.\tab}\ilvl0 \ltrpar\s3\cf0\ls0\aspalpha\li707\ri0\lin707\rin0\fi-283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. } -\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 2.\tab}\ilvl0 \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. } -\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\sa283\f3\fs16\f3\fs16\f3\fs16 3.\tab}\ilvl0 \ltrpar\s3\cf0\ls0\aspalpha\li707\ri0\lin707\rin0\fi-283\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 This notice may not be removed or altered from any source distribution. } -\par \pard\plain \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe1041\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 ____________________________________________________________} +\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 1.\tab}\ilvl0 \ltrpar\s3\cf0\ls0\aspalpha\li707\ri0\lin707\rin0\fi-283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. } +\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\f3\fs16\f3\fs16\f3\fs16 2.\tab}\ilvl0 \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. } +\par \pard\plain {\listtext\pard\plain \li707\ri0\lin707\rin0\fi-283\sa283\f3\fs16\f3\fs16\f3\fs16 3.\tab}\ilvl0 \ltrpar\s3\cf0\ls0\aspalpha\li707\ri0\lin707\rin0\fi-283\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 This notice may not be removed or altered from any source distribution. } +\par \pard\plain \ltrpar\s3\cf0\aspalpha\sa283\ql\rtlch\af3\afs16\lang255\ltrch\dbch\af3\langfe255\hich\f3\fs16\lang1033\loch\f3\fs16\lang1033 {\rtlch \ltrch\loch\f3\fs16\lang1033\i0\b0 ____________________________________________________________} \par } \ No newline at end of file diff --git a/Volume/Cipher.cpp b/Volume/Cipher.cpp index 2c6e0d1..f497ce9 100644 --- a/Volume/Cipher.cpp +++ b/Volume/Cipher.cpp @@ -1,212 +1,212 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/Platform.h" -#include "Cipher.h" -#include "Crypto/Aes.h" -#include "Crypto/Blowfish.h" -#include "Crypto/Des.h" -#include "Crypto/Cast.h" -#include "Crypto/Serpent.h" -#include "Crypto/Twofish.h" - -namespace TrueCrypt -{ - Cipher::Cipher () : Initialized (false) - { - } - - Cipher::~Cipher () - { - } - - void Cipher::DecryptBlock (byte *data) const - { - if (!Initialized) - throw NotInitialized (SRC_POS); - - Decrypt (data); - } - - void Cipher::EncryptBlock (byte *data) const - { - if (!Initialized) - throw NotInitialized (SRC_POS); - - Encrypt (data); - } - - CipherList Cipher::GetAvailableCiphers () - { - CipherList l; - - l.push_back (shared_ptr (new CipherAES ())); - l.push_back (shared_ptr (new CipherSerpent ())); - l.push_back (shared_ptr (new CipherTwofish ())); - l.push_back (shared_ptr (new CipherBlowfish ())); - l.push_back (shared_ptr (new CipherCast5 ())); - l.push_back (shared_ptr (new CipherTripleDES ())); - - return l; - } - - void Cipher::SetKey (const ConstBufferPtr &key) - { - if (key.Size() != GetKeySize ()) - throw ParameterIncorrect (SRC_POS); - - if (!Initialized) - ScheduledKey.Allocate (GetScheduledKeySize ()); - - SetCipherKey (key); - Key.CopyFrom (key); - Initialized = true; - } - -#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -#undef TC_EXCEPTION_NODECL -#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (CipherException); - - - // AES - void CipherAES::Decrypt (byte *data) const - { - aes_decrypt (data, data, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx))); - } - - void CipherAES::Encrypt (byte *data) const - { - aes_encrypt (data, data, (aes_encrypt_ctx *) ScheduledKey.Ptr()); - } - - size_t CipherAES::GetScheduledKeySize () const - { - return sizeof(aes_encrypt_ctx) + sizeof(aes_decrypt_ctx); - } - - void CipherAES::SetCipherKey (const byte *key) - { - if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ScheduledKey.Ptr()) != EXIT_SUCCESS) - throw CipherInitError (SRC_POS); - - if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx))) != EXIT_SUCCESS) - throw CipherInitError (SRC_POS); - } - - - // Blowfish - void CipherBlowfish::Decrypt (byte *data) const - { - BlowfishEncryptLE (data, data, (BF_KEY *) ScheduledKey.Ptr(), 0); - } - - void CipherBlowfish::Encrypt (byte *data) const - { - BlowfishEncryptLE (data, data, (BF_KEY *) ScheduledKey.Ptr(), 1); - } - - size_t CipherBlowfish::GetScheduledKeySize () const - { - return sizeof (BF_KEY); - } - - void CipherBlowfish::SetCipherKey (const byte *key) - { - BlowfishSetKey ((BF_KEY *) ScheduledKey.Ptr(), static_cast (GetKeySize ()), (unsigned char *) key); - } - - - // CAST5 - void CipherCast5::Decrypt (byte *data) const - { - Cast5Decrypt (data, data, (CAST_KEY *) ScheduledKey.Ptr()); - } - - void CipherCast5::Encrypt (byte *data) const - { - Cast5Encrypt (data, data, (CAST_KEY *) ScheduledKey.Ptr()); - } - - size_t CipherCast5::GetScheduledKeySize () const - { - return sizeof (CAST_KEY); - } - - void CipherCast5::SetCipherKey (const byte *key) - { - Cast5SetKey ((CAST_KEY *) ScheduledKey.Ptr(), static_cast (GetKeySize ()), (unsigned char *) key); - } - - - // Serpent - void CipherSerpent::Decrypt (byte *data) const - { - serpent_decrypt (data, data, ScheduledKey); - } - - void CipherSerpent::Encrypt (byte *data) const - { - serpent_encrypt (data, data, ScheduledKey); - } - - size_t CipherSerpent::GetScheduledKeySize () const - { - return 140*4; - } - - void CipherSerpent::SetCipherKey (const byte *key) - { - serpent_set_key (key, static_cast (GetKeySize ()), ScheduledKey); - } - - - // Triple-DES - void CipherTripleDES::Decrypt (byte *data) const - { - TripleDesEncrypt (data, data, (TDES_KEY *) ScheduledKey.Ptr(), 0); - } - - void CipherTripleDES::Encrypt (byte *data) const - { - TripleDesEncrypt (data, data, (TDES_KEY *) ScheduledKey.Ptr(), 1); - } - - size_t CipherTripleDES::GetScheduledKeySize () const - { - return sizeof (TDES_KEY); - } - - void CipherTripleDES::SetCipherKey (const byte *key) - { - TripleDesSetKey (key, GetKeySize(), (TDES_KEY *) ScheduledKey.Ptr()); - } - - - // Twofish - void CipherTwofish::Decrypt (byte *data) const - { - twofish_decrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data); - } - - void CipherTwofish::Encrypt (byte *data) const - { - twofish_encrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data); - } - - size_t CipherTwofish::GetScheduledKeySize () const - { - return TWOFISH_KS; - } - - void CipherTwofish::SetCipherKey (const byte *key) - { - twofish_set_key ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *) key, static_cast (GetKeySize ()) * 8); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/Platform.h" +#include "Cipher.h" +#include "Crypto/Aes.h" +#include "Crypto/Blowfish.h" +#include "Crypto/Des.h" +#include "Crypto/Cast.h" +#include "Crypto/Serpent.h" +#include "Crypto/Twofish.h" + +namespace TrueCrypt +{ + Cipher::Cipher () : Initialized (false) + { + } + + Cipher::~Cipher () + { + } + + void Cipher::DecryptBlock (byte *data) const + { + if (!Initialized) + throw NotInitialized (SRC_POS); + + Decrypt (data); + } + + void Cipher::EncryptBlock (byte *data) const + { + if (!Initialized) + throw NotInitialized (SRC_POS); + + Encrypt (data); + } + + CipherList Cipher::GetAvailableCiphers () + { + CipherList l; + + l.push_back (shared_ptr (new CipherAES ())); + l.push_back (shared_ptr (new CipherSerpent ())); + l.push_back (shared_ptr (new CipherTwofish ())); + l.push_back (shared_ptr (new CipherBlowfish ())); + l.push_back (shared_ptr (new CipherCast5 ())); + l.push_back (shared_ptr (new CipherTripleDES ())); + + return l; + } + + void Cipher::SetKey (const ConstBufferPtr &key) + { + if (key.Size() != GetKeySize ()) + throw ParameterIncorrect (SRC_POS); + + if (!Initialized) + ScheduledKey.Allocate (GetScheduledKeySize ()); + + SetCipherKey (key); + Key.CopyFrom (key); + Initialized = true; + } + +#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +#undef TC_EXCEPTION_NODECL +#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (CipherException); + + + // AES + void CipherAES::Decrypt (byte *data) const + { + aes_decrypt (data, data, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx))); + } + + void CipherAES::Encrypt (byte *data) const + { + aes_encrypt (data, data, (aes_encrypt_ctx *) ScheduledKey.Ptr()); + } + + size_t CipherAES::GetScheduledKeySize () const + { + return sizeof(aes_encrypt_ctx) + sizeof(aes_decrypt_ctx); + } + + void CipherAES::SetCipherKey (const byte *key) + { + if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ScheduledKey.Ptr()) != EXIT_SUCCESS) + throw CipherInitError (SRC_POS); + + if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx))) != EXIT_SUCCESS) + throw CipherInitError (SRC_POS); + } + + + // Blowfish + void CipherBlowfish::Decrypt (byte *data) const + { + BlowfishEncryptLE (data, data, (BF_KEY *) ScheduledKey.Ptr(), 0); + } + + void CipherBlowfish::Encrypt (byte *data) const + { + BlowfishEncryptLE (data, data, (BF_KEY *) ScheduledKey.Ptr(), 1); + } + + size_t CipherBlowfish::GetScheduledKeySize () const + { + return sizeof (BF_KEY); + } + + void CipherBlowfish::SetCipherKey (const byte *key) + { + BlowfishSetKey ((BF_KEY *) ScheduledKey.Ptr(), static_cast (GetKeySize ()), (unsigned char *) key); + } + + + // CAST5 + void CipherCast5::Decrypt (byte *data) const + { + Cast5Decrypt (data, data, (CAST_KEY *) ScheduledKey.Ptr()); + } + + void CipherCast5::Encrypt (byte *data) const + { + Cast5Encrypt (data, data, (CAST_KEY *) ScheduledKey.Ptr()); + } + + size_t CipherCast5::GetScheduledKeySize () const + { + return sizeof (CAST_KEY); + } + + void CipherCast5::SetCipherKey (const byte *key) + { + Cast5SetKey ((CAST_KEY *) ScheduledKey.Ptr(), static_cast (GetKeySize ()), (unsigned char *) key); + } + + + // Serpent + void CipherSerpent::Decrypt (byte *data) const + { + serpent_decrypt (data, data, ScheduledKey); + } + + void CipherSerpent::Encrypt (byte *data) const + { + serpent_encrypt (data, data, ScheduledKey); + } + + size_t CipherSerpent::GetScheduledKeySize () const + { + return 140*4; + } + + void CipherSerpent::SetCipherKey (const byte *key) + { + serpent_set_key (key, static_cast (GetKeySize ()), ScheduledKey); + } + + + // Triple-DES + void CipherTripleDES::Decrypt (byte *data) const + { + TripleDesEncrypt (data, data, (TDES_KEY *) ScheduledKey.Ptr(), 0); + } + + void CipherTripleDES::Encrypt (byte *data) const + { + TripleDesEncrypt (data, data, (TDES_KEY *) ScheduledKey.Ptr(), 1); + } + + size_t CipherTripleDES::GetScheduledKeySize () const + { + return sizeof (TDES_KEY); + } + + void CipherTripleDES::SetCipherKey (const byte *key) + { + TripleDesSetKey (key, GetKeySize(), (TDES_KEY *) ScheduledKey.Ptr()); + } + + + // Twofish + void CipherTwofish::Decrypt (byte *data) const + { + twofish_decrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data); + } + + void CipherTwofish::Encrypt (byte *data) const + { + twofish_encrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data); + } + + size_t CipherTwofish::GetScheduledKeySize () const + { + return TWOFISH_KS; + } + + void CipherTwofish::SetCipherKey (const byte *key) + { + twofish_set_key ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *) key, static_cast (GetKeySize ()) * 8); + } +} diff --git a/Volume/Cipher.h b/Volume/Cipher.h index 700c509..ca226e2 100644 --- a/Volume/Cipher.h +++ b/Volume/Cipher.h @@ -1,108 +1,108 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_Ciphers -#define TC_HEADER_Encryption_Ciphers - -#include "Platform/Platform.h" - - -namespace TrueCrypt -{ - class Cipher; - typedef vector < shared_ptr > CipherList; - - class Cipher - { - public: - virtual ~Cipher (); - - virtual void DecryptBlock (byte *data) const; - virtual void EncryptBlock (byte *data) const; - static CipherList GetAvailableCiphers (); - virtual size_t GetBlockSize () const = 0; - virtual const SecureBuffer &GetKey () const { return Key; } - virtual size_t GetKeySize () const = 0; - virtual wstring GetName () const = 0; - virtual shared_ptr GetNew () const = 0; - virtual void SetKey (const ConstBufferPtr &key); - - static const int MaxBlockSize = 16; - - protected: - Cipher (); - - virtual void Decrypt (byte *data) const = 0; - virtual void Encrypt (byte *data) const = 0; - virtual size_t GetScheduledKeySize () const = 0; - virtual void SetCipherKey (const byte *key) = 0; - - bool Initialized; - SecureBuffer Key; - SecureBuffer ScheduledKey; - - private: - Cipher (const Cipher &); - Cipher &operator= (const Cipher &); - }; - - struct CipherException : public Exception - { - protected: - CipherException () { } - CipherException (const string &message) : Exception (message) { } - CipherException (const string &message, const wstring &subject) : Exception (message, subject) { } - }; - - -#define TC_CIPHER(NAME, BLOCK_SIZE, KEY_SIZE) \ - class TC_JOIN (Cipher,NAME) : public Cipher \ - { \ - public: \ - TC_JOIN (Cipher,NAME) () { } \ - virtual ~TC_JOIN (Cipher,NAME) () { } \ -\ - virtual size_t GetBlockSize () const { return BLOCK_SIZE; }; \ - virtual size_t GetKeySize () const { return KEY_SIZE; }; \ - virtual wstring GetName () const { return L###NAME; }; \ - virtual shared_ptr GetNew () const { return shared_ptr (new TC_JOIN (Cipher,NAME)()); } \ -\ - protected: \ - virtual void Decrypt (byte *data) const; \ - virtual void Encrypt (byte *data) const; \ - virtual size_t GetScheduledKeySize () const; \ - virtual void SetCipherKey (const byte *key); \ -\ - private: \ - TC_JOIN (Cipher,NAME) (const TC_JOIN (Cipher,NAME) &); \ - TC_JOIN (Cipher,NAME) &operator= (const TC_JOIN (Cipher,NAME) &); \ - } - - TC_CIPHER (AES, 16, 32); - TC_CIPHER (Blowfish, 8, 56); - TC_CIPHER (Cast5, 8, 16); - TC_CIPHER (Serpent, 16, 32); - TC_CIPHER (TripleDES, 8, 24); - TC_CIPHER (Twofish, 16, 32); - -#undef TC_CIPHER - - -#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,CipherException) - -#undef TC_EXCEPTION_SET -#define TC_EXCEPTION_SET \ - TC_EXCEPTION (CipherInitError); \ - TC_EXCEPTION (WeakKeyDetected); - - TC_EXCEPTION_SET; - -#undef TC_EXCEPTION -} - -#endif // TC_HEADER_Encryption_Ciphers +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_Ciphers +#define TC_HEADER_Encryption_Ciphers + +#include "Platform/Platform.h" + + +namespace TrueCrypt +{ + class Cipher; + typedef vector < shared_ptr > CipherList; + + class Cipher + { + public: + virtual ~Cipher (); + + virtual void DecryptBlock (byte *data) const; + virtual void EncryptBlock (byte *data) const; + static CipherList GetAvailableCiphers (); + virtual size_t GetBlockSize () const = 0; + virtual const SecureBuffer &GetKey () const { return Key; } + virtual size_t GetKeySize () const = 0; + virtual wstring GetName () const = 0; + virtual shared_ptr GetNew () const = 0; + virtual void SetKey (const ConstBufferPtr &key); + + static const int MaxBlockSize = 16; + + protected: + Cipher (); + + virtual void Decrypt (byte *data) const = 0; + virtual void Encrypt (byte *data) const = 0; + virtual size_t GetScheduledKeySize () const = 0; + virtual void SetCipherKey (const byte *key) = 0; + + bool Initialized; + SecureBuffer Key; + SecureBuffer ScheduledKey; + + private: + Cipher (const Cipher &); + Cipher &operator= (const Cipher &); + }; + + struct CipherException : public Exception + { + protected: + CipherException () { } + CipherException (const string &message) : Exception (message) { } + CipherException (const string &message, const wstring &subject) : Exception (message, subject) { } + }; + + +#define TC_CIPHER(NAME, BLOCK_SIZE, KEY_SIZE) \ + class TC_JOIN (Cipher,NAME) : public Cipher \ + { \ + public: \ + TC_JOIN (Cipher,NAME) () { } \ + virtual ~TC_JOIN (Cipher,NAME) () { } \ +\ + virtual size_t GetBlockSize () const { return BLOCK_SIZE; }; \ + virtual size_t GetKeySize () const { return KEY_SIZE; }; \ + virtual wstring GetName () const { return L###NAME; }; \ + virtual shared_ptr GetNew () const { return shared_ptr (new TC_JOIN (Cipher,NAME)()); } \ +\ + protected: \ + virtual void Decrypt (byte *data) const; \ + virtual void Encrypt (byte *data) const; \ + virtual size_t GetScheduledKeySize () const; \ + virtual void SetCipherKey (const byte *key); \ +\ + private: \ + TC_JOIN (Cipher,NAME) (const TC_JOIN (Cipher,NAME) &); \ + TC_JOIN (Cipher,NAME) &operator= (const TC_JOIN (Cipher,NAME) &); \ + } + + TC_CIPHER (AES, 16, 32); + TC_CIPHER (Blowfish, 8, 56); + TC_CIPHER (Cast5, 8, 16); + TC_CIPHER (Serpent, 16, 32); + TC_CIPHER (TripleDES, 8, 24); + TC_CIPHER (Twofish, 16, 32); + +#undef TC_CIPHER + + +#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,CipherException) + +#undef TC_EXCEPTION_SET +#define TC_EXCEPTION_SET \ + TC_EXCEPTION (CipherInitError); \ + TC_EXCEPTION (WeakKeyDetected); + + TC_EXCEPTION_SET; + +#undef TC_EXCEPTION +} + +#endif // TC_HEADER_Encryption_Ciphers diff --git a/Volume/Crc32.h b/Volume/Crc32.h index 0daf0b7..5858575 100644 --- a/Volume/Crc32.h +++ b/Volume/Crc32.h @@ -1,44 +1,44 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_Crc32 -#define TC_HEADER_Encryption_Crc32 - -#include "Platform/Platform.h" -#include "Common/Crc.h" - -namespace TrueCrypt -{ - class Crc32 - { - public: - Crc32 () : CrcValue (0xffffFFFF) { }; - virtual ~Crc32 () { }; - - uint32 Get () const { return CrcValue ^ 0xffffFFFF; } - - uint32 Process (byte data) - { - return CrcValue = crc_32_tab[(byte) (CrcValue ^ data)] ^ (CrcValue >> 8); - } - - static uint32 ProcessBuffer (const ConstBufferPtr &buffer) - { - return ::GetCrc32 (const_cast (buffer.Get()), static_cast (buffer.Size())); - } - - protected: - uint32 CrcValue; - - private: - Crc32 (const Crc32 &); - Crc32 &operator= (const Crc32 &); - }; -} - -#endif // TC_HEADER_Encryption_Crc32 +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_Crc32 +#define TC_HEADER_Encryption_Crc32 + +#include "Platform/Platform.h" +#include "Common/Crc.h" + +namespace TrueCrypt +{ + class Crc32 + { + public: + Crc32 () : CrcValue (0xffffFFFF) { }; + virtual ~Crc32 () { }; + + uint32 Get () const { return CrcValue ^ 0xffffFFFF; } + + uint32 Process (byte data) + { + return CrcValue = crc_32_tab[(byte) (CrcValue ^ data)] ^ (CrcValue >> 8); + } + + static uint32 ProcessBuffer (const ConstBufferPtr &buffer) + { + return ::GetCrc32 (const_cast (buffer.Get()), static_cast (buffer.Size())); + } + + protected: + uint32 CrcValue; + + private: + Crc32 (const Crc32 &); + Crc32 &operator= (const Crc32 &); + }; +} + +#endif // TC_HEADER_Encryption_Crc32 diff --git a/Volume/EncryptionAlgorithm.cpp b/Volume/EncryptionAlgorithm.cpp index 4705fb8..582e0cc 100644 --- a/Volume/EncryptionAlgorithm.cpp +++ b/Volume/EncryptionAlgorithm.cpp @@ -1,345 +1,345 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "EncryptionAlgorithm.h" -#include "EncryptionModeCBC.h" -#include "EncryptionModeLRW.h" -#include "EncryptionModeXTS.h" - -namespace TrueCrypt -{ - EncryptionAlgorithm::EncryptionAlgorithm () : Deprecated (false) - { - } - - EncryptionAlgorithm::~EncryptionAlgorithm () - { - } - - void EncryptionAlgorithm::Decrypt (byte *data, uint64 length) const - { - if_debug (ValidateState ()); - Mode->Decrypt (data, length); - } - - void EncryptionAlgorithm::Decrypt (const BufferPtr &data) const - { - Decrypt (data, data.Size()); - } - - void EncryptionAlgorithm::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - if_debug (ValidateState()); - Mode->DecryptSectors (data, sectorIndex, sectorCount, sectorSize); - } - - void EncryptionAlgorithm::Encrypt (byte *data, uint64 length) const - { - if_debug (ValidateState()); - Mode->Encrypt (data, length); - } - - void EncryptionAlgorithm::Encrypt (const BufferPtr &data) const - { - Encrypt (data, data.Size()); - } - - void EncryptionAlgorithm::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - if_debug (ValidateState ()); - Mode->EncryptSectors (data, sectorIndex, sectorCount, sectorSize); - } - - EncryptionAlgorithmList EncryptionAlgorithm::GetAvailableAlgorithms () - { - EncryptionAlgorithmList l; - - l.push_back (shared_ptr (new AES ())); - l.push_back (shared_ptr (new Serpent ())); - l.push_back (shared_ptr (new Twofish ())); - l.push_back (shared_ptr (new AESTwofish ())); - l.push_back (shared_ptr (new AESTwofishSerpent ())); - l.push_back (shared_ptr (new SerpentAES ())); - l.push_back (shared_ptr (new SerpentTwofishAES ())); - l.push_back (shared_ptr (new TwofishSerpent ())); - - l.push_back (shared_ptr (new AESBlowfish ())); - l.push_back (shared_ptr (new AESBlowfishSerpent ())); - l.push_back (shared_ptr (new Blowfish ())); - l.push_back (shared_ptr (new Cast5 ())); - l.push_back (shared_ptr (new TripleDES ())); - return l; - } - - size_t EncryptionAlgorithm::GetLargestKeySize (const EncryptionAlgorithmList &algorithms) - { - size_t largestKeySize = 0; - - foreach_ref (const EncryptionAlgorithm &ea, algorithms) - { - if (ea.GetKeySize() > largestKeySize) - largestKeySize = ea.GetKeySize(); - } - - return largestKeySize; - } - - size_t EncryptionAlgorithm::GetKeySize () const - { - if (Ciphers.size() < 1) - throw NotInitialized (SRC_POS); - - size_t keySize = 0; - - foreach_ref (const Cipher &c, Ciphers) - keySize += c.GetKeySize(); - - return keySize; - } - - size_t EncryptionAlgorithm::GetMaxBlockSize () const - { - size_t blockSize = 0; - - foreach_ref (const Cipher &c, Ciphers) - if (c.GetBlockSize() > blockSize) - blockSize = c.GetBlockSize(); - - return blockSize; - } - - size_t EncryptionAlgorithm::GetMinBlockSize () const - { - size_t blockSize = 0; - - foreach_ref (const Cipher &c, Ciphers) - if (blockSize == 0 || c.GetBlockSize() < blockSize) - blockSize = c.GetBlockSize(); - - return blockSize; - } - - shared_ptr EncryptionAlgorithm::GetMode () const - { - if (Mode.get() == nullptr) - throw NotInitialized (SRC_POS); - - return Mode; - } - - wstring EncryptionAlgorithm::GetName () const - { - if (Ciphers.size() < 1) - throw NotInitialized (SRC_POS); - - wstring name; - - foreach_reverse_ref (const Cipher &c, Ciphers) - { - if (name.empty()) - name = c.GetName(); - else - name += wstring (L"-") + c.GetName(); - } - - return name; - } - - bool EncryptionAlgorithm::IsModeSupported (const EncryptionMode &mode) const - { - bool supported = false; - - foreach_ref (const EncryptionMode &em, SupportedModes) - { - if (typeid (mode) == typeid (em)) - { - supported = true; - break; - } - } - - return supported; - } - - - bool EncryptionAlgorithm::IsModeSupported (const shared_ptr mode) const - { - return IsModeSupported (*mode); - } - - void EncryptionAlgorithm::SetMode (shared_ptr mode) - { - if (!IsModeSupported (*mode)) - throw ParameterIncorrect (SRC_POS); - - mode->SetCiphers (Ciphers); - Mode = mode; - } - - void EncryptionAlgorithm::SetKey (const ConstBufferPtr &key) - { - if (Ciphers.size() < 1) - throw NotInitialized (SRC_POS); - - if (GetKeySize() != key.Size()) - throw ParameterIncorrect (SRC_POS); - - size_t keyOffset = 0; - foreach_ref (Cipher &c, Ciphers) - { - c.SetKey (key.GetRange (keyOffset, c.GetKeySize())); - keyOffset += c.GetKeySize(); - } - } - - void EncryptionAlgorithm::ValidateState () const - { - if (Ciphers.size() < 1 || Mode.get() == nullptr) - throw NotInitialized (SRC_POS); - } - - // AES - AES::AES () - { - Ciphers.push_back (shared_ptr (new CipherAES())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // AES-Blowfish - AESBlowfish::AESBlowfish () - { - Deprecated = true; - - Ciphers.push_back (shared_ptr (new CipherBlowfish ())); - Ciphers.push_back (shared_ptr (new CipherAES ())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // AES-Blowfish-Serpent - AESBlowfishSerpent::AESBlowfishSerpent () - { - Deprecated = true; - - Ciphers.push_back (shared_ptr (new CipherSerpent ())); - Ciphers.push_back (shared_ptr (new CipherBlowfish ())); - Ciphers.push_back (shared_ptr (new CipherAES ())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // AES-Twofish - AESTwofish::AESTwofish () - { - Ciphers.push_back (shared_ptr (new CipherTwofish ())); - Ciphers.push_back (shared_ptr (new CipherAES ())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // AES-Twofish-Serpent - AESTwofishSerpent::AESTwofishSerpent () - { - Ciphers.push_back (shared_ptr (new CipherSerpent ())); - Ciphers.push_back (shared_ptr (new CipherTwofish ())); - Ciphers.push_back (shared_ptr (new CipherAES ())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // Blowfish - Blowfish::Blowfish () - { - Deprecated = true; - Ciphers.push_back (shared_ptr (new CipherBlowfish())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // CAST5 - Cast5::Cast5 () - { - Deprecated = true; - Ciphers.push_back (shared_ptr (new CipherCast5())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // Serpent - Serpent::Serpent () - { - Ciphers.push_back (shared_ptr (new CipherSerpent())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // Serpent-AES - SerpentAES::SerpentAES () - { - Ciphers.push_back (shared_ptr (new CipherAES ())); - Ciphers.push_back (shared_ptr (new CipherSerpent ())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // Triple-DES - TripleDES::TripleDES () - { - Deprecated = true; - Ciphers.push_back (shared_ptr (new CipherTripleDES())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // Twofish - Twofish::Twofish () - { - Ciphers.push_back (shared_ptr (new CipherTwofish())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // Twofish-Serpent - TwofishSerpent::TwofishSerpent () - { - Ciphers.push_back (shared_ptr (new CipherSerpent ())); - Ciphers.push_back (shared_ptr (new CipherTwofish ())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - // Serpent-Twofish-AES - SerpentTwofishAES::SerpentTwofishAES () - { - Ciphers.push_back (shared_ptr (new CipherAES ())); - Ciphers.push_back (shared_ptr (new CipherTwofish ())); - Ciphers.push_back (shared_ptr (new CipherSerpent ())); - - SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "EncryptionAlgorithm.h" +#include "EncryptionModeCBC.h" +#include "EncryptionModeLRW.h" +#include "EncryptionModeXTS.h" + +namespace TrueCrypt +{ + EncryptionAlgorithm::EncryptionAlgorithm () : Deprecated (false) + { + } + + EncryptionAlgorithm::~EncryptionAlgorithm () + { + } + + void EncryptionAlgorithm::Decrypt (byte *data, uint64 length) const + { + if_debug (ValidateState ()); + Mode->Decrypt (data, length); + } + + void EncryptionAlgorithm::Decrypt (const BufferPtr &data) const + { + Decrypt (data, data.Size()); + } + + void EncryptionAlgorithm::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState()); + Mode->DecryptSectors (data, sectorIndex, sectorCount, sectorSize); + } + + void EncryptionAlgorithm::Encrypt (byte *data, uint64 length) const + { + if_debug (ValidateState()); + Mode->Encrypt (data, length); + } + + void EncryptionAlgorithm::Encrypt (const BufferPtr &data) const + { + Encrypt (data, data.Size()); + } + + void EncryptionAlgorithm::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + Mode->EncryptSectors (data, sectorIndex, sectorCount, sectorSize); + } + + EncryptionAlgorithmList EncryptionAlgorithm::GetAvailableAlgorithms () + { + EncryptionAlgorithmList l; + + l.push_back (shared_ptr (new AES ())); + l.push_back (shared_ptr (new Serpent ())); + l.push_back (shared_ptr (new Twofish ())); + l.push_back (shared_ptr (new AESTwofish ())); + l.push_back (shared_ptr (new AESTwofishSerpent ())); + l.push_back (shared_ptr (new SerpentAES ())); + l.push_back (shared_ptr (new SerpentTwofishAES ())); + l.push_back (shared_ptr (new TwofishSerpent ())); + + l.push_back (shared_ptr (new AESBlowfish ())); + l.push_back (shared_ptr (new AESBlowfishSerpent ())); + l.push_back (shared_ptr (new Blowfish ())); + l.push_back (shared_ptr (new Cast5 ())); + l.push_back (shared_ptr (new TripleDES ())); + return l; + } + + size_t EncryptionAlgorithm::GetLargestKeySize (const EncryptionAlgorithmList &algorithms) + { + size_t largestKeySize = 0; + + foreach_ref (const EncryptionAlgorithm &ea, algorithms) + { + if (ea.GetKeySize() > largestKeySize) + largestKeySize = ea.GetKeySize(); + } + + return largestKeySize; + } + + size_t EncryptionAlgorithm::GetKeySize () const + { + if (Ciphers.size() < 1) + throw NotInitialized (SRC_POS); + + size_t keySize = 0; + + foreach_ref (const Cipher &c, Ciphers) + keySize += c.GetKeySize(); + + return keySize; + } + + size_t EncryptionAlgorithm::GetMaxBlockSize () const + { + size_t blockSize = 0; + + foreach_ref (const Cipher &c, Ciphers) + if (c.GetBlockSize() > blockSize) + blockSize = c.GetBlockSize(); + + return blockSize; + } + + size_t EncryptionAlgorithm::GetMinBlockSize () const + { + size_t blockSize = 0; + + foreach_ref (const Cipher &c, Ciphers) + if (blockSize == 0 || c.GetBlockSize() < blockSize) + blockSize = c.GetBlockSize(); + + return blockSize; + } + + shared_ptr EncryptionAlgorithm::GetMode () const + { + if (Mode.get() == nullptr) + throw NotInitialized (SRC_POS); + + return Mode; + } + + wstring EncryptionAlgorithm::GetName () const + { + if (Ciphers.size() < 1) + throw NotInitialized (SRC_POS); + + wstring name; + + foreach_reverse_ref (const Cipher &c, Ciphers) + { + if (name.empty()) + name = c.GetName(); + else + name += wstring (L"-") + c.GetName(); + } + + return name; + } + + bool EncryptionAlgorithm::IsModeSupported (const EncryptionMode &mode) const + { + bool supported = false; + + foreach_ref (const EncryptionMode &em, SupportedModes) + { + if (typeid (mode) == typeid (em)) + { + supported = true; + break; + } + } + + return supported; + } + + + bool EncryptionAlgorithm::IsModeSupported (const shared_ptr mode) const + { + return IsModeSupported (*mode); + } + + void EncryptionAlgorithm::SetMode (shared_ptr mode) + { + if (!IsModeSupported (*mode)) + throw ParameterIncorrect (SRC_POS); + + mode->SetCiphers (Ciphers); + Mode = mode; + } + + void EncryptionAlgorithm::SetKey (const ConstBufferPtr &key) + { + if (Ciphers.size() < 1) + throw NotInitialized (SRC_POS); + + if (GetKeySize() != key.Size()) + throw ParameterIncorrect (SRC_POS); + + size_t keyOffset = 0; + foreach_ref (Cipher &c, Ciphers) + { + c.SetKey (key.GetRange (keyOffset, c.GetKeySize())); + keyOffset += c.GetKeySize(); + } + } + + void EncryptionAlgorithm::ValidateState () const + { + if (Ciphers.size() < 1 || Mode.get() == nullptr) + throw NotInitialized (SRC_POS); + } + + // AES + AES::AES () + { + Ciphers.push_back (shared_ptr (new CipherAES())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Blowfish + AESBlowfish::AESBlowfish () + { + Deprecated = true; + + Ciphers.push_back (shared_ptr (new CipherBlowfish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Blowfish-Serpent + AESBlowfishSerpent::AESBlowfishSerpent () + { + Deprecated = true; + + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + Ciphers.push_back (shared_ptr (new CipherBlowfish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Twofish + AESTwofish::AESTwofish () + { + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // AES-Twofish-Serpent + AESTwofishSerpent::AESTwofishSerpent () + { + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + Ciphers.push_back (shared_ptr (new CipherAES ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Blowfish + Blowfish::Blowfish () + { + Deprecated = true; + Ciphers.push_back (shared_ptr (new CipherBlowfish())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // CAST5 + Cast5::Cast5 () + { + Deprecated = true; + Ciphers.push_back (shared_ptr (new CipherCast5())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Serpent + Serpent::Serpent () + { + Ciphers.push_back (shared_ptr (new CipherSerpent())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Serpent-AES + SerpentAES::SerpentAES () + { + Ciphers.push_back (shared_ptr (new CipherAES ())); + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Triple-DES + TripleDES::TripleDES () + { + Deprecated = true; + Ciphers.push_back (shared_ptr (new CipherTripleDES())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Twofish + Twofish::Twofish () + { + Ciphers.push_back (shared_ptr (new CipherTwofish())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Twofish-Serpent + TwofishSerpent::TwofishSerpent () + { + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + // Serpent-Twofish-AES + SerpentTwofishAES::SerpentTwofishAES () + { + Ciphers.push_back (shared_ptr (new CipherAES ())); + Ciphers.push_back (shared_ptr (new CipherTwofish ())); + Ciphers.push_back (shared_ptr (new CipherSerpent ())); + + SupportedModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } +} diff --git a/Volume/EncryptionAlgorithm.h b/Volume/EncryptionAlgorithm.h index 24dfeec..6c757cd 100644 --- a/Volume/EncryptionAlgorithm.h +++ b/Volume/EncryptionAlgorithm.h @@ -1,93 +1,93 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_EncryptionAlgorithm -#define TC_HEADER_Encryption_EncryptionAlgorithm - -#include "Platform/Platform.h" -#include "Cipher.h" -#include "EncryptionMode.h" - -namespace TrueCrypt -{ - class EncryptionAlgorithm; - typedef list < shared_ptr > EncryptionAlgorithmList; - - class EncryptionAlgorithm - { - public: - virtual ~EncryptionAlgorithm (); - - virtual void Decrypt (byte *data, uint64 length) const; - virtual void Decrypt (const BufferPtr &data) const; - virtual void DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual void Encrypt (byte *data, uint64 length) const; - virtual void Encrypt (const BufferPtr &data) const; - virtual void EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - static EncryptionAlgorithmList GetAvailableAlgorithms (); - virtual const CipherList &GetCiphers () const { return Ciphers; } - virtual shared_ptr GetNew () const = 0; - virtual size_t GetMaxBlockSize () const; - virtual size_t GetMinBlockSize () const; - static size_t GetLargestKeySize (const EncryptionAlgorithmList &algorithms); - virtual size_t GetKeySize () const; - virtual shared_ptr GetMode () const; - virtual wstring GetName () const; - bool IsDeprecated () const { return Deprecated; } - virtual bool IsModeSupported (const EncryptionMode &mode) const; - virtual bool IsModeSupported (const shared_ptr mode) const; - virtual void SetKey (const ConstBufferPtr &key); - virtual void SetMode (shared_ptr mode); - - protected: - EncryptionAlgorithm (); - - void ValidateState () const; - - CipherList Ciphers; - bool Deprecated; - shared_ptr Mode; - EncryptionModeList SupportedModes; - - private: - EncryptionAlgorithm (const EncryptionAlgorithm &); - EncryptionAlgorithm &operator= (const EncryptionAlgorithm &); - }; - -#define TC_ENCRYPTION_ALGORITHM(NAME) \ - class NAME : public EncryptionAlgorithm \ - { \ - public: \ - NAME (); \ - virtual ~NAME () { } \ -\ - virtual shared_ptr GetNew () const { return shared_ptr (new NAME()); } \ -\ - private: \ - NAME (const NAME &); \ - NAME &operator= (const NAME &); \ - } - - TC_ENCRYPTION_ALGORITHM (AES); - TC_ENCRYPTION_ALGORITHM (AESBlowfish); - TC_ENCRYPTION_ALGORITHM (AESBlowfishSerpent); - TC_ENCRYPTION_ALGORITHM (AESTwofish); - TC_ENCRYPTION_ALGORITHM (AESTwofishSerpent); - TC_ENCRYPTION_ALGORITHM (Blowfish); - TC_ENCRYPTION_ALGORITHM (Cast5); - TC_ENCRYPTION_ALGORITHM (Serpent); - TC_ENCRYPTION_ALGORITHM (SerpentAES); - TC_ENCRYPTION_ALGORITHM (TripleDES); - TC_ENCRYPTION_ALGORITHM (Twofish); - TC_ENCRYPTION_ALGORITHM (TwofishSerpent); - TC_ENCRYPTION_ALGORITHM (SerpentTwofishAES); - -#undef TC_ENCRYPTION_ALGORITHM -} - -#endif // TC_HEADER_Encryption_EncryptionAlgorithm +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_EncryptionAlgorithm +#define TC_HEADER_Encryption_EncryptionAlgorithm + +#include "Platform/Platform.h" +#include "Cipher.h" +#include "EncryptionMode.h" + +namespace TrueCrypt +{ + class EncryptionAlgorithm; + typedef list < shared_ptr > EncryptionAlgorithmList; + + class EncryptionAlgorithm + { + public: + virtual ~EncryptionAlgorithm (); + + virtual void Decrypt (byte *data, uint64 length) const; + virtual void Decrypt (const BufferPtr &data) const; + virtual void DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual void Encrypt (byte *data, uint64 length) const; + virtual void Encrypt (const BufferPtr &data) const; + virtual void EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + static EncryptionAlgorithmList GetAvailableAlgorithms (); + virtual const CipherList &GetCiphers () const { return Ciphers; } + virtual shared_ptr GetNew () const = 0; + virtual size_t GetMaxBlockSize () const; + virtual size_t GetMinBlockSize () const; + static size_t GetLargestKeySize (const EncryptionAlgorithmList &algorithms); + virtual size_t GetKeySize () const; + virtual shared_ptr GetMode () const; + virtual wstring GetName () const; + bool IsDeprecated () const { return Deprecated; } + virtual bool IsModeSupported (const EncryptionMode &mode) const; + virtual bool IsModeSupported (const shared_ptr mode) const; + virtual void SetKey (const ConstBufferPtr &key); + virtual void SetMode (shared_ptr mode); + + protected: + EncryptionAlgorithm (); + + void ValidateState () const; + + CipherList Ciphers; + bool Deprecated; + shared_ptr Mode; + EncryptionModeList SupportedModes; + + private: + EncryptionAlgorithm (const EncryptionAlgorithm &); + EncryptionAlgorithm &operator= (const EncryptionAlgorithm &); + }; + +#define TC_ENCRYPTION_ALGORITHM(NAME) \ + class NAME : public EncryptionAlgorithm \ + { \ + public: \ + NAME (); \ + virtual ~NAME () { } \ +\ + virtual shared_ptr GetNew () const { return shared_ptr (new NAME()); } \ +\ + private: \ + NAME (const NAME &); \ + NAME &operator= (const NAME &); \ + } + + TC_ENCRYPTION_ALGORITHM (AES); + TC_ENCRYPTION_ALGORITHM (AESBlowfish); + TC_ENCRYPTION_ALGORITHM (AESBlowfishSerpent); + TC_ENCRYPTION_ALGORITHM (AESTwofish); + TC_ENCRYPTION_ALGORITHM (AESTwofishSerpent); + TC_ENCRYPTION_ALGORITHM (Blowfish); + TC_ENCRYPTION_ALGORITHM (Cast5); + TC_ENCRYPTION_ALGORITHM (Serpent); + TC_ENCRYPTION_ALGORITHM (SerpentAES); + TC_ENCRYPTION_ALGORITHM (TripleDES); + TC_ENCRYPTION_ALGORITHM (Twofish); + TC_ENCRYPTION_ALGORITHM (TwofishSerpent); + TC_ENCRYPTION_ALGORITHM (SerpentTwofishAES); + +#undef TC_ENCRYPTION_ALGORITHM +} + +#endif // TC_HEADER_Encryption_EncryptionAlgorithm diff --git a/Volume/EncryptionMode.cpp b/Volume/EncryptionMode.cpp index 20ddda5..90885e6 100644 --- a/Volume/EncryptionMode.cpp +++ b/Volume/EncryptionMode.cpp @@ -1,63 +1,63 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "EncryptionMode.h" -#include "EncryptionModeCBC.h" -#include "EncryptionModeLRW.h" -#include "EncryptionModeXTS.h" -#include "EncryptionThreadPool.h" - -namespace TrueCrypt -{ - EncryptionMode::EncryptionMode () : KeySet (false), SectorOffset (0) - { - } - - EncryptionMode::~EncryptionMode () - { - } - - void EncryptionMode::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - EncryptionThreadPool::DoWork (EncryptionThreadPool::WorkType::DecryptDataUnits, this, data, sectorIndex, sectorCount, sectorSize); - } - - void EncryptionMode::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - EncryptionThreadPool::DoWork (EncryptionThreadPool::WorkType::EncryptDataUnits, this, data, sectorIndex, sectorCount, sectorSize); - } - - EncryptionModeList EncryptionMode::GetAvailableModes () - { - EncryptionModeList l; - - l.push_back (shared_ptr (new EncryptionModeXTS ())); - l.push_back (shared_ptr (new EncryptionModeLRW ())); - l.push_back (shared_ptr (new EncryptionModeCBC ())); - - return l; - } - - void EncryptionMode::ValidateState () const - { - if (!KeySet || Ciphers.size() < 1) - throw NotInitialized (SRC_POS); - } - - void EncryptionMode::ValidateParameters (byte *data, uint64 length) const - { - if ((Ciphers.size() > 0 && (length % Ciphers.front()->GetBlockSize()) != 0)) - throw ParameterIncorrect (SRC_POS); - } - - void EncryptionMode::ValidateParameters (byte *data, uint64 sectorCount, size_t sectorSize) const - { - if (sectorCount == 0 || sectorSize == 0 || (sectorSize % EncryptionDataUnitSize) != 0) - throw ParameterIncorrect (SRC_POS); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "EncryptionMode.h" +#include "EncryptionModeCBC.h" +#include "EncryptionModeLRW.h" +#include "EncryptionModeXTS.h" +#include "EncryptionThreadPool.h" + +namespace TrueCrypt +{ + EncryptionMode::EncryptionMode () : KeySet (false), SectorOffset (0) + { + } + + EncryptionMode::~EncryptionMode () + { + } + + void EncryptionMode::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + EncryptionThreadPool::DoWork (EncryptionThreadPool::WorkType::DecryptDataUnits, this, data, sectorIndex, sectorCount, sectorSize); + } + + void EncryptionMode::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + EncryptionThreadPool::DoWork (EncryptionThreadPool::WorkType::EncryptDataUnits, this, data, sectorIndex, sectorCount, sectorSize); + } + + EncryptionModeList EncryptionMode::GetAvailableModes () + { + EncryptionModeList l; + + l.push_back (shared_ptr (new EncryptionModeXTS ())); + l.push_back (shared_ptr (new EncryptionModeLRW ())); + l.push_back (shared_ptr (new EncryptionModeCBC ())); + + return l; + } + + void EncryptionMode::ValidateState () const + { + if (!KeySet || Ciphers.size() < 1) + throw NotInitialized (SRC_POS); + } + + void EncryptionMode::ValidateParameters (byte *data, uint64 length) const + { + if ((Ciphers.size() > 0 && (length % Ciphers.front()->GetBlockSize()) != 0)) + throw ParameterIncorrect (SRC_POS); + } + + void EncryptionMode::ValidateParameters (byte *data, uint64 sectorCount, size_t sectorSize) const + { + if (sectorCount == 0 || sectorSize == 0 || (sectorSize % EncryptionDataUnitSize) != 0) + throw ParameterIncorrect (SRC_POS); + } +} diff --git a/Volume/EncryptionMode.h b/Volume/EncryptionMode.h index 66bf3e4..caa9a36 100644 --- a/Volume/EncryptionMode.h +++ b/Volume/EncryptionMode.h @@ -1,61 +1,61 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_EncryptionMode -#define TC_HEADER_Encryption_EncryptionMode - -#include "Platform/Platform.h" -#include "Cipher.h" - -namespace TrueCrypt -{ - class EncryptionMode; - typedef list < shared_ptr > EncryptionModeList; - - class EncryptionMode - { - public: - virtual ~EncryptionMode (); - - virtual void Decrypt (byte *data, uint64 length) const = 0; - virtual void DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const = 0; - virtual void Encrypt (byte *data, uint64 length) const = 0; - virtual void EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const = 0; - static EncryptionModeList GetAvailableModes (); - virtual const SecureBuffer &GetKey () const { throw NotApplicable (SRC_POS); } - virtual size_t GetKeySize () const = 0; - virtual wstring GetName () const = 0; - virtual shared_ptr GetNew () const = 0; - virtual uint64 GetSectorOffset () const { return SectorOffset; } - virtual bool IsKeySet () const { return KeySet; } - virtual void SetKey (const ConstBufferPtr &key) = 0; - virtual void SetCiphers (const CipherList &ciphers) { Ciphers = ciphers; } - virtual void SetSectorOffset (int64 offset) { SectorOffset = offset; } - - protected: - EncryptionMode (); - - virtual void ValidateState () const; - void ValidateParameters (byte *data, uint64 length) const; - virtual void ValidateParameters (byte *data, uint64 sectorCount, size_t sectorSize) const; - - static const size_t EncryptionDataUnitSize = 512; - - CipherList Ciphers; - bool KeySet; - uint64 SectorOffset; - - private: - EncryptionMode (const EncryptionMode &); - EncryptionMode &operator= (const EncryptionMode &); - }; -} - -#endif // TC_HEADER_Encryption_EncryptionMode +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_EncryptionMode +#define TC_HEADER_Encryption_EncryptionMode + +#include "Platform/Platform.h" +#include "Cipher.h" + +namespace TrueCrypt +{ + class EncryptionMode; + typedef list < shared_ptr > EncryptionModeList; + + class EncryptionMode + { + public: + virtual ~EncryptionMode (); + + virtual void Decrypt (byte *data, uint64 length) const = 0; + virtual void DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const = 0; + virtual void Encrypt (byte *data, uint64 length) const = 0; + virtual void EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const = 0; + static EncryptionModeList GetAvailableModes (); + virtual const SecureBuffer &GetKey () const { throw NotApplicable (SRC_POS); } + virtual size_t GetKeySize () const = 0; + virtual wstring GetName () const = 0; + virtual shared_ptr GetNew () const = 0; + virtual uint64 GetSectorOffset () const { return SectorOffset; } + virtual bool IsKeySet () const { return KeySet; } + virtual void SetKey (const ConstBufferPtr &key) = 0; + virtual void SetCiphers (const CipherList &ciphers) { Ciphers = ciphers; } + virtual void SetSectorOffset (int64 offset) { SectorOffset = offset; } + + protected: + EncryptionMode (); + + virtual void ValidateState () const; + void ValidateParameters (byte *data, uint64 length) const; + virtual void ValidateParameters (byte *data, uint64 sectorCount, size_t sectorSize) const; + + static const size_t EncryptionDataUnitSize = 512; + + CipherList Ciphers; + bool KeySet; + uint64 SectorOffset; + + private: + EncryptionMode (const EncryptionMode &); + EncryptionMode &operator= (const EncryptionMode &); + }; +} + +#endif // TC_HEADER_Encryption_EncryptionMode diff --git a/Volume/EncryptionModeCBC.cpp b/Volume/EncryptionModeCBC.cpp index cd1f9eb..d78b9a3 100644 --- a/Volume/EncryptionModeCBC.cpp +++ b/Volume/EncryptionModeCBC.cpp @@ -1,335 +1,335 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/Memory.h" -#include "Common/Crc.h" -#include "Common/Endian.h" -#include "EncryptionModeCBC.h" - -namespace TrueCrypt -{ - void EncryptionModeCBC::Decrypt (byte *data, uint64 length) const - { - if_debug (ValidateState ()); - if_debug (ValidateParameters (data, length)); - - if (IsOuterCBC (Ciphers)) - { - DecryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); - } - else - { - for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); - iCipherList != Ciphers.rend(); - ++iCipherList) - { - CipherList cl; - cl.push_back (*iCipherList); - - DecryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); - } - } - } - - void EncryptionModeCBC::DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const - { - size_t blockSize = ciphers.front()->GetBlockSize(); - if (blockSize != 8 && blockSize != 16) - throw ParameterIncorrect (SRC_POS); - - uint32 *data32 = (uint32 *) data; - uint32 bufIV[4]; - uint32 ct[4]; - uint64 i; - - bufIV[0] = iv[0]; - bufIV[1] = iv[1]; - if (blockSize == 16) - { - bufIV[2] = iv[2]; - bufIV[3] = iv[3]; - } - - for (i = 0; i < length / blockSize; i++) - { - // Dewhitening - data32[0] ^= whitening[0]; - data32[1] ^= whitening[1]; - if (blockSize == 16) - { - data32[2] ^= whitening[0]; - data32[3] ^= whitening[1]; - } - - // CBC - ct[0] = data32[0]; - ct[1] = data32[1]; - if (blockSize == 16) - { - ct[2] = data32[2]; - ct[3] = data32[3]; - } - - for (CipherList::const_reverse_iterator iCipherList = ciphers.rbegin(); - iCipherList != ciphers.rend(); - ++iCipherList) - { - const Cipher &c = **iCipherList; - - if (c.GetBlockSize () != blockSize) - throw ParameterIncorrect (SRC_POS); - - c.DecryptBlock ((byte *) data32); - } - - // CBC - data32[0] ^= bufIV[0]; - data32[1] ^= bufIV[1]; - bufIV[0] = ct[0]; - bufIV[1] = ct[1]; - if (blockSize == 16) - { - data32[2] ^= bufIV[2]; - data32[3] ^= bufIV[3]; - bufIV[2] = ct[2]; - bufIV[3] = ct[3]; - } - - data32 += blockSize / sizeof(*data32); - } - - Memory::Erase (bufIV, sizeof (bufIV)); - Memory::Erase (ct, sizeof (ct)); - } - - void EncryptionModeCBC::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - if_debug (ValidateState ()); - if_debug (ValidateParameters (data, sectorCount, sectorSize)); - - uint32 sectorIV[4]; - uint32 sectorWhitening[2]; - - while (sectorCount--) - { - if (IsOuterCBC (Ciphers)) - { - InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); - DecryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening); - } - else - { - for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); - iCipherList != Ciphers.rend(); - ++iCipherList) - { - const Cipher &c = **iCipherList; - CipherList cl; - cl.push_back (*iCipherList); - - InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); - DecryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening); - } - } - - data += sectorSize; - sectorIndex++; - } - - Memory::Erase (sectorIV, sizeof (sectorIV)); - Memory::Erase (sectorWhitening, sizeof (sectorWhitening)); - } - - void EncryptionModeCBC::Encrypt (byte *data, uint64 length) const - { - if_debug (ValidateState ()); - if_debug (ValidateParameters (data, length)); - - if (IsOuterCBC (Ciphers)) - { - EncryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); - } - else - { - for (CipherList::const_iterator iCipherList = Ciphers.begin(); - iCipherList != Ciphers.end(); - ++iCipherList) - { - CipherList cl; - cl.push_back (*iCipherList); - - EncryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); - } - } - } - - void EncryptionModeCBC::EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const - { - size_t blockSize = ciphers.front()->GetBlockSize(); - if (blockSize != 8 && blockSize != 16) - throw ParameterIncorrect (SRC_POS); - - uint32 *data32 = (uint32 *) data; - uint32 bufIV[4]; - uint64 i; - - bufIV[0] = iv[0]; - bufIV[1] = iv[1]; - if (blockSize == 16) - { - bufIV[2] = iv[2]; - bufIV[3] = iv[3]; - } - - for (i = 0; i < length / blockSize; i++) - { - data32[0] ^= bufIV[0]; - data32[1] ^= bufIV[1]; - if (blockSize == 16) - { - data32[2] ^= bufIV[2]; - data32[3] ^= bufIV[3]; - } - - for (CipherList::const_iterator iCipherList = ciphers.begin(); - iCipherList != ciphers.end(); - ++iCipherList) - { - const Cipher &c = **iCipherList; - - if (c.GetBlockSize () != blockSize) - throw ParameterIncorrect (SRC_POS); - - c.EncryptBlock ((byte *) data32); - } - - bufIV[0] = data32[0]; - bufIV[1] = data32[1]; - if (blockSize == 16) - { - bufIV[2] = data32[2]; - bufIV[3] = data32[3]; - } - - data32[0] ^= whitening[0]; - data32[1] ^= whitening[1]; - if (blockSize == 16) - { - data32[2] ^= whitening[0]; - data32[3] ^= whitening[1]; - } - - data32 += blockSize / sizeof(*data32); - } - - Memory::Erase (bufIV, sizeof (bufIV)); - } - - void EncryptionModeCBC::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - if_debug (ValidateState ()); - if_debug (ValidateParameters (data, sectorCount, sectorSize)); - - uint32 sectorIV[4]; - uint32 sectorWhitening[2]; - - while (sectorCount--) - { - if (IsOuterCBC (Ciphers)) - { - InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); - EncryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening); - } - else - { - for (CipherList::const_iterator iCipherList = Ciphers.begin(); - iCipherList != Ciphers.end(); - ++iCipherList) - { - const Cipher &c = **iCipherList; - CipherList cl; - cl.push_back (*iCipherList); - - InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); - EncryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening); - } - } - - data += sectorSize; - sectorIndex++; - } - - Memory::Erase (sectorIV, sizeof (sectorIV)); - Memory::Erase (sectorWhitening, sizeof (sectorWhitening)); - } - - void EncryptionModeCBC::InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const - { - if (blockSize != 8 && blockSize != 16) - throw ParameterIncorrect (SRC_POS); - - uint64 iv64[4]; - uint32 *iv32 = (uint32 *) iv64; - - iv64[0] = ivSeed[0] ^ Endian::Little (sectorIndex); - iv64[1] = ivSeed[1] ^ Endian::Little (sectorIndex); - iv64[2] = ivSeed[2] ^ Endian::Little (sectorIndex); - if (blockSize == 16) - { - iv64[3] = ivSeed[3] ^ Endian::Little (sectorIndex); - } - - iv[0] = iv32[0]; - iv[1] = iv32[1]; - - if (blockSize == 8) - { - whitening[0] = Endian::Little ( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) ); - whitening[1] = Endian::Little ( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) ); - } - else - { - iv[2] = iv32[2]; - iv[3] = iv32[3]; - - whitening[0] = Endian::Little ( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) ); - whitening[1] = Endian::Little ( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) ); - } - } - - bool EncryptionModeCBC::IsOuterCBC (const CipherList &ciphers) const - { - if (ciphers.size() < 2) - return false; - - size_t blockSize = ciphers.front()->GetBlockSize(); - - for (CipherList::const_iterator iCipherList = ciphers.begin(); - iCipherList != ciphers.end(); - ++iCipherList) - { - const Cipher &c = **iCipherList; - if (c.GetBlockSize() != blockSize) - return false; - } - - return true; - } - - void EncryptionModeCBC::SetKey (const ConstBufferPtr &key) - { - if (key.Size() != GetKeySize ()) - throw ParameterIncorrect (SRC_POS); - - if (!KeySet) - IV.Allocate (GetKeySize ()); - - IV.CopyFrom (key); - KeySet = true; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/Memory.h" +#include "Common/Crc.h" +#include "Common/Endian.h" +#include "EncryptionModeCBC.h" + +namespace TrueCrypt +{ + void EncryptionModeCBC::Decrypt (byte *data, uint64 length) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, length)); + + if (IsOuterCBC (Ciphers)) + { + DecryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + else + { + for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); + iCipherList != Ciphers.rend(); + ++iCipherList) + { + CipherList cl; + cl.push_back (*iCipherList); + + DecryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + } + } + + void EncryptionModeCBC::DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const + { + size_t blockSize = ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + uint32 *data32 = (uint32 *) data; + uint32 bufIV[4]; + uint32 ct[4]; + uint64 i; + + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + for (i = 0; i < length / blockSize; i++) + { + // Dewhitening + data32[0] ^= whitening[0]; + data32[1] ^= whitening[1]; + if (blockSize == 16) + { + data32[2] ^= whitening[0]; + data32[3] ^= whitening[1]; + } + + // CBC + ct[0] = data32[0]; + ct[1] = data32[1]; + if (blockSize == 16) + { + ct[2] = data32[2]; + ct[3] = data32[3]; + } + + for (CipherList::const_reverse_iterator iCipherList = ciphers.rbegin(); + iCipherList != ciphers.rend(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + + if (c.GetBlockSize () != blockSize) + throw ParameterIncorrect (SRC_POS); + + c.DecryptBlock ((byte *) data32); + } + + // CBC + data32[0] ^= bufIV[0]; + data32[1] ^= bufIV[1]; + bufIV[0] = ct[0]; + bufIV[1] = ct[1]; + if (blockSize == 16) + { + data32[2] ^= bufIV[2]; + data32[3] ^= bufIV[3]; + bufIV[2] = ct[2]; + bufIV[3] = ct[3]; + } + + data32 += blockSize / sizeof(*data32); + } + + Memory::Erase (bufIV, sizeof (bufIV)); + Memory::Erase (ct, sizeof (ct)); + } + + void EncryptionModeCBC::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + uint32 sectorIV[4]; + uint32 sectorWhitening[2]; + + while (sectorCount--) + { + if (IsOuterCBC (Ciphers)) + { + InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + DecryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening); + } + else + { + for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); + iCipherList != Ciphers.rend(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + CipherList cl; + cl.push_back (*iCipherList); + + InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + DecryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening); + } + } + + data += sectorSize; + sectorIndex++; + } + + Memory::Erase (sectorIV, sizeof (sectorIV)); + Memory::Erase (sectorWhitening, sizeof (sectorWhitening)); + } + + void EncryptionModeCBC::Encrypt (byte *data, uint64 length) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, length)); + + if (IsOuterCBC (Ciphers)) + { + EncryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + else + { + for (CipherList::const_iterator iCipherList = Ciphers.begin(); + iCipherList != Ciphers.end(); + ++iCipherList) + { + CipherList cl; + cl.push_back (*iCipherList); + + EncryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset)); + } + } + } + + void EncryptionModeCBC::EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const + { + size_t blockSize = ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + uint32 *data32 = (uint32 *) data; + uint32 bufIV[4]; + uint64 i; + + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + for (i = 0; i < length / blockSize; i++) + { + data32[0] ^= bufIV[0]; + data32[1] ^= bufIV[1]; + if (blockSize == 16) + { + data32[2] ^= bufIV[2]; + data32[3] ^= bufIV[3]; + } + + for (CipherList::const_iterator iCipherList = ciphers.begin(); + iCipherList != ciphers.end(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + + if (c.GetBlockSize () != blockSize) + throw ParameterIncorrect (SRC_POS); + + c.EncryptBlock ((byte *) data32); + } + + bufIV[0] = data32[0]; + bufIV[1] = data32[1]; + if (blockSize == 16) + { + bufIV[2] = data32[2]; + bufIV[3] = data32[3]; + } + + data32[0] ^= whitening[0]; + data32[1] ^= whitening[1]; + if (blockSize == 16) + { + data32[2] ^= whitening[0]; + data32[3] ^= whitening[1]; + } + + data32 += blockSize / sizeof(*data32); + } + + Memory::Erase (bufIV, sizeof (bufIV)); + } + + void EncryptionModeCBC::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + uint32 sectorIV[4]; + uint32 sectorWhitening[2]; + + while (sectorCount--) + { + if (IsOuterCBC (Ciphers)) + { + InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + EncryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening); + } + else + { + for (CipherList::const_iterator iCipherList = Ciphers.begin(); + iCipherList != Ciphers.end(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + CipherList cl; + cl.push_back (*iCipherList); + + InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening); + EncryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening); + } + } + + data += sectorSize; + sectorIndex++; + } + + Memory::Erase (sectorIV, sizeof (sectorIV)); + Memory::Erase (sectorWhitening, sizeof (sectorWhitening)); + } + + void EncryptionModeCBC::InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const + { + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + uint64 iv64[4]; + uint32 *iv32 = (uint32 *) iv64; + + iv64[0] = ivSeed[0] ^ Endian::Little (sectorIndex); + iv64[1] = ivSeed[1] ^ Endian::Little (sectorIndex); + iv64[2] = ivSeed[2] ^ Endian::Little (sectorIndex); + if (blockSize == 16) + { + iv64[3] = ivSeed[3] ^ Endian::Little (sectorIndex); + } + + iv[0] = iv32[0]; + iv[1] = iv32[1]; + + if (blockSize == 8) + { + whitening[0] = Endian::Little ( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) ); + whitening[1] = Endian::Little ( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) ); + } + else + { + iv[2] = iv32[2]; + iv[3] = iv32[3]; + + whitening[0] = Endian::Little ( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) ); + whitening[1] = Endian::Little ( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) ); + } + } + + bool EncryptionModeCBC::IsOuterCBC (const CipherList &ciphers) const + { + if (ciphers.size() < 2) + return false; + + size_t blockSize = ciphers.front()->GetBlockSize(); + + for (CipherList::const_iterator iCipherList = ciphers.begin(); + iCipherList != ciphers.end(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + if (c.GetBlockSize() != blockSize) + return false; + } + + return true; + } + + void EncryptionModeCBC::SetKey (const ConstBufferPtr &key) + { + if (key.Size() != GetKeySize ()) + throw ParameterIncorrect (SRC_POS); + + if (!KeySet) + IV.Allocate (GetKeySize ()); + + IV.CopyFrom (key); + KeySet = true; + } +} diff --git a/Volume/EncryptionModeCBC.h b/Volume/EncryptionModeCBC.h index fd2f2ad..9a83b34 100644 --- a/Volume/EncryptionModeCBC.h +++ b/Volume/EncryptionModeCBC.h @@ -1,47 +1,47 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_EncryptionModeCBC -#define TC_HEADER_Encryption_EncryptionModeCBC - -#include "Platform/Platform.h" -#include "EncryptionMode.h" - -namespace TrueCrypt -{ - class EncryptionModeCBC : public EncryptionMode - { - public: - EncryptionModeCBC () { } - virtual ~EncryptionModeCBC () { } - - virtual void Decrypt (byte *data, uint64 length) const; - virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual void Encrypt (byte *data, uint64 length) const; - virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual size_t GetKeySize () const { return 32; }; - virtual wstring GetName () const { return L"CBC"; }; - virtual shared_ptr GetNew () const { return shared_ptr (new EncryptionModeCBC); } - virtual void SetKey (const ConstBufferPtr &key); - - protected: - void DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const; - void EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const; - void InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const; - bool IsOuterCBC (const CipherList &ciphers) const; - - SecureBuffer IV; - static const int WhiteningIVOffset = 8; - - private: - EncryptionModeCBC (const EncryptionModeCBC &); - EncryptionModeCBC &operator= (const EncryptionModeCBC &); - }; -} - -#endif // TC_HEADER_Encryption_EncryptionModeCBC +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_EncryptionModeCBC +#define TC_HEADER_Encryption_EncryptionModeCBC + +#include "Platform/Platform.h" +#include "EncryptionMode.h" + +namespace TrueCrypt +{ + class EncryptionModeCBC : public EncryptionMode + { + public: + EncryptionModeCBC () { } + virtual ~EncryptionModeCBC () { } + + virtual void Decrypt (byte *data, uint64 length) const; + virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual void Encrypt (byte *data, uint64 length) const; + virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual size_t GetKeySize () const { return 32; }; + virtual wstring GetName () const { return L"CBC"; }; + virtual shared_ptr GetNew () const { return shared_ptr (new EncryptionModeCBC); } + virtual void SetKey (const ConstBufferPtr &key); + + protected: + void DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const; + void EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const; + void InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const; + bool IsOuterCBC (const CipherList &ciphers) const; + + SecureBuffer IV; + static const int WhiteningIVOffset = 8; + + private: + EncryptionModeCBC (const EncryptionModeCBC &); + EncryptionModeCBC &operator= (const EncryptionModeCBC &); + }; +} + +#endif // TC_HEADER_Encryption_EncryptionModeCBC diff --git a/Volume/EncryptionModeLRW.cpp b/Volume/EncryptionModeLRW.cpp index 38e4c17..49386cb 100644 --- a/Volume/EncryptionModeLRW.cpp +++ b/Volume/EncryptionModeLRW.cpp @@ -1,195 +1,195 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "EncryptionModeLRW.h" -#include "Common/GfMul.h" - -namespace TrueCrypt -{ - void EncryptionModeLRW::Decrypt (byte *data, uint64 length) const - { - if_debug (ValidateState ()); - DecryptBuffer (data, length, 1); - } - - void EncryptionModeLRW::DecryptBuffer (byte *data, uint64 length, uint64 blockIndex) const - { - size_t blockSize = Ciphers.front()->GetBlockSize(); - if (blockSize != 8 && blockSize != 16) - throw ParameterIncorrect (SRC_POS); - - byte i[8]; - *(uint64 *)i = Endian::Big (blockIndex); - - byte t[Cipher::MaxBlockSize]; - - for (unsigned int b = 0; b < length / blockSize; b++) - { - if (blockSize == 8) - { - Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr())); - Xor64 ((uint64 *)data, (uint64 *)t); - } - else - { - Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr())); - Xor128 ((uint64 *)data, (uint64 *)t); - } - - for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); - iCipherList != Ciphers.rend(); - ++iCipherList) - { - const Cipher &c = **iCipherList; - - if (c.GetBlockSize () != blockSize) - throw ParameterIncorrect (SRC_POS); - - c.DecryptBlock (data); - } - - if (blockSize == 8) - Xor64 ((uint64 *)data, (uint64 *)t); - else - Xor128 ((uint64 *)data, (uint64 *)t); - - data += blockSize; - IncrementBlockIndex (i); - } - - Memory::Erase (t, sizeof (t)); - } - - void EncryptionModeLRW::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - if_debug (ValidateState ()); - if_debug (ValidateParameters (data, sectorCount, sectorSize)); - - DecryptBuffer (data, - sectorCount * sectorSize, - SectorToBlockIndex (sectorIndex)); - } - - void EncryptionModeLRW::Encrypt (byte *data, uint64 length) const - { - ValidateState (); - EncryptBuffer (data, length, 1); - } - - void EncryptionModeLRW::EncryptBuffer (byte *data, uint64 length, uint64 blockIndex) const - { - size_t blockSize = Ciphers.front()->GetBlockSize(); - if (blockSize != 8 && blockSize != 16) - throw ParameterIncorrect (SRC_POS); - - byte i[8]; - *(uint64 *)i = Endian::Big (blockIndex); - - byte t[Cipher::MaxBlockSize]; - - for (unsigned int b = 0; b < length / blockSize; b++) - { - if (blockSize == 8) - { - Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr())); - Xor64 ((uint64 *)data, (uint64 *)t); - } - else - { - Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr())); - Xor128 ((uint64 *)data, (uint64 *)t); - } - - for (CipherList::const_iterator iCipherList = Ciphers.begin(); - iCipherList != Ciphers.end(); - ++iCipherList) - { - const Cipher &c = **iCipherList; - - if (c.GetBlockSize () != blockSize) - throw ParameterIncorrect (SRC_POS); - - c.EncryptBlock (data); - } - - if (blockSize == 8) - Xor64 ((uint64 *)data, (uint64 *)t); - else - Xor128 ((uint64 *)data, (uint64 *)t); - - data += blockSize; - IncrementBlockIndex (i); - } - - Memory::Erase (t, sizeof (t)); - } - - void EncryptionModeLRW::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - if_debug (ValidateState ()); - if_debug (ValidateParameters (data, sectorCount, sectorSize)); - - EncryptBuffer (data, - sectorCount * sectorSize, - SectorToBlockIndex (sectorIndex)); - } - - void EncryptionModeLRW::IncrementBlockIndex (byte *index) const - { - if (index[7] != 0xff) - index[7]++; - else - *(uint64 *)index = Endian::Big ( Endian::Big (*(uint64 *)index) + 1 ); - } - - uint64 EncryptionModeLRW::SectorToBlockIndex (uint64 sectorIndex) const - { - sectorIndex -= SectorOffset; - - switch (Ciphers.front()->GetBlockSize()) - { - case 8: - return (sectorIndex << 6) | 1; - - case 16: - return (sectorIndex << 5) | 1; - - default: - throw ParameterIncorrect (SRC_POS); - } - } - - void EncryptionModeLRW::SetKey (const ConstBufferPtr &key) - { - if (key.Size() != 16) - throw ParameterIncorrect (SRC_POS); - - if (!KeySet) - GfContext.Allocate (sizeof (GfCtx)); - - if (!Gf64TabInit ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr()))) - throw bad_alloc(); - - if (!Gf128Tab64Init ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr()))) - throw bad_alloc(); - - Key.CopyFrom (key); - KeySet = true; - } - - void EncryptionModeLRW::Xor64 (uint64 *a, const uint64 *b) const - { - *a ^= *b; - } - - void EncryptionModeLRW::Xor128 (uint64 *a, const uint64 *b) const - { - *a++ ^= *b++; - *a ^= *b; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "EncryptionModeLRW.h" +#include "Common/GfMul.h" + +namespace TrueCrypt +{ + void EncryptionModeLRW::Decrypt (byte *data, uint64 length) const + { + if_debug (ValidateState ()); + DecryptBuffer (data, length, 1); + } + + void EncryptionModeLRW::DecryptBuffer (byte *data, uint64 length, uint64 blockIndex) const + { + size_t blockSize = Ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + byte i[8]; + *(uint64 *)i = Endian::Big (blockIndex); + + byte t[Cipher::MaxBlockSize]; + + for (unsigned int b = 0; b < length / blockSize; b++) + { + if (blockSize == 8) + { + Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor64 ((uint64 *)data, (uint64 *)t); + } + else + { + Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor128 ((uint64 *)data, (uint64 *)t); + } + + for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin(); + iCipherList != Ciphers.rend(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + + if (c.GetBlockSize () != blockSize) + throw ParameterIncorrect (SRC_POS); + + c.DecryptBlock (data); + } + + if (blockSize == 8) + Xor64 ((uint64 *)data, (uint64 *)t); + else + Xor128 ((uint64 *)data, (uint64 *)t); + + data += blockSize; + IncrementBlockIndex (i); + } + + Memory::Erase (t, sizeof (t)); + } + + void EncryptionModeLRW::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + DecryptBuffer (data, + sectorCount * sectorSize, + SectorToBlockIndex (sectorIndex)); + } + + void EncryptionModeLRW::Encrypt (byte *data, uint64 length) const + { + ValidateState (); + EncryptBuffer (data, length, 1); + } + + void EncryptionModeLRW::EncryptBuffer (byte *data, uint64 length, uint64 blockIndex) const + { + size_t blockSize = Ciphers.front()->GetBlockSize(); + if (blockSize != 8 && blockSize != 16) + throw ParameterIncorrect (SRC_POS); + + byte i[8]; + *(uint64 *)i = Endian::Big (blockIndex); + + byte t[Cipher::MaxBlockSize]; + + for (unsigned int b = 0; b < length / blockSize; b++) + { + if (blockSize == 8) + { + Gf64MulTab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor64 ((uint64 *)data, (uint64 *)t); + } + else + { + Gf128MulBy64Tab (i, t, (GfCtx *) (GfContext.Ptr())); + Xor128 ((uint64 *)data, (uint64 *)t); + } + + for (CipherList::const_iterator iCipherList = Ciphers.begin(); + iCipherList != Ciphers.end(); + ++iCipherList) + { + const Cipher &c = **iCipherList; + + if (c.GetBlockSize () != blockSize) + throw ParameterIncorrect (SRC_POS); + + c.EncryptBlock (data); + } + + if (blockSize == 8) + Xor64 ((uint64 *)data, (uint64 *)t); + else + Xor128 ((uint64 *)data, (uint64 *)t); + + data += blockSize; + IncrementBlockIndex (i); + } + + Memory::Erase (t, sizeof (t)); + } + + void EncryptionModeLRW::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + if_debug (ValidateState ()); + if_debug (ValidateParameters (data, sectorCount, sectorSize)); + + EncryptBuffer (data, + sectorCount * sectorSize, + SectorToBlockIndex (sectorIndex)); + } + + void EncryptionModeLRW::IncrementBlockIndex (byte *index) const + { + if (index[7] != 0xff) + index[7]++; + else + *(uint64 *)index = Endian::Big ( Endian::Big (*(uint64 *)index) + 1 ); + } + + uint64 EncryptionModeLRW::SectorToBlockIndex (uint64 sectorIndex) const + { + sectorIndex -= SectorOffset; + + switch (Ciphers.front()->GetBlockSize()) + { + case 8: + return (sectorIndex << 6) | 1; + + case 16: + return (sectorIndex << 5) | 1; + + default: + throw ParameterIncorrect (SRC_POS); + } + } + + void EncryptionModeLRW::SetKey (const ConstBufferPtr &key) + { + if (key.Size() != 16) + throw ParameterIncorrect (SRC_POS); + + if (!KeySet) + GfContext.Allocate (sizeof (GfCtx)); + + if (!Gf64TabInit ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr()))) + throw bad_alloc(); + + if (!Gf128Tab64Init ((unsigned char *) key.Get(), (GfCtx *) (GfContext.Ptr()))) + throw bad_alloc(); + + Key.CopyFrom (key); + KeySet = true; + } + + void EncryptionModeLRW::Xor64 (uint64 *a, const uint64 *b) const + { + *a ^= *b; + } + + void EncryptionModeLRW::Xor128 (uint64 *a, const uint64 *b) const + { + *a++ ^= *b++; + *a ^= *b; + } +} diff --git a/Volume/EncryptionModeLRW.h b/Volume/EncryptionModeLRW.h index a04b40e..a5547ee 100644 --- a/Volume/EncryptionModeLRW.h +++ b/Volume/EncryptionModeLRW.h @@ -1,50 +1,50 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_EncryptionModeLRW -#define TC_HEADER_Encryption_EncryptionModeLRW - -#include "Platform/Platform.h" -#include "EncryptionMode.h" - -namespace TrueCrypt -{ - class EncryptionModeLRW : public EncryptionMode - { - public: - EncryptionModeLRW () { } - virtual ~EncryptionModeLRW () { } - - virtual void Decrypt (byte *data, uint64 length) const; - virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual void Encrypt (byte *data, uint64 length) const; - virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual const SecureBuffer &GetKey () const { return Key; } - virtual size_t GetKeySize () const { return 16; }; - virtual wstring GetName () const { return L"LRW"; }; - virtual shared_ptr GetNew () const { return shared_ptr (new EncryptionModeLRW); } - virtual void SetKey (const ConstBufferPtr &key); - - protected: - void DecryptBuffer (byte *plainText, uint64 length, uint64 blockIndex) const; - void EncryptBuffer (byte *plainText, uint64 length, uint64 blockIndex) const; - void IncrementBlockIndex (byte *index) const; - uint64 SectorToBlockIndex (uint64 sectorIndex) const; - void Xor64 (uint64 *a, const uint64 *b) const; - void Xor128 (uint64 *a, const uint64 *b) const; - - SecureBuffer GfContext; - SecureBuffer Key; - - private: - EncryptionModeLRW (const EncryptionModeLRW &); - EncryptionModeLRW &operator= (const EncryptionModeLRW &); - }; -} - -#endif // TC_HEADER_Encryption_EncryptionModeLRW +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_EncryptionModeLRW +#define TC_HEADER_Encryption_EncryptionModeLRW + +#include "Platform/Platform.h" +#include "EncryptionMode.h" + +namespace TrueCrypt +{ + class EncryptionModeLRW : public EncryptionMode + { + public: + EncryptionModeLRW () { } + virtual ~EncryptionModeLRW () { } + + virtual void Decrypt (byte *data, uint64 length) const; + virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual void Encrypt (byte *data, uint64 length) const; + virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual const SecureBuffer &GetKey () const { return Key; } + virtual size_t GetKeySize () const { return 16; }; + virtual wstring GetName () const { return L"LRW"; }; + virtual shared_ptr GetNew () const { return shared_ptr (new EncryptionModeLRW); } + virtual void SetKey (const ConstBufferPtr &key); + + protected: + void DecryptBuffer (byte *plainText, uint64 length, uint64 blockIndex) const; + void EncryptBuffer (byte *plainText, uint64 length, uint64 blockIndex) const; + void IncrementBlockIndex (byte *index) const; + uint64 SectorToBlockIndex (uint64 sectorIndex) const; + void Xor64 (uint64 *a, const uint64 *b) const; + void Xor128 (uint64 *a, const uint64 *b) const; + + SecureBuffer GfContext; + SecureBuffer Key; + + private: + EncryptionModeLRW (const EncryptionModeLRW &); + EncryptionModeLRW &operator= (const EncryptionModeLRW &); + }; +} + +#endif // TC_HEADER_Encryption_EncryptionModeLRW diff --git a/Volume/EncryptionModeXTS.cpp b/Volume/EncryptionModeXTS.cpp index 1bcdfac..df48325 100644 --- a/Volume/EncryptionModeXTS.cpp +++ b/Volume/EncryptionModeXTS.cpp @@ -1,330 +1,330 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "EncryptionModeXTS.h" -#include "Common/Crypto.h" - -namespace TrueCrypt -{ - void EncryptionModeXTS::Encrypt (byte *data, uint64 length) const - { - EncryptBuffer (data, length, 0); - } - - void EncryptionModeXTS::EncryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const - { - if_debug (ValidateState()); - - CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.begin(); - - for (CipherList::const_iterator iCipher = Ciphers.begin(); iCipher != Ciphers.end(); ++iCipher) - { - EncryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0); - ++iSecondaryCipher; - } - - assert (iSecondaryCipher == SecondaryCiphers.end()); - } - - void EncryptionModeXTS::EncryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const - { - byte finalCarry; - byte whiteningValue [BYTES_PER_XTS_BLOCK]; - byte byteBufUnitNo [BYTES_PER_XTS_BLOCK]; - uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue; - uint64 *bufPtr = (uint64 *) buffer; - unsigned int startBlock = startCipherBlockNo, endBlock, block; - uint64 blockCount, dataUnitNo; - - startDataUnitNo += SectorOffset; - - /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the - finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block - number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented - as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if - the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is - derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */ - - // Convert the 64-bit data unit number into a little-endian 16-byte array. - // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. - dataUnitNo = startDataUnitNo; - *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); - *((uint64 *) byteBufUnitNo + 1) = 0; - - if (length % BYTES_PER_XTS_BLOCK) - TC_THROW_FATAL_EXCEPTION; - - blockCount = length / BYTES_PER_XTS_BLOCK; - - // Process all blocks in the buffer - while (blockCount > 0) - { - if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) - endBlock = startBlock + (unsigned int) blockCount; - else - endBlock = BLOCKS_PER_XTS_DATA_UNIT; - - whiteningValuePtr64 = (uint64 *) whiteningValue; - - // Encrypt the data unit number using the secondary key (in order to generate the first - // whitening value for this data unit) - *whiteningValuePtr64 = *((uint64 *) byteBufUnitNo); - *(whiteningValuePtr64 + 1) = 0; - secondaryCipher.EncryptBlock (whiteningValue); - - // Generate (and apply) subsequent whitening values for blocks in this data unit and - // encrypt all relevant blocks in this data unit - for (block = 0; block < endBlock; block++) - { - if (block >= startBlock) - { - // Pre-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr-- ^= *whiteningValuePtr64--; - - // Actual encryption - cipher.EncryptBlock (reinterpret_cast (bufPtr)); - - // Post-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr++ ^= *whiteningValuePtr64; - } - else - whiteningValuePtr64++; - - // Derive the next whitening value - -#if BYTE_ORDER == LITTLE_ENDIAN - - // Little-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x8000000000000000ULL) ? - 135 : 0; - - *whiteningValuePtr64-- <<= 1; - - if (*whiteningValuePtr64 & 0x8000000000000000ULL) - *(whiteningValuePtr64 + 1) |= 1; - - *whiteningValuePtr64 <<= 1; -#else - - // Big-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x80) ? - 135 : 0; - - *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); - - whiteningValuePtr64--; - - if (*whiteningValuePtr64 & 0x80) - *(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL; - - *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); -#endif - - whiteningValue[0] ^= finalCarry; - } - - blockCount -= endBlock - startBlock; - startBlock = 0; - dataUnitNo++; - *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); - } - - FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); - } - - void EncryptionModeXTS::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - EncryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE); - } - - size_t EncryptionModeXTS::GetKeySize () const - { - if (Ciphers.empty()) - throw NotInitialized (SRC_POS); - - size_t keySize = 0; - foreach_ref (const Cipher &cipher, SecondaryCiphers) - { - keySize += cipher.GetKeySize(); - } - - return keySize; - } - - void EncryptionModeXTS::Decrypt (byte *data, uint64 length) const - { - DecryptBuffer (data, length, 0); - } - - void EncryptionModeXTS::DecryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const - { - if_debug (ValidateState()); - - CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.end(); - - for (CipherList::const_reverse_iterator iCipher = Ciphers.rbegin(); iCipher != Ciphers.rend(); ++iCipher) - { - --iSecondaryCipher; - DecryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0); - } - - assert (iSecondaryCipher == SecondaryCiphers.begin()); - } - - void EncryptionModeXTS::DecryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const - { - byte finalCarry; - byte whiteningValue [BYTES_PER_XTS_BLOCK]; - byte byteBufUnitNo [BYTES_PER_XTS_BLOCK]; - uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue; - uint64 *bufPtr = (uint64 *) buffer; - unsigned int startBlock = startCipherBlockNo, endBlock, block; - uint64 blockCount, dataUnitNo; - - startDataUnitNo += SectorOffset; - - // Convert the 64-bit data unit number into a little-endian 16-byte array. - // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. - dataUnitNo = startDataUnitNo; - *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); - *((uint64 *) byteBufUnitNo + 1) = 0; - - if (length % BYTES_PER_XTS_BLOCK) - TC_THROW_FATAL_EXCEPTION; - - blockCount = length / BYTES_PER_XTS_BLOCK; - - // Process all blocks in the buffer - while (blockCount > 0) - { - if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) - endBlock = startBlock + (unsigned int) blockCount; - else - endBlock = BLOCKS_PER_XTS_DATA_UNIT; - - whiteningValuePtr64 = (uint64 *) whiteningValue; - - // Encrypt the data unit number using the secondary key (in order to generate the first - // whitening value for this data unit) - *whiteningValuePtr64 = *((uint64 *) byteBufUnitNo); - *(whiteningValuePtr64 + 1) = 0; - secondaryCipher.EncryptBlock (whiteningValue); - - // Generate (and apply) subsequent whitening values for blocks in this data unit and - // decrypt all relevant blocks in this data unit - for (block = 0; block < endBlock; block++) - { - if (block >= startBlock) - { - // Post-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr-- ^= *whiteningValuePtr64--; - - // Actual decryption - cipher.DecryptBlock (reinterpret_cast (bufPtr)); - - // Pre-whitening - *bufPtr++ ^= *whiteningValuePtr64++; - *bufPtr++ ^= *whiteningValuePtr64; - } - else - whiteningValuePtr64++; - - // Derive the next whitening value - -#if BYTE_ORDER == LITTLE_ENDIAN - - // Little-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x8000000000000000ULL) ? - 135 : 0; - - *whiteningValuePtr64-- <<= 1; - - if (*whiteningValuePtr64 & 0x8000000000000000ULL) - *(whiteningValuePtr64 + 1) |= 1; - - *whiteningValuePtr64 <<= 1; - -#else - // Big-endian platforms - - finalCarry = - (*whiteningValuePtr64 & 0x80) ? - 135 : 0; - - *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); - - whiteningValuePtr64--; - - if (*whiteningValuePtr64 & 0x80) - *(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL; - - *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); -#endif - - whiteningValue[0] ^= finalCarry; - } - - blockCount -= endBlock - startBlock; - startBlock = 0; - dataUnitNo++; - *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); - } - - FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); - } - - void EncryptionModeXTS::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const - { - DecryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE); - } - - void EncryptionModeXTS::SetCiphers (const CipherList &ciphers) - { - EncryptionMode::SetCiphers (ciphers); - - SecondaryCiphers.clear(); - - foreach_ref (const Cipher &cipher, ciphers) - { - SecondaryCiphers.push_back (cipher.GetNew()); - } - - if (SecondaryKey.Size() > 0) - SetSecondaryCipherKeys(); - } - - void EncryptionModeXTS::SetKey (const ConstBufferPtr &key) - { - SecondaryKey.Allocate (key.Size()); - SecondaryKey.CopyFrom (key); - - if (!SecondaryCiphers.empty()) - SetSecondaryCipherKeys(); - } - - void EncryptionModeXTS::SetSecondaryCipherKeys () - { - size_t keyOffset = 0; - foreach_ref (Cipher &cipher, SecondaryCiphers) - { - cipher.SetKey (SecondaryKey.GetRange (keyOffset, cipher.GetKeySize())); - keyOffset += cipher.GetKeySize(); - } - - KeySet = true; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "EncryptionModeXTS.h" +#include "Common/Crypto.h" + +namespace TrueCrypt +{ + void EncryptionModeXTS::Encrypt (byte *data, uint64 length) const + { + EncryptBuffer (data, length, 0); + } + + void EncryptionModeXTS::EncryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const + { + if_debug (ValidateState()); + + CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.begin(); + + for (CipherList::const_iterator iCipher = Ciphers.begin(); iCipher != Ciphers.end(); ++iCipher) + { + EncryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0); + ++iSecondaryCipher; + } + + assert (iSecondaryCipher == SecondaryCiphers.end()); + } + + void EncryptionModeXTS::EncryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const + { + byte finalCarry; + byte whiteningValue [BYTES_PER_XTS_BLOCK]; + byte byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue; + uint64 *bufPtr = (uint64 *) buffer; + unsigned int startBlock = startCipherBlockNo, endBlock, block; + uint64 blockCount, dataUnitNo; + + startDataUnitNo += SectorOffset; + + /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the + finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block + number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented + as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if + the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is + derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */ + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. + dataUnitNo = startDataUnitNo; + *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); + *((uint64 *) byteBufUnitNo + 1) = 0; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Process all blocks in the buffer + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + whiteningValuePtr64 = (uint64 *) whiteningValue; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + *whiteningValuePtr64 = *((uint64 *) byteBufUnitNo); + *(whiteningValuePtr64 + 1) = 0; + secondaryCipher.EncryptBlock (whiteningValue); + + // Generate (and apply) subsequent whitening values for blocks in this data unit and + // encrypt all relevant blocks in this data unit + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + // Pre-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr-- ^= *whiteningValuePtr64--; + + // Actual encryption + cipher.EncryptBlock (reinterpret_cast (bufPtr)); + + // Post-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr++ ^= *whiteningValuePtr64; + } + else + whiteningValuePtr64++; + + // Derive the next whitening value + +#if BYTE_ORDER == LITTLE_ENDIAN + + // Little-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x8000000000000000ULL) ? + 135 : 0; + + *whiteningValuePtr64-- <<= 1; + + if (*whiteningValuePtr64 & 0x8000000000000000ULL) + *(whiteningValuePtr64 + 1) |= 1; + + *whiteningValuePtr64 <<= 1; +#else + + // Big-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x80) ? + 135 : 0; + + *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); + + whiteningValuePtr64--; + + if (*whiteningValuePtr64 & 0x80) + *(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL; + + *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); +#endif + + whiteningValue[0] ^= finalCarry; + } + + blockCount -= endBlock - startBlock; + startBlock = 0; + dataUnitNo++; + *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); + } + + FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); + } + + void EncryptionModeXTS::EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + EncryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE); + } + + size_t EncryptionModeXTS::GetKeySize () const + { + if (Ciphers.empty()) + throw NotInitialized (SRC_POS); + + size_t keySize = 0; + foreach_ref (const Cipher &cipher, SecondaryCiphers) + { + keySize += cipher.GetKeySize(); + } + + return keySize; + } + + void EncryptionModeXTS::Decrypt (byte *data, uint64 length) const + { + DecryptBuffer (data, length, 0); + } + + void EncryptionModeXTS::DecryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const + { + if_debug (ValidateState()); + + CipherList::const_iterator iSecondaryCipher = SecondaryCiphers.end(); + + for (CipherList::const_reverse_iterator iCipher = Ciphers.rbegin(); iCipher != Ciphers.rend(); ++iCipher) + { + --iSecondaryCipher; + DecryptBufferXTS (**iCipher, **iSecondaryCipher, data, length, startDataUnitNo, 0); + } + + assert (iSecondaryCipher == SecondaryCiphers.begin()); + } + + void EncryptionModeXTS::DecryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const + { + byte finalCarry; + byte whiteningValue [BYTES_PER_XTS_BLOCK]; + byte byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + uint64 *whiteningValuePtr64 = (uint64 *) whiteningValue; + uint64 *bufPtr = (uint64 *) buffer; + unsigned int startBlock = startCipherBlockNo, endBlock, block; + uint64 blockCount, dataUnitNo; + + startDataUnitNo += SectorOffset; + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. + dataUnitNo = startDataUnitNo; + *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); + *((uint64 *) byteBufUnitNo + 1) = 0; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Process all blocks in the buffer + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + whiteningValuePtr64 = (uint64 *) whiteningValue; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + *whiteningValuePtr64 = *((uint64 *) byteBufUnitNo); + *(whiteningValuePtr64 + 1) = 0; + secondaryCipher.EncryptBlock (whiteningValue); + + // Generate (and apply) subsequent whitening values for blocks in this data unit and + // decrypt all relevant blocks in this data unit + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + // Post-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr-- ^= *whiteningValuePtr64--; + + // Actual decryption + cipher.DecryptBlock (reinterpret_cast (bufPtr)); + + // Pre-whitening + *bufPtr++ ^= *whiteningValuePtr64++; + *bufPtr++ ^= *whiteningValuePtr64; + } + else + whiteningValuePtr64++; + + // Derive the next whitening value + +#if BYTE_ORDER == LITTLE_ENDIAN + + // Little-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x8000000000000000ULL) ? + 135 : 0; + + *whiteningValuePtr64-- <<= 1; + + if (*whiteningValuePtr64 & 0x8000000000000000ULL) + *(whiteningValuePtr64 + 1) |= 1; + + *whiteningValuePtr64 <<= 1; + +#else + // Big-endian platforms + + finalCarry = + (*whiteningValuePtr64 & 0x80) ? + 135 : 0; + + *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); + + whiteningValuePtr64--; + + if (*whiteningValuePtr64 & 0x80) + *(whiteningValuePtr64 + 1) |= 0x0100000000000000ULL; + + *whiteningValuePtr64 = Endian::Little (Endian::Little (*whiteningValuePtr64) << 1); +#endif + + whiteningValue[0] ^= finalCarry; + } + + blockCount -= endBlock - startBlock; + startBlock = 0; + dataUnitNo++; + *((uint64 *) byteBufUnitNo) = Endian::Little (dataUnitNo); + } + + FAST_ERASE64 (whiteningValue, sizeof (whiteningValue)); + } + + void EncryptionModeXTS::DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const + { + DecryptBuffer (data, sectorCount * sectorSize, sectorIndex * sectorSize / ENCRYPTION_DATA_UNIT_SIZE); + } + + void EncryptionModeXTS::SetCiphers (const CipherList &ciphers) + { + EncryptionMode::SetCiphers (ciphers); + + SecondaryCiphers.clear(); + + foreach_ref (const Cipher &cipher, ciphers) + { + SecondaryCiphers.push_back (cipher.GetNew()); + } + + if (SecondaryKey.Size() > 0) + SetSecondaryCipherKeys(); + } + + void EncryptionModeXTS::SetKey (const ConstBufferPtr &key) + { + SecondaryKey.Allocate (key.Size()); + SecondaryKey.CopyFrom (key); + + if (!SecondaryCiphers.empty()) + SetSecondaryCipherKeys(); + } + + void EncryptionModeXTS::SetSecondaryCipherKeys () + { + size_t keyOffset = 0; + foreach_ref (Cipher &cipher, SecondaryCiphers) + { + cipher.SetKey (SecondaryKey.GetRange (keyOffset, cipher.GetKeySize())); + keyOffset += cipher.GetKeySize(); + } + + KeySet = true; + } +} diff --git a/Volume/EncryptionModeXTS.h b/Volume/EncryptionModeXTS.h index 5acadd2..1baacbf 100644 --- a/Volume/EncryptionModeXTS.h +++ b/Volume/EncryptionModeXTS.h @@ -1,50 +1,50 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_EncryptionModeXTS -#define TC_HEADER_Volume_EncryptionModeXTS - -#include "Platform/Platform.h" -#include "EncryptionMode.h" - -namespace TrueCrypt -{ - class EncryptionModeXTS : public EncryptionMode - { - public: - EncryptionModeXTS () { } - virtual ~EncryptionModeXTS () { } - - virtual void Decrypt (byte *data, uint64 length) const; - virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual void Encrypt (byte *data, uint64 length) const; - virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; - virtual const SecureBuffer &GetKey () const { return SecondaryKey; } - virtual size_t GetKeySize () const; - virtual wstring GetName () const { return L"XTS"; }; - virtual shared_ptr GetNew () const { return shared_ptr (new EncryptionModeXTS); } - virtual void SetCiphers (const CipherList &ciphers); - virtual void SetKey (const ConstBufferPtr &key); - - protected: - void DecryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const; - void DecryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const; - void EncryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const; - void EncryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const; - void SetSecondaryCipherKeys (); - - SecureBuffer SecondaryKey; - CipherList SecondaryCiphers; - - private: - EncryptionModeXTS (const EncryptionModeXTS &); - EncryptionModeXTS &operator= (const EncryptionModeXTS &); - }; -} - -#endif // TC_HEADER_Volume_EncryptionModeXTS +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_EncryptionModeXTS +#define TC_HEADER_Volume_EncryptionModeXTS + +#include "Platform/Platform.h" +#include "EncryptionMode.h" + +namespace TrueCrypt +{ + class EncryptionModeXTS : public EncryptionMode + { + public: + EncryptionModeXTS () { } + virtual ~EncryptionModeXTS () { } + + virtual void Decrypt (byte *data, uint64 length) const; + virtual void DecryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual void Encrypt (byte *data, uint64 length) const; + virtual void EncryptSectorsCurrentThread (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const; + virtual const SecureBuffer &GetKey () const { return SecondaryKey; } + virtual size_t GetKeySize () const; + virtual wstring GetName () const { return L"XTS"; }; + virtual shared_ptr GetNew () const { return shared_ptr (new EncryptionModeXTS); } + virtual void SetCiphers (const CipherList &ciphers); + virtual void SetKey (const ConstBufferPtr &key); + + protected: + void DecryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const; + void DecryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const; + void EncryptBuffer (byte *data, uint64 length, uint64 startDataUnitNo) const; + void EncryptBufferXTS (const Cipher &cipher, const Cipher &secondaryCipher, byte *buffer, uint64 length, uint64 startDataUnitNo, unsigned int startCipherBlockNo) const; + void SetSecondaryCipherKeys (); + + SecureBuffer SecondaryKey; + CipherList SecondaryCiphers; + + private: + EncryptionModeXTS (const EncryptionModeXTS &); + EncryptionModeXTS &operator= (const EncryptionModeXTS &); + }; +} + +#endif // TC_HEADER_Volume_EncryptionModeXTS diff --git a/Volume/EncryptionTest.cpp b/Volume/EncryptionTest.cpp index 1c0f93b..994e551 100644 --- a/Volume/EncryptionTest.cpp +++ b/Volume/EncryptionTest.cpp @@ -1,861 +1,861 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Cipher.h" -#include "Common/Crc.h" -#include "EncryptionAlgorithm.h" -#include "EncryptionMode.h" -#include "EncryptionModeCBC.h" -#include "EncryptionModeLRW.h" -#include "EncryptionModeXTS.h" -#include "EncryptionTest.h" -#include "Pkcs5Kdf.h" - -namespace TrueCrypt -{ - void EncryptionTest::TestAll () - { - TestCiphers(); - TestXtsAES(); - TestXts(); - TestLegacyModes(); - TestPkcs5(); - } - - void EncryptionTest::TestLegacyModes () - { - byte buf[SECTOR_SIZE * 2]; - byte iv[32]; - unsigned int i; - uint32 crc; - uint64 secNo = 0x0234567890ABCDEFull; - - for (i = 0; i < sizeof (buf); i++) - buf[i] = (byte) i; - - for (i = 0; i < sizeof (iv); i++) - iv[i] = (byte) i; - - EncryptionModeList encModes = EncryptionMode::GetAvailableModes (); - - foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms()) - { - foreach (shared_ptr mode, encModes) - { - if (typeid (*mode) == typeid (EncryptionModeXTS)) - continue; - - if (!mode->IsKeySet()) - { - mode->SetKey (ConstBufferPtr (iv, mode->GetKeySize())); - mode->SetSectorOffset (1); - } - - if (ea.IsModeSupported (mode)) - { - ea.SetMode (mode); - ea.SetKey (ConstBufferPtr (buf, ea.GetKeySize())); - - ea.EncryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); - ea.DecryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); - ea.EncryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); - - crc = ::GetCrc32 (buf, sizeof (buf)); - - if (typeid (*mode) == typeid (EncryptionModeLRW)) - { - if (typeid (ea) == typeid (AES) && crc != 0x5237acf9) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (AESTwofish) && crc != 0x4ed0fd80) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (AESTwofishSerpent) && crc != 0xea04b3cf) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (Blowfish) && crc != 0xf94d5300) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (Cast5) && crc != 0x33971e82) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (Serpent) && crc != 0x7fb86805) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (TripleDES) && crc != 0x2b20bb84) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (Twofish) && crc != 0xa9de0f0b) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (TwofishSerpent) && crc != 0xca65c5cd) throw TestFailed (SRC_POS); - } - - if (typeid (*mode) == typeid (EncryptionModeCBC)) - { - if (typeid (ea) == typeid (AES) && crc != 0x2274f53d) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (AESBlowfish) && crc != 0xa7a80c84) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (AESBlowfishSerpent) && crc != 0xa0584562) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (AESTwofish) && crc != 0x3c226444) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (AESTwofishSerpent) && crc != 0x5e5e77fd) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (Blowfish) && crc != 0x033899a1) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (Cast5) && crc != 0x331cecc7) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (Serpent) && crc != 0x42dff3d4) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (TripleDES) && crc != 0xfe497d0c) throw TestFailed (SRC_POS); - if (typeid (ea) == typeid (TwofishSerpent) && crc != 0xa7b659f3) throw TestFailed (SRC_POS); - } - - ea.DecryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); - } - } - } - } - - - struct CipherTestVector - { - byte Key[32]; - byte Plaintext[16]; - byte Ciphertext[16]; - }; - - static const CipherTestVector AESTestVectors[] = - { - { - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - }, - { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff - }, - { - 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 - } - } - }; - - static const CipherTestVector SerpentTestVectors[] = - { - { - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - }, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - }, - { - 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c - } - } - }; - - static const CipherTestVector TwofishTestVectors[] = - { - { - { - 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, - 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F - }, - { - 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 - }, - { - 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA - } - } - }; - - static void TestCipher (Cipher &cipher, const CipherTestVector *testVector, size_t testVectorCount) - { - Buffer buffer (cipher.GetBlockSize()); - for (size_t i = 0; i < testVectorCount; ++i) - { - cipher.SetKey (ConstBufferPtr (testVector[i].Key, sizeof (testVector[i].Key))); - buffer.CopyFrom (ConstBufferPtr (testVector[i].Plaintext, sizeof (testVector[i].Plaintext))); - cipher.EncryptBlock (buffer); - - if (memcmp (buffer, testVector[i].Ciphertext, buffer.Size()) != 0) - throw TestFailed (SRC_POS); - } - } - - - void EncryptionTest::TestCiphers () - { - CipherAES aes; - TestCipher (aes, AESTestVectors, array_capacity (AESTestVectors)); - - CipherSerpent serpent; - TestCipher (serpent, SerpentTestVectors, array_capacity (SerpentTestVectors)); - - CipherTwofish twofish; - TestCipher (twofish, TwofishTestVectors, array_capacity (TwofishTestVectors)); - - } - - const EncryptionTest::XtsTestVector EncryptionTest::XtsTestVectors[] = - { - /* XTS-AES-256 */ - { - // IEEE 1619 - Vector 10 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b, - 0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd, - 0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0, - 0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca, - 0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0, - 0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f, - 0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec, - 0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a, - 0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1, - 0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae, - 0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29, - 0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac, - 0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f, - 0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85, - 0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa, - 0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51 - } - }, - { - // IEEE 1619 - Vector 11 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11, - 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2, - 0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d, - 0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01, - 0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79, - 0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a, - 0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6, - 0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80, - 0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a, - 0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0, - 0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75, - 0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63, - 0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a, - 0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68, - 0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90, - 0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03 - } - }, - { - // IEEE 1619 - Vector 12 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00, - 0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49, - 0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8, - 0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1, - 0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf, - 0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e, - 0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6, - 0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79, - 0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0, - 0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64, - 0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d, - 0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a, - 0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2, - 0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce, - 0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36, - 0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26 - } - }, - { - // IEEE 1619 - Vector 13 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5, - 0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1, - 0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac, - 0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e, - 0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3, - 0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5, - 0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9, - 0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c, - 0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53, - 0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7, - 0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf, - 0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00, - 0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60, - 0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55, - 0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c, - 0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20 - } - }, - { - // IEEE 1619 - Vector 14 - - { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, - { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, - { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff }, - 0, - { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }, - { - 0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23, - 0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80, - 0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04, - 0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4, - 0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b, - 0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34, - 0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8, - 0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff, - 0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b, - 0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6, - 0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa, - 0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc, - 0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a, - 0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46, - 0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde, - 0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9 - } - } - }; - - void EncryptionTest::TestXtsAES () - { - unsigned __int8 p[ENCRYPTION_DATA_UNIT_SIZE]; - uint64 dataUnitNo; - int i; - - for (i = 0; i < array_capacity (XtsTestVectors); i++) - { - AES aes; - shared_ptr xts (new EncryptionModeXTS); - - aes.SetKey (ConstBufferPtr (XtsTestVectors[i].key1, sizeof (XtsTestVectors[i].key1))); - xts->SetKey (ConstBufferPtr (XtsTestVectors[i].key2, sizeof (XtsTestVectors[i].key2))); - aes.SetMode (xts); - - memcpy (p, XtsTestVectors[i].plaintext, sizeof (p)); - - dataUnitNo = Endian::Big (*((uint64 *) XtsTestVectors[i].dataUnitNo)); - - aes.EncryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); - - aes.DecryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); - if (memcmp (XtsTestVectors[i].ciphertext, p, sizeof (p)) == 0) - throw TestFailed (SRC_POS); - - aes.EncryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); - - if (memcmp (XtsTestVectors[i].ciphertext, p, sizeof (p)) != 0) - throw TestFailed (SRC_POS); - } - } - - void EncryptionTest::TestXts () - { - unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 4]; - unsigned int i; - uint32 crc; - uint64 unitNo; - uint64 nbrUnits; - uint64 writeOffset; - int testCase = 0; - int nTestsPerformed = 0; - - static const byte testKey[] = - { - 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, - 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 - }; - - /* Encryption/decryption of data units (typically, volume data sectors) */ - - nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; - - /* The buffer can accommodate 4 data units and we'll test 4 cases by "scrolling". The data unit 0xFFFFFFFFFF - will "move" from the start of the buffer to its end. For a 512-byte data unit, the byte offset 562949953420800 - corresponds to the data unit 0xFFFFFFFFFF. */ - for (writeOffset = 562949953420800LL; - writeOffset > 562949953420800LL - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE; - writeOffset -= ENCRYPTION_DATA_UNIT_SIZE) - { - unitNo = writeOffset / ENCRYPTION_DATA_UNIT_SIZE; - - // Test all EAs that support this mode of operation - foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms()) - { - shared_ptr mode (new EncryptionModeXTS); - - if (!ea.IsModeSupported (mode)) - continue; - - ea.SetKey (ConstBufferPtr (testKey, ea.GetKeySize())); - - Buffer modeKey (ea.GetKeySize()); - for (size_t mi = 0; mi < modeKey.Size(); mi++) - modeKey[mi] = (byte) mi; - modeKey.CopyFrom (ConstBufferPtr (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2, sizeof (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2))); - - mode->SetKey (modeKey); - ea.SetMode (mode); - - // Each data unit will contain the same plaintext - for (i = 0; i < nbrUnits; i++) - { - memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, - XtsTestVectors[array_capacity (XtsTestVectors)-1].plaintext, - ENCRYPTION_DATA_UNIT_SIZE); - } - - ea.EncryptSectors (buf, unitNo, nbrUnits, ENCRYPTION_DATA_UNIT_SIZE); - - crc = GetCrc32 (buf, sizeof (buf)); - - if (typeid (ea) == typeid (AES)) - { - // Verify the ciphertext of the "moving" data unit using the IEEE test vector #14 - if (memcmp (XtsTestVectors[array_capacity (XtsTestVectors)-1].ciphertext, - (unsigned char *) buf + testCase * ENCRYPTION_DATA_UNIT_SIZE, - ENCRYPTION_DATA_UNIT_SIZE) != 0) - { - throw TestFailed (SRC_POS); - } - - // CRC of all data units in the buffer for each test case - switch (testCase) - { - case 0: - if (crc != 0x888f2990) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0xea28ea34) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0xe058f5a2) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0x10473dc9) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - else if (typeid (ea) == typeid (Serpent)) - { - switch (testCase) - { - case 0: - if (crc != 0x7edfecb3) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0x357baaaa) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0xc7b9fca5) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0xb5263e0c) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - else if (typeid (ea) == typeid (Twofish)) - { - switch (testCase) - { - case 0: - if (crc != 0x91525124) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0x2895cc47) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0x6bee346d) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0xb1c45759) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - else if (typeid (ea) == typeid (AESTwofish)) - { - switch (testCase) - { - case 0: - if (crc != 0x6cea7fa2) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0x69052c4c) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0x88db8de5) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0xf16fd8c5) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - else if (typeid (ea) == typeid (AESTwofishSerpent)) - { - switch (testCase) - { - case 0: - if (crc != 0xa2d7d82a) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0xdbf76412) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0xdf0ea03e) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0xdadedff7) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - else if (typeid (ea) == typeid (SerpentAES)) - { - switch (testCase) - { - case 0: - if (crc != 0x6dd133b3) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0x0e5717d2) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0x39f83cd9) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0x8a79fa2c) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - else if (typeid (ea) == typeid (SerpentTwofishAES)) - { - switch (testCase) - { - case 0: - if (crc != 0xe536daf8) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0x3ae89e7f) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0x2cc1301a) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0xcac7bdc7) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - else if (typeid (ea) == typeid (TwofishSerpent)) - { - switch (testCase) - { - case 0: - if (crc != 0x2686c859) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 1: - if (crc != 0x8a201780) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 2: - if (crc != 0x8dd13796) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - case 3: - if (crc != 0xe95196cb) - throw TestFailed (SRC_POS); - nTestsPerformed++; - break; - } - } - - if (crc == 0x9f5edd58) - throw TestFailed (SRC_POS); - - ea.DecryptSectors (buf, unitNo, nbrUnits, ENCRYPTION_DATA_UNIT_SIZE); - - if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) - throw TestFailed (SRC_POS); - - nTestsPerformed++; - } - testCase++; - } - - /* Encryption/decryption of a buffer (typically, a volume header) */ - - nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; - - // Test all EAs that support this mode of operation - foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms()) - { - shared_ptr mode (new EncryptionModeXTS); - - if (!ea.IsModeSupported (mode)) - continue; - - ea.SetKey (ConstBufferPtr (testKey, ea.GetKeySize())); - - Buffer modeKey (ea.GetKeySize()); - for (size_t mi = 0; mi < modeKey.Size(); mi++) - modeKey[mi] = (byte) mi; - modeKey.CopyFrom (ConstBufferPtr (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2, sizeof (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2))); - - mode->SetKey (modeKey); - ea.SetMode (mode); - - // Each data unit will contain the same plaintext - for (i = 0; i < nbrUnits; i++) - { - memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, - XtsTestVectors[array_capacity (XtsTestVectors)-1].plaintext, - ENCRYPTION_DATA_UNIT_SIZE); - } - - ea.Encrypt (buf, sizeof (buf)); - - crc = GetCrc32 (buf, sizeof (buf)); - - if (typeid (ea) == typeid (AES)) - { - if (crc != 0x33b91fab) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - else if (typeid (ea) == typeid (Serpent)) - { - if (crc != 0x3494d480) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - else if (typeid (ea) == typeid (Twofish)) - { - if (crc != 0xc4d65b46) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - else if (typeid (ea) == typeid (AESTwofish)) - { - if (crc != 0x14ce7385) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - else if (typeid (ea) == typeid (AESTwofishSerpent)) - { - if (crc != 0x0ec81bf7) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - else if (typeid (ea) == typeid (SerpentAES)) - { - if (crc != 0x42f919ad) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - else if (typeid (ea) == typeid (SerpentTwofishAES)) - { - if (crc != 0x208d5c58) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - else if (typeid (ea) == typeid (TwofishSerpent)) - { - if (crc != 0xbe78cec1) - throw TestFailed (SRC_POS); - nTestsPerformed++; - } - - if (crc == 0x9f5edd58) - throw TestFailed (SRC_POS); - - ea.Decrypt (buf, sizeof (buf)); - - if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) - throw TestFailed (SRC_POS); - - nTestsPerformed++; - } - - if (nTestsPerformed != 80) - throw TestFailed (SRC_POS); - } - - void EncryptionTest::TestPkcs5 () - { - VolumePassword password ("password", 8); - static const byte saltData[] = { 0x12, 0x34, 0x56, 0x78 }; - ConstBufferPtr salt (saltData, sizeof (saltData)); - Buffer derivedKey (4); - - Pkcs5HmacRipemd160 pkcs5HmacRipemd160; - pkcs5HmacRipemd160.DeriveKey (derivedKey, password, salt, 5); - if (memcmp (derivedKey.Ptr(), "\x7a\x3d\x7c\x03", 4) != 0) - throw TestFailed (SRC_POS); - - Pkcs5HmacSha1 pkcs5HmacSha1; - pkcs5HmacSha1.DeriveKey (derivedKey, password, salt, 5); - if (memcmp (derivedKey.Ptr(), "\x5c\x75\xce\xf0", 4) != 0) - throw TestFailed (SRC_POS); - - Pkcs5HmacSha512 pkcs5HmacSha512; - pkcs5HmacSha512.DeriveKey (derivedKey, password, salt, 5); - if (memcmp (derivedKey.Ptr(), "\x13\x64\xae\xf8", 4) != 0) - throw TestFailed (SRC_POS); - - Pkcs5HmacWhirlpool pkcs5HmacWhirlpool; - pkcs5HmacWhirlpool.DeriveKey (derivedKey, password, salt, 5); - if (memcmp (derivedKey.Ptr(), "\x50\x7c\x36\x6f", 4) != 0) - throw TestFailed (SRC_POS); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Cipher.h" +#include "Common/Crc.h" +#include "EncryptionAlgorithm.h" +#include "EncryptionMode.h" +#include "EncryptionModeCBC.h" +#include "EncryptionModeLRW.h" +#include "EncryptionModeXTS.h" +#include "EncryptionTest.h" +#include "Pkcs5Kdf.h" + +namespace TrueCrypt +{ + void EncryptionTest::TestAll () + { + TestCiphers(); + TestXtsAES(); + TestXts(); + TestLegacyModes(); + TestPkcs5(); + } + + void EncryptionTest::TestLegacyModes () + { + byte buf[SECTOR_SIZE * 2]; + byte iv[32]; + unsigned int i; + uint32 crc; + uint64 secNo = 0x0234567890ABCDEFull; + + for (i = 0; i < sizeof (buf); i++) + buf[i] = (byte) i; + + for (i = 0; i < sizeof (iv); i++) + iv[i] = (byte) i; + + EncryptionModeList encModes = EncryptionMode::GetAvailableModes (); + + foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms()) + { + foreach (shared_ptr mode, encModes) + { + if (typeid (*mode) == typeid (EncryptionModeXTS)) + continue; + + if (!mode->IsKeySet()) + { + mode->SetKey (ConstBufferPtr (iv, mode->GetKeySize())); + mode->SetSectorOffset (1); + } + + if (ea.IsModeSupported (mode)) + { + ea.SetMode (mode); + ea.SetKey (ConstBufferPtr (buf, ea.GetKeySize())); + + ea.EncryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); + ea.DecryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); + ea.EncryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); + + crc = ::GetCrc32 (buf, sizeof (buf)); + + if (typeid (*mode) == typeid (EncryptionModeLRW)) + { + if (typeid (ea) == typeid (AES) && crc != 0x5237acf9) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (AESTwofish) && crc != 0x4ed0fd80) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (AESTwofishSerpent) && crc != 0xea04b3cf) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (Blowfish) && crc != 0xf94d5300) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (Cast5) && crc != 0x33971e82) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (Serpent) && crc != 0x7fb86805) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (TripleDES) && crc != 0x2b20bb84) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (Twofish) && crc != 0xa9de0f0b) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (TwofishSerpent) && crc != 0xca65c5cd) throw TestFailed (SRC_POS); + } + + if (typeid (*mode) == typeid (EncryptionModeCBC)) + { + if (typeid (ea) == typeid (AES) && crc != 0x2274f53d) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (AESBlowfish) && crc != 0xa7a80c84) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (AESBlowfishSerpent) && crc != 0xa0584562) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (AESTwofish) && crc != 0x3c226444) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (AESTwofishSerpent) && crc != 0x5e5e77fd) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (Blowfish) && crc != 0x033899a1) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (Cast5) && crc != 0x331cecc7) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (Serpent) && crc != 0x42dff3d4) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (TripleDES) && crc != 0xfe497d0c) throw TestFailed (SRC_POS); + if (typeid (ea) == typeid (TwofishSerpent) && crc != 0xa7b659f3) throw TestFailed (SRC_POS); + } + + ea.DecryptSectors (buf, secNo, sizeof (buf) / SECTOR_SIZE, SECTOR_SIZE); + } + } + } + } + + + struct CipherTestVector + { + byte Key[32]; + byte Plaintext[16]; + byte Ciphertext[16]; + }; + + static const CipherTestVector AESTestVectors[] = + { + { + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }, + { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }, + { + 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 + } + } + }; + + static const CipherTestVector SerpentTestVectors[] = + { + { + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }, + { + 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c + } + } + }; + + static const CipherTestVector TwofishTestVectors[] = + { + { + { + 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, + 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F + }, + { + 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 + }, + { + 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA + } + } + }; + + static void TestCipher (Cipher &cipher, const CipherTestVector *testVector, size_t testVectorCount) + { + Buffer buffer (cipher.GetBlockSize()); + for (size_t i = 0; i < testVectorCount; ++i) + { + cipher.SetKey (ConstBufferPtr (testVector[i].Key, sizeof (testVector[i].Key))); + buffer.CopyFrom (ConstBufferPtr (testVector[i].Plaintext, sizeof (testVector[i].Plaintext))); + cipher.EncryptBlock (buffer); + + if (memcmp (buffer, testVector[i].Ciphertext, buffer.Size()) != 0) + throw TestFailed (SRC_POS); + } + } + + + void EncryptionTest::TestCiphers () + { + CipherAES aes; + TestCipher (aes, AESTestVectors, array_capacity (AESTestVectors)); + + CipherSerpent serpent; + TestCipher (serpent, SerpentTestVectors, array_capacity (SerpentTestVectors)); + + CipherTwofish twofish; + TestCipher (twofish, TwofishTestVectors, array_capacity (TwofishTestVectors)); + + } + + const EncryptionTest::XtsTestVector EncryptionTest::XtsTestVectors[] = + { + /* XTS-AES-256 */ + { + // IEEE 1619 - Vector 10 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b, + 0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd, + 0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0, + 0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca, + 0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0, + 0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f, + 0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec, + 0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a, + 0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1, + 0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae, + 0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29, + 0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac, + 0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f, + 0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85, + 0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa, + 0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51 + } + }, + { + // IEEE 1619 - Vector 11 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11, + 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2, + 0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d, + 0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01, + 0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79, + 0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a, + 0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6, + 0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80, + 0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a, + 0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0, + 0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75, + 0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63, + 0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a, + 0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68, + 0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90, + 0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03 + } + }, + { + // IEEE 1619 - Vector 12 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00, + 0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49, + 0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8, + 0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1, + 0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf, + 0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e, + 0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6, + 0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79, + 0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0, + 0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64, + 0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d, + 0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a, + 0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2, + 0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce, + 0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36, + 0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26 + } + }, + { + // IEEE 1619 - Vector 13 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5, + 0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1, + 0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac, + 0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e, + 0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3, + 0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5, + 0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9, + 0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c, + 0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53, + 0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7, + 0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf, + 0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00, + 0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60, + 0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55, + 0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c, + 0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20 + } + }, + { + // IEEE 1619 - Vector 14 + + { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 }, + { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 }, + { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff }, + 0, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, + { + 0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23, + 0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80, + 0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04, + 0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4, + 0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b, + 0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34, + 0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8, + 0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff, + 0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b, + 0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6, + 0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa, + 0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc, + 0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a, + 0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46, + 0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde, + 0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9 + } + } + }; + + void EncryptionTest::TestXtsAES () + { + unsigned __int8 p[ENCRYPTION_DATA_UNIT_SIZE]; + uint64 dataUnitNo; + size_t i; + + for (i = 0; i < array_capacity (XtsTestVectors); i++) + { + AES aes; + shared_ptr xts (new EncryptionModeXTS); + + aes.SetKey (ConstBufferPtr (XtsTestVectors[i].key1, sizeof (XtsTestVectors[i].key1))); + xts->SetKey (ConstBufferPtr (XtsTestVectors[i].key2, sizeof (XtsTestVectors[i].key2))); + aes.SetMode (xts); + + memcpy (p, XtsTestVectors[i].plaintext, sizeof (p)); + + dataUnitNo = Endian::Big (*((uint64 *) XtsTestVectors[i].dataUnitNo)); + + aes.EncryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); + + aes.DecryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); + if (memcmp (XtsTestVectors[i].ciphertext, p, sizeof (p)) == 0) + throw TestFailed (SRC_POS); + + aes.EncryptSectors (p, dataUnitNo, sizeof (p) / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE); + + if (memcmp (XtsTestVectors[i].ciphertext, p, sizeof (p)) != 0) + throw TestFailed (SRC_POS); + } + } + + void EncryptionTest::TestXts () + { + unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 4]; + unsigned int i; + uint32 crc; + uint64 unitNo; + uint64 nbrUnits; + uint64 writeOffset; + int testCase = 0; + int nTestsPerformed = 0; + + static const byte testKey[] = + { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 + }; + + /* Encryption/decryption of data units (typically, volume data sectors) */ + + nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; + + /* The buffer can accommodate 4 data units and we'll test 4 cases by "scrolling". The data unit 0xFFFFFFFFFF + will "move" from the start of the buffer to its end. For a 512-byte data unit, the byte offset 562949953420800 + corresponds to the data unit 0xFFFFFFFFFF. */ + for (writeOffset = 562949953420800LL; + writeOffset > 562949953420800LL - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE; + writeOffset -= ENCRYPTION_DATA_UNIT_SIZE) + { + unitNo = writeOffset / ENCRYPTION_DATA_UNIT_SIZE; + + // Test all EAs that support this mode of operation + foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms()) + { + shared_ptr mode (new EncryptionModeXTS); + + if (!ea.IsModeSupported (mode)) + continue; + + ea.SetKey (ConstBufferPtr (testKey, ea.GetKeySize())); + + Buffer modeKey (ea.GetKeySize()); + for (size_t mi = 0; mi < modeKey.Size(); mi++) + modeKey[mi] = (byte) mi; + modeKey.CopyFrom (ConstBufferPtr (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2, sizeof (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2))); + + mode->SetKey (modeKey); + ea.SetMode (mode); + + // Each data unit will contain the same plaintext + for (i = 0; i < nbrUnits; i++) + { + memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, + XtsTestVectors[array_capacity (XtsTestVectors)-1].plaintext, + ENCRYPTION_DATA_UNIT_SIZE); + } + + ea.EncryptSectors (buf, unitNo, nbrUnits, ENCRYPTION_DATA_UNIT_SIZE); + + crc = GetCrc32 (buf, sizeof (buf)); + + if (typeid (ea) == typeid (AES)) + { + // Verify the ciphertext of the "moving" data unit using the IEEE test vector #14 + if (memcmp (XtsTestVectors[array_capacity (XtsTestVectors)-1].ciphertext, + (unsigned char *) buf + testCase * ENCRYPTION_DATA_UNIT_SIZE, + ENCRYPTION_DATA_UNIT_SIZE) != 0) + { + throw TestFailed (SRC_POS); + } + + // CRC of all data units in the buffer for each test case + switch (testCase) + { + case 0: + if (crc != 0x888f2990) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0xea28ea34) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0xe058f5a2) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0x10473dc9) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + else if (typeid (ea) == typeid (Serpent)) + { + switch (testCase) + { + case 0: + if (crc != 0x7edfecb3) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0x357baaaa) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0xc7b9fca5) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0xb5263e0c) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + else if (typeid (ea) == typeid (Twofish)) + { + switch (testCase) + { + case 0: + if (crc != 0x91525124) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0x2895cc47) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0x6bee346d) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0xb1c45759) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + else if (typeid (ea) == typeid (AESTwofish)) + { + switch (testCase) + { + case 0: + if (crc != 0x6cea7fa2) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0x69052c4c) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0x88db8de5) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0xf16fd8c5) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + else if (typeid (ea) == typeid (AESTwofishSerpent)) + { + switch (testCase) + { + case 0: + if (crc != 0xa2d7d82a) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0xdbf76412) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0xdf0ea03e) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0xdadedff7) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + else if (typeid (ea) == typeid (SerpentAES)) + { + switch (testCase) + { + case 0: + if (crc != 0x6dd133b3) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0x0e5717d2) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0x39f83cd9) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0x8a79fa2c) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + else if (typeid (ea) == typeid (SerpentTwofishAES)) + { + switch (testCase) + { + case 0: + if (crc != 0xe536daf8) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0x3ae89e7f) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0x2cc1301a) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0xcac7bdc7) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + else if (typeid (ea) == typeid (TwofishSerpent)) + { + switch (testCase) + { + case 0: + if (crc != 0x2686c859) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 1: + if (crc != 0x8a201780) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 2: + if (crc != 0x8dd13796) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + case 3: + if (crc != 0xe95196cb) + throw TestFailed (SRC_POS); + nTestsPerformed++; + break; + } + } + + if (crc == 0x9f5edd58) + throw TestFailed (SRC_POS); + + ea.DecryptSectors (buf, unitNo, nbrUnits, ENCRYPTION_DATA_UNIT_SIZE); + + if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) + throw TestFailed (SRC_POS); + + nTestsPerformed++; + } + testCase++; + } + + /* Encryption/decryption of a buffer (typically, a volume header) */ + + nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE; + + // Test all EAs that support this mode of operation + foreach_ref (EncryptionAlgorithm &ea, EncryptionAlgorithm::GetAvailableAlgorithms()) + { + shared_ptr mode (new EncryptionModeXTS); + + if (!ea.IsModeSupported (mode)) + continue; + + ea.SetKey (ConstBufferPtr (testKey, ea.GetKeySize())); + + Buffer modeKey (ea.GetKeySize()); + for (size_t mi = 0; mi < modeKey.Size(); mi++) + modeKey[mi] = (byte) mi; + modeKey.CopyFrom (ConstBufferPtr (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2, sizeof (XtsTestVectors[array_capacity (XtsTestVectors)-1].key2))); + + mode->SetKey (modeKey); + ea.SetMode (mode); + + // Each data unit will contain the same plaintext + for (i = 0; i < nbrUnits; i++) + { + memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE, + XtsTestVectors[array_capacity (XtsTestVectors)-1].plaintext, + ENCRYPTION_DATA_UNIT_SIZE); + } + + ea.Encrypt (buf, sizeof (buf)); + + crc = GetCrc32 (buf, sizeof (buf)); + + if (typeid (ea) == typeid (AES)) + { + if (crc != 0x33b91fab) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + else if (typeid (ea) == typeid (Serpent)) + { + if (crc != 0x3494d480) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + else if (typeid (ea) == typeid (Twofish)) + { + if (crc != 0xc4d65b46) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + else if (typeid (ea) == typeid (AESTwofish)) + { + if (crc != 0x14ce7385) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + else if (typeid (ea) == typeid (AESTwofishSerpent)) + { + if (crc != 0x0ec81bf7) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + else if (typeid (ea) == typeid (SerpentAES)) + { + if (crc != 0x42f919ad) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + else if (typeid (ea) == typeid (SerpentTwofishAES)) + { + if (crc != 0x208d5c58) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + else if (typeid (ea) == typeid (TwofishSerpent)) + { + if (crc != 0xbe78cec1) + throw TestFailed (SRC_POS); + nTestsPerformed++; + } + + if (crc == 0x9f5edd58) + throw TestFailed (SRC_POS); + + ea.Decrypt (buf, sizeof (buf)); + + if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58) + throw TestFailed (SRC_POS); + + nTestsPerformed++; + } + + if (nTestsPerformed != 80) + throw TestFailed (SRC_POS); + } + + void EncryptionTest::TestPkcs5 () + { + VolumePassword password ("password", 8); + static const byte saltData[] = { 0x12, 0x34, 0x56, 0x78 }; + ConstBufferPtr salt (saltData, sizeof (saltData)); + Buffer derivedKey (4); + + Pkcs5HmacRipemd160 pkcs5HmacRipemd160; + pkcs5HmacRipemd160.DeriveKey (derivedKey, password, salt, 5); + if (memcmp (derivedKey.Ptr(), "\x7a\x3d\x7c\x03", 4) != 0) + throw TestFailed (SRC_POS); + + Pkcs5HmacSha1 pkcs5HmacSha1; + pkcs5HmacSha1.DeriveKey (derivedKey, password, salt, 5); + if (memcmp (derivedKey.Ptr(), "\x5c\x75\xce\xf0", 4) != 0) + throw TestFailed (SRC_POS); + + Pkcs5HmacSha512 pkcs5HmacSha512; + pkcs5HmacSha512.DeriveKey (derivedKey, password, salt, 5); + if (memcmp (derivedKey.Ptr(), "\x13\x64\xae\xf8", 4) != 0) + throw TestFailed (SRC_POS); + + Pkcs5HmacWhirlpool pkcs5HmacWhirlpool; + pkcs5HmacWhirlpool.DeriveKey (derivedKey, password, salt, 5); + if (memcmp (derivedKey.Ptr(), "\x50\x7c\x36\x6f", 4) != 0) + throw TestFailed (SRC_POS); + } +} diff --git a/Volume/EncryptionTest.h b/Volume/EncryptionTest.h index 550aab8..dbaefbf 100644 --- a/Volume/EncryptionTest.h +++ b/Volume/EncryptionTest.h @@ -1,49 +1,49 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_EncryptionTest -#define TC_HEADER_Encryption_EncryptionTest - -#include "Platform/Platform.h" -#include "Common/Crypto.h" - -namespace TrueCrypt -{ - class EncryptionTest - { - public: - static void TestAll (); - - protected: - static void TestCiphers (); - static void TestLegacyModes (); - static void TestPkcs5 (); - static void TestXts (); - static void TestXtsAES (); - - struct XtsTestVector - { - byte key1[32]; - byte key2[32]; - byte dataUnitNo[8]; - unsigned int blockNo; - byte plaintext[ENCRYPTION_DATA_UNIT_SIZE]; - byte ciphertext[ENCRYPTION_DATA_UNIT_SIZE]; - }; - - static const XtsTestVector XtsTestVectors[]; - - private: - EncryptionTest (); - virtual ~EncryptionTest (); - EncryptionTest (const EncryptionTest &); - EncryptionTest &operator= (const EncryptionTest &); - }; -} - -#endif // TC_HEADER_Encryption_EncryptionTest +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_EncryptionTest +#define TC_HEADER_Encryption_EncryptionTest + +#include "Platform/Platform.h" +#include "Common/Crypto.h" + +namespace TrueCrypt +{ + class EncryptionTest + { + public: + static void TestAll (); + + protected: + static void TestCiphers (); + static void TestLegacyModes (); + static void TestPkcs5 (); + static void TestXts (); + static void TestXtsAES (); + + struct XtsTestVector + { + byte key1[32]; + byte key2[32]; + byte dataUnitNo[8]; + unsigned int blockNo; + byte plaintext[ENCRYPTION_DATA_UNIT_SIZE]; + byte ciphertext[ENCRYPTION_DATA_UNIT_SIZE]; + }; + + static const XtsTestVector XtsTestVectors[]; + + private: + EncryptionTest (); + virtual ~EncryptionTest (); + EncryptionTest (const EncryptionTest &); + EncryptionTest &operator= (const EncryptionTest &); + }; +} + +#endif // TC_HEADER_Encryption_EncryptionTest diff --git a/Volume/EncryptionThreadPool.cpp b/Volume/EncryptionThreadPool.cpp index 6e6961f..7c6bc6b 100644 --- a/Volume/EncryptionThreadPool.cpp +++ b/Volume/EncryptionThreadPool.cpp @@ -1,317 +1,325 @@ -/* -Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - -Governed by the TrueCrypt License 2.7 the full text of which is contained -in the file License.txt included in TrueCrypt binary and source code -distribution packages. -*/ - -#ifdef TC_UNIX -# include -#endif - -#ifdef TC_MACOSX -# include -# include -#endif - -#include "Platform/SyncEvent.h" -#include "Platform/SystemLog.h" -#include "Common/Crypto.h" -#include "EncryptionThreadPool.h" - -namespace TrueCrypt -{ - void EncryptionThreadPool::DoWork (WorkType::Enum type, const EncryptionMode *encryptionMode, byte *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize) - { - size_t fragmentCount; - size_t unitsPerFragment; - size_t remainder; - - byte *fragmentData; - uint64 fragmentStartUnitNo; - - WorkItem *workItem; - WorkItem *firstFragmentWorkItem; - - if (unitCount == 0) - return; - - if (!ThreadPoolRunning || unitCount == 1) - { - switch (type) - { - case WorkType::DecryptDataUnits: - encryptionMode->DecryptSectorsCurrentThread (data, startUnitNo, unitCount, sectorSize); - break; - - case WorkType::EncryptDataUnits: - encryptionMode->EncryptSectorsCurrentThread (data, startUnitNo, unitCount, sectorSize); - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - - return; - } - - if (unitCount <= ThreadCount) - { - fragmentCount = (size_t) unitCount; - unitsPerFragment = 1; - remainder = 0; - } - else - { - fragmentCount = ThreadCount; - unitsPerFragment = (size_t) unitCount / ThreadCount; - remainder = (size_t) unitCount % ThreadCount; - - if (remainder > 0) - ++unitsPerFragment; - } - - fragmentData = data; - fragmentStartUnitNo = startUnitNo; - - { - ScopeLock lock (EnqueueMutex); - firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition]; - - while (firstFragmentWorkItem->State != WorkItem::State::Free) - { - WorkItemCompletedEvent.Wait(); - } - - firstFragmentWorkItem->OutstandingFragmentCount.Set (fragmentCount); - firstFragmentWorkItem->ItemException.reset(); - - while (fragmentCount-- > 0) - { - workItem = &WorkItemQueue[EnqueuePosition++]; - - if (EnqueuePosition >= QueueSize) - EnqueuePosition = 0; - - while (workItem->State != WorkItem::State::Free) - { - WorkItemCompletedEvent.Wait(); - } - - workItem->Type = type; - workItem->FirstFragment = firstFragmentWorkItem; - - workItem->Encryption.Mode = encryptionMode; - workItem->Encryption.Data = fragmentData; - workItem->Encryption.UnitCount = unitsPerFragment; - workItem->Encryption.StartUnitNo = fragmentStartUnitNo; - workItem->Encryption.SectorSize = sectorSize; - - fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE; - fragmentStartUnitNo += unitsPerFragment; - - if (remainder > 0 && --remainder == 0) - --unitsPerFragment; - - workItem->State.Set (WorkItem::State::Ready); - WorkItemReadyEvent.Signal(); - } - } - - firstFragmentWorkItem->ItemCompletedEvent.Wait(); - - auto_ptr itemException; - if (firstFragmentWorkItem->ItemException.get()) - itemException = firstFragmentWorkItem->ItemException; - - firstFragmentWorkItem->State.Set (WorkItem::State::Free); - WorkItemCompletedEvent.Signal(); - - if (itemException.get()) - itemException->Throw(); - } - - void EncryptionThreadPool::Start () - { - if (ThreadPoolRunning) - return; - -#ifdef TC_WINDOWS - - SYSTEM_INFO sysInfo; - GetSystemInfo (&sysInfo); - size_t cpuCount = sysInfo.dwNumberOfProcessors; - -#elif defined (_SC_NPROCESSORS_ONLN) - - ssize_t cpuCount = sysconf (_SC_NPROCESSORS_ONLN); - -#elif defined (TC_MACOSX) - - int cpuCount; - int mib[2] = { CTL_HW, HW_NCPU }; - size_t len = sizeof (cpuCount); - sysctl (mib, 2, &cpuCount, &len, nullptr, 0); - -#else -# error Cannot determine CPU count -#endif - - if (cpuCount < 2) - return; - - if (cpuCount > MaxThreadCount) - cpuCount = MaxThreadCount; - - StopPending = false; - DequeuePosition = 0; - EnqueuePosition = 0; - - for (size_t i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) - { - WorkItemQueue[i].State.Set (WorkItem::State::Free); - } - - try - { - for (ThreadCount = 0; ThreadCount < cpuCount; ++ThreadCount) - { - struct ThreadFunctor : public Functor - { - virtual void operator() () - { - WorkThreadProc(); - } - }; - - make_shared_auto (Thread, thread); - thread->Start (new ThreadFunctor ()); - RunningThreads.push_back (thread); - } - } - catch (...) - { - try - { - ThreadPoolRunning = true; - Stop(); - } catch (...) { } - - throw; - } - - ThreadPoolRunning = true; - } - - void EncryptionThreadPool::Stop () - { - if (!ThreadPoolRunning) - return; - - StopPending = true; - WorkItemReadyEvent.Signal(); - - foreach_ref (const Thread &thread, RunningThreads) - { - thread.Join(); - } - - ThreadCount = 0; - ThreadPoolRunning = false; - } - - void EncryptionThreadPool::WorkThreadProc () - { - try - { - WorkItem *workItem; - - while (!StopPending) - { - { - ScopeLock lock (DequeueMutex); - - workItem = &WorkItemQueue[DequeuePosition++]; - - if (DequeuePosition >= QueueSize) - DequeuePosition = 0; - - while (!StopPending && workItem->State != WorkItem::State::Ready) - { - WorkItemReadyEvent.Wait(); - } - - workItem->State.Set (WorkItem::State::Busy); - } - - if (StopPending) - break; - - try - { - switch (workItem->Type) - { - case WorkType::DecryptDataUnits: - workItem->Encryption.Mode->DecryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize); - break; - - case WorkType::EncryptDataUnits: - workItem->Encryption.Mode->EncryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize); - break; - - default: - throw ParameterIncorrect (SRC_POS); - } - } - catch (Exception &e) - { - workItem->FirstFragment->ItemException.reset (e.CloneNew()); - } - catch (exception &e) - { - workItem->FirstFragment->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e))); - } - catch (...) - { - workItem->FirstFragment->ItemException.reset (new UnknownException (SRC_POS)); - } - - if (workItem != workItem->FirstFragment) - { - workItem->State.Set (WorkItem::State::Free); - WorkItemCompletedEvent.Signal(); - } - - if (workItem->FirstFragment->OutstandingFragmentCount.Decrement() == 0) - workItem->FirstFragment->ItemCompletedEvent.Signal(); - } - } - catch (exception &e) - { - SystemLog::WriteException (e); - } - catch (...) - { - SystemLog::WriteException (UnknownException (SRC_POS)); - } - } - - volatile bool EncryptionThreadPool::ThreadPoolRunning = false; - volatile bool EncryptionThreadPool::StopPending = false; - - size_t EncryptionThreadPool::ThreadCount; - - EncryptionThreadPool::WorkItem EncryptionThreadPool::WorkItemQueue[QueueSize]; - - volatile size_t EncryptionThreadPool::EnqueuePosition; - volatile size_t EncryptionThreadPool::DequeuePosition; - - Mutex EncryptionThreadPool::EnqueueMutex; - Mutex EncryptionThreadPool::DequeueMutex; - - SyncEvent EncryptionThreadPool::WorkItemReadyEvent; - SyncEvent EncryptionThreadPool::WorkItemCompletedEvent; - - list < shared_ptr > EncryptionThreadPool::RunningThreads; -} +/* +Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + +Governed by the TrueCrypt License 2.8 the full text of which is contained +in the file License.txt included in TrueCrypt binary and source code +distribution packages. +*/ + +#ifdef TC_UNIX +# include +#endif + +#ifdef TC_MACOSX +# include +# include +#endif + +#include "Platform/SyncEvent.h" +#include "Platform/SystemLog.h" +#include "Common/Crypto.h" +#include "EncryptionThreadPool.h" + +namespace TrueCrypt +{ + void EncryptionThreadPool::DoWork (WorkType::Enum type, const EncryptionMode *encryptionMode, byte *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize) + { + size_t fragmentCount; + size_t unitsPerFragment; + size_t remainder; + + byte *fragmentData; + uint64 fragmentStartUnitNo; + + WorkItem *workItem; + WorkItem *firstFragmentWorkItem; + + if (unitCount == 0) + return; + + if (!ThreadPoolRunning || unitCount == 1) + { + switch (type) + { + case WorkType::DecryptDataUnits: + encryptionMode->DecryptSectorsCurrentThread (data, startUnitNo, unitCount, sectorSize); + break; + + case WorkType::EncryptDataUnits: + encryptionMode->EncryptSectorsCurrentThread (data, startUnitNo, unitCount, sectorSize); + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + + return; + } + + if (unitCount <= ThreadCount) + { + fragmentCount = (size_t) unitCount; + unitsPerFragment = 1; + remainder = 0; + } + else + { + fragmentCount = ThreadCount; + unitsPerFragment = (size_t) unitCount / ThreadCount; + remainder = (size_t) unitCount % ThreadCount; + + if (remainder > 0) + ++unitsPerFragment; + } + + fragmentData = data; + fragmentStartUnitNo = startUnitNo; + + { + ScopeLock lock (EnqueueMutex); + firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition]; + + while (firstFragmentWorkItem->State != WorkItem::State::Free) + { + WorkItemCompletedEvent.Wait(); + } + + firstFragmentWorkItem->OutstandingFragmentCount.Set (fragmentCount); + firstFragmentWorkItem->ItemException.reset(); + + while (fragmentCount-- > 0) + { + workItem = &WorkItemQueue[EnqueuePosition++]; + + if (EnqueuePosition >= QueueSize) + EnqueuePosition = 0; + + while (workItem->State != WorkItem::State::Free) + { + WorkItemCompletedEvent.Wait(); + } + + workItem->Type = type; + workItem->FirstFragment = firstFragmentWorkItem; + + workItem->Encryption.Mode = encryptionMode; + workItem->Encryption.Data = fragmentData; + workItem->Encryption.UnitCount = unitsPerFragment; + workItem->Encryption.StartUnitNo = fragmentStartUnitNo; + workItem->Encryption.SectorSize = sectorSize; + + fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE; + fragmentStartUnitNo += unitsPerFragment; + + if (remainder > 0 && --remainder == 0) + --unitsPerFragment; + + workItem->State.Set (WorkItem::State::Ready); + WorkItemReadyEvent.Signal(); + } + } + + firstFragmentWorkItem->ItemCompletedEvent.Wait(); + + auto_ptr itemException; + if (firstFragmentWorkItem->ItemException.get()) + itemException = firstFragmentWorkItem->ItemException; + + firstFragmentWorkItem->State.Set (WorkItem::State::Free); + WorkItemCompletedEvent.Signal(); + + if (itemException.get()) + itemException->Throw(); + } + + void EncryptionThreadPool::Start () + { + if (ThreadPoolRunning) + return; + + size_t cpuCount; + +#ifdef TC_WINDOWS + + SYSTEM_INFO sysInfo; + GetSystemInfo (&sysInfo); + cpuCount = sysInfo.dwNumberOfProcessors; + +#elif defined (_SC_NPROCESSORS_ONLN) + + cpuCount = (size_t) sysconf (_SC_NPROCESSORS_ONLN); + if (cpuCount == (size_t) -1) + cpuCount = 1; + +#elif defined (TC_MACOSX) + + int cpuCountSys; + int mib[2] = { CTL_HW, HW_NCPU }; + + size_t len = sizeof (cpuCountSys); + if (sysctl (mib, 2, &cpuCountSys, &len, nullptr, 0) == -1) + cpuCountSys = 1; + + cpuCount = (size_t) cpuCountSys; + +#else +# error Cannot determine CPU count +#endif + + if (cpuCount < 2) + return; + + if (cpuCount > MaxThreadCount) + cpuCount = MaxThreadCount; + + StopPending = false; + DequeuePosition = 0; + EnqueuePosition = 0; + + for (size_t i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) + { + WorkItemQueue[i].State.Set (WorkItem::State::Free); + } + + try + { + for (ThreadCount = 0; ThreadCount < cpuCount; ++ThreadCount) + { + struct ThreadFunctor : public Functor + { + virtual void operator() () + { + WorkThreadProc(); + } + }; + + make_shared_auto (Thread, thread); + thread->Start (new ThreadFunctor ()); + RunningThreads.push_back (thread); + } + } + catch (...) + { + try + { + ThreadPoolRunning = true; + Stop(); + } catch (...) { } + + throw; + } + + ThreadPoolRunning = true; + } + + void EncryptionThreadPool::Stop () + { + if (!ThreadPoolRunning) + return; + + StopPending = true; + WorkItemReadyEvent.Signal(); + + foreach_ref (const Thread &thread, RunningThreads) + { + thread.Join(); + } + + ThreadCount = 0; + ThreadPoolRunning = false; + } + + void EncryptionThreadPool::WorkThreadProc () + { + try + { + WorkItem *workItem; + + while (!StopPending) + { + { + ScopeLock lock (DequeueMutex); + + workItem = &WorkItemQueue[DequeuePosition++]; + + if (DequeuePosition >= QueueSize) + DequeuePosition = 0; + + while (!StopPending && workItem->State != WorkItem::State::Ready) + { + WorkItemReadyEvent.Wait(); + } + + workItem->State.Set (WorkItem::State::Busy); + } + + if (StopPending) + break; + + try + { + switch (workItem->Type) + { + case WorkType::DecryptDataUnits: + workItem->Encryption.Mode->DecryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize); + break; + + case WorkType::EncryptDataUnits: + workItem->Encryption.Mode->EncryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize); + break; + + default: + throw ParameterIncorrect (SRC_POS); + } + } + catch (Exception &e) + { + workItem->FirstFragment->ItemException.reset (e.CloneNew()); + } + catch (exception &e) + { + workItem->FirstFragment->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e))); + } + catch (...) + { + workItem->FirstFragment->ItemException.reset (new UnknownException (SRC_POS)); + } + + if (workItem != workItem->FirstFragment) + { + workItem->State.Set (WorkItem::State::Free); + WorkItemCompletedEvent.Signal(); + } + + if (workItem->FirstFragment->OutstandingFragmentCount.Decrement() == 0) + workItem->FirstFragment->ItemCompletedEvent.Signal(); + } + } + catch (exception &e) + { + SystemLog::WriteException (e); + } + catch (...) + { + SystemLog::WriteException (UnknownException (SRC_POS)); + } + } + + volatile bool EncryptionThreadPool::ThreadPoolRunning = false; + volatile bool EncryptionThreadPool::StopPending = false; + + size_t EncryptionThreadPool::ThreadCount; + + EncryptionThreadPool::WorkItem EncryptionThreadPool::WorkItemQueue[QueueSize]; + + volatile size_t EncryptionThreadPool::EnqueuePosition; + volatile size_t EncryptionThreadPool::DequeuePosition; + + Mutex EncryptionThreadPool::EnqueueMutex; + Mutex EncryptionThreadPool::DequeueMutex; + + SyncEvent EncryptionThreadPool::WorkItemReadyEvent; + SyncEvent EncryptionThreadPool::WorkItemCompletedEvent; + + list < shared_ptr > EncryptionThreadPool::RunningThreads; +} diff --git a/Volume/EncryptionThreadPool.h b/Volume/EncryptionThreadPool.h index 58bb1fd..ebebc10 100644 --- a/Volume/EncryptionThreadPool.h +++ b/Volume/EncryptionThreadPool.h @@ -1,87 +1,87 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_EncryptionThreadPool -#define TC_HEADER_Volume_EncryptionThreadPool - -#include "Platform/Platform.h" -#include "EncryptionMode.h" - -namespace TrueCrypt -{ - class EncryptionThreadPool - { - public: - struct WorkType - { - enum Enum - { - EncryptDataUnits, - DecryptDataUnits, - DeriveKey - }; - }; - - struct WorkItem - { - struct State - { - enum Enum - { - Free, - Ready, - Busy - }; - }; - - struct WorkItem *FirstFragment; - auto_ptr ItemException; - SyncEvent ItemCompletedEvent; - SharedVal OutstandingFragmentCount; - SharedVal State; - WorkType::Enum Type; - - union - { - struct - { - const EncryptionMode *Mode; - byte *Data; - uint64 StartUnitNo; - uint64 UnitCount; - size_t SectorSize; - } Encryption; - }; - }; - - static void DoWork (WorkType::Enum type, const EncryptionMode *mode, byte *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize); - static bool IsRunning () { return ThreadPoolRunning; } - static void Start (); - static void Stop (); - - protected: - static void WorkThreadProc (); - - static const size_t MaxThreadCount = 32; - static const size_t QueueSize = MaxThreadCount * 2; - - static Mutex DequeueMutex; - static volatile size_t DequeuePosition; - static volatile size_t EnqueuePosition; - static Mutex EnqueueMutex; - static list < shared_ptr > RunningThreads; - static volatile bool StopPending; - static size_t ThreadCount; - static volatile bool ThreadPoolRunning; - static SyncEvent WorkItemCompletedEvent; - static WorkItem WorkItemQueue[QueueSize]; - static SyncEvent WorkItemReadyEvent; - }; -} - -#endif // TC_HEADER_Volume_EncryptionThreadPool +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_EncryptionThreadPool +#define TC_HEADER_Volume_EncryptionThreadPool + +#include "Platform/Platform.h" +#include "EncryptionMode.h" + +namespace TrueCrypt +{ + class EncryptionThreadPool + { + public: + struct WorkType + { + enum Enum + { + EncryptDataUnits, + DecryptDataUnits, + DeriveKey + }; + }; + + struct WorkItem + { + struct State + { + enum Enum + { + Free, + Ready, + Busy + }; + }; + + struct WorkItem *FirstFragment; + auto_ptr ItemException; + SyncEvent ItemCompletedEvent; + SharedVal OutstandingFragmentCount; + SharedVal State; + WorkType::Enum Type; + + union + { + struct + { + const EncryptionMode *Mode; + byte *Data; + uint64 StartUnitNo; + uint64 UnitCount; + size_t SectorSize; + } Encryption; + }; + }; + + static void DoWork (WorkType::Enum type, const EncryptionMode *mode, byte *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize); + static bool IsRunning () { return ThreadPoolRunning; } + static void Start (); + static void Stop (); + + protected: + static void WorkThreadProc (); + + static const size_t MaxThreadCount = 32; + static const size_t QueueSize = MaxThreadCount * 2; + + static Mutex DequeueMutex; + static volatile size_t DequeuePosition; + static volatile size_t EnqueuePosition; + static Mutex EnqueueMutex; + static list < shared_ptr > RunningThreads; + static volatile bool StopPending; + static size_t ThreadCount; + static volatile bool ThreadPoolRunning; + static SyncEvent WorkItemCompletedEvent; + static WorkItem WorkItemQueue[QueueSize]; + static SyncEvent WorkItemReadyEvent; + }; +} + +#endif // TC_HEADER_Volume_EncryptionThreadPool diff --git a/Volume/Hash.cpp b/Volume/Hash.cpp index 6d733f1..726214c 100644 --- a/Volume/Hash.cpp +++ b/Volume/Hash.cpp @@ -1,138 +1,138 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Hash.h" - -#include "Crypto/Rmd160.h" -#include "Crypto/Sha1.h" -#include "Crypto/Sha2.h" -#include "Crypto/Whirlpool.h" - -namespace TrueCrypt -{ - HashList Hash::GetAvailableAlgorithms () - { - HashList l; - - l.push_back (shared_ptr (new Ripemd160 ())); - l.push_back (shared_ptr (new Sha512 ())); - l.push_back (shared_ptr (new Whirlpool ())); - l.push_back (shared_ptr (new Sha1 ())); - - return l; - } - - void Hash::ValidateDataParameters (const ConstBufferPtr &data) const - { - if (data.Size() < 1) - throw ParameterIncorrect (SRC_POS); - } - - void Hash::ValidateDigestParameters (const BufferPtr &buffer) const - { - if (buffer.Size() != GetDigestSize ()) - throw ParameterIncorrect (SRC_POS); - } - - // RIPEMD-160 - Ripemd160::Ripemd160 () - { - Context.Allocate (sizeof (RMD160_CTX)); - Init(); - } - - void Ripemd160::GetDigest (const BufferPtr &buffer) - { - if_debug (ValidateDigestParameters (buffer)); - RMD160Final (buffer, (RMD160_CTX *) Context.Ptr()); - } - - void Ripemd160::Init () - { - RMD160Init ((RMD160_CTX *) Context.Ptr()); - } - - void Ripemd160::ProcessData (const ConstBufferPtr &data) - { - if_debug (ValidateDataParameters (data)); - RMD160Update ((RMD160_CTX *) Context.Ptr(), data.Get(), (int) data.Size()); - } - - // SHA-1 - Sha1::Sha1 () - { - Deprecated = true; - Context.Allocate (sizeof (sha1_ctx)); - Init(); - } - - void Sha1::GetDigest (const BufferPtr &buffer) - { - if_debug (ValidateDigestParameters (buffer)); - sha1_end (buffer, (sha1_ctx *) Context.Ptr()); - } - - void Sha1::Init () - { - sha1_begin ((sha1_ctx *) Context.Ptr()); - } - - void Sha1::ProcessData (const ConstBufferPtr &data) - { - if_debug (ValidateDataParameters (data)); - sha1_hash (data.Get(), (int) data.Size(), (sha1_ctx *) Context.Ptr()); - } - - // SHA-512 - Sha512::Sha512 () - { - Context.Allocate (sizeof (sha512_ctx)); - Init(); - } - - void Sha512::GetDigest (const BufferPtr &buffer) - { - if_debug (ValidateDigestParameters (buffer)); - sha512_end (buffer, (sha512_ctx *) Context.Ptr()); - } - - void Sha512::Init () - { - sha512_begin ((sha512_ctx *) Context.Ptr()); - } - - void Sha512::ProcessData (const ConstBufferPtr &data) - { - if_debug (ValidateDataParameters (data)); - sha512_hash (data.Get(), (int) data.Size(), (sha512_ctx *) Context.Ptr()); - } - - // Whirlpool - Whirlpool::Whirlpool () - { - Context.Allocate (sizeof (WHIRLPOOL_CTX)); - Init(); - } - - void Whirlpool::GetDigest (const BufferPtr &buffer) - { - if_debug (ValidateDigestParameters (buffer)); - WHIRLPOOL_finalize ((WHIRLPOOL_CTX *) Context.Ptr(), buffer); - } - - void Whirlpool::Init () - { - WHIRLPOOL_init ((WHIRLPOOL_CTX *) Context.Ptr()); - } - - void Whirlpool::ProcessData (const ConstBufferPtr &data) - { - if_debug (ValidateDataParameters (data)); - WHIRLPOOL_add (data.Get(), (int) data.Size() * 8, (WHIRLPOOL_CTX *) Context.Ptr()); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Hash.h" + +#include "Crypto/Rmd160.h" +#include "Crypto/Sha1.h" +#include "Crypto/Sha2.h" +#include "Crypto/Whirlpool.h" + +namespace TrueCrypt +{ + HashList Hash::GetAvailableAlgorithms () + { + HashList l; + + l.push_back (shared_ptr (new Ripemd160 ())); + l.push_back (shared_ptr (new Sha512 ())); + l.push_back (shared_ptr (new Whirlpool ())); + l.push_back (shared_ptr (new Sha1 ())); + + return l; + } + + void Hash::ValidateDataParameters (const ConstBufferPtr &data) const + { + if (data.Size() < 1) + throw ParameterIncorrect (SRC_POS); + } + + void Hash::ValidateDigestParameters (const BufferPtr &buffer) const + { + if (buffer.Size() != GetDigestSize ()) + throw ParameterIncorrect (SRC_POS); + } + + // RIPEMD-160 + Ripemd160::Ripemd160 () + { + Context.Allocate (sizeof (RMD160_CTX)); + Init(); + } + + void Ripemd160::GetDigest (const BufferPtr &buffer) + { + if_debug (ValidateDigestParameters (buffer)); + RMD160Final (buffer, (RMD160_CTX *) Context.Ptr()); + } + + void Ripemd160::Init () + { + RMD160Init ((RMD160_CTX *) Context.Ptr()); + } + + void Ripemd160::ProcessData (const ConstBufferPtr &data) + { + if_debug (ValidateDataParameters (data)); + RMD160Update ((RMD160_CTX *) Context.Ptr(), data.Get(), (int) data.Size()); + } + + // SHA-1 + Sha1::Sha1 () + { + Deprecated = true; + Context.Allocate (sizeof (sha1_ctx)); + Init(); + } + + void Sha1::GetDigest (const BufferPtr &buffer) + { + if_debug (ValidateDigestParameters (buffer)); + sha1_end (buffer, (sha1_ctx *) Context.Ptr()); + } + + void Sha1::Init () + { + sha1_begin ((sha1_ctx *) Context.Ptr()); + } + + void Sha1::ProcessData (const ConstBufferPtr &data) + { + if_debug (ValidateDataParameters (data)); + sha1_hash (data.Get(), (int) data.Size(), (sha1_ctx *) Context.Ptr()); + } + + // SHA-512 + Sha512::Sha512 () + { + Context.Allocate (sizeof (sha512_ctx)); + Init(); + } + + void Sha512::GetDigest (const BufferPtr &buffer) + { + if_debug (ValidateDigestParameters (buffer)); + sha512_end (buffer, (sha512_ctx *) Context.Ptr()); + } + + void Sha512::Init () + { + sha512_begin ((sha512_ctx *) Context.Ptr()); + } + + void Sha512::ProcessData (const ConstBufferPtr &data) + { + if_debug (ValidateDataParameters (data)); + sha512_hash (data.Get(), (int) data.Size(), (sha512_ctx *) Context.Ptr()); + } + + // Whirlpool + Whirlpool::Whirlpool () + { + Context.Allocate (sizeof (WHIRLPOOL_CTX)); + Init(); + } + + void Whirlpool::GetDigest (const BufferPtr &buffer) + { + if_debug (ValidateDigestParameters (buffer)); + WHIRLPOOL_finalize ((WHIRLPOOL_CTX *) Context.Ptr(), buffer); + } + + void Whirlpool::Init () + { + WHIRLPOOL_init ((WHIRLPOOL_CTX *) Context.Ptr()); + } + + void Whirlpool::ProcessData (const ConstBufferPtr &data) + { + if_debug (ValidateDataParameters (data)); + WHIRLPOOL_add (data.Get(), (int) data.Size() * 8, (WHIRLPOOL_CTX *) Context.Ptr()); + } +} diff --git a/Volume/Hash.h b/Volume/Hash.h index 4997c3a..3862d05 100644 --- a/Volume/Hash.h +++ b/Volume/Hash.h @@ -1,135 +1,135 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_Hash -#define TC_HEADER_Encryption_Hash - -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - class Hash; - typedef list < shared_ptr > HashList; - - class Hash - { - public: - Hash () : Deprecated (false) { } - virtual ~Hash () { } - - static HashList GetAvailableAlgorithms (); - virtual void GetDigest (const BufferPtr &buffer) = 0; - virtual size_t GetBlockSize () const = 0; - virtual size_t GetDigestSize () const = 0; - virtual wstring GetName () const = 0; - virtual shared_ptr GetNew () const = 0; - virtual void Init () = 0; - bool IsDeprecated () const { return Deprecated; } - virtual void ProcessData (const ConstBufferPtr &data) = 0; - virtual void ValidateDataParameters (const ConstBufferPtr &data) const; - virtual void ValidateDigestParameters (const BufferPtr &buffer) const; - - protected: - SecureBuffer Context; - bool Deprecated; - - private: - Hash (const Hash &); - Hash &operator= (const Hash &); - }; - - // RIPEMD-160 - class Ripemd160 : public Hash - { - public: - Ripemd160 (); - virtual ~Ripemd160 () { } - - virtual void GetDigest (const BufferPtr &buffer); - virtual size_t GetBlockSize () const { return 64; } - virtual size_t GetDigestSize () const { return 160 / 8; } - virtual wstring GetName () const { return L"RIPEMD-160"; } - virtual shared_ptr GetNew () const { return shared_ptr (new Ripemd160); } - virtual void Init (); - virtual void ProcessData (const ConstBufferPtr &data); - - protected: - - private: - Ripemd160 (const Ripemd160 &); - Ripemd160 &operator= (const Ripemd160 &); - }; - - // SHA-1 - class Sha1 : public Hash - { - public: - Sha1 (); - virtual ~Sha1 () { } - - virtual void GetDigest (const BufferPtr &buffer); - virtual size_t GetBlockSize () const { return 64; } - virtual size_t GetDigestSize () const { return 160 / 8; } - virtual wstring GetName () const { return L"SHA-1"; } - virtual shared_ptr GetNew () const { return shared_ptr (new Sha1); } - virtual void Init (); - virtual void ProcessData (const ConstBufferPtr &data); - - protected: - - private: - Sha1 (const Sha1 &); - Sha1 &operator= (const Sha1 &); - }; - - // SHA-512 - class Sha512 : public Hash - { - public: - Sha512 (); - virtual ~Sha512 () { } - - virtual void GetDigest (const BufferPtr &buffer); - virtual size_t GetBlockSize () const { return 128; } - virtual size_t GetDigestSize () const { return 512 / 8; } - virtual wstring GetName () const { return L"SHA-512"; } - virtual shared_ptr GetNew () const { return shared_ptr (new Sha512); } - virtual void Init (); - virtual void ProcessData (const ConstBufferPtr &data); - - protected: - - private: - Sha512 (const Sha512 &); - Sha512 &operator= (const Sha512 &); - }; - - // Whirlpool - class Whirlpool : public Hash - { - public: - Whirlpool (); - virtual ~Whirlpool () { } - - virtual void GetDigest (const BufferPtr &buffer); - virtual size_t GetBlockSize () const { return 64; } - virtual size_t GetDigestSize () const { return 512 / 8; } - virtual wstring GetName () const { return L"Whirlpool"; } - virtual shared_ptr GetNew () const { return shared_ptr (new Whirlpool); } - virtual void Init (); - virtual void ProcessData (const ConstBufferPtr &data); - - protected: - - private: - Whirlpool (const Whirlpool &); - Whirlpool &operator= (const Whirlpool &); - }; -} - -#endif // TC_HEADER_Encryption_Hash +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_Hash +#define TC_HEADER_Encryption_Hash + +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + class Hash; + typedef list < shared_ptr > HashList; + + class Hash + { + public: + Hash () : Deprecated (false) { } + virtual ~Hash () { } + + static HashList GetAvailableAlgorithms (); + virtual void GetDigest (const BufferPtr &buffer) = 0; + virtual size_t GetBlockSize () const = 0; + virtual size_t GetDigestSize () const = 0; + virtual wstring GetName () const = 0; + virtual shared_ptr GetNew () const = 0; + virtual void Init () = 0; + bool IsDeprecated () const { return Deprecated; } + virtual void ProcessData (const ConstBufferPtr &data) = 0; + virtual void ValidateDataParameters (const ConstBufferPtr &data) const; + virtual void ValidateDigestParameters (const BufferPtr &buffer) const; + + protected: + SecureBuffer Context; + bool Deprecated; + + private: + Hash (const Hash &); + Hash &operator= (const Hash &); + }; + + // RIPEMD-160 + class Ripemd160 : public Hash + { + public: + Ripemd160 (); + virtual ~Ripemd160 () { } + + virtual void GetDigest (const BufferPtr &buffer); + virtual size_t GetBlockSize () const { return 64; } + virtual size_t GetDigestSize () const { return 160 / 8; } + virtual wstring GetName () const { return L"RIPEMD-160"; } + virtual shared_ptr GetNew () const { return shared_ptr (new Ripemd160); } + virtual void Init (); + virtual void ProcessData (const ConstBufferPtr &data); + + protected: + + private: + Ripemd160 (const Ripemd160 &); + Ripemd160 &operator= (const Ripemd160 &); + }; + + // SHA-1 + class Sha1 : public Hash + { + public: + Sha1 (); + virtual ~Sha1 () { } + + virtual void GetDigest (const BufferPtr &buffer); + virtual size_t GetBlockSize () const { return 64; } + virtual size_t GetDigestSize () const { return 160 / 8; } + virtual wstring GetName () const { return L"SHA-1"; } + virtual shared_ptr GetNew () const { return shared_ptr (new Sha1); } + virtual void Init (); + virtual void ProcessData (const ConstBufferPtr &data); + + protected: + + private: + Sha1 (const Sha1 &); + Sha1 &operator= (const Sha1 &); + }; + + // SHA-512 + class Sha512 : public Hash + { + public: + Sha512 (); + virtual ~Sha512 () { } + + virtual void GetDigest (const BufferPtr &buffer); + virtual size_t GetBlockSize () const { return 128; } + virtual size_t GetDigestSize () const { return 512 / 8; } + virtual wstring GetName () const { return L"SHA-512"; } + virtual shared_ptr GetNew () const { return shared_ptr (new Sha512); } + virtual void Init (); + virtual void ProcessData (const ConstBufferPtr &data); + + protected: + + private: + Sha512 (const Sha512 &); + Sha512 &operator= (const Sha512 &); + }; + + // Whirlpool + class Whirlpool : public Hash + { + public: + Whirlpool (); + virtual ~Whirlpool () { } + + virtual void GetDigest (const BufferPtr &buffer); + virtual size_t GetBlockSize () const { return 64; } + virtual size_t GetDigestSize () const { return 512 / 8; } + virtual wstring GetName () const { return L"Whirlpool"; } + virtual shared_ptr GetNew () const { return shared_ptr (new Whirlpool); } + virtual void Init (); + virtual void ProcessData (const ConstBufferPtr &data); + + protected: + + private: + Whirlpool (const Whirlpool &); + Whirlpool &operator= (const Whirlpool &); + }; +} + +#endif // TC_HEADER_Encryption_Hash diff --git a/Volume/Keyfile.cpp b/Volume/Keyfile.cpp index e4ab8f4..e275898 100644 --- a/Volume/Keyfile.cpp +++ b/Volume/Keyfile.cpp @@ -1,164 +1,164 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Platform/Serializer.h" -#include "Common/SecurityToken.h" -#include "Crc32.h" -#include "Keyfile.h" - -namespace TrueCrypt -{ - void Keyfile::Apply (const BufferPtr &pool) const - { - if (Path.IsDirectory()) - throw ParameterIncorrect (SRC_POS); - - File file; - - Crc32 crc32; - size_t poolPos = 0; - uint64 totalLength = 0; - uint64 readLength; - - SecureBuffer keyfileBuf (File::GetOptimalReadSize()); - - if (SecurityToken::IsKeyfilePathValid (Path)) - { - // Apply keyfile generated by a security token - vector keyfileData; - SecurityToken::GetKeyfileData (SecurityTokenKeyfile (wstring (Path)), keyfileData); - - if (keyfileData.size() < MinProcessedLength) - throw InsufficientData (SRC_POS, Path); - - for (size_t i = 0; i < keyfileData.size(); i++) - { - uint32 crc = crc32.Process (keyfileData[i]); - - pool[poolPos++] += (byte) (crc >> 24); - pool[poolPos++] += (byte) (crc >> 16); - pool[poolPos++] += (byte) (crc >> 8); - pool[poolPos++] += (byte) crc; - - if (poolPos >= pool.Size()) - poolPos = 0; - - if (++totalLength >= MaxProcessedLength) - break; - } - - Memory::Erase (&keyfileData.front(), keyfileData.size()); - goto done; - } - - file.Open (Path, File::OpenRead, File::ShareRead, File::PreserveTimestamps); - - while ((readLength = file.Read (keyfileBuf)) > 0) - { - for (size_t i = 0; i < readLength; i++) - { - uint32 crc = crc32.Process (keyfileBuf[i]); - - pool[poolPos++] += (byte) (crc >> 24); - pool[poolPos++] += (byte) (crc >> 16); - pool[poolPos++] += (byte) (crc >> 8); - pool[poolPos++] += (byte) crc; - - if (poolPos >= pool.Size()) - poolPos = 0; - - if (++totalLength >= MaxProcessedLength) - goto done; - } - } -done: - if (totalLength < MinProcessedLength) - throw InsufficientData (SRC_POS, Path); - } - - shared_ptr Keyfile::ApplyListToPassword (shared_ptr keyfiles, shared_ptr password) - { - if (!password) - password.reset (new VolumePassword); - - if (!keyfiles || keyfiles->size() < 1) - return password; - - KeyfileList keyfilesExp; - - // Enumerate directories - foreach (shared_ptr keyfile, *keyfiles) - { - if (FilesystemPath (*keyfile).IsDirectory()) - { - foreach_ref (const FilePath &path, Directory::GetFilePaths (*keyfile)) - { - keyfilesExp.push_back (make_shared (path)); - } - } - else - { - keyfilesExp.push_back (keyfile); - } - } - - make_shared_auto (VolumePassword, newPassword); - - if (keyfilesExp.size() < 1) - { - newPassword->Set (*password); - } - else - { - SecureBuffer keyfilePool (VolumePassword::MaxSize); - - // Pad password with zeros if shorter than max length - keyfilePool.Zero(); - keyfilePool.CopyFrom (ConstBufferPtr (password->DataPtr(), password->Size())); - - // Apply all keyfiles - foreach_ref (const Keyfile &k, keyfilesExp) - { - k.Apply (keyfilePool); - } - - newPassword->Set (keyfilePool); - } - - return newPassword; - } - - shared_ptr Keyfile::DeserializeList (shared_ptr stream, const string &name) - { - shared_ptr keyfiles; - Serializer sr (stream); - - if (!sr.DeserializeBool (name + "Null")) - { - keyfiles.reset (new KeyfileList); - foreach (const wstring &k, sr.DeserializeWStringList (name)) - keyfiles->push_back (make_shared (k)); - } - return keyfiles; - } - - void Keyfile::SerializeList (shared_ptr stream, const string &name, shared_ptr keyfiles) - { - Serializer sr (stream); - sr.Serialize (name + "Null", keyfiles == nullptr); - if (keyfiles) - { - list sl; - - foreach_ref (const Keyfile &k, *keyfiles) - sl.push_back (FilesystemPath (k)); - - sr.Serialize (name, sl); - } - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Platform/Serializer.h" +#include "Common/SecurityToken.h" +#include "Crc32.h" +#include "Keyfile.h" + +namespace TrueCrypt +{ + void Keyfile::Apply (const BufferPtr &pool) const + { + if (Path.IsDirectory()) + throw ParameterIncorrect (SRC_POS); + + File file; + + Crc32 crc32; + size_t poolPos = 0; + uint64 totalLength = 0; + uint64 readLength; + + SecureBuffer keyfileBuf (File::GetOptimalReadSize()); + + if (SecurityToken::IsKeyfilePathValid (Path)) + { + // Apply keyfile generated by a security token + vector keyfileData; + SecurityToken::GetKeyfileData (SecurityTokenKeyfile (wstring (Path)), keyfileData); + + if (keyfileData.size() < MinProcessedLength) + throw InsufficientData (SRC_POS, Path); + + for (size_t i = 0; i < keyfileData.size(); i++) + { + uint32 crc = crc32.Process (keyfileData[i]); + + pool[poolPos++] += (byte) (crc >> 24); + pool[poolPos++] += (byte) (crc >> 16); + pool[poolPos++] += (byte) (crc >> 8); + pool[poolPos++] += (byte) crc; + + if (poolPos >= pool.Size()) + poolPos = 0; + + if (++totalLength >= MaxProcessedLength) + break; + } + + Memory::Erase (&keyfileData.front(), keyfileData.size()); + goto done; + } + + file.Open (Path, File::OpenRead, File::ShareRead, File::PreserveTimestamps); + + while ((readLength = file.Read (keyfileBuf)) > 0) + { + for (size_t i = 0; i < readLength; i++) + { + uint32 crc = crc32.Process (keyfileBuf[i]); + + pool[poolPos++] += (byte) (crc >> 24); + pool[poolPos++] += (byte) (crc >> 16); + pool[poolPos++] += (byte) (crc >> 8); + pool[poolPos++] += (byte) crc; + + if (poolPos >= pool.Size()) + poolPos = 0; + + if (++totalLength >= MaxProcessedLength) + goto done; + } + } +done: + if (totalLength < MinProcessedLength) + throw InsufficientData (SRC_POS, Path); + } + + shared_ptr Keyfile::ApplyListToPassword (shared_ptr keyfiles, shared_ptr password) + { + if (!password) + password.reset (new VolumePassword); + + if (!keyfiles || keyfiles->size() < 1) + return password; + + KeyfileList keyfilesExp; + + // Enumerate directories + foreach (shared_ptr keyfile, *keyfiles) + { + if (FilesystemPath (*keyfile).IsDirectory()) + { + foreach_ref (const FilePath &path, Directory::GetFilePaths (*keyfile)) + { + keyfilesExp.push_back (make_shared (path)); + } + } + else + { + keyfilesExp.push_back (keyfile); + } + } + + make_shared_auto (VolumePassword, newPassword); + + if (keyfilesExp.size() < 1) + { + newPassword->Set (*password); + } + else + { + SecureBuffer keyfilePool (VolumePassword::MaxSize); + + // Pad password with zeros if shorter than max length + keyfilePool.Zero(); + keyfilePool.CopyFrom (ConstBufferPtr (password->DataPtr(), password->Size())); + + // Apply all keyfiles + foreach_ref (const Keyfile &k, keyfilesExp) + { + k.Apply (keyfilePool); + } + + newPassword->Set (keyfilePool); + } + + return newPassword; + } + + shared_ptr Keyfile::DeserializeList (shared_ptr stream, const string &name) + { + shared_ptr keyfiles; + Serializer sr (stream); + + if (!sr.DeserializeBool (name + "Null")) + { + keyfiles.reset (new KeyfileList); + foreach (const wstring &k, sr.DeserializeWStringList (name)) + keyfiles->push_back (make_shared (k)); + } + return keyfiles; + } + + void Keyfile::SerializeList (shared_ptr stream, const string &name, shared_ptr keyfiles) + { + Serializer sr (stream); + sr.Serialize (name + "Null", keyfiles == nullptr); + if (keyfiles) + { + list sl; + + foreach_ref (const Keyfile &k, *keyfiles) + sl.push_back (FilesystemPath (k)); + + sr.Serialize (name, sl); + } + } +} diff --git a/Volume/Keyfile.h b/Volume/Keyfile.h index 7a2e49d..88caf9a 100644 --- a/Volume/Keyfile.h +++ b/Volume/Keyfile.h @@ -1,46 +1,46 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_Keyfile -#define TC_HEADER_Encryption_Keyfile - -#include "Platform/Platform.h" -#include "Platform/Stream.h" -#include "VolumePassword.h" - -namespace TrueCrypt -{ - class Keyfile; - typedef list < shared_ptr > KeyfileList; - - class Keyfile - { - public: - Keyfile (const FilesystemPath &path) : Path (path) { } - virtual ~Keyfile () { }; - - operator FilesystemPath () const { return Path; } - static shared_ptr ApplyListToPassword (shared_ptr keyfiles, shared_ptr password); - static shared_ptr DeserializeList (shared_ptr stream, const string &name); - static void SerializeList (shared_ptr stream, const string &name, shared_ptr keyfiles); - - static const int MinProcessedLength = 1; - static const int MaxProcessedLength = 1024 * 1024; - - protected: - void Apply (const BufferPtr &pool) const; - - FilesystemPath Path; - - private: - Keyfile (const Keyfile &); - Keyfile &operator= (const Keyfile &); - }; -} - -#endif // TC_HEADER_Encryption_Keyfile +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_Keyfile +#define TC_HEADER_Encryption_Keyfile + +#include "Platform/Platform.h" +#include "Platform/Stream.h" +#include "VolumePassword.h" + +namespace TrueCrypt +{ + class Keyfile; + typedef list < shared_ptr > KeyfileList; + + class Keyfile + { + public: + Keyfile (const FilesystemPath &path) : Path (path) { } + virtual ~Keyfile () { }; + + operator FilesystemPath () const { return Path; } + static shared_ptr ApplyListToPassword (shared_ptr keyfiles, shared_ptr password); + static shared_ptr DeserializeList (shared_ptr stream, const string &name); + static void SerializeList (shared_ptr stream, const string &name, shared_ptr keyfiles); + + static const size_t MinProcessedLength = 1; + static const size_t MaxProcessedLength = 1024 * 1024; + + protected: + void Apply (const BufferPtr &pool) const; + + FilesystemPath Path; + + private: + Keyfile (const Keyfile &); + Keyfile &operator= (const Keyfile &); + }; +} + +#endif // TC_HEADER_Encryption_Keyfile diff --git a/Volume/Pkcs5Kdf.cpp b/Volume/Pkcs5Kdf.cpp index 4f8009c..eb8a4e6 100644 --- a/Volume/Pkcs5Kdf.cpp +++ b/Volume/Pkcs5Kdf.cpp @@ -1,96 +1,96 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Common/Pkcs5.h" -#include "Pkcs5Kdf.h" -#include "VolumePassword.h" - -namespace TrueCrypt -{ - Pkcs5Kdf::Pkcs5Kdf () - { - } - - Pkcs5Kdf::~Pkcs5Kdf () - { - } - - void Pkcs5Kdf::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt) const - { - DeriveKey (key, password, salt, GetIterationCount()); - } - - shared_ptr Pkcs5Kdf::GetAlgorithm (const wstring &name) - { - foreach (shared_ptr kdf, GetAvailableAlgorithms()) - { - if (kdf->GetName() == name) - return kdf; - } - throw ParameterIncorrect (SRC_POS); - } - - shared_ptr Pkcs5Kdf::GetAlgorithm (const Hash &hash) - { - foreach (shared_ptr kdf, GetAvailableAlgorithms()) - { - if (typeid (*kdf->GetHash()) == typeid (hash)) - return kdf; - } - - throw ParameterIncorrect (SRC_POS); - } - - Pkcs5KdfList Pkcs5Kdf::GetAvailableAlgorithms () - { - Pkcs5KdfList l; - - l.push_back (shared_ptr (new Pkcs5HmacRipemd160 ())); - l.push_back (shared_ptr (new Pkcs5HmacSha512 ())); - l.push_back (shared_ptr (new Pkcs5HmacWhirlpool ())); - l.push_back (shared_ptr (new Pkcs5HmacSha1 ())); - - return l; - } - - void Pkcs5Kdf::ValidateParameters (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const - { - if (key.Size() < 1 || password.Size() < 1 || salt.Size() < 1 || iterationCount < 1) - throw ParameterIncorrect (SRC_POS); - } - - void Pkcs5HmacRipemd160::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const - { - ValidateParameters (key, password, salt, iterationCount); - derive_key_ripemd160 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); - } - - void Pkcs5HmacRipemd160_1000::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const - { - ValidateParameters (key, password, salt, iterationCount); - derive_key_ripemd160 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); - } - - void Pkcs5HmacSha1::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const - { - ValidateParameters (key, password, salt, iterationCount); - derive_key_sha1 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); - } - - void Pkcs5HmacSha512::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const - { - ValidateParameters (key, password, salt, iterationCount); - derive_key_sha512 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); - } - - void Pkcs5HmacWhirlpool::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const - { - ValidateParameters (key, password, salt, iterationCount); - derive_key_whirlpool ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Common/Pkcs5.h" +#include "Pkcs5Kdf.h" +#include "VolumePassword.h" + +namespace TrueCrypt +{ + Pkcs5Kdf::Pkcs5Kdf () + { + } + + Pkcs5Kdf::~Pkcs5Kdf () + { + } + + void Pkcs5Kdf::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt) const + { + DeriveKey (key, password, salt, GetIterationCount()); + } + + shared_ptr Pkcs5Kdf::GetAlgorithm (const wstring &name) + { + foreach (shared_ptr kdf, GetAvailableAlgorithms()) + { + if (kdf->GetName() == name) + return kdf; + } + throw ParameterIncorrect (SRC_POS); + } + + shared_ptr Pkcs5Kdf::GetAlgorithm (const Hash &hash) + { + foreach (shared_ptr kdf, GetAvailableAlgorithms()) + { + if (typeid (*kdf->GetHash()) == typeid (hash)) + return kdf; + } + + throw ParameterIncorrect (SRC_POS); + } + + Pkcs5KdfList Pkcs5Kdf::GetAvailableAlgorithms () + { + Pkcs5KdfList l; + + l.push_back (shared_ptr (new Pkcs5HmacRipemd160 ())); + l.push_back (shared_ptr (new Pkcs5HmacSha512 ())); + l.push_back (shared_ptr (new Pkcs5HmacWhirlpool ())); + l.push_back (shared_ptr (new Pkcs5HmacSha1 ())); + + return l; + } + + void Pkcs5Kdf::ValidateParameters (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const + { + if (key.Size() < 1 || password.Size() < 1 || salt.Size() < 1 || iterationCount < 1) + throw ParameterIncorrect (SRC_POS); + } + + void Pkcs5HmacRipemd160::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const + { + ValidateParameters (key, password, salt, iterationCount); + derive_key_ripemd160 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); + } + + void Pkcs5HmacRipemd160_1000::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const + { + ValidateParameters (key, password, salt, iterationCount); + derive_key_ripemd160 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); + } + + void Pkcs5HmacSha1::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const + { + ValidateParameters (key, password, salt, iterationCount); + derive_key_sha1 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); + } + + void Pkcs5HmacSha512::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const + { + ValidateParameters (key, password, salt, iterationCount); + derive_key_sha512 ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); + } + + void Pkcs5HmacWhirlpool::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const + { + ValidateParameters (key, password, salt, iterationCount); + derive_key_whirlpool ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size()); + } +} diff --git a/Volume/Pkcs5Kdf.h b/Volume/Pkcs5Kdf.h index 2a04522..854f469 100644 --- a/Volume/Pkcs5Kdf.h +++ b/Volume/Pkcs5Kdf.h @@ -1,127 +1,127 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_Pkcs5 -#define TC_HEADER_Encryption_Pkcs5 - -#include "Platform/Platform.h" -#include "Hash.h" -#include "VolumePassword.h" - -namespace TrueCrypt -{ - class Pkcs5Kdf; - typedef list < shared_ptr > Pkcs5KdfList; - - class Pkcs5Kdf - { - public: - virtual ~Pkcs5Kdf (); - - virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt) const; - virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const = 0; - static shared_ptr GetAlgorithm (const wstring &name); - static shared_ptr GetAlgorithm (const Hash &hash); - static Pkcs5KdfList GetAvailableAlgorithms (); - virtual shared_ptr GetHash () const = 0; - virtual int GetIterationCount () const = 0; - virtual wstring GetName () const = 0; - virtual bool IsDeprecated () const { return GetHash()->IsDeprecated(); } - - protected: - Pkcs5Kdf (); - - void ValidateParameters (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; - - private: - Pkcs5Kdf (const Pkcs5Kdf &); - Pkcs5Kdf &operator= (const Pkcs5Kdf &); - }; - - class Pkcs5HmacRipemd160 : public Pkcs5Kdf - { - public: - Pkcs5HmacRipemd160 () { } - virtual ~Pkcs5HmacRipemd160 () { } - - virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; - virtual shared_ptr GetHash () const { return shared_ptr (new Ripemd160); } - virtual int GetIterationCount () const { return 2000; } - virtual wstring GetName () const { return L"HMAC-RIPEMD-160"; } - - private: - Pkcs5HmacRipemd160 (const Pkcs5HmacRipemd160 &); - Pkcs5HmacRipemd160 &operator= (const Pkcs5HmacRipemd160 &); - }; - - class Pkcs5HmacRipemd160_1000 : public Pkcs5Kdf - { - public: - Pkcs5HmacRipemd160_1000 () { } - virtual ~Pkcs5HmacRipemd160_1000 () { } - - virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; - virtual shared_ptr GetHash () const { return shared_ptr (new Ripemd160); } - virtual int GetIterationCount () const { return 1000; } - virtual wstring GetName () const { return L"HMAC-RIPEMD-160"; } - - private: - Pkcs5HmacRipemd160_1000 (const Pkcs5HmacRipemd160_1000 &); - Pkcs5HmacRipemd160_1000 &operator= (const Pkcs5HmacRipemd160_1000 &); - }; - - class Pkcs5HmacSha1 : public Pkcs5Kdf - { - public: - Pkcs5HmacSha1 () { } - virtual ~Pkcs5HmacSha1 () { } - - virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; - virtual shared_ptr GetHash () const { return shared_ptr (new Sha1); } - virtual int GetIterationCount () const { return 2000; } - virtual wstring GetName () const { return L"HMAC-SHA-1"; } - - private: - Pkcs5HmacSha1 (const Pkcs5HmacSha1 &); - Pkcs5HmacSha1 &operator= (const Pkcs5HmacSha1 &); - }; - - class Pkcs5HmacSha512 : public Pkcs5Kdf - { - public: - Pkcs5HmacSha512 () { } - virtual ~Pkcs5HmacSha512 () { } - - virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; - virtual shared_ptr GetHash () const { return shared_ptr (new Sha512); } - virtual int GetIterationCount () const { return 1000; } - virtual wstring GetName () const { return L"HMAC-SHA-512"; } - - private: - Pkcs5HmacSha512 (const Pkcs5HmacSha512 &); - Pkcs5HmacSha512 &operator= (const Pkcs5HmacSha512 &); - }; - - class Pkcs5HmacWhirlpool : public Pkcs5Kdf - { - public: - Pkcs5HmacWhirlpool () { } - virtual ~Pkcs5HmacWhirlpool () { } - - virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; - virtual shared_ptr GetHash () const { return shared_ptr (new Whirlpool); } - virtual int GetIterationCount () const { return 1000; } - virtual wstring GetName () const { return L"HMAC-Whirlpool"; } - - private: - Pkcs5HmacWhirlpool (const Pkcs5HmacWhirlpool &); - Pkcs5HmacWhirlpool &operator= (const Pkcs5HmacWhirlpool &); - }; -} - -#endif // TC_HEADER_Encryption_Pkcs5 +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_Pkcs5 +#define TC_HEADER_Encryption_Pkcs5 + +#include "Platform/Platform.h" +#include "Hash.h" +#include "VolumePassword.h" + +namespace TrueCrypt +{ + class Pkcs5Kdf; + typedef list < shared_ptr > Pkcs5KdfList; + + class Pkcs5Kdf + { + public: + virtual ~Pkcs5Kdf (); + + virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt) const; + virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const = 0; + static shared_ptr GetAlgorithm (const wstring &name); + static shared_ptr GetAlgorithm (const Hash &hash); + static Pkcs5KdfList GetAvailableAlgorithms (); + virtual shared_ptr GetHash () const = 0; + virtual int GetIterationCount () const = 0; + virtual wstring GetName () const = 0; + virtual bool IsDeprecated () const { return GetHash()->IsDeprecated(); } + + protected: + Pkcs5Kdf (); + + void ValidateParameters (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; + + private: + Pkcs5Kdf (const Pkcs5Kdf &); + Pkcs5Kdf &operator= (const Pkcs5Kdf &); + }; + + class Pkcs5HmacRipemd160 : public Pkcs5Kdf + { + public: + Pkcs5HmacRipemd160 () { } + virtual ~Pkcs5HmacRipemd160 () { } + + virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; + virtual shared_ptr GetHash () const { return shared_ptr (new Ripemd160); } + virtual int GetIterationCount () const { return 2000; } + virtual wstring GetName () const { return L"HMAC-RIPEMD-160"; } + + private: + Pkcs5HmacRipemd160 (const Pkcs5HmacRipemd160 &); + Pkcs5HmacRipemd160 &operator= (const Pkcs5HmacRipemd160 &); + }; + + class Pkcs5HmacRipemd160_1000 : public Pkcs5Kdf + { + public: + Pkcs5HmacRipemd160_1000 () { } + virtual ~Pkcs5HmacRipemd160_1000 () { } + + virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; + virtual shared_ptr GetHash () const { return shared_ptr (new Ripemd160); } + virtual int GetIterationCount () const { return 1000; } + virtual wstring GetName () const { return L"HMAC-RIPEMD-160"; } + + private: + Pkcs5HmacRipemd160_1000 (const Pkcs5HmacRipemd160_1000 &); + Pkcs5HmacRipemd160_1000 &operator= (const Pkcs5HmacRipemd160_1000 &); + }; + + class Pkcs5HmacSha1 : public Pkcs5Kdf + { + public: + Pkcs5HmacSha1 () { } + virtual ~Pkcs5HmacSha1 () { } + + virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; + virtual shared_ptr GetHash () const { return shared_ptr (new Sha1); } + virtual int GetIterationCount () const { return 2000; } + virtual wstring GetName () const { return L"HMAC-SHA-1"; } + + private: + Pkcs5HmacSha1 (const Pkcs5HmacSha1 &); + Pkcs5HmacSha1 &operator= (const Pkcs5HmacSha1 &); + }; + + class Pkcs5HmacSha512 : public Pkcs5Kdf + { + public: + Pkcs5HmacSha512 () { } + virtual ~Pkcs5HmacSha512 () { } + + virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; + virtual shared_ptr GetHash () const { return shared_ptr (new Sha512); } + virtual int GetIterationCount () const { return 1000; } + virtual wstring GetName () const { return L"HMAC-SHA-512"; } + + private: + Pkcs5HmacSha512 (const Pkcs5HmacSha512 &); + Pkcs5HmacSha512 &operator= (const Pkcs5HmacSha512 &); + }; + + class Pkcs5HmacWhirlpool : public Pkcs5Kdf + { + public: + Pkcs5HmacWhirlpool () { } + virtual ~Pkcs5HmacWhirlpool () { } + + virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const; + virtual shared_ptr GetHash () const { return shared_ptr (new Whirlpool); } + virtual int GetIterationCount () const { return 1000; } + virtual wstring GetName () const { return L"HMAC-Whirlpool"; } + + private: + Pkcs5HmacWhirlpool (const Pkcs5HmacWhirlpool &); + Pkcs5HmacWhirlpool &operator= (const Pkcs5HmacWhirlpool &); + }; +} + +#endif // TC_HEADER_Encryption_Pkcs5 diff --git a/Volume/Version.h b/Volume/Version.h index ffd6fe9..e5e0561 100644 --- a/Volume/Version.h +++ b/Volume/Version.h @@ -1,25 +1,25 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_Version -#define TC_HEADER_Volume_Version - -#include "Platform/PlatformBase.h" -#include "Common/Tcdefs.h" - -namespace TrueCrypt -{ - class Version - { - public: - static const string String () { return VERSION_STRING; } - static const uint16 Number () { return VERSION_NUM; } - }; -} - -#endif // TC_HEADER_Volume_Version +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_Version +#define TC_HEADER_Volume_Version + +#include "Platform/PlatformBase.h" +#include "Common/Tcdefs.h" + +namespace TrueCrypt +{ + class Version + { + public: + static const string String () { return VERSION_STRING; } + static const uint16 Number () { return VERSION_NUM; } + }; +} + +#endif // TC_HEADER_Volume_Version diff --git a/Volume/Volume.cpp b/Volume/Volume.cpp index a447d0c..391e10a 100644 --- a/Volume/Volume.cpp +++ b/Volume/Volume.cpp @@ -1,376 +1,376 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_WINDOWS -#include -#endif -#include "EncryptionModeLRW.h" -#include "EncryptionModeXTS.h" -#include "Volume.h" -#include "VolumeHeader.h" -#include "VolumeLayout.h" -#include "Common/Crypto.h" - -namespace TrueCrypt -{ - Volume::Volume () - : HiddenVolumeProtectionTriggered (false), - SystemEncryption (false), - VolumeDataSize (0), - TopWriteOffset (0), - TotalDataRead (0), - TotalDataWritten (0) - { - } - - Volume::~Volume () - { - } - - void Volume::CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength) - { - uint64 writeHostEndOffset = writeHostOffset + writeLength - 1; - - if ((writeHostOffset < ProtectedRangeStart) ? (writeHostEndOffset >= ProtectedRangeStart) : (writeHostOffset <= ProtectedRangeEnd - 1)) - { - HiddenVolumeProtectionTriggered = true; - throw VolumeProtected (SRC_POS); - } - } - - void Volume::Close () - { - if (VolumeFile.get() == nullptr) - throw NotInitialized (SRC_POS); - - VolumeFile.reset(); - } - - shared_ptr Volume::GetEncryptionAlgorithm () const - { - if_debug (ValidateState ()); - return EA; - } - - shared_ptr Volume::GetEncryptionMode () const - { - if_debug (ValidateState ()); - return EA->GetMode(); - } - - void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) - { - make_shared_auto (File, file); - - File::FileOpenFlags flags = (preserveTimestamps ? File::PreserveTimestamps : File::FlagsNone); - - try - { - if (protection == VolumeProtection::ReadOnly) - file->Open (volumePath, File::OpenRead, File::ShareRead, flags); - else - file->Open (volumePath, File::OpenReadWrite, File::ShareNone, flags); - } - catch (SystemException &e) - { - if (e.GetErrorCode() == -#ifdef TC_WINDOWS - ERROR_SHARING_VIOLATION) -#else - EAGAIN) -#endif - { - if (!sharedAccessAllowed) - throw VolumeHostInUse (SRC_POS); - - file->Open (volumePath, protection == VolumeProtection::ReadOnly ? File::OpenRead : File::OpenReadWrite, File::ShareReadWriteIgnoreLock, flags); - } - else - throw; - } - - return Open (file, password, keyfiles, protection, protectionPassword, protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); - } - - void Volume::Open (shared_ptr volumeFile, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) - { - if (!volumeFile) - throw ParameterIncorrect (SRC_POS); - - Protection = protection; - VolumeFile = volumeFile; - SystemEncryption = partitionInSystemEncryptionScope; - - try - { - VolumeHostSize = VolumeFile->Length(); - shared_ptr passwordKey = Keyfile::ApplyListToPassword (keyfiles, password); - - bool skipLayoutV1Normal = false; - - // Test volume layouts - foreach (shared_ptr layout, VolumeLayout::GetAvailableLayouts (volumeType)) - { - if (skipLayoutV1Normal && typeid (*layout) == typeid (VolumeLayoutV1Normal)) - { - // Skip VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal - continue; - } - - if (useBackupHeaders && !layout->HasBackupHeader()) - continue; - - SecureBuffer headerBuffer (layout->GetHeaderSize()); - - if (layout->HasDriveHeader()) - { - if (!partitionInSystemEncryptionScope) - continue; - - if (!GetPath().IsDevice()) - throw PartitionDeviceRequired (SRC_POS); - - File driveDevice; - driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition()); - - int headerOffset = layout->GetHeaderOffset(); - - if (headerOffset >= 0) - driveDevice.SeekAt (headerOffset); - else - driveDevice.SeekEnd (headerOffset); - - if (driveDevice.Read (headerBuffer) != layout->GetHeaderSize()) - continue; - } - else - { - if (partitionInSystemEncryptionScope) - continue; - - int headerOffset = useBackupHeaders ? layout->GetBackupHeaderOffset() : layout->GetHeaderOffset(); - - if (headerOffset >= 0) - VolumeFile->SeekAt (headerOffset); - else - VolumeFile->SeekEnd (headerOffset); - - if (VolumeFile->Read (headerBuffer) != layout->GetHeaderSize()) - continue; - } - - EncryptionAlgorithmList layoutEncryptionAlgorithms = layout->GetSupportedEncryptionAlgorithms(); - EncryptionModeList layoutEncryptionModes = layout->GetSupportedEncryptionModes(); - - if (typeid (*layout) == typeid (VolumeLayoutV2Normal)) - { - skipLayoutV1Normal = true; - - // Test all algorithms and modes of VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal - layoutEncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms(); - layoutEncryptionModes = EncryptionMode::GetAvailableModes(); - } - - shared_ptr header = layout->GetHeader(); - - if (header->Decrypt (headerBuffer, *passwordKey, layout->GetSupportedKeyDerivationFunctions(), layoutEncryptionAlgorithms, layoutEncryptionModes)) - { - // Header decrypted - - if (typeid (*layout) == typeid (VolumeLayoutV2Normal) && header->GetRequiredMinProgramVersion() < 0x600) - { - // VolumeLayoutV1Normal has been opened as VolumeLayoutV2Normal - layout.reset (new VolumeLayoutV1Normal); - header->SetSize (layout->GetHeaderSize()); - layout->SetHeader (header); - } - - Type = layout->GetType(); - SectorSize = header->GetSectorSize(); - - VolumeDataOffset = layout->GetDataOffset (VolumeHostSize); - VolumeDataSize = layout->GetDataSize (VolumeHostSize); - - Header = header; - Layout = layout; - EA = header->GetEncryptionAlgorithm(); - EncryptionMode &mode = *EA->GetMode(); - - if (layout->HasDriveHeader()) - { - if (header->GetEncryptedAreaLength() != header->GetVolumeDataSize()) - throw VolumeEncryptionNotCompleted (SRC_POS); - - uint64 partitionStartOffset = VolumeFile->GetPartitionDeviceStartOffset(); - - if (partitionStartOffset < header->GetEncryptedAreaStart() - || partitionStartOffset >= header->GetEncryptedAreaStart() + header->GetEncryptedAreaLength()) - throw PasswordIncorrect (SRC_POS); - - mode.SetSectorOffset (partitionStartOffset / ENCRYPTION_DATA_UNIT_SIZE); - } - else if (typeid (mode) == typeid (EncryptionModeLRW)) - { - mode.SetSectorOffset (VolumeDataOffset / SectorSize); - } - - // Volume protection - if (Protection == VolumeProtection::HiddenVolumeReadOnly) - { - if (Type == VolumeType::Hidden) - throw PasswordIncorrect (SRC_POS); - else - { - try - { - Volume protectedVolume; - - protectedVolume.Open (VolumeFile, - protectionPassword, protectionKeyfiles, - VolumeProtection::ReadOnly, - shared_ptr (), shared_ptr (), - VolumeType::Hidden, - useBackupHeaders); - - if (protectedVolume.GetType() != VolumeType::Hidden) - ParameterIncorrect (SRC_POS); - - ProtectedRangeStart = protectedVolume.VolumeDataOffset; - ProtectedRangeEnd = protectedVolume.VolumeDataOffset + protectedVolume.VolumeDataSize; - - if (typeid (*protectedVolume.Layout) == typeid (VolumeLayoutV1Hidden)) - ProtectedRangeEnd += protectedVolume.Layout->GetHeaderSize(); - } - catch (PasswordException&) - { - if (protectionKeyfiles && !protectionKeyfiles->empty()) - throw ProtectionPasswordKeyfilesIncorrect (SRC_POS); - throw ProtectionPasswordIncorrect (SRC_POS); - } - } - } - return; - } - } - - if (partitionInSystemEncryptionScope) - throw PasswordOrKeyboardLayoutIncorrect (SRC_POS); - - if (!partitionInSystemEncryptionScope && GetPath().IsDevice()) - { - // Check if the device contains TrueCrypt Boot Loader - try - { - File driveDevice; - driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition()); - - Buffer mbr (VolumeFile->GetDeviceSectorSize()); - driveDevice.ReadAt (mbr, 0); - - // Search for the string "TrueCrypt" - size_t nameLen = strlen (TC_APP_NAME); - for (size_t i = 0; i < mbr.Size() - nameLen; ++i) - { - if (memcmp (mbr.Ptr() + i, TC_APP_NAME, nameLen) == 0) - throw PasswordOrMountOptionsIncorrect (SRC_POS); - } - } - catch (PasswordOrMountOptionsIncorrect&) { throw; } - catch (...) { } - } - - if (keyfiles && !keyfiles->empty()) - throw PasswordKeyfilesIncorrect (SRC_POS); - throw PasswordIncorrect (SRC_POS); - } - catch (...) - { - Close(); - throw; - } - } - - void Volume::ReadSectors (const BufferPtr &buffer, uint64 byteOffset) - { - if_debug (ValidateState ()); - - uint64 length = buffer.Size(); - uint64 hostOffset = VolumeDataOffset + byteOffset; - - if (length % SectorSize != 0 || byteOffset % SectorSize != 0) - throw ParameterIncorrect (SRC_POS); - - if (VolumeFile->ReadAt (buffer, hostOffset) != length) - throw MissingVolumeData (SRC_POS); - - EA->DecryptSectors (buffer, hostOffset / SectorSize, length / SectorSize, SectorSize); - - TotalDataRead += length; - } - - void Volume::ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf) - { - if_debug (ValidateState ()); - - if (Protection == VolumeProtection::ReadOnly) - throw VolumeReadOnly (SRC_POS); - - SecureBuffer newHeaderBuffer (Layout->GetHeaderSize()); - - Header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, newPkcs5Kdf); - - int headerOffset = backupHeader ? Layout->GetBackupHeaderOffset() : Layout->GetHeaderOffset(); - - if (headerOffset >= 0) - VolumeFile->SeekAt (headerOffset); - else - VolumeFile->SeekEnd (headerOffset); - - VolumeFile->Write (newHeaderBuffer); - } - - void Volume::ValidateState () const - { - if (VolumeFile.get() == nullptr) - throw NotInitialized (SRC_POS); - } - - void Volume::WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset) - { - if_debug (ValidateState ()); - - uint64 length = buffer.Size(); - uint64 hostOffset = VolumeDataOffset + byteOffset; - - if (length % SectorSize != 0 - || byteOffset % SectorSize != 0 - || byteOffset + length > VolumeDataSize) - throw ParameterIncorrect (SRC_POS); - - if (Protection == VolumeProtection::ReadOnly) - throw VolumeReadOnly (SRC_POS); - - if (HiddenVolumeProtectionTriggered) - throw VolumeProtected (SRC_POS); - - if (Protection == VolumeProtection::HiddenVolumeReadOnly) - CheckProtectedRange (hostOffset, length); - - SecureBuffer encBuf (buffer.Size()); - encBuf.CopyFrom (buffer); - - EA->EncryptSectors (encBuf, hostOffset / SectorSize, length / SectorSize, SectorSize); - VolumeFile->WriteAt (encBuf, hostOffset); - - TotalDataWritten += length; - - uint64 writeEndOffset = byteOffset + buffer.Size(); - if (writeEndOffset > TopWriteOffset) - TopWriteOffset = writeEndOffset; - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_WINDOWS +#include +#endif +#include "EncryptionModeLRW.h" +#include "EncryptionModeXTS.h" +#include "Volume.h" +#include "VolumeHeader.h" +#include "VolumeLayout.h" +#include "Common/Crypto.h" + +namespace TrueCrypt +{ + Volume::Volume () + : HiddenVolumeProtectionTriggered (false), + SystemEncryption (false), + VolumeDataSize (0), + TopWriteOffset (0), + TotalDataRead (0), + TotalDataWritten (0) + { + } + + Volume::~Volume () + { + } + + void Volume::CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength) + { + uint64 writeHostEndOffset = writeHostOffset + writeLength - 1; + + if ((writeHostOffset < ProtectedRangeStart) ? (writeHostEndOffset >= ProtectedRangeStart) : (writeHostOffset <= ProtectedRangeEnd - 1)) + { + HiddenVolumeProtectionTriggered = true; + throw VolumeProtected (SRC_POS); + } + } + + void Volume::Close () + { + if (VolumeFile.get() == nullptr) + throw NotInitialized (SRC_POS); + + VolumeFile.reset(); + } + + shared_ptr Volume::GetEncryptionAlgorithm () const + { + if_debug (ValidateState ()); + return EA; + } + + shared_ptr Volume::GetEncryptionMode () const + { + if_debug (ValidateState ()); + return EA->GetMode(); + } + + void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + { + make_shared_auto (File, file); + + File::FileOpenFlags flags = (preserveTimestamps ? File::PreserveTimestamps : File::FlagsNone); + + try + { + if (protection == VolumeProtection::ReadOnly) + file->Open (volumePath, File::OpenRead, File::ShareRead, flags); + else + file->Open (volumePath, File::OpenReadWrite, File::ShareNone, flags); + } + catch (SystemException &e) + { + if (e.GetErrorCode() == +#ifdef TC_WINDOWS + ERROR_SHARING_VIOLATION) +#else + EAGAIN) +#endif + { + if (!sharedAccessAllowed) + throw VolumeHostInUse (SRC_POS); + + file->Open (volumePath, protection == VolumeProtection::ReadOnly ? File::OpenRead : File::OpenReadWrite, File::ShareReadWriteIgnoreLock, flags); + } + else + throw; + } + + return Open (file, password, keyfiles, protection, protectionPassword, protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); + } + + void Volume::Open (shared_ptr volumeFile, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, shared_ptr protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + { + if (!volumeFile) + throw ParameterIncorrect (SRC_POS); + + Protection = protection; + VolumeFile = volumeFile; + SystemEncryption = partitionInSystemEncryptionScope; + + try + { + VolumeHostSize = VolumeFile->Length(); + shared_ptr passwordKey = Keyfile::ApplyListToPassword (keyfiles, password); + + bool skipLayoutV1Normal = false; + + // Test volume layouts + foreach (shared_ptr layout, VolumeLayout::GetAvailableLayouts (volumeType)) + { + if (skipLayoutV1Normal && typeid (*layout) == typeid (VolumeLayoutV1Normal)) + { + // Skip VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal + continue; + } + + if (useBackupHeaders && !layout->HasBackupHeader()) + continue; + + SecureBuffer headerBuffer (layout->GetHeaderSize()); + + if (layout->HasDriveHeader()) + { + if (!partitionInSystemEncryptionScope) + continue; + + if (!GetPath().IsDevice()) + throw PartitionDeviceRequired (SRC_POS); + + File driveDevice; + driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition()); + + int headerOffset = layout->GetHeaderOffset(); + + if (headerOffset >= 0) + driveDevice.SeekAt (headerOffset); + else + driveDevice.SeekEnd (headerOffset); + + if (driveDevice.Read (headerBuffer) != layout->GetHeaderSize()) + continue; + } + else + { + if (partitionInSystemEncryptionScope) + continue; + + int headerOffset = useBackupHeaders ? layout->GetBackupHeaderOffset() : layout->GetHeaderOffset(); + + if (headerOffset >= 0) + VolumeFile->SeekAt (headerOffset); + else + VolumeFile->SeekEnd (headerOffset); + + if (VolumeFile->Read (headerBuffer) != layout->GetHeaderSize()) + continue; + } + + EncryptionAlgorithmList layoutEncryptionAlgorithms = layout->GetSupportedEncryptionAlgorithms(); + EncryptionModeList layoutEncryptionModes = layout->GetSupportedEncryptionModes(); + + if (typeid (*layout) == typeid (VolumeLayoutV2Normal)) + { + skipLayoutV1Normal = true; + + // Test all algorithms and modes of VolumeLayoutV1Normal as it shares header location with VolumeLayoutV2Normal + layoutEncryptionAlgorithms = EncryptionAlgorithm::GetAvailableAlgorithms(); + layoutEncryptionModes = EncryptionMode::GetAvailableModes(); + } + + shared_ptr header = layout->GetHeader(); + + if (header->Decrypt (headerBuffer, *passwordKey, layout->GetSupportedKeyDerivationFunctions(), layoutEncryptionAlgorithms, layoutEncryptionModes)) + { + // Header decrypted + + if (typeid (*layout) == typeid (VolumeLayoutV2Normal) && header->GetRequiredMinProgramVersion() < 0x600) + { + // VolumeLayoutV1Normal has been opened as VolumeLayoutV2Normal + layout.reset (new VolumeLayoutV1Normal); + header->SetSize (layout->GetHeaderSize()); + layout->SetHeader (header); + } + + Type = layout->GetType(); + SectorSize = header->GetSectorSize(); + + VolumeDataOffset = layout->GetDataOffset (VolumeHostSize); + VolumeDataSize = layout->GetDataSize (VolumeHostSize); + + Header = header; + Layout = layout; + EA = header->GetEncryptionAlgorithm(); + EncryptionMode &mode = *EA->GetMode(); + + if (layout->HasDriveHeader()) + { + if (header->GetEncryptedAreaLength() != header->GetVolumeDataSize()) + throw VolumeEncryptionNotCompleted (SRC_POS); + + uint64 partitionStartOffset = VolumeFile->GetPartitionDeviceStartOffset(); + + if (partitionStartOffset < header->GetEncryptedAreaStart() + || partitionStartOffset >= header->GetEncryptedAreaStart() + header->GetEncryptedAreaLength()) + throw PasswordIncorrect (SRC_POS); + + mode.SetSectorOffset (partitionStartOffset / ENCRYPTION_DATA_UNIT_SIZE); + } + else if (typeid (mode) == typeid (EncryptionModeLRW)) + { + mode.SetSectorOffset (VolumeDataOffset / SectorSize); + } + + // Volume protection + if (Protection == VolumeProtection::HiddenVolumeReadOnly) + { + if (Type == VolumeType::Hidden) + throw PasswordIncorrect (SRC_POS); + else + { + try + { + Volume protectedVolume; + + protectedVolume.Open (VolumeFile, + protectionPassword, protectionKeyfiles, + VolumeProtection::ReadOnly, + shared_ptr (), shared_ptr (), + VolumeType::Hidden, + useBackupHeaders); + + if (protectedVolume.GetType() != VolumeType::Hidden) + ParameterIncorrect (SRC_POS); + + ProtectedRangeStart = protectedVolume.VolumeDataOffset; + ProtectedRangeEnd = protectedVolume.VolumeDataOffset + protectedVolume.VolumeDataSize; + + if (typeid (*protectedVolume.Layout) == typeid (VolumeLayoutV1Hidden)) + ProtectedRangeEnd += protectedVolume.Layout->GetHeaderSize(); + } + catch (PasswordException&) + { + if (protectionKeyfiles && !protectionKeyfiles->empty()) + throw ProtectionPasswordKeyfilesIncorrect (SRC_POS); + throw ProtectionPasswordIncorrect (SRC_POS); + } + } + } + return; + } + } + + if (partitionInSystemEncryptionScope) + throw PasswordOrKeyboardLayoutIncorrect (SRC_POS); + + if (!partitionInSystemEncryptionScope && GetPath().IsDevice()) + { + // Check if the device contains TrueCrypt Boot Loader + try + { + File driveDevice; + driveDevice.Open (DevicePath (wstring (GetPath())).ToHostDriveOfPartition()); + + Buffer mbr (VolumeFile->GetDeviceSectorSize()); + driveDevice.ReadAt (mbr, 0); + + // Search for the string "TrueCrypt" + size_t nameLen = strlen (TC_APP_NAME); + for (size_t i = 0; i < mbr.Size() - nameLen; ++i) + { + if (memcmp (mbr.Ptr() + i, TC_APP_NAME, nameLen) == 0) + throw PasswordOrMountOptionsIncorrect (SRC_POS); + } + } + catch (PasswordOrMountOptionsIncorrect&) { throw; } + catch (...) { } + } + + if (keyfiles && !keyfiles->empty()) + throw PasswordKeyfilesIncorrect (SRC_POS); + throw PasswordIncorrect (SRC_POS); + } + catch (...) + { + Close(); + throw; + } + } + + void Volume::ReadSectors (const BufferPtr &buffer, uint64 byteOffset) + { + if_debug (ValidateState ()); + + uint64 length = buffer.Size(); + uint64 hostOffset = VolumeDataOffset + byteOffset; + + if (length % SectorSize != 0 || byteOffset % SectorSize != 0) + throw ParameterIncorrect (SRC_POS); + + if (VolumeFile->ReadAt (buffer, hostOffset) != length) + throw MissingVolumeData (SRC_POS); + + EA->DecryptSectors (buffer, hostOffset / SectorSize, length / SectorSize, SectorSize); + + TotalDataRead += length; + } + + void Volume::ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf) + { + if_debug (ValidateState ()); + + if (Protection == VolumeProtection::ReadOnly) + throw VolumeReadOnly (SRC_POS); + + SecureBuffer newHeaderBuffer (Layout->GetHeaderSize()); + + Header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, newPkcs5Kdf); + + int headerOffset = backupHeader ? Layout->GetBackupHeaderOffset() : Layout->GetHeaderOffset(); + + if (headerOffset >= 0) + VolumeFile->SeekAt (headerOffset); + else + VolumeFile->SeekEnd (headerOffset); + + VolumeFile->Write (newHeaderBuffer); + } + + void Volume::ValidateState () const + { + if (VolumeFile.get() == nullptr) + throw NotInitialized (SRC_POS); + } + + void Volume::WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset) + { + if_debug (ValidateState ()); + + uint64 length = buffer.Size(); + uint64 hostOffset = VolumeDataOffset + byteOffset; + + if (length % SectorSize != 0 + || byteOffset % SectorSize != 0 + || byteOffset + length > VolumeDataSize) + throw ParameterIncorrect (SRC_POS); + + if (Protection == VolumeProtection::ReadOnly) + throw VolumeReadOnly (SRC_POS); + + if (HiddenVolumeProtectionTriggered) + throw VolumeProtected (SRC_POS); + + if (Protection == VolumeProtection::HiddenVolumeReadOnly) + CheckProtectedRange (hostOffset, length); + + SecureBuffer encBuf (buffer.Size()); + encBuf.CopyFrom (buffer); + + EA->EncryptSectors (encBuf, hostOffset / SectorSize, length / SectorSize, SectorSize); + VolumeFile->WriteAt (encBuf, hostOffset); + + TotalDataWritten += length; + + uint64 writeEndOffset = byteOffset + buffer.Size(); + if (writeEndOffset > TopWriteOffset) + TopWriteOffset = writeEndOffset; + } +} diff --git a/Volume/Volume.h b/Volume/Volume.h index 5ee2e85..0ad2182 100644 --- a/Volume/Volume.h +++ b/Volume/Volume.h @@ -1,126 +1,126 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_Volume -#define TC_HEADER_Volume_Volume - -#include "Platform/Platform.h" -#include "Platform/StringConverter.h" -#include "EncryptionAlgorithm.h" -#include "EncryptionMode.h" -#include "Keyfile.h" -#include "VolumePassword.h" -#include "VolumeException.h" -#include "VolumeLayout.h" - -namespace TrueCrypt -{ - class VolumePath - { - public: - VolumePath () { } - VolumePath (const wstring &path) { Data = path; } - VolumePath (const FilesystemPath &path) { Data = path; } - - bool operator== (const VolumePath &other) const { return Data == other.Data; } - bool operator!= (const VolumePath &other) const { return Data != other.Data; } - operator FilesystemPath () const { return FilesystemPath (Data); } - operator string () const { return StringConverter::ToSingle (Data); } - operator wstring () const { return Data; } - - bool IsDevice () const { return FilesystemPath (Data).IsBlockDevice() || FilesystemPath (Data).IsCharacterDevice(); } - bool IsEmpty () const { return Data.empty(); } - - protected: - wstring Data; - }; - - typedef list VolumePathList; - - struct VolumeHostType - { - enum Enum - { - Unknown, - File, - Device - }; - }; - - struct VolumeProtection - { - enum Enum - { - None, - ReadOnly, - HiddenVolumeReadOnly - }; - }; - - class Volume - { - public: - Volume (); - virtual ~Volume (); - - void Close (); - shared_ptr GetEncryptionAlgorithm () const; - shared_ptr GetEncryptionMode () const; - shared_ptr GetFile () const { return VolumeFile; } - shared_ptr GetHeader () const { return Header; } - uint64 GetHeaderCreationTime () const { return Header->GetHeaderCreationTime(); } - uint64 GetHostSize () const { return VolumeHostSize; } - shared_ptr GetLayout () const { return Layout; } - VolumePath GetPath () const { return VolumeFile->GetPath(); } - VolumeProtection::Enum GetProtectionType () const { return Protection; } - shared_ptr GetPkcs5Kdf () const { return Header->GetPkcs5Kdf(); } - uint32 GetSaltSize () const { return Header->GetSaltSize(); } - size_t GetSectorSize () const { return SectorSize; } - uint64 GetSize () const { return VolumeDataSize; } - uint64 GetTopWriteOffset () const { return TopWriteOffset; } - uint64 GetTotalDataRead () const { return TotalDataRead; } - uint64 GetTotalDataWritten () const { return TotalDataWritten; } - VolumeType::Enum GetType () const { return Type; } - uint64 GetVolumeCreationTime () const { return Header->GetVolumeCreationTime(); } - bool IsHiddenVolumeProtectionTriggered () const { return HiddenVolumeProtectionTriggered; } - bool IsInSystemEncryptionScope () const { return SystemEncryption; } - void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); - void Open (shared_ptr volumeFile, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); - void ReadSectors (const BufferPtr &buffer, uint64 byteOffset); - void ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf); - void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset); - - protected: - void CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength); - void ValidateState () const; - - shared_ptr EA; - shared_ptr Header; - bool HiddenVolumeProtectionTriggered; - shared_ptr Layout; - uint64 ProtectedRangeStart; - uint64 ProtectedRangeEnd; - VolumeProtection::Enum Protection; - size_t SectorSize; - bool SystemEncryption; - VolumeType::Enum Type; - shared_ptr VolumeFile; - uint64 VolumeHostSize; - uint64 VolumeDataOffset; - uint64 VolumeDataSize; - uint64 TopWriteOffset; - uint64 TotalDataRead; - uint64 TotalDataWritten; - - private: - Volume (const Volume &); - Volume &operator= (const Volume &); - }; -} - -#endif // TC_HEADER_Volume_Volume +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_Volume +#define TC_HEADER_Volume_Volume + +#include "Platform/Platform.h" +#include "Platform/StringConverter.h" +#include "EncryptionAlgorithm.h" +#include "EncryptionMode.h" +#include "Keyfile.h" +#include "VolumePassword.h" +#include "VolumeException.h" +#include "VolumeLayout.h" + +namespace TrueCrypt +{ + class VolumePath + { + public: + VolumePath () { } + VolumePath (const wstring &path) { Data = path; } + VolumePath (const FilesystemPath &path) { Data = path; } + + bool operator== (const VolumePath &other) const { return Data == other.Data; } + bool operator!= (const VolumePath &other) const { return Data != other.Data; } + operator FilesystemPath () const { return FilesystemPath (Data); } + operator string () const { return StringConverter::ToSingle (Data); } + operator wstring () const { return Data; } + + bool IsDevice () const { return FilesystemPath (Data).IsBlockDevice() || FilesystemPath (Data).IsCharacterDevice(); } + bool IsEmpty () const { return Data.empty(); } + + protected: + wstring Data; + }; + + typedef list VolumePathList; + + struct VolumeHostType + { + enum Enum + { + Unknown, + File, + Device + }; + }; + + struct VolumeProtection + { + enum Enum + { + None, + ReadOnly, + HiddenVolumeReadOnly + }; + }; + + class Volume + { + public: + Volume (); + virtual ~Volume (); + + void Close (); + shared_ptr GetEncryptionAlgorithm () const; + shared_ptr GetEncryptionMode () const; + shared_ptr GetFile () const { return VolumeFile; } + shared_ptr GetHeader () const { return Header; } + uint64 GetHeaderCreationTime () const { return Header->GetHeaderCreationTime(); } + uint64 GetHostSize () const { return VolumeHostSize; } + shared_ptr GetLayout () const { return Layout; } + VolumePath GetPath () const { return VolumeFile->GetPath(); } + VolumeProtection::Enum GetProtectionType () const { return Protection; } + shared_ptr GetPkcs5Kdf () const { return Header->GetPkcs5Kdf(); } + uint32 GetSaltSize () const { return Header->GetSaltSize(); } + size_t GetSectorSize () const { return SectorSize; } + uint64 GetSize () const { return VolumeDataSize; } + uint64 GetTopWriteOffset () const { return TopWriteOffset; } + uint64 GetTotalDataRead () const { return TotalDataRead; } + uint64 GetTotalDataWritten () const { return TotalDataWritten; } + VolumeType::Enum GetType () const { return Type; } + uint64 GetVolumeCreationTime () const { return Header->GetVolumeCreationTime(); } + bool IsHiddenVolumeProtectionTriggered () const { return HiddenVolumeProtectionTriggered; } + bool IsInSystemEncryptionScope () const { return SystemEncryption; } + void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); + void Open (shared_ptr volumeFile, shared_ptr password, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); + void ReadSectors (const BufferPtr &buffer, uint64 byteOffset); + void ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf); + void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset); + + protected: + void CheckProtectedRange (uint64 writeHostOffset, uint64 writeLength); + void ValidateState () const; + + shared_ptr EA; + shared_ptr Header; + bool HiddenVolumeProtectionTriggered; + shared_ptr Layout; + uint64 ProtectedRangeStart; + uint64 ProtectedRangeEnd; + VolumeProtection::Enum Protection; + size_t SectorSize; + bool SystemEncryption; + VolumeType::Enum Type; + shared_ptr VolumeFile; + uint64 VolumeHostSize; + uint64 VolumeDataOffset; + uint64 VolumeDataSize; + uint64 TopWriteOffset; + uint64 TotalDataRead; + uint64 TotalDataWritten; + + private: + Volume (const Volume &); + Volume &operator= (const Volume &); + }; +} + +#endif // TC_HEADER_Volume_Volume diff --git a/Volume/Volume.make b/Volume/Volume.make index 88c7d1a..068b15d 100644 --- a/Volume/Volume.make +++ b/Volume/Volume.make @@ -1,50 +1,50 @@ -# -# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. -# -# Governed by the TrueCrypt License 2.7 the full text of which is contained -# in the file License.txt included in TrueCrypt binary and source code -# distribution packages. -# - -OBJS := -OBJS += Cipher.o -OBJS += EncryptionAlgorithm.o -OBJS += EncryptionMode.o -OBJS += EncryptionModeCBC.o -OBJS += EncryptionModeLRW.o -OBJS += EncryptionModeXTS.o -OBJS += EncryptionTest.o -OBJS += EncryptionThreadPool.o -OBJS += Hash.o -OBJS += Keyfile.o -OBJS += Pkcs5Kdf.o -OBJS += Volume.o -OBJS += VolumeException.o -OBJS += VolumeHeader.o -OBJS += VolumeInfo.o -OBJS += VolumeLayout.o -OBJS += VolumePassword.o -OBJS += VolumePasswordCache.o - -OBJS += ../Crypto/Aescrypt.o -OBJS += ../Crypto/Aeskey.o -OBJS += ../Crypto/Aestab.o -OBJS += ../Crypto/Blowfish.o -OBJS += ../Crypto/Cast.o -OBJS += ../Crypto/Des.o -OBJS += ../Crypto/Rmd160.o -OBJS += ../Crypto/Serpent.o -OBJS += ../Crypto/Sha1.o -OBJS += ../Crypto/Sha2.o -OBJS += ../Crypto/Twofish.o -OBJS += ../Crypto/Whirlpool.o - -OBJS += ../Common/Crc.o -OBJS += ../Common/Endian.o -OBJS += ../Common/GfMul.o -OBJS += ../Common/Pkcs5.o -OBJS += ../Common/SecurityToken.o - -VolumeLibrary: Volume.a - -include $(BUILD_INC)/Makefile.inc +# +# Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. +# +# Governed by the TrueCrypt License 2.8 the full text of which is contained +# in the file License.txt included in TrueCrypt binary and source code +# distribution packages. +# + +OBJS := +OBJS += Cipher.o +OBJS += EncryptionAlgorithm.o +OBJS += EncryptionMode.o +OBJS += EncryptionModeCBC.o +OBJS += EncryptionModeLRW.o +OBJS += EncryptionModeXTS.o +OBJS += EncryptionTest.o +OBJS += EncryptionThreadPool.o +OBJS += Hash.o +OBJS += Keyfile.o +OBJS += Pkcs5Kdf.o +OBJS += Volume.o +OBJS += VolumeException.o +OBJS += VolumeHeader.o +OBJS += VolumeInfo.o +OBJS += VolumeLayout.o +OBJS += VolumePassword.o +OBJS += VolumePasswordCache.o + +OBJS += ../Crypto/Aescrypt.o +OBJS += ../Crypto/Aeskey.o +OBJS += ../Crypto/Aestab.o +OBJS += ../Crypto/Blowfish.o +OBJS += ../Crypto/Cast.o +OBJS += ../Crypto/Des.o +OBJS += ../Crypto/Rmd160.o +OBJS += ../Crypto/Serpent.o +OBJS += ../Crypto/Sha1.o +OBJS += ../Crypto/Sha2.o +OBJS += ../Crypto/Twofish.o +OBJS += ../Crypto/Whirlpool.o + +OBJS += ../Common/Crc.o +OBJS += ../Common/Endian.o +OBJS += ../Common/GfMul.o +OBJS += ../Common/Pkcs5.o +OBJS += ../Common/SecurityToken.o + +VolumeLibrary: Volume.a + +include $(BUILD_INC)/Makefile.inc diff --git a/Volume/VolumeException.cpp b/Volume/VolumeException.cpp index bc98535..9b13c79 100644 --- a/Volume/VolumeException.cpp +++ b/Volume/VolumeException.cpp @@ -1,32 +1,32 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "VolumeException.h" -#include "Platform/SerializerFactory.h" - -namespace TrueCrypt -{ - // Do not inline the constructors to ensure this module is not optimized away - VolumeException::VolumeException () - { - } - - VolumeException::VolumeException (const string &message) : Exception (message) - { - } - - VolumeException::VolumeException (const string &message, const wstring &subject) : Exception (message, subject) - { - } - -#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -#undef TC_EXCEPTION_NODECL -#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (VolumeException); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "VolumeException.h" +#include "Platform/SerializerFactory.h" + +namespace TrueCrypt +{ + // Do not inline the constructors to ensure this module is not optimized away + VolumeException::VolumeException () + { + } + + VolumeException::VolumeException (const string &message) : Exception (message) + { + } + + VolumeException::VolumeException (const string &message, const wstring &subject) : Exception (message, subject) + { + } + +#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +#undef TC_EXCEPTION_NODECL +#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (VolumeException); +} diff --git a/Volume/VolumeException.h b/Volume/VolumeException.h index e0139a3..d4ad990 100644 --- a/Volume/VolumeException.h +++ b/Volume/VolumeException.h @@ -1,41 +1,41 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_VolumeExceptions -#define TC_HEADER_Volume_VolumeExceptions - -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - struct VolumeException : public Exception - { - protected: - VolumeException (); - VolumeException (const string &message); - VolumeException (const string &message, const wstring &subject); - }; - -#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,VolumeException) - -#undef TC_EXCEPTION_SET -#define TC_EXCEPTION_SET \ - TC_EXCEPTION (HigherVersionRequired); \ - TC_EXCEPTION (MissingVolumeData); \ - TC_EXCEPTION (MountedVolumeInUse); \ - TC_EXCEPTION (VolumeEncryptionNotCompleted); \ - TC_EXCEPTION (VolumeHostInUse); \ - TC_EXCEPTION (VolumeProtected); \ - TC_EXCEPTION (VolumeReadOnly); - - TC_EXCEPTION_SET; - -#undef TC_EXCEPTION -} - -#endif // TC_HEADER_Volume_VolumeExceptions +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_VolumeExceptions +#define TC_HEADER_Volume_VolumeExceptions + +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + struct VolumeException : public Exception + { + protected: + VolumeException (); + VolumeException (const string &message); + VolumeException (const string &message, const wstring &subject); + }; + +#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,VolumeException) + +#undef TC_EXCEPTION_SET +#define TC_EXCEPTION_SET \ + TC_EXCEPTION (HigherVersionRequired); \ + TC_EXCEPTION (MissingVolumeData); \ + TC_EXCEPTION (MountedVolumeInUse); \ + TC_EXCEPTION (VolumeEncryptionNotCompleted); \ + TC_EXCEPTION (VolumeHostInUse); \ + TC_EXCEPTION (VolumeProtected); \ + TC_EXCEPTION (VolumeReadOnly); + + TC_EXCEPTION_SET; + +#undef TC_EXCEPTION +} + +#endif // TC_HEADER_Volume_VolumeExceptions diff --git a/Volume/VolumeHeader.cpp b/Volume/VolumeHeader.cpp index 0248987..f674560 100644 --- a/Volume/VolumeHeader.cpp +++ b/Volume/VolumeHeader.cpp @@ -1,304 +1,304 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Crc32.h" -#include "EncryptionModeXTS.h" -#include "Pkcs5Kdf.h" -#include "Pkcs5Kdf.h" -#include "VolumeHeader.h" -#include "VolumeException.h" - -namespace TrueCrypt -{ - VolumeHeader::VolumeHeader (uint32 size) - { - Init(); - HeaderSize = size; - EncryptedHeaderDataSize = size - EncryptedHeaderDataOffset; - } - - VolumeHeader::~VolumeHeader () - { - Init(); - } - - void VolumeHeader::Init () - { - VolumeKeyAreaCrc32 = 0; - VolumeCreationTime = 0; - HeaderCreationTime = 0; - mVolumeType = VolumeType::Unknown; - HiddenVolumeDataSize = 0; - VolumeDataSize = 0; - EncryptedAreaStart = 0; - EncryptedAreaLength = 0; - Flags = 0; - } - - void VolumeHeader::Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options) - { - if (options.DataKey.Size() != options.EA->GetKeySize() * 2 || options.Salt.Size() != GetSaltSize()) - throw ParameterIncorrect (SRC_POS); - - headerBuffer.Zero(); - - HeaderVersion = CurrentHeaderVersion; - RequiredMinProgramVersion = CurrentRequiredMinProgramVersion; - - DataAreaKey.Zero(); - DataAreaKey.CopyFrom (options.DataKey); - - VolumeCreationTime = 0; - HiddenVolumeDataSize = (options.Type == VolumeType::Hidden ? options.VolumeDataSize : 0); - VolumeDataSize = options.VolumeDataSize; - - EncryptedAreaStart = options.VolumeDataStart; - EncryptedAreaLength = options.VolumeDataSize; - - EA = options.EA; - shared_ptr mode (new EncryptionModeXTS ()); - EA->SetMode (mode); - - EncryptNew (headerBuffer, options.Salt, options.HeaderKey, options.Kdf); - } - - bool VolumeHeader::Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, const Pkcs5KdfList &keyDerivationFunctions, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes) - { - if (password.Size() < 1) - throw PasswordEmpty (SRC_POS); - - ConstBufferPtr salt (encryptedData.GetRange (SaltOffset, SaltSize)); - SecureBuffer header (EncryptedHeaderDataSize); - SecureBuffer headerKey (GetLargestSerializedKeySize()); - - foreach (shared_ptr pkcs5, keyDerivationFunctions) - { - pkcs5->DeriveKey (headerKey, password, salt); - - foreach (shared_ptr mode, encryptionModes) - { - if (typeid (*mode) != typeid (EncryptionModeXTS)) - mode->SetKey (headerKey.GetRange (0, mode->GetKeySize())); - - foreach (shared_ptr ea, encryptionAlgorithms) - { - if (!ea->IsModeSupported (mode)) - continue; - - if (typeid (*mode) == typeid (EncryptionModeXTS)) - { - ea->SetKey (headerKey.GetRange (0, ea->GetKeySize())); - - mode = mode->GetNew(); - mode->SetKey (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize())); - } - else - { - ea->SetKey (headerKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize())); - } - - ea->SetMode (mode); - - header.CopyFrom (encryptedData.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize)); - ea->Decrypt (header); - - if (Deserialize (header, ea, mode)) - { - EA = ea; - Pkcs5 = pkcs5; - return true; - } - } - } - } - - return false; - } - - bool VolumeHeader::Deserialize (const ConstBufferPtr &header, shared_ptr &ea, shared_ptr &mode) - { - if (header.Size() != EncryptedHeaderDataSize) - throw ParameterIncorrect (SRC_POS); - - if (header[0] != 'T' || - header[1] != 'R' || - header[2] != 'U' || - header[3] != 'E') - return false; - - size_t offset = 4; - HeaderVersion = DeserializeEntry (header, offset); - - if (HeaderVersion < MinAllowedHeaderVersion) - return false; - - if (HeaderVersion > CurrentHeaderVersion) - throw HigherVersionRequired (SRC_POS); - - if (HeaderVersion >= 4 - && Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) - != DeserializeEntryAt (header, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) - { - return false; - } - - RequiredMinProgramVersion = DeserializeEntry (header, offset); - - if (RequiredMinProgramVersion > Version::Number()) - throw HigherVersionRequired (SRC_POS); - - VolumeKeyAreaCrc32 = DeserializeEntry (header, offset); - VolumeCreationTime = DeserializeEntry (header, offset); - HeaderCreationTime = DeserializeEntry (header, offset); - HiddenVolumeDataSize = DeserializeEntry (header, offset); - mVolumeType = (HiddenVolumeDataSize != 0 ? VolumeType::Hidden : VolumeType::Normal); - VolumeDataSize = DeserializeEntry (header, offset); - EncryptedAreaStart = DeserializeEntry (header, offset); - EncryptedAreaLength = DeserializeEntry (header, offset); - Flags = DeserializeEntry (header, offset); - - offset = DataAreaKeyOffset; - - if (VolumeKeyAreaCrc32 != Crc32::ProcessBuffer (header.GetRange (offset, DataKeyAreaMaxSize))) - return false; - - DataAreaKey.CopyFrom (header.GetRange (offset, DataKeyAreaMaxSize)); - - ea = ea->GetNew(); - mode = mode->GetNew(); - - if (typeid (*mode) == typeid (EncryptionModeXTS)) - { - ea->SetKey (header.GetRange (offset, ea->GetKeySize())); - mode->SetKey (header.GetRange (offset + ea->GetKeySize(), ea->GetKeySize())); - } - else - { - mode->SetKey (header.GetRange (offset, mode->GetKeySize())); - ea->SetKey (header.GetRange (offset + LegacyEncryptionModeKeyAreaSize, ea->GetKeySize())); - } - - ea->SetMode (mode); - - return true; - } - - template - T VolumeHeader::DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const - { - offset += sizeof (T); - - if (offset > header.Size()) - throw ParameterIncorrect (SRC_POS); - - return Endian::Big (*reinterpret_cast (header.Get() + offset - sizeof (T))); - } - - template - T VolumeHeader::DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const - { - if (offset > header.Size()) - throw ParameterIncorrect (SRC_POS); - - return Endian::Big (*reinterpret_cast (header.Get() + offset)); - } - - void VolumeHeader::EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf) - { - if (newHeaderBuffer.Size() != HeaderSize || newSalt.Size() != SaltSize) - throw ParameterIncorrect (SRC_POS); - - shared_ptr mode = EA->GetMode()->GetNew(); - shared_ptr ea = EA->GetNew(); - - if (typeid (*mode) == typeid (EncryptionModeXTS)) - { - mode->SetKey (newHeaderKey.GetRange (EA->GetKeySize(), EA->GetKeySize())); - ea->SetKey (newHeaderKey.GetRange (0, ea->GetKeySize())); - } - else - { - mode->SetKey (newHeaderKey.GetRange (0, mode->GetKeySize())); - ea->SetKey (newHeaderKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize())); - } - - ea->SetMode (mode); - - newHeaderBuffer.CopyFrom (newSalt); - - BufferPtr headerData = newHeaderBuffer.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize); - Serialize (headerData); - ea->Encrypt (headerData); - - if (newPkcs5Kdf) - Pkcs5 = newPkcs5Kdf; - } - - size_t VolumeHeader::GetLargestSerializedKeySize () - { - size_t largestKey = EncryptionAlgorithm::GetLargestKeySize (EncryptionAlgorithm::GetAvailableAlgorithms()); - - // XTS mode requires the same key size as the encryption algorithm. - // Legacy modes may require larger key than XTS. - if (LegacyEncryptionModeKeyAreaSize + largestKey > largestKey * 2) - return LegacyEncryptionModeKeyAreaSize + largestKey; - - return largestKey * 2; - } - - void VolumeHeader::Serialize (const BufferPtr &header) const - { - if (header.Size() != EncryptedHeaderDataSize) - throw ParameterIncorrect (SRC_POS); - - header.Zero(); - - header[0] = 'T'; - header[1] = 'R'; - header[2] = 'U'; - header[3] = 'E'; - size_t offset = 4; - - header.GetRange (DataAreaKeyOffset, DataAreaKey.Size()).CopyFrom (DataAreaKey); - - uint16 headerVersion = CurrentHeaderVersion; - SerializeEntry (headerVersion, header, offset); - SerializeEntry (RequiredMinProgramVersion, header, offset); - SerializeEntry (Crc32::ProcessBuffer (header.GetRange (DataAreaKeyOffset, DataKeyAreaMaxSize)), header, offset); - - uint64 reserved64 = 0; - SerializeEntry (reserved64, header, offset); - SerializeEntry (reserved64, header, offset); - - SerializeEntry (HiddenVolumeDataSize, header, offset); - SerializeEntry (VolumeDataSize, header, offset); - SerializeEntry (EncryptedAreaStart, header, offset); - SerializeEntry (EncryptedAreaLength, header, offset); - SerializeEntry (Flags, header, offset); - - offset = TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC; - SerializeEntry (Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)), header, offset); - } - - template - void VolumeHeader::SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const - { - offset += sizeof (T); - - if (offset > header.Size()) - throw ParameterIncorrect (SRC_POS); - - *reinterpret_cast (header.Get() + offset - sizeof (T)) = Endian::Big (entry); - } - - void VolumeHeader::SetSize (uint32 headerSize) - { - HeaderSize = headerSize; - EncryptedHeaderDataSize = HeaderSize - EncryptedHeaderDataOffset; - } -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Crc32.h" +#include "EncryptionModeXTS.h" +#include "Pkcs5Kdf.h" +#include "Pkcs5Kdf.h" +#include "VolumeHeader.h" +#include "VolumeException.h" + +namespace TrueCrypt +{ + VolumeHeader::VolumeHeader (uint32 size) + { + Init(); + HeaderSize = size; + EncryptedHeaderDataSize = size - EncryptedHeaderDataOffset; + } + + VolumeHeader::~VolumeHeader () + { + Init(); + } + + void VolumeHeader::Init () + { + VolumeKeyAreaCrc32 = 0; + VolumeCreationTime = 0; + HeaderCreationTime = 0; + mVolumeType = VolumeType::Unknown; + HiddenVolumeDataSize = 0; + VolumeDataSize = 0; + EncryptedAreaStart = 0; + EncryptedAreaLength = 0; + Flags = 0; + } + + void VolumeHeader::Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options) + { + if (options.DataKey.Size() != options.EA->GetKeySize() * 2 || options.Salt.Size() != GetSaltSize()) + throw ParameterIncorrect (SRC_POS); + + headerBuffer.Zero(); + + HeaderVersion = CurrentHeaderVersion; + RequiredMinProgramVersion = CurrentRequiredMinProgramVersion; + + DataAreaKey.Zero(); + DataAreaKey.CopyFrom (options.DataKey); + + VolumeCreationTime = 0; + HiddenVolumeDataSize = (options.Type == VolumeType::Hidden ? options.VolumeDataSize : 0); + VolumeDataSize = options.VolumeDataSize; + + EncryptedAreaStart = options.VolumeDataStart; + EncryptedAreaLength = options.VolumeDataSize; + + EA = options.EA; + shared_ptr mode (new EncryptionModeXTS ()); + EA->SetMode (mode); + + EncryptNew (headerBuffer, options.Salt, options.HeaderKey, options.Kdf); + } + + bool VolumeHeader::Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, const Pkcs5KdfList &keyDerivationFunctions, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes) + { + if (password.Size() < 1) + throw PasswordEmpty (SRC_POS); + + ConstBufferPtr salt (encryptedData.GetRange (SaltOffset, SaltSize)); + SecureBuffer header (EncryptedHeaderDataSize); + SecureBuffer headerKey (GetLargestSerializedKeySize()); + + foreach (shared_ptr pkcs5, keyDerivationFunctions) + { + pkcs5->DeriveKey (headerKey, password, salt); + + foreach (shared_ptr mode, encryptionModes) + { + if (typeid (*mode) != typeid (EncryptionModeXTS)) + mode->SetKey (headerKey.GetRange (0, mode->GetKeySize())); + + foreach (shared_ptr ea, encryptionAlgorithms) + { + if (!ea->IsModeSupported (mode)) + continue; + + if (typeid (*mode) == typeid (EncryptionModeXTS)) + { + ea->SetKey (headerKey.GetRange (0, ea->GetKeySize())); + + mode = mode->GetNew(); + mode->SetKey (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize())); + } + else + { + ea->SetKey (headerKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize())); + } + + ea->SetMode (mode); + + header.CopyFrom (encryptedData.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize)); + ea->Decrypt (header); + + if (Deserialize (header, ea, mode)) + { + EA = ea; + Pkcs5 = pkcs5; + return true; + } + } + } + } + + return false; + } + + bool VolumeHeader::Deserialize (const ConstBufferPtr &header, shared_ptr &ea, shared_ptr &mode) + { + if (header.Size() != EncryptedHeaderDataSize) + throw ParameterIncorrect (SRC_POS); + + if (header[0] != 'T' || + header[1] != 'R' || + header[2] != 'U' || + header[3] != 'E') + return false; + + size_t offset = 4; + HeaderVersion = DeserializeEntry (header, offset); + + if (HeaderVersion < MinAllowedHeaderVersion) + return false; + + if (HeaderVersion > CurrentHeaderVersion) + throw HigherVersionRequired (SRC_POS); + + if (HeaderVersion >= 4 + && Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) + != DeserializeEntryAt (header, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)) + { + return false; + } + + RequiredMinProgramVersion = DeserializeEntry (header, offset); + + if (RequiredMinProgramVersion > Version::Number()) + throw HigherVersionRequired (SRC_POS); + + VolumeKeyAreaCrc32 = DeserializeEntry (header, offset); + VolumeCreationTime = DeserializeEntry (header, offset); + HeaderCreationTime = DeserializeEntry (header, offset); + HiddenVolumeDataSize = DeserializeEntry (header, offset); + mVolumeType = (HiddenVolumeDataSize != 0 ? VolumeType::Hidden : VolumeType::Normal); + VolumeDataSize = DeserializeEntry (header, offset); + EncryptedAreaStart = DeserializeEntry (header, offset); + EncryptedAreaLength = DeserializeEntry (header, offset); + Flags = DeserializeEntry (header, offset); + + offset = DataAreaKeyOffset; + + if (VolumeKeyAreaCrc32 != Crc32::ProcessBuffer (header.GetRange (offset, DataKeyAreaMaxSize))) + return false; + + DataAreaKey.CopyFrom (header.GetRange (offset, DataKeyAreaMaxSize)); + + ea = ea->GetNew(); + mode = mode->GetNew(); + + if (typeid (*mode) == typeid (EncryptionModeXTS)) + { + ea->SetKey (header.GetRange (offset, ea->GetKeySize())); + mode->SetKey (header.GetRange (offset + ea->GetKeySize(), ea->GetKeySize())); + } + else + { + mode->SetKey (header.GetRange (offset, mode->GetKeySize())); + ea->SetKey (header.GetRange (offset + LegacyEncryptionModeKeyAreaSize, ea->GetKeySize())); + } + + ea->SetMode (mode); + + return true; + } + + template + T VolumeHeader::DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const + { + offset += sizeof (T); + + if (offset > header.Size()) + throw ParameterIncorrect (SRC_POS); + + return Endian::Big (*reinterpret_cast (header.Get() + offset - sizeof (T))); + } + + template + T VolumeHeader::DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const + { + if (offset > header.Size()) + throw ParameterIncorrect (SRC_POS); + + return Endian::Big (*reinterpret_cast (header.Get() + offset)); + } + + void VolumeHeader::EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf) + { + if (newHeaderBuffer.Size() != HeaderSize || newSalt.Size() != SaltSize) + throw ParameterIncorrect (SRC_POS); + + shared_ptr mode = EA->GetMode()->GetNew(); + shared_ptr ea = EA->GetNew(); + + if (typeid (*mode) == typeid (EncryptionModeXTS)) + { + mode->SetKey (newHeaderKey.GetRange (EA->GetKeySize(), EA->GetKeySize())); + ea->SetKey (newHeaderKey.GetRange (0, ea->GetKeySize())); + } + else + { + mode->SetKey (newHeaderKey.GetRange (0, mode->GetKeySize())); + ea->SetKey (newHeaderKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize())); + } + + ea->SetMode (mode); + + newHeaderBuffer.CopyFrom (newSalt); + + BufferPtr headerData = newHeaderBuffer.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize); + Serialize (headerData); + ea->Encrypt (headerData); + + if (newPkcs5Kdf) + Pkcs5 = newPkcs5Kdf; + } + + size_t VolumeHeader::GetLargestSerializedKeySize () + { + size_t largestKey = EncryptionAlgorithm::GetLargestKeySize (EncryptionAlgorithm::GetAvailableAlgorithms()); + + // XTS mode requires the same key size as the encryption algorithm. + // Legacy modes may require larger key than XTS. + if (LegacyEncryptionModeKeyAreaSize + largestKey > largestKey * 2) + return LegacyEncryptionModeKeyAreaSize + largestKey; + + return largestKey * 2; + } + + void VolumeHeader::Serialize (const BufferPtr &header) const + { + if (header.Size() != EncryptedHeaderDataSize) + throw ParameterIncorrect (SRC_POS); + + header.Zero(); + + header[0] = 'T'; + header[1] = 'R'; + header[2] = 'U'; + header[3] = 'E'; + size_t offset = 4; + + header.GetRange (DataAreaKeyOffset, DataAreaKey.Size()).CopyFrom (DataAreaKey); + + uint16 headerVersion = CurrentHeaderVersion; + SerializeEntry (headerVersion, header, offset); + SerializeEntry (RequiredMinProgramVersion, header, offset); + SerializeEntry (Crc32::ProcessBuffer (header.GetRange (DataAreaKeyOffset, DataKeyAreaMaxSize)), header, offset); + + uint64 reserved64 = 0; + SerializeEntry (reserved64, header, offset); + SerializeEntry (reserved64, header, offset); + + SerializeEntry (HiddenVolumeDataSize, header, offset); + SerializeEntry (VolumeDataSize, header, offset); + SerializeEntry (EncryptedAreaStart, header, offset); + SerializeEntry (EncryptedAreaLength, header, offset); + SerializeEntry (Flags, header, offset); + + offset = TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC; + SerializeEntry (Crc32::ProcessBuffer (header.GetRange (0, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC)), header, offset); + } + + template + void VolumeHeader::SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const + { + offset += sizeof (T); + + if (offset > header.Size()) + throw ParameterIncorrect (SRC_POS); + + *reinterpret_cast (header.Get() + offset - sizeof (T)) = Endian::Big (entry); + } + + void VolumeHeader::SetSize (uint32 headerSize) + { + HeaderSize = headerSize; + EncryptedHeaderDataSize = HeaderSize - EncryptedHeaderDataOffset; + } +} diff --git a/Volume/VolumeHeader.h b/Volume/VolumeHeader.h index db35429..e011e50 100644 --- a/Volume/VolumeHeader.h +++ b/Volume/VolumeHeader.h @@ -1,124 +1,124 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_VolumeHeader -#define TC_HEADER_Volume_VolumeHeader - -#include "Common/Tcdefs.h" -#include "Common/Volumes.h" -#include "Platform/Platform.h" -#include "Volume/EncryptionAlgorithm.h" -#include "Volume/EncryptionMode.h" -#include "Volume/Keyfile.h" -#include "Volume/VolumePassword.h" -#include "Volume/Pkcs5Kdf.h" -#include "Version.h" - - -// For specifications of the volume header see Common/Volumes.c - -namespace TrueCrypt -{ - typedef uint64 VolumeTime; - - struct VolumeType - { - enum Enum - { - Unknown, - Normal, - Hidden - }; - }; - - struct VolumeHeaderCreationOptions - { - ConstBufferPtr DataKey; - shared_ptr EA; - shared_ptr Kdf; - ConstBufferPtr HeaderKey; - ConstBufferPtr Salt; - uint64 VolumeDataSize; - uint64 VolumeDataStart; - VolumeType::Enum Type; - }; - - class VolumeHeader - { - public: - VolumeHeader (uint32 HeaderSize); - virtual ~VolumeHeader (); - - void Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options); - bool Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, const Pkcs5KdfList &keyDerivationFunctions, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes); - void EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf); - uint64 GetEncryptedAreaStart () const { return EncryptedAreaStart; } - uint64 GetEncryptedAreaLength () const { return EncryptedAreaLength; } - shared_ptr GetEncryptionAlgorithm () const { return EA; } - uint32 GetFlags () const { return Flags; } - VolumeTime GetHeaderCreationTime () const { return HeaderCreationTime; } - uint64 GetHiddenVolumeDataSize () const { return HiddenVolumeDataSize; } - static size_t GetLargestSerializedKeySize (); - shared_ptr GetPkcs5Kdf () const { return Pkcs5; } - uint16 GetRequiredMinProgramVersion () const { return RequiredMinProgramVersion; } - size_t GetSectorSize () const { return 512; } - static uint32 GetSaltSize () { return SaltSize; } - uint64 GetVolumeDataSize () const { return VolumeDataSize; } - VolumeTime GetVolumeCreationTime () const { return VolumeCreationTime; } - void SetSize (uint32 headerSize); - - protected: - bool Deserialize (const ConstBufferPtr &header, shared_ptr &ea, shared_ptr &mode); - template T DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const; - template T DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const; - void Init (); - void Serialize (const BufferPtr &header) const; - template void SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const; - - uint32 HeaderSize; - - static const uint16 CurrentHeaderVersion = VOLUME_HEADER_VERSION; - static const uint16 CurrentRequiredMinProgramVersion = TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION; - static const uint16 MinAllowedHeaderVersion = 1; - - static const int SaltOffset = 0; - static const uint32 SaltSize = 64; - - static const int EncryptedHeaderDataOffset = SaltOffset + SaltSize; - uint32 EncryptedHeaderDataSize; - - static const uint32 LegacyEncryptionModeKeyAreaSize = 32; - static const int DataKeyAreaMaxSize = 256; - static const uint32 DataAreaKeyOffset = DataKeyAreaMaxSize - EncryptedHeaderDataOffset; - - shared_ptr EA; - shared_ptr Pkcs5; - - uint16 HeaderVersion; - uint16 RequiredMinProgramVersion; - uint32 VolumeKeyAreaCrc32; - - VolumeTime VolumeCreationTime; - VolumeTime HeaderCreationTime; - - VolumeType::Enum mVolumeType; - uint64 HiddenVolumeDataSize; - uint64 VolumeDataSize; - uint64 EncryptedAreaStart; - uint64 EncryptedAreaLength; - uint32 Flags; - - SecureBuffer DataAreaKey; - - private: - VolumeHeader (const VolumeHeader &); - VolumeHeader &operator= (const VolumeHeader &); - }; -} - -#endif // TC_HEADER_Volume_VolumeHeader +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_VolumeHeader +#define TC_HEADER_Volume_VolumeHeader + +#include "Common/Tcdefs.h" +#include "Common/Volumes.h" +#include "Platform/Platform.h" +#include "Volume/EncryptionAlgorithm.h" +#include "Volume/EncryptionMode.h" +#include "Volume/Keyfile.h" +#include "Volume/VolumePassword.h" +#include "Volume/Pkcs5Kdf.h" +#include "Version.h" + + +// For specifications of the volume header see Common/Volumes.c + +namespace TrueCrypt +{ + typedef uint64 VolumeTime; + + struct VolumeType + { + enum Enum + { + Unknown, + Normal, + Hidden + }; + }; + + struct VolumeHeaderCreationOptions + { + ConstBufferPtr DataKey; + shared_ptr EA; + shared_ptr Kdf; + ConstBufferPtr HeaderKey; + ConstBufferPtr Salt; + uint64 VolumeDataSize; + uint64 VolumeDataStart; + VolumeType::Enum Type; + }; + + class VolumeHeader + { + public: + VolumeHeader (uint32 HeaderSize); + virtual ~VolumeHeader (); + + void Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options); + bool Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, const Pkcs5KdfList &keyDerivationFunctions, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes); + void EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf); + uint64 GetEncryptedAreaStart () const { return EncryptedAreaStart; } + uint64 GetEncryptedAreaLength () const { return EncryptedAreaLength; } + shared_ptr GetEncryptionAlgorithm () const { return EA; } + uint32 GetFlags () const { return Flags; } + VolumeTime GetHeaderCreationTime () const { return HeaderCreationTime; } + uint64 GetHiddenVolumeDataSize () const { return HiddenVolumeDataSize; } + static size_t GetLargestSerializedKeySize (); + shared_ptr GetPkcs5Kdf () const { return Pkcs5; } + uint16 GetRequiredMinProgramVersion () const { return RequiredMinProgramVersion; } + size_t GetSectorSize () const { return 512; } + static uint32 GetSaltSize () { return SaltSize; } + uint64 GetVolumeDataSize () const { return VolumeDataSize; } + VolumeTime GetVolumeCreationTime () const { return VolumeCreationTime; } + void SetSize (uint32 headerSize); + + protected: + bool Deserialize (const ConstBufferPtr &header, shared_ptr &ea, shared_ptr &mode); + template T DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const; + template T DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const; + void Init (); + void Serialize (const BufferPtr &header) const; + template void SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const; + + uint32 HeaderSize; + + static const uint16 CurrentHeaderVersion = VOLUME_HEADER_VERSION; + static const uint16 CurrentRequiredMinProgramVersion = TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION; + static const uint16 MinAllowedHeaderVersion = 1; + + static const int SaltOffset = 0; + static const uint32 SaltSize = 64; + + static const int EncryptedHeaderDataOffset = SaltOffset + SaltSize; + uint32 EncryptedHeaderDataSize; + + static const uint32 LegacyEncryptionModeKeyAreaSize = 32; + static const int DataKeyAreaMaxSize = 256; + static const uint32 DataAreaKeyOffset = DataKeyAreaMaxSize - EncryptedHeaderDataOffset; + + shared_ptr EA; + shared_ptr Pkcs5; + + uint16 HeaderVersion; + uint16 RequiredMinProgramVersion; + uint32 VolumeKeyAreaCrc32; + + VolumeTime VolumeCreationTime; + VolumeTime HeaderCreationTime; + + VolumeType::Enum mVolumeType; + uint64 HiddenVolumeDataSize; + uint64 VolumeDataSize; + uint64 EncryptedAreaStart; + uint64 EncryptedAreaLength; + uint32 Flags; + + SecureBuffer DataAreaKey; + + private: + VolumeHeader (const VolumeHeader &); + VolumeHeader &operator= (const VolumeHeader &); + }; +} + +#endif // TC_HEADER_Volume_VolumeHeader diff --git a/Volume/VolumeInfo.cpp b/Volume/VolumeInfo.cpp index 628b23a..1813ad4 100644 --- a/Volume/VolumeInfo.cpp +++ b/Volume/VolumeInfo.cpp @@ -1,118 +1,118 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Common/Tcdefs.h" -#include "VolumeInfo.h" -#include "Platform/SerializerFactory.h" - -namespace TrueCrypt -{ - void VolumeInfo::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - - sr.Deserialize ("ProgramVersion", ProgramVersion); - AuxMountPoint = sr.DeserializeWString ("AuxMountPoint"); - sr.Deserialize ("EncryptionAlgorithmBlockSize", EncryptionAlgorithmBlockSize); - sr.Deserialize ("EncryptionAlgorithmKeySize", EncryptionAlgorithmKeySize); - sr.Deserialize ("EncryptionAlgorithmMinBlockSize", EncryptionAlgorithmMinBlockSize); - EncryptionAlgorithmName = sr.DeserializeWString ("EncryptionAlgorithmName"); - EncryptionModeName = sr.DeserializeWString ("EncryptionModeName"); - sr.Deserialize ("HeaderCreationTime", HeaderCreationTime); - sr.Deserialize ("HiddenVolumeProtectionTriggered", HiddenVolumeProtectionTriggered); - LoopDevice = sr.DeserializeWString ("LoopDevice"); - - if (ProgramVersion >= 0x600) - sr.Deserialize ("MinRequiredProgramVersion", MinRequiredProgramVersion); - - MountPoint = sr.DeserializeWString ("MountPoint"); - Path = sr.DeserializeWString ("Path"); - sr.Deserialize ("Pkcs5IterationCount", Pkcs5IterationCount); - Pkcs5PrfName = sr.DeserializeWString ("Pkcs5PrfName"); - Protection = static_cast (sr.DeserializeInt32 ("Protection")); - sr.Deserialize ("SerialInstanceNumber", SerialInstanceNumber); - sr.Deserialize ("Size", Size); - sr.Deserialize ("SlotNumber", SlotNumber); - - if (ProgramVersion >= 0x620) - sr.Deserialize ("SystemEncryption", SystemEncryption); - - if (ProgramVersion >= 0x600) - sr.Deserialize ("TopWriteOffset", TopWriteOffset); - - sr.Deserialize ("TotalDataRead", TotalDataRead); - sr.Deserialize ("TotalDataWritten", TotalDataWritten); - Type = static_cast (sr.DeserializeInt32 ("Type")); - VirtualDevice = sr.DeserializeWString ("VirtualDevice"); - sr.Deserialize ("VolumeCreationTime", VolumeCreationTime); - } - - bool VolumeInfo::FirstVolumeMountedAfterSecond (shared_ptr first, shared_ptr second) - { - return first->SerialInstanceNumber > second->SerialInstanceNumber; - } - - void VolumeInfo::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - - const uint32 version = VERSION_NUM; - sr.Serialize ("ProgramVersion", version); - sr.Serialize ("AuxMountPoint", wstring (AuxMountPoint)); - sr.Serialize ("EncryptionAlgorithmBlockSize", EncryptionAlgorithmBlockSize); - sr.Serialize ("EncryptionAlgorithmKeySize", EncryptionAlgorithmKeySize); - sr.Serialize ("EncryptionAlgorithmMinBlockSize", EncryptionAlgorithmMinBlockSize); - sr.Serialize ("EncryptionAlgorithmName", EncryptionAlgorithmName); - sr.Serialize ("EncryptionModeName", EncryptionModeName); - sr.Serialize ("HeaderCreationTime", HeaderCreationTime); - sr.Serialize ("HiddenVolumeProtectionTriggered", HiddenVolumeProtectionTriggered); - sr.Serialize ("LoopDevice", wstring (LoopDevice)); - sr.Serialize ("MinRequiredProgramVersion", MinRequiredProgramVersion); - sr.Serialize ("MountPoint", wstring (MountPoint)); - sr.Serialize ("Path", wstring (Path)); - sr.Serialize ("Pkcs5IterationCount", Pkcs5IterationCount); - sr.Serialize ("Pkcs5PrfName", Pkcs5PrfName); - sr.Serialize ("Protection", static_cast (Protection)); - sr.Serialize ("SerialInstanceNumber", SerialInstanceNumber); - sr.Serialize ("Size", Size); - sr.Serialize ("SlotNumber", SlotNumber); - sr.Serialize ("SystemEncryption", SystemEncryption); - sr.Serialize ("TopWriteOffset", TopWriteOffset); - sr.Serialize ("TotalDataRead", TotalDataRead); - sr.Serialize ("TotalDataWritten", TotalDataWritten); - sr.Serialize ("Type", static_cast (Type)); - sr.Serialize ("VirtualDevice", wstring (VirtualDevice)); - sr.Serialize ("VolumeCreationTime", VolumeCreationTime); - } - - void VolumeInfo::Set (const Volume &volume) - { - EncryptionAlgorithmBlockSize = static_cast (volume.GetEncryptionAlgorithm()->GetMaxBlockSize()); - EncryptionAlgorithmKeySize = static_cast (volume.GetEncryptionAlgorithm()->GetKeySize()); - EncryptionAlgorithmMinBlockSize = static_cast (volume.GetEncryptionAlgorithm()->GetMinBlockSize()); - EncryptionAlgorithmName = volume.GetEncryptionAlgorithm()->GetName(); - EncryptionModeName = volume.GetEncryptionMode()->GetName(); - HeaderCreationTime = volume.GetHeaderCreationTime(); - VolumeCreationTime = volume.GetVolumeCreationTime(); - HiddenVolumeProtectionTriggered = volume.IsHiddenVolumeProtectionTriggered(); - MinRequiredProgramVersion = volume.GetHeader()->GetRequiredMinProgramVersion(); - Path = volume.GetPath(); - Pkcs5IterationCount = volume.GetPkcs5Kdf()->GetIterationCount(); - Pkcs5PrfName = volume.GetPkcs5Kdf()->GetName(); - Protection = volume.GetProtectionType(); - Size = volume.GetSize(); - SystemEncryption = volume.IsInSystemEncryptionScope(); - Type = volume.GetType(); - TopWriteOffset = volume.GetTopWriteOffset(); - TotalDataRead = volume.GetTotalDataRead(); - TotalDataWritten = volume.GetTotalDataWritten(); - } - - TC_SERIALIZER_FACTORY_ADD_CLASS (VolumeInfo); -} +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Common/Tcdefs.h" +#include "VolumeInfo.h" +#include "Platform/SerializerFactory.h" + +namespace TrueCrypt +{ + void VolumeInfo::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + + sr.Deserialize ("ProgramVersion", ProgramVersion); + AuxMountPoint = sr.DeserializeWString ("AuxMountPoint"); + sr.Deserialize ("EncryptionAlgorithmBlockSize", EncryptionAlgorithmBlockSize); + sr.Deserialize ("EncryptionAlgorithmKeySize", EncryptionAlgorithmKeySize); + sr.Deserialize ("EncryptionAlgorithmMinBlockSize", EncryptionAlgorithmMinBlockSize); + EncryptionAlgorithmName = sr.DeserializeWString ("EncryptionAlgorithmName"); + EncryptionModeName = sr.DeserializeWString ("EncryptionModeName"); + sr.Deserialize ("HeaderCreationTime", HeaderCreationTime); + sr.Deserialize ("HiddenVolumeProtectionTriggered", HiddenVolumeProtectionTriggered); + LoopDevice = sr.DeserializeWString ("LoopDevice"); + + if (ProgramVersion >= 0x600) + sr.Deserialize ("MinRequiredProgramVersion", MinRequiredProgramVersion); + + MountPoint = sr.DeserializeWString ("MountPoint"); + Path = sr.DeserializeWString ("Path"); + sr.Deserialize ("Pkcs5IterationCount", Pkcs5IterationCount); + Pkcs5PrfName = sr.DeserializeWString ("Pkcs5PrfName"); + Protection = static_cast (sr.DeserializeInt32 ("Protection")); + sr.Deserialize ("SerialInstanceNumber", SerialInstanceNumber); + sr.Deserialize ("Size", Size); + sr.Deserialize ("SlotNumber", SlotNumber); + + if (ProgramVersion >= 0x620) + sr.Deserialize ("SystemEncryption", SystemEncryption); + + if (ProgramVersion >= 0x600) + sr.Deserialize ("TopWriteOffset", TopWriteOffset); + + sr.Deserialize ("TotalDataRead", TotalDataRead); + sr.Deserialize ("TotalDataWritten", TotalDataWritten); + Type = static_cast (sr.DeserializeInt32 ("Type")); + VirtualDevice = sr.DeserializeWString ("VirtualDevice"); + sr.Deserialize ("VolumeCreationTime", VolumeCreationTime); + } + + bool VolumeInfo::FirstVolumeMountedAfterSecond (shared_ptr first, shared_ptr second) + { + return first->SerialInstanceNumber > second->SerialInstanceNumber; + } + + void VolumeInfo::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + + const uint32 version = VERSION_NUM; + sr.Serialize ("ProgramVersion", version); + sr.Serialize ("AuxMountPoint", wstring (AuxMountPoint)); + sr.Serialize ("EncryptionAlgorithmBlockSize", EncryptionAlgorithmBlockSize); + sr.Serialize ("EncryptionAlgorithmKeySize", EncryptionAlgorithmKeySize); + sr.Serialize ("EncryptionAlgorithmMinBlockSize", EncryptionAlgorithmMinBlockSize); + sr.Serialize ("EncryptionAlgorithmName", EncryptionAlgorithmName); + sr.Serialize ("EncryptionModeName", EncryptionModeName); + sr.Serialize ("HeaderCreationTime", HeaderCreationTime); + sr.Serialize ("HiddenVolumeProtectionTriggered", HiddenVolumeProtectionTriggered); + sr.Serialize ("LoopDevice", wstring (LoopDevice)); + sr.Serialize ("MinRequiredProgramVersion", MinRequiredProgramVersion); + sr.Serialize ("MountPoint", wstring (MountPoint)); + sr.Serialize ("Path", wstring (Path)); + sr.Serialize ("Pkcs5IterationCount", Pkcs5IterationCount); + sr.Serialize ("Pkcs5PrfName", Pkcs5PrfName); + sr.Serialize ("Protection", static_cast (Protection)); + sr.Serialize ("SerialInstanceNumber", SerialInstanceNumber); + sr.Serialize ("Size", Size); + sr.Serialize ("SlotNumber", SlotNumber); + sr.Serialize ("SystemEncryption", SystemEncryption); + sr.Serialize ("TopWriteOffset", TopWriteOffset); + sr.Serialize ("TotalDataRead", TotalDataRead); + sr.Serialize ("TotalDataWritten", TotalDataWritten); + sr.Serialize ("Type", static_cast (Type)); + sr.Serialize ("VirtualDevice", wstring (VirtualDevice)); + sr.Serialize ("VolumeCreationTime", VolumeCreationTime); + } + + void VolumeInfo::Set (const Volume &volume) + { + EncryptionAlgorithmBlockSize = static_cast (volume.GetEncryptionAlgorithm()->GetMaxBlockSize()); + EncryptionAlgorithmKeySize = static_cast (volume.GetEncryptionAlgorithm()->GetKeySize()); + EncryptionAlgorithmMinBlockSize = static_cast (volume.GetEncryptionAlgorithm()->GetMinBlockSize()); + EncryptionAlgorithmName = volume.GetEncryptionAlgorithm()->GetName(); + EncryptionModeName = volume.GetEncryptionMode()->GetName(); + HeaderCreationTime = volume.GetHeaderCreationTime(); + VolumeCreationTime = volume.GetVolumeCreationTime(); + HiddenVolumeProtectionTriggered = volume.IsHiddenVolumeProtectionTriggered(); + MinRequiredProgramVersion = volume.GetHeader()->GetRequiredMinProgramVersion(); + Path = volume.GetPath(); + Pkcs5IterationCount = volume.GetPkcs5Kdf()->GetIterationCount(); + Pkcs5PrfName = volume.GetPkcs5Kdf()->GetName(); + Protection = volume.GetProtectionType(); + Size = volume.GetSize(); + SystemEncryption = volume.IsInSystemEncryptionScope(); + Type = volume.GetType(); + TopWriteOffset = volume.GetTopWriteOffset(); + TotalDataRead = volume.GetTotalDataRead(); + TotalDataWritten = volume.GetTotalDataWritten(); + } + + TC_SERIALIZER_FACTORY_ADD_CLASS (VolumeInfo); +} diff --git a/Volume/VolumeInfo.h b/Volume/VolumeInfo.h index b228bff..aa59d17 100644 --- a/Volume/VolumeInfo.h +++ b/Volume/VolumeInfo.h @@ -1,66 +1,66 @@ -/* - Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_VolumeInfo -#define TC_HEADER_Volume_VolumeInfo - -#include "Platform/Platform.h" -#include "Platform/Serializable.h" -#include "Volume/Volume.h" -#include "Volume/VolumeSlot.h" - -namespace TrueCrypt -{ - class VolumeInfo; - typedef list < shared_ptr > VolumeInfoList; - - class VolumeInfo : public Serializable - { - public: - VolumeInfo () { } - virtual ~VolumeInfo () { } - - TC_SERIALIZABLE (VolumeInfo); - static bool FirstVolumeMountedAfterSecond (shared_ptr first, shared_ptr second); - void Set (const Volume &volume); - - // Modifying this structure can introduce incompatibility with previous versions - DirectoryPath AuxMountPoint; - uint32 EncryptionAlgorithmBlockSize; - uint32 EncryptionAlgorithmKeySize; - uint32 EncryptionAlgorithmMinBlockSize; - wstring EncryptionAlgorithmName; - wstring EncryptionModeName; - VolumeTime HeaderCreationTime; - bool HiddenVolumeProtectionTriggered; - DevicePath LoopDevice; - uint32 MinRequiredProgramVersion; - DirectoryPath MountPoint; - VolumePath Path; - uint32 Pkcs5IterationCount; - wstring Pkcs5PrfName; - uint32 ProgramVersion; - VolumeProtection::Enum Protection; - uint64 SerialInstanceNumber; - uint64 Size; - VolumeSlotNumber SlotNumber; - bool SystemEncryption; - uint64 TopWriteOffset; - uint64 TotalDataRead; - uint64 TotalDataWritten; - VolumeType::Enum Type; - DevicePath VirtualDevice; - VolumeTime VolumeCreationTime; - - private: - VolumeInfo (const VolumeInfo &); - VolumeInfo &operator= (const VolumeInfo &); - }; -} - -#endif // TC_HEADER_Volume_VolumeInfo +/* + Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_VolumeInfo +#define TC_HEADER_Volume_VolumeInfo + +#include "Platform/Platform.h" +#include "Platform/Serializable.h" +#include "Volume/Volume.h" +#include "Volume/VolumeSlot.h" + +namespace TrueCrypt +{ + class VolumeInfo; + typedef list < shared_ptr > VolumeInfoList; + + class VolumeInfo : public Serializable + { + public: + VolumeInfo () { } + virtual ~VolumeInfo () { } + + TC_SERIALIZABLE (VolumeInfo); + static bool FirstVolumeMountedAfterSecond (shared_ptr first, shared_ptr second); + void Set (const Volume &volume); + + // Modifying this structure can introduce incompatibility with previous versions + DirectoryPath AuxMountPoint; + uint32 EncryptionAlgorithmBlockSize; + uint32 EncryptionAlgorithmKeySize; + uint32 EncryptionAlgorithmMinBlockSize; + wstring EncryptionAlgorithmName; + wstring EncryptionModeName; + VolumeTime HeaderCreationTime; + bool HiddenVolumeProtectionTriggered; + DevicePath LoopDevice; + uint32 MinRequiredProgramVersion; + DirectoryPath MountPoint; + VolumePath Path; + uint32 Pkcs5IterationCount; + wstring Pkcs5PrfName; + uint32 ProgramVersion; + VolumeProtection::Enum Protection; + uint64 SerialInstanceNumber; + uint64 Size; + VolumeSlotNumber SlotNumber; + bool SystemEncryption; + uint64 TopWriteOffset; + uint64 TotalDataRead; + uint64 TotalDataWritten; + VolumeType::Enum Type; + DevicePath VirtualDevice; + VolumeTime VolumeCreationTime; + + private: + VolumeInfo (const VolumeInfo &); + VolumeInfo &operator= (const VolumeInfo &); + }; +} + +#endif // TC_HEADER_Volume_VolumeInfo diff --git a/Volume/VolumeLayout.cpp b/Volume/VolumeLayout.cpp index ca26939..aad6f77 100644 --- a/Volume/VolumeLayout.cpp +++ b/Volume/VolumeLayout.cpp @@ -1,254 +1,254 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "Volume/EncryptionMode.h" -#include "Volume/EncryptionModeCBC.h" -#include "Volume/EncryptionModeLRW.h" -#include "Volume/EncryptionModeXTS.h" -#include "VolumeLayout.h" -#include "Boot/Windows/BootCommon.h" - -namespace TrueCrypt -{ - VolumeLayout::VolumeLayout () - { - } - - VolumeLayout::~VolumeLayout () - { - } - - VolumeLayoutList VolumeLayout::GetAvailableLayouts (VolumeType::Enum type) - { - VolumeLayoutList layouts; - - layouts.push_back (shared_ptr (new VolumeLayoutV2Normal ())); - layouts.push_back (shared_ptr (new VolumeLayoutV1Normal ())); - layouts.push_back (shared_ptr (new VolumeLayoutV2Hidden ())); - layouts.push_back (shared_ptr (new VolumeLayoutV1Hidden ())); - layouts.push_back (shared_ptr (new VolumeLayoutSystemEncryption ())); - - if (type != VolumeType::Unknown) - { - VolumeLayoutList l; - - foreach (shared_ptr vl, layouts) - { - if (vl->GetType() == type) - l.push_back (vl); - } - - layouts = l; - } - - return layouts; - } - - shared_ptr VolumeLayout::GetHeader () - { - if (Header.get() == nullptr) - Header.reset (new VolumeHeader (GetHeaderSize())); - - return Header; - } - - - VolumeLayoutV1Normal::VolumeLayoutV1Normal () - { - Type = VolumeType::Normal; - HeaderOffset = TC_VOLUME_HEADER_OFFSET; - HeaderSize = TC_VOLUME_HEADER_SIZE_LEGACY; - - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); - - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfishSerpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Blowfish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Cast5 ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new TripleDES ())); - - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - uint64 VolumeLayoutV1Normal::GetDataOffset (uint64 volumeHostSize) const - { - return HeaderSize; - } - - uint64 VolumeLayoutV1Normal::GetDataSize (uint64 volumeHostSize) const - { - return volumeHostSize - GetHeaderSize(); - } - - - VolumeLayoutV1Hidden::VolumeLayoutV1Hidden () - { - Type = VolumeType::Hidden; - HeaderOffset = -TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; - HeaderSize = TC_VOLUME_HEADER_SIZE_LEGACY; - - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); - - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfishSerpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Blowfish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Cast5 ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new TripleDES ())); - - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeLRW ())); - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeCBC ())); - } - - uint64 VolumeLayoutV1Hidden::GetDataOffset (uint64 volumeHostSize) const - { - return volumeHostSize - GetDataSize (volumeHostSize) + HeaderOffset; - } - - uint64 VolumeLayoutV1Hidden::GetDataSize (uint64 volumeHostSize) const - { - return Header->GetHiddenVolumeDataSize (); - } - - - VolumeLayoutV2Normal::VolumeLayoutV2Normal () - { - Type = VolumeType::Normal; - HeaderOffset = TC_VOLUME_HEADER_OFFSET; - HeaderSize = TC_VOLUME_HEADER_SIZE; - BackupHeaderOffset = -TC_VOLUME_HEADER_GROUP_SIZE; - - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); - - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); - } - - uint64 VolumeLayoutV2Normal::GetDataOffset (uint64 volumeHostSize) const - { - return Header->GetEncryptedAreaStart(); - } - - uint64 VolumeLayoutV2Normal::GetDataSize (uint64 volumeHostSize) const - { - return Header->GetVolumeDataSize(); - } - - uint64 VolumeLayoutV2Normal::GetMaxDataSize (uint64 volumeSize) const - { - if (volumeSize < TC_TOTAL_VOLUME_HEADERS_SIZE) - return 0; - - return volumeSize - TC_TOTAL_VOLUME_HEADERS_SIZE; - } - - - VolumeLayoutV2Hidden::VolumeLayoutV2Hidden () - { - Type = VolumeType::Hidden; - HeaderOffset = TC_HIDDEN_VOLUME_HEADER_OFFSET; - HeaderSize = TC_VOLUME_HEADER_SIZE; - BackupHeaderOffset = -TC_HIDDEN_VOLUME_HEADER_OFFSET; - - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); - - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); - } - - uint64 VolumeLayoutV2Hidden::GetDataOffset (uint64 volumeHostSize) const - { - return Header->GetEncryptedAreaStart(); - } - - uint64 VolumeLayoutV2Hidden::GetDataSize (uint64 volumeHostSize) const - { - return Header->GetVolumeDataSize(); - } - - uint64 VolumeLayoutV2Hidden::GetMaxDataSize (uint64 volumeSize) const - { - // Reserve free space at the end of the host filesystem - uint64 reservedSize; - - if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD) - reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE; - else - reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; // Ensure size of a hidden volume larger than TC_VOLUME_SMALL_SIZE_THRESHOLD is a multiple of the maximum supported sector size - - if (volumeSize < reservedSize) - return 0; - - return volumeSize - reservedSize; - } - - - VolumeLayoutSystemEncryption::VolumeLayoutSystemEncryption () - { - Type = VolumeType::Normal; - HeaderOffset = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; - HeaderSize = TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE; - - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); - SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); - - SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); - } - - uint64 VolumeLayoutSystemEncryption::GetDataOffset (uint64 volumeHostSize) const - { - return 0; - } - - uint64 VolumeLayoutSystemEncryption::GetDataSize (uint64 volumeHostSize) const - { - return volumeHostSize; - } - - Pkcs5KdfList VolumeLayoutSystemEncryption::GetSupportedKeyDerivationFunctions () const - { - Pkcs5KdfList l; - - l.push_back (shared_ptr (new Pkcs5HmacRipemd160_1000 ())); - return l; - } -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "Volume/EncryptionMode.h" +#include "Volume/EncryptionModeCBC.h" +#include "Volume/EncryptionModeLRW.h" +#include "Volume/EncryptionModeXTS.h" +#include "VolumeLayout.h" +#include "Boot/Windows/BootCommon.h" + +namespace TrueCrypt +{ + VolumeLayout::VolumeLayout () + { + } + + VolumeLayout::~VolumeLayout () + { + } + + VolumeLayoutList VolumeLayout::GetAvailableLayouts (VolumeType::Enum type) + { + VolumeLayoutList layouts; + + layouts.push_back (shared_ptr (new VolumeLayoutV2Normal ())); + layouts.push_back (shared_ptr (new VolumeLayoutV1Normal ())); + layouts.push_back (shared_ptr (new VolumeLayoutV2Hidden ())); + layouts.push_back (shared_ptr (new VolumeLayoutV1Hidden ())); + layouts.push_back (shared_ptr (new VolumeLayoutSystemEncryption ())); + + if (type != VolumeType::Unknown) + { + VolumeLayoutList l; + + foreach (shared_ptr vl, layouts) + { + if (vl->GetType() == type) + l.push_back (vl); + } + + layouts = l; + } + + return layouts; + } + + shared_ptr VolumeLayout::GetHeader () + { + if (Header.get() == nullptr) + Header.reset (new VolumeHeader (GetHeaderSize())); + + return Header; + } + + + VolumeLayoutV1Normal::VolumeLayoutV1Normal () + { + Type = VolumeType::Normal; + HeaderOffset = TC_VOLUME_HEADER_OFFSET; + HeaderSize = TC_VOLUME_HEADER_SIZE_LEGACY; + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Blowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Cast5 ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TripleDES ())); + + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + uint64 VolumeLayoutV1Normal::GetDataOffset (uint64 volumeHostSize) const + { + return HeaderSize; + } + + uint64 VolumeLayoutV1Normal::GetDataSize (uint64 volumeHostSize) const + { + return volumeHostSize - GetHeaderSize(); + } + + + VolumeLayoutV1Hidden::VolumeLayoutV1Hidden () + { + Type = VolumeType::Hidden; + HeaderOffset = -TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; + HeaderSize = TC_VOLUME_HEADER_SIZE_LEGACY; + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESBlowfishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Blowfish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Cast5 ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TripleDES ())); + + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeLRW ())); + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeCBC ())); + } + + uint64 VolumeLayoutV1Hidden::GetDataOffset (uint64 volumeHostSize) const + { + return volumeHostSize - GetDataSize (volumeHostSize) + HeaderOffset; + } + + uint64 VolumeLayoutV1Hidden::GetDataSize (uint64 volumeHostSize) const + { + return Header->GetHiddenVolumeDataSize (); + } + + + VolumeLayoutV2Normal::VolumeLayoutV2Normal () + { + Type = VolumeType::Normal; + HeaderOffset = TC_VOLUME_HEADER_OFFSET; + HeaderSize = TC_VOLUME_HEADER_SIZE; + BackupHeaderOffset = -TC_VOLUME_HEADER_GROUP_SIZE; + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); + } + + uint64 VolumeLayoutV2Normal::GetDataOffset (uint64 volumeHostSize) const + { + return Header->GetEncryptedAreaStart(); + } + + uint64 VolumeLayoutV2Normal::GetDataSize (uint64 volumeHostSize) const + { + return Header->GetVolumeDataSize(); + } + + uint64 VolumeLayoutV2Normal::GetMaxDataSize (uint64 volumeSize) const + { + if (volumeSize < TC_TOTAL_VOLUME_HEADERS_SIZE) + return 0; + + return volumeSize - TC_TOTAL_VOLUME_HEADERS_SIZE; + } + + + VolumeLayoutV2Hidden::VolumeLayoutV2Hidden () + { + Type = VolumeType::Hidden; + HeaderOffset = TC_HIDDEN_VOLUME_HEADER_OFFSET; + HeaderSize = TC_VOLUME_HEADER_SIZE; + BackupHeaderOffset = -TC_HIDDEN_VOLUME_HEADER_OFFSET; + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); + } + + uint64 VolumeLayoutV2Hidden::GetDataOffset (uint64 volumeHostSize) const + { + return Header->GetEncryptedAreaStart(); + } + + uint64 VolumeLayoutV2Hidden::GetDataSize (uint64 volumeHostSize) const + { + return Header->GetVolumeDataSize(); + } + + uint64 VolumeLayoutV2Hidden::GetMaxDataSize (uint64 volumeSize) const + { + // Reserve free space at the end of the host filesystem + uint64 reservedSize; + + if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD) + reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE; + else + reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; // Ensure size of a hidden volume larger than TC_VOLUME_SMALL_SIZE_THRESHOLD is a multiple of the maximum supported sector size + + if (volumeSize < reservedSize) + return 0; + + return volumeSize - reservedSize; + } + + + VolumeLayoutSystemEncryption::VolumeLayoutSystemEncryption () + { + Type = VolumeType::Normal; + HeaderOffset = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + HeaderSize = TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE; + + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Serpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new Twofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofish ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new AESTwofishSerpent ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new SerpentTwofishAES ())); + SupportedEncryptionAlgorithms.push_back (shared_ptr (new TwofishSerpent ())); + + SupportedEncryptionModes.push_back (shared_ptr (new EncryptionModeXTS ())); + } + + uint64 VolumeLayoutSystemEncryption::GetDataOffset (uint64 volumeHostSize) const + { + return 0; + } + + uint64 VolumeLayoutSystemEncryption::GetDataSize (uint64 volumeHostSize) const + { + return volumeHostSize; + } + + Pkcs5KdfList VolumeLayoutSystemEncryption::GetSupportedKeyDerivationFunctions () const + { + Pkcs5KdfList l; + + l.push_back (shared_ptr (new Pkcs5HmacRipemd160_1000 ())); + return l; + } +} diff --git a/Volume/VolumeLayout.h b/Volume/VolumeLayout.h index 5a8c5ca..3520763 100644 --- a/Volume/VolumeLayout.h +++ b/Volume/VolumeLayout.h @@ -1,153 +1,153 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_VolumeLayout -#define TC_HEADER_Volume_VolumeLayout - -#include "Platform/Platform.h" -#include "Volume/EncryptionAlgorithm.h" -#include "Volume/EncryptionMode.h" -#include "Volume/Pkcs5Kdf.h" -#include "VolumeHeader.h" - -namespace TrueCrypt -{ - class VolumeLayout; - typedef list < shared_ptr > VolumeLayoutList; - - class VolumeLayout - { - public: - virtual ~VolumeLayout (); - - static VolumeLayoutList GetAvailableLayouts (VolumeType::Enum type = VolumeType::Unknown); - virtual int GetBackupHeaderOffset () const { return BackupHeaderOffset; } // Positive value: offset from the start of host, negative: offset from the end - virtual uint64 GetDataOffset (uint64 volumeHostSize) const = 0; - virtual uint64 GetDataSize (uint64 volumeHostSize) const = 0; - virtual shared_ptr GetHeader (); - virtual int GetHeaderOffset () const { return HeaderOffset; } // Positive value: offset from the start of host, negative: offset from the end - virtual uint32 GetHeaderSize () const { return HeaderSize; } - virtual uint64 GetMaxDataSize (uint64 volumeSize) const = 0; - virtual EncryptionAlgorithmList GetSupportedEncryptionAlgorithms () const { return SupportedEncryptionAlgorithms; } - virtual Pkcs5KdfList GetSupportedKeyDerivationFunctions () const { return Pkcs5Kdf::GetAvailableAlgorithms(); } - virtual EncryptionModeList GetSupportedEncryptionModes () const { return SupportedEncryptionModes; } - virtual VolumeType::Enum GetType () const { return Type; } - virtual bool HasBackupHeader () const = 0; - virtual bool HasDriveHeader () const { return false; } - virtual void SetHeader (shared_ptr header) { Header = header; } - - protected: - VolumeLayout (); - - EncryptionAlgorithmList SupportedEncryptionAlgorithms; - EncryptionModeList SupportedEncryptionModes; - - int BackupHeaderOffset; - int HeaderOffset; - uint32 HeaderSize; - VolumeType::Enum Type; - - shared_ptr Header; - - private: - VolumeLayout (const VolumeLayout &); - VolumeLayout &operator= (const VolumeLayout &); - }; - - - class VolumeLayoutV1Normal : public VolumeLayout - { - public: - VolumeLayoutV1Normal (); - virtual ~VolumeLayoutV1Normal () { } - - virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); } - virtual uint64 GetDataOffset (uint64 volumeHostSize) const; - virtual uint64 GetDataSize (uint64 volumeHostSize) const; - virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); } - virtual bool HasBackupHeader () const { return false; } - - private: - VolumeLayoutV1Normal (const VolumeLayoutV1Normal &); - VolumeLayoutV1Normal &operator= (const VolumeLayoutV1Normal &); - }; - - - class VolumeLayoutV1Hidden : public VolumeLayout - { - public: - VolumeLayoutV1Hidden (); - virtual ~VolumeLayoutV1Hidden () { } - - virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); } - virtual uint64 GetDataOffset (uint64 volumeHostSize) const; - virtual uint64 GetDataSize (uint64 volumeHostSize) const; - virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); } - virtual bool HasBackupHeader () const { return false; } - - private: - VolumeLayoutV1Hidden (const VolumeLayoutV1Hidden &); - VolumeLayoutV1Hidden &operator= (const VolumeLayoutV1Hidden &); - }; - - - class VolumeLayoutV2Normal : public VolumeLayout - { - public: - VolumeLayoutV2Normal (); - virtual ~VolumeLayoutV2Normal () { } - - virtual uint64 GetDataOffset (uint64 volumeHostSize) const; - virtual uint64 GetDataSize (uint64 volumeHostSize) const; - virtual uint64 GetMaxDataSize (uint64 volumeSize) const; - virtual bool HasBackupHeader () const { return true; } - - private: - VolumeLayoutV2Normal (const VolumeLayoutV2Normal &); - VolumeLayoutV2Normal &operator= (const VolumeLayoutV2Normal &); - }; - - - class VolumeLayoutV2Hidden : public VolumeLayout - { - public: - VolumeLayoutV2Hidden (); - virtual ~VolumeLayoutV2Hidden () { } - - virtual uint64 GetDataOffset (uint64 volumeHostSize) const; - virtual uint64 GetDataSize (uint64 volumeHostSize) const; - virtual uint64 GetMaxDataSize (uint64 volumeSize) const; - virtual bool HasBackupHeader () const { return true; } - - private: - VolumeLayoutV2Hidden (const VolumeLayoutV2Hidden &); - VolumeLayoutV2Hidden &operator= (const VolumeLayoutV2Hidden &); - }; - - - class VolumeLayoutSystemEncryption : public VolumeLayout - { - public: - VolumeLayoutSystemEncryption (); - virtual ~VolumeLayoutSystemEncryption () { } - - virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); } - virtual uint64 GetDataOffset (uint64 volumeHostSize) const; - virtual uint64 GetDataSize (uint64 volumeHostSize) const; - virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); } - virtual Pkcs5KdfList GetSupportedKeyDerivationFunctions () const; - virtual bool HasBackupHeader () const { return false; } - virtual bool HasDriveHeader () const { return true; } - - private: - VolumeLayoutSystemEncryption (const VolumeLayoutSystemEncryption &); - VolumeLayoutSystemEncryption &operator= (const VolumeLayoutSystemEncryption &); - }; -} - -#endif // TC_HEADER_Volume_VolumeLayout +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_VolumeLayout +#define TC_HEADER_Volume_VolumeLayout + +#include "Platform/Platform.h" +#include "Volume/EncryptionAlgorithm.h" +#include "Volume/EncryptionMode.h" +#include "Volume/Pkcs5Kdf.h" +#include "VolumeHeader.h" + +namespace TrueCrypt +{ + class VolumeLayout; + typedef list < shared_ptr > VolumeLayoutList; + + class VolumeLayout + { + public: + virtual ~VolumeLayout (); + + static VolumeLayoutList GetAvailableLayouts (VolumeType::Enum type = VolumeType::Unknown); + virtual int GetBackupHeaderOffset () const { return BackupHeaderOffset; } // Positive value: offset from the start of host, negative: offset from the end + virtual uint64 GetDataOffset (uint64 volumeHostSize) const = 0; + virtual uint64 GetDataSize (uint64 volumeHostSize) const = 0; + virtual shared_ptr GetHeader (); + virtual int GetHeaderOffset () const { return HeaderOffset; } // Positive value: offset from the start of host, negative: offset from the end + virtual uint32 GetHeaderSize () const { return HeaderSize; } + virtual uint64 GetMaxDataSize (uint64 volumeSize) const = 0; + virtual EncryptionAlgorithmList GetSupportedEncryptionAlgorithms () const { return SupportedEncryptionAlgorithms; } + virtual Pkcs5KdfList GetSupportedKeyDerivationFunctions () const { return Pkcs5Kdf::GetAvailableAlgorithms(); } + virtual EncryptionModeList GetSupportedEncryptionModes () const { return SupportedEncryptionModes; } + virtual VolumeType::Enum GetType () const { return Type; } + virtual bool HasBackupHeader () const = 0; + virtual bool HasDriveHeader () const { return false; } + virtual void SetHeader (shared_ptr header) { Header = header; } + + protected: + VolumeLayout (); + + EncryptionAlgorithmList SupportedEncryptionAlgorithms; + EncryptionModeList SupportedEncryptionModes; + + int BackupHeaderOffset; + int HeaderOffset; + uint32 HeaderSize; + VolumeType::Enum Type; + + shared_ptr Header; + + private: + VolumeLayout (const VolumeLayout &); + VolumeLayout &operator= (const VolumeLayout &); + }; + + + class VolumeLayoutV1Normal : public VolumeLayout + { + public: + VolumeLayoutV1Normal (); + virtual ~VolumeLayoutV1Normal () { } + + virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); } + virtual uint64 GetDataOffset (uint64 volumeHostSize) const; + virtual uint64 GetDataSize (uint64 volumeHostSize) const; + virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); } + virtual bool HasBackupHeader () const { return false; } + + private: + VolumeLayoutV1Normal (const VolumeLayoutV1Normal &); + VolumeLayoutV1Normal &operator= (const VolumeLayoutV1Normal &); + }; + + + class VolumeLayoutV1Hidden : public VolumeLayout + { + public: + VolumeLayoutV1Hidden (); + virtual ~VolumeLayoutV1Hidden () { } + + virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); } + virtual uint64 GetDataOffset (uint64 volumeHostSize) const; + virtual uint64 GetDataSize (uint64 volumeHostSize) const; + virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); } + virtual bool HasBackupHeader () const { return false; } + + private: + VolumeLayoutV1Hidden (const VolumeLayoutV1Hidden &); + VolumeLayoutV1Hidden &operator= (const VolumeLayoutV1Hidden &); + }; + + + class VolumeLayoutV2Normal : public VolumeLayout + { + public: + VolumeLayoutV2Normal (); + virtual ~VolumeLayoutV2Normal () { } + + virtual uint64 GetDataOffset (uint64 volumeHostSize) const; + virtual uint64 GetDataSize (uint64 volumeHostSize) const; + virtual uint64 GetMaxDataSize (uint64 volumeSize) const; + virtual bool HasBackupHeader () const { return true; } + + private: + VolumeLayoutV2Normal (const VolumeLayoutV2Normal &); + VolumeLayoutV2Normal &operator= (const VolumeLayoutV2Normal &); + }; + + + class VolumeLayoutV2Hidden : public VolumeLayout + { + public: + VolumeLayoutV2Hidden (); + virtual ~VolumeLayoutV2Hidden () { } + + virtual uint64 GetDataOffset (uint64 volumeHostSize) const; + virtual uint64 GetDataSize (uint64 volumeHostSize) const; + virtual uint64 GetMaxDataSize (uint64 volumeSize) const; + virtual bool HasBackupHeader () const { return true; } + + private: + VolumeLayoutV2Hidden (const VolumeLayoutV2Hidden &); + VolumeLayoutV2Hidden &operator= (const VolumeLayoutV2Hidden &); + }; + + + class VolumeLayoutSystemEncryption : public VolumeLayout + { + public: + VolumeLayoutSystemEncryption (); + virtual ~VolumeLayoutSystemEncryption () { } + + virtual int GetBackupHeaderOffset () const { throw NotApplicable (SRC_POS); } + virtual uint64 GetDataOffset (uint64 volumeHostSize) const; + virtual uint64 GetDataSize (uint64 volumeHostSize) const; + virtual uint64 GetMaxDataSize (uint64 volumeSize) const { throw NotApplicable (SRC_POS); } + virtual Pkcs5KdfList GetSupportedKeyDerivationFunctions () const; + virtual bool HasBackupHeader () const { return false; } + virtual bool HasDriveHeader () const { return true; } + + private: + VolumeLayoutSystemEncryption (const VolumeLayoutSystemEncryption &); + VolumeLayoutSystemEncryption &operator= (const VolumeLayoutSystemEncryption &); + }; +} + +#endif // TC_HEADER_Volume_VolumeLayout diff --git a/Volume/VolumePassword.cpp b/Volume/VolumePassword.cpp index 16cdcac..ee192f5 100644 --- a/Volume/VolumePassword.cpp +++ b/Volume/VolumePassword.cpp @@ -1,167 +1,167 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "VolumePassword.h" -#include "Platform/SerializerFactory.h" -#include "Platform/StringConverter.h" - -namespace TrueCrypt -{ - VolumePassword::VolumePassword () : PasswordSize (0), Unportable (false) - { - AllocateBuffer (); - } - - VolumePassword::VolumePassword (const char *password, size_t size) - { - Set ((const byte *) password, size); - } - - VolumePassword::VolumePassword (const byte *password, size_t size) - { - Set (password, size); - } - - VolumePassword::VolumePassword (const wchar_t *password, size_t charCount) - { - Set (password, charCount); - } - - VolumePassword::VolumePassword (const wstring &password) - { - Set (password.c_str(), password.size()); - } - - VolumePassword::~VolumePassword () - { - } - - void VolumePassword::AllocateBuffer () - { - if (!PasswordBuffer.IsAllocated ()) - PasswordBuffer.Allocate (MaxSize); - } - - void VolumePassword::CheckPortability () const - { - if (Unportable || !IsPortable()) - throw UnportablePassword (SRC_POS); - } - - void VolumePassword::Deserialize (shared_ptr stream) - { - Serializer sr (stream); - uint64 passwordSize; - sr.Deserialize ("PasswordSize", passwordSize); - PasswordSize = static_cast (passwordSize); - sr.Deserialize ("PasswordBuffer", BufferPtr (PasswordBuffer)); - - Buffer wipeBuffer (128 * 1024); - sr.Deserialize ("WipeData", wipeBuffer); - } - - bool VolumePassword::IsPortable () const - { - for (size_t i = 0; i < PasswordSize; i++) - { - if (PasswordBuffer[i] >= 0x7f || PasswordBuffer[i] < 0x20) - return false; - } - return true; - } - - void VolumePassword::Serialize (shared_ptr stream) const - { - Serializable::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("PasswordSize", static_cast (PasswordSize)); - sr.Serialize ("PasswordBuffer", ConstBufferPtr (PasswordBuffer)); - - // Wipe password from an eventual pipe buffer - Buffer wipeBuffer (128 * 1024); - wipeBuffer.Zero(); - sr.Serialize ("WipeData", ConstBufferPtr (wipeBuffer)); - } - - void VolumePassword::Set (const byte *password, size_t size) - { - AllocateBuffer (); - - if (size > MaxSize) - throw PasswordTooLong (SRC_POS); - - PasswordBuffer.CopyFrom (ConstBufferPtr (password, size)); - PasswordSize = size; - - Unportable = !IsPortable(); - } - - void VolumePassword::Set (const wchar_t *password, size_t charCount) - { - if (charCount > MaxSize) - throw PasswordTooLong (SRC_POS); - - union Conv - { - byte b[sizeof (wchar_t)]; - wchar_t c; - }; - - Conv conv; - conv.c = L'A'; - - int lsbPos = -1; - for (size_t i = 0; i < sizeof (conv.b); ++i) - { - if (conv.b[i] == L'A') - { - lsbPos = i; - break; - } - } - - if (lsbPos == -1) - throw ParameterIncorrect (SRC_POS); - - bool unportable = false; - byte passwordBuf[MaxSize]; - for (size_t i = 0; i < charCount; ++i) - { - conv.c = password[i]; - passwordBuf[i] = conv.b[lsbPos]; - for (int j = 0; j < sizeof (wchar_t); ++j) - { - if (j != lsbPos && conv.b[j] != 0) - unportable = true; - } - } - - Set (passwordBuf, charCount); - - if (unportable) - Unportable = true; - } - - void VolumePassword::Set (const ConstBufferPtr &password) - { - Set (password, password.Size()); - } - - void VolumePassword::Set (const VolumePassword &password) - { - Set (password.DataPtr(), password.Size()); - } - - TC_SERIALIZER_FACTORY_ADD_CLASS (VolumePassword); - -#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -#undef TC_EXCEPTION_NODECL -#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (PasswordException); -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "VolumePassword.h" +#include "Platform/SerializerFactory.h" +#include "Platform/StringConverter.h" + +namespace TrueCrypt +{ + VolumePassword::VolumePassword () : PasswordSize (0), Unportable (false) + { + AllocateBuffer (); + } + + VolumePassword::VolumePassword (const char *password, size_t size) + { + Set ((const byte *) password, size); + } + + VolumePassword::VolumePassword (const byte *password, size_t size) + { + Set (password, size); + } + + VolumePassword::VolumePassword (const wchar_t *password, size_t charCount) + { + Set (password, charCount); + } + + VolumePassword::VolumePassword (const wstring &password) + { + Set (password.c_str(), password.size()); + } + + VolumePassword::~VolumePassword () + { + } + + void VolumePassword::AllocateBuffer () + { + if (!PasswordBuffer.IsAllocated ()) + PasswordBuffer.Allocate (MaxSize); + } + + void VolumePassword::CheckPortability () const + { + if (Unportable || !IsPortable()) + throw UnportablePassword (SRC_POS); + } + + void VolumePassword::Deserialize (shared_ptr stream) + { + Serializer sr (stream); + uint64 passwordSize; + sr.Deserialize ("PasswordSize", passwordSize); + PasswordSize = static_cast (passwordSize); + sr.Deserialize ("PasswordBuffer", BufferPtr (PasswordBuffer)); + + Buffer wipeBuffer (128 * 1024); + sr.Deserialize ("WipeData", wipeBuffer); + } + + bool VolumePassword::IsPortable () const + { + for (size_t i = 0; i < PasswordSize; i++) + { + if (PasswordBuffer[i] >= 0x7f || PasswordBuffer[i] < 0x20) + return false; + } + return true; + } + + void VolumePassword::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("PasswordSize", static_cast (PasswordSize)); + sr.Serialize ("PasswordBuffer", ConstBufferPtr (PasswordBuffer)); + + // Wipe password from an eventual pipe buffer + Buffer wipeBuffer (128 * 1024); + wipeBuffer.Zero(); + sr.Serialize ("WipeData", ConstBufferPtr (wipeBuffer)); + } + + void VolumePassword::Set (const byte *password, size_t size) + { + AllocateBuffer (); + + if (size > MaxSize) + throw PasswordTooLong (SRC_POS); + + PasswordBuffer.CopyFrom (ConstBufferPtr (password, size)); + PasswordSize = size; + + Unportable = !IsPortable(); + } + + void VolumePassword::Set (const wchar_t *password, size_t charCount) + { + if (charCount > MaxSize) + throw PasswordTooLong (SRC_POS); + + union Conv + { + byte b[sizeof (wchar_t)]; + wchar_t c; + }; + + Conv conv; + conv.c = L'A'; + + int lsbPos = -1; + for (size_t i = 0; i < sizeof (conv.b); ++i) + { + if (conv.b[i] == L'A') + { + lsbPos = i; + break; + } + } + + if (lsbPos == -1) + throw ParameterIncorrect (SRC_POS); + + bool unportable = false; + byte passwordBuf[MaxSize]; + for (size_t i = 0; i < charCount; ++i) + { + conv.c = password[i]; + passwordBuf[i] = conv.b[lsbPos]; + for (int j = 0; j < (int) sizeof (wchar_t); ++j) + { + if (j != lsbPos && conv.b[j] != 0) + unportable = true; + } + } + + Set (passwordBuf, charCount); + + if (unportable) + Unportable = true; + } + + void VolumePassword::Set (const ConstBufferPtr &password) + { + Set (password, password.Size()); + } + + void VolumePassword::Set (const VolumePassword &password) + { + Set (password.DataPtr(), password.Size()); + } + + TC_SERIALIZER_FACTORY_ADD_CLASS (VolumePassword); + +#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +#undef TC_EXCEPTION_NODECL +#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (PasswordException); +} diff --git a/Volume/VolumePassword.h b/Volume/VolumePassword.h index fb5b7c6..8ac976c 100644 --- a/Volume/VolumePassword.h +++ b/Volume/VolumePassword.h @@ -1,92 +1,92 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Encryption_Password -#define TC_HEADER_Encryption_Password - -#include "Platform/Platform.h" -#include "Platform/Serializable.h" - -namespace TrueCrypt -{ - class VolumePassword : public Serializable - { - public: - VolumePassword (); - VolumePassword (const byte *password, size_t size); - VolumePassword (const char *password, size_t size); - VolumePassword (const wchar_t *password, size_t charCount); - VolumePassword (const wstring &password); - VolumePassword (const VolumePassword &password) { Set (password); } - virtual ~VolumePassword (); - - bool operator== (const VolumePassword &other) const { return ConstBufferPtr (DataPtr(), Size()).IsDataEqual (ConstBufferPtr (other.DataPtr(), other.Size())); } - bool operator!= (const VolumePassword &other) const { return !(*this == other); } - VolumePassword &operator= (const VolumePassword &password) { Set (password); return *this; } - - operator BufferPtr () const { return BufferPtr (PasswordBuffer); } - - void CheckPortability () const; - byte *DataPtr () const { return PasswordBuffer; } - bool IsEmpty () const { return PasswordSize == 0; } - size_t Size () const { return PasswordSize; } - void Set (const byte *password, size_t size); - void Set (const wchar_t *password, size_t charCount); - void Set (const ConstBufferPtr &password); - void Set (const VolumePassword &password); - - TC_SERIALIZABLE (VolumePassword); - - static const size_t MaxSize = 64; - static const size_t WarningSizeThreshold = 12; - - protected: - void AllocateBuffer (); - bool IsPortable () const; - - SecureBuffer PasswordBuffer; - - size_t PasswordSize; - bool Unportable; - }; - - struct PasswordException : public Exception - { - protected: - PasswordException () { } - PasswordException (const string &message) : Exception (message) { } - PasswordException (const string &message, const wstring &subject) : Exception (message, subject) { } - }; - - TC_EXCEPTION_DECL (PasswordIncorrect, PasswordException); - TC_EXCEPTION_DECL (PasswordKeyfilesIncorrect, PasswordIncorrect); - TC_EXCEPTION_DECL (PasswordOrKeyboardLayoutIncorrect, PasswordException); - TC_EXCEPTION_DECL (PasswordOrMountOptionsIncorrect, PasswordException); - TC_EXCEPTION_DECL (ProtectionPasswordIncorrect, PasswordIncorrect); - TC_EXCEPTION_DECL (ProtectionPasswordKeyfilesIncorrect, PasswordIncorrect); - -#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,PasswordException) - -#undef TC_EXCEPTION_SET -#define TC_EXCEPTION_SET \ - TC_EXCEPTION_NODECL (PasswordIncorrect); \ - TC_EXCEPTION_NODECL (PasswordKeyfilesIncorrect); \ - TC_EXCEPTION_NODECL (PasswordOrKeyboardLayoutIncorrect); \ - TC_EXCEPTION_NODECL (PasswordOrMountOptionsIncorrect); \ - TC_EXCEPTION_NODECL (ProtectionPasswordIncorrect); \ - TC_EXCEPTION_NODECL (ProtectionPasswordKeyfilesIncorrect); \ - TC_EXCEPTION (PasswordEmpty); \ - TC_EXCEPTION (PasswordTooLong); \ - TC_EXCEPTION (UnportablePassword); - - TC_EXCEPTION_SET; - -#undef TC_EXCEPTION -} - -#endif // TC_HEADER_Encryption_Password +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Encryption_Password +#define TC_HEADER_Encryption_Password + +#include "Platform/Platform.h" +#include "Platform/Serializable.h" + +namespace TrueCrypt +{ + class VolumePassword : public Serializable + { + public: + VolumePassword (); + VolumePassword (const byte *password, size_t size); + VolumePassword (const char *password, size_t size); + VolumePassword (const wchar_t *password, size_t charCount); + VolumePassword (const wstring &password); + VolumePassword (const VolumePassword &password) { Set (password); } + virtual ~VolumePassword (); + + bool operator== (const VolumePassword &other) const { return ConstBufferPtr (DataPtr(), Size()).IsDataEqual (ConstBufferPtr (other.DataPtr(), other.Size())); } + bool operator!= (const VolumePassword &other) const { return !(*this == other); } + VolumePassword &operator= (const VolumePassword &password) { Set (password); return *this; } + + operator BufferPtr () const { return BufferPtr (PasswordBuffer); } + + void CheckPortability () const; + byte *DataPtr () const { return PasswordBuffer; } + bool IsEmpty () const { return PasswordSize == 0; } + size_t Size () const { return PasswordSize; } + void Set (const byte *password, size_t size); + void Set (const wchar_t *password, size_t charCount); + void Set (const ConstBufferPtr &password); + void Set (const VolumePassword &password); + + TC_SERIALIZABLE (VolumePassword); + + static const size_t MaxSize = 64; + static const size_t WarningSizeThreshold = 12; + + protected: + void AllocateBuffer (); + bool IsPortable () const; + + SecureBuffer PasswordBuffer; + + size_t PasswordSize; + bool Unportable; + }; + + struct PasswordException : public Exception + { + protected: + PasswordException () { } + PasswordException (const string &message) : Exception (message) { } + PasswordException (const string &message, const wstring &subject) : Exception (message, subject) { } + }; + + TC_EXCEPTION_DECL (PasswordIncorrect, PasswordException); + TC_EXCEPTION_DECL (PasswordKeyfilesIncorrect, PasswordIncorrect); + TC_EXCEPTION_DECL (PasswordOrKeyboardLayoutIncorrect, PasswordException); + TC_EXCEPTION_DECL (PasswordOrMountOptionsIncorrect, PasswordException); + TC_EXCEPTION_DECL (ProtectionPasswordIncorrect, PasswordIncorrect); + TC_EXCEPTION_DECL (ProtectionPasswordKeyfilesIncorrect, PasswordIncorrect); + +#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,PasswordException) + +#undef TC_EXCEPTION_SET +#define TC_EXCEPTION_SET \ + TC_EXCEPTION_NODECL (PasswordIncorrect); \ + TC_EXCEPTION_NODECL (PasswordKeyfilesIncorrect); \ + TC_EXCEPTION_NODECL (PasswordOrKeyboardLayoutIncorrect); \ + TC_EXCEPTION_NODECL (PasswordOrMountOptionsIncorrect); \ + TC_EXCEPTION_NODECL (ProtectionPasswordIncorrect); \ + TC_EXCEPTION_NODECL (ProtectionPasswordKeyfilesIncorrect); \ + TC_EXCEPTION (PasswordEmpty); \ + TC_EXCEPTION (PasswordTooLong); \ + TC_EXCEPTION (UnportablePassword); + + TC_EXCEPTION_SET; + +#undef TC_EXCEPTION +} + +#endif // TC_HEADER_Encryption_Password diff --git a/Volume/VolumePasswordCache.cpp b/Volume/VolumePasswordCache.cpp index c2442a9..8a8f526 100644 --- a/Volume/VolumePasswordCache.cpp +++ b/Volume/VolumePasswordCache.cpp @@ -1,43 +1,43 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#include "VolumePasswordCache.h" - -namespace TrueCrypt -{ - CachedPasswordList VolumePasswordCache::GetPasswords () - { - CachedPasswordList passwords; - - foreach_ref (const VolumePassword &password, CachedPasswords) - passwords.push_back (make_shared (VolumePassword (password))); - - return passwords; - } - - void VolumePasswordCache::Store (const VolumePassword &newPassword) - { - CachedPasswordList::iterator iter = CachedPasswords.begin(); - foreach_ref (const VolumePassword &password, CachedPasswords) - { - if (newPassword == password) - { - CachedPasswords.erase (iter); - break; - } - iter++; - } - - CachedPasswords.push_front (make_shared (VolumePassword (newPassword))); - - if (CachedPasswords.size() > Capacity) - CachedPasswords.pop_back(); - } - - CachedPasswordList VolumePasswordCache::CachedPasswords; -} +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#include "VolumePasswordCache.h" + +namespace TrueCrypt +{ + CachedPasswordList VolumePasswordCache::GetPasswords () + { + CachedPasswordList passwords; + + foreach_ref (const VolumePassword &password, CachedPasswords) + passwords.push_back (make_shared (VolumePassword (password))); + + return passwords; + } + + void VolumePasswordCache::Store (const VolumePassword &newPassword) + { + CachedPasswordList::iterator iter = CachedPasswords.begin(); + foreach_ref (const VolumePassword &password, CachedPasswords) + { + if (newPassword == password) + { + CachedPasswords.erase (iter); + break; + } + iter++; + } + + CachedPasswords.push_front (make_shared (VolumePassword (newPassword))); + + if (CachedPasswords.size() > Capacity) + CachedPasswords.pop_back(); + } + + CachedPasswordList VolumePasswordCache::CachedPasswords; +} diff --git a/Volume/VolumePasswordCache.h b/Volume/VolumePasswordCache.h index d97a53b..39a2b28 100644 --- a/Volume/VolumePasswordCache.h +++ b/Volume/VolumePasswordCache.h @@ -1,36 +1,36 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_VolumePasswordCache -#define TC_HEADER_Volume_VolumePasswordCache - -#include "Platform/Platform.h" -#include "VolumePassword.h" - -namespace TrueCrypt -{ - typedef list < shared_ptr < VolumePassword > > CachedPasswordList; - - class VolumePasswordCache - { - public: - static CachedPasswordList GetPasswords (); - static bool IsEmpty () { return CachedPasswords.empty(); } - static void Store (const VolumePassword &newPassword); - static void Clear () { CachedPasswords.clear(); } - static const int Capacity = 4; - - protected: - static CachedPasswordList CachedPasswords; - - private: - VolumePasswordCache (); - }; -} - -#endif // TC_HEADER_Volume_VolumePasswordCache +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_VolumePasswordCache +#define TC_HEADER_Volume_VolumePasswordCache + +#include "Platform/Platform.h" +#include "VolumePassword.h" + +namespace TrueCrypt +{ + typedef list < shared_ptr < VolumePassword > > CachedPasswordList; + + class VolumePasswordCache + { + public: + static CachedPasswordList GetPasswords (); + static bool IsEmpty () { return CachedPasswords.empty(); } + static void Store (const VolumePassword &newPassword); + static void Clear () { CachedPasswords.clear(); } + static const size_t Capacity = 4; + + protected: + static CachedPasswordList CachedPasswords; + + private: + VolumePasswordCache (); + }; +} + +#endif // TC_HEADER_Volume_VolumePasswordCache diff --git a/Volume/VolumeSlot.h b/Volume/VolumeSlot.h index 31eb25b..16dede1 100644 --- a/Volume/VolumeSlot.h +++ b/Volume/VolumeSlot.h @@ -1,19 +1,19 @@ -/* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. - - Governed by the TrueCrypt License 2.7 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. -*/ - -#ifndef TC_HEADER_Volume_VolumeSlot -#define TC_HEADER_Volume_VolumeSlot - -#include "Platform/Platform.h" - -namespace TrueCrypt -{ - typedef uint32 VolumeSlotNumber; -} - -#endif // TC_HEADER_Volume_VolumeSlot +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.8 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef TC_HEADER_Volume_VolumeSlot +#define TC_HEADER_Volume_VolumeSlot + +#include "Platform/Platform.h" + +namespace TrueCrypt +{ + typedef uint32 VolumeSlotNumber; +} + +#endif // TC_HEADER_Volume_VolumeSlot