"Fossies" - the Fresh Open Source Software Archive

Member "src/Core/FatFormatter.cpp" (10 Oct 2018, 10879 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "FatFormatter.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Legal Notice: Some portions of the source code contained in this file were
    3  derived from the source code of TrueCrypt 7.1a, which is
    4  Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
    5  governed by the TrueCrypt License 3.0, also from the source code of
    6  Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
    7  and which is governed by the 'License Agreement for Encryption for the Masses'
    8  Modifications and additions to the original source code (contained in this file)
    9  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   10  and are governed by the Apache License 2.0 the full text of which is
   11  contained in the file License.txt included in VeraCrypt binary and source
   12  code distribution packages. */
   13 
   14 #include "Common/Tcdefs.h"
   15 #include "Platform/Platform.h"
   16 #include "Volume/VolumeHeader.h"
   17 #include "FatFormatter.h"
   18 #include "RandomNumberGenerator.h"
   19 
   20 namespace VeraCrypt
   21 {
   22     struct fatparams
   23     {
   24         char volume_name[11];
   25         uint32 num_sectors; /* total number of sectors */
   26         uint32 cluster_count;   /* number of clusters */
   27         uint32 size_root_dir;   /* size of the root directory in bytes */
   28         uint32 size_fat;        /* size of FAT */
   29         uint32 fats;
   30         uint32 media;
   31         uint32 cluster_size;
   32         uint32 fat_length;
   33         uint16 dir_entries;
   34         uint16 sector_size;
   35         uint32 hidden;
   36         uint16 reserved;
   37         uint16 sectors;
   38         uint32 total_sect;
   39 
   40         uint16 heads;
   41         uint16 secs_track;
   42 
   43     };
   44 
   45     static void GetFatParams (fatparams * ft)
   46     {
   47         uint64 volumeSize = (uint64) ft->num_sectors * ft->sector_size;
   48         unsigned int fatsecs;
   49 
   50         if(ft->cluster_size == 0)   // 'Default' cluster size
   51         {
   52             uint32 clusterSize;
   53 
   54             // Determine optimal cluster size to minimize FAT size (mounting delay), maximize number of files, keep 4 KB alignment, etc.
   55             if (volumeSize >= 2 * BYTES_PER_TB)
   56                 clusterSize = 256 * BYTES_PER_KB;
   57             else if (volumeSize >= 512 * BYTES_PER_GB)
   58                 clusterSize = 128 * BYTES_PER_KB;
   59             else if (volumeSize >= 128 * BYTES_PER_GB)
   60                 clusterSize = 64 * BYTES_PER_KB;
   61             else if (volumeSize >= 64 * BYTES_PER_GB)
   62                 clusterSize = 32 * BYTES_PER_KB;
   63             else if (volumeSize >= 32 * BYTES_PER_GB)
   64                 clusterSize = 16 * BYTES_PER_KB;
   65             else if (volumeSize >= 16 * BYTES_PER_GB)
   66                 clusterSize = 8 * BYTES_PER_KB;
   67             else if (volumeSize >= 512 * BYTES_PER_MB)
   68                 clusterSize = 4 * BYTES_PER_KB;
   69             else if (volumeSize >= 256 * BYTES_PER_MB)
   70                 clusterSize = 2 * BYTES_PER_KB;
   71             else if (volumeSize >= 1 * BYTES_PER_MB)
   72                 clusterSize = 1 * BYTES_PER_KB;
   73             else
   74                 clusterSize = 512;
   75 
   76             ft->cluster_size = clusterSize / ft->sector_size;
   77 
   78             if (ft->cluster_size == 0)
   79                 ft->cluster_size = 1;
   80 
   81             if (ft->cluster_size * ft->sector_size > TC_MAX_FAT_CLUSTER_SIZE)
   82                 ft->cluster_size = TC_MAX_FAT_CLUSTER_SIZE / ft->sector_size;
   83 
   84             if (ft->cluster_size > 128)
   85                 ft->cluster_size = 128;
   86         }
   87 
   88         if (volumeSize <= TC_MAX_FAT_CLUSTER_SIZE * 4)
   89             ft->cluster_size = 1;
   90 
   91         // Geometry always set to SECTORS/1/1
   92         ft->secs_track = 1;
   93         ft->heads = 1;
   94 
   95         ft->dir_entries = 512;
   96         ft->fats = 2;
   97         ft->media = 0xf8;
   98         ft->hidden = 0;
   99 
  100         ft->size_root_dir = ft->dir_entries * 32;
  101 
  102         // FAT12
  103         ft->size_fat = 12;
  104         ft->reserved = 2;
  105         fatsecs = ft->num_sectors - (ft->size_root_dir + ft->sector_size - 1) / ft->sector_size - ft->reserved;
  106         ft->cluster_count = (int) (((int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size));
  107         ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + ft->sector_size - 1) / ft->sector_size;
  108 
  109         if (ft->cluster_count >= 4085) // FAT16
  110         {
  111             ft->size_fat = 16;
  112             ft->reserved = 2;
  113             fatsecs = ft->num_sectors - (ft->size_root_dir + ft->sector_size - 1) / ft->sector_size - ft->reserved;
  114             ft->cluster_count = (int) (((int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size));
  115             ft->fat_length = (ft->cluster_count * 2 + ft->sector_size - 1) / ft->sector_size;
  116         }
  117 
  118         if(ft->cluster_count >= 65525) // FAT32
  119         {
  120             ft->size_fat = 32;
  121             ft->reserved = 32 - 1;
  122 
  123             do
  124             {
  125                 ft->reserved++;
  126 
  127                 fatsecs = ft->num_sectors - ft->reserved;
  128                 ft->size_root_dir = ft->cluster_size * ft->sector_size;
  129                 ft->cluster_count = (int) (((int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size));
  130                 ft->fat_length = (ft->cluster_count * 4 + ft->sector_size - 1) / ft->sector_size;
  131 
  132                 // Align data area on TC_MAX_VOLUME_SECTOR_SIZE
  133 
  134             } while (ft->sector_size == TC_SECTOR_SIZE_LEGACY
  135                 && (ft->reserved * ft->sector_size + ft->fat_length * ft->fats * ft->sector_size) % TC_MAX_VOLUME_SECTOR_SIZE != 0);
  136         }
  137 
  138         ft->cluster_count -= ft->fat_length * ft->fats / ft->cluster_size;
  139 
  140         if (ft->num_sectors >= 65536 || ft->size_fat == 32)
  141         {
  142             ft->sectors = 0;
  143             ft->total_sect = ft->num_sectors;
  144         }
  145         else
  146         {
  147             ft->sectors = (uint16) ft->num_sectors;
  148             ft->total_sect = 0;
  149         }
  150     }
  151 
  152     static void PutBoot (fatparams * ft, byte *boot, uint32 volumeId)
  153     {
  154         int cnt = 0;
  155 
  156         boot[cnt++] = 0xeb; /* boot jump */     
  157         boot[cnt++] = (ft->size_fat == 32)? 0x58: 0x3c;
  158         boot[cnt++] = 0x90;
  159         memcpy (boot + cnt, "MSDOS5.0", 8); /* system id */
  160         cnt += 8;
  161         *(int16 *)(boot + cnt) = Endian::Little (ft->sector_size);  /* bytes per sector */
  162         cnt += 2;
  163         boot[cnt++] = (int8) ft->cluster_size;          /* sectors per cluster */
  164         *(int16 *)(boot + cnt) = Endian::Little (ft->reserved);     /* reserved sectors */
  165         cnt += 2;
  166         boot[cnt++] = (int8) ft->fats;                  /* 2 fats */
  167 
  168         if(ft->size_fat == 32)
  169         {
  170             boot[cnt++] = 0x00;
  171             boot[cnt++] = 0x00;
  172         }
  173         else
  174         {
  175             *(int16 *)(boot + cnt) = Endian::Little (ft->dir_entries);  /* 512 root entries */
  176             cnt += 2;
  177         }
  178 
  179         *(int16 *)(boot + cnt) = Endian::Little (ft->sectors);      /* # sectors */
  180         cnt += 2;
  181         boot[cnt++] = (int8) ft->media;                 /* media byte */
  182 
  183         if(ft->size_fat == 32)
  184         {
  185             boot[cnt++] = 0x00;
  186             boot[cnt++] = 0x00;
  187         }
  188         else
  189         {
  190             *(uint16 *)(boot + cnt) = Endian::Little ((uint16) ft->fat_length); /* fat size */
  191             cnt += 2;
  192         }
  193 
  194         *(int16 *)(boot + cnt) = Endian::Little (ft->secs_track);   /* # sectors per track */
  195         cnt += 2;
  196         *(int16 *)(boot + cnt) = Endian::Little (ft->heads);            /* # heads */
  197         cnt += 2;
  198         *(int32 *)(boot + cnt) = Endian::Little (ft->hidden);       /* # hidden sectors */
  199         cnt += 4;
  200         *(int32 *)(boot + cnt) = Endian::Little (ft->total_sect);   /* # huge sectors */
  201         cnt += 4;
  202 
  203         if(ft->size_fat == 32)
  204         {
  205             *(int32 *)(boot + cnt) = Endian::Little (ft->fat_length); cnt += 4; /* fat size 32 */
  206             boot[cnt++] = 0x00; /* ExtFlags */
  207             boot[cnt++] = 0x00;
  208             boot[cnt++] = 0x00; /* FSVer */
  209             boot[cnt++] = 0x00;
  210             boot[cnt++] = 0x02; /* RootClus */
  211             boot[cnt++] = 0x00;
  212             boot[cnt++] = 0x00;
  213             boot[cnt++] = 0x00;
  214             boot[cnt++] = 0x01; /* FSInfo */
  215             boot[cnt++] = 0x00;
  216             boot[cnt++] = 0x06; /* BkBootSec */
  217             boot[cnt++] = 0x00;
  218             memset(boot+cnt, 0, 12); cnt+=12;   /* Reserved */
  219         }
  220 
  221         boot[cnt++] = 0x00; /* drive number */   // FIXED 80 > 00
  222         boot[cnt++] = 0x00; /* reserved */
  223         boot[cnt++] = 0x29; /* boot sig */
  224 
  225         *(int32 *)(boot + cnt) = volumeId;
  226         cnt += 4;
  227 
  228         memcpy (boot + cnt, ft->volume_name, 11);   /* vol title */
  229         cnt += 11;
  230 
  231         switch(ft->size_fat) /* filesystem type */
  232         {
  233         case 12: memcpy (boot + cnt, "FAT12   ", 8); break;
  234         case 16: memcpy (boot + cnt, "FAT16   ", 8); break;
  235         case 32: memcpy (boot + cnt, "FAT32   ", 8); break;
  236         }
  237         cnt += 8;
  238 
  239         memset (boot + cnt, 0, ft->size_fat==32 ? 420:448); /* boot code */
  240         cnt += ft->size_fat==32 ? 420:448;
  241         boot[cnt++] = 0x55;
  242         boot[cnt++] = 0xaa; /* boot sig */
  243     }
  244 
  245 
  246     /* FAT32 FSInfo */
  247     static void PutFSInfo (byte *sector, fatparams *ft)
  248     {
  249         memset (sector, 0, ft->sector_size);
  250         sector[3] = 0x41; /* LeadSig */
  251         sector[2] = 0x61;
  252         sector[1] = 0x52;
  253         sector[0] = 0x52;
  254         sector[484+3] = 0x61; /* StrucSig */
  255         sector[484+2] = 0x41;
  256         sector[484+1] = 0x72;
  257         sector[484+0] = 0x72;
  258 
  259         // Free cluster count
  260         *(uint32 *)(sector + 488) = Endian::Little (ft->cluster_count - ft->size_root_dir / ft->sector_size / ft->cluster_size);
  261 
  262         // Next free cluster
  263         *(uint32 *)(sector + 492) = Endian::Little ((uint32) 2);
  264 
  265         sector[508+3] = 0xaa; /* TrailSig */
  266         sector[508+2] = 0x55;
  267         sector[508+1] = 0x00;
  268         sector[508+0] = 0x00;
  269     }
  270 
  271     void FatFormatter::Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize, uint32 sectorSize)
  272     {
  273         fatparams fatParams;
  274 
  275 #if TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
  276 #error TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
  277 #endif
  278         fatParams.sector_size = (uint16) sectorSize;
  279 
  280         if (deviceSize / fatParams.sector_size > 0xffffFFFF)
  281             throw ParameterIncorrect (SRC_POS);
  282 
  283         fatParams.num_sectors = (uint32) (deviceSize / fatParams.sector_size);
  284         fatParams.cluster_size = clusterSize / fatParams.sector_size;
  285         memcpy (fatParams.volume_name, "NO NAME    ", 11);
  286         GetFatParams (&fatParams);
  287         fatparams *ft = &fatParams;
  288 
  289         SecureBuffer sector (ft->sector_size);
  290         uint32 sectorNumber = 0;
  291 
  292         /* Write the data area */
  293 
  294         sector.Zero();
  295 
  296         uint32 volumeId;
  297         RandomNumberGenerator::GetDataFast (BufferPtr ((byte *) &volumeId, sizeof (volumeId)));
  298 
  299         PutBoot (ft, (byte *) sector, volumeId);
  300         writeSector (sector); ++sectorNumber;
  301 
  302         /* fat32 boot area */
  303         if (ft->size_fat == 32)
  304         {
  305             /* fsinfo */
  306             PutFSInfo((byte *) sector, ft);
  307             writeSector (sector); ++sectorNumber;
  308 
  309             /* reserved */
  310             while (sectorNumber < 6)
  311             {
  312                 sector.Zero();
  313                 sector[508+3] = 0xaa; /* TrailSig */
  314                 sector[508+2] = 0x55;
  315                 writeSector (sector); ++sectorNumber;
  316             }
  317 
  318             /* bootsector backup */
  319             sector.Zero();
  320             PutBoot (ft, (byte *) sector, volumeId);
  321             writeSector (sector); ++sectorNumber;
  322 
  323             PutFSInfo((byte *) sector, ft);
  324             writeSector (sector); ++sectorNumber;
  325         }
  326 
  327         /* reserved */
  328         while (sectorNumber < (uint32)ft->reserved)
  329         {
  330             sector.Zero();
  331             writeSector (sector); ++sectorNumber;
  332         }
  333 
  334         /* write fat */
  335         for (uint32 x = 1; x <= ft->fats; x++)
  336         {
  337             for (uint32 n = 0; n < ft->fat_length; n++)
  338             {
  339                 sector.Zero();
  340 
  341                 if (n == 0)
  342                 {
  343                     byte fat_sig[12];
  344                     if (ft->size_fat == 32)
  345                     {
  346                         fat_sig[0] = (byte) ft->media;
  347                         fat_sig[1] = fat_sig[2] = 0xff;
  348                         fat_sig[3] = 0x0f;
  349                         fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff;
  350                         fat_sig[7] = 0x0f;
  351                         fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff;
  352                         fat_sig[11] = 0x0f;
  353                         memcpy (sector, fat_sig, 12);
  354                     }
  355                     else if (ft->size_fat == 16)
  356                     {
  357                         fat_sig[0] = (byte) ft->media;
  358                         fat_sig[1] = 0xff;
  359                         fat_sig[2] = 0xff;
  360                         fat_sig[3] = 0xff;
  361                         memcpy (sector, fat_sig, 4);
  362                     }
  363                     else if (ft->size_fat == 12)
  364                     {
  365                         fat_sig[0] = (byte) ft->media;
  366                         fat_sig[1] = 0xff;
  367                         fat_sig[2] = 0xff;
  368                         fat_sig[3] = 0x00;
  369                         memcpy (sector, fat_sig, 4);
  370                     }
  371                 }
  372 
  373                 if (!writeSector (sector))
  374                     return;
  375             }
  376         }
  377 
  378         /* write rootdir */
  379         for (uint32 x = 0; x < ft->size_root_dir / ft->sector_size; x++)
  380         {
  381             sector.Zero();
  382             if (!writeSector (sector))
  383                 return;
  384         }
  385     }
  386 }