/*  MAC-f1
 *    This file contains an implementation of whatever it is that
 *    MAC-f1 is deemed to do. In this case, MAC-f1 simply takes an
 *    arbitrary length string and calculates DES(string), returning
 *    that as output.  for security reasons, the program can't be
 *    called with the key as argument, so instead, it is passed the
 *    key in as the first string, and all the following strings are
 *    encrypted under that key.
 *
 *  Written by Yoav Yerushalmi as part of the MAC.el package, see
 *  comments in MAC.el for further info.  
 */

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

#define MAX_BLOCK_LEN 1024
         /* maximum size of input in any one string */

#define   min(a,b)        ((a) < (b) ? (a) : (b))

void outfun(unsigned char);

int main() {
  char input[9], output[9];
  char str1[MAX_BLOCK_LEN + 1];
  char str2[MAX_BLOCK_LEN + 1];
  unsigned char temp[MAX_BLOCK_LEN + 1];
  unsigned char out1[MAX_BLOCK_LEN + 1];
  unsigned char out2[MAX_BLOCK_LEN + 1];
  int ref, outputlen;
  int len1, len2, shorter;


  signal(SIGHUP, exit);
  memset(str1, '\0', MAX_BLOCK_LEN);
  if (!fgets(str1, MAX_BLOCK_LEN, stdin)) {
    perror("failed to get key : ");
    exit(1);
  }
  des_setkey(str1);
  while (!feof(stdin)) {
    if ((fgets(str1, MAX_BLOCK_LEN, stdin)) &&
	(fgets(str2, MAX_BLOCK_LEN, stdin))) {
      len1 = strlen(str1)-1;
      len2 = strlen(str2)-1;
      len1 = (len1 / 3);
      len2 = (len2 / 3);
      ref = 0;
      while (ref < len1) {
	temp[ref] = (unsigned char)strtol(&str1[(ref * 3)], NULL, 16);
	ref++;
      }
      memcpy(str1, temp, ref);
      str1[len1] = '\0'; /* remove the trailing newline */

      ref = 0;
      while (ref < len2) {
	temp[ref] = (unsigned char)strtol(&str2[(ref * 3)], NULL, 16);
	ref++;
      }
      memcpy(str2, temp, ref);
      str2[len2] = '\0'; /* remove the trailing newline */

      /*  Calculate DES(str1)  */
      len1 -= 8;
      ref = 0;
      while (ref <= len1) {
	memcpy(input, &str1[ref], 8);
	des_cipher(input, output, 0, 1);
	memcpy(&out1[ref], output, 8);
	ref += 8;
      }
      len1 += 8;
      if (ref < len1) {
	memset(input, '\0', 8);
	strcpy(input, &str1[ref]);
	des_cipher(input, output, 0, 1);
	memcpy(&out1[ref], output, 8);
	ref += 8;
      }
      out1[ref] = '\0';
      
      /* Calculate DES(str2)  */
      len2 -= 8;      
      ref = 0;
      while (ref <= len2) {
	memcpy(input, &str2[ref], 8);
	des_cipher(input, output, 0, 1);
	memcpy(&out2[ref], output, 8);
	ref += 8;
      }
      len2 += 8;
      if (ref < len2) {
	memset(input, '\0', 8);
	strcpy(input, &str2[ref]);
	des_cipher(input, output, 0, 1);
	memcpy(&out2[ref], output, 8);
	ref += 8;
      }
      out2[ref] = '\0';
      
      /* Calculate DES(str1) (xor) DES(str2)  */
      shorter = min(len1, len2);
      outputlen = shorter + ((8 - (shorter % 8)) % 8);
      for (ref=0; ref<outputlen; ref++)
	outfun(out1[ref] ^ out2[ref]);
      if (len1>len2)
	while (ref < (len1 + ((8 - (len1 % 8)) % 8))) {
	  outfun(out1[ref]);
	  ref++;
	}
      if (len2 > len1)
	while (ref < (len2 + ((8 - (len2 % 8)) % 8))) {
	  outfun(out2[ref]);
	  ref++;
	}
      printf ("\n");
      fflush(stdout);
    }
  }
}

void outfun(unsigned char foo)
  {
    printf("%02x ", foo);
  }

