diff --git a/src/internal.c b/src/internal.c index f74b96726..2324598c5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9199,13 +9199,21 @@ int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) * to be used for triggering retransmission of whole DtlsMsgPool. * change cipher suite type is not verified here */ - return ((fragOffset == 0) && - (((ssl->options.side == WOLFSSL_SERVER_END) && - ((type == client_hello) || - ((ssl->options.verifyPeer) && (type == certificate)) || - ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) || - ((ssl->options.side == WOLFSSL_CLIENT_END) && - (type == hello_request || type == server_hello)))); + if (fragOffset == 0) { + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (type == client_hello) + return 1; + else if (ssl->options.verifyPeer && type == certificate) + return 1; + else if (!ssl->options.verifyPeer && type == client_key_exchange) + return 1; + } + else { + if (type == hello_request || type == server_hello) + return 1; + } + } + return 0; } @@ -20003,9 +20011,10 @@ static int HandleDTLSDecryptFailed(WOLFSSL* ssl) static int DtlsShouldDrop(WOLFSSL* ssl, int retcode) { - if (ssl->options.handShakeDone && !IsEncryptionOn(ssl, 0)) { + if (ssl->options.handShakeDone && !IsEncryptionOn(ssl, 0) && + !ssl->options.dtlsHsRetain) { WOLFSSL_MSG("Silently dropping plaintext DTLS message " - "on established connection."); + "on established connection when we have nothing to send."); return 1; } diff --git a/tests/api.c b/tests/api.c index ddb7b025f..1b067be6d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -64936,6 +64936,73 @@ static int test_dtls_client_hello_timeout(void) return EXPECT_RESULT(); } +/* DTLS test when dropping the changed cipher spec message */ +static int test_dtls_dropped_ccs(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL_CTX *ctx_s = NULL; + WOLFSSL *ssl_c = NULL; + WOLFSSL *ssl_s = NULL; + struct test_memio_ctx test_ctx; + DtlsRecordLayerHeader* dtlsRH; + size_t len; + byte data[1]; + + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); + + /* CH1 */ + ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + /* HVR */ + ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); + /* CH2 */ + ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + /* Server first flight */ + ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); + /* Client flight */ + ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + /* Server ccs + finished */ + ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1); + + /* Drop the ccs */ + dtlsRH = (DtlsRecordLayerHeader*)test_ctx.c_buff; + len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]); + ExpectIntEQ(len, 1); + ExpectIntEQ(dtlsRH->type, change_cipher_spec); + if (EXPECT_SUCCESS()) { + XMEMMOVE(test_ctx.c_buff, test_ctx.c_buff + + sizeof(DtlsRecordLayerHeader) + len, test_ctx.c_len - + (sizeof(DtlsRecordLayerHeader) + len)); + } + test_ctx.c_len -= sizeof(DtlsRecordLayerHeader) + len; + + /* Client rtx flight */ + ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); + /* Server ccs + finished rtx */ + ExpectIntEQ(wolfSSL_read(ssl_s, data, sizeof(data)), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); + /* Client processes finished */ + ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); +#endif + return EXPECT_RESULT(); +} /** * Make sure we don't send RSA Signature Hash Algorithms in the * CertificateRequest when we don't have any such ciphers set. @@ -66286,6 +66353,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_dtls_downgrade_scr), TEST_DECL(test_dtls_client_hello_timeout_downgrade), TEST_DECL(test_dtls_client_hello_timeout), + TEST_DECL(test_dtls_dropped_ccs), TEST_DECL(test_certreq_sighash_algos), /* This test needs to stay at the end to clean up any caches allocated. */ TEST_DECL(test_wolfSSL_Cleanup)