/* LINTLIBRARY */
/*
 * This routine takes a UNIX encrypted password, obtains the output
 * of the cryptographic function, and applies ip * (e,e) to it.  The
 * result is useful for dictionary search attacks on passwords.
 *
 * ENTRY POINT: unsigned char *decrypt(pw)
 * ARGUMENTS:	char *pw;
 *			The 13 character encrypted password
 * RETURNS:	see above
 * SIDE EFFECT: The output is stored in a static array and so will be
 *		overwritten every time this routine is called.
 *
 * (c) Copyright 1987 by Matt Bishop and the Universities Space Research
 *			 Association.
 * This work was funded by grant NCC 2-398 from the National Aeronautics
 * and Space Administration to the Universities Space Research Association.
 *
 * Author's Address:
 *		Matt Bishop
 *		Research Institute for Advanced Computer Science
 *		NASA Ames Research Center
 *		Moffett Field, CA  94035
 * ARPANET:	mab@riacs.edu, mab@icarus.riacs.edu
 * CSNET:	mab@riacs.edu
 * UUCP:	...!decvax!decwrl!riacs!mab
 *		...!ihnp4!ames!riacs!mab
 *		...!ucbvax!ames!riacs!mab
 */

#include <stdio.h>
#include "des.h"

#define MAXKEYS	8192

/*
 * the static array for the encrypted password
 */
static long rval[MAXKEYS][2];			/* buffer for decryption */

long **decrypt(pw, cnt)
     char pw[][14];			/* password */
     long cnt;
{
  register int i;			/* counters in for loops */
  unsigned char c[11];		/* used to convert back to password */
  unsigned char msg[MAXKEYS][8];			/* buffer for decryption */
  long t;
  
  /*
   * invert the mapping to [./0-9A-Za-z]
   */
  for(t = 0; t < cnt; t++) {
    for(i = 2; i < 13; i++){
      if (pw[t][i] > 'Z')
	c[i-2] = pw[t][i] - 6 - 7 - '.';
      else if (pw[t][i] > '9')
	c[i-2] = pw[t][i] - 7 - '.';
      else
	c[i-2] = pw[t][i] - '.';
    }
    /*
     * explode the bits
     */
    msg[t][0] = (c[0]<<2)|((c[1]>>4)&0x3);
    msg[t][1] = ((c[1]&0xf)<<4)|((c[2]>>2)&0xf);
    msg[t][2] = ((c[2]&0x3)<<6)|c[3];
    msg[t][3] = (c[4]<<2)|((c[5]>>4)&0x3);
    msg[t][4] = ((c[5]&0xf)<<4)|((c[6]>>2)&0xf);
    msg[t][5] = ((c[6]&0x3)<<6)|c[7];
    msg[t][6] = (c[8]<<2)|((c[9]>>4)&0x3);
    msg[t][7] = ((c[9]&0xf)<<4)|((c[10]>>2)&0xf);

  }
  /*
   * apply ip * (e, e)
   * and then swap the halves
   */
  shc_ine(msg, rval, cnt);
  
  /*
   * return the address of the result
   */
  return(rval);
}

/*
 * the static array for the encrypted password
 */
static long msg[MAXKEYS][2];

long **shc_crypt(pw, salt, cnt)
     char pw[][9];			/* password */
     char salt[][3];			/* salt */
     long cnt;
{
  register int i;			/* counters in for loops */
  unsigned char kpw[MAXKEYS][8];		/* message, key used to run des */
  long t;
  /*
   * initialize the key and message to 0
   */
  for(t=0; t< cnt; t++)
    for(i = 0; i < 8; i++)
      kpw[t][i] = 0x00;
  
  /*
   * now build the key and set it
   */
  for(t = 0; t < cnt; t++) 
    for(i = 0; pw[t][i] && i < 8; i++)
      kpw[t][i] = ((pw[t][i])&0x7f)<<1;
  shc_key(kpw, cnt);
  
  /*
   * this sets up the seed and permutes the relevant tables
   */
  init_shc(salt, cnt);
  
  /*
   * the heart of the password algorithm --
   * encrypt the 0 message 25 times
   */
  shc_run(msg);
  
  /*
   * return the message
   */
  return(msg);
}

/*
 * This initializes the salt; it puts it in a form the 
 * fast DES algorithm can use to best advantage
 */
static init_shc(seed, cnt)
     char seed[][3];			/* the two-character salt */
{
  register int i, j, k;		/* counters in for loops */
  register int c;			/* used to permute eperm[] array */
  long salt[MAXKEYS];		/* the bitmask passed to make the salt */
  long t;
  
  /*
   * juggle the array
   */
  for(t=0; t < cnt; t++) {
    salt[t] = 0;
    for(i = 0; i < 2; i++){
      /*
       * map it into a permutation character
       */
      c = seed[t][i];
      if (c > 'Z') 
	c -= 6;
      if (c > '9')
	c -= 7;
      c -= '.';
      /*
       * permute
       */
      for (j = 0; j < 6; j++){
	k = 6 * i + j;
	salt[t] |= ((c>>j)&01)<<(11-k);
      }
    }
  }
  shc_makesalt(salt,cnt);
}

