dtls13: support fragmentation, sending and receiving

This commit implements the core of the header parsing, building, and the sending
and receiving routines that handle fragmentation and defragmentation.

* In DTLSv1.3 the header used for protected messages is a variable-length header,
and it is described RFC9147 Section 4.

* Fragmentation happens after building the full message, if necessary. If the
underlying I/O can't send a fragment because of a WANT_WRITE error, the sending
of fragments will continue in the next invocation of
wolfSSL_connect/wolfSSL_accept/wolfSSL_write. In this case the message is saved
in a buffer inside the WolfSSL object.

* Defragmentation works like DTLSv1.2 defragmentation, and re-use
most of the same code.

* The Dtls13AddHeaders() function does not add the record layer header, but it
lefts space for it. It is eventually placed by BuildTls13Message() to allow
easier management of sequence numbers.
pull/4907/head
Marco Oliverio 2022-05-20 09:59:34 +02:00 committed by David Garske
parent 173077b142
commit d079662765
5 changed files with 2212 additions and 112 deletions

File diff suppressed because it is too large Load Diff

View File

@ -506,8 +506,16 @@ static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
{
#ifdef WOLFSSL_DTLS
/* For DTLS, epoch 0 is always not encrypted. */
if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0)
return 0;
if (ssl->options.dtls && !isSend) {
if (!IsAtLeastTLSv1_3(ssl->version) && ssl->keys.curEpoch == 0)
return 0;
#ifdef WOLFSSL_DTLS13
else if (IsAtLeastTLSv1_3(ssl->version)
&& w64IsZero(ssl->keys.curEpoch64))
return 0;
#endif /* WOLFSSL_DTLS13 */
}
#endif /* WOLFSSL_DTLS */
return ssl->keys.encryptionOn &&
@ -7425,8 +7433,8 @@ void FreeHandshakeResources(WOLFSSL* ssl)
WOLFSSL_ENTER("FreeHandshakeResources");
#ifdef WOLFSSL_DTLS
/* DTLS_POOL */
if (ssl->options.dtls) {
/* DTLS_POOL (DTLSv1.3 flushes the queue autonomously) */
if (ssl->options.dtls && !IsAtLeastTLSv1_3(ssl->version)) {
DtlsMsgPoolReset(ssl);
DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
ssl->dtls_rx_msg_list = NULL;
@ -8759,8 +8767,19 @@ int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
#endif
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
adj += DTLS_RECORD_EXTRA;
sz -= DTLS_RECORD_EXTRA;
if (IsAtLeastTLSv1_3(ssl->version)) {
#ifdef WOLFSSL_DTLS13
word16 dtls_record_extra;
dtls_record_extra = Dtls13GetRlHeaderLength(IsEncryptionOn(ssl, 1));
dtls_record_extra -= RECORD_HEADER_SZ;
adj += dtls_record_extra;
sz -= dtls_record_extra;
#endif /* WOLFSSL_DTLS13 */
} else {
adj += DTLS_RECORD_EXTRA;
sz -= DTLS_RECORD_EXTRA;
}
}
#endif
@ -8784,6 +8803,12 @@ int HashInput(WOLFSSL* ssl, const byte* input, int sz)
if (ssl->options.dtls) {
adj -= DTLS_HANDSHAKE_EXTRA;
sz += DTLS_HANDSHAKE_EXTRA;
#ifdef WOLFSSL_DTLS13
if (IsAtLeastTLSv1_3(ssl->version))
return Dtls13HashHandshake(ssl, adj, sz);
#endif /* WOLFSSL_DTLS13 */
}
#endif
@ -9466,7 +9491,12 @@ int CheckAvailableSize(WOLFSSL *ssl, int size)
#else
ssl->dtls_expected_rx
#endif
) {
#ifdef WOLFSSL_DTLS13
/* DTLS1.3 uses the output buffer to store the full message and deal
with fragmentation later in dtls13HandshakeSend() */
&& !IsAtLeastTLSv1_3(ssl->version)
#endif /* WOLFSSL_DTLS13 */
) {
WOLFSSL_MSG("CheckAvailableSize() called with size greater than MTU.");
return DTLS_SIZE_ERROR;
}
@ -9482,15 +9512,171 @@ int CheckAvailableSize(WOLFSSL *ssl, int size)
return 0;
}
#ifdef WOLFSSL_DTLS13
static int GetDtls13RecordHeader(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, RecordLayerHeader* rh, word16* size)
{
Dtls13UnifiedHdrInfo hdrInfo;
w64wrapper epochNumber;
byte epochBits;
int readSize;
int ret;
readSize = ssl->buffers.inputBuffer.length - *inOutIdx;
epochBits = *input & EE_MASK;
ret = Dtls13ReconstructEpochNumber(ssl, epochBits, &epochNumber);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG_EX("reconstructed epoch number: %ld",
epochNumber);
#endif /* WOLFSSL_DEBUG_TLS */
/* protected records always use unified_headers in DTLSv1.3 */
if (w64IsZero(epochNumber))
return SEQUENCE_ERROR;
if (ssl->dtls13DecryptEpoch == NULL)
return BAD_STATE_E;
#ifdef WOLFSSL_EARLY_DATA
if (w64Equal(epochNumber, w64From32(0x0, DTLS13_EPOCH_EARLYDATA)) &&
ssl->options.handShakeDone) {
WOLFSSL_MSG("discarding early data after handshake");
return SEQUENCE_ERROR;
}
#endif /* WOLFSSL_DTLS13 */
if (!w64Equal(ssl->dtls13DecryptEpoch->epochNumber, epochNumber)) {
ret = Dtls13SetEpochKeys(ssl, epochNumber, DECRYPT_SIDE_ONLY);
if (ret != 0)
return SEQUENCE_ERROR;
}
ret = Dtls13ParseUnifiedRecordLayer(ssl, input + *inOutIdx, readSize,
&hdrInfo);
if (ret != 0)
return ret;
*size = hdrInfo.recordLength;
c16toa(*size, rh->length);
/* type is implicit */
rh->type = application_data;
/* version is implicit */
rh->pvMajor = ssl->version.major;
rh->pvMinor = DTLSv1_2_MINOR;
ssl->keys.curEpoch64 = epochNumber;
ret = Dtls13ReconstructSeqNumber(ssl, &hdrInfo, &ssl->keys.curSeq);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG_EX("reconstructed seq number: %ld",
ssl->keys.curSeq);
#endif /* WOLFSSL_DEBUG_TLS */
*inOutIdx += hdrInfo.headerLength;
ssl->dtls13CurRlLength = hdrInfo.headerLength;
return 0;
}
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_DTLS
static int GetDtlsRecordHeader(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, RecordLayerHeader* rh, word16* size)
{
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ,
FUZZ_HEAD, ssl->fuzzerCtx);
#endif
#ifdef WOLFSSL_DTLS13
word32 read_size;
read_size = ssl->buffers.inputBuffer.length - *inOutIdx;
if (Dtls13IsUnifiedHeader(*(input + *inOutIdx))) {
/* version 1.3 already negotiated */
if (ssl->options.tls1_3)
return GetDtls13RecordHeader(ssl, input, inOutIdx, rh, size);
}
/* not a unified header, check that we have at least
DTLS_RECORD_HEADER_SZ */
if (read_size < DTLS_RECORD_HEADER_SZ)
return LENGTH_ERROR;
#endif /* WOLFSSL_DTLS13 */
/* type and version in same spot */
XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
*inOutIdx += ENUM_LEN + VERSION_SZ;
ato16(input + *inOutIdx, &ssl->keys.curEpoch);
#ifdef WOLFSSL_DTLS13
/* only non protected message can use the DTLSPlaintext record header */
if (ssl->options.tls1_3 && ssl->keys.curEpoch != 0)
return SEQUENCE_ERROR;
w64Zero(&ssl->keys.curEpoch64);
if (!w64IsZero(ssl->dtls13DecryptEpoch->epochNumber))
Dtls13SetEpochKeys(ssl, ssl->keys.curEpoch64, DECRYPT_SIDE_ONLY);
#endif /* WOLFSSL_DTLS13 */
*inOutIdx += OPAQUE16_LEN;
if (ssl->options.haveMcast) {
#ifdef WOLFSSL_MULTICAST
ssl->keys.curPeerId = input[*inOutIdx];
ssl->keys.curSeq_hi = input[*inOutIdx+1];
#endif
}
else
ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
*inOutIdx += OPAQUE16_LEN;
ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
*inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */
#ifdef WOLFSSL_DTLS13
/* DTLSv1.3 PlainText records use DTLSv1.2 sequence number encoding. Update
the DTLv1.3 word64 version as well */
ssl->keys.curSeq = w64From32(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo);
#endif /* WOLFSSL_DTLS13 */
ato16(input + *inOutIdx, size);
*inOutIdx += LENGTH_SZ;
return 0;
}
#endif /* WOLFSSL_DTLS */
/* do all verify and sanity checks on record header */
static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
RecordLayerHeader* rh, word16 *size)
{
byte tls12minor;
#ifdef WOLFSSL_DTLS
int ret;
#endif /* WOLFSSL_DTLS */
#ifdef OPENSSL_ALL
word32 start = *inOutIdx;
#endif
(void)tls12minor;
if (!ssl->options.dtls) {
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
@ -9503,34 +9689,16 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
else {
#ifdef WOLFSSL_DTLS
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ,
FUZZ_HEAD, ssl->fuzzerCtx);
#endif
/* type and version in same sport */
XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
*inOutIdx += ENUM_LEN + VERSION_SZ;
ato16(input + *inOutIdx, &ssl->keys.curEpoch);
*inOutIdx += OPAQUE16_LEN;
if (ssl->options.haveMcast) {
#ifdef WOLFSSL_MULTICAST
ssl->keys.curPeerId = input[*inOutIdx];
ssl->keys.curSeq_hi = input[*inOutIdx+1];
#endif
}
else
ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
*inOutIdx += OPAQUE16_LEN;
ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
*inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */
ato16(input + *inOutIdx, size);
*inOutIdx += LENGTH_SZ;
ret = GetDtlsRecordHeader(ssl, input, inOutIdx, rh, size);
if (ret != 0)
return ret;
#endif
}
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl)) {
/* DTLSv1.3 MUST check window after deprotecting to avoid timing channel
(RFC9147 Section 4.5.1) */
if (IsDtlsNotSctpMode(ssl) && !IsAtLeastTLSv1_3(ssl->version)) {
if (!DtlsCheckWindow(ssl) ||
(rh->type == application_data && ssl->keys.curEpoch == 0) ||
(rh->type == alert && ssl->options.handShakeDone &&
@ -14904,6 +15072,51 @@ static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl)
return 1;
}
#ifdef WOLFSSL_DTLS13
static WC_INLINE int Dtls13CheckWindow(WOLFSSL* ssl)
{
w64wrapper nextSeq, seq;
w64wrapper diff64;
word32 *window;
int wordOffset;
int wordIndex;
word32 diff;
if (ssl->dtls13DecryptEpoch == NULL) {
WOLFSSL_MSG("Can't find decrypting epoch");
return 0;
}
nextSeq = ssl->dtls13DecryptEpoch->nextPeerSeqNumber;
window = ssl->dtls13DecryptEpoch->window;
seq = ssl->keys.curSeq;
if (w64GTE(seq, nextSeq))
return 1;
/* seq < nextSeq, nextSeq - seq */
diff64 = w64Sub(nextSeq, seq);
/* diff >= DTLS_SEQ_BITS, outside of the window */
if (w64GT(diff64, w64From32(0, DTLS_SEQ_BITS)))
return 0;
/* we are assuming DTLS_SEQ_BITS <= 2**32 */
diff = w64GetLow32(diff64);
/* zero based index */
diff--;
wordIndex = ((int)diff) / DTLS_WORD_BITS;
wordOffset = ((int)diff) % DTLS_WORD_BITS;
if (window[wordIndex] & (1 << wordOffset))
return 0;
return 1;
}
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_MULTICAST
static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
@ -15050,6 +15263,60 @@ static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
return _DtlsUpdateWindow(ssl, next_hi, next_lo, window);
}
#ifdef WOLFSSL_DTLS13
static WC_INLINE int Dtls13UpdateWindow(WOLFSSL* ssl)
{
w64wrapper nextSeq, seq;
w64wrapper diff64;
word32 *window;
int wordOffset;
int wordIndex;
word32 diff;
if (ssl->dtls13DecryptEpoch == NULL) {
WOLFSSL_MSG("Can't find decrypting Epoch");
return BAD_STATE_E;
}
nextSeq = ssl->dtls13DecryptEpoch->nextPeerSeqNumber;
window = ssl->dtls13DecryptEpoch->window;
seq = ssl->keys.curSeq;
/* seq < nextSeq */
if (w64LT(seq, nextSeq)) {
diff64 = w64Sub(nextSeq, seq);
/* zero based index */
w64Decrement(&diff64);
/* FIXME: check that diff64 < DTLS_WORDS_BITS */
diff = w64GetLow32(diff64);
wordIndex = ((int)diff) / DTLS_WORD_BITS;
wordOffset = ((int)diff) % DTLS_WORD_BITS;
if (wordIndex >= WOLFSSL_DTLS_WINDOW_WORDS) {
WOLFSSL_MSG("Invalid sequence number to Dtls13UpdateWindow");
return BAD_STATE_E;
}
window[wordIndex] |= (1 << wordOffset);
return 1;
}
/* seq >= nextSeq, seq - nextSeq */
diff64 = w64Sub(seq, nextSeq);
/* as we are considering nextSeq inside the window, we should add + 1 */
w64Increment(&diff64);
DtlsUpdateWindowGTSeq(w64GetLow32(diff64), window);
w64Increment(&seq);
ssl->dtls13DecryptEpoch->nextPeerSeqNumber = seq;
return 1;
}
#endif /* WOLFSSL_DTLS13 */
int DtlsMsgDrain(WOLFSSL* ssl)
{
@ -17468,8 +17735,15 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
readSz = RECORD_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
if (ssl->options.dtls) {
readSz = DTLS_RECORD_HEADER_SZ;
#ifdef WOLFSSL_DTLS13
if (ssl->options.tls1_3) {
/* dtls1.3 unified header can be as little as 2 bytes */
readSz = DTLS_UNIFIED_HEADER_MIN_SZ;
}
#endif /* WOLFSSL_DTLS13 */
}
#endif
/* get header or return error */
@ -17565,6 +17839,11 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* get the record layer header */
case getRecordLayerHeader:
/* DTLSv1.3 record numbers in the header are encrypted, and AAD
* uses the unecrypted form. Because of this we need to modify the
* header, decrypting the numbers inside
* DtlsParseUnifiedRecordLayer(). This violates the const attribute
* of the buffer parameter of GetRecordHeader() used here. */
ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
&ssl->curRL, &ssl->curSize);
@ -17785,11 +18064,22 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
else
{
#ifdef WOLFSSL_TLS13
byte *aad = (byte*)&ssl->curRL;
word16 aad_size = RECORD_HEADER_SZ;
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls) {
/* aad now points to the record header */
aad = in->buffer +
in->idx - ssl->dtls13CurRlLength;
aad_size = ssl->dtls13CurRlLength;
}
#endif /* WOLFSSL_DTLS13 */
ret = DecryptTls13(ssl,
in->buffer + in->idx,
in->buffer + in->idx,
ssl->curSize,
(byte*)&ssl->curRL, RECORD_HEADER_SZ, 1);
aad, aad_size, 1);
#else
ret = DECRYPT_ERROR;
#endif /* WOLFSSL_TLS13 */
@ -17816,6 +18106,15 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
else {
WOLFSSL_MSG("Decrypt failed");
WOLFSSL_ERROR(ret);
#ifdef WOLFSSL_DTLS13
if (ssl->options.tls1_3 && ssl->options.dtls) {
WOLFSSL_MSG("DTLS: Ignoring decrypted failed record");
ssl->options.processReply = doProcessInit;
ssl->buffers.inputBuffer.idx =
ssl->buffers.inputBuffer.length;
return 0;
}
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_EARLY_DATA
if (ssl->options.tls1_3) {
if (ssl->options.side == WOLFSSL_SERVER_END &&
@ -17936,6 +18235,35 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* the record layer is here */
case runProcessingOneRecord:
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
if(!Dtls13CheckWindow(ssl)) {
/* drop packet */
WOLFSSL_MSG(
"Dropping DTLS record outside receiving window");
ssl->options.processReply = doProcessInit;
ssl->buffers.inputBuffer.idx += ssl->curSize;
if (ssl->buffers.inputBuffer.idx >
ssl->buffers.inputBuffer.length)
return BUFFER_E;
continue;
}
ret = Dtls13UpdateWindow(ssl);
if (ret != 1) {
WOLFSSL_ERROR(ret);
return ret;
}
ret = Dtls13RecordRecvd(ssl);
if (ret != 0) {
WOLFSSL_ERROR(ret);
return ret;
}
}
#endif /* WOLFSSL_DTLS13 */
ssl->options.processReply = runProcessingOneMessage;
FALL_THROUGH;
@ -17986,7 +18314,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
}
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl)) {
if (IsDtlsNotSctpMode(ssl) && !IsAtLeastTLSv1_3(ssl->version)) {
DtlsUpdateWindow(ssl);
}
#endif /* WOLFSSL_DTLS */
@ -17999,11 +18327,36 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* debugging in DoHandShakeMsg */
if (ssl->options.dtls) {
#ifdef WOLFSSL_DTLS
ret = DoDtlsHandShakeMsg(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
if (!IsAtLeastTLSv1_3(ssl->version)) {
ret = DoDtlsHandShakeMsg(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
}
#endif
#ifdef WOLFSSL_DTLS13
if (IsAtLeastTLSv1_3(ssl->version)) {
ret = Dtls13HandshakeRecv(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
#ifdef WOLFSSL_EARLY_DATA
if (ret == 0 &&
ssl->options.side == WOLFSSL_SERVER_END &&
ssl->earlyData > early_data_ext &&
ssl->options.handShakeState == HANDSHAKE_DONE) {
/* return so wolfSSL_read_early_data can return
exit */
ssl->earlyData = no_early_data;
ssl->options.processReply = doProcessInit;
return ZERO_RETURN;
}
#endif /* WOLFSSL_EARLY_DATA */
}
#endif /* WOLFSSL_DTLS13 */
}
else if (!IsAtLeastTLSv1_3(ssl->version)
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12)
@ -20497,6 +20850,42 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
#endif
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls && ssl->options.tls1_3) {
byte isEarlyData = 0;
if (ssl->dtls13EncryptEpoch == NULL)
return ssl->error = BAD_STATE_E;
#ifdef WOLFSSL_EARLY_DATA
isEarlyData = ssl->earlyData != no_early_data;
#endif
if (isEarlyData) {
#ifdef WOLFSSL_EARLY_DATA
ret = Dtls13SetEpochKeys(ssl,
w64From32(0x0, DTLS13_EPOCH_EARLYDATA), ENCRYPT_SIDE_ONLY);
if (ret != 0) {
WOLFSSL_MSG(
"trying to send early data without epoch 1");
ssl->error = BUILD_MSG_ERROR;
return WOLFSSL_FATAL_ERROR;
}
#endif /* WOLFSSL_EARLY_DATA */
}
else if (!w64Equal(
ssl->dtls13EncryptEpoch->epochNumber,
ssl->dtls13Epoch)) {
ret = Dtls13SetEpochKeys(
ssl, ssl->dtls13Epoch, ENCRYPT_SIDE_ONLY);
if (ret != 0) {
ssl->error = BUILD_MSG_ERROR;
return WOLFSSL_FATAL_ERROR;
}
}
}
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
buffSz = wolfSSL_GetMaxFragSize(ssl, sz - sent);
@ -20840,12 +21229,33 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type)
* TLS 1.3 encrypts handshake packets after the ServerHello
*/
if (IsEncryptionOn(ssl, 1)) {
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls
&& IsAtLeastTLSv1_3(ssl->version)
&& !w64Equal(ssl->dtls13EncryptEpoch->epochNumber, ssl->dtls13Epoch)) {
ret = Dtls13SetEpochKeys(ssl, ssl->dtls13Epoch, ENCRYPT_SIDE_ONLY);
if (ret != 0)
return ret;
}
#endif /* WOLFSSL_DTLS13 */
sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert,
0, 0, 0, CUR_ORDER);
}
else {
AddRecordHeader(output, ALERT_SIZE, alert, ssl, CUR_ORDER);
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
ret = Dtls13RlAddPlaintextHeader(ssl, output, alert, ALERT_SIZE);
if (ret != 0)
return ret;
}
else
#endif /* WOLFSSL_DTLS13 */
{
AddRecordHeader(output, ALERT_SIZE, alert, ssl, CUR_ORDER);
}
output += RECORD_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)

View File

@ -2081,6 +2081,15 @@ int SetCipherSpecs(WOLFSSL* ssl)
#endif
}
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls &&
ssl->version.major == DTLS_MAJOR &&
ssl->version.minor <= DTLSv1_3_MINOR) {
ssl->options.tls = 1;
ssl->options.tls1_3 = 1;
}
#endif /* WOLFSSL_DTLS13 */
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (IsAtLeastTLSv1_3(ssl->version) || ssl->specs.cipher_type != block)
ssl->options.encThenMac = 0;
@ -2966,7 +2975,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
#ifdef HAVE_SECURE_RENEGOTIATION
#ifdef WOLFSSL_DTLS
if (ret == 0 && ssl->options.dtls) {
if (ret == 0 && ssl->options.dtls && !ssl->options.tls1_3) {
if (wc_encrypt)
wc_encrypt->src = keys == &ssl->keys ? KEYS : SCR;
if (wc_decrypt)

File diff suppressed because it is too large Load Diff

View File

@ -1294,6 +1294,8 @@ enum Misc {
DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */
DTLS_UNIFIED_HEADER_MIN_SZ = 2,
DTLS_RECORD_HEADER_MAX_SZ = 13,
DTLS_HANDSHAKE_EXTRA = 8, /* diff from normal */
DTLS_RECORD_EXTRA = 8, /* diff from normal */
DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */
@ -2256,6 +2258,12 @@ typedef struct Keys {
word16 curEpoch; /* Received epoch in current record */
word16 curSeq_hi; /* Received sequence in current record */
word32 curSeq_lo;
#ifdef WOLFSSL_DTLS13
w64wrapper curEpoch64; /* Received epoch in current record */
w64wrapper curSeq;
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_MULTICAST
byte curPeerId; /* Received peer group ID in current record */
#endif
@ -4319,6 +4327,15 @@ typedef enum EarlyDataState {
#ifdef WOLFSSL_DTLS13
typedef struct Dtls13UnifiedHdrInfo {
word16 recordLength;
word16 headerLength;
byte seqLo;
byte seqHi;
byte seqHiPresent:1;
byte epochBits;
} Dtls13UnifiedHdrInfo;
enum {
DTLS13_EPOCH_EARLYDATA = 1,
DTLS13_EPOCH_HANDSHAKE = 2,
@ -4557,8 +4574,15 @@ struct WOLFSSL {
w64wrapper dtls13Epoch;
w64wrapper dtls13PeerEpoch;
#endif /* WOLFSSL_DTLS13 */
word16 dtls13CurRlLength;
/* used to store the message if it needs to be fragmented */
buffer dtls13FragmentsBuffer;
byte dtls13SendingFragments:1;
word32 dtls13MessageLength;
word32 dtls13FragOffset;
byte dtls13FragHandshakeType;
#endif /* WOLFSSL_DTLS13 */
#endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_CALLBACKS
TimeoutInfo timeoutInfo; /* info saved during handshake */
@ -4842,7 +4866,10 @@ enum ContentType {
change_cipher_spec = 20,
alert = 21,
handshake = 22,
application_data = 23
application_data = 23,
#ifdef WOLFSSL_DTLS13
ack = 26,
#endif /* WOLFSSL_DTLS13 */
};
@ -5309,11 +5336,44 @@ WOLFSSL_LOCAL int Dtls13NewEpoch(WOLFSSL* ssl, w64wrapper epochNumber,
int side);
WOLFSSL_LOCAL int Dtls13SetEpochKeys(WOLFSSL* ssl, w64wrapper epochNumber,
enum encrypt_side side);
WOLFSSL_LOCAL int Dtls13GetSeq(WOLFSSL* ssl, int order, word32* seq,
byte increment);
WOLFSSL_LOCAL int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision);
WOLFSSL_LOCAL int Dtls13SetRecordNumberKeys(WOLFSSL* ssl,
enum encrypt_side side);
WOLFSSL_LOCAL int Dtls13AddHeaders(byte* output, word32 length,
enum HandShakeType hs_type, WOLFSSL* ssl);
WOLFSSL_LOCAL word16 Dtls13GetHeadersLength(enum HandShakeType type);
WOLFSSL_LOCAL word16 Dtls13GetRlHeaderLength(byte is_encrypted);
WOLFSSL_LOCAL int Dtls13RlAddCiphertextHeader(WOLFSSL* ssl, byte* out,
word16 length);
WOLFSSL_LOCAL int Dtls13RlAddPlaintextHeader(WOLFSSL* ssl, byte* out,
enum ContentType content_type, word16 length);
WOLFSSL_LOCAL int Dtls13EncryptRecordNumber(WOLFSSL* ssl, byte* hdr,
word16 recordLength);
WOLFSSL_LOCAL int Dtls13IsUnifiedHeader(byte header_flags);
WOLFSSL_LOCAL int Dtls13ParseUnifiedRecordLayer(WOLFSSL* ssl, const byte* input,
word16 input_size, Dtls13UnifiedHdrInfo* hdrInfo);
WOLFSSL_LOCAL int Dtls13HandshakeSend(WOLFSSL* ssl, byte* output,
word16 output_size, word16 length, enum HandShakeType handshake_type,
int hash_output);
WOLFSSL_LOCAL int Dtls13RecordRecvd(WOLFSSL* ssl);
WOLFSSL_LOCAL int Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input,
word32* inOutIdx, word32 totalSz);
WOLFSSL_LOCAL int Dtls13HandshakeAddHeader(WOLFSSL* ssl, byte* output,
enum HandShakeType msg_type, word32 length);
#define EE_MASK (0x3)
WOLFSSL_LOCAL int Dtls13FragmentsContinue(WOLFSSL* ssl);
WOLFSSL_LOCAL int Dtls13ReconstructEpochNumber(WOLFSSL* ssl, byte epochBits,
w64wrapper* epoch);
WOLFSSL_LOCAL int Dtls13ReconstructSeqNumber(WOLFSSL* ssl,
Dtls13UnifiedHdrInfo* hdrInfo, w64wrapper* out);
WOLFSSL_LOCAL int Dtls13HashHandshake(WOLFSSL* ssl, const byte* output,
word16 length);
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_STATIC_EPHEMERAL
WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr);
#endif