@@ -2814,3 +2814,98 @@ int test_dtls13_no_session_id_echo(void)
28142814#endif
28152815 return EXPECT_RESULT ();
28162816}
2817+
2818+ /* Test that a DTLS 1.3 handshake with an oversized certificate chain does
2819+ * not crash or cause out-of-bounds access in SendTls13Certificate. */
2820+ int test_dtls13_oversized_cert_chain (void )
2821+ {
2822+ EXPECT_DECLS ;
2823+ #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && defined(WOLFSSL_DTLS13 ) \
2824+ && !defined(NO_FILESYSTEM ) && !defined(NO_RSA )
2825+ WOLFSSL_CTX * ctx_c = NULL , * ctx_s = NULL ;
2826+ WOLFSSL * ssl_c = NULL , * ssl_s = NULL ;
2827+ struct test_memio_ctx test_ctx ;
2828+ XFILE f = XBADFILE ;
2829+ long sz = 0 ;
2830+ byte * cert = NULL ;
2831+ byte * chain = NULL ;
2832+ int copies , off , i ;
2833+
2834+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
2835+
2836+ /* Read server cert */
2837+ f = XFOPEN (svrCertFile , "rb" );
2838+ ExpectTrue (f != XBADFILE );
2839+ if (EXPECT_SUCCESS ()) {
2840+ (void )XFSEEK (f , 0 , XSEEK_END );
2841+ sz = XFTELL (f );
2842+ (void )XFSEEK (f , 0 , XSEEK_SET );
2843+ }
2844+ ExpectTrue (sz > 0 );
2845+ cert = (byte * )XMALLOC ((size_t )(sz + 1 ), NULL , DYNAMIC_TYPE_TMP_BUFFER );
2846+ ExpectNotNull (cert );
2847+ if (EXPECT_SUCCESS ())
2848+ ExpectIntEQ ((int )XFREAD (cert , 1 , (size_t )sz , f ), (int )sz );
2849+ if (f != XBADFILE )
2850+ XFCLOSE (f );
2851+
2852+ /* Build an oversized chain by duplicating the cert */
2853+ copies = EXPECT_SUCCESS () ? (int )(70000 / sz ) + 2 : 0 ;
2854+ chain = (byte * )XMALLOC ((size_t )(sz * copies + 1 ), NULL ,
2855+ DYNAMIC_TYPE_TMP_BUFFER );
2856+ ExpectNotNull (chain );
2857+ off = 0 ;
2858+ if (EXPECT_SUCCESS ()) {
2859+ for (i = 0 ; i < copies ; i ++ ) {
2860+ XMEMCPY (chain + off , cert , (size_t )sz );
2861+ off += (int )sz ;
2862+ }
2863+ }
2864+
2865+ /* Server context: load the oversized chain */
2866+ ExpectNotNull (ctx_s = wolfSSL_CTX_new (wolfDTLSv1_3_server_method ()));
2867+ ExpectIntEQ (wolfSSL_CTX_use_certificate_chain_buffer (ctx_s ,
2868+ chain , (long )off ), WOLFSSL_SUCCESS );
2869+ ExpectIntEQ (wolfSSL_CTX_use_PrivateKey_file (ctx_s , svrKeyFile ,
2870+ WOLFSSL_FILETYPE_PEM ), WOLFSSL_SUCCESS );
2871+ if (EXPECT_SUCCESS ()) {
2872+ wolfSSL_SetIORecv (ctx_s , test_memio_read_cb );
2873+ wolfSSL_SetIOSend (ctx_s , test_memio_write_cb );
2874+ }
2875+
2876+ /* Client context: no verification (chain certs are duplicates) */
2877+ ExpectNotNull (ctx_c = wolfSSL_CTX_new (wolfDTLSv1_3_client_method ()));
2878+ if (EXPECT_SUCCESS ()) {
2879+ wolfSSL_CTX_set_verify (ctx_c , WOLFSSL_VERIFY_NONE , NULL );
2880+ wolfSSL_SetIORecv (ctx_c , test_memio_read_cb );
2881+ wolfSSL_SetIOSend (ctx_c , test_memio_write_cb );
2882+ }
2883+
2884+ ExpectNotNull (ssl_s = wolfSSL_new (ctx_s ));
2885+ if (EXPECT_SUCCESS ()) {
2886+ wolfSSL_SetIOWriteCtx (ssl_s , & test_ctx );
2887+ wolfSSL_SetIOReadCtx (ssl_s , & test_ctx );
2888+ }
2889+
2890+ ExpectNotNull (ssl_c = wolfSSL_new (ctx_c ));
2891+ if (EXPECT_SUCCESS ()) {
2892+ wolfSSL_SetIOWriteCtx (ssl_c , & test_ctx );
2893+ wolfSSL_SetIOReadCtx (ssl_c , & test_ctx );
2894+ }
2895+
2896+ /* Handshake must not crash. If SendTls13Certificate mishandles the
2897+ * oversized chain this will trigger a wild pointer dereference or stack
2898+ * overflow resulting with the test failing.
2899+ * The correct behaviour either returns BUFFER_E or succeeds
2900+ * if the build config truncated the chain during loading. */
2901+ (void )test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL );
2902+
2903+ wolfSSL_free (ssl_c );
2904+ wolfSSL_free (ssl_s );
2905+ wolfSSL_CTX_free (ctx_c );
2906+ wolfSSL_CTX_free (ctx_s );
2907+ XFREE (cert , NULL , DYNAMIC_TYPE_TMP_BUFFER );
2908+ XFREE (chain , NULL , DYNAMIC_TYPE_TMP_BUFFER );
2909+ #endif
2910+ return EXPECT_RESULT ();
2911+ }
0 commit comments