Coverage Report

Created: 2025-12-14 06:24

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
176k
{
93
176k
  const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER };
94
176k
  const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
95
176k
  const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
96
176k
  u_int i;
97
176k
  char *cp;
98
99
176k
  if (prop == NULL)
100
0
    fatal_f("proposal missing");
101
102
  /* Append EXT_INFO signalling to KexAlgorithms */
103
176k
  if (kexalgos == NULL)
104
0
    kexalgos = defprop[PROPOSAL_KEX_ALGS];
105
176k
  if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
106
88.4k
      "ext-info-s,kex-strict-s-v00@openssh.com" :
107
176k
      "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
108
0
    fatal_f("kex_names_cat");
109
110
1.94M
  for (i = 0; i < PROPOSAL_MAX; i++) {
111
1.76M
    switch(i) {
112
176k
    case PROPOSAL_KEX_ALGS:
113
176k
      prop[i] = compat_kex_proposal(ssh, cp);
114
176k
      break;
115
176k
    case PROPOSAL_ENC_ALGS_CTOS:
116
353k
    case PROPOSAL_ENC_ALGS_STOC:
117
353k
      prop[i] = xstrdup(ciphers ? ciphers : defprop[i]);
118
353k
      break;
119
176k
    case PROPOSAL_MAC_ALGS_CTOS:
120
353k
    case PROPOSAL_MAC_ALGS_STOC:
121
353k
      prop[i]  = xstrdup(macs ? macs : defprop[i]);
122
353k
      break;
123
176k
    case PROPOSAL_COMP_ALGS_CTOS:
124
353k
    case PROPOSAL_COMP_ALGS_STOC:
125
353k
      prop[i] = xstrdup(comp ? comp : defprop[i]);
126
353k
      break;
127
176k
    case PROPOSAL_SERVER_HOST_KEY_ALGS:
128
176k
      prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]);
129
176k
      break;
130
353k
    default:
131
353k
      prop[i] = xstrdup(defprop[i]);
132
1.76M
    }
133
1.76M
  }
134
176k
  free(cp);
135
176k
}
136
137
void
138
kex_proposal_free_entries(char *prop[PROPOSAL_MAX])
139
177k
{
140
177k
  u_int i;
141
142
1.94M
  for (i = 0; i < PROPOSAL_MAX; i++)
143
1.77M
    free(prop[i]);
144
177k
}
145
146
/* put algorithm proposal into buffer */
147
int
148
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
149
263k
{
150
263k
  u_int i;
151
263k
  int r;
152
153
263k
  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.48M
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
160
4.22M
    if ((r = sshbuf_put_u8(b, 0)) != 0)
161
0
      return r;
162
4.22M
  }
163
2.90M
  for (i = 0; i < PROPOSAL_MAX; i++) {
164
2.63M
    if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
165
0
      return r;
166
2.63M
  }
167
263k
  if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
168
263k
      (r = sshbuf_put_u32(b, 0)) != 0)  /* uint32 reserved */
169
0
    return r;
170
263k
  return 0;
171
263k
}
172
173
/* parse buffer and return algorithm proposal */
174
int
175
kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
176
235k
{
177
235k
  struct sshbuf *b = NULL;
178
235k
  u_char v;
179
235k
  u_int i;
180
235k
  char **proposal = NULL;
181
235k
  int r;
182
183
235k
  *propp = NULL;
184
235k
  if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
185
0
    return SSH_ERR_ALLOC_FAIL;
186
235k
  if ((b = sshbuf_fromb(raw)) == NULL) {
187
0
    r = SSH_ERR_ALLOC_FAIL;
188
0
    goto out;
189
0
  }
190
235k
  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.58M
  for (i = 0; i < PROPOSAL_MAX; i++) {
196
2.34M
    if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
197
540
      error_fr(r, "parse proposal %u", i);
198
540
      goto out;
199
540
    }
200
2.34M
    debug2("%s: %s", proposal_names[i], proposal[i]);
201
2.34M
  }
202
  /* first kex follows / reserved */
203
234k
  if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
204
234k
      (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */
205
0
    error_fr(r, "parse");
206
0
    goto out;
207
0
  }
208
234k
  if (first_kex_follows != NULL)
209
73.6k
    *first_kex_follows = v;
210
234k
  debug2("first_kex_follows %d ", v);
211
234k
  debug2("reserved %u ", i);
212
234k
  r = 0;
213
234k
  *propp = proposal;
214
235k
 out:
215
235k
  if (r != 0 && proposal != NULL)
216
540
    kex_prop_free(proposal);
217
235k
  sshbuf_free(b);
218
235k
  return r;
219
234k
}
220
221
void
222
kex_prop_free(char **proposal)
223
235k
{
224
235k
  u_int i;
225
226
235k
  if (proposal == NULL)
227
540
    return;
228
2.58M
  for (i = 0; i < PROPOSAL_MAX; i++)
229
2.34M
    free(proposal[i]);
230
234k
  free(proposal);
231
234k
}
232
233
int
234
kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
235
1.79M
{
236
1.79M
  int r;
237
238
  /* If in strict mode, any unexpected message is an error */
239
1.79M
  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.79M
  error_f("type %u seq %u", type, seq);
244
1.79M
  if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
245
1.79M
      (r = sshpkt_put_u32(ssh, seq)) != 0 ||
246
1.79M
      (r = sshpkt_send(ssh)) != 0)
247
0
    return r;
248
1.79M
  return 0;
249
1.79M
}
250
251
static void
252
kex_reset_dispatch(struct ssh *ssh)
253
177k
{
254
177k
  ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
255
177k
      SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
256
177k
}
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
765
{
336
765
  int r;
337
765
  struct sshbuf *m = NULL;
338
339
765
  if ((ssh->kex->flags & KEX_INITIAL) == 0)
340
0
    return 0;
341
765
  if (!ssh->kex->ext_info_c && !ssh->kex->ext_info_s)
342
659
    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
765
{
393
765
  int r;
394
395
765
  kex_reset_dispatch(ssh);
396
765
  if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
397
765
      (r = sshpkt_send(ssh)) != 0)
398
0
    return r;
399
765
  debug("SSH2_MSG_NEWKEYS sent");
400
765
  ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
401
765
  if ((r = kex_maybe_send_ext_info(ssh)) != 0)
402
0
    return r;
403
765
  debug("expecting SSH2_MSG_NEWKEYS");
404
765
  return 0;
405
765
}
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
345
{
524
345
  struct kex *kex = ssh->kex;
525
345
  int r, initial = (kex->flags & KEX_INITIAL) != 0;
526
345
  char *cp, **prop;
527
528
345
  debug("SSH2_MSG_NEWKEYS received");
529
345
  if (kex->ext_info_c && initial)
530
0
    ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info);
531
345
  ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
532
345
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
533
345
  if ((r = sshpkt_get_end(ssh)) != 0)
534
3
    return r;
535
342
  if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
536
0
    return r;
537
342
  if (initial) {
538
    /* Remove initial KEX signalling from proposal for rekeying */
539
342
    if ((r = kex_buf2prop(kex->my, NULL, &prop)) != 0)
540
0
      return r;
541
342
    if ((cp = match_filter_denylist(prop[PROPOSAL_KEX_ALGS],
542
342
        kex->server ?
543
342
        "ext-info-s,kex-strict-s-v00@openssh.com" :
544
342
        "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
342
    free(prop[PROPOSAL_KEX_ALGS]);
549
342
    prop[PROPOSAL_KEX_ALGS] = cp;
550
342
    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
342
    kex_proposal_free_entries(prop);
558
342
    free(prop);
559
342
  }
560
342
  kex->done = 1;
561
342
  kex->flags &= ~KEX_INITIAL;
562
342
  sshbuf_reset(kex->peer);
563
342
  kex->flags &= ~KEX_INIT_SENT;
564
342
  return 0;
565
342
}
566
567
int
568
kex_send_kexinit(struct ssh *ssh)
569
86.6k
{
570
86.6k
  u_char *cookie;
571
86.6k
  struct kex *kex = ssh->kex;
572
86.6k
  int r;
573
574
86.6k
  if (kex == NULL) {
575
0
    error_f("no kex");
576
0
    return SSH_ERR_INTERNAL_ERROR;
577
0
  }
578
86.6k
  if (kex->flags & KEX_INIT_SENT)
579
0
    return 0;
580
86.6k
  kex->done = 0;
581
582
  /* generate a random cookie */
583
86.6k
  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
86.6k
  if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
589
0
    error_f("buffer error");
590
0
    return SSH_ERR_INTERNAL_ERROR;
591
0
  }
592
86.6k
  arc4random_buf(cookie, KEX_COOKIE_LEN);
593
594
86.6k
  if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
595
86.6k
      (r = sshpkt_putb(ssh, kex->my)) != 0 ||
596
86.6k
      (r = sshpkt_send(ssh)) != 0) {
597
0
    error_fr(r, "compose reply");
598
0
    return r;
599
0
  }
600
86.6k
  debug("SSH2_MSG_KEXINIT sent");
601
86.6k
  kex->flags |= KEX_INIT_SENT;
602
86.6k
  return 0;
603
86.6k
}
604
605
int
606
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
607
76.9k
{
608
76.9k
  struct kex *kex = ssh->kex;
609
76.9k
  const u_char *ptr;
610
76.9k
  u_int i;
611
76.9k
  size_t dlen;
612
76.9k
  int r;
613
614
76.9k
  debug("SSH2_MSG_KEXINIT received");
615
76.9k
  if (kex == NULL) {
616
0
    error_f("no kex");
617
0
    return SSH_ERR_INTERNAL_ERROR;
618
0
  }
619
76.9k
  free(kex->name);
620
76.9k
  kex->name = NULL;
621
76.9k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
622
76.9k
  ptr = sshpkt_ptr(ssh, &dlen);
623
76.9k
  if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
624
0
    return r;
625
626
  /* discard packet */
627
1.30M
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
628
1.22M
    if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
629
240
      error_fr(r, "discard cookie");
630
240
      return r;
631
240
    }
632
1.22M
  }
633
826k
  for (i = 0; i < PROPOSAL_MAX; i++) {
634
751k
    if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
635
1.87k
      error_fr(r, "discard proposal");
636
1.87k
      return r;
637
1.87k
    }
638
751k
  }
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
74.8k
  if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
650
74.7k
      (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
651
74.7k
      (r = sshpkt_get_end(ssh)) != 0)
652
630
      return r;
653
654
74.1k
  if (!(kex->flags & KEX_INIT_SENT))
655
0
    if ((r = kex_send_kexinit(ssh)) != 0)
656
0
      return r;
657
74.1k
  if ((r = kex_choose_conf(ssh, seq)) != 0)
658
61.2k
    return r;
659
660
12.9k
  if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
661
12.9k
    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.9k
}
666
667
struct kex *
668
kex_new(void)
669
176k
{
670
176k
  struct kex *kex;
671
672
176k
  if ((kex = calloc(1, sizeof(*kex))) == NULL ||
673
176k
      (kex->peer = sshbuf_new()) == NULL ||
674
176k
      (kex->my = sshbuf_new()) == NULL ||
675
176k
      (kex->client_version = sshbuf_new()) == NULL ||
676
176k
      (kex->server_version = sshbuf_new()) == NULL ||
677
176k
      (kex->session_id = sshbuf_new()) == NULL) {
678
0
    kex_free(kex);
679
0
    return NULL;
680
0
  }
681
176k
  return kex;
682
176k
}
683
684
void
685
kex_free_newkeys(struct newkeys *newkeys)
686
732k
{
687
732k
  if (newkeys == NULL)
688
706k
    return;
689
25.9k
  if (newkeys->enc.key) {
690
1.53k
    explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
691
1.53k
    free(newkeys->enc.key);
692
1.53k
    newkeys->enc.key = NULL;
693
1.53k
  }
694
25.9k
  if (newkeys->enc.iv) {
695
1.53k
    explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
696
1.53k
    free(newkeys->enc.iv);
697
1.53k
    newkeys->enc.iv = NULL;
698
1.53k
  }
699
25.9k
  free(newkeys->enc.name);
700
25.9k
  explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
701
25.9k
  free(newkeys->comp.name);
702
25.9k
  explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
703
25.9k
  mac_clear(&newkeys->mac);
704
25.9k
  if (newkeys->mac.key) {
705
1.53k
    explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
706
1.53k
    free(newkeys->mac.key);
707
1.53k
    newkeys->mac.key = NULL;
708
1.53k
  }
709
25.9k
  free(newkeys->mac.name);
710
25.9k
  explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
711
25.9k
  freezero(newkeys, sizeof(*newkeys));
712
25.9k
}
713
714
void
715
kex_free(struct kex *kex)
716
176k
{
717
176k
  u_int mode;
718
719
176k
  if (kex == NULL)
720
0
    return;
721
722
176k
#ifdef WITH_OPENSSL
723
176k
  DH_free(kex->dh);
724
176k
#ifdef OPENSSL_HAS_ECC
725
176k
  EC_KEY_free(kex->ec_client_key);
726
176k
#endif /* OPENSSL_HAS_ECC */
727
176k
#endif /* WITH_OPENSSL */
728
530k
  for (mode = 0; mode < MODE_MAX; mode++) {
729
353k
    kex_free_newkeys(kex->newkeys[mode]);
730
353k
    kex->newkeys[mode] = NULL;
731
353k
  }
732
176k
  sshbuf_free(kex->peer);
733
176k
  sshbuf_free(kex->my);
734
176k
  sshbuf_free(kex->client_version);
735
176k
  sshbuf_free(kex->server_version);
736
176k
  sshbuf_free(kex->client_pub);
737
176k
  sshbuf_free(kex->session_id);
738
176k
  sshbuf_free(kex->initial_sig);
739
176k
  sshkey_free(kex->initial_hostkey);
740
176k
  free(kex->failed_choice);
741
176k
  free(kex->hostkey_alg);
742
176k
  free(kex->name);
743
176k
  free(kex->server_sig_algs);
744
176k
  free(kex);
745
176k
}
746
747
int
748
kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
749
176k
{
750
176k
  int r;
751
752
176k
  if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
753
0
    return r;
754
176k
  ssh->kex->flags = KEX_INITIAL;
755
176k
  kex_reset_dispatch(ssh);
756
176k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
757
176k
  return 0;
758
176k
}
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.9k
{
797
25.9k
  char *name = match_list(client, server, NULL);
798
799
25.9k
  if (name == NULL)
800
9
    return SSH_ERR_NO_CIPHER_ALG_MATCH;
801
25.9k
  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.9k
  enc->name = name;
807
25.9k
  enc->enabled = 0;
808
25.9k
  enc->iv = NULL;
809
25.9k
  enc->iv_len = cipher_ivlen(enc->cipher);
810
25.9k
  enc->key = NULL;
811
25.9k
  enc->key_len = cipher_keylen(enc->cipher);
812
25.9k
  enc->block_size = cipher_blocksize(enc->cipher);
813
25.9k
  return 0;
814
25.9k
}
815
816
static int
817
choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
818
25.9k
{
819
25.9k
  char *name = match_list(client, server, NULL);
820
821
25.9k
  if (name == NULL)
822
15
    return SSH_ERR_NO_MAC_ALG_MATCH;
823
25.8k
  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.8k
  mac->name = name;
829
25.8k
  mac->key = NULL;
830
25.8k
  mac->enabled = 0;
831
25.8k
  return 0;
832
25.8k
}
833
834
static int
835
choose_comp(struct sshcomp *comp, char *client, char *server)
836
25.8k
{
837
25.8k
  char *name = match_list(client, server, NULL);
838
839
25.8k
  if (name == NULL)
840
20
    return SSH_ERR_NO_COMPRESS_ALG_MATCH;
841
25.8k
#ifdef WITH_ZLIB
842
25.8k
  if (strcmp(name, "zlib@openssh.com") == 0) {
843
2.23k
    comp->type = COMP_DELAYED;
844
2.23k
  } else
845
23.6k
#endif  /* WITH_ZLIB */
846
23.6k
  if (strcmp(name, "none") == 0) {
847
23.6k
    comp->type = COMP_NONE;
848
23.6k
  } 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.8k
  comp->name = name;
854
25.8k
  return 0;
855
25.8k
}
856
857
static int
858
choose_kex(struct kex *k, char *client, char *server)
859
73.6k
{
860
73.6k
  k->name = match_list(client, server, NULL);
861
862
73.6k
  debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
863
73.6k
  if (k->name == NULL)
864
52.2k
    return SSH_ERR_NO_KEX_ALG_MATCH;
865
21.4k
  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.3k
  k->kex_type = kex_type_from_name(k->name);
870
21.3k
  k->hash_alg = kex_hash_from_name(k->name);
871
21.3k
  k->ec_nid = kex_nid_from_name(k->name);
872
21.3k
  return 0;
873
21.4k
}
874
875
static int
876
choose_hostkeyalg(struct kex *k, char *client, char *server)
877
21.3k
{
878
21.3k
  free(k->hostkey_alg);
879
21.3k
  k->hostkey_alg = match_list(client, server, NULL);
880
881
21.3k
  debug("kex: host key algorithm: %s",
882
21.3k
      k->hostkey_alg ? k->hostkey_alg : "(no match)");
883
21.3k
  if (k->hostkey_alg == NULL)
884
8.33k
    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.08k
{
897
1.08k
  static int check[] = {
898
1.08k
    PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
899
1.08k
  };
900
1.08k
  int *idx;
901
1.08k
  char *p;
902
903
3.26k
  for (idx = &check[0]; *idx != -1; idx++) {
904
2.17k
    if ((p = strchr(my[*idx], ',')) != NULL)
905
1.08k
      *p = '\0';
906
2.17k
    if ((p = strchr(peer[*idx], ',')) != NULL)
907
3
      *p = '\0';
908
2.17k
    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.17k
  }
914
1.08k
  debug2("proposals match");
915
1.08k
  return (1);
916
1.08k
}
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.1k
{
927
74.1k
  struct kex *kex = ssh->kex;
928
74.1k
  struct newkeys *newkeys;
929
74.1k
  char **my = NULL, **peer = NULL;
930
74.1k
  char **cprop, **sprop;
931
74.1k
  int nenc, nmac, ncomp;
932
74.1k
  u_int mode, ctos, need, dh_need, authlen;
933
74.1k
  int r, first_kex_follows;
934
935
74.1k
  debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
936
74.1k
  if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
937
0
    goto out;
938
74.1k
  debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
939
74.1k
  if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
940
540
    goto out;
941
942
73.6k
  if (kex->server) {
943
36.5k
    cprop=peer;
944
36.5k
    sprop=my;
945
37.0k
  } else {
946
37.0k
    cprop=my;
947
37.0k
    sprop=peer;
948
37.0k
  }
949
950
  /* Check whether peer supports ext_info/kex_strict */
951
73.6k
  if ((kex->flags & KEX_INITIAL) != 0) {
952
73.6k
    if (kex->server) {
953
36.5k
      kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
954
36.5k
      kex->kex_strict = kexalgs_contains(peer,
955
36.5k
          "kex-strict-c-v00@openssh.com");
956
37.0k
    } else {
957
37.0k
      kex->ext_info_s = kexalgs_contains(peer, "ext-info-s");
958
37.0k
      kex->kex_strict = kexalgs_contains(peer,
959
37.0k
          "kex-strict-s-v00@openssh.com");
960
37.0k
    }
961
73.6k
    if (kex->kex_strict) {
962
8.86k
      debug3_f("will use strict KEX ordering");
963
8.86k
      if (seq != 0)
964
0
        ssh_packet_disconnect(ssh,
965
0
            "strict KEX violation: "
966
0
            "KEXINIT was not the first packet");
967
8.86k
    }
968
73.6k
  }
969
970
  /* Check whether client supports rsa-sha2 algorithms */
971
73.6k
  if (kex->server && (kex->flags & KEX_INITIAL)) {
972
36.5k
    if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
973
36.5k
        "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
974
15
      kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
975
36.5k
    if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
976
36.5k
        "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
977
15
      kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
978
36.5k
  }
979
980
  /* Algorithm Negotiation */
981
73.6k
  if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
982
73.6k
      sprop[PROPOSAL_KEX_ALGS])) != 0) {
983
52.3k
    kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
984
52.3k
    peer[PROPOSAL_KEX_ALGS] = NULL;
985
52.3k
    goto out;
986
52.3k
  }
987
21.3k
  if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
988
21.3k
      sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
989
8.33k
    kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
990
8.33k
    peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
991
8.33k
    goto out;
992
8.33k
  }
993
38.8k
  for (mode = 0; mode < MODE_MAX; mode++) {
994
25.9k
    if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
995
0
      r = SSH_ERR_ALLOC_FAIL;
996
0
      goto out;
997
0
    }
998
25.9k
    kex->newkeys[mode] = newkeys;
999
25.9k
    ctos = (!kex->server && mode == MODE_OUT) ||
1000
19.8k
        (kex->server && mode == MODE_IN);
1001
25.9k
    nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
1002
25.9k
    nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
1003
25.9k
    ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
1004
25.9k
    if ((r = choose_enc(&newkeys->enc, cprop[nenc],
1005
25.9k
        sprop[nenc])) != 0) {
1006
9
      kex->failed_choice = peer[nenc];
1007
9
      peer[nenc] = NULL;
1008
9
      goto out;
1009
9
    }
1010
25.9k
    authlen = cipher_authlen(newkeys->enc.cipher);
1011
    /* ignore mac for authenticated encryption */
1012
25.9k
    if (authlen == 0 &&
1013
25.9k
        (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
1014
25.9k
        sprop[nmac])) != 0) {
1015
15
      kex->failed_choice = peer[nmac];
1016
15
      peer[nmac] = NULL;
1017
15
      goto out;
1018
15
    }
1019
25.8k
    if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
1020
25.8k
        sprop[ncomp])) != 0) {
1021
20
      kex->failed_choice = peer[ncomp];
1022
20
      peer[ncomp] = NULL;
1023
20
      goto out;
1024
20
    }
1025
25.8k
    debug("kex: %s cipher: %s MAC: %s compression: %s",
1026
25.8k
        ctos ? "client->server" : "server->client",
1027
25.8k
        newkeys->enc.name,
1028
25.8k
        authlen == 0 ? newkeys->mac.name : "<implicit>",
1029
25.8k
        newkeys->comp.name);
1030
25.8k
  }
1031
12.9k
  need = dh_need = 0;
1032
38.7k
  for (mode = 0; mode < MODE_MAX; mode++) {
1033
25.8k
    newkeys = kex->newkeys[mode];
1034
25.8k
    need = MAXIMUM(need, newkeys->enc.key_len);
1035
25.8k
    need = MAXIMUM(need, newkeys->enc.block_size);
1036
25.8k
    need = MAXIMUM(need, newkeys->enc.iv_len);
1037
25.8k
    need = MAXIMUM(need, newkeys->mac.key_len);
1038
25.8k
    dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
1039
25.8k
    dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
1040
25.8k
    dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
1041
25.8k
    dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
1042
25.8k
  }
1043
  /* XXX need runden? */
1044
12.9k
  kex->we_need = need;
1045
12.9k
  kex->dh_need = dh_need;
1046
1047
  /* ignore the next message if the proposals do not match */
1048
12.9k
  if (first_kex_follows && !proposals_match(my, peer))
1049
0
    ssh->dispatch_skip_packets = 1;
1050
12.9k
  r = 0;
1051
74.1k
 out:
1052
74.1k
  kex_prop_free(my);
1053
74.1k
  kex_prop_free(peer);
1054
74.1k
  return r;
1055
12.9k
}
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.59k
{
1061
4.59k
  struct kex *kex = ssh->kex;
1062
4.59k
  struct ssh_digest_ctx *hashctx = NULL;
1063
4.59k
  char c = id;
1064
4.59k
  u_int have;
1065
4.59k
  size_t mdsz;
1066
4.59k
  u_char *digest;
1067
4.59k
  int r;
1068
1069
4.59k
  if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
1070
0
    return SSH_ERR_INVALID_ARGUMENT;
1071
4.59k
  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.59k
  if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1078
4.59k
      ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1079
4.59k
      ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1080
4.59k
      ssh_digest_update(hashctx, &c, 1) != 0 ||
1081
4.59k
      ssh_digest_update_buffer(hashctx, kex->session_id) != 0 ||
1082
4.59k
      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.59k
  ssh_digest_free(hashctx);
1088
4.59k
  hashctx = NULL;
1089
1090
  /*
1091
   * expand key:
1092
   * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
1093
   * Key = K1 || K2 || ... || Kn
1094
   */
1095
6.66k
  for (have = mdsz; need > have; have += mdsz) {
1096
2.07k
    if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1097
2.07k
        ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1098
2.07k
        ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1099
2.07k
        ssh_digest_update(hashctx, digest, have) != 0 ||
1100
2.07k
        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.07k
    ssh_digest_free(hashctx);
1106
2.07k
    hashctx = NULL;
1107
2.07k
  }
1108
#ifdef DEBUG_KEX
1109
  fprintf(stderr, "key '%c'== ", c);
1110
  dump_digest("key", digest, need);
1111
#endif
1112
4.59k
  *keyp = digest;
1113
4.59k
  digest = NULL;
1114
4.59k
  r = 0;
1115
4.59k
 out:
1116
4.59k
  free(digest);
1117
4.59k
  ssh_digest_free(hashctx);
1118
4.59k
  return r;
1119
4.59k
}
1120
1121
5.35k
#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
765
{
1126
765
  struct kex *kex = ssh->kex;
1127
765
  u_char *keys[NKEYS];
1128
765
  u_int i, j, mode, ctos;
1129
765
  int r;
1130
1131
  /* save initial hash as session id */
1132
765
  if ((kex->flags & KEX_INITIAL) != 0) {
1133
765
    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
765
    if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0)
1138
0
      return r;
1139
765
  } 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.35k
  for (i = 0; i < NKEYS; i++) {
1144
4.59k
    if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
1145
4.59k
        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.59k
  }
1151
2.29k
  for (mode = 0; mode < MODE_MAX; mode++) {
1152
1.53k
    ctos = (!kex->server && mode == MODE_OUT) ||
1153
1.53k
        (kex->server && mode == MODE_IN);
1154
1.53k
    kex->newkeys[mode]->enc.iv  = keys[ctos ? 0 : 1];
1155
1.53k
    kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
1156
1.53k
    kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
1157
1.53k
  }
1158
765
  return 0;
1159
765
}
1160
1161
int
1162
kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
1163
824
{
1164
824
  struct kex *kex = ssh->kex;
1165
1166
824
  *pubp = NULL;
1167
824
  *prvp = NULL;
1168
824
  if (kex->load_host_public_key == NULL ||
1169
824
      kex->load_host_private_key == NULL) {
1170
0
    error_f("missing hostkey loader");
1171
0
    return SSH_ERR_INVALID_ARGUMENT;
1172
0
  }
1173
824
  *pubp = kex->load_host_public_key(kex->hostkey_type,
1174
824
      kex->hostkey_nid, ssh);
1175
824
  *prvp = kex->load_host_private_key(kex->hostkey_type,
1176
824
      kex->hostkey_nid, ssh);
1177
824
  if (*pubp == NULL)
1178
0
    return SSH_ERR_NO_HOSTKEY_LOADED;
1179
824
  return 0;
1180
824
}
1181
1182
int
1183
kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
1184
583
{
1185
583
  struct kex *kex = ssh->kex;
1186
1187
583
  if (kex->verify_host_key == NULL) {
1188
0
    error_f("missing hostkey verifier");
1189
0
    return SSH_ERR_INVALID_ARGUMENT;
1190
0
  }
1191
583
  if (server_host_key->type != kex->hostkey_type ||
1192
579
      (kex->hostkey_type == KEY_ECDSA &&
1193
112
      server_host_key->ecdsa_nid != kex->hostkey_nid))
1194
4
    return SSH_ERR_KEY_TYPE_MISMATCH;
1195
579
  if (kex->verify_host_key(server_host_key, ssh) == -1)
1196
98
    return  SSH_ERR_SIGNATURE_INVALID;
1197
481
  return 0;
1198
579
}
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