diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h index 881ffd96..b37f2bab 100644 --- a/include/libssh/crypto.h +++ b/include/libssh/crypto.h @@ -99,6 +99,10 @@ enum ssh_key_exchange_e { SSH_GSS_KEX_DH_GROUP14_SHA256, /* gss-group16-sha512-* */ SSH_GSS_KEX_DH_GROUP16_SHA512, + /* gss-nistp256-sha256-* */ + SSH_GSS_KEX_ECDH_NISTP256_SHA256, + /* gss-curve25519-sha256-* */ + SSH_GSS_KEX_CURVE25519_SHA256, }; enum ssh_cipher_e { diff --git a/include/libssh/gssapi.h b/include/libssh/gssapi.h index 0ab5e2aa..fd1216f2 100644 --- a/include/libssh/gssapi.h +++ b/include/libssh/gssapi.h @@ -29,7 +29,10 @@ /* all OID begin with the tag identifier + length */ #define SSH_OID_TAG 06 -#define GSSAPI_KEY_EXCHANGE_SUPPORTED "gss-group14-sha256-,gss-group16-sha512-," +#define GSSAPI_KEY_EXCHANGE_SUPPORTED "gss-group14-sha256-," \ + "gss-group16-sha512-," \ + "gss-nistp256-sha256-," \ + "gss-curve25519-sha256-" typedef struct ssh_gssapi_struct *ssh_gssapi; diff --git a/include/libssh/dh-gss.h b/include/libssh/kex-gss.h similarity index 69% rename from include/libssh/dh-gss.h rename to include/libssh/kex-gss.h index 76676bf5..65ae2fe4 100644 --- a/include/libssh/dh-gss.h +++ b/include/libssh/kex-gss.h @@ -1,5 +1,5 @@ /* - * dh-gss.h - diffie-hellman GSSAPI key exchange + * kex-gss.h - GSSAPI key exchange * * This file is part of the SSH Library * @@ -20,17 +20,17 @@ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ -#ifndef DH_GSS_H_ -#define DH_GSS_H_ +#ifndef KEX_GSS_H_ +#define KEX_GSS_H_ #include "config.h" #ifdef WITH_GSSAPI -int ssh_client_gss_dh_init(ssh_session session); -void ssh_server_gss_dh_init(ssh_session session); -int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet); -void ssh_client_gss_dh_remove_callbacks(ssh_session session); -void ssh_client_gss_dh_remove_callback_hostkey(ssh_session session); +int ssh_client_gss_kex_init(ssh_session session); +void ssh_server_gss_kex_init(ssh_session session); +int ssh_server_gss_kex_process_init(ssh_session session, ssh_buffer packet); +void ssh_client_gss_kex_remove_callbacks(ssh_session session); +void ssh_client_gss_kex_remove_callback_hostkey(ssh_session session); #endif /* WITH_GSSAPI */ -#endif /* DH_GSS_H_ */ +#endif /* KEX_GSS_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f800b01c..eca80e38 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -286,7 +286,7 @@ if (WITH_GSSAPI AND GSSAPI_FOUND) set(libssh_SRCS ${libssh_SRCS} gssapi.c - dh-gss.c + kex-gss.c ) endif (WITH_GSSAPI AND GSSAPI_FOUND) diff --git a/src/client.c b/src/client.c index 760abed9..625adb0b 100644 --- a/src/client.c +++ b/src/client.c @@ -31,7 +31,7 @@ #endif #include "libssh/buffer.h" -#include "libssh/dh-gss.h" +#include "libssh/kex-gss.h" #include "libssh/dh.h" #include "libssh/options.h" #include "libssh/packet.h" @@ -271,7 +271,9 @@ int dh_handshake(ssh_session session) #ifdef WITH_GSSAPI case SSH_GSS_KEX_DH_GROUP14_SHA256: case SSH_GSS_KEX_DH_GROUP16_SHA512: - rc = ssh_client_gss_dh_init(session); + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + case SSH_GSS_KEX_CURVE25519_SHA256: + rc = ssh_client_gss_kex_init(session); break; #endif case SSH_KEX_DH_GROUP1_SHA1: diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c index b5f66987..ebfbf8a3 100644 --- a/src/ecdh_crypto.c +++ b/src/ecdh_crypto.c @@ -56,6 +56,7 @@ static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { #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 diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c index 82b6a2fd..b2c61555 100644 --- a/src/ecdh_gcrypt.c +++ b/src/ecdh_gcrypt.c @@ -37,7 +37,8 @@ * @brief Map the given key exchange enum value to its curve name. */ static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { - if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256) { + if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256 || + kex_type == SSH_GSS_KEX_ECDH_NISTP256_SHA256) { return "NIST P-256"; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) { return "NIST P-384"; diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c index 507db705..f95c77b9 100644 --- a/src/ecdh_mbedcrypto.c +++ b/src/ecdh_mbedcrypto.c @@ -39,7 +39,8 @@ #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) { + if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256 || + kex_type == SSH_GSS_KEX_ECDH_NISTP256_SHA256) { return MBEDTLS_ECP_DP_SECP256R1; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) { return MBEDTLS_ECP_DP_SECP384R1; diff --git a/src/dh-gss.c b/src/kex-gss.c similarity index 56% rename from src/dh-gss.c rename to src/kex-gss.c index 2b870e7d..bb1c8dab 100644 --- a/src/dh-gss.c +++ b/src/kex-gss.c @@ -1,5 +1,5 @@ /* - * dh-gss.c - diffie-hellman GSSAPI key exchange + * kex-gss.c - GSSAPI key exchange * * This file is part of the SSH Library * @@ -30,50 +30,112 @@ #include "libssh/buffer.h" #include "libssh/crypto.h" -#include "libssh/dh-gss.h" +#include "libssh/kex-gss.h" +#include "libssh/bignum.h" +#include "libssh/curve25519.h" +#include "libssh/ecdh.h" #include "libssh/dh.h" #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/ssh2.h" -static SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_reply); +static SSH_PACKET_CALLBACK(ssh_packet_client_gss_kex_reply); -static ssh_packet_callback gss_dh_client_callbacks[] = { - ssh_packet_client_gss_dh_reply, +static ssh_packet_callback gss_kex_client_callbacks[] = { + ssh_packet_client_gss_kex_reply, }; -static struct ssh_packet_callbacks_struct ssh_gss_dh_client_callbacks = { +static struct ssh_packet_callbacks_struct ssh_gss_kex_client_callbacks = { .start = SSH2_MSG_KEXGSS_COMPLETE, .n_callbacks = 1, - .callbacks = gss_dh_client_callbacks, + .callbacks = gss_kex_client_callbacks, .user = NULL, }; -static SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_hostkey); +static SSH_PACKET_CALLBACK(ssh_packet_client_gss_kex_hostkey); -static ssh_packet_callback gss_dh_client_callback_hostkey[] = { - ssh_packet_client_gss_dh_hostkey, +static ssh_packet_callback gss_kex_client_callback_hostkey[] = { + ssh_packet_client_gss_kex_hostkey, }; -static struct ssh_packet_callbacks_struct ssh_gss_dh_client_callback_hostkey = { +static struct ssh_packet_callbacks_struct ssh_gss_kex_client_callback_hostkey = { .start = SSH2_MSG_KEXGSS_HOSTKEY, .n_callbacks = 1, - .callbacks = gss_dh_client_callback_hostkey, + .callbacks = gss_kex_client_callback_hostkey, .user = NULL, }; +static ssh_string dh_init(ssh_session session) +{ + int rc, keypair; +#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L + const_bignum const_pubkey; +#endif + bignum pubkey = NULL; + ssh_string pubkey_string = NULL; + struct ssh_crypto_struct *crypto = session->next_crypto; + + if (session->server) { + keypair = DH_SERVER_KEYPAIR; + } else { + keypair = DH_CLIENT_KEYPAIR; + } + + rc = ssh_dh_init_common(crypto); + if (rc != SSH_OK) { + goto end; + } + + rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, keypair); + if (rc != SSH_OK) { + goto end; + } + +#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L + rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, keypair, NULL, &const_pubkey); + bignum_dup(const_pubkey, &pubkey); +#else + rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, keypair, NULL, &pubkey); +#endif + if (rc != SSH_OK) { + goto end; + } + + pubkey_string = ssh_make_bignum_string(pubkey); + +end: + bignum_safe_free(pubkey); + return pubkey_string; +} + +static int dh_import_peer_key(ssh_session session, ssh_string peer_key) +{ + int rc, keypair; + bignum peer_key_bn; + struct ssh_crypto_struct *crypto = session->next_crypto; + + if (session->server) { + keypair = DH_CLIENT_KEYPAIR; + } else { + keypair = DH_SERVER_KEYPAIR; + } + + peer_key_bn = ssh_make_string_bn(peer_key); + rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, keypair, NULL, peer_key_bn); + if (rc != SSH_OK) { + bignum_safe_free(peer_key_bn); + } + + return rc; +} + /** @internal * @brief Starts gssapi key exchange */ -int ssh_client_gss_dh_init(ssh_session session) +int ssh_client_gss_kex_init(ssh_session session) { struct ssh_crypto_struct *crypto = session->next_crypto; -#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L - const_bignum pubkey; -#else - bignum pubkey = NULL; -#endif /* OPENSSL_VERSION_NUMBER */ - int rc; + int rc, ret = SSH_ERROR; /* oid selected for authentication */ gss_OID_set selected = GSS_C_NO_OID_SET; OM_uint32 maj_stat, min_stat; @@ -81,27 +143,52 @@ int ssh_client_gss_dh_init(ssh_session session) gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; OM_uint32 oflags; + ssh_string pubkey = NULL; - rc = ssh_dh_init_common(crypto); - if (rc == SSH_ERROR) { - goto error; - } - - rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR); - if (rc == SSH_ERROR) { - goto error; - } - rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, - DH_CLIENT_KEYPAIR, - NULL, - &pubkey); - if (rc != SSH_OK) { - goto error; + switch (crypto->kex_type) { + case SSH_GSS_KEX_DH_GROUP14_SHA256: + case SSH_GSS_KEX_DH_GROUP16_SHA512: + pubkey = dh_init(session); + if (pubkey == NULL) { + ssh_set_error(session, SSH_FATAL, "Failed to generate DH keypair"); + goto out; + } + break; + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + rc = ssh_ecdh_init(session); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Failed to generate ECDH keypair"); + goto out; + } + pubkey = ssh_string_copy(crypto->ecdh_client_pubkey); + break; + case SSH_GSS_KEX_CURVE25519_SHA256: + rc = ssh_curve25519_init(session); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Failed to generate Curve25519 keypair"); + goto out; + } + pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE); + if (pubkey == NULL) { + ssh_set_error_oom(session); + goto out; + } + rc = ssh_string_fill(pubkey, + crypto->curve25519_client_pubkey, + CURVE25519_PUBKEY_SIZE); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Failed to copy Curve25519 pubkey"); + goto out; + } + break; + default: + ssh_set_error(session, SSH_FATAL, "Unsupported GSSAPI KEX method"); + goto out; } rc = ssh_gssapi_init(session); - if (rc == SSH_ERROR) { - goto error; + if (rc != SSH_OK) { + goto out; } if (session->opts.gss_server_identity != NULL) { @@ -110,12 +197,12 @@ int ssh_client_gss_dh_init(ssh_session session) rc = ssh_gssapi_import_name(session->gssapi, gss_host); if (rc != SSH_OK) { - goto error; + goto out; } rc = ssh_gssapi_client_identity(session, &selected); - if (rc == SSH_ERROR) { - goto error; + if (rc != SSH_OK) { + goto out; } session->gssapi->client.flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG; @@ -129,61 +216,58 @@ int ssh_client_gss_dh_init(ssh_session session) "Initializing gssapi context", maj_stat, min_stat); - goto error; + goto out; } if (!(oflags & GSS_C_INTEG_FLAG) || !(oflags & GSS_C_MUTUAL_FLAG)) { SSH_LOG(SSH_LOG_WARN, "GSSAPI(init) integrity and mutual flags were not set"); - goto error; + goto out; } rc = ssh_buffer_pack(session->out_buffer, - "bdPB", + "bdPS", SSH2_MSG_KEXGSS_INIT, output_token.length, (size_t)output_token.length, output_token.value, pubkey); if (rc != SSH_OK) { - goto error; + goto out; } - gss_release_buffer(&min_stat, &output_token); -#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L - bignum_safe_free(pubkey); -#endif /* register the packet callbacks */ - ssh_packet_set_callbacks(session, &ssh_gss_dh_client_callbacks); - ssh_packet_set_callbacks(session, &ssh_gss_dh_client_callback_hostkey); + ssh_packet_set_callbacks(session, &ssh_gss_kex_client_callbacks); + ssh_packet_set_callbacks(session, &ssh_gss_kex_client_callback_hostkey); session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); - return rc; -error: -#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L - bignum_safe_free(pubkey); -#endif + if (rc != SSH_OK) { + goto out; + } + + ret = SSH_OK; + +out: gss_release_buffer(&min_stat, &output_token); - ssh_dh_cleanup(crypto); - return SSH_ERROR; + ssh_string_free(pubkey); + return ret; } -void ssh_client_gss_dh_remove_callbacks(ssh_session session) +void ssh_client_gss_kex_remove_callbacks(ssh_session session) { - ssh_packet_remove_callbacks(session, &ssh_gss_dh_client_callbacks); + ssh_packet_remove_callbacks(session, &ssh_gss_kex_client_callbacks); } -void ssh_client_gss_dh_remove_callback_hostkey(ssh_session session) +void ssh_client_gss_kex_remove_callback_hostkey(ssh_session session) { - ssh_packet_remove_callbacks(session, &ssh_gss_dh_client_callback_hostkey); + ssh_packet_remove_callbacks(session, &ssh_gss_kex_client_callback_hostkey); } -SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_reply) +SSH_PACKET_CALLBACK(ssh_packet_client_gss_kex_reply) { struct ssh_crypto_struct *crypto = session->next_crypto; - ssh_string pubkey_blob = NULL, mic = NULL, otoken = NULL; + ssh_string mic = NULL, otoken = NULL, server_pubkey = NULL; uint8_t b; - bignum server_pubkey; int rc; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; @@ -193,12 +277,14 @@ SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_reply) (void)type; (void)user; - ssh_client_gss_dh_remove_callbacks(session); + ssh_client_gss_kex_remove_callbacks(session); - rc = ssh_buffer_unpack(packet, "BSbS", &server_pubkey, &mic, &b, &otoken); - if (rc == SSH_ERROR) { + rc = ssh_buffer_unpack(packet, "SSbS", &server_pubkey, &mic, &b, &otoken); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "No public key in server reply"); goto error; } + SSH_STRING_FREE(session->gssapi_key_exchange_mic); session->gssapi_key_exchange_mic = mic; input_token.length = ssh_string_len(otoken); @@ -211,23 +297,37 @@ SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_reply) goto error; } SSH_STRING_FREE(otoken); - rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, - DH_SERVER_KEYPAIR, - NULL, - server_pubkey); - if (rc != SSH_OK) { - SSH_STRING_FREE(pubkey_blob); - bignum_safe_free(server_pubkey); + + switch (crypto->kex_type) { + case SSH_GSS_KEX_DH_GROUP14_SHA256: + case SSH_GSS_KEX_DH_GROUP16_SHA512: + rc = dh_import_peer_key(session, server_pubkey); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Could not import server pubkey"); + goto error; + } + rc = ssh_dh_compute_shared_secret(crypto->dh_ctx, + DH_CLIENT_KEYPAIR, + DH_SERVER_KEYPAIR, + &crypto->shared_secret); + ssh_dh_debug_crypto(crypto); + break; + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + crypto->ecdh_server_pubkey = ssh_string_copy(server_pubkey); + rc = ecdh_build_k(session); + break; + case SSH_GSS_KEX_CURVE25519_SHA256: + memcpy(crypto->curve25519_server_pubkey, + ssh_string_data(server_pubkey), + CURVE25519_PUBKEY_SIZE); + rc = ssh_curve25519_build_k(session); + break; + default: + ssh_set_error(session, SSH_FATAL, "Unsupported GSSAPI KEX method"); goto error; } - - rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx, - DH_CLIENT_KEYPAIR, - DH_SERVER_KEYPAIR, - &session->next_crypto->shared_secret); - ssh_dh_debug_crypto(session->next_crypto); - if (rc == SSH_ERROR) { - ssh_set_error(session, SSH_FATAL, "Could not generate shared secret"); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Could not derive shared secret"); goto error; } @@ -236,15 +336,18 @@ SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_reply) if (rc == SSH_ERROR) { goto error; } + + ssh_string_free(server_pubkey); session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; return SSH_PACKET_USED; + error: - ssh_dh_cleanup(session->next_crypto); + ssh_string_free(server_pubkey); session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } -SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_hostkey) +SSH_PACKET_CALLBACK(ssh_packet_client_gss_kex_hostkey) { ssh_string pubkey_blob = NULL; int rc; @@ -252,7 +355,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_hostkey) (void)type; (void)user; - ssh_client_gss_dh_remove_callback_hostkey(session); + ssh_client_gss_kex_remove_callback_hostkey(session); rc = ssh_buffer_unpack(packet, "S", &pubkey_blob); if (rc == SSH_ERROR) { @@ -270,52 +373,45 @@ SSH_PACKET_CALLBACK(ssh_packet_client_gss_dh_hostkey) return SSH_PACKET_USED; error: - ssh_dh_cleanup(session->next_crypto); session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } #ifdef WITH_SERVER -static SSH_PACKET_CALLBACK(ssh_packet_server_gss_dh_init); +static SSH_PACKET_CALLBACK(ssh_packet_server_gss_kex_init); -static ssh_packet_callback gss_dh_server_callbacks[] = { - ssh_packet_server_gss_dh_init, +static ssh_packet_callback gss_kex_server_callbacks[] = { + ssh_packet_server_gss_kex_init, }; -static struct ssh_packet_callbacks_struct ssh_gss_dh_server_callbacks = { +static struct ssh_packet_callbacks_struct ssh_gss_kex_server_callbacks = { .start = SSH2_MSG_KEXGSS_INIT, .n_callbacks = 1, - .callbacks = gss_dh_server_callbacks, + .callbacks = gss_kex_server_callbacks, .user = NULL, }; /** @internal * @brief sets up the gssapi kex callbacks */ -void ssh_server_gss_dh_init(ssh_session session) +void ssh_server_gss_kex_init(ssh_session session) { /* register the packet callbacks */ - ssh_packet_set_callbacks(session, &ssh_gss_dh_server_callbacks); - - ssh_dh_init_common(session->next_crypto); + ssh_packet_set_callbacks(session, &ssh_gss_kex_server_callbacks); } /** @internal * @brief processes a SSH_MSG_KEXGSS_INIT and sends * the appropriate SSH_MSG_KEXGSS_COMPLETE */ -int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet) +int ssh_server_gss_kex_process_init(ssh_session session, ssh_buffer packet) { struct ssh_crypto_struct *crypto = session->next_crypto; ssh_key privkey = NULL; enum ssh_digest_e digest = SSH_DIGEST_AUTO; - bignum client_pubkey; -#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L - const_bignum server_pubkey; -#else - bignum server_pubkey = NULL; -#endif /* OPENSSL_VERSION_NUMBER */ + ssh_string client_pubkey = NULL; + ssh_string server_pubkey = NULL; int rc; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; @@ -336,33 +432,70 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet) input_token.length = ssh_string_len(otoken); input_token.value = ssh_string_data(otoken); - rc = ssh_buffer_unpack(packet, "B", &client_pubkey); + rc = ssh_buffer_unpack(packet, "S", &client_pubkey); if (rc == SSH_ERROR) { - ssh_set_error(session, SSH_FATAL, "No e number in client request"); + ssh_set_error(session, SSH_FATAL, "No public key in client request"); goto error; } - rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, - DH_CLIENT_KEYPAIR, - NULL, - client_pubkey); + switch (crypto->kex_type) { + case SSH_GSS_KEX_DH_GROUP14_SHA256: + case SSH_GSS_KEX_DH_GROUP16_SHA512: + server_pubkey = dh_init(session); + if (server_pubkey == NULL) { + ssh_set_error(session, SSH_FATAL, "Could not generate a DH keypair"); + goto error; + } + rc = dh_import_peer_key(session, client_pubkey); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Could not import client pubkey"); + goto error; + } + rc = ssh_dh_compute_shared_secret(crypto->dh_ctx, + DH_SERVER_KEYPAIR, + DH_CLIENT_KEYPAIR, + &crypto->shared_secret); + ssh_dh_debug_crypto(crypto); + break; + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + rc = ssh_ecdh_init(session); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Could not generate an ECDH keypair"); + goto error; + } + crypto->ecdh_client_pubkey = ssh_string_copy(client_pubkey); + server_pubkey = ssh_string_copy(crypto->ecdh_server_pubkey); + rc = ecdh_build_k(session); + break; + case SSH_GSS_KEX_CURVE25519_SHA256: + rc = ssh_curve25519_init(session); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Could not generate a Curve25519 keypair"); + goto error; + } + server_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE); + if (server_pubkey == NULL) { + ssh_set_error_oom(session); + goto error; + } + rc = ssh_string_fill(server_pubkey, + crypto->curve25519_server_pubkey, + CURVE25519_PUBKEY_SIZE); + if (rc != SSH_OK) { + ssh_set_error(session, SSH_FATAL, "Failed to copy Curve25519 pubkey"); + goto error; + } + memcpy(crypto->curve25519_client_pubkey, + ssh_string_data(client_pubkey), + CURVE25519_PUBKEY_SIZE); + rc = ssh_curve25519_build_k(session); + break; + default: + ssh_set_error(session, SSH_FATAL, "Unsupported GSSAPI KEX method"); + goto error; + } if (rc != SSH_OK) { - bignum_safe_free(client_pubkey); - goto error; - } - - rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR); - if (rc == SSH_ERROR) { - goto error; - } - - rc = ssh_dh_compute_shared_secret(crypto->dh_ctx, - DH_SERVER_KEYPAIR, - DH_CLIENT_KEYPAIR, - &crypto->shared_secret); - ssh_dh_debug_crypto(crypto); - if (rc == SSH_ERROR) { - ssh_set_error(session, SSH_FATAL, "Could not generate shared secret"); + ssh_set_error(session, SSH_FATAL, "Could not derive shared secret"); goto error; } @@ -400,14 +533,6 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet) SSH_STRING_FREE(server_pubkey_blob); } - rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, - DH_SERVER_KEYPAIR, - NULL, - &server_pubkey); - if (rc != SSH_OK) { - goto error; - } - rc = ssh_gssapi_init(session); if (rc == SSH_ERROR) { goto error; @@ -485,7 +610,7 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet) } rc = ssh_buffer_pack(session->out_buffer, - "bBdPbdP", + "bSdPbdP", SSH2_MSG_KEXGSS_COMPLETE, server_pubkey, mic.length, @@ -495,9 +620,6 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet) output_token.length, (size_t)output_token.length, output_token.value); -#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L - bignum_safe_free(server_pubkey); -#endif if (rc != SSH_OK) { ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); @@ -520,15 +642,14 @@ int ssh_server_gss_dh_process_init(ssh_session session, ssh_buffer packet) goto error; } + ssh_string_free(server_pubkey); + ssh_string_free(client_pubkey); return SSH_OK; error: SSH_STRING_FREE(server_pubkey_blob); -#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L - bignum_safe_free(server_pubkey); -#endif - + ssh_string_free(server_pubkey); + ssh_string_free(client_pubkey); session->session_state = SSH_SESSION_STATE_ERROR; - ssh_dh_cleanup(session->next_crypto); return SSH_ERROR; } @@ -536,13 +657,13 @@ error: * @brief parse an incoming SSH_MSG_KEXGSS_INIT packet and complete * Diffie-Hellman key exchange **/ -static SSH_PACKET_CALLBACK(ssh_packet_server_gss_dh_init) +static SSH_PACKET_CALLBACK(ssh_packet_server_gss_kex_init) { (void)type; (void)user; SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_KEXGSS_INIT"); - ssh_packet_remove_callbacks(session, &ssh_gss_dh_server_callbacks); - ssh_server_gss_dh_process_init(session, packet); + ssh_packet_remove_callbacks(session, &ssh_gss_kex_server_callbacks); + ssh_server_gss_kex_process_init(session, packet); return SSH_PACKET_USED; } diff --git a/src/kex.c b/src/kex.c index c0d228e9..63694286 100644 --- a/src/kex.c +++ b/src/kex.c @@ -44,13 +44,13 @@ #ifdef HAVE_MLKEM #include "libssh/hybrid_mlkem.h" #endif +#include "libssh/kex-gss.h" #include "libssh/knownhosts.h" #include "libssh/misc.h" #include "libssh/pki.h" #include "libssh/bignum.h" #include "libssh/token.h" #include "libssh/gssapi.h" -#include "libssh/dh-gss.h" #ifdef HAVE_BLOWFISH # define BLOWFISH ",blowfish-cbc" @@ -958,6 +958,10 @@ kex_select_kex_type(const char *kex) return SSH_GSS_KEX_DH_GROUP14_SHA256; } else if (strncmp(kex, "gss-group16-sha512-", 19) == 0) { return SSH_GSS_KEX_DH_GROUP16_SHA512; + } else if (strncmp(kex, "gss-nistp256-sha256-", 20) == 0) { + return SSH_GSS_KEX_ECDH_NISTP256_SHA256; + } else if (strncmp(kex, "gss-curve25519-sha256-", 22) == 0) { + return SSH_GSS_KEX_CURVE25519_SHA256; } else if (strcmp(kex, "diffie-hellman-group14-sha1") == 0) { return SSH_KEX_DH_GROUP14_SHA1; } else if (strcmp(kex, "diffie-hellman-group14-sha256") == 0) { @@ -1017,8 +1021,10 @@ static void revert_kex_callbacks(ssh_session session) break; case SSH_GSS_KEX_DH_GROUP14_SHA256: case SSH_GSS_KEX_DH_GROUP16_SHA512: + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + case SSH_GSS_KEX_CURVE25519_SHA256: #ifdef WITH_GSSAPI - ssh_client_gss_dh_remove_callbacks(session); + ssh_client_gss_kex_remove_callbacks(session); #endif /* WITH_GSSAPI */ break; #ifdef WITH_GEX @@ -1591,6 +1597,7 @@ int ssh_make_sessionid(ssh_session session) case SSH_KEX_ECDH_SHA2_NISTP256: case SSH_KEX_ECDH_SHA2_NISTP384: case SSH_KEX_ECDH_SHA2_NISTP521: + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: if (session->next_crypto->ecdh_client_pubkey == NULL || session->next_crypto->ecdh_server_pubkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "ECDH parameter missing"); @@ -1609,6 +1616,7 @@ int ssh_make_sessionid(ssh_session session) #ifdef HAVE_CURVE25519 case SSH_KEX_CURVE25519_SHA256: case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: + case SSH_GSS_KEX_CURVE25519_SHA256: rc = ssh_buffer_pack(buf, "dPdP", CURVE25519_PUBKEY_SIZE, @@ -1727,6 +1735,8 @@ int ssh_make_sessionid(ssh_session session) 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 case SSH_KEX_DH_GEX_SHA256: #endif /* WITH_GEX */ @@ -2043,6 +2053,8 @@ bool ssh_kex_is_gss(struct ssh_crypto_struct *crypto) switch (crypto->kex_type) { case SSH_GSS_KEX_DH_GROUP14_SHA256: case SSH_GSS_KEX_DH_GROUP16_SHA512: + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + case SSH_GSS_KEX_CURVE25519_SHA256: return true; default: return false; diff --git a/src/packet.c b/src/packet.c index 7647892c..31edaff9 100644 --- a/src/packet.c +++ b/src/packet.c @@ -434,7 +434,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se * * Transitions: * - session->dh_handshake_state = DH_STATE_INIT_SENT - * then calls ssh_packet_client_gss_dh_reply which triggers: + * then calls ssh_packet_client_gss_kex_reply which triggers: * - session->dh_handshake_state = DH_STATE_NEWKEYS_SENT * */ diff --git a/src/session.c b/src/session.c index 4bdd8d5c..35867e4e 100644 --- a/src/session.c +++ b/src/session.c @@ -489,6 +489,8 @@ const char* ssh_get_kex_algo(ssh_session session) { return "diffie-hellman-group18-sha512"; case SSH_KEX_ECDH_SHA2_NISTP256: return "ecdh-sha2-nistp256"; + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + return "gss-nistp256-sha256-"; case SSH_KEX_ECDH_SHA2_NISTP384: return "ecdh-sha2-nistp384"; case SSH_KEX_ECDH_SHA2_NISTP521: @@ -497,6 +499,8 @@ const char* ssh_get_kex_algo(ssh_session session) { return "curve25519-sha256"; case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: return "curve25519-sha256@libssh.org"; + case SSH_GSS_KEX_CURVE25519_SHA256: + return "gss-curve25519-sha256-"; case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM: return "sntrup761x25519-sha512@openssh.com"; case SSH_KEX_SNTRUP761X25519_SHA512: diff --git a/src/wrapper.c b/src/wrapper.c index a5f63269..3ecb607b 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -49,12 +49,12 @@ #include "libssh/dh-gex.h" #endif /* WITH_GEX */ #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/dh-gss.h" static struct ssh_hmac_struct ssh_hmac_tab[] = { { "hmac-sha1", SSH_HMAC_SHA1, false }, @@ -591,7 +591,9 @@ int crypt_set_algorithms_server(ssh_session session){ #ifdef WITH_GSSAPI case SSH_GSS_KEX_DH_GROUP14_SHA256: case SSH_GSS_KEX_DH_GROUP16_SHA512: - ssh_server_gss_dh_init(session); + case SSH_GSS_KEX_ECDH_NISTP256_SHA256: + case SSH_GSS_KEX_CURVE25519_SHA256: + ssh_server_gss_kex_init(session); break; #endif /* WITH_GSSAPI */ #ifdef WITH_GEX diff --git a/tests/client/torture_gssapi_key_exchange.c b/tests/client/torture_gssapi_key_exchange.c index 61962ac0..cddaf09a 100644 --- a/tests/client/torture_gssapi_key_exchange.c +++ b/tests/client/torture_gssapi_key_exchange.c @@ -130,90 +130,80 @@ static void torture_gssapi_key_exchange_no_tgt(void **state) rc = ssh_connect(session); assert_ssh_return_code(session, rc); - assert_int_not_equal(session->current_crypto->kex_type, - SSH_GSS_KEX_DH_GROUP14_SHA256); - assert_int_not_equal(session->current_crypto->kex_type, - SSH_GSS_KEX_DH_GROUP16_SHA512); + assert_false(ssh_kex_is_gss(session->current_crypto)); + + torture_teardown_kdc_server(state); +} + +static void torture_gssapi_key_exchange_alg(void **state, + const char *kex_string, + enum ssh_key_exchange_e kex_type) +{ + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + int rc; + bool t = true; + + /* Skip test if in FIPS mode */ + if (ssh_fips_mode()) { + skip(); + } + + /* Valid */ + torture_setup_kdc_server( + state, + "kadmin.local addprinc -randkey host/server.libssh.site \n" + "kadmin.local ktadd -k $(dirname $0)/d/ssh.keytab host/server.libssh.site \n" + "kadmin.local addprinc -pw bar alice \n" + "kadmin.local list_principals", + + "echo bar | kinit alice"); + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_options_set(s->ssh.session, + SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, + kex_string); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_connect(session); + assert_ssh_return_code(session, rc); + + assert_int_equal(session->current_crypto->kex_type, kex_type); torture_teardown_kdc_server(state); } static void torture_gssapi_key_exchange_gss_group14_sha256(void **state) { - struct torture_state *s = *state; - ssh_session session = s->ssh.session; - int rc; - bool t = true; - - /* Skip test if in FIPS mode */ - if (ssh_fips_mode()) { - skip(); - } - - /* Valid */ - torture_setup_kdc_server( - state, - "kadmin.local addprinc -randkey host/server.libssh.site \n" - "kadmin.local ktadd -k $(dirname $0)/d/ssh.keytab host/server.libssh.site \n" - "kadmin.local addprinc -pw bar alice \n" - "kadmin.local list_principals", - - "echo bar | kinit alice"); - - rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_options_set(s->ssh.session, - SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, - "gss-group14-sha256-"); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_connect(session); - assert_ssh_return_code(session, rc); - - assert_int_equal(session->current_crypto->kex_type, - SSH_GSS_KEX_DH_GROUP14_SHA256); - - torture_teardown_kdc_server(state); + torture_gssapi_key_exchange_alg(state, + "gss-group14-sha256-", + SSH_GSS_KEX_DH_GROUP14_SHA256); } static void torture_gssapi_key_exchange_gss_group16_sha512(void **state) { - struct torture_state *s = *state; - ssh_session session = s->ssh.session; - int rc; - bool t = true; + torture_gssapi_key_exchange_alg(state, + "gss-group16-sha512-", + SSH_GSS_KEX_DH_GROUP16_SHA512); +} - /* Skip test if in FIPS mode */ +static void torture_gssapi_key_exchange_gss_nistp256_sha256(void **state) +{ + torture_gssapi_key_exchange_alg(state, + "gss-nistp256-sha256-", + SSH_GSS_KEX_ECDH_NISTP256_SHA256); +} + +static void torture_gssapi_key_exchange_gss_curve25519_sha256(void **state) +{ if (ssh_fips_mode()) { skip(); } - - /* Valid */ - torture_setup_kdc_server( - state, - "kadmin.local addprinc -randkey host/server.libssh.site \n" - "kadmin.local ktadd -k $(dirname $0)/d/ssh.keytab host/server.libssh.site \n" - "kadmin.local addprinc -pw bar alice \n" - "kadmin.local list_principals", - - "echo bar | kinit alice"); - - rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_options_set(s->ssh.session, - SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, - "gss-group16-sha512-"); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_connect(session); - assert_ssh_return_code(session, rc); - - assert_true(session->current_crypto->kex_type == - SSH_GSS_KEX_DH_GROUP16_SHA512); - - torture_teardown_kdc_server(state); + torture_gssapi_key_exchange_alg(state, + "gss-curve25519-sha256-", + SSH_GSS_KEX_CURVE25519_SHA256); } static void torture_gssapi_key_exchange_auth(void **state) @@ -304,6 +294,14 @@ int torture_run_tests(void) torture_gssapi_key_exchange_gss_group16_sha512, session_setup, session_teardown), + cmocka_unit_test_setup_teardown( + torture_gssapi_key_exchange_gss_nistp256_sha256, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown( + torture_gssapi_key_exchange_gss_curve25519_sha256, + session_setup, + session_teardown), cmocka_unit_test_setup_teardown(torture_gssapi_key_exchange_auth, session_setup, session_teardown), diff --git a/tests/server/torture_gssapi_server_key_exchange.c b/tests/server/torture_gssapi_server_key_exchange.c index edceee92..a7d72eea 100644 --- a/tests/server/torture_gssapi_server_key_exchange.c +++ b/tests/server/torture_gssapi_server_key_exchange.c @@ -137,7 +137,10 @@ static void setup_config(void **state) /* Enable GSSAPI key exchange */ ss->gssapi_key_exchange = true; - ss->gssapi_key_exchange_algs = "gss-group14-sha256-,gss-group16-sha512-"; + ss->gssapi_key_exchange_algs = "gss-group14-sha256-," + "gss-group16-sha512-," + "gss-nistp256-sha256-," + "gss-curve25519-sha256-"; tss->state = s; tss->ss = ss; @@ -348,108 +351,89 @@ static void torture_gssapi_server_key_exchange_no_tgt(void **state) rc = ssh_connect(session); assert_ssh_return_code(session, rc); - assert_int_not_equal(session->current_crypto->kex_type, - SSH_GSS_KEX_DH_GROUP14_SHA256); - assert_int_not_equal(session->current_crypto->kex_type, - SSH_GSS_KEX_DH_GROUP16_SHA512); + assert_false(ssh_kex_is_gss(session->current_crypto)); + + torture_teardown_kdc_server((void **)&s); +} + +static void torture_gssapi_server_key_exchange_alg(void **state, + const char *kex_string, + enum ssh_key_exchange_e kex_type) +{ + struct test_server_st *tss = *state; + struct torture_state *s = NULL; + ssh_session session; + int rc; + bool t = true; + + /* Skip test if in FIPS mode */ + if (ssh_fips_mode()) { + skip(); + } + + assert_non_null(tss); + + s = tss->state; + assert_non_null(s); + + session = s->ssh.session; + assert_non_null(session); + + /* Valid */ + torture_setup_kdc_server( + (void **)&s, + "kadmin.local addprinc -randkey host/server.libssh.site \n" + "kadmin.local ktadd -k $(dirname $0)/d/ssh.keytab host/server.libssh.site \n" + "kadmin.local addprinc -pw bar alice \n" + "kadmin.local list_principals", + + "echo bar | kinit alice"); + + rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_options_set(s->ssh.session, + SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, + kex_string); + assert_ssh_return_code(s->ssh.session, rc); + + rc = ssh_connect(session); + assert_ssh_return_code(session, rc); + + assert_int_equal(session->current_crypto->kex_type, kex_type); torture_teardown_kdc_server((void **)&s); } static void torture_gssapi_server_key_exchange_gss_group14_sha256(void **state) { - struct test_server_st *tss = *state; - struct torture_state *s = NULL; - ssh_session session; - int rc; - bool t = true; - - /* Skip test if in FIPS mode */ - if (ssh_fips_mode()) { - skip(); - } - - assert_non_null(tss); - - s = tss->state; - assert_non_null(s); - - session = s->ssh.session; - assert_non_null(session); - - /* Valid */ - torture_setup_kdc_server( - (void **)&s, - "kadmin.local addprinc -randkey host/server.libssh.site \n" - "kadmin.local ktadd -k $(dirname $0)/d/ssh.keytab host/server.libssh.site \n" - "kadmin.local addprinc -pw bar alice \n" - "kadmin.local list_principals", - - "echo bar | kinit alice"); - - rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_options_set(s->ssh.session, - SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, - "gss-group14-sha256-"); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_connect(session); - assert_ssh_return_code(session, rc); - - assert_int_equal(session->current_crypto->kex_type, - SSH_GSS_KEX_DH_GROUP14_SHA256); - - torture_teardown_kdc_server((void **)&s); + torture_gssapi_server_key_exchange_alg(state, + "gss-group14-sha256-", + SSH_GSS_KEX_DH_GROUP14_SHA256); } static void torture_gssapi_server_key_exchange_gss_group16_sha512(void **state) { - struct test_server_st *tss = *state; - struct torture_state *s = NULL; - ssh_session session; - int rc; - bool t = true; + torture_gssapi_server_key_exchange_alg(state, + "gss-group16-sha512-", + SSH_GSS_KEX_DH_GROUP16_SHA512); +} - /* Skip test if in FIPS mode */ +static void torture_gssapi_server_key_exchange_gss_nistp256_sha256(void **state) +{ + torture_gssapi_server_key_exchange_alg(state, + "gss-nistp256-sha256-", + SSH_GSS_KEX_ECDH_NISTP256_SHA256); +} + +static void torture_gssapi_server_key_exchange_gss_curve25519_sha256(void **state) +{ if (ssh_fips_mode()) { skip(); } - - assert_non_null(tss); - - s = tss->state; - assert_non_null(s); - - session = s->ssh.session; - assert_non_null(session); - - /* Valid */ - torture_setup_kdc_server( - (void **)&s, - "kadmin.local addprinc -randkey host/server.libssh.site \n" - "kadmin.local ktadd -k $(dirname $0)/d/ssh.keytab host/server.libssh.site \n" - "kadmin.local addprinc -pw bar alice \n" - "kadmin.local list_principals", - - "echo bar | kinit alice"); - - rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_GSSAPI_KEY_EXCHANGE, &t); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_options_set(s->ssh.session, - SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS, - "gss-group16-sha512-"); - assert_ssh_return_code(s->ssh.session, rc); - - rc = ssh_connect(session); - assert_ssh_return_code(session, rc); - - assert_int_equal(session->current_crypto->kex_type, - SSH_GSS_KEX_DH_GROUP16_SHA512); - - torture_teardown_kdc_server((void **)&s); + torture_gssapi_server_key_exchange_alg(state, + "gss-curve25519-sha256-", + SSH_GSS_KEX_CURVE25519_SHA256); } static void torture_gssapi_server_key_exchange_auth(void **state) @@ -559,6 +543,14 @@ int torture_run_tests(void) torture_gssapi_server_key_exchange_gss_group16_sha512, session_setup, session_teardown), + cmocka_unit_test_setup_teardown( + torture_gssapi_server_key_exchange_gss_nistp256_sha256, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown( + torture_gssapi_server_key_exchange_gss_curve25519_sha256, + session_setup, + session_teardown), cmocka_unit_test_setup_teardown(torture_gssapi_server_key_exchange_auth, session_setup, session_teardown), diff --git a/tests/server/torture_gssapi_server_key_exchange_null.c b/tests/server/torture_gssapi_server_key_exchange_null.c index 2d3580c1..f439f50d 100644 --- a/tests/server/torture_gssapi_server_key_exchange_null.c +++ b/tests/server/torture_gssapi_server_key_exchange_null.c @@ -95,7 +95,10 @@ static void setup_config(void **state) /* Enable GSSAPI key exchange */ ss->gssapi_key_exchange = true; - ss->gssapi_key_exchange_algs = "gss-group14-sha256-,gss-group16-sha512-"; + ss->gssapi_key_exchange_algs = "gss-group14-sha256-," + "gss-group16-sha512-," + "gss-nistp256-sha256-," + "gss-curve25519-sha256-"; tss->state = s; tss->ss = ss;