From: Frederik Wedel-Heinen Date: Wed, 3 Jan 2024 13:31:15 +0000 (+0100) Subject: Support dtls 1.3 downgrade mechanism X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=344262cddfe3192fe73bfba6f0d93b8b49c9382a;p=thirdparty%2Fopenssl.git Support dtls 1.3 downgrade mechanism Reviewed-by: Viktor Dukhovni Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23320) --- diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 8f85ef9d336..beece1153ab 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -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 }; diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index dbe2edf4bd1..4f606c3ef0e 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -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 diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 50f7444bc43..3eb37b09bf9 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -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) { diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 0e3feea2154..8a3597c4883 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -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; diff --git a/test/recipes/70-test_tls13downgrade.t b/test/recipes/70-test_tls13downgrade.t index 999a79e62a8..67e7b30a57c 100644 --- a/test/recipes/70-test_tls13downgrade.t +++ b/test/recipes/70-test_tls13downgrade.t @@ -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); diff --git a/util/perl/TLSProxy/Certificate.pm b/util/perl/TLSProxy/Certificate.pm index 43771697476..3b800d7369a 100644 --- a/util/perl/TLSProxy/Certificate.pm +++ b/util/perl/TLSProxy/Certificate.pm @@ -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, diff --git a/util/perl/TLSProxy/CertificateRequest.pm b/util/perl/TLSProxy/CertificateRequest.pm index 67943490bd1..8b5dce7afbc 100644 --- a/util/perl/TLSProxy/CertificateRequest.pm +++ b/util/perl/TLSProxy/CertificateRequest.pm @@ -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, diff --git a/util/perl/TLSProxy/CertificateVerify.pm b/util/perl/TLSProxy/CertificateVerify.pm index 637298525da..cbaf0951340 100644 --- a/util/perl/TLSProxy/CertificateVerify.pm +++ b/util/perl/TLSProxy/CertificateVerify.pm @@ -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, diff --git a/util/perl/TLSProxy/ClientHello.pm b/util/perl/TLSProxy/ClientHello.pm index c24065f2b91..d638634963c 100644 --- a/util/perl/TLSProxy/ClientHello.pm +++ b/util/perl/TLSProxy/ClientHello.pm @@ -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, diff --git a/util/perl/TLSProxy/EncryptedExtensions.pm b/util/perl/TLSProxy/EncryptedExtensions.pm index 8b1e76afd5d..c970420bda0 100644 --- a/util/perl/TLSProxy/EncryptedExtensions.pm +++ b/util/perl/TLSProxy/EncryptedExtensions.pm @@ -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, diff --git a/util/perl/TLSProxy/HelloVerifyRequest.pm b/util/perl/TLSProxy/HelloVerifyRequest.pm index 6fa7f1ac617..9ca0bf5f900 100644 --- a/util/perl/TLSProxy/HelloVerifyRequest.pm +++ b/util/perl/TLSProxy/HelloVerifyRequest.pm @@ -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, diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm index 3075761424b..0239b509522 100644 --- a/util/perl/TLSProxy/Message.pm +++ b/util/perl/TLSProxy/Message.pm @@ -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 { diff --git a/util/perl/TLSProxy/NewSessionTicket.pm b/util/perl/TLSProxy/NewSessionTicket.pm index 26dcc17bb05..d60ea8d78fc 100644 --- a/util/perl/TLSProxy/NewSessionTicket.pm +++ b/util/perl/TLSProxy/NewSessionTicket.pm @@ -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, diff --git a/util/perl/TLSProxy/ServerHello.pm b/util/perl/TLSProxy/ServerHello.pm index 3741898a3e2..92643701abf 100644 --- a/util/perl/TLSProxy/ServerHello.pm +++ b/util/perl/TLSProxy/ServerHello.pm @@ -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, diff --git a/util/perl/TLSProxy/ServerKeyExchange.pm b/util/perl/TLSProxy/ServerKeyExchange.pm index 160ff366883..2e9b006ea82 100644 --- a/util/perl/TLSProxy/ServerKeyExchange.pm +++ b/util/perl/TLSProxy/ServerKeyExchange.pm @@ -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,