/*
 * T.C.F.S. Utils 2.0 $Revision: 2.1 $
 *
 * Authors:	Giuseppe Cattaneo, <cattaneo@udsab.dia.unisa.it>
 *		Giuseppe Persiano, <giuper@udsab.dia.unisa.it>
 *		Luigi Catuogno, <luicat@mikonos.dia.unisa.it>
 *		Angelo Celentano, <angcel@mikonos.dia.unisa.it>
 *		Andrea Cozzolino, <andcoz@mikonos.dia.unisa.it>
 *		Aniello Del Sorbo, <anidel@mikonos.dia.unisa.it>
 *		Ermelindo Mauriello, <ermmau@mikonos.dia.unisa.it>
 *		Raffaele Pisapia, <rafpis@mikonos.dia.unisa.it>
 *
 * Permission  to use,  copy,  and modify this  software  without fee
 * is hereby granted, provided that this entire notice is included in
 * all  copies  of  any  software  which  is  or includes  a copy  or
 * modification of this  software and in all copies of the supporting
 * documentation for such software.
 *
 * This  software maybe  be used for  any purpose provided  the above 
 * copyright  notice  is  retained.  It is  supplied as  is, with  no 
 * warranty expressed or implied.
 */

/*
 *       $Source: /home/anidel/Wip/TCFS-2.2.0a/tcfslib-0.2/src/RCS/gentcfskey.c,v $
 *        $State: Exp $
 *
 *     $Revision: 2.1 $
 *       $Author: anidel $
 *         $Date: 1998/11/02 15:38:55 $
 *       $Locker:  $
 */

static const char *RCSid="$Id: gentcfskey.c,v 2.1 1998/11/02 15:38:55 anidel Exp $";
/* -+-_== */ 

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

#include "md5.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;
}
