1/* 2 * Dropbear - a SSH2 server 3 * 4 * Copyright (c) 2002,2003 Matt Johnston 5 * All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. */ 24 25#include "includes.h" 26#include "dbutil.h" 27#include "signkey.h" 28#include "bignum.h" 29#include "random.h" 30#include "buffer.h" 31#include "gendss.h" 32#include "dss.h" 33 34#define QSIZE 20 /* 160 bit */ 35 36/* This is just a test */ 37 38#ifdef DROPBEAR_DSS 39 40static void getq(dss_key *key); 41static void getp(dss_key *key, unsigned int size); 42static void getg(dss_key *key); 43static void getx(dss_key *key); 44static void gety(dss_key *key); 45 46dss_key * gen_dss_priv_key(unsigned int size) { 47 48 dss_key *key; 49 50 key = (dss_key*)m_malloc(sizeof(dss_key)); 51 52 key->p = (mp_int*)m_malloc(sizeof(mp_int)); 53 key->q = (mp_int*)m_malloc(sizeof(mp_int)); 54 key->g = (mp_int*)m_malloc(sizeof(mp_int)); 55 key->y = (mp_int*)m_malloc(sizeof(mp_int)); 56 key->x = (mp_int*)m_malloc(sizeof(mp_int)); 57 m_mp_init_multi(key->p, key->q, key->g, key->y, key->x, NULL); 58 59 seedrandom(); 60 61 getq(key); 62 getp(key, size); 63 getg(key); 64 getx(key); 65 gety(key); 66 67 return key; 68 69} 70 71static void getq(dss_key *key) { 72 73 char buf[QSIZE]; 74 75 /* 160 bit prime */ 76 genrandom(buf, QSIZE); 77 buf[0] |= 0x80; /* top bit high */ 78 buf[QSIZE-1] |= 0x01; /* bottom bit high */ 79 80 bytes_to_mp(key->q, buf, QSIZE); 81 82 /* 18 rounds are required according to HAC */ 83 if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) { 84 fprintf(stderr, "dss key generation failed\n"); 85 exit(1); 86 } 87} 88 89static void getp(dss_key *key, unsigned int size) { 90 91 DEF_MP_INT(tempX); 92 DEF_MP_INT(tempC); 93 DEF_MP_INT(tempP); 94 DEF_MP_INT(temp2q); 95 int result; 96 unsigned char *buf; 97 98 m_mp_init_multi(&tempX, &tempC, &tempP, &temp2q, NULL); 99 100 101 /* 2*q */ 102 if (mp_mul_d(key->q, 2, &temp2q) != MP_OKAY) { 103 fprintf(stderr, "dss key generation failed\n"); 104 exit(1); 105 } 106 107 buf = (unsigned char*)m_malloc(size); 108 109 result = 0; 110 do { 111 112 genrandom(buf, size); 113 buf[0] |= 0x80; /* set the top bit high */ 114 115 /* X is a random mp_int */ 116 bytes_to_mp(&tempX, buf, size); 117 118 /* C = X mod 2q */ 119 if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) { 120 fprintf(stderr, "dss key generation failed\n"); 121 exit(1); 122 } 123 124 /* P = X - (C - 1) = X - C + 1*/ 125 if (mp_sub(&tempX, &tempC, &tempP) != MP_OKAY) { 126 fprintf(stderr, "dss key generation failed\n"); 127 exit(1); 128 } 129 130 if (mp_add_d(&tempP, 1, key->p) != MP_OKAY) { 131 fprintf(stderr, "dss key generation failed\n"); 132 exit(1); 133 } 134 135 /* now check for prime, 5 rounds is enough according to HAC */ 136 /* result == 1 => p is prime */ 137 if (mp_prime_is_prime(key->p, 5, &result) != MP_OKAY) { 138 fprintf(stderr, "dss key generation failed\n"); 139 exit(1); 140 } 141 } while (!result); 142 143 mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL); 144 m_burn(buf, size); 145 m_free(buf); 146} 147 148static void getg(dss_key * key) { 149 150 DEF_MP_INT(div); 151 DEF_MP_INT(h); 152 DEF_MP_INT(val); 153 154 m_mp_init_multi(&div, &h, &val, NULL); 155 156 /* get div=(p-1)/q */ 157 if (mp_sub_d(key->p, 1, &val) != MP_OKAY) { 158 fprintf(stderr, "dss key generation failed\n"); 159 exit(1); 160 } 161 if (mp_div(&val, key->q, &div, NULL) != MP_OKAY) { 162 fprintf(stderr, "dss key generation failed\n"); 163 exit(1); 164 } 165 166 /* initialise h=1 */ 167 mp_set(&h, 1); 168 do { 169 /* now keep going with g=h^div mod p, until g > 1 */ 170 if (mp_exptmod(&h, &div, key->p, key->g) != MP_OKAY) { 171 fprintf(stderr, "dss key generation failed\n"); 172 exit(1); 173 } 174 175 if (mp_add_d(&h, 1, &h) != MP_OKAY) { 176 fprintf(stderr, "dss key generation failed\n"); 177 exit(1); 178 } 179 180 } while (mp_cmp_d(key->g, 1) != MP_GT); 181 182 mp_clear_multi(&div, &h, &val, NULL); 183} 184 185static void getx(dss_key *key) { 186 187 gen_random_mpint(key->q, key->x); 188} 189 190static void gety(dss_key *key) { 191 192 if (mp_exptmod(key->g, key->x, key->p, key->y) != MP_OKAY) { 193 fprintf(stderr, "dss key generation failed\n"); 194 exit(1); 195 } 196} 197 198#endif /* DROPBEAR_DSS */ 199