mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 04:10:39 +09:00
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:
1
.clang-format-ignore
Normal file
1
.clang-format-ignore
Normal file
@@ -0,0 +1 @@
|
||||
src/external/*
|
||||
@@ -104,9 +104,10 @@ if (OPENSSL_FOUND)
|
||||
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
||||
check_function_exists(EVP_chacha20 HAVE_OPENSSL_EVP_CHACHA20)
|
||||
|
||||
# Check for ML-KEM768 availability (OpenSSL 3.5+)
|
||||
# Check for ML-KEM availability (OpenSSL 3.5+)
|
||||
if (OPENSSL_VERSION VERSION_GREATER_EQUAL "3.5.0")
|
||||
set(HAVE_MLKEM 1)
|
||||
set(HAVE_OPENSSL_MLKEM 1)
|
||||
set(HAVE_MLKEM1024 1)
|
||||
endif ()
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
@@ -235,7 +236,8 @@ if (GCRYPT_FOUND)
|
||||
set(HAVE_GCRYPT_CURVE25519 1)
|
||||
endif (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
|
||||
if (GCRYPT_VERSION VERSION_GREATER_EQUAL "1.10.1")
|
||||
set(HAVE_MLKEM 1)
|
||||
set(HAVE_GCRYPT_MLKEM 1)
|
||||
set(HAVE_MLKEM1024 1)
|
||||
endif ()
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
|
||||
@@ -194,8 +194,14 @@
|
||||
/* Define to 1 if we have support for blowfish */
|
||||
#cmakedefine HAVE_BLOWFISH 1
|
||||
|
||||
/* Define to 1 if we have support for ML-KEM */
|
||||
#cmakedefine HAVE_MLKEM 1
|
||||
/* Define to 1 if we have support for ML-KEM in libgcrypt */
|
||||
#cmakedefine HAVE_GCRYPT_MLKEM 1
|
||||
|
||||
/* Define to 1 if we have support for ML-KEM in OpenSSL */
|
||||
#cmakedefine HAVE_OPENSSL_MLKEM 1
|
||||
|
||||
/* Define to 1 if we have support for ML-KEM1024 in either backend */
|
||||
#cmakedefine HAVE_MLKEM1024 1
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
|
||||
@@ -87,14 +87,14 @@ enum ssh_key_exchange_e {
|
||||
SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM,
|
||||
/* sntrup761x25519-sha512 */
|
||||
SSH_KEX_SNTRUP761X25519_SHA512,
|
||||
#ifdef HAVE_MLKEM
|
||||
/* mlkem768x25519-sha256 */
|
||||
SSH_KEX_MLKEM768X25519_SHA256,
|
||||
/* mlkem768nistp256-sha256 */
|
||||
SSH_KEX_MLKEM768NISTP256_SHA256,
|
||||
#ifdef HAVE_MLKEM1024
|
||||
/* mlkem1024nistp384-sha384 */
|
||||
SSH_KEX_MLKEM1024NISTP384_SHA384,
|
||||
#endif /* HAVE_MLKEM */
|
||||
#endif /* HAVE_MLKEM1024 */
|
||||
/* gss-group14-sha256-* */
|
||||
SSH_GSS_KEX_DH_GROUP14_SHA256,
|
||||
/* gss-group16-sha512-* */
|
||||
@@ -159,16 +159,14 @@ struct ssh_crypto_struct {
|
||||
ssh_curve25519_pubkey curve25519_client_pubkey;
|
||||
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||
#endif
|
||||
#ifdef HAVE_MLKEM
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#ifdef HAVE_OPENSSL_MLKEM
|
||||
EVP_PKEY *mlkem_privkey;
|
||||
#else
|
||||
unsigned char *mlkem_privkey;
|
||||
size_t mlkem_privkey_len;
|
||||
#else
|
||||
EVP_PKEY *mlkem_privkey;
|
||||
#endif
|
||||
ssh_string mlkem_client_pubkey;
|
||||
ssh_string mlkem_ciphertext;
|
||||
#endif
|
||||
#ifdef HAVE_SNTRUP761
|
||||
ssh_sntrup761_privkey sntrup761_privkey;
|
||||
ssh_sntrup761_pubkey sntrup761_client_pubkey;
|
||||
|
||||
@@ -36,16 +36,20 @@ extern "C" {
|
||||
struct mlkem_type_info {
|
||||
size_t pubkey_size;
|
||||
size_t ciphertext_size;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#ifdef HAVE_GCRYPT_MLKEM
|
||||
size_t privkey_size;
|
||||
enum gcry_kem_algos alg;
|
||||
#else
|
||||
#elif defined(HAVE_OPENSSL_MLKEM)
|
||||
const char *name;
|
||||
#else
|
||||
size_t privkey_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern const struct mlkem_type_info MLKEM768_INFO;
|
||||
#ifdef HAVE_MLKEM1024
|
||||
extern const struct mlkem_type_info MLKEM1024_INFO;
|
||||
#endif
|
||||
|
||||
#define MLKEM_SHARED_SECRET_SIZE 32
|
||||
|
||||
|
||||
127
include/libssh/mlkem_native.h
Normal file
127
include/libssh/mlkem_native.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MLKEM_NATIVE_H_
|
||||
#define MLKEM_NATIVE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
A monomorphic instance of libcrux_ml_kem.types.MlKemPrivateKey
|
||||
with const generics
|
||||
- $2400size_t
|
||||
*/
|
||||
typedef struct libcrux_ml_kem_types_MlKemPrivateKey_d9_s {
|
||||
uint8_t value[2400U];
|
||||
} libcrux_ml_kem_types_MlKemPrivateKey_d9;
|
||||
|
||||
/**
|
||||
A monomorphic instance of libcrux_ml_kem.types.MlKemPublicKey
|
||||
with const generics
|
||||
- $1184size_t
|
||||
*/
|
||||
typedef struct libcrux_ml_kem_types_MlKemPublicKey_30_s {
|
||||
uint8_t value[1184U];
|
||||
} libcrux_ml_kem_types_MlKemPublicKey_30;
|
||||
|
||||
typedef struct libcrux_ml_kem_mlkem768_MlKem768KeyPair_s {
|
||||
libcrux_ml_kem_types_MlKemPrivateKey_d9 sk;
|
||||
libcrux_ml_kem_types_MlKemPublicKey_30 pk;
|
||||
} libcrux_ml_kem_mlkem768_MlKem768KeyPair;
|
||||
|
||||
typedef struct libcrux_ml_kem_mlkem768_MlKem768Ciphertext_s {
|
||||
uint8_t value[1088U];
|
||||
} libcrux_ml_kem_mlkem768_MlKem768Ciphertext;
|
||||
|
||||
/**
|
||||
A monomorphic instance of K.
|
||||
with types libcrux_ml_kem_types_MlKemCiphertext[[$1088size_t]],
|
||||
uint8_t[32size_t]
|
||||
|
||||
*/
|
||||
typedef struct tuple_c2_s {
|
||||
libcrux_ml_kem_mlkem768_MlKem768Ciphertext fst;
|
||||
uint8_t snd[32U];
|
||||
} tuple_c2;
|
||||
|
||||
/**
|
||||
Generate ML-KEM 768 Key Pair
|
||||
*/
|
||||
libcrux_ml_kem_mlkem768_MlKem768KeyPair
|
||||
libcrux_ml_kem_mlkem768_portable_generate_key_pair(uint8_t randomness[64U]);
|
||||
|
||||
/**
|
||||
Validate a public key.
|
||||
|
||||
Returns `true` if valid, and `false` otherwise.
|
||||
*/
|
||||
bool libcrux_ml_kem_mlkem768_portable_validate_public_key(
|
||||
libcrux_ml_kem_types_MlKemPublicKey_30 *public_key);
|
||||
|
||||
/**
|
||||
Encapsulate ML-KEM 768
|
||||
|
||||
Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple.
|
||||
The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`]
|
||||
bytes of `randomness`.
|
||||
*/
|
||||
tuple_c2 libcrux_ml_kem_mlkem768_portable_encapsulate(
|
||||
libcrux_ml_kem_types_MlKemPublicKey_30 *public_key,
|
||||
uint8_t randomness[32U]);
|
||||
|
||||
/**
|
||||
Decapsulate ML-KEM 768
|
||||
|
||||
Generates an [`MlKemSharedSecret`].
|
||||
The input is a reference to an [`MlKem768PrivateKey`] and an
|
||||
[`MlKem768Ciphertext`].
|
||||
*/
|
||||
void libcrux_ml_kem_mlkem768_portable_decapsulate(
|
||||
libcrux_ml_kem_types_MlKemPrivateKey_d9 *private_key,
|
||||
libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext,
|
||||
uint8_t ret[32U]);
|
||||
|
||||
/* rename some types to be a bit more ergonomic */
|
||||
#define libcrux_mlkem768_keypair libcrux_ml_kem_mlkem768_MlKem768KeyPair_s
|
||||
#define libcrux_mlkem768_pk libcrux_ml_kem_types_MlKemPublicKey_30_s
|
||||
#define libcrux_mlkem768_sk libcrux_ml_kem_types_MlKemPrivateKey_d9_s
|
||||
#define libcrux_mlkem768_ciphertext libcrux_ml_kem_mlkem768_MlKem768Ciphertext_s
|
||||
#define libcrux_mlkem768_enc_result tuple_c2_s
|
||||
/* defines for PRNG inputs */
|
||||
#define LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN 64U
|
||||
#define LIBCRUX_ML_KEM_ENC_PRNG_LEN 32
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MLKEM_NATIVE_H_ */
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
8896
src/external/libcrux_mlkem768_sha3.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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),
|
||||
|
||||
31
src/kex.c
31
src/kex.c
@@ -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;
|
||||
|
||||
@@ -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
202
src/mlkem_native.c
Normal 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;
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -90,6 +90,11 @@ if (CLIENT_TESTING)
|
||||
"-Wl,--wrap=sntrup761_keypair"
|
||||
"-Wl,--wrap=sntrup761_enc"
|
||||
"-Wl,--wrap=sntrup761_dec")
|
||||
list(APPEND WRAP_SYMBOLS
|
||||
"-Wl,--wrap=libcrux_ml_kem_mlkem768_portable_generate_key_pair"
|
||||
"-Wl,--wrap=libcrux_ml_kem_mlkem768_portable_validate_public_key"
|
||||
"-Wl,--wrap=libcrux_ml_kem_mlkem768_portable_encapsulate"
|
||||
"-Wl,--wrap=libcrux_ml_kem_mlkem768_portable_decapsulate")
|
||||
|
||||
add_library(${TORTURE_SHARED_LIBRARY}
|
||||
SHARED
|
||||
|
||||
@@ -752,7 +752,7 @@ torture_algorithms_ecdh_sntrup761x25519_sha512(void **state)
|
||||
}
|
||||
#endif /* OPENSSH_SNTRUP761X25519_SHA512 */
|
||||
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM768X25519_SHA256)
|
||||
#if defined(OPENSSH_MLKEM768X25519_SHA256)
|
||||
static void torture_algorithms_ecdh_mlkem768x25519_sha256(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
@@ -766,9 +766,9 @@ static void torture_algorithms_ecdh_mlkem768x25519_sha256(void **state)
|
||||
NULL /*cipher*/,
|
||||
NULL /*hmac*/);
|
||||
}
|
||||
#endif /* HAVE_MLKEM && defined(OPENSSH_MLKEM768X25519_SHA256) */
|
||||
#endif /* defined(OPENSSH_MLKEM768X25519_SHA256) */
|
||||
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM768NISTP256_SHA256)
|
||||
#if defined(OPENSSH_MLKEM768NISTP256_SHA256)
|
||||
static void torture_algorithms_ecdh_mlkem768nistp256_sha256(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
@@ -782,9 +782,9 @@ static void torture_algorithms_ecdh_mlkem768nistp256_sha256(void **state)
|
||||
NULL /*cipher*/,
|
||||
NULL /*hmac*/);
|
||||
}
|
||||
#endif /* HAVE_MLKEM && defined(OPENSSH_MLKEM768NISTP256_SHA256) */
|
||||
#endif /* defined(OPENSSH_MLKEM768NISTP256_SHA256) */
|
||||
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM1024NISTP384_SHA384)
|
||||
#if defined(HAVE_MLKEM1024) && defined(OPENSSH_MLKEM1024NISTP384_SHA384)
|
||||
static void torture_algorithms_ecdh_mlkem1024nistp384_sha384(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
@@ -798,7 +798,7 @@ static void torture_algorithms_ecdh_mlkem1024nistp384_sha384(void **state)
|
||||
NULL /*cipher*/,
|
||||
NULL /*hmac*/);
|
||||
}
|
||||
#endif /* HAVE_MLKEM && defined(OPENSSH_MLKEM1024NISTP384_SHA384) */
|
||||
#endif /* HAVE_MLKEM1024 && defined(OPENSSH_MLKEM1024NISTP384_SHA384) */
|
||||
|
||||
static void torture_algorithms_dh_group1(void **state) {
|
||||
struct torture_state *s = *state;
|
||||
@@ -1077,21 +1077,21 @@ int torture_run_tests(void) {
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#endif /* OPENSSH_SNTRUP761X25519_SHA512 */
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM768X25519_SHA256)
|
||||
#if defined(OPENSSH_MLKEM768X25519_SHA256)
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_mlkem768x25519_sha256,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#endif /* HAVE_MLKEM && defined(OPENSSH_MLKEM768X25519_SHA256) */
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM768NISTP256_SHA256)
|
||||
#endif /* defined(OPENSSH_MLKEM768X25519_SHA256) */
|
||||
#if defined(OPENSSH_MLKEM768NISTP256_SHA256)
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_mlkem768nistp256_sha256,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#endif /* defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM768NISTP256_SHA256) */
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM1024NISTP384_SHA384)
|
||||
#endif /* defined(OPENSSH_MLKEM768NISTP256_SHA256) */
|
||||
#if defined(HAVE_MLKEM1024) && defined(OPENSSH_MLKEM1024NISTP384_SHA384)
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_mlkem1024nistp384_sha384,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#endif /* defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM1024NISTP384_SHA384) */
|
||||
#endif /* defined(HAVE_MLKEM1024) && defined(OPENSSH_MLKEM1024NISTP384_SHA384) */
|
||||
#if defined(HAVE_ECC)
|
||||
cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_sha2_nistp256,
|
||||
session_setup,
|
||||
|
||||
@@ -88,8 +88,19 @@ target_link_libraries(sntrup761_override
|
||||
set(SNTRUP761_OVERRIDE_LIBRARY
|
||||
${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}sntrup761_override${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
# mlkem768_override
|
||||
add_library(mlkem768_override SHARED
|
||||
mlkem768_override.c
|
||||
${libssh_SOURCE_DIR}/src/external/libcrux_mlkem768_sha3.c
|
||||
${override_src}
|
||||
)
|
||||
target_link_libraries(mlkem768_override
|
||||
PRIVATE ${override_libs})
|
||||
set(MLKEM768_OVERRIDE_LIBRARY
|
||||
${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}mlkem768_override${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
set(OVERRIDE_LIBRARIES
|
||||
${CHACHA20_OVERRIDE_LIBRARY}:${POLY1305_OVERRIDE_LIBRARY}:${ED25519_OVERRIDE_LIBRARY}:${CURVE25519_OVERRIDE_LIBRARY}:${SNTRUP761_OVERRIDE_LIBRARY}
|
||||
${CHACHA20_OVERRIDE_LIBRARY}:${POLY1305_OVERRIDE_LIBRARY}:${ED25519_OVERRIDE_LIBRARY}:${CURVE25519_OVERRIDE_LIBRARY}:${SNTRUP761_OVERRIDE_LIBRARY}:${MLKEM768_OVERRIDE_LIBRARY}
|
||||
)
|
||||
|
||||
if (WITH_MBEDTLS)
|
||||
@@ -107,6 +118,7 @@ if (WITH_MBEDTLS)
|
||||
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_ED25519=1")
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_SNTRUP761=1")
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_MLKEM=1")
|
||||
elseif (WITH_GCRYPT)
|
||||
if (HAVE_GCRYPT_CHACHA_POLY)
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=0")
|
||||
@@ -122,6 +134,11 @@ elseif (WITH_GCRYPT)
|
||||
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_ED25519=1")
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_SNTRUP761=0")
|
||||
if(HAVE_GCRYPT_MLKEM)
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_MLKEM=0")
|
||||
else()
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_MLKEM=1")
|
||||
endif()
|
||||
else ()
|
||||
if (HAVE_OPENSSL_EVP_CHACHA20)
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=0")
|
||||
@@ -131,6 +148,11 @@ else ()
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CURVE25519=0")
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_ED25519=0")
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_SNTRUP761=1")
|
||||
if(HAVE_OPENSSL_MLKEM)
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_MLKEM=0")
|
||||
else()
|
||||
list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_MLKEM=1")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (NOT OSX)
|
||||
@@ -162,6 +184,7 @@ foreach(_OVERRIDE_TEST ${LIBSSH_OVERRIDE_TESTS})
|
||||
ed25519_override
|
||||
curve25519_override
|
||||
sntrup761_override
|
||||
mlkem768_override
|
||||
)
|
||||
|
||||
if (OSX)
|
||||
|
||||
83
tests/external_override/mlkem768_override.c
Normal file
83
tests/external_override/mlkem768_override.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2021 - 2025 Red Hat, Inc.
|
||||
*
|
||||
* Authors: Anderson Toshiyuki Sasaki
|
||||
* 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, either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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,
|
||||
* see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <libssh/priv.h>
|
||||
|
||||
#include "libssh/mlkem_native.h"
|
||||
#include "mlkem768_override.h"
|
||||
|
||||
static bool internal_function_called = false;
|
||||
|
||||
libcrux_ml_kem_mlkem768_MlKem768KeyPair
|
||||
__wrap_libcrux_ml_kem_mlkem768_portable_generate_key_pair(
|
||||
uint8_t randomness[64U])
|
||||
{
|
||||
fprintf(stderr, "%s: Internal implementation was called\n", __func__);
|
||||
internal_function_called = true;
|
||||
return libcrux_ml_kem_mlkem768_portable_generate_key_pair(randomness);
|
||||
}
|
||||
|
||||
bool __wrap_libcrux_ml_kem_mlkem768_portable_validate_public_key(
|
||||
libcrux_ml_kem_types_MlKemPublicKey_30 *public_key)
|
||||
{
|
||||
fprintf(stderr, "%s: Internal implementation was called\n", __func__);
|
||||
internal_function_called = true;
|
||||
return libcrux_ml_kem_mlkem768_portable_validate_public_key(public_key);
|
||||
}
|
||||
|
||||
tuple_c2 __wrap_libcrux_ml_kem_mlkem768_portable_encapsulate(
|
||||
libcrux_ml_kem_types_MlKemPublicKey_30 *public_key,
|
||||
uint8_t randomness[32U])
|
||||
{
|
||||
fprintf(stderr, "%s: Internal implementation was called\n", __func__);
|
||||
internal_function_called = true;
|
||||
return libcrux_ml_kem_mlkem768_portable_encapsulate(public_key, randomness);
|
||||
}
|
||||
|
||||
void __wrap_libcrux_ml_kem_mlkem768_portable_decapsulate(
|
||||
libcrux_ml_kem_types_MlKemPrivateKey_d9 *private_key,
|
||||
libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext,
|
||||
uint8_t ret[32U])
|
||||
{
|
||||
fprintf(stderr, "%s: Internal implementation was called\n", __func__);
|
||||
internal_function_called = true;
|
||||
return libcrux_ml_kem_mlkem768_portable_decapsulate(private_key,
|
||||
ciphertext,
|
||||
ret);
|
||||
}
|
||||
|
||||
bool internal_mlkem768_function_called(void)
|
||||
{
|
||||
return internal_function_called;
|
||||
}
|
||||
|
||||
void reset_mlkem768_function_called(void)
|
||||
{
|
||||
internal_function_called = false;
|
||||
}
|
||||
43
tests/external_override/mlkem768_override.h
Normal file
43
tests/external_override/mlkem768_override.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2021 - 2025 Red Hat, Inc.
|
||||
*
|
||||
* Authors: Anderson Toshiyuki Sasaki
|
||||
* 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, either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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,
|
||||
* see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "libssh/mlkem_native.h"
|
||||
|
||||
libcrux_ml_kem_mlkem768_MlKem768KeyPair
|
||||
__wrap_libcrux_ml_kem_mlkem768_portable_generate_key_pair(
|
||||
uint8_t randomness[64U]);
|
||||
|
||||
bool __wrap_libcrux_ml_kem_mlkem768_portable_validate_public_key(
|
||||
libcrux_ml_kem_types_MlKemPublicKey_30 *public_key);
|
||||
|
||||
tuple_c2 __wrap_libcrux_ml_kem_mlkem768_portable_encapsulate(
|
||||
libcrux_ml_kem_types_MlKemPublicKey_30 *public_key,
|
||||
uint8_t randomness[32U]);
|
||||
|
||||
void __wrap_libcrux_ml_kem_mlkem768_portable_decapsulate(
|
||||
libcrux_ml_kem_types_MlKemPrivateKey_d9 *private_key,
|
||||
libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext,
|
||||
uint8_t ret[32U]);
|
||||
|
||||
bool internal_mlkem768_function_called(void);
|
||||
void reset_mlkem768_function_called(void);
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "chacha20_override.h"
|
||||
#include "curve25519_override.h"
|
||||
#include "ed25519_override.h"
|
||||
#include "mlkem768_override.h"
|
||||
#include "poly1305_override.h"
|
||||
#include "sntrup761_override.h"
|
||||
|
||||
@@ -119,6 +120,8 @@ static int session_setup(void **state)
|
||||
reset_poly1305_function_called();
|
||||
reset_curve25519_function_called();
|
||||
reset_ed25519_function_called();
|
||||
reset_sntrup761_function_called();
|
||||
reset_mlkem768_function_called();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -324,6 +327,64 @@ torture_override_ecdh_sntrup761x25519_sha512(void **state)
|
||||
}
|
||||
#endif /* OPENSSH_SNTRUP761X25519_SHA512 */
|
||||
|
||||
#ifdef OPENSSH_MLKEM768X25519_SHA256
|
||||
static void torture_override_mlkem768x25519_sha256(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
bool internal_curve25519_called;
|
||||
bool internal_mlkem768_called;
|
||||
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
test_algorithm(s->ssh.session,
|
||||
"mlkem768x25519-sha256",
|
||||
NULL, /* cipher */
|
||||
NULL /* hostkey */);
|
||||
|
||||
internal_curve25519_called = internal_curve25519_function_called();
|
||||
internal_mlkem768_called = internal_mlkem768_function_called();
|
||||
|
||||
#if SHOULD_CALL_INTERNAL_MLKEM
|
||||
assert_true(internal_mlkem768_called);
|
||||
#else
|
||||
assert_false(internal_mlkem768_called);
|
||||
#endif
|
||||
|
||||
#if SHOULD_CALL_INTERNAL_CURVE25519
|
||||
assert_true(internal_curve25519_called);
|
||||
#else
|
||||
assert_false(internal_curve25519_called);
|
||||
#endif
|
||||
}
|
||||
#endif /* OPENSSH_MLKEM768X25519_SHA256 */
|
||||
|
||||
#ifdef OPENSSH_MLKEM768NISTP256_SHA256
|
||||
static void torture_override_mlkem768nistp256_sha256(void **state)
|
||||
{
|
||||
struct torture_state *s = *state;
|
||||
bool internal_mlkem768_called;
|
||||
|
||||
if (ssh_fips_mode()) {
|
||||
skip();
|
||||
}
|
||||
|
||||
test_algorithm(s->ssh.session,
|
||||
"mlkem768nistp256-sha256",
|
||||
NULL, /* cipher */
|
||||
NULL /* hostkey */);
|
||||
|
||||
internal_mlkem768_called = internal_mlkem768_function_called();
|
||||
|
||||
#if SHOULD_CALL_INTERNAL_MLKEM
|
||||
assert_true(internal_mlkem768_called);
|
||||
#else
|
||||
assert_false(internal_mlkem768_called);
|
||||
#endif
|
||||
}
|
||||
#endif /* OPENSSH_MLKEM768NISTP256_SHA256 */
|
||||
|
||||
#ifdef OPENSSH_SSH_ED25519
|
||||
static void torture_override_ed25519(void **state)
|
||||
{
|
||||
@@ -378,6 +439,16 @@ int torture_run_tests(void)
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#endif /* OPENSSH_SNTRUP761X25519_SHA512 */
|
||||
#ifdef OPENSSH_MLKEM768X25519_SHA256
|
||||
cmocka_unit_test_setup_teardown(torture_override_mlkem768x25519_sha256,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#endif /* OPENSSH_MLKEM768X25519_SHA256 */
|
||||
#ifdef OPENSSH_MLKEM768NISTP256_SHA256
|
||||
cmocka_unit_test_setup_teardown(torture_override_mlkem768nistp256_sha256,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
#endif /* OPENSSH_MLKEM768NISTP256_SHA256 */
|
||||
#ifdef OPENSSH_SSH_ED25519
|
||||
cmocka_unit_test_setup_teardown(torture_override_ed25519,
|
||||
session_setup,
|
||||
|
||||
@@ -306,7 +306,7 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
#define PKDTESTS_KEX_SNTRUP761(f, client, kexcmd)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM768X25519_SHA256)
|
||||
#if defined(OPENSSH_MLKEM768X25519_SHA256)
|
||||
#define PKDTESTS_KEX_MLKEM768X25519(f, client, kexcmd) \
|
||||
f(client, rsa_mlkem768x25519_sha256, kexcmd("mlkem768x25519-sha256"), setup_rsa, teardown, LIBSSH_RSA_TESTKEY) \
|
||||
f(client, ecdsa_256_mlkem768x25519_sha256, kexcmd("mlkem768x25519-sha256"), setup_ecdsa_256, teardown, LIBSSH_ECDSA_256_TESTKEY) \
|
||||
@@ -317,7 +317,7 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
#define PKDTESTS_KEX_MLKEM768X25519(f, client, kexcmd)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM768NISTP256_SHA256)
|
||||
#if defined(OPENSSH_MLKEM768NISTP256_SHA256)
|
||||
#define PKDTESTS_KEX_MLKEM768NISTP256(f, client, kexcmd) \
|
||||
f(client, rsa_mlkem768nistp256_sha256, kexcmd("mlkem768nistp256-sha256"), setup_rsa, teardown, LIBSSH_RSA_TESTKEY) \
|
||||
f(client, ecdsa_256_mlkem768nistp256_sha256, kexcmd("mlkem768nistp256-sha256"), setup_ecdsa_256, teardown, LIBSSH_ECDSA_256_TESTKEY) \
|
||||
@@ -328,7 +328,7 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
|
||||
#define PKDTESTS_KEX_MLKEM768NISTP256(f, client, kexcmd)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MLKEM) && defined(OPENSSH_MLKEM1024NISTP384_SHA384)
|
||||
#if defined(HAVE_MLKEM1024) && defined(OPENSSH_MLKEM1024NISTP384_SHA384)
|
||||
#define PKDTESTS_KEX_MLKEM1024NISTP384(f, client, kexcmd) \
|
||||
f(client, rsa_mlkem1024nistp384_sha384, kexcmd("mlkem1024nistp384-sha384"), setup_rsa, teardown, LIBSSH_RSA_TESTKEY) \
|
||||
f(client, ecdsa_256_mlkem1024nistp384_sha384, kexcmd("mlkem1024nistp384-sha384"), setup_ecdsa_256, teardown, LIBSSH_ECDSA_256_TESTKEY) \
|
||||
|
||||
@@ -346,7 +346,6 @@ static void torture_algorithm_aes128gcm_with_no_hmac_overlap(void **state)
|
||||
test_algorithm_no_hmac_overlap(state, "aes128-gcm@openssh.com");
|
||||
}
|
||||
|
||||
#ifdef HAVE_MLKEM
|
||||
/*
|
||||
* Check the self-compatibility of a given key exchange method.
|
||||
*/
|
||||
@@ -418,6 +417,7 @@ static void torture_algorithm_mlkem768nistp256_self_compat(void **state)
|
||||
test_kex_self_compat(state, "mlkem768nistp256-sha256");
|
||||
}
|
||||
|
||||
#ifdef HAVE_MLKEM1024
|
||||
static void torture_algorithm_mlkem1024nistp384_self_compat(void **state)
|
||||
{
|
||||
if (ssh_fips_mode()) {
|
||||
@@ -425,7 +425,7 @@ static void torture_algorithm_mlkem1024nistp384_self_compat(void **state)
|
||||
}
|
||||
test_kex_self_compat(state, "mlkem1024nistp384-sha384");
|
||||
}
|
||||
#endif /* HAVE_MLKEM */
|
||||
#endif /* HAVE_MLKEM1024 */
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
@@ -437,14 +437,14 @@ int torture_run_tests(void)
|
||||
setup_temp_dir, teardown_temp_dir),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithm_aes128gcm_with_no_hmac_overlap,
|
||||
setup_temp_dir, teardown_temp_dir),
|
||||
#ifdef HAVE_MLKEM
|
||||
cmocka_unit_test_setup_teardown(torture_algorithm_mlkem768x25119_self_compat,
|
||||
setup_temp_dir, teardown_temp_dir),
|
||||
cmocka_unit_test_setup_teardown(torture_algorithm_mlkem768nistp256_self_compat,
|
||||
setup_temp_dir, teardown_temp_dir),
|
||||
#ifdef HAVE_MLKEM1024
|
||||
cmocka_unit_test_setup_teardown(torture_algorithm_mlkem1024nistp384_self_compat,
|
||||
setup_temp_dir, teardown_temp_dir),
|
||||
#endif /* HAVE_MLKEM */
|
||||
#endif /* HAVE_MLKEM1024 */
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
@@ -282,7 +282,7 @@ static void torture_options_get_key_exchange(void **state)
|
||||
"diffie-hellman-group16-sha512,"
|
||||
"diffie-hellman-group18-sha512");
|
||||
} else {
|
||||
#ifdef HAVE_MLKEM
|
||||
#ifdef HAVE_MLKEM1024
|
||||
assert_string_equal(value,
|
||||
"mlkem768x25519-sha256,"
|
||||
"mlkem768nistp256-sha256,"
|
||||
@@ -296,6 +296,8 @@ static void torture_options_get_key_exchange(void **state)
|
||||
"diffie-hellman-group14-sha256");
|
||||
#else
|
||||
assert_string_equal(value,
|
||||
"mlkem768x25519-sha256,"
|
||||
"mlkem768nistp256-sha256,"
|
||||
"sntrup761x25519-sha512,"
|
||||
"sntrup761x25519-sha512@openssh.com,"
|
||||
"curve25519-sha256,curve25519-sha256@libssh.org,"
|
||||
|
||||
Reference in New Issue
Block a user