Skip to content

Commit c8f3a8f

Browse files
authored
fix: negotiate handshake until the end in wolfSSL_read/wolfSSL_write (#7237)
* tls: negotiate until hs is complete in wolfSSL_read/wolfSSL_write Don't rely on ssl->options.handShakeSate == HANDSHAKE_DONE to check if negotiation is needed. wolfSSL_Connect() or wolfSSL_Accept() job may not yet be completed and/or some messages may be waiting in the buffer because of non-blocking I/O. * tests: test case for handshake with wolfSSL_read()/wolfSSL_write() * doc: clarify wolfSSL_write() * internal.c: rename: need_negotiate -> ssl_in_handshake
1 parent 585f0f1 commit c8f3a8f

3 files changed

Lines changed: 176 additions & 23 deletions

File tree

doc/dox_comments/header_files/ssl.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,15 +2086,18 @@ int wolfSSL_get_using_nonblock(WOLFSSL*);
20862086
\brief This function writes sz bytes from the buffer, data, to the SSL
20872087
connection, ssl. If necessary, wolfSSL_write() will negotiate an SSL/TLS
20882088
session if the handshake has not already been performed yet by
2089-
wolfSSL_connect() or wolfSSL_accept(). wolfSSL_write() works with both
2090-
blocking and non-blocking I/O. When the underlying I/O is non-blocking,
2091-
wolfSSL_write() will return when the underlying I/O could not satisfy the
2092-
needs of wolfSSL_write() to continue. In this case, a call to
2093-
wolfSSL_get_error() will yield either SSL_ERROR_WANT_READ or
2094-
SSL_ERROR_WANT_WRITE. The calling process must then repeat the call to
2095-
wolfSSL_write() when the underlying I/O is ready. If the underlying I/O
2096-
is blocking, wolfSSL_write() will only return once the buffer data of
2097-
size sz has been completely written or an error occurred.
2089+
wolfSSL_connect() or wolfSSL_accept(). When using (D)TLSv1.3 and early data
2090+
feature is compiled in, this function progresses the handshake only up to
2091+
the point when it is possible to send data. Next invokations of
2092+
wolfSSL_Connect()/wolfSSL_Accept()/wolfSSL_read() will complete the
2093+
handshake. wolfSSL_write() works with both blocking and non-blocking I/O.
2094+
When the underlying I/O is non-blocking, wolfSSL_write() will return when
2095+
the underlying I/O could not satisfy the needs of wolfSSL_write() to
2096+
continue. In this case, a call to wolfSSL_get_error() will yield either
2097+
SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. The calling process must then
2098+
repeat the call to wolfSSL_write() when the underlying I/O is ready. If the
2099+
underlying I/O is blocking, wolfSSL_write() will only return once the buffer
2100+
data of size sz has been completely written or an error occurred.
20982101
20992102
\return >0 the number of bytes written upon success.
21002103
\return 0 will be returned upon failure. Call wolfSSL_get_error() for

src/internal.c

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24040,6 +24040,52 @@ static int CheckTLS13AEADSendLimit(WOLFSSL* ssl)
2404024040
}
2404124041
#endif /* WOLFSSL_TLS13 && !WOLFSSL_TLS13_IGNORE_AEAD_LIMITS */
2404224042

24043+
/**
24044+
* ssl_in_handshake():
24045+
* Invoked in wolfSSL_read/wolfSSL_write to check if wolfSSL_negotiate() is
24046+
* needed in the handshake.
24047+
*
24048+
* In TLSv1.2 negotiate until the end of the handshake, unless:
24049+
* 1 in SCR and sending data or
24050+
* 2 in SCR and we have plain data ready
24051+
* Early data logic may bypass this logic in TLSv1.3 when appropriate.
24052+
*/
24053+
static int ssl_in_handshake(WOLFSSL *ssl, int send)
24054+
{
24055+
if (IsSCR(ssl)) {
24056+
if (send) {
24057+
/* allow sending data in SCR */
24058+
return 0;
24059+
} else {
24060+
/* allow reading buffered data in SCR */
24061+
if (ssl->buffers.clearOutputBuffer.length != 0)
24062+
return 0;
24063+
}
24064+
return 1;
24065+
}
24066+
24067+
if (ssl->options.handShakeState != HANDSHAKE_DONE)
24068+
return 1;
24069+
24070+
if (ssl->options.side == WOLFSSL_SERVER_END) {
24071+
if (IsAtLeastTLSv1_3(ssl->version))
24072+
return ssl->options.acceptState < TLS13_TICKET_SENT;
24073+
if (IsAtLeastTLSv1_2(ssl))
24074+
return ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
24075+
return 0;
24076+
}
24077+
24078+
if (ssl->options.side == WOLFSSL_CLIENT_END) {
24079+
if (IsAtLeastTLSv1_3(ssl->version))
24080+
return ssl->options.connectState < FINISHED_DONE;
24081+
if (IsAtLeastTLSv1_2(ssl))
24082+
return ssl->options.connectState < SECOND_REPLY_DONE;
24083+
return 0;
24084+
}
24085+
24086+
return 0;
24087+
}
24088+
2404324089
int SendData(WOLFSSL* ssl, const void* data, int sz)
2404424090
{
2404524091
int sent = 0, /* plainText size */
@@ -24091,7 +24137,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
2409124137
}
2409224138
else
2409324139
#endif
24094-
if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) {
24140+
if (ssl_in_handshake(ssl, 1)) {
2409524141
int err;
2409624142
WOLFSSL_MSG("handshake not complete, trying to finish");
2409724143
if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
@@ -24343,19 +24389,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
2434324389
else
2434424390
#endif
2434524391
{
24346-
int negotiate = 0;
24347-
#ifdef HAVE_SECURE_RENEGOTIATION
24348-
if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
24349-
if (ssl->options.handShakeState != HANDSHAKE_DONE
24350-
&& ssl->buffers.clearOutputBuffer.length == 0)
24351-
negotiate = 1;
24352-
}
24353-
else
24354-
#endif
24355-
if (ssl->options.handShakeState != HANDSHAKE_DONE)
24356-
negotiate = 1;
24357-
24358-
if (negotiate) {
24392+
if (ssl_in_handshake(ssl, 0)) {
2435924393
int err;
2436024394
WOLFSSL_MSG("Handshake not complete, trying to finish");
2436124395
if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {

tests/api.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69676,6 +69676,121 @@ static int test_write_dup(void)
6967669676
return EXPECT_RESULT();
6967769677
}
6967869678

69679+
static int test_read_write_hs(void)
69680+
{
69681+
69682+
EXPECT_DECLS;
69683+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12)
69684+
WOLFSSL_CTX *ctx_s = NULL, *ctx_c = NULL;
69685+
WOLFSSL *ssl_s = NULL, *ssl_c = NULL;
69686+
struct test_memio_ctx test_ctx;
69687+
uint8_t test_buffer[16];
69688+
unsigned int test;
69689+
69690+
/* test == 0 : client writes, server reads */
69691+
/* test == 1 : server writes, client reads */
69692+
for (test = 0; test < 2; test++) {
69693+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
69694+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
69695+
wolfTLSv1_2_client_method,
69696+
wolfTLSv1_2_server_method), 0);
69697+
ExpectIntEQ(wolfSSL_set_group_messages(ssl_s), WOLFSSL_SUCCESS);
69698+
/* CH -> */
69699+
if (test == 0) {
69700+
ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), -1);
69701+
} else {
69702+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer,
69703+
sizeof(test_buffer)), -1);
69704+
}
69705+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
69706+
69707+
/* <- SH + SKE + SHD */
69708+
if (test == 0) {
69709+
ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer,
69710+
sizeof(test_buffer)), -1);
69711+
} else {
69712+
ExpectIntEQ(wolfSSL_write(ssl_s, "hello", 5), -1);
69713+
}
69714+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
69715+
69716+
/* -> CKE + CLIENT FINISHED */
69717+
if (test == 0) {
69718+
ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), -1);
69719+
} else {
69720+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer,
69721+
sizeof(test_buffer)), -1);
69722+
}
69723+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
69724+
69725+
/* abide clang static analyzer */
69726+
if (ssl_s != NULL) {
69727+
/* disable group message to separate sending of ChangeCipherspec
69728+
* from Finished */
69729+
ssl_s->options.groupMessages = 0;
69730+
}
69731+
/* allow writing of CS, but not FINISHED */
69732+
test_ctx.c_len = TEST_MEMIO_BUF_SZ - 6;
69733+
69734+
/* <- CS */
69735+
if (test == 0) {
69736+
ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer,
69737+
sizeof(test_buffer)), -1);
69738+
} else {
69739+
ExpectIntEQ(wolfSSL_write(ssl_s, "hello", 5), -1);
69740+
}
69741+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE);
69742+
69743+
/* move CS message where the client can read it */
69744+
memmove(test_ctx.c_buff,
69745+
(test_ctx.c_buff + TEST_MEMIO_BUF_SZ - 6), 6);
69746+
test_ctx.c_len = 6;
69747+
/* read CS */
69748+
if (test == 0) {
69749+
ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), -1);
69750+
} else {
69751+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer,
69752+
sizeof(test_buffer)), -1);
69753+
}
69754+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
69755+
ExpectIntEQ(test_ctx.c_len, 0);
69756+
69757+
if (test == 0) {
69758+
/* send SERVER FINISHED */
69759+
ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer,
69760+
sizeof(test_buffer)), -1);
69761+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1),
69762+
WOLFSSL_ERROR_WANT_READ);
69763+
} else {
69764+
/* send SERVER FINISHED + App Data */
69765+
ExpectIntEQ(wolfSSL_write(ssl_s, "hello", 5), 5);
69766+
}
69767+
69768+
ExpectIntGT(test_ctx.c_len, 0);
69769+
69770+
/* Send and receive the data */
69771+
if (test == 0) {
69772+
ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), 5);
69773+
ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer,
69774+
sizeof(test_buffer)), 5);
69775+
} else {
69776+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer,
69777+
sizeof(test_buffer)), 5);
69778+
}
69779+
69780+
ExpectBufEQ(test_buffer, "hello", 5);
69781+
69782+
wolfSSL_free(ssl_c);
69783+
wolfSSL_free(ssl_s);
69784+
wolfSSL_CTX_free(ctx_c);
69785+
wolfSSL_CTX_free(ctx_s);
69786+
ssl_c = ssl_s = NULL;
69787+
ctx_c = ctx_s = NULL;
69788+
}
69789+
69790+
#endif
69791+
return EXPECT_RESULT();
69792+
}
69793+
6967969794
/*----------------------------------------------------------------------------*
6968069795
| Main
6968169796
*----------------------------------------------------------------------------*/
@@ -70983,6 +71098,7 @@ TEST_CASE testCases[] = {
7098371098
TEST_DECL(test_tls13_early_data),
7098471099
TEST_DECL(test_tls_multi_handshakes_one_record),
7098571100
TEST_DECL(test_write_dup),
71101+
TEST_DECL(test_read_write_hs),
7098671102
/* This test needs to stay at the end to clean up any caches allocated. */
7098771103
TEST_DECL(test_wolfSSL_Cleanup)
7098871104
};

0 commit comments

Comments
 (0)