bf46d3d0095e6d3b8f3e6ccb8a0baad06052708f
[bcm963xx.git] / userapps / opensource / sshd / gendss.c
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
40 static void getq(dss_key *key);
41 static void getp(dss_key *key, unsigned int size);
42 static void getg(dss_key *key);
43 static void getx(dss_key *key);
44 static void gety(dss_key *key);
45
46 dss_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
71 static 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
89 static 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
148 static 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
185 static void getx(dss_key *key) {
186
187         gen_random_mpint(key->q, key->x);
188 }
189
190 static 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 */