[oe-commits] [openembedded-core] 02/15: openssl: Security fix CVE-2016-2181

git at git.openembedded.org git at git.openembedded.org
Thu Oct 6 07:52:00 UTC 2016


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

commit c3d4cc8e452b29d4ca620b5c93d22a88c5aa1f03
Author: Armin Kuster <akuster at mvista.com>
AuthorDate: Fri Sep 23 23:09:29 2016 -0700

    openssl: Security fix CVE-2016-2181
    
    affects openssl < 1.0.1i
    
    Signed-off-by: Armin Kuster <akuster at mvista.com>
---
 .../openssl/openssl/CVE-2016-2181_p1.patch         |  91 ++++++++
 .../openssl/openssl/CVE-2016-2181_p2.patch         | 239 +++++++++++++++++++++
 .../openssl/openssl/CVE-2016-2181_p3.patch         |  30 +++
 .../recipes-connectivity/openssl/openssl_1.0.2h.bb |   3 +
 4 files changed, 363 insertions(+)

diff --git a/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p1.patch b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p1.patch
new file mode 100644
index 0000000..9149dbe
--- /dev/null
+++ b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p1.patch
@@ -0,0 +1,91 @@
+From 20744f6b40b5ded059a848f66d6ba922f2a62eb3 Mon Sep 17 00:00:00 2001
+From: Matt Caswell <matt at openssl.org>
+Date: Tue, 5 Jul 2016 11:46:26 +0100
+Subject: [PATCH] Fix DTLS unprocessed records bug
+
+During a DTLS handshake we may get records destined for the next epoch
+arrive before we have processed the CCS. In that case we can't decrypt or
+verify the record yet, so we buffer it for later use. When we do receive
+the CCS we work through the queue of unprocessed records and process them.
+
+Unfortunately the act of processing wipes out any existing packet data
+that we were still working through. This includes any records from the new
+epoch that were in the same packet as the CCS. We should only process the
+buffered records if we've not got any data left.
+
+Reviewed-by: Richard Levitte <levitte at openssl.org>
+
+Upstream-Status: Backport
+CVE: CVE-2016-2180 patch 1
+Signed-off-by: Armin Kuster <akuster at mvista.com>
+
+---
+ ssl/d1_pkt.c | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
+index fe30ec7..1fb119d 100644
+--- a/ssl/d1_pkt.c
++++ b/ssl/d1_pkt.c
+@@ -319,6 +319,7 @@ static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
+ static int dtls1_process_buffered_records(SSL *s)
+ {
+     pitem *item;
++    SSL3_BUFFER *rb;
+ 
+     item = pqueue_peek(s->d1->unprocessed_rcds.q);
+     if (item) {
+@@ -326,6 +327,19 @@ static int dtls1_process_buffered_records(SSL *s)
+         if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
+             return (1);         /* Nothing to do. */
+ 
++        rb = &s->s3->rbuf;
++
++        if (rb->left > 0) {
++            /*
++             * We've still got data from the current packet to read. There could
++             * be a record from the new epoch in it - so don't overwrite it
++             * with the unprocessed records yet (we'll do it when we've
++             * finished reading the current packet).
++             */
++            return 1;
++        }
++
++
+         /* Process all the records. */
+         while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
+             dtls1_get_unprocessed_record(s);
+@@ -581,6 +595,7 @@ int dtls1_get_record(SSL *s)
+ 
+     rr = &(s->s3->rrec);
+ 
++ again:
+     /*
+      * The epoch may have changed.  If so, process all the pending records.
+      * This is a non-blocking operation.
+@@ -593,7 +608,6 @@ int dtls1_get_record(SSL *s)
+         return 1;
+ 
+     /* get something from the wire */
+- again:
+     /* check if we have the header */
+     if ((s->rstate != SSL_ST_READ_BODY) ||
+         (s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
+@@ -1830,8 +1844,13 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+     if (rr->epoch == s->d1->r_epoch)
+         return &s->d1->bitmap;
+ 
+-    /* Only HM and ALERT messages can be from the next epoch */
++    /*
++     * Only HM and ALERT messages can be from the next epoch and only if we
++     * have already processed all of the unprocessed records from the last
++     * epoch
++     */
+     else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
++             s->d1->unprocessed_rcds.epoch != s->d1->r_epoch &&
+              (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+         *is_next_epoch = 1;
+         return &s->d1->next_bitmap;
+-- 
+2.7.4
+
diff --git a/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch
new file mode 100644
index 0000000..ecf138a
--- /dev/null
+++ b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch
@@ -0,0 +1,239 @@
+From 3884b47b7c255c2e94d9b387ee83c7e8bb981258 Mon Sep 17 00:00:00 2001
+From: Matt Caswell <matt at openssl.org>
+Date: Tue, 5 Jul 2016 12:04:37 +0100
+Subject: [PATCH] Fix DTLS replay protection
+
+The DTLS implementation provides some protection against replay attacks
+in accordance with RFC6347 section 4.1.2.6.
+
+A sliding "window" of valid record sequence numbers is maintained with
+the "right" hand edge of the window set to the highest sequence number we
+have received so far. Records that arrive that are off the "left" hand
+edge of the window are rejected. Records within the window are checked
+against a list of records received so far. If we already received it then
+we also reject the new record.
+
+If we have not already received the record, or the sequence number is off
+the right hand edge of the window then we verify the MAC of the record.
+If MAC verification fails then we discard the record. Otherwise we mark
+the record as received. If the sequence number was off the right hand edge
+of the window, then we slide the window along so that the right hand edge
+is in line with the newly received sequence number.
+
+Records may arrive for future epochs, i.e. a record from after a CCS being
+sent, can arrive before the CCS does if the packets get re-ordered. As we
+have not yet received the CCS we are not yet in a position to decrypt or
+validate the MAC of those records. OpenSSL places those records on an
+unprocessed records queue. It additionally updates the window immediately,
+even though we have not yet verified the MAC. This will only occur if
+currently in a handshake/renegotiation.
+
+This could be exploited by an attacker by sending a record for the next
+epoch (which does not have to decrypt or have a valid MAC), with a very
+large sequence number. This means the right hand edge of the window is
+moved very far to the right, and all subsequent legitimate packets are
+dropped causing a denial of service.
+
+A similar effect can be achieved during the initial handshake. In this
+case there is no MAC key negotiated yet. Therefore an attacker can send a
+message for the current epoch with a very large sequence number. The code
+will process the record as normal. If the hanshake message sequence number
+(as opposed to the record sequence number that we have been talking about
+so far) is in the future then the injected message is bufferred to be
+handled later, but the window is still updated. Therefore all subsequent
+legitimate handshake records are dropped. This aspect is not considered a
+security issue because there are many ways for an attacker to disrupt the
+initial handshake and prevent it from completing successfully (e.g.
+injection of a handshake message will cause the Finished MAC to fail and
+the handshake to be aborted). This issue comes about as a result of trying
+to do replay protection, but having no integrity mechanism in place yet.
+Does it even make sense to have replay protection in epoch 0? That
+issue isn't addressed here though.
+
+This addressed an OCAP Audit issue.
+
+CVE-2016-2181
+
+Upstream-Status: Backport
+CVE: CVE-2016-2181 patch2
+Signed-off-by: Armin Kuster <akuster at mvista.com>
+
+
+Reviewed-by: Richard Levitte <levitte at openssl.org>
+---
+ ssl/d1_pkt.c  | 60 +++++++++++++++++++++++++++++++++++++++++++++++------------
+ ssl/ssl.h     |  1 +
+ ssl/ssl_err.c |  4 +++-
+ 3 files changed, 52 insertions(+), 13 deletions(-)
+
+Index: openssl-1.0.2h/ssl/d1_pkt.c
+===================================================================
+--- openssl-1.0.2h.orig/ssl/d1_pkt.c
++++ openssl-1.0.2h/ssl/d1_pkt.c
+@@ -194,7 +194,7 @@ static int dtls1_record_needs_buffering(
+ #endif
+ static int dtls1_buffer_record(SSL *s, record_pqueue *q,
+                                unsigned char *priority);
+-static int dtls1_process_record(SSL *s);
++static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
+ 
+ /* copy buffered record into SSL structure */
+ static int dtls1_copy_record(SSL *s, pitem *item)
+@@ -320,13 +320,18 @@ static int dtls1_process_buffered_record
+ {
+     pitem *item;
+     SSL3_BUFFER *rb;
++    SSL3_RECORD *rr;
++    DTLS1_BITMAP *bitmap;
++    unsigned int is_next_epoch;
++    int replayok = 1;
+ 
+     item = pqueue_peek(s->d1->unprocessed_rcds.q);
+     if (item) {
+         /* Check if epoch is current. */
+         if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
+-            return (1);         /* Nothing to do. */
++            return 1;         /* Nothing to do. */
+ 
++        rr = &s->s3->rrec;
+         rb = &s->s3->rbuf;
+ 
+         if (rb->left > 0) {
+@@ -343,11 +348,41 @@ static int dtls1_process_buffered_record
+         /* Process all the records. */
+         while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
+             dtls1_get_unprocessed_record(s);
+-            if (!dtls1_process_record(s))
+-                return (0);
++            bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
++            if (bitmap == NULL) {
++                /*
++                 * Should not happen. This will only ever be NULL when the
++                 * current record is from a different epoch. But that cannot
++                 * be the case because we already checked the epoch above
++                 */
++                 SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
++                        ERR_R_INTERNAL_ERROR);
++                 return 0;
++            }
++#ifndef OPENSSL_NO_SCTP
++            /* Only do replay check if no SCTP bio */
++            if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
++#endif
++            {
++                /*
++                 * Check whether this is a repeat, or aged record. We did this
++                 * check once already when we first received the record - but
++                 * we might have updated the window since then due to
++                 * records we subsequently processed.
++                 */
++                replayok = dtls1_record_replay_check(s, bitmap);
++            }
++
++            if (!replayok || !dtls1_process_record(s, bitmap)) {
++                /* dump this record */
++                rr->length = 0;
++                s->packet_length = 0;
++                continue;
++            }
++
+             if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
+                                     s->s3->rrec.seq_num) < 0)
+-                return -1;
++                return 0;
+         }
+     }
+ 
+@@ -358,7 +393,7 @@ static int dtls1_process_buffered_record
+     s->d1->processed_rcds.epoch = s->d1->r_epoch;
+     s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
+ 
+-    return (1);
++    return 1;
+ }
+ 
+ #if 0
+@@ -405,7 +440,7 @@ static int dtls1_get_buffered_record(SSL
+ 
+ #endif
+ 
+-static int dtls1_process_record(SSL *s)
++static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
+ {
+     int i, al;
+     int enc_err;
+@@ -565,6 +600,10 @@ static int dtls1_process_record(SSL *s)
+ 
+     /* we have pulled in a full packet so zero things */
+     s->packet_length = 0;
++
++    /* Mark receipt of record. */
++    dtls1_record_bitmap_update(s, bitmap);
++
+     return (1);
+ 
+  f_err:
+@@ -600,7 +639,7 @@ int dtls1_get_record(SSL *s)
+      * The epoch may have changed.  If so, process all the pending records.
+      * This is a non-blocking operation.
+      */
+-    if (dtls1_process_buffered_records(s) < 0)
++    if (!dtls1_process_buffered_records(s))
+         return -1;
+ 
+     /* if we're renegotiating, then there may be buffered records */
+@@ -735,20 +774,17 @@ int dtls1_get_record(SSL *s)
+             if (dtls1_buffer_record
+                 (s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
+                 return -1;
+-            /* Mark receipt of record. */
+-            dtls1_record_bitmap_update(s, bitmap);
+         }
+         rr->length = 0;
+         s->packet_length = 0;
+         goto again;
+     }
+ 
+-    if (!dtls1_process_record(s)) {
++    if (!dtls1_process_record(s, bitmap)) {
+         rr->length = 0;
+         s->packet_length = 0;   /* dump this record */
+         goto again;             /* get another record */
+     }
+-    dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
+ 
+     return (1);
+ 
+Index: openssl-1.0.2h/ssl/ssl.h
+===================================================================
+--- openssl-1.0.2h.orig/ssl/ssl.h
++++ openssl-1.0.2h/ssl/ssl.h
+@@ -2623,6 +2623,7 @@ void ERR_load_SSL_strings(void);
+ # define SSL_F_DTLS1_HEARTBEAT                            305
+ # define SSL_F_DTLS1_OUTPUT_CERT_CHAIN                    255
+ # define SSL_F_DTLS1_PREPROCESS_FRAGMENT                  288
++# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS             404
+ # define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE           256
+ # define SSL_F_DTLS1_PROCESS_RECORD                       257
+ # define SSL_F_DTLS1_READ_BYTES                           258
+Index: openssl-1.0.2h/ssl/ssl_err.c
+===================================================================
+--- openssl-1.0.2h.orig/ssl/ssl_err.c
++++ openssl-1.0.2h/ssl/ssl_err.c
+@@ -1,6 +1,6 @@
+ /* ssl/ssl_err.c */
+ /* ====================================================================
+- * Copyright (c) 1999-2015 The OpenSSL Project.  All rights reserved.
++ * Copyright (c) 1999-2016 The OpenSSL Project.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -93,6 +93,8 @@ static ERR_STRING_DATA SSL_str_functs[]
+     {ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "dtls1_heartbeat"},
+     {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "dtls1_output_cert_chain"},
+     {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"},
++    {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS),
++     "DTLS1_PROCESS_BUFFERED_RECORDS"},
+     {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),
+      "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
+     {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"},
diff --git a/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p3.patch b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p3.patch
new file mode 100644
index 0000000..a752f89
--- /dev/null
+++ b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p3.patch
@@ -0,0 +1,30 @@
+From 26aebca74e38ae09f673c2045cc8e2ef762d265a Mon Sep 17 00:00:00 2001
+From: Matt Caswell <matt at openssl.org>
+Date: Wed, 17 Aug 2016 17:55:36 +0100
+Subject: [PATCH] Update function error code
+
+A function error code needed updating due to merge issues.
+
+Reviewed-by: Richard Levitte <levitte at openssl.org>
+
+Upstream-Status: Backport
+CVE: CVE-2016-2181 patch 3
+Signed-off-by: Armin Kuster <akuster at mvista.com>
+
+---
+ ssl/ssl.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: openssl-1.0.2h/ssl/ssl.h
+===================================================================
+--- openssl-1.0.2h.orig/ssl/ssl.h
++++ openssl-1.0.2h/ssl/ssl.h
+@@ -2623,7 +2623,7 @@ void ERR_load_SSL_strings(void);
+ # define SSL_F_DTLS1_HEARTBEAT                            305
+ # define SSL_F_DTLS1_OUTPUT_CERT_CHAIN                    255
+ # define SSL_F_DTLS1_PREPROCESS_FRAGMENT                  288
+-# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS             404
++# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS             424
+ # define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE           256
+ # define SSL_F_DTLS1_PROCESS_RECORD                       257
+ # define SSL_F_DTLS1_READ_BYTES                           258
diff --git a/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb b/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb
index 764f1a2..d97b771 100644
--- a/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb
+++ b/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb
@@ -41,6 +41,9 @@ SRC_URI += "file://configure-targets.patch \
             file://CVE-2016-2177.patch \
             file://CVE-2016-2178.patch \
             file://CVE-2016-2180.patch \
+            file://CVE-2016-2181_p1.patch \
+            file://CVE-2016-2181_p2.patch \
+            file://CVE-2016-2181_p3.patch \
            "
 
 SRC_URI[md5sum] = "9392e65072ce4b614c1392eefc1f23d0"

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


More information about the Openembedded-commits mailing list