Coverage Report

Created: 2025-09-05 06:12

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