summaryrefslogtreecommitdiffstats
path: root/extra/wolfssl/wolfssl/src/dtls13.c
diff options
context:
space:
mode:
Diffstat (limited to 'extra/wolfssl/wolfssl/src/dtls13.c')
-rw-r--r--extra/wolfssl/wolfssl/src/dtls13.c170
1 files changed, 138 insertions, 32 deletions
diff --git a/extra/wolfssl/wolfssl/src/dtls13.c b/extra/wolfssl/wolfssl/src/dtls13.c
index b5fecafd..3591d67b 100644
--- a/extra/wolfssl/wolfssl/src/dtls13.c
+++ b/extra/wolfssl/wolfssl/src/dtls13.c
@@ -277,10 +277,7 @@ static int Dtls13GetRnMask(WOLFSSL* ssl, const byte* ciphertext, byte* mask,
/* assuming CIPHER[0..3] should be interpreted as little endian 32-bits
integer. The draft rfc isn't really clear on that. See sec 4.2.3 of
the draft. See also Section 2.3 of the Chacha RFC. */
- XMEMCPY(&counter, ciphertext, sizeof(counter));
-#ifdef BIG_ENDIAN
- counter = ByteReverseWord32(counter);
-#endif /* BIG_ENDIAN */
+ ato32le(ciphertext, &counter);
ret = wc_Chacha_SetIV(c->chacha, &ciphertext[4], counter);
if (ret != 0)
@@ -355,6 +352,7 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
WOLFSSL_ENTER("Dtls13ProcessBufferedMessages");
while (msg != NULL) {
+ int downgraded = 0;
idx = 0;
/* message not in order */
@@ -365,8 +363,32 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
if (!msg->ready)
break;
- ret = DoTls13HandShakeMsgType(ssl, msg->fullMsg, &idx, msg->type,
- msg->sz, msg->sz);
+#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
+ ret = MsgCheckEncryption(ssl, msg->type, msg->encrypted);
+ if (ret != 0) {
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ break;
+ }
+#endif
+
+ /* We may have DTLS <=1.2 msgs stored from before we knew which version
+ * we were going to use. Interpret correctly. */
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+ ret = DoTls13HandShakeMsgType(ssl, msg->fullMsg, &idx, msg->type,
+ msg->sz, msg->sz);
+ if (!IsAtLeastTLSv1_3(ssl->version))
+ downgraded = 1;
+ }
+ else {
+#if !defined(WOLFSSL_NO_TLS12)
+ ret = DoHandShakeMsgType(ssl, msg->fullMsg, &idx, msg->type,
+ msg->sz, msg->sz);
+#else
+ WOLFSSL_MSG("DTLS1.2 disabled with WOLFSSL_NO_TLS12");
+ WOLFSSL_ERROR_VERBOSE(NOT_COMPILED_IN);
+ ret = NOT_COMPILED_IN;
+#endif
+ }
/* processing certificate_request triggers a connect. The error came
* from there, the message can be considered processed successfully.
@@ -374,7 +396,13 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
* waiting to flush the output buffer. */
if ((ret == 0 || ret == WANT_WRITE) || (msg->type == certificate_request &&
ssl->options.handShakeDone && ret == WC_PENDING_E)) {
- Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type);
+ if (IsAtLeastTLSv1_3(ssl->version))
+ Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type);
+ else if (downgraded)
+ /* DoHandShakeMsgType normally handles the hs number but if
+ * DoTls13HandShakeMsgType processed 1.2 msgs then this wasn't
+ * incremented. */
+ ssl->keys.dtls_expected_peer_handshake_number++;
ssl->dtls_rx_msg_list = msg->next;
DtlsMsgDelete(msg, ssl->heap);
@@ -628,7 +656,7 @@ static void Dtls13RtxRecordUnlink(WOLFSSL* ssl, Dtls13RtxRecord** prevNext,
*prevNext = r->next;
}
-static void Dtls13RtxFlushBuffered(WOLFSSL* ssl, byte keepNewSessionTicket)
+void Dtls13RtxFlushBuffered(WOLFSSL* ssl, byte keepNewSessionTicket)
{
Dtls13RtxRecord *r, **prevNext;
@@ -809,10 +837,16 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs,
Dtls13MaybeSaveClientHello(ssl);
/* In the handshake, receiving part of the next flight, acknowledge the
- sent flight. The only exception is, on the server side, receiving the
- last client flight does not ACK any sent new_session_ticket
- messages. */
- Dtls13RtxFlushBuffered(ssl, 1);
+ * sent flight. */
+ /* On the server side, receiving the last client flight does not ACK any
+ * sent new_session_ticket messages. */
+ /* We don't want to clear the buffer until we have done version
+ * negotiation in the SH or have received a unified header in the
+ * DTLS record. */
+ if (ssl->options.serverState >= SERVER_HELLO_COMPLETE ||
+ ssl->options.seenUnifiedHdr)
+ /* Use 1.2 API to clear 1.2 buffers too */
+ DtlsMsgPoolReset(ssl);
}
if (ssl->keys.dtls_peer_handshake_number <
@@ -856,6 +890,8 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs,
void Dtls13FreeFsmResources(WOLFSSL* ssl)
{
Dtls13RtxFlushAcks(ssl);
+ /* Use 1.2 API to clear 1.2 buffers too */
+ DtlsMsgPoolReset(ssl);
Dtls13RtxFlushBuffered(ssl, 0);
}
@@ -921,8 +957,10 @@ static int Dtls13SendFragmentedInternal(WOLFSSL* ssl)
}
ret = CheckAvailableSize(ssl, recordLength + MAX_MSG_EXTRA);
- if (ret != 0)
+ if (ret != 0) {
+ Dtls13FreeFragmentsBuffer(ssl);
return ret;
+ }
output = GetOutputBuffer(ssl);
@@ -1551,6 +1589,19 @@ static int Dtls13RtxSendBuffered(WOLFSSL* ssl)
return 0;
}
+static int Dtls13AcceptFragmented(WOLFSSL *ssl, enum HandShakeType type)
+{
+ if (IsEncryptionOn(ssl, 0))
+ return 1;
+ if (ssl->options.side == WOLFSSL_CLIENT_END && type == server_hello)
+ return 1;
+#ifdef WOLFSSL_DTLS_CH_FRAG
+ if (ssl->options.side == WOLFSSL_SERVER_END && type == client_hello &&
+ ssl->options.dtls13ChFrag && ssl->options.dtlsStateful)
+ return 1;
+#endif
+ return 0;
+}
/**
* Dtls13HandshakeRecv() - process an handshake message. Deal with
fragmentation if needed
@@ -1579,6 +1630,13 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
if (ret != 0)
return PARSE_ERROR;
+ /* Need idx + fragLength as we don't advance the inputBuffer idx value */
+ ret = EarlySanityCheckMsgReceived(ssl, handshakeType, idx + fragLength);
+ if (ret != 0) {
+ WOLFSSL_ERROR(ret);
+ return ret;
+ }
+
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.acceptState < TLS13_ACCEPT_FIRST_REPLY_DONE) {
if (handshakeType != client_hello) {
@@ -1624,13 +1682,35 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
isFirst = fragOff == 0;
isComplete = isFirst && fragLength == messageLength;
- if (!isComplete && !IsEncryptionOn(ssl, 0)) {
+ if (!isComplete && !Dtls13AcceptFragmented(ssl, handshakeType)) {
+#ifdef WOLFSSL_DTLS_CH_FRAG
+ byte tls13 = 0;
+ /* check if the first CH fragment contains a valid cookie */
+ if (ssl->options.dtls13ChFrag && !ssl->options.dtlsStateful &&
+ isFirst && handshakeType == client_hello &&
+ DoClientHelloStateless(ssl, input + idx, fragLength, 1, &tls13)
+ == 0 && tls13) {
+ /* We can save this message and continue as stateful. */
+ if (ssl->chGoodCb != NULL) {
+ int cbret = ssl->chGoodCb(ssl, ssl->chGoodCtx);
+ if (cbret < 0) {
+ ssl->error = cbret;
+ WOLFSSL_MSG("ClientHello Good Cb don't continue error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ WOLFSSL_MSG("ClientHello fragment verified");
+ }
+ else
+#endif
+ {
#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("DTLS1.3 not accepting fragmented plaintext message");
+ WOLFSSL_MSG("DTLS1.3 not accepting fragmented plaintext message");
#endif /* WOLFSSL_DEBUG_TLS */
- /* ignore the message */
- *processedSize = idx + fragLength + ssl->keys.padSz;
- return 0;
+ /* ignore the message */
+ *processedSize = idx + fragLength + ssl->keys.padSz;
+ return 0;
+ }
}
usingAsyncCrypto = ssl->devId != INVALID_DEVID;
@@ -2347,7 +2427,11 @@ static int Dtls13WriteAckMessage(WOLFSSL* ssl,
c16toa(msgSz, ackMessage);
ackMessage += OPAQUE16_LEN;
+ WOLFSSL_MSG("write ack records");
+
while (recordNumberList != NULL) {
+ WOLFSSL_MSG_EX("epoch %d seq %d", recordNumberList->epoch,
+ recordNumberList->seq);
c64toa(&recordNumberList->epoch, ackMessage);
ackMessage += OPAQUE64_LEN;
c64toa(&recordNumberList->seq, ackMessage);
@@ -2474,7 +2558,12 @@ int Dtls13RtxTimeout(WOLFSSL* ssl)
{
int ret = 0;
- if (ssl->dtls13Rtx.seenRecords != NULL) {
+ /* We don't want to send acks until we have done version
+ * negotiation in the SH or have received a unified header in the
+ * DTLS record. */
+ if (ssl->dtls13Rtx.seenRecords != NULL &&
+ (ssl->options.serverState >= SERVER_HELLO_COMPLETE ||
+ ssl->options.seenUnifiedHdr)) {
ssl->dtls13Rtx.sendAcks = 0;
/* reset fast timeout as we are sending ACKs */
ssl->dtls13FastTimeout = 0;
@@ -2534,10 +2623,13 @@ int DoDtls13Ack(WOLFSSL* ssl, const byte* input, word32 inputSize,
if (length % (DTLS13_RN_SIZE) != 0)
return PARSE_ERROR;
+ WOLFSSL_MSG("read ack records");
+
ackMessage = input + OPAQUE16_LEN;
for (i = 0; i < length; i += DTLS13_RN_SIZE) {
ato64(ackMessage + i, &epoch);
ato64(ackMessage + i + OPAQUE64_LEN, &seq);
+ WOLFSSL_MSG_EX("epoch %d seq %d", epoch, seq);
Dtls13RtxRemoveRecord(ssl, epoch, seq);
}
@@ -2608,14 +2700,13 @@ int SendDtls13Ack(WOLFSSL* ssl)
if (ret != 0)
return ret;
- if (w64IsZero(ssl->dtls13EncryptEpoch->epochNumber)) {
-
- ret = Dtls13WriteAckMessage(ssl, ssl->dtls13Rtx.seenRecords, &length);
- if (ret != 0)
- return ret;
+ ret = Dtls13WriteAckMessage(ssl, ssl->dtls13Rtx.seenRecords, &length);
+ if (ret != 0)
+ return ret;
- output = GetOutputBuffer(ssl);
+ output = GetOutputBuffer(ssl);
+ if (w64IsZero(ssl->dtls13EncryptEpoch->epochNumber)) {
ret = Dtls13RlAddPlaintextHeader(ssl, output, ack, (word16)length);
if (ret != 0)
return ret;
@@ -2623,13 +2714,6 @@ int SendDtls13Ack(WOLFSSL* ssl)
ssl->buffers.outputBuffer.length += length + DTLS_RECORD_HEADER_SZ;
}
else {
-
- ret = Dtls13WriteAckMessage(ssl, ssl->dtls13Rtx.seenRecords, &length);
- if (ret != 0)
- return ret;
-
- output = GetOutputBuffer(ssl);
-
outputSize = ssl->buffers.outputBuffer.bufferSize -
ssl->buffers.outputBuffer.idx -
ssl->buffers.outputBuffer.length;
@@ -2770,4 +2854,26 @@ int Dtls13CheckAEADFailLimit(WOLFSSL* ssl)
}
#endif
+#ifdef WOLFSSL_DTLS_CH_FRAG
+int wolfSSL_dtls13_allow_ch_frag(WOLFSSL *ssl, int enabled)
+{
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ return WOLFSSL_FAILURE;
+ }
+ ssl->options.dtls13ChFrag = !!enabled;
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
+int wolfSSL_dtls13_no_hrr_on_resume(WOLFSSL *ssl, int enabled)
+{
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ return WOLFSSL_FAILURE;
+ }
+ ssl->options.dtls13NoHrrOnResume = !!enabled;
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
#endif /* WOLFSSL_DTLS13 */