Coverage Report

Created: 2025-10-10 06:39

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