mud_dist/area/
/*$Id: crypt.c,v 1.2 2005/02/22 23:55:16 ahsile Exp $*/

#include "crypt.h"

static void 
perm (a, e, pc, n)
     register char *a, *e;
     register char *pc;
     int n;
{
  for (; n--; pc++, a++)
    *a = e[*pc];
}

static void 
crypt_main (nachr_l, nachr_r, schl)
     register char *nachr_l, *nachr_r;
     register char *schl;
{
  char tmp[KS];
  register int sbval;
  register char *tp = tmp;
  register char *e = EE;
  register int i, j;

  for (i = 0; i < 8; i++)
    {
      for (j = 0, sbval = 0; j < 6; j++)
	sbval = (sbval << 1) | (nachr_r[*e++] ^ *schl++);
      sbval = S_BOX[i][sbval];
      for (tp += 4, j = 4; j--; sbval >>= 1)
	*--tp = sbval & 1;
      tp += 4;
    }

  e = PERM;
  for (i = 0; i < BS2; i++)
    *nachr_l++ ^= tmp[*e++];
}

void 
encrypt (char *nachr, int decr)
{
  char (*schl)[KS] = decr ? schluessel + 15 : schluessel;
  char tmp[BS];
  int i;

  perm (tmp, nachr, IP, BS);

  for (i = 8; i--;)
    {
      crypt_main (tmp, tmp + BS2, *schl);
      if (decr)
	schl--;
      else
	schl++;
      crypt_main (tmp + BS2, tmp, *schl);
      if (decr)
	schl--;
      else
	schl++;
    }

  perm (nachr, tmp, EP, BS);
}

void setkey (char *schl)
{
  char tmp1[IS];
  register unsigned int ls = 0x7efc;
  register int i, j, k;
  register int shval = 0;
  register char *akt_schl;

  memcpy (EE, E0, KS);
  perm (tmp1, schl, PC1, IS);

  for (i = 0; i < 16; i++)
    {
      shval += 1 + (ls & 1);
      akt_schl = schluessel[i];
      for (j = 0; j < KS; j++)
	{
	  if ((k = PC2[j]) >= IS2)
	    {
	      if ((k += shval) >= IS)
		k = (k - IS2) % IS2 + IS2;
	    }
	  else if ((k += shval) >= IS2)
	    k %= IS2;
	  *akt_schl++ = tmp1[k];
	}
      ls >>= 1;
    }
}

char *crypt (const char *pass, const char *salt)
{
  static char retkey[14];
  char key[BS + 2];
  char *k;
  int tmp, keybyte;
  int i, j;

  memset (key, 0, BS + 2);

  for (k = key, i = 0; i < BS; i++)
    {
      if (!(keybyte = *pass++))
	break;
      k += 7;
      for (j = 0; j < 7; j++, i++)
	{
	  *--k = keybyte & 1;
	  keybyte >>= 1;
	}
      k += 8;
    }

  setkey (key);
  memset (key, 0, BS + 2);

  for (k = EE, i = 0; i < 2; i++)
    {
      retkey[i] = keybyte = *salt++;
      if (keybyte > 'Z')
	keybyte -= 'a' - 'Z' - 1;
      if (keybyte > '9')
	keybyte -= 'A' - '9' - 1;
      keybyte -= '.';

      for (j = 0; j < 6; j++, keybyte >>= 1, k++)
	{
	  if (!(keybyte & 1))
	    continue;
	  tmp = *k;
	  *k = k[24];
	  k[24] = tmp;
	}
    }

  for (i = 0; i < 25; i++)
    encrypt (key, 0);

  for (k = key, i = 0; i < 11; i++)
    {
      for (j = keybyte = 0; j < 6; j++)
	{
	  keybyte <<= 1;
	  keybyte |= *k++;
	}

      keybyte += '.';
      if (keybyte > '9')
	keybyte += 'A' - '9' - 1;
      if (keybyte > 'Z')
	keybyte += 'a' - 'Z' - 1;
      retkey[i + 2] = keybyte;
    }

  retkey[i + 2] = 0;

  if (!retkey[1])
    retkey[1] = *retkey;

  return retkey;
}