Native ML-KEM768 implementation

for cryptographic backends that do not have support for ML-KEM (old
OpenSSL and Gcrypt; MbedTLS).

Based on the libcrux implementation used in OpenSSH, taken from this
revision:

https://github.com/openssh/openssh-portable/blob/6aba700/libcrux_mlkem768_sha3.h

But refactored to separate C and header file to support testing and
removed unused functions (to make compiler happy).

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
This commit is contained in:
Jakub Jelen
2025-12-19 12:00:41 +01:00
parent 9780fa2f01
commit 34db488e4d
27 changed files with 9569 additions and 91 deletions

View File

@@ -105,6 +105,7 @@ set(libssh_SRCS
error.c
getpass.c
gzip.c
hybrid_mlkem.c
init.c
kdf.c
kex.c
@@ -115,6 +116,7 @@ set(libssh_SRCS
match.c
messages.c
misc.c
mlkem.c
options.c
packet.c
packet_cb.c
@@ -196,12 +198,12 @@ if (WITH_GCRYPT)
)
endif(HAVE_GCRYPT_CURVE25519)
if (HAVE_MLKEM)
if (HAVE_GCRYPT_MLKEM)
set(libssh_SRCS
${libssh_SRCS}
mlkem_gcrypt.c
)
endif (HAVE_MLKEM)
endif (HAVE_GCRYPT_MLKEM)
elseif (WITH_MBEDTLS)
set(libssh_SRCS
${libssh_SRCS}
@@ -255,12 +257,12 @@ else (WITH_GCRYPT)
chachapoly.c
)
endif (NOT HAVE_OPENSSL_EVP_CHACHA20)
if (HAVE_MLKEM)
if (HAVE_OPENSSL_MLKEM)
set(libssh_SRCS
${libssh_SRCS}
mlkem_crypto.c
)
endif (HAVE_MLKEM)
endif (HAVE_OPENSSL_MLKEM)
endif (WITH_GCRYPT)
if (WITH_SFTP)
@@ -313,13 +315,18 @@ if (NOT WITH_NACL)
endif()
endif (NOT WITH_NACL)
if (HAVE_MLKEM)
set(libssh_SRCS
${libssh_SRCS}
hybrid_mlkem.c
mlkem.c
)
endif (HAVE_MLKEM)
if (NOT HAVE_MLKEM1024)
set(libssh_SRCS
${libssh_SRCS}
mlkem_native.c
external/libcrux_mlkem768_sha3.c
)
if (WITH_WERROR_DECLARATION_AFTER_STATEMENT_FLAG)
set_source_files_properties(external/libcrux_mlkem768_sha3.c
PROPERTIES
COMPILE_FLAGS -Wno-error=declaration-after-statement)
endif()
endif()
if (WITH_FIDO2)
set(libssh_SRCS

View File

@@ -47,9 +47,7 @@
#include "libssh/misc.h"
#include "libssh/pki.h"
#include "libssh/kex.h"
#ifdef HAVE_MLKEM
#include "libssh/hybrid_mlkem.h"
#endif
#ifndef _WIN32
#ifdef HAVE_PTHREAD
@@ -308,13 +306,13 @@ int dh_handshake(ssh_session session)
rc = ssh_client_sntrup761x25519_init(session);
break;
#endif
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
rc = ssh_client_hybrid_mlkem_init(session);
break;
#endif
default:
rc = SSH_ERROR;
}

View File

@@ -53,13 +53,11 @@ static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) {
#endif /* OPENSSL_VERSION_NUMBER */
switch (kex_type) {
case SSH_KEX_ECDH_SHA2_NISTP256:
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768NISTP256_SHA256:
#endif
case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
return NISTP256;
case SSH_KEX_ECDH_SHA2_NISTP384:
#ifdef HAVE_MLKEM
#if HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
return NISTP384;

View File

@@ -41,12 +41,10 @@ static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type)
switch (kex_type) {
case SSH_KEX_ECDH_SHA2_NISTP256:
case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768NISTP256_SHA256:
#endif
return "NIST P-256";
case SSH_KEX_ECDH_SHA2_NISTP384:
#ifdef HAVE_MLKEM
#if HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
return "NIST P-384";

View File

@@ -38,16 +38,21 @@
#ifdef HAVE_ECDH
static mbedtls_ecp_group_id ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) {
if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256 ||
kex_type == SSH_GSS_KEX_ECDH_NISTP256_SHA256) {
static mbedtls_ecp_group_id
ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type)
{
switch (kex_type) {
case SSH_KEX_ECDH_SHA2_NISTP256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
return MBEDTLS_ECP_DP_SECP256R1;
} else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) {
case SSH_KEX_ECDH_SHA2_NISTP384:
return MBEDTLS_ECP_DP_SECP384R1;
} else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP521) {
case SSH_KEX_ECDH_SHA2_NISTP521:
return MBEDTLS_ECP_DP_SECP521R1;
default:
return MBEDTLS_ECP_DP_NONE;
}
return MBEDTLS_ECP_DP_NONE;
}

8896
src/external/libcrux_mlkem768_sha3.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -102,9 +102,11 @@ static ssh_string derive_ecdh_secret(ssh_session session)
case SSH_KEX_MLKEM768NISTP256_SHA256:
secret = derive_nist_curve_secret(session, NISTP256_SHARED_SECRET_SIZE);
break;
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
secret = derive_nist_curve_secret(session, NISTP384_SHARED_SECRET_SIZE);
break;
#endif
default:
ssh_set_error(session, SSH_FATAL, "Unsupported KEX type");
return NULL;
@@ -129,10 +131,12 @@ static int derive_hybrid_secret(ssh_session session,
digest = sha256;
digest_len = SHA256_DIGEST_LEN;
break;
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
digest = sha384;
digest_len = SHA384_DIGEST_LEN;
break;
#endif
default:
ssh_set_error(session, SSH_FATAL, "Unsupported KEX type");
goto cleanup;
@@ -244,7 +248,9 @@ int ssh_client_hybrid_mlkem_init(ssh_session session)
crypto->curve25519_client_pubkey);
break;
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
rc = ssh_ecdh_init(session);
if (rc != SSH_OK) {
ssh_set_error(session,
@@ -435,7 +441,9 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_hybrid_mlkem_reply)
#endif
break;
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
ecdh_server_pubkey_size = ssh_buffer_get_len(server_reply_buffer);
ssh_string_free(crypto->ecdh_server_pubkey);
crypto->ecdh_server_pubkey = ssh_string_new(ecdh_server_pubkey_size);
@@ -585,7 +593,9 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_hybrid_mlkem_init)
#endif
break;
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
rc = ssh_ecdh_init(session);
if (rc != SSH_OK) {
ssh_set_error(session,
@@ -682,7 +692,9 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_hybrid_mlkem_init)
#endif
break;
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
ecdh_client_pubkey_size = ssh_buffer_get_len(client_init_buffer);
ssh_string_free(crypto->ecdh_client_pubkey);
crypto->ecdh_client_pubkey = ssh_string_new(ecdh_client_pubkey_size);
@@ -760,7 +772,9 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_hybrid_mlkem_init)
crypto->curve25519_server_pubkey);
break;
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
rc = ssh_buffer_pack(server_reply_buffer,
"PP",
ssh_string_len(crypto->mlkem_ciphertext),

View File

@@ -41,9 +41,7 @@
#include "libssh/string.h"
#include "libssh/curve25519.h"
#include "libssh/sntrup761.h"
#ifdef HAVE_MLKEM
#include "libssh/hybrid_mlkem.h"
#endif
#include "libssh/kex-gss.h"
#include "libssh/knownhosts.h"
#include "libssh/misc.h"
@@ -107,13 +105,14 @@
#define SNTRUP761X25519 ""
#endif /* HAVE_SNTRUP761 */
#ifdef HAVE_MLKEM
#ifdef HAVE_MLKEM1024
#define HYBRID_MLKEM "mlkem768x25519-sha256," \
"mlkem768nistp256-sha256," \
"mlkem1024nistp384-sha384,"
#else
#define HYBRID_MLKEM ""
#endif /* HAVE_MLKEM */
#define HYBRID_MLKEM "mlkem768x25519-sha256," \
"mlkem768nistp256-sha256,"
#endif /* HAVE_MLKEM1024 */
#ifdef HAVE_ECC
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
@@ -996,11 +995,11 @@ kex_select_kex_type(const char *kex)
return SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM;
} else if (strcmp(kex, "sntrup761x25519-sha512") == 0) {
return SSH_KEX_SNTRUP761X25519_SHA512;
#ifdef HAVE_MLKEM
} else if (strcmp(kex, "mlkem768x25519-sha256") == 0) {
return SSH_KEX_MLKEM768X25519_SHA256;
} else if (strcmp(kex, "mlkem768nistp256-sha256") == 0) {
return SSH_KEX_MLKEM768NISTP256_SHA256;
#ifdef HAVE_MLKEM1024
} else if (strcmp(kex, "mlkem1024nistp384-sha384") == 0) {
return SSH_KEX_MLKEM1024NISTP384_SHA384;
#endif
@@ -1058,13 +1057,13 @@ static void revert_kex_callbacks(ssh_session session)
ssh_client_sntrup761x25519_remove_callbacks(session);
break;
#endif
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
ssh_client_hybrid_mlkem_remove_callbacks(session);
break;
#endif
}
}
@@ -1664,10 +1663,11 @@ int ssh_make_sessionid(ssh_session session)
}
break;
#endif /* HAVE_SNTRUP761 */
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
rc = ssh_buffer_pack(buf,
"SS",
session->next_crypto->hybrid_client_init,
@@ -1679,7 +1679,6 @@ int ssh_make_sessionid(ssh_session session)
goto error;
}
break;
#endif /* HAVE_MLKEM */
default:
/* Handle unsupported kex types - this should not happen in normal operation */
rc = SSH_ERROR;
@@ -1694,13 +1693,13 @@ int ssh_make_sessionid(ssh_session session)
session->next_crypto->shared_secret,
SHA512_DIGEST_LEN);
break;
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
rc = ssh_buffer_pack(buf, "S", session->next_crypto->hybrid_shared_secret);
break;
#endif /* HAVE_MLKEM */
default:
rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
break;
@@ -1737,10 +1736,8 @@ int ssh_make_sessionid(ssh_session session)
case SSH_KEX_ECDH_SHA2_NISTP256:
case SSH_KEX_CURVE25519_SHA256:
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
#endif
case SSH_GSS_KEX_ECDH_NISTP256_SHA256:
case SSH_GSS_KEX_CURVE25519_SHA256:
#ifdef WITH_GEX
@@ -1757,7 +1754,7 @@ int ssh_make_sessionid(ssh_session session)
session->next_crypto->secret_hash);
break;
case SSH_KEX_ECDH_SHA2_NISTP384:
#ifdef HAVE_MLKEM
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
session->next_crypto->digest_len = SHA384_DIGEST_LENGTH;
@@ -1925,13 +1922,13 @@ int ssh_generate_session_keys(ssh_session session)
k_string = ssh_make_padded_bignum_string(crypto->shared_secret,
crypto->digest_len);
break;
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
k_string = ssh_string_copy(crypto->hybrid_shared_secret);
break;
#endif /* HAVE_MLKEM */
default:
k_string = ssh_make_bignum_string(crypto->shared_secret);
break;

View File

@@ -30,8 +30,10 @@ const struct mlkem_type_info *kex_type_to_mlkem_info(enum ssh_key_exchange_e kex
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
return &MLKEM768_INFO;
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
return &MLKEM1024_INFO;
#endif
default:
return NULL;
}

202
src/mlkem_native.c Normal file
View File

@@ -0,0 +1,202 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 by Red Hat, Inc.
*
* Author: Jakub Jelen <jjelen@redhat.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "config.h"
#include "libssh/crypto.h"
#include "libssh/mlkem.h"
#include "libssh/mlkem_native.h"
#include "libssh/session.h"
#define crypto_kem_mlkem768_PUBLICKEYBYTES 1184
#define crypto_kem_mlkem768_SECRETKEYBYTES 2400
#define crypto_kem_mlkem768_CIPHERTEXTBYTES 1088
const struct mlkem_type_info MLKEM768_INFO = {
.pubkey_size = crypto_kem_mlkem768_PUBLICKEYBYTES,
.privkey_size = crypto_kem_mlkem768_SECRETKEYBYTES,
.ciphertext_size = crypto_kem_mlkem768_CIPHERTEXTBYTES,
};
int ssh_mlkem_init(ssh_session session)
{
int ret = SSH_ERROR;
struct ssh_crypto_struct *crypto = session->next_crypto;
const struct mlkem_type_info *mlkem_info = NULL;
unsigned char rnd[LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN];
struct libcrux_mlkem768_keypair keypair;
int err;
mlkem_info = kex_type_to_mlkem_info(crypto->kex_type);
if (mlkem_info == NULL) {
SSH_LOG(SSH_LOG_WARNING, "Unknown ML-KEM type");
goto cleanup;
}
err = ssh_get_random(rnd, sizeof(rnd), 0);
if (err != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to generate random data for ML-KEM keygen");
goto cleanup;
}
keypair = libcrux_ml_kem_mlkem768_portable_generate_key_pair(rnd);
if (ssh_string_len(crypto->mlkem_client_pubkey) < mlkem_info->pubkey_size) {
SSH_STRING_FREE(crypto->mlkem_client_pubkey);
}
if (crypto->mlkem_client_pubkey == NULL) {
crypto->mlkem_client_pubkey = ssh_string_new(mlkem_info->pubkey_size);
if (crypto->mlkem_client_pubkey == NULL) {
ssh_set_error_oom(session);
goto cleanup;
}
}
err = ssh_string_fill(crypto->mlkem_client_pubkey,
keypair.pk.value,
mlkem_info->pubkey_size);
if (err) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to fill the string with client pubkey");
goto cleanup;
}
if (crypto->mlkem_privkey == NULL) {
crypto->mlkem_privkey = malloc(mlkem_info->privkey_size);
if (crypto->mlkem_privkey == NULL) {
ssh_set_error_oom(session);
goto cleanup;
}
}
memcpy(crypto->mlkem_privkey, keypair.sk.value, mlkem_info->privkey_size);
crypto->mlkem_privkey_len = mlkem_info->privkey_size;
ret = SSH_OK;
cleanup:
ssh_burn(&keypair, sizeof(keypair));
ssh_burn(rnd, sizeof(rnd));
return ret;
}
int ssh_mlkem_encapsulate(ssh_session session,
ssh_mlkem_shared_secret shared_secret)
{
int ret = SSH_ERROR;
const struct mlkem_type_info *mlkem_info = NULL;
struct ssh_crypto_struct *crypto = session->next_crypto;
const unsigned char *pubkey_data = NULL;
ssh_string pubkey = crypto->mlkem_client_pubkey;
struct libcrux_mlkem768_enc_result enc;
struct libcrux_mlkem768_pk mlkem_pub = {0};
unsigned char rnd[LIBCRUX_ML_KEM_ENC_PRNG_LEN];
int err;
if (pubkey == NULL) {
SSH_LOG(SSH_LOG_WARNING, "Missing pubkey in session");
return SSH_ERROR;
}
mlkem_info = kex_type_to_mlkem_info(crypto->kex_type);
if (mlkem_info == NULL) {
SSH_LOG(SSH_LOG_WARNING, "Unknown ML-KEM type");
return SSH_ERROR;
}
pubkey_data = ssh_string_data(pubkey);
memcpy(mlkem_pub.value, pubkey_data, mlkem_info->pubkey_size);
err = libcrux_ml_kem_mlkem768_portable_validate_public_key(&mlkem_pub);
if (err == 0) {
SSH_LOG(SSH_LOG_WARNING, "Invalid public key");
return SSH_ERROR;
}
err = ssh_get_random(rnd, sizeof(rnd), 0);
if (err != 1) {
SSH_LOG(SSH_LOG_WARNING,
"Failed to generate random data for ML-KEM keygen");
goto cleanup;
}
enc = libcrux_ml_kem_mlkem768_portable_encapsulate(&mlkem_pub, rnd);
if (ssh_string_len(crypto->mlkem_ciphertext) < mlkem_info->ciphertext_size) {
SSH_STRING_FREE(crypto->mlkem_ciphertext);
}
if (crypto->mlkem_ciphertext == NULL) {
crypto->mlkem_ciphertext = ssh_string_new(mlkem_info->ciphertext_size);
if (crypto->mlkem_ciphertext == NULL) {
ssh_set_error_oom(session);
goto cleanup;
}
}
err = ssh_string_fill(crypto->mlkem_ciphertext,
enc.fst.value,
sizeof(enc.fst.value));
if (err != SSH_OK) {
SSH_LOG(SSH_LOG_WARNING, "Failed to fill the string with ciphertext");
goto cleanup;
}
memcpy(shared_secret, enc.snd, sizeof(enc.snd));
ret = SSH_OK;
cleanup:
ssh_burn(rnd, sizeof(rnd));
ssh_burn(&enc, sizeof(enc));
return ret;
}
int ssh_mlkem_decapsulate(const ssh_session session,
ssh_mlkem_shared_secret shared_secret)
{
const struct mlkem_type_info *mlkem_info = NULL;
struct ssh_crypto_struct *crypto = session->next_crypto;
ssh_string ciphertext = NULL;
unsigned char *ciphertext_data = NULL;
struct libcrux_mlkem768_sk mlkem_priv = {0};
struct libcrux_mlkem768_ciphertext mlkem_ciphertext = {0};
mlkem_info = kex_type_to_mlkem_info(crypto->kex_type);
if (mlkem_info == NULL) {
SSH_LOG(SSH_LOG_WARNING, "Unknown ML-KEM type");
return SSH_ERROR;
}
ciphertext = crypto->mlkem_ciphertext;
if (ciphertext == NULL) {
SSH_LOG(SSH_LOG_WARNING, "Missing ciphertext in session");
return SSH_ERROR;
}
ciphertext_data = ssh_string_data(ciphertext);
memcpy(mlkem_ciphertext.value,
ciphertext_data,
sizeof(mlkem_ciphertext.value));
memcpy(mlkem_priv.value, crypto->mlkem_privkey, crypto->mlkem_privkey_len);
libcrux_ml_kem_mlkem768_portable_decapsulate(&mlkem_priv,
&mlkem_ciphertext,
shared_secret);
return SSH_OK;
}

View File

@@ -505,14 +505,14 @@ const char* ssh_get_kex_algo(ssh_session session) {
return "sntrup761x25519-sha512@openssh.com";
case SSH_KEX_SNTRUP761X25519_SHA512:
return "sntrup761x25519-sha512";
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
return "mlkem768x25519-sha256";
case SSH_KEX_MLKEM768NISTP256_SHA256:
return "mlkem768nistp256-sha256";
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
return "mlkem1024nistp384-sha384";
#endif /* HAVE_MLKEM */
#endif /* HAVE_MLKEM1024 */
#ifdef WITH_GEX
case SSH_KEX_DH_GEX_SHA1:
return "diffie-hellman-group-exchange-sha1";

View File

@@ -51,10 +51,8 @@
#include "libssh/curve25519.h"
#include "libssh/kex-gss.h"
#include "libssh/ecdh.h"
#include "libssh/sntrup761.h"
#ifdef HAVE_MLKEM
#include "libssh/hybrid_mlkem.h"
#endif
#include "libssh/sntrup761.h"
static struct ssh_hmac_struct ssh_hmac_tab[] = {
{ "hmac-sha1", SSH_HMAC_SHA1, false },
@@ -230,15 +228,14 @@ void crypto_free(struct ssh_crypto_struct *crypto)
SAFE_FREE(crypto->kex_methods[i]);
}
#ifdef HAVE_MLKEM
#ifdef HAVE_LIBGCRYPT
#ifdef HAVE_OPENSSL_MLKEM
EVP_PKEY_free(crypto->mlkem_privkey);
#else
if (crypto->mlkem_privkey != NULL) {
ssh_burn(crypto->mlkem_privkey, crypto->mlkem_privkey_len);
SAFE_FREE(crypto->mlkem_privkey);
crypto->mlkem_privkey_len = 0;
}
#else
EVP_PKEY_free(crypto->mlkem_privkey);
#endif
ssh_string_burn(crypto->hybrid_shared_secret);
ssh_string_free(crypto->mlkem_client_pubkey);
@@ -246,7 +243,6 @@ void crypto_free(struct ssh_crypto_struct *crypto)
ssh_string_free(crypto->hybrid_client_init);
ssh_string_free(crypto->hybrid_server_reply);
ssh_string_free(crypto->hybrid_shared_secret);
#endif
ssh_burn(crypto, sizeof(struct ssh_crypto_struct));
@@ -629,13 +625,13 @@ int crypt_set_algorithms_server(ssh_session session){
ssh_server_sntrup761x25519_init(session);
break;
#endif
#ifdef HAVE_MLKEM
case SSH_KEX_MLKEM768X25519_SHA256:
case SSH_KEX_MLKEM768NISTP256_SHA256:
#ifdef HAVE_MLKEM1024
case SSH_KEX_MLKEM1024NISTP384_SHA384:
#endif
ssh_server_hybrid_mlkem_init(session);
break;
#endif
default:
ssh_set_error(session,
SSH_FATAL,