home *** CD-ROM | disk | FTP | other *** search
- /* This file is a part of SecureDevice 1.3
- Copyright (C) 1994 by Max Loewenthal and Arthur Helwig
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <stdio.h>
- #include <conio.h>
- #include <malloc.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <ctype.h>
- #include <dos.h>
- #include <dir.h>
- #include "md5.h"
- #include "usuals.h"
- #include "globals.h"
-
- #define MinorName "MKVOLUME"
- #define MinorVer "1.02"
-
- #define errWriteFile 1
- #define errSectRead 2
- #define errChDir 3
- #define errGetPathInfo 4
- #define errCantFindFile 5
- #define errHideError 6
- #define errPassphraseMismatch 7
-
- char *errmsg[]={"This is not an error! Should not occur\n",
- "Error writing data to file\n",
- "Error reading sector\n",
- "Error changing directory\n",
- "Error getting path info\n",
- "Error finding file\n",
- "Error hiding file\n",
- "Error: passphrases don't match\n"};
-
- extern far void IdeaCFB(void far *iv,void far *key,void far *plain,
- void far *cipher,unsigned len);
- extern far void IdeaCFBx(void far *iv,void far *key,void far *cipher,
- void far *plain,unsigned len);
-
- typedef unsigned long int dword;
-
- #define NOFFATS 2
- #define ROOTSIZE 112
- #define KEYLEN KeySize/2
- #define SBUFSIZE 20
-
- #define low16(x) (x & 0xFFFF)
- #define hi16(x) (x >> 16)
- #define odd(x) (x & 1)
-
- FILE *F;
-
- int ERRNUM=0;
- boolean FAT12;
- int sectspfat;
- int rootsects;
- int clustsize; /* Sectors per cluster */
- dword nofsects,nofdatasects,nofdataclust;
- dword filesize;
- unsigned char sectbuffer[SBUFSIZE][SectorSize];
- unsigned char key[MaxPwdLen];
- word16 iv[4];
- word16 expkey[KEYLEN];
-
- int writesector(int n);
- int crypt_n_write(void);
- int createbootsec(void);
- int createfats(void);
- int createroot(void);
- int createdatasects(void);
- void givehelp(void);
-
- void error(char *msg)
- { printf("%s",msg);
- exit(0);
- }
-
- void invgets(char *input)
- { unsigned i=0;
- char c;
- while(i<(MaxPwdLen-1))
- { c=getch();
- if(c=='\x0d')
- { printf("\n");
- *input='\0';
- return;
- }
- if(c=='\b')
- { if(i>0)
- { i--;
- input--;
- printf("\b \b");
- }
- }
- else
- { printf("*");
- *input++=c;
- i++;
- }
- }
- }
-
- int getkey(unsigned char *key)
- { char pass1[MaxPwdLen];
- char pass2[MaxPwdLen];
- MD5_CTX md5buf;
- unsigned k;
-
- printf("Enter passphrase: ");
- invgets(pass1);
- printf("\nRe-enter passphrase: ");
- invgets(pass2);
-
- if(strcmp(pass1,pass2))
- { ERRNUM=errPassphraseMismatch;
- return(1);
- }
-
- MD5Init(&md5buf);
- MD5Update(&md5buf,pass1,strlen(pass1));
- MD5Final(key,&md5buf);
-
- burn(pass1);
- burn(pass2);
- return(0);
- }
-
- /* Compute IDEA encryption subkeys Z */
- void en_key_idea(word16 *userkey, word16 *Z)
- { unsigned i,j;
- word16 *Y=Z;
- /*
- * shifts
- */
- for (j=0; j<8; j++)
- Z[j] = *userkey++;
-
- for (i=0; j<KEYLEN; j++)
- { i++;
- Z[i+7] = Z[i & 7] << 9 | Z[i+1 & 7] >> 7;
- Z += i & 8;
- i &= 7;
- }
- for(i=0;i<KEYLEN;i++)
- Y[i]^=0x0dae;
- } /* en_key_idea */
-
- int writesector(int n)
-
- { if(fwrite(sectbuffer,SectorSize,n,F)!=n)
- { ERRNUM=errWriteFile;
- return(1);
- }
- return(0);
- }
-
- int crypt_n_write()
- { fpos_t Fpos;
- dword sectnum;
- char *dummy;
- word16 myiv[4];
-
- if(fgetpos(F,&Fpos)) return(1);
-
- sectnum=(Fpos / SectorSize);
-
- myiv[0]=iv[0] ^ low16(sectnum);
- myiv[1]=iv[1] ^ hi16(sectnum);
- myiv[2]=iv[2] ^ low16(sectnum);
- myiv[3]=iv[3] ^ hi16(sectnum);
-
- IdeaCFB(myiv,expkey,dummy,dummy,1);
- IdeaCFB(myiv,expkey,sectbuffer,sectbuffer,1+SectorSize/8);
-
- return(writesector(1));
- }
-
- int createbootsec()
- { char *dummy;
- word16 myiv[4];
- word16 signature[4];
- int i;
- struct bsect { char jmp[3],oem[8];
- word16 sectsize;
- byte clustsize;
- word16 ressects;
- byte fatcnt;
- word16 rootsize,totsects;
- byte meddesc;
- word16 sectspfat,sectsptrack,nofheads;
- word32 hidden,totsectsl;
- byte physdrv,reserved,signature;
- word32 serial;
- char label[11],fatid[8];
- word16 iv[4],check[4];
- } boot;
- boot.jmp[0]=0xEB;
- boot.jmp[1]=0;
- boot.jmp[2]=0;
- strncpy(boot.oem,"SECDEV ",8);
- boot.sectsize=SectorSize;
- boot.clustsize=clustsize;
- boot.ressects=1;
- boot.fatcnt=NOFFATS;
- boot.rootsize=ROOTSIZE;
- boot.totsects=(nofsects<=0xFFFF?nofsects:0);
- boot.meddesc=0xF8;
- boot.sectspfat=sectspfat;
- boot.sectsptrack=8;
- boot.nofheads=1;
- boot.hidden=0;
- boot.totsectsl=nofsects;
- boot.physdrv=0;
- boot.reserved=0;
- boot.signature=0x29;
- boot.serial=(word32)random(0x10000) << 16 ^ random(0x10000);
- memset(boot.label,' ',sizeof(boot.label));
- if(FAT12)
- strncpy(boot.fatid,"FAT12 ",8); else
- strncpy(boot.fatid,"FAT16 ",8);
- memcpy(boot.iv,iv,sizeof(iv));
- for(i=1;i<4;i++) signature[i]=random(0x10000);
- signature[0]=0x1234;
- for(i=0;i<4;i++) myiv[i]=~iv[i];
- IdeaCFB(myiv,expkey,dummy,dummy,1);
- IdeaCFB(myiv,expkey,signature,boot.check,1+1);
-
- burn(sectbuffer);
- memcpy(sectbuffer,&boot,sizeof(boot));
-
- printf("Writing bootsector...\n");
- return(writesector(1));
- }
-
- int createroot()
- { int i;
- printf("Writing root directory...\n");
- for(i=0;i<rootsects;i++)
- { burn(sectbuffer);
- if(crypt_n_write()) return(1);
- }
- return(0);
- }
-
- int createfats()
- { int i,j;
- printf("Writing FATs...\n");
- for (i=0;i<NOFFATS;i++)
- { burn(sectbuffer);
- if(FAT12)
- { sectbuffer[0][0]=0xF8;
- sectbuffer[0][1]=0xFF;
- sectbuffer[0][2]=0xFF;
- }
- else
- { sectbuffer[0][0]=0xF8;
- sectbuffer[0][1]=0xFF;
- sectbuffer[0][2]=0xFF;
- sectbuffer[0][3]=0xFF;
- }
- if(crypt_n_write()) return(1);
- for(j=1;j<sectspfat;j++)
- { burn(sectbuffer);
- if(crypt_n_write()) return(1);
- }
- }
- return(0);
- }
-
- int createdatasects()
- { dword i;
- int j;
- printf("About to write %ld data sectors...\n",nofdatasects);
- for(i=0;i<SBUFSIZE;i++)
- for(j=0;j<SectorSize;j++)
- sectbuffer[i][j]=random(256);
-
- for(i=0;i<nofdatasects;)
- { printf("Writing sector %ld\r",i);
- j=SBUFSIZE;
- if((i+j)>nofdatasects) j=nofdatasects-i;
- if(writesector(j)) return(1);
- i+=j;
- }
- printf("Written %ld sectors\n",i);
- return(0);
- }
-
- int readsect(char Drv,word16 Sect)
- { struct { word32 startsect;
- word16 Count;
- char far *DTA;
- } CBlock;
- int error=0;
- if(_osmajor<4)
- asm { mov al,Drv
- sub al,'A'
- mov cx,1
- mov dx,Sect
- mov bx,OFFSET sectbuffer
- push bp
- push si
- push di
- int 25h
- pop ax
- pop di
- pop si
- pop bp
- adc error,0
- }
- else { CBlock.startsect=Sect;
- CBlock.Count=1;
- CBlock.DTA=§buffer;
- asm { push ds
- mov al,Drv
- sub al,'A'
- mov cx,-1
- lea bx,CBlock
- push ss
- pop ds
- push bp
- push si
- push di
- int 25h
- pop ax
- pop di
- pop si
- pop bp
- pop ds
- adc error,0
- }
- }
- if(error) ERRNUM=errSectRead;
- return(error);
- }
-
- int FollowChain(int *Fragments,char Drive,word16 StartClust)
- { struct DPB { char Drv,SubUnit;
- word16 sectsize;
- char SectpClust,pSectpClust;
- word16 ReservedSects;
- char Fatcnt;
- word16 MaxDir,DataSect,NofClust;
- char SectspFat;
- word16 Rootoffset;
- char *DevicePtr,MedDesc,Accessed,*NextDev;} far *dpbptr;
- union REGS regs;
- struct SREGS segregs;
- boolean FAT12;
- int FatInBuf=-1;
- word16 PrevClust=-1,CurClust,Part1,Part2;
- int FatSect,InFat;
-
- *Fragments=0;
- regs.h.ah = 0x32;
- regs.h.dl = Drive-'A'+1;
- intdosx(®s, ®s, &segregs);
- if(regs.h.al!=0) return(1);
- dpbptr=MK_FP(segregs.ds,regs.x.bx);
- FAT12=(dpbptr->NofClust<=0xFF6);
-
- CurClust=StartClust;
-
- if(FAT12)
- while(CurClust<=0xFF6)
- { if(CurClust!=PrevClust+1) (*Fragments)++;
- PrevClust=CurClust;
- FatSect=((long)CurClust*3/2) / dpbptr->sectsize;
- InFat=((long)CurClust*3/2) % dpbptr->sectsize;
- if(FatInBuf!=FatSect) if(readsect(Drive,dpbptr->ReservedSects+FatSect)) return(1);
- FatInBuf=FatSect;
- Part1=sectbuffer[0][InFat++];
- if(InFat>=dpbptr->sectsize)
- { InFat=0; FatSect++;
- if(FatInBuf!=FatSect)
- if(readsect(Drive,dpbptr->ReservedSects+FatSect)) return(1);
- FatInBuf=FatSect;
- }
- Part2=sectbuffer[0][InFat];
-
- if(odd(CurClust))
- CurClust=Part1 >>4 | (Part2 << 4);
- else
- CurClust=Part1 | ((Part2 & 0xF) << 8);
- }
- else
- while(CurClust<=0xFFF6)
- { if(CurClust!=PrevClust+1) (*Fragments)++;
- PrevClust=CurClust;
- FatSect=((long)CurClust*2) / dpbptr->sectsize;
- InFat=((long)CurClust*2) % dpbptr->sectsize;
- if(FatInBuf!=FatSect) if(readsect(Drive,dpbptr->ReservedSects+FatSect)) return(1);
- FatInBuf=FatSect;
- CurClust=sectbuffer[0][InFat] | (sectbuffer[0][InFat+1] << 8);
- }
- return(0);
- }
-
- int checkfrag (int *Fragments,char Drive, char Name[_MAX_FNAME],char Ext[_MAX_EXT])
- { struct fcb FCB;
- struct DTA { char Drv,Name[8],Ext[3],Attr,Filler[10];
- word16 Time,Date,Clust;} far *DTAPtr;
- word16 PrevClust,Clust;
- char OldPath[_MAX_PATH],NewPath[_MAX_PATH];
-
- if(getcurdir(Drive-'A'+1,OldPath))
- { ERRNUM=errGetPathInfo;
- return(1);
- }
-
- strcpy(NewPath,"X:\\");
- NewPath[0]=Drive;
- if(chdir(NewPath))
- { ERRNUM=errChDir;
- return(1);
- }
-
- if(Ext[0]=='.') Ext++;
-
- FCB.fcb_drive = Drive-'A'+1;
- memset(FCB.fcb_name,' ',sizeof(FCB.fcb_name));
- memset(FCB.fcb_ext,' ',sizeof(FCB.fcb_ext));
- memcpy(FCB.fcb_name,Name,strlen(Name));
- memcpy(FCB.fcb_ext,Ext,strlen(Ext));
-
- { union REGS regs;
- struct SREGS segregs;
-
- regs.h.ah = 0x11;
- regs.x.dx = FP_OFF(&FCB);
- segregs.ds = FP_SEG(&FCB);
- intdosx(®s, ®s, &segregs);
- if(regs.h.al!=0)
- { ERRNUM=errCantFindFile;
- return(1);
- }
-
- regs.h.ah = 0x2F;
- intdosx(®s,®s,&segregs);
- DTAPtr=MK_FP(segregs.es,regs.x.bx);
- }
-
- if(FollowChain(Fragments,Drive,DTAPtr->Clust)) return(1);
-
- strcpy(NewPath,"X:\\");
- NewPath[0]=Drive;
- strcat(NewPath,OldPath);
- if(chdir(NewPath))
- { ERRNUM=errChDir;
- return(1);
- }
- return(0);
- }
-
- void givehelp()
- { printf("Usage: MKVOL <filename> <filesize | all>\n\
- You will be prompted for a passphrase that will give you access\n\
- to the newly created volume.\n\n\
- The file that will be created MUST be located in the root directory\n\
- of the drive. After creation, it will be marked readonly, hidden and\n\
- system file, to prevent it from being accidently deleted, or moved.\n\n");
- exit(0);
- }
-
-
- void main(int argc,char *argv[])
- { char FileName[_MAX_PATH],
- Drive,
- RootName[_MAX_FNAME],
- RootExt[_MAX_EXT];
- char UseAllspace=0;
- int NofFragments;
-
- printf("%s %s's %s %s\n",MajorName,MajorVer,MinorName,MinorVer);
- printf("Written by %s\n\n",AuthorName);
-
- randomize();
- if(argc<3) givehelp();
-
- if(!strcmpi(argv[2],"all"))
- { printf("Using all available space\n");
- UseAllspace=1;
- } else
- if(sscanf(argv[2],"%ld",&filesize)!=1)
- error("Error in size\n");
-
- if(_fullpath(FileName,argv[1],sizeof(FileName))==NULL)
- error("Error in getting full path info\n");
-
- { char Drv[_MAX_DRIVE],Dir[_MAX_DIR];
- struct fatinfo diskinfo;
- _splitpath(FileName,Drv,Dir,RootName,RootExt);
- if(strcmp(Dir,"\\"))
- error("The specified filename is not in the root directory\n");
-
- Drive=toupper(Drv[0]);
- getfat (Drive-'A'+1,&diskinfo);
- if(diskinfo.fi_bysec!=512)
- error("The target drive doesn't have 512 bytes per sector\n");
- clustsize=diskinfo.fi_sclus;
- }
-
- if(UseAllspace)
- { struct dfree Dfree;
- getdfree(Drive-'A'+1,&Dfree);
- if(Dfree.df_sclus==0xFFFF)
- error("Error getting diskfree information\n");
- filesize=(long)Dfree.df_avail*Dfree.df_bsec*Dfree.df_sclus;
- printf("Available space: %ld\n",filesize);
- }
-
- if(getkey(key)) error(errmsg[ERRNUM]);
- en_key_idea((word16 *) key,expkey);
- burn(key);
-
- nofsects=filesize/SectorSize;
- rootsects=ROOTSIZE*32/SectorSize;
-
- if(nofsects<1+rootsects+1*sectspfat)
- error ("Size is too small");
-
- { boolean ok;
- sectspfat=0;
- do
- { sectspfat++;
- nofdatasects=nofsects-1-rootsects-NOFFATS*sectspfat;
- nofdataclust=nofdatasects/clustsize;
- FAT12=nofdataclust<=0xFF6;
- ok=nofdataclust<=(dword)sectspfat*SectorSize*2/(FAT12?3:4);
- } while(!ok);
- }
-
- printf("\nCreating volume:\n");
- printf("Root entries :%d\n",ROOTSIZE);
- printf("Root sectors :%d\n",rootsects);
- printf("FAT type :%d bit\n",(FAT12?12:16));
- printf("# Sectors in 1 FAT :%d\n",sectspfat);
- printf("# FAT copies :%d\n",NOFFATS);
- printf("Sectors per cluster :%d\n",clustsize);
- printf("# data clusters :%lu\n\n",nofdataclust);
-
- if(nofdataclust>0xFFF0)
- error("Error: # data clusters too large.\n\
- Sectors/cluster should be higher if you want this volume size");
-
- iv[0]=random(0x10000);
- iv[1]=random(0x10000);
- iv[2]=random(0x10000);
- iv[3]=random(0x10000);
-
- if((F=fopen(FileName,"w+b"))==NULL)
- { perror("Cannot create file");
- exit(0);
- }
-
- { if(!(createbootsec()))
- if(!(createfats()))
- if(!(createroot()))
- createdatasects();
- fclose(F);
- if(ERRNUM) error(errmsg[ERRNUM]);
- }
-
- printf("Ready. Checking fragmentation...\n");
-
- if(checkfrag (&NofFragments,Drive,RootName,RootExt))
- error(errmsg[ERRNUM]);
-
- printf("File is fragmented into %d pieces.\n\n",NofFragments);
- if(NofFragments>MaxNofParts)
- { printf("This file is too fragmented for use. If you still attempt to use it,\n\
- you'll get a 'General Failure'-error if you try to access it. Unfragment your\n\
- hard disk first, then manually make your file hidden, system and readonly.\n");
- printf("Then you can normally use the file.\n");
- }
- else
- { printf("Hiding file...\n");
- if(_dos_setfileattr(FileName,FA_HIDDEN | FA_SYSTEM | FA_RDONLY))
- error(errmsg[errHideError]);
- }
-
- printf("Done! To access this volume: place the name of this file in your CONFIG.SYS\n\
- after the SECDEV.SYS command. Refer to the documentation for more info.\n\n");
- }
-