/*                               -*- Mode: C -*- 
 * sslcrypt.c -- 
 * Copyright (c) 1995 Shaun Savage.
 * All rights reserved.
 *
 * Author          : Shaun Savage
 * Created On      : Sun May  7 16:05:57 1995
 * Last Modified By: Shaun Savage
 * Last Modified On: Sun May  7 17:32:08 1995
 * Update Count    : 6
 * Status          : Unknown, Use with caution!
 * PURPOSE
 * 	|>Contains the prottype and support routine for encryption <|
 * TABLE OF CONTENTS
 * 
 * dummyCrypt {
 *    data and functions 
 *    };
 */

#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "ssl.h"
#include "md5.h"

static
int Init(crypto *crypt,u_char *key, int klen, u_char *arg, int alen, int type)
   {
   return 0;
   }

static
int Update(crypto *crypt, u_char *obuf, u_char *ibuf, int len)
   {
   return 0;
   }

static
int Finish(crypto *crypt, u_char *buf, int len)
   {
   return 0;
   }

static
int enCrypt(crypto *crypt, u_char *buf, int len)
   {
   u_char tbuf[8] = "HEMPHEMP";
   Init(crypt, crypt->mKey, crypt->mkeyLen, crypt->arg, crypt->argLen, EN0);
   Update(crypt, buf, buf, len);
   Finish(crypt, tbuf, 0);
   return 0;
   }

static
int deCrypt(crypto *crypt, u_char *buf, int len)
   {
   u_char tbuf[8] = "HEMPHEMP";
   Init(crypt, crypt->mKey, crypt->mkeyLen, crypt->arg, crypt->argLen, DE1);
   Update(crypt, buf, buf, len);
   Finish(crypt, tbuf, 0);
   return 0;
   }

static
int mkKey(ssllib *ssl, crypto *crypt, int srv)
   {
   u_char km[3][MD5_LEN];
   sidRec *sid = ssl->sid;

   crypt->mKey = sid->key;
   crypt->mkeyLen = sid->keyLen;
   crypt->arg  = sid->arg;
   crypt->argLen  = sid->argLen;
   keyMaterial(ssl, km[0], "0");

   return 0;
   }

crypto dummyCrypt = {
   0,
   0,
   0, NULL,
   0, NULL,
   0, NULL, NULL,
   0, NULL,
   Init,
   Update,
   Finish,
   enCrypt,
   deCrypt,
   mkKey
};

crypto * CryptCopy(crypto *to, crypto *from)
   {
   memcpy((char*)to,(char*)from,sizeof(crypto));
   
   to->mKey = (u_char*) malloc(to->mkeyLen);
   if (from->mKey)
      memcpy(to->mKey, from->mKey, to->mkeyLen);
   to->arg = (u_char*) malloc(to->argLen);
   if (from->arg)
      memcpy(to->arg, from->arg, to->argLen);
  
   to->rdKey = (u_char*) malloc(to->keyLen);
   if (from->rdKey)
      memcpy(to->rdKey, from->rdKey, to->keyLen);
   to->wrKey = (u_char*) malloc(to->keyLen);
   if (from->wrKey)
      memcpy(to->wrKey, from->wrKey, to->keyLen);
   
   to->context = (u_char*) malloc(to->cxLen);
   if (from->context)
      memcpy(to->context, from->context, to->cxLen);
   return to;
   }

void genRand(u_char *ptr, int len)
   {
   MD5_CTX md5;
   int cnt = len / MD5_LEN;
   u_char buf[64];
   long seed = rand();
   MD5Init(&md5);
   MD5Update(&md5, (u_char*)&seed,4);
   MD5Update(&md5, (u_char*)ptr,sizeof(char*));
   MD5Update(&md5, (u_char*)buf,sizeof(buf));
   MD5Final(&md5);
   for (seed=0;seed<cnt;seed++)
      {
      MD5Update(&md5, (u_char*)&seed,4);
      memcpy(ptr, md5.digest, 16);
      ptr+=16;
      }
   MD5Final(&md5);
   memcpy(ptr,md5.digest, len % 16);
   }


void keyMaterial(ssllib *ssl, u_char *buf, char *str)
   {
   sidRec *sid = ssl->sid;
   MD5_CTX md5;
   MD5Init(&md5);
   MD5Update(&md5, sid->key, sid->keyLen);
   if (str && *str)
      MD5Update(&md5, str, strlen(str));
   MD5Update(&md5, ssl->chal, ssl->chalLen);
   MD5Update(&md5, ssl->cid, ssl->cidLen);
   MD5Final(&md5);
   memcpy(buf, md5.digest, MD5_LEN);
   }
 
/* called from client */
int privSID(u_char *buf, int fd)
   {
   MD5_CTX md5;
   int rslt;
   size_t len;
   struct sockaddr_in server;
   struct sockaddr_in client;
   bzero(&server, sizeof(server));
   bzero(&client, sizeof(client));
   rslt = getsockname(fd,(struct sockaddr*) &client, &len);
   rslt = getpeername(fd,(struct sockaddr*) &server, &len); 
   MD5Init(&md5);
   MD5Update(&md5,UAuth,UAUTH_LEN);
   MD5Update(&md5,(u_char*)&server, sizeof(server));
   MD5Final(&md5);
   memcpy(buf, md5.digest, MD5_LEN);
   return MD5_LEN;
   }

#define PASS_LEN    32
#define URAND_LEN   16
#define SYSRAND_LEN 16
#define UKEY_LEN    16

u_char  SysRand[];

u_char* GetUKey(u_char *ukey, u_char *urand, char *pass, short useq)
   {
   char cbuf[PASS_LEN+URAND_LEN+4+1];
   int i, len = strlen(pass);
   MD5_CTX md5;
   
   if ((pass == NULL) || (urand == NULL) || (ukey == NULL))
      {
      return NULL;
      }

   /* clear User Key before use */
   for (i=0;i<UKEY_LEN;i++)
      ukey[i] = 0;

   if (len > PASS_LEN)
      {
      /* pass phrase too long */
      }

   sprintf(cbuf, "%04x", useq);
   cbuf[4]=0;
   memcpy(&cbuf[4], urand, URAND_LEN);
   memcpy(&cbuf[20], pass, len);
   len = 4+URAND_LEN + len;

   MD5Init(&md5);
   MD5Update(&md5, &cbuf, len);
   MD5Final(&md5);
   memcpy(ukey, md5.digest,MD5_LEN);

   memset(cbuf, 0, len);

   return ukey;
   }


u_char*  AuthUsr(u_char *uauth, u_char *urand, char *pass, short seq)
   {
   int i, len;
   u_char cbuf[UKEY_LEN + SYSRAND_LEN];
   MD5_CTX md5;

   len = UKEY_LEN + SYSRAND_LEN;
   GetUKey(cbuf, urand, pass, seq);
   memcpy(&cbuf[UKEY_LEN], SysRand, SYSRAND_LEN);

   MD5Init(&md5);
   MD5Update(&md5, cbuf,len);
   MD5Final(&md5);
   memcpy(uauth, md5.digest, MD5_LEN);

   memset(cbuf, 0, len);
   memset(&md5, 0, sizeof(MD5_CTX));
   return uauth;
   }







