diff options
author | Matt Johnston <matt@ucc.asn.au> | 2004-06-01 02:46:09 +0000 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2004-06-01 02:46:09 +0000 |
commit | 674a60748884dc55ee7091b7c23a41240e75f73c (patch) | |
tree | 3b5a173c356f867b94df3873b57ff36d33129ea7 /gendss.c |
Makefile.in contains updated files required
--HG--
extra : convert_revision : cc8a8c49dc70e632c352853a39801089b08149be
Diffstat (limited to 'gendss.c')
-rw-r--r-- | gendss.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/gendss.c b/gendss.c new file mode 100644 index 0000000..3e9db09 --- /dev/null +++ b/gendss.c @@ -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 */ |