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

1.1.1.6 ! root        1: /* Legal Notice: The source code contained in this file has been derived from
        !             2:    the source code of Encryption for the Masses 2.02a, which is Copyright (c)
        !             3:    1998-99 Paul Le Roux and which is covered by the 'License Agreement for
        !             4:    Encryption for the Masses'. Modifications and additions to that source code
        !             5:    contained in this file are Copyright (c) 2004-2005 TrueCrypt Foundation and
        !             6:    Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.0
        !             7:    the full text of which is contained in the file License.txt included in
        !             8:    TrueCrypt binary and source code distribution archives.  */
        !             9: 
        !            10: #include "Tcdefs.h"
        !            11: 
        !            12: #include "Crypto.h"
        !            13: #include "Fat.h"
        !            14: #include "Format.h"
        !            15: #include "Volumes.h"
        !            16: #include "Progress.h"
        !            17: #include "Apidrvr.h"
        !            18: #include "Dlgcode.h"
        !            19: #include "Language.h"
        !            20: #include "Resource.h"
        !            21: #include "Common.h"
        !            22: #include "Random.h"
1.1.1.3   root       23: 
1.1       root       24: int
                     25: FormatVolume (char *lpszFilename,
                     26:              BOOL bDevice,
1.1.1.3   root       27:                  char *volumePath,
1.1       root       28:              unsigned __int64 size,
1.1.1.4   root       29:                  unsigned __int64 hiddenVolHostSize,
1.1.1.6 ! root       30:              Password *password,
1.1       root       31:              int cipher,
                     32:              int pkcs5,
                     33:                  BOOL quickFormat,
1.1.1.3   root       34:                  int fileSystem,
                     35:                  int clusterSize,
1.1.1.6 ! root       36:                  wchar_t *summaryMsg,
1.1.1.4   root       37:              HWND hwndDlg,
                     38:                  BOOL hiddenVol,
                     39:                  int *realClusterSize)
1.1       root       40: {
                     41:        int nStatus;
                     42:        PCRYPTO_INFO cryptoInfo;
1.1.1.4   root       43:        HANDLE dev = INVALID_HANDLE_VALUE;
1.1.1.3   root       44:        DWORD dwError, dwThen, dwNow;
1.1       root       45:        diskio_f write;
1.1.1.3   root       46:        char header[SECTOR_SIZE];
1.1.1.4   root       47:        unsigned __int64 num_sectors, startSector;
1.1.1.3   root       48:        fatparams ft;
1.1.1.4   root       49:        FILETIME ftCreationTime;
                     50:        FILETIME ftLastWriteTime;
                     51:        FILETIME ftLastAccessTime;
                     52:        BOOL bTimeStampValid = FALSE;
1.1.1.3   root       53:        
1.1.1.4   root       54:        if (!hiddenVol)
                     55:                size -= HEADER_SIZE;    
1.1       root       56: 
1.1.1.4   root       57:        num_sectors = size / SECTOR_SIZE;
1.1.1.3   root       58:        VirtualLock (header, sizeof (header));
1.1       root       59: 
1.1.1.3   root       60:        /* Copies any header structures into header, but does not do any
1.1       root       61:           disk io */
1.1.1.3   root       62:        nStatus = VolumeWriteHeader (header,
1.1       root       63:                                     cipher,
1.1.1.6 ! root       64:                                     password,
1.1       root       65:                                     pkcs5,
                     66:                                         0,
                     67:                                         0,
1.1.1.4   root       68:                                     &cryptoInfo,
1.1.1.6 ! root       69:                                         hiddenVol ? size : 0,
        !            70:                                         FALSE);
1.1       root       71: 
                     72:        if (nStatus != 0)
1.1.1.3   root       73:        {
                     74:                burn (header, sizeof (header));
                     75:                VirtualUnlock (header, sizeof (header));
1.1       root       76:                return nStatus;
1.1.1.3   root       77:        }
                     78: 
                     79:        write = (diskio_f) _lwrite;
                     80: 
1.1.1.6 ! root       81:        if (bDevice)
1.1.1.3   root       82:        {
                     83:                dev = CreateFile (lpszFilename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1.1.1.4   root       84:                if (dev == INVALID_HANDLE_VALUE)
                     85:                {
                     86:                        // Try opening device in shared mode
                     87:                        dev = CreateFile (lpszFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                     88:                        if (dev != INVALID_HANDLE_VALUE)
                     89:                        {
1.1.1.6 ! root       90:                                if (IDNO == MessageBoxW (hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
1.1.1.4   root       91:                                {
                     92:                                        CloseHandle (dev);
                     93:                                        dev = INVALID_HANDLE_VALUE;
                     94:                                }
                     95:                        }
                     96:                }
1.1.1.3   root       97:        }
                     98:        else
                     99:        {
1.1.1.4   root      100:                // We could support FILE_ATTRIBUTE_HIDDEN as an option
                    101:                // (Now if the container has hidden or system file attribute, the OS will not allow
                    102:                // overwritting it; so the user will have to delete it manually).
                    103:                dev = CreateFile (lpszFilename, GENERIC_WRITE,
                    104:                        hiddenVol ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
                    105:                        NULL, hiddenVol ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
1.1.1.6 ! root      106: 
        !           107:                if (!hiddenVol)
        !           108:                {
        !           109:                        // Preallocate file
        !           110:                        LARGE_INTEGER volumeSize;
        !           111:                        volumeSize.QuadPart = size;
        !           112: 
        !           113:                        if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
        !           114:                                || !SetEndOfFile (dev)
        !           115:                                || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
        !           116:                        {
        !           117:                                handleWin32Error (hwndDlg);
        !           118:                                nStatus = ERR_OS_ERROR; goto error;
        !           119:                        }
        !           120:                }
1.1.1.3   root      121:        }
                    122: 
                    123:        if (dev == INVALID_HANDLE_VALUE)
                    124:        {
1.1.1.6 ! root      125:                handleWin32Error (hwndDlg);
        !           126:                nStatus = ERR_OS_ERROR; 
        !           127:                goto error;
1.1.1.4   root      128:        }
                    129: 
1.1.1.6 ! root      130:        if (hiddenVol && !bDevice && bPreserveTimestamp)
1.1.1.4   root      131:        {
                    132:                /* Remember the container timestamp (used to reset file date and time of file-hosted
                    133:                containers to preserve plausible deniability of hidden volume)  */
                    134:                if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
                    135:                {
                    136:                        bTimeStampValid = FALSE;
1.1.1.6 ! root      137:                        MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.4   root      138:                }
                    139:                else
                    140:                        bTimeStampValid = TRUE;
1.1.1.3   root      141:        }
1.1       root      142: 
                    143:        KillTimer (hwndDlg, 0xff);
                    144: 
1.1.1.3   root      145:        InitProgressBar (num_sectors);
                    146:        dwThen = GetTickCount ();
1.1.1.2   root      147: 
1.1.1.4   root      148: 
1.1.1.6 ! root      149:        /* Volume header */
1.1.1.4   root      150: 
                    151:        // Hidden volume setup
                    152:        if (hiddenVol)
                    153:        {
                    154:                // Check hidden volume size
                    155:                if (hiddenVolHostSize < MIN_HIDDEN_VOLUME_HOST_SIZE || hiddenVolHostSize > MAX_HIDDEN_VOLUME_HOST_SIZE)
                    156:                {               
                    157:                        nStatus = ERR_VOL_SIZE_WRONG; goto error;
                    158:                }
                    159: 
                    160:                // Seek to hidden volume header location
                    161:                if (!SeekHiddenVolHeader ((HFILE) dev, hiddenVolHostSize, bDevice))
                    162:                {
                    163:                        nStatus = ERR_VOL_SEEKING; goto error;
                    164:                }
                    165: 
                    166:        }
                    167: 
                    168:        // Write the volume header
                    169:        if ((*write) ((HFILE) dev, header, HEADER_SIZE) == HFILE_ERROR)
                    170:                return ERR_OS_ERROR;
                    171: 
                    172: 
1.1.1.6 ! root      173:        /* Data area */
1.1.1.4   root      174: 
                    175:        startSector = 1;        // Data area of normal volume starts right after volume header
                    176: 
                    177:        if (hiddenVol)
                    178:        {
                    179:                // Calculate data area position of hidden volume
                    180:                unsigned __int64 startOffset = hiddenVolHostSize - size - HIDDEN_VOL_HEADER_OFFSET;
                    181: 
                    182:                // Validate the offset
                    183:                if (startOffset % SECTOR_SIZE != 0)
                    184:                {
1.1.1.6 ! root      185:                        nStatus = ERR_VOL_SIZE_WRONG; 
        !           186:                        goto error;
1.1.1.4   root      187:                }
                    188: 
                    189:                startSector = startOffset / SECTOR_SIZE;        
                    190:                quickFormat = TRUE;             // To entirely format a hidden volume would be redundant
                    191:        }
                    192: 
                    193:        // Format filesystem
                    194: 
1.1.1.3   root      195:        switch (fileSystem)
                    196:        {
                    197:        case FILESYS_NONE:
1.1.1.4   root      198:        case FILESYS_NTFS: // NTFS volume is just prepared for quick format performed by system
1.1.1.6 ! root      199:                nStatus = FormatNoFs (startSector, num_sectors, (HFILE) dev, cryptoInfo, write, quickFormat);
1.1.1.3   root      200:                break;
                    201: 
                    202:        case FILESYS_FAT:
1.1.1.4   root      203:                if (num_sectors > 0xFFFFffff)
                    204:                {
1.1.1.6 ! root      205:                        nStatus = ERR_VOL_SIZE_WRONG; 
        !           206:                        goto error;
1.1.1.4   root      207:                }
                    208: 
                    209:                // Calculate the fats, root dir etc
                    210:                ft.num_sectors = (unsigned int) (num_sectors);
                    211:                ft.cluster_size = clusterSize;
1.1.1.6 ! root      212:                memcpy (ft.volume_name, "NO NAME    ", 11);
1.1.1.4   root      213:                GetFatParams (&ft); 
                    214:                *realClusterSize = ft.cluster_size * SECTOR_SIZE;
                    215: 
1.1.1.6 ! root      216:                nStatus = FormatFat (startSector, &ft, (HFILE) dev, cryptoInfo, write, quickFormat);
1.1.1.3   root      217:                break;
                    218:        }
1.1       root      219: 
1.1.1.4   root      220: error:
                    221: 
1.1.1.3   root      222:        dwNow = GetTickCount ();
                    223: 
                    224:        burn (header, sizeof (header));
                    225:        VirtualUnlock (header, sizeof (header));
1.1       root      226: 
                    227:        crypto_close (cryptoInfo);
1.1.1.4   root      228: 
                    229:        if (bTimeStampValid)
                    230:        {
                    231:                // Restore the container timestamp (to preserve plausible deniability of the hidden volume) 
                    232:                if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.6 ! root      233:                        MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
        !           234:        }
        !           235: 
        !           236:        if (!bDevice && !hiddenVol && nStatus != 0)
        !           237:        {
        !           238:                // Remove preallocated part before closing file handle if format failed
        !           239:                if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
        !           240:                        SetEndOfFile (dev);
1.1.1.4   root      241:        }
                    242: 
1.1.1.3   root      243:        CloseHandle (dev);
1.1       root      244: 
1.1.1.3   root      245:        dwError = GetLastError();
1.1       root      246: 
1.1.1.6 ! root      247:        if (nStatus != 0)
1.1       root      248:                SetLastError(dwError);
1.1.1.3   root      249:        else
                    250:        {
                    251:                switch (fileSystem)
                    252:                {
                    253:                case FILESYS_NONE:
1.1.1.6 ! root      254:                        swprintf (summaryMsg
        !           255:                                , GetString ("FORMAT_STAT")
1.1.1.3   root      256:                                , num_sectors, num_sectors*512/1024/1024
1.1.1.6 ! root      257:                                , GetString ("NONE")
1.1.1.3   root      258:                                , (dwNow - dwThen)/1000);
                    259:                        break;
                    260: 
                    261:                case FILESYS_FAT:
1.1.1.6 ! root      262:                        swprintf (summaryMsg 
        !           263:                                , GetString ("FORMAT_STAT_FAT")
1.1.1.3   root      264:                                , ft.num_sectors, ((__int64) ft.num_sectors*512)/1024/1024, ft.size_fat
                    265:                                , (int) (512*ft.fats*ft.fat_length),
                    266:                                (int) (512*ft.cluster_size), ft.cluster_count,
                    267:                                (dwNow - dwThen)/1000);
                    268:                        break;
                    269: 
                    270:                case FILESYS_NTFS:
                    271:                        {
1.1.1.4   root      272:                                // NTFS format is performed by system so we first need to mount the volume
                    273:                                int driveNo = GetLastAvailableDrive ();
1.1.1.5   root      274:                                MountOptions mountOptions;
                    275:                                
1.1.1.3   root      276:                                if (driveNo == -1)
                    277:                                {
1.1.1.6 ! root      278:                                        MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
        !           279:                                        MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
        !           280: 
1.1.1.3   root      281:                                        return ERR_NO_FREE_DRIVES;
                    282:                                }
                    283: 
1.1.1.5   root      284:                                mountOptions.ReadOnly = FALSE;
                    285:                                mountOptions.Removable = FALSE;
1.1.1.6 ! root      286:                                mountOptions.ProtectHiddenVolume = FALSE;
        !           287:                                mountOptions.PreserveTimestamp = bPreserveTimestamp;
1.1.1.5   root      288: 
1.1.1.6 ! root      289:                                if (MountVolume (hwndDlg, driveNo, volumePath, password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
1.1.1.3   root      290:                                {
1.1.1.6 ! root      291:                                        MessageBoxW (hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
        !           292:                                        MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.3   root      293:                                        return ERR_VOL_MOUNT_FAILED;
                    294:                                }
                    295: 
1.1.1.4   root      296:                                // Quickformat volume as NTFS
1.1.1.3   root      297:                                if (!FormatNtfs (driveNo, clusterSize))
                    298:                                {
1.1.1.6 ! root      299:                                        MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_FAILED"), lpszTitle, MB_ICONERROR);
1.1.1.4   root      300:                                
                    301:                                        if (!UnmountVolume (hwndDlg, driveNo, FALSE))
1.1.1.6 ! root      302:                                                MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.4   root      303: 
1.1.1.3   root      304:                                        return ERR_VOL_FORMAT_BAD;
                    305:                                }
                    306: 
1.1.1.4   root      307:                                if (!UnmountVolume (hwndDlg, driveNo, FALSE))
1.1.1.6 ! root      308:                                        MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      309: 
                    310:                                dwNow = GetTickCount ();
                    311: 
1.1.1.6 ! root      312:                                swprintf (summaryMsg,
        !           313:                                        GetString ("FORMAT_STAT")
        !           314:                                        , num_sectors
        !           315:                                        , num_sectors*512/1024/1024
        !           316:                                        , L"NTFS"
1.1.1.3   root      317:                                        , (dwNow - dwThen)/1000);
                    318: 
                    319:                                break;
                    320:                        }
                    321:                }
                    322:        }
                    323: 
1.1       root      324:        return nStatus;
1.1.1.3   root      325: }
1.1       root      326: 
1.1.1.3   root      327: 
1.1.1.6 ! root      328: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, HFILE dev, PCRYPTO_INFO cryptoInfo, diskio_f write, BOOL quickFormat)
1.1.1.3   root      329: {
                    330:        int write_buf_cnt = 0;
                    331:        char sector[SECTOR_SIZE], *write_buf;
1.1.1.4   root      332:        unsigned __int64 nSecNo = startSector;
                    333:        LARGE_INTEGER startOffset;
                    334:        LARGE_INTEGER newOffset;
1.1.1.6 ! root      335:        int retVal;
1.1.1.4   root      336: 
                    337:        // Seek to start sector
                    338:        startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6 ! root      339:        if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
        !           340:                || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4   root      341:        {
                    342:                return ERR_VOL_SEEKING;
                    343:        }
1.1.1.3   root      344: 
                    345:        write_buf = TCalloc (WRITE_BUF_SIZE);
                    346:        memset (sector, 0, sizeof (sector));
                    347: 
1.1.1.4   root      348:        // Write sectors
1.1.1.3   root      349:        if(!quickFormat)
                    350:        {
1.1.1.4   root      351:                /* Generate a random key and IV to be used for "dummy" encryption that will fill the
                    352:                   free disk space (data area) with random data. That will reduce the amount of
                    353:                   predictable plaintext within the volume and also increase the level of plausible
                    354:                   deniability of hidden volumes. */
                    355:                char key[DISKKEY_SIZE];
                    356:                RandgetBytes (key, DISKKEY_SIZE, FALSE); 
                    357:                RandgetBytes (cryptoInfo->iv, sizeof cryptoInfo->iv, FALSE); 
1.1.1.6 ! root      358: 
        !           359:                retVal = EAInit (cryptoInfo->ea, key, cryptoInfo->ks);
        !           360:                if (retVal != 0)
        !           361:                        return retVal;
        !           362: 
1.1.1.4   root      363:                RandgetBytes (sector, 256, FALSE); 
                    364:                RandgetBytes (sector + 256, 256, FALSE); 
                    365: 
1.1.1.3   root      366:                while (num_sectors--)
                    367:                {
1.1.1.6 ! root      368:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
        !           369:                                cryptoInfo, write) == FALSE)
1.1.1.3   root      370:                                goto fail;
                    371:                }
                    372:                if (write_buf_cnt != 0 && (*write) (dev, write_buf, write_buf_cnt) == HFILE_ERROR)
                    373:                        goto fail;
                    374:        }
                    375:        else
                    376:                nSecNo = num_sectors;
                    377: 
                    378:        UpdateProgressBar (nSecNo);
                    379: 
                    380:        TCfree (write_buf);
                    381:        return 0;
                    382: 
                    383: fail:
                    384: 
                    385:        TCfree (write_buf);
                    386:        return ERR_OS_ERROR;
1.1       root      387: }
1.1.1.3   root      388: 
                    389: 
                    390: volatile BOOLEAN FormatExResult;
                    391: 
                    392: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
                    393: {
                    394:        if (command == FMIFS_DONE)
                    395:                FormatExResult = *(BOOLEAN *) parameter;
                    396:        return TRUE;
                    397: }
                    398: 
                    399: BOOL FormatNtfs (int driveNo, int clusterSize)
                    400: {
                    401:        WCHAR dir[8] = { driveNo + 'A', 0 };
                    402:        PFORMATEX FormatEx;
                    403:        HMODULE hModule = LoadLibrary ("fmifs.dll");
                    404: 
                    405:        if (hModule == NULL)
                    406:                return FALSE;
                    407: 
                    408:        if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
                    409:        {
                    410:                FreeLibrary (hModule);
                    411:                return FALSE;
                    412:        }
                    413: 
                    414:        wcscat (dir, L":\\");
                    415: 
                    416:        FormatExResult = FALSE;
                    417: 
                    418:        if (*(char *)dir > 'C' && *(char *)dir <= 'Z')
                    419:                FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * 512, FormatExCallback);
                    420: 
                    421:        FreeLibrary (hModule);
                    422:        return FormatExResult;
                    423: }
                    424: 
                    425: BOOL
                    426: WriteSector (HFILE dev, char *sector,
                    427:             char *write_buf, int *write_buf_cnt,
1.1.1.6 ! root      428:             __int64 *nSecNo, PCRYPTO_INFO cryptoInfo,
        !           429:             diskio_f write)
1.1.1.3   root      430: {
1.1.1.6 ! root      431:        static DWORD updateTime = 0;
1.1.1.4   root      432: 
1.1.1.6 ! root      433:        EncryptSectors ((unsigned __int32 *) sector,
1.1.1.4   root      434:                (*nSecNo)++, 1, cryptoInfo->ks, cryptoInfo->iv, cryptoInfo->ea);
                    435: 
1.1.1.3   root      436:        memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
                    437:        (*write_buf_cnt) += SECTOR_SIZE;
                    438: 
                    439:        if (*write_buf_cnt == WRITE_BUF_SIZE)
                    440:        {
                    441:                if ((*write) (dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR)
                    442:                        return FALSE;
                    443:                else
                    444:                        *write_buf_cnt = 0;
                    445:        }
1.1.1.6 ! root      446:        
        !           447:        if (GetTickCount () - updateTime > 25)
1.1.1.3   root      448:        {
1.1.1.6 ! root      449:                if (UpdateProgressBar (*nSecNo))
1.1.1.3   root      450:                        return FALSE;
1.1.1.6 ! root      451: 
        !           452:                updateTime = GetTickCount ();
1.1.1.3   root      453:        }
                    454: 
                    455:        return TRUE;
                    456: 
                    457: }

unix.superglobalmegacorp.com

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