Coverage Report

Created: 2025-08-26 06:33

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