View | Details | Raw Unified | Return to bug 387 | Differences between
and this patch

Collapse All | Expand All

(-)kex.c (-15 / +6 lines)
Lines 44-54 Link Here
44
44
45
#define KEX_COOKIE_LEN	16
45
#define KEX_COOKIE_LEN	16
46
46
47
/* Use privilege separation for sshd */
48
int use_privsep;
49
struct monitor *pmonitor;
50
51
52
/* prototype */
47
/* prototype */
53
static void kex_kexinit_finish(Kex *);
48
static void kex_kexinit_finish(Kex *);
54
static void kex_choose_conf(Kex *);
49
static void kex_choose_conf(Kex *);
Lines 237-250 Link Here
237
232
238
	kex_choose_conf(kex);
233
	kex_choose_conf(kex);
239
234
240
	switch (kex->kex_type) {
235
	if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
241
	case DH_GRP1_SHA1:
236
	    kex->kex[kex->kex_type] != NULL) {
242
		kexdh(kex);
237
		(kex->kex[kex->kex_type])(kex);
243
		break;
238
	} else {
244
	case DH_GEX_SHA1:
245
		kexgex(kex);
246
		break;
247
	default:
248
		fatal("Unsupported key exchange %d", kex->kex_type);
239
		fatal("Unsupported key exchange %d", kex->kex_type);
249
	}
240
	}
250
}
241
}
Lines 301-309 Link Here
301
	if (k->name == NULL)
292
	if (k->name == NULL)
302
		fatal("no kex alg");
293
		fatal("no kex alg");
303
	if (strcmp(k->name, KEX_DH1) == 0) {
294
	if (strcmp(k->name, KEX_DH1) == 0) {
304
		k->kex_type = DH_GRP1_SHA1;
295
		k->kex_type = KEX_DH_GRP1_SHA1;
305
	} else if (strcmp(k->name, KEX_DHGEX) == 0) {
296
	} else if (strcmp(k->name, KEX_DHGEX) == 0) {
306
		k->kex_type = DH_GEX_SHA1;
297
		k->kex_type = KEX_DH_GEX_SHA1;
307
	} else
298
	} else
308
		fatal("bad kex alg %s", k->name);
299
		fatal("bad kex alg %s", k->name);
309
}
300
}
(-)kex.h (-5 / +16 lines)
Lines 55-62 Link Here
55
};
55
};
56
56
57
enum kex_exchange {
57
enum kex_exchange {
58
	DH_GRP1_SHA1,
58
	KEX_DH_GRP1_SHA1,
59
	DH_GEX_SHA1
59
	KEX_DH_GEX_SHA1,
60
	KEX_MAX
60
};
61
};
61
62
62
#define KEX_INIT_SENT	0x0001
63
#define KEX_INIT_SENT	0x0001
Lines 112-117 Link Here
112
	int	(*verify_host_key)(Key *);
113
	int	(*verify_host_key)(Key *);
113
	Key	*(*load_host_key)(int);
114
	Key	*(*load_host_key)(int);
114
	int	(*host_key_index)(Key *);
115
	int	(*host_key_index)(Key *);
116
	void	(*kex[KEX_MAX])(Kex *);
115
};
117
};
116
118
117
Kex	*kex_setup(char *[PROPOSAL_MAX]);
119
Kex	*kex_setup(char *[PROPOSAL_MAX]);
Lines 121-130 Link Here
121
void	 kex_input_kexinit(int, u_int32_t, void *);
123
void	 kex_input_kexinit(int, u_int32_t, void *);
122
void	 kex_derive_keys(Kex *, u_char *, BIGNUM *);
124
void	 kex_derive_keys(Kex *, u_char *, BIGNUM *);
123
125
124
void	 kexdh(Kex *);
125
void	 kexgex(Kex *);
126
127
Newkeys *kex_get_newkeys(int);
126
Newkeys *kex_get_newkeys(int);
127
128
void	 kexdh_client(Kex *);
129
void	 kexdh_server(Kex *);
130
void	 kexgex_client(Kex *);
131
void	 kexgex_server(Kex *);
132
133
u_char *
134
kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
135
    BIGNUM *, BIGNUM *, BIGNUM *);
136
u_char *
137
kexgex_hash(char *, char *, char *, int, char *, int, u_char *, int,
138
    int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *);
128
139
129
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
140
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
130
void	dump_digest(char *, u_char *, int);
141
void	dump_digest(char *, u_char *, int);
(-)kexdh.c (-229 / +2 lines)
Lines 25-45 Link Here
25
#include "includes.h"
25
#include "includes.h"
26
RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
26
RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
27
27
28
#include <openssl/crypto.h>
28
#include <openssl/evp.h>
29
#include <openssl/bn.h>
30
29
31
#include "xmalloc.h"
32
#include "buffer.h"
30
#include "buffer.h"
33
#include "bufaux.h"
31
#include "bufaux.h"
34
#include "key.h"
35
#include "kex.h"
36
#include "log.h"
37
#include "packet.h"
38
#include "dh.h"
39
#include "ssh2.h"
32
#include "ssh2.h"
40
#include "monitor_wrap.h"
41
33
42
static u_char *
34
u_char *
43
kex_dh_hash(
35
kex_dh_hash(
44
    char *client_version_string,
36
    char *client_version_string,
45
    char *server_version_string,
37
    char *server_version_string,
Lines 85-307 Link Here
85
	dump_digest("hash", digest, EVP_MD_size(evp_md));
77
	dump_digest("hash", digest, EVP_MD_size(evp_md));
86
#endif
78
#endif
87
	return digest;
79
	return digest;
88
}
89
90
/* client */
91
92
static void
93
kexdh_client(Kex *kex)
94
{
95
	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
96
	DH *dh;
97
	Key *server_host_key;
98
	u_char *server_host_key_blob = NULL, *signature = NULL;
99
	u_char *kbuf, *hash;
100
	u_int klen, kout, slen, sbloblen;
101
102
	/* generate and send 'e', client DH public key */
103
	dh = dh_new_group1();
104
	dh_gen_key(dh, kex->we_need * 8);
105
	packet_start(SSH2_MSG_KEXDH_INIT);
106
	packet_put_bignum2(dh->pub_key);
107
	packet_send();
108
109
	debug("sending SSH2_MSG_KEXDH_INIT");
110
#ifdef DEBUG_KEXDH
111
	DHparams_print_fp(stderr, dh);
112
	fprintf(stderr, "pub= ");
113
	BN_print_fp(stderr, dh->pub_key);
114
	fprintf(stderr, "\n");
115
#endif
116
117
	debug("expecting SSH2_MSG_KEXDH_REPLY");
118
	packet_read_expect(SSH2_MSG_KEXDH_REPLY);
119
120
	/* key, cert */
121
	server_host_key_blob = packet_get_string(&sbloblen);
122
	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
123
	if (server_host_key == NULL)
124
		fatal("cannot decode server_host_key_blob");
125
	if (server_host_key->type != kex->hostkey_type)
126
		fatal("type mismatch for decoded server_host_key_blob");
127
	if (kex->verify_host_key == NULL)
128
		fatal("cannot verify server_host_key");
129
	if (kex->verify_host_key(server_host_key) == -1)
130
		fatal("server_host_key verification failed");
131
132
	/* DH paramter f, server public DH key */
133
	if ((dh_server_pub = BN_new()) == NULL)
134
		fatal("dh_server_pub == NULL");
135
	packet_get_bignum2(dh_server_pub);
136
137
#ifdef DEBUG_KEXDH
138
	fprintf(stderr, "dh_server_pub= ");
139
	BN_print_fp(stderr, dh_server_pub);
140
	fprintf(stderr, "\n");
141
	debug("bits %d", BN_num_bits(dh_server_pub));
142
#endif
143
144
	/* signed H */
145
	signature = packet_get_string(&slen);
146
	packet_check_eom();
147
148
	if (!dh_pub_is_valid(dh, dh_server_pub))
149
		packet_disconnect("bad server public DH value");
150
151
	klen = DH_size(dh);
152
	kbuf = xmalloc(klen);
153
	kout = DH_compute_key(kbuf, dh_server_pub, dh);
154
#ifdef DEBUG_KEXDH
155
	dump_digest("shared secret", kbuf, kout);
156
#endif
157
	if ((shared_secret = BN_new()) == NULL)
158
		fatal("kexdh_client: BN_new failed");
159
	BN_bin2bn(kbuf, kout, shared_secret);
160
	memset(kbuf, 0, klen);
161
	xfree(kbuf);
162
163
	/* calc and verify H */
164
	hash = kex_dh_hash(
165
	    kex->client_version_string,
166
	    kex->server_version_string,
167
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
168
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
169
	    server_host_key_blob, sbloblen,
170
	    dh->pub_key,
171
	    dh_server_pub,
172
	    shared_secret
173
	);
174
	xfree(server_host_key_blob);
175
	BN_clear_free(dh_server_pub);
176
	DH_free(dh);
177
178
	if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
179
		fatal("key_verify failed for server_host_key");
180
	key_free(server_host_key);
181
	xfree(signature);
182
183
	/* save session id */
184
	if (kex->session_id == NULL) {
185
		kex->session_id_len = 20;
186
		kex->session_id = xmalloc(kex->session_id_len);
187
		memcpy(kex->session_id, hash, kex->session_id_len);
188
	}
189
190
	kex_derive_keys(kex, hash, shared_secret);
191
	BN_clear_free(shared_secret);
192
	kex_finish(kex);
193
}
194
195
/* server */
196
197
static void
198
kexdh_server(Kex *kex)
199
{
200
	BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
201
	DH *dh;
202
	Key *server_host_key;
203
	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
204
	u_int sbloblen, klen, kout;
205
	u_int slen;
206
207
	/* generate server DH public key */
208
	dh = dh_new_group1();
209
	dh_gen_key(dh, kex->we_need * 8);
210
211
	debug("expecting SSH2_MSG_KEXDH_INIT");
212
	packet_read_expect(SSH2_MSG_KEXDH_INIT);
213
214
	if (kex->load_host_key == NULL)
215
		fatal("Cannot load hostkey");
216
	server_host_key = kex->load_host_key(kex->hostkey_type);
217
	if (server_host_key == NULL)
218
		fatal("Unsupported hostkey type %d", kex->hostkey_type);
219
220
	/* key, cert */
221
	if ((dh_client_pub = BN_new()) == NULL)
222
		fatal("dh_client_pub == NULL");
223
	packet_get_bignum2(dh_client_pub);
224
	packet_check_eom();
225
226
#ifdef DEBUG_KEXDH
227
	fprintf(stderr, "dh_client_pub= ");
228
	BN_print_fp(stderr, dh_client_pub);
229
	fprintf(stderr, "\n");
230
	debug("bits %d", BN_num_bits(dh_client_pub));
231
#endif
232
233
#ifdef DEBUG_KEXDH
234
	DHparams_print_fp(stderr, dh);
235
	fprintf(stderr, "pub= ");
236
	BN_print_fp(stderr, dh->pub_key);
237
	fprintf(stderr, "\n");
238
#endif
239
	if (!dh_pub_is_valid(dh, dh_client_pub))
240
		packet_disconnect("bad client public DH value");
241
242
	klen = DH_size(dh);
243
	kbuf = xmalloc(klen);
244
	kout = DH_compute_key(kbuf, dh_client_pub, dh);
245
#ifdef DEBUG_KEXDH
246
	dump_digest("shared secret", kbuf, kout);
247
#endif
248
	if ((shared_secret = BN_new()) == NULL)
249
		fatal("kexdh_server: BN_new failed");
250
	BN_bin2bn(kbuf, kout, shared_secret);
251
	memset(kbuf, 0, klen);
252
	xfree(kbuf);
253
254
	key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
255
256
	/* calc H */
257
	hash = kex_dh_hash(
258
	    kex->client_version_string,
259
	    kex->server_version_string,
260
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
261
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
262
	    server_host_key_blob, sbloblen,
263
	    dh_client_pub,
264
	    dh->pub_key,
265
	    shared_secret
266
	);
267
	BN_clear_free(dh_client_pub);
268
269
	/* save session id := H */
270
	/* XXX hashlen depends on KEX */
271
	if (kex->session_id == NULL) {
272
		kex->session_id_len = 20;
273
		kex->session_id = xmalloc(kex->session_id_len);
274
		memcpy(kex->session_id, hash, kex->session_id_len);
275
	}
276
277
	/* sign H */
278
	/* XXX hashlen depends on KEX */
279
	PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
280
281
	/* destroy_sensitive_data(); */
282
283
	/* send server hostkey, DH pubkey 'f' and singed H */
284
	packet_start(SSH2_MSG_KEXDH_REPLY);
285
	packet_put_string(server_host_key_blob, sbloblen);
286
	packet_put_bignum2(dh->pub_key);	/* f */
287
	packet_put_string(signature, slen);
288
	packet_send();
289
290
	xfree(signature);
291
	xfree(server_host_key_blob);
292
	/* have keys, free DH */
293
	DH_free(dh);
294
295
	kex_derive_keys(kex, hash, shared_secret);
296
	BN_clear_free(shared_secret);
297
	kex_finish(kex);
298
}
299
300
void
301
kexdh(Kex *kex)
302
{
303
	if (kex->server)
304
		kexdh_server(kex);
305
	else
306
		kexdh_client(kex);
307
}
80
}
(-)kexdhc.c (+137 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#include "includes.h"
26
RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
27
28
#include "xmalloc.h"
29
#include "key.h"
30
#include "kex.h"
31
#include "log.h"
32
#include "packet.h"
33
#include "dh.h"
34
#include "ssh2.h"
35
36
void
37
kexdh_client(Kex *kex)
38
{
39
	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
40
	DH *dh;
41
	Key *server_host_key;
42
	u_char *server_host_key_blob = NULL, *signature = NULL;
43
	u_char *kbuf, *hash;
44
	u_int klen, kout, slen, sbloblen;
45
46
	/* generate and send 'e', client DH public key */
47
	dh = dh_new_group1();
48
	dh_gen_key(dh, kex->we_need * 8);
49
	packet_start(SSH2_MSG_KEXDH_INIT);
50
	packet_put_bignum2(dh->pub_key);
51
	packet_send();
52
53
	debug("sending SSH2_MSG_KEXDH_INIT");
54
#ifdef DEBUG_KEXDH
55
	DHparams_print_fp(stderr, dh);
56
	fprintf(stderr, "pub= ");
57
	BN_print_fp(stderr, dh->pub_key);
58
	fprintf(stderr, "\n");
59
#endif
60
61
	debug("expecting SSH2_MSG_KEXDH_REPLY");
62
	packet_read_expect(SSH2_MSG_KEXDH_REPLY);
63
64
	/* key, cert */
65
	server_host_key_blob = packet_get_string(&sbloblen);
66
	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
67
	if (server_host_key == NULL)
68
		fatal("cannot decode server_host_key_blob");
69
	if (server_host_key->type != kex->hostkey_type)
70
		fatal("type mismatch for decoded server_host_key_blob");
71
	if (kex->verify_host_key == NULL)
72
		fatal("cannot verify server_host_key");
73
	if (kex->verify_host_key(server_host_key) == -1)
74
		fatal("server_host_key verification failed");
75
76
	/* DH paramter f, server public DH key */
77
	if ((dh_server_pub = BN_new()) == NULL)
78
		fatal("dh_server_pub == NULL");
79
	packet_get_bignum2(dh_server_pub);
80
81
#ifdef DEBUG_KEXDH
82
	fprintf(stderr, "dh_server_pub= ");
83
	BN_print_fp(stderr, dh_server_pub);
84
	fprintf(stderr, "\n");
85
	debug("bits %d", BN_num_bits(dh_server_pub));
86
#endif
87
88
	/* signed H */
89
	signature = packet_get_string(&slen);
90
	packet_check_eom();
91
92
	if (!dh_pub_is_valid(dh, dh_server_pub))
93
		packet_disconnect("bad server public DH value");
94
95
	klen = DH_size(dh);
96
	kbuf = xmalloc(klen);
97
	kout = DH_compute_key(kbuf, dh_server_pub, dh);
98
#ifdef DEBUG_KEXDH
99
	dump_digest("shared secret", kbuf, kout);
100
#endif
101
	if ((shared_secret = BN_new()) == NULL)
102
		fatal("kexdh_client: BN_new failed");
103
	BN_bin2bn(kbuf, kout, shared_secret);
104
	memset(kbuf, 0, klen);
105
	xfree(kbuf);
106
107
	/* calc and verify H */
108
	hash = kex_dh_hash(
109
	    kex->client_version_string,
110
	    kex->server_version_string,
111
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
112
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
113
	    server_host_key_blob, sbloblen,
114
	    dh->pub_key,
115
	    dh_server_pub,
116
	    shared_secret
117
	);
118
	xfree(server_host_key_blob);
119
	BN_clear_free(dh_server_pub);
120
	DH_free(dh);
121
122
	if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
123
		fatal("key_verify failed for server_host_key");
124
	key_free(server_host_key);
125
	xfree(signature);
126
127
	/* save session id */
128
	if (kex->session_id == NULL) {
129
		kex->session_id_len = 20;
130
		kex->session_id = xmalloc(kex->session_id_len);
131
		memcpy(kex->session_id, hash, kex->session_id_len);
132
	}
133
134
	kex_derive_keys(kex, hash, shared_secret);
135
	BN_clear_free(shared_secret);
136
	kex_finish(kex);
137
}
(-)kexdhs.c (+138 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#include "includes.h"
26
RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
27
28
#include "xmalloc.h"
29
#include "key.h"
30
#include "kex.h"
31
#include "log.h"
32
#include "packet.h"
33
#include "dh.h"
34
#include "ssh2.h"
35
#include "monitor_wrap.h"
36
37
void
38
kexdh_server(Kex *kex)
39
{
40
	BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
41
	DH *dh;
42
	Key *server_host_key;
43
	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
44
	u_int sbloblen, klen, kout;
45
	u_int slen;
46
47
	/* generate server DH public key */
48
	dh = dh_new_group1();
49
	dh_gen_key(dh, kex->we_need * 8);
50
51
	debug("expecting SSH2_MSG_KEXDH_INIT");
52
	packet_read_expect(SSH2_MSG_KEXDH_INIT);
53
54
	if (kex->load_host_key == NULL)
55
		fatal("Cannot load hostkey");
56
	server_host_key = kex->load_host_key(kex->hostkey_type);
57
	if (server_host_key == NULL)
58
		fatal("Unsupported hostkey type %d", kex->hostkey_type);
59
60
	/* key, cert */
61
	if ((dh_client_pub = BN_new()) == NULL)
62
		fatal("dh_client_pub == NULL");
63
	packet_get_bignum2(dh_client_pub);
64
	packet_check_eom();
65
66
#ifdef DEBUG_KEXDH
67
	fprintf(stderr, "dh_client_pub= ");
68
	BN_print_fp(stderr, dh_client_pub);
69
	fprintf(stderr, "\n");
70
	debug("bits %d", BN_num_bits(dh_client_pub));
71
#endif
72
73
#ifdef DEBUG_KEXDH
74
	DHparams_print_fp(stderr, dh);
75
	fprintf(stderr, "pub= ");
76
	BN_print_fp(stderr, dh->pub_key);
77
	fprintf(stderr, "\n");
78
#endif
79
	if (!dh_pub_is_valid(dh, dh_client_pub))
80
		packet_disconnect("bad client public DH value");
81
82
	klen = DH_size(dh);
83
	kbuf = xmalloc(klen);
84
	kout = DH_compute_key(kbuf, dh_client_pub, dh);
85
#ifdef DEBUG_KEXDH
86
	dump_digest("shared secret", kbuf, kout);
87
#endif
88
	if ((shared_secret = BN_new()) == NULL)
89
		fatal("kexdh_server: BN_new failed");
90
	BN_bin2bn(kbuf, kout, shared_secret);
91
	memset(kbuf, 0, klen);
92
	xfree(kbuf);
93
94
	key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
95
96
	/* calc H */
97
	hash = kex_dh_hash(
98
	    kex->client_version_string,
99
	    kex->server_version_string,
100
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
101
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
102
	    server_host_key_blob, sbloblen,
103
	    dh_client_pub,
104
	    dh->pub_key,
105
	    shared_secret
106
	);
107
	BN_clear_free(dh_client_pub);
108
109
	/* save session id := H */
110
	/* XXX hashlen depends on KEX */
111
	if (kex->session_id == NULL) {
112
		kex->session_id_len = 20;
113
		kex->session_id = xmalloc(kex->session_id_len);
114
		memcpy(kex->session_id, hash, kex->session_id_len);
115
	}
116
117
	/* sign H */
118
	/* XXX hashlen depends on KEX */
119
	PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
120
121
	/* destroy_sensitive_data(); */
122
123
	/* send server hostkey, DH pubkey 'f' and singed H */
124
	packet_start(SSH2_MSG_KEXDH_REPLY);
125
	packet_put_string(server_host_key_blob, sbloblen);
126
	packet_put_bignum2(dh->pub_key);	/* f */
127
	packet_put_string(signature, slen);
128
	packet_send();
129
130
	xfree(signature);
131
	xfree(server_host_key_blob);
132
	/* have keys, free DH */
133
	DH_free(dh);
134
135
	kex_derive_keys(kex, hash, shared_secret);
136
	BN_clear_free(shared_secret);
137
	kex_finish(kex);
138
}
(-)kexgex.c (-324 / +2 lines)
Lines 26-46 Link Here
26
#include "includes.h"
26
#include "includes.h"
27
RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
27
RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
28
28
29
#include <openssl/bn.h>
29
#include <openssl/evp.h>
30
30
31
#include "xmalloc.h"
32
#include "buffer.h"
31
#include "buffer.h"
33
#include "bufaux.h"
32
#include "bufaux.h"
34
#include "key.h"
35
#include "kex.h"
33
#include "kex.h"
36
#include "log.h"
37
#include "packet.h"
38
#include "dh.h"
39
#include "ssh2.h"
34
#include "ssh2.h"
40
#include "compat.h"
41
#include "monitor_wrap.h"
42
35
43
static u_char *
36
u_char *
44
kexgex_hash(
37
kexgex_hash(
45
    char *client_version_string,
38
    char *client_version_string,
46
    char *server_version_string,
39
    char *server_version_string,
Lines 96-414 Link Here
96
	dump_digest("hash", digest, EVP_MD_size(evp_md));
89
	dump_digest("hash", digest, EVP_MD_size(evp_md));
97
#endif
90
#endif
98
	return digest;
91
	return digest;
99
}
100
101
/* client */
102
103
static void
104
kexgex_client(Kex *kex)
105
{
106
	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
107
	BIGNUM *p = NULL, *g = NULL;
108
	Key *server_host_key;
109
	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
110
	u_int klen, kout, slen, sbloblen;
111
	int min, max, nbits;
112
	DH *dh;
113
114
	nbits = dh_estimate(kex->we_need * 8);
115
116
	if (datafellows & SSH_OLD_DHGEX) {
117
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD sent");
118
119
		/* Old GEX request */
120
		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
121
		packet_put_int(nbits);
122
		min = DH_GRP_MIN;
123
		max = DH_GRP_MAX;
124
	} else {
125
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent");
126
127
		/* New GEX request */
128
		min = DH_GRP_MIN;
129
		max = DH_GRP_MAX;
130
		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
131
		packet_put_int(min);
132
		packet_put_int(nbits);
133
		packet_put_int(max);
134
	}
135
#ifdef DEBUG_KEXDH
136
	fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
137
	    min, nbits, max);
138
#endif
139
	packet_send();
140
141
	debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
142
	packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP);
143
144
	if ((p = BN_new()) == NULL)
145
		fatal("BN_new");
146
	packet_get_bignum2(p);
147
	if ((g = BN_new()) == NULL)
148
		fatal("BN_new");
149
	packet_get_bignum2(g);
150
	packet_check_eom();
151
152
	if (BN_num_bits(p) < min || BN_num_bits(p) > max)
153
		fatal("DH_GEX group out of range: %d !< %d !< %d",
154
		    min, BN_num_bits(p), max);
155
156
	dh = dh_new_group(g, p);
157
	dh_gen_key(dh, kex->we_need * 8);
158
159
#ifdef DEBUG_KEXDH
160
	DHparams_print_fp(stderr, dh);
161
	fprintf(stderr, "pub= ");
162
	BN_print_fp(stderr, dh->pub_key);
163
	fprintf(stderr, "\n");
164
#endif
165
166
	debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
167
	/* generate and send 'e', client DH public key */
168
	packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
169
	packet_put_bignum2(dh->pub_key);
170
	packet_send();
171
172
	debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
173
	packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY);
174
175
	/* key, cert */
176
	server_host_key_blob = packet_get_string(&sbloblen);
177
	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
178
	if (server_host_key == NULL)
179
		fatal("cannot decode server_host_key_blob");
180
	if (server_host_key->type != kex->hostkey_type)
181
		fatal("type mismatch for decoded server_host_key_blob");
182
	if (kex->verify_host_key == NULL)
183
		fatal("cannot verify server_host_key");
184
	if (kex->verify_host_key(server_host_key) == -1)
185
		fatal("server_host_key verification failed");
186
187
	/* DH paramter f, server public DH key */
188
	if ((dh_server_pub = BN_new()) == NULL)
189
		fatal("dh_server_pub == NULL");
190
	packet_get_bignum2(dh_server_pub);
191
192
#ifdef DEBUG_KEXDH
193
	fprintf(stderr, "dh_server_pub= ");
194
	BN_print_fp(stderr, dh_server_pub);
195
	fprintf(stderr, "\n");
196
	debug("bits %d", BN_num_bits(dh_server_pub));
197
#endif
198
199
	/* signed H */
200
	signature = packet_get_string(&slen);
201
	packet_check_eom();
202
203
	if (!dh_pub_is_valid(dh, dh_server_pub))
204
		packet_disconnect("bad server public DH value");
205
206
	klen = DH_size(dh);
207
	kbuf = xmalloc(klen);
208
	kout = DH_compute_key(kbuf, dh_server_pub, dh);
209
#ifdef DEBUG_KEXDH
210
	dump_digest("shared secret", kbuf, kout);
211
#endif
212
	if ((shared_secret = BN_new()) == NULL)
213
		fatal("kexgex_client: BN_new failed");
214
	BN_bin2bn(kbuf, kout, shared_secret);
215
	memset(kbuf, 0, klen);
216
	xfree(kbuf);
217
218
	if (datafellows & SSH_OLD_DHGEX)
219
		min = max = -1;
220
221
	/* calc and verify H */
222
	hash = kexgex_hash(
223
	    kex->client_version_string,
224
	    kex->server_version_string,
225
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
226
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
227
	    server_host_key_blob, sbloblen,
228
	    min, nbits, max,
229
	    dh->p, dh->g,
230
	    dh->pub_key,
231
	    dh_server_pub,
232
	    shared_secret
233
	);
234
	/* have keys, free DH */
235
	DH_free(dh);
236
	xfree(server_host_key_blob);
237
	BN_clear_free(dh_server_pub);
238
239
	if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
240
		fatal("key_verify failed for server_host_key");
241
	key_free(server_host_key);
242
	xfree(signature);
243
244
	/* save session id */
245
	if (kex->session_id == NULL) {
246
		kex->session_id_len = 20;
247
		kex->session_id = xmalloc(kex->session_id_len);
248
		memcpy(kex->session_id, hash, kex->session_id_len);
249
	}
250
	kex_derive_keys(kex, hash, shared_secret);
251
	BN_clear_free(shared_secret);
252
253
	kex_finish(kex);
254
}
255
256
/* server */
257
258
static void
259
kexgex_server(Kex *kex)
260
{
261
	BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
262
	Key *server_host_key;
263
	DH *dh;
264
	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
265
	u_int sbloblen, klen, kout, slen;
266
	int min = -1, max = -1, nbits = -1, type;
267
268
	if (kex->load_host_key == NULL)
269
		fatal("Cannot load hostkey");
270
	server_host_key = kex->load_host_key(kex->hostkey_type);
271
	if (server_host_key == NULL)
272
		fatal("Unsupported hostkey type %d", kex->hostkey_type);
273
274
	type = packet_read();
275
	switch (type) {
276
	case SSH2_MSG_KEX_DH_GEX_REQUEST:
277
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
278
		min = packet_get_int();
279
		nbits = packet_get_int();
280
		max = packet_get_int();
281
		min = MAX(DH_GRP_MIN, min);
282
		max = MIN(DH_GRP_MAX, max);
283
		break;
284
	case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD:
285
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received");
286
		nbits = packet_get_int();
287
		min = DH_GRP_MIN;
288
		max = DH_GRP_MAX;
289
		/* unused for old GEX */
290
		break;
291
	default:
292
		fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type);
293
	}
294
	packet_check_eom();
295
296
	if (max < min || nbits < min || max < nbits)
297
		fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
298
		    min, nbits, max);
299
300
	/* Contact privileged parent */
301
	dh = PRIVSEP(choose_dh(min, nbits, max));
302
	if (dh == NULL)
303
		packet_disconnect("Protocol error: no matching DH grp found");
304
305
	debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
306
	packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
307
	packet_put_bignum2(dh->p);
308
	packet_put_bignum2(dh->g);
309
	packet_send();
310
311
	/* flush */
312
	packet_write_wait();
313
314
	/* Compute our exchange value in parallel with the client */
315
	dh_gen_key(dh, kex->we_need * 8);
316
317
	debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
318
	packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT);
319
320
	/* key, cert */
321
	if ((dh_client_pub = BN_new()) == NULL)
322
		fatal("dh_client_pub == NULL");
323
	packet_get_bignum2(dh_client_pub);
324
	packet_check_eom();
325
326
#ifdef DEBUG_KEXDH
327
	fprintf(stderr, "dh_client_pub= ");
328
	BN_print_fp(stderr, dh_client_pub);
329
	fprintf(stderr, "\n");
330
	debug("bits %d", BN_num_bits(dh_client_pub));
331
#endif
332
333
#ifdef DEBUG_KEXDH
334
	DHparams_print_fp(stderr, dh);
335
	fprintf(stderr, "pub= ");
336
	BN_print_fp(stderr, dh->pub_key);
337
	fprintf(stderr, "\n");
338
#endif
339
	if (!dh_pub_is_valid(dh, dh_client_pub))
340
		packet_disconnect("bad client public DH value");
341
342
	klen = DH_size(dh);
343
	kbuf = xmalloc(klen);
344
	kout = DH_compute_key(kbuf, dh_client_pub, dh);
345
#ifdef DEBUG_KEXDH
346
	dump_digest("shared secret", kbuf, kout);
347
#endif
348
	if ((shared_secret = BN_new()) == NULL)
349
		fatal("kexgex_server: BN_new failed");
350
	BN_bin2bn(kbuf, kout, shared_secret);
351
	memset(kbuf, 0, klen);
352
	xfree(kbuf);
353
354
	key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
355
356
	if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
357
		min = max = -1;
358
359
	/* calc H */			/* XXX depends on 'kex' */
360
	hash = kexgex_hash(
361
	    kex->client_version_string,
362
	    kex->server_version_string,
363
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
364
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
365
	    server_host_key_blob, sbloblen,
366
	    min, nbits, max,
367
	    dh->p, dh->g,
368
	    dh_client_pub,
369
	    dh->pub_key,
370
	    shared_secret
371
	);
372
	BN_clear_free(dh_client_pub);
373
374
	/* save session id := H */
375
	/* XXX hashlen depends on KEX */
376
	if (kex->session_id == NULL) {
377
		kex->session_id_len = 20;
378
		kex->session_id = xmalloc(kex->session_id_len);
379
		memcpy(kex->session_id, hash, kex->session_id_len);
380
	}
381
382
	/* sign H */
383
	/* XXX hashlen depends on KEX */
384
	PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
385
386
	/* destroy_sensitive_data(); */
387
388
	/* send server hostkey, DH pubkey 'f' and singed H */
389
	debug("SSH2_MSG_KEX_DH_GEX_REPLY sent");
390
	packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
391
	packet_put_string(server_host_key_blob, sbloblen);
392
	packet_put_bignum2(dh->pub_key);	/* f */
393
	packet_put_string(signature, slen);
394
	packet_send();
395
396
	xfree(signature);
397
	xfree(server_host_key_blob);
398
	/* have keys, free DH */
399
	DH_free(dh);
400
401
	kex_derive_keys(kex, hash, shared_secret);
402
	BN_clear_free(shared_secret);
403
404
	kex_finish(kex);
405
}
406
407
void
408
kexgex(Kex *kex)
409
{
410
	if (kex->server)
411
		kexgex_server(kex);
412
	else
413
		kexgex_client(kex);
414
}
92
}
(-)kexgexc.c (+189 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2000 Niels Provos.  All rights reserved.
3
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "includes.h"
27
RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
28
29
#include "xmalloc.h"
30
#include "key.h"
31
#include "kex.h"
32
#include "log.h"
33
#include "packet.h"
34
#include "dh.h"
35
#include "ssh2.h"
36
#include "compat.h"
37
38
void
39
kexgex_client(Kex *kex)
40
{
41
	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
42
	BIGNUM *p = NULL, *g = NULL;
43
	Key *server_host_key;
44
	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
45
	u_int klen, kout, slen, sbloblen;
46
	int min, max, nbits;
47
	DH *dh;
48
49
	nbits = dh_estimate(kex->we_need * 8);
50
51
	if (datafellows & SSH_OLD_DHGEX) {
52
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD sent");
53
54
		/* Old GEX request */
55
		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
56
		packet_put_int(nbits);
57
		min = DH_GRP_MIN;
58
		max = DH_GRP_MAX;
59
	} else {
60
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent");
61
62
		/* New GEX request */
63
		min = DH_GRP_MIN;
64
		max = DH_GRP_MAX;
65
		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
66
		packet_put_int(min);
67
		packet_put_int(nbits);
68
		packet_put_int(max);
69
	}
70
#ifdef DEBUG_KEXDH
71
	fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
72
	    min, nbits, max);
73
#endif
74
	packet_send();
75
76
	debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
77
	packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP);
78
79
	if ((p = BN_new()) == NULL)
80
		fatal("BN_new");
81
	packet_get_bignum2(p);
82
	if ((g = BN_new()) == NULL)
83
		fatal("BN_new");
84
	packet_get_bignum2(g);
85
	packet_check_eom();
86
87
	if (BN_num_bits(p) < min || BN_num_bits(p) > max)
88
		fatal("DH_GEX group out of range: %d !< %d !< %d",
89
		    min, BN_num_bits(p), max);
90
91
	dh = dh_new_group(g, p);
92
	dh_gen_key(dh, kex->we_need * 8);
93
94
#ifdef DEBUG_KEXDH
95
	DHparams_print_fp(stderr, dh);
96
	fprintf(stderr, "pub= ");
97
	BN_print_fp(stderr, dh->pub_key);
98
	fprintf(stderr, "\n");
99
#endif
100
101
	debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
102
	/* generate and send 'e', client DH public key */
103
	packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
104
	packet_put_bignum2(dh->pub_key);
105
	packet_send();
106
107
	debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
108
	packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY);
109
110
	/* key, cert */
111
	server_host_key_blob = packet_get_string(&sbloblen);
112
	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
113
	if (server_host_key == NULL)
114
		fatal("cannot decode server_host_key_blob");
115
	if (server_host_key->type != kex->hostkey_type)
116
		fatal("type mismatch for decoded server_host_key_blob");
117
	if (kex->verify_host_key == NULL)
118
		fatal("cannot verify server_host_key");
119
	if (kex->verify_host_key(server_host_key) == -1)
120
		fatal("server_host_key verification failed");
121
122
	/* DH paramter f, server public DH key */
123
	if ((dh_server_pub = BN_new()) == NULL)
124
		fatal("dh_server_pub == NULL");
125
	packet_get_bignum2(dh_server_pub);
126
127
#ifdef DEBUG_KEXDH
128
	fprintf(stderr, "dh_server_pub= ");
129
	BN_print_fp(stderr, dh_server_pub);
130
	fprintf(stderr, "\n");
131
	debug("bits %d", BN_num_bits(dh_server_pub));
132
#endif
133
134
	/* signed H */
135
	signature = packet_get_string(&slen);
136
	packet_check_eom();
137
138
	if (!dh_pub_is_valid(dh, dh_server_pub))
139
		packet_disconnect("bad server public DH value");
140
141
	klen = DH_size(dh);
142
	kbuf = xmalloc(klen);
143
	kout = DH_compute_key(kbuf, dh_server_pub, dh);
144
#ifdef DEBUG_KEXDH
145
	dump_digest("shared secret", kbuf, kout);
146
#endif
147
	if ((shared_secret = BN_new()) == NULL)
148
		fatal("kexgex_client: BN_new failed");
149
	BN_bin2bn(kbuf, kout, shared_secret);
150
	memset(kbuf, 0, klen);
151
	xfree(kbuf);
152
153
	if (datafellows & SSH_OLD_DHGEX)
154
		min = max = -1;
155
156
	/* calc and verify H */
157
	hash = kexgex_hash(
158
	    kex->client_version_string,
159
	    kex->server_version_string,
160
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
161
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
162
	    server_host_key_blob, sbloblen,
163
	    min, nbits, max,
164
	    dh->p, dh->g,
165
	    dh->pub_key,
166
	    dh_server_pub,
167
	    shared_secret
168
	);
169
	/* have keys, free DH */
170
	DH_free(dh);
171
	xfree(server_host_key_blob);
172
	BN_clear_free(dh_server_pub);
173
174
	if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
175
		fatal("key_verify failed for server_host_key");
176
	key_free(server_host_key);
177
	xfree(signature);
178
179
	/* save session id */
180
	if (kex->session_id == NULL) {
181
		kex->session_id_len = 20;
182
		kex->session_id = xmalloc(kex->session_id_len);
183
		memcpy(kex->session_id, hash, kex->session_id_len);
184
	}
185
	kex_derive_keys(kex, hash, shared_secret);
186
	BN_clear_free(shared_secret);
187
188
	kex_finish(kex);
189
}
(-)kexgexs.c (+186 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2000 Niels Provos.  All rights reserved.
3
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "includes.h"
27
RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
28
29
#include "xmalloc.h"
30
#include "key.h"
31
#include "kex.h"
32
#include "log.h"
33
#include "packet.h"
34
#include "dh.h"
35
#include "ssh2.h"
36
#include "compat.h"
37
#include "monitor_wrap.h"
38
39
void
40
kexgex_server(Kex *kex)
41
{
42
	BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
43
	Key *server_host_key;
44
	DH *dh;
45
	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
46
	u_int sbloblen, klen, kout, slen;
47
	int min = -1, max = -1, nbits = -1, type;
48
49
	if (kex->load_host_key == NULL)
50
		fatal("Cannot load hostkey");
51
	server_host_key = kex->load_host_key(kex->hostkey_type);
52
	if (server_host_key == NULL)
53
		fatal("Unsupported hostkey type %d", kex->hostkey_type);
54
55
	type = packet_read();
56
	switch (type) {
57
	case SSH2_MSG_KEX_DH_GEX_REQUEST:
58
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
59
		min = packet_get_int();
60
		nbits = packet_get_int();
61
		max = packet_get_int();
62
		min = MAX(DH_GRP_MIN, min);
63
		max = MIN(DH_GRP_MAX, max);
64
		break;
65
	case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD:
66
		debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received");
67
		nbits = packet_get_int();
68
		min = DH_GRP_MIN;
69
		max = DH_GRP_MAX;
70
		/* unused for old GEX */
71
		break;
72
	default:
73
		fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type);
74
	}
75
	packet_check_eom();
76
77
	if (max < min || nbits < min || max < nbits)
78
		fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
79
		    min, nbits, max);
80
81
	/* Contact privileged parent */
82
	dh = PRIVSEP(choose_dh(min, nbits, max));
83
	if (dh == NULL)
84
		packet_disconnect("Protocol error: no matching DH grp found");
85
86
	debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
87
	packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
88
	packet_put_bignum2(dh->p);
89
	packet_put_bignum2(dh->g);
90
	packet_send();
91
92
	/* flush */
93
	packet_write_wait();
94
95
	/* Compute our exchange value in parallel with the client */
96
	dh_gen_key(dh, kex->we_need * 8);
97
98
	debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
99
	packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT);
100
101
	/* key, cert */
102
	if ((dh_client_pub = BN_new()) == NULL)
103
		fatal("dh_client_pub == NULL");
104
	packet_get_bignum2(dh_client_pub);
105
	packet_check_eom();
106
107
#ifdef DEBUG_KEXDH
108
	fprintf(stderr, "dh_client_pub= ");
109
	BN_print_fp(stderr, dh_client_pub);
110
	fprintf(stderr, "\n");
111
	debug("bits %d", BN_num_bits(dh_client_pub));
112
#endif
113
114
#ifdef DEBUG_KEXDH
115
	DHparams_print_fp(stderr, dh);
116
	fprintf(stderr, "pub= ");
117
	BN_print_fp(stderr, dh->pub_key);
118
	fprintf(stderr, "\n");
119
#endif
120
	if (!dh_pub_is_valid(dh, dh_client_pub))
121
		packet_disconnect("bad client public DH value");
122
123
	klen = DH_size(dh);
124
	kbuf = xmalloc(klen);
125
	kout = DH_compute_key(kbuf, dh_client_pub, dh);
126
#ifdef DEBUG_KEXDH
127
	dump_digest("shared secret", kbuf, kout);
128
#endif
129
	if ((shared_secret = BN_new()) == NULL)
130
		fatal("kexgex_server: BN_new failed");
131
	BN_bin2bn(kbuf, kout, shared_secret);
132
	memset(kbuf, 0, klen);
133
	xfree(kbuf);
134
135
	key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
136
137
	if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
138
		min = max = -1;
139
140
	/* calc H */			/* XXX depends on 'kex' */
141
	hash = kexgex_hash(
142
	    kex->client_version_string,
143
	    kex->server_version_string,
144
	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
145
	    buffer_ptr(&kex->my), buffer_len(&kex->my),
146
	    server_host_key_blob, sbloblen,
147
	    min, nbits, max,
148
	    dh->p, dh->g,
149
	    dh_client_pub,
150
	    dh->pub_key,
151
	    shared_secret
152
	);
153
	BN_clear_free(dh_client_pub);
154
155
	/* save session id := H */
156
	/* XXX hashlen depends on KEX */
157
	if (kex->session_id == NULL) {
158
		kex->session_id_len = 20;
159
		kex->session_id = xmalloc(kex->session_id_len);
160
		memcpy(kex->session_id, hash, kex->session_id_len);
161
	}
162
163
	/* sign H */
164
	/* XXX hashlen depends on KEX */
165
	PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
166
167
	/* destroy_sensitive_data(); */
168
169
	/* send server hostkey, DH pubkey 'f' and singed H */
170
	debug("SSH2_MSG_KEX_DH_GEX_REPLY sent");
171
	packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
172
	packet_put_string(server_host_key_blob, sbloblen);
173
	packet_put_bignum2(dh->pub_key);	/* f */
174
	packet_put_string(signature, slen);
175
	packet_send();
176
177
	xfree(signature);
178
	xfree(server_host_key_blob);
179
	/* have keys, free DH */
180
	DH_free(dh);
181
182
	kex_derive_keys(kex, hash, shared_secret);
183
	BN_clear_free(shared_secret);
184
185
	kex_finish(kex);
186
}
(-)monitor.c (+2 lines)
Lines 791-796 Link Here
791
791
792
	buffer_clear(m);
792
	buffer_clear(m);
793
	buffer_put_int(m, allowed);
793
	buffer_put_int(m, allowed);
794
	buffer_put_int(m, forced_command != NULL);
794
795
795
	mm_append_debug(m);
796
	mm_append_debug(m);
796
797
Lines 1153-1158 Link Here
1153
	}
1154
	}
1154
	buffer_clear(m);
1155
	buffer_clear(m);
1155
	buffer_put_int(m, allowed);
1156
	buffer_put_int(m, allowed);
1157
	buffer_put_int(m, forced_command != NULL);
1156
1158
1157
	/* clear temporarily storage (used by generate challenge) */
1159
	/* clear temporarily storage (used by generate challenge) */
1158
	monitor_reset_key_state();
1160
	monitor_reset_key_state();
(-)monitor_wrap.c (-2 / +19 lines)
Lines 34-39 Link Here
34
#include "dh.h"
34
#include "dh.h"
35
#include "kex.h"
35
#include "kex.h"
36
#include "auth.h"
36
#include "auth.h"
37
#include "auth-options.h"
37
#include "buffer.h"
38
#include "buffer.h"
38
#include "bufaux.h"
39
#include "bufaux.h"
39
#include "packet.h"
40
#include "packet.h"
Lines 310-316 Link Here
310
	Buffer m;
311
	Buffer m;
311
	u_char *blob;
312
	u_char *blob;
312
	u_int len;
313
	u_int len;
313
	int allowed = 0;
314
	int allowed = 0, have_forced = 0;
314
315
315
	debug3("%s entering", __func__);
316
	debug3("%s entering", __func__);
316
317
Lines 332-337 Link Here
332
333
333
	allowed = buffer_get_int(&m);
334
	allowed = buffer_get_int(&m);
334
335
336
	/* fake forced command */
337
	if (forced_command) {
338
		xfree(forced_command);
339
		forced_command = NULL;
340
	}
341
	have_forced = buffer_get_int(&m);
342
	forced_command = have_forced ? xstrdup("true") : NULL;
343
335
	/* Send potential debug messages */
344
	/* Send potential debug messages */
336
	mm_send_debug(&m);
345
	mm_send_debug(&m);
337
346
Lines 834-840 Link Here
834
	Key *key;
843
	Key *key;
835
	u_char *blob;
844
	u_char *blob;
836
	u_int blen;
845
	u_int blen;
837
	int allowed = 0;
846
	int allowed = 0, have_forced = 0;
838
847
839
	debug3("%s entering", __func__);
848
	debug3("%s entering", __func__);
840
849
Lines 845-850 Link Here
845
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
854
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
846
855
847
	allowed = buffer_get_int(&m);
856
	allowed = buffer_get_int(&m);
857
858
	/* fake forced command */
859
	if (forced_command) {
860
		xfree(forced_command);
861
		forced_command = NULL;
862
	}
863
	have_forced = buffer_get_int(&m);
864
	forced_command = have_forced ? xstrdup("true") : NULL;
848
865
849
	if (allowed && rkey != NULL) {
866
	if (allowed && rkey != NULL) {
850
		blob = buffer_get_string(&m, &blen);
867
		blob = buffer_get_string(&m, &blen);
(-)ssh-keyscan.c (+2 lines)
Lines 335-340 Link Here
335
	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA?
335
	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA?
336
	    "ssh-dss": "ssh-rsa";
336
	    "ssh-dss": "ssh-rsa";
337
	c->c_kex = kex_setup(myproposal);
337
	c->c_kex = kex_setup(myproposal);
338
	c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
339
	c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
338
	c->c_kex->verify_host_key = hostjump;
340
	c->c_kex->verify_host_key = hostjump;
339
341
340
	if (!(j = setjmp(kexjmp))) {
342
	if (!(j = setjmp(kexjmp))) {
(-)sshconnect2.c (+2 lines)
Lines 110-115 Link Here
110
110
111
	/* start key exchange */
111
	/* start key exchange */
112
	kex = kex_setup(myproposal);
112
	kex = kex_setup(myproposal);
113
	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
114
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
113
	kex->client_version_string=client_version_string;
115
	kex->client_version_string=client_version_string;
114
	kex->server_version_string=server_version_string;
116
	kex->server_version_string=server_version_string;
115
	kex->verify_host_key=&verify_host_key_callback;
117
	kex->verify_host_key=&verify_host_key_callback;
(-)sshd.c (-2 / +4 lines)
Lines 189-196 Link Here
189
int startup_pipe;		/* in child */
189
int startup_pipe;		/* in child */
190
190
191
/* variables used for privilege separation */
191
/* variables used for privilege separation */
192
extern struct monitor *pmonitor;
192
int use_privsep;
193
extern int use_privsep;
193
struct monitor *pmonitor;
194
194
195
/* Prototypes for various functions defined later in this file. */
195
/* Prototypes for various functions defined later in this file. */
196
void destroy_sensitive_data(void);
196
void destroy_sensitive_data(void);
Lines 1746-1751 Link Here
1746
1746
1747
	/* start key exchange */
1747
	/* start key exchange */
1748
	kex = kex_setup(myproposal);
1748
	kex = kex_setup(myproposal);
1749
	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
1750
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1749
	kex->server = 1;
1751
	kex->server = 1;
1750
	kex->client_version_string=client_version_string;
1752
	kex->client_version_string=client_version_string;
1751
	kex->server_version_string=server_version_string;
1753
	kex->server_version_string=server_version_string;
(-)lib/Makefile (+1 lines)
Lines 9-14 Link Here
9
	rsa.c tildexpand.c ttymodes.c xmalloc.c atomicio.c \
9
	rsa.c tildexpand.c ttymodes.c xmalloc.c atomicio.c \
10
	key.c dispatch.c kex.c mac.c uuencode.c misc.c \
10
	key.c dispatch.c kex.c mac.c uuencode.c misc.c \
11
	rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c \
11
	rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c \
12
	kexdhs.c kexdhc.c kexgexs.c kexgexc.c \
12
	scard.c monitor_wrap.c monitor_fdpass.c msg.c progressmeter.c
13
	scard.c monitor_wrap.c monitor_fdpass.c msg.c progressmeter.c
13
14
14
DEBUGLIBS= no
15
DEBUGLIBS= no

Return to bug 387