Coverage Report

Created: 2025-12-14 06:20

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