Coverage Report

Created: 2026-01-06 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libssh/src/kex.c
Line
Count
Source
1
/*
2
 * kex.c - key exchange
3
 *
4
 * This file is part of the SSH Library
5
 *
6
 * Copyright (c) 2003-2008 by Aris Adamantiadis
7
 *
8
 * The SSH Library is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or (at your
11
 * option) any later version.
12
 *
13
 * The SSH Library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16
 * License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with the SSH Library; see the file COPYING.  If not, write to
20
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21
 * MA 02111-1307, USA.
22
 */
23
24
#include "config.h"
25
26
#include <string.h>
27
#include <stdlib.h>
28
#include <stdio.h>
29
#include <stdbool.h>
30
31
#include "libssh/libssh.h"
32
#include "libssh/priv.h"
33
#include "libssh/buffer.h"
34
#include "libssh/dh.h"
35
#ifdef WITH_GEX
36
#include "libssh/dh-gex.h"
37
#endif /* WITH_GEX */
38
#include "libssh/kex.h"
39
#include "libssh/session.h"
40
#include "libssh/ssh2.h"
41
#include "libssh/string.h"
42
#include "libssh/curve25519.h"
43
#include "libssh/sntrup761.h"
44
#ifdef HAVE_MLKEM
45
#include "libssh/hybrid_mlkem.h"
46
#endif
47
#include "libssh/kex-gss.h"
48
#include "libssh/knownhosts.h"
49
#include "libssh/misc.h"
50
#include "libssh/pki.h"
51
#include "libssh/bignum.h"
52
#include "libssh/token.h"
53
#include "libssh/gssapi.h"
54
55
#ifdef HAVE_BLOWFISH
56
# define BLOWFISH ",blowfish-cbc"
57
#else
58
# define BLOWFISH ""
59
#endif
60
61
#ifdef HAVE_LIBGCRYPT
62
# define AES "aes256-gcm@openssh.com,aes128-gcm@openssh.com," \
63
             "aes256-ctr,aes192-ctr,aes128-ctr"
64
# define AES_CBC ",aes256-cbc,aes192-cbc,aes128-cbc"
65
# define DES_SUPPORTED ",3des-cbc"
66
67
#elif defined(HAVE_LIBMBEDCRYPTO)
68
# ifdef MBEDTLS_GCM_C
69
#  define GCM "aes256-gcm@openssh.com,aes128-gcm@openssh.com,"
70
# else
71
#  define GCM ""
72
# endif /* MBEDTLS_GCM_C */
73
# define AES GCM "aes256-ctr,aes192-ctr,aes128-ctr"
74
# define AES_CBC ",aes256-cbc,aes192-cbc,aes128-cbc"
75
# define DES_SUPPORTED ",3des-cbc"
76
77
#elif defined(HAVE_LIBCRYPTO)
78
# ifdef HAVE_OPENSSL_AES_H
79
#  define GCM "aes256-gcm@openssh.com,aes128-gcm@openssh.com,"
80
#  define AES GCM "aes256-ctr,aes192-ctr,aes128-ctr"
81
#  define AES_CBC ",aes256-cbc,aes192-cbc,aes128-cbc"
82
# else /* HAVE_OPENSSL_AES_H */
83
#  define AES ""
84
#  define AES_CBC ""
85
# endif /* HAVE_OPENSSL_AES_H */
86
87
# define DES_SUPPORTED ",3des-cbc"
88
#endif /* HAVE_LIBCRYPTO */
89
90
#ifdef WITH_ZLIB
91
#define ZLIB "none,zlib@openssh.com,zlib"
92
#define ZLIB_DEFAULT "none,zlib@openssh.com"
93
#else
94
#define ZLIB "none"
95
#define ZLIB_DEFAULT "none"
96
#endif /* WITH_ZLIB */
97
98
#ifdef HAVE_CURVE25519
99
#define CURVE25519 "curve25519-sha256,curve25519-sha256@libssh.org,"
100
#else
101
#define CURVE25519 ""
102
#endif /* HAVE_CURVE25519 */
103
104
#ifdef HAVE_SNTRUP761
105
#define SNTRUP761X25519 "sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,"
106
#else
107
#define SNTRUP761X25519 ""
108
#endif /* HAVE_SNTRUP761 */
109
110
#ifdef HAVE_MLKEM
111
#define HYBRID_MLKEM "mlkem768x25519-sha256," \
112
                     "mlkem768nistp256-sha256," \
113
                     "mlkem1024nistp384-sha384,"
114
#else
115
#define HYBRID_MLKEM ""
116
#endif /* HAVE_MLKEM */
117
118
#ifdef HAVE_ECC
119
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
120
#define EC_HOSTKEYS "ecdsa-sha2-nistp521," \
121
                    "ecdsa-sha2-nistp384," \
122
                    "ecdsa-sha2-nistp256,"
123
#define EC_SK_HOSTKEYS "sk-ecdsa-sha2-nistp256@openssh.com,"
124
#define EC_FIPS_PUBLIC_KEY_ALGOS "ecdsa-sha2-nistp521-cert-v01@openssh.com," \
125
                                 "ecdsa-sha2-nistp384-cert-v01@openssh.com," \
126
                                 "ecdsa-sha2-nistp256-cert-v01@openssh.com,"
127
#define EC_PUBLIC_KEY_ALGORITHMS EC_FIPS_PUBLIC_KEY_ALGOS \
128
                                 "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,"
129
#else
130
#define ECDH ""
131
#define EC_HOSTKEYS ""
132
#define EC_SK_HOSTKEYS ""
133
#define EC_FIPS_PUBLIC_KEY_ALGOS ""
134
#define EC_PUBLIC_KEY_ALGORITHMS ""
135
#endif /* HAVE_ECC */
136
137
#ifdef WITH_INSECURE_NONE
138
#define NONE ",none"
139
#else
140
#define NONE
141
#endif /* WITH_INSECURE_NONE */
142
143
0
#define HOSTKEYS "ssh-ed25519," \
144
0
                 EC_HOSTKEYS \
145
0
                 "sk-ssh-ed25519@openssh.com," \
146
0
                 EC_SK_HOSTKEYS \
147
0
                 "rsa-sha2-512," \
148
0
                 "rsa-sha2-256," \
149
0
                 "ssh-rsa"
150
#define DEFAULT_HOSTKEYS "ssh-ed25519," \
151
                         EC_HOSTKEYS \
152
                         "sk-ssh-ed25519@openssh.com," \
153
                         EC_SK_HOSTKEYS \
154
                         "rsa-sha2-512," \
155
                         "rsa-sha2-256"
156
157
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519-cert-v01@openssh.com," \
158
                              "sk-ssh-ed25519-cert-v01@openssh.com," \
159
                              EC_PUBLIC_KEY_ALGORITHMS \
160
                              "rsa-sha2-512-cert-v01@openssh.com," \
161
                              "rsa-sha2-256-cert-v01@openssh.com," \
162
                              "ssh-rsa-cert-v01@openssh.com," \
163
                              HOSTKEYS
164
#define DEFAULT_PUBLIC_KEY_ALGORITHMS "ssh-ed25519-cert-v01@openssh.com," \
165
                                      EC_PUBLIC_KEY_ALGORITHMS \
166
                                      "rsa-sha2-512-cert-v01@openssh.com," \
167
                                      "rsa-sha2-256-cert-v01@openssh.com," \
168
                                      DEFAULT_HOSTKEYS
169
170
#ifdef WITH_GEX
171
#define GEX_SHA256 "diffie-hellman-group-exchange-sha256,"
172
#define GEX_SHA1 "diffie-hellman-group-exchange-sha1,"
173
#else
174
#define GEX_SHA256
175
#define GEX_SHA1
176
#endif /* WITH_GEX */
177
178
#define CHACHA20 "chacha20-poly1305@openssh.com,"
179
180
#define DEFAULT_KEY_EXCHANGE \
181
    HYBRID_MLKEM \
182
    SNTRUP761X25519 \
183
    CURVE25519 \
184
    ECDH \
185
    "diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
186
    GEX_SHA256 \
187
    "diffie-hellman-group14-sha256" \
188
189
#define KEY_EXCHANGE_SUPPORTED \
190
    GEX_SHA1 \
191
    DEFAULT_KEY_EXCHANGE \
192
    ",diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
193
194
/* RFC 8308 */
195
0
#define KEX_EXTENSION_CLIENT "ext-info-c"
196
/* Strict kex mitigation against CVE-2023-48795 */
197
0
#define KEX_STRICT_CLIENT "kex-strict-c-v00@openssh.com"
198
0
#define KEX_STRICT_SERVER "kex-strict-s-v00@openssh.com"
199
200
/* Allowed algorithms in FIPS mode */
201
#define FIPS_ALLOWED_CIPHERS "aes256-gcm@openssh.com,"\
202
                             "aes256-ctr,"\
203
                             "aes256-cbc,"\
204
                             "aes128-gcm@openssh.com,"\
205
                             "aes128-ctr,"\
206
                             "aes128-cbc"
207
208
#define FIPS_ALLOWED_HOSTKEYS EC_HOSTKEYS \
209
                              "rsa-sha2-512," \
210
                              "rsa-sha2-256"
211
212
#define FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS EC_FIPS_PUBLIC_KEY_ALGOS \
213
                                           "rsa-sha2-512-cert-v01@openssh.com," \
214
                                           "rsa-sha2-256-cert-v01@openssh.com," \
215
                                           FIPS_ALLOWED_HOSTKEYS
216
217
#define FIPS_ALLOWED_KEX "ecdh-sha2-nistp256,"\
218
                         "ecdh-sha2-nistp384,"\
219
                         "ecdh-sha2-nistp521,"\
220
                         "diffie-hellman-group-exchange-sha256,"\
221
                         "diffie-hellman-group14-sha256,"\
222
                         "diffie-hellman-group16-sha512,"\
223
                         "diffie-hellman-group18-sha512"
224
225
#define FIPS_ALLOWED_MACS "hmac-sha2-256-etm@openssh.com,"\
226
                          "hmac-sha1-etm@openssh.com,"\
227
                          "hmac-sha2-512-etm@openssh.com,"\
228
                          "hmac-sha2-256,"\
229
                          "hmac-sha1,"\
230
                          "hmac-sha2-512"
231
232
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
233
static const char *fips_methods[] = {
234
    FIPS_ALLOWED_KEX,
235
    FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS,
236
    FIPS_ALLOWED_CIPHERS,
237
    FIPS_ALLOWED_CIPHERS,
238
    FIPS_ALLOWED_MACS,
239
    FIPS_ALLOWED_MACS,
240
    ZLIB_DEFAULT,
241
    ZLIB_DEFAULT,
242
    "",
243
    "",
244
    NULL
245
};
246
247
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
248
static const char *default_methods[] = {
249
    DEFAULT_KEY_EXCHANGE,
250
    DEFAULT_PUBLIC_KEY_ALGORITHMS,
251
    CHACHA20 AES,
252
    CHACHA20 AES,
253
    "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512",
254
    "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512",
255
    ZLIB_DEFAULT,
256
    ZLIB_DEFAULT,
257
    "",
258
    "",
259
    NULL
260
};
261
262
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
263
static const char *supported_methods[] = {
264
  KEY_EXCHANGE_SUPPORTED,
265
  PUBLIC_KEY_ALGORITHMS,
266
  CHACHA20 AES AES_CBC BLOWFISH DES_SUPPORTED NONE,
267
  CHACHA20 AES AES_CBC BLOWFISH DES_SUPPORTED NONE,
268
  "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1" NONE,
269
  "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1" NONE,
270
  ZLIB,
271
  ZLIB,
272
  "",
273
  "",
274
  NULL
275
};
276
277
/* descriptions of the key exchange packet */
278
static const char *ssh_kex_descriptions[] = {
279
  "kex algos",
280
  "server host key algo",
281
  "encryption client->server",
282
  "encryption server->client",
283
  "mac algo client->server",
284
  "mac algo server->client",
285
  "compression algo client->server",
286
  "compression algo server->client",
287
  "languages client->server",
288
  "languages server->client",
289
  NULL
290
};
291
292
const char *ssh_kex_get_default_methods(enum ssh_kex_types_e type)
293
0
{
294
0
    if (type >= SSH_KEX_METHODS) {
295
0
        return NULL;
296
0
    }
297
298
0
    return default_methods[type];
299
0
}
300
const char *ssh_kex_get_supported_method(enum ssh_kex_types_e type)
301
0
{
302
0
    if (type >= SSH_KEX_METHODS) {
303
0
        return NULL;
304
0
    }
305
306
0
    return supported_methods[type];
307
0
}
308
309
const char *ssh_kex_get_description(enum ssh_kex_types_e type)
310
0
{
311
0
    if (type >= SSH_KEX_METHODS) {
312
0
        return NULL;
313
0
    }
314
315
0
    return ssh_kex_descriptions[type];
316
0
}
317
318
const char *ssh_kex_get_fips_methods(enum ssh_kex_types_e type)
319
0
{
320
0
    if (type >= SSH_KEX_METHODS) {
321
0
        return NULL;
322
0
    }
323
324
0
    return fips_methods[type];
325
0
}
326
327
/**
328
 * @brief Get a list of supported algorithms of a given type. This respects the
329
 * FIPS mode status.
330
 *
331
 * @param[in] type The type of the algorithm to query (SSH_KEX, SSH_MAC_C_S,
332
 * ...).
333
 *
334
 * @return The list of supported methods as comma-separated string, or NULL for
335
 * unknown type.
336
 */
337
const char *ssh_get_supported_methods(enum ssh_kex_types_e type)
338
0
{
339
0
    if (ssh_fips_mode()) {
340
0
        return ssh_kex_get_fips_methods(type);
341
0
    } else {
342
0
        return ssh_kex_get_supported_method(type);
343
0
    }
344
0
}
345
346
/**
347
 * @internal
348
 * @brief returns whether the first client key exchange algorithm or
349
 *        hostkey type matches its server counterpart
350
 * @returns whether the first client key exchange algorithm or hostkey type
351
 *          matches its server counterpart
352
 */
353
static int cmp_first_kex_algo(const char *client_str,
354
0
                              const char *server_str) {
355
0
    size_t client_kex_len;
356
0
    size_t server_kex_len;
357
358
0
    char *colon = NULL;
359
360
0
    int is_wrong = 1;
361
362
0
    if (client_str == NULL || server_str == NULL) {
363
0
        return is_wrong;
364
0
    }
365
366
0
    colon = strchr(client_str, ',');
367
0
    if (colon == NULL) {
368
0
        client_kex_len = strlen(client_str);
369
0
    } else {
370
0
        client_kex_len = colon - client_str;
371
0
    }
372
373
0
    colon = strchr(server_str, ',');
374
0
    if (colon == NULL) {
375
0
        server_kex_len = strlen(server_str);
376
0
    } else {
377
0
        server_kex_len = colon - server_str;
378
0
    }
379
380
0
    if (client_kex_len != server_kex_len) {
381
0
        return is_wrong;
382
0
    }
383
384
0
    is_wrong = (strncmp(client_str, server_str, client_kex_len) != 0);
385
386
0
    return is_wrong;
387
0
}
388
389
SSH_PACKET_CALLBACK(ssh_packet_kexinit)
390
0
{
391
0
    int i, ok;
392
0
    struct ssh_crypto_struct *crypto = session->next_crypto;
393
0
    int server_kex = session->server;
394
0
    ssh_string str = NULL;
395
0
    char *strings[SSH_KEX_METHODS] = {0};
396
0
    int rc = SSH_ERROR;
397
0
    size_t len;
398
399
0
    uint8_t first_kex_packet_follows = 0;
400
0
    uint32_t kexinit_reserved = 0;
401
402
0
    (void)type;
403
0
    (void)user;
404
405
0
    SSH_LOG(SSH_LOG_TRACE, "KEXINIT received");
406
407
0
    if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) {
408
0
        if (session->dh_handshake_state == DH_STATE_FINISHED) {
409
0
            SSH_LOG(SSH_LOG_DEBUG, "Peer initiated key re-exchange");
410
            /* Reset the sent flag if the re-kex was initiated by the peer */
411
0
            session->flags &= ~SSH_SESSION_FLAG_KEXINIT_SENT;
412
0
        } else if (session->flags & SSH_SESSION_FLAG_KEXINIT_SENT &&
413
0
                   session->dh_handshake_state == DH_STATE_INIT_SENT) {
414
            /* This happens only when we are sending our-guessed first kex
415
             * packet right after our KEXINIT packet. */
416
0
            SSH_LOG(SSH_LOG_DEBUG, "Received peer kexinit answer.");
417
0
        } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
418
0
            ssh_set_error(session, SSH_FATAL,
419
0
                          "SSH_KEXINIT received in wrong state");
420
0
            goto error;
421
0
        }
422
0
    } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) {
423
0
        ssh_set_error(session, SSH_FATAL,
424
0
                      "SSH_KEXINIT received in wrong state");
425
0
        goto error;
426
0
    }
427
428
0
    if (server_kex) {
429
0
#ifdef WITH_SERVER
430
0
        len = ssh_buffer_get_data(packet, crypto->client_kex.cookie, 16);
431
0
        if (len != 16) {
432
0
            ssh_set_error(session, SSH_FATAL,
433
0
                          "ssh_packet_kexinit: no cookie in packet");
434
0
            goto error;
435
0
        }
436
437
0
        ok = ssh_hashbufin_add_cookie(session, crypto->client_kex.cookie);
438
0
        if (ok < 0) {
439
0
            ssh_set_error(session, SSH_FATAL,
440
0
                          "ssh_packet_kexinit: adding cookie failed");
441
0
            goto error;
442
0
        }
443
444
0
        ok = server_set_kex(session);
445
0
        if (ok == SSH_ERROR) {
446
0
            goto error;
447
0
        }
448
0
#endif /* WITH_SERVER */
449
0
    } else {
450
0
        len = ssh_buffer_get_data(packet, crypto->server_kex.cookie, 16);
451
0
        if (len != 16) {
452
0
            ssh_set_error(session, SSH_FATAL,
453
0
                          "ssh_packet_kexinit: no cookie in packet");
454
0
            goto error;
455
0
        }
456
457
0
        ok = ssh_hashbufin_add_cookie(session, crypto->server_kex.cookie);
458
0
        if (ok < 0) {
459
0
            ssh_set_error(session, SSH_FATAL,
460
0
                          "ssh_packet_kexinit: adding cookie failed");
461
0
            goto error;
462
0
        }
463
464
0
        ok = ssh_set_client_kex(session);
465
0
        if (ok == SSH_ERROR) {
466
0
            goto error;
467
0
        }
468
0
    }
469
470
0
    for (i = 0; i < SSH_KEX_METHODS; i++) {
471
0
        str = ssh_buffer_get_ssh_string(packet);
472
0
        if (str == NULL) {
473
0
          goto error;
474
0
        }
475
476
0
        rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str);
477
0
        if (rc < 0) {
478
0
            ssh_set_error(session, SSH_FATAL,
479
0
                          "Error adding string in hash buffer");
480
0
            goto error;
481
0
        }
482
483
0
        strings[i] = ssh_string_to_char(str);
484
0
        if (strings[i] == NULL) {
485
0
            ssh_set_error_oom(session);
486
0
            goto error;
487
0
        }
488
0
        SSH_STRING_FREE(str);
489
0
        str = NULL;
490
0
    }
491
492
    /* copy the peer kex info into an array of strings */
493
0
    if (server_kex) {
494
0
#ifdef WITH_SERVER
495
0
        for (i = 0; i < SSH_KEX_METHODS; i++) {
496
0
            crypto->client_kex.methods[i] = strings[i];
497
0
        }
498
0
#endif /* WITH_SERVER */
499
0
    } else { /* client */
500
0
        for (i = 0; i < SSH_KEX_METHODS; i++) {
501
0
            crypto->server_kex.methods[i] = strings[i];
502
0
        }
503
0
    }
504
505
    /*
506
     * Handle the two final fields for the KEXINIT message (RFC 4253 7.1):
507
     *
508
     *      boolean      first_kex_packet_follows
509
     *      uint32       0 (reserved for future extension)
510
     *
511
     * Notably if clients set 'first_kex_packet_follows', it is expected
512
     * that its value is included when computing the session ID (see
513
     * 'make_sessionid').
514
     */
515
516
0
    rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows);
517
0
    if (rc != 1) {
518
0
        goto error;
519
0
    }
520
521
0
    rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows);
522
0
    if (rc < 0) {
523
0
        goto error;
524
0
    }
525
526
0
    rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved);
527
0
    if (rc < 0) {
528
0
        goto error;
529
0
    }
530
531
    /*
532
     * Remember whether 'first_kex_packet_follows' was set and the client
533
     * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
534
     * must be ignored on the server side.
535
     * Client needs to start the Key exchange over with the correct method
536
     */
537
0
    if (first_kex_packet_follows || session->send_first_kex_follows) {
538
0
        char **client_methods = crypto->client_kex.methods;
539
0
        char **server_methods = crypto->server_kex.methods;
540
0
        session->first_kex_follows_guess_wrong =
541
0
            cmp_first_kex_algo(client_methods[SSH_KEX],
542
0
                               server_methods[SSH_KEX]) ||
543
0
            cmp_first_kex_algo(client_methods[SSH_HOSTKEYS],
544
0
                               server_methods[SSH_HOSTKEYS]);
545
0
            SSH_LOG(SSH_LOG_DEBUG, "The initial guess was %s.",
546
0
                    session->first_kex_follows_guess_wrong ? "wrong" : "right");
547
0
    }
548
549
    /*
550
     * handle the "strict KEX" feature. If supported by peer, then set up the
551
     * flag and verify packet sequence numbers.
552
     */
553
0
    if (server_kex) {
554
0
        ok = match_group(crypto->client_kex.methods[SSH_KEX],
555
0
                         KEX_STRICT_CLIENT);
556
0
        if (ok) {
557
0
            SSH_LOG(SSH_LOG_DEBUG, "Client supports strict kex, enabling.");
558
0
            session->flags |= SSH_SESSION_FLAG_KEX_STRICT;
559
0
        }
560
0
    } else {
561
        /* client kex */
562
0
        ok = match_group(crypto->server_kex.methods[SSH_KEX],
563
0
                         KEX_STRICT_SERVER);
564
0
        if (ok) {
565
0
            SSH_LOG(SSH_LOG_DEBUG, "Server supports strict kex, enabling.");
566
0
            session->flags |= SSH_SESSION_FLAG_KEX_STRICT;
567
0
        }
568
0
    }
569
0
#ifdef WITH_SERVER
570
0
    if (server_kex) {
571
        /*
572
         * If client sent a ext-info-c message in the kex list, it supports
573
         * RFC 8308 extension negotiation.
574
         */
575
0
        ok = match_group(crypto->client_kex.methods[SSH_KEX],
576
0
                         KEX_EXTENSION_CLIENT);
577
0
        if (ok) {
578
0
            const char *hostkeys = NULL, *wanted_hostkeys = NULL;
579
580
            /* The client supports extension negotiation */
581
0
            session->extensions |= SSH_EXT_NEGOTIATION;
582
            /*
583
             * RFC 8332 Section 3.1: Use for Server Authentication
584
             * Check what algorithms were provided in the SSH_HOSTKEYS list
585
             * by the client and enable the respective extensions to provide
586
             * correct signature in the next packet if RSA is negotiated
587
             */
588
0
            hostkeys = crypto->client_kex.methods[SSH_HOSTKEYS];
589
0
            wanted_hostkeys = session->opts.wanted_methods[SSH_HOSTKEYS];
590
0
            ok = match_group(hostkeys, "rsa-sha2-512");
591
0
            if (ok) {
592
                /* Check if rsa-sha2-512 is allowed by config */
593
0
                if (wanted_hostkeys != NULL) {
594
0
                    char *is_allowed = ssh_find_matching(wanted_hostkeys,
595
0
                                                         "rsa-sha2-512");
596
0
                    if (is_allowed != NULL) {
597
0
                        session->extensions |= SSH_EXT_SIG_RSA_SHA512;
598
0
                    }
599
0
                    SAFE_FREE(is_allowed);
600
0
                }
601
0
            }
602
0
            ok = match_group(hostkeys, "rsa-sha2-256");
603
0
            if (ok) {
604
                /* Check if rsa-sha2-256 is allowed by config */
605
0
                if (wanted_hostkeys != NULL) {
606
0
                    char *is_allowed = ssh_find_matching(wanted_hostkeys,
607
0
                                                         "rsa-sha2-256");
608
0
                    if (is_allowed != NULL) {
609
0
                        session->extensions |= SSH_EXT_SIG_RSA_SHA256;
610
0
                    }
611
0
                    SAFE_FREE(is_allowed);
612
0
                }
613
0
            }
614
615
            /*
616
             * Ensure that the client preference is honored for the case
617
             * both signature types are enabled.
618
             */
619
0
            if ((session->extensions & SSH_EXT_SIG_RSA_SHA256) &&
620
0
                (session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
621
0
                char *rsa_sig_ext = NULL;
622
0
                session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512);
623
0
                rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256",
624
0
                                                hostkeys);
625
0
                if (rsa_sig_ext == NULL) {
626
0
                    goto error; /* should never happen */
627
0
                } else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) {
628
0
                    session->extensions |= SSH_EXT_SIG_RSA_SHA512;
629
0
                } else if (strcmp(rsa_sig_ext, "rsa-sha2-256") == 0) {
630
0
                    session->extensions |= SSH_EXT_SIG_RSA_SHA256;
631
0
                } else {
632
0
                    SAFE_FREE(rsa_sig_ext);
633
0
                    goto error; /* should never happen */
634
0
                }
635
0
                SAFE_FREE(rsa_sig_ext);
636
0
            }
637
638
0
            SSH_LOG(SSH_LOG_DEBUG, "The client supports extension "
639
0
                    "negotiation. Enabled signature algorithms: %s%s",
640
0
                    session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "",
641
0
                    session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : "");
642
0
        }
643
0
    }
644
0
#endif /* WITH_SERVER */
645
646
    /* Note, that his overwrites authenticated state in case of rekeying */
647
0
    session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED;
648
    /* if we already sent our initial key exchange packet, do not reset the
649
     * DH state. We will know if we were right with our guess only in
650
     * dh_handshake_state() */
651
0
    if (session->send_first_kex_follows == false) {
652
0
        session->dh_handshake_state = DH_STATE_INIT;
653
0
    }
654
0
    session->ssh_connection_callback(session);
655
0
    return SSH_PACKET_USED;
656
657
0
error:
658
0
    SSH_STRING_FREE(str);
659
0
    for (i = 0; i < SSH_KEX_METHODS; i++) {
660
0
        if (server_kex) {
661
0
#ifdef WITH_SERVER
662
0
            session->next_crypto->client_kex.methods[i] = NULL;
663
0
#endif /* WITH_SERVER */
664
0
        } else { /* client */
665
0
            session->next_crypto->server_kex.methods[i] = NULL;
666
0
        }
667
0
        SAFE_FREE(strings[i]);
668
0
    }
669
670
0
    session->session_state = SSH_SESSION_STATE_ERROR;
671
672
0
    return SSH_PACKET_USED;
673
0
}
674
675
0
void ssh_list_kex(struct ssh_kex_struct *kex) {
676
0
  int i = 0;
677
678
#ifdef DEBUG_CRYPTO
679
  ssh_log_hexdump("session cookie", kex->cookie, 16);
680
#endif
681
682
0
  for(i = 0; i < SSH_KEX_METHODS; i++) {
683
0
    if (kex->methods[i] == NULL) {
684
0
      continue;
685
0
    }
686
0
    SSH_LOG(SSH_LOG_FUNCTIONS, "%s: %s",
687
0
        ssh_kex_descriptions[i], kex->methods[i]);
688
0
  }
689
0
}
690
691
/**
692
 * @internal
693
 *
694
 * @brief selects the hostkey mechanisms to be chosen for the key exchange,
695
 * as some hostkey mechanisms may be present in known_hosts files.
696
 *
697
 * @returns a cstring containing a comma-separated list of hostkey methods.
698
 *          NULL if no method matches
699
 */
700
char *ssh_client_select_hostkeys(ssh_session session)
701
0
{
702
0
    const char *wanted = NULL;
703
0
    char *wanted_without_certs = NULL;
704
0
    char *known_hosts_algorithms = NULL;
705
0
    char *known_hosts_ordered = NULL;
706
0
    char *new_hostkeys = NULL;
707
0
    char *fips_hostkeys = NULL;
708
709
0
    wanted = session->opts.wanted_methods[SSH_HOSTKEYS];
710
0
    if (wanted == NULL) {
711
0
        if (ssh_fips_mode()) {
712
0
            wanted = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
713
0
        } else {
714
0
            wanted = ssh_kex_get_default_methods(SSH_HOSTKEYS);
715
0
        }
716
0
    }
717
718
    /* This removes the certificate types, unsupported for now */
719
0
    wanted_without_certs = ssh_find_all_matching(HOSTKEYS, wanted);
720
0
    if (wanted_without_certs == NULL) {
721
0
        SSH_LOG(SSH_LOG_TRACE,
722
0
                "List of allowed host key algorithms is empty or contains only "
723
0
                "unsupported algorithms");
724
0
        return NULL;
725
0
    }
726
727
0
    SSH_LOG(SSH_LOG_DEBUG,
728
0
            "Order of wanted host keys: \"%s\"",
729
0
            wanted_without_certs);
730
731
0
    known_hosts_algorithms = ssh_known_hosts_get_algorithms_names(session);
732
0
    if (known_hosts_algorithms == NULL) {
733
0
        SSH_LOG(SSH_LOG_DEBUG,
734
0
                "No key found in known_hosts; "
735
0
                "changing host key method to \"%s\"",
736
0
                wanted_without_certs);
737
738
0
        return wanted_without_certs;
739
0
    }
740
741
0
    SSH_LOG(SSH_LOG_DEBUG,
742
0
            "Algorithms found in known_hosts files: \"%s\"",
743
0
            known_hosts_algorithms);
744
745
    /* Filter and order the keys from known_hosts according to wanted list */
746
0
    known_hosts_ordered = ssh_find_all_matching(known_hosts_algorithms,
747
0
                                                wanted_without_certs);
748
0
    SAFE_FREE(known_hosts_algorithms);
749
0
    if (known_hosts_ordered == NULL) {
750
0
        SSH_LOG(SSH_LOG_DEBUG,
751
0
                "No key found in known_hosts is allowed; "
752
0
                "changing host key method to \"%s\"",
753
0
                wanted_without_certs);
754
755
0
        return wanted_without_certs;
756
0
    }
757
758
    /* Append the other supported keys after the preferred ones
759
     * This function tolerates NULL pointers in parameters */
760
0
    new_hostkeys = ssh_append_without_duplicates(known_hosts_ordered,
761
0
                                                 wanted_without_certs);
762
0
    SAFE_FREE(known_hosts_ordered);
763
0
    SAFE_FREE(wanted_without_certs);
764
0
    if (new_hostkeys == NULL) {
765
0
        ssh_set_error_oom(session);
766
0
        return NULL;
767
0
    }
768
769
0
    if (ssh_fips_mode()) {
770
        /* Filter out algorithms not allowed in FIPS mode */
771
0
        fips_hostkeys = ssh_keep_fips_algos(SSH_HOSTKEYS, new_hostkeys);
772
0
        SAFE_FREE(new_hostkeys);
773
0
        if (fips_hostkeys == NULL) {
774
0
            SSH_LOG(SSH_LOG_TRACE,
775
0
                    "None of the wanted host keys or keys in known_hosts files "
776
0
                    "is allowed in FIPS mode.");
777
0
            return NULL;
778
0
        }
779
0
        new_hostkeys = fips_hostkeys;
780
0
    }
781
782
0
    SSH_LOG(SSH_LOG_DEBUG,
783
0
            "Changing host key method to \"%s\"",
784
0
            new_hostkeys);
785
786
0
    return new_hostkeys;
787
0
}
788
789
/**
790
 * @brief sets the key exchange parameters to be sent to the server,
791
 *        in function of the options and available methods.
792
 */
793
int ssh_set_client_kex(ssh_session session)
794
0
{
795
0
    struct ssh_kex_struct *client = &session->next_crypto->client_kex;
796
0
    const char *wanted = NULL;
797
0
    int ok;
798
0
    int i;
799
0
    bool gssapi_null_alg = false;
800
0
    char *hostkeys = NULL;
801
802
    /* Skip if already set, for example for the rekey or when we do the guessing
803
     * it could have been already used to make some protocol decisions. */
804
0
    if (client->methods[0] != NULL) {
805
0
        return SSH_OK;
806
0
    }
807
808
0
    ok = ssh_get_random(client->cookie, 16, 0);
809
0
    if (!ok) {
810
0
        ssh_set_error(session, SSH_FATAL, "PRNG error");
811
0
        return SSH_ERROR;
812
0
    }
813
#ifdef WITH_GSSAPI
814
    if (session->opts.gssapi_key_exchange) {
815
        char *gssapi_algs = NULL;
816
817
        ok = ssh_gssapi_init(session);
818
        if (ok != SSH_OK) {
819
            ssh_set_error_oom(session);
820
            return SSH_ERROR;
821
        }
822
823
        ok = ssh_gssapi_import_name(session->gssapi, session->opts.host);
824
        if (ok != SSH_OK) {
825
            return SSH_ERROR;
826
        }
827
828
        gssapi_algs = ssh_gssapi_kex_mechs(session);
829
        if (gssapi_algs == NULL) {
830
            return SSH_ERROR;
831
        }
832
833
        /* Prefix the default algorithms with gsskex algs */
834
        if (ssh_fips_mode()) {
835
            session->opts.wanted_methods[SSH_KEX] =
836
                ssh_prefix_without_duplicates(fips_methods[SSH_KEX],
837
                                              gssapi_algs);
838
        } else {
839
            session->opts.wanted_methods[SSH_KEX] =
840
                ssh_prefix_without_duplicates(default_methods[SSH_KEX],
841
                                              gssapi_algs);
842
        }
843
844
        gssapi_null_alg = true;
845
846
        SAFE_FREE(gssapi_algs);
847
    }
848
#endif
849
850
    /* Set the list of allowed algorithms in order of preference, if it hadn't
851
     * been set yet. */
852
0
    for (i = 0; i < SSH_KEX_METHODS; i++) {
853
0
        if (i == SSH_HOSTKEYS) {
854
            /* Set the hostkeys in the following order:
855
             * - First: keys present in known_hosts files ordered by preference
856
             * - Next: other wanted algorithms ordered by preference */
857
0
            client->methods[i] = ssh_client_select_hostkeys(session);
858
0
            if (client->methods[i] == NULL) {
859
0
                ssh_set_error_oom(session);
860
0
                return SSH_ERROR;
861
0
            }
862
0
            if (gssapi_null_alg) {
863
0
                hostkeys =
864
0
                    ssh_append_without_duplicates(client->methods[i], "null");
865
0
                if (hostkeys == NULL) {
866
0
                    ssh_set_error_oom(session);
867
0
                    return SSH_ERROR;
868
0
                }
869
0
                SAFE_FREE(client->methods[i]);
870
0
                client->methods[i] = hostkeys;
871
0
            }
872
0
            continue;
873
0
        }
874
875
0
        wanted = session->opts.wanted_methods[i];
876
0
        if (wanted == NULL) {
877
0
            if (ssh_fips_mode()) {
878
0
                wanted = fips_methods[i];
879
0
            } else {
880
0
                wanted = default_methods[i];
881
0
            }
882
0
        }
883
0
        client->methods[i] = strdup(wanted);
884
0
        if (client->methods[i] == NULL) {
885
0
            ssh_set_error_oom(session);
886
0
            return SSH_ERROR;
887
0
        }
888
0
    }
889
890
    /* For rekeying, skip the extension negotiation */
891
0
    if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
892
0
        return SSH_OK;
893
0
    }
894
895
0
    ok = ssh_kex_append_extensions(session, client);
896
0
    if (ok != SSH_OK){
897
0
        return ok;
898
0
    }
899
900
0
    return SSH_OK;
901
0
}
902
903
int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex)
904
0
{
905
0
    char *kex = NULL;
906
0
    char *kex_tmp = NULL;
907
0
    size_t kex_len, len;
908
909
    /* Here we append ext-info-c and kex-strict-c-v00@openssh.com for client
910
     * and kex-strict-s-v00@openssh.com for server to the list of kex algorithms
911
     */
912
0
    kex = pkex->methods[SSH_KEX];
913
0
    len = strlen(kex);
914
0
    if (session->server) {
915
        /* Comma, nul byte */
916
0
        kex_len = len + 1 + strlen(KEX_STRICT_SERVER) + 1;
917
0
    } else {
918
        /* Comma, comma, nul byte */
919
0
        kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 +
920
0
                  strlen(KEX_STRICT_CLIENT) + 1;
921
0
    }
922
0
    if (kex_len >= MAX_PACKET_LEN) {
923
        /* Overflow */
924
0
        return SSH_ERROR;
925
0
    }
926
0
    kex_tmp = realloc(kex, kex_len);
927
0
    if (kex_tmp == NULL) {
928
0
        ssh_set_error_oom(session);
929
0
        return SSH_ERROR;
930
0
    }
931
0
    if (session->server){
932
0
        snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_STRICT_SERVER);
933
0
    } else {
934
0
        snprintf(kex_tmp + len,
935
0
                 kex_len - len,
936
0
                 ",%s,%s",
937
0
                 KEX_EXTENSION_CLIENT,
938
0
                 KEX_STRICT_CLIENT);
939
0
    }
940
0
    pkex->methods[SSH_KEX] = kex_tmp;
941
0
    return SSH_OK;
942
0
}
943
944
static const char *ssh_find_aead_hmac(const char *cipher)
945
0
{
946
0
    if (cipher == NULL) {
947
0
        return NULL;
948
0
    } else if (strcmp(cipher, "chacha20-poly1305@openssh.com") == 0) {
949
0
        return "aead-poly1305";
950
0
    } else if (strcmp(cipher, "aes256-gcm@openssh.com") == 0) {
951
0
        return "aead-gcm";
952
0
    } else if (strcmp(cipher, "aes128-gcm@openssh.com") == 0) {
953
0
        return "aead-gcm";
954
0
    }
955
0
    return NULL;
956
0
}
957
958
static enum ssh_key_exchange_e
959
kex_select_kex_type(const char *kex)
960
0
{
961
0
    if (strcmp(kex, "diffie-hellman-group1-sha1") == 0) {
962
0
        return SSH_KEX_DH_GROUP1_SHA1;
963
0
    } else if (strncmp(kex, "gss-group14-sha256-", 19) == 0) {
964
0
        return SSH_GSS_KEX_DH_GROUP14_SHA256;
965
0
    } else if (strncmp(kex, "gss-group16-sha512-", 19) == 0) {
966
0
        return SSH_GSS_KEX_DH_GROUP16_SHA512;
967
0
    } else if (strncmp(kex, "gss-nistp256-sha256-", 20) == 0) {
968
0
        return SSH_GSS_KEX_ECDH_NISTP256_SHA256;
969
0
    } else if (strncmp(kex, "gss-curve25519-sha256-", 22) == 0) {
970
0
        return SSH_GSS_KEX_CURVE25519_SHA256;
971
0
    } else if (strcmp(kex, "diffie-hellman-group14-sha1") == 0) {
972
0
        return SSH_KEX_DH_GROUP14_SHA1;
973
0
    } else if (strcmp(kex, "diffie-hellman-group14-sha256") == 0) {
974
0
        return SSH_KEX_DH_GROUP14_SHA256;
975
0
    } else if (strcmp(kex, "diffie-hellman-group16-sha512") == 0) {
976
0
        return SSH_KEX_DH_GROUP16_SHA512;
977
0
    } else if (strcmp(kex, "diffie-hellman-group18-sha512") == 0) {
978
0
        return SSH_KEX_DH_GROUP18_SHA512;
979
0
#ifdef WITH_GEX
980
0
    } else if (strcmp(kex, "diffie-hellman-group-exchange-sha1") == 0) {
981
0
        return SSH_KEX_DH_GEX_SHA1;
982
0
    } else if (strcmp(kex, "diffie-hellman-group-exchange-sha256") == 0) {
983
0
        return SSH_KEX_DH_GEX_SHA256;
984
0
#endif /* WITH_GEX */
985
0
    } else if (strcmp(kex, "ecdh-sha2-nistp256") == 0) {
986
0
        return SSH_KEX_ECDH_SHA2_NISTP256;
987
0
    } else if (strcmp(kex, "ecdh-sha2-nistp384") == 0) {
988
0
        return SSH_KEX_ECDH_SHA2_NISTP384;
989
0
    } else if (strcmp(kex, "ecdh-sha2-nistp521") == 0) {
990
0
        return SSH_KEX_ECDH_SHA2_NISTP521;
991
0
    } else if (strcmp(kex, "curve25519-sha256@libssh.org") == 0) {
992
0
        return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
993
0
    } else if (strcmp(kex, "curve25519-sha256") == 0) {
994
0
        return SSH_KEX_CURVE25519_SHA256;
995
0
    } else if (strcmp(kex, "sntrup761x25519-sha512@openssh.com") == 0) {
996
0
        return SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM;
997
0
    } else if (strcmp(kex, "sntrup761x25519-sha512") == 0) {
998
0
        return SSH_KEX_SNTRUP761X25519_SHA512;
999
#ifdef HAVE_MLKEM
1000
    } else if (strcmp(kex, "mlkem768x25519-sha256") == 0) {
1001
        return SSH_KEX_MLKEM768X25519_SHA256;
1002
    } else if (strcmp(kex, "mlkem768nistp256-sha256") == 0) {
1003
        return SSH_KEX_MLKEM768NISTP256_SHA256;
1004
    } else if (strcmp(kex, "mlkem1024nistp384-sha384") == 0) {
1005
        return SSH_KEX_MLKEM1024NISTP384_SHA384;
1006
#endif
1007
0
    }
1008
    /* should not happen. We should be getting only valid names at this stage */
1009
0
    return 0;
1010
0
}
1011
1012
1013
/** @internal
1014
 * @brief Reverts guessed callbacks set during the dh_handshake()
1015
 * @param session session handle
1016
 * @returns void
1017
 */
1018
static void revert_kex_callbacks(ssh_session session)
1019
0
{
1020
0
    switch (session->next_crypto->kex_type) {
1021
0
    case SSH_KEX_DH_GROUP1_SHA1:
1022
0
    case SSH_KEX_DH_GROUP14_SHA1:
1023
0
    case SSH_KEX_DH_GROUP14_SHA256:
1024
0
    case SSH_KEX_DH_GROUP16_SHA512:
1025
0
    case SSH_KEX_DH_GROUP18_SHA512:
1026
0
        ssh_client_dh_remove_callbacks(session);
1027
0
        break;
1028
0
    case SSH_GSS_KEX_DH_GROUP14_SHA256:
1029
0
    case SSH_GSS_KEX_DH_GROUP16_SHA512:
1030
0
    case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
1031
0
    case SSH_GSS_KEX_CURVE25519_SHA256:
1032
#ifdef WITH_GSSAPI
1033
        ssh_client_gss_kex_remove_callbacks(session);
1034
#endif /* WITH_GSSAPI */
1035
0
        break;
1036
0
#ifdef WITH_GEX
1037
0
    case SSH_KEX_DH_GEX_SHA1:
1038
0
    case SSH_KEX_DH_GEX_SHA256:
1039
0
        ssh_client_dhgex_remove_callbacks(session);
1040
0
        break;
1041
0
#endif /* WITH_GEX */
1042
0
#ifdef HAVE_ECDH
1043
0
    case SSH_KEX_ECDH_SHA2_NISTP256:
1044
0
    case SSH_KEX_ECDH_SHA2_NISTP384:
1045
0
    case SSH_KEX_ECDH_SHA2_NISTP521:
1046
0
        ssh_client_ecdh_remove_callbacks(session);
1047
0
        break;
1048
0
#endif
1049
0
#ifdef HAVE_CURVE25519
1050
0
    case SSH_KEX_CURVE25519_SHA256:
1051
0
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
1052
0
        ssh_client_curve25519_remove_callbacks(session);
1053
0
        break;
1054
0
#endif
1055
0
#ifdef HAVE_SNTRUP761
1056
0
    case SSH_KEX_SNTRUP761X25519_SHA512:
1057
0
    case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
1058
0
        ssh_client_sntrup761x25519_remove_callbacks(session);
1059
0
        break;
1060
0
#endif
1061
#ifdef HAVE_MLKEM
1062
    case SSH_KEX_MLKEM768X25519_SHA256:
1063
    case SSH_KEX_MLKEM768NISTP256_SHA256:
1064
    case SSH_KEX_MLKEM1024NISTP384_SHA384:
1065
        ssh_client_hybrid_mlkem_remove_callbacks(session);
1066
        break;
1067
#endif
1068
0
    }
1069
0
}
1070
1071
/** @brief Select the different methods on basis of client's and
1072
 * server's kex messages, and watches out if a match is possible.
1073
 */
1074
int ssh_kex_select_methods (ssh_session session)
1075
0
{
1076
0
    struct ssh_crypto_struct *crypto = session->next_crypto;
1077
0
    struct ssh_kex_struct *server = &crypto->server_kex;
1078
0
    struct ssh_kex_struct *client = &crypto->client_kex;
1079
0
    char *ext_start = NULL;
1080
0
    const char *aead_hmac = NULL;
1081
0
    enum ssh_key_exchange_e kex_type;
1082
0
    int i;
1083
1084
    /* Here we should drop the extensions from the list so we avoid matching.
1085
     * it. We added it to the end, so we can just truncate the string here */
1086
0
    if (session->client) {
1087
0
        ext_start = strstr(client->methods[SSH_KEX], "," KEX_EXTENSION_CLIENT);
1088
0
        if (ext_start != NULL) {
1089
0
            ext_start[0] = '\0';
1090
0
        }
1091
0
    }
1092
0
    if (session->server) {
1093
0
        ext_start = strstr(server->methods[SSH_KEX], "," KEX_STRICT_SERVER);
1094
0
        if (ext_start != NULL) {
1095
0
            ext_start[0] = '\0';
1096
0
        }
1097
0
    }
1098
1099
0
    for (i = 0; i < SSH_KEX_METHODS; i++) {
1100
0
        crypto->kex_methods[i] = ssh_find_matching(server->methods[i],
1101
0
                                                   client->methods[i]);
1102
1103
0
        if (i == SSH_MAC_C_S || i == SSH_MAC_S_C) {
1104
0
            aead_hmac = ssh_find_aead_hmac(crypto->kex_methods[i - 2]);
1105
0
            if (aead_hmac) {
1106
0
                free(crypto->kex_methods[i]);
1107
0
                crypto->kex_methods[i] = strdup(aead_hmac);
1108
0
            }
1109
0
        }
1110
0
        if (crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S) {
1111
0
            ssh_set_error(session, SSH_FATAL,
1112
0
                          "kex error : no match for method %s: server [%s], "
1113
0
                          "client [%s]", ssh_kex_descriptions[i],
1114
0
                          server->methods[i], client->methods[i]);
1115
0
            return SSH_ERROR;
1116
0
        } else if ((i >= SSH_LANG_C_S) && (crypto->kex_methods[i] == NULL)) {
1117
            /* we can safely do that for languages */
1118
0
            crypto->kex_methods[i] = strdup("");
1119
0
        }
1120
0
    }
1121
1122
    /* We can not set this value directly as the old value is needed to revert
1123
     * callbacks if we are client */
1124
0
    kex_type = kex_select_kex_type(crypto->kex_methods[SSH_KEX]);
1125
0
    if (session->client && session->first_kex_follows_guess_wrong) {
1126
0
        SSH_LOG(SSH_LOG_DEBUG, "Our guess was wrong. Restarting the KEX");
1127
        /* We need to remove the wrong callbacks and start kex again */
1128
0
        revert_kex_callbacks(session);
1129
0
        session->dh_handshake_state = DH_STATE_INIT;
1130
0
        session->first_kex_follows_guess_wrong = false;
1131
0
    }
1132
0
    crypto->kex_type = kex_type;
1133
1134
0
    SSH_LOG(SSH_LOG_DEBUG, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
1135
0
            session->next_crypto->kex_methods[SSH_KEX],
1136
0
            session->next_crypto->kex_methods[SSH_HOSTKEYS],
1137
0
            session->next_crypto->kex_methods[SSH_CRYPT_C_S],
1138
0
            session->next_crypto->kex_methods[SSH_CRYPT_S_C],
1139
0
            session->next_crypto->kex_methods[SSH_MAC_C_S],
1140
0
            session->next_crypto->kex_methods[SSH_MAC_S_C],
1141
0
            session->next_crypto->kex_methods[SSH_COMP_C_S],
1142
0
            session->next_crypto->kex_methods[SSH_COMP_S_C],
1143
0
            session->next_crypto->kex_methods[SSH_LANG_C_S],
1144
0
            session->next_crypto->kex_methods[SSH_LANG_S_C]
1145
0
    );
1146
0
    return SSH_OK;
1147
0
}
1148
1149
1150
/* this function only sends the predefined set of kex methods */
1151
int ssh_send_kex(ssh_session session)
1152
0
{
1153
0
    struct ssh_kex_struct *kex = (session->server ?
1154
0
        &session->next_crypto->server_kex :
1155
0
        &session->next_crypto->client_kex);
1156
0
    ssh_string str = NULL;
1157
0
    int i;
1158
0
    int rc;
1159
0
    int first_kex_packet_follows = 0;
1160
1161
    /* Only client can initiate the handshake methods we implement. If we
1162
     * already received the peer mechanisms, there is no point in guessing */
1163
0
    if (session->client &&
1164
0
        session->session_state != SSH_SESSION_STATE_KEXINIT_RECEIVED &&
1165
0
        session->send_first_kex_follows) {
1166
0
        first_kex_packet_follows = 1;
1167
0
    }
1168
1169
0
    SSH_LOG(SSH_LOG_TRACE,
1170
0
            "Sending KEXINIT packet, first_kex_packet_follows = %d",
1171
0
            first_kex_packet_follows);
1172
1173
0
    rc = ssh_buffer_pack(session->out_buffer,
1174
0
                         "bP",
1175
0
                         SSH2_MSG_KEXINIT,
1176
0
                         (size_t)16,
1177
0
                         kex->cookie); /* cookie */
1178
0
    if (rc != SSH_OK)
1179
0
        goto error;
1180
0
    if (ssh_hashbufout_add_cookie(session) < 0) {
1181
0
        goto error;
1182
0
    }
1183
1184
0
    ssh_list_kex(kex);
1185
1186
0
    for (i = 0; i < SSH_KEX_METHODS; i++) {
1187
0
        str = ssh_string_from_char(kex->methods[i]);
1188
0
        if (str == NULL) {
1189
0
            goto error;
1190
0
        }
1191
1192
0
        rc = ssh_buffer_add_ssh_string(session->out_hashbuf, str);
1193
0
        if (rc < 0) {
1194
0
            goto error;
1195
0
        }
1196
0
        rc = ssh_buffer_add_ssh_string(session->out_buffer, str);
1197
0
        if (rc < 0) {
1198
0
            goto error;
1199
0
        }
1200
0
        SSH_STRING_FREE(str);
1201
0
        str = NULL;
1202
0
    }
1203
1204
0
    rc = ssh_buffer_pack(session->out_buffer,
1205
0
                         "bd",
1206
0
                         first_kex_packet_follows,
1207
0
                         0);
1208
0
    if (rc != SSH_OK) {
1209
0
        goto error;
1210
0
    }
1211
1212
    /* Prepare also the first_kex_packet_follows and reserved to 0 */
1213
0
    rc = ssh_buffer_add_u8(session->out_hashbuf, first_kex_packet_follows);
1214
0
    if (rc < 0) {
1215
0
        goto error;
1216
0
    }
1217
0
    rc = ssh_buffer_add_u32(session->out_hashbuf, 0);
1218
0
    if (rc < 0) {
1219
0
        goto error;
1220
0
    }
1221
1222
0
    rc = ssh_packet_send(session);
1223
0
    if (rc == SSH_ERROR) {
1224
0
        return -1;
1225
0
    }
1226
1227
0
    session->flags |= SSH_SESSION_FLAG_KEXINIT_SENT;
1228
0
    SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent");
1229
1230
    /* If we indicated that we are sending the guessed key exchange packet,
1231
     * do it now. The packet is simple, but we need to do some preparations */
1232
0
    if (first_kex_packet_follows == 1) {
1233
0
        char *list = kex->methods[SSH_KEX];
1234
0
        char *colon = strchr(list, ',');
1235
0
        size_t kex_name_len = colon ? (size_t)(colon - list) : strlen(list);
1236
0
        char *kex_name = calloc(kex_name_len + 1, 1);
1237
0
        if (kex_name == NULL) {
1238
0
            ssh_set_error_oom(session);
1239
0
            goto error;
1240
0
        }
1241
0
        snprintf(kex_name, kex_name_len + 1, "%.*s", (int)kex_name_len, list);
1242
0
        SSH_LOG(SSH_LOG_TRACE, "Sending the first kex packet for %s", kex_name);
1243
1244
0
        session->next_crypto->kex_type = kex_select_kex_type(kex_name);
1245
0
        free(kex_name);
1246
1247
        /* run the first step of the DH handshake */
1248
0
        session->dh_handshake_state = DH_STATE_INIT;
1249
0
        if (dh_handshake(session) == SSH_ERROR) {
1250
0
            goto error;
1251
0
        }
1252
0
    }
1253
0
    return 0;
1254
1255
0
error:
1256
0
    ssh_buffer_reinit(session->out_buffer);
1257
0
    ssh_buffer_reinit(session->out_hashbuf);
1258
0
    SSH_STRING_FREE(str);
1259
1260
0
    return -1;
1261
0
}
1262
1263
/*
1264
 * Key re-exchange (rekey) is triggered by this function.
1265
 * It can not be called again after the rekey is initialized!
1266
 */
1267
int ssh_send_rekex(ssh_session session)
1268
0
{
1269
0
    int rc;
1270
1271
0
    if (session->dh_handshake_state != DH_STATE_FINISHED) {
1272
        /* Rekey/Key exchange is already in progress */
1273
0
        SSH_LOG(SSH_LOG_PACKET, "Attempting rekey in bad state");
1274
0
        return SSH_ERROR;
1275
0
    }
1276
1277
0
    if (session->current_crypto == NULL) {
1278
        /* No current crypto used -- can not exchange it */
1279
0
        SSH_LOG(SSH_LOG_PACKET, "No crypto to rekey");
1280
0
        return SSH_ERROR;
1281
0
    }
1282
1283
0
    if (session->client) {
1284
0
        rc = ssh_set_client_kex(session);
1285
0
        if (rc != SSH_OK) {
1286
0
            SSH_LOG(SSH_LOG_PACKET, "Failed to set client kex");
1287
0
            return rc;
1288
0
        }
1289
0
    } else {
1290
0
#ifdef WITH_SERVER
1291
0
        rc = server_set_kex(session);
1292
0
        if (rc == SSH_ERROR) {
1293
0
            SSH_LOG(SSH_LOG_PACKET, "Failed to set server kex");
1294
0
            return rc;
1295
0
        }
1296
#else
1297
        SSH_LOG(SSH_LOG_PACKET, "Invalid session state.");
1298
        return SSH_ERROR;
1299
#endif /* WITH_SERVER */
1300
0
    }
1301
1302
0
    session->dh_handshake_state = DH_STATE_INIT;
1303
0
    rc = ssh_send_kex(session);
1304
0
    if (rc < 0) {
1305
0
        SSH_LOG(SSH_LOG_PACKET, "Failed to send kex");
1306
0
        return rc;
1307
0
    }
1308
1309
    /* Reset the handshake state */
1310
0
    session->dh_handshake_state = DH_STATE_INIT_SENT;
1311
0
    return SSH_OK;
1312
0
}
1313
1314
/* returns a copy of the provided list if everything is supported,
1315
 * otherwise a new list of the supported algorithms */
1316
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list)
1317
0
{
1318
0
    if (algo > SSH_LANG_S_C) {
1319
0
        return NULL;
1320
0
    }
1321
1322
0
    return ssh_find_all_matching(supported_methods[algo], list);
1323
0
}
1324
1325
/**
1326
 * @internal
1327
 *
1328
 * @brief Return a newly allocated string containing only the FIPS allowed
1329
 * algorithms from the list.
1330
 *
1331
 * @param[in] algo  The type of the methods to filter
1332
 * @param[in] list  The list to be filtered
1333
 *
1334
 * @return A newly allocated list containing only the FIPS allowed algorithms from
1335
 * the list; NULL in case of error.
1336
 */
1337
char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list)
1338
0
{
1339
0
    if (algo > SSH_LANG_S_C) {
1340
0
        return NULL;
1341
0
    }
1342
1343
0
    return ssh_find_all_matching(fips_methods[algo], list);
1344
0
}
1345
1346
/**
1347
 * @internal
1348
 *
1349
 * @brief Return a newly allocated string containing the default
1350
 * algorithms plus the algorithms specified in list. If the system
1351
 * runs in fips mode, this will add only fips approved algorithms.
1352
 * Empty list will cause error.
1353
 *
1354
 * @param[in] algo  The type of the methods to filter
1355
 * @param[in] list  The list to be appended
1356
 *
1357
 * @return A newly allocated list containing the default algorithms and the
1358
 * algorithms in list at the end; NULL in case of error.
1359
 */
1360
char *ssh_add_to_default_algos(enum ssh_kex_types_e algo, const char *list)
1361
0
{
1362
0
    char *tmp = NULL, *ret = NULL;
1363
1364
0
    if (algo > SSH_LANG_S_C || list == NULL || list[0] == '\0') {
1365
0
        return NULL;
1366
0
    }
1367
1368
0
    if (ssh_fips_mode()) {
1369
0
        tmp = ssh_append_without_duplicates(fips_methods[algo], list);
1370
0
        ret = ssh_find_all_matching(fips_methods[algo], tmp);
1371
0
    } else {
1372
0
        tmp = ssh_append_without_duplicates(default_methods[algo], list);
1373
0
        ret = ssh_find_all_matching(supported_methods[algo], tmp);
1374
0
    }
1375
1376
0
    free(tmp);
1377
0
    return ret;
1378
0
}
1379
1380
/**
1381
 * @internal
1382
 *
1383
 * @brief Return a newly allocated string containing the default
1384
 * algorithms excluding the algorithms specified in list. If the system
1385
 * runs in fips mode, this will remove from the fips_methods list.
1386
 *
1387
 * @param[in] algo  The type of the methods to filter
1388
 * @param[in] list  The list to be exclude
1389
 *
1390
 * @return A newly allocated list containing the default algorithms without the
1391
 * algorithms in list; NULL in case of error.
1392
 */
1393
char *ssh_remove_from_default_algos(enum ssh_kex_types_e algo, const char *list)
1394
0
{
1395
0
    if (algo > SSH_LANG_S_C) {
1396
0
        return NULL;
1397
0
    }
1398
1399
0
    if (list == NULL || list[0] == '\0') {
1400
0
        if (ssh_fips_mode()) {
1401
0
            return strdup(fips_methods[algo]);
1402
0
        } else {
1403
0
            return strdup(default_methods[algo]);
1404
0
        }
1405
0
    }
1406
1407
0
    if (ssh_fips_mode()) {
1408
0
        return ssh_remove_all_matching(fips_methods[algo], list);
1409
0
    } else {
1410
0
        return ssh_remove_all_matching(default_methods[algo], list);
1411
0
    }
1412
0
}
1413
1414
/**
1415
 * @internal
1416
 *
1417
 * @brief Return a newly allocated string containing the default
1418
 * algorithms with prioritized algorithms specified in list. If the
1419
 * algorithms are present in the default list they get prioritized, if not
1420
 * they are added to the front of the default list. If the system
1421
 * runs in fips mode, this will work with the fips_methods list.
1422
 * Empty list will cause error.
1423
 *
1424
 * @param[in] algo  The type of the methods to filter
1425
 * @param[in] list  The list to be pushed to priority
1426
 *
1427
 * @return A newly allocated list containing the default algorithms prioritized
1428
 * with the algorithms in list at the beginning of the list; NULL in case
1429
 * of error.
1430
 */
1431
char *ssh_prefix_default_algos(enum ssh_kex_types_e algo, const char *list)
1432
0
{
1433
0
    char *ret = NULL, *tmp = NULL;
1434
1435
0
    if (algo > SSH_LANG_S_C || list == NULL || list[0] == '\0') {
1436
0
        return NULL;
1437
0
    }
1438
1439
0
    if (ssh_fips_mode()) {
1440
0
        tmp = ssh_prefix_without_duplicates(fips_methods[algo], list);
1441
0
        ret = ssh_find_all_matching(fips_methods[algo], tmp);
1442
0
    } else {
1443
0
        tmp = ssh_prefix_without_duplicates(default_methods[algo], list);
1444
0
        ret = ssh_find_all_matching(supported_methods[algo], tmp);
1445
0
    }
1446
1447
0
    free(tmp);
1448
0
    return ret;
1449
0
}
1450
1451
int ssh_make_sessionid(ssh_session session)
1452
0
{
1453
0
    ssh_string num = NULL;
1454
0
    ssh_buffer server_hash = NULL;
1455
0
    ssh_buffer client_hash = NULL;
1456
0
    ssh_buffer buf = NULL;
1457
0
    ssh_string server_pubkey_blob = NULL;
1458
0
#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L
1459
0
    const_bignum client_pubkey, server_pubkey;
1460
#else
1461
    bignum client_pubkey = NULL, server_pubkey = NULL;
1462
#endif /* OPENSSL_VERSION_NUMBER */
1463
0
#ifdef WITH_GEX
1464
0
#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L
1465
0
    const_bignum modulus, generator;
1466
#else
1467
    bignum modulus = NULL, generator = NULL;
1468
#endif /* OPENSSL_VERSION_NUMBER */
1469
0
#endif /* WITH_GEX */
1470
0
    int rc = SSH_ERROR;
1471
1472
0
    buf = ssh_buffer_new();
1473
0
    if (buf == NULL) {
1474
0
        ssh_set_error_oom(session);
1475
0
        return rc;
1476
0
    }
1477
1478
0
    rc = ssh_buffer_pack(buf,
1479
0
                         "ss",
1480
0
                         session->clientbanner,
1481
0
                         session->serverbanner);
1482
0
    if (rc == SSH_ERROR) {
1483
0
        ssh_set_error(session,
1484
0
                      SSH_FATAL,
1485
0
                      "Failed to pack client and server banner");
1486
0
        goto error;
1487
0
    }
1488
1489
0
    if (session->client) {
1490
0
        server_hash = session->in_hashbuf;
1491
0
        client_hash = session->out_hashbuf;
1492
0
    } else {
1493
0
        server_hash = session->out_hashbuf;
1494
0
        client_hash = session->in_hashbuf;
1495
0
    }
1496
1497
0
    rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
1498
0
    if (rc != SSH_OK) {
1499
0
        ssh_set_error(session,
1500
0
                      SSH_FATAL,
1501
0
                      "Failed to get next server pubkey blob");
1502
0
        goto error;
1503
0
    }
1504
1505
0
    if (server_pubkey_blob == NULL) {
1506
0
        if ((session->server && ssh_kex_is_gss(session->next_crypto)) ||
1507
0
            session->opts.gssapi_key_exchange) {
1508
0
            server_pubkey_blob = ssh_string_new(0);
1509
0
            if (server_pubkey_blob == NULL) {
1510
0
                ssh_set_error_oom(session);
1511
0
                rc = SSH_ERROR;
1512
0
                goto error;
1513
0
            }
1514
0
        }
1515
0
    }
1516
1517
0
    rc = ssh_buffer_pack(buf,
1518
0
                         "dPdPS",
1519
0
                         ssh_buffer_get_len(client_hash),
1520
0
                         (size_t)ssh_buffer_get_len(client_hash),
1521
0
                         ssh_buffer_get(client_hash),
1522
0
                         ssh_buffer_get_len(server_hash),
1523
0
                         (size_t)ssh_buffer_get_len(server_hash),
1524
0
                         ssh_buffer_get(server_hash),
1525
0
                         server_pubkey_blob);
1526
0
    SSH_STRING_FREE(server_pubkey_blob);
1527
0
    if (rc != SSH_OK){
1528
0
        ssh_set_error(session,
1529
0
                      SSH_FATAL,
1530
0
                      "Failed to pack hashes and pubkey blob");
1531
0
        goto error;
1532
0
    }
1533
1534
0
    switch(session->next_crypto->kex_type) {
1535
0
    case SSH_KEX_DH_GROUP1_SHA1:
1536
0
    case SSH_KEX_DH_GROUP14_SHA1:
1537
0
    case SSH_KEX_DH_GROUP14_SHA256:
1538
0
    case SSH_GSS_KEX_DH_GROUP14_SHA256:
1539
0
    case SSH_KEX_DH_GROUP16_SHA512:
1540
0
    case SSH_GSS_KEX_DH_GROUP16_SHA512:
1541
0
    case SSH_KEX_DH_GROUP18_SHA512:
1542
0
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
1543
0
                                     DH_CLIENT_KEYPAIR, NULL, &client_pubkey);
1544
0
        if (rc != SSH_OK) {
1545
0
            goto error;
1546
0
        }
1547
0
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
1548
0
                                     DH_SERVER_KEYPAIR, NULL, &server_pubkey);
1549
0
        if (rc != SSH_OK) {
1550
0
            goto error;
1551
0
        }
1552
0
        rc = ssh_buffer_pack(buf,
1553
0
                             "BB",
1554
0
                             client_pubkey,
1555
0
                             server_pubkey);
1556
0
        if (rc != SSH_OK) {
1557
0
            ssh_set_error(session, SSH_FATAL, "Failed to pack DH pubkeys");
1558
0
            goto error;
1559
0
        }
1560
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
1561
        bignum_safe_free(client_pubkey);
1562
        bignum_safe_free(server_pubkey);
1563
#endif /* OPENSSL_VERSION_NUMBER */
1564
0
        break;
1565
0
#ifdef WITH_GEX
1566
0
    case SSH_KEX_DH_GEX_SHA1:
1567
0
    case SSH_KEX_DH_GEX_SHA256:
1568
0
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
1569
0
                                     DH_CLIENT_KEYPAIR, NULL, &client_pubkey);
1570
0
        if (rc != SSH_OK) {
1571
0
            goto error;
1572
0
        }
1573
0
        rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx,
1574
0
                                     DH_SERVER_KEYPAIR, NULL, &server_pubkey);
1575
0
        if (rc != SSH_OK) {
1576
0
            goto error;
1577
0
        }
1578
0
        rc = ssh_dh_get_parameters(session->next_crypto->dh_ctx,
1579
0
                                   &modulus, &generator);
1580
0
        if (rc != SSH_OK) {
1581
0
            goto error;
1582
0
        }
1583
0
        rc = ssh_buffer_pack(buf,
1584
0
                    "dddBBBB",
1585
0
                    session->next_crypto->dh_pmin,
1586
0
                    session->next_crypto->dh_pn,
1587
0
                    session->next_crypto->dh_pmax,
1588
0
                    modulus,
1589
0
                    generator,
1590
0
                    client_pubkey,
1591
0
                    server_pubkey);
1592
0
        if (rc != SSH_OK) {
1593
0
            ssh_set_error(session, SSH_FATAL, "Failed to pack DH GEX params");
1594
0
            goto error;
1595
0
        }
1596
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
1597
        bignum_safe_free(modulus);
1598
        bignum_safe_free(generator);
1599
#endif /* OPENSSL_VERSION_NUMBER */
1600
0
        break;
1601
0
#endif /* WITH_GEX */
1602
0
#ifdef HAVE_ECDH
1603
0
    case SSH_KEX_ECDH_SHA2_NISTP256:
1604
0
    case SSH_KEX_ECDH_SHA2_NISTP384:
1605
0
    case SSH_KEX_ECDH_SHA2_NISTP521:
1606
0
    case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
1607
0
        if (session->next_crypto->ecdh_client_pubkey == NULL ||
1608
0
            session->next_crypto->ecdh_server_pubkey == NULL) {
1609
0
            SSH_LOG(SSH_LOG_TRACE, "ECDH parameter missing");
1610
0
            goto error;
1611
0
        }
1612
0
        rc = ssh_buffer_pack(buf,
1613
0
                             "SS",
1614
0
                             session->next_crypto->ecdh_client_pubkey,
1615
0
                             session->next_crypto->ecdh_server_pubkey);
1616
0
        if (rc != SSH_OK) {
1617
0
            ssh_set_error(session, SSH_FATAL, "Failed to pack ECDH pubkeys");
1618
0
            goto error;
1619
0
        }
1620
0
        break;
1621
0
#endif /* HAVE_ECDH */
1622
0
#ifdef HAVE_CURVE25519
1623
0
    case SSH_KEX_CURVE25519_SHA256:
1624
0
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
1625
0
    case SSH_GSS_KEX_CURVE25519_SHA256:
1626
0
        rc = ssh_buffer_pack(buf,
1627
0
                             "dPdP",
1628
0
                             CURVE25519_PUBKEY_SIZE,
1629
0
                             (size_t)CURVE25519_PUBKEY_SIZE,
1630
0
                             session->next_crypto->curve25519_client_pubkey,
1631
0
                             CURVE25519_PUBKEY_SIZE,
1632
0
                             (size_t)CURVE25519_PUBKEY_SIZE,
1633
0
                             session->next_crypto->curve25519_server_pubkey);
1634
1635
0
        if (rc != SSH_OK) {
1636
0
            ssh_set_error(session,
1637
0
                          SSH_FATAL,
1638
0
                          "Failed to pack Curve25519 pubkeys");
1639
0
            goto error;
1640
0
        }
1641
0
        break;
1642
0
#endif /* HAVE_CURVE25519 */
1643
0
#ifdef HAVE_SNTRUP761
1644
0
    case SSH_KEX_SNTRUP761X25519_SHA512:
1645
0
    case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
1646
0
        rc = ssh_buffer_pack(buf,
1647
0
                             "dPPdPP",
1648
0
                             SNTRUP761_PUBLICKEY_SIZE + CURVE25519_PUBKEY_SIZE,
1649
0
                             (size_t)SNTRUP761_PUBLICKEY_SIZE,
1650
0
                             session->next_crypto->sntrup761_client_pubkey,
1651
0
                             (size_t)CURVE25519_PUBKEY_SIZE,
1652
0
                             session->next_crypto->curve25519_client_pubkey,
1653
0
                             SNTRUP761_CIPHERTEXT_SIZE + CURVE25519_PUBKEY_SIZE,
1654
0
                             (size_t)SNTRUP761_CIPHERTEXT_SIZE,
1655
0
                             session->next_crypto->sntrup761_ciphertext,
1656
0
                             (size_t)CURVE25519_PUBKEY_SIZE,
1657
0
                             session->next_crypto->curve25519_server_pubkey);
1658
1659
0
        if (rc != SSH_OK) {
1660
0
            ssh_set_error(session,
1661
0
                          SSH_FATAL,
1662
0
                          "Failed to pack SNTRU Prime params");
1663
0
            goto error;
1664
0
        }
1665
0
        break;
1666
0
#endif /* HAVE_SNTRUP761 */
1667
#ifdef HAVE_MLKEM
1668
    case SSH_KEX_MLKEM768X25519_SHA256:
1669
    case SSH_KEX_MLKEM768NISTP256_SHA256:
1670
    case SSH_KEX_MLKEM1024NISTP384_SHA384:
1671
        rc = ssh_buffer_pack(buf,
1672
                             "SS",
1673
                             session->next_crypto->hybrid_client_init,
1674
                             session->next_crypto->hybrid_server_reply);
1675
        if (rc != SSH_OK) {
1676
            ssh_set_error(session,
1677
                          SSH_FATAL,
1678
                          "Failed to pack ML-KEM individual components");
1679
            goto error;
1680
        }
1681
        break;
1682
#endif /* HAVE_MLKEM */
1683
0
    default:
1684
        /* Handle unsupported kex types - this should not happen in normal operation */
1685
0
        rc = SSH_ERROR;
1686
0
        ssh_set_error(session, SSH_FATAL, "Unsupported KEX algorithm");
1687
0
        goto error;
1688
0
    }
1689
0
    switch (session->next_crypto->kex_type) {
1690
0
    case SSH_KEX_SNTRUP761X25519_SHA512:
1691
0
    case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
1692
0
        rc = ssh_buffer_pack(buf,
1693
0
                             "F",
1694
0
                             session->next_crypto->shared_secret,
1695
0
                             SHA512_DIGEST_LEN);
1696
0
        break;
1697
#ifdef HAVE_MLKEM
1698
    case SSH_KEX_MLKEM768X25519_SHA256:
1699
    case SSH_KEX_MLKEM768NISTP256_SHA256:
1700
    case SSH_KEX_MLKEM1024NISTP384_SHA384:
1701
        rc = ssh_buffer_pack(buf, "S", session->next_crypto->hybrid_shared_secret);
1702
        break;
1703
#endif /* HAVE_MLKEM */
1704
0
    default:
1705
0
        rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
1706
0
        break;
1707
0
    }
1708
0
    if (rc != SSH_OK) {
1709
0
        ssh_set_error(session, SSH_FATAL, "Failed to pack shared secret");
1710
0
        goto error;
1711
0
    }
1712
1713
#ifdef DEBUG_CRYPTO
1714
    ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
1715
#endif
1716
1717
    /* Set rc for the following switch statement in case we goto error. */
1718
0
    rc = SSH_ERROR;
1719
0
    switch (session->next_crypto->kex_type) {
1720
0
    case SSH_KEX_DH_GROUP1_SHA1:
1721
0
    case SSH_KEX_DH_GROUP14_SHA1:
1722
0
#ifdef WITH_GEX
1723
0
    case SSH_KEX_DH_GEX_SHA1:
1724
0
#endif /* WITH_GEX */
1725
0
        session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
1726
0
        session->next_crypto->digest_type = SSH_KDF_SHA1;
1727
0
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
1728
0
        if (session->next_crypto->secret_hash == NULL) {
1729
0
            ssh_set_error_oom(session);
1730
0
            goto error;
1731
0
        }
1732
0
        sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
1733
0
                                   session->next_crypto->secret_hash);
1734
0
        break;
1735
0
    case SSH_KEX_DH_GROUP14_SHA256:
1736
0
    case SSH_GSS_KEX_DH_GROUP14_SHA256:
1737
0
    case SSH_KEX_ECDH_SHA2_NISTP256:
1738
0
    case SSH_KEX_CURVE25519_SHA256:
1739
0
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
1740
#ifdef HAVE_MLKEM
1741
    case SSH_KEX_MLKEM768X25519_SHA256:
1742
    case SSH_KEX_MLKEM768NISTP256_SHA256:
1743
#endif
1744
0
    case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
1745
0
    case SSH_GSS_KEX_CURVE25519_SHA256:
1746
0
#ifdef WITH_GEX
1747
0
    case SSH_KEX_DH_GEX_SHA256:
1748
0
#endif /* WITH_GEX */
1749
0
        session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
1750
0
        session->next_crypto->digest_type = SSH_KDF_SHA256;
1751
0
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
1752
0
        if (session->next_crypto->secret_hash == NULL) {
1753
0
            ssh_set_error_oom(session);
1754
0
            goto error;
1755
0
        }
1756
0
        sha256(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
1757
0
                                     session->next_crypto->secret_hash);
1758
0
        break;
1759
0
    case SSH_KEX_ECDH_SHA2_NISTP384:
1760
#ifdef HAVE_MLKEM
1761
    case SSH_KEX_MLKEM1024NISTP384_SHA384:
1762
#endif
1763
0
        session->next_crypto->digest_len = SHA384_DIGEST_LENGTH;
1764
0
        session->next_crypto->digest_type = SSH_KDF_SHA384;
1765
0
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
1766
0
        if (session->next_crypto->secret_hash == NULL) {
1767
0
            ssh_set_error_oom(session);
1768
0
            goto error;
1769
0
        }
1770
0
        sha384(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
1771
0
                                     session->next_crypto->secret_hash);
1772
0
        break;
1773
0
    case SSH_KEX_DH_GROUP16_SHA512:
1774
0
    case SSH_GSS_KEX_DH_GROUP16_SHA512:
1775
0
    case SSH_KEX_DH_GROUP18_SHA512:
1776
0
    case SSH_KEX_ECDH_SHA2_NISTP521:
1777
0
    case SSH_KEX_SNTRUP761X25519_SHA512:
1778
0
    case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
1779
0
        session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
1780
0
        session->next_crypto->digest_type = SSH_KDF_SHA512;
1781
0
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
1782
0
        if (session->next_crypto->secret_hash == NULL) {
1783
0
            ssh_set_error_oom(session);
1784
0
            goto error;
1785
0
        }
1786
0
        sha512(ssh_buffer_get(buf),
1787
0
               ssh_buffer_get_len(buf),
1788
0
               session->next_crypto->secret_hash);
1789
0
        break;
1790
0
    default:
1791
        /* Handle unsupported kex types - this should not happen in normal operation */
1792
0
        ssh_set_error(session, SSH_FATAL, "Unsupported KEX algorithm for hash computation");
1793
0
        rc = SSH_ERROR;
1794
0
        goto error;
1795
0
    }
1796
1797
    /* During the first kex, secret hash and session ID are equal. However, after
1798
     * a key re-exchange, a new secret hash is calculated. This hash will not replace
1799
     * but complement existing session id.
1800
     */
1801
0
    if (!session->next_crypto->session_id) {
1802
0
        session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
1803
0
        if (session->next_crypto->session_id == NULL) {
1804
0
            ssh_set_error_oom(session);
1805
0
            rc = SSH_ERROR;
1806
0
            goto error;
1807
0
        }
1808
0
        memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
1809
0
                session->next_crypto->digest_len);
1810
  /* Initial length is the same as secret hash */
1811
0
  session->next_crypto->session_id_len = session->next_crypto->digest_len;
1812
0
    }
1813
#ifdef DEBUG_CRYPTO
1814
    SSH_LOG(SSH_LOG_DEBUG, "Session hash: \n");
1815
    ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
1816
    ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->session_id_len);
1817
#endif /* DEBUG_CRYPTO */
1818
1819
0
    rc = SSH_OK;
1820
0
error:
1821
0
    SSH_BUFFER_FREE(buf);
1822
0
    SSH_BUFFER_FREE(client_hash);
1823
0
    SSH_BUFFER_FREE(server_hash);
1824
1825
0
    session->in_hashbuf = NULL;
1826
0
    session->out_hashbuf = NULL;
1827
1828
0
    SSH_STRING_FREE(num);
1829
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
1830
    bignum_safe_free(client_pubkey);
1831
    bignum_safe_free(server_pubkey);
1832
#endif /* OPENSSL_VERSION_NUMBER */
1833
1834
0
    return rc;
1835
0
}
1836
1837
int ssh_hashbufout_add_cookie(ssh_session session)
1838
0
{
1839
0
    int rc;
1840
1841
0
    session->out_hashbuf = ssh_buffer_new();
1842
0
    if (session->out_hashbuf == NULL) {
1843
0
        return -1;
1844
0
    }
1845
1846
0
    rc = ssh_buffer_allocate_size(session->out_hashbuf,
1847
0
            sizeof(uint8_t) + 16);
1848
0
    if (rc < 0) {
1849
0
        ssh_buffer_reinit(session->out_hashbuf);
1850
0
        return -1;
1851
0
    }
1852
1853
0
    if (ssh_buffer_add_u8(session->out_hashbuf, 20) < 0) {
1854
0
        ssh_buffer_reinit(session->out_hashbuf);
1855
0
        return -1;
1856
0
    }
1857
1858
0
    if (session->server) {
1859
0
        if (ssh_buffer_add_data(session->out_hashbuf,
1860
0
                    session->next_crypto->server_kex.cookie, 16) < 0) {
1861
0
            ssh_buffer_reinit(session->out_hashbuf);
1862
0
            return -1;
1863
0
        }
1864
0
    } else {
1865
0
        if (ssh_buffer_add_data(session->out_hashbuf,
1866
0
                    session->next_crypto->client_kex.cookie, 16) < 0) {
1867
0
            ssh_buffer_reinit(session->out_hashbuf);
1868
0
            return -1;
1869
0
        }
1870
0
    }
1871
1872
0
    return 0;
1873
0
}
1874
1875
int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie)
1876
0
{
1877
0
    int rc;
1878
1879
0
    session->in_hashbuf = ssh_buffer_new();
1880
0
    if (session->in_hashbuf == NULL) {
1881
0
        return -1;
1882
0
    }
1883
1884
0
    rc = ssh_buffer_allocate_size(session->in_hashbuf,
1885
0
            sizeof(uint8_t) + 20 + 16);
1886
0
    if (rc < 0) {
1887
0
        ssh_buffer_reinit(session->in_hashbuf);
1888
0
        return -1;
1889
0
    }
1890
1891
0
    if (ssh_buffer_add_u8(session->in_hashbuf, 20) < 0) {
1892
0
        ssh_buffer_reinit(session->in_hashbuf);
1893
0
        return -1;
1894
0
    }
1895
0
    if (ssh_buffer_add_data(session->in_hashbuf,cookie, 16) < 0) {
1896
0
        ssh_buffer_reinit(session->in_hashbuf);
1897
0
        return -1;
1898
0
    }
1899
1900
0
    return 0;
1901
0
}
1902
1903
int ssh_generate_session_keys(ssh_session session)
1904
0
{
1905
0
    ssh_string k_string = NULL;
1906
0
    struct ssh_crypto_struct *crypto = session->next_crypto;
1907
0
    unsigned char *key = NULL;
1908
0
    unsigned char *IV_cli_to_srv = NULL;
1909
0
    unsigned char *IV_srv_to_cli = NULL;
1910
0
    unsigned char *enckey_cli_to_srv = NULL;
1911
0
    unsigned char *enckey_srv_to_cli = NULL;
1912
0
    unsigned char *intkey_cli_to_srv = NULL;
1913
0
    unsigned char *intkey_srv_to_cli = NULL;
1914
0
    size_t key_len = 0;
1915
0
    size_t IV_len = 0;
1916
0
    size_t enckey_cli_to_srv_len = 0;
1917
0
    size_t enckey_srv_to_cli_len = 0;
1918
0
    size_t intkey_cli_to_srv_len = 0;
1919
0
    size_t intkey_srv_to_cli_len = 0;
1920
0
    int rc = -1;
1921
1922
0
    switch (session->next_crypto->kex_type) {
1923
0
    case SSH_KEX_SNTRUP761X25519_SHA512:
1924
0
    case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
1925
0
        k_string = ssh_make_padded_bignum_string(crypto->shared_secret,
1926
0
                                                 crypto->digest_len);
1927
0
        break;
1928
#ifdef HAVE_MLKEM
1929
    case SSH_KEX_MLKEM768X25519_SHA256:
1930
    case SSH_KEX_MLKEM768NISTP256_SHA256:
1931
    case SSH_KEX_MLKEM1024NISTP384_SHA384:
1932
        k_string = ssh_string_copy(crypto->hybrid_shared_secret);
1933
        break;
1934
#endif /* HAVE_MLKEM */
1935
0
    default:
1936
0
        k_string = ssh_make_bignum_string(crypto->shared_secret);
1937
0
        break;
1938
0
    }
1939
0
    if (k_string == NULL) {
1940
0
        ssh_set_error_oom(session);
1941
0
        goto error;
1942
0
    }
1943
    /* See RFC4251 Section 5 for the definition of mpint which is the
1944
     * encoding we need to use for key in the SSH KDF */
1945
0
    key = (unsigned char *)k_string;
1946
0
    key_len = ssh_string_len(k_string) + 4;
1947
1948
0
    IV_len = crypto->digest_len;
1949
0
    if (session->client) {
1950
0
        enckey_cli_to_srv_len = crypto->out_cipher->keysize / 8;
1951
0
        enckey_srv_to_cli_len = crypto->in_cipher->keysize / 8;
1952
0
        intkey_cli_to_srv_len = hmac_digest_len(crypto->out_hmac);
1953
0
        intkey_srv_to_cli_len = hmac_digest_len(crypto->in_hmac);
1954
0
    } else {
1955
0
        enckey_cli_to_srv_len = crypto->in_cipher->keysize / 8;
1956
0
        enckey_srv_to_cli_len = crypto->out_cipher->keysize / 8;
1957
0
        intkey_cli_to_srv_len = hmac_digest_len(crypto->in_hmac);
1958
0
        intkey_srv_to_cli_len = hmac_digest_len(crypto->out_hmac);
1959
0
    }
1960
1961
0
    IV_cli_to_srv = malloc(IV_len);
1962
0
    IV_srv_to_cli = malloc(IV_len);
1963
0
    enckey_cli_to_srv = malloc(enckey_cli_to_srv_len);
1964
0
    enckey_srv_to_cli = malloc(enckey_srv_to_cli_len);
1965
0
    intkey_cli_to_srv = malloc(intkey_cli_to_srv_len);
1966
0
    intkey_srv_to_cli = malloc(intkey_srv_to_cli_len);
1967
0
    if (IV_cli_to_srv == NULL || IV_srv_to_cli == NULL ||
1968
0
        enckey_cli_to_srv == NULL || enckey_srv_to_cli == NULL ||
1969
0
        intkey_cli_to_srv == NULL || intkey_srv_to_cli == NULL) {
1970
0
        ssh_set_error_oom(session);
1971
0
        goto error;
1972
0
    }
1973
1974
    /* IV */
1975
0
    rc = ssh_kdf(crypto, key, key_len, 'A', IV_cli_to_srv, IV_len);
1976
0
    if (rc < 0) {
1977
0
        goto error;
1978
0
    }
1979
0
    rc = ssh_kdf(crypto, key, key_len, 'B', IV_srv_to_cli, IV_len);
1980
0
    if (rc < 0) {
1981
0
        goto error;
1982
0
    }
1983
    /* Encryption Key */
1984
0
    rc = ssh_kdf(crypto, key, key_len, 'C', enckey_cli_to_srv,
1985
0
                 enckey_cli_to_srv_len);
1986
0
    if (rc < 0) {
1987
0
        goto error;
1988
0
    }
1989
0
    rc = ssh_kdf(crypto, key, key_len, 'D', enckey_srv_to_cli,
1990
0
                 enckey_srv_to_cli_len);
1991
0
    if (rc < 0) {
1992
0
        goto error;
1993
0
    }
1994
    /* Integrity Key */
1995
0
    rc = ssh_kdf(crypto, key, key_len, 'E', intkey_cli_to_srv,
1996
0
                 intkey_cli_to_srv_len);
1997
0
    if (rc < 0) {
1998
0
        goto error;
1999
0
    }
2000
0
    rc = ssh_kdf(crypto, key, key_len, 'F', intkey_srv_to_cli,
2001
0
                 intkey_srv_to_cli_len);
2002
0
    if (rc < 0) {
2003
0
        goto error;
2004
0
    }
2005
2006
0
    if (session->client) {
2007
0
        crypto->encryptIV = IV_cli_to_srv;
2008
0
        crypto->decryptIV = IV_srv_to_cli;
2009
0
        crypto->encryptkey = enckey_cli_to_srv;
2010
0
        crypto->decryptkey = enckey_srv_to_cli;
2011
0
        crypto->encryptMAC = intkey_cli_to_srv;
2012
0
        crypto->decryptMAC = intkey_srv_to_cli;
2013
0
    } else {
2014
0
        crypto->encryptIV = IV_srv_to_cli;
2015
0
        crypto->decryptIV = IV_cli_to_srv;
2016
0
        crypto->encryptkey = enckey_srv_to_cli;
2017
0
        crypto->decryptkey = enckey_cli_to_srv;
2018
0
        crypto->encryptMAC = intkey_srv_to_cli;
2019
0
        crypto->decryptMAC = intkey_cli_to_srv;
2020
0
    }
2021
2022
#ifdef DEBUG_CRYPTO
2023
    ssh_log_hexdump("Client to Server IV", IV_cli_to_srv, IV_len);
2024
    ssh_log_hexdump("Server to Client IV", IV_srv_to_cli, IV_len);
2025
    ssh_log_hexdump("Client to Server Encryption Key", enckey_cli_to_srv,
2026
                   enckey_cli_to_srv_len);
2027
    ssh_log_hexdump("Server to Client Encryption Key", enckey_srv_to_cli,
2028
                   enckey_srv_to_cli_len);
2029
    ssh_log_hexdump("Client to Server Integrity Key", intkey_cli_to_srv,
2030
                   intkey_cli_to_srv_len);
2031
    ssh_log_hexdump("Server to Client Integrity Key", intkey_srv_to_cli,
2032
                   intkey_srv_to_cli_len);
2033
#endif /* DEBUG_CRYPTO */
2034
2035
0
    rc = 0;
2036
0
error:
2037
0
    ssh_string_burn(k_string);
2038
0
    SSH_STRING_FREE(k_string);
2039
0
    if (rc != 0) {
2040
0
        free(IV_cli_to_srv);
2041
0
        free(IV_srv_to_cli);
2042
0
        free(enckey_cli_to_srv);
2043
0
        free(enckey_srv_to_cli);
2044
0
        free(intkey_cli_to_srv);
2045
0
        free(intkey_srv_to_cli);
2046
0
    }
2047
2048
0
    return rc;
2049
0
}
2050
2051
/** @internal
2052
 * @brief Check if a given crypto context has a GSSAPI KEX set
2053
 *
2054
 * @param[in] crypto The SSH crypto context
2055
 * @return true if the KEX of the context is a GSSAPI KEX, false otherwise
2056
 */
2057
bool ssh_kex_is_gss(struct ssh_crypto_struct *crypto)
2058
0
{
2059
0
    switch (crypto->kex_type) {
2060
0
    case SSH_GSS_KEX_DH_GROUP14_SHA256:
2061
0
    case SSH_GSS_KEX_DH_GROUP16_SHA512:
2062
0
    case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
2063
0
    case SSH_GSS_KEX_CURVE25519_SHA256:
2064
0
        return true;
2065
0
    default:
2066
        return false;
2067
0
    }
2068
0
}