@@ -907,8 +907,9 @@ int test_tls_set_session_min_downgrade(void)
907907}
908908
909909#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
910- !defined(WOLFSSL_NO_TLS12 ) && defined(HAVE_SNI ) && \
911- defined(HAVE_SESSION_TICKET ) && !defined(NO_SESSION_CACHE )
910+ (!defined(WOLFSSL_NO_TLS12 ) || defined(WOLFSSL_TLS13 )) && \
911+ defined(HAVE_SNI ) && defined(HAVE_SESSION_TICKET ) && \
912+ !defined(NO_SESSION_CACHE )
912913/* Accept-all SNI callback. */
913914static int accept_any_sni_cb (WOLFSSL * ssl , int * ret , void * arg )
914915{
@@ -988,6 +989,145 @@ int test_tls12_session_id_resumption_sni_mismatch(void)
988989 return EXPECT_RESULT ();
989990}
990991
992+ /* TLS 1.3 PSK resumption must fall back to a full handshake if the SNI in
993+ * the resumed ClientHello does not match the SNI bound to the original
994+ * session (RFC 6066 Section 3 / RFC 8446 Section 4.6.1). */
995+ int test_tls13_session_resumption_sni_mismatch (void )
996+ {
997+ EXPECT_DECLS ;
998+ #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && defined(WOLFSSL_TLS13 ) && \
999+ defined(HAVE_SNI ) && defined(HAVE_SESSION_TICKET ) && \
1000+ !defined(NO_SESSION_CACHE )
1001+ WOLFSSL_CTX * ctx_c = NULL , * ctx_s = NULL ;
1002+ WOLFSSL * ssl_c = NULL , * ssl_s = NULL ;
1003+ WOLFSSL_SESSION * sess = NULL ;
1004+ struct test_memio_ctx test_ctx ;
1005+ const char * sniA = "public.example" ;
1006+ const char * sniB = "admin.example" ;
1007+ byte readBuf [16 ];
1008+
1009+ /* Step 1: full TLS 1.3 handshake under SNI=public.example to obtain a
1010+ * session ticket. The server-side SNI callback ensures ssl->extensions
1011+ * retains the client's SNI in builds that don't compile in
1012+ * WOLFSSL_ALWAYS_KEEP_SNI. */
1013+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
1014+ ExpectIntEQ (test_memio_setup (& test_ctx , & ctx_c , & ctx_s , & ssl_c , & ssl_s ,
1015+ wolfTLSv1_3_client_method , wolfTLSv1_3_server_method ), 0 );
1016+ wolfSSL_CTX_set_servername_callback (ctx_s , accept_any_sni_cb );
1017+ ExpectIntEQ (wolfSSL_UseSNI (ssl_c , WOLFSSL_SNI_HOST_NAME ,
1018+ sniA , (word16 )XSTRLEN (sniA )), WOLFSSL_SUCCESS );
1019+ ExpectIntEQ (test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL ), 0 );
1020+ /* Sanity: the first handshake was not a resumption. */
1021+ ExpectIntEQ (wolfSSL_session_reused (ssl_s ), 0 );
1022+ /* Drive the post-handshake NewSessionTicket through to the client so
1023+ * the saved session is a real resumption ticket. */
1024+ ExpectIntEQ (wolfSSL_read (ssl_c , readBuf , sizeof (readBuf )), -1 );
1025+ ExpectIntEQ (wolfSSL_get_error (ssl_c , -1 ), WOLFSSL_ERROR_WANT_READ );
1026+ ExpectNotNull (sess = wolfSSL_get1_session (ssl_c ));
1027+
1028+ wolfSSL_free (ssl_c ); ssl_c = NULL ;
1029+ wolfSSL_free (ssl_s ); ssl_s = NULL ;
1030+
1031+ /* Step 2: new SSL objects on the SAME WOLFSSL_CTX (so the server's
1032+ * ticket key still matches). The client offers the saved session but
1033+ * advertises a *different* SNI. The server MUST NOT resume because the
1034+ * SNI differs from the original. */
1035+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
1036+ ExpectNotNull (ssl_c = wolfSSL_new (ctx_c ));
1037+ wolfSSL_SetIOReadCtx (ssl_c , & test_ctx );
1038+ wolfSSL_SetIOWriteCtx (ssl_c , & test_ctx );
1039+ ExpectNotNull (ssl_s = wolfSSL_new (ctx_s ));
1040+ wolfSSL_SetIOReadCtx (ssl_s , & test_ctx );
1041+ wolfSSL_SetIOWriteCtx (ssl_s , & test_ctx );
1042+ ExpectIntEQ (wolfSSL_UseSNI (ssl_c , WOLFSSL_SNI_HOST_NAME ,
1043+ sniB , (word16 )XSTRLEN (sniB )), WOLFSSL_SUCCESS );
1044+ ExpectIntEQ (wolfSSL_set_session (ssl_c , sess ), WOLFSSL_SUCCESS );
1045+ ExpectIntEQ (test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL ), 0 );
1046+
1047+ /* Desired behavior: server falls back to a full handshake because the
1048+ * SNI in the ClientHello does not match the SNI bound to the cached
1049+ * ticket. Both sides should report no resumption. */
1050+ ExpectIntEQ (wolfSSL_session_reused (ssl_s ), 0 );
1051+ ExpectIntEQ (wolfSSL_session_reused (ssl_c ), 0 );
1052+
1053+ wolfSSL_SESSION_free (sess );
1054+ wolfSSL_free (ssl_c );
1055+ wolfSSL_free (ssl_s );
1056+ wolfSSL_CTX_free (ctx_c );
1057+ wolfSSL_CTX_free (ctx_s );
1058+ #endif
1059+ return EXPECT_RESULT ();
1060+ }
1061+
1062+ /* Regression test for the post-ALPN_Select PSK-head check.
1063+ * When ALPN_Select runs before CheckPreSharedKeys (so the per-PSK
1064+ * binding check has the negotiated ALPN available), TLSX_SetALPN
1065+ * prepends a new ALPN entry to ssl->extensions, displacing the PSK
1066+ * extension from the head of the list. The "PSK was last in
1067+ * ClientHello" check therefore must run right after TLSX_Parse,
1068+ * not inside CheckPreSharedKeys. This test exercises that path
1069+ * (TLS 1.3 PSK resumption with ALPN, no SNI callback -- the grpc
1070+ * server scenario). */
1071+ int test_tls13_resumption_with_alpn (void )
1072+ {
1073+ EXPECT_DECLS ;
1074+ #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && defined(WOLFSSL_TLS13 ) && \
1075+ defined(HAVE_SNI ) && defined(HAVE_ALPN ) && defined(HAVE_SESSION_TICKET ) && \
1076+ !defined(NO_SESSION_CACHE )
1077+ WOLFSSL_CTX * ctx_c = NULL , * ctx_s = NULL ;
1078+ WOLFSSL * ssl_c = NULL , * ssl_s = NULL ;
1079+ WOLFSSL_SESSION * sess = NULL ;
1080+ struct test_memio_ctx test_ctx ;
1081+ const char * sni = "foo.test.google.fr" ;
1082+ const char alpn [] = "h2" ;
1083+ byte readBuf [16 ];
1084+
1085+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
1086+ ExpectIntEQ (test_memio_setup (& test_ctx , & ctx_c , & ctx_s , & ssl_c , & ssl_s ,
1087+ wolfTLSv1_3_client_method , wolfTLSv1_3_server_method ), 0 );
1088+ ExpectIntEQ (wolfSSL_UseSNI (ssl_c , WOLFSSL_SNI_HOST_NAME ,
1089+ sni , (word16 )XSTRLEN (sni )), WOLFSSL_SUCCESS );
1090+ ExpectIntEQ (wolfSSL_UseALPN (ssl_c , (char * )alpn , (word32 )XSTRLEN (alpn ),
1091+ WOLFSSL_ALPN_FAILED_ON_MISMATCH ), WOLFSSL_SUCCESS );
1092+ ExpectIntEQ (wolfSSL_UseALPN (ssl_s , (char * )alpn , (word32 )XSTRLEN (alpn ),
1093+ WOLFSSL_ALPN_FAILED_ON_MISMATCH ), WOLFSSL_SUCCESS );
1094+ ExpectIntEQ (test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL ), 0 );
1095+ ExpectIntEQ (wolfSSL_session_reused (ssl_s ), 0 );
1096+ ExpectIntEQ (wolfSSL_read (ssl_c , readBuf , sizeof (readBuf )), -1 );
1097+ ExpectIntEQ (wolfSSL_get_error (ssl_c , -1 ), WOLFSSL_ERROR_WANT_READ );
1098+ ExpectNotNull (sess = wolfSSL_get1_session (ssl_c ));
1099+
1100+ wolfSSL_free (ssl_c ); ssl_c = NULL ;
1101+ wolfSSL_free (ssl_s ); ssl_s = NULL ;
1102+
1103+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
1104+ ExpectNotNull (ssl_c = wolfSSL_new (ctx_c ));
1105+ wolfSSL_SetIOReadCtx (ssl_c , & test_ctx );
1106+ wolfSSL_SetIOWriteCtx (ssl_c , & test_ctx );
1107+ ExpectNotNull (ssl_s = wolfSSL_new (ctx_s ));
1108+ wolfSSL_SetIOReadCtx (ssl_s , & test_ctx );
1109+ wolfSSL_SetIOWriteCtx (ssl_s , & test_ctx );
1110+ ExpectIntEQ (wolfSSL_UseSNI (ssl_c , WOLFSSL_SNI_HOST_NAME ,
1111+ sni , (word16 )XSTRLEN (sni )), WOLFSSL_SUCCESS );
1112+ ExpectIntEQ (wolfSSL_UseALPN (ssl_c , (char * )alpn , (word32 )XSTRLEN (alpn ),
1113+ WOLFSSL_ALPN_FAILED_ON_MISMATCH ), WOLFSSL_SUCCESS );
1114+ ExpectIntEQ (wolfSSL_UseALPN (ssl_s , (char * )alpn , (word32 )XSTRLEN (alpn ),
1115+ WOLFSSL_ALPN_FAILED_ON_MISMATCH ), WOLFSSL_SUCCESS );
1116+ ExpectIntEQ (wolfSSL_set_session (ssl_c , sess ), WOLFSSL_SUCCESS );
1117+ ExpectIntEQ (test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL ), 0 );
1118+
1119+ ExpectIntEQ (wolfSSL_session_reused (ssl_s ), 1 );
1120+ ExpectIntEQ (wolfSSL_session_reused (ssl_c ), 1 );
1121+
1122+ wolfSSL_SESSION_free (sess );
1123+ wolfSSL_free (ssl_c );
1124+ wolfSSL_free (ssl_s );
1125+ wolfSSL_CTX_free (ctx_c );
1126+ wolfSSL_CTX_free (ctx_s );
1127+ #endif
1128+ return EXPECT_RESULT ();
1129+ }
1130+
9911131int test_tls_set_curves_list_ecc_fallback (void )
9921132{
9931133 EXPECT_DECLS ;
0 commit comments