Ver código fonte

Merge pull request #7010 from julek-wolfssl/dtls13-0.5-rtt

dtls13: Add support for 0.5-RTT data
Sean Parkinson 6 meses atrás
pai
commit
c6d6100136
3 arquivos alterados com 64 adições e 13 exclusões
  1. 40 10
      src/internal.c
  2. 8 1
      src/ssl.c
  3. 16 2
      tests/api.c

+ 40 - 10
src/internal.c

@@ -19609,7 +19609,8 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
         return BUFFER_ERROR;
     }
 #ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData > early_data_ext) {
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+            ssl->earlyData > early_data_ext) {
         if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) {
             if (sniff == NO_SNIFF) {
                 SendAlert(ssl, alert_fatal, unexpected_message);
@@ -19649,11 +19650,14 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
 #endif
 
     *inOutIdx = idx;
+#ifdef WOLFSSL_DTLS13
+    if (ssl->options.connectState == WAIT_FINISHED_ACK) {
+        /* DTLS 1.3 is waiting for an ACK but we can still return app data. */
+        return APP_DATA_READY;
+    }
+#endif
 #ifdef HAVE_SECURE_RENEGOTIATION
     if (IsSCR(ssl)) {
-        /* Reset the processReply state since
-         * we finished processing this message. */
-        ssl->options.processReply = doProcessInit;
         /* If we are in a secure renegotiation then APP DATA is treated
          * differently */
         return APP_DATA_READY;
@@ -20246,7 +20250,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
 #endif
 
     if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE
-    #ifdef HAVE_SECURE_RENEGOTIATION
+    #if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13)
         && ssl->error != APP_DATA_READY
     #endif
     #ifdef WOLFSSL_ASYNC_CRYPT
@@ -21213,7 +21217,13 @@ default:
                                                 &ssl->buffers.inputBuffer.idx,
                                                               NO_SNIFF)) != 0) {
                         WOLFSSL_ERROR(ret);
-                        return ret;
+                    #if defined(WOLFSSL_DTLS13) || \
+                        defined(HAVE_SECURE_RENEGOTIATION)
+                        /* Not really an error. We will return after cleaning
+                         * up the processReply state. */
+                        if (ret != APP_DATA_READY)
+                    #endif
+                            return ret;
                     }
                     break;
 
@@ -21270,9 +21280,18 @@ default:
             /* input exhausted */
             if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length
 #ifdef WOLFSSL_DTLS
-                /* If app data was processed then return now to avoid
-                 * dropping any app data. */
-                || (ssl->options.dtls && ssl->curRL.type == application_data)
+                || (ssl->options.dtls &&
+                    /* If app data was processed then return now to avoid
+                     * dropping any app data. */
+                    (ssl->curRL.type == application_data ||
+                    /* client: if we processed a finished message, return to
+                     *         allow higher layers to establish the crypto
+                     *         parameters of the connection. The remaining data
+                     *         may be app data that we would drop without the
+                     *         crypto setup. */
+                    (ssl->options.side == WOLFSSL_CLIENT_END &&
+                        ssl->options.serverState == SERVER_FINISHED_COMPLETE &&
+                        ssl->options.handShakeState != HANDSHAKE_DONE)))
 #endif
                 ) {
                 /* Shrink input buffer when we successfully finish record
@@ -21327,6 +21346,11 @@ default:
              * by higher layers. */
             if (ret != 0)
                 return ret;
+#endif
+#if defined(WOLFSSL_DTLS13) || defined(HAVE_SECURE_RENEGOTIATION)
+            /* Signal to user that we have application data ready to read */
+            if (ret == APP_DATA_READY)
+                return ret;
 #endif
             /* It is safe to shrink the input buffer here now. local vars will
              * be reset to the new starting value. */
@@ -23598,6 +23622,12 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
         groupMsgs = 1;
     #endif
     }
+    else if (IsAtLeastTLSv1_3(ssl->version) &&
+            ssl->options.side == WOLFSSL_SERVER_END &&
+            ssl->options.acceptState >= TLS13_ACCEPT_FINISHED_SENT) {
+        /* We can send data without waiting on peer finished msg */
+        WOLFSSL_MSG("server sending data before receiving client finished");
+    }
     else
 #endif
     if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) {
@@ -23835,7 +23865,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
 #ifdef WOLFSSL_ASYNC_CRYPT
             && ssl->error != WC_PENDING_E
 #endif
-#ifdef HAVE_SECURE_RENEGOTIATION
+#if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13)
             && ssl->error != APP_DATA_READY
 #endif
     ) {

+ 8 - 1
src/ssl.c

@@ -3233,7 +3233,14 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
     }
 #endif
 #ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) {
+    if (IsAtLeastTLSv1_3(ssl->version) &&
+            ssl->options.side == WOLFSSL_SERVER_END &&
+            ssl->options.acceptState >= TLS13_ACCEPT_FINISHED_SENT) {
+        /* We can send data without waiting on peer finished msg */
+        WOLFSSL_MSG("server sending data before receiving client finished");
+    }
+    else if (ssl->earlyData != no_early_data &&
+            (ret = wolfSSL_negotiate(ssl)) < 0) {
         ssl->error = ret;
         return WOLFSSL_FATAL_ERROR;
     }

+ 16 - 2
tests/api.c

@@ -68148,6 +68148,7 @@ static int test_dtls13_early_data(void)
     char msg[] = "This is early data";
     char msg2[] = "This is client data";
     char msg3[] = "This is server data";
+    char msg4[] = "This is server immediate data";
     char msgBuf[50];
 
     XMEMSET(&test_ctx, 0, sizeof(test_ctx));
@@ -68175,6 +68176,7 @@ static int test_dtls13_early_data(void)
     ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS);
 #endif
 
+    /* Test 0-RTT data */
     ExpectIntEQ(wolfSSL_write_early_data(ssl_c, msg, sizeof(msg),
             &written), sizeof(msg));
     ExpectIntEQ(written, sizeof(msg));
@@ -68184,6 +68186,15 @@ static int test_dtls13_early_data(void)
     ExpectIntEQ(read, sizeof(msg));
     ExpectStrEQ(msg, msgBuf);
 
+    /* Test 0.5-RTT data */
+    ExpectIntEQ(wolfSSL_write(ssl_s, msg4, sizeof(msg4)), sizeof(msg4));
+
+    ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
+    ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), APP_DATA_READY);
+
+    ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), sizeof(msg4));
+    ExpectStrEQ(msg4, msgBuf);
+
     /* Complete handshake */
     ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
     ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
@@ -68195,11 +68206,14 @@ static int test_dtls13_early_data(void)
      * parsing logic. */
     ExpectFalse(wolfSSL_is_init_finished(ssl_s));
     ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, sizeof(msgBuf),
-            &read), WOLFSSL_FAILURE);
-    ExpectTrue(wolfSSL_is_init_finished(ssl_s));
+            &read), -1);
+    ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
 
     ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
 
+    ExpectTrue(wolfSSL_is_init_finished(ssl_s));
+
+
     /* Test bi-directional write */
     ExpectIntEQ(wolfSSL_write(ssl_c, msg2, sizeof(msg2)), sizeof(msg2));
     ExpectIntEQ(wolfSSL_read(ssl_s, msgBuf, sizeof(msgBuf)), sizeof(msg2));