Annotation of truecrypt/common/format.c, revision 1.1.1.12

1.1.1.10  root        1: /*
1.1.1.12! root        2:  Legal Notice: Some portions of the source code contained in this file were
        !             3:  derived from the source code of Encryption for the Masses 2.02a, which is
        !             4:  Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
        !             5:  Agreement for Encryption for the Masses'. Modifications and additions to
        !             6:  the original source code (contained in this file) and all other portions of
        !             7:  this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed
        !             8:  by the TrueCrypt License 2.4 the full text of which is contained in the
        !             9:  file License.txt included in TrueCrypt binary and source code distribution
1.1.1.10  root       10:  packages. */
                     11: 
                     12: #include <stdlib.h>
                     13: #include <string.h>
1.1.1.6   root       14: 
                     15: #include "Tcdefs.h"
                     16: 
1.1.1.9   root       17: #include "Common.h"
1.1.1.6   root       18: #include "Crypto.h"
                     19: #include "Fat.h"
                     20: #include "Format.h"
1.1.1.9   root       21: #include "Random.h"
1.1.1.6   root       22: #include "Volumes.h"
1.1.1.8   root       23: 
                     24: #ifdef _WIN32
1.1.1.6   root       25: #include "Apidrvr.h"
                     26: #include "Dlgcode.h"
                     27: #include "Language.h"
1.1.1.8   root       28: #include "Progress.h"
1.1.1.6   root       29: #include "Resource.h"
1.1.1.10  root       30: #include "../Format/FormatCom.h"
1.1.1.3   root       31: 
1.1.1.12! root       32: int FormatVolume (char *volumePath,
1.1       root       33:              BOOL bDevice,
                     34:              unsigned __int64 size,
1.1.1.4   root       35:                  unsigned __int64 hiddenVolHostSize,
1.1.1.6   root       36:              Password *password,
1.1.1.7   root       37:              int ea,
1.1       root       38:              int pkcs5,
                     39:                  BOOL quickFormat,
1.1.1.8   root       40:                  BOOL sparseFileSwitch,
1.1.1.3   root       41:                  int fileSystem,
                     42:                  int clusterSize,
1.1.1.4   root       43:              HWND hwndDlg,
                     44:                  BOOL hiddenVol,
1.1.1.10  root       45:                  int *realClusterSize,
                     46:                  BOOL uac)
1.1       root       47: {
                     48:        int nStatus;
1.1.1.12! root       49:        PCRYPTO_INFO cryptoInfo = NULL;
1.1.1.4   root       50:        HANDLE dev = INVALID_HANDLE_VALUE;
1.1.1.10  root       51:        DWORD dwError;
                     52:        char header[HEADER_SIZE];
1.1.1.4   root       53:        unsigned __int64 num_sectors, startSector;
1.1.1.3   root       54:        fatparams ft;
1.1.1.4   root       55:        FILETIME ftCreationTime;
                     56:        FILETIME ftLastWriteTime;
                     57:        FILETIME ftLastAccessTime;
                     58:        BOOL bTimeStampValid = FALSE;
1.1.1.12! root       59:        BOOL bInstantRetryOtherFilesys = FALSE;
1.1.1.10  root       60:        char dosDev[TC_MAX_PATH] = { 0 };
                     61:        char devName[MAX_PATH] = { 0 };
                     62:        int driveLetter = -1;
                     63:        WCHAR deviceName[MAX_PATH];
                     64: 
1.1.1.12! root       65:        /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is
        !            66:        less than MAX_FAT_VOLUME_SIZE, the user is asked within this function whether he wants to instantly
        !            67:        retry FAT format instead (to avoid having to re-create the whole container again). If the user
        !            68:        answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed 
        !            69:        and some destructive operations that were performed during the first attempt must be (and are) skipped. 
        !            70:        Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format',
        !            71:        determine whether they (or their portions) need to be skipped during such a second attempt; if so, 
        !            72:        use the 'bInstantRetryOtherFilesys' flag to skip them. */
        !            73: 
1.1.1.4   root       74:        if (!hiddenVol)
                     75:                size -= HEADER_SIZE;    
1.1       root       76: 
1.1.1.4   root       77:        num_sectors = size / SECTOR_SIZE;
1.1.1.10  root       78: 
                     79:        if (bDevice)
                     80:        {
                     81:                strcpy ((char *)deviceName, volumePath);
                     82:                ToUNICODE ((char *)deviceName);
                     83: 
                     84:                driveLetter = GetDiskDeviceDriveLetter (deviceName);
                     85:        }
                     86: 
1.1.1.3   root       87:        VirtualLock (header, sizeof (header));
1.1       root       88: 
1.1.1.12! root       89:        /* Copies any header structures into header, but does not do any disk I/O */
        !            90:        nStatus = VolumeWriteHeader (FALSE,
        !            91:                                     header,
1.1.1.7   root       92:                                     ea,
1.1.1.12! root       93:                                         FIRST_MODE_OF_OPERATION_ID,
1.1.1.6   root       94:                                     password,
1.1       root       95:                                     pkcs5,
1.1.1.12! root       96:                                         NULL,
1.1       root       97:                                         0,
1.1.1.4   root       98:                                     &cryptoInfo,
1.1.1.12! root       99:                                         size,
1.1.1.6   root      100:                                         hiddenVol ? size : 0,
1.1.1.12! root      101:                                         0,
        !           102:                                         size,
1.1.1.6   root      103:                                         FALSE);
1.1       root      104: 
                    105:        if (nStatus != 0)
1.1.1.3   root      106:        {
                    107:                burn (header, sizeof (header));
                    108:                VirtualUnlock (header, sizeof (header));
1.1       root      109:                return nStatus;
1.1.1.3   root      110:        }
                    111: 
1.1.1.12! root      112: begin_format:
        !           113: 
1.1.1.6   root      114:        if (bDevice)
1.1.1.3   root      115:        {
1.1.1.10  root      116:                /* Device-hosted volume */
1.1.1.11  root      117:                DWORD dwResult;
1.1.1.10  root      118:                int nPass;
                    119: 
                    120:                if (FakeDosNameForDevice (volumePath, dosDev, devName, FALSE) != 0)
1.1.1.4   root      121:                {
1.1.1.10  root      122:                        handleWin32Error (hwndDlg);
                    123:                        return ERR_DONT_REPORT;
                    124:                }
                    125: 
                    126:                if (IsDeviceMounted (devName))
                    127:                {
                    128:                        if ((dev = DismountDrive (devName)) == INVALID_HANDLE_VALUE)
1.1.1.4   root      129:                        {
1.1.1.11  root      130:                                Error ("FORMAT_CANT_DISMOUNT_FILESYS");
                    131:                                nStatus = ERR_DONT_REPORT; 
                    132:                                goto error;
1.1.1.10  root      133:                        }
                    134:                }
                    135:                else if (nCurrentOS == WIN_VISTA_OR_LATER && driveLetter == -1)
                    136:                {
                    137:                        // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition 
                    138:                        // to which no drive letter has been assigned under the system. This problem can be worked
                    139:                        // around by assigning a drive letter to the partition temporarily.
                    140: 
                    141:                        char szDriveLetter[] = { 'A', ':', 0 };
                    142:                        char rootPath[] = { 'A', ':', '\\', 0 };
                    143:                        char uniqVolName[MAX_PATH+1] = { 0 };
                    144:                        int tmpDriveLetter = -1;
                    145:                        BOOL bResult = FALSE;
                    146: 
                    147:                        tmpDriveLetter = GetFirstAvailableDrive ();
                    148:  
                    149:                        if (tmpDriveLetter != -1)
                    150:                        {
                    151:                                rootPath[0] += tmpDriveLetter;
                    152:                                szDriveLetter[0] += tmpDriveLetter;
                    153: 
                    154:                                if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volumePath))
                    155:                                {
                    156:                                        bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
                    157: 
                    158:                                        DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
                    159:                                                szDriveLetter,
                    160:                                                volumePath);
                    161: 
                    162:                                        if (bResult 
                    163:                                                && SetVolumeMountPoint (rootPath, uniqVolName))
                    164:                                        {
                    165:                                                // The drive letter can be removed immediately
                    166:                                                DeleteVolumeMountPoint (rootPath);
                    167:                                        }
                    168:                                }
                    169:                        }
                    170:                }
                    171: 
                    172:                // Perform open - 'quick format' - close - open to prevent Windows from restoring NTFS boot sector backup
                    173:                for (nPass = 0; nPass < 2; nPass++)
                    174:                {
                    175:                        // Try exclusive access mode first
                    176:                        if (dev == INVALID_HANDLE_VALUE)
                    177:                                dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
                    178: 
                    179:                        if (dev == INVALID_HANDLE_VALUE)
                    180:                        {
                    181:                                // Retry in shared mode
                    182:                                dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                    183:                                if (dev != INVALID_HANDLE_VALUE)
                    184:                                {
                    185:                                        if (IDNO == MessageBoxW (hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
                    186:                                        {
                    187:                                                nStatus = ERR_DONT_REPORT; 
                    188:                                                goto error;
                    189:                                        }
                    190:                                }
                    191:                                else
                    192:                                {
                    193:                                        handleWin32Error (hwndDlg);
                    194:                                        nStatus = ERR_DONT_REPORT; 
                    195:                                        goto error;
                    196:                                }
                    197:                        }
                    198: 
1.1.1.12! root      199:                        if (hiddenVol || bInstantRetryOtherFilesys)
1.1.1.10  root      200:                                break;  // The following "quick format" operation would damage the outer volume
                    201: 
                    202:                        if (nPass == 0)
                    203:                        {
                    204:                                char buf[65536];
                    205:                                DWORD bw;
                    206: 
                    207:                                // Pseudo "quick format" to prevent Windows from restoring NTFS boot sector backup
                    208:                                memset (buf, 0, sizeof (buf));
                    209:                                WriteFile (dev, buf, sizeof (buf), &bw, NULL);
                    210:                                FlushFileBuffers (dev);
                    211:                                CloseHandle (dev);
                    212:                                dev = INVALID_HANDLE_VALUE;
1.1.1.4   root      213:                        }
                    214:                }
1.1.1.11  root      215: 
                    216:                if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
                    217:                {
                    218:                        Error ("FORMAT_CANT_DISMOUNT_FILESYS");
                    219:                        nStatus = ERR_DONT_REPORT; 
                    220:                        goto error;
                    221:                }
1.1.1.3   root      222:        }
                    223:        else
                    224:        {
1.1.1.10  root      225:                /* File-hosted volume */
                    226: 
1.1.1.4   root      227:                // We could support FILE_ATTRIBUTE_HIDDEN as an option
                    228:                // (Now if the container has hidden or system file attribute, the OS will not allow
                    229:                // overwritting it; so the user will have to delete it manually).
1.1.1.10  root      230:                dev = CreateFile (volumePath, GENERIC_WRITE,
1.1.1.12! root      231:                        (hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
        !           232:                        NULL, (hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
1.1.1.6   root      233: 
1.1.1.8   root      234:                if (dev == INVALID_HANDLE_VALUE)
                    235:                {
                    236:                        handleWin32Error (hwndDlg);
1.1.1.10  root      237:                        nStatus = ERR_DONT_REPORT; 
1.1.1.8   root      238:                        goto error;
                    239:                }
                    240: 
1.1.1.12! root      241:                if (!hiddenVol && !bInstantRetryOtherFilesys)
1.1.1.6   root      242:                {
                    243:                        LARGE_INTEGER volumeSize;
1.1.1.8   root      244:                        volumeSize.QuadPart = size + HEADER_SIZE;
1.1.1.6   root      245: 
1.1.1.8   root      246:                        if (sparseFileSwitch && quickFormat)
                    247:                        {
                    248:                                // Create as sparse file container
                    249:                                DWORD tmp;
                    250:                                if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
                    251:                                {
                    252:                                        handleWin32Error (hwndDlg);
1.1.1.10  root      253:                                        nStatus = ERR_DONT_REPORT; 
1.1.1.8   root      254:                                        goto error;
                    255:                                }
                    256:                        }
                    257: 
                    258:                        // Preallocate the file
1.1.1.6   root      259:                        if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
                    260:                                || !SetEndOfFile (dev)
                    261:                                || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
                    262:                        {
                    263:                                handleWin32Error (hwndDlg);
1.1.1.10  root      264:                                nStatus = ERR_DONT_REPORT;
1.1.1.7   root      265:                                goto error;
1.1.1.6   root      266:                        }
                    267:                }
1.1.1.3   root      268:        }
                    269: 
1.1.1.6   root      270:        if (hiddenVol && !bDevice && bPreserveTimestamp)
1.1.1.4   root      271:        {
                    272:                /* Remember the container timestamp (used to reset file date and time of file-hosted
                    273:                containers to preserve plausible deniability of hidden volume)  */
                    274:                if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
                    275:                {
                    276:                        bTimeStampValid = FALSE;
1.1.1.6   root      277:                        MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.4   root      278:                }
                    279:                else
                    280:                        bTimeStampValid = TRUE;
1.1.1.3   root      281:        }
1.1       root      282: 
                    283:        KillTimer (hwndDlg, 0xff);
                    284: 
1.1.1.6   root      285:        /* Volume header */
1.1.1.4   root      286: 
                    287:        // Hidden volume setup
                    288:        if (hiddenVol)
                    289:        {
                    290:                // Check hidden volume size
                    291:                if (hiddenVolHostSize < MIN_HIDDEN_VOLUME_HOST_SIZE || hiddenVolHostSize > MAX_HIDDEN_VOLUME_HOST_SIZE)
                    292:                {               
1.1.1.7   root      293:                        nStatus = ERR_VOL_SIZE_WRONG;
                    294:                        goto error;
1.1.1.4   root      295:                }
                    296: 
                    297:                // Seek to hidden volume header location
                    298:                if (!SeekHiddenVolHeader ((HFILE) dev, hiddenVolHostSize, bDevice))
                    299:                {
1.1.1.7   root      300:                        nStatus = ERR_VOL_SEEKING;
                    301:                        goto error;
1.1.1.4   root      302:                }
                    303: 
                    304:        }
1.1.1.12! root      305:        else if (bInstantRetryOtherFilesys)
        !           306:        {
        !           307:                // The previous file system format failed and the user wants to try again with a different file system.
        !           308:                // The volume header had been written successfully so we need to seek to the byte after the header.
        !           309: 
        !           310:                LARGE_INTEGER offset, offsetNew;
        !           311: 
        !           312:                offset.QuadPart = HEADER_SIZE;
        !           313: 
        !           314:                if (SetFilePointerEx ((HANDLE) dev, offset, &offsetNew, FILE_BEGIN) == 0
        !           315:                        || offsetNew.QuadPart != offset.QuadPart)
        !           316:                {
        !           317:                        nStatus = ERR_VOL_SEEKING;
        !           318:                        goto error;
        !           319:                }
        !           320:        }
1.1.1.4   root      321: 
1.1.1.12! root      322:        if (!bInstantRetryOtherFilesys)
1.1.1.10  root      323:        {
1.1.1.12! root      324:                // Write the volume header
        !           325:                if (_lwrite ((HFILE) dev, header, HEADER_SIZE) == HFILE_ERROR)
        !           326:                {
        !           327:                        handleWin32Error (hwndDlg);
        !           328:                        nStatus = ERR_DONT_REPORT;
        !           329:                        goto error;
        !           330:                }
1.1.1.10  root      331:        }
1.1.1.4   root      332: 
1.1.1.6   root      333:        /* Data area */
1.1.1.4   root      334: 
1.1.1.10  root      335:        startSector = HEADER_SIZE / SECTOR_SIZE;        // Data area of normal volume starts right after volume header
1.1.1.4   root      336: 
                    337:        if (hiddenVol)
                    338:        {
                    339:                // Calculate data area position of hidden volume
                    340:                unsigned __int64 startOffset = hiddenVolHostSize - size - HIDDEN_VOL_HEADER_OFFSET;
1.1.1.7   root      341:                cryptoInfo->hiddenVolumeOffset = startOffset;
1.1.1.4   root      342: 
                    343:                // Validate the offset
                    344:                if (startOffset % SECTOR_SIZE != 0)
                    345:                {
1.1.1.6   root      346:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    347:                        goto error;
1.1.1.4   root      348:                }
                    349: 
                    350:                startSector = startOffset / SECTOR_SIZE;        
                    351:                quickFormat = TRUE;             // To entirely format a hidden volume would be redundant
                    352:        }
                    353: 
                    354:        // Format filesystem
                    355: 
1.1.1.3   root      356:        switch (fileSystem)
                    357:        {
                    358:        case FILESYS_NONE:
1.1.1.10  root      359:        case FILESYS_NTFS:
1.1.1.8   root      360:                nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, quickFormat);
1.1.1.3   root      361:                break;
1.1.1.10  root      362:                
1.1.1.3   root      363:        case FILESYS_FAT:
1.1.1.4   root      364:                if (num_sectors > 0xFFFFffff)
                    365:                {
1.1.1.6   root      366:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    367:                        goto error;
1.1.1.4   root      368:                }
                    369: 
                    370:                // Calculate the fats, root dir etc
                    371:                ft.num_sectors = (unsigned int) (num_sectors);
                    372:                ft.cluster_size = clusterSize;
1.1.1.6   root      373:                memcpy (ft.volume_name, "NO NAME    ", 11);
1.1.1.4   root      374:                GetFatParams (&ft); 
                    375:                *realClusterSize = ft.cluster_size * SECTOR_SIZE;
                    376: 
1.1.1.8   root      377:                nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, quickFormat);
1.1.1.3   root      378:                break;
                    379:        }
1.1       root      380: 
1.1.1.10  root      381: error:
                    382:        dwError = GetLastError();
1.1.1.3   root      383: 
                    384:        burn (header, sizeof (header));
                    385:        VirtualUnlock (header, sizeof (header));
1.1       root      386: 
1.1.1.11  root      387:        if (dev != INVALID_HANDLE_VALUE)
1.1.1.4   root      388:        {
1.1.1.11  root      389:                if (!bDevice && !hiddenVol && nStatus != 0)
                    390:                {
                    391:                        // Remove preallocated part before closing file handle if format failed
                    392:                        if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
                    393:                                SetEndOfFile (dev);
                    394:                }
1.1.1.6   root      395: 
1.1.1.11  root      396:                FlushFileBuffers (dev);
1.1.1.4   root      397: 
1.1.1.11  root      398:                if (bTimeStampValid)
                    399:                {
                    400:                        // Restore the container timestamp (to preserve plausible deniability of the hidden volume) 
                    401:                        if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
                    402:                                MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
                    403:                }
                    404: 
                    405:                CloseHandle (dev);
                    406:                dev = INVALID_HANDLE_VALUE;
                    407:        }
1.1       root      408: 
1.1.1.6   root      409:        if (nStatus != 0)
1.1.1.3   root      410:        {
1.1.1.10  root      411:                SetLastError(dwError);
1.1.1.12! root      412:                goto fv_end;
1.1.1.10  root      413:        }
1.1.1.6   root      414: 
1.1.1.10  root      415:        if (fileSystem == FILESYS_NTFS)
                    416:        {
                    417:                // Quick-format volume as NTFS
                    418:                int driveNo = GetLastAvailableDrive ();
                    419:                MountOptions mountOptions;
                    420:                int retCode;
1.1.1.3   root      421: 
1.1.1.10  root      422:                ZeroMemory (&mountOptions, sizeof (mountOptions));
1.1.1.5   root      423: 
1.1.1.10  root      424:                if (driveNo == -1)
                    425:                {
                    426:                        MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
                    427:                        MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.3   root      428: 
1.1.1.12! root      429:                        nStatus = ERR_NO_FREE_DRIVES;
        !           430:                        goto fv_end;
1.1.1.10  root      431:                }
1.1.1.4   root      432: 
1.1.1.10  root      433:                mountOptions.ReadOnly = FALSE;
                    434:                mountOptions.Removable = FALSE;
                    435:                mountOptions.ProtectHiddenVolume = FALSE;
                    436:                mountOptions.PreserveTimestamp = bPreserveTimestamp;
1.1.1.3   root      437: 
1.1.1.10  root      438:                if (MountVolume (hwndDlg, driveNo, volumePath, password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
                    439:                {
                    440:                        MessageBoxW (hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
                    441:                        MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.12! root      442:                        nStatus = ERR_VOL_MOUNT_FAILED;
        !           443:                        goto fv_end;
1.1.1.10  root      444:                }
1.1.1.3   root      445: 
1.1.1.10  root      446:                if (!IsAdmin () && IsUacSupported ())
                    447:                        retCode = UacFormatNtfs (hwndDlg, driveNo, clusterSize);
                    448:                else
                    449:                        retCode = FormatNtfs (driveNo, clusterSize);
1.1.1.3   root      450: 
1.1.1.10  root      451:                if (retCode != TRUE)
                    452:                {
                    453:                        if (!UnmountVolume (hwndDlg, driveNo, FALSE))
                    454:                                MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      455: 
1.1.1.12! root      456:                        if (size <= MAX_FAT_VOLUME_SIZE)
        !           457:                        {
        !           458:                                if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES)
        !           459:                                {
        !           460:                                        // NTFS format failed and the user wants to try FAT format immediately
        !           461:                                        fileSystem = FILESYS_FAT;
        !           462:                                        bInstantRetryOtherFilesys = TRUE;
        !           463:                                        quickFormat = TRUE;             // Volume has already been successfully TC-formatted
        !           464:                                        clusterSize = 0;                // Default cluster size
        !           465:                                        goto begin_format;
        !           466:                                }
        !           467:                        }
        !           468:                        else
        !           469:                                Error ("FORMAT_NTFS_FAILED");
        !           470: 
        !           471:                        nStatus = ERR_DONT_REPORT;
        !           472:                        goto fv_end;
1.1.1.3   root      473:                }
1.1.1.10  root      474: 
                    475:                if (!UnmountVolume (hwndDlg, driveNo, FALSE))
                    476:                        MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      477:        }
                    478: 
1.1.1.12! root      479: fv_end:
        !           480: 
        !           481:        if (dosDev[0])
        !           482:                RemoveFakeDosName (volumePath, dosDev);
        !           483: 
        !           484:        crypto_close (cryptoInfo);
        !           485: 
1.1       root      486:        return nStatus;
1.1.1.3   root      487: }
1.1       root      488: 
1.1.1.12! root      489: #endif // _WIN32
1.1.1.3   root      490: 
1.1.1.8   root      491: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1.1.3   root      492: {
                    493:        int write_buf_cnt = 0;
                    494:        char sector[SECTOR_SIZE], *write_buf;
1.1.1.4   root      495:        unsigned __int64 nSecNo = startSector;
1.1.1.12! root      496:        int retVal = 0;
        !           497:        char temporaryKey[MASTER_KEYDATA_SIZE];
        !           498:        char originalK2[MASTER_KEYDATA_SIZE];
1.1.1.4   root      499: 
1.1.1.8   root      500: #ifdef _WIN32
                    501:        LARGE_INTEGER startOffset;
                    502:        LARGE_INTEGER newOffset;
                    503: 
1.1.1.4   root      504:        // Seek to start sector
                    505:        startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6   root      506:        if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
                    507:                || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4   root      508:        {
                    509:                return ERR_VOL_SEEKING;
                    510:        }
1.1.1.12! root      511: 
        !           512:        VirtualLock (temporaryKey, sizeof (temporaryKey));
        !           513:        VirtualLock (originalK2, sizeof (originalK2));
1.1.1.8   root      514: #endif
1.1.1.3   root      515: 
1.1.1.8   root      516:        write_buf = (char *) TCalloc (WRITE_BUF_SIZE);
1.1.1.3   root      517:        memset (sector, 0, sizeof (sector));
                    518: 
1.1.1.12! root      519:        // Remember the original secondary key (XTS mode) before generating a temporary one
        !           520:        memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
        !           521: 
1.1.1.7   root      522:        /* Fill the rest of the data area with random data */
                    523: 
1.1.1.3   root      524:        if(!quickFormat)
                    525:        {
1.1.1.7   root      526:                /* Generate a random temporary key set to be used for "dummy" encryption that will fill
                    527:                the free disk space (data area) with random data.  This is necessary for plausible
1.1.1.12! root      528:                deniability of hidden volumes. */
1.1.1.6   root      529: 
1.1.1.9   root      530:                // Temporary master key
                    531:                if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
                    532:                        goto fail;
1.1.1.12! root      533: 
        !           534:                // Temporary secondary key (XTS mode)
        !           535:                if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
1.1.1.9   root      536:                        goto fail;
1.1.1.7   root      537: 
                    538:                retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.12! root      539:                if (retVal != ERR_SUCCESS)
        !           540:                        goto fail;
        !           541: 
1.1.1.7   root      542:                if (!EAInitMode (cryptoInfo))
                    543:                {
1.1.1.12! root      544:                        retVal = ERR_MODE_INIT_FAILED;
        !           545:                        goto fail;
1.1.1.7   root      546:                }
1.1.1.4   root      547: 
1.1.1.3   root      548:                while (num_sectors--)
                    549:                {
1.1.1.12! root      550:                        /* Generate random plaintext. Note that reused plaintext blocks are not a concern here
        !           551:                        since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do 
        !           552:                        occur commonly on media in the "real world", so it might actually be a fatal mistake
        !           553:                        to try to avoid them completely. */
1.1.1.9   root      554: 
1.1.1.12! root      555: #if RNG_POOL_SIZE < SECTOR_SIZE
        !           556: #error RNG_POOL_SIZE < SECTOR_SIZE
1.1.1.7   root      557: #endif
                    558: 
1.1.1.9   root      559: #ifdef _WIN32
1.1.1.12! root      560:                        if (!RandpeekBytes (sector, SECTOR_SIZE))
1.1.1.9   root      561:                                goto fail;
                    562: #else
                    563:                        if ((nSecNo & 0x3fff) == 0)
                    564:                        {
1.1.1.12! root      565:                                if (!RandgetBytes (sector, SECTOR_SIZE, FALSE))
1.1.1.9   root      566:                                        goto fail;
                    567:                        }
                    568: #endif
1.1.1.7   root      569:                        // Encrypt the random plaintext and write it to the disk
1.1.1.6   root      570:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      571:                                cryptoInfo) == FALSE)
1.1.1.3   root      572:                                goto fail;
                    573:                }
1.1.1.8   root      574:                if (write_buf_cnt != 0 && 
                    575: #ifdef _WIN32
                    576:                        _lwrite ((HFILE)dev, write_buf, write_buf_cnt) == HFILE_ERROR)
                    577: #else
                    578:                        fwrite (write_buf, 1, write_buf_cnt, (FILE *)dev) != (size_t)write_buf_cnt)
                    579: #endif
1.1.1.3   root      580:                        goto fail;
                    581:        }
                    582:        else
                    583:                nSecNo = num_sectors;
                    584: 
                    585:        UpdateProgressBar (nSecNo);
                    586: 
1.1.1.12! root      587:        // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
        !           588:        memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
        !           589: 
        !           590:        // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
        !           591:        retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
        !           592:        if (retVal != ERR_SUCCESS)
        !           593:                goto fail;
        !           594:        if (!EAInitMode (cryptoInfo))
        !           595:        {
        !           596:                retVal = ERR_MODE_INIT_FAILED;
        !           597:                goto fail;
        !           598:        }
        !           599: 
        !           600:        if (write_buf != NULL)
        !           601:                TCfree (write_buf);
        !           602: 
1.1.1.7   root      603:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12! root      604:        burn (originalK2, sizeof(originalK2));
        !           605: #ifdef _WIN32
        !           606:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
        !           607:        VirtualUnlock (originalK2, sizeof (originalK2));
        !           608: #endif
1.1.1.3   root      609:        return 0;
                    610: 
                    611: fail:
                    612: 
1.1.1.12! root      613:        if (write_buf != NULL)
        !           614:                TCfree (write_buf);
        !           615: 
1.1.1.7   root      616:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12! root      617:        burn (originalK2, sizeof(originalK2));
        !           618: #ifdef _WIN32
        !           619:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
        !           620:        VirtualUnlock (originalK2, sizeof (originalK2));
        !           621: #endif
        !           622:        return (retVal ? retVal : ERR_OS_ERROR);
1.1       root      623: }
1.1.1.3   root      624: 
1.1.1.8   root      625: #ifdef _WIN32
1.1.1.3   root      626: 
                    627: volatile BOOLEAN FormatExResult;
                    628: 
                    629: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
                    630: {
                    631:        if (command == FMIFS_DONE)
                    632:                FormatExResult = *(BOOLEAN *) parameter;
                    633:        return TRUE;
                    634: }
                    635: 
                    636: BOOL FormatNtfs (int driveNo, int clusterSize)
                    637: {
                    638:        WCHAR dir[8] = { driveNo + 'A', 0 };
                    639:        PFORMATEX FormatEx;
                    640:        HMODULE hModule = LoadLibrary ("fmifs.dll");
1.1.1.10  root      641:        int i;
1.1.1.3   root      642: 
                    643:        if (hModule == NULL)
                    644:                return FALSE;
                    645: 
                    646:        if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
                    647:        {
                    648:                FreeLibrary (hModule);
                    649:                return FALSE;
                    650:        }
                    651: 
                    652:        wcscat (dir, L":\\");
                    653: 
                    654:        FormatExResult = FALSE;
                    655: 
1.1.1.12! root      656:        // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
1.1.1.10  root      657:        // It often helps to retry several times.
                    658:        for (i = 0; i < 10 && FormatExResult != TRUE; i++)
                    659:        {
1.1.1.11  root      660:                FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
1.1.1.10  root      661:        }
1.1.1.3   root      662: 
                    663:        FreeLibrary (hModule);
                    664:        return FormatExResult;
                    665: }
                    666: 
1.1.1.8   root      667: #endif
                    668: 
1.1.1.12! root      669: BOOL WriteSector (void *dev, char *sector,
1.1.1.3   root      670:             char *write_buf, int *write_buf_cnt,
1.1.1.8   root      671:             __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
1.1.1.3   root      672: {
1.1.1.8   root      673:        static __int32 updateTime = 0;
1.1.1.12! root      674:        UINT64_STRUCT unitNo;
        !           675: 
        !           676:        unitNo.Value = *nSecNo * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE;
        !           677: 
        !           678:        EncryptDataUnits (sector, &unitNo, SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
1.1.1.4   root      679: 
1.1.1.12! root      680:        (*nSecNo)++;
1.1.1.4   root      681: 
1.1.1.3   root      682:        memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
                    683:        (*write_buf_cnt) += SECTOR_SIZE;
                    684: 
                    685:        if (*write_buf_cnt == WRITE_BUF_SIZE)
                    686:        {
1.1.1.8   root      687:                if (
                    688: #ifdef _WIN32
                    689:                        _lwrite ((HFILE)dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR)
                    690: #else
                    691:                        fwrite (write_buf, 1, WRITE_BUF_SIZE, (FILE *)dev) != WRITE_BUF_SIZE)
                    692: #endif
1.1.1.3   root      693:                        return FALSE;
                    694:                else
                    695:                        *write_buf_cnt = 0;
                    696:        }
1.1.1.6   root      697:        
1.1.1.8   root      698: #ifdef _WIN32
1.1.1.6   root      699:        if (GetTickCount () - updateTime > 25)
1.1.1.3   root      700:        {
1.1.1.6   root      701:                if (UpdateProgressBar (*nSecNo))
1.1.1.3   root      702:                        return FALSE;
1.1.1.6   root      703: 
                    704:                updateTime = GetTickCount ();
1.1.1.3   root      705:        }
1.1.1.8   root      706: #else
                    707:        UpdateProgressBar (*nSecNo);
                    708: #endif
1.1.1.3   root      709: 
                    710:        return TRUE;
                    711: 
                    712: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.