Skip to content

Commit 76ddb65

Browse files
committed
wip
1 parent b02ddde commit 76ddb65

5 files changed

Lines changed: 151 additions & 4 deletions

File tree

src/dtls13.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,9 +2706,28 @@ int Dtls13DoScheduledWork(WOLFSSL* ssl)
27062706
ret = wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
27072707
#endif
27082708
if (sendAcks) {
2709-
ret = SendDtls13Ack(ssl);
2710-
if (ret != 0)
2711-
return ret;
2709+
#ifdef HAVE_WRITE_DUP
2710+
/* The read side cannot encrypt. Transfer the seenRecords list to the
2711+
* shared WriteDup struct so the write side sends the ACK instead. */
2712+
if (ssl->dupWrite != NULL && ssl->dupSide == READ_DUP_SIDE) {
2713+
if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
2714+
struct Dtls13RecordNumber** tail =
2715+
(struct Dtls13RecordNumber**)&ssl->dupWrite->sendAckList;
2716+
while (*tail != NULL)
2717+
tail = &(*tail)->next;
2718+
*tail = ssl->dtls13Rtx.seenRecords;
2719+
ssl->dtls13Rtx.seenRecords = NULL;
2720+
ssl->dupWrite->sendAcks = 1;
2721+
wc_UnLockMutex(&ssl->dupWrite->dupMutex);
2722+
}
2723+
}
2724+
else
2725+
#endif /* HAVE_WRITE_DUP */
2726+
{
2727+
ret = SendDtls13Ack(ssl);
2728+
if (ret != 0)
2729+
return ret;
2730+
}
27122731
}
27132732

27142733
if (ssl->dtls13Rtx.retransmit) {

src/internal.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25985,6 +25985,10 @@ static int CheckTLS13AEADSendLimit(WOLFSSL* ssl)
2598525985
}
2598625986
#ifdef WOLFSSL_DTLS13
2598725987
if (ssl->options.dtls) {
25988+
if (ssl->dtls13EncryptEpoch == NULL) {
25989+
WOLFSSL_MSG("DTLS 1.3 encrypt epoch not set");
25990+
return BAD_STATE_E;
25991+
}
2598825992
seq = ssl->dtls13EncryptEpoch->nextSeqNumber;
2598925993
}
2599025994
else

src/ssl.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,17 @@ void FreeWriteDup(WOLFSSL* ssl)
748748

749749
if (doFree) {
750750
WOLFSSL_MSG("Doing WriteDup full free, count to zero");
751+
#ifdef WOLFSSL_DTLS13
752+
/* Free any pending ACK list that was never consumed by the write side */
753+
{
754+
struct Dtls13RecordNumber* rn = ssl->dupWrite->sendAckList;
755+
while (rn != NULL) {
756+
struct Dtls13RecordNumber* next = rn->next;
757+
XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
758+
rn = next;
759+
}
760+
}
761+
#endif
751762
wc_FreeMutex(&ssl->dupWrite->dupMutex);
752763
XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
753764
}
@@ -807,6 +818,31 @@ static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
807818
/* dup side now owns encrypt/write ciphers */
808819
XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
809820

821+
#ifdef WOLFSSL_DTLS13
822+
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
823+
/* Copy epoch array (contains only value types — safe to memcpy). */
824+
XMEMCPY(dup->dtls13Epochs, ssl->dtls13Epochs, sizeof(ssl->dtls13Epochs));
825+
826+
/* Re-point dtls13EncryptEpoch into dup's own epoch array. */
827+
if (ssl->dtls13EncryptEpoch != NULL) {
828+
dup->dtls13EncryptEpoch =
829+
&dup->dtls13Epochs[ssl->dtls13EncryptEpoch - ssl->dtls13Epochs];
830+
}
831+
/* dtls13DecryptEpoch is not needed by the write-only side; leave NULL. */
832+
833+
/* Copy current write epoch number (checked in Dtls13SendMessage). */
834+
dup->dtls13Epoch = ssl->dtls13Epoch;
835+
836+
/* Transfer record-number encryption cipher ownership to dup.
837+
* FreeCiphers() frees the aes/chacha pointer, so sharing it would
838+
* cause a double-free; use the same ownership-transfer pattern as
839+
* for ssl->encrypt above. */
840+
XMEMCPY(&dup->dtlsRecordNumberEncrypt, &ssl->dtlsRecordNumberEncrypt,
841+
sizeof(RecordNumberCiphers));
842+
XMEMSET(&ssl->dtlsRecordNumberEncrypt, 0, sizeof(RecordNumberCiphers));
843+
}
844+
#endif /* WOLFSSL_DTLS13 */
845+
810846
dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
811847
dup->CBIOSend = ssl->CBIOSend;
812848
#ifdef OPENSSL_EXTRA
@@ -2455,6 +2491,54 @@ static int wolfSSL_write_internal(WOLFSSL* ssl, const void* data, size_t sz)
24552491
ssl->error = dupErr;
24562492
return WOLFSSL_FATAL_ERROR;
24572493
}
2494+
2495+
#ifdef WOLFSSL_DTLS13
2496+
/* DTLS 1.3: the read side cannot encrypt, so it delegates ACK sending
2497+
* to the write side. Check if an ACK was requested and send it. */
2498+
if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE &&
2499+
ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
2500+
byte ackNeeded = 0;
2501+
2502+
if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
2503+
ackNeeded = ssl->dupWrite->sendAcks;
2504+
if (ackNeeded) {
2505+
/* Insert each record number so the
2506+
* ACK message is properly ordered. */
2507+
struct Dtls13RecordNumber* rn;
2508+
for (rn = ssl->dupWrite->sendAckList; rn != NULL;
2509+
rn = rn->next) {
2510+
ret = Dtls13RtxAddAck(ssl, rn->epoch, rn->seq);
2511+
if (ret != 0)
2512+
break;
2513+
}
2514+
/* Clear only on success so no ACKs get dropped */
2515+
if (ret == 0) {
2516+
rn = ssl->dupWrite->sendAckList;
2517+
ssl->dupWrite->sendAckList = NULL;
2518+
ssl->dupWrite->sendAcks = 0;
2519+
while (rn != NULL) {
2520+
struct Dtls13RecordNumber* next = rn->next;
2521+
XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
2522+
rn = next;
2523+
}
2524+
}
2525+
}
2526+
wc_UnLockMutex(&ssl->dupWrite->dupMutex);
2527+
if (ret != 0) {
2528+
ssl->error = ret;
2529+
return WOLFSSL_FATAL_ERROR;
2530+
}
2531+
}
2532+
2533+
if (ackNeeded) {
2534+
ret = SendDtls13Ack(ssl);
2535+
if (ret != 0) {
2536+
ssl->error = ret;
2537+
return WOLFSSL_FATAL_ERROR;
2538+
}
2539+
}
2540+
}
2541+
#endif /* WOLFSSL_DTLS13 */
24582542
}
24592543
#endif
24602544

tests/api.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32012,7 +32012,7 @@ static int test_write_dup(void)
3201232012
{
3201332013
EXPECT_DECLS;
3201432014
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_WRITE_DUP)
32015-
size_t i, j;
32015+
size_t i, j, k;
3201632016
char hiWorld[] = "dup message";
3201732017
char readData[sizeof(hiWorld) + 5];
3201832018
struct {
@@ -32023,9 +32023,11 @@ static int test_write_dup(void)
3202332023
} methods[] = {
3202432024
#ifndef WOLFSSL_NO_TLS12
3202532025
{wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLS 1.2", WOLFSSL_TLSV1_2},
32026+
{wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLS 1.2", WOLFSSL_TLSV1_2},
3202632027
#endif
3202732028
#ifdef WOLFSSL_TLS13
3202832029
{wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLS 1.3", WOLFSSL_TLSV1_3},
32030+
{wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "TLS 1.3", WOLFSSL_TLSV1_3},
3202932031
#endif
3203032032
};
3203132033
struct {
@@ -32130,6 +32132,38 @@ static int test_write_dup(void)
3213032132
WC_NO_ERR_TRACE(WRITE_DUP_READ_E));
3213132133
ExpectIntEQ(wolfSSL_read(ssl_c, readData, sizeof(readData)),
3213232134
sizeof(hiWorld));
32135+
#ifdef WOLFSSL_DTLS13
32136+
/* After ssl_c (read side) processes the post-handshake
32137+
* NewSessionTicket it must have delegated the ACK to the
32138+
* write side via the shared WriteDup struct. */
32139+
if (methods[i].client_meth == wolfDTLSv1_3_client_method) {
32140+
ExpectNotNull(ssl_c->dupWrite);
32141+
ExpectIntEQ(ssl_c->dupWrite->sendAcks, 1);
32142+
ExpectNotNull(ssl_s->dtls13Rtx.rtxRecords);
32143+
32144+
/* Send some data to trigger the ACK. */
32145+
ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)),
32146+
sizeof(hiWorld));
32147+
ExpectIntEQ(wolfSSL_read(ssl_s, readData, sizeof(readData)),
32148+
sizeof(hiWorld));
32149+
32150+
/* Make sure the ACK has been sent and the retransmit list is
32151+
* empty. */
32152+
ExpectIntEQ(ssl_c->dupWrite->sendAcks, 0);
32153+
ExpectNull(ssl_s->dtls13Rtx.rtxRecords);
32154+
}
32155+
#endif
32156+
32157+
for (k = 0; k < 10; k++) {
32158+
ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)),
32159+
sizeof(hiWorld));
32160+
ExpectIntEQ(wolfSSL_read(ssl_s, readData, sizeof(readData)),
32161+
sizeof(hiWorld));
32162+
ExpectIntEQ(wolfSSL_write(ssl_s, hiWorld, sizeof(hiWorld)),
32163+
sizeof(hiWorld));
32164+
ExpectIntEQ(wolfSSL_read(ssl_c, readData, sizeof(readData)),
32165+
sizeof(hiWorld));
32166+
}
3213332167

3213432168
if (EXPECT_SUCCESS())
3213532169
printf("ok\n");

wolfssl/internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5759,6 +5759,12 @@ typedef struct BuildMsgArgs {
57595759
wolfSSL_Mutex dupMutex; /* reference count mutex */
57605760
int dupCount; /* reference count */
57615761
int dupErr; /* under dupMutex, pass to other side */
5762+
#ifdef WOLFSSL_DTLS13
5763+
/* DTLS 1.3: read side cannot encrypt, so it passes ACK work to the
5764+
* write side. Protected by dupMutex. */
5765+
byte sendAcks;
5766+
struct Dtls13RecordNumber* sendAckList; /* ownership transferred */
5767+
#endif
57625768
} WriteDup;
57635769

57645770
WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl);

0 commit comments

Comments
 (0)