From ca0e2dcf0a31dd3d53cac23ba34b823ae77fe04a Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Mon, 6 Jul 2026 03:19:21 +0200 Subject: [PATCH] openssl: add debug traces to ML-KEM ed25519 KEX codepath [ci skip] Also enable a success-path debug message in the OpenSSL no-deprecated job. Bug: https://github.com/libssh2/libssh2/pull/1644#issuecomment-4761871304 Follow-up tp bc77633d5a1eb317ad296a034bf1d0f92c251318 Follow-up to a69fb2a48f08ab35ac3ffc067ae1c5ade40631fb #2092 Follow-up to 8e4c14b0fe5eba7ce9ef43da8a2048af4ab1132f #2083 Follow-up to 3ba252e2a6fe04d17ea13ad870698a4028c8ab4c #1644 Closes #2259 --- .github/workflows/ci.yml | 1 + src/crypto.h | 2 +- src/hostkey.c | 2 +- src/kex.c | 37 +++++++++++++++++++++++++++++++++++++ src/openssl.c | 27 +++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e05dd89..cbd50d3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -578,6 +578,7 @@ jobs: fi if [ "${MATRIX_CRYPTO}" = 'OpenSSL-3-no-deprecated' ]; then options+=' -DENABLE_DEBUG_LOGGING=ON' + cflags+=' -DLIBSSH2_DEBUG_MLKEM' fi cmake -B bld -G Ninja ${options} $TOOLCHAIN_OPTION \ -DCMAKE_C_FLAGS="${cflags}" \ diff --git a/src/crypto.h b/src/crypto.h index 2a5bf696..8c932fbf 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -297,7 +297,7 @@ int ssh2_ed25519_new_private_frommemory_sk(ssh2_ed25519_ctx **ed_ctx, int ssh2_ed25519_sign(ssh2_ed25519_ctx *ed_ctx, LIBSSH2_SESSION *session, uint8_t **out_sig, size_t *out_sig_len, const uint8_t *message, size_t message_len); -int ssh2_ed25519_verify(ssh2_ed25519_ctx *ed_ctx, +int ssh2_ed25519_verify(ssh2_ed25519_ctx *ed_ctx, LIBSSH2_SESSION *session, const uint8_t *s, size_t s_len, const uint8_t *m, size_t m_len); #endif /* LIBSSH2_ED25519 */ diff --git a/src/hostkey.c b/src/hostkey.c index ce218bc0..408d5cff 100644 --- a/src/hostkey.c +++ b/src/hostkey.c @@ -1163,7 +1163,7 @@ static int hostkey_method_ssh_ed25519_sig_verify(LIBSSH2_SESSION *session, if(sig_len != SSH2_ED25519_SIG_LEN) return -1; - return ssh2_ed25519_verify(ctx, sig, sig_len, m, m_len); + return ssh2_ed25519_verify(ctx, session, sig, sig_len, m, m_len); } /* diff --git a/src/kex.c b/src/kex.c index a052cff8..43b3e7bd 100644 --- a/src/kex.c +++ b/src/kex.c @@ -1456,6 +1456,12 @@ static int kex_method_ec_sha_hash_create_verify( "Unable to initialize hash context EC/ED"); if(session->local.banner) { +#ifdef LIBSSH2_DEBUG_MLKEM + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "kex_method_ec_sha_hash_create_verify: %s " + "session->local.banner=|%s|", session->hostkey->name, + session->local.banner)); +#endif ssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)(strlen((const char *)session->local.banner) - 2)); hok &= ssh2_hash_update(&ctx, exchange_state->h_sig_comp, 4); @@ -1463,6 +1469,12 @@ static int kex_method_ec_sha_hash_create_verify( strlen((const char *)session->local.banner) - 2); } else { +#ifdef LIBSSH2_DEBUG_MLKEM + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "kex_method_ec_sha_hash_create_verify: %s " + "default_banner=|%s|", session->hostkey->name, + LIBSSH2_SSH_DEFAULT_BANNER)); +#endif ssh2_htonu32(exchange_state->h_sig_comp, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); hok &= ssh2_hash_update(&ctx, exchange_state->h_sig_comp, 4); @@ -1470,12 +1482,37 @@ static int kex_method_ec_sha_hash_create_verify( sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); } +#ifdef LIBSSH2_DEBUG_MLKEM + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "kex_method_ec_sha_hash_create_verify: %s " + "session->remote.banner=|%s|", session->hostkey->name, + session->remote.banner)); +#endif ssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)strlen((const char *)session->remote.banner)); hok &= ssh2_hash_update(&ctx, exchange_state->h_sig_comp, 4); hok &= ssh2_hash_update(&ctx, session->remote.banner, strlen((const char *)session->remote.banner)); +#ifdef LIBSSH2_DEBUG_MLKEM + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "kex_method_ec_sha_hash_create_verify: %s " + "session->local.kexinit_len=|%lu| " + "session->remote.kexinit_len=|%lu| " + "session->server_hostkey_len=|%lu| " + "public_pq_key_len=|%lu| " + "public_key_len=|%lu| " + "server_public_key_len=|%lu| " + "exchange_state->k_value_len=|%lu|", + session->hostkey->name, + (unsigned long)session->local.kexinit_len, + (unsigned long)session->remote.kexinit_len, + (unsigned long)session->server_hostkey_len, + (unsigned long)public_pq_key_len, + (unsigned long)public_key_len, + (unsigned long)server_public_key_len, + (unsigned long)exchange_state->k_value_len)); +#endif ssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)session->local.kexinit_len); hok &= ssh2_hash_update(&ctx, exchange_state->h_sig_comp, 4); diff --git a/src/openssl.c b/src/openssl.c index a3c9168c..aaa08c2b 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -3730,20 +3730,39 @@ clean_exit: return rc == 1 ? 0 : -1; } -int ssh2_ed25519_verify(ssh2_ed25519_ctx *ed_ctx, const uint8_t *s, - size_t s_len, const uint8_t *m, size_t m_len) +int ssh2_ed25519_verify(ssh2_ed25519_ctx *ed_ctx, LIBSSH2_SESSION *session, + const uint8_t *s, size_t s_len, + const uint8_t *m, size_t m_len) { int ret = -1; EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); - if(!md_ctx) + if(!md_ctx) { + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "ssh2_ed25519_verify(): EVP_MD_CTX_new() failed")); return -1; + } ret = EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, ed_ctx); - if(ret != 1) + if(ret != 1) { + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "ssh2_ed25519_verify(): EVP_DigestVerifyInit()->%d", ret)); goto clean_exit; + } + + (void)session; +#ifdef LIBSSH2_DEBUG_MLKEM + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "ssh2_ed25519_verify(%p, %lu, %p, %lu)", + (const void *)s, (unsigned long)s_len, + (const void *)m, (unsigned long)m_len)); +#endif ret = EVP_DigestVerify(md_ctx, s, s_len, m, m_len); + if(ret != 1) + ssh2_deb((session, LIBSSH2_TRACE_KEX, + "ssh2_ed25519_verify(): EVP_DigestVerify()->%d (ossl: %lu)", + ret, ret ? ERR_peek_last_error() : 0)); clean_exit: