"Fossies" - the Fresh Open Source Software Archive

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