diff gendss.c @ 4:fe6bca95afa7

Makefile.in contains updated files required
author Matt Johnston <matt@ucc.asn.au>
date Tue, 01 Jun 2004 02:46:09 +0000
parents
children aecba0e16e9c b0316ce64e4b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gendss.c	Tue Jun 01 02:46:09 2004 +0000
@@ -0,0 +1,215 @@
+/*
+ * Dropbear - a SSH2 server
+ * 
+ * Copyright (c) 2002,2003 Matt Johnston
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE. */
+
+#include "includes.h"
+#include "dbutil.h"
+#include "signkey.h"
+#include "bignum.h"
+#include "random.h"
+#include "buffer.h"
+#include "gendss.h"
+#include "dss.h"
+
+#define PSIZE 128 /* 1024 bit*/
+#define QSIZE 20 /* 160 bit */
+
+#ifdef DROPBEAR_DSS
+
+static void getq(dss_key *key);
+static void getp(dss_key *key, unsigned int size);
+static void getg(dss_key *key);
+static void getx(dss_key *key);
+static void gety(dss_key *key);
+
+dss_key * gen_dss_priv_key(unsigned int size) {
+
+	dss_key *key;
+
+	key = (dss_key*)m_malloc(sizeof(dss_key));
+
+	key->p = (mp_int*)m_malloc(sizeof(mp_int));
+	key->q = (mp_int*)m_malloc(sizeof(mp_int));
+	key->g = (mp_int*)m_malloc(sizeof(mp_int));
+	key->y = (mp_int*)m_malloc(sizeof(mp_int));
+	key->x = (mp_int*)m_malloc(sizeof(mp_int));
+	m_mp_init_multi(key->p, key->q, key->g, key->y, key->x, NULL);
+	
+	seedrandom();
+	
+	getq(key);
+	getp(key, size);
+	getg(key);
+	getx(key);
+	gety(key);
+
+	return key;
+	
+}
+
+static void getq(dss_key *key) {
+
+	char buf[QSIZE];
+
+	/* 160 bit prime */
+	genrandom(buf, QSIZE);
+	buf[0] |= 0x80; /* top bit high */
+	buf[QSIZE-1] |= 0x01; /* bottom bit high */
+
+	if (mp_read_unsigned_bin(key->q, buf, QSIZE) != MP_OKAY) {
+		fprintf(stderr, "dss key generation failed\n");
+		exit(1);
+	}
+
+	/* 18 rounds are required according to HAC */
+	if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) {
+		fprintf(stderr, "dss key generation failed\n");
+		exit(1);
+	}
+}
+
+static void getp(dss_key *key, unsigned int size) {
+
+	mp_int tempX, tempC, tempP, temp2q;
+	int result;
+	unsigned char *buf;
+
+	m_mp_init_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
+
+
+	/* 2*q */
+	if (mp_mul_d(key->q, 2, &temp2q) != MP_OKAY) {
+		fprintf(stderr, "dss key generation failed\n");
+		exit(1);
+	}
+	
+	buf = (unsigned char*)m_malloc(size);
+
+	result = 0;
+	do {
+		
+		genrandom(buf, size);
+		buf[0] |= 0x80; /* set the top bit high */
+
+		/* X is a random mp_int */
+		if (mp_read_unsigned_bin(&tempX, buf, size) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+			exit(1);
+		}
+
+		/* C = X mod 2q */
+		if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+			exit(1);
+		}
+
+		/* P = X - (C - 1) = X - C + 1*/
+		if (mp_sub(&tempX, &tempC, &tempP) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+			exit(1);
+		}
+		
+		if (mp_add_d(&tempP, 1, key->p) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+			exit(1);
+		}
+
+		/* now check for prime, 5 rounds is enough according to HAC */
+		/* result == 1  =>  p is prime */
+		if (mp_prime_is_prime(key->p, 5, &result) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+			exit(1);
+		}
+	} while (!result);
+
+	mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
+	m_free(buf);
+}
+
+static void getg(dss_key * key) {
+
+	char printbuf[1000];
+	mp_int div, h, val;
+
+	m_mp_init_multi(&div, &h, &val, NULL);
+
+	/* get div=(p-1)/q */
+	if (mp_sub_d(key->p, 1, &val) != MP_OKAY) {
+		fprintf(stderr, "dss key generation failed\n");
+		exit(1);
+	}
+	if (mp_div(&val, key->q, &div, NULL) != MP_OKAY) {
+		fprintf(stderr, "dss key generation failed\n");
+		exit(1);
+	}
+
+	/* initialise h=1 */
+	mp_set(&h, 1);
+	do {
+		/* now keep going with g=h^div mod p, until g > 1 */
+		if (mp_exptmod(&h, &div, key->p, key->g) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+			exit(1);
+		}
+
+		if (mp_add_d(&h, 1, &h) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+			exit(1);
+		}
+	
+	} while (mp_cmp_d(key->g, 1) != MP_GT);
+
+	mp_toradix(key->g, printbuf, 10);
+
+	mp_clear_multi(&div, &h, &val, NULL);
+}
+
+static void getx(dss_key *key) {
+
+	mp_int val;
+	char buf[QSIZE];
+	
+	m_mp_init(&val);
+	
+	do {
+		genrandom(buf, QSIZE);
+
+		if (mp_read_unsigned_bin(&val, buf, QSIZE) != MP_OKAY) {
+			fprintf(stderr, "dss key generation failed\n");
+		}
+	} while ((mp_cmp_d(&val, 1) == MP_GT) && (mp_cmp(&val, key->q) == MP_LT));
+
+	mp_copy(&val, key->x);
+	mp_clear(&val);
+
+}
+
+static void gety(dss_key *key) {
+
+	if (mp_exptmod(key->g, key->x, key->p, key->y) != MP_OKAY) {
+		fprintf(stderr, "dss key generation failed\n");
+		exit(1);
+	}
+}
+
+#endif /* DROPBEAR_DSS */