home *** CD-ROM | disk | FTP | other *** search
/ CD-X 1 / cdx_01.iso / shareuti / secdev13 / source / mkvolume.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-02  |  15.9 KB  |  601 lines

  1. /* This file is a part of SecureDevice 1.3
  2.    Copyright (C) 1994 by Max Loewenthal and Arthur Helwig
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <conio.h>
  20. #include <malloc.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <time.h>
  24. #include <ctype.h>
  25. #include <dos.h>
  26. #include <dir.h>
  27. #include "md5.h"
  28. #include "usuals.h"
  29. #include "globals.h"
  30.  
  31. #define MinorName "MKVOLUME"
  32. #define MinorVer "1.02"
  33.  
  34. #define errWriteFile 1
  35. #define errSectRead 2
  36. #define errChDir 3
  37. #define errGetPathInfo 4
  38. #define errCantFindFile 5
  39. #define errHideError 6
  40. #define errPassphraseMismatch 7
  41.  
  42. char *errmsg[]={"This is not an error! Should not occur\n",
  43.                 "Error writing data to file\n",
  44.                 "Error reading sector\n",
  45.                 "Error changing directory\n",
  46.                 "Error getting path info\n",
  47.                 "Error finding file\n",
  48.                 "Error hiding file\n",
  49.                 "Error: passphrases don't match\n"};
  50.  
  51. extern far void IdeaCFB(void far *iv,void far *key,void far *plain,
  52.          void far *cipher,unsigned len);
  53. extern far void IdeaCFBx(void far *iv,void far *key,void far *cipher,
  54.          void far *plain,unsigned len);
  55.  
  56. typedef unsigned long int dword;
  57.  
  58. #define NOFFATS 2
  59. #define ROOTSIZE 112
  60. #define KEYLEN KeySize/2
  61. #define SBUFSIZE 20
  62.  
  63. #define low16(x) (x & 0xFFFF)
  64. #define hi16(x) (x >> 16)
  65. #define odd(x) (x & 1)
  66.  
  67. FILE *F;
  68.  
  69. int ERRNUM=0;
  70. boolean FAT12;
  71. int sectspfat;
  72. int rootsects;
  73. int clustsize;         /* Sectors per cluster */
  74. dword nofsects,nofdatasects,nofdataclust;
  75. dword filesize;
  76. unsigned char sectbuffer[SBUFSIZE][SectorSize];
  77. unsigned char key[MaxPwdLen];
  78. word16 iv[4];
  79. word16 expkey[KEYLEN];
  80.  
  81. int writesector(int n);
  82. int crypt_n_write(void);
  83. int createbootsec(void);
  84. int createfats(void);
  85. int createroot(void);
  86. int createdatasects(void);
  87. void givehelp(void);
  88.  
  89. void error(char *msg)
  90. { printf("%s",msg);
  91.   exit(0);
  92. }
  93.  
  94. void invgets(char *input)
  95. { unsigned i=0;
  96.   char c;
  97.   while(i<(MaxPwdLen-1))
  98.     { c=getch();
  99.       if(c=='\x0d')
  100.         { printf("\n");
  101.           *input='\0';
  102.           return;
  103.         }
  104.       if(c=='\b')
  105.         { if(i>0)
  106.            { i--;
  107.              input--;
  108.              printf("\b \b");
  109.            }
  110.         }
  111.       else
  112.        { printf("*");
  113.          *input++=c;
  114.          i++;
  115.        }
  116.     }
  117.   }
  118.  
  119. int getkey(unsigned char *key)
  120. { char pass1[MaxPwdLen];
  121.   char pass2[MaxPwdLen];
  122.   MD5_CTX md5buf;
  123.   unsigned k;
  124.  
  125.   printf("Enter passphrase: ");
  126.   invgets(pass1);
  127.   printf("\nRe-enter passphrase: ");
  128.   invgets(pass2);
  129.  
  130.   if(strcmp(pass1,pass2))
  131.     { ERRNUM=errPassphraseMismatch;
  132.       return(1);
  133.     }
  134.  
  135.   MD5Init(&md5buf);
  136.   MD5Update(&md5buf,pass1,strlen(pass1));
  137.   MD5Final(key,&md5buf);
  138.  
  139.   burn(pass1);
  140.   burn(pass2);
  141.   return(0);
  142.   }
  143.  
  144. /*      Compute IDEA encryption subkeys Z */
  145. void en_key_idea(word16 *userkey, word16 *Z)
  146. { unsigned i,j;
  147.   word16 *Y=Z;
  148.   /*
  149.    * shifts
  150.    */
  151.   for (j=0; j<8; j++)
  152.      Z[j] = *userkey++;
  153.  
  154.   for (i=0; j<KEYLEN; j++)
  155.   { i++;
  156.     Z[i+7] = Z[i & 7] << 9 | Z[i+1 & 7] >> 7;
  157.     Z += i & 8;
  158.     i &= 7;
  159.   }
  160.   for(i=0;i<KEYLEN;i++)
  161.      Y[i]^=0x0dae;
  162. }        /* en_key_idea */
  163.  
  164. int writesector(int n)
  165.  
  166. { if(fwrite(sectbuffer,SectorSize,n,F)!=n)
  167.     { ERRNUM=errWriteFile;
  168.       return(1);
  169.     }
  170.   return(0);
  171. }
  172.  
  173. int crypt_n_write()
  174. { fpos_t Fpos;
  175.   dword sectnum;
  176.   char *dummy;
  177.   word16 myiv[4];
  178.  
  179.   if(fgetpos(F,&Fpos)) return(1);
  180.  
  181.   sectnum=(Fpos / SectorSize);
  182.  
  183.   myiv[0]=iv[0] ^ low16(sectnum);
  184.   myiv[1]=iv[1] ^ hi16(sectnum);
  185.   myiv[2]=iv[2] ^ low16(sectnum);
  186.   myiv[3]=iv[3] ^ hi16(sectnum);
  187.  
  188.   IdeaCFB(myiv,expkey,dummy,dummy,1);
  189.   IdeaCFB(myiv,expkey,sectbuffer,sectbuffer,1+SectorSize/8);
  190.  
  191.   return(writesector(1));
  192. }
  193.  
  194. int createbootsec()
  195. { char *dummy;
  196.   word16 myiv[4];
  197.   word16 signature[4];
  198.   int i;
  199.   struct bsect { char jmp[3],oem[8];
  200.                  word16 sectsize;
  201.                  byte clustsize;
  202.                  word16 ressects;
  203.                  byte fatcnt;
  204.                  word16 rootsize,totsects;
  205.                  byte meddesc;
  206.                  word16 sectspfat,sectsptrack,nofheads;
  207.                  word32 hidden,totsectsl;
  208.                  byte physdrv,reserved,signature;
  209.                  word32 serial;
  210.                  char label[11],fatid[8];
  211.                  word16 iv[4],check[4];
  212.                } boot;
  213.   boot.jmp[0]=0xEB;
  214.   boot.jmp[1]=0;
  215.   boot.jmp[2]=0;
  216.   strncpy(boot.oem,"SECDEV  ",8);
  217.   boot.sectsize=SectorSize;
  218.   boot.clustsize=clustsize;
  219.   boot.ressects=1;
  220.   boot.fatcnt=NOFFATS;
  221.   boot.rootsize=ROOTSIZE;
  222.   boot.totsects=(nofsects<=0xFFFF?nofsects:0);
  223.   boot.meddesc=0xF8;
  224.   boot.sectspfat=sectspfat;
  225.   boot.sectsptrack=8;
  226.   boot.nofheads=1;
  227.   boot.hidden=0;
  228.   boot.totsectsl=nofsects;
  229.   boot.physdrv=0;
  230.   boot.reserved=0;
  231.   boot.signature=0x29;
  232.   boot.serial=(word32)random(0x10000) << 16 ^ random(0x10000);
  233.   memset(boot.label,' ',sizeof(boot.label));
  234.   if(FAT12)
  235.     strncpy(boot.fatid,"FAT12   ",8); else
  236.     strncpy(boot.fatid,"FAT16   ",8);
  237.   memcpy(boot.iv,iv,sizeof(iv));
  238.   for(i=1;i<4;i++) signature[i]=random(0x10000);
  239.   signature[0]=0x1234;
  240.   for(i=0;i<4;i++) myiv[i]=~iv[i];
  241.   IdeaCFB(myiv,expkey,dummy,dummy,1);
  242.   IdeaCFB(myiv,expkey,signature,boot.check,1+1);
  243.  
  244.   burn(sectbuffer);
  245.   memcpy(sectbuffer,&boot,sizeof(boot));
  246.  
  247.   printf("Writing bootsector...\n");
  248.   return(writesector(1));
  249. }
  250.  
  251. int createroot()
  252. { int i;
  253.   printf("Writing root directory...\n");
  254.   for(i=0;i<rootsects;i++)
  255.     { burn(sectbuffer);
  256.       if(crypt_n_write()) return(1);
  257.     }
  258.   return(0);
  259. }
  260.  
  261. int createfats()
  262. { int i,j;
  263.   printf("Writing FATs...\n");
  264.   for (i=0;i<NOFFATS;i++)
  265.     { burn(sectbuffer);
  266.       if(FAT12)
  267.         { sectbuffer[0][0]=0xF8;
  268.           sectbuffer[0][1]=0xFF;
  269.           sectbuffer[0][2]=0xFF;
  270.         }
  271.       else
  272.         { sectbuffer[0][0]=0xF8;
  273.           sectbuffer[0][1]=0xFF;
  274.           sectbuffer[0][2]=0xFF;
  275.           sectbuffer[0][3]=0xFF;
  276.         }
  277.       if(crypt_n_write()) return(1);
  278.       for(j=1;j<sectspfat;j++)
  279.         { burn(sectbuffer);
  280.           if(crypt_n_write()) return(1);
  281.         }
  282.     }
  283.   return(0);
  284. }
  285.  
  286. int createdatasects()
  287. { dword i;
  288.   int j;
  289.   printf("About to write %ld data sectors...\n",nofdatasects);
  290.   for(i=0;i<SBUFSIZE;i++)
  291.     for(j=0;j<SectorSize;j++)
  292.       sectbuffer[i][j]=random(256);
  293.  
  294.   for(i=0;i<nofdatasects;)
  295.    { printf("Writing sector %ld\r",i);
  296.      j=SBUFSIZE;
  297.      if((i+j)>nofdatasects) j=nofdatasects-i;
  298.      if(writesector(j)) return(1);
  299.      i+=j;
  300.    }
  301.   printf("Written %ld sectors\n",i);
  302.   return(0);
  303. }
  304.  
  305. int readsect(char Drv,word16 Sect)
  306. { struct { word32 startsect;
  307.            word16 Count;
  308.            char far *DTA;
  309.          } CBlock;
  310.   int error=0;
  311.   if(_osmajor<4)
  312.       asm { mov    al,Drv
  313.             sub    al,'A'
  314.             mov    cx,1
  315.             mov    dx,Sect
  316.             mov    bx,OFFSET sectbuffer
  317.             push   bp
  318.             push   si
  319.             push   di
  320.             int    25h
  321.             pop    ax
  322.             pop    di
  323.             pop    si
  324.             pop    bp
  325.             adc    error,0
  326.           }
  327.       else { CBlock.startsect=Sect;
  328.              CBlock.Count=1;
  329.              CBlock.DTA=§buffer;
  330.              asm { push ds
  331.                    mov    al,Drv
  332.                    sub    al,'A'
  333.                    mov    cx,-1
  334.                    lea    bx,CBlock
  335.                    push   ss
  336.                    pop    ds
  337.                    push   bp
  338.                    push   si
  339.                    push   di
  340.                    int    25h
  341.                    pop    ax
  342.                    pop    di
  343.                    pop    si
  344.                    pop    bp
  345.                    pop    ds
  346.                    adc    error,0
  347.                  }
  348.            }
  349.   if(error) ERRNUM=errSectRead;
  350.   return(error);
  351. }
  352.  
  353. int FollowChain(int *Fragments,char Drive,word16 StartClust)
  354. { struct DPB { char Drv,SubUnit;
  355.                word16 sectsize;
  356.                char SectpClust,pSectpClust;
  357.                word16 ReservedSects;
  358.                char Fatcnt;
  359.                word16 MaxDir,DataSect,NofClust;
  360.                char SectspFat;
  361.                word16 Rootoffset;
  362.                char *DevicePtr,MedDesc,Accessed,*NextDev;} far *dpbptr;
  363.   union REGS regs;
  364.   struct SREGS segregs;
  365.   boolean FAT12;
  366.   int FatInBuf=-1;
  367.   word16 PrevClust=-1,CurClust,Part1,Part2;
  368.   int FatSect,InFat;
  369.  
  370.   *Fragments=0;
  371.   regs.h.ah = 0x32;
  372.   regs.h.dl = Drive-'A'+1;
  373.   intdosx(®s, ®s, &segregs);
  374.   if(regs.h.al!=0) return(1);
  375.   dpbptr=MK_FP(segregs.ds,regs.x.bx);
  376.   FAT12=(dpbptr->NofClust<=0xFF6);
  377.  
  378.   CurClust=StartClust;
  379.  
  380.   if(FAT12)
  381.     while(CurClust<=0xFF6)
  382.       { if(CurClust!=PrevClust+1) (*Fragments)++;
  383.         PrevClust=CurClust;
  384.         FatSect=((long)CurClust*3/2) / dpbptr->sectsize;
  385.         InFat=((long)CurClust*3/2) % dpbptr->sectsize;
  386.         if(FatInBuf!=FatSect) if(readsect(Drive,dpbptr->ReservedSects+FatSect)) return(1);
  387.         FatInBuf=FatSect;
  388.         Part1=sectbuffer[0][InFat++];
  389.         if(InFat>=dpbptr->sectsize)
  390.           {  InFat=0; FatSect++;
  391.              if(FatInBuf!=FatSect)
  392.                if(readsect(Drive,dpbptr->ReservedSects+FatSect)) return(1);
  393.              FatInBuf=FatSect;
  394.           }
  395.         Part2=sectbuffer[0][InFat];
  396.  
  397.         if(odd(CurClust))
  398.           CurClust=Part1 >>4 | (Part2 << 4);
  399.         else
  400.           CurClust=Part1 | ((Part2 & 0xF) << 8);
  401.       }
  402.     else
  403.       while(CurClust<=0xFFF6)
  404.         { if(CurClust!=PrevClust+1) (*Fragments)++;
  405.           PrevClust=CurClust;
  406.           FatSect=((long)CurClust*2) / dpbptr->sectsize;
  407.           InFat=((long)CurClust*2) % dpbptr->sectsize;
  408.           if(FatInBuf!=FatSect) if(readsect(Drive,dpbptr->ReservedSects+FatSect)) return(1);
  409.           FatInBuf=FatSect;
  410.           CurClust=sectbuffer[0][InFat] | (sectbuffer[0][InFat+1] << 8);
  411.         }
  412.   return(0);
  413. }
  414.  
  415. int checkfrag (int *Fragments,char Drive, char Name[_MAX_FNAME],char Ext[_MAX_EXT])
  416. { struct fcb FCB;
  417.   struct DTA { char Drv,Name[8],Ext[3],Attr,Filler[10];
  418.                word16 Time,Date,Clust;} far *DTAPtr;
  419.   word16 PrevClust,Clust;
  420.   char OldPath[_MAX_PATH],NewPath[_MAX_PATH];
  421.  
  422.   if(getcurdir(Drive-'A'+1,OldPath))
  423.     { ERRNUM=errGetPathInfo;
  424.       return(1);
  425.     }
  426.  
  427.   strcpy(NewPath,"X:\\");
  428.   NewPath[0]=Drive;
  429.   if(chdir(NewPath))
  430.     { ERRNUM=errChDir;
  431.       return(1);
  432.     }
  433.  
  434.   if(Ext[0]=='.') Ext++;
  435.  
  436.   FCB.fcb_drive = Drive-'A'+1;
  437.   memset(FCB.fcb_name,' ',sizeof(FCB.fcb_name));
  438.   memset(FCB.fcb_ext,' ',sizeof(FCB.fcb_ext));
  439.   memcpy(FCB.fcb_name,Name,strlen(Name));
  440.   memcpy(FCB.fcb_ext,Ext,strlen(Ext));
  441.  
  442.   { union REGS regs;
  443.     struct SREGS segregs;
  444.  
  445.     regs.h.ah = 0x11;
  446.     regs.x.dx = FP_OFF(&FCB);
  447.     segregs.ds = FP_SEG(&FCB);
  448.     intdosx(®s, ®s, &segregs);
  449.     if(regs.h.al!=0)
  450.       { ERRNUM=errCantFindFile;
  451.         return(1);
  452.       }
  453.  
  454.     regs.h.ah = 0x2F;
  455.     intdosx(®s,®s,&segregs);
  456.     DTAPtr=MK_FP(segregs.es,regs.x.bx);
  457.   }
  458.  
  459.   if(FollowChain(Fragments,Drive,DTAPtr->Clust)) return(1);
  460.  
  461.   strcpy(NewPath,"X:\\");
  462.   NewPath[0]=Drive;
  463.   strcat(NewPath,OldPath);
  464.   if(chdir(NewPath))
  465.     { ERRNUM=errChDir;
  466.       return(1);
  467.     }
  468.   return(0);
  469. }
  470.  
  471. void givehelp()
  472. { printf("Usage: MKVOL <filename> <filesize | all>\n\
  473. You will be prompted for a passphrase that will give you access\n\
  474. to the newly created volume.\n\n\
  475. The file that will be created MUST be located in the root directory\n\
  476. of the drive. After creation, it will be marked readonly, hidden and\n\
  477. system file, to prevent it from being accidently deleted, or moved.\n\n");
  478.   exit(0);
  479. }
  480.  
  481.  
  482. void main(int argc,char *argv[])
  483. { char FileName[_MAX_PATH],
  484.        Drive,
  485.        RootName[_MAX_FNAME],
  486.        RootExt[_MAX_EXT];
  487.   char UseAllspace=0;
  488.   int NofFragments;
  489.  
  490.   printf("%s %s's %s %s\n",MajorName,MajorVer,MinorName,MinorVer);
  491.   printf("Written by %s\n\n",AuthorName);
  492.  
  493.   randomize();
  494.   if(argc<3) givehelp();
  495.  
  496.   if(!strcmpi(argv[2],"all"))
  497.     { printf("Using all available space\n");
  498.       UseAllspace=1;
  499.     } else
  500.     if(sscanf(argv[2],"%ld",&filesize)!=1)
  501.       error("Error in size\n");
  502.  
  503.   if(_fullpath(FileName,argv[1],sizeof(FileName))==NULL)
  504.     error("Error in getting full path info\n");
  505.  
  506.   { char Drv[_MAX_DRIVE],Dir[_MAX_DIR];
  507.     struct fatinfo diskinfo;
  508.     _splitpath(FileName,Drv,Dir,RootName,RootExt);
  509.     if(strcmp(Dir,"\\"))
  510.       error("The specified filename is not in the root directory\n");
  511.  
  512.     Drive=toupper(Drv[0]);
  513.     getfat (Drive-'A'+1,&diskinfo);
  514.     if(diskinfo.fi_bysec!=512)
  515.       error("The target drive doesn't have 512 bytes per sector\n");
  516.     clustsize=diskinfo.fi_sclus;
  517.   }
  518.  
  519.   if(UseAllspace)
  520.     { struct dfree Dfree;
  521.       getdfree(Drive-'A'+1,&Dfree);
  522.       if(Dfree.df_sclus==0xFFFF)
  523.         error("Error getting diskfree information\n");
  524.       filesize=(long)Dfree.df_avail*Dfree.df_bsec*Dfree.df_sclus;
  525.       printf("Available space: %ld\n",filesize);
  526.     }
  527.  
  528.   if(getkey(key)) error(errmsg[ERRNUM]);
  529.   en_key_idea((word16 *) key,expkey);
  530.   burn(key);
  531.  
  532.   nofsects=filesize/SectorSize;
  533.   rootsects=ROOTSIZE*32/SectorSize;
  534.  
  535.   if(nofsects<1+rootsects+1*sectspfat)
  536.     error ("Size is too small");
  537.  
  538.   { boolean ok;
  539.     sectspfat=0;
  540.     do
  541.     { sectspfat++;
  542.       nofdatasects=nofsects-1-rootsects-NOFFATS*sectspfat;
  543.       nofdataclust=nofdatasects/clustsize;
  544.       FAT12=nofdataclust<=0xFF6;
  545.       ok=nofdataclust<=(dword)sectspfat*SectorSize*2/(FAT12?3:4);
  546.     } while(!ok);
  547.   }
  548.  
  549.   printf("\nCreating volume:\n");
  550.   printf("Root entries          :%d\n",ROOTSIZE);
  551.   printf("Root sectors          :%d\n",rootsects);
  552.   printf("FAT type              :%d bit\n",(FAT12?12:16));
  553.   printf("# Sectors in 1 FAT    :%d\n",sectspfat);
  554.   printf("# FAT copies          :%d\n",NOFFATS);
  555.   printf("Sectors per cluster   :%d\n",clustsize);
  556.   printf("# data clusters       :%lu\n\n",nofdataclust);
  557.  
  558.   if(nofdataclust>0xFFF0)
  559.     error("Error: # data clusters too large.\n\
  560. Sectors/cluster should be higher if you want this volume size");
  561.  
  562.   iv[0]=random(0x10000);
  563.   iv[1]=random(0x10000);
  564.   iv[2]=random(0x10000);
  565.   iv[3]=random(0x10000);
  566.  
  567.   if((F=fopen(FileName,"w+b"))==NULL)
  568.     {  perror("Cannot create file");
  569.        exit(0);
  570.     }
  571.  
  572.   { if(!(createbootsec()))
  573.      if(!(createfats()))
  574.       if(!(createroot()))
  575.         createdatasects();
  576.     fclose(F);
  577.     if(ERRNUM) error(errmsg[ERRNUM]);
  578.   }
  579.  
  580.   printf("Ready. Checking fragmentation...\n");
  581.  
  582.   if(checkfrag (&NofFragments,Drive,RootName,RootExt))
  583.     error(errmsg[ERRNUM]);
  584.  
  585.   printf("File is fragmented into %d pieces.\n\n",NofFragments);
  586.   if(NofFragments>MaxNofParts)
  587.     {  printf("This file is too fragmented for use. If you still attempt to use it,\n\
  588. you'll get a 'General Failure'-error if you try to access it. Unfragment your\n\
  589. hard disk first, then manually make your file hidden, system and readonly.\n");
  590.        printf("Then you can normally use the file.\n");
  591.     }
  592.     else
  593.     {  printf("Hiding file...\n");
  594.        if(_dos_setfileattr(FileName,FA_HIDDEN | FA_SYSTEM | FA_RDONLY))
  595.          error(errmsg[errHideError]);
  596.     }
  597.  
  598.   printf("Done! To access this volume: place the name of this file in your CONFIG.SYS\n\
  599. after the SECDEV.SYS command. Refer to the documentation for more info.\n\n");
  600. }
  601.