/*
 *	Transparent Cryptographic File System (TCFS) for NetBSD 
 *	Author and mantainer: 	Luigi Catuogno [luicat@tcfs.unisa.it]
 *	
 *	references:		http://tcfs.dia.unisa.it
 *				tcfs-bsd@tcfs.unisa.it
 */

/*
 *	Base utility set v0.1
 *
 *	  $Source: /home/luicat/source/lib/RCS/gentcfskey.c,v $
 *	   $State: Exp $
 *	$Revision: 1.1 $
 *	  $Author: luicat $
 *	    $Date: 1999/10/28 10:24:48 $
 *
 */

static const char *RCSid="$id: $";

/* RCS_HEADER_ENDS_HERE */



#include <stdio.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <kdes.h>

#include <md5.h>
#include <tcfs.h>
#include <tcfsdefines.h>

char *gentcfskey (void)
{
	int i=0, kcount=0;
	struct timeval tempo;
	struct termios oldtty, newtty;
	char *buff;
	OctetString *in, *res;
	des_key_schedule ks;
	
	buff=(char*)calloc(4096, sizeof(char));

	if (tcgetattr (0, &oldtty)<0)
	{
		fprintf (stderr, "This is not a terminal!!\n");
		exit (1);
	}

	bcopy (&oldtty, &newtty, sizeof (struct termios));
	newtty.c_lflag &= ~ICANON;
	newtty.c_lflag &= ~ECHO;
	newtty.c_cc[VMIN]=1;
	newtty.c_cc[VTIME]=0;
	printf ("press 10 keys:");
	fflush (stdout);

	if (tcsetattr (0, TCSANOW, &newtty)<0)
	{
		perror ("Error setting terminal attributes");
		exit (1);
	}

	while (kcount<10)
	{
		char c=0;
		if (read(0, &c, 1)==1)
		{
			struct timeval oldtempo;
	
			oldtempo.tv_sec=tempo.tv_sec;
			oldtempo.tv_usec=tempo.tv_usec;
			gettimeofday(&tempo, NULL);
			*(buff+kcount*9)=c;
			bcopy ((long*)&tempo.tv_sec, (char*)(buff+kcount*9+1), 4);
			tempo.tv_sec-=oldtempo.tv_sec;
			bcopy ((long*)&tempo.tv_sec, (char*)(buff+kcount*9+5), 4);
			printf("*");
			fflush (stdout);
			kcount++;
		}
	}

	if (tcsetattr (0, TCSANOW, &oldtty)<0)
	{
		perror ("Error while resetting terminal");
		exit (1);
	}

	printf ("\nOk.\n");
	in=(OctetString*)malloc(sizeof(OctetString));
	res=(OctetString*)malloc(sizeof(OctetString));
	res->octets=(char*)calloc(16,sizeof(char));
	in->octets=buff;
	in->noctets=KEYSIZE;
	md5_hash (in, res, SEC_END);

	while ((i*8)<=KEYSIZE)
	 {
	   des_set_key ((des_cblock *)res->octets, ks);
	   des_ecb_encrypt ((des_cblock *)(buff+i*8), (des_cblock *)(buff+i*8), ks, DES_ENCRYPT);
	   des_set_key ((des_cblock *)res->octets+KEYSIZE, ks);
	   des_ecb_encrypt ((des_cblock *)(buff+i*8), (des_cblock *)(buff+i*8), ks, DES_DECRYPT);
	   des_set_key ((des_cblock *)res->octets, ks);
	   des_ecb_encrypt ((des_cblock *)(buff+i*8), (des_cblock *)(buff+i*8), ks, DES_ENCRYPT);
	   i++;
 	 }

	*(buff+KEYSIZE)='\0';
	free(res->octets);
	free(res);
	free(in);

	return buff;
}
