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

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

unix.superglobalmegacorp.com

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