Coverage Report

Created: 2026-10-23 07:09

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