/* $Id: des.c,v 2.3 2005/12/19 15:40:41 ksb Exp $ */ #include #include #include #include #include "machine.h" #include "passgen.h" /***************************************************************************** * DES.C VERSION 4.00 * *---------------------------------------------------------------------------* * D A T A E N C R Y P T I O N S T A N D A R D * * FEDERAL INFORMATION PROCESSING STANDARDS PUBLICATION (FIPS PUB) 46 * * JANUARY 15, 1977 * *---------------------------------------------------------------------------* * This software was produced at the National Institute of Standards (NIST) * * as a part of research efforts and is for demonstration purposes only. Our* * primary goals in its design did not include widespread use outside of * * our own laboratories. Acceptance of this software implies that you * * agree to use it for non-commercial purposes only and that you agree to * * accept it as nonproprietary and unlicensed, not supported by NIST, and * * not carrying any warranty, either expressed or implied, as to its * * performance or fitness for any particular purpose. * *---------------------------------------------------------------------------* * Cryptographic devices and technical data regarding them are subject to * * Federal Government export controls as specified in Title 22, Code of * * Federal Regulations, Parts 121 through 128. Cryptographic devices * * implementing the Data Encryption Standard (DES) and technical data * * regarding them must comply with these Federal regulations. * *---------------------------------------------------------------------------* * Produced at the National Institute of Standards and Technology (NIST) * * Computer Systems Laboratory (CSL) Security Technology Group (SECTECH) * ****************************************************************************/ /**************************************************************************** * SETKEY() Generate key schedule for given key and type of cryption * ****************************************************************************/ /* PERMUTED CHOICE 1 (PC1) */ UINT 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, }; /* Schedule of left shifts for C and D blocks */ USHORT shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 }; /* PERMUTED CHOICE 2 (PC2) */ UINT 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, }; /* Key schedule of 16 48-bit subkeys generated from 64-bit key */ BYTE KS[16][48]; int Setkey(sw1,sw2,pkey) int sw1; /* parity: 0=ignore,1=check */ int sw2; /* type cryption: 0=encrypt,1=decrypt */ BYTE *pkey; /* 64-bit key packed into 8 bytes */ { register UINT i, j, k, t1, t2; static BYTE key[64]; static BYTE CD[56]; /* Double-check 'parity' parameter */ if (sw1 != 0 && sw1 != 1) { (void)printf("\007*** Setkey: bad parity parameter (%d)\ ***\n", sw1); return(0); } /* Double-check 'type of cryption' parameter */ if (sw2 != 0 && sw2 != 1) { (void)printf("\007*** Setkey: bad cryption parameter (%d)\ ***\n",sw2); return(0); } /* Unpack KEY from 8 bits/byte into 1 bit/byte */ unpack8(pkey,key); /* Check for ODD key parity */ if (sw1 == 1) { for (i=0; i<64; i++) { k = 1; for (j=0; j<7; j++,i++) k = (k + key[i]) % 2; if (key[i] != k) return(0); } } /* Permute unpacked key with PC1 to generate C and D */ for (i=0; i<56; i++) CD[i] = key[PC1[i]-1]; /* Rotate and permute C and D to generate 16 subkeys */ for (i=0; i<16; i++) { /* Rotate C and D */ for (j=0; j>3) & 1; f[k+1] = (t>>2) & 1; f[k+2] = (t>>1) & 1; f[k+3] = t & 1; } for (j=0; j<32; j++) { /* Copy R */ t = LR[j+32]; /* Permute f w/ P and XOR w/ L to generate ne w R */ LR[j+32] = LR[j] ^ f[P[j]-1]; /* Copy original R to new L */ LR[j] = t; } } /* Permute L and R with reverse IP-1 to generate output block */ for (j=0; j<64; j++) block[j] = LR[RFP[j]-1]; /* Pack data into 8 bits per byte */ pack8(out,block); } /***************************************************************************** * PACK8() Pack 64 bytes at 1 bit/byte into 8 bytes at 8bits/byte * ****************************************************************************/ void pack8(packed,binary) BYTE *packed; /* packed block ( 8 bytes at 8 bits/byte) */ BYTE *binary; /* the unpacked block (64 bytes at 1 bit/byte ) */ { register UINT i, j, k; for (i=0; i<8; i++) { k = 0; for (j=0; j<8; j++) k = (k<<1) + *binary++; *packed++ = k; } } /**************************************************************************** * UNPACK8() Unpack 8 bytes at 8 bits/byte into 64 bytes at 1it/byte * ****************************************************************************/ void unpack8(packed,binary) BYTE *packed; /* packed block (8 bytes at 8 bits/byte) */ BYTE *binary; /* unpacked block (64 bytes at 1 bit/byte) */ { register UINT i, j, k; for (i=0; i<8; i++) { k = *packed++; for (j=0; j<8; j++) *binary++ = (k>>(7-j)) & 01; } } /**************************************************************************** * KRYPT() Encrypt/decrypt key or key pair * ***************************************************************************/ int krypt(sw1,sw2,sw3,kek,sw4,ikey,okey) int sw1; /* ODD parity: 0=ignore, 1=check & report */ int sw2; /* type of cryption: 0=encrypt, 1=decrypt */ int sw3; /* length of kek: 1=single, 2=pair */ BYTE *kek; /* packed key-encrypting key */ int sw4; /* length of key: 1=single, 2=pair */ BYTE *ikey; /* packed input key */ BYTE *okey; /* packed output key */ { BYTE tkey[PKEYLEN]; /* DOUBLE-CHECK PARAMETERS */ if (sw3!=SINGLE && sw3!=PAIR) { (void)printf("krypt: bad kek length (%d)",sw3); exit(1); } if (sw4!=SINGLE && sw4!=PAIR) { (void)printf("krypt: bad key length (%d)",sw4); exit(1); } if (sw3==SINGLE && sw4==PAIR) exit(1); if (!Setkey(sw1,sw2,kek)) return(FALSE); des(ikey,okey); if (sw3==SINGLE && sw4==SINGLE) return(TRUE); /* single by single */ if (!Setkey(sw1,sw2^01,kek+PKEYLEN)) return(FALSE); des(okey,tkey); (void) Setkey(sw1,sw2,kek); des(tkey,okey); if (sw4==SINGLE) return(TRUE); /* single by double */ (void) krypt(sw1,sw2,PAIR,kek,SINGLE,ikey+PKEYLEN,okey+PKEYLEN); return(TRUE); /* double by double */ } /*************************************************************************** * RANDOM() Pseudorandom KEY and IV Generator. * ***************************************************************************/ /* Random Key */ static BYTE rndkey[PAIR*PKEYLEN] = {0xE0,0x9A,0xA8,0x0F,0xAB,0x72,0x1C,0x3D, 0x8F,0x7D,0xC9,0x9E,0x8F,0x02,0xB6,0x2A}; /* Seed */ static BYTE seed[PKEYLEN] = {0xCF,0x65,0xAE,0x7F,0xB1,0x79,0xBB,0xE3}; void Random(dest,odd) BYTE *dest; /* destination for random KEY or IV */ int odd; /* generate ODD parity? 0=no, 1=yes */ { BYTE dt[PKEYLEN]; /* date/time vector */ BYTE i[PKEYLEN]; BYTE j[PKEYLEN]; BYTE r[PKEYLEN]; /* DOUBLE-CHECK PARAMETERS */ if (odd!=FALSE && odd!=TRUE) { (void)printf("random: bad generate parity option (%d)", odd); exit(1); } /* GET DATE/TIME VECTOR */ daytime(dt); /* I = eRNDKEY(DT) */ (void) krypt(IGNORE,ENCRYPT,PAIR,rndkey,SINGLE,dt,i); /* R = eRNDKEY(I + V) */ (void) bytnxor(j,i,seed,PKEYLEN); (void) krypt(IGNORE,ENCRYPT,PAIR,rndkey,SINGLE,j,r); /* new seed = eRNDKEY(R + I) */ (void) bytnxor(j,i,r,PKEYLEN); (void) krypt(IGNORE,ENCRYPT,PAIR,rndkey,SINGLE,j,seed); /* GENERATE ODD PARITY, IF NEEDED */ if (odd) set_parity(r,SINGLE); (void) bytncpy(dest,r,PKEYLEN); } /**************************************************************************** * SET_PARITY() Set ODD parity * ***************************************************************************/ void set_parity(key,len) BYTE *key; /* packed 64 or 128-bit key */ int len; /* key length: 1=SINGLE, 2=PAIR */ { int i, j, parity, mask; /* DOUBLE-CHECK PARAMETER */ if (len!=SINGLE && len!=PAIR) { (void)printf("set_parity: bad len parameter (%d)", len); exit(1); } for (i=0; i<(len*PKEYLEN); i++) { parity = 1; mask = 2; for (j=0; j<7; j++) { parity = (parity + ((key[i] & mask) >> (j+1))) % 2; mask = 2 * mask; } if (parity==0) key[i] = key[i] & 0xfe;/* clear */ if (parity==1) key[i] = key[i] | 0x01;/* set */ } } void daytime(dt) BYTE *dt; /* dt[8] = 64-bit block based on date & time */ { register int i; int tt[8]; time_t timer; struct tm *bdt; time_t time(); clock_t clock(); (void)time(&timer); bdt = localtime(&timer); tt[0] = bdt->tm_year; /* years since 1900 */ tt[1] = bdt->tm_mon; /* months since January - [0, 11] */ tt[2] = bdt->tm_mday; /* day of the month - [1, 31] */ tt[3] = bdt->tm_hour; /* hours since midnight - [0, 23] */ tt[4] = bdt->tm_min; /* minutes after the hour - [0, 59] */ tt[5] = bdt->tm_sec; /* seconds after the minute - [0, 59] */ tt[6] = bdt->tm_isdst; /* Daylight Saving Time flag */ tt[7] = (int)clock(); /* clock ticks since program invocation */ for (i=0;i<8;i++) dt[i] = (char) tt[i]; } /************************************************************************** * BYTNCPY() Copy block of packed BYTEs * **************************************************************************/ BYTE *bytncpy(dest,src,len) /* return pointer to destinat ion block */ BYTE *dest; /* destination block */ BYTE *src; /* source block */ int len; /* number of bytes */ { while (len-- > 0) *dest++ = *src++; return(dest); } /**************************************************************************** * BYTNXOR() XOR blocks of packed BYTEs * ****************************************************************************/ BYTE *bytnxor(dest,src1,src2,len) /* return ptr to des tination block */ BYTE *dest; /* destination block */ BYTE *src1; /* source block 1 */ BYTE *src2; /* source block 2 */ int len; /* number of BYTEs */ { while (len-- > 0) *dest++ = *src1++ ^ *src2++; return(dest); }