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