[openssl] master update

Matt Caswell matt at openssl.org
Thu Mar 25 13:48:12 UTC 2021


The branch master has been updated
       via  468d9d556409a53da2c5d16961f9531dd10a6e1b (commit)
       via  39a140597d874e554b736885ac4dea16ac40a87a (commit)
       via  02b1636fe3db274497304a3e95a4e32ced7e841b (commit)
       via  112580c27b829b0ac0874d5c5787195f27c7952c (commit)
       via  ae937a096c6ce42d016281b91677f78de3f3cfe3 (commit)
      from  eb78f9552307248ca5ccfc28d61faa823dae7c7e (commit)


- Log -----------------------------------------------------------------
commit 468d9d556409a53da2c5d16961f9531dd10a6e1b
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 25 10:20:50 2021 +0000

    Update CHANGES.md and NEWS.md for new release
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>

commit 39a140597d874e554b736885ac4dea16ac40a87a
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 18 16:52:10 2021 +0000

    Ensure buffer/length pairs are always in sync
    
    Following on from CVE-2021-3449 which was caused by a non-zero length
    associated with a NULL buffer, other buffer/length pairs are updated to
    ensure that they too are always in sync.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>

commit 02b1636fe3db274497304a3e95a4e32ced7e841b
Author: Peter Kaestle <peter.kaestle at nokia.com>
Date:   Mon Mar 15 13:19:56 2021 +0100

    ssl sigalg extension: fix NULL pointer dereference
    
    As the variable peer_sigalgslen is not cleared on ssl rehandshake, it's
    possible to crash an openssl tls secured server remotely by sending a
    manipulated hello message in a rehandshake.
    
    On such a manipulated rehandshake, tls1_set_shared_sigalgs() calls
    tls12_shared_sigalgs() with the peer_sigalgslen of the previous
    handshake, while the peer_sigalgs has been freed.
    As a result tls12_shared_sigalgs() walks over the available
    peer_sigalgs and tries to access data of a NULL pointer.
    
    This issue was introduced by c589c34e61 (Add support for the TLS 1.3
    signature_algorithms_cert extension, 2018-01-11).
    
    Signed-off-by: Peter Kästle <peter.kaestle at nokia.com>
    Signed-off-by: Samuel Sapalski <samuel.sapalski at nokia.com>
    
    CVE-2021-3449
    
    CLA: trivial
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 112580c27b829b0ac0874d5c5787195f27c7952c
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 18 15:29:04 2021 +0000

    Add a test for CVE-2021-3449
    
    We perform a reneg handshake, where the second ClientHello drops the
    sig_algs extension. It must also contain cert_sig_algs for the test to
    work.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>

commit ae937a096c6ce42d016281b91677f78de3f3cfe3
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 18 15:25:42 2021 +0000

    Teach TLSProxy how to encrypt <= TLSv1.2 ETM records
    
    Previously TLSProxy only knew how to "repack" messages for TLSv1.3.
    Most of the handshake in <= TLSv1.2 is unencrypted so this hasn't been
    too much of restriction. However we now want to modify reneg handshakes
    which are encrypted so we need to add that capability.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 CHANGES.md                           | 43 ++++++++++++++++++++++++++++++++++++
 NEWS.md                              |  5 +++++
 ssl/s3_lib.c                         |  5 ++++-
 ssl/ssl_lib.c                        | 14 +++++++++---
 ssl/statem/extensions.c              |  2 ++
 ssl/statem/extensions_clnt.c         | 13 +++++++++--
 ssl/statem/statem_clnt.c             |  7 +++++-
 ssl/statem/statem_srvr.c             | 15 ++++++++++---
 test/recipes/70-test_renegotiation.t | 36 +++++++++++++++++++++++++++++-
 util/perl/TLSProxy/Message.pm        | 37 +++++++++++++++++++++++++------
 10 files changed, 159 insertions(+), 18 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 559f09a035..c57b9ad4a5 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1661,6 +1661,49 @@ OpenSSL 1.1.1
 
 ### Changes between 1.1.1j and 1.1.1k [xx XXX xxxx]
 
+ * Fixed a problem with verifying a certificate chain when using the
+   X509_V_FLAG_X509_STRICT flag. This flag enables additional security checks of
+   the certificates present in a certificate chain. It is not set by default.
+
+   Starting from OpenSSL version 1.1.1h a check to disallow certificates in
+   the chain that have explicitly encoded elliptic curve parameters was added
+   as an additional strict check.
+
+   An error in the implementation of this check meant that the result of a
+   previous check to confirm that certificates in the chain are valid CA
+   certificates was overwritten. This effectively bypasses the check
+   that non-CA certificates must not be able to issue other certificates.
+
+   If a "purpose" has been configured then there is a subsequent opportunity
+   for checks that the certificate is a valid CA.  All of the named "purpose"
+   values implemented in libcrypto perform this check.  Therefore, where
+   a purpose is set the certificate chain will still be rejected even when the
+   strict flag has been used. A purpose is set by default in libssl client and
+   server certificate verification routines, but it can be overridden or
+   removed by an application.
+
+   In order to be affected, an application must explicitly set the
+   X509_V_FLAG_X509_STRICT verification flag and either not set a purpose
+   for the certificate verification or, in the case of TLS client or server
+   applications, override the default purpose.
+   ([CVE-2021-3450])
+
+   *Tomáš Mráz*
+
+ * Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously
+   crafted renegotiation ClientHello message from a client. If a TLSv1.2
+   renegotiation ClientHello omits the signature_algorithms extension (where it
+   was present in the initial ClientHello), but includes a
+   signature_algorithms_cert extension then a NULL pointer dereference will
+   result, leading to a crash and a denial of service attack.
+
+   A server is only vulnerable if it has TLSv1.2 and renegotiation enabled
+   (which is the default configuration). OpenSSL TLS clients are not impacted by
+   this issue.
+   ([CVE-2021-3449])
+
+   *Peter Kästle and Samuel Sapalski*
+
 ### Changes between 1.1.1i and 1.1.1j [16 Feb 2021]
 
  * Fixed the X509_issuer_and_serial_hash() function. It attempts to
diff --git a/NEWS.md b/NEWS.md
index a9e796dd7b..923a713087 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -87,6 +87,11 @@ OpenSSL 1.1.1
 
 ### Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [under development]
 
+  * Fixed a problem with verifying a certificate chain when using the
+    X509_V_FLAG_X509_STRICT flag ([CVE-2021-3450])
+  * Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously
+    crafted renegotiation ClientHello message from a client ([CVE-2021-3449])
+
 ### Major changes between OpenSSL 1.1.1i and OpenSSL 1.1.1j [16 Feb 2021]
 
   * Fixed a NULL pointer deref in the X509_issuer_and_serial_hash()
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 19ae6d9a28..f5b063319b 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -4603,6 +4603,7 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
 
         OPENSSL_clear_free(s->s3.tmp.psk, psklen);
         s->s3.tmp.psk = NULL;
+        s->s3.tmp.psklen = 0;
         if (!s->method->ssl3_enc->generate_master_secret(s,
                     s->session->master_key, pskpms, pskpmslen,
                     &s->session->master_key_length)) {
@@ -4632,8 +4633,10 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
         else
             OPENSSL_cleanse(pms, pmslen);
     }
-    if (s->server == 0)
+    if (s->server == 0) {
         s->s3.tmp.pms = NULL;
+        s->s3.tmp.pmslen = 0;
+    }
     return ret;
 }
 
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 4cb40bd89b..57e8d15798 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -772,8 +772,10 @@ SSL *SSL_new(SSL_CTX *ctx)
         s->ext.ecpointformats =
             OPENSSL_memdup(ctx->ext.ecpointformats,
                            ctx->ext.ecpointformats_len);
-        if (!s->ext.ecpointformats)
+        if (!s->ext.ecpointformats) {
+            s->ext.ecpointformats_len = 0;
             goto err;
+        }
         s->ext.ecpointformats_len =
             ctx->ext.ecpointformats_len;
     }
@@ -782,8 +784,10 @@ SSL *SSL_new(SSL_CTX *ctx)
             OPENSSL_memdup(ctx->ext.supportedgroups,
                            ctx->ext.supportedgroups_len
                                 * sizeof(*ctx->ext.supportedgroups));
-        if (!s->ext.supportedgroups)
+        if (!s->ext.supportedgroups) {
+            s->ext.supportedgroups_len = 0;
             goto err;
+        }
         s->ext.supportedgroups_len = ctx->ext.supportedgroups_len;
     }
 
@@ -793,8 +797,10 @@ SSL *SSL_new(SSL_CTX *ctx)
 
     if (s->ctx->ext.alpn) {
         s->ext.alpn = OPENSSL_malloc(s->ctx->ext.alpn_len);
-        if (s->ext.alpn == NULL)
+        if (s->ext.alpn == NULL) {
+            s->ext.alpn_len = 0;
             goto err;
+        }
         memcpy(s->ext.alpn, s->ctx->ext.alpn, s->ctx->ext.alpn_len);
         s->ext.alpn_len = s->ctx->ext.alpn_len;
     }
@@ -2990,6 +2996,7 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
     OPENSSL_free(ctx->ext.alpn);
     ctx->ext.alpn = OPENSSL_memdup(protos, protos_len);
     if (ctx->ext.alpn == NULL) {
+        ctx->ext.alpn_len = 0;
         ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
         return 1;
     }
@@ -3009,6 +3016,7 @@ int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
     OPENSSL_free(ssl->ext.alpn);
     ssl->ext.alpn = OPENSSL_memdup(protos, protos_len);
     if (ssl->ext.alpn == NULL) {
+        ssl->ext.alpn_len = 0;
         ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
         return 1;
     }
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index 5e21ff8593..0ce436d082 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -1114,6 +1114,7 @@ static int init_sig_algs(SSL *s, unsigned int context)
     /* Clear any signature algorithms extension received */
     OPENSSL_free(s->s3.tmp.peer_sigalgs);
     s->s3.tmp.peer_sigalgs = NULL;
+    s->s3.tmp.peer_sigalgslen = 0;
 
     return 1;
 }
@@ -1123,6 +1124,7 @@ static int init_sig_algs_cert(SSL *s, ossl_unused unsigned int context)
     /* Clear any signature algorithms extension received */
     OPENSSL_free(s->s3.tmp.peer_cert_sigalgs);
     s->s3.tmp.peer_cert_sigalgs = NULL;
+    s->s3.tmp.peer_cert_sigalgslen = 0;
 
     return 1;
 }
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index cac713fff0..b3ef1bc16a 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -810,6 +810,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
         OPENSSL_free(s->psksession_id);
         s->psksession_id = OPENSSL_memdup(id, idlen);
         if (s->psksession_id == NULL) {
+            s->psksession_id_len = 0;
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
@@ -1337,6 +1338,7 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
         OPENSSL_free(s->ext.peer_ecpointformats);
         s->ext.peer_ecpointformats = OPENSSL_malloc(ecpointformats_len);
         if (s->ext.peer_ecpointformats == NULL) {
+            s->ext.peer_ecpointformats_len = 0;
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             return 0;
         }
@@ -1446,8 +1448,12 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         s->ext.scts_len = (uint16_t)size;
         if (size > 0) {
             s->ext.scts = OPENSSL_malloc(size);
-            if (s->ext.scts == NULL
-                    || !PACKET_copy_bytes(pkt, s->ext.scts, size)) {
+            if (s->ext.scts == NULL) {
+                s->ext.scts_len = 0;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+            if (!PACKET_copy_bytes(pkt, s->ext.scts, size)) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
@@ -1541,6 +1547,7 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     OPENSSL_free(s->ext.npn);
     s->ext.npn = OPENSSL_malloc(selected_len);
     if (s->ext.npn == NULL) {
+        s->ext.npn_len = 0;
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
     }
@@ -1578,6 +1585,7 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     OPENSSL_free(s->s3.alpn_selected);
     s->s3.alpn_selected = OPENSSL_malloc(len);
     if (s->s3.alpn_selected == NULL) {
+        s->s3.alpn_selected_len = 0;
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
     }
@@ -1606,6 +1614,7 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         s->session->ext.alpn_selected =
             OPENSSL_memdup(s->s3.alpn_selected, s->s3.alpn_selected_len);
         if (s->session->ext.alpn_selected == NULL) {
+            s->session->ext.alpn_selected_len = 0;
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             return 0;
         }
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 666ee43363..8686b1e684 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -2352,6 +2352,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
         s->s3.tmp.ctype_len = 0;
         OPENSSL_free(s->pha_context);
         s->pha_context = NULL;
+        s->pha_context_len = 0;
 
         if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
             !PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
@@ -2642,14 +2643,15 @@ int tls_process_cert_status_body(SSL *s, PACKET *pkt)
     }
     s->ext.ocsp.resp = OPENSSL_malloc(resplen);
     if (s->ext.ocsp.resp == NULL) {
+        s->ext.ocsp.resp_len = 0;
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
         return 0;
     }
+    s->ext.ocsp.resp_len = resplen;
     if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
         SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
         return 0;
     }
-    s->ext.ocsp.resp_len = resplen;
 
     return 1;
 }
@@ -3313,9 +3315,11 @@ int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
  err:
     OPENSSL_clear_free(s->s3.tmp.pms, s->s3.tmp.pmslen);
     s->s3.tmp.pms = NULL;
+    s->s3.tmp.pmslen = 0;
 #ifndef OPENSSL_NO_PSK
     OPENSSL_clear_free(s->s3.tmp.psk, s->s3.tmp.psklen);
     s->s3.tmp.psk = NULL;
+    s->s3.tmp.psklen = 0;
 #endif
     return 0;
 }
@@ -3387,6 +3391,7 @@ int tls_client_key_exchange_post_work(SSL *s)
  err:
     OPENSSL_clear_free(pms, pmslen);
     s->s3.tmp.pms = NULL;
+    s->s3.tmp.pmslen = 0;
     return 0;
 }
 
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index aca17868b1..bad3619170 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -2116,6 +2116,7 @@ int tls_handle_alpn(SSL *s)
             OPENSSL_free(s->s3.alpn_selected);
             s->s3.alpn_selected = OPENSSL_memdup(selected, selected_len);
             if (s->s3.alpn_selected == NULL) {
+                s->s3.alpn_selected_len = 0;
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
@@ -2725,10 +2726,15 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
         if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
             OPENSSL_free(s->pha_context);
             s->pha_context_len = 32;
-            if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL
-                    || RAND_bytes_ex(s->ctx->libctx, s->pha_context,
+            if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL) {
+                s->pha_context_len = 0;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+                return 0;
+            }
+            if (RAND_bytes_ex(s->ctx->libctx, s->pha_context,
                                      s->pha_context_len) <= 0
-                    || !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
+                    || !WPACKET_sub_memcpy_u8(pkt, s->pha_context,
+                                              s->pha_context_len)) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
@@ -2828,6 +2834,7 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
     OPENSSL_cleanse(psk, psklen);
 
     if (s->s3.tmp.psk == NULL) {
+        s->s3.tmp.psklen = 0;
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
         return 0;
     }
@@ -3329,6 +3336,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
 #ifndef OPENSSL_NO_PSK
     OPENSSL_clear_free(s->s3.tmp.psk, s->s3.tmp.psklen);
     s->s3.tmp.psk = NULL;
+    s->s3.tmp.psklen = 0;
 #endif
     return MSG_PROCESS_ERROR;
 }
@@ -3921,6 +3929,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
             s->session->ext.alpn_selected =
                 OPENSSL_memdup(s->s3.alpn_selected, s->s3.alpn_selected_len);
             if (s->session->ext.alpn_selected == NULL) {
+                s->session->ext.alpn_selected_len = 0;
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
diff --git a/test/recipes/70-test_renegotiation.t b/test/recipes/70-test_renegotiation.t
index 68b9ba1aa0..7643b9be69 100644
--- a/test/recipes/70-test_renegotiation.t
+++ b/test/recipes/70-test_renegotiation.t
@@ -38,7 +38,7 @@ my $proxy = TLSProxy::Proxy->new(
 $proxy->clientflags("-no_tls1_3");
 $proxy->reneg(1);
 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 3;
+plan tests => 4;
 ok(TLSProxy::Message->success(), "Basic renegotiation");
 
 #Test 2: Client does not send the Reneg SCSV. Reneg should fail
@@ -78,6 +78,20 @@ SKIP: {
        "Check ClientHello version is the same");
 }
 
+SKIP: {
+    skip "TLSv1.2 disabled", 1
+        if disabled("tls1_2");
+
+    #Test 4: Test for CVE-2021-3449. client_sig_algs instead of sig_algs in
+    #        resumption ClientHello
+    $proxy->clear();
+    $proxy->filter(\&sigalgs_filter);
+    $proxy->clientflags("-tls1_2");
+    $proxy->reneg(1);
+    $proxy->start();
+    ok(TLSProxy::Message->fail(), "client_sig_algs instead of sig_algs");
+}
+
 sub reneg_filter
 {
     my $proxy = shift;
@@ -97,3 +111,23 @@ sub reneg_filter
         }
     }
 }
+
+sub sigalgs_filter
+{
+    my $proxy = shift;
+    my $cnt = 0;
+
+    # We're only interested in the second ClientHello message
+    foreach my $message (@{$proxy->message_list}) {
+        if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
+            next if ($cnt++ == 0);
+
+            my $sigs = pack "C10", 0x00, 0x08,
+                            # rsa_pkcs_sha{256,384,512,1}
+                            0x04, 0x01,  0x05, 0x01,  0x06, 0x01,  0x02, 0x01;
+            $message->set_extension(TLSProxy::Message::EXT_SIG_ALGS_CERT, $sigs);
+            $message->delete_extension(TLSProxy::Message::EXT_SIG_ALGS);
+            $message->repack();
+        }
+    }
+}
diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm
index 4780302a51..7926d0041b 100644
--- a/util/perl/TLSProxy/Message.pm
+++ b/util/perl/TLSProxy/Message.pm
@@ -448,7 +448,7 @@ sub ciphersuite
 }
 
 #Update all the underlying records with the modified data from this message
-#Note: Only supports re-encrypting for TLSv1.3
+#Note: Only supports TLSv1.3 and ETM encryption
 sub repack
 {
     my $self = shift;
@@ -490,15 +490,38 @@ sub repack
         # (If a length override is ever needed to construct invalid packets,
         #  use an explicit override field instead.)
         $rec->decrypt_len(length($rec->decrypt_data));
-        $rec->len($rec->len + length($msgdata) - $old_length);
-        # Only support re-encryption for TLSv1.3.
-        if (TLSProxy::Proxy->is_tls13() && $rec->encrypted()) {
-            #Add content type (1 byte) and 16 tag bytes
-            $rec->data($rec->decrypt_data
-                .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16));
+        # Only support re-encryption for TLSv1.3 and ETM.
+        if ($rec->encrypted()) {
+            if (TLSProxy::Proxy->is_tls13()) {
+                #Add content type (1 byte) and 16 tag bytes
+                $rec->data($rec->decrypt_data
+                    .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16));
+            } elsif ($rec->etm()) {
+                my $data = $rec->decrypt_data;
+                #Add padding
+                my $padval = length($data) % 16;
+                $padval = 15 - $padval;
+                for (0..$padval) {
+                    $data .= pack("C", $padval);
+                }
+
+                #Add MAC. Assumed to be 20 bytes
+                foreach my $macval (0..19) {
+                    $data .= pack("C", $macval);
+                }
+
+                if ($rec->version() >= TLSProxy::Record::VERS_TLS_1_1) {
+                    #Explicit IV
+                    $data = ("\0"x16).$data;
+                }
+                $rec->data($data);
+            } else {
+                die "Unsupported encryption: No ETM";
+            }
         } else {
             $rec->data($rec->decrypt_data);
         }
+        $rec->len(length($rec->data));
 
         #Update the fragment len in case we changed it above
         ${$self->message_frag_lens}[0] = length($msgdata)


More information about the openssl-commits mailing list