Annotation of truecrypt/common/fat.c, revision 1.1.1.19

1.1.1.10  root        1: /*
1.1.1.12  root        2:  Legal Notice: Some portions of the source code contained in this file were
                      3:  derived from the source code of Encryption for the Masses 2.02a, which is
                      4:  Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
                      5:  Agreement for Encryption for the Masses'. Modifications and additions to
1.1.1.18  root        6:  the original source code (contained in this file) and all other portions
1.1.1.19! root        7:  of this file are Copyright (c) 2003-2010 TrueCrypt Developers Association
        !             8:  and are governed by the TrueCrypt License 3.0 the full text of which is
1.1.1.18  root        9:  contained in the file License.txt included in TrueCrypt binary and source
                     10:  code distribution packages. */
1.1.1.10  root       11: 
                     12: #include <stdlib.h>
                     13: #include <string.h>
                     14: #include <time.h>
1.1.1.6   root       15: 
                     16: #include "Tcdefs.h"
                     17: 
                     18: #include "Crypto.h"
1.1.1.10  root       19: #include "Common/Endian.h"
1.1.1.6   root       20: #include "Format.h"
                     21: #include "Fat.h"
                     22: #include "Progress.h"
1.1.1.8   root       23: #include "Random.h"
1.1.1.19! root       24: #include "Volumes.h"
1.1       root       25: 
                     26: void
                     27: GetFatParams (fatparams * ft)
                     28: {
1.1.1.19! root       29:        uint64 volumeSize = (uint64) ft->num_sectors * ft->sector_size;
1.1.1.10  root       30:        unsigned int fatsecs;
1.1.1.19! root       31: 
1.1.1.5   root       32:        if(ft->cluster_size == 0)       // 'Default' cluster size
1.1       root       33:        {
1.1.1.19! root       34:                uint32 clusterSize;
        !            35: 
        !            36:                // Determine optimal cluster size to minimize FAT size (mounting delay), maximize number of files, keep 4 KB alignment, etc.
        !            37:                if (volumeSize >= 2 * BYTES_PER_TB)
        !            38:                        clusterSize = 256 * BYTES_PER_KB;
        !            39:                else if (volumeSize >= 512 * BYTES_PER_GB)
        !            40:                        clusterSize = 128 * BYTES_PER_KB;
        !            41:                else if (volumeSize >= 128 * BYTES_PER_GB)
        !            42:                        clusterSize = 64 * BYTES_PER_KB;
        !            43:                else if (volumeSize >= 64 * BYTES_PER_GB)
        !            44:                        clusterSize = 32 * BYTES_PER_KB;
        !            45:                else if (volumeSize >= 32 * BYTES_PER_GB)
        !            46:                        clusterSize = 16 * BYTES_PER_KB;
        !            47:                else if (volumeSize >= 16 * BYTES_PER_GB)
        !            48:                        clusterSize = 8 * BYTES_PER_KB;
        !            49:                else if (volumeSize >= 512 * BYTES_PER_MB)
        !            50:                        clusterSize = 4 * BYTES_PER_KB;
        !            51:                else if (volumeSize >= 256 * BYTES_PER_MB)
        !            52:                        clusterSize = 2 * BYTES_PER_KB;
        !            53:                else if (volumeSize >= 1 * BYTES_PER_MB)
        !            54:                        clusterSize = 1 * BYTES_PER_KB;
1.1       root       55:                else
1.1.1.19! root       56:                        clusterSize = 512;
        !            57: 
        !            58:                ft->cluster_size = clusterSize / ft->sector_size;
        !            59:                
        !            60:                if (ft->cluster_size == 0)
1.1       root       61:                        ft->cluster_size = 1;
1.1.1.19! root       62: 
        !            63:                if (ft->cluster_size * ft->sector_size > TC_MAX_FAT_CLUSTER_SIZE)
        !            64:                        ft->cluster_size = TC_MAX_FAT_CLUSTER_SIZE / ft->sector_size;
        !            65: 
        !            66:                if (ft->cluster_size > 128)
        !            67:                        ft->cluster_size = 128;
1.1       root       68:        }
                     69: 
1.1.1.19! root       70:        if (volumeSize <= TC_MAX_FAT_CLUSTER_SIZE * 4)
        !            71:                ft->cluster_size = 1;
        !            72: 
1.1       root       73:        // Geometry always set to SECTORS/1/1
                     74:        ft->secs_track = 1; 
                     75:        ft->heads = 1; 
                     76: 
                     77:        ft->dir_entries = 512;
                     78:        ft->fats = 2;
                     79:        ft->media = 0xf8;
1.1.1.11  root       80:        ft->hidden = 0;
1.1       root       81: 
                     82:        ft->size_root_dir = ft->dir_entries * 32;
                     83: 
1.1.1.6   root       84:        // FAT12
1.1       root       85:        ft->size_fat = 12;
1.1.1.6   root       86:        ft->reserved = 2;
1.1.1.19! root       87:        fatsecs = ft->num_sectors - (ft->size_root_dir + ft->sector_size - 1) / ft->sector_size - ft->reserved;
        !            88:        ft->cluster_count = (int) (((__int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size + 3));
        !            89:        ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + ft->sector_size - 1) / ft->sector_size;
1.1       root       90: 
1.1.1.6   root       91:        if (ft->cluster_count >= 4085) // FAT16
1.1       root       92:        {
                     93:                ft->size_fat = 16;
1.1.1.11  root       94:                ft->reserved = 2;
1.1.1.19! root       95:                fatsecs = ft->num_sectors - (ft->size_root_dir + ft->sector_size - 1) / ft->sector_size - ft->reserved;
        !            96:                ft->cluster_count = (int) (((__int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size + 4));
        !            97:                ft->fat_length = (ft->cluster_count * 2 + ft->sector_size - 1) / ft->sector_size;
1.1       root       98:        }
1.1.1.6   root       99:        
                    100:        if(ft->cluster_count >= 65525) // FAT32
1.1       root      101:        {
                    102:                ft->size_fat = 32;
1.1.1.19! root      103:                ft->reserved = 32 - 1;
        !           104: 
        !           105:                do
        !           106:                {
        !           107:                        ft->reserved++;
        !           108: 
        !           109:                        fatsecs = ft->num_sectors - ft->reserved;
        !           110:                        ft->size_root_dir = ft->cluster_size * ft->sector_size;
        !           111:                        ft->cluster_count = (int) (((__int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size + 8));
        !           112:                        ft->fat_length = (ft->cluster_count * 4 + ft->sector_size - 1) / ft->sector_size;
        !           113: 
        !           114:                // Align data area on TC_MAX_VOLUME_SECTOR_SIZE
        !           115: 
        !           116:                } while (ft->sector_size == TC_SECTOR_SIZE_LEGACY
        !           117:                                && (ft->reserved * ft->sector_size + ft->fat_length * ft->fats * ft->sector_size) % TC_MAX_VOLUME_SECTOR_SIZE != 0);
1.1       root      118:        }
                    119: 
                    120:        if (ft->num_sectors >= 65536 || ft->size_fat == 32)
                    121:        {
                    122:                ft->sectors = 0;
                    123:                ft->total_sect = ft->num_sectors;
                    124:        }
                    125:        else
                    126:        {
1.1.1.17  root      127:                ft->sectors = (uint16) ft->num_sectors;
1.1       root      128:                ft->total_sect = 0;
                    129:        }
                    130: }
                    131: 
                    132: void
                    133: PutBoot (fatparams * ft, unsigned char *boot)
                    134: {
                    135:        int cnt = 0;
                    136: 
                    137:        boot[cnt++] = 0xeb;     /* boot jump */
                    138:        boot[cnt++] = 0x3c;
                    139:        boot[cnt++] = 0x90;
1.1.1.6   root      140:        memcpy (boot + cnt, "MSDOS5.0", 8); /* system id */
1.1       root      141:        cnt += 8;
1.1.1.10  root      142:        *(__int16 *)(boot + cnt) = LE16(ft->sector_size);       /* bytes per sector */
1.1       root      143:        cnt += 2;
1.1.1.10  root      144:        boot[cnt++] = (__int8) ft->cluster_size;                        /* sectors per cluster */
                    145:        *(__int16 *)(boot + cnt) = LE16(ft->reserved);          /* reserved sectors */
1.1.1.6   root      146:        cnt += 2;
1.1.1.10  root      147:        boot[cnt++] = (__int8) ft->fats;                                        /* 2 fats */
1.1       root      148: 
                    149:        if(ft->size_fat == 32)
                    150:        {
                    151:                boot[cnt++] = 0x00;
                    152:                boot[cnt++] = 0x00;
                    153:        }
                    154:        else
                    155:        {
1.1.1.10  root      156:                *(__int16 *)(boot + cnt) = LE16(ft->dir_entries);       /* 512 root entries */
1.1       root      157:                cnt += 2;
                    158:        }
                    159: 
1.1.1.10  root      160:        *(__int16 *)(boot + cnt) = LE16(ft->sectors);           /* # sectors */
1.1       root      161:        cnt += 2;
1.1.1.10  root      162:        boot[cnt++] = (__int8) ft->media;                                       /* media byte */
1.1       root      163: 
                    164:        if(ft->size_fat == 32)  
                    165:        {
                    166:                boot[cnt++] = 0x00;
                    167:                boot[cnt++] = 0x00;
                    168:        }
                    169:        else 
                    170:        { 
1.1.1.17  root      171:                *(__int16 *)(boot + cnt) = LE16((uint16) ft->fat_length);       /* fat size */
1.1       root      172:                cnt += 2;
                    173:        }
                    174: 
1.1.1.10  root      175:        *(__int16 *)(boot + cnt) = LE16(ft->secs_track);        /* # sectors per track */
1.1       root      176:        cnt += 2;
1.1.1.10  root      177:        *(__int16 *)(boot + cnt) = LE16(ft->heads);                     /* # heads */
1.1       root      178:        cnt += 2;
1.1.1.10  root      179:        *(__int32 *)(boot + cnt) = LE32(ft->hidden);            /* # hidden sectors */
1.1.1.6   root      180:        cnt += 4;
1.1.1.10  root      181:        *(__int32 *)(boot + cnt) = LE32(ft->total_sect);        /* # huge sectors */
1.1       root      182:        cnt += 4;
                    183: 
                    184:        if(ft->size_fat == 32)
                    185:        {
1.1.1.10  root      186:                *(__int32 *)(boot + cnt) = LE32(ft->fat_length); cnt += 4;      /* fat size 32 */
1.1.1.6   root      187:                boot[cnt++] = 0x00;     /* ExtFlags */
1.1       root      188:                boot[cnt++] = 0x00;
                    189:                boot[cnt++] = 0x00;     /* FSVer */
                    190:                boot[cnt++] = 0x00;
                    191:                boot[cnt++] = 0x02;     /* RootClus */
                    192:                boot[cnt++] = 0x00;
                    193:                boot[cnt++] = 0x00;
                    194:                boot[cnt++] = 0x00;
                    195:                boot[cnt++] = 0x01;     /* FSInfo */
                    196:                boot[cnt++] = 0x00;
                    197:                boot[cnt++] = 0x06;     /* BkBootSec */
                    198:                boot[cnt++] = 0x00;
                    199:                memset(boot+cnt, 0, 12); cnt+=12;       /* Reserved */
                    200:        }
                    201: 
1.1.1.6   root      202:        boot[cnt++] = 0x00;     /* drive number */   // FIXED 80 > 00
1.1       root      203:        boot[cnt++] = 0x00;     /* reserved */
                    204:        boot[cnt++] = 0x29;     /* boot sig */
1.1.1.13  root      205: 
1.1.1.19! root      206:        memcpy (boot + cnt, ft->volume_id, 4);          /* vol id */
1.1       root      207:        cnt += 4;
1.1.1.13  root      208: 
1.1.1.6   root      209:        memcpy (boot + cnt, ft->volume_name, 11);       /* vol title */
1.1       root      210:        cnt += 11;
                    211: 
                    212:        switch(ft->size_fat) /* filesystem type */
                    213:        {
                    214:                case 12: memcpy (boot + cnt, "FAT12   ", 8); break;
                    215:                case 16: memcpy (boot + cnt, "FAT16   ", 8); break;
                    216:                case 32: memcpy (boot + cnt, "FAT32   ", 8); break;
                    217:        }
                    218:        cnt += 8;
                    219: 
                    220:        memset (boot + cnt, 0, ft->size_fat==32 ? 420:448);     /* boot code */
                    221:        cnt += ft->size_fat==32 ? 420:448;
                    222:        boot[cnt++] = 0x55;
                    223:        boot[cnt++] = 0xaa;     /* boot sig */
                    224: }
                    225: 
1.1.1.10  root      226: 
1.1       root      227: /* FAT32 FSInfo */
1.1.1.17  root      228: static void PutFSInfo (unsigned char *sector, fatparams *ft)
1.1       root      229: {
1.1.1.19! root      230:        memset (sector, 0, ft->sector_size);
1.1.1.6   root      231:        sector[3]=0x41; /* LeadSig */
                    232:        sector[2]=0x61; 
                    233:        sector[1]=0x52; 
                    234:        sector[0]=0x52; 
                    235:        sector[484+3]=0x61; /* StrucSig */
                    236:        sector[484+2]=0x41; 
                    237:        sector[484+1]=0x72; 
                    238:        sector[484+0]=0x72; 
1.1.1.13  root      239: 
                    240:        // Free cluster count
1.1.1.19! root      241:        *(uint32 *)(sector + 488) = LE32 (ft->cluster_count - ft->size_root_dir / ft->sector_size / ft->cluster_size);
1.1.1.13  root      242: 
1.1.1.17  root      243:        // Next free cluster
                    244:        *(uint32 *)(sector + 492) = LE32 (2);
                    245: 
1.1.1.6   root      246:        sector[508+3]=0xaa; /* TrailSig */
                    247:        sector[508+2]=0x55;
                    248:        sector[508+1]=0x00;
                    249:        sector[508+0]=0x00;
1.1       root      250: }
                    251: 
                    252: 
                    253: int
1.1.1.8   root      254: FormatFat (unsigned __int64 startSector, fatparams * ft, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1       root      255: {
                    256:        int write_buf_cnt = 0;
1.1.1.19! root      257:        char sector[TC_MAX_VOLUME_SECTOR_SIZE], *write_buf;
1.1.1.4   root      258:        unsigned __int64 nSecNo = startSector;
1.1       root      259:        int x, n;
1.1.1.6   root      260:        int retVal;
1.1.1.12  root      261:        char temporaryKey[MASTER_KEYDATA_SIZE];
1.1       root      262: 
1.1.1.8   root      263:        LARGE_INTEGER startOffset;
                    264:        LARGE_INTEGER newOffset;
                    265: 
1.1.1.4   root      266:        // Seek to start sector
1.1.1.19! root      267:        startOffset.QuadPart = startSector * ft->sector_size;
1.1.1.6   root      268:        if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
                    269:                || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4   root      270:        {
                    271:                return ERR_VOL_SEEKING;
                    272:        }
1.1       root      273: 
1.1.1.4   root      274:        /* Write the data area */
1.1       root      275: 
1.1.1.17  root      276:        write_buf = (char *)TCalloc (FormatWriteBufferSize);
1.1.1.15  root      277:        if (!write_buf)
                    278:                return ERR_OUTOFMEMORY;
                    279: 
1.1.1.19! root      280:        memset (sector, 0, ft->sector_size);
        !           281: 
        !           282:        RandgetBytes (ft->volume_id, sizeof (ft->volume_id), FALSE);
1.1       root      283: 
                    284:        PutBoot (ft, (unsigned char *) sector);
1.1.1.6   root      285:        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      286:                cryptoInfo) == FALSE)
1.1       root      287:                goto fail;
                    288: 
                    289:        /* fat32 boot area */
                    290:        if (ft->size_fat == 32)                         
                    291:        {
                    292:                /* fsinfo */
1.1.1.13  root      293:                PutFSInfo((unsigned char *) sector, ft);
1.1.1.6   root      294:                if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      295:                        cryptoInfo) == FALSE)
1.1       root      296:                        goto fail;
                    297: 
                    298:                /* reserved */
1.1.1.4   root      299:                while (nSecNo - startSector < 6)
1.1       root      300:                {
1.1.1.19! root      301:                        memset (sector, 0, ft->sector_size);
1.1       root      302:                        sector[508+3]=0xaa; /* TrailSig */
                    303:                        sector[508+2]=0x55;
1.1.1.6   root      304:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      305:                                cryptoInfo) == FALSE)
1.1       root      306:                                goto fail;
                    307:                }
                    308:                
                    309:                /* bootsector backup */
1.1.1.19! root      310:                memset (sector, 0, ft->sector_size);
1.1       root      311:                PutBoot (ft, (unsigned char *) sector);
1.1.1.6   root      312:                if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      313:                                 cryptoInfo) == FALSE)
1.1       root      314:                        goto fail;
                    315: 
1.1.1.13  root      316:                PutFSInfo((unsigned char *) sector, ft);
1.1.1.6   root      317:                if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      318:                        cryptoInfo) == FALSE)
1.1       root      319:                        goto fail;
1.1.1.6   root      320:        }
1.1       root      321: 
1.1.1.6   root      322:        /* reserved */
1.1.1.8   root      323:        while (nSecNo - startSector < (unsigned int)ft->reserved)
1.1.1.6   root      324:        {
1.1.1.19! root      325:                memset (sector, 0, ft->sector_size);
1.1.1.6   root      326:                if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      327:                        cryptoInfo) == FALSE)
1.1.1.6   root      328:                        goto fail;
1.1       root      329:        }
                    330: 
                    331:        /* write fat */
                    332:        for (x = 1; x <= ft->fats; x++)
                    333:        {
                    334:                for (n = 0; n < ft->fat_length; n++)
                    335:                {
1.1.1.19! root      336:                        memset (sector, 0, ft->sector_size);
1.1       root      337: 
                    338:                        if (n == 0)
                    339:                        {
                    340:                                unsigned char fat_sig[12];
                    341:                                if (ft->size_fat == 32)
                    342:                                {
                    343:                                        fat_sig[0] = (unsigned char) ft->media;
                    344:                                        fat_sig[1] = fat_sig[2] = 0xff;
                    345:                                        fat_sig[3] = 0x0f;
                    346:                                        fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff;
                    347:                                        fat_sig[7] = 0x0f;
                    348:                                        fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff;
                    349:                                        fat_sig[11] = 0x0f;
                    350:                                        memcpy (sector, fat_sig, 12);
                    351:                                }                               
                    352:                                else if (ft->size_fat == 16)
                    353:                                {
                    354:                                        fat_sig[0] = (unsigned char) ft->media;
                    355:                                        fat_sig[1] = 0xff;
                    356:                                        fat_sig[2] = 0xff;
                    357:                                        fat_sig[3] = 0xff;
                    358:                                        memcpy (sector, fat_sig, 4);
                    359:                                }
                    360:                                else if (ft->size_fat == 12)
                    361:                                {
                    362:                                        fat_sig[0] = (unsigned char) ft->media;
                    363:                                        fat_sig[1] = 0xff;
                    364:                                        fat_sig[2] = 0xff;
                    365:                                        fat_sig[3] = 0x00;
                    366:                                        memcpy (sector, fat_sig, 4);
                    367:                                }
                    368:                        }
                    369: 
1.1.1.6   root      370:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      371:                                    cryptoInfo) == FALSE)
1.1       root      372:                                goto fail;
                    373:                }
                    374:        }
                    375: 
                    376: 
                    377:        /* write rootdir */
1.1.1.19! root      378:        for (x = 0; x < ft->size_root_dir / ft->sector_size; x++)
1.1       root      379:        {
1.1.1.19! root      380:                memset (sector, 0, ft->sector_size);
1.1.1.6   root      381:                if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      382:                                 cryptoInfo) == FALSE)
1.1       root      383:                        goto fail;
                    384: 
                    385:        }
                    386: 
1.1.1.7   root      387:        /* Fill the rest of the data area with random data */
1.1.1.4   root      388: 
1.1       root      389:        if(!quickFormat)
                    390:        {
1.1.1.13  root      391:                if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
                    392:                        goto fail;
                    393: 
1.1.1.7   root      394:                /* Generate a random temporary key set to be used for "dummy" encryption that will fill
                    395:                the free disk space (data area) with random data.  This is necessary for plausible
                    396:                deniability of hidden volumes (and also reduces the amount of predictable plaintext
                    397:                within the volume). */
1.1       root      398: 
1.1.1.9   root      399:                // Temporary master key
                    400:                if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
                    401:                        goto fail;
1.1.1.12  root      402: 
                    403:                // Temporary secondary key (XTS mode)
                    404:                if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))               
1.1.1.9   root      405:                        goto fail;
1.1.1.6   root      406: 
1.1.1.7   root      407:                retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.12  root      408:                if (retVal != ERR_SUCCESS)
1.1.1.7   root      409:                {
                    410:                        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.6   root      411:                        return retVal;
1.1.1.7   root      412:                }
                    413:                if (!EAInitMode (cryptoInfo))
                    414:                {
                    415:                        burn (temporaryKey, sizeof(temporaryKey));
                    416:                        return ERR_MODE_INIT_FAILED;
                    417:                }
1.1       root      418: 
1.1.1.19! root      419:                x = ft->num_sectors - ft->reserved - ft->size_root_dir / ft->sector_size - ft->fat_length * 2;
1.1       root      420:                while (x--)
                    421:                {
1.1.1.6   root      422:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      423:                                cryptoInfo) == FALSE)
1.1       root      424:                                goto fail;
                    425:                }
1.1.1.19! root      426:                UpdateProgressBar (nSecNo * ft->sector_size);
1.1       root      427:        }
1.1.1.3   root      428:        else
1.1.1.19! root      429:                UpdateProgressBar ((uint64) ft->num_sectors * ft->sector_size);
1.1.1.8   root      430: 
1.1.1.13  root      431:        if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
1.1       root      432:                goto fail;
                    433: 
                    434:        TCfree (write_buf);
1.1.1.7   root      435:        burn (temporaryKey, sizeof(temporaryKey));
1.1       root      436:        return 0;
                    437: 
1.1.1.7   root      438: fail:
1.1       root      439: 
                    440:        TCfree (write_buf);
1.1.1.7   root      441:        burn (temporaryKey, sizeof(temporaryKey));
1.1       root      442:        return ERR_OS_ERROR;
                    443: }

unix.superglobalmegacorp.com

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