/* DES encryption command.  Original by JIS (I think) */

/*
 *------------------------------------------------------------------
 *
 * $Source: /afs/net.mit.edu/tools/src/crypt/RCS/des_crypt.c,v $
 * $Revision: 1.1 $
 * $Date: 90/03/26 19:29:32 $
 * $State: Exp $
 * $Author: tom $
 * $Locker:  $
 *
 * $Log:	des_crypt.c,v $
 * Revision 1.1  90/03/26  19:29:32  tom
 * Initial revision
 * 
 * Revision 1.2  90/03/25  17:57:07  jon
 * make it work with new krb names and add informational messages (time and header)
 * 
 *------------------------------------------------------------------
 */

#ifndef lint
static char *rcsid_des_crypt_c = "$Header: /afs/net.mit.edu/tools/src/crypt/RCS/des_crypt.c,v 1.1 90/03/26 19:29:32 tom Exp $";
#endif	lint

#include <sys/file.h>
#include <sys/time.h>
#include <stdio.h>
#include <pwd.h>
#include "des.h"
Key_schedule KEYSCHED;
C_Block key;
char inbuf[512];
char oubuf[512];
int ind;
int oud;

#define VERSION "DESC0001"

struct header {
  char version[8];
  char username[8];
  unsigned long date_time;
  char hostname[32];
};

main(argc,argv)
int argc;
char *argv[];
{
  int encrypt, length, *p;
  struct timeval start, end;
  struct header h;
  long ivec[2];
  struct passwd *pwd;

  if (argc != 4) {
    fprintf (stderr, "%s: Usage: %s infile outfile mode.\n", argv[0],
	     argv[0]);
    exit (1);
  }
  if (!strcmp(argv[3], "e")) encrypt = 1;
  else if(!strcmp(argv[3], "d")) encrypt = 0;
  else {
    encrypt = 777; /* shut the compiler up */
    fprintf (stderr, "%s: Mode must be e (encrypt) or d (decrypt).\n",
	     argv[0]);
    exit (1);
  }

  if ((ind = open(argv[1], O_RDONLY, 0666)) < 0) {
    fprintf (stderr, "%s: Cannot open %s for input.\n",
	     argv[0], argv[1]);
    exit (1);
  }
  if (!strcmp(argv[2], "-")) oud = dup(1);
  else if ((oud = open(argv[2], O_CREAT|O_WRONLY, 0666)) < 0) {
    fprintf (stderr, "%s: Cannot open %s for output.\n",
	     argv[0], argv[2]);
    exit (1);
  }
  (void) freopen ("/dev/tty", "r", stdin);
  (void) freopen ("/dev/tty", "w", stdout);
  des_read_password (key, "Enter Key (remember it!!)> ", 1);
  if (des_key_sched (key, KEYSCHED) < 0) {
    fprintf (stderr, "%s: Key parity error. des_key_sched failed.\n", argv[0]);
    exit (1);
  }

  bcopy((char *)&(key[0]), (char *)&ivec[0], 4);
  bcopy((char *)&(key[4]), (char *)&ivec[1], 4);

  if (gettimeofday(&start, 0)) {
    perror("Gettimeofday failed");
    exit (22);
  }

  fprintf (stderr, "\nStarting encryption at %s", ctime(&start.tv_sec));

  bzero (&h, sizeof(h));
  if (encrypt) {
    strncpy(h.version, VERSION, sizeof(h.version));
    if (pwd = getpwuid(getuid()))
      strncpy(h.username, pwd->pw_name, 8);
    gethostname(&h.hostname, sizeof(h.hostname));
    h.date_time = start.tv_sec;
    if (write(oud, &h, sizeof(h)) != sizeof(h)) {
      perror("header write failed");
      exit(33);
    }
  }
  else {
    if (read(ind, &h, sizeof(h)) != sizeof(h)) {
      perror("can't read file header");
      lseek(ind, 0, L_SET);
    }
    if (strncmp(h.version, VERSION, 8) != 0) {
      fprintf ("wrong version, trying to decrypt anyway.\n");
      lseek(ind, 0, L_SET);
    }
    fprintf(stderr, "\nFile originally encrypted by %s@%s on %s\n",
	    h.username, h.hostname, ctime(&h.date_time));
  }

  fflush(stderr);

  for (;;) {
    if((length = read (ind, inbuf, 512)) < 0) {
      fprintf (stderr, "%s: Error reading from input.\n", argv[0]);
      exit (1);
    } else if (length == 0) {
      fprintf (stderr, "\n");
      break;
    }
    cbc_encrypt (inbuf, oubuf, length, KEYSCHED, ivec, encrypt);
    length = (length+7)& ~07;
    write (oud, oubuf, length);
    if (encrypt) p = (int *)&oubuf[length-8];
    else p = (int *)&inbuf[length-8];
    ivec[0] = *p++;
    ivec[1] = *p;
  }

  if (gettimeofday(&end, 0)) {
    perror("Gettimeofday failed");
    exit (22);
  }

  fprintf (stderr, "Finished encryption at %s", ctime(&end.tv_sec));
  exit(0);
}

  
  
