Coverage Report

Created: 2026-06-07 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libssh/src/wrapper.c
Line
Count
Source
1
/*
2
 * wrapper.c - wrapper for crypto functions
3
 *
4
 * This file is part of the SSH Library
5
 *
6
 * Copyright (c) 2003-2013   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
/*
25
 * Why a wrapper?
26
 *
27
 * Let's say you want to port libssh from libcrypto of openssl to libfoo
28
 * you are going to spend hours removing every reference to SHA1_Update()
29
 * to libfoo_sha1_update after the work is finished, you're going to have
30
 * only this file to modify it's not needed to say that your modifications
31
 * are welcome.
32
 */
33
34
#include "config.h"
35
36
37
#include <stdlib.h>
38
#include <stdio.h>
39
#include <string.h>
40
41
#include "libssh/priv.h"
42
#include "libssh/session.h"
43
#include "libssh/crypto.h"
44
#include "libssh/wrapper.h"
45
#include "libssh/pki.h"
46
#include "libssh/poly1305.h"
47
#include "libssh/dh.h"
48
#ifdef WITH_GEX
49
#include "libssh/dh-gex.h"
50
#endif /* WITH_GEX */
51
#include "libssh/curve25519.h"
52
#include "libssh/kex-gss.h"
53
#include "libssh/ecdh.h"
54
#include "libssh/hybrid_mlkem.h"
55
#include "libssh/sntrup761.h"
56
57
static struct ssh_hmac_struct ssh_hmac_tab[] = {
58
  { "hmac-sha1",                     SSH_HMAC_SHA1,          false },
59
  { "hmac-sha2-256",                 SSH_HMAC_SHA256,        false },
60
  { "hmac-sha2-512",                 SSH_HMAC_SHA512,        false },
61
  { "hmac-md5",                      SSH_HMAC_MD5,           false },
62
  { "aead-poly1305",                 SSH_HMAC_AEAD_POLY1305, false },
63
  { "aead-gcm",                      SSH_HMAC_AEAD_GCM,      false },
64
  { "hmac-sha1-etm@openssh.com",     SSH_HMAC_SHA1,          true  },
65
  { "hmac-sha2-256-etm@openssh.com", SSH_HMAC_SHA256,        true  },
66
  { "hmac-sha2-512-etm@openssh.com", SSH_HMAC_SHA512,        true  },
67
  { "hmac-md5-etm@openssh.com",      SSH_HMAC_MD5,           true  },
68
#ifdef WITH_INSECURE_NONE
69
  { "none",                          SSH_HMAC_NONE,          false },
70
#endif /* WITH_INSECURE_NONE */
71
  { NULL,                            0,                      false }
72
};
73
74
11.7k
struct ssh_hmac_struct *ssh_get_hmactab(void) {
75
11.7k
  return ssh_hmac_tab;
76
11.7k
}
77
78
442k
size_t hmac_digest_len(enum ssh_hmac_e type) {
79
442k
  switch(type) {
80
32.6k
    case SSH_HMAC_SHA1:
81
32.6k
      return SHA_DIGEST_LEN;
82
10.8k
    case SSH_HMAC_SHA256:
83
10.8k
      return SHA256_DIGEST_LEN;
84
0
    case SSH_HMAC_SHA512:
85
0
      return SHA512_DIGEST_LEN;
86
0
    case SSH_HMAC_MD5:
87
0
      return MD5_DIGEST_LEN;
88
0
    case SSH_HMAC_AEAD_POLY1305:
89
0
      return POLY1305_TAGLEN;
90
0
    case SSH_HMAC_AEAD_GCM:
91
0
      return AES_GCM_TAGLEN;
92
398k
    default:
93
398k
      return 0;
94
442k
  }
95
442k
}
96
97
const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, bool etm)
98
0
{
99
0
  int i = 0;
100
0
  struct ssh_hmac_struct *ssh_hmactab = ssh_get_hmactab();
101
0
  while (ssh_hmactab[i].name &&
102
0
         ((ssh_hmactab[i].hmac_type != hmac_type) ||
103
0
          (ssh_hmactab[i].etm != etm))) {
104
0
    i++;
105
0
  }
106
0
  return ssh_hmactab[i].name;
107
0
}
108
109
/* it allocates a new cipher structure based on its offset into the global table */
110
23.5k
static struct ssh_cipher_struct *cipher_new(uint8_t offset) {
111
23.5k
  struct ssh_cipher_struct *cipher = NULL;
112
113
23.5k
  cipher = malloc(sizeof(struct ssh_cipher_struct));
114
23.5k
  if (cipher == NULL) {
115
0
    return NULL;
116
0
  }
117
118
  /* note the memcpy will copy the pointers : so, you shouldn't free them */
119
23.5k
  memcpy(cipher, &ssh_get_ciphertab()[offset], sizeof(*cipher));
120
121
23.5k
  return cipher;
122
23.5k
}
123
124
94.4k
void ssh_cipher_clear(struct ssh_cipher_struct *cipher){
125
#ifdef HAVE_LIBGCRYPT
126
    unsigned int i;
127
#endif
128
129
94.4k
    if (cipher == NULL) {
130
70.9k
        return;
131
70.9k
    }
132
133
#ifdef HAVE_LIBGCRYPT
134
    if (cipher->key) {
135
        for (i = 0; i < (cipher->keylen / sizeof(gcry_cipher_hd_t)); i++) {
136
            gcry_cipher_close(cipher->key[i]);
137
        }
138
        SAFE_FREE(cipher->key);
139
    }
140
#endif
141
142
23.5k
    if (cipher->cleanup != NULL) {
143
3.20k
        cipher->cleanup(cipher);
144
3.20k
    }
145
23.5k
}
146
147
94.4k
static void cipher_free(struct ssh_cipher_struct *cipher) {
148
94.4k
  ssh_cipher_clear(cipher);
149
94.4k
  SAFE_FREE(cipher);
150
94.4k
}
151
152
struct ssh_crypto_struct *crypto_new(void)
153
47.9k
{
154
47.9k
    struct ssh_crypto_struct *crypto = NULL;
155
156
47.9k
    crypto = calloc(1, sizeof(struct ssh_crypto_struct));
157
47.9k
    if (crypto == NULL) {
158
748
        return NULL;
159
748
    }
160
47.2k
    return crypto;
161
47.9k
}
162
163
void crypto_free(struct ssh_crypto_struct *crypto)
164
68.5k
{
165
68.5k
    size_t i;
166
167
68.5k
    if (crypto == NULL) {
168
21.2k
        return;
169
21.2k
    }
170
171
47.2k
    ssh_key_free(crypto->server_pubkey);
172
173
47.2k
    ssh_dh_cleanup(crypto);
174
47.2k
    bignum_safe_free(crypto->shared_secret);
175
47.2k
#ifdef HAVE_ECDH
176
47.2k
    SAFE_FREE(crypto->ecdh_client_pubkey);
177
47.2k
    SAFE_FREE(crypto->ecdh_server_pubkey);
178
47.2k
    if (crypto->ecdh_privkey != NULL) {
179
608
#ifdef HAVE_OPENSSL_ECC
180
608
#if OPENSSL_VERSION_NUMBER < 0x30000000L
181
608
        EC_KEY_free(crypto->ecdh_privkey);
182
#else
183
        EVP_PKEY_free(crypto->ecdh_privkey);
184
#endif /* OPENSSL_VERSION_NUMBER */
185
#elif defined HAVE_GCRYPT_ECC
186
        gcry_sexp_release(crypto->ecdh_privkey);
187
#elif defined HAVE_LIBMBEDCRYPTO
188
        mbedtls_ecp_keypair_free(crypto->ecdh_privkey);
189
        SAFE_FREE(crypto->ecdh_privkey);
190
#endif /* HAVE_LIBGCRYPT */
191
608
        crypto->ecdh_privkey = NULL;
192
608
    }
193
47.2k
#endif
194
47.2k
#ifdef HAVE_LIBCRYPTO
195
47.2k
    EVP_PKEY_free(crypto->curve25519_privkey);
196
#elif defined(HAVE_GCRYPT_CURVE25519)
197
    gcry_sexp_release(crypto->curve25519_privkey);
198
#endif
199
47.2k
    SAFE_FREE(crypto->dh_server_signature);
200
47.2k
    if (crypto->session_id != NULL) {
201
20.5k
        ssh_burn(crypto->session_id, crypto->session_id_len);
202
20.5k
        SAFE_FREE(crypto->session_id);
203
20.5k
    }
204
47.2k
    if (crypto->secret_hash != NULL) {
205
11.1k
        ssh_burn(crypto->secret_hash, crypto->digest_len);
206
11.1k
        SAFE_FREE(crypto->secret_hash);
207
11.1k
    }
208
47.2k
    compress_cleanup(crypto);
209
47.2k
    SAFE_FREE(crypto->encryptIV);
210
47.2k
    SAFE_FREE(crypto->decryptIV);
211
47.2k
    SAFE_FREE(crypto->encryptMAC);
212
47.2k
    SAFE_FREE(crypto->decryptMAC);
213
47.2k
    if (crypto->encryptkey != NULL) {
214
11.1k
        ssh_burn(crypto->encryptkey, crypto->out_cipher->keysize / 8);
215
11.1k
        SAFE_FREE(crypto->encryptkey);
216
11.1k
    }
217
47.2k
    if (crypto->decryptkey != NULL) {
218
11.1k
        ssh_burn(crypto->decryptkey, crypto->in_cipher->keysize / 8);
219
11.1k
        SAFE_FREE(crypto->decryptkey);
220
11.1k
    }
221
222
47.2k
    cipher_free(crypto->in_cipher);
223
47.2k
    cipher_free(crypto->out_cipher);
224
225
519k
    for (i = 0; i < SSH_KEX_METHODS; i++) {
226
472k
        SAFE_FREE(crypto->client_kex.methods[i]);
227
472k
        SAFE_FREE(crypto->server_kex.methods[i]);
228
472k
        SAFE_FREE(crypto->kex_methods[i]);
229
472k
    }
230
231
#ifdef HAVE_OPENSSL_MLKEM
232
    EVP_PKEY_free(crypto->mlkem_privkey);
233
#else
234
47.2k
    if (crypto->mlkem_privkey != NULL) {
235
1.42k
        ssh_burn(crypto->mlkem_privkey, crypto->mlkem_privkey_len);
236
1.42k
        SAFE_FREE(crypto->mlkem_privkey);
237
1.42k
        crypto->mlkem_privkey_len = 0;
238
1.42k
    }
239
47.2k
#endif
240
47.2k
    ssh_string_burn(crypto->hybrid_shared_secret);
241
47.2k
    ssh_string_free(crypto->mlkem_client_pubkey);
242
47.2k
    ssh_string_free(crypto->mlkem_ciphertext);
243
47.2k
    ssh_string_free(crypto->hybrid_client_init);
244
47.2k
    ssh_string_free(crypto->hybrid_server_reply);
245
47.2k
    ssh_string_free(crypto->hybrid_shared_secret);
246
247
47.2k
    ssh_burn(crypto, sizeof(struct ssh_crypto_struct));
248
249
47.2k
    SAFE_FREE(crypto);
250
47.2k
}
251
252
static void
253
compression_enable(ssh_session session,
254
                   enum ssh_crypto_direction_e direction,
255
                   bool delayed)
256
0
{
257
    /* The delayed compression is turned on AFTER authentication. This means
258
     * that we need to turn it on immediately in case of rekeying */
259
0
    if (delayed && !(session->flags & SSH_SESSION_FLAG_AUTHENTICATED)) {
260
0
        if (direction == SSH_DIRECTION_IN) {
261
0
            session->next_crypto->delayed_compress_in = 1;
262
0
        } else { /* SSH_DIRECTION_OUT */
263
0
            session->next_crypto->delayed_compress_out = 1;
264
0
        }
265
0
    } else {
266
0
        if (direction == SSH_DIRECTION_IN) {
267
0
            session->next_crypto->do_compress_in = 1;
268
0
        } else { /* SSH_DIRECTION_OUT */
269
0
            session->next_crypto->do_compress_out = 1;
270
0
        }
271
0
    }
272
0
}
273
274
static int crypt_set_algorithms2(ssh_session session)
275
2.51k
{
276
2.51k
    const char *wanted = NULL;
277
2.51k
    const char *method = NULL;
278
2.51k
    struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
279
2.51k
    struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab();
280
2.51k
    uint8_t i = 0;
281
2.51k
    int cmp;
282
283
    /*
284
     * We must scan the kex entries to find crypto algorithms and set their
285
     * appropriate structure.
286
     */
287
288
    /* out */
289
2.51k
    wanted = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
290
21.6k
    for (i = 0; i < 64 && ssh_ciphertab[i].name != NULL; ++i) {
291
21.6k
        cmp = strcmp(wanted, ssh_ciphertab[i].name);
292
21.6k
        if (cmp == 0) {
293
2.51k
            break;
294
2.51k
        }
295
21.6k
    }
296
297
2.51k
    if (ssh_ciphertab[i].name == NULL) {
298
0
        ssh_set_error(session, SSH_FATAL,
299
0
                "crypt_set_algorithms2: no crypto algorithm function found for %s",
300
0
                wanted);
301
0
        return SSH_ERROR;
302
0
    }
303
2.51k
    SSH_LOG(SSH_LOG_PACKET, "Set output algorithm to %s", wanted);
304
305
2.51k
    session->next_crypto->out_cipher = cipher_new(i);
306
2.51k
    if (session->next_crypto->out_cipher == NULL) {
307
0
        ssh_set_error_oom(session);
308
0
        return SSH_ERROR;
309
0
    }
310
311
2.51k
    if (session->next_crypto->out_cipher->aead_encrypt != NULL) {
312
        /* this cipher has integrated MAC */
313
0
        if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
314
0
            wanted = "aead-poly1305";
315
0
        } else {
316
0
            wanted = "aead-gcm";
317
0
        }
318
2.51k
    } else {
319
        /*
320
         * We must scan the kex entries to find hmac algorithms and set their
321
         * appropriate structure.
322
         */
323
324
        /* out */
325
2.51k
        wanted = session->next_crypto->kex_methods[SSH_MAC_C_S];
326
2.51k
    }
327
328
21.3k
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
329
21.3k
        cmp = strcmp(wanted, ssh_hmactab[i].name);
330
21.3k
        if (cmp == 0) {
331
2.51k
            break;
332
2.51k
        }
333
21.3k
    }
334
335
2.51k
    if (ssh_hmactab[i].name == NULL) {
336
0
        ssh_set_error(session, SSH_FATAL,
337
0
                "crypt_set_algorithms2: no hmac algorithm function found for %s",
338
0
                wanted);
339
0
        return SSH_ERROR;
340
0
    }
341
2.51k
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted);
342
343
2.51k
    session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
344
2.51k
    session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm;
345
346
    /* in */
347
2.51k
    wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
348
349
21.6k
    for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
350
21.6k
        cmp = strcmp(wanted, ssh_ciphertab[i].name);
351
21.6k
        if (cmp == 0) {
352
2.51k
            break;
353
2.51k
        }
354
21.6k
    }
355
356
2.51k
    if (ssh_ciphertab[i].name == NULL) {
357
0
        ssh_set_error(session, SSH_FATAL,
358
0
                "Crypt_set_algorithms: no crypto algorithm function found for %s",
359
0
                wanted);
360
0
        return SSH_ERROR;
361
0
    }
362
2.51k
    SSH_LOG(SSH_LOG_PACKET, "Set input algorithm to %s", wanted);
363
364
2.51k
    session->next_crypto->in_cipher = cipher_new(i);
365
2.51k
    if (session->next_crypto->in_cipher == NULL) {
366
0
        ssh_set_error_oom(session);
367
0
        return SSH_ERROR;
368
0
    }
369
370
2.51k
    if (session->next_crypto->in_cipher->aead_encrypt != NULL){
371
        /* this cipher has integrated MAC */
372
0
        if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
373
0
            wanted = "aead-poly1305";
374
0
        } else {
375
0
            wanted = "aead-gcm";
376
0
        }
377
2.51k
    } else {
378
        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
379
2.51k
        wanted = session->next_crypto->kex_methods[SSH_MAC_S_C];
380
2.51k
    }
381
382
21.3k
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
383
21.3k
        cmp = strcmp(wanted, ssh_hmactab[i].name);
384
21.3k
        if (cmp == 0) {
385
2.51k
            break;
386
2.51k
        }
387
21.3k
    }
388
389
2.51k
    if (ssh_hmactab[i].name == NULL) {
390
0
        ssh_set_error(session, SSH_FATAL,
391
0
                "crypt_set_algorithms2: no hmac algorithm function found for %s",
392
0
                wanted);
393
0
        return SSH_ERROR;
394
0
    }
395
2.51k
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", wanted);
396
397
2.51k
    session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
398
2.51k
    session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm;
399
400
    /* compression: client */
401
2.51k
    method = session->next_crypto->kex_methods[SSH_COMP_C_S];
402
2.51k
    cmp = strcmp(method, "zlib");
403
2.51k
    if (cmp == 0) {
404
0
        SSH_LOG(SSH_LOG_PACKET, "enabling C->S compression");
405
0
        compression_enable(session, SSH_DIRECTION_OUT, false);
406
0
    }
407
2.51k
    cmp = strcmp(method, "zlib@openssh.com");
408
2.51k
    if (cmp == 0) {
409
0
        SSH_LOG(SSH_LOG_PACKET, "enabling C->S delayed compression");
410
0
        compression_enable(session, SSH_DIRECTION_OUT, true);
411
0
    }
412
413
2.51k
    method = session->next_crypto->kex_methods[SSH_COMP_S_C];
414
2.51k
    cmp = strcmp(method, "zlib");
415
2.51k
    if (cmp == 0) {
416
0
        SSH_LOG(SSH_LOG_PACKET, "enabling S->C compression");
417
0
        compression_enable(session, SSH_DIRECTION_IN, false);
418
0
    }
419
2.51k
    cmp = strcmp(method, "zlib@openssh.com");
420
2.51k
    if (cmp == 0) {
421
0
        SSH_LOG(SSH_LOG_PACKET, "enabling S->C delayed compression");
422
0
        compression_enable(session, SSH_DIRECTION_IN, true);
423
0
    }
424
425
2.51k
    return SSH_OK;
426
2.51k
}
427
428
int crypt_set_algorithms_client(ssh_session session)
429
2.51k
{
430
2.51k
    return crypt_set_algorithms2(session);
431
2.51k
}
432
433
#ifdef WITH_SERVER
434
9.24k
int crypt_set_algorithms_server(ssh_session session){
435
9.24k
    const char *method = NULL;
436
9.24k
    uint8_t i = 0;
437
9.24k
    struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
438
9.24k
    struct ssh_hmac_struct   *ssh_hmactab=ssh_get_hmactab();
439
9.24k
    int cmp;
440
9.24k
    int rc;
441
442
9.24k
    if (session == NULL) {
443
0
        return SSH_ERROR;
444
0
    }
445
446
    /*
447
     * We must scan the kex entries to find crypto algorithms and set their
448
     * appropriate structure
449
     */
450
    /* out */
451
9.24k
    method = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
452
453
95.6k
    for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
454
95.6k
        cmp = strcmp(method, ssh_ciphertab[i].name);
455
95.6k
        if (cmp == 0) {
456
9.24k
          break;
457
9.24k
        }
458
95.6k
    }
459
460
9.24k
    if (ssh_ciphertab[i].name == NULL) {
461
0
        ssh_set_error(session,SSH_FATAL,"crypt_set_algorithms_server : "
462
0
                "no crypto algorithm function found for %s",method);
463
0
        return SSH_ERROR;
464
0
    }
465
9.24k
    SSH_LOG(SSH_LOG_PACKET,"Set output algorithm %s",method);
466
467
9.24k
    session->next_crypto->out_cipher = cipher_new(i);
468
9.24k
    if (session->next_crypto->out_cipher == NULL) {
469
0
        ssh_set_error_oom(session);
470
0
        return SSH_ERROR;
471
0
    }
472
473
9.24k
    if (session->next_crypto->out_cipher->aead_encrypt != NULL){
474
        /* this cipher has integrated MAC */
475
0
        if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
476
0
            method = "aead-poly1305";
477
0
        } else {
478
0
            method = "aead-gcm";
479
0
        }
480
9.24k
    } else {
481
        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
482
        /* out */
483
9.24k
        method = session->next_crypto->kex_methods[SSH_MAC_S_C];
484
9.24k
    }
485
    /* HMAC algorithm selection */
486
487
95.3k
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
488
95.3k
        cmp = strcmp(method, ssh_hmactab[i].name);
489
95.3k
        if (cmp == 0) {
490
9.24k
            break;
491
9.24k
        }
492
95.3k
    }
493
494
9.24k
    if (ssh_hmactab[i].name == NULL) {
495
0
      ssh_set_error(session, SSH_FATAL,
496
0
          "crypt_set_algorithms_server: no hmac algorithm function found for %s",
497
0
          method);
498
0
        return SSH_ERROR;
499
0
    }
500
9.24k
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", method);
501
502
9.24k
    session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
503
9.24k
    session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm;
504
505
    /* in */
506
9.24k
    method = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
507
508
95.6k
    for (i = 0; ssh_ciphertab[i].name; i++) {
509
95.6k
        cmp = strcmp(method, ssh_ciphertab[i].name);
510
95.6k
        if (cmp == 0) {
511
9.24k
            break;
512
9.24k
        }
513
95.6k
    }
514
515
9.24k
    if (ssh_ciphertab[i].name == NULL) {
516
0
        ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server :"
517
0
                "no crypto algorithm function found for %s",method);
518
0
        return SSH_ERROR;
519
0
    }
520
9.24k
    SSH_LOG(SSH_LOG_PACKET,"Set input algorithm %s",method);
521
522
9.24k
    session->next_crypto->in_cipher = cipher_new(i);
523
9.24k
    if (session->next_crypto->in_cipher == NULL) {
524
0
        ssh_set_error_oom(session);
525
0
        return SSH_ERROR;
526
0
    }
527
528
9.24k
    if (session->next_crypto->in_cipher->aead_encrypt != NULL){
529
        /* this cipher has integrated MAC */
530
0
        if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
531
0
            method = "aead-poly1305";
532
0
        } else {
533
0
            method = "aead-gcm";
534
0
        }
535
9.24k
    } else {
536
        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
537
9.24k
        method = session->next_crypto->kex_methods[SSH_MAC_C_S];
538
9.24k
    }
539
540
95.3k
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
541
95.3k
        cmp = strcmp(method, ssh_hmactab[i].name);
542
95.3k
        if (cmp == 0) {
543
9.24k
            break;
544
9.24k
        }
545
95.3k
    }
546
547
9.24k
    if (ssh_hmactab[i].name == NULL) {
548
0
      ssh_set_error(session, SSH_FATAL,
549
0
          "crypt_set_algorithms_server: no hmac algorithm function found for %s",
550
0
          method);
551
0
        return SSH_ERROR;
552
0
    }
553
9.24k
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", method);
554
555
9.24k
    session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
556
9.24k
    session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm;
557
558
    /* compression */
559
9.24k
    method = session->next_crypto->kex_methods[SSH_COMP_C_S];
560
9.24k
    cmp = strcmp(method, "zlib");
561
9.24k
    if (cmp == 0) {
562
0
        SSH_LOG(SSH_LOG_PACKET, "enabling C->S compression");
563
0
        compression_enable(session, SSH_DIRECTION_IN, false);
564
0
    }
565
9.24k
    cmp = strcmp(method, "zlib@openssh.com");
566
9.24k
    if (cmp == 0) {
567
0
        SSH_LOG(SSH_LOG_PACKET, "enabling C->S delayed compression");
568
0
        compression_enable(session, SSH_DIRECTION_IN, true);
569
0
    }
570
571
9.24k
    method = session->next_crypto->kex_methods[SSH_COMP_S_C];
572
9.24k
    cmp = strcmp(method, "zlib");
573
9.24k
    if (cmp == 0) {
574
0
        SSH_LOG(SSH_LOG_PACKET, "enabling S->C compression");
575
0
        compression_enable(session, SSH_DIRECTION_OUT, false);
576
0
    }
577
9.24k
    cmp = strcmp(method, "zlib@openssh.com");
578
9.24k
    if (cmp == 0) {
579
0
        SSH_LOG(SSH_LOG_PACKET, "enabling S->C delayed compression");
580
0
        compression_enable(session, SSH_DIRECTION_OUT, true);
581
0
    }
582
583
9.24k
    method = session->next_crypto->kex_methods[SSH_HOSTKEYS];
584
585
    /* For GSSAPI key exchange, hostkey algorithm may be "null" */
586
9.24k
    if (strcmp(method, "null") == 0) {
587
0
        session->srv.hostkey = SSH_KEYTYPE_UNKNOWN;
588
0
        session->srv.hostkey_digest = SSH_DIGEST_AUTO;
589
9.24k
    } else {
590
9.24k
        rc = ssh_key_type_and_hash_from_signature_name(
591
9.24k
            method,
592
9.24k
            &session->srv.hostkey,
593
9.24k
            &session->srv.hostkey_digest);
594
9.24k
        if (rc != SSH_OK) {
595
0
            ssh_set_error(session,
596
0
                          SSH_FATAL,
597
0
                          "unknown hostkey algorithm %s",
598
0
                          method);
599
0
            return SSH_ERROR;
600
0
        }
601
9.24k
    }
602
603
    /* setup DH key exchange type */
604
9.24k
    switch (session->next_crypto->kex_type) {
605
0
    case SSH_KEX_DH_GROUP1_SHA1:
606
0
    case SSH_KEX_DH_GROUP14_SHA1:
607
24
    case SSH_KEX_DH_GROUP14_SHA256:
608
49
    case SSH_KEX_DH_GROUP16_SHA512:
609
90
    case SSH_KEX_DH_GROUP18_SHA512:
610
90
      ssh_server_dh_init(session);
611
90
      break;
612
#ifdef WITH_GSSAPI
613
    case SSH_GSS_KEX_DH_GROUP14_SHA256:
614
    case SSH_GSS_KEX_DH_GROUP16_SHA512:
615
    case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
616
    case SSH_GSS_KEX_CURVE25519_SHA256:
617
        ssh_server_gss_kex_init(session);
618
        break;
619
#endif /* WITH_GSSAPI */
620
0
#ifdef WITH_GEX
621
0
    case SSH_KEX_DH_GEX_SHA1:
622
281
    case SSH_KEX_DH_GEX_SHA256:
623
281
      ssh_server_dhgex_init(session);
624
281
      break;
625
0
#endif /* WITH_GEX */
626
0
#ifdef HAVE_ECDH
627
61
    case SSH_KEX_ECDH_SHA2_NISTP256:
628
64
    case SSH_KEX_ECDH_SHA2_NISTP384:
629
72
    case SSH_KEX_ECDH_SHA2_NISTP521:
630
72
      ssh_server_ecdh_init(session);
631
72
      break;
632
0
#endif
633
0
#ifdef HAVE_CURVE25519
634
7.61k
    case SSH_KEX_CURVE25519_SHA256:
635
7.61k
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
636
7.61k
        ssh_server_curve25519_init(session);
637
7.61k
        break;
638
0
#endif
639
0
#ifdef HAVE_SNTRUP761
640
8
    case SSH_KEX_SNTRUP761X25519_SHA512:
641
40
    case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
642
40
        ssh_server_sntrup761x25519_init(session);
643
40
        break;
644
0
#endif
645
967
    case SSH_KEX_MLKEM768X25519_SHA256:
646
1.14k
    case SSH_KEX_MLKEM768NISTP256_SHA256:
647
#ifdef HAVE_MLKEM1024
648
    case SSH_KEX_MLKEM1024NISTP384_SHA384:
649
#endif
650
1.14k
        ssh_server_hybrid_mlkem_init(session);
651
1.14k
        break;
652
0
    default:
653
0
        ssh_set_error(session,
654
0
                      SSH_FATAL,
655
0
                      "crypt_set_algorithms_server: could not find init "
656
0
                      "handler for kex type %d",
657
0
                      session->next_crypto->kex_type);
658
0
        return SSH_ERROR;
659
9.24k
    }
660
9.24k
    return SSH_OK;
661
9.24k
}
662
663
#endif /* WITH_SERVER */