@@ -4542,6 +4542,129 @@ int test_tls13_plaintext_alert(void)
45424542
45434543 wolfSSL_free (ssl );
45444544 wolfSSL_CTX_free (ctx );
4545+ ssl = NULL ;
4546+ ctx = NULL ;
4547+
4548+ /* Negative test: a plaintext alert must NOT be ignored once the peer has
4549+ * responded with an encrypted handshake message. Complete a handshake so
4550+ * the peer is encrypting, then feed the client a plaintext alert. */
4551+ #if !defined(NO_WOLFSSL_CLIENT ) && !defined(NO_FILESYSTEM )
4552+ {
4553+ WOLFSSL_CTX * ctx_c = NULL ;
4554+ WOLFSSL_CTX * ctx_s = NULL ;
4555+ WOLFSSL * ssl_c = NULL ;
4556+ WOLFSSL * ssl_s = NULL ;
4557+ struct test_memio_ctx test_ctx ;
4558+ /* Plaintext alert record: fatal (2), handshake_failure (40). */
4559+ byte ptAlert [] = { 0x15 , 0x03 , 0x03 , 0x00 , 0x02 , 0x02 , 0x28 };
4560+ char data [16 ];
4561+
4562+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
4563+ ExpectIntEQ (test_memio_setup (& test_ctx , & ctx_c , & ctx_s , & ssl_c , & ssl_s ,
4564+ wolfTLSv1_3_client_method , wolfTLSv1_3_server_method ), 0 );
4565+ ExpectIntEQ (test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL ), 0 );
4566+
4567+ /* Drop any post-handshake data (e.g. session tickets) queued for the
4568+ * client and feed it only the plaintext alert. */
4569+ test_memio_clear_buffer (& test_ctx , 1 );
4570+ ExpectIntEQ (test_memio_inject_message (& test_ctx , 1 , (const char * )ptAlert ,
4571+ (int )sizeof (ptAlert )), 0 );
4572+
4573+ /* Plaintext alert is rejected as the peer is encrypting. */
4574+ ExpectIntLT (wolfSSL_read (ssl_c , data , (int )sizeof (data )), 0 );
4575+ ExpectIntEQ (wolfSSL_get_error (ssl_c , WOLFSSL_FATAL_ERROR ),
4576+ WC_NO_ERR_TRACE (PARSE_ERROR ));
4577+
4578+ wolfSSL_free (ssl_c );
4579+ wolfSSL_free (ssl_s );
4580+ wolfSSL_CTX_free (ctx_c );
4581+ wolfSSL_CTX_free (ctx_s );
4582+ }
4583+
4584+ /* Negative test (server): a plaintext alert must NOT be ignored once the
4585+ * client has sent an encrypted handshake message, even before the
4586+ * handshake is complete. Use client authentication so that the client
4587+ * sends an encrypted Certificate message before Finished. */
4588+ {
4589+ WOLFSSL_CTX * ctx_c = NULL ;
4590+ WOLFSSL_CTX * ctx_s = NULL ;
4591+ WOLFSSL * ssl_c = NULL ;
4592+ WOLFSSL * ssl_s = NULL ;
4593+ struct test_memio_ctx test_ctx ;
4594+ /* Plaintext alert record: fatal (2), handshake_failure (40). */
4595+ byte ptAlert [] = { 0x15 , 0x03 , 0x03 , 0x00 , 0x02 , 0x02 , 0x28 };
4596+ int end = 0 ;
4597+
4598+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
4599+ ExpectIntEQ (test_memio_setup (& test_ctx , & ctx_c , & ctx_s , & ssl_c , & ssl_s ,
4600+ wolfTLSv1_3_client_method , wolfTLSv1_3_server_method ), 0 );
4601+ /* Server requires a client certificate. */
4602+ ExpectTrue (wolfSSL_CTX_load_verify_locations (ctx_s , cliCertFile ,
4603+ NULL ) == WOLFSSL_SUCCESS );
4604+ if (EXPECT_SUCCESS ()) {
4605+ wolfSSL_set_verify (ssl_s , WOLFSSL_VERIFY_PEER |
4606+ WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT , NULL );
4607+ }
4608+ ExpectTrue (wolfSSL_use_certificate_file (ssl_c , cliCertFile ,
4609+ CERT_FILETYPE ) == WOLFSSL_SUCCESS );
4610+ ExpectTrue (wolfSSL_use_PrivateKey_file (ssl_c , cliKeyFile ,
4611+ CERT_FILETYPE ) == WOLFSSL_SUCCESS );
4612+
4613+ /* Client Hello. */
4614+ ExpectIntEQ (wolfSSL_connect (ssl_c ), -1 );
4615+ ExpectIntEQ (wolfSSL_get_error (ssl_c , -1 ), WOLFSSL_ERROR_WANT_READ );
4616+ /* Server flight including CertificateRequest. */
4617+ ExpectIntEQ (wolfSSL_accept (ssl_s ), -1 );
4618+ ExpectIntEQ (wolfSSL_get_error (ssl_s , -1 ), WOLFSSL_ERROR_WANT_READ );
4619+ /* Client flight: [CCS,] Certificate, CertificateVerify, Finished. */
4620+ ExpectIntEQ (wolfSSL_connect (ssl_c ), WOLFSSL_SUCCESS );
4621+
4622+ /* Find the end of the first encrypted record (outer content type
4623+ * application_data) the client sent - the Certificate message. */
4624+ while (end + 5 <= test_ctx .s_len ) {
4625+ byte recType = test_ctx .s_buff [end ];
4626+ end += 5 + ((test_ctx .s_buff [end + 3 ] << 8 ) |
4627+ test_ctx .s_buff [end + 4 ]);
4628+ if (recType == 0x17 )
4629+ break ;
4630+ }
4631+ ExpectIntLE (end , test_ctx .s_len );
4632+ ExpectIntGT (end , 0 );
4633+ /* Remove the records after it (CertificateVerify and Finished),
4634+ * working backwards a message at a time. */
4635+ while (EXPECT_SUCCESS () && test_ctx .s_len > end ) {
4636+ int i ;
4637+ int msgOff = 0 ;
4638+
4639+ for (i = 0 ; i < test_ctx .s_msg_count - 1 ; i ++ )
4640+ msgOff += test_ctx .s_msg_sizes [i ];
4641+ if (msgOff >= end ) {
4642+ /* Last message is wholly after the Certificate record. */
4643+ ExpectIntEQ (test_memio_drop_message (& test_ctx , 0 ,
4644+ test_ctx .s_msg_count - 1 ), 0 );
4645+ }
4646+ else {
4647+ /* Last message also holds the records to keep. */
4648+ ExpectIntEQ (test_memio_remove_from_buffer (& test_ctx , 0 , end ,
4649+ test_ctx .s_len - end ), 0 );
4650+ }
4651+ }
4652+ /* Follow the encrypted Certificate message with a plaintext alert. */
4653+ ExpectIntEQ (test_memio_inject_message (& test_ctx , 0 ,
4654+ (const char * )ptAlert , (int )sizeof (ptAlert )), 0 );
4655+
4656+ /* Plaintext alert is rejected as the client has sent an encrypted
4657+ * handshake message. */
4658+ ExpectIntEQ (wolfSSL_accept (ssl_s ), -1 );
4659+ ExpectIntEQ (wolfSSL_get_error (ssl_s , WOLFSSL_FATAL_ERROR ),
4660+ WC_NO_ERR_TRACE (PARSE_ERROR ));
4661+
4662+ wolfSSL_free (ssl_c );
4663+ wolfSSL_free (ssl_s );
4664+ wolfSSL_CTX_free (ctx_c );
4665+ wolfSSL_CTX_free (ctx_s );
4666+ }
4667+ #endif
45454668#else
45464669 /* Fail on plaintext alert when encryption keys on. */
45474670
0 commit comments