void __fastcall TfrmSpeedTest::Test(bool Decode) { WaitCursor(); for (int i = 0; i < memFiles->Lines->Count; i++) if (FileExists(memFiles->Lines->Strings[i])) { __int64 FStringLength; AnsiString S = StringFromFile(memFiles->Lines->Strings[i], FStringLength); Cardinal FStartTime = GetTickCount(); if (Decode) SimpleXMLDecode(S, false); else SimpleXMLEncode(S); AddInfo(memFiles->Lines->Strings[i], Decode, FStringLength, GetTickCount() - FStartTime, sgResults->Cells[0][1] != ""); } }
void __fastcall TfrmSpeedTest::WMDropFiles(TWMDropFiles& Message) { char buf[MAX_PATH-1]; WaitCursor(); int Count = DragQueryFile(reinterpret_cast<void*>(Message.Drop), 0xFFFFFFFF, NULL, 0); try { for (int i = 0; i < Count; i++) { DragQueryFile(reinterpret_cast<void*>(Message.Drop), i, buf, sizeof(buf)); if (FileExists(buf)) memFiles->Lines->Add(buf); } } __finally { DragFinish(reinterpret_cast<void*>(Message.Drop)); } }
/* ExpandVolume Sets the volume size in the volume header (and backup header) to a larger value, and resizes the filesystem within the volume (only NTFS supported) Parameters: hwndDlg : HWND [in] handle to progress dialog lpszVolume : char * [in] Pointer to a string that contains the path to the truecrypt volume pVolumePassword : Password * [in] Pointer to the volume password newHostSize : uint64 [in] new value of the volume host size (can be zero for devices, which means the volume should use all space of the host device) initFreeSpace : BOOL [in] if true, the new volume space will be initalized with random data Return value: int with Truecrypt error code (ERR_SUCCESS on success) Remarks: a lot of code is from TrueCrypt 'Common\Password.c' :: ChangePwd() */ static int ExpandVolume (HWND hwndDlg, wchar_t *lpszVolume, Password *pVolumePassword, int VolumePkcs5, int VolumePim, uint64 newHostSize, BOOL initFreeSpace) { int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR; wchar_t szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; wchar_t 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; uint64 hostSize=0, newDataAreaSize, currentVolSize; DWORD HostSectorSize; FILETIME ftCreationTime; FILETIME ftLastWriteTime; FILETIME ftLastAccessTime; BOOL bTimeStampValid = FALSE; LARGE_INTEGER headerOffset; BOOL backupHeader; byte *wipeBuffer = NULL; uint32 workChunkSize = TC_VOLUME_HEADER_GROUP_SIZE; if (pVolumePassword->Length == 0) return -1; WaitCursor (); CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), lpszVolume, &bDevice); if (bDevice == FALSE) { wcscpy (szCFDevice, szDiskFile); } else { nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(szCFDevice), FALSE); if (nDosLinkCreated != 0) // note: nStatus == ERR_OS_ERROR 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; HostSectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME; //TO DO: get the real host disk sector size } 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; HostSectorSize = driveInfo.BytesPerSector; } 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; HostSectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME; //TO DO: get the real host disk sector size } if (Randinit ()) { if (CryptoAPILastError == ERROR_SUCCESS) nStatus = ERR_RAND_INIT_FAILED; else nStatus = ERR_CAPI_INIT_FAILED; 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"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); } else bTimeStampValid = TRUE; } // Seek the volume header headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET; 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, pVolumePassword, VolumePkcs5, VolumePim, FALSE, &cryptoInfo, NULL); if (nStatus == ERR_CIPHER_INIT_WEAK_KEY) nStatus = 0; // We can ignore this error here 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; } if (bDevice && newHostSize == 0) { // this means we shall take all host space as new volume size newHostSize = hostSize; } if ( newHostSize % cryptoInfo->SectorSize != 0 || newHostSize > TC_MAX_VOLUME_SIZE || (bDevice && newHostSize > hostSize) ) { // 1. must be multiple of sector size // 2. truecrypt volume size limit // 3. for devices volume size can't be larger than host size cryptoInfo = NULL; nStatus = ERR_PARAMETER_INCORRECT; goto error; } newDataAreaSize = GetVolumeDataAreaSize (newHostSize, cryptoInfo->LegacyVolume); if (cryptoInfo->LegacyVolume) { if (bDevice) { if (initFreeSpace) { // unsupported cryptoInfo = NULL; nStatus = ERR_PARAMETER_INCORRECT; goto error; } else { // note: dummy value (only used for parameter checks) cryptoInfo->VolumeSize.Value = newDataAreaSize - TC_MINVAL_FS_EXPAND; } } else { cryptoInfo->VolumeSize.Value = GetVolumeDataAreaSize (hostSize, TRUE); } } currentVolSize = GetVolumeSizeByDataAreaSize (cryptoInfo->VolumeSize.Value, cryptoInfo->LegacyVolume); if ( newDataAreaSize < cryptoInfo->VolumeSize.Value + TC_MINVAL_FS_EXPAND ) { // shrinking a volume or enlarging by less then TC_MINVAL_FS_EXPAND is not allowed cryptoInfo = NULL; nStatus = ERR_PARAMETER_INCORRECT; goto error; } InitProgressBar ( newHostSize, currentVolSize, FALSE, FALSE, FALSE, TRUE); if (bVolTransformThreadCancel) { SetLastError(0); nStatus = ERR_USER_ABORT; goto error; } if (!bDevice) { LARGE_INTEGER liNewSize; liNewSize.QuadPart=(LONGLONG)newHostSize; // Preallocate the file if (!SetFilePointerEx (dev, liNewSize, NULL, FILE_BEGIN) || !SetEndOfFile (dev) || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0) { nStatus = ERR_OS_ERROR; goto error; } } if (initFreeSpace) { uint64 startSector; int64 num_sectors; // fill new space with random data startSector = currentVolSize/HostSectorSize ; num_sectors = (newHostSize/HostSectorSize) - startSector; if (bDevice && !StartFormatWriteThread()) { nStatus = ERR_OS_ERROR; goto error; } DebugAddProgressDlgStatus(hwndDlg, L"Writing random data to new space ...\r\n"); SetFormatSectorSize(HostSectorSize); nStatus = FormatNoFs (hwndDlg, startSector, num_sectors, dev, cryptoInfo, FALSE); dwError = GetLastError(); StopFormatWriteThread(); SetLastError (dwError); } else { UpdateProgressBar(newHostSize); } if (nStatus != ERR_SUCCESS) { dwError = GetLastError(); DebugAddProgressDlgStatus(hwndDlg, L"Error: failed to write random data ...\r\n"); if ( !bDevice ) { // restore original size of the container file LARGE_INTEGER liOldSize; liOldSize.QuadPart=(LONGLONG)hostSize; if (!SetFilePointerEx (dev, liOldSize, NULL, FILE_BEGIN) || !SetEndOfFile (dev)) { DebugAddProgressDlgStatus(hwndDlg, L"Warning: failed to restore original size of the container file\r\n"); } } SetLastError (dwError); goto error; } RandSetHashFunction (cryptoInfo->pkcs5); // Re-encrypt the volume header forn non-legacy volumes: backup header first backupHeader = TRUE; headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET + newHostSize - TC_VOLUME_HEADER_GROUP_SIZE; /* note: updating the header is not neccessary for legay volumes */ while ( !cryptoInfo->LegacyVolume ) { if (backupHeader) DebugAddProgressDlgStatus(hwndDlg, L"Writing re-encrypted backup header ...\r\n"); else DebugAddProgressDlgStatus(hwndDlg, L"Writing re-encrypted primary header ...\r\n"); // Prepare new volume header nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE, buffer, cryptoInfo->ea, cryptoInfo->mode, pVolumePassword, cryptoInfo->pkcs5, VolumePim, (char*)(cryptoInfo->master_keydata), &ci, newDataAreaSize, 0, // hiddenVolumeSize cryptoInfo->EncryptedAreaStart.Value, newDataAreaSize, cryptoInfo->RequiredProgramVersion, cryptoInfo->HeaderFlags, cryptoInfo->SectorSize, TRUE ); // use slow poll 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 ( ( backupHeader && !initFreeSpace ) || ( bDevice && !cryptoInfo->LegacyVolume && !cryptoInfo->hiddenVolume && cryptoInfo->HeaderVersion == 4 // BUG in TrueCrypt: doing this only for v4 make no sense && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0 && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0 ) ) { //DebugAddProgressDlgStatus(hwndDlg, L"WriteRandomDataToReservedHeaderAreas() ...\r\n"); nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, newDataAreaSize, !backupHeader, backupHeader); if (nStatus != ERR_SUCCESS) goto error; } FlushFileBuffers (dev); if (!backupHeader) break; backupHeader = FALSE; headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET; // offset for main header } /* header successfully updated */ nStatus = ERR_SUCCESS; if (bVolTransformThreadCancel) { nStatus = ERR_USER_ABORT; goto error; } /* wipe old backup header */ if ( !cryptoInfo->LegacyVolume ) { byte wipeRandChars [TC_WIPE_RAND_CHAR_COUNT]; byte wipeRandCharsUpdate [TC_WIPE_RAND_CHAR_COUNT]; byte wipePass; UINT64_STRUCT unitNo; LARGE_INTEGER offset; WipeAlgorithmId wipeAlgorithm = TC_WIPE_35_GUTMANN; if ( !RandgetBytes (hwndDlg, wipeRandChars, TC_WIPE_RAND_CHAR_COUNT, TRUE) || !RandgetBytes (hwndDlg, wipeRandCharsUpdate, TC_WIPE_RAND_CHAR_COUNT, TRUE) ) { nStatus = ERR_OS_ERROR; goto error; } DebugAddProgressDlgStatus(hwndDlg, L"Wiping old backup header ...\r\n"); wipeBuffer = (byte *) TCalloc (workChunkSize); if (!wipeBuffer) { nStatus = ERR_OUTOFMEMORY; goto error; } offset.QuadPart = currentVolSize - TC_VOLUME_HEADER_GROUP_SIZE; unitNo.Value = offset.QuadPart; for (wipePass = 1; wipePass <= GetWipePassCount (wipeAlgorithm); ++wipePass) { if (!WipeBuffer (wipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, workChunkSize)) { ULONG i; for (i = 0; i < workChunkSize; ++i) { wipeBuffer[i] = wipePass; } EncryptDataUnits (wipeBuffer, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo); memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); } if ( !SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) || _lwrite ((HFILE)dev, (LPCSTR)wipeBuffer, workChunkSize) == HFILE_ERROR ) { // Write error DebugAddProgressDlgStatus(hwndDlg, L"Warning: Failed to wipe old backup header\r\n"); MessageBoxW (hwndDlg, L"WARNING: Failed to wipe old backup header!\n\nIt may be possible to use the current volume password to decrypt the old backup header even after a future password change.\n", lpszTitle, MB_OK | MB_ICONEXCLAMATION); if (wipePass == 1) continue; // retry once // non-critical error - it's better to continue nStatus = ERR_SUCCESS; goto error; } FlushFileBuffers(dev); // we don't check FlushFileBuffers() return code, because it fails for devices // (same implementation in password.c - a bug or not ???) } burn (wipeRandChars, TC_WIPE_RAND_CHAR_COUNT); burn (wipeRandCharsUpdate, TC_WIPE_RAND_CHAR_COUNT); } error: dwError = GetLastError (); if (wipeBuffer) { burn (wipeBuffer, workChunkSize); TCfree (wipeBuffer); wipeBuffer = NULL; } 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"), lpszTitle, MB_OK | MB_ICONEXCLAMATION); } if (dev != INVALID_HANDLE_VALUE) CloseHandle ((HANDLE) dev); if (nDosLinkCreated == 0) RemoveFakeDosName (szDiskFile, szDosDevice); RandStop (FALSE); if (bVolTransformThreadCancel) nStatus = ERR_USER_ABORT; SetLastError (dwError); if (nStatus == ERR_SUCCESS) { nStatus = ExtendFileSystem (hwndDlg, lpszVolume, pVolumePassword, VolumePkcs5, VolumePim, newDataAreaSize); } return nStatus; }
/* ExpandVolumeWizard Expands a trucrypt volume (wizard for user interface) Parameters: hwndDlg : HWND [in] handle to parent window (if any) szVolume : char * [in] Pointer to a string with the volume name (e.g. '\Device\Harddisk0\Partition1' or 'C:\topsecret.tc') Return value: none */ void ExpandVolumeWizard (HWND hwndDlg, char *lpszVolume) { int nStatus = ERR_OS_ERROR; wchar_t szTmp[4096]; Password VolumePassword; int VolumePkcs5 = 0; uint64 hostSize, volSize, hostSizeFree, maxSizeFS; BOOL bIsDevice, bIsLegacy; DWORD dwError; int driveNo; enum EV_FileSystem volFSType; char rootPath[] = "A:\\"; switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE)) { case 1: case 2: MessageBoxW (hwndDlg, L"A VeraCrypt system volume can't be expanded.", lpszTitle, MB_OK|MB_ICONEXCLAMATION); goto ret; } EnableElevatedCursorChange (hwndDlg); WaitCursor(); if (IsMountedVolume (lpszVolume)) { Warning ("DISMOUNT_FIRST", hwndDlg); goto ret; } if (Randinit() != ERR_SUCCESS) { nStatus = ERR_PARAMETER_INCORRECT; goto error; } NormalCursor(); // 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, hwndDlg)) { case 1: MessageBoxW (hwndDlg, L"An outer volume containing a hidden volume can't be expanded, because this destroys the hidden volume.", lpszTitle, MB_OK|MB_ICONEXCLAMATION); goto ret; case 2: break; default: nStatus = ERR_SUCCESS; goto ret; } WaitCursor(); nStatus = QueryVolumeInfo(hwndDlg,lpszVolume,&hostSizeFree,&maxSizeFS); if (nStatus!=ERR_SUCCESS) { nStatus = ERR_OS_ERROR; goto error; } NormalCursor(); while (TRUE) { OpenVolumeContext expandVol; BOOL truecryptMode = FALSE; if (!VeraCryptExpander::ExtcvAskVolumePassword (hwndDlg, &VolumePassword, &VolumePkcs5, &truecryptMode, "ENTER_NORMAL_VOL_PASSWORD", FALSE)) { goto ret; } EnableElevatedCursorChange (hwndDlg); WaitCursor(); if (KeyFilesEnable && FirstKeyFile) KeyFilesApply (hwndDlg, &VolumePassword, FirstKeyFile); WaitCursor (); OpenVolumeThreadParam threadParam; threadParam.context = &expandVol; threadParam.volumePath = lpszVolume; threadParam.password = &VolumePassword; threadParam.pkcs5_prf = VolumePkcs5; threadParam.truecryptMode = FALSE; threadParam.write = FALSE; threadParam.preserveTimestamps = bPreserveTimestamp; threadParam.useBackupHeader = FALSE; threadParam.nStatus = &nStatus; ShowWaitDialog (hwndDlg, TRUE, OpenVolumeWaitThreadProc, &threadParam); NormalCursor (); dwError = GetLastError(); if (nStatus == ERR_SUCCESS) { bIsDevice = expandVol.IsDevice; bIsLegacy = expandVol.CryptoInfo->LegacyVolume; hostSize = expandVol.HostSize; VolumePkcs5 = expandVol.CryptoInfo->pkcs5; if ( bIsLegacy ) { if ( bIsDevice ) volSize = 0; // updated later else volSize = hostSize; } else { volSize = GetVolumeSizeByDataAreaSize (expandVol.CryptoInfo->VolumeSize.Value, bIsLegacy); } CloseVolume (&expandVol); break; } else if (nStatus != ERR_PASSWORD_WRONG) { SetLastError (dwError); goto error; } NormalCursor(); handleError (hwndDlg, nStatus); } WaitCursor(); // auto mount the volume to check the file system type nStatus=MountVolTemp(hwndDlg, lpszVolume, &driveNo, &VolumePassword, VolumePkcs5); if (nStatus != ERR_SUCCESS) goto error; rootPath[0] += driveNo; if ( !GetFileSystemType(rootPath,&volFSType) ) volFSType = EV_FS_TYPE_RAW; if ( bIsLegacy && bIsDevice && volFSType == EV_FS_TYPE_NTFS ) { uint64 NumberOfSectors; DWORD BytesPerSector; if ( !GetNtfsNumberOfSectors(rootPath, &NumberOfSectors, &BytesPerSector) ) nStatus = ERR_OS_ERROR; // NTFS reported size does not include boot sector copy at volume end volSize = ( NumberOfSectors + 1 ) * BytesPerSector; } UnmountVolume (hwndDlg, driveNo, TRUE); NormalCursor(); if (nStatus != ERR_SUCCESS) goto error; if ( bIsDevice && bIsLegacy && volFSType != EV_FS_TYPE_NTFS ) { MessageBoxW (hwndDlg, L"Expanding a device hosted legacy volume with no NTFS file system\n" L"is unsupported.\n" L"Note that expanding the VeraCrypt volume itself is not neccessary\n" L"for legacy volumes.\n", lpszTitle, MB_OK|MB_ICONEXCLAMATION); goto ret; } // check if there is enough free space on host device/drive to expand the volume if ( (bIsDevice && hostSize < volSize + TC_MINVAL_FS_EXPAND) || (!bIsDevice && hostSizeFree < TC_MINVAL_FS_EXPAND) ) { MessageBoxW (hwndDlg, L"Not enough free space to expand the volume", lpszTitle, MB_OK|MB_ICONEXCLAMATION); goto ret; } if (!bIsDevice && hostSize != volSize ) { // there is some junk data at the end of the volume if (MessageBoxW (hwndDlg, L"Warning: The container file is larger than the VeraCrypt volume area. The data after the VeraCrypt volume area will be overwritten.\n\nDo you want to continue?", lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO) goto ret; } switch (volFSType) { case EV_FS_TYPE_NTFS: break; case EV_FS_TYPE_FAT: if (MessageBoxW (hwndDlg,L"Warning: The VeraCrypt volume contains a FAT file system!\n\nOnly the VeraCrypt volume itself will be expanded, but not the file system.\n\nDo you want to continue?", lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO) goto ret; break; default: if (MessageBoxW (hwndDlg,L"Warning: The VeraCrypt volume contains an unknown or no file system!\n\nOnly the VeraCrypt volume itself will be expanded, the file system remains unchanged.\n\nDo you want to continue?", lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO) goto ret; } EXPAND_VOL_THREAD_PARAMS VolExpandParam; VolExpandParam.bInitFreeSpace = (bIsLegacy && bIsDevice) ? FALSE:TRUE; VolExpandParam.szVolumeName = lpszVolume; VolExpandParam.FileSystem = volFSType; VolExpandParam.pVolumePassword = &VolumePassword; VolExpandParam.VolumePkcs5 = VolumePkcs5; VolExpandParam.bIsDevice = bIsDevice; VolExpandParam.bIsLegacy = bIsLegacy; VolExpandParam.oldSize = bIsDevice ? volSize : hostSize; VolExpandParam.newSize = hostSize; VolExpandParam.hostSizeFree = hostSizeFree; while (1) { uint64 newVolumeSize; if (IDCANCEL == DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_SIZE_DIALOG), hwndDlg, (DLGPROC) ExpandVolSizeDlgProc, (LPARAM) &VolExpandParam)) { goto ret; } newVolumeSize = VolExpandParam.newSize; if ( !bIsDevice ) { if ( newVolumeSize < hostSize + TC_MINVAL_FS_EXPAND) { swprintf(szTmp,L"New volume size too small, must be at least %I64u kB larger than the current size.",TC_MINVAL_FS_EXPAND/BYTES_PER_KB); MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION ); continue; } if ( newVolumeSize - hostSize > hostSizeFree ) { swprintf(szTmp,L"New volume size too large, not enough space on host drive."); MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION ); continue; } if ( newVolumeSize>maxSizeFS ) { swprintf(szTmp,L"Maximum file size of %I64u MB on host drive exceeded.",maxSizeFS/BYTES_PER_MB); MessageBoxW (hwndDlg, L"!\n",lpszTitle, MB_OK | MB_ICONEXCLAMATION ); continue; } } if ( newVolumeSize > TC_MAX_VOLUME_SIZE ) { // note: current limit TC_MAX_VOLUME_SIZE is 1 PetaByte swprintf(szTmp,L"Maximum VeraCrypt volume size of %I64u TB exceeded!\n",TC_MAX_VOLUME_SIZE/BYTES_PER_TB); MessageBoxW (hwndDlg, szTmp,lpszTitle, MB_OK | MB_ICONEXCLAMATION ); if (bIsDevice) break; // TODO: ask to limit volume size to TC_MAX_VOLUME_SIZE continue; } break; } VolExpandParam.oldSize = volSize; // start progress dialog DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_EXPAND_PROGRESS_DLG), hwndDlg, (DLGPROC) ExpandVolProgressDlgProc, (LPARAM) &VolExpandParam ); ret: nStatus = ERR_SUCCESS; error: if (nStatus != 0) handleError (hwndDlg, nStatus); burn (&VolumePassword, sizeof (VolumePassword)); RestoreDefaultKeyFilesParam(); RandStop (FALSE); NormalCursor(); return; }
BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static EXPAND_VOL_THREAD_PARAMS *pProgressDlgParam; static BOOL bVolTransformStarted = FALSE; static BOOL showRandPool = TRUE; WORD lw = LOWORD (wParam); switch (msg) { case WM_INITDIALOG: { char szOldHostSize[512], szNewHostSize[512]; pProgressDlgParam = (EXPAND_VOL_THREAD_PARAMS*)lParam; bVolTransformStarted = FALSE; showRandPool = TRUE; hCurPage = hwndDlg; nPbar = IDC_PROGRESS_BAR; GetSpaceString(szOldHostSize,sizeof(szOldHostSize),pProgressDlgParam->oldSize,pProgressDlgParam->bIsDevice); GetSpaceString(szNewHostSize,sizeof(szNewHostSize),pProgressDlgParam->newSize,pProgressDlgParam->bIsDevice); SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_OLDSIZE), szOldHostSize); SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NEWSIZE), szNewHostSize); SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NAME), pProgressDlgParam->szVolumeName); SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_FILE_SYSTEM), szFileSystemStr[pProgressDlgParam->FileSystem]); SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_INITSPACE), pProgressDlgParam->bInitFreeSpace?"Yes":"No"); SendMessage (GetDlgItem (hwndDlg, IDC_BOX_STATUS), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE); SendMessage (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); // set status text if ( !pProgressDlgParam->bInitFreeSpace && pProgressDlgParam->bIsLegacy ) { showRandPool = FALSE; EnableWindow (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), FALSE); EnableWindow (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), FALSE); SetDlgItemText(hwndDlg, IDC_BOX_STATUS, "Click 'Continue' to expand the volume."); } else { SetDlgItemText(hwndDlg, IDC_BOX_STATUS, "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 'Continue' to expand the volume."); } SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), BM_SETCHECK, showRandPool ? BST_CHECKED : BST_UNCHECKED, 0); SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL); } return 0; case TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED: { int nStatus = (int)lParam; NormalCursor (); if (nStatus != 0) { if ( nStatus != ERR_USER_ABORT ) AddProgressDlgStatus (hwndDlg, "Error: volume expansion failed."); else AddProgressDlgStatus (hwndDlg, "Error: operation aborted by user."); } else { AddProgressDlgStatus (hwndDlg, "Finished. Volume successfully expanded."); } SetWindowText (GetDlgItem (hwndDlg, IDOK), "Exit"); EnableWindow (GetDlgItem (hwndDlg, IDOK), TRUE); EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE); } return 1; case WM_TIMER: switch (wParam) { case TIMER_ID_RANDVIEW: { unsigned char tmp[16]; char szRndPool[64], *t; DWORD *p; if (!showRandPool) return 1; RandpeekBytes (hwndDlg, tmp, sizeof (tmp)); for ( p = (DWORD*)(tmp + sizeof(tmp)), t=szRndPool; p > (DWORD*)tmp; ) { int len; if ( (len = sprintf ( t, "%08X", *--p)) < 0 ) return 1; t += len; } SetWindowText (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), szRndPool); burn (tmp, sizeof(tmp)); burn (szRndPool, sizeof(szRndPool)); } return 1; } return 0; case WM_COMMAND: if (lw == IDC_DISPLAY_POOL_CONTENTS) { showRandPool = IsButtonChecked (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS)); return 1; } if (lw == IDCANCEL) { if (bVolTransformStarted) { if (MessageBoxW (hwndDlg, L"Warning: Volume expansion is in progress!\n\nStopping now may result in a damaged volume.\n\nDo you really want to cancel?", lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO) return 1; // tell the volume transform thread to terminate bVolTransformThreadCancel = TRUE; } EndDialog (hwndDlg, lw); return 1; } if (lw == IDOK) { if (bVolTransformStarted) { // TransformThreadFunction finished -> OK button is now exit EndDialog (hwndDlg, lw); } else { showRandPool = FALSE; KillTimer (hwndDlg, TIMER_ID_RANDVIEW); EnableWindow (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), FALSE); EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); SetProgressDlgStatus (hwndDlg, "Starting volume expansion ...\r\n"); bVolTransformStarted = TRUE; pProgressDlgParam->hwndDlg = hwndDlg; if ( _beginthread (volTransformThreadFunction, 0, pProgressDlgParam) == -1L ) { handleError (hwndDlg, ERR_OS_ERROR); EndDialog (hwndDlg, lw); } WaitCursor(); } return 1; } return 0; } return 0; }
int ChangePwd (const char *lpszVolume, Password *oldPassword, int old_pkcs5, int old_pim, BOOL truecryptMode, Password *newPassword, int pkcs5, int pim, int wipePassCount, 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; DWORD bytesRead; BOOL bDevice; unsigned __int64 hostSize = 0; int volumeType; int wipePass; FILETIME ftCreationTime; FILETIME ftLastWriteTime; FILETIME ftLastAccessTime; BOOL bTimeStampValid = FALSE; LARGE_INTEGER headerOffset; BOOL backupHeader; DISK_GEOMETRY driveInfo; if (oldPassword->Length == 0 || newPassword->Length == 0) return -1; if ((wipePassCount <= 0) || (truecryptMode && (old_pkcs5 == SHA256))) { nStatus = ERR_PARAMETER_INCORRECT; handleError (hwndDlg, nStatus, SRC_POS); return nStatus; } if (!lpszVolume) { nStatus = ERR_OUTOFMEMORY; handleError (hwndDlg, nStatus, SRC_POS); return nStatus; } WaitCursor (); CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), lpszVolume, &bDevice); if (bDevice == FALSE) { strcpy (szCFDevice, szDiskFile); } else { nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(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 = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL); if (!bResult) goto error; bResult = GetPartitionInfo (lpszVolume, &diskInfo); if (bResult) { hostSize = diskInfo.PartitionLength.QuadPart; } else { 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 ()) { if (CryptoAPILastError == ERROR_SUCCESS) nStatus = ERR_RAND_INIT_FAILED; else nStatus = ERR_CAPI_INIT_FAILED; goto error; } SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */ if (!bDevice && bPreserveTimestamp) { if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) bTimeStampValid = FALSE; 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; } if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) { nStatus = ERR_OS_ERROR; goto error; } /* Read in volume header */ if (!ReadEffectiveVolumeHeader (bDevice, dev, buffer, &bytesRead)) { nStatus = ERR_OS_ERROR; goto error; } if (bytesRead != 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, old_pkcs5, old_pim, truecryptMode, &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 wipePassCount 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 < wipePassCount; wipePass++) { // Prepare new volume header nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE, buffer, cryptoInfo->ea, cryptoInfo->mode, newPassword, cryptoInfo->pkcs5, pim, cryptoInfo->master_keydata, &ci, cryptoInfo->VolumeSize.Value, (volumeType == TC_VOLUME_TYPE_HIDDEN) ? cryptoInfo->hiddenVolumeSize : 0, cryptoInfo->EncryptedAreaStart.Value, cryptoInfo->EncryptedAreaLength.Value, truecryptMode? 0 : cryptoInfo->RequiredProgramVersion, cryptoInfo->HeaderFlags, cryptoInfo->SectorSize, wipePass < wipePassCount - 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; } if (!WriteEffectiveVolumeHeader (bDevice, dev, buffer)) { 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 (hwndDlg, 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) SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime); 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, SRC_POS); return nStatus; }
/* -------------------------------------------------------------------- */ void SpecWinUp(Widget w, XtPointer client, XtPointer call) { int i, nSets; bool saveState = Freeze; XmToggleButtonCallbackStruct *cb = (XmToggleButtonCallbackStruct *)call; static bool firstTime = true; /* If this is 'unset' from one of the ToggleButtons, then bail. */ if (cb && cb->reason == XmCR_VALUE_CHANGED && cb->set == false) return; if (NumberDataSets < 1) return; if ((long)client > 1 && NumberDataSets < 2) { HandleError("Co-PSD requires two data sets.", Interactive, IRET); return; } WaitCursor(MainWindow); WaitCursor(ControlWindow); if (client) psd[0].display = (long)client; if (firstTime) { CreateSpectrumWindow(); initPlotGC(&specPlot); } else WaitCursor(SpectrumWindow); for (i = 0; i < 6; ++i) if (i == psd[0].display - 1) XmToggleButtonSetState(typeButts[i], true, false); else XmToggleButtonSetState(typeButts[i], false, false); Freeze = true; psd[0].frequency = dataSet[0].nPoints / NumberSeconds; psd[0].freqPerBin = (double)psd[0].frequency / (psd[0].M << 1); switch (psd[0].display) { case SPECTRA: XtSetSensitive(pmOptButt[1], true); XtSetSensitive(pmOptButt[2], true); XtSetSensitive(pmOptButt[3], true); nSets = std::min(NumberDataSets, MAX_PSD); for (i = 1; i < nSets; ++i) { psd[i].frequency = dataSet[i].nPoints / NumberSeconds; psd[i].freqPerBin = (double)psd[i].frequency / (psd[i].M << 1); } ComputeSpectrum(); break; case COSPECTRA: case QUADRATURE: case RATIO: XtSetSensitive(pmOptButt[1], false); XtSetSensitive(pmOptButt[2], true); XtSetSensitive(pmOptButt[3], true); ComputeCoSpectrum(); break; case COHERENCE: case PHASE: XtSetSensitive(pmOptButt[1], false); XtSetSensitive(pmOptButt[2], false); XtSetSensitive(pmOptButt[3], false); ComputeCoSpectrum(); break; default: fprintf(stderr, "SpecWinUp: Invalid spectral display.\n"); return; } Freeze = saveState; specPlot.windowOpen = true; XtManageChild(SpectrumWindow); XtPopup(XtParent(SpectrumWindow), XtGrabNone); if (firstTime) { WaitCursor(SpectrumWindow); ResizeSpecWindow(NULL, NULL, NULL); setDefaults(); XtAddCallback(specPlot.canvas, XmNexposeCallback, (XtCallbackProc)PlotSpectrum, NULL); XtAddCallback(specPlot.canvas, XmNresizeCallback, (XtCallbackProc)ResizeSpecWindow, NULL); XtAddCallback(specPlot.canvas, XmNresizeCallback, (XtCallbackProc)PlotSpectrum, NULL); firstTime = false; } PlotSpectrum(NULL, NULL, NULL); if (AsciiWinOpen) SetASCIIdata(NULL, NULL, NULL); PointerCursor(MainWindow); PointerCursor(ControlWindow); PointerCursor(SpectrumWindow); } /* END SPECWINUP */