From: Daniel Kubec Date: Thu, 2 Apr 2026 13:25:29 +0000 (+0100) Subject: EAP-FAST: echo Session ID on PAC-based session resumption X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=004e9255e4e70454c9e9f46dad181d4c6a20c294;p=thirdparty%2Fopenssl.git EAP-FAST: echo Session ID on PAC-based session resumption Ensure that when a ClientHello includes both a Session ID and a PAC-Opaque in the SessionTicket extension, the server echoes the same Session ID in the ServerHello if the session is resumed based on the PAC-Opaque. Fixes #29095 Signed-off-by: Daniel Kubec Co-authored-by: Matt Caswell Reviewed-by: Nikola Pajkovsky Reviewed-by: Tomas Mraz MergeDate: Thu Apr 16 17:01:03 2026 (Merged from https://github.com/openssl/openssl/pull/30695) --- diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 97455842ecb..f061a47f4b5 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -2156,6 +2156,19 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) s->peer_ciphers = ciphers; s->session->verify_result = X509_V_OK; + /* + * Per RFC 4851, Section 3.2.2: + * If the ClientHello contains both a Session ID and a PAC-Opaque in + * the SessionTicket extension, and the server resumes the session + * using the PAC-Opaque, it should echo the same Session ID in the + * ServerHello. + */ + if (clienthello->session_id_len > 0) { + memcpy(s->session->session_id, clienthello->session_id, + clienthello->session_id_len); + s->session->session_id_length = clienthello->session_id_len; + } + ciphers = NULL; /* check if some cipher was preferred by call back */ diff --git a/test/sslapitest.c b/test/sslapitest.c index 411d0076812..9e994062d51 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -11197,11 +11197,13 @@ static int secret_cb(SSL *s, void *secretin, int *secret_len, /* * Test the session_secret_cb which is designed for use with EAP-FAST */ -static int test_session_secret_cb(void) +static int test_session_secret_cb(int idx) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; - SSL_SESSION *secret_sess = NULL; + SSL_SESSION *secret_sess = NULL, *server_sess = NULL; + unsigned int sess_len; + const unsigned char *sessid; int testresult = 0; if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), @@ -11235,12 +11237,20 @@ static int test_session_secret_cb(void) NULL, NULL))) goto end; - /* - * No session ids for EAP-FAST - otherwise the state machine gets very - * confused. - */ - if (!TEST_true(SSL_SESSION_set1_id(secret_sess, NULL, 0))) - goto end; + if (idx == 0) { + /* + * Normal case: no session id + */ + if (!TEST_true(SSL_SESSION_set1_id(secret_sess, NULL, 0))) + goto end; + } else { + /* + * Set an explicit session id. Normally we don't support this, but we + * can get away with it if we reset the session id later + */ + if (!TEST_true(SSL_SESSION_set1_id(secret_sess, (unsigned char *)"sessionid", 9))) + goto end; + } if (!TEST_true(SSL_set_min_proto_version(clientssl, TLS1_2_VERSION)) || !TEST_true(SSL_set_max_proto_version(serverssl, TLS1_2_VERSION)) @@ -11251,13 +11261,39 @@ static int test_session_secret_cb(void) || !TEST_true(SSL_set_session(clientssl, secret_sess))) goto end; + if (idx == 1) { + /* + * We just send the ClientHello here. We expect this to fail with + * SSL_ERROR_WANT_READ + */ + if (!TEST_int_le(SSL_connect(clientssl), 0)) + goto end; + /* Reset the session id to avoid confusing the state machine */ + if (!TEST_true(SSL_SESSION_set1_id(secret_sess, NULL, 0))) + goto end; + } if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) goto end; + /* Check that session resumption was successful */ + if (!TEST_true(SSL_session_reused(clientssl)) + || !TEST_true(SSL_session_reused(serverssl))) + goto end; + + if (idx == 1) { + server_sess = SSL_get1_session(serverssl); + if (!TEST_ptr(server_sess)) + goto end; + sessid = SSL_SESSION_get_id(server_sess, &sess_len); + + if (!TEST_mem_eq(sessid, sess_len, "sessionid", 9)) + goto end; + } testresult = 1; end: SSL_SESSION_free(secret_sess); + SSL_SESSION_free(server_sess); SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); @@ -14910,7 +14946,7 @@ int setup_tests(void) #endif #ifndef OPENSSL_NO_TLS1_2 ADD_TEST(test_ssl_dup); - ADD_TEST(test_session_secret_cb); + ADD_ALL_TESTS(test_session_secret_cb, 2); #ifndef OPENSSL_NO_DH ADD_ALL_TESTS(test_set_tmp_dh, 11); ADD_ALL_TESTS(test_dh_auto, 7);