DTLS fixes with WANT_WRITE simulations

- WANT_WRITE could be returned in unexpected places. This patch takes care of that.
- Change state after SendBuffered only if in a sending state to begin with.
- Adapt client and server to simulate WANT_WRITE with DTLS
pull/5084/head
Juliusz Sosinowicz 2022-04-26 15:51:50 +02:00
parent 798d81723b
commit a31b76878f
6 changed files with 97 additions and 24 deletions

View File

@ -232,9 +232,12 @@ static int NonBlockingSSL_Connect(WOLFSSL* ssl)
}
}
#ifdef WOLFSSL_DTLS
else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) &&
wolfSSL_dtls_got_timeout(ssl) >= 0) {
error = WOLFSSL_ERROR_WANT_READ;
else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl)) {
ret = wolfSSL_dtls_got_timeout(ssl);
if (ret != WOLFSSL_SUCCESS)
error = wolfSSL_get_error(ssl, ret);
else
error = WOLFSSL_ERROR_WANT_READ;
}
#endif
else {
@ -3561,6 +3564,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
err_sys("error in setting fd");
}
if (simulateWantWrite) {
wolfSSL_SetIOWriteCtx(ssl, (void*)&sockfd);
}
/* STARTTLS */
if (doSTARTTLS) {
if (StartTLS_Init(&sockfd) != WOLFSSL_SUCCESS) {

View File

@ -354,9 +354,12 @@ static int NonBlockingSSL_Accept(SSL* ssl)
error = WOLFSSL_ERROR_WANT_READ;
}
#ifdef WOLFSSL_DTLS
else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) &&
wolfSSL_dtls_got_timeout(ssl) >= 0) {
error = WOLFSSL_ERROR_WANT_READ;
else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl)) {
ret = wolfSSL_dtls_got_timeout(ssl);
if (ret != WOLFSSL_SUCCESS)
error = wolfSSL_get_error(ssl, ret);
else
error = WOLFSSL_ERROR_WANT_READ;
}
#endif
else {
@ -2958,6 +2961,15 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
else {
wolfSSL_dtls_set_peer(ssl, &client_addr, client_len);
}
if (simulateWantWrite) {
/* connect on a udp to associate peer with this fd to make it
* simpler for SimulateWantWriteIOSendCb */
if (connect(clientfd, (struct sockaddr*)&client_addr,
client_len) != 0) {
err_sys_ex(catastrophic, "error in connecting to peer");
}
wolfSSL_SetIOWriteCtx(ssl, (void*)&sockfd);
}
}
#endif

View File

@ -8883,9 +8883,8 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
dataSz += DTLS_HANDSHAKE_HEADER_SZ;
AddHandShakeHeader(data,
inputSz, ssl->fragOffset, fragSz, type, ssl);
}
if (ssl->options.dtls)
ssl->keys.dtls_handshake_number--;
}
if (IsDtlsNotSctpMode(ssl) &&
(ret = DtlsMsgPoolSave(ssl, data,
fragSz + DTLS_HANDSHAKE_HEADER_SZ, type))
@ -17479,6 +17478,11 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
#endif
}
if (ret != 0
/* DoDtlsHandShakeMsg can return a WANT_WRITE when
* calling DtlsMsgPoolSend. This msg is done
* processing so let's move on. */
&& (!ssl->options.dtls
|| ret != WANT_WRITE)
#ifdef WOLFSSL_ASYNC_CRYPT
/* In async case, on pending, move onto next message.
* Current message should have been DtlsMsgStore'ed and
@ -26783,6 +26787,12 @@ int SendCertificateVerify(WOLFSSL* ssl)
if (args->output == NULL) {
ERROR_OUT(BUFFER_ERROR, exit_scv);
}
#ifdef WOLFSSL_DTLS
/* We have re-entered this funtion after a WANT_WRITE. Make sure
* the handshake number stays the same. */
if (ssl->options.dtls && ssl->fragOffset != 0)
ssl->keys.dtls_handshake_number--;
#endif
AddHeaders(args->output, (word32)args->length + args->extraSz +
VERIFY_HEADER, certificate_verify, ssl);
@ -28871,6 +28881,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
case TLS_ASYNC_FINALIZE:
{
#ifdef WOLFSSL_DTLS
/* We have re-entered this funtion after a WANT_WRITE. Make sure
* the handshake number stays the same. */
if (ssl->options.dtls && ssl->fragOffset != 0)
ssl->keys.dtls_handshake_number--;
#endif
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
defined(HAVE_CURVE448)
if (ssl->specs.kea == ecdhe_psk_kea ||

View File

@ -11836,9 +11836,17 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
* fragment, fragOffset is zero again, and the state can be
* advanced. */
if (ssl->fragOffset == 0) {
ssl->options.connectState++;
WOLFSSL_MSG("connect state: "
"Advanced from last buffered fragment send");
if (ssl->options.connectState == CONNECT_BEGIN ||
ssl->options.connectState == HELLO_AGAIN ||
ssl->options.connectState == FIRST_REPLY_DONE ||
ssl->options.connectState == FIRST_REPLY_FIRST ||
ssl->options.connectState == FIRST_REPLY_SECOND ||
ssl->options.connectState == FIRST_REPLY_THIRD ||
ssl->options.connectState == FIRST_REPLY_FOURTH) {
ssl->options.connectState++;
WOLFSSL_MSG("connect state: "
"Advanced from last buffered fragment send");
}
}
else {
WOLFSSL_MSG("connect state: "
@ -12303,9 +12311,19 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
* fragment, fragOffset is zero again, and the state can be
* advanced. */
if (ssl->fragOffset == 0) {
ssl->options.acceptState++;
WOLFSSL_MSG("accept state: "
"Advanced from last buffered fragment send");
if (ssl->options.acceptState == ACCEPT_FIRST_REPLY_DONE ||
ssl->options.acceptState == SERVER_HELLO_SENT ||
ssl->options.acceptState == CERT_SENT ||
ssl->options.acceptState == CERT_STATUS_SENT ||
ssl->options.acceptState == KEY_EXCHANGE_SENT ||
ssl->options.acceptState == CERT_REQ_SENT ||
ssl->options.acceptState == ACCEPT_SECOND_REPLY_DONE ||
ssl->options.acceptState == TICKET_SENT ||
ssl->options.acceptState == CHANGE_CIPHER_SENT) {
ssl->options.acceptState++;
WOLFSSL_MSG("accept state: "
"Advanced from last buffered fragment send");
}
}
else {
WOLFSSL_MSG("accept state: "

View File

@ -8637,9 +8637,18 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
* fragment, fragOffset is zero again, and the state can be
* advanced. */
if (ssl->fragOffset == 0) {
ssl->options.connectState++;
WOLFSSL_MSG("connect state: "
"Advanced from last buffered fragment send");
/* Only increment from states in which we send data */
if (ssl->options.connectState == CONNECT_BEGIN ||
ssl->options.connectState == HELLO_AGAIN ||
ssl->options.connectState == FIRST_REPLY_DONE ||
ssl->options.connectState == FIRST_REPLY_FIRST ||
ssl->options.connectState == FIRST_REPLY_SECOND ||
ssl->options.connectState == FIRST_REPLY_THIRD ||
ssl->options.connectState == FIRST_REPLY_FOURTH) {
ssl->options.connectState++;
WOLFSSL_MSG("connect state: "
"Advanced from last buffered fragment send");
}
}
else {
WOLFSSL_MSG("connect state: "
@ -9592,9 +9601,22 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
* fragment, fragOffset is zero again, and the state can be
* advanced. */
if (ssl->fragOffset == 0) {
ssl->options.acceptState++;
WOLFSSL_MSG("accept state: "
"Advanced from last buffered fragment send");
/* Only increment from states in which we send data */
if (ssl->options.acceptState == TLS13_ACCEPT_CLIENT_HELLO_DONE ||
ssl->options.acceptState == TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE ||
ssl->options.acceptState == TLS13_ACCEPT_SECOND_REPLY_DONE ||
ssl->options.acceptState == TLS13_SERVER_HELLO_SENT ||
ssl->options.acceptState == TLS13_ACCEPT_THIRD_REPLY_DONE ||
ssl->options.acceptState == TLS13_SERVER_EXTENSIONS_SENT ||
ssl->options.acceptState == TLS13_CERT_REQ_SENT ||
ssl->options.acceptState == TLS13_CERT_SENT ||
ssl->options.acceptState == TLS13_CERT_VERIFY_SENT ||
ssl->options.acceptState == TLS13_ACCEPT_FINISHED_SENT ||
ssl->options.acceptState == TLS13_ACCEPT_FINISHED_DONE) {
ssl->options.acceptState++;
WOLFSSL_MSG("accept state: "
"Advanced from last buffered fragment send");
}
}
else {
WOLFSSL_MSG("accept state: "

View File

@ -1847,10 +1847,8 @@ static WC_INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port,
}
tcp_socket(sockfd, udp, sctp);
if (!udp) {
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
err_sys_with_errno("tcp connect failed");
}
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
err_sys_with_errno("tcp connect failed");
}
#endif /* WOLFSSL_WOLFSENTRY_HOOKS */