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

1.1.1.10  root        1: /*
                      2:  Legal Notice: The source code contained in this file has been derived from
                      3:  the source code of Encryption for the Masses 2.02a, which is Copyright (c)
                      4:  Paul Le Roux and which is covered by the 'License Agreement for Encryption
                      5:  for the Masses'. Modifications and additions to that source code contained
                      6:  in this file are Copyright (c) TrueCrypt Foundation and are covered by the
1.1.1.11! root        7:  TrueCrypt License 2.3 the full text of which is contained in the file
1.1.1.10  root        8:  License.txt included in TrueCrypt binary and source code distribution
                      9:  packages. */
                     10: 
                     11: #include <stdlib.h>
                     12: #include <string.h>
1.1.1.6   root       13: 
                     14: #include "Tcdefs.h"
                     15: 
1.1.1.9   root       16: #include "Common.h"
1.1.1.6   root       17: #include "Crypto.h"
                     18: #include "Fat.h"
                     19: #include "Format.h"
1.1.1.9   root       20: #include "Random.h"
1.1.1.6   root       21: #include "Volumes.h"
1.1.1.8   root       22: 
                     23: #ifdef _WIN32
1.1.1.6   root       24: #include "Apidrvr.h"
                     25: #include "Dlgcode.h"
                     26: #include "Language.h"
1.1.1.8   root       27: #include "Progress.h"
1.1.1.6   root       28: #include "Resource.h"
1.1.1.10  root       29: #include "../Format/FormatCom.h"
1.1.1.3   root       30: 
1.1       root       31: int
1.1.1.10  root       32: FormatVolume (char *volumePath,
1.1       root       33:              BOOL bDevice,
                     34:              unsigned __int64 size,
1.1.1.4   root       35:                  unsigned __int64 hiddenVolHostSize,
1.1.1.6   root       36:              Password *password,
1.1.1.7   root       37:              int ea,
1.1       root       38:              int pkcs5,
                     39:                  BOOL quickFormat,
1.1.1.8   root       40:                  BOOL sparseFileSwitch,
1.1.1.3   root       41:                  int fileSystem,
                     42:                  int clusterSize,
1.1.1.4   root       43:              HWND hwndDlg,
                     44:                  BOOL hiddenVol,
1.1.1.10  root       45:                  int *realClusterSize,
                     46:                  BOOL uac)
1.1       root       47: {
                     48:        int nStatus;
                     49:        PCRYPTO_INFO cryptoInfo;
1.1.1.4   root       50:        HANDLE dev = INVALID_HANDLE_VALUE;
1.1.1.10  root       51:        DWORD dwError;
                     52:        char header[HEADER_SIZE];
1.1.1.4   root       53:        unsigned __int64 num_sectors, startSector;
1.1.1.3   root       54:        fatparams ft;
1.1.1.4   root       55:        FILETIME ftCreationTime;
                     56:        FILETIME ftLastWriteTime;
                     57:        FILETIME ftLastAccessTime;
                     58:        BOOL bTimeStampValid = FALSE;
1.1.1.10  root       59:        char dosDev[TC_MAX_PATH] = { 0 };
                     60:        char devName[MAX_PATH] = { 0 };
                     61:        int driveLetter = -1;
                     62:        WCHAR deviceName[MAX_PATH];
                     63: 
1.1.1.4   root       64:        if (!hiddenVol)
                     65:                size -= HEADER_SIZE;    
1.1       root       66: 
1.1.1.4   root       67:        num_sectors = size / SECTOR_SIZE;
1.1.1.10  root       68: 
                     69:        if (bDevice)
                     70:        {
                     71:                strcpy ((char *)deviceName, volumePath);
                     72:                ToUNICODE ((char *)deviceName);
                     73: 
                     74:                driveLetter = GetDiskDeviceDriveLetter (deviceName);
                     75:        }
                     76: 
1.1.1.3   root       77:        VirtualLock (header, sizeof (header));
1.1       root       78: 
1.1.1.3   root       79:        /* Copies any header structures into header, but does not do any
1.1       root       80:           disk io */
1.1.1.3   root       81:        nStatus = VolumeWriteHeader (header,
1.1.1.7   root       82:                                     ea,
                     83:                                         LRW, // The only supported mode of operation when creating new volumes
1.1.1.6   root       84:                                     password,
1.1       root       85:                                     pkcs5,
                     86:                                         0,
                     87:                                         0,
1.1.1.4   root       88:                                     &cryptoInfo,
1.1.1.6   root       89:                                         hiddenVol ? size : 0,
                     90:                                         FALSE);
1.1       root       91: 
                     92:        if (nStatus != 0)
1.1.1.3   root       93:        {
                     94:                burn (header, sizeof (header));
                     95:                VirtualUnlock (header, sizeof (header));
1.1       root       96:                return nStatus;
1.1.1.3   root       97:        }
                     98: 
1.1.1.6   root       99:        if (bDevice)
1.1.1.3   root      100:        {
1.1.1.10  root      101:                /* Device-hosted volume */
1.1.1.11! root      102:                DWORD dwResult;
1.1.1.10  root      103:                int nPass;
                    104: 
                    105:                if (FakeDosNameForDevice (volumePath, dosDev, devName, FALSE) != 0)
1.1.1.4   root      106:                {
1.1.1.10  root      107:                        handleWin32Error (hwndDlg);
                    108:                        return ERR_DONT_REPORT;
                    109:                }
                    110: 
                    111:                if (IsDeviceMounted (devName))
                    112:                {
                    113:                        if ((dev = DismountDrive (devName)) == INVALID_HANDLE_VALUE)
1.1.1.4   root      114:                        {
1.1.1.11! root      115:                                Error ("FORMAT_CANT_DISMOUNT_FILESYS");
        !           116:                                nStatus = ERR_DONT_REPORT; 
        !           117:                                goto error;
1.1.1.10  root      118:                        }
                    119:                }
                    120:                else if (nCurrentOS == WIN_VISTA_OR_LATER && driveLetter == -1)
                    121:                {
                    122:                        // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition 
                    123:                        // to which no drive letter has been assigned under the system. This problem can be worked
                    124:                        // around by assigning a drive letter to the partition temporarily.
                    125: 
                    126:                        char szDriveLetter[] = { 'A', ':', 0 };
                    127:                        char rootPath[] = { 'A', ':', '\\', 0 };
                    128:                        char uniqVolName[MAX_PATH+1] = { 0 };
                    129:                        int tmpDriveLetter = -1;
                    130:                        BOOL bResult = FALSE;
                    131: 
                    132:                        tmpDriveLetter = GetFirstAvailableDrive ();
                    133:  
                    134:                        if (tmpDriveLetter != -1)
                    135:                        {
                    136:                                rootPath[0] += tmpDriveLetter;
                    137:                                szDriveLetter[0] += tmpDriveLetter;
                    138: 
                    139:                                if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volumePath))
                    140:                                {
                    141:                                        bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
                    142: 
                    143:                                        DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
                    144:                                                szDriveLetter,
                    145:                                                volumePath);
                    146: 
                    147:                                        if (bResult 
                    148:                                                && SetVolumeMountPoint (rootPath, uniqVolName))
                    149:                                        {
                    150:                                                // The drive letter can be removed immediately
                    151:                                                DeleteVolumeMountPoint (rootPath);
                    152:                                        }
                    153:                                }
                    154:                        }
                    155:                }
                    156: 
                    157:                // Perform open - 'quick format' - close - open to prevent Windows from restoring NTFS boot sector backup
                    158:                for (nPass = 0; nPass < 2; nPass++)
                    159:                {
                    160:                        // Try exclusive access mode first
                    161:                        if (dev == INVALID_HANDLE_VALUE)
                    162:                                dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
                    163: 
                    164:                        if (dev == INVALID_HANDLE_VALUE)
                    165:                        {
                    166:                                // Retry in shared mode
                    167:                                dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                    168:                                if (dev != INVALID_HANDLE_VALUE)
                    169:                                {
                    170:                                        if (IDNO == MessageBoxW (hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
                    171:                                        {
                    172:                                                nStatus = ERR_DONT_REPORT; 
                    173:                                                goto error;
                    174:                                        }
                    175:                                }
                    176:                                else
                    177:                                {
                    178:                                        handleWin32Error (hwndDlg);
                    179:                                        nStatus = ERR_DONT_REPORT; 
                    180:                                        goto error;
                    181:                                }
                    182:                        }
                    183: 
                    184:                        if (hiddenVol)
                    185:                                break;  // The following "quick format" operation would damage the outer volume
                    186: 
                    187:                        if (nPass == 0)
                    188:                        {
                    189:                                char buf[65536];
                    190:                                DWORD bw;
                    191: 
                    192:                                // Pseudo "quick format" to prevent Windows from restoring NTFS boot sector backup
                    193:                                memset (buf, 0, sizeof (buf));
                    194:                                WriteFile (dev, buf, sizeof (buf), &bw, NULL);
                    195:                                FlushFileBuffers (dev);
                    196:                                CloseHandle (dev);
                    197:                                dev = INVALID_HANDLE_VALUE;
1.1.1.4   root      198:                        }
                    199:                }
1.1.1.11! root      200: 
        !           201:                if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
        !           202:                {
        !           203:                        Error ("FORMAT_CANT_DISMOUNT_FILESYS");
        !           204:                        nStatus = ERR_DONT_REPORT; 
        !           205:                        goto error;
        !           206:                }
1.1.1.3   root      207:        }
                    208:        else
                    209:        {
1.1.1.10  root      210:                /* File-hosted volume */
                    211: 
1.1.1.4   root      212:                // We could support FILE_ATTRIBUTE_HIDDEN as an option
                    213:                // (Now if the container has hidden or system file attribute, the OS will not allow
                    214:                // overwritting it; so the user will have to delete it manually).
1.1.1.10  root      215:                dev = CreateFile (volumePath, GENERIC_WRITE,
1.1.1.4   root      216:                        hiddenVol ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
                    217:                        NULL, hiddenVol ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
1.1.1.6   root      218: 
1.1.1.8   root      219:                if (dev == INVALID_HANDLE_VALUE)
                    220:                {
                    221:                        handleWin32Error (hwndDlg);
1.1.1.10  root      222:                        nStatus = ERR_DONT_REPORT; 
1.1.1.8   root      223:                        goto error;
                    224:                }
                    225: 
1.1.1.6   root      226:                if (!hiddenVol)
                    227:                {
                    228:                        LARGE_INTEGER volumeSize;
1.1.1.8   root      229:                        volumeSize.QuadPart = size + HEADER_SIZE;
1.1.1.6   root      230: 
1.1.1.8   root      231:                        if (sparseFileSwitch && quickFormat)
                    232:                        {
                    233:                                // Create as sparse file container
                    234:                                DWORD tmp;
                    235:                                if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
                    236:                                {
                    237:                                        handleWin32Error (hwndDlg);
1.1.1.10  root      238:                                        nStatus = ERR_DONT_REPORT; 
1.1.1.8   root      239:                                        goto error;
                    240:                                }
                    241:                        }
                    242: 
                    243:                        // Preallocate the file
1.1.1.6   root      244:                        if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
                    245:                                || !SetEndOfFile (dev)
                    246:                                || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
                    247:                        {
                    248:                                handleWin32Error (hwndDlg);
1.1.1.10  root      249:                                nStatus = ERR_DONT_REPORT;
1.1.1.7   root      250:                                goto error;
1.1.1.6   root      251:                        }
                    252:                }
1.1.1.3   root      253:        }
                    254: 
1.1.1.6   root      255:        if (hiddenVol && !bDevice && bPreserveTimestamp)
1.1.1.4   root      256:        {
                    257:                /* Remember the container timestamp (used to reset file date and time of file-hosted
                    258:                containers to preserve plausible deniability of hidden volume)  */
                    259:                if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
                    260:                {
                    261:                        bTimeStampValid = FALSE;
1.1.1.6   root      262:                        MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.4   root      263:                }
                    264:                else
                    265:                        bTimeStampValid = TRUE;
1.1.1.3   root      266:        }
1.1       root      267: 
                    268:        KillTimer (hwndDlg, 0xff);
                    269: 
1.1.1.6   root      270:        /* Volume header */
1.1.1.4   root      271: 
                    272:        // Hidden volume setup
                    273:        if (hiddenVol)
                    274:        {
                    275:                // Check hidden volume size
                    276:                if (hiddenVolHostSize < MIN_HIDDEN_VOLUME_HOST_SIZE || hiddenVolHostSize > MAX_HIDDEN_VOLUME_HOST_SIZE)
                    277:                {               
1.1.1.7   root      278:                        nStatus = ERR_VOL_SIZE_WRONG;
                    279:                        goto error;
1.1.1.4   root      280:                }
                    281: 
                    282:                // Seek to hidden volume header location
                    283:                if (!SeekHiddenVolHeader ((HFILE) dev, hiddenVolHostSize, bDevice))
                    284:                {
1.1.1.7   root      285:                        nStatus = ERR_VOL_SEEKING;
                    286:                        goto error;
1.1.1.4   root      287:                }
                    288: 
                    289:        }
                    290: 
                    291:        // Write the volume header
1.1.1.8   root      292:        if (_lwrite ((HFILE) dev, header, HEADER_SIZE) == HFILE_ERROR)
1.1.1.10  root      293:        {
                    294:                handleWin32Error (hwndDlg);
                    295:                nStatus = ERR_DONT_REPORT;
                    296:                goto error;
                    297:        }
1.1.1.4   root      298: 
1.1.1.6   root      299:        /* Data area */
1.1.1.4   root      300: 
1.1.1.10  root      301:        startSector = HEADER_SIZE / SECTOR_SIZE;        // Data area of normal volume starts right after volume header
1.1.1.4   root      302: 
                    303:        if (hiddenVol)
                    304:        {
                    305:                // Calculate data area position of hidden volume
                    306:                unsigned __int64 startOffset = hiddenVolHostSize - size - HIDDEN_VOL_HEADER_OFFSET;
1.1.1.7   root      307:                cryptoInfo->hiddenVolumeOffset = startOffset;
1.1.1.4   root      308: 
                    309:                // Validate the offset
                    310:                if (startOffset % SECTOR_SIZE != 0)
                    311:                {
1.1.1.6   root      312:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    313:                        goto error;
1.1.1.4   root      314:                }
                    315: 
                    316:                startSector = startOffset / SECTOR_SIZE;        
                    317:                quickFormat = TRUE;             // To entirely format a hidden volume would be redundant
                    318:        }
                    319: 
                    320:        // Format filesystem
                    321: 
1.1.1.3   root      322:        switch (fileSystem)
                    323:        {
                    324:        case FILESYS_NONE:
1.1.1.10  root      325:        case FILESYS_NTFS:
1.1.1.8   root      326:                nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, quickFormat);
1.1.1.3   root      327:                break;
1.1.1.10  root      328:                
1.1.1.3   root      329:        case FILESYS_FAT:
1.1.1.4   root      330:                if (num_sectors > 0xFFFFffff)
                    331:                {
1.1.1.6   root      332:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    333:                        goto error;
1.1.1.4   root      334:                }
                    335: 
                    336:                // Calculate the fats, root dir etc
                    337:                ft.num_sectors = (unsigned int) (num_sectors);
                    338:                ft.cluster_size = clusterSize;
1.1.1.6   root      339:                memcpy (ft.volume_name, "NO NAME    ", 11);
1.1.1.4   root      340:                GetFatParams (&ft); 
                    341:                *realClusterSize = ft.cluster_size * SECTOR_SIZE;
                    342: 
1.1.1.8   root      343:                nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, quickFormat);
1.1.1.3   root      344:                break;
                    345:        }
1.1       root      346: 
1.1.1.10  root      347: error:
                    348:        dwError = GetLastError();
1.1.1.3   root      349: 
                    350:        burn (header, sizeof (header));
                    351:        VirtualUnlock (header, sizeof (header));
1.1       root      352: 
                    353:        crypto_close (cryptoInfo);
1.1.1.4   root      354: 
1.1.1.11! root      355:        if (dev != INVALID_HANDLE_VALUE)
1.1.1.4   root      356:        {
1.1.1.11! root      357:                if (!bDevice && !hiddenVol && nStatus != 0)
        !           358:                {
        !           359:                        // Remove preallocated part before closing file handle if format failed
        !           360:                        if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
        !           361:                                SetEndOfFile (dev);
        !           362:                }
1.1.1.6   root      363: 
1.1.1.11! root      364:                FlushFileBuffers (dev);
1.1.1.4   root      365: 
1.1.1.11! root      366:                if (bTimeStampValid)
        !           367:                {
        !           368:                        // Restore the container timestamp (to preserve plausible deniability of the hidden volume) 
        !           369:                        if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
        !           370:                                MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
        !           371:                }
        !           372: 
        !           373:                CloseHandle (dev);
        !           374:                dev = INVALID_HANDLE_VALUE;
        !           375:        }
1.1       root      376: 
1.1.1.10  root      377:        if (dosDev[0])
                    378:                RemoveFakeDosName (volumePath, dosDev);
1.1       root      379: 
1.1.1.6   root      380:        if (nStatus != 0)
1.1.1.3   root      381:        {
1.1.1.10  root      382:                SetLastError(dwError);
                    383:                return nStatus;
                    384:        }
1.1.1.6   root      385: 
1.1.1.10  root      386:        if (fileSystem == FILESYS_NTFS)
                    387:        {
                    388:                // Quick-format volume as NTFS
                    389:                int driveNo = GetLastAvailableDrive ();
                    390:                MountOptions mountOptions;
                    391:                int retCode;
1.1.1.3   root      392: 
1.1.1.10  root      393:                ZeroMemory (&mountOptions, sizeof (mountOptions));
1.1.1.5   root      394: 
1.1.1.10  root      395:                if (driveNo == -1)
                    396:                {
                    397:                        MessageBoxW (hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
                    398:                        MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.3   root      399: 
1.1.1.10  root      400:                        return ERR_NO_FREE_DRIVES;
                    401:                }
1.1.1.4   root      402: 
1.1.1.10  root      403:                mountOptions.ReadOnly = FALSE;
                    404:                mountOptions.Removable = FALSE;
                    405:                mountOptions.ProtectHiddenVolume = FALSE;
                    406:                mountOptions.PreserveTimestamp = bPreserveTimestamp;
1.1.1.3   root      407: 
1.1.1.10  root      408:                if (MountVolume (hwndDlg, driveNo, volumePath, password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
                    409:                {
                    410:                        MessageBoxW (hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
                    411:                        MessageBoxW (hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
                    412:                        return ERR_VOL_MOUNT_FAILED;
                    413:                }
1.1.1.3   root      414: 
1.1.1.10  root      415:                if (!IsAdmin () && IsUacSupported ())
                    416:                        retCode = UacFormatNtfs (hwndDlg, driveNo, clusterSize);
                    417:                else
                    418:                        retCode = FormatNtfs (driveNo, clusterSize);
1.1.1.3   root      419: 
1.1.1.10  root      420:                if (retCode != TRUE)
                    421:                {
                    422:                        if (!UnmountVolume (hwndDlg, driveNo, FALSE))
                    423:                                MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      424: 
1.1.1.10  root      425:                        Error ("FORMAT_NTFS_FAILED");
                    426:                        return ERR_DONT_REPORT;
1.1.1.3   root      427:                }
1.1.1.10  root      428: 
                    429:                if (!UnmountVolume (hwndDlg, driveNo, FALSE))
                    430:                        MessageBoxW (hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      431:        }
                    432: 
1.1       root      433:        return nStatus;
1.1.1.3   root      434: }
1.1       root      435: 
1.1.1.8   root      436: #endif
1.1.1.3   root      437: 
1.1.1.8   root      438: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1.1.3   root      439: {
                    440:        int write_buf_cnt = 0;
                    441:        char sector[SECTOR_SIZE], *write_buf;
1.1.1.4   root      442:        unsigned __int64 nSecNo = startSector;
1.1.1.6   root      443:        int retVal;
1.1.1.7   root      444:        char temporaryKey[DISKKEY_SIZE];
1.1.1.4   root      445: 
1.1.1.8   root      446: #ifdef _WIN32
                    447:        LARGE_INTEGER startOffset;
                    448:        LARGE_INTEGER newOffset;
                    449: 
1.1.1.4   root      450:        // Seek to start sector
                    451:        startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6   root      452:        if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
                    453:                || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4   root      454:        {
                    455:                return ERR_VOL_SEEKING;
                    456:        }
1.1.1.8   root      457: #endif
1.1.1.3   root      458: 
1.1.1.8   root      459:        write_buf = (char *) TCalloc (WRITE_BUF_SIZE);
1.1.1.3   root      460:        memset (sector, 0, sizeof (sector));
                    461: 
1.1.1.7   root      462:        /* Fill the rest of the data area with random data */
                    463: 
1.1.1.3   root      464:        if(!quickFormat)
                    465:        {
1.1.1.7   root      466:                /* Generate a random temporary key set to be used for "dummy" encryption that will fill
                    467:                the free disk space (data area) with random data.  This is necessary for plausible
                    468:                deniability of hidden volumes (and also reduces the amount of predictable plaintext
                    469:                within the volume). */
1.1.1.6   root      470: 
1.1.1.9   root      471:                // Temporary master key
                    472:                if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
                    473:                        goto fail;
                    474:                // Secondary key (LRW mode)
                    475:                if (!RandgetBytes (cryptoInfo->iv, sizeof cryptoInfo->iv, FALSE))
                    476:                        goto fail;
1.1.1.7   root      477: 
                    478:                retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.6   root      479:                if (retVal != 0)
1.1.1.7   root      480:                {
                    481:                        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.6   root      482:                        return retVal;
1.1.1.7   root      483:                }
                    484:                if (!EAInitMode (cryptoInfo))
                    485:                {
                    486:                        burn (temporaryKey, sizeof(temporaryKey));
                    487:                        return ERR_MODE_INIT_FAILED;
                    488:                }
1.1.1.4   root      489: 
1.1.1.3   root      490:                while (num_sectors--)
                    491:                {
1.1.1.7   root      492:                        /* Generate random plaintext. Note that reused plaintext blocks are not a concern
                    493:                        here since LRW mode is designed to hide patterns. Furthermore, patterns in plaintext
                    494:                        do occur commonly on media in the "real world", so it might actually be a fatal
                    495:                        mistake to try to avoid them completely. */
1.1.1.9   root      496: 
                    497: #if RNG_POOL_SIZE > SECTOR_SIZE
                    498: #error RNG_POOL_SIZE > SECTOR_SIZE
1.1.1.7   root      499: #endif
                    500: 
1.1.1.9   root      501: #ifdef _WIN32
                    502:                        if (!RandpeekBytes (sector, RNG_POOL_SIZE)
                    503:                                || !RandpeekBytes (sector + RNG_POOL_SIZE, SECTOR_SIZE - RNG_POOL_SIZE))
                    504:                                goto fail;
                    505: #else
                    506:                        if ((nSecNo & 0x3fff) == 0)
                    507:                        {
                    508:                                if (!RandgetBytes (sector, RNG_POOL_SIZE, FALSE)
                    509:                                        || !RandgetBytes (sector + RNG_POOL_SIZE, SECTOR_SIZE - RNG_POOL_SIZE, FALSE))
                    510:                                        goto fail;
                    511:                        }
                    512: #endif
1.1.1.7   root      513:                        // Encrypt the random plaintext and write it to the disk
1.1.1.6   root      514:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      515:                                cryptoInfo) == FALSE)
1.1.1.3   root      516:                                goto fail;
                    517:                }
1.1.1.8   root      518:                if (write_buf_cnt != 0 && 
                    519: #ifdef _WIN32
                    520:                        _lwrite ((HFILE)dev, write_buf, write_buf_cnt) == HFILE_ERROR)
                    521: #else
                    522:                        fwrite (write_buf, 1, write_buf_cnt, (FILE *)dev) != (size_t)write_buf_cnt)
                    523: #endif
1.1.1.3   root      524:                        goto fail;
                    525:        }
                    526:        else
                    527:                nSecNo = num_sectors;
                    528: 
                    529:        UpdateProgressBar (nSecNo);
                    530: 
                    531:        TCfree (write_buf);
1.1.1.7   root      532:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.3   root      533:        return 0;
                    534: 
                    535: fail:
                    536: 
                    537:        TCfree (write_buf);
1.1.1.7   root      538:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.3   root      539:        return ERR_OS_ERROR;
1.1       root      540: }
1.1.1.3   root      541: 
1.1.1.8   root      542: #ifdef _WIN32
1.1.1.3   root      543: 
                    544: volatile BOOLEAN FormatExResult;
                    545: 
                    546: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
                    547: {
                    548:        if (command == FMIFS_DONE)
                    549:                FormatExResult = *(BOOLEAN *) parameter;
                    550:        return TRUE;
                    551: }
                    552: 
                    553: BOOL FormatNtfs (int driveNo, int clusterSize)
                    554: {
                    555:        WCHAR dir[8] = { driveNo + 'A', 0 };
                    556:        PFORMATEX FormatEx;
                    557:        HMODULE hModule = LoadLibrary ("fmifs.dll");
1.1.1.10  root      558:        int i;
1.1.1.3   root      559: 
                    560:        if (hModule == NULL)
                    561:                return FALSE;
                    562: 
                    563:        if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
                    564:        {
                    565:                FreeLibrary (hModule);
                    566:                return FALSE;
                    567:        }
                    568: 
                    569:        wcscat (dir, L":\\");
                    570: 
                    571:        FormatExResult = FALSE;
                    572: 
1.1.1.10  root      573:        // Windows sometimes fail to format a volume (hosted on a removable medium) as NTFS.
                    574:        // It often helps to retry several times.
                    575:        for (i = 0; i < 10 && FormatExResult != TRUE; i++)
                    576:        {
1.1.1.11! root      577:                FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
1.1.1.10  root      578:        }
1.1.1.3   root      579: 
                    580:        FreeLibrary (hModule);
                    581:        return FormatExResult;
                    582: }
                    583: 
1.1.1.8   root      584: #endif
                    585: 
1.1.1.3   root      586: BOOL
1.1.1.8   root      587: WriteSector (void *dev, char *sector,
1.1.1.3   root      588:             char *write_buf, int *write_buf_cnt,
1.1.1.8   root      589:             __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
1.1.1.3   root      590: {
1.1.1.8   root      591:        static __int32 updateTime = 0;
1.1.1.4   root      592: 
1.1.1.6   root      593:        EncryptSectors ((unsigned __int32 *) sector,
1.1.1.7   root      594:                (*nSecNo)++, 1, cryptoInfo);
1.1.1.4   root      595: 
1.1.1.3   root      596:        memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
                    597:        (*write_buf_cnt) += SECTOR_SIZE;
                    598: 
                    599:        if (*write_buf_cnt == WRITE_BUF_SIZE)
                    600:        {
1.1.1.8   root      601:                if (
                    602: #ifdef _WIN32
                    603:                        _lwrite ((HFILE)dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR)
                    604: #else
                    605:                        fwrite (write_buf, 1, WRITE_BUF_SIZE, (FILE *)dev) != WRITE_BUF_SIZE)
                    606: #endif
1.1.1.3   root      607:                        return FALSE;
                    608:                else
                    609:                        *write_buf_cnt = 0;
                    610:        }
1.1.1.6   root      611:        
1.1.1.8   root      612: #ifdef _WIN32
1.1.1.6   root      613:        if (GetTickCount () - updateTime > 25)
1.1.1.3   root      614:        {
1.1.1.6   root      615:                if (UpdateProgressBar (*nSecNo))
1.1.1.3   root      616:                        return FALSE;
1.1.1.6   root      617: 
                    618:                updateTime = GetTickCount ();
1.1.1.3   root      619:        }
1.1.1.8   root      620: #else
                    621:        UpdateProgressBar (*nSecNo);
                    622: #endif
1.1.1.3   root      623: 
                    624:        return TRUE;
                    625: 
                    626: }

unix.superglobalmegacorp.com

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