Coverage Report

Created: 2025-11-24 06:28

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