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

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

unix.superglobalmegacorp.com

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