@@ -5873,3 +5873,269 @@ int test_tls13_clear_preserves_psk_dhe(void)
58735873#endif
58745874 return EXPECT_RESULT ();
58755875}
5876+
5877+ #if defined(WOLFSSL_TLS13 ) && \
5878+ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
5879+ !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_WOLFSSL_SERVER ) && \
5880+ (defined(BUILD_TLS_AES_128_GCM_SHA256 ) || \
5881+ defined(BUILD_TLS_AES_256_GCM_SHA384 ) || \
5882+ defined(BUILD_TLS_CHACHA20_POLY1305_SHA256 ) || \
5883+ defined(BUILD_TLS_AES_128_CCM_SHA256 ) || \
5884+ defined(BUILD_TLS_AES_128_CCM_8_SHA256 ))
5885+ /* One iteration of the AEAD fuzz test: run a fresh handshake
5886+ * up to the point where the first AEAD-protected record from the side under
5887+ * test sits in the receiver's input buffer, flip one random byte of the
5888+ * encrypted payload to a random non-zero value, and confirm the receiver
5889+ * fails with VERIFY_MAC_ERROR. side==0 fuzzes the server's first encrypted
5890+ * record (EncryptedExtensions, read by the client). side==1 fuzzes the
5891+ * client's first encrypted record (Finished, read by the server). */
5892+ static int test_tls13_cipher_fuzz_once (WC_RNG * rng ,
5893+ const char * cipher , int side )
5894+ {
5895+ EXPECT_DECLS ;
5896+ WOLFSSL_CTX * ctx_c = NULL ;
5897+ WOLFSSL_CTX * ctx_s = NULL ;
5898+ WOLFSSL * ssl_c = NULL ;
5899+ WOLFSSL * ssl_s = NULL ;
5900+ struct test_memio_ctx test_ctx ;
5901+ byte * buf = NULL ;
5902+ int buf_len = 0 ;
5903+ int rec_off = 0 ;
5904+ int rec_len = 0 ;
5905+ int fuzz_off ;
5906+ byte fuzz_xor ;
5907+ word32 rand32 ;
5908+ int ret ;
5909+ int err ;
5910+
5911+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
5912+ test_ctx .c_ciphers = cipher ;
5913+ test_ctx .s_ciphers = cipher ;
5914+ ExpectIntEQ (test_memio_setup (& test_ctx , & ctx_c , & ctx_s , & ssl_c , & ssl_s ,
5915+ wolfTLSv1_3_client_method , wolfTLSv1_3_server_method ), 0 );
5916+
5917+ /* Drive the handshake forward until the side being fuzzed has written
5918+ * its first AEAD-encrypted record into the peer's read buffer. The
5919+ * server's first encrypted record is queued after its first
5920+ * wolfSSL_accept() (EncryptedExtensions, immediately following
5921+ * ServerHello). The client's first encrypted record is queued once
5922+ * wolfSSL_connect() returns success and the client has sent its
5923+ * Finished. */
5924+ ExpectIntNE (wolfSSL_connect (ssl_c ), WOLFSSL_SUCCESS );
5925+ ExpectIntEQ (wolfSSL_get_error (ssl_c , -1 ), WOLFSSL_ERROR_WANT_READ );
5926+ ExpectIntNE (wolfSSL_accept (ssl_s ), WOLFSSL_SUCCESS );
5927+ ExpectIntEQ (wolfSSL_get_error (ssl_s , -1 ), WOLFSSL_ERROR_WANT_READ );
5928+ if (side == 1 ) {
5929+ ExpectIntEQ (wolfSSL_connect (ssl_c ), WOLFSSL_SUCCESS );
5930+ buf = test_ctx .s_buff ;
5931+ buf_len = test_ctx .s_len ;
5932+ }
5933+ else {
5934+ buf = test_ctx .c_buff ;
5935+ buf_len = test_ctx .c_len ;
5936+ }
5937+
5938+ /* Walk the TLS records in the target buffer and locate the first
5939+ * application_data record (content type 0x17), which holds the first
5940+ * encrypted handshake message. Plaintext records (ServerHello,
5941+ * ChangeCipherSpec for middlebox compatibility) precede it and must be
5942+ * skipped over. */
5943+ if (EXPECT_SUCCESS ()) {
5944+ int off = 0 ;
5945+ while (off + 5 <= buf_len ) {
5946+ int this_len = ((int )buf [off + 3 ] << 8 ) | (int )buf [off + 4 ];
5947+ if (buf [off ] == 0x17 ) {
5948+ rec_off = off ;
5949+ rec_len = this_len ;
5950+ break ;
5951+ }
5952+ off += 5 + this_len ;
5953+ }
5954+ }
5955+ ExpectIntGT (rec_len , 0 );
5956+ ExpectIntLE (rec_off + 5 + rec_len , buf_len );
5957+
5958+ /* Pick a random offset within the encrypted payload (skipping the
5959+ * 5-byte record header) and XOR it with a non-zero value so the byte
5960+ * is guaranteed to change. */
5961+ if (EXPECT_SUCCESS ()) {
5962+ rand32 = 0 ;
5963+ ExpectIntEQ (wc_RNG_GenerateBlock (rng , (byte * )& rand32 ,
5964+ sizeof (rand32 )), 0 );
5965+ fuzz_off = rec_off + 5 + (int )(rand32 % (word32 )rec_len );
5966+ do {
5967+ ExpectIntEQ (wc_RNG_GenerateByte (rng , & fuzz_xor ), 0 );
5968+ } while (EXPECT_SUCCESS () && fuzz_xor == 0 );
5969+ buf [fuzz_off ] ^= fuzz_xor ;
5970+ }
5971+
5972+ /* Drive the receiving side. It must report VERIFY_MAC_ERROR - the
5973+ * corrupted cipher text or tag must surface as a hard error. */
5974+ if (EXPECT_SUCCESS ()) {
5975+ if (side == 1 ) {
5976+ ret = wolfSSL_accept (ssl_s );
5977+ err = wolfSSL_get_error (ssl_s , ret );
5978+ }
5979+ else {
5980+ ret = wolfSSL_connect (ssl_c );
5981+ err = wolfSSL_get_error (ssl_c , ret );
5982+ }
5983+ ExpectIntEQ (ret , WOLFSSL_FATAL_ERROR );
5984+ ExpectTrue ((err == VERIFY_MAC_ERROR ) || (err == AES_GCM_AUTH_E ) ||
5985+ (err == AES_CCM_AUTH_E ));
5986+ }
5987+
5988+ wolfSSL_free (ssl_c );
5989+ wolfSSL_CTX_free (ctx_c );
5990+ wolfSSL_free (ssl_s );
5991+ wolfSSL_CTX_free (ctx_s );
5992+ return EXPECT_RESULT ();
5993+ }
5994+
5995+ /* Run 10 fuzz iterations per side for a single cipher suite. */
5996+ static int test_tls13_cipher_fuzz_cs (WC_RNG * rng , const char * cipher )
5997+ {
5998+ EXPECT_DECLS ;
5999+ int side ;
6000+ int iter ;
6001+
6002+ for (side = 0 ; side < 2 && EXPECT_SUCCESS (); side ++ ) {
6003+ for (iter = 0 ; iter < 10 && EXPECT_SUCCESS (); iter ++ ) {
6004+ int _r = test_tls13_cipher_fuzz_once (rng , cipher , side );
6005+ if (_r != TEST_SUCCESS ) {
6006+ fprintf (stderr , "FAIL cipher=%s side=%d iter=%d\n" ,
6007+ cipher , side , iter );
6008+ }
6009+ ExpectIntEQ (_r , TEST_SUCCESS );
6010+ }
6011+ }
6012+ return EXPECT_RESULT ();
6013+ }
6014+ #endif
6015+
6016+ /* Each per-cipher-suite test below runs the fuzz body (test_tls13_cipher_fuzz_cs)
6017+ * against a single AEAD cipher: it flips a random byte of the first encrypted
6018+ * record on each side of a TLS 1.3 handshake and expects the receiver to fail
6019+ * authentication. AEAD authentication makes it cryptographically infeasible
6020+ * for any single-byte change in the ciphertext or tag to leave authentication
6021+ * intact, so the receiver must report a hard auth error. */
6022+
6023+ int test_tls13_cipher_fuzz_aes128_gcm_sha256 (void )
6024+ {
6025+ EXPECT_DECLS ;
6026+ #if defined(WOLFSSL_TLS13 ) && \
6027+ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
6028+ !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_WOLFSSL_SERVER ) && \
6029+ defined(BUILD_TLS_AES_128_GCM_SHA256 )
6030+ WC_RNG rng ;
6031+ int rngInit = 0 ;
6032+
6033+ XMEMSET (& rng , 0 , sizeof (rng ));
6034+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
6035+ if (EXPECT_SUCCESS ())
6036+ rngInit = 1 ;
6037+
6038+ ExpectIntEQ (test_tls13_cipher_fuzz_cs (& rng , "TLS13-AES128-GCM-SHA256" ),
6039+ TEST_SUCCESS );
6040+
6041+ if (rngInit )
6042+ wc_FreeRng (& rng );
6043+ #endif
6044+ return EXPECT_RESULT ();
6045+ }
6046+
6047+ int test_tls13_cipher_fuzz_aes256_gcm_sha384 (void )
6048+ {
6049+ EXPECT_DECLS ;
6050+ #if defined(WOLFSSL_TLS13 ) && \
6051+ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
6052+ !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_WOLFSSL_SERVER ) && \
6053+ defined(BUILD_TLS_AES_256_GCM_SHA384 )
6054+ WC_RNG rng ;
6055+ int rngInit = 0 ;
6056+
6057+ XMEMSET (& rng , 0 , sizeof (rng ));
6058+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
6059+ if (EXPECT_SUCCESS ())
6060+ rngInit = 1 ;
6061+
6062+ ExpectIntEQ (test_tls13_cipher_fuzz_cs (& rng , "TLS13-AES256-GCM-SHA384" ),
6063+ TEST_SUCCESS );
6064+
6065+ if (rngInit )
6066+ wc_FreeRng (& rng );
6067+ #endif
6068+ return EXPECT_RESULT ();
6069+ }
6070+
6071+ int test_tls13_cipher_fuzz_chacha20_poly1305_sha256 (void )
6072+ {
6073+ EXPECT_DECLS ;
6074+ #if defined(WOLFSSL_TLS13 ) && \
6075+ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
6076+ !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_WOLFSSL_SERVER ) && \
6077+ defined(BUILD_TLS_CHACHA20_POLY1305_SHA256 )
6078+ WC_RNG rng ;
6079+ int rngInit = 0 ;
6080+
6081+ XMEMSET (& rng , 0 , sizeof (rng ));
6082+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
6083+ if (EXPECT_SUCCESS ())
6084+ rngInit = 1 ;
6085+
6086+ ExpectIntEQ (test_tls13_cipher_fuzz_cs (& rng ,
6087+ "TLS13-CHACHA20-POLY1305-SHA256" ), TEST_SUCCESS );
6088+
6089+ if (rngInit )
6090+ wc_FreeRng (& rng );
6091+ #endif
6092+ return EXPECT_RESULT ();
6093+ }
6094+
6095+ int test_tls13_cipher_fuzz_aes128_ccm_sha256 (void )
6096+ {
6097+ EXPECT_DECLS ;
6098+ #if defined(WOLFSSL_TLS13 ) && \
6099+ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
6100+ !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_WOLFSSL_SERVER ) && \
6101+ defined(BUILD_TLS_AES_128_CCM_SHA256 )
6102+ WC_RNG rng ;
6103+ int rngInit = 0 ;
6104+
6105+ XMEMSET (& rng , 0 , sizeof (rng ));
6106+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
6107+ if (EXPECT_SUCCESS ())
6108+ rngInit = 1 ;
6109+
6110+ ExpectIntEQ (test_tls13_cipher_fuzz_cs (& rng , "TLS13-AES128-CCM-SHA256" ),
6111+ TEST_SUCCESS );
6112+
6113+ if (rngInit )
6114+ wc_FreeRng (& rng );
6115+ #endif
6116+ return EXPECT_RESULT ();
6117+ }
6118+
6119+ int test_tls13_cipher_fuzz_aes128_ccm_8_sha256 (void )
6120+ {
6121+ EXPECT_DECLS ;
6122+ #if defined(WOLFSSL_TLS13 ) && \
6123+ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
6124+ !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_WOLFSSL_SERVER ) && \
6125+ defined(BUILD_TLS_AES_128_CCM_8_SHA256 )
6126+ WC_RNG rng ;
6127+ int rngInit = 0 ;
6128+
6129+ XMEMSET (& rng , 0 , sizeof (rng ));
6130+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
6131+ if (EXPECT_SUCCESS ())
6132+ rngInit = 1 ;
6133+
6134+ ExpectIntEQ (test_tls13_cipher_fuzz_cs (& rng , "TLS13-AES128-CCM-8-SHA256" ),
6135+ TEST_SUCCESS );
6136+
6137+ if (rngInit )
6138+ wc_FreeRng (& rng );
6139+ #endif
6140+ return EXPECT_RESULT ();
6141+ }
0 commit comments