/*
   Copyright R.M.A.Lucock 1991
*/

/*
* Function to DES encrypt a block of 64 bits, given the key bits in
* an external array _KSB. The input block has the bits numbered in
* reverse order to the usual convention for programming. During the
* initial permutation, DES 'bit 1' is mapped to standard 'bit' 1
* of the lower word. The final permutation reverses this so that
* everything looks OK to DES on exiting this routine.
*/

#include "adesdat.h"

extern unsigned long *KSB;
static unsigned long mask[32] =
   {
   0x80000000,0x40000000,0x20000000,0x10000000,0x8000000,0x4000000,0x2000000,0x1000000,
   0x800000,0x400000,0x200000,0x100000,0x80000,0x40000,0x20000,0x10000,
   0x8000,0x4000,0x2000,0x1000,0x800,0x400,0x200,0x100,
   0x80,0x40,0x20,0x10,0x8,0x4,0x2,0x1
   };

void encrypt(unsigned long *block, int nmode)
{
unsigned long XHP[2] , RHP , LHP , temp;
register unsigned long d2 , d5 , d6 , loop , *a0 , *a6;
int wloop , mloop , nloop;

#ifdef NMODE

int bytex , wordex;

union
   {
   unsigned long l;
   unsigned char c[4];
   } stx1 , stx2;

#endif


a6 = (unsigned long *)&KSB;
d5 = d6 = 0;
a0 = fp_tab;

#ifdef NMODE
wordex = nmode & 2;
if(wordex != 0)
   {
   temp = block[1];
   block[1] = block[0];
   block[0] = temp;
   }

bytex = nmode & 1;
if(bytex != 0)
   {
   for(loop=0; loop < 2; ++loop)
      {
      stx1.l = block[loop];
      stx2.c[0] = stx1.c[3];
      stx2.c[1] = stx1.c[2];
      stx2.c[2] = stx1.c[1];
      stx2.c[3] = stx1.c[0];
      block[loop] = stx2.l;
      }
   }
#endif


/* do initial perm */

for(wloop = 0; wloop < 2; ++wloop)
   {
   d2 = block[wloop];
   loop = 0;
   while(loop < 32)
      {
      if(d2 & mask[loop++])
         d6 |= *a0;

      ++a0;

      if(d2 & mask[loop++])
         d5 |= *a0;

      ++a0;
      }
   }

d2 = RHP = d6;
LHP  = d5;


/*
* Now do 16 iterations
*/

for(mloop=0; mloop < 16; ++mloop)
   {

/*
* expand the right hand side of the block (upper long word) from 32
* bits to 48, using the E-bit table.
* We loop from upper bits to lower bits so that we can use the loop
* counter for indexing
*/

   d5 = d6 = 0;

   if(d2 & 0x1)
      {
      d5 |= 0x2;
      d6 |= 0x8000;
      }

   if(d2 & 0x2)
      {
      d5 |= 0x4;
      }

   if(d2 & 0x4)
      {
      d5 |= 0x8;
      }

   if(d2 & 0x8)
      {
      d5 |= 0x10;
      d5 |= 0x40;
      }

   if(d2 & 0x10)
      {
      d5 |= 0x20;
      d5 |= 0x80;
      }

   if(d2 & 0x20)
      {
      d5 |= 0x100;
      }

   if(d2 & 0x40)
      {
      d5 |= 0x200;
      }

   if(d2 & 0x80)
      {
      d5 |= 0x400;
      d5 |= 0x1000;
      }

   if(d2 & 0x100)
      {
      d5 |= 0x800;
      d5 |= 0x2000;
      }

   if(d2 & 0x200)
      {
      d5 |= 0x4000;
      }

   if(d2 & 0x400)
      {
      d5 |= 0x8000;
      }

   if(d2 & 0x800)
      {
      d5 |= 0x10000;
      d5 |= 0x40000;
      }

   if(d2 & 0x1000)
      {
      d5 |= 0x20000;
      d5 |= 0x80000;
      }

   if(d2 & 0x2000)
      {
      d5 |= 0x100000;
      }

   if(d2 & 0x4000)
      {
      d5 |= 0x200000;
      }

   if(d2 & 0x8000)
      {
      d5 |= 0x400000;
      d5 |= 0x1000000;
      }

   if(d2 & 0x10000)
      {
      d5 |= 0x800000;
      d5 |= 0x2000000;
      }

   if(d2 & 0x20000)
      {
      d5 |= 0x4000000;
      }

   if(d2 & 0x40000)
      {
      d5 |= 0x8000000;
      }

   if(d2 & 0x80000)
      {
      d5 |= 0x10000000;
      d5 |= 0x40000000;
      }

   if(d2 & 0x100000)
      {
      d5 |= 0x20000000;
      d5 |= 0x80000000;
      }

   if(d2 & 0x200000)
      {
      d6 |= 0x1;
      }

   if(d2 & 0x400000)
      {
      d6 |= 0x2;
      }

   if(d2 & 0x800000)
      {
      d6 |= 0x4;
      d6 |= 0x10;
      }

   if(d2 & 0x1000000)
      {
      d6 |= 0x8;
      d6 |= 0x20;
      }

   if(d2 & 0x2000000)
      {
      d6 |= 0x40;
      }

   if(d2 & 0x4000000)
      {
      d6 |= 0x80;
      }

   if(d2 & 0x8000000)
      {
      d6 |= 0x100;
      d6 |= 0x400;
      }

   if(d2 & 0x10000000)
      {
      d6 |= 0x200;
      d6 |= 0x800;
      }

   if(d2 & 0x20000000)
      {
      d6 |= 0x1000;
      }

   if(d2 & 0x40000000)
      {
      d6 |= 0x2000;
      }

   if(d2 & 0x80000000)
      {
      d5 |= 0x1;
      d6 |= 0x4000;
      }


/*
* Now exclusive-or the results with the key for this iteration
*/

   d5 ^= *(a6++);
   d6 ^= *(a6++);

/*
* We now have 48 bits, in 8 groups of six bits. We use each group
* to index into relevant the s-box table to pick up a four bit number
* which will replace the six bit number. We label the groups 1-8.
*/

   a0 = sbox_tab;
   temp = d6;
   d6 = 0;
   for(loop=0; loop < 5; ++loop)
      {
      d2 = (d5 & 63);
      d5 >>= 6;
      d6 |= a0[d2];
      a0 += 64;
      }

/*
* We now have the lower two bits of group 6 in d3, and the upper four
* bits in d4.
*/

   d5 |= (temp<<2);

   for(loop=0; loop < 3; ++loop)
      {
      d2 = (d5 & 63);
      d5 >>= 6;
      d6 |= a0[d2];
      a0 += 64;
      }

/*
* the result is in register d6. We permute it using the P table. This is
* a simple 32-bit to 32-bit perm.
*/

   d2 = 0;

   if(d6 & 0x8000)
      d2 |= 0x1;

   if(d6 & 0x40)
      d2 |= 0x2;

   if(d6 & 0x80000)
      d2 |= 0x4;

   if(d6 & 0x100000)
      d2 |= 0x8;

   if(d6 & 0x10000000)
      d2 |= 0x10;

   if(d6 & 0x800)
      d2 |= 0x20;

   if(d6 & 0x8000000)
      d2 |= 0x40;

   if(d6 & 0x10000)
      d2 |= 0x80;

   if(d6 & 0x1)
      d2 |= 0x100;

   if(d6 & 0x4000)
      d2 |= 0x200;

   if(d6 & 0x400000)
      d2 |= 0x400;

   if(d6 & 0x2000000)
      d2 |= 0x800;

   if(d6 & 0x10)
      d2 |= 0x1000;

   if(d6 & 0x20000)
      d2 |= 0x2000;

   if(d6 & 0x40000000)
      d2 |= 0x4000;

   if(d6 & 0x200)
      d2 |= 0x8000;

   if(d6 & 0x2)
      d2 |= 0x10000;

   if(d6 & 0x80)
      d2 |= 0x20000;

   if(d6 & 0x800000)
      d2 |= 0x40000;

   if(d6 & 0x2000)
      d2 |= 0x80000;

   if(d6 & 0x80000000)
      d2 |= 0x100000;

   if(d6 & 0x4000000)
      d2 |= 0x200000;

   if(d6 & 0x4)
      d2 |= 0x400000;

   if(d6 & 0x100)
      d2 |= 0x800000;

   if(d6 & 0x40000)
      d2 |= 0x1000000;

   if(d6 & 0x1000)
      d2 |= 0x2000000;

   if(d6 & 0x20000000)
      d2 |= 0x4000000;

   if(d6 & 0x20)
      d2 |= 0x8000000;

   if(d6 & 0x200000)
      d2 |= 0x10000000;

   if(d6 & 0x400)
      d2 |= 0x20000000;

   if(d6 & 0x8)
      d2 |= 0x40000000;

   if(d6 & 0x1000000)
      d2 |= 0x80000000;


/*
* All of this has been done on the right hand part (RHP) of the block
* (the upper long word). We now exclusive-or the result with the LHP;
* the original RHP becomes the LHP while the result becomes the new
* RHP
*/

   d2 ^= LHP;
   LHP = RHP;
   RHP = d2;

/*
* This is the end of the main iteration loop.
*/

   }

/*
* Now exchange RHP and LHP before performing the final iteration
*/

XHP[0] = RHP;
XHP[1] = LHP;

a0 = ip_tab;
d5 = d6 = 0;


/* do final perm */

for(wloop=0; wloop < 2; ++wloop)
   {
   d2 = XHP[wloop];
   loop = 32;
   for(mloop=0; mloop < 4; ++mloop)
      {
      for(nloop=0; nloop < 4; ++nloop)
         {
         if(d2 & mask[--loop])
            d6 |= *a0;

         ++a0;
         }

      for(nloop=0; nloop < 4; ++nloop)
         {
         if(d2 & mask[--loop])
            d5 |= *a0;

         ++a0;
         }
      }
   }


block[0] = d5;
block[1] = d6;


#ifdef NMODE
if(bytex != 0)
   {
   for(loop=0; loop < 2; ++loop)
      {
      stx1.l = block[loop];
      stx2.c[0] = stx1.c[3];
      stx2.c[1] = stx1.c[2];
      stx2.c[2] = stx1.c[1];
      stx2.c[3] = stx1.c[0];
      block[loop] = stx2.l;
      }
   }

if(wordex != 0)
   {
   temp = block[1];
   block[1] = block[0];
   block[0] = temp;
   }
#endif
}

