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

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
1.1.1.5 ! root        3:    additions to that source code contained in this file are Copyright (c) 2004-2005
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.1.5 ! root       18: #include "common.h"
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;
1.1.1.5 ! root      247:                                MountOptions mountOptions;
        !           248:                                
1.1.1.3   root      249:                                if (driveNo == -1)
                    250:                                {
1.1.1.4   root      251:                                        MessageBox (hwndDlg, "No free drive letter available. NTFS formatting cannot continue.", lpszTitle, ICON_HAND);
1.1.1.3   root      252:                                        return ERR_NO_FREE_DRIVES;
                    253:                                }
                    254: 
1.1.1.5 ! root      255:                                mountOptions.ReadOnly = FALSE;
        !           256:                                mountOptions.Removable = FALSE;
        !           257: 
        !           258:                                if (MountVolume (hwndDlg, driveNo, volumePath, lpszPassword, FALSE, TRUE, &mountOptions, FALSE) < 1)
1.1.1.3   root      259:                                {
                    260:                                        MessageBox (hwndDlg, "Cannot mount volume. NTFS formatting cannot continue.", lpszTitle, ICON_HAND);
                    261:                                        return ERR_VOL_MOUNT_FAILED;
                    262:                                }
                    263: 
1.1.1.4   root      264:                                // Quickformat volume as NTFS
1.1.1.3   root      265:                                if (!FormatNtfs (driveNo, clusterSize))
                    266:                                {
1.1.1.4   root      267:                                        MessageBox (hwndDlg, "NTFS formatting failed.\nTry using FAT file system instead.", lpszTitle, MB_ICONERROR);
                    268:                                
                    269:                                        if (!UnmountVolume (hwndDlg, driveNo, FALSE))
                    270:                                                MessageBox (hwndDlg, "Volume dismount failed.", lpszTitle, MB_ICONERROR);
                    271: 
1.1.1.3   root      272:                                        return ERR_VOL_FORMAT_BAD;
                    273:                                }
                    274: 
1.1.1.4   root      275:                                if (!UnmountVolume (hwndDlg, driveNo, FALSE))
                    276:                                        MessageBox (hwndDlg, "Formatting succeeded but volume cannot be dismounted.", lpszTitle, MB_ICONEXCLAMATION);
1.1.1.3   root      277: 
                    278:                                dwNow = GetTickCount ();
                    279: 
                    280:                                sprintf (summaryMsg, "Volume size:\t\t%I64d sectors (%I64d MB)\nFile system:\t\tNTFS"
                    281:                                        "\n\nFormatting took %lu seconds."
                    282:                                        , num_sectors, num_sectors*512/1024/1024
                    283:                                        , (dwNow - dwThen)/1000);
                    284: 
                    285:                                break;
                    286:                        }
                    287:                }
                    288:        }
                    289: 
1.1       root      290:        return nStatus;
1.1.1.3   root      291: }
1.1       root      292: 
1.1.1.3   root      293: 
1.1.1.4   root      294: 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      295: {
                    296:        int write_buf_cnt = 0;
                    297:        char sector[SECTOR_SIZE], *write_buf;
                    298:        int progress = 0;
1.1.1.4   root      299:        unsigned __int64 nSecNo = startSector;
                    300:        LARGE_INTEGER startOffset;
                    301:        LARGE_INTEGER newOffset;
                    302: 
                    303:        // Seek to start sector
                    304:        startOffset.QuadPart = startSector * SECTOR_SIZE;
                    305:        if (SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN) == 0
                    306:                || newOffset.QuadPart != newOffset.QuadPart)
                    307:        {
                    308:                return ERR_VOL_SEEKING;
                    309:        }
1.1.1.3   root      310: 
                    311:        write_buf = TCalloc (WRITE_BUF_SIZE);
                    312:        memset (sector, 0, sizeof (sector));
                    313: 
1.1.1.4   root      314:        // Write sectors
1.1.1.3   root      315:        if(!quickFormat)
                    316:        {
1.1.1.4   root      317:                /* Generate a random key and IV to be used for "dummy" encryption that will fill the
                    318:                   free disk space (data area) with random data. That will reduce the amount of
                    319:                   predictable plaintext within the volume and also increase the level of plausible
                    320:                   deniability of hidden volumes. */
                    321:                char key[DISKKEY_SIZE];
                    322:                RandgetBytes (key, DISKKEY_SIZE, FALSE); 
                    323:                RandgetBytes (cryptoInfo->iv, sizeof cryptoInfo->iv, FALSE); 
                    324:                EAInit (cryptoInfo->ea, key, cryptoInfo->ks);
                    325:                RandgetBytes (sector, 256, FALSE); 
                    326:                RandgetBytes (sector + 256, 256, FALSE); 
                    327: 
1.1.1.3   root      328:                while (num_sectors--)
                    329:                {
                    330:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress,
                    331:                                cryptoInfo, nFrequency, write) == FALSE)
                    332:                                goto fail;
                    333:                }
                    334:                if (write_buf_cnt != 0 && (*write) (dev, write_buf, write_buf_cnt) == HFILE_ERROR)
                    335:                        goto fail;
                    336:        }
                    337:        else
                    338:                nSecNo = num_sectors;
                    339: 
                    340:        UpdateProgressBar (nSecNo);
                    341: 
                    342:        TCfree (write_buf);
                    343:        return 0;
                    344: 
                    345: fail:
                    346: 
                    347:        TCfree (write_buf);
                    348:        return ERR_OS_ERROR;
1.1       root      349: }
1.1.1.3   root      350: 
                    351: 
                    352: volatile BOOLEAN FormatExResult;
                    353: 
                    354: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
                    355: {
                    356:        if (command == FMIFS_DONE)
                    357:                FormatExResult = *(BOOLEAN *) parameter;
                    358:        return TRUE;
                    359: }
                    360: 
                    361: BOOL FormatNtfs (int driveNo, int clusterSize)
                    362: {
                    363:        WCHAR dir[8] = { driveNo + 'A', 0 };
                    364:        PFORMATEX FormatEx;
                    365:        HMODULE hModule = LoadLibrary ("fmifs.dll");
                    366: 
                    367:        if (hModule == NULL)
                    368:                return FALSE;
                    369: 
                    370:        if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
                    371:        {
                    372:                FreeLibrary (hModule);
                    373:                return FALSE;
                    374:        }
                    375: 
                    376:        wcscat (dir, L":\\");
                    377: 
                    378:        FormatExResult = FALSE;
                    379: 
                    380:        if (*(char *)dir > 'C' && *(char *)dir <= 'Z')
                    381:                FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * 512, FormatExCallback);
                    382: 
                    383:        FreeLibrary (hModule);
                    384:        return FormatExResult;
                    385: }
                    386: 
                    387: BOOL
                    388: WriteSector (HFILE dev, char *sector,
                    389:             char *write_buf, int *write_buf_cnt,
                    390:             __int64 *nSecNo, int *progress, PCRYPTO_INFO cryptoInfo,
                    391:             int nFrequency, diskio_f write)
                    392: {
1.1.1.4   root      393: 
                    394:        EncryptSectors ((unsigned long *) sector,
                    395:                (*nSecNo)++, 1, cryptoInfo->ks, cryptoInfo->iv, cryptoInfo->ea);
                    396: 
1.1.1.3   root      397:        memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
                    398:        (*write_buf_cnt) += SECTOR_SIZE;
                    399: 
                    400: 
                    401:        if (*write_buf_cnt == WRITE_BUF_SIZE)
                    402:        {
                    403:                if ((*write) (dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR)
                    404:                        return FALSE;
                    405:                else
                    406:                        *write_buf_cnt = 0;
                    407:        }
                    408: 
                    409:        if (++(*progress) == nFrequency)
                    410:        {
                    411:                if (UpdateProgressBar (*nSecNo) == TRUE)
                    412:                        return FALSE;
                    413:                *progress = 0;
                    414:        }
                    415: 
                    416:        return TRUE;
                    417: 
                    418: }

unix.superglobalmegacorp.com

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