"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/Format.c" (10 Oct 2018, 31088 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Format.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.18_Source_vs_1.19_Source.

    1 /*
    2  Legal Notice: Some portions of the source code contained in this file were
    3  derived from the source code of TrueCrypt 7.1a, which is
    4  Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
    5  governed by the TrueCrypt License 3.0, also from the source code of
    6  Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
    7  and which is governed by the 'License Agreement for Encryption for the Masses'
    8  Modifications and additions to the original source code (contained in this file)
    9  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   10  and are governed by the Apache License 2.0 the full text of which is
   11  contained in the file License.txt included in VeraCrypt binary and source
   12  code distribution packages. */
   13 
   14 #include <stdlib.h>
   15 #include <string.h>
   16 
   17 #include "Tcdefs.h"
   18 
   19 #include "Common.h"
   20 #include "Crypto.h"
   21 #include "Fat.h"
   22 #include "Format.h"
   23 #include "Random.h"
   24 #include "Volumes.h"
   25 
   26 #include "Apidrvr.h"
   27 #include "Dlgcode.h"
   28 #include "Language.h"
   29 #include "Progress.h"
   30 #include "Resource.h"
   31 #include "Format/FormatCom.h"
   32 #include "Format/Tcformat.h"
   33 
   34 #include <Strsafe.h>
   35 
   36 #ifndef SRC_POS
   37 #define SRC_POS (__FUNCTION__ ":" TC_TO_STRING(__LINE__))
   38 #endif
   39 
   40 int FormatWriteBufferSize = 1024 * 1024;
   41 static uint32 FormatSectorSize = 0;
   42 
   43 
   44 uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize)
   45 {
   46     uint64 reservedSize;
   47 
   48     if (hiddenVolume)
   49     {
   50         // Reserve free space at the end of the host filesystem. FAT file system fills the last sector with
   51         // zeroes (marked as free; observed when quick format was performed using the OS format tool).
   52         // Therefore, when the outer volume is mounted with hidden volume protection, such write operations
   53         // (e.g. quick formatting the outer volume filesystem as FAT) would needlessly trigger hidden volume
   54         // protection.
   55 
   56 #if TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE > 4096
   57 #   error   TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE too large for very small volumes. Revise the code.
   58 #endif
   59 
   60 #if TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH < TC_MAX_VOLUME_SECTOR_SIZE
   61 #   error   TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH too small.
   62 #endif
   63 
   64         if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD)
   65             reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE;
   66         else
   67             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
   68     }
   69     else
   70     {
   71         reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE;
   72     }
   73 
   74     if (volumeSize < reservedSize)
   75         return 0;
   76 
   77     return volumeSize - reservedSize;
   78 }
   79 
   80 
   81 int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
   82 {
   83     int nStatus;
   84     PCRYPTO_INFO cryptoInfo = NULL;
   85     HANDLE dev = INVALID_HANDLE_VALUE;
   86     DWORD dwError;
   87     char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
   88     unsigned __int64 num_sectors, startSector;
   89     fatparams ft;
   90     FILETIME ftCreationTime;
   91     FILETIME ftLastWriteTime;
   92     FILETIME ftLastAccessTime;
   93     BOOL bTimeStampValid = FALSE;
   94     BOOL bInstantRetryOtherFilesys = FALSE;
   95     WCHAR dosDev[TC_MAX_PATH] = { 0 };
   96     WCHAR devName[MAX_PATH] = { 0 };
   97     int driveLetter = -1;
   98     WCHAR deviceName[MAX_PATH];
   99     uint64 dataOffset, dataAreaSize;
  100     LARGE_INTEGER offset;
  101     BOOL bFailedRequiredDASD = FALSE;
  102     HWND hwndDlg = volParams->hwndDlg;
  103 
  104     FormatSectorSize = volParams->sectorSize;
  105 
  106     if (FormatSectorSize < TC_MIN_VOLUME_SECTOR_SIZE
  107         || FormatSectorSize > TC_MAX_VOLUME_SECTOR_SIZE
  108         || FormatSectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
  109     {
  110         Error ("SECTOR_SIZE_UNSUPPORTED", hwndDlg);
  111         return ERR_DONT_REPORT;
  112     }
  113 
  114     /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is
  115     less than the maximum FAT size, the user is asked within this function whether he wants to instantly
  116     retry FAT format instead (to avoid having to re-create the whole container again). If the user
  117     answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed
  118     and some destructive operations that were performed during the first attempt must be (and are) skipped.
  119     Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format',
  120     determine whether they (or their portions) need to be skipped during such a second attempt; if so,
  121     use the 'bInstantRetryOtherFilesys' flag to skip them. */
  122 
  123     if (volParams->hiddenVol)
  124     {
  125         dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size;
  126     }
  127     else
  128     {
  129         if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE)
  130             return ERR_VOL_SIZE_WRONG;
  131 
  132         dataOffset = TC_VOLUME_DATA_OFFSET;
  133     }
  134 
  135     dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size);
  136 
  137     num_sectors = dataAreaSize / FormatSectorSize;
  138 
  139     if (volParams->bDevice)
  140     {
  141         StringCchCopyW (deviceName, ARRAYSIZE(deviceName), volParams->volumePath);
  142 
  143         driveLetter = GetDiskDeviceDriveLetter (deviceName);
  144     }
  145 
  146     VirtualLock (header, sizeof (header));
  147 
  148     nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
  149                      header,
  150                      volParams->ea,
  151                      FIRST_MODE_OF_OPERATION_ID,
  152                      volParams->password,
  153                      volParams->pkcs5,
  154                       volParams->pim,
  155                      NULL,
  156                      &cryptoInfo,
  157                      dataAreaSize,
  158                      volParams->hiddenVol ? dataAreaSize : 0,
  159                      dataOffset,
  160                      dataAreaSize,
  161                      0,
  162                      volParams->headerFlags,
  163                      FormatSectorSize,
  164                      FALSE);
  165 
  166     /* cryptoInfo sanity check to make Coverity happy eventhough it can't be NULL if nStatus = 0 */
  167     if ((nStatus != 0) || !cryptoInfo)
  168     {
  169         burn (header, sizeof (header));
  170         VirtualUnlock (header, sizeof (header));
  171         return nStatus? nStatus : ERR_OUTOFMEMORY;
  172     }
  173 
  174 begin_format:
  175 
  176     if (volParams->bDevice)
  177     {
  178         /* Device-hosted volume */
  179 
  180         DWORD dwResult;
  181         int nPass;
  182 
  183         if (FakeDosNameForDevice (volParams->volumePath, dosDev, sizeof(dosDev), devName, sizeof(devName), FALSE) != 0)
  184             return ERR_OS_ERROR;
  185 
  186         if (IsDeviceMounted (devName))
  187         {
  188             if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE)
  189             {
  190                 Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg);
  191                 nStatus = ERR_DONT_REPORT;
  192                 goto error;
  193             }
  194 
  195             /* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver
  196             would otherwise prevent us from writing to hidden sectors). */
  197 
  198             if (!DeviceIoControl (dev,
  199                 FSCTL_ALLOW_EXTENDED_DASD_IO,
  200                 NULL,
  201                 0,
  202                 NULL,
  203                 0,
  204                 &dwResult,
  205                 NULL))
  206             {
  207                 bFailedRequiredDASD = TRUE;
  208             }
  209         }
  210         else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1)
  211         {
  212             // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition
  213             // to which no drive letter has been assigned under the system. This problem can be worked
  214             // around by assigning a drive letter to the partition temporarily.
  215 
  216             wchar_t szDriveLetter[] = { L'A', L':', 0 };
  217             wchar_t rootPath[] = { L'A', L':', L'\\', 0 };
  218             wchar_t uniqVolName[MAX_PATH+1] = { 0 };
  219             int tmpDriveLetter = -1;
  220             BOOL bResult = FALSE;
  221 
  222             tmpDriveLetter = GetFirstAvailableDrive ();
  223 
  224             if (tmpDriveLetter != -1)
  225             {
  226                 rootPath[0] += (wchar_t) tmpDriveLetter;
  227                 szDriveLetter[0] += (wchar_t) tmpDriveLetter;
  228 
  229                 if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath))
  230                 {
  231                     bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
  232 
  233                     DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
  234                         szDriveLetter,
  235                         volParams->volumePath);
  236 
  237                     if (bResult
  238                         && SetVolumeMountPoint (rootPath, uniqVolName))
  239                     {
  240                         // The drive letter can be removed now
  241                         DeleteVolumeMountPoint (rootPath);
  242                     }
  243                 }
  244             }
  245         }
  246 
  247         // For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be
  248         // redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed,
  249         // bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However,
  250         // for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly
  251         // send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result.
  252 
  253         DeviceIoControl (dev,
  254             FSCTL_ALLOW_EXTENDED_DASD_IO,
  255             NULL,
  256             0,
  257             NULL,
  258             0,
  259             &dwResult,
  260             NULL);
  261 
  262 
  263         // If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open
  264         // so that the filesystem driver does not prevent us from formatting hidden sectors.
  265         for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++)
  266         {
  267             int retryCount;
  268 
  269             retryCount = 0;
  270 
  271             // Try exclusive access mode first
  272             // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries).
  273             while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES)
  274             {
  275                 dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  276 
  277                 if (retryCount > 1)
  278                     Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY);
  279             }
  280 
  281             if (dev == INVALID_HANDLE_VALUE)
  282             {
  283                 // Exclusive access denied -- retry in shared mode
  284                 dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  285                 if (dev != INVALID_HANDLE_VALUE)
  286                 {
  287                     if (!volParams->bForceOperation && (Silent || (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))))
  288                     {
  289                         nStatus = ERR_DONT_REPORT;
  290                         goto error;
  291                     }
  292                 }
  293                 else
  294                 {
  295                     handleWin32Error (volParams->hwndDlg, SRC_POS);
  296                     Error ("CANT_ACCESS_VOL", hwndDlg);
  297                     nStatus = ERR_DONT_REPORT;
  298                     goto error;
  299                 }
  300             }
  301 
  302             if (volParams->hiddenVol || bInstantRetryOtherFilesys)
  303                 break;  // The following "quick format" operation would damage the outer volume
  304 
  305             if (nPass == 0)
  306             {
  307                 char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE];
  308                 DWORD bw;
  309 
  310                 // Perform pseudo "quick format" so that the filesystem driver does not prevent us from
  311                 // formatting hidden sectors
  312                 memset (buf, 0, sizeof (buf));
  313 
  314                 if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL))
  315                 {
  316                     nStatus = ERR_OS_ERROR;
  317                     goto error;
  318                 }
  319 
  320                 FlushFileBuffers (dev);
  321                 CloseHandle (dev);
  322                 dev = INVALID_HANDLE_VALUE;
  323             }
  324         }
  325 
  326         if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
  327         {
  328             Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg);
  329             nStatus = ERR_DONT_REPORT;
  330             goto error;
  331         }
  332     }
  333     else
  334     {
  335         /* File-hosted volume */
  336 
  337         dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE,
  338             (volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
  339             NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
  340 
  341         if (dev == INVALID_HANDLE_VALUE)
  342         {
  343             nStatus = ERR_OS_ERROR;
  344             goto error;
  345         }
  346 
  347         DisableFileCompression (dev);
  348 
  349         if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
  350         {
  351             LARGE_INTEGER volumeSize;
  352             volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
  353 
  354             if (volParams->sparseFileSwitch && volParams->quickFormat)
  355             {
  356                 // Create as sparse file container
  357                 DWORD tmp;
  358                 if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
  359                 {
  360                     nStatus = ERR_OS_ERROR;
  361                     goto error;
  362                 }
  363             }
  364 
  365             // Preallocate the file
  366             if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
  367                 || !SetEndOfFile (dev)
  368                 || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
  369             {
  370                 nStatus = ERR_OS_ERROR;
  371                 goto error;
  372             }
  373         }
  374     }
  375 
  376     if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
  377     {
  378         if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
  379             bTimeStampValid = FALSE;
  380         else
  381             bTimeStampValid = TRUE;
  382     }
  383 
  384     if (volParams->hwndDlg && volParams->bGuiMode) KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
  385 
  386     /* Volume header */
  387 
  388     // Hidden volume setup
  389     if (volParams->hiddenVol)
  390     {
  391         LARGE_INTEGER headerOffset;
  392 
  393         // Check hidden volume size
  394         if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
  395         {
  396             nStatus = ERR_VOL_SIZE_WRONG;
  397             goto error;
  398         }
  399 
  400         // Seek to hidden volume header location
  401 
  402         headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
  403 
  404         if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
  405         {
  406             nStatus = ERR_OS_ERROR;
  407             goto error;
  408         }
  409     }
  410     else if (bInstantRetryOtherFilesys)
  411     {
  412         // The previous file system format failed and the user wants to try again with a different file system.
  413         // The volume header had been written successfully so we need to seek to the byte after the header.
  414 
  415         LARGE_INTEGER offset;
  416         offset.QuadPart = TC_VOLUME_DATA_OFFSET;
  417         if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
  418         {
  419             nStatus = ERR_OS_ERROR;
  420             goto error;
  421         }
  422     }
  423 
  424     if (!bInstantRetryOtherFilesys)
  425     {
  426         // Write the volume header
  427         if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header))
  428         {
  429             nStatus = ERR_OS_ERROR;
  430             goto error;
  431         }
  432 
  433         // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
  434         if (!volParams->bDevice && !volParams->hiddenVol)
  435         {
  436             byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
  437             DWORD bytesWritten;
  438             ZeroMemory (buf, sizeof (buf));
  439 
  440             if (!WriteFile (dev, buf, sizeof (buf), &bytesWritten, NULL))
  441             {
  442                 nStatus = ERR_OS_ERROR;
  443                 goto error;
  444             }
  445 
  446             if (bytesWritten != sizeof (buf))
  447             {
  448                 nStatus = ERR_PARAMETER_INCORRECT;
  449                 goto error;
  450             }
  451         }
  452     }
  453 
  454     if (volParams->hiddenVol)
  455     {
  456         // Calculate data area position of hidden volume
  457         cryptoInfo->hiddenVolumeOffset = dataOffset;
  458 
  459         // Validate the offset
  460         if (dataOffset % FormatSectorSize != 0)
  461         {
  462             nStatus = ERR_VOL_SIZE_WRONG;
  463             goto error;
  464         }
  465 
  466         volParams->quickFormat = TRUE;      // To entirely format a hidden volume would be redundant
  467     }
  468 
  469     /* Data area */
  470     startSector = dataOffset / FormatSectorSize;
  471 
  472     // Format filesystem
  473 
  474     switch (volParams->fileSystem)
  475     {
  476     case FILESYS_NONE:
  477     case FILESYS_NTFS:
  478     case FILESYS_EXFAT:
  479     case FILESYS_REFS:
  480 
  481         if (volParams->bDevice && !StartFormatWriteThread())
  482         {
  483             nStatus = ERR_OS_ERROR;
  484             goto error;
  485         }
  486 
  487         nStatus = FormatNoFs (hwndDlg, startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat);
  488 
  489         if (volParams->bDevice)
  490             StopFormatWriteThread();
  491 
  492         break;
  493 
  494     case FILESYS_FAT:
  495         if (num_sectors > 0xFFFFffff)
  496         {
  497             nStatus = ERR_VOL_SIZE_WRONG;
  498             goto error;
  499         }
  500 
  501         // Calculate the fats, root dir etc
  502         ft.num_sectors = (unsigned int) (num_sectors);
  503 
  504 #if TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
  505 #error TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
  506 #endif
  507 
  508         ft.sector_size = (uint16) FormatSectorSize;
  509         ft.cluster_size = volParams->clusterSize;
  510         memcpy (ft.volume_name, "NO NAME    ", 11);
  511         GetFatParams (&ft);
  512         *(volParams->realClusterSize) = ft.cluster_size * FormatSectorSize;
  513 
  514         if (volParams->bDevice && !StartFormatWriteThread())
  515         {
  516             nStatus = ERR_OS_ERROR;
  517             goto error;
  518         }
  519 
  520         nStatus = FormatFat (hwndDlg, startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat);
  521 
  522         if (volParams->bDevice)
  523             StopFormatWriteThread();
  524 
  525         break;
  526 
  527     default:
  528         nStatus = ERR_PARAMETER_INCORRECT;
  529         goto error;
  530     }
  531 
  532     if (nStatus != ERR_SUCCESS)
  533         goto error;
  534 
  535     // Write header backup
  536     offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
  537 
  538     if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
  539     {
  540         nStatus = ERR_OS_ERROR;
  541         goto error;
  542     }
  543 
  544     nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
  545         header,
  546         volParams->ea,
  547         FIRST_MODE_OF_OPERATION_ID,
  548         volParams->password,
  549         volParams->pkcs5,
  550         volParams->pim,
  551         cryptoInfo->master_keydata,
  552         &cryptoInfo,
  553         dataAreaSize,
  554         volParams->hiddenVol ? dataAreaSize : 0,
  555         dataOffset,
  556         dataAreaSize,
  557         0,
  558         volParams->headerFlags,
  559         FormatSectorSize,
  560         FALSE);
  561 
  562     if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header))
  563     {
  564         nStatus = ERR_OS_ERROR;
  565         goto error;
  566     }
  567 
  568     // Fill reserved header sectors (including the backup header area) with random data
  569     if (!volParams->hiddenVol)
  570     {
  571         BOOL bUpdateBackup = FALSE;
  572 
  573         nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, dataAreaSize, FALSE, FALSE);
  574 
  575         if (nStatus != ERR_SUCCESS)
  576             goto error;
  577 
  578         // write fake hidden volume header to protect against attacks that use statistical entropy
  579         // analysis to detect presence of hidden volumes.
  580         
  581         while (TRUE)
  582         {
  583             PCRYPTO_INFO dummyInfo = NULL;
  584             LARGE_INTEGER hiddenOffset;
  585 
  586             hiddenOffset.QuadPart = bUpdateBackup ? dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE + TC_HIDDEN_VOLUME_HEADER_OFFSET: TC_HIDDEN_VOLUME_HEADER_OFFSET;
  587 
  588             nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
  589                 header,
  590                 volParams->ea,
  591                 FIRST_MODE_OF_OPERATION_ID,
  592                 NULL,
  593                 0,
  594                 0,
  595                 NULL,
  596                 &dummyInfo,
  597                 dataAreaSize,
  598                 dataAreaSize,
  599                 dataOffset,
  600                 dataAreaSize,
  601                 0,
  602                 volParams->headerFlags,
  603                 FormatSectorSize,
  604                 FALSE);
  605 
  606             if (nStatus != ERR_SUCCESS)
  607                 goto error;
  608 
  609             crypto_close (dummyInfo);
  610 
  611             if (!SetFilePointerEx ((HANDLE) dev, hiddenOffset, NULL, FILE_BEGIN))
  612             {
  613                 nStatus = ERR_OS_ERROR;
  614                 goto error;
  615             }
  616 
  617             if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header))
  618             {
  619                 nStatus = ERR_OS_ERROR;
  620                 goto error;
  621             }
  622 
  623             if (bUpdateBackup)
  624                 break;
  625 
  626             bUpdateBackup = TRUE;
  627         }
  628     }
  629 
  630 #ifndef DEBUG
  631     if (volParams->quickFormat && volParams->fileSystem != FILESYS_NTFS && volParams->fileSystem != FILESYS_EXFAT && volParams->fileSystem != FILESYS_REFS)
  632         Sleep (500);    // User-friendly GUI
  633 #endif
  634 
  635 error:
  636     dwError = GetLastError();
  637 
  638     burn (header, sizeof (header));
  639     VirtualUnlock (header, sizeof (header));
  640 
  641     if (dev != INVALID_HANDLE_VALUE)
  642     {
  643         if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
  644         {
  645             // Remove preallocated part before closing file handle if format failed
  646             if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
  647                 SetEndOfFile (dev);
  648         }
  649 
  650         FlushFileBuffers (dev);
  651 
  652         if (bTimeStampValid)
  653             SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
  654 
  655         CloseHandle (dev);
  656         dev = INVALID_HANDLE_VALUE;
  657     }
  658 
  659     if (nStatus != 0)
  660     {
  661         SetLastError(dwError);
  662         goto fv_end;
  663     }
  664 
  665     if (volParams->fileSystem == FILESYS_NTFS || volParams->fileSystem == FILESYS_EXFAT || volParams->fileSystem == FILESYS_REFS)
  666     {
  667         // Quick-format volume as NTFS
  668         int driveNo = GetLastAvailableDrive ();
  669         MountOptions mountOptions;
  670         int retCode;
  671         int fsType = volParams->fileSystem;
  672 
  673         ZeroMemory (&mountOptions, sizeof (mountOptions));
  674 
  675         if (driveNo == -1)
  676         {
  677             if (!Silent)
  678             {
  679                 MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
  680                 MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
  681             }
  682 
  683             nStatus = ERR_NO_FREE_DRIVES;
  684             goto fv_end;
  685         }
  686 
  687         mountOptions.ReadOnly = FALSE;
  688         mountOptions.Removable = FALSE;
  689         mountOptions.ProtectHiddenVolume = FALSE;
  690         mountOptions.PreserveTimestamp = bPreserveTimestamp;
  691         mountOptions.PartitionInInactiveSysEncScope = FALSE;
  692         mountOptions.UseBackupHeader = FALSE;
  693 
  694         if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, volParams->pkcs5, volParams->pim, FALSE, FALSE, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
  695         {
  696             if (!Silent)
  697             {
  698                 MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
  699                 MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
  700             }
  701             nStatus = ERR_VOL_MOUNT_FAILED;
  702             goto fv_end;
  703         }
  704 
  705         if (!Silent && !IsAdmin () && IsUacSupported ())
  706             retCode = UacFormatFs (volParams->hwndDlg, driveNo, volParams->clusterSize, fsType);
  707         else
  708             retCode = FormatFs (driveNo, volParams->clusterSize, fsType);
  709 
  710         if (retCode != TRUE)
  711         {
  712             if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent)
  713                 MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
  714 
  715             if (dataAreaSize <= TC_MAX_FAT_SECTOR_COUNT * FormatSectorSize)
  716             {
  717                 if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT", hwndDlg) == IDYES)
  718                 {
  719                     // NTFS format failed and the user wants to try FAT format immediately
  720                     volParams->fileSystem = FILESYS_FAT;
  721                     bInstantRetryOtherFilesys = TRUE;
  722                     volParams->quickFormat = TRUE;      // Volume has already been successfully TC-formatted
  723                     volParams->clusterSize = 0;     // Default cluster size
  724                     goto begin_format;
  725                 }
  726             }
  727             else
  728                 Error ("FORMAT_NTFS_FAILED", hwndDlg);
  729 
  730             nStatus = ERR_DONT_REPORT;
  731             goto fv_end;
  732         }
  733 
  734         if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent)
  735             MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
  736     }
  737 
  738 fv_end:
  739     dwError = GetLastError();
  740 
  741     if (dosDev[0])
  742         RemoveFakeDosName (volParams->volumePath, dosDev);
  743 
  744     crypto_close (cryptoInfo);
  745 
  746     SetLastError (dwError);
  747     return nStatus;
  748 }
  749 
  750 
  751 int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
  752 {
  753     int write_buf_cnt = 0;
  754     char sector[TC_MAX_VOLUME_SECTOR_SIZE], *write_buf;
  755     unsigned __int64 nSecNo = startSector;
  756     int retVal = 0;
  757     DWORD err;
  758     CRYPTOPP_ALIGN_DATA(16) char temporaryKey[MASTER_KEYDATA_SIZE];
  759     CRYPTOPP_ALIGN_DATA(16) char originalK2[MASTER_KEYDATA_SIZE];
  760 
  761     LARGE_INTEGER startOffset;
  762     LARGE_INTEGER newOffset;
  763 
  764     // Seek to start sector
  765     startOffset.QuadPart = startSector * FormatSectorSize;
  766     if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
  767         || newOffset.QuadPart != startOffset.QuadPart)
  768     {
  769         return ERR_OS_ERROR;
  770     }
  771 
  772     write_buf = (char *)TCalloc (FormatWriteBufferSize);
  773     if (!write_buf)
  774         return ERR_OUTOFMEMORY;
  775 
  776     VirtualLock (temporaryKey, sizeof (temporaryKey));
  777     VirtualLock (originalK2, sizeof (originalK2));
  778 
  779     memset (sector, 0, sizeof (sector));
  780 
  781     // Remember the original secondary key (XTS mode) before generating a temporary one
  782     memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
  783 
  784     /* Fill the rest of the data area with random data */
  785 
  786     if(!quickFormat)
  787     {
  788         /* Generate a random temporary key set to be used for "dummy" encryption that will fill
  789         the free disk space (data area) with random data.  This is necessary for plausible
  790         deniability of hidden volumes. */
  791 
  792         // Temporary master key
  793         if (!RandgetBytes (hwndDlg, temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
  794             goto fail;
  795 
  796         // Temporary secondary key (XTS mode)
  797         if (!RandgetBytes (hwndDlg, cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
  798             goto fail;
  799 
  800         retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
  801         if (retVal != ERR_SUCCESS)
  802             goto fail;
  803 
  804         if (!EAInitMode (cryptoInfo))
  805         {
  806             retVal = ERR_MODE_INIT_FAILED;
  807             goto fail;
  808         }
  809 
  810         while (num_sectors--)
  811         {
  812             if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
  813                 cryptoInfo) == FALSE)
  814                 goto fail;
  815         }
  816 
  817         if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
  818             goto fail;
  819     }
  820     else
  821         nSecNo = num_sectors;
  822 
  823     UpdateProgressBar (nSecNo * FormatSectorSize);
  824 
  825     // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
  826     memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
  827 
  828     // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
  829     retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
  830     if (retVal != ERR_SUCCESS)
  831         goto fail;
  832     if (!EAInitMode (cryptoInfo))
  833     {
  834         retVal = ERR_MODE_INIT_FAILED;
  835         goto fail;
  836     }
  837 
  838     burn (temporaryKey, sizeof(temporaryKey));
  839     burn (originalK2, sizeof(originalK2));
  840     VirtualUnlock (temporaryKey, sizeof (temporaryKey));
  841     VirtualUnlock (originalK2, sizeof (originalK2));
  842     TCfree (write_buf);
  843 
  844     return 0;
  845 
  846 fail:
  847     err = GetLastError();
  848 
  849     burn (temporaryKey, sizeof(temporaryKey));
  850     burn (originalK2, sizeof(originalK2));
  851     VirtualUnlock (temporaryKey, sizeof (temporaryKey));
  852     VirtualUnlock (originalK2, sizeof (originalK2));
  853     TCfree (write_buf);
  854 
  855     SetLastError (err);
  856     return (retVal ? retVal : ERR_OS_ERROR);
  857 }
  858 
  859 
  860 volatile BOOLEAN FormatExError;
  861 
  862 BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
  863 {
  864     if (FormatExError)
  865         return FALSE;
  866 
  867     switch(command) {
  868     case FMIFS_PROGRESS:
  869         break;
  870     case FMIFS_STRUCTURE_PROGRESS:
  871         break;
  872     case FMIFS_DONE:
  873         if(*(BOOLEAN*)parameter == FALSE) {
  874             FormatExError = TRUE;
  875         }
  876         break;
  877     case FMIFS_DONE_WITH_STRUCTURE:
  878         break;
  879     case FMIFS_INCOMPATIBLE_FILE_SYSTEM:
  880         FormatExError = TRUE;
  881         break;
  882     case FMIFS_ACCESS_DENIED:
  883         FormatExError = TRUE;
  884         break;
  885     case FMIFS_MEDIA_WRITE_PROTECTED:
  886         FormatExError = TRUE;
  887         break;
  888     case FMIFS_VOLUME_IN_USE:
  889         FormatExError = TRUE;
  890         break;
  891     case FMIFS_DEVICE_NOT_READY:
  892         FormatExError = TRUE;
  893         break;
  894     case FMIFS_CANT_QUICK_FORMAT:
  895         FormatExError = TRUE;
  896         break;
  897     case FMIFS_BAD_LABEL:
  898         FormatExError = TRUE;
  899         break;
  900     case FMIFS_OUTPUT:
  901         break;
  902     case FMIFS_CLUSTER_SIZE_TOO_BIG:
  903     case FMIFS_CLUSTER_SIZE_TOO_SMALL:
  904         FormatExError = TRUE;
  905         break;
  906     case FMIFS_VOLUME_TOO_BIG:
  907     case FMIFS_VOLUME_TOO_SMALL:
  908         FormatExError = TRUE;
  909         break;
  910     case FMIFS_NO_MEDIA_IN_DRIVE:
  911         FormatExError = TRUE;
  912         break;
  913     default:
  914         FormatExError = TRUE;
  915         break;
  916     }
  917     return (FormatExError? FALSE : TRUE);
  918 }
  919 
  920 BOOL FormatFs (int driveNo, int clusterSize, int fsType)
  921 {
  922     wchar_t dllPath[MAX_PATH] = {0};
  923     WCHAR dir[8] = { (WCHAR) driveNo + L'A', 0 };
  924     PFORMATEX FormatEx;
  925     HMODULE hModule;
  926     int i;
  927     WCHAR szFsFormat[16];
  928     WCHAR szLabel[2] = {0};
  929     switch (fsType)
  930     {
  931         case FILESYS_NTFS:
  932             StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"NTFS");
  933             break;
  934         case FILESYS_EXFAT:
  935             StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"EXFAT");
  936             break;
  937         case FILESYS_REFS:
  938             StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"ReFS");
  939             break;
  940         default:
  941             return FALSE;
  942     }
  943 
  944 
  945     if (GetSystemDirectory (dllPath, MAX_PATH))
  946     {
  947         StringCchCatW(dllPath, ARRAYSIZE(dllPath), L"\\fmifs.dll");
  948     }
  949     else
  950         StringCchCopyW(dllPath, ARRAYSIZE(dllPath), L"C:\\Windows\\System32\\fmifs.dll");
  951 
  952     hModule = LoadLibrary (dllPath);
  953 
  954     if (hModule == NULL)
  955         return FALSE;
  956 
  957     if (!(FormatEx = (PFORMATEX) GetProcAddress (GetModuleHandle (L"fmifs.dll"), "FormatEx")))
  958     {
  959         FreeLibrary (hModule);
  960         return FALSE;
  961     }
  962 
  963     StringCchCatW (dir, ARRAYSIZE(dir), L":\\");
  964 
  965     FormatExError = TRUE;
  966 
  967     // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
  968     // It often helps to retry several times.
  969     for (i = 0; i < 50 && FormatExError; i++)
  970     {
  971         FormatExError = FALSE;
  972         FormatEx (dir, FMIFS_HARDDISK, szFsFormat, szLabel, TRUE, clusterSize * FormatSectorSize, FormatExCallback);
  973     }
  974 
  975     // The device may be referenced for some time after FormatEx() returns
  976     Sleep (4000);
  977 
  978     FreeLibrary (hModule);
  979     return FormatExError? FALSE : TRUE;
  980 }
  981 
  982 BOOL FormatNtfs (int driveNo, int clusterSize)
  983 {
  984     return FormatFs (driveNo, clusterSize, FILESYS_NTFS);
  985 }
  986 
  987 BOOL WriteSector (void *dev, char *sector,
  988          char *write_buf, int *write_buf_cnt,
  989          __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
  990 {
  991     static __int32 updateTime = 0;
  992 
  993     (*nSecNo)++;
  994 
  995     memcpy (write_buf + *write_buf_cnt, sector, FormatSectorSize);
  996     (*write_buf_cnt) += FormatSectorSize;
  997 
  998     if (*write_buf_cnt == FormatWriteBufferSize && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
  999         return FALSE;
 1000 
 1001     if (GetTickCount () - updateTime > 25)
 1002     {
 1003         if (UpdateProgressBar (*nSecNo * FormatSectorSize))
 1004             return FALSE;
 1005 
 1006         updateTime = GetTickCount ();
 1007     }
 1008 
 1009     return TRUE;
 1010 
 1011 }
 1012 
 1013 
 1014 static volatile BOOL WriteThreadRunning;
 1015 static volatile BOOL WriteThreadExitRequested;
 1016 static HANDLE WriteThreadHandle;
 1017 
 1018 static byte *WriteThreadBuffer;
 1019 static HANDLE WriteBufferEmptyEvent;
 1020 static HANDLE WriteBufferFullEvent;
 1021 
 1022 static volatile HANDLE WriteRequestHandle;
 1023 static volatile int WriteRequestSize;
 1024 static volatile DWORD WriteRequestResult;
 1025 
 1026 
 1027 static void __cdecl FormatWriteThreadProc (void *arg)
 1028 {
 1029     DWORD bytesWritten;
 1030 
 1031     SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
 1032 
 1033     while (!WriteThreadExitRequested)
 1034     {
 1035         if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED)
 1036         {
 1037             handleWin32Error (NULL, SRC_POS);
 1038             break;
 1039         }
 1040 
 1041         if (WriteThreadExitRequested)
 1042             break;
 1043 
 1044         if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL))
 1045             WriteRequestResult = GetLastError();
 1046         else
 1047             WriteRequestResult = ERROR_SUCCESS;
 1048 
 1049         if (!SetEvent (WriteBufferEmptyEvent))
 1050         {
 1051             handleWin32Error (NULL, SRC_POS);
 1052             break;
 1053         }
 1054     }
 1055 
 1056     WriteThreadRunning = FALSE;
 1057     _endthread();
 1058 }
 1059 
 1060 
 1061 static BOOL StartFormatWriteThread ()
 1062 {
 1063     DWORD sysErr;
 1064 
 1065     WriteBufferEmptyEvent = NULL;
 1066     WriteBufferFullEvent = NULL;
 1067     WriteThreadBuffer = NULL;
 1068 
 1069     WriteBufferEmptyEvent = CreateEvent (NULL, FALSE, TRUE, NULL);
 1070     if (!WriteBufferEmptyEvent)
 1071         goto err;
 1072 
 1073     WriteBufferFullEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 1074     if (!WriteBufferFullEvent)
 1075         goto err;
 1076 
 1077     WriteThreadBuffer = TCalloc (FormatWriteBufferSize);
 1078     if (!WriteThreadBuffer)
 1079     {
 1080         SetLastError (ERROR_OUTOFMEMORY);
 1081         goto err;
 1082     }
 1083 
 1084     WriteThreadExitRequested = FALSE;
 1085     WriteRequestResult = ERROR_SUCCESS;
 1086 
 1087     WriteThreadHandle = (HANDLE) _beginthread (FormatWriteThreadProc, 0, NULL);
 1088     if ((uintptr_t) WriteThreadHandle == -1L)
 1089         goto err;
 1090 
 1091     WriteThreadRunning = TRUE;
 1092     return TRUE;
 1093 
 1094 err:
 1095     sysErr = GetLastError();
 1096 
 1097     if (WriteBufferEmptyEvent)
 1098         CloseHandle (WriteBufferEmptyEvent);
 1099     if (WriteBufferFullEvent)
 1100         CloseHandle (WriteBufferFullEvent);
 1101     if (WriteThreadBuffer)
 1102         TCfree (WriteThreadBuffer);
 1103 
 1104     SetLastError (sysErr);
 1105     return FALSE;
 1106 }
 1107 
 1108 
 1109 static void StopFormatWriteThread ()
 1110 {
 1111     if (WriteThreadRunning)
 1112     {
 1113         WaitForSingleObject (WriteBufferEmptyEvent, INFINITE);
 1114 
 1115         WriteThreadExitRequested = TRUE;
 1116         SetEvent (WriteBufferFullEvent);
 1117 
 1118         WaitForSingleObject (WriteThreadHandle, INFINITE);
 1119     }
 1120 
 1121     CloseHandle (WriteBufferEmptyEvent);
 1122     CloseHandle (WriteBufferFullEvent);
 1123     TCfree (WriteThreadBuffer);
 1124 }
 1125 
 1126 
 1127 BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
 1128 {
 1129     UINT64_STRUCT unitNo;
 1130     DWORD bytesWritten;
 1131 
 1132     if (*write_buf_cnt == 0)
 1133         return TRUE;
 1134 
 1135     unitNo.Value = (*nSecNo * FormatSectorSize - *write_buf_cnt) / ENCRYPTION_DATA_UNIT_SIZE;
 1136 
 1137     EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
 1138 
 1139     if (WriteThreadRunning)
 1140     {
 1141         if (WaitForSingleObject (WriteBufferEmptyEvent, INFINITE) == WAIT_FAILED)
 1142             return FALSE;
 1143 
 1144         if (WriteRequestResult != ERROR_SUCCESS)
 1145         {
 1146             SetEvent (WriteBufferEmptyEvent);
 1147             SetLastError (WriteRequestResult);
 1148             return FALSE;
 1149         }
 1150 
 1151         memcpy (WriteThreadBuffer, write_buf, *write_buf_cnt);
 1152         WriteRequestHandle = dev;
 1153         WriteRequestSize = *write_buf_cnt;
 1154 
 1155         if (!SetEvent (WriteBufferFullEvent))
 1156             return FALSE;
 1157     }
 1158     else
 1159     {
 1160         if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL))
 1161             return FALSE;
 1162     }
 1163 
 1164     *write_buf_cnt = 0;
 1165     return TRUE;
 1166 }