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

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

unix.superglobalmegacorp.com

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