]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Support dtls 1.3 downgrade mechanism
authorFrederik Wedel-Heinen <frederik.wedel-heinen@dencrypt.dk>
Wed, 3 Jan 2024 13:31:15 +0000 (14:31 +0100)
committerTomas Mraz <tomas@openssl.org>
Thu, 9 Jan 2025 17:07:48 +0000 (18:07 +0100)
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23320)

15 files changed:
ssl/s3_lib.c
ssl/ssl_local.h
ssl/statem/statem_lib.c
ssl/statem/statem_srvr.c
test/recipes/70-test_tls13downgrade.t
util/perl/TLSProxy/Certificate.pm
util/perl/TLSProxy/CertificateRequest.pm
util/perl/TLSProxy/CertificateVerify.pm
util/perl/TLSProxy/ClientHello.pm
util/perl/TLSProxy/EncryptedExtensions.pm
util/perl/TLSProxy/HelloVerifyRequest.pm
util/perl/TLSProxy/Message.pm
util/perl/TLSProxy/NewSessionTicket.pm
util/perl/TLSProxy/ServerHello.pm
util/perl/TLSProxy/ServerKeyExchange.pm

index 8f85ef9d3369467d6a0b06f0fcbeafda1b22d228..beece1153ab88a12a4d1b540b179c0911be81efc 100644 (file)
@@ -26,7 +26,7 @@
 #define SSL3_NUM_CIPHERS        OSSL_NELEM(ssl3_ciphers)
 #define SSL3_NUM_SCSVS          OSSL_NELEM(ssl3_scsvs)
 
-/* TLSv1.3 downgrade protection sentinel values */
+/* TLSv1.3 downgrade protection sentinel values (rfc8446 4.1.3.) */
 const unsigned char tls11downgrade[] = {
     0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00
 };
index dbe2edf4bd1779cd82c0e4520f78441c34e07427..4f606c3ef0eb0af68d67e74a1e97f2748e607aa0 100644 (file)
@@ -1920,6 +1920,12 @@ typedef struct sigalg_lookup_st {
     int enabled;
 } SIGALG_LOOKUP;
 
+typedef enum downgrade_en {
+    DOWNGRADE_NONE,
+    DOWNGRADE_TO_1_2,
+    DOWNGRADE_TO_1_1
+} DOWNGRADE;
+
 /* DTLS structures */
 
 # ifndef OPENSSL_NO_SCTP
@@ -1997,7 +2003,8 @@ typedef struct dtls1_state_st {
     /* Buffered (sent) handshake records */
     pqueue *sent_messages;
     /* Flag to indicate current HelloVerifyRequest status */
-    enum {SSL_HVR_NONE = 0, SSL_HVR_RECEIVED} hello_verify_request;
+    enum {SSL_HVR_NONE = 0, SSL_HVR_RECEIVED, SSL_HVR_SENT} hello_verify_request;
+    DOWNGRADE downgrade_after_hvr; /* Only used by a stateful server */
     size_t link_mtu;      /* max on-the-wire DTLS packet size */
     size_t mtu;           /* max DTLS packet size */
     dtls_msg_info w_msg;
@@ -2226,12 +2233,6 @@ typedef struct ssl3_enc_method {
  */
 # define SSL_ENC_FLAG_TLS1_2_CIPHERS     0x10
 
-typedef enum downgrade_en {
-    DOWNGRADE_NONE,
-    DOWNGRADE_TO_1_2,
-    DOWNGRADE_TO_1_1
-} DOWNGRADE;
-
 /*
  * Dummy status type for the status_type extension. Indicates no status type
  * set
index 50f7444bc436d96d30f0bb2cf2ba14b55bb950e5..3eb37b09bf9594b4d7204b35c79cdffd76fa4c6e 100644 (file)
@@ -2106,23 +2106,27 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
 
 static void check_for_downgrade(SSL_CONNECTION *s, int vers, DOWNGRADE *dgrd)
 {
-    if (vers == TLS1_2_VERSION
-            && ssl_version_supported(s, TLS1_3_VERSION, NULL)) {
+    int version12 = SSL_CONNECTION_IS_DTLS(s) ? DTLS1_2_VERSION : TLS1_2_VERSION;
+    int version13 = SSL_CONNECTION_IS_DTLS(s) ? DTLS1_3_VERSION : TLS1_3_VERSION;
+
+    if (vers == version12 && ssl_version_supported(s, version13, NULL)) {
         *dgrd = DOWNGRADE_TO_1_2;
-    } else if (!SSL_CONNECTION_IS_DTLS(s)
-            && vers < TLS1_2_VERSION
+    } else if (ssl_version_cmp(s, vers, version12) < 0
                /*
-                * We need to ensure that a server that disables TLSv1.2
-                * (creating a hole between TLSv1.3 and TLSv1.1) can still
-                * complete handshakes with clients that support TLSv1.2 and
-                * below. Therefore we do not enable the sentinel if TLSv1.3 is
-                * enabled and TLSv1.2 is not.
+                * We need to ensure that a server that disables (D)TLSv1.2
+                * (creating a hole between (D)TLSv1.3 and (D)TLSv1.1) can still
+                * complete handshakes with clients that support (D)TLSv1.2 and
+                * below. Therefore we do not enable the sentinel if (D)TLSv1.3 is
+                * enabled and (D)TLSv1.2 is not.
                 */
-            && ssl_version_supported(s, TLS1_2_VERSION, NULL)) {
+                && ssl_version_supported(s, version12, NULL)) {
         *dgrd = DOWNGRADE_TO_1_1;
     } else {
         *dgrd = DOWNGRADE_NONE;
     }
+
+    if (SSL_CONNECTION_IS_DTLS(s))
+        s->d1->downgrade_after_hvr = *dgrd;
 }
 
 /*
@@ -2168,7 +2172,20 @@ int ssl_choose_server_version(SSL_CONNECTION *s, CLIENTHELLO_MSG *hello,
         if (!SSL_CONNECTION_IS_VERSION13(s)) {
             if (ssl_version_cmp(s, client_version, s->version) < 0)
                 return SSL_R_WRONG_SSL_VERSION;
-            *dgrd = DOWNGRADE_NONE;
+
+            /*
+             * The downgrade sentinel is selected when parsing the first
+             * ClientHello. If this server has sent a HelloVerifyRequest, the
+             * sentinel is recovered while parsing the second ClientHello in
+             * order to apply it to the ServerHello random value.
+             */
+            if (SSL_CONNECTION_IS_DTLS(s)
+                    && s->d1->hello_verify_request != SSL_HVR_NONE) {
+                *dgrd = s->d1->downgrade_after_hvr;
+            } else {
+                *dgrd = DOWNGRADE_NONE;
+            }
+
             /*
              * If this SSL handle is not from a version flexible method we don't
              * (and never did) check min/max FIPS or Suite B constraints.  Hope
@@ -2308,6 +2325,8 @@ int ssl_choose_client_version(SSL_CONNECTION *s, int version,
     const version_info *vent;
     const version_info *table;
     int ret, ver_min, ver_max, real_max, origv;
+    const int version12 = SSL_CONNECTION_IS_DTLS(s) ? DTLS1_2_VERSION
+                                                    : TLS1_2_VERSION;
     SSL *ssl = SSL_CONNECTION_GET_SSL(s);
     const int version1_3 = SSL_CONNECTION_IS_DTLS(s) ? DTLS1_3_VERSION
                                                      : TLS1_3_VERSION;
@@ -2374,28 +2393,26 @@ int ssl_choose_client_version(SSL_CONNECTION *s, int version,
         real_max = ver_max;
 
     /* Check for downgrades */
-    if (s->version == TLS1_2_VERSION && real_max > s->version) {
-        if (memcmp(tls12downgrade,
-                   s->s3.server_random + SSL3_RANDOM_SIZE
-                                        - sizeof(tls12downgrade),
-                   sizeof(tls12downgrade)) == 0) {
-            s->version = origv;
-            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
-                     SSL_R_INAPPROPRIATE_FALLBACK);
-            return 0;
-        }
-    } else if (!SSL_CONNECTION_IS_DTLS(s)
-               && s->version < TLS1_2_VERSION
-               && real_max > s->version) {
-        if (memcmp(tls11downgrade,
-                   s->s3.server_random + SSL3_RANDOM_SIZE
-                                        - sizeof(tls11downgrade),
-                   sizeof(tls11downgrade)) == 0) {
-            s->version = origv;
-            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
-                     SSL_R_INAPPROPRIATE_FALLBACK);
-            return 0;
-        }
+    if (s->version == version12
+            && ssl_version_cmp(s, real_max, s->version) > 0
+            && memcmp(tls12downgrade,
+                      s->s3.server_random + SSL3_RANDOM_SIZE
+                                          - sizeof(tls12downgrade),
+                      sizeof(tls12downgrade)) == 0) {
+        s->version = origv;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_R_INAPPROPRIATE_FALLBACK);
+        return 0;
+    } else if (ssl_version_cmp(s, s->version, version12) < 0
+               && ssl_version_cmp(s, real_max, s->version) > 0
+               && memcmp(tls11downgrade,
+                         s->s3.server_random + SSL3_RANDOM_SIZE
+                                             - sizeof(tls11downgrade),
+                         sizeof(tls11downgrade)) == 0) {
+        s->version = origv;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_R_INAPPROPRIATE_FALLBACK);
+        return 0;
     }
 
     for (vent = table; vent->version != 0; ++vent) {
index 0e3feea21542cbb7da13e9269d3d50cbdccbd1a9..8a3597c488356bd637299d29c47f954b2bea7341 100644 (file)
@@ -1402,6 +1402,12 @@ CON_FUNC_RETURN dtls_construct_hello_verify_request(SSL_CONNECTION *s,
         return CON_FUNC_ERROR;
     }
 
+    /*
+     * Server must recover the downgrade sentinel in case it sends a
+     * HelloVerifyRequest.
+     */
+    s->d1->hello_verify_request = SSL_HVR_SENT;
+
     return CON_FUNC_SUCCESS;
 }
 
@@ -1613,8 +1619,6 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL_CONNECTION *s, PACKET *pkt)
         }
 
         if (SSL_CONNECTION_IS_DTLS(s)) {
-            int minversion, maxversion;
-
             if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
                 SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
                 goto err;
@@ -1625,23 +1629,6 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL_CONNECTION *s, PACKET *pkt)
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 goto err;
             }
-
-            /*
-             * If the connection supports DTLSv1.3:
-             *      We continue to process ClientHello's without cookies
-             *
-             * Otherwise, if we require cookies and this ClientHello doesn't
-             * contain one:
-             *      Return since we do not want to allocate any memory yet
-             */
-            if ((SSL_get_options(SSL_CONNECTION_GET_SSL(s)) & SSL_OP_COOKIE_EXCHANGE)
-                    && clienthello->dtls_cookie_len == 0
-                    && ossl_assert(ssl_get_min_max_version(s, &minversion,
-                                                           &maxversion, NULL) == 0)
-                    && ssl_version_cmp(s, maxversion, DTLS1_3_VERSION) < 0) {
-                OPENSSL_free(clienthello);
-                return MSG_PROCESS_FINISHED_READING;
-            }
         }
 
         if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
@@ -1682,6 +1669,30 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL_CONNECTION *s, PACKET *pkt)
         goto err;
     }
 
+    if (SSL_CONNECTION_IS_DTLS(s)) {
+        int minversion, maxversion;
+
+        /*
+         * If the connection supports DTLSv1.3 or if the ClientHello was sent
+         * with the SupportedVersions extension:
+         *      We continue to process ClientHello's without cookies
+         *
+         * Otherwise, if we require cookies and this ClientHello doesn't
+         * contain one:
+         *      Return since we do not want to allocate any memory yet
+         */
+        if ((SSL_get_options(SSL_CONNECTION_GET_SSL(s)) & SSL_OP_COOKIE_EXCHANGE)
+                && clienthello->dtls_cookie_len == 0
+                && ossl_assert(ssl_get_min_max_version(s, &minversion,
+                                                       &maxversion, NULL) == 0)
+                && ssl_version_cmp(s, maxversion, DTLS1_3_VERSION) < 0
+                && !clienthello->pre_proc_exts[TLSEXT_IDX_supported_versions].present) {
+            OPENSSL_free(clienthello->pre_proc_exts);
+            OPENSSL_free(clienthello);
+            return MSG_PROCESS_FINISHED_READING;
+        }
+    }
+
     s->clienthello = clienthello;
 
     return MSG_PROCESS_CONTINUE_PROCESSING;
index 999a79e62a84c6705064b660bcb0fbfb01b180fa..67e7b30a57c3eb518d0f98cd605d1b29adadd58e 100644 (file)
@@ -23,17 +23,8 @@ plan skip_all => "$test_name needs the dynamic engine feature enabled"
 plan skip_all => "$test_name needs the sock feature enabled"
     if disabled("sock");
 
-plan skip_all => "$test_name needs TLS1.3 and TLS1.2 enabled"
-    if disabled("tls1_3")
-       || (disabled("ec") && disabled("dh"))
-       || disabled("tls1_2");
-
-my $proxy = TLSProxy::Proxy->new(
-    undef,
-    cmdstr(app(["openssl"]), display => 1),
-    srctop_file("apps", "server.pem"),
-    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
-);
+plan skip_all => "$test_name needs EC or DH enabled"
+    if disabled("ec") && disabled("dh");
 
 use constant {
     DOWNGRADE_TO_TLS_1_2 => 0,
@@ -41,82 +32,143 @@ use constant {
     FALLBACK_FROM_TLS_1_3 => 2,
 };
 
-#Test 1: Downgrade from TLSv1.3 to TLSv1.2
-$proxy->filter(\&downgrade_filter);
-my $testtype = DOWNGRADE_TO_TLS_1_2;
-$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 6;
-ok(TLSProxy::Message->fail(), "Downgrade TLSv1.3 to TLSv1.2");
-
-#Test 2: Downgrade from TLSv1.3 to TLSv1.1
-$proxy->clear();
-$testtype = DOWNGRADE_TO_TLS_1_1;
-$proxy->start();
-ok(TLSProxy::Message->fail(), "Downgrade TLSv1.3 to TLSv1.1");
-
-#Test 3: Downgrade from TLSv1.2 to TLSv1.1
-$proxy->clear();
-$proxy->clientflags("-no_tls1_3");
-$proxy->serverflags("-no_tls1_3");
-$proxy->start();
-ok(TLSProxy::Message->fail(), "Downgrade TLSv1.2 to TLSv1.1");
-
-#Test 4: Client falls back from TLSv1.3 (server does not support the fallback
-#        SCSV)
-$proxy->clear();
-$testtype = FALLBACK_FROM_TLS_1_3;
-$proxy->clientflags("-fallback_scsv -no_tls1_3");
-$proxy->start();
-my $alert = TLSProxy::Message->alert();
-ok(TLSProxy::Message->fail()
-   && !$alert->server()
-   && $alert->description() == TLSProxy::Message::AL_DESC_ILLEGAL_PARAMETER,
-   "Fallback from TLSv1.3");
+my $testcount = 6;
+plan tests => 2 * $testcount;
+
+my $testtype;
+
+SKIP: {
+    skip "TLS 1.2 or 1.3 is disabled", $testcount if disabled("tls1_3")
+                                                     || disabled("tls1_2");
+    # Run tests with TLS
+    run_tests(0);
+}
 
 SKIP: {
-    skip "TLSv1.1 disabled", 2 if disabled("tls1_1");
-    #Test 5: A client side protocol "hole" should not be detected as a downgrade
+    skip "DTLS 1.2 or 1.3 is disabled", $testcount if disabled("dtls1_3")
+                                                      || disabled("dtls1_2");
+    skip "DTLSProxy does not work on Windows", $testcount if $^O =~ /^(MSWin32)$/;
+    run_tests(1);
+}
+
+sub run_tests
+{
+    my $run_test_as_dtls = shift;
+    my $proto1_1 = $run_test_as_dtls == 1 ? "DTLSv1" : "TLSv1.1";
+    my $proto1_2 = $run_test_as_dtls == 1 ? "DTLSv1.2" : "TLSv1.2";
+    my $proto1_3 = $run_test_as_dtls == 1 ? "DTLSv1.3" : "TLSv1.3";
+
+    my $proxy;
+    if ($run_test_as_dtls == 1) {
+        $proxy = TLSProxy::Proxy->new_dtls(
+            undef,
+            cmdstr(app([ "openssl" ]), display => 1),
+            srctop_file("apps", "server.pem"),
+            (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
+        );
+    } else {
+        $proxy = TLSProxy::Proxy->new(
+            undef,
+            cmdstr(app([ "openssl" ]), display => 1),
+            srctop_file("apps", "server.pem"),
+            (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
+        );
+    }
+
+    #Test 1: Downgrade from (D)TLSv1.3 to (D)TLSv1.2
     $proxy->clear();
-    $proxy->filter(undef);
-    $proxy->clientflags("-no_tls1_2");
-    $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
+    $proxy->filter(\&downgrade_filter);
+    $testtype = DOWNGRADE_TO_TLS_1_2;
+    skip "Unable to start up Proxy for tests", $testcount if !$proxy->start() &&
+                                                             !TLSProxy::Message->fail();
+    ok(TLSProxy::Message->fail(), "Downgrade ".$proto1_3." to ".$proto1_2);
+
+    #Test 2: Downgrade from (D)TLSv1.3 to TLSv1.1/DTLSv1
+    $proxy->clear();
+    $testtype = DOWNGRADE_TO_TLS_1_1;
     $proxy->start();
-    ok(TLSProxy::Message->success(), "TLSv1.2 client-side protocol hole");
+    ok(TLSProxy::Message->fail(), "Downgrade ".$proto1_3." to ".$proto1_1);
 
-    #Test 6: A server side protocol "hole" should not be detected as a downgrade
+    #Test 3: Downgrade from (D)TLSv1.2 to TLSv1.1/DTLSv1
     $proxy->clear();
-    $proxy->filter(undef);
-    $proxy->serverflags("-no_tls1_2");
+    $proxy->clientflags("-max_protocol ".$proto1_2);
+    $proxy->serverflags("-max_protocol ".$proto1_2);
     $proxy->start();
-    ok(TLSProxy::Message->success(), "TLSv1.2 server-side protocol hole");
+    ok(TLSProxy::Message->fail(), "Downgrade ".$proto1_2." to ".$proto1_1);
+
+    #Test 4: Client falls back from (D)TLSv1.3 (server does not support the
+    #        fallback SCSV)
+    $proxy->clear();
+    $testtype = FALLBACK_FROM_TLS_1_3;
+    $proxy->clientflags("-fallback_scsv -max_protocol ".$proto1_2);
+    $proxy->start();
+    my $alert = TLSProxy::Message->alert();
+    ok(TLSProxy::Message->fail()
+        && !$alert->server()
+        && $alert->description() == TLSProxy::Message::AL_DESC_ILLEGAL_PARAMETER,
+        "Fallback from ".$proto1_3);
+
+    SKIP: {
+        skip "TLSv1.1 disabled", 2 if disabled("tls1_1");
+        skip "Missing support for no_dtls1_2", 2 if $run_test_as_dtls == 1;
+        #Test 5: A client side protocol "hole" should not be detected as a downgrade
+        $proxy->clear();
+        $proxy->filter(undef);
+        $proxy->clientflags("-no_tls1_2");
+        $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
+        $proxy->start();
+        ok(TLSProxy::Message->success(), $proto1_2." client-side protocol hole");
+
+        #Test 6: A server side protocol "hole" should not be detected as a downgrade
+        $proxy->clear();
+        $proxy->filter(undef);
+        $proxy->serverflags("-no_tls1_2");
+        $proxy->start();
+        ok(TLSProxy::Message->success(), $proto1_2." server-side protocol hole");
+    }
 }
 
 sub downgrade_filter
 {
     my $proxy = shift;
 
-    # We're only interested in the initial ClientHello
-    if ($proxy->flight != 0) {
+    # We're only interested in the initial ClientHello except if we are expecting
+    # DTLS1.2 handshake in which case the client will send a second ClientHello
+    my $second_client_hello = $testtype == FALLBACK_FROM_TLS_1_3 && $proxy->isdtls
+                              && $proxy->flight == 2;
+
+    if ($proxy->flight != 0 && !$second_client_hello) {
         return;
     }
 
-    my $message = ${$proxy->message_list}[0];
+    my $message;
+
+    if ($second_client_hello == 0) {
+        $message = ${$proxy->message_list}[0];
+    } else {
+        $message = ${$proxy->message_list}[2];
+    }
 
-    my $ext;
     if ($testtype == FALLBACK_FROM_TLS_1_3) {
         #The default ciphersuite we use for TLSv1.2 without any SCSV
         my @ciphersuites = (TLSProxy::Message::CIPHER_RSA_WITH_AES_128_CBC_SHA);
         $message->ciphersuite_len(2 * scalar @ciphersuites);
         $message->ciphersuites(\@ciphersuites);
     } else {
+        my $ext;
+        my $version12hi = $proxy->isdtls == 1 ? 0xFE : 0x03;
+        my $version12lo = $proxy->isdtls == 1 ? 0xFD : 0x03;
+        my $version11hi = $proxy->isdtls == 1 ? 0xFE : 0x03;
+        my $version11lo = $proxy->isdtls == 1 ? 0xFF : 0x02;
+
         if ($testtype == DOWNGRADE_TO_TLS_1_2) {
             $ext = pack "C3",
                 0x02, # Length
-                0x03, 0x03; #TLSv1.2
+                $version12hi, $version12lo;
         } else {
             $ext = pack "C3",
                 0x02, # Length
-                0x03, 0x02; #TLSv1.1
+                $version11hi, $version11lo;
         }
 
         $message->set_extension(TLSProxy::Message::EXT_SUPPORTED_VERSIONS, $ext);
index 437716974765ed928b4749655341f9b83e25cd09..3b800d7369ab66d267c60de4877a7dee3b128e41 100644 (file)
@@ -18,7 +18,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -30,7 +30,7 @@ sub new
         $server,
         TLSProxy::Message::MT_CERTIFICATE,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index 67943490bd18bcc0cc04fcf8f342a572223c59ee..8b5dce7afbce91277d2f9053b6c7a2b4f0493d30 100644 (file)
@@ -18,7 +18,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -30,7 +30,7 @@ sub new
         $server,
         TLSProxy::Message::MT_CERTIFICATE_REQUEST,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index 637298525da93b665fbb4706bacd9976d5429d61..cbaf0951340957077f7241f1903a8e3c2854f3e1 100644 (file)
@@ -18,7 +18,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -30,7 +30,7 @@ sub new
         $server,
         TLSProxy::Message::MT_CERTIFICATE_VERIFY,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index c24065f2b91078faa2fe0f757dd2890eddcaee1a..d638634963cf65eb7c726168e8e35c1c9ffd6daa 100644 (file)
@@ -20,7 +20,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -32,7 +32,7 @@ sub new
         $server,
         TLSProxy::Message::MT_CLIENT_HELLO,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index 8b1e76afd5d8c6c2b20efd34feee57c3f6b17312..c970420bda05364ef5b29bf525ec74ab33e3bfc5 100644 (file)
@@ -18,7 +18,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -30,7 +30,7 @@ sub new
         $server,
         TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index 6fa7f1ac617d2912387f9a5881f058c4e25ae5e6..9ca0bf5f900bb4eebba34bd1ad9a6ff74c2be203 100644 (file)
@@ -21,7 +21,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -33,7 +33,7 @@ sub new
         $server,
         TLSProxy::Message::MT_HELLO_VERIFY_REQUEST,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index 3075761424bddbadab81cfb09162e9845a55e410..0239b509522eae28f9a0325790180a748a4e3a88 100644 (file)
@@ -48,6 +48,7 @@ use constant {
     AL_DESC_ILLEGAL_PARAMETER => 47,
     AL_DESC_DECODE_ERROR => 50,
     AL_DESC_PROTOCOL_VERSION => 70,
+    AL_DESC_INAPPROPRIATE_FALLBACK => 86,
     AL_DESC_NO_RENEGOTIATION => 100,
     AL_DESC_MISSING_EXTENSION => 109
 };
@@ -225,11 +226,11 @@ sub get_messages
                     $payload .= substr($record->decrypt_data, 0, $recoffset);
                     push @message_frag_lens, $recoffset;
                     if ($isdtls) {
-                        # We must set $msgseq, $msgfrag, $msgfragoffs
+                        # We must set $msgseq, $msgfraglen, $msgfragoffs
                         die "Internal error: cannot handle partial dtls messages\n"
                     }
                     $message = create_message($server, $mt,
-                        #$msgseq, $msgfrag, $msgfragoffs,
+                        #$msgseq, $msgfraglen, $msgfragoffs,
                         0, 0, 0,
                         $payload, $startoffset, $isdtls);
                     push @messages, $message;
@@ -256,16 +257,16 @@ sub get_messages
                 my $lenhi;
                 my $lenlo;
                 my $msgseq;
-                my $msgfrag;
+                my $msgfraglen;
                 my $msgfragoffs;
                 if ($isdtls) {
-                    my $msgfraghi;
-                    my $msgfraglo;
+                    my $msgfraglenhi;
+                    my $msgfraglenlo;
                     my $msgfragoffshi;
                     my $msgfragoffslo;
-                    ($mt, $lenhi, $lenlo, $msgseq, $msgfraghi, $msgfraglo, $msgfragoffshi, $msgfragoffslo) =
+                    ($mt, $lenhi, $lenlo, $msgseq, $msgfragoffshi, $msgfragoffslo, $msgfraglenhi, $msgfraglenlo) =
                         unpack('CnCnnCnC', substr($record->decrypt_data, $recoffset));
-                    $msgfrag = ($msgfraghi << 8) | $msgfraglo;
+                    $msgfraglen = ($msgfraglenhi << 8) | $msgfraglenlo;
                     $msgfragoffs = ($msgfragoffshi << 8) | $msgfragoffslo;
                 } else {
                     ($mt, $lenhi, $lenlo) =
@@ -274,6 +275,10 @@ sub get_messages
                 $messlen = ($lenhi << 8) | $lenlo;
                 print "  Message type: $message_type{$mt}($mt)\n";
                 print "  Message Length: $messlen\n";
+                if ($isdtls) {
+                    print "  Message fragment length: $msgfraglen\n";
+                    print "  Message fragment offset: $msgfragoffs\n";
+                }
                 $startoffset = $recoffset;
                 $recoffset += $msgheaderlen;
                 $payload = "";
@@ -287,7 +292,7 @@ sub get_messages
                         $recoffset += $messlen;
                         push @message_frag_lens, $messlen;
                         $message = create_message($server, $mt, $msgseq,
-                                                  $msgfrag, $msgfragoffs,
+                                                  $msgfraglen, $msgfragoffs,
                                                   $payload, $startoffset, $isdtls);
                         push @messages, $message;
 
@@ -337,7 +342,7 @@ sub get_messages
 #construct it
 sub create_message
 {
-    my ($server, $mt, $msgseq, $msgfrag, $msgfragoffs, $data, $startoffset, $isdtls) = @_;
+    my ($server, $mt, $msgseq, $msgfraglen, $msgfragoffs, $data, $startoffset, $isdtls) = @_;
     my $message;
 
     if ($mt == MT_CLIENT_HELLO) {
@@ -345,7 +350,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -358,7 +363,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -371,7 +376,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -384,7 +389,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -397,7 +402,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -410,7 +415,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -423,7 +428,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -436,7 +441,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -449,7 +454,7 @@ sub create_message
             $message = TLSProxy::NewSessionTicket->new_dtls(
                 $server,
                 $msgseq,
-                $msgfrag,
+                $msgfraglen,
                 $msgfragoffs,
                 $data,
                 [@message_rec_list],
@@ -471,7 +476,7 @@ sub create_message
             $isdtls,
             $server,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -486,7 +491,7 @@ sub create_message
             $server,
             $mt,
             $msgseq,
-            $msgfrag,
+            $msgfraglen,
             $msgfragoffs,
             $data,
             [@message_rec_list],
@@ -526,7 +531,7 @@ sub new
         $server,
         $mt,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -540,7 +545,7 @@ sub new
         records => $records,
         mt => $mt,
         msgseq => $msgseq,
-        msgfrag => $msgfrag,
+        msgfraglen => $msgfraglen,
         msgfragoffs => $msgfragoffs,
         startoffset => $startoffset,
         message_frag_lens => $message_frag_lens,
@@ -574,14 +579,21 @@ sub repack
     my $lenhi = length($self->data) >> 8;
 
     if ($self->{isdtls}) {
-        my $msgfraghi = $self->msgfrag >> 8;
-        my $msgfraglo = $self->msgfrag & 0xff;
+        my $msgfraglenhi = $self->msgfraglen >> 8;
+        my $msgfraglenlo = $self->msgfraglen & 0xff;
         my $msgfragoffshi = $self->msgfragoffs >> 8;
         my $msgfragoffslo = $self->msgfragoffs & 0xff;
 
+        if (length($self->data) != $self->msgfraglen) {
+            # TLSProxy does not support message fragmentation hence we can just
+            # overwrite the fragment lengths
+            $msgfraglenhi = $lenhi;
+            $msgfraglenlo = $lenlo;
+            print "DTLS Message Fragment Length overwritten with actual message size.\n"
+        }
         $msgdata = pack('CnCnnCnC', $self->mt, $lenhi, $lenlo, $self->msgseq,
-                                    $msgfraghi, $msgfraglo,
-                                    $msgfragoffshi, $msgfragoffslo).$self->data;
+                                    $msgfragoffshi, $msgfragoffslo,
+                                    $msgfraglenhi, $msgfraglenlo).$self->data;
     } else {
         $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data;
     }
@@ -703,13 +715,13 @@ sub msgseq
     }
     return $self->{msgseq};
 }
-sub msgfrag
+sub msgfraglen
 {
     my $self = shift;
     if (@_) {
-        $self->{msgfrag} = shift;
+        $self->{msgfraglen} = shift;
     }
-    return $self->{msgfrag};
+    return $self->{msgfraglen};
 }
 sub msgfragoffs
 {
index 26dcc17bb05a4cb26cb0b75cebbcf5afd26434bc..d60ea8d78fcc3b127e22340fbdc9da42a2db06ab 100644 (file)
@@ -18,7 +18,7 @@ sub new_dtls
 
     my ($server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -29,7 +29,7 @@ sub new_dtls
         1,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -66,7 +66,7 @@ sub init{
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -78,7 +78,7 @@ sub init{
         $server,
         TLSProxy::Message::MT_NEW_SESSION_TICKET,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index 3741898a3e2c8f42c2421a48400c606c5456c60a..92643701abf9efe8832253b515a639ba7248931b 100644 (file)
@@ -25,7 +25,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -37,7 +37,7 @@ sub new
         $server,
         TLSProxy::Message::MT_SERVER_HELLO,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
index 160ff366883f9875d588e2b10954445df64730f5..2e9b006ea82fb14168ea21f6771a644ff12c93e0 100644 (file)
@@ -18,7 +18,7 @@ sub new
     my ($isdtls,
         $server,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,
@@ -30,7 +30,7 @@ sub new
         $server,
         TLSProxy::Message::MT_SERVER_KEY_EXCHANGE,
         $msgseq,
-        $msgfrag,
+        $msgfraglen,
         $msgfragoffs,
         $data,
         $records,