Coverage Report

Created: 2026-02-26 06:55

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