GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ssh/lib/../kex.c Lines: 306 506 60.5 %
Date: 2017-11-07 Branches: 147 344 42.7 %

Line Branch Exec Source
1
/* $OpenBSD: kex.c,v 1.134 2017/06/13 12:13:59 djm Exp $ */
2
/*
3
 * Copyright (c) 2000, 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
27
#include <signal.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
32
#ifdef WITH_OPENSSL
33
#include <openssl/crypto.h>
34
#endif
35
36
#include "ssh2.h"
37
#include "packet.h"
38
#include "compat.h"
39
#include "cipher.h"
40
#include "sshkey.h"
41
#include "kex.h"
42
#include "log.h"
43
#include "mac.h"
44
#include "match.h"
45
#include "misc.h"
46
#include "dispatch.h"
47
#include "monitor.h"
48
49
#include "ssherr.h"
50
#include "sshbuf.h"
51
#include "digest.h"
52
53
/* prototype */
54
static int kex_choose_conf(struct ssh *);
55
static int kex_input_newkeys(int, u_int32_t, struct ssh *);
56
57
static const char *proposal_names[PROPOSAL_MAX] = {
58
	"KEX algorithms",
59
	"host key algorithms",
60
	"ciphers ctos",
61
	"ciphers stoc",
62
	"MACs ctos",
63
	"MACs stoc",
64
	"compression ctos",
65
	"compression stoc",
66
	"languages ctos",
67
	"languages stoc",
68
};
69
70
struct kexalg {
71
	char *name;
72
	u_int type;
73
	int ec_nid;
74
	int hash_alg;
75
};
76
static const struct kexalg kexalgs[] = {
77
#ifdef WITH_OPENSSL
78
	{ KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
79
	{ KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
80
	{ KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
81
	{ KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
82
	{ KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 },
83
	{ KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
84
	{ KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
85
	{ KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2,
86
	    NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
87
	{ KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1,
88
	    SSH_DIGEST_SHA384 },
89
	{ KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
90
	    SSH_DIGEST_SHA512 },
91
#endif
92
	{ KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
93
	{ KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
94
	{ NULL, -1, -1, -1},
95
};
96
97
char *
98
kex_alg_list(char sep)
99
{
100
	char *ret = NULL, *tmp;
101
	size_t nlen, rlen = 0;
102
	const struct kexalg *k;
103
104
	for (k = kexalgs; k->name != NULL; k++) {
105
		if (ret != NULL)
106
			ret[rlen++] = sep;
107
		nlen = strlen(k->name);
108
		if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
109
			free(ret);
110
			return NULL;
111
		}
112
		ret = tmp;
113
		memcpy(ret + rlen, k->name, nlen + 1);
114
		rlen += nlen;
115
	}
116
	return ret;
117
}
118
119
static const struct kexalg *
120
kex_alg_by_name(const char *name)
121
{
122
	const struct kexalg *k;
123
124
23
	for (k = kexalgs; k->name != NULL; k++) {
125
11
		if (strcmp(k->name, name) == 0)
126
1
			return k;
127
	}
128
	return NULL;
129
1
}
130
131
/* Validate KEX method name list */
132
int
133
kex_names_valid(const char *names)
134
{
135
	char *s, *cp, *p;
136
137
	if (names == NULL || strcmp(names, "") == 0)
138
		return 0;
139
	if ((s = cp = strdup(names)) == NULL)
140
		return 0;
141
	for ((p = strsep(&cp, ",")); p && *p != '\0';
142
	    (p = strsep(&cp, ","))) {
143
		if (kex_alg_by_name(p) == NULL) {
144
			error("Unsupported KEX algorithm \"%.100s\"", p);
145
			free(s);
146
			return 0;
147
		}
148
	}
149
	debug3("kex names ok: [%s]", names);
150
	free(s);
151
	return 1;
152
}
153
154
/*
155
 * Concatenate algorithm names, avoiding duplicates in the process.
156
 * Caller must free returned string.
157
 */
158
char *
159
kex_names_cat(const char *a, const char *b)
160
{
161
2
	char *ret = NULL, *tmp = NULL, *cp, *p, *m;
162
	size_t len;
163
164

2
	if (a == NULL || *a == '\0')
165
		return NULL;
166

2
	if (b == NULL || *b == '\0')
167
		return strdup(a);
168
1
	if (strlen(b) > 1024*1024)
169
		return NULL;
170
1
	len = strlen(a) + strlen(b) + 2;
171

2
	if ((tmp = cp = strdup(b)) == NULL ||
172
1
	    (ret = calloc(1, len)) == NULL) {
173
		free(tmp);
174
		return NULL;
175
	}
176
1
	strlcpy(ret, a, len);
177

5
	for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
178
1
		if ((m = match_list(ret, p, NULL)) != NULL) {
179
			free(m);
180
			continue; /* Algorithm already present */
181
		}
182

2
		if (strlcat(ret, ",", len) >= len ||
183
1
		    strlcat(ret, p, len) >= len) {
184
			free(tmp);
185
			free(ret);
186
			return NULL; /* Shouldn't happen */
187
		}
188
	}
189
1
	free(tmp);
190
1
	return ret;
191
1
}
192
193
/*
194
 * Assemble a list of algorithms from a default list and a string from a
195
 * configuration file. The user-provided string may begin with '+' to
196
 * indicate that it should be appended to the default or '-' that the
197
 * specified names should be removed.
198
 */
199
int
200
kex_assemble_names(const char *def, char **list)
201
{
202
	char *ret;
203
204

393
	if (list == NULL || *list == NULL || **list == '\0') {
205
131
		*list = strdup(def);
206
131
		return 0;
207
	}
208
	if (**list == '+') {
209
		if ((ret = kex_names_cat(def, *list + 1)) == NULL)
210
			return SSH_ERR_ALLOC_FAIL;
211
		free(*list);
212
		*list = ret;
213
	} else if (**list == '-') {
214
		if ((ret = match_filter_list(def, *list + 1)) == NULL)
215
			return SSH_ERR_ALLOC_FAIL;
216
		free(*list);
217
		*list = ret;
218
	}
219
220
	return 0;
221
131
}
222
223
/* put algorithm proposal into buffer */
224
int
225
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
226
{
227
	u_int i;
228
	int r;
229
230
4
	sshbuf_reset(b);
231
232
	/*
233
	 * add a dummy cookie, the cookie will be overwritten by
234
	 * kex_send_kexinit(), each time a kexinit is set
235
	 */
236
68
	for (i = 0; i < KEX_COOKIE_LEN; i++) {
237
32
		if ((r = sshbuf_put_u8(b, 0)) != 0)
238
			return r;
239
	}
240
44
	for (i = 0; i < PROPOSAL_MAX; i++) {
241
20
		if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
242
			return r;
243
	}
244

4
	if ((r = sshbuf_put_u8(b, 0)) != 0 ||	/* first_kex_packet_follows */
245
2
	    (r = sshbuf_put_u32(b, 0)) != 0)	/* uint32 reserved */
246
		return r;
247
2
	return 0;
248
2
}
249
250
/* parse buffer and return algorithm proposal */
251
int
252
kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
253
{
254
	struct sshbuf *b = NULL;
255
4
	u_char v;
256
2
	u_int i;
257
	char **proposal = NULL;
258
	int r;
259
260
2
	*propp = NULL;
261
2
	if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
262
		return SSH_ERR_ALLOC_FAIL;
263
2
	if ((b = sshbuf_fromb(raw)) == NULL) {
264
		r = SSH_ERR_ALLOC_FAIL;
265
		goto out;
266
	}
267
2
	if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */
268
		goto out;
269
	/* extract kex init proposal strings */
270
44
	for (i = 0; i < PROPOSAL_MAX; i++) {
271
20
		if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0)
272
			goto out;
273
20
		debug2("%s: %s", proposal_names[i], proposal[i]);
274
	}
275
	/* first kex follows / reserved */
276

4
	if ((r = sshbuf_get_u8(b, &v)) != 0 ||	/* first_kex_follows */
277
2
	    (r = sshbuf_get_u32(b, &i)) != 0)	/* reserved */
278
		goto out;
279
2
	if (first_kex_follows != NULL)
280
1
		*first_kex_follows = v;
281
2
	debug2("first_kex_follows %d ", v);
282
2
	debug2("reserved %u ", i);
283
	r = 0;
284
2
	*propp = proposal;
285
 out:
286
2
	if (r != 0 && proposal != NULL)
287
		kex_prop_free(proposal);
288
2
	sshbuf_free(b);
289
2
	return r;
290
2
}
291
292
void
293
kex_prop_free(char **proposal)
294
{
295
	u_int i;
296
297
4
	if (proposal == NULL)
298
		return;
299
44
	for (i = 0; i < PROPOSAL_MAX; i++)
300
20
		free(proposal[i]);
301
2
	free(proposal);
302
4
}
303
304
/* ARGSUSED */
305
static int
306
kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
307
{
308
	int r;
309
310
	error("kex protocol error: type %d seq %u", type, seq);
311
	if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
312
	    (r = sshpkt_put_u32(ssh, seq)) != 0 ||
313
	    (r = sshpkt_send(ssh)) != 0)
314
		return r;
315
	return 0;
316
}
317
318
static void
319
kex_reset_dispatch(struct ssh *ssh)
320
{
321
4
	ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
322
	    SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
323
2
}
324
325
static int
326
kex_send_ext_info(struct ssh *ssh)
327
{
328
	int r;
329
	char *algs;
330
331
	if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
332
		return SSH_ERR_ALLOC_FAIL;
333
	if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
334
	    (r = sshpkt_put_u32(ssh, 1)) != 0 ||
335
	    (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
336
	    (r = sshpkt_put_cstring(ssh, algs)) != 0 ||
337
	    (r = sshpkt_send(ssh)) != 0)
338
		goto out;
339
	/* success */
340
	r = 0;
341
 out:
342
	free(algs);
343
	return r;
344
}
345
346
int
347
kex_send_newkeys(struct ssh *ssh)
348
{
349
	int r;
350
351
2
	kex_reset_dispatch(ssh);
352

2
	if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
353
1
	    (r = sshpkt_send(ssh)) != 0)
354
		return r;
355
1
	debug("SSH2_MSG_NEWKEYS sent");
356
1
	debug("expecting SSH2_MSG_NEWKEYS");
357
1
	ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
358
1
	if (ssh->kex->ext_info_c)
359
		if ((r = kex_send_ext_info(ssh)) != 0)
360
			return r;
361
1
	return 0;
362
1
}
363
364
int
365
kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
366
{
367
2
	struct kex *kex = ssh->kex;
368
1
	u_int32_t i, ninfo;
369
1
	char *name, *found;
370
1
	u_char *val;
371
1
	size_t vlen;
372
	int r;
373
374
1
	debug("SSH2_MSG_EXT_INFO received");
375
1
	ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
376
1
	if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
377
		return r;
378
4
	for (i = 0; i < ninfo; i++) {
379
1
		if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
380
			return r;
381
1
		if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
382
			free(name);
383
			return r;
384
		}
385
1
		if (strcmp(name, "server-sig-algs") == 0) {
386
			/* Ensure no \0 lurking in value */
387
1
			if (memchr(val, '\0', vlen) != NULL) {
388
				error("%s: nul byte in %s", __func__, name);
389
				return SSH_ERR_INVALID_FORMAT;
390
			}
391
1
			debug("%s: %s=<%s>", __func__, name, val);
392
1
			found = match_list("rsa-sha2-256", val, NULL);
393
1
			if (found) {
394
				kex->rsa_sha2 = 256;
395
				free(found);
396
			}
397
1
			found = match_list("rsa-sha2-512", val, NULL);
398
1
			if (found) {
399
				kex->rsa_sha2 = 512;
400
				free(found);
401
			}
402
		} else
403
			debug("%s: %s (unrecognised)", __func__, name);
404
1
		free(name);
405
1
		free(val);
406
	}
407
1
	return sshpkt_get_end(ssh);
408
1
}
409
410
static int
411
kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
412
{
413
2
	struct kex *kex = ssh->kex;
414
	int r;
415
416
1
	debug("SSH2_MSG_NEWKEYS received");
417
1
	ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
418
1
	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
419
1
	if ((r = sshpkt_get_end(ssh)) != 0)
420
		return r;
421
1
	if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
422
		return r;
423
1
	kex->done = 1;
424
1
	sshbuf_reset(kex->peer);
425
	/* sshbuf_reset(kex->my); */
426
1
	kex->flags &= ~KEX_INIT_SENT;
427
1
	free(kex->name);
428
1
	kex->name = NULL;
429
1
	return 0;
430
1
}
431
432
int
433
kex_send_kexinit(struct ssh *ssh)
434
{
435
	u_char *cookie;
436
2
	struct kex *kex = ssh->kex;
437
	int r;
438
439
1
	if (kex == NULL)
440
		return SSH_ERR_INTERNAL_ERROR;
441
1
	if (kex->flags & KEX_INIT_SENT)
442
		return 0;
443
1
	kex->done = 0;
444
445
	/* generate a random cookie */
446
1
	if (sshbuf_len(kex->my) < KEX_COOKIE_LEN)
447
		return SSH_ERR_INVALID_FORMAT;
448
1
	if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL)
449
		return SSH_ERR_INTERNAL_ERROR;
450
1
	arc4random_buf(cookie, KEX_COOKIE_LEN);
451
452

2
	if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
453
1
	    (r = sshpkt_putb(ssh, kex->my)) != 0 ||
454
1
	    (r = sshpkt_send(ssh)) != 0)
455
		return r;
456
1
	debug("SSH2_MSG_KEXINIT sent");
457
1
	kex->flags |= KEX_INIT_SENT;
458
1
	return 0;
459
1
}
460
461
/* ARGSUSED */
462
int
463
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
464
{
465
2
	struct kex *kex = ssh->kex;
466
	const u_char *ptr;
467
	u_int i;
468
1
	size_t dlen;
469
	int r;
470
471
1
	debug("SSH2_MSG_KEXINIT received");
472
1
	if (kex == NULL)
473
		return SSH_ERR_INVALID_ARGUMENT;
474
475
1
	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
476
1
	ptr = sshpkt_ptr(ssh, &dlen);
477
1
	if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
478
		return r;
479
480
	/* discard packet */
481
34
	for (i = 0; i < KEX_COOKIE_LEN; i++)
482
16
		if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
483
			return r;
484
22
	for (i = 0; i < PROPOSAL_MAX; i++)
485
10
		if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
486
			return r;
487
	/*
488
	 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
489
	 * KEX method has the server move first, but a server might be using
490
	 * a custom method or one that we otherwise don't support. We should
491
	 * be prepared to remember first_kex_follows here so we can eat a
492
	 * packet later.
493
	 * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
494
	 * for cases where the server *doesn't* go first. I guess we should
495
	 * ignore it when it is set for these cases, which is what we do now.
496
	 */
497

2
	if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||	/* first_kex_follows */
498
1
	    (r = sshpkt_get_u32(ssh, NULL)) != 0 ||	/* reserved */
499
1
	    (r = sshpkt_get_end(ssh)) != 0)
500
			return r;
501
502
1
	if (!(kex->flags & KEX_INIT_SENT))
503
		if ((r = kex_send_kexinit(ssh)) != 0)
504
			return r;
505
1
	if ((r = kex_choose_conf(ssh)) != 0)
506
		return r;
507
508

2
	if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
509
1
		return (kex->kex[kex->kex_type])(ssh);
510
511
	return SSH_ERR_INTERNAL_ERROR;
512
1
}
513
514
int
515
kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
516
{
517
	struct kex *kex;
518
	int r;
519
520
2
	*kexp = NULL;
521
1
	if ((kex = calloc(1, sizeof(*kex))) == NULL)
522
		return SSH_ERR_ALLOC_FAIL;
523

2
	if ((kex->peer = sshbuf_new()) == NULL ||
524
1
	    (kex->my = sshbuf_new()) == NULL) {
525
		r = SSH_ERR_ALLOC_FAIL;
526
		goto out;
527
	}
528
1
	if ((r = kex_prop2buf(kex->my, proposal)) != 0)
529
		goto out;
530
1
	kex->done = 0;
531
1
	kex_reset_dispatch(ssh);
532
1
	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
533
	r = 0;
534
1
	*kexp = kex;
535
 out:
536
1
	if (r != 0)
537
		kex_free(kex);
538
1
	return r;
539
1
}
540
541
void
542
kex_free_newkeys(struct newkeys *newkeys)
543
{
544
4
	if (newkeys == NULL)
545
		return;
546
2
	if (newkeys->enc.key) {
547
2
		explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
548
2
		free(newkeys->enc.key);
549
2
		newkeys->enc.key = NULL;
550
2
	}
551
2
	if (newkeys->enc.iv) {
552
2
		explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
553
2
		free(newkeys->enc.iv);
554
2
		newkeys->enc.iv = NULL;
555
2
	}
556
2
	free(newkeys->enc.name);
557
2
	explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
558
2
	free(newkeys->comp.name);
559
2
	explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
560
2
	mac_clear(&newkeys->mac);
561
2
	if (newkeys->mac.key) {
562
2
		explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
563
2
		free(newkeys->mac.key);
564
2
		newkeys->mac.key = NULL;
565
2
	}
566
2
	free(newkeys->mac.name);
567
2
	explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
568
2
	explicit_bzero(newkeys, sizeof(*newkeys));
569
2
	free(newkeys);
570
4
}
571
572
void
573
kex_free(struct kex *kex)
574
{
575
	u_int mode;
576
577
#ifdef WITH_OPENSSL
578
	if (kex->dh)
579
		DH_free(kex->dh);
580
	if (kex->ec_client_key)
581
		EC_KEY_free(kex->ec_client_key);
582
#endif
583
	for (mode = 0; mode < MODE_MAX; mode++) {
584
		kex_free_newkeys(kex->newkeys[mode]);
585
		kex->newkeys[mode] = NULL;
586
	}
587
	sshbuf_free(kex->peer);
588
	sshbuf_free(kex->my);
589
	free(kex->session_id);
590
	free(kex->client_version_string);
591
	free(kex->server_version_string);
592
	free(kex->failed_choice);
593
	free(kex->hostkey_alg);
594
	free(kex->name);
595
	free(kex);
596
}
597
598
int
599
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
600
{
601
	int r;
602
603
2
	if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
604
		return r;
605
1
	if ((r = kex_send_kexinit(ssh)) != 0) {		/* we start */
606
		kex_free(ssh->kex);
607
		ssh->kex = NULL;
608
		return r;
609
	}
610
1
	return 0;
611
1
}
612
613
/*
614
 * Request key re-exchange, returns 0 on success or a ssherr.h error
615
 * code otherwise. Must not be called if KEX is incomplete or in-progress.
616
 */
617
int
618
kex_start_rekex(struct ssh *ssh)
619
{
620
	if (ssh->kex == NULL) {
621
		error("%s: no kex", __func__);
622
		return SSH_ERR_INTERNAL_ERROR;
623
	}
624
	if (ssh->kex->done == 0) {
625
		error("%s: requested twice", __func__);
626
		return SSH_ERR_INTERNAL_ERROR;
627
	}
628
	ssh->kex->done = 0;
629
	return kex_send_kexinit(ssh);
630
}
631
632
static int
633
choose_enc(struct sshenc *enc, char *client, char *server)
634
{
635
4
	char *name = match_list(client, server, NULL);
636
637
2
	if (name == NULL)
638
		return SSH_ERR_NO_CIPHER_ALG_MATCH;
639
2
	if ((enc->cipher = cipher_by_name(name)) == NULL) {
640
		free(name);
641
		return SSH_ERR_INTERNAL_ERROR;
642
	}
643
2
	enc->name = name;
644
2
	enc->enabled = 0;
645
2
	enc->iv = NULL;
646
2
	enc->iv_len = cipher_ivlen(enc->cipher);
647
2
	enc->key = NULL;
648
2
	enc->key_len = cipher_keylen(enc->cipher);
649
2
	enc->block_size = cipher_blocksize(enc->cipher);
650
2
	return 0;
651
2
}
652
653
static int
654
choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
655
{
656
	char *name = match_list(client, server, NULL);
657
658
	if (name == NULL)
659
		return SSH_ERR_NO_MAC_ALG_MATCH;
660
	if (mac_setup(mac, name) < 0) {
661
		free(name);
662
		return SSH_ERR_INTERNAL_ERROR;
663
	}
664
	/* truncate the key */
665
	if (ssh->compat & SSH_BUG_HMAC)
666
		mac->key_len = 16;
667
	mac->name = name;
668
	mac->key = NULL;
669
	mac->enabled = 0;
670
	return 0;
671
}
672
673
static int
674
choose_comp(struct sshcomp *comp, char *client, char *server)
675
{
676
4
	char *name = match_list(client, server, NULL);
677
678
2
	if (name == NULL)
679
		return SSH_ERR_NO_COMPRESS_ALG_MATCH;
680
2
	if (strcmp(name, "zlib@openssh.com") == 0) {
681
		comp->type = COMP_DELAYED;
682
2
	} else if (strcmp(name, "zlib") == 0) {
683
		comp->type = COMP_ZLIB;
684
2
	} else if (strcmp(name, "none") == 0) {
685
		comp->type = COMP_NONE;
686
	} else {
687
		free(name);
688
		return SSH_ERR_INTERNAL_ERROR;
689
	}
690
2
	comp->name = name;
691
2
	return 0;
692
2
}
693
694
static int
695
choose_kex(struct kex *k, char *client, char *server)
696
{
697
	const struct kexalg *kexalg;
698
699
2
	k->name = match_list(client, server, NULL);
700
701
3
	debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
702
1
	if (k->name == NULL)
703
		return SSH_ERR_NO_KEX_ALG_MATCH;
704
1
	if ((kexalg = kex_alg_by_name(k->name)) == NULL)
705
		return SSH_ERR_INTERNAL_ERROR;
706
1
	k->kex_type = kexalg->type;
707
1
	k->hash_alg = kexalg->hash_alg;
708
1
	k->ec_nid = kexalg->ec_nid;
709
1
	return 0;
710
1
}
711
712
static int
713
choose_hostkeyalg(struct kex *k, char *client, char *server)
714
{
715
2
	k->hostkey_alg = match_list(client, server, NULL);
716
717
1
	debug("kex: host key algorithm: %s",
718
3
	    k->hostkey_alg ? k->hostkey_alg : "(no match)");
719
1
	if (k->hostkey_alg == NULL)
720
		return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
721
1
	k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
722
1
	if (k->hostkey_type == KEY_UNSPEC)
723
		return SSH_ERR_INTERNAL_ERROR;
724
1
	k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
725
1
	return 0;
726
1
}
727
728
static int
729
proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
730
{
731
	static int check[] = {
732
		PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
733
	};
734
	int *idx;
735
	char *p;
736
737
	for (idx = &check[0]; *idx != -1; idx++) {
738
		if ((p = strchr(my[*idx], ',')) != NULL)
739
			*p = '\0';
740
		if ((p = strchr(peer[*idx], ',')) != NULL)
741
			*p = '\0';
742
		if (strcmp(my[*idx], peer[*idx]) != 0) {
743
			debug2("proposal mismatch: my %s peer %s",
744
			    my[*idx], peer[*idx]);
745
			return (0);
746
		}
747
	}
748
	debug2("proposals match");
749
	return (1);
750
}
751
752
static int
753
kex_choose_conf(struct ssh *ssh)
754
{
755
2
	struct kex *kex = ssh->kex;
756
	struct newkeys *newkeys;
757
1
	char **my = NULL, **peer = NULL;
758
	char **cprop, **sprop;
759
	int nenc, nmac, ncomp;
760
	u_int mode, ctos, need, dh_need, authlen;
761
1
	int r, first_kex_follows;
762
763
1
	debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
764
1
	if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
765
		goto out;
766
1
	debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
767
1
	if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
768
		goto out;
769
770
1
	if (kex->server) {
771
		cprop=peer;
772
		sprop=my;
773
	} else {
774
1
		cprop=my;
775
1
		sprop=peer;
776
	}
777
778
	/* Check whether client supports ext_info_c */
779
1
	if (kex->server) {
780
		char *ext;
781
782
		ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
783
		kex->ext_info_c = (ext != NULL);
784
		free(ext);
785
	}
786
787
	/* Algorithm Negotiation */
788
3
	if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
789
2
	    sprop[PROPOSAL_KEX_ALGS])) != 0) {
790
		kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
791
		peer[PROPOSAL_KEX_ALGS] = NULL;
792
		goto out;
793
	}
794
3
	if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
795
2
	    sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
796
		kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
797
		peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
798
		goto out;
799
	}
800
6
	for (mode = 0; mode < MODE_MAX; mode++) {
801
2
		if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
802
			r = SSH_ERR_ALLOC_FAIL;
803
			goto out;
804
		}
805
2
		kex->newkeys[mode] = newkeys;
806
4
		ctos = (!kex->server && mode == MODE_OUT) ||
807
1
		    (kex->server && mode == MODE_IN);
808
2
		nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
809
2
		nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
810
2
		ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
811
6
		if ((r = choose_enc(&newkeys->enc, cprop[nenc],
812
4
		    sprop[nenc])) != 0) {
813
			kex->failed_choice = peer[nenc];
814
			peer[nenc] = NULL;
815
			goto out;
816
		}
817
2
		authlen = cipher_authlen(newkeys->enc.cipher);
818
		/* ignore mac for authenticated encryption */
819

2
		if (authlen == 0 &&
820
		    (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
821
		    sprop[nmac])) != 0) {
822
			kex->failed_choice = peer[nmac];
823
			peer[nmac] = NULL;
824
			goto out;
825
		}
826
6
		if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
827
4
		    sprop[ncomp])) != 0) {
828
			kex->failed_choice = peer[ncomp];
829
			peer[ncomp] = NULL;
830
			goto out;
831
		}
832
2
		debug("kex: %s cipher: %s MAC: %s compression: %s",
833
2
		    ctos ? "client->server" : "server->client",
834
2
		    newkeys->enc.name,
835
4
		    authlen == 0 ? newkeys->mac.name : "<implicit>",
836
2
		    newkeys->comp.name);
837
	}
838
	need = dh_need = 0;
839
6
	for (mode = 0; mode < MODE_MAX; mode++) {
840
2
		newkeys = kex->newkeys[mode];
841
6
		need = MAXIMUM(need, newkeys->enc.key_len);
842
6
		need = MAXIMUM(need, newkeys->enc.block_size);
843
6
		need = MAXIMUM(need, newkeys->enc.iv_len);
844
6
		need = MAXIMUM(need, newkeys->mac.key_len);
845
6
		dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
846
6
		dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
847
6
		dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
848
6
		dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
849
	}
850
	/* XXX need runden? */
851
1
	kex->we_need = need;
852
1
	kex->dh_need = dh_need;
853
854
	/* ignore the next message if the proposals do not match */
855

1
	if (first_kex_follows && !proposals_match(my, peer) &&
856
	    !(ssh->compat & SSH_BUG_FIRSTKEX))
857
		ssh->dispatch_skip_packets = 1;
858
1
	r = 0;
859
 out:
860
1
	kex_prop_free(my);
861
1
	kex_prop_free(peer);
862
1
	return r;
863
1
}
864
865
static int
866
derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
867
    const struct sshbuf *shared_secret, u_char **keyp)
868
{
869
12
	struct kex *kex = ssh->kex;
870
	struct ssh_digest_ctx *hashctx = NULL;
871
6
	char c = id;
872
	u_int have;
873
	size_t mdsz;
874
	u_char *digest;
875
	int r;
876
877
6
	if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
878
		return SSH_ERR_INVALID_ARGUMENT;
879
6
	if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
880
		r = SSH_ERR_ALLOC_FAIL;
881
		goto out;
882
	}
883
884
	/* K1 = HASH(K || H || "A" || session_id) */
885

12
	if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
886
6
	    ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
887
6
	    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
888
6
	    ssh_digest_update(hashctx, &c, 1) != 0 ||
889
12
	    ssh_digest_update(hashctx, kex->session_id,
890
12
	    kex->session_id_len) != 0 ||
891
6
	    ssh_digest_final(hashctx, digest, mdsz) != 0) {
892
		r = SSH_ERR_LIBCRYPTO_ERROR;
893
		goto out;
894
	}
895
6
	ssh_digest_free(hashctx);
896
	hashctx = NULL;
897
898
	/*
899
	 * expand key:
900
	 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
901
	 * Key = K1 || K2 || ... || Kn
902
	 */
903
24
	for (have = mdsz; need > have; have += mdsz) {
904

12
		if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
905
6
		    ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
906
6
		    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
907
6
		    ssh_digest_update(hashctx, digest, have) != 0 ||
908
6
		    ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
909
			r = SSH_ERR_LIBCRYPTO_ERROR;
910
			goto out;
911
		}
912
6
		ssh_digest_free(hashctx);
913
		hashctx = NULL;
914
	}
915
#ifdef DEBUG_KEX
916
	fprintf(stderr, "key '%c'== ", c);
917
	dump_digest("key", digest, need);
918
#endif
919
6
	*keyp = digest;
920
	digest = NULL;
921
6
	r = 0;
922
 out:
923
6
	free(digest);
924
6
	ssh_digest_free(hashctx);
925
6
	return r;
926
6
}
927
928
#define NKEYS	6
929
int
930
kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
931
    const struct sshbuf *shared_secret)
932
{
933
2
	struct kex *kex = ssh->kex;
934
1
	u_char *keys[NKEYS];
935
	u_int i, j, mode, ctos;
936
	int r;
937
938
14
	for (i = 0; i < NKEYS; i++) {
939
18
		if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
940
12
		    shared_secret, &keys[i])) != 0) {
941
			for (j = 0; j < i; j++)
942
				free(keys[j]);
943
			return r;
944
		}
945
	}
946
6
	for (mode = 0; mode < MODE_MAX; mode++) {
947
4
		ctos = (!kex->server && mode == MODE_OUT) ||
948
1
		    (kex->server && mode == MODE_IN);
949
2
		kex->newkeys[mode]->enc.iv  = keys[ctos ? 0 : 1];
950
2
		kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
951
2
		kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
952
	}
953
1
	return 0;
954
1
}
955
956
#ifdef WITH_OPENSSL
957
int
958
kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
959
    const BIGNUM *secret)
960
{
961
	struct sshbuf *shared_secret;
962
	int r;
963
964
	if ((shared_secret = sshbuf_new()) == NULL)
965
		return SSH_ERR_ALLOC_FAIL;
966
	if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0)
967
		r = kex_derive_keys(ssh, hash, hashlen, shared_secret);
968
	sshbuf_free(shared_secret);
969
	return r;
970
}
971
#endif
972
973
974
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
975
void
976
dump_digest(char *msg, u_char *digest, int len)
977
{
978
	fprintf(stderr, "%s\n", msg);
979
	sshbuf_dump_data(digest, len, stderr);
980
}
981
#endif