summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--dh.c21
-rw-r--r--dh.h4
-rw-r--r--kex.c386
-rw-r--r--kex.h58
-rw-r--r--sshconnect2.c409
-rw-r--r--sshd.c359
7 files changed, 284 insertions, 959 deletions
diff --git a/ChangeLog b/ChangeLog
index df8ebde1c..0a84a5257 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,10 @@
6 - stevesk@cvs.openbsd.org 2001/04/03 13:56:11 6 - stevesk@cvs.openbsd.org 2001/04/03 13:56:11
7 [sftp-glob.c ssh-agent.c ssh-keygen.c] 7 [sftp-glob.c ssh-agent.c ssh-keygen.c]
8 free() -> xfree() 8 free() -> xfree()
9 - markus@cvs.openbsd.org 2001/04/03 19:53:29
10 [dh.c dh.h kex.c kex.h sshconnect2.c sshd.c]
11 move kex to kex*.c, used dispatch_set() callbacks for kex. should
12 make rekeying easier.
9 13
1020010403 1420010403
11 - OpenBSD CVS Sync 15 - OpenBSD CVS Sync
@@ -4816,4 +4820,4 @@
4816 - Wrote replacements for strlcpy and mkdtemp 4820 - Wrote replacements for strlcpy and mkdtemp
4817 - Released 1.0pre1 4821 - Released 1.0pre1
4818 4822
4819$Id: ChangeLog,v 1.1049 2001/04/04 01:53:20 mouring Exp $ 4823$Id: ChangeLog,v 1.1050 2001/04/04 01:56:17 mouring Exp $
diff --git a/dh.c b/dh.c
index 6c53b0038..03b9fd1b8 100644
--- a/dh.c
+++ b/dh.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: dh.c,v 1.11 2001/03/29 21:17:39 markus Exp $"); 26RCSID("$OpenBSD: dh.c,v 1.12 2001/04/03 19:53:29 markus Exp $");
27 27
28#include "xmalloc.h" 28#include "xmalloc.h"
29 29
@@ -273,3 +273,22 @@ dh_new_group1(void)
273 273
274 return (dh_new_group_asc(gen, group1)); 274 return (dh_new_group_asc(gen, group1));
275} 275}
276
277/*
278 * Estimates the group order for a Diffie-Hellman group that has an
279 * attack complexity approximately the same as O(2**bits). Estimate
280 * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
281 */
282
283int
284dh_estimate(int bits)
285{
286
287 if (bits < 64)
288 return (512); /* O(2**63) */
289 if (bits < 128)
290 return (1024); /* O(2**86) */
291 if (bits < 192)
292 return (2048); /* O(2**116) */
293 return (4096); /* O(2**156) */
294}
diff --git a/dh.h b/dh.h
index 13d2fa162..e8b2944ce 100644
--- a/dh.h
+++ b/dh.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: dh.h,v 1.4 2001/03/29 21:17:39 markus Exp $ */ 1/* $OpenBSD: dh.h,v 1.5 2001/04/03 19:53:29 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Niels Provos. All rights reserved. 4 * Copyright (c) 2000 Niels Provos. All rights reserved.
@@ -40,6 +40,8 @@ DH *dh_new_group1(void);
40void dh_gen_key(DH *, int); 40void dh_gen_key(DH *, int);
41int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); 41int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
42 42
43int dh_estimate(int bits);
44
43#define DH_GRP_MIN 1024 45#define DH_GRP_MIN 1024
44#define DH_GRP_MAX 8192 46#define DH_GRP_MAX 8192
45 47
diff --git a/kex.c b/kex.c
index 576d4b56e..a0a5b46fe 100644
--- a/kex.c
+++ b/kex.c
@@ -23,12 +23,9 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: kex.c,v 1.25 2001/03/29 21:17:39 markus Exp $"); 26RCSID("$OpenBSD: kex.c,v 1.26 2001/04/03 19:53:29 markus Exp $");
27 27
28#include <openssl/crypto.h> 28#include <openssl/crypto.h>
29#include <openssl/bio.h>
30#include <openssl/bn.h>
31#include <openssl/pem.h>
32 29
33#include "ssh2.h" 30#include "ssh2.h"
34#include "xmalloc.h" 31#include "xmalloc.h"
@@ -42,233 +39,169 @@ RCSID("$OpenBSD: kex.c,v 1.25 2001/03/29 21:17:39 markus Exp $");
42#include "log.h" 39#include "log.h"
43#include "mac.h" 40#include "mac.h"
44#include "match.h" 41#include "match.h"
42#include "dispatch.h"
45 43
46#define KEX_COOKIE_LEN 16 44#define KEX_COOKIE_LEN 16
47 45
48Buffer * 46void kex_kexinit_finish(Kex *kex);
49kex_init(char *myproposal[PROPOSAL_MAX]) 47void kex_choose_conf(Kex *k);
48
49/* put algorithm proposal into buffer */
50void
51kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
50{ 52{
51 int first_kex_packet_follows = 0;
52 u_char cookie[KEX_COOKIE_LEN];
53 u_int32_t rand = 0; 53 u_int32_t rand = 0;
54 int i; 54 int i;
55 Buffer *ki = xmalloc(sizeof(*ki)); 55
56 buffer_clear(b);
56 for (i = 0; i < KEX_COOKIE_LEN; i++) { 57 for (i = 0; i < KEX_COOKIE_LEN; i++) {
57 if (i % 4 == 0) 58 if (i % 4 == 0)
58 rand = arc4random(); 59 rand = arc4random();
59 cookie[i] = rand & 0xff; 60 buffer_put_char(b, rand & 0xff);
60 rand >>= 8; 61 rand >>= 8;
61 } 62 }
62 buffer_init(ki);
63 buffer_append(ki, (char *)cookie, sizeof cookie);
64 for (i = 0; i < PROPOSAL_MAX; i++) 63 for (i = 0; i < PROPOSAL_MAX; i++)
65 buffer_put_cstring(ki, myproposal[i]); 64 buffer_put_cstring(b, proposal[i]);
66 buffer_put_char(ki, first_kex_packet_follows); 65 buffer_put_char(b, 0); /* first_kex_packet_follows */
67 buffer_put_int(ki, 0); /* uint32 reserved */ 66 buffer_put_int(b, 0); /* uint32 reserved */
68 return ki;
69} 67}
70 68
71/* send kexinit, parse and save reply */ 69/* parse buffer and return algorithm proposal */
72void 70char **
73kex_exchange_kexinit( 71kex_buf2prop(Buffer *raw)
74 Buffer *my_kexinit, Buffer *peer_kexint,
75 char *peer_proposal[PROPOSAL_MAX])
76{ 72{
73 Buffer b;
77 int i; 74 int i;
78 char *ptr; 75 char **proposal;
79 int plen;
80 76
81 debug("send KEXINIT"); 77 proposal = xmalloc(PROPOSAL_MAX * sizeof(char *));
82 packet_start(SSH2_MSG_KEXINIT); 78
83 packet_put_raw(buffer_ptr(my_kexinit), buffer_len(my_kexinit)); 79 buffer_init(&b);
84 packet_send(); 80 buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
85 packet_write_wait();
86 debug("done");
87
88 /*
89 * read and save raw KEXINIT payload in buffer. this is used during
90 * computation of the session_id and the session keys.
91 */
92 debug("wait KEXINIT");
93 packet_read_expect(&plen, SSH2_MSG_KEXINIT);
94 ptr = packet_get_raw(&plen);
95 buffer_append(peer_kexint, ptr, plen);
96
97 /* parse packet and save algorithm proposal */
98 /* skip cookie */ 81 /* skip cookie */
99 for (i = 0; i < KEX_COOKIE_LEN; i++) 82 for (i = 0; i < KEX_COOKIE_LEN; i++)
100 packet_get_char(); 83 buffer_get_char(&b);
101 /* extract kex init proposal strings */ 84 /* extract kex init proposal strings */
102 for (i = 0; i < PROPOSAL_MAX; i++) { 85 for (i = 0; i < PROPOSAL_MAX; i++) {
103 peer_proposal[i] = packet_get_string(NULL); 86 proposal[i] = buffer_get_string(&b,NULL);
104 debug("got kexinit: %s", peer_proposal[i]); 87 debug2("kex_parse_kexinit: %s", proposal[i]);
105 } 88 }
106 /* first kex follow / reserved */ 89 /* first kex follows / reserved */
107 i = packet_get_char(); 90 i = buffer_get_char(&b);
108 debug("first kex follow: %d ", i); 91 debug2("kex_parse_kexinit: first_kex_follows %d ", i);
109 i = packet_get_int(); 92 i = buffer_get_int(&b);
110 debug("reserved: %d ", i); 93 debug2("kex_parse_kexinit: reserved %d ", i);
111 packet_done(); 94 buffer_free(&b);
112 debug("done"); 95 return proposal;
113} 96}
114 97
115#ifdef DEBUG_KEX
116void 98void
117dump_digest(u_char *digest, int len) 99kex_prop_free(char **proposal)
118{ 100{
119 int i; 101 int i;
120 for (i = 0; i< len; i++){ 102
121 fprintf(stderr, "%02x", digest[i]); 103 for (i = 0; i < PROPOSAL_MAX; i++)
122 if(i%2!=0) 104 xfree(proposal[i]);
123 fprintf(stderr, " "); 105 xfree(proposal);
124 }
125 fprintf(stderr, "\n");
126} 106}
127#endif
128 107
129u_char * 108void
130kex_hash( 109kex_protocol_error(int type, int plen, void *ctxt)
131 char *client_version_string,
132 char *server_version_string,
133 char *ckexinit, int ckexinitlen,
134 char *skexinit, int skexinitlen,
135 char *serverhostkeyblob, int sbloblen,
136 BIGNUM *client_dh_pub,
137 BIGNUM *server_dh_pub,
138 BIGNUM *shared_secret)
139{ 110{
140 Buffer b; 111 error("Hm, kex protocol error: type %d plen %d", type, plen);
141 static u_char digest[EVP_MAX_MD_SIZE]; 112}
142 EVP_MD *evp_md = EVP_sha1();
143 EVP_MD_CTX md;
144
145 buffer_init(&b);
146 buffer_put_string(&b, client_version_string, strlen(client_version_string));
147 buffer_put_string(&b, server_version_string, strlen(server_version_string));
148
149 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
150 buffer_put_int(&b, ckexinitlen+1);
151 buffer_put_char(&b, SSH2_MSG_KEXINIT);
152 buffer_append(&b, ckexinit, ckexinitlen);
153 buffer_put_int(&b, skexinitlen+1);
154 buffer_put_char(&b, SSH2_MSG_KEXINIT);
155 buffer_append(&b, skexinit, skexinitlen);
156
157 buffer_put_string(&b, serverhostkeyblob, sbloblen);
158 buffer_put_bignum2(&b, client_dh_pub);
159 buffer_put_bignum2(&b, server_dh_pub);
160 buffer_put_bignum2(&b, shared_secret);
161
162#ifdef DEBUG_KEX
163 buffer_dump(&b);
164#endif
165 113
166 EVP_DigestInit(&md, evp_md); 114void
167 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 115kex_send_newkeys(void)
168 EVP_DigestFinal(&md, digest, NULL); 116{
117 packet_start(SSH2_MSG_NEWKEYS);
118 packet_send();
119 /* packet_write_wait(); */
120 debug("SSH2_MSG_NEWKEYS sent");
121}
169 122
170 buffer_free(&b); 123void
124kex_input_newkeys(int type, int plen, void *ctxt)
125{
126 Kex *kex = ctxt;
127 int i;
171 128
172#ifdef DEBUG_KEX 129 debug("SSH2_MSG_NEWKEYS received");
173 dump_digest(digest, evp_md->md_size); 130 kex->newkeys = 1;
174#endif 131 for (i = 30; i <= 49; i++)
175 return digest; 132 dispatch_set(i, &kex_protocol_error);
133 buffer_clear(&kex->peer);
134 buffer_clear(&kex->my);
135 kex->flags &= ~KEX_INIT_SENT;
176} 136}
177 137
178u_char * 138void
179kex_hash_gex( 139kex_send_kexinit(Kex *kex)
180 char *client_version_string,
181 char *server_version_string,
182 char *ckexinit, int ckexinitlen,
183 char *skexinit, int skexinitlen,
184 char *serverhostkeyblob, int sbloblen,
185 int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen,
186 BIGNUM *client_dh_pub,
187 BIGNUM *server_dh_pub,
188 BIGNUM *shared_secret)
189{ 140{
190 Buffer b; 141 packet_start(SSH2_MSG_KEXINIT);
191 static u_char digest[EVP_MAX_MD_SIZE]; 142 packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
192 EVP_MD *evp_md = EVP_sha1(); 143 packet_send();
193 EVP_MD_CTX md; 144 debug("SSH2_MSG_KEXINIT sent");
194 145 kex->flags |= KEX_INIT_SENT;
195 buffer_init(&b); 146}
196 buffer_put_string(&b, client_version_string, strlen(client_version_string));
197 buffer_put_string(&b, server_version_string, strlen(server_version_string));
198
199 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
200 buffer_put_int(&b, ckexinitlen+1);
201 buffer_put_char(&b, SSH2_MSG_KEXINIT);
202 buffer_append(&b, ckexinit, ckexinitlen);
203 buffer_put_int(&b, skexinitlen+1);
204 buffer_put_char(&b, SSH2_MSG_KEXINIT);
205 buffer_append(&b, skexinit, skexinitlen);
206
207 buffer_put_string(&b, serverhostkeyblob, sbloblen);
208 if (min == -1 || max == -1)
209 buffer_put_int(&b, wantbits);
210 else {
211 buffer_put_int(&b, min);
212 buffer_put_int(&b, wantbits);
213 buffer_put_int(&b, max);
214 }
215 buffer_put_bignum2(&b, prime);
216 buffer_put_bignum2(&b, gen);
217 buffer_put_bignum2(&b, client_dh_pub);
218 buffer_put_bignum2(&b, server_dh_pub);
219 buffer_put_bignum2(&b, shared_secret);
220 147
221#ifdef DEBUG_KEX 148void
222 buffer_dump(&b); 149kex_input_kexinit(int type, int plen, void *ctxt)
223#endif 150{
151 char *ptr;
152 int dlen;
153 Kex *kex = (Kex *)ctxt;
224 154
225 EVP_DigestInit(&md, evp_md); 155 dispatch_set(SSH2_MSG_KEXINIT, &kex_protocol_error);
226 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 156 debug("SSH2_MSG_KEXINIT received");
227 EVP_DigestFinal(&md, digest, NULL);
228 157
229 buffer_free(&b); 158 ptr = packet_get_raw(&dlen);
159 buffer_append(&kex->peer, ptr, dlen);
230 160
231#ifdef DEBUG_KEX 161 kex_kexinit_finish(kex);
232 dump_digest(digest, evp_md->md_size);
233#endif
234 return digest;
235} 162}
236 163
237u_char * 164Kex *
238derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret) 165kex_start(char *proposal[PROPOSAL_MAX])
239{ 166{
240 Buffer b; 167 Kex *kex;
241 EVP_MD *evp_md = EVP_sha1(); 168 int i;
242 EVP_MD_CTX md;
243 char c = id;
244 int have;
245 int mdsz = evp_md->md_size;
246 u_char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
247
248 buffer_init(&b);
249 buffer_put_bignum2(&b, shared_secret);
250 169
251 EVP_DigestInit(&md, evp_md); 170 kex = xmalloc(sizeof(*kex));
252 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */ 171 memset(kex, 0, sizeof(*kex));
253 EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */ 172 buffer_init(&kex->peer);
254 EVP_DigestUpdate(&md, &c, 1); /* key id */ 173 buffer_init(&kex->my);
255 EVP_DigestUpdate(&md, hash, mdsz); /* session id */ 174 kex_prop2buf(&kex->my, proposal);
256 EVP_DigestFinal(&md, digest, NULL); 175 kex->newkeys = 0;
176
177 kex_send_kexinit(kex); /* we start */
178 /* Numbers 30-49 are used for kex packets */
179 for (i = 30; i <= 49; i++)
180 dispatch_set(i, kex_protocol_error);
181
182 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
183 dispatch_set(SSH2_MSG_NEWKEYS, &kex_input_newkeys);
184 return kex;
185}
257 186
258 /* expand */ 187void
259 for (have = mdsz; need > have; have += mdsz) { 188kex_kexinit_finish(Kex *kex)
260 EVP_DigestInit(&md, evp_md); 189{
261 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 190 if (!(kex->flags & KEX_INIT_SENT))
262 EVP_DigestUpdate(&md, hash, mdsz); 191 kex_send_kexinit(kex);
263 EVP_DigestUpdate(&md, digest, have); 192
264 EVP_DigestFinal(&md, digest + have, NULL); 193 kex_choose_conf(kex);
194
195 switch(kex->kex_type) {
196 case DH_GRP1_SHA1:
197 kexdh(kex);
198 break;
199 case DH_GEX_SHA1:
200 kexgex(kex);
201 break;
202 default:
203 fatal("Unsupported key exchange %d", kex->kex_type);
265 } 204 }
266 buffer_free(&b);
267#ifdef DEBUG_KEX
268 fprintf(stderr, "Digest '%c'== ", c);
269 dump_digest(digest, need);
270#endif
271 return digest;
272} 205}
273 206
274void 207void
@@ -340,17 +273,25 @@ choose_hostkeyalg(Kex *k, char *client, char *server)
340 xfree(hostkeyalg); 273 xfree(hostkeyalg);
341} 274}
342 275
343Kex * 276void
344kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server) 277kex_choose_conf(Kex *k)
345{ 278{
279 char **my, **peer;
280 char **cprop, **sprop;
346 int mode; 281 int mode;
347 int ctos; /* direction: if true client-to-server */ 282 int ctos; /* direction: if true client-to-server */
348 int need; 283 int need;
349 Kex *k;
350 284
351 k = xmalloc(sizeof(*k)); 285 my = kex_buf2prop(&k->my);
352 memset(k, 0, sizeof(*k)); 286 peer = kex_buf2prop(&k->peer);
353 k->server = server; 287
288 if (k->server) {
289 cprop=peer;
290 sprop=my;
291 } else {
292 cprop=my;
293 sprop=peer;
294 }
354 295
355 for (mode = 0; mode < MODE_MAX; mode++) { 296 for (mode = 0; mode < MODE_MAX; mode++) {
356 int nenc, nmac, ncomp; 297 int nenc, nmac, ncomp;
@@ -381,11 +322,51 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
381 } 322 }
382 /* XXX need runden? */ 323 /* XXX need runden? */
383 k->we_need = need; 324 k->we_need = need;
384 return k; 325
326 kex_prop_free(my);
327 kex_prop_free(peer);
328
329}
330
331u_char *
332derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret)
333{
334 Buffer b;
335 EVP_MD *evp_md = EVP_sha1();
336 EVP_MD_CTX md;
337 char c = id;
338 int have;
339 int mdsz = evp_md->md_size;
340 u_char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
341
342 buffer_init(&b);
343 buffer_put_bignum2(&b, shared_secret);
344
345 EVP_DigestInit(&md, evp_md);
346 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */
347 EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */
348 EVP_DigestUpdate(&md, &c, 1); /* key id */
349 EVP_DigestUpdate(&md, hash, mdsz); /* session id */
350 EVP_DigestFinal(&md, digest, NULL);
351
352 /* expand */
353 for (have = mdsz; need > have; have += mdsz) {
354 EVP_DigestInit(&md, evp_md);
355 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
356 EVP_DigestUpdate(&md, hash, mdsz);
357 EVP_DigestUpdate(&md, digest, have);
358 EVP_DigestFinal(&md, digest + have, NULL);
359 }
360 buffer_free(&b);
361#ifdef DEBUG_KEX
362 fprintf(stderr, "key '%c'== ", c);
363 dump_digest("key", digest, need);
364#endif
365 return digest;
385} 366}
386 367
387#define NKEYS 6 368#define NKEYS 6
388int 369void
389kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret) 370kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret)
390{ 371{
391 int i; 372 int i;
@@ -402,5 +383,22 @@ kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret)
402 k->enc[mode].key = keys[ctos ? 2 : 3]; 383 k->enc[mode].key = keys[ctos ? 2 : 3];
403 k->mac[mode].key = keys[ctos ? 4 : 5]; 384 k->mac[mode].key = keys[ctos ? 4 : 5];
404 } 385 }
405 return 0;
406} 386}
387
388#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
389void
390dump_digest(char *msg, u_char *digest, int len)
391{
392 int i;
393
394 fprintf(stderr, "%s\n", msg);
395 for (i = 0; i< len; i++){
396 fprintf(stderr, "%02x", digest[i]);
397 if (i%32 == 31)
398 fprintf(stderr, "\n");
399 else if (i%8 == 7)
400 fprintf(stderr, " ");
401 }
402 fprintf(stderr, "\n");
403}
404#endif
diff --git a/kex.h b/kex.h
index 4cc87d527..58f6d82c0 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.17 2001/03/29 21:17:40 markus Exp $ */ 1/* $OpenBSD: kex.h,v 1.18 2001/04/03 19:53:29 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -28,6 +28,8 @@
28 28
29#include <openssl/evp.h> 29#include <openssl/evp.h>
30#include "buffer.h" 30#include "buffer.h"
31#include "cipher.h"
32#include "key.h"
31 33
32#define KEX_DH1 "diffie-hellman-group1-sha1" 34#define KEX_DH1 "diffie-hellman-group1-sha1"
33#define KEX_DHGEX "diffie-hellman-group-exchange-sha1" 35#define KEX_DHGEX "diffie-hellman-group-exchange-sha1"
@@ -82,6 +84,7 @@ struct Comp {
82 int enabled; 84 int enabled;
83 char *name; 85 char *name;
84}; 86};
87#define KEX_INIT_SENT 0x0001
85struct Kex { 88struct Kex {
86 Enc enc [MODE_MAX]; 89 Enc enc [MODE_MAX];
87 Mac mac [MODE_MAX]; 90 Mac mac [MODE_MAX];
@@ -91,40 +94,31 @@ struct Kex {
91 char *name; 94 char *name;
92 int hostkey_type; 95 int hostkey_type;
93 int kex_type; 96 int kex_type;
97
98 /* used during kex */
99 Buffer my;
100 Buffer peer;
101 int newkeys;
102 int flags;
103 void *state;
104 char *client_version_string;
105 char *server_version_string;
106
107 int (*check_host_key)(Key *hostkey);
108 Key *(*load_host_key)(int type);
94}; 109};
95 110
96Buffer *kex_init(char *myproposal[PROPOSAL_MAX]); 111void kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret);
97void
98kex_exchange_kexinit(
99 Buffer *my_kexinit, Buffer *peer_kexint,
100 char *peer_proposal[PROPOSAL_MAX]);
101Kex *
102kex_choose_conf(char *cprop[PROPOSAL_MAX],
103 char *sprop[PROPOSAL_MAX], int server);
104int kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret);
105void packet_set_kex(Kex *k); 112void packet_set_kex(Kex *k);
113Kex *kex_start(char *proposal[PROPOSAL_MAX]);
114void kex_send_newkeys(void);
115void kex_protocol_error(int type, int plen, void *ctxt);
106 116
107u_char * 117void kexdh(Kex *);
108kex_hash( 118void kexgex(Kex *);
109 char *client_version_string, 119
110 char *server_version_string, 120#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
111 char *ckexinit, int ckexinitlen, 121void dump_digest(char *msg, u_char *digest, int len);
112 char *skexinit, int skexinitlen, 122#endif
113 char *serverhostkeyblob, int sbloblen,
114 BIGNUM *client_dh_pub,
115 BIGNUM *server_dh_pub,
116 BIGNUM *shared_secret);
117 123
118u_char *
119kex_hash_gex(
120 char *client_version_string,
121 char *server_version_string,
122 char *ckexinit, int ckexinitlen,
123 char *skexinit, int skexinitlen,
124 char *serverhostkeyblob, int sbloblen,
125 int min, int wantbits, int max,
126 BIGNUM *prime, BIGNUM *gen,
127 BIGNUM *client_dh_pub,
128 BIGNUM *server_dh_pub,
129 BIGNUM *shared_secret);
130#endif 124#endif
diff --git a/sshconnect2.c b/sshconnect2.c
index 460d614f0..4ed39a23e 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.60 2001/03/29 21:06:21 stevesk Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.61 2001/04/03 19:53:29 markus Exp $");
27 27
28#include <openssl/bn.h> 28#include <openssl/bn.h>
29#include <openssl/md5.h> 29#include <openssl/md5.h>
@@ -47,15 +47,12 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.60 2001/03/29 21:06:21 stevesk Exp $");
47#include "authfile.h" 47#include "authfile.h"
48#include "cli.h" 48#include "cli.h"
49#include "dh.h" 49#include "dh.h"
50#include "dispatch.h"
51#include "authfd.h" 50#include "authfd.h"
52#include "log.h" 51#include "log.h"
53#include "readconf.h" 52#include "readconf.h"
54#include "readpass.h" 53#include "readpass.h"
55#include "match.h" 54#include "match.h"
56 55#include "dispatch.h"
57void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
58void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
59 56
60/* import */ 57/* import */
61extern char *client_version_string; 58extern char *client_version_string;
@@ -69,13 +66,24 @@ extern Options options;
69u_char *session_id2 = NULL; 66u_char *session_id2 = NULL;
70int session_id2_len = 0; 67int session_id2_len = 0;
71 68
69char *xxx_host;
70struct sockaddr *xxx_hostaddr;
71
72int
73check_host_key_callback(Key *hostkey)
74{
75 check_host_key(xxx_host, xxx_hostaddr, hostkey,
76 options.user_hostfile2, options.system_hostfile2);
77 return 0;
78}
79
72void 80void
73ssh_kex2(char *host, struct sockaddr *hostaddr) 81ssh_kex2(char *host, struct sockaddr *hostaddr)
74{ 82{
75 int i, plen;
76 Kex *kex; 83 Kex *kex;
77 Buffer *client_kexinit, *server_kexinit; 84
78 char *sprop[PROPOSAL_MAX]; 85 xxx_host = host;
86 xxx_hostaddr = hostaddr;
79 87
80 if (options.ciphers == (char *)-1) { 88 if (options.ciphers == (char *)-1) {
81 log("No valid ciphers for protocol version 2 given, using defaults."); 89 log("No valid ciphers for protocol version 2 given, using defaults.");
@@ -101,46 +109,13 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
101 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; 109 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
102 } 110 }
103 111
104 /* buffers with raw kexinit messages */ 112 kex = kex_start(myproposal);
105 server_kexinit = xmalloc(sizeof(*server_kexinit)); 113 kex->client_version_string=client_version_string;
106 buffer_init(server_kexinit); 114 kex->server_version_string=server_version_string;
107 client_kexinit = kex_init(myproposal); 115 kex->check_host_key=&check_host_key_callback;
108
109 /* algorithm negotiation */
110 kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
111 kex = kex_choose_conf(myproposal, sprop, 0);
112 for (i = 0; i < PROPOSAL_MAX; i++)
113 xfree(sprop[i]);
114
115 /* server authentication and session key agreement */
116 switch(kex->kex_type) {
117 case DH_GRP1_SHA1:
118 ssh_dh1_client(kex, host, hostaddr,
119 client_kexinit, server_kexinit);
120 break;
121 case DH_GEX_SHA1:
122 ssh_dhgex_client(kex, host, hostaddr, client_kexinit,
123 server_kexinit);
124 break;
125 default:
126 fatal("Unsupported key exchange %d", kex->kex_type);
127 }
128
129 buffer_free(client_kexinit);
130 buffer_free(server_kexinit);
131 xfree(client_kexinit);
132 xfree(server_kexinit);
133 116
134 debug("Wait SSH2_MSG_NEWKEYS."); 117 /* start key exchange */
135 packet_read_expect(&plen, SSH2_MSG_NEWKEYS); 118 dispatch_run(DISPATCH_BLOCK, &kex->newkeys, kex);
136 packet_done();
137 debug("GOT SSH2_MSG_NEWKEYS.");
138
139 debug("send SSH2_MSG_NEWKEYS.");
140 packet_start(SSH2_MSG_NEWKEYS);
141 packet_send();
142 packet_write_wait();
143 debug("done: send SSH2_MSG_NEWKEYS.");
144 119
145#ifdef DEBUG_KEXDH 120#ifdef DEBUG_KEXDH
146 /* send 1st encrypted/maced/compressed message */ 121 /* send 1st encrypted/maced/compressed message */
@@ -149,339 +124,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
149 packet_send(); 124 packet_send();
150 packet_write_wait(); 125 packet_write_wait();
151#endif 126#endif
152 debug("done: KEX2."); 127 debug("done: ssh_kex2.");
153}
154
155/* diffie-hellman-group1-sha1 */
156
157void
158ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
159 Buffer *client_kexinit, Buffer *server_kexinit)
160{
161#ifdef DEBUG_KEXDH
162 int i;
163#endif
164 int plen, dlen;
165 u_int klen, kout;
166 char *signature = NULL;
167 u_int slen;
168 char *server_host_key_blob = NULL;
169 Key *server_host_key;
170 u_int sbloblen;
171 DH *dh;
172 BIGNUM *dh_server_pub = 0;
173 BIGNUM *shared_secret = 0;
174 u_char *kbuf;
175 u_char *hash;
176
177 debug("Sending SSH2_MSG_KEXDH_INIT.");
178 /* generate and send 'e', client DH public key */
179 dh = dh_new_group1();
180 dh_gen_key(dh, kex->we_need * 8);
181 packet_start(SSH2_MSG_KEXDH_INIT);
182 packet_put_bignum2(dh->pub_key);
183 packet_send();
184 packet_write_wait();
185
186#ifdef DEBUG_KEXDH
187 fprintf(stderr, "\np= ");
188 BN_print_fp(stderr, dh->p);
189 fprintf(stderr, "\ng= ");
190 BN_print_fp(stderr, dh->g);
191 fprintf(stderr, "\npub= ");
192 BN_print_fp(stderr, dh->pub_key);
193 fprintf(stderr, "\n");
194 DHparams_print_fp(stderr, dh);
195#endif
196
197 debug("Wait SSH2_MSG_KEXDH_REPLY.");
198
199 packet_read_expect(&plen, SSH2_MSG_KEXDH_REPLY);
200
201 debug("Got SSH2_MSG_KEXDH_REPLY.");
202
203 /* key, cert */
204 server_host_key_blob = packet_get_string(&sbloblen);
205 server_host_key = key_from_blob(server_host_key_blob, sbloblen);
206 if (server_host_key == NULL)
207 fatal("cannot decode server_host_key_blob");
208
209 check_host_key(host, hostaddr, server_host_key,
210 options.user_hostfile2, options.system_hostfile2);
211
212 /* DH paramter f, server public DH key */
213 dh_server_pub = BN_new();
214 if (dh_server_pub == NULL)
215 fatal("dh_server_pub == NULL");
216 packet_get_bignum2(dh_server_pub, &dlen);
217
218#ifdef DEBUG_KEXDH
219 fprintf(stderr, "\ndh_server_pub= ");
220 BN_print_fp(stderr, dh_server_pub);
221 fprintf(stderr, "\n");
222 debug("bits %d", BN_num_bits(dh_server_pub));
223#endif
224
225 /* signed H */
226 signature = packet_get_string(&slen);
227 packet_done();
228
229 if (!dh_pub_is_valid(dh, dh_server_pub))
230 packet_disconnect("bad server public DH value");
231
232 klen = DH_size(dh);
233 kbuf = xmalloc(klen);
234 kout = DH_compute_key(kbuf, dh_server_pub, dh);
235#ifdef DEBUG_KEXDH
236 debug("shared secret: len %d/%d", klen, kout);
237 fprintf(stderr, "shared secret == ");
238 for (i = 0; i< kout; i++)
239 fprintf(stderr, "%02x", (kbuf[i])&0xff);
240 fprintf(stderr, "\n");
241#endif
242 shared_secret = BN_new();
243
244 BN_bin2bn(kbuf, kout, shared_secret);
245 memset(kbuf, 0, klen);
246 xfree(kbuf);
247
248 /* calc and verify H */
249 hash = kex_hash(
250 client_version_string,
251 server_version_string,
252 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
253 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
254 server_host_key_blob, sbloblen,
255 dh->pub_key,
256 dh_server_pub,
257 shared_secret
258 );
259 xfree(server_host_key_blob);
260 DH_free(dh);
261 BN_free(dh_server_pub);
262#ifdef DEBUG_KEXDH
263 fprintf(stderr, "hash == ");
264 for (i = 0; i< 20; i++)
265 fprintf(stderr, "%02x", (hash[i])&0xff);
266 fprintf(stderr, "\n");
267#endif
268 if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1)
269 fatal("key_verify failed for server_host_key");
270 key_free(server_host_key);
271 xfree(signature);
272
273 kex_derive_keys(kex, hash, shared_secret);
274 BN_clear_free(shared_secret);
275 packet_set_kex(kex);
276
277 /* save session id */
278 session_id2_len = 20;
279 session_id2 = xmalloc(session_id2_len);
280 memcpy(session_id2, hash, session_id2_len);
281}
282
283/* diffie-hellman-group-exchange-sha1 */
284
285/*
286 * Estimates the group order for a Diffie-Hellman group that has an
287 * attack complexity approximately the same as O(2**bits). Estimate
288 * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
289 */
290
291int
292dh_estimate(int bits)
293{
294
295 if (bits < 64)
296 return (512); /* O(2**63) */
297 if (bits < 128)
298 return (1024); /* O(2**86) */
299 if (bits < 192)
300 return (2048); /* O(2**116) */
301 return (4096); /* O(2**156) */
302}
303
304void
305ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
306 Buffer *client_kexinit, Buffer *server_kexinit)
307{
308#ifdef DEBUG_KEXDH
309 int i;
310#endif
311 int plen, dlen;
312 u_int klen, kout;
313 char *signature = NULL;
314 u_int slen, nbits, min, max;
315 char *server_host_key_blob = NULL;
316 Key *server_host_key;
317 u_int sbloblen;
318 DH *dh;
319 BIGNUM *dh_server_pub = 0;
320 BIGNUM *shared_secret = 0;
321 BIGNUM *p = 0, *g = 0;
322 u_char *kbuf;
323 u_char *hash;
324
325 nbits = dh_estimate(kex->we_need * 8);
326
327 if (datafellows & SSH_OLD_DHGEX) {
328 debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST_OLD.");
329
330 /* Old GEX request */
331 packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
332 packet_put_int(nbits);
333 min = DH_GRP_MIN;
334 max = DH_GRP_MAX;
335 } else {
336 debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
337
338 /* New GEX request */
339 min = DH_GRP_MIN;
340 max = DH_GRP_MAX;
341
342 packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
343 packet_put_int(min);
344 packet_put_int(nbits);
345 packet_put_int(max);
346 }
347 packet_send();
348 packet_write_wait();
349
350#ifdef DEBUG_KEXDH
351 fprintf(stderr, "\nmin = %d, nbits = %d, max = %d", min, nbits, max);
352#endif
353
354 debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP.");
355
356 packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
357
358 debug("Got SSH2_MSG_KEX_DH_GEX_GROUP.");
359
360 if ((p = BN_new()) == NULL)
361 fatal("BN_new");
362 packet_get_bignum2(p, &dlen);
363 if ((g = BN_new()) == NULL)
364 fatal("BN_new");
365 packet_get_bignum2(g, &dlen);
366
367 if (BN_num_bits(p) < min || BN_num_bits(p) > max)
368 fatal("DH_GEX group out of range: %d !< %d !< %d",
369 min, BN_num_bits(p), max);
370
371 dh = dh_new_group(g, p);
372
373 dh_gen_key(dh, kex->we_need * 8);
374
375#ifdef DEBUG_KEXDH
376 fprintf(stderr, "\np= ");
377 BN_print_fp(stderr, dh->p);
378 fprintf(stderr, "\ng= ");
379 BN_print_fp(stderr, dh->g);
380 fprintf(stderr, "\npub= ");
381 BN_print_fp(stderr, dh->pub_key);
382 fprintf(stderr, "\n");
383 DHparams_print_fp(stderr, dh);
384#endif
385
386 debug("Sending SSH2_MSG_KEX_DH_GEX_INIT.");
387 /* generate and send 'e', client DH public key */
388 packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
389 packet_put_bignum2(dh->pub_key);
390 packet_send();
391 packet_write_wait();
392
393 debug("Wait SSH2_MSG_KEX_DH_GEX_REPLY.");
394
395 packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
396
397 debug("Got SSH2_MSG_KEXDH_REPLY.");
398
399 /* key, cert */
400 server_host_key_blob = packet_get_string(&sbloblen);
401 server_host_key = key_from_blob(server_host_key_blob, sbloblen);
402 if (server_host_key == NULL)
403 fatal("cannot decode server_host_key_blob");
404
405 check_host_key(host, hostaddr, server_host_key,
406 options.user_hostfile2, options.system_hostfile2);
407
408 /* DH paramter f, server public DH key */
409 dh_server_pub = BN_new();
410 if (dh_server_pub == NULL)
411 fatal("dh_server_pub == NULL");
412 packet_get_bignum2(dh_server_pub, &dlen);
413
414#ifdef DEBUG_KEXDH
415 fprintf(stderr, "\ndh_server_pub= ");
416 BN_print_fp(stderr, dh_server_pub);
417 fprintf(stderr, "\n");
418 debug("bits %d", BN_num_bits(dh_server_pub));
419#endif
420
421 /* signed H */
422 signature = packet_get_string(&slen);
423 packet_done();
424
425 if (!dh_pub_is_valid(dh, dh_server_pub))
426 packet_disconnect("bad server public DH value");
427
428 klen = DH_size(dh);
429 kbuf = xmalloc(klen);
430 kout = DH_compute_key(kbuf, dh_server_pub, dh);
431#ifdef DEBUG_KEXDH
432 debug("shared secret: len %d/%d", klen, kout);
433 fprintf(stderr, "shared secret == ");
434 for (i = 0; i< kout; i++)
435 fprintf(stderr, "%02x", (kbuf[i])&0xff);
436 fprintf(stderr, "\n");
437#endif
438 shared_secret = BN_new();
439
440 BN_bin2bn(kbuf, kout, shared_secret);
441 memset(kbuf, 0, klen);
442 xfree(kbuf);
443
444 if (datafellows & SSH_OLD_DHGEX) {
445 /* These values are not included in the hash */
446 min = -1;
447 max = -1;
448 }
449
450 /* calc and verify H */
451 hash = kex_hash_gex(
452 client_version_string,
453 server_version_string,
454 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
455 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
456 server_host_key_blob, sbloblen,
457 min, nbits, max,
458 dh->p, dh->g,
459 dh->pub_key,
460 dh_server_pub,
461 shared_secret
462 );
463 xfree(server_host_key_blob);
464 DH_free(dh);
465 BN_free(dh_server_pub);
466#ifdef DEBUG_KEXDH
467 fprintf(stderr, "hash == ");
468 for (i = 0; i< 20; i++)
469 fprintf(stderr, "%02x", (hash[i])&0xff);
470 fprintf(stderr, "\n");
471#endif
472 if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1)
473 fatal("key_verify failed for server_host_key");
474 key_free(server_host_key);
475 xfree(signature);
476
477 kex_derive_keys(kex, hash, shared_secret);
478 BN_clear_free(shared_secret);
479 packet_set_kex(kex);
480
481 /* save session id */
482 session_id2_len = 20;
483 session_id2 = xmalloc(session_id2_len);
484 memcpy(session_id2, hash, session_id2_len);
485} 128}
486 129
487/* 130/*
@@ -563,6 +206,7 @@ ssh_userauth2(const char *server_user, char *host)
563 Authctxt authctxt; 206 Authctxt authctxt;
564 int type; 207 int type;
565 int plen; 208 int plen;
209 int i;
566 210
567 if (options.challenge_reponse_authentication) 211 if (options.challenge_reponse_authentication)
568 options.kbd_interactive_authentication = 1; 212 options.kbd_interactive_authentication = 1;
@@ -603,7 +247,10 @@ ssh_userauth2(const char *server_user, char *host)
603 /* initial userauth request */ 247 /* initial userauth request */
604 userauth_none(&authctxt); 248 userauth_none(&authctxt);
605 249
606 dispatch_init(&input_userauth_error); 250 //dispatch_init(&input_userauth_error);
251 for (i = 50; i <= 254; i++) {
252 dispatch_set(i, &input_userauth_error);
253 }
607 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); 254 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
608 dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); 255 dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
609 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); 256 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
diff --git a/sshd.c b/sshd.c
index b5e2d0f6f..c54675962 100644
--- a/sshd.c
+++ b/sshd.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: sshd.c,v 1.185 2001/03/29 23:42:01 djm Exp $"); 43RCSID("$OpenBSD: sshd.c,v 1.186 2001/04/03 19:53:29 markus Exp $");
44 44
45#include <openssl/dh.h> 45#include <openssl/dh.h>
46#include <openssl/bn.h> 46#include <openssl/bn.h>
@@ -70,6 +70,7 @@ RCSID("$OpenBSD: sshd.c,v 1.185 2001/03/29 23:42:01 djm Exp $");
70#include "canohost.h" 70#include "canohost.h"
71#include "auth.h" 71#include "auth.h"
72#include "misc.h" 72#include "misc.h"
73#include "dispatch.h"
73 74
74#ifdef LIBWRAP 75#ifdef LIBWRAP
75#include <tcpd.h> 76#include <tcpd.h>
@@ -1407,14 +1408,7 @@ do_ssh1_kex(void)
1407void 1408void
1408do_ssh2_kex(void) 1409do_ssh2_kex(void)
1409{ 1410{
1410 Buffer *server_kexinit;
1411 Buffer *client_kexinit;
1412 int payload_len;
1413 int i;
1414 Kex *kex; 1411 Kex *kex;
1415 char *cprop[PROPOSAL_MAX];
1416
1417/* KEXINIT */
1418 1412
1419 if (options.ciphers != NULL) { 1413 if (options.ciphers != NULL) {
1420 myproposal[PROPOSAL_ENC_ALGS_CTOS] = 1414 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
@@ -1431,36 +1425,14 @@ do_ssh2_kex(void)
1431 } 1425 }
1432 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); 1426 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
1433 1427
1434 server_kexinit = kex_init(myproposal); 1428 kex = kex_start(myproposal);
1435 client_kexinit = xmalloc(sizeof(*client_kexinit)); 1429 kex->server = 1;
1436 buffer_init(client_kexinit); 1430 kex->client_version_string=client_version_string;
1437 1431 kex->server_version_string=server_version_string;
1438 /* algorithm negotiation */ 1432 kex->load_host_key=&get_hostkey_by_type;
1439 kex_exchange_kexinit(server_kexinit, client_kexinit, cprop);
1440 kex = kex_choose_conf(cprop, myproposal, 1);
1441 for (i = 0; i < PROPOSAL_MAX; i++)
1442 xfree(cprop[i]);
1443
1444 switch (kex->kex_type) {
1445 case DH_GRP1_SHA1:
1446 ssh_dh1_server(kex, client_kexinit, server_kexinit);
1447 break;
1448 case DH_GEX_SHA1:
1449 ssh_dhgex_server(kex, client_kexinit, server_kexinit);
1450 break;
1451 default:
1452 fatal("Unsupported key exchange %d", kex->kex_type);
1453 }
1454
1455 debug("send SSH2_MSG_NEWKEYS.");
1456 packet_start(SSH2_MSG_NEWKEYS);
1457 packet_send();
1458 packet_write_wait();
1459 debug("done: send SSH2_MSG_NEWKEYS.");
1460 1433
1461 debug("Wait SSH2_MSG_NEWKEYS."); 1434 /* start key exchange */
1462 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); 1435 dispatch_run(DISPATCH_BLOCK, &kex->newkeys, kex);
1463 debug("GOT SSH2_MSG_NEWKEYS.");
1464 1436
1465#ifdef DEBUG_KEXDH 1437#ifdef DEBUG_KEXDH
1466 /* send 1st encrypted/maced/compressed message */ 1438 /* send 1st encrypted/maced/compressed message */
@@ -1469,316 +1441,5 @@ do_ssh2_kex(void)
1469 packet_send(); 1441 packet_send();
1470 packet_write_wait(); 1442 packet_write_wait();
1471#endif 1443#endif
1472 1444 debug("KEX done");
1473 debug("done: KEX2.");
1474}
1475
1476/*
1477 * SSH2 key exchange
1478 */
1479
1480/* diffie-hellman-group1-sha1 */
1481
1482void
1483ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
1484{
1485#ifdef DEBUG_KEXDH
1486 int i;
1487#endif
1488 int payload_len, dlen;
1489 int slen;
1490 u_char *signature = NULL;
1491 u_char *server_host_key_blob = NULL;
1492 u_int sbloblen;
1493 u_int klen, kout;
1494 u_char *kbuf;
1495 u_char *hash;
1496 BIGNUM *shared_secret = 0;
1497 DH *dh;
1498 BIGNUM *dh_client_pub = 0;
1499 Key *hostkey;
1500
1501 hostkey = get_hostkey_by_type(kex->hostkey_type);
1502 if (hostkey == NULL)
1503 fatal("Unsupported hostkey type %d", kex->hostkey_type);
1504
1505/* KEXDH */
1506 /* generate DH key */
1507 dh = dh_new_group1(); /* XXX depends on 'kex' */
1508 dh_gen_key(dh, kex->we_need * 8);
1509
1510 debug("Wait SSH2_MSG_KEXDH_INIT.");
1511 packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT);
1512
1513 /* key, cert */
1514 dh_client_pub = BN_new();
1515 if (dh_client_pub == NULL)
1516 fatal("dh_client_pub == NULL");
1517 packet_get_bignum2(dh_client_pub, &dlen);
1518
1519#ifdef DEBUG_KEXDH
1520 fprintf(stderr, "\ndh_client_pub= ");
1521 BN_print_fp(stderr, dh_client_pub);
1522 fprintf(stderr, "\n");
1523 debug("bits %d", BN_num_bits(dh_client_pub));
1524#endif
1525
1526#ifdef DEBUG_KEXDH
1527 fprintf(stderr, "\np= ");
1528 BN_print_fp(stderr, dh->p);
1529 fprintf(stderr, "\ng= ");
1530 bn_print(dh->g);
1531 fprintf(stderr, "\npub= ");
1532 BN_print_fp(stderr, dh->pub_key);
1533 fprintf(stderr, "\n");
1534 DHparams_print_fp(stderr, dh);
1535#endif
1536 if (!dh_pub_is_valid(dh, dh_client_pub))
1537 packet_disconnect("bad client public DH value");
1538
1539 klen = DH_size(dh);
1540 kbuf = xmalloc(klen);
1541 kout = DH_compute_key(kbuf, dh_client_pub, dh);
1542
1543#ifdef DEBUG_KEXDH
1544 debug("shared secret: len %d/%d", klen, kout);
1545 fprintf(stderr, "shared secret == ");
1546 for (i = 0; i< kout; i++)
1547 fprintf(stderr, "%02x", (kbuf[i])&0xff);
1548 fprintf(stderr, "\n");
1549#endif
1550 shared_secret = BN_new();
1551
1552 BN_bin2bn(kbuf, kout, shared_secret);
1553 memset(kbuf, 0, klen);
1554 xfree(kbuf);
1555
1556 /* XXX precompute? */
1557 key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
1558
1559 /* calc H */ /* XXX depends on 'kex' */
1560 hash = kex_hash(
1561 client_version_string,
1562 server_version_string,
1563 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
1564 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
1565 (char *)server_host_key_blob, sbloblen,
1566 dh_client_pub,
1567 dh->pub_key,
1568 shared_secret
1569 );
1570 buffer_free(client_kexinit);
1571 buffer_free(server_kexinit);
1572 xfree(client_kexinit);
1573 xfree(server_kexinit);
1574 BN_free(dh_client_pub);
1575#ifdef DEBUG_KEXDH
1576 fprintf(stderr, "hash == ");
1577 for (i = 0; i< 20; i++)
1578 fprintf(stderr, "%02x", (hash[i])&0xff);
1579 fprintf(stderr, "\n");
1580#endif
1581 /* save session id := H */
1582 /* XXX hashlen depends on KEX */
1583 session_id2_len = 20;
1584 session_id2 = xmalloc(session_id2_len);
1585 memcpy(session_id2, hash, session_id2_len);
1586
1587 /* sign H */
1588 /* XXX hashlen depends on KEX */
1589 key_sign(hostkey, &signature, &slen, hash, 20);
1590
1591 destroy_sensitive_data();
1592
1593 /* send server hostkey, DH pubkey 'f' and singed H */
1594 packet_start(SSH2_MSG_KEXDH_REPLY);
1595 packet_put_string((char *)server_host_key_blob, sbloblen);
1596 packet_put_bignum2(dh->pub_key); /* f */
1597 packet_put_string((char *)signature, slen);
1598 packet_send();
1599 xfree(signature);
1600 xfree(server_host_key_blob);
1601 packet_write_wait();
1602
1603 kex_derive_keys(kex, hash, shared_secret);
1604 BN_clear_free(shared_secret);
1605 packet_set_kex(kex);
1606
1607 /* have keys, free DH */
1608 DH_free(dh);
1609}
1610
1611/* diffie-hellman-group-exchange-sha1 */
1612
1613void
1614ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
1615{
1616#ifdef DEBUG_KEXDH
1617 int i;
1618#endif
1619 int payload_len, dlen;
1620 int slen, nbits, type, min, max;
1621 u_char *signature = NULL;
1622 u_char *server_host_key_blob = NULL;
1623 u_int sbloblen;
1624 u_int klen, kout;
1625 u_char *kbuf;
1626 u_char *hash;
1627 BIGNUM *shared_secret = 0;
1628 DH *dh;
1629 BIGNUM *dh_client_pub = 0;
1630 Key *hostkey;
1631
1632 hostkey = get_hostkey_by_type(kex->hostkey_type);
1633 if (hostkey == NULL)
1634 fatal("Unsupported hostkey type %d", kex->hostkey_type);
1635
1636/* KEXDHGEX */
1637 debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST.");
1638 type = packet_read(&payload_len);
1639 if (type != SSH2_MSG_KEX_DH_GEX_REQUEST_OLD &&
1640 type != SSH2_MSG_KEX_DH_GEX_REQUEST)
1641 packet_disconnect("Protocol error: expected type %d or %d, got %d",
1642 SSH2_MSG_KEX_DH_GEX_REQUEST_OLD,
1643 SSH2_MSG_KEX_DH_GEX_REQUEST,
1644 type);
1645 if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) {
1646 nbits = packet_get_int();
1647 min = DH_GRP_MIN;
1648 max = DH_GRP_MAX;
1649 } else {
1650 min = packet_get_int();
1651 nbits = packet_get_int();
1652 max = packet_get_int();
1653
1654 min = MAX(DH_GRP_MIN, min);
1655 max = MIN(DH_GRP_MAX, max);
1656 }
1657
1658 if (max < min || nbits < min || max < nbits)
1659 fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
1660 min, nbits, max);
1661
1662 dh = choose_dh(min, nbits, max);
1663 if (dh == NULL)
1664 packet_disconnect("Protocol error: no matching DH grp found");
1665
1666 debug("Sending SSH2_MSG_KEX_DH_GEX_GROUP.");
1667 packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
1668 packet_put_bignum2(dh->p);
1669 packet_put_bignum2(dh->g);
1670 packet_send();
1671 packet_write_wait();
1672
1673 /* Compute our exchange value in parallel with the client */
1674
1675 dh_gen_key(dh, kex->we_need * 8);
1676
1677 debug("Wait SSH2_MSG_KEX_DH_GEX_INIT.");
1678 packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT);
1679
1680 /* key, cert */
1681 dh_client_pub = BN_new();
1682 if (dh_client_pub == NULL)
1683 fatal("dh_client_pub == NULL");
1684 packet_get_bignum2(dh_client_pub, &dlen);
1685
1686#ifdef DEBUG_KEXDH
1687 fprintf(stderr, "\ndh_client_pub= ");
1688 BN_print_fp(stderr, dh_client_pub);
1689 fprintf(stderr, "\n");
1690 debug("bits %d", BN_num_bits(dh_client_pub));
1691#endif
1692
1693#ifdef DEBUG_KEXDH
1694 fprintf(stderr, "\np= ");
1695 BN_print_fp(stderr, dh->p);
1696 fprintf(stderr, "\ng= ");
1697 bn_print(dh->g);
1698 fprintf(stderr, "\npub= ");
1699 BN_print_fp(stderr, dh->pub_key);
1700 fprintf(stderr, "\n");
1701 DHparams_print_fp(stderr, dh);
1702#endif
1703 if (!dh_pub_is_valid(dh, dh_client_pub))
1704 packet_disconnect("bad client public DH value");
1705
1706 klen = DH_size(dh);
1707 kbuf = xmalloc(klen);
1708 kout = DH_compute_key(kbuf, dh_client_pub, dh);
1709
1710#ifdef DEBUG_KEXDH
1711 debug("shared secret: len %d/%d", klen, kout);
1712 fprintf(stderr, "shared secret == ");
1713 for (i = 0; i< kout; i++)
1714 fprintf(stderr, "%02x", (kbuf[i])&0xff);
1715 fprintf(stderr, "\n");
1716#endif
1717 shared_secret = BN_new();
1718
1719 BN_bin2bn(kbuf, kout, shared_secret);
1720 memset(kbuf, 0, klen);
1721 xfree(kbuf);
1722
1723 /* XXX precompute? */
1724 key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
1725
1726 if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) {
1727 /* These values are not included in the hash */
1728 min = -1;
1729 max = -1;
1730 }
1731
1732 /* calc H */ /* XXX depends on 'kex' */
1733 hash = kex_hash_gex(
1734 client_version_string,
1735 server_version_string,
1736 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
1737 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
1738 (char *)server_host_key_blob, sbloblen,
1739 min, nbits, max,
1740 dh->p, dh->g,
1741 dh_client_pub,
1742 dh->pub_key,
1743 shared_secret
1744 );
1745 buffer_free(client_kexinit);
1746 buffer_free(server_kexinit);
1747 xfree(client_kexinit);
1748 xfree(server_kexinit);
1749 BN_free(dh_client_pub);
1750#ifdef DEBUG_KEXDH
1751 fprintf(stderr, "hash == ");
1752 for (i = 0; i< 20; i++)
1753 fprintf(stderr, "%02x", (hash[i])&0xff);
1754 fprintf(stderr, "\n");
1755#endif
1756 /* save session id := H */
1757 /* XXX hashlen depends on KEX */
1758 session_id2_len = 20;
1759 session_id2 = xmalloc(session_id2_len);
1760 memcpy(session_id2, hash, session_id2_len);
1761
1762 /* sign H */
1763 /* XXX hashlen depends on KEX */
1764 key_sign(hostkey, &signature, &slen, hash, 20);
1765
1766 destroy_sensitive_data();
1767
1768 /* send server hostkey, DH pubkey 'f' and singed H */
1769 packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
1770 packet_put_string((char *)server_host_key_blob, sbloblen);
1771 packet_put_bignum2(dh->pub_key); /* f */
1772 packet_put_string((char *)signature, slen);
1773 packet_send();
1774 xfree(signature);
1775 xfree(server_host_key_blob);
1776 packet_write_wait();
1777
1778 kex_derive_keys(kex, hash, shared_secret);
1779 BN_clear_free(shared_secret);
1780 packet_set_kex(kex);
1781
1782 /* have keys, free DH */
1783 DH_free(dh);
1784} 1445}