Coverage Report

Created: 2026-10-17 06:40

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