
/* genkey.c - Mark Henderson (markh@wimsey.bc.ca) */
#include "l3.h"
main(int argc, char *argv[])
{
	unsigned char *p1 = NULL;
	unsigned char *p0 = NULL;
	char outfile[128];
	unsigned int idlen;
	unsigned char key[16];	/* for key to key */
	unsigned char iv[8];
	int bits, i, k;
	FILE *private, *public;
	MP_INT *e, *p, *q, *n;
	init(e);
	init(p);
	init(q);
	init(n);

	if (argc < 2) {
		fprintf(stderr, 
			"usage error: %s file [bits] [randomdata...]\n", argv[0]);
		exit(1);
	}
	bits = 1024;	/* default */
	if (argc >= 3) {
		bits = atoi(argv[2]);
		if (bits < (LKEYLEN*8+4) || bits > MAXBITS) {
			fprintf(stderr, "valid range for bits is %d-%d\n", LKEYLEN*8+4, 
				MAXBITS);
			fprintf(stderr, "usage error: %s file [bits]\n", argv[0]);
			exit(1);
		}
	}

	bits /= 2;

	strncpy(outfile, argv[1], 120);
	strcat(outfile, ".prv");

	if (!(private = fopen(outfile, "wb"))) {
		fprintf(stderr, "could not open %s for write\n", outfile);
		exit(1);
	}
	strncpy(outfile, argv[1], 120);
	strcat(outfile, ".pub");

	if (!(public = fopen(outfile, "wb"))) {
		fprintf(stderr, "could not open %s for write\n", outfile);
		exit(1);
	}

	initrandom();
	for (i = 3; i < argc; i++)
		if (argv[i] && (k = strlen(argv[i]))) {
			seedrandom((unsigned char *) argv[i], k);
			zap((unsigned char *) argv[i], k);
		}

	do {
		if (p0)
			free(p0);
		if (p1)
			free(p1);
		fprintf(stderr, "enter password for key -- end with <CR> \n");
		p0 = getstring(1);
		fprintf(stderr, "enter again for verification\n");
		p1 = getstring(1);
	} while (strcmp(p0, p1));

	mdstring(p0, strlen(p0), key);
	zap(p0, strlen(p0));;
	zap(p1, strlen(p1));
	for (i = 0; i < 8; i++)
		iv[i] = 0;

	fprintf(stderr, "please enter a random string -- end with <CR>\n");
	(void) getstring(0);
#ifdef FIXED_E
	mpz_set_ui(e, 65537);
#else
	/* make e nice and big */
	mpz_set_ui(e, 1L);
	mpz_mul_2exp(e, e, (unsigned long) bits / 2);
	mpz_add_ui(e, e, 1L);
#endif

	/* generate a key */
	genkey(p, q, e, bits);
	mpz_mul(n, p, q);

	write_number(public, n);
	write_number(public, e);
	write_numberx(private, p, key, iv);
	write_numberx(private, q, key, iv);
	zap(key, 16);
	write_number(private, e);
	fclose(private);
	fclose(public);
	closerandom();
	exit(0);
}
