/* This file is responsible for decrypting an encrypted file. It 
   takes the following arguments:

   PKE-decode {name} {source} {dest}

        {name}   : name of person whose private key is to be
	           used.
	
	{source} : source filename, or '-' for stdin.
	{dest}   : destination filename, or '-' for stdout.
*/

#include "incremental.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <pwd.h>

void read_key(char *, R_RSA_PRIVATE_KEY *),
  pke_decrypt(int, int, R_RSA_PRIVATE_KEY),
  get_home(char *);

int main(int argc, char *argv[]) {
  int fdin, fdout;
  R_RSA_PRIVATE_KEY key;

  if (argc != 4) { 
    fprintf(stderr, "usage: %s {name} {source} {dest}\n", argv[0]);
    fprintf(stderr, "\t where {source} and {dest} may be '-' for\n");
    fprintf(stderr, "\t stdin or stdout respectively\n");
    exit(1);
  }
  
  if (!strcmp("-", argv[2]))
    fdin = STDIN_FILENO;
  else
    if ((fdin = open(argv[2], O_RDONLY)) < 0) {
      perror("input open");
      exit(1);
    }
  if (!strcmp("-", argv[3]))
    fdout = STDOUT_FILENO;
  else
    if ((fdout = open(argv[3], O_RDWR|O_CREAT, S_IRUSR|S_IWUSR))<0){
      perror("output open");
      exit(1);
    }

  read_key(argv[1], &key);
  pke_decrypt(fdin, fdout, key);
}
	
void read_key(char *name, R_RSA_PRIVATE_KEY *key){
  /* reads a key in from {name}.prv, and returns the key */
  int fd;
  char keyname[MAXPATHLEN];
  
  get_home(keyname);
  strcat(keyname, PKE_PATH);
  strcat(keyname, name);
  strcat(keyname, ".prv");

  if ((fd = open(keyname, O_RDONLY)) < 0) {
    perror("key input open failed");
    exit(1);
    }
  
  read(fd, &(key->bits), sizeof(key->bits));
  read(fd, &(key->modulus), sizeof(key->modulus));
  read(fd, &(key->publicExponent), sizeof(key->publicExponent));
  read(fd, &(key->exponent), sizeof(key->exponent));
  read(fd, &(key->prime[0]), sizeof(key->prime[0]));
  read(fd, &(key->prime[1]), sizeof(key->prime[1]));
  read(fd, &(key->primeExponent), sizeof(key->primeExponent));
  read(fd, &(key->coefficient), sizeof(key->coefficient));

  close(fd);
}


void pke_decrypt(int fdin, int fdout, R_RSA_PRIVATE_KEY key) {
  /* read from in, decode, output to out */
  char enc_data[MAX_ENC_DATA_LEN], out_data[DATA_SIZE], 
    temp[DATA_LEN];
  int outlen, status, inlen;

  while ((read(fdin, &inlen, sizeof(int)) == sizeof(int)) &&
	 (read(fdin, enc_data, inlen) == inlen)) {
    if ((status = RSAPrivateDecrypt
	 (temp, &outlen, enc_data, inlen, &key)) != 0)
      fprintf(stderr, "Error decrypting.. continuing\n");
    pke_decode(temp, out_data);
    if ((write(fdout, out_data, DATA_SIZE)) != DATA_SIZE)
      fprintf(stderr, "error writing data.. continuing\n");
  }
}

pke_decode(char *input, char *output){
  /* converts an encoded string with randomizer to just string */
  char *inptr = (input + RANDOM_PAD_SIZE) , *outptr;
  int count = 0;

  for (outptr = output;
       outptr < (output + DATA_SIZE);
       outptr++)
    *outptr = *inptr++;
}
    

void get_home(result)
char *result;
{
  struct passwd *pwd;
 
  if (strcpy(result,(char *)getenv("HOME")))
    return;
  if (pwd = getpwuid(getuid())){
    strcpy(result, pwd->pw_dir);
    return;
  }
  else{
    strcpy(result, "/");
    return;
  }
}
