[openssl-commits] [openssl] OpenSSL_1_1_0-stable update

Matt Caswell matt at openssl.org
Wed Sep 21 19:47:30 UTC 2016


The branch OpenSSL_1_1_0-stable has been updated
       via  df6b5e29ffea2d5a3e08de92fb765fdb21c7a21e (commit)
       via  4b390b6c3f8df925dc92a3dd6b022baa9a2f4650 (commit)
      from  f757ce2a3df9c16c2ddbf83bf1725f6a89bccade (commit)


- Log -----------------------------------------------------------------
commit df6b5e29ffea2d5a3e08de92fb765fdb21c7a21e
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Sep 19 11:57:07 2016 +0100

    Excessive allocation of memory in dtls1_preprocess_fragment()
    
    This issue is very similar to CVE-2016-6307 described in the previous
    commit. The underlying defect is different but the security analysis and
    impacts are the same except that it impacts DTLS.
    
    A DTLS message includes 3 bytes for its length in the header for the
    message.
    This would allow for messages up to 16Mb in length. Messages of this length
    are excessive and OpenSSL includes a check to ensure that a peer is sending
    reasonably sized messages in order to avoid too much memory being consumed
    to service a connection. A flaw in the logic of version 1.1.0 means that
    memory for the message is allocated too early, prior to the excessive
    message length check. Due to way memory is allocated in OpenSSL this could
    mean an attacker could force up to 21Mb to be allocated to service a
    connection. This could lead to a Denial of Service through memory
    exhaustion. However, the excessive message length check still takes place,
    and this would cause the connection to immediately fail. Assuming that the
    application calls SSL_free() on the failed conneciton in a timely manner
    then the 21Mb of allocated memory will then be immediately freed again.
    Therefore the excessive memory allocation will be transitory in nature.
    This then means that there is only a security impact if:
    
    1) The application does not call SSL_free() in a timely manner in the
    event that the connection fails
    or
    2) The application is working in a constrained environment where there
    is very little free memory
    or
    3) The attacker initiates multiple connection attempts such that there
    are multiple connections in a state where memory has been allocated for
    the connection; SSL_free() has not yet been called; and there is
    insufficient memory to service the multiple requests.
    
    Except in the instance of (1) above any Denial Of Service is likely to
    be transitory because as soon as the connection fails the memory is
    subsequently freed again in the SSL_free() call. However there is an
    increased risk during this period of application crashes due to the lack
    of memory - which would then mean a more serious Denial of Service.
    
    This issue does not affect TLS users.
    
    Issue was reported by Shi Lei (Gear Team, Qihoo 360 Inc.).
    
    CVE-2016-6308
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (cherry picked from commit 48c054fec3506417b2598837b8062aae7114c200)

commit 4b390b6c3f8df925dc92a3dd6b022baa9a2f4650
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Sep 19 11:39:21 2016 +0100

    Excessive allocation of memory in tls_get_message_header()
    
    A TLS message includes 3 bytes for its length in the header for the message.
    This would allow for messages up to 16Mb in length. Messages of this length
    are excessive and OpenSSL includes a check to ensure that a peer is sending
    reasonably sized messages in order to avoid too much memory being consumed
    to service a connection. A flaw in the logic of version 1.1.0 means that
    memory for the message is allocated too early, prior to the excessive
    message length check. Due to way memory is allocated in OpenSSL this could
    mean an attacker could force up to 21Mb to be allocated to service a
    connection. This could lead to a Denial of Service through memory
    exhaustion. However, the excessive message length check still takes place,
    and this would cause the connection to immediately fail. Assuming that the
    application calls SSL_free() on the failed conneciton in a timely manner
    then the 21Mb of allocated memory will then be immediately freed again.
    Therefore the excessive memory allocation will be transitory in nature.
    This then means that there is only a security impact if:
    
    1) The application does not call SSL_free() in a timely manner in the
    event that the connection fails
    or
    2) The application is working in a constrained environment where there
    is very little free memory
    or
    3) The attacker initiates multiple connection attempts such that there
    are multiple connections in a state where memory has been allocated for
    the connection; SSL_free() has not yet been called; and there is
    insufficient memory to service the multiple requests.
    
    Except in the instance of (1) above any Denial Of Service is likely to
    be transitory because as soon as the connection fails the memory is
    subsequently freed again in the SSL_free() call. However there is an
    increased risk during this period of application crashes due to the lack
    of memory - which would then mean a more serious Denial of Service.
    
    This issue does not affect DTLS users.
    
    Issue was reported by Shi Lei (Gear Team, Qihoo 360 Inc.).
    
    CVE-2016-6307
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (cherry picked from commit c1ef7c971d0bbf117c3c80f65b5875e2e7b024b1)

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

Summary of changes:
 ssl/statem/statem.c      | 11 +++++++++++
 ssl/statem/statem_dtls.c | 35 ++++++++++++++++++-----------------
 ssl/statem/statem_lib.c  | 10 ----------
 3 files changed, 29 insertions(+), 27 deletions(-)

diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index df30085..8bc1feb 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -542,6 +542,17 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
                 return SUB_STATE_ERROR;
             }
 
+            /* dtls_get_message already did this */
+            if (!SSL_IS_DTLS(s)
+                    && s->s3->tmp.message_size > 0
+                    && !BUF_MEM_grow_clean(s->init_buf,
+                                           (int)s->s3->tmp.message_size
+                                           + SSL3_HM_HEADER_LENGTH)) {
+                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+                SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB);
+                return SUB_STATE_ERROR;
+            }
+
             st->read_state = READ_STATE_BODY;
             /* Fall through */
 
diff --git a/ssl/statem/statem_dtls.c b/ssl/statem/statem_dtls.c
index de2de09..043f41b 100644
--- a/ssl/statem/statem_dtls.c
+++ b/ssl/statem/statem_dtls.c
@@ -388,6 +388,20 @@ int dtls_get_message(SSL *s, int *mt, unsigned long *len)
     return 1;
 }
 
+/*
+ * dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
+ * may be greater if the maximum certificate list size requires it.
+ */
+static unsigned long dtls1_max_handshake_message_len(const SSL *s)
+{
+    unsigned long max_len =
+        DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+    if (max_len < (unsigned long)s->max_cert_list)
+        return s->max_cert_list;
+    return max_len;
+}
+
 static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
 {
     size_t frag_off, frag_len, msg_len;
@@ -397,15 +411,16 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
     frag_len = msg_hdr->frag_len;
 
     /* sanity checking */
-    if ((frag_off + frag_len) > msg_len) {
+    if ((frag_off + frag_len) > msg_len
+            || msg_len > dtls1_max_handshake_message_len(s)) {
         SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
         return SSL_AD_ILLEGAL_PARAMETER;
     }
 
     if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
         /*
-         * msg_len is limited to 2^24, but is effectively checked against max
-         * above
+         * msg_len is limited to 2^24, but is effectively checked against
+         * dtls_max_handshake_message_len(s) above
          */
         if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
             SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
@@ -493,20 +508,6 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok)
         return 0;
 }
 
-/*
- * dtls1_max_handshake_message_len returns the maximum number of bytes
- * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
- * may be greater if the maximum certificate list size requires it.
- */
-static unsigned long dtls1_max_handshake_message_len(const SSL *s)
-{
-    unsigned long max_len =
-        DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
-    if (max_len < (unsigned long)s->max_cert_list)
-        return s->max_cert_list;
-    return max_len;
-}
-
 static int
 dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
 {
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 19b75a7..31a84e4 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -414,10 +414,6 @@ int tls_get_message_header(SSL *s, int *mt)
          */
         l = RECORD_LAYER_get_rrec_length(&s->rlayer)
             + SSL3_HM_HEADER_LENGTH;
-        if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) {
-            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB);
-            goto err;
-        }
         s->s3->tmp.message_size = l;
 
         s->init_msg = s->init_buf->data;
@@ -430,11 +426,6 @@ int tls_get_message_header(SSL *s, int *mt)
             SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
             goto f_err;
         }
-        if (l && !BUF_MEM_grow_clean(s->init_buf,
-                                     (int)l + SSL3_HM_HEADER_LENGTH)) {
-            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, ERR_R_BUF_LIB);
-            goto err;
-        }
         s->s3->tmp.message_size = l;
 
         s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
@@ -444,7 +435,6 @@ int tls_get_message_header(SSL *s, int *mt)
     return 1;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
- err:
     return 0;
 }
 


More information about the openssl-commits mailing list