/* 
#  This is version 0.3 of absent
#
#               Copyright (c) 1999 by AT&T.
#  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.
#
#  SOME PARTS OF ABSENT MAY BE RESTRICTED UNDER UNITED STATES EXPORT
#  REGULATIONS.
#
#  THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
#  IMPLIED WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE
#  ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
#  MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
#  PURPOSE.
*/
/* This file contains

      void gen_master_key(master_secret)
         takes in a C_Block and sets it to
         64 bits of true random

      int gen_key(master_key,new_key)
         takes in a master_key and a C_Block
         and sets new_key to a new value, hmac_md5
         as a pseudorandom function

      int check_time(time_t candidate_time)
         returns 0 if time has expired, and
         a 1 otherwise

*/

#include "keys.h"




/* Generate a master key using true rand from cryptolib 
   which is currently in absent/random/randbyte.c (librand.a) */

void gen_master_key(master_secret)
C_Block master_secret;

{
unsigned long half1;
unsigned long half2;

   half1 = trand32();
   half2 = trand32();

   bcopy(&half1,master_secret,4);
   bcopy(&half2,master_secret+4,4);

}
   


/* Generates a key from the master key 
   returns -1 on error, 0 otherwise */

int gen_key(counter,master_key,new_key)
     /* in our original implementation, this used DES as a PRNG.
	however, owing to export considerations, we can't go
	that route in the shipping version.  this uses the less-
	secure approach of HMAC_MD5.  concerned users may want to
	modify 	this code. */
long counter;
C_Block master_key;
C_Block new_key;

{
  C_Block counter_string;
  unsigned char keytemp[65];
  
  counter++;
  store_key(counter, master_key,MASTER_KEY); /* Must increment master
                                                     key in file */
   bcopy(&counter,counter_string,4);
   bzero(counter_string+4,4);
   hmac_md5(counter_string, 4, master_key, 8, keytemp);
   /* we need to truncate here; it's no great loss, but it's worth
      noting that this further weakens this as an rng. */
   bcopy(keytemp, new_key, 8);
   return(0);
}

/* returns 0 if time has expired and a 1 if not */

int check_time(candidate_time)
time_t candidate_time;

{
time_t temp_time;

   temp_time = time(NULL) + SLACK_TIME;

   if (candidate_time > temp_time) {
      return(0);
   } else {
      return(1);
   }

}

/* Store the key in filename */
/* If counter is not zero, it is stored first, then the key */
/* If counter is zero, only key is stored */

void store_key(counter,key,filename)
long counter;
unsigned char*  key;
char *filename;

{

int fd;

   if ( (fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRWXU)) < 0)
      printf("Cannot create key file.\n");

   if (counter != 0) {
       if ( write(fd,&counter,4) !=4 )
          printf("Error writing counter.\n");
   }

   if(write(fd,key,8) != 8)
      printf("Error writing key.\n");

   close(fd);  

}


/* Assumes key is already allocated 8 bytes */
/* If counter is sent in as a zero, don't read in a
   counter. 
   Returns 1 on success, -1 on failure */

int read_key(counter,key,filename)
long *counter;
unsigned char*  key;
char *filename;

{

int fd;

   if ( (fd = open(filename,O_RDONLY)) < 0)
      syslog(LOG_ERR, "Cannot create key file: ");

   if (counter) {
       if(read(fd,counter,4) != 4)
           syslog(LOG_ERR, "Error reading counter ");
   }
      

   if(read(fd,key,8) != 8) {
      syslog(LOG_ERR, "Error reading key. ");
      return(-1);
   }

   close(fd);  

   return(1);
}












