[oe-commits] [openembedded-core] 05/14: openssl: Security fix CVE-2016-2179

git at git.openembedded.org git at git.openembedded.org
Tue Sep 27 08:13:46 UTC 2016


rpurdie pushed a commit to branch krogoth
in repository openembedded-core.

commit 8eb58cf801a26ec17dfc67bae2881f0fc03ea49b
Author: Armin Kuster <akuster at mvista.com>
AuthorDate: Fri Sep 23 23:03:14 2016 -0700

    openssl: Security fix CVE-2016-2179
    
    affects openssl < 1.0.1i
    
    Signed-off-by: Armin Kuster <akuster at mvista.com>
---
 .../openssl/openssl/CVE-2016-2179.patch            | 255 +++++++++++++++++++++
 .../recipes-connectivity/openssl/openssl_1.0.2h.bb |   1 +
 2 files changed, 256 insertions(+)

diff --git a/meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch
new file mode 100644
index 0000000..3a80696
--- /dev/null
+++ b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch
@@ -0,0 +1,255 @@
+From 26f2c5774f117aea588e8f31fad38bcf14e83bec Mon Sep 17 00:00:00 2001
+From: Matt Caswell <matt at openssl.org>
+Date: Thu, 30 Jun 2016 13:17:08 +0100
+Subject: [PATCH] Fix DTLS buffered message DoS attack
+
+DTLS can handle out of order record delivery. Additionally since
+handshake messages can be bigger than will fit into a single packet, the
+messages can be fragmented across multiple records (as with normal TLS).
+That means that the messages can arrive mixed up, and we have to
+reassemble them. We keep a queue of buffered messages that are "from the
+future", i.e. messages we're not ready to deal with yet but have arrived
+early. The messages held there may not be full yet - they could be one
+or more fragments that are still in the process of being reassembled.
+
+The code assumes that we will eventually complete the reassembly and
+when that occurs the complete message is removed from the queue at the
+point that we need to use it.
+
+However, DTLS is also tolerant of packet loss. To get around that DTLS
+messages can be retransmitted. If we receive a full (non-fragmented)
+message from the peer after previously having received a fragment of
+that message, then we ignore the message in the queue and just use the
+non-fragmented version. At that point the queued message will never get
+removed.
+
+Additionally the peer could send "future" messages that we never get to
+in order to complete the handshake. Each message has a sequence number
+(starting from 0). We will accept a message fragment for the current
+message sequence number, or for any sequence up to 10 into the future.
+However if the Finished message has a sequence number of 2, anything
+greater than that in the queue is just left there.
+
+So, in those two ways we can end up with "orphaned" data in the queue
+that will never get removed - except when the connection is closed. At
+that point all the queues are flushed.
+
+An attacker could seek to exploit this by filling up the queues with
+lots of large messages that are never going to be used in order to
+attempt a DoS by memory exhaustion.
+
+I will assume that we are only concerned with servers here. It does not
+seem reasonable to be concerned about a memory exhaustion attack on a
+client. They are unlikely to process enough connections for this to be
+an issue.
+
+A "long" handshake with many messages might be 5 messages long (in the
+incoming direction), e.g. ClientHello, Certificate, ClientKeyExchange,
+CertificateVerify, Finished. So this would be message sequence numbers 0
+to 4. Additionally we can buffer up to 10 messages in the future.
+Therefore the maximum number of messages that an attacker could send
+that could get orphaned would typically be 15.
+
+The maximum size that a DTLS message is allowed to be is defined by
+max_cert_list, which by default is 100k. Therefore the maximum amount of
+"orphaned" memory per connection is 1500k.
+
+Message sequence numbers get reset after the Finished message, so
+renegotiation will not extend the maximum number of messages that can be
+orphaned per connection.
+
+As noted above, the queues do get cleared when the connection is closed.
+Therefore in order to mount an effective attack, an attacker would have
+to open many simultaneous connections.
+
+Issue reported by Quan Luo.
+
+CVE-2016-2179
+
+Reviewed-by: Richard Levitte <levitte at openssl.org>
+
+Upstream-Status: Backport
+CVE: CVE-2016-2179
+Signed-off-by: Armin Kuster <akuster at mvista.com>
+
+---
+ ssl/d1_both.c  | 32 ++++++++++++++++----------------
+ ssl/d1_clnt.c  |  1 +
+ ssl/d1_lib.c   | 37 ++++++++++++++++++++++++++-----------
+ ssl/d1_srvr.c  |  3 ++-
+ ssl/ssl_locl.h |  3 ++-
+ 5 files changed, 47 insertions(+), 29 deletions(-)
+
+Index: openssl-1.0.2h/ssl/d1_both.c
+===================================================================
+--- openssl-1.0.2h.orig/ssl/d1_both.c
++++ openssl-1.0.2h/ssl/d1_both.c
+@@ -618,11 +618,23 @@ static int dtls1_retrieve_buffered_fragm
+     int al;
+ 
+     *ok = 0;
+-    item = pqueue_peek(s->d1->buffered_messages);
+-    if (item == NULL)
+-        return 0;
++    do {
++        item = pqueue_peek(s->d1->buffered_messages);
++        if (item == NULL)
++            return 0;
++
++        frag = (hm_fragment *)item->data;
++
++        if (frag->msg_header.seq < s->d1->handshake_read_seq) {
++            /* This is a stale message that has been buffered so clear it */
++            pqueue_pop(s->d1->buffered_messages);
++            dtls1_hm_fragment_free(frag);
++            pitem_free(item);
++            item = NULL;
++            frag = NULL;
++        }
++    } while (item == NULL);
+ 
+-    frag = (hm_fragment *)item->data;
+ 
+     /* Don't return if reassembly still in progress */
+     if (frag->reassembly != NULL)
+@@ -1296,18 +1308,6 @@ dtls1_retransmit_message(SSL *s, unsigne
+     return ret;
+ }
+ 
+-/* call this function when the buffered messages are no longer needed */
+-void dtls1_clear_record_buffer(SSL *s)
+-{
+-    pitem *item;
+-
+-    for (item = pqueue_pop(s->d1->sent_messages);
+-         item != NULL; item = pqueue_pop(s->d1->sent_messages)) {
+-        dtls1_hm_fragment_free((hm_fragment *)item->data);
+-        pitem_free(item);
+-    }
+-}
+-
+ unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p,
+                                         unsigned char mt, unsigned long len,
+                                         unsigned long frag_off,
+Index: openssl-1.0.2h/ssl/d1_clnt.c
+===================================================================
+--- openssl-1.0.2h.orig/ssl/d1_clnt.c
++++ openssl-1.0.2h/ssl/d1_clnt.c
+@@ -769,6 +769,7 @@ int dtls1_connect(SSL *s)
+             /* done with handshaking */
+             s->d1->handshake_read_seq = 0;
+             s->d1->next_handshake_write_seq = 0;
++            dtls1_clear_received_buffer(s);
+             goto end;
+             /* break; */
+ 
+Index: openssl-1.0.2h/ssl/d1_lib.c
+===================================================================
+--- openssl-1.0.2h.orig/ssl/d1_lib.c
++++ openssl-1.0.2h/ssl/d1_lib.c
+@@ -170,7 +170,6 @@ int dtls1_new(SSL *s)
+ static void dtls1_clear_queues(SSL *s)
+ {
+     pitem *item = NULL;
+-    hm_fragment *frag = NULL;
+     DTLS1_RECORD_DATA *rdata;
+ 
+     while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
+@@ -191,28 +190,44 @@ static void dtls1_clear_queues(SSL *s)
+         pitem_free(item);
+     }
+ 
++    while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
++        rdata = (DTLS1_RECORD_DATA *)item->data;
++        if (rdata->rbuf.buf) {
++            OPENSSL_free(rdata->rbuf.buf);
++        }
++        OPENSSL_free(item->data);
++        pitem_free(item);
++    }
++
++    dtls1_clear_received_buffer(s);
++    dtls1_clear_sent_buffer(s);
++}
++
++void dtls1_clear_received_buffer(SSL *s)
++{
++    pitem *item = NULL;
++    hm_fragment *frag = NULL;
++
+     while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
+         frag = (hm_fragment *)item->data;
+         dtls1_hm_fragment_free(frag);
+         pitem_free(item);
+     }
++}
++
++void dtls1_clear_sent_buffer(SSL *s)
++{
++    pitem *item = NULL;
++    hm_fragment *frag = NULL;
+ 
+     while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
+         frag = (hm_fragment *)item->data;
+         dtls1_hm_fragment_free(frag);
+         pitem_free(item);
+     }
+-
+-    while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
+-        rdata = (DTLS1_RECORD_DATA *)item->data;
+-        if (rdata->rbuf.buf) {
+-            OPENSSL_free(rdata->rbuf.buf);
+-        }
+-        OPENSSL_free(item->data);
+-        pitem_free(item);
+-    }
+ }
+ 
++
+ void dtls1_free(SSL *s)
+ {
+     ssl3_free(s);
+@@ -456,7 +471,7 @@ void dtls1_stop_timer(SSL *s)
+     BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
+              &(s->d1->next_timeout));
+     /* Clear retransmission buffer */
+-    dtls1_clear_record_buffer(s);
++    dtls1_clear_sent_buffer(s);
+ }
+ 
+ int dtls1_check_timeout_num(SSL *s)
+Index: openssl-1.0.2h/ssl/d1_srvr.c
+===================================================================
+--- openssl-1.0.2h.orig/ssl/d1_srvr.c
++++ openssl-1.0.2h/ssl/d1_srvr.c
+@@ -313,7 +313,7 @@ int dtls1_accept(SSL *s)
+         case SSL3_ST_SW_HELLO_REQ_B:
+ 
+             s->shutdown = 0;
+-            dtls1_clear_record_buffer(s);
++            dtls1_clear_sent_buffer(s);
+             dtls1_start_timer(s);
+             ret = ssl3_send_hello_request(s);
+             if (ret <= 0)
+@@ -894,6 +894,7 @@ int dtls1_accept(SSL *s)
+             /* next message is server hello */
+             s->d1->handshake_write_seq = 0;
+             s->d1->next_handshake_write_seq = 0;
++            dtls1_clear_received_buffer(s);
+             goto end;
+             /* break; */
+ 
+Index: openssl-1.0.2h/ssl/ssl_locl.h
+===================================================================
+--- openssl-1.0.2h.orig/ssl/ssl_locl.h
++++ openssl-1.0.2h/ssl/ssl_locl.h
+@@ -1242,7 +1242,8 @@ int dtls1_retransmit_message(SSL *s, uns
+                              unsigned long frag_off, int *found);
+ int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
+ int dtls1_retransmit_buffered_messages(SSL *s);
+-void dtls1_clear_record_buffer(SSL *s);
++void dtls1_clear_received_buffer(SSL *s);
++void dtls1_clear_sent_buffer(SSL *s);
+ void dtls1_get_message_header(unsigned char *data,
+                               struct hm_header_st *msg_hdr);
+ void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
diff --git a/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb b/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb
index 0db19fa..0e4dfee 100644
--- a/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb
+++ b/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb
@@ -39,6 +39,7 @@ SRC_URI += "file://find.pl;subdir=${BP}/util/ \
             file://configure-musl-target.patch \
             file://parallel.patch \
 	    file://CVE-2016-2178.patch \
+            file://CVE-2016-2179.patch \
            "
 SRC_URI[md5sum] = "9392e65072ce4b614c1392eefc1f23d0"
 SRC_URI[sha256sum] = "1d4007e53aad94a5b2002fe045ee7bb0b3d98f1a47f8b2bc851dcd1c74332919"

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Openembedded-commits mailing list