//******************************************************************************
//
// Options handling
//
// .....
//
//******************************************************************************
//------------------------------------------------------------------------------
// library includes
//------------------------------------------------------------------------------
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//------------------------------------------------------------------------------
// columbo includes
//------------------------------------------------------------------------------
#include "proto.h"
#include "error.h"
#include "options.h"
//------------------------------------------------------------------
// machine specific intel architecture:
//------------------------------------------------------------------
#define TRACE 0
#undef LITTLE_ENDIAN
//------------------------------------------------------------------
// constant
//------------------------------------------------------------------
#define maxoptsize 512000
//------------------------------------------------------------------
// security
//------------------------------------------------------------------
#define secure(a,b) if (!(b==a%63 )) {yyexit(8057 );}
//#define DEBUG
//------------------------------------------------------------------
// wide char conversion
//------------------------------------------------------------------
#define psmallchar(aa,bb) \
char * optionsfilename=malloc(1000 ); \
int p=0 ,q=0 ;char d=aa[p]; \
while (aa[p]) { \
bb[q]=aa[p]; \
q++;p+=2 ;} \
bb[q]=0 ;
//------------------------------------------------------------------
// getoptions
//------------------------------------------------------------------
__declspec(dllexport) int getoptions(long optsize,char * optin,char * opt, long callkey) {
long optkeylen=8 ;unsigned char * soptions;long iosize;FILE *fi;
unsigned char sin[maxoptsize], sout[maxoptsize];long i;
unsigned char cc;unsigned char key[9 ], *buf=(char *)malloc(9 );
unsigned char * ast(unsigned char * s);
// convert to bytestring
psmallchar(optin,optionsfilename)
//get filename for key
for (i=strlen(optionsfilename)-1 ;(i>0 ) && (optionsfilename[i]!='\\' ) && (optionsfilename[i]!='/' );i--);
soptions=optionsfilename+i+1 ;
// right caller?
secure(optsize,callkey)
// take care
if (optsize>maxoptsize) yyexit(8058 );
// construct Key DES3
#if defined (DELPHI) | defined (MINGW) | defined (LINUX)
for (i=0 ;i<=3 ;i++) key[2 *i] = soptions[3 +i];
for (i=0 ;i<=3 ;i++) key[2 *i+1 ] = soptions[9 -i];
#else
key[0 ]=soptions[7 ]-1 ;
key[1 ]=soptions[5 ];
key[2 ]=soptions[0 ]-2 ;
for (i=0 ;i<=1 ;i++) key[3 +i] = soptions[4 -2 *i];
key[5 ]=soptions[3 ];
for (i=0 ;i<=1 ;i++) key[6 +i] = soptions[6 ];
for (i=0 ;i<=1 ;i++) key[6 +i] += 64 ;
for (i=0 ;i<8 ;i++) buf[i]=key[i];buf[8 ]=0 ;
buf=as(buf);
for (i=0 ;i<8 ;i++) key[i]=buf[i];
#endif
//
if ((fi=fopen(optionsfilename,"rb" ))!=NULL) {
iosize=0 ;
while (fscanf(fi,"%c" ,&cc) && (iosize<optsize)) {
sin[iosize]=cc;
iosize+=1 ;}
fclose(fi);
// Check for licence in Opt.R.dat
if (abs(iosize - optsize) > 0 ) {
//oerror("8036! Optionen korrupt");
yyexit(8059 );}
if (optsize>maxoptsize) {
//oerror("8037! Optionen korrupt");
yyexit(8060 );}
// ------- decrypt ---------
decrypt(sin,sout,key,optsize,optkeylen);
for (i=0 ;i<optsize;i++) opt[i]=sout[i];
// right caller?
secure(optsize,callkey)
// ------- fin -------------
if (optsize-iosize>0 ) {
//oerror("8038! falsche Gre");
}}
else
yyexit(8061 );
#if TRACE
if (opt) {
JString win=opt+27 ;
printf("win=%s\n" ,win);}
#endif
return 0 ;}
//-----------------------------------------------------------------
// putoptions
//-----------------------------------------------------------------
__declspec(dllexport) int putoptions(long optsize,char * optin,char * opt, long callkey) {
//int cputoptions(long optsize,unsigned char* optionsfilename,unsigned char* opt) {
long optkeylen=8 ;static unsigned char * soptions;long iosize;FILE *fi;
unsigned char sin[maxoptsize], sout[maxoptsize];long i;static unsigned char key[9 ];
psmallchar(optin,optionsfilename)
// get filename for key
for (i=strlen(optionsfilename)-1 ;(i>0 ) && (optionsfilename[i]!='\\' )&& (optionsfilename[i]!='/' );i--);
soptions=optionsfilename+i+1 ;
// right caller?
secure(optsize,callkey)
// take care
if (optsize>maxoptsize) yyexit(8062 );
// construct Key DES3
for (i=0 ;i<=3 ;i++) key[2 *i] = soptions[3 +i];
for (i=0 ;i<=3 ;i++) key[2 *i+1 ] = soptions[9 -i];
//
// ------ encrypt --------
for (i=0 ;i<optsize;i++) sin[i] =opt[i];
//for (i=0;i<optsize;i++) sout[i]=sin[i];
encrypt(sin,sout,key,optsize,optkeylen);
// ------- fin -------------
if ((fi=fopen(optionsfilename,"wb" ))!=NULL) {
iosize=0 ;
while (iosize<optsize) {
fprintf(fi,"%c" ,sout[iosize]);
iosize+=1 ;}
fclose(fi);
// right caller?
secure(optsize,callkey)
if (optsize-iosize>0 ) {
//oerror("8038! falsche Gre");
}}
else
yyexit(8063 );
return 0 ;}
//------------------------------------------------------------------
// getoptions
//------------------------------------------------------------------
__declspec(dllexport) int patchoptions(long optsize,char * optionsfilename,char * opt, long callkey,
char *ipaddr,char *winprodid,char *diskid,char *edit) {
long i;
const long Windowsproductid=26 ; // string[24]
const long IPAddr=101 ; // string[24]
const long DiskId=76 ; // string[24]
const long Edition=3129 ; // byte?
//const long Activated=3128+1; // boolean
//const long EthernetAddr=126+1; // string[24]
//const long CPU=51+1; // string[24]
getoptions(optsize,optionsfilename,opt,callkey);
if (winprodid) {
int ll=strlen(winprodid);
opt[Windowsproductid]=ll;
if (ll>24 ) yyexit(8064 );
for (i=1 ;i<=ll;i++)
opt[Windowsproductid+i]=winprodid[i-1 ];}
if (ipaddr) {
int ll=strlen(ipaddr);
opt[IPAddr]=ll;
opt[IPAddr+ll]=0 ;
if (ll>24 ) yyexit(8065 );
for (i=1 ;i<=ll;i++)
opt[IPAddr+i]=ipaddr[i-1 ];}
if (diskid) {
int ll=strlen(diskid);
opt[DiskId]=ll;
opt[DiskId+ll]=0 ;
if (ll>24 ) yyexit(8066 );
for (i=1 ;i<=ll;i++)
opt[DiskId+i]=diskid[i-1 ];}
if (edit) {
int ll=strlen(edit);
if (ll>24 ) yyexit(8067 );
for (i=0 ;i<4 ;i++)
opt[Edition+i]=edit[i];}
putoptions(optsize,optionsfilename,opt,callkey);
return 0 ;}
//-----------------------------------------------------------------------------
// make transparent char an ascii
//-----------------------------------------------------------------------------
unsigned char t2a(unsigned char c) {
unsigned char e;
if (c==' ' ) e=0 ;
else if ((c>='a' ) && (c<='z' )) e=c-'a' +1 ;
else if ((c>='A' ) && (c<='Z' )) e=c-'A' +26 +1 ;
else if ((c>='0' ) && (c<='9' )) e=c-'0' +26 +26 +1 ;
else if (c=='-' ) e=10 +26 +26 +1 ;
else exit (100 );
return e;}
//-----------------------------------------------------------------------------
// make transparent char an ascii
//-----------------------------------------------------------------------------
unsigned char a2t(unsigned char c) {
unsigned char e;
if (c==0 ) e=' ' ;
else if ((c>=1 ) && (c<=26 )) e=c+'a' -1 ;
else if ((c>=27 ) && (c<=52 )) e=c-26 +'A' -1 ;
else if ((c>=53 ) && (c<=62 )) e=c-52 +'0' -1 ;
else if (c==63 ) e='-' ;
else exit (100 );
return e;}
//-----------------------------------------------------------------------------
// make a string transparent
//-----------------------------------------------------------------------------
unsigned char *b642a(unsigned char * win, unsigned int ll) {
unsigned int i,j,k;int b[4 ];unsigned int ol=3 *(ll/4 +1 );
unsigned long z;unsigned char *er=malloc(8 *(ol/8 +1 ));
if (ll>65 ) exit (100 );
k=0 ;j=0 ;b[0 ]=b[1 ]=b[2 ]=b[3 ]=0 ;
for (i=0 ;i<strlen(win);i++) {
b[k]=t2a(win[i]);
k++;
if (k==4 ) {z=b[3 ]+64 *b[2 ]+64 *64 *b[1 ]+64 *64 *64 *b[0 ];
er[j]=z/(256 *256 );z=z-256 *256 *er[j];j++;
er[j]=z/256 ;z=z-256 *er[j];j++;
er[j]=z;j++;
k=0 ;b[0 ]=b[1 ]=b[2 ]=b[3 ]=0 ;}}
if (k>0 ) {z=b[3 ]+64 *b[2 ]+64 *64 *b[1 ]+64 *64 *64 *b[0 ];
er[j]=z/(256 *256 );z=z-256 *256 *er[j];j++;
er[j]=z/256 ;z=z-256 *er[j];j++;
er[j]=z;j++;}
//if (j!=ol) exit(100);
return er;}
//-----------------------------------------------------------------------------
// make a string transparent
//-----------------------------------------------------------------------------
unsigned char *a2b64(unsigned char * win, unsigned int ll) {
unsigned int i,j=0 ;int k=0 ,t=0 ;int b[4 ];unsigned int ol=4 *ll/3 ;
unsigned char *er=malloc(8 *(ol/8 +1 ));
unsigned long z=0 ;b[0 ]=b[1 ]=b[2 ]=b[3 ]=0 ;
if (3 *ll/4 +1 >64 ) exit (100 );
for (i=0 ;(i<ol) && (win[i]!=0 );i++) {
if (t==0 ) {z=win[i];t++;}
else if (t==1 ) {z=z*256 +win[i];t++;}
else if (t==2 ) {z=z*256 +win[i];t++;}
if (t>2 ) {
b[3 ]=z%64 ;z=z/64 ;
b[2 ]=z%64 ;z=z/64 ;
b[1 ]=z%64 ;z=z/64 ;
b[0 ]=z;t=0 ;z=0 ;
for (k=0 ;k<4 ;k++) {
er[j]=a2t(b[k]);
j++;}}}
if (t>0 ) {
if (t==1 ) z=z*256 *256 ;
else if (t==2 ) z=z*256 ;
b[3 ]=z%64 ;z=z/64 ;
b[2 ]=z%64 ;z=z/64 ;
b[1 ]=z%64 ;z=z/64 ;
b[0 ]=z;t=0 ;z=0 ;
for (k=0 ;k<4 ;k++) {
er[j]=a2t(b[k]);
j++;}}
//for (i=j;i>0;i--) if (er[i]==' ') er[i+1]=0;
er[j]=0 ;
//if (j!=ol+4) exit(100);
return er;}
//-----------------------------------------------------------------------------
// encrypt
//-----------------------------------------------------------------------------
__declspec(dllexport) int activate(char ** sin,char ** sout,char * key) {
#define codelength 64
unsigned int llt=strlen(*sin)>0 ?strlen(*sin):strlen(*sout),llk=strlen(key),lla,lld;
unsigned int i,j,k,inp=(strlen(*sin)>0 );int ol=8 *(llt/8 +1 );
unsigned char *work, *work1, *erg=malloc(8 *(llt/8 +1 )), *win=malloc(8 *(llt/8 +1 ));
if (llt>codelength) exit (100 );
if (inp) strcpy(win,*sin); else strcpy(win,*sout);
// Length must be 32:24 or multiple
llt=strlen(win);
if (llt!=codelength) exit (100 );
work=b642a(win,llt);
lla=3 *llt/4 ;
//lla=24;
//work1=a2b64(work,lla);
lld=8 *((lla+7 )/8 );
for (i=lla+1 ;i<=lld;i++) work[i]=0 ; // fill up
if (inp) {encrypt(work,erg,key,lld,llk);}
else {decrypt(work,erg,key,lld,llk);}
//if (inp) {decrypt(erg,work,key,lld,llk);erg=work;win=a2trans(work,lld);}
//else {encrypt(erg,work,key,lld,llk);erg=work;win=a2trans(work,lld);}
if (inp) win=*sout=a2b64(erg,lld); else win=*sin=a2b64(erg,lld);
win[llt]=0 ; // now shorten to original length
return 0 ;}
//-----------------------------------------------------------------------------
// encrypt
//-----------------------------------------------------------------------------
int encrypt(char * sin,char * sout,char * key,long datalen,long keylen) {
long i,c,b=8 ,k,ll=datalen / b+1 ;
char deskey[8 ];char work[8 ];
for (i=0 ;i<8 ;i++) deskey[i]=i+1 ;
if (datalen % b!=0 ) return -711 ;
if (keylen !=8 ) return -711 ;
desinit(0 );
for (k=0 ;k<3 ;k++) { // 3DES
for (i=0 ;i<8 ;i++) {
int m=(i+1023 )%8 ;
int t=deskey[m];
deskey[m]=deskey[i];
deskey[i]=t;}
if (k==0 ) setkey(key);
else setkey(deskey);
for (i=0 ;i<ll;i++) {
int u=b;if (i*b+b>datalen) u=datalen-i*b;
for (c=0 ;c<u;c++) work[c]=sin[i*b+c];
if (u<b) for (c=u;c<b;c++) work[c]=0 ;
endes(work);
for (c=0 ;c<u;c++) sout[i*b+c]=work[c];}}
return 0 ;}
//-----------------------------------------------------------------------------
// encrypt
//-----------------------------------------------------------------------------
int decrypt(char * sin,char * sout,char * key,long datalen,long keylen) {
long i,c,b=8 ,k,ll=datalen / b+1 ;
char deskey[8 ];char work[8 ];
for (i=0 ;i<8 ;i++) deskey[i]=i+1 ;
if (datalen % b!=0 ) return -711 ;
if (keylen !=8 ) return -711 ;
desinit(0 );
for (k=0 ;k<3 ;k++) { // 3DES
for (i=0 ;i<8 ;i++) {
int m=(i+1023 )%8 ;
int t=deskey[m];
deskey[m]=deskey[i];
deskey[i]=t;}
if (k==0 ) setkey(key);
else setkey(deskey);
for (i=0 ;i<ll;i++) {
int u=b;if (i*b+b>datalen) u=datalen-i*b;
for (c=0 ;c<u;c++) work[c]=sin[i*b+c];
#if TRACE
printf("%i:dedes=%02x%02x%02x%02x%02x%02x%02x%02x\n" ,i,work[0 ],work[1 ],work[2 ],work[3 ],work[4 ],work[5 ],work[6 ],work[7 ]);
#endif
dedes(work);
for (c=0 ;c<u;c++) sout[i*b+c]=work[c];}}
return 0 ;}
//-----------------------------------------------------------------------------
// Sofware DES functions
// written 12 Dec 1986 by Phil Karn, KA9Q; large sections adapted from
// the 1977 public-domain program by Jim Gillogly
//-----------------------------------------------------------------------------
#if defined (LITTLE_ENDIAN)
long byteswap();
#endif
/* Tables defined in the Data Encryption Standard documents */
/* initial permutation IP */
static char ip[] = {
58 , 50 , 42 , 34 , 26 , 18 , 10 , 2 ,
60 , 52 , 44 , 36 , 28 , 20 , 12 , 4 ,
62 , 54 , 46 , 38 , 30 , 22 , 14 , 6 ,
64 , 56 , 48 , 40 , 32 , 24 , 16 , 8 ,
57 , 49 , 41 , 33 , 25 , 17 , 9 , 1 ,
59 , 51 , 43 , 35 , 27 , 19 , 11 , 3 ,
61 , 53 , 45 , 37 , 29 , 21 , 13 , 5 ,
63 , 55 , 47 , 39 , 31 , 23 , 15 , 7
};
/* final permutation IP^-1 */
static char fp[] = {
40 , 8 , 48 , 16 , 56 , 24 , 64 , 32 ,
39 , 7 , 47 , 15 , 55 , 23 , 63 , 31 ,
38 , 6 , 46 , 14 , 54 , 22 , 62 , 30 ,
37 , 5 , 45 , 13 , 53 , 21 , 61 , 29 ,
36 , 4 , 44 , 12 , 52 , 20 , 60 , 28 ,
35 , 3 , 43 , 11 , 51 , 19 , 59 , 27 ,
34 , 2 , 42 , 10 , 50 , 18 , 58 , 26 ,
33 , 1 , 41 , 9 , 49 , 17 , 57 , 25
};
/* expansion operation matrix
* This is for reference only ; it is unused in the code
* as the f ( ) function performs it implicitly for speed
*/
#ifdef notdef
static char ei[] = {
32 , 1 , 2 , 3 , 4 , 5 ,
4 , 5 , 6 , 7 , 8 , 9 ,
8 , 9 , 10 , 11 , 12 , 13 ,
12 , 13 , 14 , 15 , 16 , 17 ,
16 , 17 , 18 , 19 , 20 , 21 ,
20 , 21 , 22 , 23 , 24 , 25 ,
24 , 25 , 26 , 27 , 28 , 29 ,
28 , 29 , 30 , 31 , 32 , 1
};
#endif
/* permuted choice table (key) */
static char pc1[] = {
57 , 49 , 41 , 33 , 25 , 17 , 9 ,
1 , 58 , 50 , 42 , 34 , 26 , 18 ,
10 , 2 , 59 , 51 , 43 , 35 , 27 ,
19 , 11 , 3 , 60 , 52 , 44 , 36 ,
63 , 55 , 47 , 39 , 31 , 23 , 15 ,
7 , 62 , 54 , 46 , 38 , 30 , 22 ,
14 , 6 , 61 , 53 , 45 , 37 , 29 ,
21 , 13 , 5 , 28 , 20 , 12 , 4
};
/* number left rotations of pc1 */
static char totrot[] = {
1 ,2 ,4 ,6 ,8 ,10 ,12 ,14 ,15 ,17 ,19 ,21 ,23 ,25 ,27 ,28
};
/* permuted choice key (table) */
static char pc2[] = {
14 , 17 , 11 , 24 , 1 , 5 ,
3 , 28 , 15 , 6 , 21 , 10 ,
23 , 19 , 12 , 4 , 26 , 8 ,
16 , 7 , 27 , 20 , 13 , 2 ,
41 , 52 , 31 , 37 , 47 , 55 ,
30 , 40 , 51 , 45 , 33 , 48 ,
44 , 49 , 39 , 56 , 34 , 53 ,
46 , 42 , 50 , 36 , 29 , 32
};
/* The (in)famous S-boxes */
static char si[8 ][64 ] = {
/* S1 */
{14 , 4 , 13 , 1 , 2 , 15 , 11 , 8 , 3 , 10 , 6 , 12 , 5 , 9 , 0 , 7 ,
0 , 15 , 7 , 4 , 14 , 2 , 13 , 1 , 10 , 6 , 12 , 11 , 9 , 5 , 3 , 8 ,
4 , 1 , 14 , 8 , 13 , 6 , 2 , 11 , 15 , 12 , 9 , 7 , 3 , 10 , 5 , 0 ,
15 , 12 , 8 , 2 , 4 , 9 , 1 , 7 , 5 , 11 , 3 , 14 , 10 , 0 , 6 , 13 },
/* S2 */
{15 , 1 , 8 , 14 , 6 , 11 , 3 , 4 , 9 , 7 , 2 , 13 , 12 , 0 , 5 , 10 ,
3 , 13 , 4 , 7 , 15 , 2 , 8 , 14 , 12 , 0 , 1 , 10 , 6 , 9 , 11 , 5 ,
0 , 14 , 7 , 11 , 10 , 4 , 13 , 1 , 5 , 8 , 12 , 6 , 9 , 3 , 2 , 15 ,
13 , 8 , 10 , 1 , 3 , 15 , 4 , 2 , 11 , 6 , 7 , 12 , 0 , 5 , 14 , 9 },
/* S3 */
{10 , 0 , 9 , 14 , 6 , 3 , 15 , 5 , 1 , 13 , 12 , 7 , 11 , 4 , 2 , 8 ,
13 , 7 , 0 , 9 , 3 , 4 , 6 , 10 , 2 , 8 , 5 , 14 , 12 , 11 , 15 , 1 ,
13 , 6 , 4 , 9 , 8 , 15 , 3 , 0 , 11 , 1 , 2 , 12 , 5 , 10 , 14 , 7 ,
1 , 10 , 13 , 0 , 6 , 9 , 8 , 7 , 4 , 15 , 14 , 3 , 11 , 5 , 2 , 12 },
/* S4 */
{ 7 , 13 , 14 , 3 , 0 , 6 , 9 , 10 , 1 , 2 , 8 , 5 , 11 , 12 , 4 , 15 ,
13 , 8 , 11 , 5 , 6 , 15 , 0 , 3 , 4 , 7 , 2 , 12 , 1 , 10 , 14 , 9 ,
10 , 6 , 9 , 0 , 12 , 11 , 7 , 13 , 15 , 1 , 3 , 14 , 5 , 2 , 8 , 4 ,
3 , 15 , 0 , 6 , 10 , 1 , 13 , 8 , 9 , 4 , 5 , 11 , 12 , 7 , 2 , 14 },
/* S5 */
{ 2 , 12 , 4 , 1 , 7 , 10 , 11 , 6 , 8 , 5 , 3 , 15 , 13 , 0 , 14 , 9 ,
14 , 11 , 2 , 12 , 4 , 7 , 13 , 1 , 5 , 0 , 15 , 10 , 3 , 9 , 8 , 6 ,
4 , 2 , 1 , 11 , 10 , 13 , 7 , 8 , 15 , 9 , 12 , 5 , 6 , 3 , 0 , 14 ,
11 , 8 , 12 , 7 , 1 , 14 , 2 , 13 , 6 , 15 , 0 , 9 , 10 , 4 , 5 , 3 },
/* S6 */
{12 , 1 , 10 , 15 , 9 , 2 , 6 , 8 , 0 , 13 , 3 , 4 , 14 , 7 , 5 , 11 ,
10 , 15 , 4 , 2 , 7 , 12 , 9 , 5 , 6 , 1 , 13 , 14 , 0 , 11 , 3 , 8 ,
9 , 14 , 15 , 5 , 2 , 8 , 12 , 3 , 7 , 0 , 4 , 10 , 1 , 13 , 11 , 6 ,
4 , 3 , 2 , 12 , 9 , 5 , 15 , 10 , 11 , 14 , 1 , 7 , 6 , 0 , 8 , 13 },
/* S7 */
{ 4 , 11 , 2 , 14 , 15 , 0 , 8 , 13 , 3 , 12 , 9 , 7 , 5 , 10 , 6 , 1 ,
13 , 0 , 11 , 7 , 4 , 9 , 1 , 10 , 14 , 3 , 5 , 12 , 2 , 15 , 8 , 6 ,
1 , 4 , 11 , 13 , 12 , 3 , 7 , 14 , 10 , 15 , 6 , 8 , 0 , 5 , 9 , 2 ,
6 , 11 , 13 , 8 , 1 , 4 , 10 , 7 , 9 , 5 , 0 , 15 , 14 , 2 , 3 , 12 },
/* S8 */
{13 , 2 , 8 , 4 , 6 , 15 , 11 , 1 , 10 , 9 , 3 , 14 , 5 , 0 , 12 , 7 ,
1 , 15 , 13 , 8 , 10 , 3 , 7 , 4 , 12 , 5 , 6 , 11 , 0 , 14 , 9 , 2 ,
7 , 11 , 4 , 1 , 9 , 12 , 14 , 2 , 0 , 6 , 10 , 13 , 15 , 3 , 5 , 8 ,
2 , 1 , 14 , 7 , 4 , 10 , 8 , 13 , 15 , 12 , 9 , 0 , 3 , 5 , 6 , 11 }
};
/* 32-bit permutation function P used on the output of the S-boxes */
static char p32i[] = {
16 , 7 , 20 , 21 ,
29 , 12 , 28 , 17 ,
1 , 15 , 23 , 26 ,
5 , 18 , 31 , 10 ,
2 , 8 , 24 , 14 ,
32 , 27 , 3 , 9 ,
19 , 13 , 30 , 6 ,
22 , 11 , 4 , 25
};
/* End of DES-defined tables */
/* Lookup tables initialized once only at startup by desinit() */
static long (*sp_)[64 ]; /* Combined S and P boxes */
static char (*iperm)[16 ][8 ]; /* Initial and final permutations */
static char (*fperm)[16 ][8 ];
/* 8 6-bit subkeys for each of 16 rounds, initialized by setkey() */
static char (*kn)[8 ];
/* bit 0 is left-most in byte */
static int bytebit[] = {
0200 ,0100 ,040 ,020 ,010 ,04 ,02 ,01
};
static int nibblebit[] = {
010 ,04 ,02 ,01
};
static int desmode;
/* Allocate space and initialize DES lookup arrays
* mode = = 0 : standard Data Encryption Algorithm
* mode = = 1 : DEA without initial and final permutations for speed
* mode = = 2 : DEA without permutations and with 128 - byte key ( completely
* independent subkeys for each round )
*/
int desinit(int mode) {
//char *malloc(); // Co3
if (sp_ != NULL){
/* Already initialized */
return 0 ;
}
desmode = mode;
if ((sp_ = (long (*)[64 ])malloc(sizeof (long ) * 8 * 64 )) == NULL){
return -1 ;
}
spinit();
kn = (char (*)[8 ])malloc(sizeof (char ) * 8 * 16 );
if (kn == NULL){
free((char *)sp_);
return -1 ;
}
if (mode == 1 || mode == 2 ) /* No permutations */
return 0 ;
iperm = (char (*)[16 ][8 ])malloc(sizeof (char ) * 16 * 16 * 8 );
if (iperm == NULL){
free((char *)sp_);
free((char *)kn);
return -1 ;
}
perminit(iperm,ip);
fperm = (char (*)[16 ][8 ])malloc(sizeof (char ) * 16 * 16 * 8 );
if (fperm == NULL){
free((char *)sp_);
free((char *)kn);
free((char *)iperm);
return -1 ;
}
perminit(fperm,fp);
return 0 ;
}
/* Free up storage used by DES */
void desdone(void ) {
if (sp_ == NULL)
return ; /* Already done */
free((char *)sp_);
free((char *)kn);
if (iperm != NULL)
free((char *)iperm);
if (fperm != NULL)
free((char *)fperm);
sp_ = NULL;
iperm = NULL;
fperm = NULL;
kn = NULL;
}
/* Set key (initialize key schedule array) */
void setkey(char *key) { /* 64 bits (will use only 56) */
char pc1m[56 ]; /* place to modify pc1 into */
char pcr[56 ]; /* place to rotate pc1 into */
int i,j,l;
int m;
/* In mode 2, the 128 bytes of subkey are set directly from the
* user ' s key , allowing him to use completely independent
* subkeys for each round . Note that the user MUST specify a
* full 128 bytes .
*
* I would like to think that this technique gives the NSA a real
* headache , but I ' m not THAT naive .
*/
if (desmode == 2 ){
for (i=0 ;i<16 ;i++)
for (j=0 ;j<8 ;j++)
kn[i][j] = *key++;
return ;
}
/* Clear key schedule */
for (i=0 ; i<16 ; i++)
for (j=0 ; j<8 ; j++)
kn[i][j]=0 ;
for (j=0 ; j<56 ; j++) { /* convert pc1 to bits of key */
l=pc1[j]-1 ; /* integer bit location */
m = l & 07 ; /* find bit */
pc1m[j]=(key[l>>3 ] & /* find which key byte l is in */
bytebit[m]) /* and which bit of that byte */
? 1 : 0 ; /* and store 1-bit result */
}
for (i=0 ; i<16 ; i++) { /* key chunk for each iteration */
for (j=0 ; j<56 ; j++) /* rotate pc1 the right amount */
pcr[j] = pc1m[(l=j+totrot[i])<(j<28 ? 28 : 56 ) ? l: l-28 ];
/* rotate left and right halves independently */
for (j=0 ; j<48 ; j++){ /* select bits individually */
/* check bit that goes to kn[j] */
if (pcr[pc2[j]-1 ]){
/* mask it in if it's there */
l= j % 6 ;
kn[i][j/6 ] |= bytebit[l] >> 2 ;
}
}
}
}
/* In-place encryption of 64-bit block */
void endes(char *block) {
int i;
unsigned long work[2 ]; /* Working data storage */
unsigned long tmp;
permute(block,iperm,(char *)work); /* Initial Permutation */
#if defined (LITTLE_ENDIAN)
work[0 ] = byteswap(work[0 ]);
work[1 ] = byteswap(work[1 ]);
#endif
/* Do the 16 rounds */
for (i=0 ; i<16 ; i++)
desround(i,work);
/* Left/right half swap */
tmp = work[0 ];
work[0 ] = work[1 ];
work[1 ] = tmp;
#if defined (LITTLE_ENDIAN)
work[0 ] = byteswap(work[0 ]);
work[1 ] = byteswap(work[1 ]);
#endif
permute((char *)work,fperm,block); /* Inverse initial permutation */
}
/* In-place decryption of 64-bit block */
void dedes(char *block) {
int i;
unsigned long work[2 ]; /* Working data storage */
unsigned long tmp;
permute(block,iperm,(char *)work); /* Initial permutation */
#if defined (LITTLE_ENDIAN)
work[0 ] = byteswap(work[0 ]);
work[1 ] = byteswap(work[1 ]);
#endif
/* Left/right half swap */
tmp = work[0 ];
work[0 ] = work[1 ];
work[1 ] = tmp;
#if TRACE
printf("dedes 1=%x %x\n" ,work[0 ],work[1 ]);
#endif
/* Do the 16 rounds in reverse order */
for (i=15 ; i >= 0 ; i--)
desround(i,work);
#if defined (LITTLE_ENDIAN)
work[0 ] = byteswap(work[0 ]);
work[1 ] = byteswap(work[1 ]);
#endif
#if TRACE
printf("desround=%x %x\n" ,work[0 ],work[1 ]);
#endif
permute((char *)work,fperm,block); /* Inverse initial permutation */
#if TRACE
printf("dedes 2=%x %x\n" ,work[0 ],work[1 ]);
#endif
}
/* Permute inblock with perm */
static void permute(char *inblock,char perm[16 ][16 ][8 ],char *outblock) {
/* result into outblock,64 bits */
/* 2K bytes defining perm. */
int i,j;
char *ib, *ob; /* ptr to input or output block */
char *p, *q;
#if TRACE
printf("inblock=%02x%02x%02x%02x%02x%02x%02x%02x\n" ,
inblock[0 ],inblock[1 ],inblock[2 ],inblock[3 ],inblock[4 ],inblock[5 ],inblock[6 ],inblock[7 ]);
#endif
if (perm == NULL){
/* No permutation, just copy */
for (i=8 ; i!=0 ; i--)
*outblock++ = *inblock++;
return ;
}
/* Clear output block */
for (i=8 , ob = outblock; i != 0 ; i--)
*ob++ = 0 ;
ib = inblock;
for (j = 0 ; j < 16 ; j += 2 , ib++) { /* for each input nibble */
int ix=(*ib >> 4 ) & 017 ;
int iy=*ib & 017 ;
ob = outblock;
p = perm[j][ix];
q = perm[j + 1 ][iy];
#if TRACE
printf("(ix,iy)=(%i,%i) (p,q)=(%02x%02x%02x%02x%02x%02x%02x%02x,%02x%02x%02x%02x%02x%02x%02x%02x)\n" ,
ix,iy,p[0 ],p[1 ],p[2 ],p[3 ],p[4 ],p[5 ],p[6 ],p[7 ],q[0 ],q[1 ],q[2 ],q[3 ],q[4 ],q[5 ],q[6 ],q[7 ]);
#endif
for (i = 8 ; i != 0 ; i--){ /* and each output byte */
*ob++ |= *p++ | *q++; /* OR the masks together*/
}
}
#if TRACE
printf("outblock=%02x%02x%02x%02x%02x%02x%02x%02x\n" ,
outblock[0 ],outblock[1 ],outblock[2 ],outblock[3 ],outblock[4 ],outblock[5 ],outblock[6 ],outblock[7 ]);
#endif
}
/* Do one DES cipher round */
static void desround(int num,unsigned long *block) { /* i.e. the num-th one */
//long f();
/* The rounds are numbered from 0 to 15. On even rounds
* the right half is fed to f ( ) and the result exclusive - ORs
* the left half ; on odd rounds the reverse is done .
*/
if (num & 1 ){
block[1 ] ^= f(block[0 ],kn[num]);
} else {
block[0 ] ^= f(block[1 ],kn[num]);
}
}
/* The nonlinear function f(r,k), the heart of DES */
static long f(unsigned long r,char subkey[8 ]) { /* 32 bits */
/* 48-bit key for this round */
long rval,rt;
#if TRACE
char *cp;
int i;
printf("f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = " ,
r,
subkey[0 ], subkey[1 ], subkey[2 ],
subkey[3 ], subkey[4 ], subkey[5 ],
subkey[6 ], subkey[7 ]);
#endif
/* Run E(R) ^ K through the combined S & P boxes
* This code takes advantage of a convenient regularity in
* E , namely that each group of 6 bits in E ( R ) feeding
* a single S - box is a contiguous segment of R .
*/
rt = (r >> 1 ) | ((r & 1 ) ? 0 x80000000 : 0 );
rval = 0 ;
rval |= sp_[0 ][((rt >> 26 ) ^ *subkey++) & 0 x3f];
rval |= sp_[1 ][((rt >> 22 ) ^ *subkey++) & 0 x3f];
rval |= sp_[2 ][((rt >> 18 ) ^ *subkey++) & 0 x3f];
rval |= sp_[3 ][((rt >> 14 ) ^ *subkey++) & 0 x3f];
rval |= sp_[4 ][((rt >> 10 ) ^ *subkey++) & 0 x3f];
rval |= sp_[5 ][((rt >> 6 ) ^ *subkey++) & 0 x3f];
rval |= sp_[6 ][((rt >> 2 ) ^ *subkey++) & 0 x3f];
rt = (r << 1 ) | ((r & 0 x80000000) ? 1 : 0 );
rval |= sp_[7 ][(rt ^ *subkey) & 0 x3f];
#if TRACE
printf(" %08lx\n" ,rval);
#endif
return rval;
}
/* initialize a perm array */
static void perminit(char perm[16 ][16 ][8 ],char p[64 ]) { /* 64-bit, either init or final */
int l, j, k;
int i,m;
/* Clear the permutation array */
for (i=0 ; i<16 ; i++)
for (j=0 ; j<16 ; j++)
for (k=0 ; k<8 ; k++)
perm[i][j][k]=0 ;
for (i=0 ;i<16 ;i++) { /* each input nibble position */
for (j = 0 ;j<16 ;j++) { /* each possible input nibble */
for (k = 0 ; k < 64 ; k++)/* each output bit position */
{ l = p[k] - 1 ; /* where does this bit come from*/
if ((l >> 2 ) != i) /* does it come from input posn?*/
continue ; /* if not, bit k is 0 */
if (!(j & nibblebit[l & 3 ]))
continue ; /* any such bit in input? */
m = k & 07 ; /* which bit is this in the byte*/
perm[i][j][k>>3 ] |= bytebit[m];
#if TRACE
printf("perminit l=%i perm[%i][%i][%i]=%i\n" ,l,i,j,k>>3 ,perm[i][j][k>>3 ]);
#endif
}}}
}
/* Initialize the lookup table for the combined S and P boxes */
static void spinit() {
char pbox[32 ];
int p,i,s,j,rowcol;
long val;
/* Compute pbox, the inverse of p32i.
* This is easier to work with
*/
for (p=0 ;p<32 ;p++){
for (i=0 ;i<32 ;i++){
if (p32i[i]-1 == p){
pbox[p] = i;
break ;
}
}
}
for (s = 0 ; s < 8 ; s++){ /* For each S-box */
for (i=0 ; i<64 ; i++){ /* For each possible input */
val = 0 ;
/* The row number is formed from the first and last
* bits ; the column number is from the middle 4
*/
rowcol = (i & 32 ) | ((i & 1 ) ? 16 : 0 ) | ((i >> 1 ) & 0 xf);
for (j=0 ;j<4 ;j++){ /* For each output bit */
if (si[s][rowcol] & (8 >> j)){
val |= 1 L << (31 - pbox[4 *s + j]);
}
}
sp_[s][i] = val;
#ifdef DEBUG
printf("sp_[%d][%2d] = %08lx\n" ,s,i,sp_[s][i]);
#endif
}
}
}
#if defined (LITTLE_ENDIAN)
/* Byte swap a long */
static unsigned long byteswap(unsigned long x) {
char *cp,tmp;
cp = (char *)&x;
tmp = cp[3 ];
cp[3 ] = cp[0 ];
cp[0 ] = tmp;
tmp = cp[2 ];
cp[2 ] = cp[1 ];
cp[1 ] = tmp;
return x;
}
#endif
//------------------------------------------------------------------------------
// E n d e d i e s e r Q u e l l e
//------------------------------------------------------------------------------
Messung V0.5 in Prozent C=78 H=73 G=75
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland