xref: /openbsd/usr.bin/ssh/kex.c (revision f5960ed9)
1 /* $OpenBSD: kex.c,v 1.187 2024/08/23 04:51:00 deraadt 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 <sys/types.h>
28 #include <errno.h>
29 #include <signal.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <poll.h>
35 
36 #ifdef WITH_OPENSSL
37 #include <openssl/crypto.h>
38 #endif
39 
40 #include "ssh.h"
41 #include "ssh2.h"
42 #include "atomicio.h"
43 #include "version.h"
44 #include "packet.h"
45 #include "compat.h"
46 #include "cipher.h"
47 #include "sshkey.h"
48 #include "kex.h"
49 #include "log.h"
50 #include "mac.h"
51 #include "match.h"
52 #include "misc.h"
53 #include "dispatch.h"
54 #include "monitor.h"
55 #include "myproposal.h"
56 
57 #include "ssherr.h"
58 #include "sshbuf.h"
59 #include "digest.h"
60 #include "xmalloc.h"
61 
62 /* prototype */
63 static int kex_choose_conf(struct ssh *, uint32_t seq);
64 static int kex_input_newkeys(int, u_int32_t, struct ssh *);
65 
66 static const char * const proposal_names[PROPOSAL_MAX] = {
67 	"KEX algorithms",
68 	"host key algorithms",
69 	"ciphers ctos",
70 	"ciphers stoc",
71 	"MACs ctos",
72 	"MACs stoc",
73 	"compression ctos",
74 	"compression stoc",
75 	"languages ctos",
76 	"languages stoc",
77 };
78 
79 /*
80  * Fill out a proposal array with dynamically allocated values, which may
81  * be modified as required for compatibility reasons.
82  * Any of the options may be NULL, in which case the default is used.
83  * Array contents must be freed by calling kex_proposal_free_entries.
84  */
85 void
kex_proposal_populate_entries(struct ssh * ssh,char * prop[PROPOSAL_MAX],const char * kexalgos,const char * ciphers,const char * macs,const char * comp,const char * hkalgs)86 kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX],
87     const char *kexalgos, const char *ciphers, const char *macs,
88     const char *comp, const char *hkalgs)
89 {
90 	const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER };
91 	const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
92 	const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
93 	u_int i;
94 	char *cp;
95 
96 	if (prop == NULL)
97 		fatal_f("proposal missing");
98 
99 	/* Append EXT_INFO signalling to KexAlgorithms */
100 	if (kexalgos == NULL)
101 		kexalgos = defprop[PROPOSAL_KEX_ALGS];
102 	if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
103 	    "ext-info-s,kex-strict-s-v00@openssh.com" :
104 	    "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
105 		fatal_f("kex_names_cat");
106 
107 	for (i = 0; i < PROPOSAL_MAX; i++) {
108 		switch(i) {
109 		case PROPOSAL_KEX_ALGS:
110 			prop[i] = compat_kex_proposal(ssh, cp);
111 			break;
112 		case PROPOSAL_ENC_ALGS_CTOS:
113 		case PROPOSAL_ENC_ALGS_STOC:
114 			prop[i] = xstrdup(ciphers ? ciphers : defprop[i]);
115 			break;
116 		case PROPOSAL_MAC_ALGS_CTOS:
117 		case PROPOSAL_MAC_ALGS_STOC:
118 			prop[i]  = xstrdup(macs ? macs : defprop[i]);
119 			break;
120 		case PROPOSAL_COMP_ALGS_CTOS:
121 		case PROPOSAL_COMP_ALGS_STOC:
122 			prop[i] = xstrdup(comp ? comp : defprop[i]);
123 			break;
124 		case PROPOSAL_SERVER_HOST_KEY_ALGS:
125 			prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]);
126 			break;
127 		default:
128 			prop[i] = xstrdup(defprop[i]);
129 		}
130 	}
131 	free(cp);
132 }
133 
134 void
kex_proposal_free_entries(char * prop[PROPOSAL_MAX])135 kex_proposal_free_entries(char *prop[PROPOSAL_MAX])
136 {
137 	u_int i;
138 
139 	for (i = 0; i < PROPOSAL_MAX; i++)
140 		free(prop[i]);
141 }
142 
143 /* put algorithm proposal into buffer */
144 int
kex_prop2buf(struct sshbuf * b,char * proposal[PROPOSAL_MAX])145 kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
146 {
147 	u_int i;
148 	int r;
149 
150 	sshbuf_reset(b);
151 
152 	/*
153 	 * add a dummy cookie, the cookie will be overwritten by
154 	 * kex_send_kexinit(), each time a kexinit is set
155 	 */
156 	for (i = 0; i < KEX_COOKIE_LEN; i++) {
157 		if ((r = sshbuf_put_u8(b, 0)) != 0)
158 			return r;
159 	}
160 	for (i = 0; i < PROPOSAL_MAX; i++) {
161 		if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
162 			return r;
163 	}
164 	if ((r = sshbuf_put_u8(b, 0)) != 0 ||	/* first_kex_packet_follows */
165 	    (r = sshbuf_put_u32(b, 0)) != 0)	/* uint32 reserved */
166 		return r;
167 	return 0;
168 }
169 
170 /* parse buffer and return algorithm proposal */
171 int
kex_buf2prop(struct sshbuf * raw,int * first_kex_follows,char *** propp)172 kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
173 {
174 	struct sshbuf *b = NULL;
175 	u_char v;
176 	u_int i;
177 	char **proposal = NULL;
178 	int r;
179 
180 	*propp = NULL;
181 	if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
182 		return SSH_ERR_ALLOC_FAIL;
183 	if ((b = sshbuf_fromb(raw)) == NULL) {
184 		r = SSH_ERR_ALLOC_FAIL;
185 		goto out;
186 	}
187 	if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */
188 		error_fr(r, "consume cookie");
189 		goto out;
190 	}
191 	/* extract kex init proposal strings */
192 	for (i = 0; i < PROPOSAL_MAX; i++) {
193 		if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
194 			error_fr(r, "parse proposal %u", i);
195 			goto out;
196 		}
197 		debug2("%s: %s", proposal_names[i], proposal[i]);
198 	}
199 	/* first kex follows / reserved */
200 	if ((r = sshbuf_get_u8(b, &v)) != 0 ||	/* first_kex_follows */
201 	    (r = sshbuf_get_u32(b, &i)) != 0) {	/* reserved */
202 		error_fr(r, "parse");
203 		goto out;
204 	}
205 	if (first_kex_follows != NULL)
206 		*first_kex_follows = v;
207 	debug2("first_kex_follows %d ", v);
208 	debug2("reserved %u ", i);
209 	r = 0;
210 	*propp = proposal;
211  out:
212 	if (r != 0 && proposal != NULL)
213 		kex_prop_free(proposal);
214 	sshbuf_free(b);
215 	return r;
216 }
217 
218 void
kex_prop_free(char ** proposal)219 kex_prop_free(char **proposal)
220 {
221 	u_int i;
222 
223 	if (proposal == NULL)
224 		return;
225 	for (i = 0; i < PROPOSAL_MAX; i++)
226 		free(proposal[i]);
227 	free(proposal);
228 }
229 
230 int
kex_protocol_error(int type,u_int32_t seq,struct ssh * ssh)231 kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
232 {
233 	int r;
234 
235 	/* If in strict mode, any unexpected message is an error */
236 	if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) {
237 		ssh_packet_disconnect(ssh, "strict KEX violation: "
238 		    "unexpected packet type %u (seqnr %u)", type, seq);
239 	}
240 	error_f("type %u seq %u", type, seq);
241 	if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
242 	    (r = sshpkt_put_u32(ssh, seq)) != 0 ||
243 	    (r = sshpkt_send(ssh)) != 0)
244 		return r;
245 	return 0;
246 }
247 
248 static void
kex_reset_dispatch(struct ssh * ssh)249 kex_reset_dispatch(struct ssh *ssh)
250 {
251 	ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
252 	    SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
253 }
254 
255 void
kex_set_server_sig_algs(struct ssh * ssh,const char * allowed_algs)256 kex_set_server_sig_algs(struct ssh *ssh, const char *allowed_algs)
257 {
258 	char *alg, *oalgs, *algs, *sigalgs;
259 	const char *sigalg;
260 
261 	/*
262 	 * NB. allowed algorithms may contain certificate algorithms that
263 	 * map to a specific plain signature type, e.g.
264 	 * rsa-sha2-512-cert-v01@openssh.com => rsa-sha2-512
265 	 * We need to be careful here to match these, retain the mapping
266 	 * and only add each signature algorithm once.
267 	 */
268 	if ((sigalgs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
269 		fatal_f("sshkey_alg_list failed");
270 	oalgs = algs = xstrdup(allowed_algs);
271 	free(ssh->kex->server_sig_algs);
272 	ssh->kex->server_sig_algs = NULL;
273 	for ((alg = strsep(&algs, ",")); alg != NULL && *alg != '\0';
274 	    (alg = strsep(&algs, ","))) {
275 		if ((sigalg = sshkey_sigalg_by_name(alg)) == NULL)
276 			continue;
277 		if (!kex_has_any_alg(sigalg, sigalgs))
278 			continue;
279 		/* Don't add an algorithm twice. */
280 		if (ssh->kex->server_sig_algs != NULL &&
281 		    kex_has_any_alg(sigalg, ssh->kex->server_sig_algs))
282 			continue;
283 		xextendf(&ssh->kex->server_sig_algs, ",", "%s", sigalg);
284 	}
285 	free(oalgs);
286 	free(sigalgs);
287 	if (ssh->kex->server_sig_algs == NULL)
288 		ssh->kex->server_sig_algs = xstrdup("");
289 }
290 
291 static int
kex_compose_ext_info_server(struct ssh * ssh,struct sshbuf * m)292 kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m)
293 {
294 	int r;
295 
296 	if (ssh->kex->server_sig_algs == NULL &&
297 	    (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
298 		return SSH_ERR_ALLOC_FAIL;
299 	if ((r = sshbuf_put_u32(m, 3)) != 0 ||
300 	    (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 ||
301 	    (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 ||
302 	    (r = sshbuf_put_cstring(m,
303 	    "publickey-hostbound@openssh.com")) != 0 ||
304 	    (r = sshbuf_put_cstring(m, "0")) != 0 ||
305 	    (r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 ||
306 	    (r = sshbuf_put_cstring(m, "0")) != 0) {
307 		error_fr(r, "compose");
308 		return r;
309 	}
310 	return 0;
311 }
312 
313 static int
kex_compose_ext_info_client(struct ssh * ssh,struct sshbuf * m)314 kex_compose_ext_info_client(struct ssh *ssh, struct sshbuf *m)
315 {
316 	int r;
317 
318 	if ((r = sshbuf_put_u32(m, 1)) != 0 ||
319 	    (r = sshbuf_put_cstring(m, "ext-info-in-auth@openssh.com")) != 0 ||
320 	    (r = sshbuf_put_cstring(m, "0")) != 0) {
321 		error_fr(r, "compose");
322 		goto out;
323 	}
324 	/* success */
325 	r = 0;
326  out:
327 	return r;
328 }
329 
330 static int
kex_maybe_send_ext_info(struct ssh * ssh)331 kex_maybe_send_ext_info(struct ssh *ssh)
332 {
333 	int r;
334 	struct sshbuf *m = NULL;
335 
336 	if ((ssh->kex->flags & KEX_INITIAL) == 0)
337 		return 0;
338 	if (!ssh->kex->ext_info_c && !ssh->kex->ext_info_s)
339 		return 0;
340 
341 	/* Compose EXT_INFO packet. */
342 	if ((m = sshbuf_new()) == NULL)
343 		fatal_f("sshbuf_new failed");
344 	if (ssh->kex->ext_info_c &&
345 	    (r = kex_compose_ext_info_server(ssh, m)) != 0)
346 		goto fail;
347 	if (ssh->kex->ext_info_s &&
348 	    (r = kex_compose_ext_info_client(ssh, m)) != 0)
349 		goto fail;
350 
351 	/* Send the actual KEX_INFO packet */
352 	debug("Sending SSH2_MSG_EXT_INFO");
353 	if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
354 	    (r = sshpkt_putb(ssh, m)) != 0 ||
355 	    (r = sshpkt_send(ssh)) != 0) {
356 		error_f("send EXT_INFO");
357 		goto fail;
358 	}
359 
360 	r = 0;
361 
362  fail:
363 	sshbuf_free(m);
364 	return r;
365 }
366 
367 int
kex_server_update_ext_info(struct ssh * ssh)368 kex_server_update_ext_info(struct ssh *ssh)
369 {
370 	int r;
371 
372 	if ((ssh->kex->flags & KEX_HAS_EXT_INFO_IN_AUTH) == 0)
373 		return 0;
374 
375 	debug_f("Sending SSH2_MSG_EXT_INFO");
376 	if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
377 	    (r = sshpkt_put_u32(ssh, 1)) != 0 ||
378 	    (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
379 	    (r = sshpkt_put_cstring(ssh, ssh->kex->server_sig_algs)) != 0 ||
380 	    (r = sshpkt_send(ssh)) != 0) {
381 		error_f("send EXT_INFO");
382 		return r;
383 	}
384 	return 0;
385 }
386 
387 int
kex_send_newkeys(struct ssh * ssh)388 kex_send_newkeys(struct ssh *ssh)
389 {
390 	int r;
391 
392 	kex_reset_dispatch(ssh);
393 	if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
394 	    (r = sshpkt_send(ssh)) != 0)
395 		return r;
396 	debug("SSH2_MSG_NEWKEYS sent");
397 	ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
398 	if ((r = kex_maybe_send_ext_info(ssh)) != 0)
399 		return r;
400 	debug("expecting SSH2_MSG_NEWKEYS");
401 	return 0;
402 }
403 
404 /* Check whether an ext_info value contains the expected version string */
405 static int
kex_ext_info_check_ver(struct kex * kex,const char * name,const u_char * val,size_t len,const char * want_ver,u_int flag)406 kex_ext_info_check_ver(struct kex *kex, const char *name,
407     const u_char *val, size_t len, const char *want_ver, u_int flag)
408 {
409 	if (memchr(val, '\0', len) != NULL) {
410 		error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name);
411 		return SSH_ERR_INVALID_FORMAT;
412 	}
413 	debug_f("%s=<%s>", name, val);
414 	if (strcmp(val, want_ver) == 0)
415 		kex->flags |= flag;
416 	else
417 		debug_f("unsupported version of %s extension", name);
418 	return 0;
419 }
420 
421 static int
kex_ext_info_client_parse(struct ssh * ssh,const char * name,const u_char * value,size_t vlen)422 kex_ext_info_client_parse(struct ssh *ssh, const char *name,
423     const u_char *value, size_t vlen)
424 {
425 	int r;
426 
427 	/* NB. some messages are only accepted in the initial EXT_INFO */
428 	if (strcmp(name, "server-sig-algs") == 0) {
429 		/* Ensure no \0 lurking in value */
430 		if (memchr(value, '\0', vlen) != NULL) {
431 			error_f("nul byte in %s", name);
432 			return SSH_ERR_INVALID_FORMAT;
433 		}
434 		debug_f("%s=<%s>", name, value);
435 		free(ssh->kex->server_sig_algs);
436 		ssh->kex->server_sig_algs = xstrdup((const char *)value);
437 	} else if (ssh->kex->ext_info_received == 1 &&
438 	    strcmp(name, "publickey-hostbound@openssh.com") == 0) {
439 		if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
440 		    "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) {
441 			return r;
442 		}
443 	} else if (ssh->kex->ext_info_received == 1 &&
444 	    strcmp(name, "ping@openssh.com") == 0) {
445 		if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
446 		    "0", KEX_HAS_PING)) != 0) {
447 			return r;
448 		}
449 	} else
450 		debug_f("%s (unrecognised)", name);
451 
452 	return 0;
453 }
454 
455 static int
kex_ext_info_server_parse(struct ssh * ssh,const char * name,const u_char * value,size_t vlen)456 kex_ext_info_server_parse(struct ssh *ssh, const char *name,
457     const u_char *value, size_t vlen)
458 {
459 	int r;
460 
461 	if (strcmp(name, "ext-info-in-auth@openssh.com") == 0) {
462 		if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
463 		    "0", KEX_HAS_EXT_INFO_IN_AUTH)) != 0) {
464 			return r;
465 		}
466 	} else
467 		debug_f("%s (unrecognised)", name);
468 	return 0;
469 }
470 
471 int
kex_input_ext_info(int type,u_int32_t seq,struct ssh * ssh)472 kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
473 {
474 	struct kex *kex = ssh->kex;
475 	const int max_ext_info = kex->server ? 1 : 2;
476 	u_int32_t i, ninfo;
477 	char *name;
478 	u_char *val;
479 	size_t vlen;
480 	int r;
481 
482 	debug("SSH2_MSG_EXT_INFO received");
483 	if (++kex->ext_info_received > max_ext_info) {
484 		error("too many SSH2_MSG_EXT_INFO messages sent by peer");
485 		return dispatch_protocol_error(type, seq, ssh);
486 	}
487 	ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
488 	if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
489 		return r;
490 	if (ninfo >= 1024) {
491 		error("SSH2_MSG_EXT_INFO with too many entries, expected "
492 		    "<=1024, received %u", ninfo);
493 		return dispatch_protocol_error(type, seq, ssh);
494 	}
495 	for (i = 0; i < ninfo; i++) {
496 		if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
497 			return r;
498 		if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
499 			free(name);
500 			return r;
501 		}
502 		debug3_f("extension %s", name);
503 		if (kex->server) {
504 			if ((r = kex_ext_info_server_parse(ssh, name,
505 			    val, vlen)) != 0)
506 				return r;
507 		} else {
508 			if ((r = kex_ext_info_client_parse(ssh, name,
509 			    val, vlen)) != 0)
510 				return r;
511 		}
512 		free(name);
513 		free(val);
514 	}
515 	return sshpkt_get_end(ssh);
516 }
517 
518 static int
kex_input_newkeys(int type,u_int32_t seq,struct ssh * ssh)519 kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
520 {
521 	struct kex *kex = ssh->kex;
522 	int r, initial = (kex->flags & KEX_INITIAL) != 0;
523 	char *cp, **prop;
524 
525 	debug("SSH2_MSG_NEWKEYS received");
526 	if (kex->ext_info_c && initial)
527 		ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info);
528 	ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
529 	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
530 	if ((r = sshpkt_get_end(ssh)) != 0)
531 		return r;
532 	if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
533 		return r;
534 	if (initial) {
535 		/* Remove initial KEX signalling from proposal for rekeying */
536 		if ((r = kex_buf2prop(kex->my, NULL, &prop)) != 0)
537 			return r;
538 		if ((cp = match_filter_denylist(prop[PROPOSAL_KEX_ALGS],
539 		    kex->server ?
540 		    "ext-info-s,kex-strict-s-v00@openssh.com" :
541 		    "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) {
542 			error_f("match_filter_denylist failed");
543 			goto fail;
544 		}
545 		free(prop[PROPOSAL_KEX_ALGS]);
546 		prop[PROPOSAL_KEX_ALGS] = cp;
547 		if ((r = kex_prop2buf(ssh->kex->my, prop)) != 0) {
548 			error_f("kex_prop2buf failed");
549  fail:
550 			kex_proposal_free_entries(prop);
551 			free(prop);
552 			return SSH_ERR_INTERNAL_ERROR;
553 		}
554 		kex_proposal_free_entries(prop);
555 		free(prop);
556 	}
557 	kex->done = 1;
558 	kex->flags &= ~KEX_INITIAL;
559 	sshbuf_reset(kex->peer);
560 	kex->flags &= ~KEX_INIT_SENT;
561 	free(kex->name);
562 	kex->name = NULL;
563 	return 0;
564 }
565 
566 int
kex_send_kexinit(struct ssh * ssh)567 kex_send_kexinit(struct ssh *ssh)
568 {
569 	u_char *cookie;
570 	struct kex *kex = ssh->kex;
571 	int r;
572 
573 	if (kex == NULL) {
574 		error_f("no kex");
575 		return SSH_ERR_INTERNAL_ERROR;
576 	}
577 	if (kex->flags & KEX_INIT_SENT)
578 		return 0;
579 	kex->done = 0;
580 
581 	/* generate a random cookie */
582 	if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) {
583 		error_f("bad kex length: %zu < %d",
584 		    sshbuf_len(kex->my), KEX_COOKIE_LEN);
585 		return SSH_ERR_INVALID_FORMAT;
586 	}
587 	if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
588 		error_f("buffer error");
589 		return SSH_ERR_INTERNAL_ERROR;
590 	}
591 	arc4random_buf(cookie, KEX_COOKIE_LEN);
592 
593 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
594 	    (r = sshpkt_putb(ssh, kex->my)) != 0 ||
595 	    (r = sshpkt_send(ssh)) != 0) {
596 		error_fr(r, "compose reply");
597 		return r;
598 	}
599 	debug("SSH2_MSG_KEXINIT sent");
600 	kex->flags |= KEX_INIT_SENT;
601 	return 0;
602 }
603 
604 int
kex_input_kexinit(int type,u_int32_t seq,struct ssh * ssh)605 kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
606 {
607 	struct kex *kex = ssh->kex;
608 	const u_char *ptr;
609 	u_int i;
610 	size_t dlen;
611 	int r;
612 
613 	debug("SSH2_MSG_KEXINIT received");
614 	if (kex == NULL) {
615 		error_f("no kex");
616 		return SSH_ERR_INTERNAL_ERROR;
617 	}
618 	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
619 	ptr = sshpkt_ptr(ssh, &dlen);
620 	if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
621 		return r;
622 
623 	/* discard packet */
624 	for (i = 0; i < KEX_COOKIE_LEN; i++) {
625 		if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
626 			error_fr(r, "discard cookie");
627 			return r;
628 		}
629 	}
630 	for (i = 0; i < PROPOSAL_MAX; i++) {
631 		if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
632 			error_fr(r, "discard proposal");
633 			return r;
634 		}
635 	}
636 	/*
637 	 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
638 	 * KEX method has the server move first, but a server might be using
639 	 * a custom method or one that we otherwise don't support. We should
640 	 * be prepared to remember first_kex_follows here so we can eat a
641 	 * packet later.
642 	 * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
643 	 * for cases where the server *doesn't* go first. I guess we should
644 	 * ignore it when it is set for these cases, which is what we do now.
645 	 */
646 	if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||	/* first_kex_follows */
647 	    (r = sshpkt_get_u32(ssh, NULL)) != 0 ||	/* reserved */
648 	    (r = sshpkt_get_end(ssh)) != 0)
649 			return r;
650 
651 	if (!(kex->flags & KEX_INIT_SENT))
652 		if ((r = kex_send_kexinit(ssh)) != 0)
653 			return r;
654 	if ((r = kex_choose_conf(ssh, seq)) != 0)
655 		return r;
656 
657 	if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
658 		return (kex->kex[kex->kex_type])(ssh);
659 
660 	error_f("unknown kex type %u", kex->kex_type);
661 	return SSH_ERR_INTERNAL_ERROR;
662 }
663 
664 struct kex *
kex_new(void)665 kex_new(void)
666 {
667 	struct kex *kex;
668 
669 	if ((kex = calloc(1, sizeof(*kex))) == NULL ||
670 	    (kex->peer = sshbuf_new()) == NULL ||
671 	    (kex->my = sshbuf_new()) == NULL ||
672 	    (kex->client_version = sshbuf_new()) == NULL ||
673 	    (kex->server_version = sshbuf_new()) == NULL ||
674 	    (kex->session_id = sshbuf_new()) == NULL) {
675 		kex_free(kex);
676 		return NULL;
677 	}
678 	return kex;
679 }
680 
681 void
kex_free_newkeys(struct newkeys * newkeys)682 kex_free_newkeys(struct newkeys *newkeys)
683 {
684 	if (newkeys == NULL)
685 		return;
686 	if (newkeys->enc.key) {
687 		explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
688 		free(newkeys->enc.key);
689 		newkeys->enc.key = NULL;
690 	}
691 	if (newkeys->enc.iv) {
692 		explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
693 		free(newkeys->enc.iv);
694 		newkeys->enc.iv = NULL;
695 	}
696 	free(newkeys->enc.name);
697 	explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
698 	free(newkeys->comp.name);
699 	explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
700 	mac_clear(&newkeys->mac);
701 	if (newkeys->mac.key) {
702 		explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
703 		free(newkeys->mac.key);
704 		newkeys->mac.key = NULL;
705 	}
706 	free(newkeys->mac.name);
707 	explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
708 	freezero(newkeys, sizeof(*newkeys));
709 }
710 
711 void
kex_free(struct kex * kex)712 kex_free(struct kex *kex)
713 {
714 	u_int mode;
715 
716 	if (kex == NULL)
717 		return;
718 
719 #ifdef WITH_OPENSSL
720 	DH_free(kex->dh);
721 	EC_KEY_free(kex->ec_client_key);
722 #endif
723 	for (mode = 0; mode < MODE_MAX; mode++) {
724 		kex_free_newkeys(kex->newkeys[mode]);
725 		kex->newkeys[mode] = NULL;
726 	}
727 	sshbuf_free(kex->peer);
728 	sshbuf_free(kex->my);
729 	sshbuf_free(kex->client_version);
730 	sshbuf_free(kex->server_version);
731 	sshbuf_free(kex->client_pub);
732 	sshbuf_free(kex->session_id);
733 	sshbuf_free(kex->initial_sig);
734 	sshkey_free(kex->initial_hostkey);
735 	free(kex->failed_choice);
736 	free(kex->hostkey_alg);
737 	free(kex->name);
738 	free(kex);
739 }
740 
741 int
kex_ready(struct ssh * ssh,char * proposal[PROPOSAL_MAX])742 kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
743 {
744 	int r;
745 
746 	if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
747 		return r;
748 	ssh->kex->flags = KEX_INITIAL;
749 	kex_reset_dispatch(ssh);
750 	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
751 	return 0;
752 }
753 
754 int
kex_setup(struct ssh * ssh,char * proposal[PROPOSAL_MAX])755 kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
756 {
757 	int r;
758 
759 	if ((r = kex_ready(ssh, proposal)) != 0)
760 		return r;
761 	if ((r = kex_send_kexinit(ssh)) != 0) {		/* we start */
762 		kex_free(ssh->kex);
763 		ssh->kex = NULL;
764 		return r;
765 	}
766 	return 0;
767 }
768 
769 /*
770  * Request key re-exchange, returns 0 on success or a ssherr.h error
771  * code otherwise. Must not be called if KEX is incomplete or in-progress.
772  */
773 int
kex_start_rekex(struct ssh * ssh)774 kex_start_rekex(struct ssh *ssh)
775 {
776 	if (ssh->kex == NULL) {
777 		error_f("no kex");
778 		return SSH_ERR_INTERNAL_ERROR;
779 	}
780 	if (ssh->kex->done == 0) {
781 		error_f("requested twice");
782 		return SSH_ERR_INTERNAL_ERROR;
783 	}
784 	ssh->kex->done = 0;
785 	return kex_send_kexinit(ssh);
786 }
787 
788 static int
choose_enc(struct sshenc * enc,char * client,char * server)789 choose_enc(struct sshenc *enc, char *client, char *server)
790 {
791 	char *name = match_list(client, server, NULL);
792 
793 	if (name == NULL)
794 		return SSH_ERR_NO_CIPHER_ALG_MATCH;
795 	if ((enc->cipher = cipher_by_name(name)) == NULL) {
796 		error_f("unsupported cipher %s", name);
797 		free(name);
798 		return SSH_ERR_INTERNAL_ERROR;
799 	}
800 	enc->name = name;
801 	enc->enabled = 0;
802 	enc->iv = NULL;
803 	enc->iv_len = cipher_ivlen(enc->cipher);
804 	enc->key = NULL;
805 	enc->key_len = cipher_keylen(enc->cipher);
806 	enc->block_size = cipher_blocksize(enc->cipher);
807 	return 0;
808 }
809 
810 static int
choose_mac(struct ssh * ssh,struct sshmac * mac,char * client,char * server)811 choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
812 {
813 	char *name = match_list(client, server, NULL);
814 
815 	if (name == NULL)
816 		return SSH_ERR_NO_MAC_ALG_MATCH;
817 	if (mac_setup(mac, name) < 0) {
818 		error_f("unsupported MAC %s", name);
819 		free(name);
820 		return SSH_ERR_INTERNAL_ERROR;
821 	}
822 	mac->name = name;
823 	mac->key = NULL;
824 	mac->enabled = 0;
825 	return 0;
826 }
827 
828 static int
choose_comp(struct sshcomp * comp,char * client,char * server)829 choose_comp(struct sshcomp *comp, char *client, char *server)
830 {
831 	char *name = match_list(client, server, NULL);
832 
833 	if (name == NULL)
834 		return SSH_ERR_NO_COMPRESS_ALG_MATCH;
835 #ifdef WITH_ZLIB
836 	if (strcmp(name, "zlib@openssh.com") == 0) {
837 		comp->type = COMP_DELAYED;
838 	} else
839 #endif	/* WITH_ZLIB */
840 	if (strcmp(name, "none") == 0) {
841 		comp->type = COMP_NONE;
842 	} else {
843 		error_f("unsupported compression scheme %s", name);
844 		free(name);
845 		return SSH_ERR_INTERNAL_ERROR;
846 	}
847 	comp->name = name;
848 	return 0;
849 }
850 
851 static int
choose_kex(struct kex * k,char * client,char * server)852 choose_kex(struct kex *k, char *client, char *server)
853 {
854 	k->name = match_list(client, server, NULL);
855 
856 	debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
857 	if (k->name == NULL)
858 		return SSH_ERR_NO_KEX_ALG_MATCH;
859 	if (!kex_name_valid(k->name)) {
860 		error_f("unsupported KEX method %s", k->name);
861 		return SSH_ERR_INTERNAL_ERROR;
862 	}
863 	k->kex_type = kex_type_from_name(k->name);
864 	k->hash_alg = kex_hash_from_name(k->name);
865 	k->ec_nid = kex_nid_from_name(k->name);
866 	return 0;
867 }
868 
869 static int
choose_hostkeyalg(struct kex * k,char * client,char * server)870 choose_hostkeyalg(struct kex *k, char *client, char *server)
871 {
872 	free(k->hostkey_alg);
873 	k->hostkey_alg = match_list(client, server, NULL);
874 
875 	debug("kex: host key algorithm: %s",
876 	    k->hostkey_alg ? k->hostkey_alg : "(no match)");
877 	if (k->hostkey_alg == NULL)
878 		return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
879 	k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
880 	if (k->hostkey_type == KEY_UNSPEC) {
881 		error_f("unsupported hostkey algorithm %s", k->hostkey_alg);
882 		return SSH_ERR_INTERNAL_ERROR;
883 	}
884 	k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
885 	return 0;
886 }
887 
888 static int
proposals_match(char * my[PROPOSAL_MAX],char * peer[PROPOSAL_MAX])889 proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
890 {
891 	static int check[] = {
892 		PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
893 	};
894 	int *idx;
895 	char *p;
896 
897 	for (idx = &check[0]; *idx != -1; idx++) {
898 		if ((p = strchr(my[*idx], ',')) != NULL)
899 			*p = '\0';
900 		if ((p = strchr(peer[*idx], ',')) != NULL)
901 			*p = '\0';
902 		if (strcmp(my[*idx], peer[*idx]) != 0) {
903 			debug2("proposal mismatch: my %s peer %s",
904 			    my[*idx], peer[*idx]);
905 			return (0);
906 		}
907 	}
908 	debug2("proposals match");
909 	return (1);
910 }
911 
912 static int
kexalgs_contains(char ** peer,const char * ext)913 kexalgs_contains(char **peer, const char *ext)
914 {
915 	return kex_has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
916 }
917 
918 static int
kex_choose_conf(struct ssh * ssh,uint32_t seq)919 kex_choose_conf(struct ssh *ssh, uint32_t seq)
920 {
921 	struct kex *kex = ssh->kex;
922 	struct newkeys *newkeys;
923 	char **my = NULL, **peer = NULL;
924 	char **cprop, **sprop;
925 	int nenc, nmac, ncomp;
926 	u_int mode, ctos, need, dh_need, authlen;
927 	int r, first_kex_follows;
928 
929 	debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
930 	if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
931 		goto out;
932 	debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
933 	if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
934 		goto out;
935 
936 	if (kex->server) {
937 		cprop=peer;
938 		sprop=my;
939 	} else {
940 		cprop=my;
941 		sprop=peer;
942 	}
943 
944 	/* Check whether peer supports ext_info/kex_strict */
945 	if ((kex->flags & KEX_INITIAL) != 0) {
946 		if (kex->server) {
947 			kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
948 			kex->kex_strict = kexalgs_contains(peer,
949 			    "kex-strict-c-v00@openssh.com");
950 		} else {
951 			kex->ext_info_s = kexalgs_contains(peer, "ext-info-s");
952 			kex->kex_strict = kexalgs_contains(peer,
953 			    "kex-strict-s-v00@openssh.com");
954 		}
955 		if (kex->kex_strict) {
956 			debug3_f("will use strict KEX ordering");
957 			if (seq != 0)
958 				ssh_packet_disconnect(ssh,
959 				    "strict KEX violation: "
960 				    "KEXINIT was not the first packet");
961 		}
962 	}
963 
964 	/* Check whether client supports rsa-sha2 algorithms */
965 	if (kex->server && (kex->flags & KEX_INITIAL)) {
966 		if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
967 		    "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
968 			kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
969 		if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
970 		    "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
971 			kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
972 	}
973 
974 	/* Algorithm Negotiation */
975 	if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
976 	    sprop[PROPOSAL_KEX_ALGS])) != 0) {
977 		kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
978 		peer[PROPOSAL_KEX_ALGS] = NULL;
979 		goto out;
980 	}
981 	if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
982 	    sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
983 		kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
984 		peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
985 		goto out;
986 	}
987 	for (mode = 0; mode < MODE_MAX; mode++) {
988 		if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
989 			r = SSH_ERR_ALLOC_FAIL;
990 			goto out;
991 		}
992 		kex->newkeys[mode] = newkeys;
993 		ctos = (!kex->server && mode == MODE_OUT) ||
994 		    (kex->server && mode == MODE_IN);
995 		nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
996 		nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
997 		ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
998 		if ((r = choose_enc(&newkeys->enc, cprop[nenc],
999 		    sprop[nenc])) != 0) {
1000 			kex->failed_choice = peer[nenc];
1001 			peer[nenc] = NULL;
1002 			goto out;
1003 		}
1004 		authlen = cipher_authlen(newkeys->enc.cipher);
1005 		/* ignore mac for authenticated encryption */
1006 		if (authlen == 0 &&
1007 		    (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
1008 		    sprop[nmac])) != 0) {
1009 			kex->failed_choice = peer[nmac];
1010 			peer[nmac] = NULL;
1011 			goto out;
1012 		}
1013 		if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
1014 		    sprop[ncomp])) != 0) {
1015 			kex->failed_choice = peer[ncomp];
1016 			peer[ncomp] = NULL;
1017 			goto out;
1018 		}
1019 		debug("kex: %s cipher: %s MAC: %s compression: %s",
1020 		    ctos ? "client->server" : "server->client",
1021 		    newkeys->enc.name,
1022 		    authlen == 0 ? newkeys->mac.name : "<implicit>",
1023 		    newkeys->comp.name);
1024 	}
1025 	need = dh_need = 0;
1026 	for (mode = 0; mode < MODE_MAX; mode++) {
1027 		newkeys = kex->newkeys[mode];
1028 		need = MAXIMUM(need, newkeys->enc.key_len);
1029 		need = MAXIMUM(need, newkeys->enc.block_size);
1030 		need = MAXIMUM(need, newkeys->enc.iv_len);
1031 		need = MAXIMUM(need, newkeys->mac.key_len);
1032 		dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
1033 		dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
1034 		dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
1035 		dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
1036 	}
1037 	/* XXX need runden? */
1038 	kex->we_need = need;
1039 	kex->dh_need = dh_need;
1040 
1041 	/* ignore the next message if the proposals do not match */
1042 	if (first_kex_follows && !proposals_match(my, peer))
1043 		ssh->dispatch_skip_packets = 1;
1044 	r = 0;
1045  out:
1046 	kex_prop_free(my);
1047 	kex_prop_free(peer);
1048 	return r;
1049 }
1050 
1051 static int
derive_key(struct ssh * ssh,int id,u_int need,u_char * hash,u_int hashlen,const struct sshbuf * shared_secret,u_char ** keyp)1052 derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
1053     const struct sshbuf *shared_secret, u_char **keyp)
1054 {
1055 	struct kex *kex = ssh->kex;
1056 	struct ssh_digest_ctx *hashctx = NULL;
1057 	char c = id;
1058 	u_int have;
1059 	size_t mdsz;
1060 	u_char *digest;
1061 	int r;
1062 
1063 	if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
1064 		return SSH_ERR_INVALID_ARGUMENT;
1065 	if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
1066 		r = SSH_ERR_ALLOC_FAIL;
1067 		goto out;
1068 	}
1069 
1070 	/* K1 = HASH(K || H || "A" || session_id) */
1071 	if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1072 	    ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1073 	    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1074 	    ssh_digest_update(hashctx, &c, 1) != 0 ||
1075 	    ssh_digest_update_buffer(hashctx, kex->session_id) != 0 ||
1076 	    ssh_digest_final(hashctx, digest, mdsz) != 0) {
1077 		r = SSH_ERR_LIBCRYPTO_ERROR;
1078 		error_f("KEX hash failed");
1079 		goto out;
1080 	}
1081 	ssh_digest_free(hashctx);
1082 	hashctx = NULL;
1083 
1084 	/*
1085 	 * expand key:
1086 	 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
1087 	 * Key = K1 || K2 || ... || Kn
1088 	 */
1089 	for (have = mdsz; need > have; have += mdsz) {
1090 		if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1091 		    ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1092 		    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1093 		    ssh_digest_update(hashctx, digest, have) != 0 ||
1094 		    ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
1095 			error_f("KDF failed");
1096 			r = SSH_ERR_LIBCRYPTO_ERROR;
1097 			goto out;
1098 		}
1099 		ssh_digest_free(hashctx);
1100 		hashctx = NULL;
1101 	}
1102 #ifdef DEBUG_KEX
1103 	fprintf(stderr, "key '%c'== ", c);
1104 	dump_digest("key", digest, need);
1105 #endif
1106 	*keyp = digest;
1107 	digest = NULL;
1108 	r = 0;
1109  out:
1110 	free(digest);
1111 	ssh_digest_free(hashctx);
1112 	return r;
1113 }
1114 
1115 #define NKEYS	6
1116 int
kex_derive_keys(struct ssh * ssh,u_char * hash,u_int hashlen,const struct sshbuf * shared_secret)1117 kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
1118     const struct sshbuf *shared_secret)
1119 {
1120 	struct kex *kex = ssh->kex;
1121 	u_char *keys[NKEYS];
1122 	u_int i, j, mode, ctos;
1123 	int r;
1124 
1125 	/* save initial hash as session id */
1126 	if ((kex->flags & KEX_INITIAL) != 0) {
1127 		if (sshbuf_len(kex->session_id) != 0) {
1128 			error_f("already have session ID at kex");
1129 			return SSH_ERR_INTERNAL_ERROR;
1130 		}
1131 		if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0)
1132 			return r;
1133 	} else if (sshbuf_len(kex->session_id) == 0) {
1134 		error_f("no session ID in rekex");
1135 		return SSH_ERR_INTERNAL_ERROR;
1136 	}
1137 	for (i = 0; i < NKEYS; i++) {
1138 		if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
1139 		    shared_secret, &keys[i])) != 0) {
1140 			for (j = 0; j < i; j++)
1141 				free(keys[j]);
1142 			return r;
1143 		}
1144 	}
1145 	for (mode = 0; mode < MODE_MAX; mode++) {
1146 		ctos = (!kex->server && mode == MODE_OUT) ||
1147 		    (kex->server && mode == MODE_IN);
1148 		kex->newkeys[mode]->enc.iv  = keys[ctos ? 0 : 1];
1149 		kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
1150 		kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
1151 	}
1152 	return 0;
1153 }
1154 
1155 int
kex_load_hostkey(struct ssh * ssh,struct sshkey ** prvp,struct sshkey ** pubp)1156 kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
1157 {
1158 	struct kex *kex = ssh->kex;
1159 
1160 	*pubp = NULL;
1161 	*prvp = NULL;
1162 	if (kex->load_host_public_key == NULL ||
1163 	    kex->load_host_private_key == NULL) {
1164 		error_f("missing hostkey loader");
1165 		return SSH_ERR_INVALID_ARGUMENT;
1166 	}
1167 	*pubp = kex->load_host_public_key(kex->hostkey_type,
1168 	    kex->hostkey_nid, ssh);
1169 	*prvp = kex->load_host_private_key(kex->hostkey_type,
1170 	    kex->hostkey_nid, ssh);
1171 	if (*pubp == NULL)
1172 		return SSH_ERR_NO_HOSTKEY_LOADED;
1173 	return 0;
1174 }
1175 
1176 int
kex_verify_host_key(struct ssh * ssh,struct sshkey * server_host_key)1177 kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
1178 {
1179 	struct kex *kex = ssh->kex;
1180 
1181 	if (kex->verify_host_key == NULL) {
1182 		error_f("missing hostkey verifier");
1183 		return SSH_ERR_INVALID_ARGUMENT;
1184 	}
1185 	if (server_host_key->type != kex->hostkey_type ||
1186 	    (kex->hostkey_type == KEY_ECDSA &&
1187 	    server_host_key->ecdsa_nid != kex->hostkey_nid))
1188 		return SSH_ERR_KEY_TYPE_MISMATCH;
1189 	if (kex->verify_host_key(server_host_key, ssh) == -1)
1190 		return  SSH_ERR_SIGNATURE_INVALID;
1191 	return 0;
1192 }
1193 
1194 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
1195 void
dump_digest(const char * msg,const u_char * digest,int len)1196 dump_digest(const char *msg, const u_char *digest, int len)
1197 {
1198 	fprintf(stderr, "%s\n", msg);
1199 	sshbuf_dump_data(digest, len, stderr);
1200 }
1201 #endif
1202 
1203 /*
1204  * Send a plaintext error message to the peer, suffixed by \r\n.
1205  * Only used during banner exchange, and there only for the server.
1206  */
1207 static void
send_error(struct ssh * ssh,char * msg)1208 send_error(struct ssh *ssh, char *msg)
1209 {
1210 	char *crnl = "\r\n";
1211 
1212 	if (!ssh->kex->server)
1213 		return;
1214 
1215 	if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1216 	    msg, strlen(msg)) != strlen(msg) ||
1217 	    atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1218 	    crnl, strlen(crnl)) != strlen(crnl))
1219 		error_f("write: %.100s", strerror(errno));
1220 }
1221 
1222 /*
1223  * Sends our identification string and waits for the peer's. Will block for
1224  * up to timeout_ms (or indefinitely if timeout_ms <= 0).
1225  * Returns on 0 success or a ssherr.h code on failure.
1226  */
1227 int
kex_exchange_identification(struct ssh * ssh,int timeout_ms,const char * version_addendum)1228 kex_exchange_identification(struct ssh *ssh, int timeout_ms,
1229     const char *version_addendum)
1230 {
1231 	int remote_major, remote_minor, mismatch, oerrno = 0;
1232 	size_t len, n;
1233 	int r, expect_nl;
1234 	u_char c;
1235 	struct sshbuf *our_version = ssh->kex->server ?
1236 	    ssh->kex->server_version : ssh->kex->client_version;
1237 	struct sshbuf *peer_version = ssh->kex->server ?
1238 	    ssh->kex->client_version : ssh->kex->server_version;
1239 	char *our_version_string = NULL, *peer_version_string = NULL;
1240 	char *cp, *remote_version = NULL;
1241 
1242 	/* Prepare and send our banner */
1243 	sshbuf_reset(our_version);
1244 	if (version_addendum != NULL && *version_addendum == '\0')
1245 		version_addendum = NULL;
1246 	if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n",
1247 	    PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
1248 	    version_addendum == NULL ? "" : " ",
1249 	    version_addendum == NULL ? "" : version_addendum)) != 0) {
1250 		oerrno = errno;
1251 		error_fr(r, "sshbuf_putf");
1252 		goto out;
1253 	}
1254 
1255 	if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1256 	    sshbuf_mutable_ptr(our_version),
1257 	    sshbuf_len(our_version)) != sshbuf_len(our_version)) {
1258 		oerrno = errno;
1259 		debug_f("write: %.100s", strerror(errno));
1260 		r = SSH_ERR_SYSTEM_ERROR;
1261 		goto out;
1262 	}
1263 	if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
1264 		oerrno = errno;
1265 		error_fr(r, "sshbuf_consume_end");
1266 		goto out;
1267 	}
1268 	our_version_string = sshbuf_dup_string(our_version);
1269 	if (our_version_string == NULL) {
1270 		error_f("sshbuf_dup_string failed");
1271 		r = SSH_ERR_ALLOC_FAIL;
1272 		goto out;
1273 	}
1274 	debug("Local version string %.100s", our_version_string);
1275 
1276 	/* Read other side's version identification. */
1277 	for (n = 0; ; n++) {
1278 		if (n >= SSH_MAX_PRE_BANNER_LINES) {
1279 			send_error(ssh, "No SSH identification string "
1280 			    "received.");
1281 			error_f("No SSH version received in first %u lines "
1282 			    "from server", SSH_MAX_PRE_BANNER_LINES);
1283 			r = SSH_ERR_INVALID_FORMAT;
1284 			goto out;
1285 		}
1286 		sshbuf_reset(peer_version);
1287 		expect_nl = 0;
1288 		for (;;) {
1289 			if (timeout_ms > 0) {
1290 				r = waitrfd(ssh_packet_get_connection_in(ssh),
1291 				    &timeout_ms, NULL);
1292 				if (r == -1 && errno == ETIMEDOUT) {
1293 					send_error(ssh, "Timed out waiting "
1294 					    "for SSH identification string.");
1295 					error("Connection timed out during "
1296 					    "banner exchange");
1297 					r = SSH_ERR_CONN_TIMEOUT;
1298 					goto out;
1299 				} else if (r == -1) {
1300 					oerrno = errno;
1301 					error_f("%s", strerror(errno));
1302 					r = SSH_ERR_SYSTEM_ERROR;
1303 					goto out;
1304 				}
1305 			}
1306 
1307 			len = atomicio(read, ssh_packet_get_connection_in(ssh),
1308 			    &c, 1);
1309 			if (len != 1 && errno == EPIPE) {
1310 				verbose_f("Connection closed by remote host");
1311 				r = SSH_ERR_CONN_CLOSED;
1312 				goto out;
1313 			} else if (len != 1) {
1314 				oerrno = errno;
1315 				error_f("read: %.100s", strerror(errno));
1316 				r = SSH_ERR_SYSTEM_ERROR;
1317 				goto out;
1318 			}
1319 			if (c == '\r') {
1320 				expect_nl = 1;
1321 				continue;
1322 			}
1323 			if (c == '\n')
1324 				break;
1325 			if (c == '\0' || expect_nl) {
1326 				verbose_f("banner line contains invalid "
1327 				    "characters");
1328 				goto invalid;
1329 			}
1330 			if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
1331 				oerrno = errno;
1332 				error_fr(r, "sshbuf_put");
1333 				goto out;
1334 			}
1335 			if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
1336 				verbose_f("banner line too long");
1337 				goto invalid;
1338 			}
1339 		}
1340 		/* Is this an actual protocol banner? */
1341 		if (sshbuf_len(peer_version) > 4 &&
1342 		    memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
1343 			break;
1344 		/* If not, then just log the line and continue */
1345 		if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
1346 			error_f("sshbuf_dup_string failed");
1347 			r = SSH_ERR_ALLOC_FAIL;
1348 			goto out;
1349 		}
1350 		/* Do not accept lines before the SSH ident from a client */
1351 		if (ssh->kex->server) {
1352 			verbose_f("client sent invalid protocol identifier "
1353 			    "\"%.256s\"", cp);
1354 			free(cp);
1355 			goto invalid;
1356 		}
1357 		debug_f("banner line %zu: %s", n, cp);
1358 		free(cp);
1359 	}
1360 	peer_version_string = sshbuf_dup_string(peer_version);
1361 	if (peer_version_string == NULL)
1362 		fatal_f("sshbuf_dup_string failed");
1363 	/* XXX must be same size for sscanf */
1364 	if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
1365 		error_f("calloc failed");
1366 		r = SSH_ERR_ALLOC_FAIL;
1367 		goto out;
1368 	}
1369 
1370 	/*
1371 	 * Check that the versions match.  In future this might accept
1372 	 * several versions and set appropriate flags to handle them.
1373 	 */
1374 	if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
1375 	    &remote_major, &remote_minor, remote_version) != 3) {
1376 		error("Bad remote protocol version identification: '%.100s'",
1377 		    peer_version_string);
1378  invalid:
1379 		send_error(ssh, "Invalid SSH identification string.");
1380 		r = SSH_ERR_INVALID_FORMAT;
1381 		goto out;
1382 	}
1383 	debug("Remote protocol version %d.%d, remote software version %.100s",
1384 	    remote_major, remote_minor, remote_version);
1385 	compat_banner(ssh, remote_version);
1386 
1387 	mismatch = 0;
1388 	switch (remote_major) {
1389 	case 2:
1390 		break;
1391 	case 1:
1392 		if (remote_minor != 99)
1393 			mismatch = 1;
1394 		break;
1395 	default:
1396 		mismatch = 1;
1397 		break;
1398 	}
1399 	if (mismatch) {
1400 		error("Protocol major versions differ: %d vs. %d",
1401 		    PROTOCOL_MAJOR_2, remote_major);
1402 		send_error(ssh, "Protocol major versions differ.");
1403 		r = SSH_ERR_NO_PROTOCOL_VERSION;
1404 		goto out;
1405 	}
1406 
1407 	if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
1408 		logit("probed from %s port %d with %s.  Don't panic.",
1409 		    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1410 		    peer_version_string);
1411 		r = SSH_ERR_CONN_CLOSED; /* XXX */
1412 		goto out;
1413 	}
1414 	if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
1415 		logit("scanned from %s port %d with %s.  Don't panic.",
1416 		    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1417 		    peer_version_string);
1418 		r = SSH_ERR_CONN_CLOSED; /* XXX */
1419 		goto out;
1420 	}
1421 	/* success */
1422 	r = 0;
1423  out:
1424 	free(our_version_string);
1425 	free(peer_version_string);
1426 	free(remote_version);
1427 	if (r == SSH_ERR_SYSTEM_ERROR)
1428 		errno = oerrno;
1429 	return r;
1430 }
1431 
1432