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

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

unix.superglobalmegacorp.com

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