/*
 * This program generates the various DES boxes that can be precomputed
 * it assumes a word length of 64 bits
 *
 * (c) Copyright 1987 by Matt Bishop and the Universities Space Research
 *			 Association.
 * This work was funded by grant NCC 2-398 from the National Aeronautics
 * and Space Administration to the Universities Space Research Association.
 *
 * Author's Address:
 *		Matt Bishop
 *		Research Institute for Advanced Computer Science
 *		NASA Ames Research Center
 *		Moffett Field, CA  94035
 * ARPANET:	mab@riacs.edu, mab@icarus.riacs.edu
 * CSNET:	mab@riacs.edu
 * UUCP:	...!decvax!decwrl!riacs!mab
 *		...!ihnp4!ames!riacs!mab
 *		...!ucbvax!ames!riacs!mab
 */
#include <stdio.h>
#include "des.h"

#define PRINT(num)	fprintf(fp, FORMAT, num)
#define PRINTI(num)	fprintf(fp, "\t0x%x,\n", num)

/*
 * The boxes are named by "box_" followed by the table name
 * followed by the number of bits the box is intended for (this
 * is just the setting of BITS), followed by the ".c" suffix
 * so they can be compiled.
 */
#define	KEY_DATA	"box_key.c"
#define	PC1_DATA	"box_pc1.c"
#define	PC2_DATA	"box_pc2.c"
#define LSH_DATA	"box_lsh.c"
#define	IPE_DATA 	"box_ipe.c"
#define	SPE6_DATA	"box_spe6.c"
#define	SPE12_DATA	"box_spe12.c"
#define EIPINV_DATA 	"box_eipinv.c"
#define	KEY_DECL	"box_key.h"
#define	PC1_DECL	"box_pc1.h"
#define	PC2_DECL	"box_pc2.h"
#define LSH_DECL	"box_lsh.h"
#define	IPE_DECL 	"box_ipe.h"
#define	SPE6_DECL	"box_spe6.h"
#define	SPE12_DECL	"box_spe12.h"
#define EIPINV_DECL 	"box_eipinv.h"

main(argc, argv)
int argc;
char **argv;
{
	register int i;		/* counter in a for loop */

	/*
	 * compute and/or print the appropriate things
	 */
	for(i = 1; i < argc; i++){
		/* compute KEY */
		if (strcmp(argv[i], KEY_DATA) == 0)
			key_compute(argv[i]);
		/* dump KEY declarations */
		else if (strcmp(argv[i], KEY_DECL) == 0)
			key_declare(argv[i]);
		/* compute PC1 */
		else if (strcmp(argv[i], PC1_DATA) == 0)
			pc1_compute(argv[i]);
		/* dump PC1 declarations */
		else if (strcmp(argv[i], PC1_DECL) == 0)
			pc1_declare(argv[i]);
		/* compute PC2 */
		else if (strcmp(argv[i], PC2_DATA) == 0)
			pc2_compute(argv[i]);
		/* dump PC2 declarations */
		else if (strcmp(argv[i], PC2_DECL) == 0)
			pc2_declare(argv[i]);
		/* print left shifts for key computation */
		else if (strcmp(argv[i], LSH_DATA) == 0)
			lsh_compute(argv[i]);
		/* dump left shift declarations */
		else if (strcmp(argv[i], LSH_DECL) == 0)
			lsh_declare(argv[i]);
		/* compute IP * (E, E) */
		else if (strcmp(argv[i], IPE_DATA) == 0)
			ipe_compute(argv[i]);
		/* dump IP * (E, E) declarations */
		else if (strcmp(argv[i], IPE_DECL) == 0)
			ipe_declare(argv[i]);
		/* compute S * P * E (6 bit path) */
		else if (strcmp(argv[i], SPE6_DATA) == 0)
			spe6_compute(argv[i]);
		/* dump S * P * E (6 bit path) declarations */
		else if (strcmp(argv[i], SPE6_DECL) == 0)
			spe6_declare(argv[i]);
		/* compute S * P * E (12 bit path) */
		else if (strcmp(argv[i], SPE12_DATA) == 0)
			spet_compute(argv[i]);
		/* dump S * P * E (12 bit path) declarations */
		else if (strcmp(argv[i], SPE12_DECL) == 0)
			spet_declare(argv[i]);
		/* compute (E^(-1), E^(-1)) * IP^(-1) */
		else if (strcmp(argv[i], EIPINV_DATA) == 0)
			eip_compute(argv[i]);
		/* dump (E^(-1), E^(-1)) * IP^(-1) declarations */
		else if (strcmp(argv[i], EIPINV_DECL) == 0)
			eip_declare(argv[i]);
		else
			fprintf(stderr, "genbox: bad option \"%s\"\n", argv[i]);
	}

	exit(0);
}

/*
 * macros to define the routines
 */
#define DATAOPEN(fp, name)	FOPEN(fp, name); HEADER(fp)
#define DECLOPEN(fp, name)	FOPEN(fp, name)
#define SPEOPEN(fp, name)       FOPEN(fp, name); WRITEPATH(fp); HEADER(fp)
#if PATH == 6 
#define WRITEPATH(fp)      fprintf(fp, "#define PATH 06\n\n");
#else
#define WRITEPATH(fp)      fprintf(fp, "#define PATH 12\n\n");
#endif

#define	FOPEN(fp, name)						 	  \
		/*							  \
		 * open the file for writing and write the library comment\
		 */							  \
		if ((fp = fopen(name, "w")) == NULL){			  \
			perror(name);					  \
			return;						  \
		}							  \
		fprintf(fp, "/* LINTLIBRARY */\n\n");
#define HEADER(fp)							  \
		/*							  \
		 * print out the obligatory header information		  \
		 */							  \
		fprintf(fp, "#include \"des.h\"\n\n");

/*
 *=============================
 * MACROS FOR ALL PERMUTATIONS
 *=============================
 */
/*
 * get the nth bit, bc bits/Unit
 */
#define getbit(a, n, bc)	(((a)[(n-1)/bc]>>((bc-1)-((n-1)%bc)))&01)

/*
 * get a permutation of 32 bits/Unit
 */
Unit permute(a, perm, count, outbits, inbits)
Unit a[];
short perm[];
int count, outbits, inbits;
{
	register int i;
	Unit res;

	res = (Unit) 0;
	count *= outbits;
	for(i = 0; i < outbits; i++)
		res |= (getbit(a, perm[count+i], inbits) << (outbits-1-i));
	return(res);
}

/*==================================
 * THE DES TABLES (and some others)
 *==================================
 */
short ip[64] = {
	58, 50, 42, 34, 26, 18, 10,  2,
	60, 52, 44, 36, 28, 20, 12,  4,
	62, 54, 46, 38, 30, 22, 14,  6,
	64, 56, 48, 40, 32, 24, 16,  8,
	57, 49, 41, 33, 25, 17,  9,  1,
	59, 51, 43, 35, 27, 19, 11,  3,
	61, 53, 45, 37, 29, 21, 13,  5,
	63, 55, 47, 39, 31, 23, 15,  7,
};
short ipinv[64] = {
	40,  8, 48, 16, 56, 24, 64, 32,
	39,  7, 47, 15, 55, 23, 63, 31,
	38,  6, 46, 14, 54, 22, 62, 30,
	37,  5, 45, 13, 53, 21, 61, 29,
	36,  4, 44, 12, 52, 20, 60, 28,
	35,  3, 43, 11, 51, 19, 59, 27,
	34,  2, 42, 10, 50, 18, 58, 26,
	33,  1, 41,  9, 49, 17, 57, 25,
};
short e[48] = {
	32,  1,  2,  3,  4,  5,
	 4,  5,  6,  7,  8,  9,
	 8,  9, 10, 11, 12, 13,
	12, 13, 14, 15, 16, 17,
	16, 17, 18, 19, 20, 21,
	20, 21, 22, 23, 24, 25,
	24, 25, 26, 27, 28, 29,
	28, 29, 30, 31, 32,  1,
};
short s[8][64] = {
	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,

	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,

	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,

	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,

	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,

	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,

	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,

	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
};
short p[32] = {
	16,  7, 20, 21,
	29, 12, 28, 17,
	 1, 15, 23, 26,
	 5, 18, 31, 10,
	 2,  8, 24, 14,
	32, 27,  3,  9,
	19, 13, 30,  6,
	22, 11,  4, 25,
};
short pc1[64] = {
	57, 49, 41, 33, 25, 17,  9,
	 1, 58, 50, 42, 34, 26, 18,
	10,  2, 59, 51, 43, 35, 27,
	19, 11,  3, 60, 52, 44, 36,
	63, 55, 47, 39, 31, 23, 15,
	 7, 62, 54, 46, 38, 30, 22,
	14,  6, 61, 53, 45, 37, 29,
	21, 13,  5, 28, 20, 12,  4,
};
short pc2[48] = {
	14, 17, 11, 24,  1,  5,
	 3, 28, 15,  6, 21, 10,
	23, 19, 12,  4, 26,  8,
	16,  7, 27, 20, 13,  2,
	41, 52, 31, 37, 47, 55,
	30, 40, 51, 45, 33, 48,
	44, 49, 39, 56, 34, 53,
	46, 42, 50, 36, 29, 32,
};
short lsh[] = {
	1, 1, 2, 2, 2, 2, 2, 2,
	1, 2, 2, 2, 2, 2, 2, 1,
};

/*
 * other tables -- the inverse of e, and a list of hex digits
 * for making file names
 */
short einv[64] = {
	 2,  3,  4,  5,
	 8,  9, 10, 11,
	14, 15, 16, 17,
	20, 21, 22, 23,
	26, 27, 28, 29,
	32, 33, 34, 35,
	38, 39, 40, 41,
	44, 45, 46, 47,
};
char *hex = "0123456789ABCDEF";

/*
 *==========================
 * PRECOMPUTATION OF IP * E
 *==========================
 */
ipe_compute(name)
char *name;
{
	register int i, j, k;		/* counters in for loops */
	FILE *fp;			/* points to file */
	short arr[96];			/* composition of ip and e2 */
	Unit buf[16];			/* initial vector */
	Unit outarr[8][4][256];		/* output array */
	Unit tmp;
	/*
	 * generate the doubled e array
	 */

	/*
	 * be sure you can write it somewhere
	 */
	DATAOPEN(fp, name);

	/*
	 * print the declaration
	 */
	fprintf(fp, "/*\n * the Initial Permutation and Expansion for the message\n */\n\n");

	/*
	 * compose the permutations
	 */
	for(i = 0; i < 48; i++)
		arr[i] = ip[e[i]-1];
	for(i = 48; i < 96; i++)
		arr[i] = ip[e[i-48]+31];

	/*
	 * now precompute the arrays
	 */
	for(i = 0; i < 8; i++)
		for(j = 0; j < 256; j++){
			/* set up the buffer */
			for(k = 0; k < 16; k++)
				buf[k] = 0;
			buf[i] = j;
			/* permute */
			for(k = 0; k < 2; k++) {

			  /* 6 or 12 bit path, bitfields or shift and mask */
			  outarr[i][k][j] = permute(buf, arr, k, 48, 8);
		      }
		}

	/*
	 * print the permutation
	 */
	for(i = 0; i < 8; i++)
		for(k = 0; k < 2; k++){
			fprintf(fp, "Unit vipe%d%d[256] = {\n", i, k);
			for(j = 0; j < 256; j++)
				PRINT(outarr[i][k][j]);
			fprintf(fp, "};\n");
		}

	/*
	 * close the data file
	 */
	(void) fclose(fp);
}
ipe_declare(name)
char *name;
{
	register int i, k;		/* counters in for loops */
	FILE *fp;			/* points to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n * extern declarations for (E, E) * IP\n */\n\n");
	/*
	 * print the declarations
	 */
	for(i = 0; i < 8; i++)
		for(k = 0; k < 2; k++)
			fprintf(fp, "extern Unit vipe%d%d[256];\n", i, k);

	(void) fclose(fp);
}

/*
 *===============================
 * PRECOMPUTATION OF E, P, and S
 *===============================
 */
/* map 6 bit number into s box row and column */
#define low(n)	((n)&0x3f)
#define high(n)	(((n)>>6)&0x3f)
#define row(n)	((((n)>>4)&0x2)|((n)&0x1))
#define col(n)	(((n)>>1)&0xf)
#define lrow(n)	row(low(n))
#define hrow(n)	row(high(n))
#define lcol(n)	col(low(n))
#define hcol(n)	col(high(n))

/*
 * precompute the e, p, and s boxes
 */
spet_compute(name)
char *name;
{
	register int i, j, k;		/* counters in for loops */
	FILE *fp;			/* pointer to file */
	Unit buf[4];			/* initial vector */
	short arr[48];			/* composition of p and e */
	Unit outarr[4][64*64];		/* output array */
	Unit tmp;


	/*
	 * be sure you can write it somewhere
	 */
	SPEOPEN(fp, name);

	/*
	 * print the declaration
	 */
	fprintf(fp, "/*\n * the Expansion, Substitution, and Permutation function\n */\n\n");

	/*
	 * compose the permutations
	 */
	for(i = 0; i < 48; i++)
		arr[i] = p[e[i]-1];

	/*
	 * now precompute the arrays
	 */
	for(i = 0; i < 4; i++)
	  for(j = 0; j < 64 * 64; j++){
	    /* set up the buffer */
	    for(k = 0; k < 4; k++)
	      buf[k] = 0;
	    /* substitute */
	    buf[i] = (s[2*i][hrow(j)*16+hcol(j)]<<4)|
	      s[2*i+1][lrow(j)*16+lcol(j)];
	    /* permute */
	    /* 6 or 12 bit path, bitfields or shift and mask */
	    outarr[i][j] = permute(buf, arr, 0, 48, 8);
	  }
	
	/*
	 * print out the structure
	 */
        for(i = 0; i < 4; i++){
	  fprintf(fp, "Unit vspet%d[64*64] = { */\n",i);
	  for(j = 0; j < 64 * 64; j++)
	    PRINT(outarr[i][j]);
	  fprintf(fp, "};\n\n");
	}

	(void) fclose(fp);
}




/*
 * Print the declarations and macros for the twelve bit path.
 */

spet_declare(name)
char *name;
{
	register int i;			/* counters in for loops */
	FILE *fp;			/* points to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	fprintf(fp, "/*\n");
	fprintf(fp, " * extern declarations for E * P * S\n");
	fprintf(fp, " */\n\n");

	fprintf(fp, "/*\n");
	fprintf(fp, " * how you reference them depends on your\n");
	fprintf(fp, " * architecture\n");
	fprintf(fp, " */\n\n");

        for(i = 0; i < 4; i++)
	  fprintf(fp, "extern Unit vspet%d[64*64];\n", i, i);


	/*
	 * close the file
	 */
	(void) fclose(fp);
}

/* map 6 bit number into s box row and column */
#define srow(n)	((((n)>>4)&0x2)|((n)&0x1))
#define scol(n)	(((n)>>1)&0xf)

/*
 * precompute the e, p, and s boxes
 */
spe6_compute(name)
char *name;
{
	register int i, j, k;		/* counters in for loops */
	FILE *fp;			/* pointer to file */
	Unit buf[8];			/* initial vector */
	short arr[48];			/* composition of p and e */
	Unit outarr[8][64];		/* output array */
	Unit tmp;

	/*
	 * be sure you can write it somewhere
	 */
	SPEOPEN(fp, name);

	/*
	 * print the declaration
	 */
	fprintf(fp, "/*\n");
        fprintf(fp, " * the Expansion, Substitution, and Permutation\n");
	fprintf(fp, " * function\n");
	fprintf(fp, " */\n\n");

	/*
	 * compose the permutations
	 */
	for(i = 0; i < 48; i++)
		arr[i] = p[e[i]-1];

	/*
	 * now precompute the arrays
	 */
	for(i = 0; i < 8; i++)
		for(j = 0; j < 64; j++){
			/* set up the buffer */
			for(k = 0; k < 8; k++)
				buf[k] = 0;
			/* substitute */
			buf[i] = s[i][row(j)*16+col(j)];
			/* permute */

			/* 6 or 12 bit path, bitfields or shift and mask */
			outarr[i][j] = permute(buf, arr, 0, 48, 4);
		}
	
	/*
	 * print the permutation
	 */

	for(i = 0; i < 8; i++){
	  fprintf(fp,"Unit vspe6%d[64] = {\n", i);
	  for(j = 0; j < 64; j++)
	    PRINT(outarr[i][j]);
	  fprintf(fp, "};\n\n");
	}

	(void) fclose(fp);
}

spe6_declare(name)
char *name;
{
	register int i;			/* counters in for loops */
	FILE *fp;			/* points to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n");
	fprintf(fp, " * extern declarations for E * P * S\n");
        fprintf(fp, " */\n\n");

	for(i = 0; i < 8; i++) 
	  fprintf(fp,"extern Unit vspe6%d[64];\n",i);

	/*
	 * now the macros
	 */
	fprintf(fp, "/*\n");
	fprintf(fp, " * how you reference them depends on your\n");
	fprintf(fp, " * architecture\n");
	fprintf(fp, " */\n");

	(void) fclose(fp);
}


/*
 *==============================================
 * PRECOMPUTATION OF (E^(-1), E^(-1)) * IP^(-1)
 *==============================================
 */
eip_compute(name)
char *name;
{
	register int i, j, k;		/* counters in for loops */
	FILE *fp;			/* pointer to file */
	Unit buf[16];			/* initial vector */
	short arr[64];			/* composition of ip^-1 and e^-1 */
	Unit outarr[16][8][64];		/* output array */
	short e2inv[64];		/* double and swapped inverse */

	/*
	 * be sure you can write it somewhere
	 */
	DATAOPEN(fp, name);

	/*
	 * print the declaration
	 */
	fprintf(fp, "/*\n * the (Contraction) and Final Permutation\n */\n\n");

	/*
	 * compose the permutations
	 */
	for(i = 0; i < 32; i++)
		e2inv[i] = einv[i] + 48;
	for(i = 32; i < 64; i++)
		e2inv[i] = einv[i-32];
	for(i = 0; i < 64; i++)
		arr[i] = e2inv[ipinv[i]-1];

	/*
	 * now precompute the arrays
	 */
	for(i = 0; i < 16; i++)
		for(j = 0; j < 64; j++){
			/* set up the buffer */
			for(k = 0; k < 16; k++)
				buf[k] = 0;
			buf[i] = j;
			/* permute */
			for(k = 0; k < 8; k++)
				outarr[i][k][j] = permute(buf, arr, k, 8, 6);
		}
	
	/*
	 * print the permutation
	 */
	for(i = 0; i < 16; i++)
		for(k = 0; k < 8; k++){
			fprintf(fp, "Intf veip%c%d[64] = {\n", hex[i], k);
			for(j = 0; j < 64; j++)
				PRINTI((unsigned char) outarr[i][k][j]);
			fprintf(fp, "};\n");
		}

	/*
	 * close the file
	 */
	(void) fclose(fp);
}
eip_declare(name)
char *name;
{
	register int i, k;		/* counters in for loops */
	FILE *fp;			/* points to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n * extern declarations for (E^-1, E^-1) * IP^-1\n */\n\n");

	/*
	 * print the declarations
	 */
	for(i = 0; i < 16; i++)
		for(k = 0; k < 8; k++)
			fprintf(fp, "extern Intf veip%c%d[64];\n", hex[i], k);
	/*
	 * now the macros
	 */
	fprintf(fp, "\n/*\n * how you reference them depends on your architecture\n */\n");
	fprintf(fp, "#define\tINITVEIP\n");
	for(i = 0; i < 16; i++)
		for(k = 0; k < 8; k++)
			fprintf(fp, "#define\tVEIP%c%d\tveip%c%d\n",
							hex[i], k, hex[i], k);



	/*
	 * close the file
	 */
	(void) fclose(fp);
}

/*
 *=======================
 * PRECOMPUTATION OF PC1
 *=======================
 */
pc1_compute(name)
char *name;
{
	register int i, j, k;		/* counters in for loops */
	FILE *fp;			/* pointer to file */
	Unit buf[8];			/* initial vector */
	Unit outarr[8][256];		/* output array */

	/*
	 * be sure you can write it somewhere
	 */
	DATAOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n * the Permuted Choice 1 for the keys\n */\n\n");

	/*
	 * now precompute the arrays
	 */
	for(i = 0; i < 8; i++)
		for(j = 0; j < 256; j++){
			/* set up the buffer */
			for(k = 0; k < 8; k++)
				buf[k] = 0;
			buf[i] = j;
			/* permute */
			outarr[i][j] = permute(buf, pc1, 0, 56, 8);
		}

	/*
	 * print the permutation
	 */
	for(i = 0; i < 8; i++){
		fprintf(fp, "Unit vpc1%d[256] = {\n", i);
		for(j = 0; j < 256; j++)
			PRINT(outarr[i][j]);
		fprintf(fp, "};\n");
	}

	/*
	 * close the file
	 */
	(void) fclose(fp);
}
pc1_declare(name)
char *name;
{
	register int i;			/* counters in for loops */
	FILE *fp;			/* points to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n * extern declarations for PC1\n */\n\n");

	/*
	 * print the declarations
	 */
	for(i = 0; i < 8; i++)
		fprintf(fp, "extern Unit vpc1%d[256];\n", i);
	/*
	 * now the macros
	 */
	fprintf(fp, "\n/*\n * how you reference them depends on your architecture\n */\n");
	fprintf(fp, "#define\tINITVPC1\n");
	for(i = 0; i < 8; i++)
		fprintf(fp, "#define\tVPC1%d\tvpc1%d\n", i, i);

	/*
	 * close the file
	 */
	(void) fclose(fp);
}

/*
 *=======================
 * PRECOMPUTATION OF PC2
 *=======================
 */
pc2_compute(name)
char *name;
{
	register int i, j, k;		/* counters in for loops */
	FILE *fp;			/* pointer to file */
	Unit buf[8];			/* initial vector */
	Unit outarr[8][128];		/* output array */
	Unit tmp;

	/*
	 * be sure you can write it somewhere
	 */
	DATAOPEN(fp, name);

	/*
	 * print the declaration
	 */
	fprintf(fp, "/*\n * the Permuted Choice 2 for the keys\n */\n\n");

	/*
	 * now precompute the arrays
	 */
	for(i = 0; i < 8; i++)
		for(j = 0; j < 128; j++){
			/* set up the buffer */
			for(k = 0; k < 8; k++)
				buf[k] = 0;
			buf[i] = j;

			/* 6 or 12 bit path, bitfields or shift and mask */
			outarr[i][j] = permute(buf, pc2, 0, 48, 7);
		      }

	/*
	 * print the permutation
	 */
	for(i = 0; i < 8; i++){
		fprintf(fp, "Unit vpc2%d[128] = {\n", i);
		for(j = 0; j < 128; j++)
			PRINT(outarr[i][j]);
		fprintf(fp, "};\n");
	}

	/*
	 * close the file
	 */
	(void) fclose(fp);
}





pc2_declare(name)
char *name;
{
	register int i;			/* counters in for loops */
	FILE *fp;			/* points to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n * extern declarations for PC2\n */\n\n");

	/*
	 * print the declarations
	 */
	for(i = 0; i < 8; i++)
		fprintf(fp, "extern Unit vpc2%d[128];\n", i);
	/*
	 * now the macros
	 */
	fprintf(fp, "\n/*\n * how you reference them depends on your architecture\n */\n");
	fprintf(fp, "#define\tINITVPC2\n");
	for(i = 0; i < 8; i++)
		fprintf(fp, "#define\tVPC2%d\tvpc2%d\n", i, i);

	/*
	 * close the file
	 */
	(void) fclose(fp);
}

/*
 *=================
 * PRINTING OF LSH
 *=================
 */
lsh_compute(name)
char *name;
{
	register int i;			/* counters in for loops */
	FILE *fp;			/* pointer to file */

	/*
	 * be sure you can write it somewhere
	 */
	DATAOPEN(fp, name);

	/*
	 * print the declaration
	 */
	fprintf(fp, "unsigned char vlsh[16] = {\t/* left shifts */\n");

	/*
	 * now dump the array
	 */
	for(i = 0; i < 16; i++)
		fprintf(fp, "\t%d,\n", lsh[i]);
	fprintf(fp, "};\n");

	/*
	 * close the file
	 */
	(void) fclose(fp);
}
lsh_declare(name)
char *name;
{
	FILE *fp;			/* points to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n * extern declaration for the left shifts\n */\n\n");

	/*
	 * print the declaration
	 */
	fprintf(fp, "extern unsigned char vlsh[16];\n");

	/*
	 * close the file
	 */
	(void) fclose(fp);
}

/*
 *=======================
 * PRECOMPUTATION OF KEY
 *=======================
 */
key_compute(name)
char *name;
{
	register int i, i1, j, k;	/* counters in for loops */
	FILE *fp;			/* pointer to file */
	Unit buf[8];			/* initial vector */
	Unit outarr[16][8][256];		/* output array */
	short perm[48];
	short tmp;
	Unit tmp2;

	/*
	 * be sure you can write it somewhere
	 */
	DATAOPEN(fp, name);

	/* print the declaration */

	fprintf(fp, "/*\n * the precomputed permutations for the keys\n */\n\n");

	for(i = 0; i < 16; i++){
		/*
		 * shift the initial permutation
		 */
		for(k = 0; k < lsh[i]; k++){
			tmp = pc1[0];
			for(j = 1; j < 28; j++)
				pc1[j-1] = pc1[j];
			pc1[27] = tmp;
			tmp = pc1[28];
			for(j = 29; j < 56; j++)
				pc1[j-1] = pc1[j];
			pc1[55] = tmp;
		}
		/*
		 * apply pc2
		 */
		for(k = 0; k < 48; k++)
			perm[k] = pc1[pc2[k]-1];
		/*
		 * now precompute the arrays
		 */
		for(i1 = 0; i1 < 8; i1++)
			for(j = 0; j < 256; j++){
				/* set up the buffer */
				for(k = 0; k < 8; k++)
					buf[k] = 0;
				buf[i1] = j;
				/* permute */

				/* 6 or 12 bit path, bitfields or shift and mask */
				  outarr[i][i1][j] = permute(buf, perm, 0, 48, 8);
			      }
	      }
	/*
	 * print the permutation
	 */
	for(i1 = 0; i1 < 8; i1++){
	  fprintf(fp, "Unit vkey%d[256][16] = {\n", i1);
	  for(j = 0; j < 256; j++)
	    for(i = 0; i < 16; i++)
	      PRINT(outarr[i][i1][j]);
	  fprintf(fp, "};\n");
	}

	(void) fclose(fp);
}



key_declare(name)
char *name;
{
	register int i, j;		/* counters in for loops */
	FILE *fp;			/* pointer to file */

	/*
	 * open the declarations file
	 */
	DECLOPEN(fp, name);

	/*
	 * print the leading comment
	 */
	fprintf(fp, "/*\n * extern declarations for key schedule permutation\n */\n\n");

	for(j = 0; j < 8; j++)
		fprintf(fp, "extern Unit vkey%d[256][16];\n", j);

	/*
	 * close the file
	 */
	(void) fclose(fp);
}

