Skip to content

Commit f431fae

Browse files
committed
wolfDTLS_accept_stateless: Fix handling for early data
- wolfDTLS_accept_stateless now returns before sending any flights. This allows the user to retrieve early data. - wolfio.c: Clearing `userSet` allows our callback to change the address while in stateless parsing
1 parent b6cfdcb commit f431fae

7 files changed

Lines changed: 274 additions & 10 deletions

File tree

src/ssl.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11012,6 +11012,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
1101211012
FALL_THROUGH;
1101311013

1101411014
case ACCEPT_FIRST_REPLY_DONE :
11015+
if (ssl->options.returnOnGoodCh) {
11016+
/* Higher level in stack wants us to return. Simulate a
11017+
* WANT_WRITE to accomplish this. */
11018+
ssl->error = WANT_WRITE;
11019+
return WOLFSSL_FATAL_ERROR;
11020+
}
1101511021
if ( (ssl->error = SendServerHello(ssl)) != 0) {
1101611022
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
1101711023
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
@@ -11312,15 +11318,19 @@ int wolfDTLS_accept_stateless(WOLFSSL* ssl)
1131211318
if (wolfDTLS_SetChGoodCb(ssl, chGoodDisableReadCB, &cb) != WOLFSSL_SUCCESS)
1131311319
return WOLFSSL_FATAL_ERROR;
1131411320

11321+
ssl->options.returnOnGoodCh = 1;
1131511322
ret = wolfSSL_accept(ssl);
11323+
ssl->options.returnOnGoodCh = 0;
1131611324
/* restore user options */
1131711325
ssl->options.disableRead = disableRead;
1131811326
(void)wolfDTLS_SetChGoodCb(ssl, cb.userCb, cb.userCtx);
1131911327
if (ret == WOLFSSL_SUCCESS) {
1132011328
WOLFSSL_MSG("should not happen. maybe the user called "
1132111329
"wolfDTLS_accept_stateless instead of wolfSSL_accept");
1132211330
}
11323-
else if (ssl->error == WC_NO_ERR_TRACE(WANT_READ)) {
11331+
else if (ssl->error == WC_NO_ERR_TRACE(WANT_READ) ||
11332+
ssl->error == WC_NO_ERR_TRACE(WANT_WRITE)) {
11333+
ssl->error = 0;
1132411334
if (ssl->options.dtlsStateful)
1132511335
ret = WOLFSSL_SUCCESS;
1132611336
else

src/tls13.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14596,6 +14596,12 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
1459614596
FALL_THROUGH;
1459714597

1459814598
case TLS13_ACCEPT_SECOND_REPLY_DONE :
14599+
if (ssl->options.returnOnGoodCh) {
14600+
/* Higher level in stack wants us to return. Simulate a
14601+
* WANT_WRITE to accomplish this. */
14602+
ssl->error = WANT_WRITE;
14603+
return WOLFSSL_FATAL_ERROR;
14604+
}
1459914605

1460014606
if ((ssl->error = SendTls13ServerHello(ssl, server_hello)) != 0) {
1460114607
WOLFSSL_ERROR(ssl->error);

src/wolfio.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,18 @@ static int isDGramSock(int sfd)
638638
}
639639
}
640640

641+
void wolfSSL_SetRecvFrom(WOLFSSL* ssl, WolfSSLRecvFrom recvFrom)
642+
{
643+
if (ssl != NULL)
644+
ssl->buffers.dtlsCtx.recvfrom = recvFrom;
645+
}
646+
647+
void wolfSSL_SetSendTo(WOLFSSL* ssl, WolfSSLSento sendTo)
648+
{
649+
if (ssl != NULL)
650+
ssl->buffers.dtlsCtx.sendto = sendTo;
651+
}
652+
641653
/* The receive embedded callback
642654
* return : nb bytes read, or error
643655
*/
@@ -686,10 +698,6 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
686698
/* Store the peer address. It is used to calculate the DTLS cookie. */
687699
newPeer = dtlsCtx->peer.sa == NULL || !ssl->options.dtlsStateful;
688700
peer = &lclPeer;
689-
if (dtlsCtx->peer.sa != NULL) {
690-
XMEMCPY(peer, (SOCKADDR_S*)dtlsCtx->peer.sa, MIN(sizeof(lclPeer),
691-
dtlsCtx->peer.sz));
692-
}
693701
peerSz = sizeof(lclPeer);
694702
}
695703

@@ -785,8 +793,16 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
785793

786794
{
787795
XSOCKLENT inPeerSz = peerSz;
788-
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz,
789-
ssl->rflags, (SOCKADDR*)peer, peer != NULL ? &inPeerSz : NULL);
796+
if (dtlsCtx->recvfrom == NULL) {
797+
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz,
798+
ssl->rflags, (SOCKADDR*)peer,
799+
peer != NULL ? &inPeerSz : NULL);
800+
}
801+
else {
802+
recvd = (int)dtlsCtx->recvfrom(sd, buf, (size_t) sz,
803+
ssl->rflags, (SOCKADDR*) peer,
804+
peer != NULL ? &inPeerSz : NULL);
805+
}
790806
/* Truncate peerSz. From the RECV(2) man page
791807
* The returned address is truncated if the buffer provided is too
792808
* small; in this case, addrlen will return a value greater than was
@@ -856,6 +872,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
856872
/* Store size of saved address. Locking handled internally. */
857873
if (wolfSSL_dtls_set_peer(ssl, peer, peerSz) != WOLFSSL_SUCCESS)
858874
return WOLFSSL_CBIO_ERR_GENERAL;
875+
dtlsCtx->userSet = 0;
859876
}
860877
#ifndef WOLFSSL_PEER_ADDRESS_CHANGES
861878
else {
@@ -914,8 +931,14 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
914931
#endif
915932
}
916933

917-
sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, ssl->wflags,
918-
(const SOCKADDR*)peer, peerSz);
934+
if (dtlsCtx->sendto == NULL) {
935+
sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, ssl->wflags,
936+
(const SOCKADDR*)peer, peerSz);
937+
}
938+
else {
939+
sent = (int)dtlsCtx->sendto(sd, buf, (size_t)sz, ssl->wflags,
940+
(const SOCKADDR*)peer, peerSz);
941+
}
919942

920943
sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING);
921944

tests/api/test_dtls.c

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,3 +1889,211 @@ int test_dtls_certreq_order(void)
18891889
#endif
18901890
return EXPECT_RESULT();
18911891
}
1892+
1893+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
1894+
struct {
1895+
struct test_memio_ctx* test_ctx;
1896+
WOLFSSL* ssl_s;
1897+
int fd;
1898+
SOCKADDR_S peer_addr;
1899+
} test_memio_wolfio_ctx;
1900+
1901+
static ssize_t test_memio_wolfio_recvfrom(int sockfd, void* buf,
1902+
size_t len, int flags, void* src_addr, void* addrlen)
1903+
{
1904+
int ret;
1905+
(void)flags;
1906+
if (sockfd != test_memio_wolfio_ctx.fd) {
1907+
errno = EINVAL;
1908+
return -1;
1909+
}
1910+
ret = test_memio_read_cb(test_memio_wolfio_ctx.ssl_s,
1911+
(char*)buf, (int)len, test_memio_wolfio_ctx.test_ctx);
1912+
if (ret <= 0) {
1913+
if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ))
1914+
errno = EAGAIN;
1915+
else
1916+
errno = EINVAL;
1917+
return -1;
1918+
}
1919+
XMEMCPY(src_addr, &test_memio_wolfio_ctx.peer_addr,
1920+
MIN(sizeof(test_memio_wolfio_ctx.peer_addr),
1921+
*(word32*)addrlen));
1922+
*(word32*)addrlen = sizeof(test_memio_wolfio_ctx.peer_addr);
1923+
return ret;
1924+
}
1925+
1926+
static ssize_t test_memio_wolfio_sendto(int sockfd, const void* buf,
1927+
size_t len, int flags, const void* dest_addr, word32 addrlen)
1928+
{
1929+
int ret;
1930+
(void) flags;
1931+
(void) dest_addr;
1932+
(void) addrlen;
1933+
if (sockfd != test_memio_wolfio_ctx.fd) {
1934+
errno = EINVAL;
1935+
return -1;
1936+
}
1937+
if (dest_addr != NULL && addrlen != 0 &&
1938+
(sizeof(test_memio_wolfio_ctx.peer_addr) != addrlen ||
1939+
XMEMCMP(dest_addr, &test_memio_wolfio_ctx.peer_addr,
1940+
addrlen) != 0)) {
1941+
errno = EINVAL;
1942+
return -1;
1943+
}
1944+
ret = test_memio_write_cb(test_memio_wolfio_ctx.ssl_s, (char*)buf,
1945+
(int)len, test_memio_wolfio_ctx.test_ctx);
1946+
if (ret <= 0) {
1947+
if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_WRITE))
1948+
errno = EAGAIN;
1949+
else
1950+
errno = EINVAL;
1951+
return -1;
1952+
}
1953+
return ret;
1954+
}
1955+
#endif
1956+
1957+
/* Test stateless API with wolfio */
1958+
int test_dtls_memio_wolfio(void)
1959+
{
1960+
EXPECT_DECLS;
1961+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
1962+
size_t i;
1963+
struct {
1964+
method_provider client_meth;
1965+
method_provider server_meth;
1966+
} params[] = {
1967+
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
1968+
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method },
1969+
#endif
1970+
#if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_DTLS)
1971+
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method },
1972+
#endif
1973+
#if !defined(NO_OLD_TLS) && defined(WOLFSSL_DTLS)
1974+
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method },
1975+
#endif
1976+
};
1977+
XMEMSET(&test_memio_wolfio_ctx, 0, sizeof(test_memio_wolfio_ctx));
1978+
for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
1979+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
1980+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
1981+
struct test_memio_ctx test_ctx;
1982+
1983+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
1984+
1985+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
1986+
params[i].client_meth, params[i].server_meth), 0);
1987+
1988+
test_memio_wolfio_ctx.test_ctx = &test_ctx;
1989+
test_memio_wolfio_ctx.ssl_s = ssl_s;
1990+
/* Large number to error out if any syscalls are called with it */
1991+
test_memio_wolfio_ctx.fd = 6000;
1992+
XMEMSET(&test_memio_wolfio_ctx.peer_addr, 0,
1993+
sizeof(test_memio_wolfio_ctx.peer_addr));
1994+
test_memio_wolfio_ctx.peer_addr.ss_family = AF_INET;
1995+
1996+
wolfSSL_dtls_set_using_nonblock(ssl_s, 1);
1997+
wolfSSL_SetRecvFrom(ssl_s, test_memio_wolfio_recvfrom);
1998+
wolfSSL_SetSendTo(ssl_s, test_memio_wolfio_sendto);
1999+
/* Restore default functions */
2000+
wolfSSL_SSLSetIORecv(ssl_s, EmbedReceiveFrom);
2001+
wolfSSL_SSLSetIOSend(ssl_s, EmbedSendTo);
2002+
ExpectIntEQ(wolfSSL_set_fd(ssl_s, test_memio_wolfio_ctx.fd),
2003+
WOLFSSL_SUCCESS);
2004+
2005+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
2006+
2007+
wolfSSL_free(ssl_s);
2008+
wolfSSL_free(ssl_c);
2009+
wolfSSL_CTX_free(ctx_s);
2010+
wolfSSL_CTX_free(ctx_c);
2011+
}
2012+
#endif
2013+
return EXPECT_RESULT();
2014+
}
2015+
2016+
/* DTLS using stateless API handling new addresses with wolfio */
2017+
int test_dtls_memio_wolfio_stateless(void)
2018+
{
2019+
EXPECT_DECLS;
2020+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
2021+
size_t i, j;
2022+
struct {
2023+
method_provider client_meth;
2024+
method_provider server_meth;
2025+
} params[] = {
2026+
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
2027+
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method },
2028+
#endif
2029+
#if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_DTLS)
2030+
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method },
2031+
#endif
2032+
#if !defined(NO_OLD_TLS) && defined(WOLFSSL_DTLS)
2033+
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method },
2034+
#endif
2035+
};
2036+
XMEMSET(&test_memio_wolfio_ctx, 0, sizeof(test_memio_wolfio_ctx));
2037+
for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
2038+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
2039+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
2040+
struct test_memio_ctx test_ctx;
2041+
char chBuf[1000];
2042+
int chSz = sizeof(chBuf);
2043+
2044+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
2045+
2046+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
2047+
params[i].client_meth, params[i].server_meth), 0);
2048+
2049+
test_memio_wolfio_ctx.test_ctx = &test_ctx;
2050+
test_memio_wolfio_ctx.ssl_s = ssl_s;
2051+
/* Large number to error out if any syscalls are called with it */
2052+
test_memio_wolfio_ctx.fd = 6000;
2053+
XMEMSET(&test_memio_wolfio_ctx.peer_addr, 0,
2054+
sizeof(test_memio_wolfio_ctx.peer_addr));
2055+
test_memio_wolfio_ctx.peer_addr.ss_family = AF_INET;
2056+
2057+
wolfSSL_dtls_set_using_nonblock(ssl_s, 1);
2058+
wolfSSL_SetRecvFrom(ssl_s, test_memio_wolfio_recvfrom);
2059+
/* Restore default functions */
2060+
wolfSSL_SSLSetIORecv(ssl_s, EmbedReceiveFrom);
2061+
ExpectIntEQ(wolfSSL_set_read_fd(ssl_s, test_memio_wolfio_ctx.fd),
2062+
WOLFSSL_SUCCESS);
2063+
2064+
/* start handshake, send first ClientHello */
2065+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
2066+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
2067+
ExpectIntEQ(test_memio_copy_message(&test_ctx, 0, chBuf, &chSz, 0), 0);
2068+
ExpectIntGT(chSz, 0);
2069+
test_memio_clear_buffer(&test_ctx, 0);
2070+
2071+
/* Send CH from different addresses */
2072+
for (j = 0; j < 10 && !EXPECT_FAIL(); j++,
2073+
(((SOCKADDR_IN*)&test_memio_wolfio_ctx.peer_addr))->sin_port++) {
2074+
const char* hrrBuf = NULL;
2075+
int hrrSz = 0;
2076+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, chBuf, chSz), 0);
2077+
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 0);
2078+
ExpectIntEQ(test_memio_get_message(&test_ctx, 1, &hrrBuf, &hrrSz, 0), 0);
2079+
ExpectNotNull(hrrBuf);
2080+
ExpectIntGT(hrrSz, 0);
2081+
test_memio_clear_buffer(&test_ctx, 0);
2082+
}
2083+
test_memio_clear_buffer(&test_ctx, 1);
2084+
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), 1);
2085+
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 0);
2086+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
2087+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
2088+
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 1);
2089+
2090+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
2091+
2092+
wolfSSL_free(ssl_s);
2093+
wolfSSL_free(ssl_c);
2094+
wolfSSL_CTX_free(ctx_s);
2095+
wolfSSL_CTX_free(ctx_c);
2096+
}
2097+
#endif
2098+
return EXPECT_RESULT();
2099+
}

tests/api/test_dtls.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ int test_dtls_replay(void);
4343
int test_dtls_srtp(void);
4444
int test_dtls_timeout(void);
4545
int test_dtls_certreq_order(void);
46+
int test_dtls_memio_wolfio(void);
47+
int test_dtls_memio_wolfio_stateless(void);
4648

4749
#define TEST_DTLS_DECLS \
4850
TEST_DECL_GROUP("dtls", test_dtls12_basic_connection_id), \
@@ -65,5 +67,7 @@ int test_dtls_certreq_order(void);
6567
TEST_DECL_GROUP("dtls", test_dtls_replay), \
6668
TEST_DECL_GROUP("dtls", test_dtls_srtp), \
6769
TEST_DECL_GROUP("dtls", test_dtls_certreq_order), \
68-
TEST_DECL_GROUP("dtls", test_dtls_timeout)
70+
TEST_DECL_GROUP("dtls", test_dtls_timeout), \
71+
TEST_DECL_GROUP("dtls", test_dtls_memio_wolfio), \
72+
TEST_DECL_GROUP("dtls", test_dtls_memio_wolfio_stateless)
6973
#endif /* TESTS_API_DTLS_H */

wolfssl/internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <wolfssl/wolfcrypt/types.h>
2828
#include <wolfssl/ssl.h>
29+
#include <wolfssl/wolfio.h>
2930
#ifdef HAVE_CRL
3031
#include <wolfssl/crl.h>
3132
#endif
@@ -2730,6 +2731,7 @@ struct WOLFSSL_SOCKADDR {
27302731
void* sa; /* pointer to the sockaddr_in or sockaddr_in6 */
27312732
};
27322733

2734+
#ifdef WOLFSSL_DTLS
27332735
typedef struct WOLFSSL_DTLS_CTX {
27342736
#ifdef WOLFSSL_RW_THREADED
27352737
/* Protect peer access after the handshake */
@@ -2743,6 +2745,8 @@ typedef struct WOLFSSL_DTLS_CTX {
27432745
#endif
27442746
int rfd;
27452747
int wfd;
2748+
WolfSSLRecvFrom recvfrom;
2749+
WolfSSLSento sendto;
27462750
byte userSet:1;
27472751
byte connected:1; /* When set indicates rfd and wfd sockets are
27482752
* connected (connect() and bind() both called).
@@ -2752,6 +2756,7 @@ typedef struct WOLFSSL_DTLS_CTX {
27522756
byte processingPendingRecord:1;
27532757
#endif
27542758
} WOLFSSL_DTLS_CTX;
2759+
#endif
27552760

27562761

27572762
typedef struct WOLFSSL_DTLS_PEERSEQ {
@@ -5086,6 +5091,7 @@ struct Options {
50865091
#endif
50875092
word16 hrrSentKeyShare:1; /* HRR sent with key share */
50885093
#endif
5094+
word16 returnOnGoodCh:1;
50895095
word16 disableRead:1;
50905096
#ifdef WOLFSSL_DTLS
50915097
byte haveMcast; /* using multicast ? */

0 commit comments

Comments
 (0)