From fee337529da2d2b386b241812e176852bd5d4c4c Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sat, 29 Aug 2026 12:06:20 +0200 Subject: irmd: Reject client encap without configured KEX A client asking for client-side encapsulation against a server that has no kex= configured left scfg->x.str NULL, crashing the handshake inside strstr(). Client encapsulation decapsulates with the server's configured static key, so a server without the configured key exchange cannot serve the request. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/irmd/oap/srv.c | 4 +++ src/irmd/oap/tests/oap_test_ml_dsa.c | 47 ++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/irmd/oap/srv.c b/src/irmd/oap/srv.c index d78fc8d4..f78e0874 100644 --- a/src/irmd/oap/srv.c +++ b/src/irmd/oap/srv.c @@ -363,6 +363,10 @@ int do_server_kex(const struct name_info * info, scfg->x.str); return -ECRYPT; } + } else if (!IS_KEX_ALGO_SET(scfg)) { + /* Client encap decaps with the configured static key */ + log_err_id(id, "Client encap without configured KEX."); + return -ECRYPT; } /* Dispatch based on algorithm type */ diff --git a/src/irmd/oap/tests/oap_test_ml_dsa.c b/src/irmd/oap/tests/oap_test_ml_dsa.c index 36712830..477b712b 100644 --- a/src/irmd/oap/tests/oap_test_ml_dsa.c +++ b/src/irmd/oap/tests/oap_test_ml_dsa.c @@ -720,6 +720,51 @@ static int test_oap_kem_srv_uncfg_all(void) return ret; } +/* Client encap must be rejected when the server has no KEX config */ +static int test_oap_kem_cli_encap_srv_uncfg(void) +{ + struct oap_test_ctx ctx; + + memset(&test_cfg, 0, sizeof(test_cfg)); + + /* Server: auth only, no KEX configured */ + + test_cfg.srv.auth = true; + + /* Client: requests KEM with client-side encapsulation */ + test_cfg.cli.kex = NID_MLKEM768; + test_cfg.cli.cipher = NID_aes_256_gcm; + test_cfg.cli.kdf = get_random_kdf(); + test_cfg.cli.kem_mode = CLI_ENCAP; + test_cfg.cli.auth = false; + + TEST_START(); + + if (oap_test_setup_kem(&ctx, root_ca_crt_ml, im_ca_crt_ml) < 0) + goto fail; + + if (oap_cli_prepare_ctx(&ctx) < 0) { + printf("Client prepare failed.\n"); + goto fail_cleanup; + } + + if (oap_srv_process_ctx(&ctx) == 0) { + printf("Server accepted client encap without KEX.\n"); + goto fail_cleanup; + } + + oap_test_teardown_kem(&ctx); + + TEST_SUCCESS(); + + return TEST_RC_SUCCESS; + fail_cleanup: + oap_test_teardown_kem(&ctx); + fail: + TEST_FAIL(); + return TEST_RC_FAIL; +} + int oap_test_ml_dsa(int argc, char **argv) { @@ -736,6 +781,7 @@ int oap_test_ml_dsa(int argc, ret |= test_oap_roundtrip_kem_all(); ret |= test_oap_kem_srv_uncfg_all(); + ret |= test_oap_kem_cli_encap_srv_uncfg(); ret |= test_oap_corrupted_request(); ret |= test_oap_corrupted_response(); @@ -765,6 +811,7 @@ int oap_test_ml_dsa(int argc, (void) test_oap_rekey_kem_forcing; (void) test_oap_kem_srv_uncfg; (void) test_oap_kem_srv_uncfg_all; + (void) test_oap_kem_cli_encap_srv_uncfg; (void) test_oap_corrupted_request; (void) test_oap_corrupted_response; (void) test_oap_truncated_request; -- cgit v1.2.3