aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorViktor Dukhovni <[email protected]>2026-07-23 08:08:35 +0200
committerNorbert Pocs <[email protected]>2026-10-09 15:56:02 +0200
commitb4bf79bd097ad9fb58417ca971cb32a45afbbcbe (patch)
treee027724717bbd3ed942d52702e96c42eaa8abe28 /test
parentPSK: Check for invalid server PSK ciphers (diff)
downloadopenssl-b4bf79bd097ad9fb58417ca971cb32a45afbbcbe.tar.gz
openssl-b4bf79bd097ad9fb58417ca971cb32a45afbbcbe.zip
Fix ECH server verify_result misuse
Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> Merge-date: Fri Oct 9 13:56:06 2026 Merged-from: https://github.com/openssl/openssl/pull/31925
Diffstat (limited to 'test')
-rw-r--r--test/ech_test.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/test/ech_test.c b/test/ech_test.c
index d2331c8b407..a4de0c9a107 100644
--- a/test/ech_test.c
+++ b/test/ech_test.c
@@ -2341,6 +2341,75 @@ end:
return res;
}
+static int ech_admit_cb(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ return 1;
+}
+
+/*
+ * Regression: on the server, SSL_ech_get1_status() must not derive its
+ * SUCCESS/BAD_NAME result from verify_result. On the server verify_result is
+ * the client certificate's verdict, which is unrelated to ECH. Here the server
+ * requests a client certificate, trusts no CA, and admits the failing chain
+ * through its verify callback (as a fingerprint- or ACL-based deployment does),
+ * so a successful handshake is left with a non-OK verify_result. ECH still
+ * succeeded, so the server status must be SSL_ECH_STATUS_SUCCESS, not
+ * SSL_ECH_STATUS_BAD_NAME.
+ */
+static int ech_unauth_client_status_test(void)
+{
+ int res = 0, serverstatus;
+ OSSL_ECHSTORE *es = NULL;
+ OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ char *sinner = NULL, *souter = NULL;
+
+ if (!TEST_ptr(es = OSSL_ECHSTORE_new(libctx, propq))
+ || !TEST_true(OSSL_ECHSTORE_new_config(es, OSSL_ECH_CURRENT_VERSION, 0,
+ "example.com", hpke_suite))
+ || !TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), TLS1_3_VERSION, TLS1_3_VERSION,
+ &sctx, &cctx, cert, privkey)))
+ goto end;
+ /*
+ * The server requests a client certificate but trusts no CA, admitting
+ * whatever the client sends via the callback -- so a successful handshake
+ * leaves verify_result non-OK.
+ */
+ SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, ech_admit_cb);
+ if (!TEST_true(SSL_CTX_use_certificate_file(cctx, cert, SSL_FILETYPE_PEM))
+ || !TEST_true(SSL_CTX_use_PrivateKey_file(cctx, privkey,
+ SSL_FILETYPE_PEM))
+ || !TEST_true(SSL_CTX_set1_echstore(cctx, es))
+ || !TEST_true(SSL_CTX_set1_echstore(sctx, es))
+ || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL))
+ || !TEST_true(SSL_set_tlsext_host_name(clientssl, "server.example"))
+ || !TEST_true(create_ssl_connection(serverssl, clientssl,
+ SSL_ERROR_NONE)))
+ goto end;
+ /* The scenario is only meaningful if the client was admitted non-OK. */
+ if (!TEST_int_ne((int)SSL_get_verify_result(serverssl), X509_V_OK))
+ goto end;
+ serverstatus = SSL_ech_get1_status(serverssl, &sinner, &souter);
+ if (verbose)
+ TEST_info("server status %d (verify_result %ld)", serverstatus,
+ SSL_get_verify_result(serverssl));
+ if (!TEST_int_eq(serverstatus, SSL_ECH_STATUS_SUCCESS))
+ goto end;
+ res = 1;
+end:
+ OPENSSL_free(sinner);
+ OPENSSL_free(souter);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ OSSL_ECHSTORE_free(es);
+ return res;
+}
+
#endif
int setup_tests(void)
@@ -2391,6 +2460,7 @@ int setup_tests(void)
ADD_ALL_TESTS(ech_grease_test, 4);
ADD_ALL_TESTS(test_ech_no_inner, suite_combos);
ADD_ALL_TESTS(test_ech_keylog_random, 4);
+ ADD_TEST(ech_unauth_client_status_test);
return 1;
err:
return 0;