Coverage Report

Created: 2025-10-13 06:07

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.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
54.6k
{
96
54.6k
  const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER };
97
54.6k
  const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
98
54.6k
  const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
99
54.6k
  u_int i;
100
54.6k
  char *cp;
101
102
54.6k
  if (prop == NULL)
103
0
    fatal_f("proposal missing");
104
105
  /* Append EXT_INFO signalling to KexAlgorithms */
106
54.6k
  if (kexalgos == NULL)
107
0
    kexalgos = defprop[PROPOSAL_KEX_ALGS];
108
54.6k
  if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
109
27.3k
      "ext-info-s,kex-strict-s-v00@openssh.com" :
110
54.6k
      "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
111
0
    fatal_f("kex_names_cat");
112
113
601k
  for (i = 0; i < PROPOSAL_MAX; i++) {
114
546k
    switch(i) {
115
54.6k
    case PROPOSAL_KEX_ALGS:
116
54.6k
      prop[i] = compat_kex_proposal(ssh, cp);
117
54.6k
      break;
118
54.6k
    case PROPOSAL_ENC_ALGS_CTOS:
119
109k
    case PROPOSAL_ENC_ALGS_STOC:
120
109k
      prop[i] = xstrdup(ciphers ? ciphers : defprop[i]);
121
109k
      break;
122
54.6k
    case PROPOSAL_MAC_ALGS_CTOS:
123
109k
    case PROPOSAL_MAC_ALGS_STOC:
124
109k
      prop[i]  = xstrdup(macs ? macs : defprop[i]);
125
109k
      break;
126
54.6k
    case PROPOSAL_COMP_ALGS_CTOS:
127
109k
    case PROPOSAL_COMP_ALGS_STOC:
128
109k
      prop[i] = xstrdup(comp ? comp : defprop[i]);
129
109k
      break;
130
54.6k
    case PROPOSAL_SERVER_HOST_KEY_ALGS:
131
54.6k
      prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]);
132
54.6k
      break;
133
109k
    default:
134
109k
      prop[i] = xstrdup(defprop[i]);
135
546k
    }
136
546k
  }
137
54.6k
  free(cp);
138
54.6k
}
139
140
void
141
kex_proposal_free_entries(char *prop[PROPOSAL_MAX])
142
54.6k
{
143
54.6k
  u_int i;
144
145
601k
  for (i = 0; i < PROPOSAL_MAX; i++)
146
546k
    free(prop[i]);
147
54.6k
}
148
149
/* put algorithm proposal into buffer */
150
int
151
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
152
69.7k
{
153
69.7k
  u_int i;
154
69.7k
  int r;
155
156
69.7k
  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.18M
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
163
1.11M
    if ((r = sshbuf_put_u8(b, 0)) != 0)
164
0
      return r;
165
1.11M
  }
166
767k
  for (i = 0; i < PROPOSAL_MAX; i++) {
167
697k
    if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
168
0
      return r;
169
697k
  }
170
69.7k
  if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
171
69.7k
      (r = sshbuf_put_u32(b, 0)) != 0)  /* uint32 reserved */
172
0
    return r;
173
69.7k
  return 0;
174
69.7k
}
175
176
/* parse buffer and return algorithm proposal */
177
int
178
kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
179
19.7k
{
180
19.7k
  struct sshbuf *b = NULL;
181
19.7k
  u_char v;
182
19.7k
  u_int i;
183
19.7k
  char **proposal = NULL;
184
19.7k
  int r;
185
186
19.7k
  *propp = NULL;
187
19.7k
  if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
188
0
    return SSH_ERR_ALLOC_FAIL;
189
19.7k
  if ((b = sshbuf_fromb(raw)) == NULL) {
190
0
    r = SSH_ERR_ALLOC_FAIL;
191
0
    goto out;
192
0
  }
193
19.7k
  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
216k
  for (i = 0; i < PROPOSAL_MAX; i++) {
199
196k
    if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
200
210
      error_fr(r, "parse proposal %u", i);
201
210
      goto out;
202
210
    }
203
196k
    debug2("%s: %s", proposal_names[i], proposal[i]);
204
196k
  }
205
  /* first kex follows / reserved */
206
19.5k
  if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
207
19.5k
      (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */
208
0
    error_fr(r, "parse");
209
0
    goto out;
210
0
  }
211
19.5k
  if (first_kex_follows != NULL)
212
2.11k
    *first_kex_follows = v;
213
19.5k
  debug2("first_kex_follows %d ", v);
214
19.5k
  debug2("reserved %u ", i);
215
19.5k
  r = 0;
216
19.5k
  *propp = proposal;
217
19.7k
 out:
218
19.7k
  if (r != 0 && proposal != NULL)
219
210
    kex_prop_free(proposal);
220
19.7k
  sshbuf_free(b);
221
19.7k
  return r;
222
19.5k
}
223
224
void
225
kex_prop_free(char **proposal)
226
19.9k
{
227
19.9k
  u_int i;
228
229
19.9k
  if (proposal == NULL)
230
210
    return;
231
217k
  for (i = 0; i < PROPOSAL_MAX; i++)
232
197k
    free(proposal[i]);
233
19.7k
  free(proposal);
234
19.7k
}
235
236
int
237
kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
238
877k
{
239
877k
  int r;
240
241
  /* If in strict mode, any unexpected message is an error */
242
877k
  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
877k
  error_f("type %u seq %u", type, seq);
247
877k
  if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
248
877k
      (r = sshpkt_put_u32(ssh, seq)) != 0 ||
249
877k
      (r = sshpkt_send(ssh)) != 0)
250
0
    return r;
251
877k
  return 0;
252
877k
}
253
254
static void
255
kex_reset_dispatch(struct ssh *ssh)
256
54.6k
{
257
54.6k
  ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
258
54.6k
      SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
259
54.6k
}
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.1k
{
575
15.1k
  u_char *cookie;
576
15.1k
  struct kex *kex = ssh->kex;
577
15.1k
  int r;
578
579
15.1k
  if (kex == NULL) {
580
0
    error_f("no kex");
581
0
    return SSH_ERR_INTERNAL_ERROR;
582
0
  }
583
15.1k
  if (kex->flags & KEX_INIT_SENT)
584
0
    return 0;
585
15.1k
  kex->done = 0;
586
587
  /* generate a random cookie */
588
15.1k
  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.1k
  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.1k
  arc4random_buf(cookie, KEX_COOKIE_LEN);
598
599
15.1k
  if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
600
15.1k
      (r = sshpkt_putb(ssh, kex->my)) != 0 ||
601
15.1k
      (r = sshpkt_send(ssh)) != 0) {
602
0
    error_fr(r, "compose reply");
603
0
    return r;
604
0
  }
605
15.1k
  debug("SSH2_MSG_KEXINIT sent");
606
15.1k
  kex->flags |= KEX_INIT_SENT;
607
15.1k
  return 0;
608
15.1k
}
609
610
int
611
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
612
6.76k
{
613
6.76k
  struct kex *kex = ssh->kex;
614
6.76k
  const u_char *ptr;
615
6.76k
  u_int i;
616
6.76k
  size_t dlen;
617
6.76k
  int r;
618
619
6.76k
  debug("SSH2_MSG_KEXINIT received");
620
6.76k
  if (kex == NULL) {
621
0
    error_f("no kex");
622
0
    return SSH_ERR_INTERNAL_ERROR;
623
0
  }
624
6.76k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
625
6.76k
  ptr = sshpkt_ptr(ssh, &dlen);
626
6.76k
  if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
627
0
    return r;
628
629
  /* discard packet */
630
110k
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
631
104k
    if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
632
480
      error_fr(r, "discard cookie");
633
480
      return r;
634
480
    }
635
104k
  }
636
39.5k
  for (i = 0; i < PROPOSAL_MAX; i++) {
637
36.7k
    if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
638
3.48k
      error_fr(r, "discard proposal");
639
3.48k
      return r;
640
3.48k
    }
641
36.7k
  }
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.80k
  if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
653
2.76k
      (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
654
2.68k
      (r = sshpkt_get_end(ssh)) != 0)
655
480
      return r;
656
657
2.32k
  if (!(kex->flags & KEX_INIT_SENT))
658
0
    if ((r = kex_send_kexinit(ssh)) != 0)
659
0
      return r;
660
2.32k
  if ((r = kex_choose_conf(ssh, seq)) != 0)
661
2.32k
    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
54.6k
{
673
54.6k
  struct kex *kex;
674
675
54.6k
  if ((kex = calloc(1, sizeof(*kex))) == NULL ||
676
54.6k
      (kex->peer = sshbuf_new()) == NULL ||
677
54.6k
      (kex->my = sshbuf_new()) == NULL ||
678
54.6k
      (kex->client_version = sshbuf_new()) == NULL ||
679
54.6k
      (kex->server_version = sshbuf_new()) == NULL ||
680
54.6k
      (kex->session_id = sshbuf_new()) == NULL) {
681
0
    kex_free(kex);
682
0
    return NULL;
683
0
  }
684
54.6k
  return kex;
685
54.6k
}
686
687
void
688
kex_free_newkeys(struct newkeys *newkeys)
689
218k
{
690
218k
  if (newkeys == NULL)
691
218k
    return;
692
96
  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
96
  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
96
  free(newkeys->enc.name);
703
96
  explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
704
96
  free(newkeys->comp.name);
705
96
  explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
706
96
  mac_clear(&newkeys->mac);
707
96
  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
96
  free(newkeys->mac.name);
713
96
  explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
714
96
  freezero(newkeys, sizeof(*newkeys));
715
96
}
716
717
void
718
kex_free(struct kex *kex)
719
54.6k
{
720
54.6k
  u_int mode;
721
722
54.6k
  if (kex == NULL)
723
0
    return;
724
725
54.6k
#ifdef WITH_OPENSSL
726
54.6k
  DH_free(kex->dh);
727
54.6k
#ifdef OPENSSL_HAS_ECC
728
54.6k
  EC_KEY_free(kex->ec_client_key);
729
54.6k
#endif /* OPENSSL_HAS_ECC */
730
54.6k
#endif /* WITH_OPENSSL */
731
163k
  for (mode = 0; mode < MODE_MAX; mode++) {
732
109k
    kex_free_newkeys(kex->newkeys[mode]);
733
109k
    kex->newkeys[mode] = NULL;
734
109k
  }
735
54.6k
  sshbuf_free(kex->peer);
736
54.6k
  sshbuf_free(kex->my);
737
54.6k
  sshbuf_free(kex->client_version);
738
54.6k
  sshbuf_free(kex->server_version);
739
54.6k
  sshbuf_free(kex->client_pub);
740
54.6k
  sshbuf_free(kex->session_id);
741
54.6k
  sshbuf_free(kex->initial_sig);
742
54.6k
  sshkey_free(kex->initial_hostkey);
743
54.6k
  free(kex->failed_choice);
744
54.6k
  free(kex->hostkey_alg);
745
54.6k
  free(kex->name);
746
54.6k
  free(kex);
747
54.6k
}
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
109k
{
757
109k
  char * adj = xstrdup(orig);
758
109k
  char * match;
759
109k
  u_int next;
760
761
109k
  const char * ccpstr = "chacha20-poly1305@openssh.com";
762
109k
  const char * ccpmtstr = "chacha20-poly1305-mt@hpnssh.org";
763
764
109k
  match = match_list(ccpmtstr, orig, &next);
765
109k
  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
109k
  return adj;
791
109k
}
792
793
int
794
kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
795
54.6k
{
796
54.6k
  int r = 0;
797
798
54.6k
#ifdef WITH_OPENSSL
799
54.6k
  char * orig_ctos = proposal[PROPOSAL_ENC_ALGS_CTOS];
800
54.6k
  char * orig_stoc = proposal[PROPOSAL_ENC_ALGS_STOC];
801
54.6k
  proposal[PROPOSAL_ENC_ALGS_CTOS] =
802
54.6k
      patch_list(proposal[PROPOSAL_ENC_ALGS_CTOS]);
803
54.6k
  proposal[PROPOSAL_ENC_ALGS_STOC] =
804
54.6k
      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
54.6k
#endif
812
813
54.6k
  if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
814
0
    goto restoreProposal;
815
54.6k
  ssh->kex->flags = KEX_INITIAL;
816
54.6k
  kex_reset_dispatch(ssh);
817
54.6k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
818
54.6k
 restoreProposal:
819
54.6k
#ifdef WITH_OPENSSL
820
54.6k
  free(proposal[PROPOSAL_ENC_ALGS_CTOS]);
821
54.6k
  free(proposal[PROPOSAL_ENC_ALGS_STOC]);
822
54.6k
  proposal[PROPOSAL_ENC_ALGS_CTOS] = orig_ctos;
823
54.6k
  proposal[PROPOSAL_ENC_ALGS_STOC] = orig_stoc;
824
54.6k
#endif
825
54.6k
  return r;
826
54.6k
}
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
96
{
865
96
  char *name = match_list(client, server, NULL);
866
867
96
  if (name == NULL)
868
17
    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.11k
{
928
2.11k
  k->name = match_list(client, server, NULL);
929
930
2.11k
  debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
931
2.11k
  if (k->name == NULL)
932
1.77k
    return SSH_ERR_NO_KEX_ALG_MATCH;
933
345
  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
330
  k->kex_type = kex_type_from_name(k->name);
938
330
  k->hash_alg = kex_hash_from_name(k->name);
939
330
  k->ec_nid = kex_nid_from_name(k->name);
940
330
  return 0;
941
345
}
942
943
static int
944
choose_hostkeyalg(struct kex *k, char *client, char *server)
945
330
{
946
330
  free(k->hostkey_alg);
947
330
  k->hostkey_alg = match_list(client, server, NULL);
948
949
330
  debug("kex: host key algorithm: %s",
950
330
      k->hostkey_alg ? k->hostkey_alg : "(no match)");
951
330
  if (k->hostkey_alg == NULL)
952
234
    return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
953
96
  k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
954
96
  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
96
  k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
959
96
  return 0;
960
96
}
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.23k
{
989
4.23k
  return kex_has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
990
4.23k
}
991
992
static int
993
kex_choose_conf(struct ssh *ssh, uint32_t seq)
994
2.32k
{
995
2.32k
  struct kex *kex = ssh->kex;
996
2.32k
  struct newkeys *newkeys;
997
2.32k
  char **my = NULL, **peer = NULL;
998
2.32k
  char **cprop, **sprop;
999
2.32k
  int nenc, nmac, ncomp;
1000
2.32k
  u_int mode, ctos, need, dh_need, authlen;
1001
2.32k
  int r, first_kex_follows;
1002
2.32k
  int auth_flag = 0;
1003
2.32k
  int log_flag = 0;
1004
1005
2.32k
  auth_flag = packet_authentication_state(ssh);
1006
2.32k
  debug("AUTH STATE IS %d", auth_flag);
1007
1008
2.32k
  debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
1009
2.32k
  if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
1010
0
    goto out;
1011
2.32k
  debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
1012
2.32k
  if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
1013
210
    goto out;
1014
1015
2.11k
  if (kex->server) {
1016
930
    cprop=peer;
1017
930
    sprop=my;
1018
1.18k
  } else {
1019
1.18k
    cprop=my;
1020
1.18k
    sprop=peer;
1021
1.18k
  }
1022
1023
  /* Check whether peer supports ext_info/kex_strict */
1024
2.11k
  if ((kex->flags & KEX_INITIAL) != 0) {
1025
2.11k
    if (kex->server) {
1026
930
      kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
1027
930
      kex->kex_strict = kexalgs_contains(peer,
1028
930
          "kex-strict-c-v00@openssh.com");
1029
1.18k
    } else {
1030
1.18k
      kex->ext_info_s = kexalgs_contains(peer, "ext-info-s");
1031
1.18k
      kex->kex_strict = kexalgs_contains(peer,
1032
1.18k
          "kex-strict-s-v00@openssh.com");
1033
1.18k
    }
1034
2.11k
    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.11k
  }
1042
1043
  /* Check whether client supports rsa-sha2 algorithms */
1044
2.11k
  if (kex->server && (kex->flags & KEX_INITIAL)) {
1045
930
    if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
1046
930
        "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
1047
0
      kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
1048
930
    if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
1049
930
        "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
1050
0
      kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
1051
930
  }
1052
1053
  /* Algorithm Negotiation */
1054
2.11k
  if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
1055
2.11k
      sprop[PROPOSAL_KEX_ALGS])) != 0) {
1056
1.78k
    kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
1057
1.78k
    peer[PROPOSAL_KEX_ALGS] = NULL;
1058
1.78k
    goto out;
1059
1.78k
  }
1060
330
  if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
1061
330
      sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
1062
234
    kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
1063
234
    peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
1064
234
    goto out;
1065
234
  }
1066
96
  for (mode = 0; mode < MODE_MAX; mode++) {
1067
96
    if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
1068
0
      r = SSH_ERR_ALLOC_FAIL;
1069
0
      goto out;
1070
0
    }
1071
96
    kex->newkeys[mode] = newkeys;
1072
96
    ctos = (!kex->server && mode == MODE_OUT) ||
1073
96
        (kex->server && mode == MODE_IN);
1074
96
    nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
1075
96
    nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
1076
96
    ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
1077
96
    if ((r = choose_enc(&newkeys->enc, cprop[nenc],
1078
96
        sprop[nenc])) != 0) {
1079
17
      kex->failed_choice = peer[nenc];
1080
17
      peer[nenc] = NULL;
1081
17
      goto out;
1082
17
    }
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.32k
 out:
1182
2.32k
  kex_prop_free(my);
1183
2.32k
  kex_prop_free(peer);
1184
2.32k
  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
}