mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 21:09:03 +02:00
openssl: Security fix CVE-2016-2179
affects openssl < 1.0.2i (From OE-Core rev: 31e8b48da540d357ac0e7ac17ff41d7eadf4f963) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
a37112a3bc
commit
9e1ca0ba84
255
meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch
Normal file
255
meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
From 00a4c1421407b6ac796688871b0a49a179c694d9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@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@openssl.org>
|
||||||
|
|
||||||
|
Upstream-Status: Backport
|
||||||
|
CVE: CVE-2106-2179
|
||||||
|
Signed-off-by: Armin Kuster <akuster@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);
|
|
@ -49,6 +49,7 @@ SRC_URI += "file://configure-targets.patch \
|
||||||
file://CVE-2016-6303.patch \
|
file://CVE-2016-6303.patch \
|
||||||
file://CVE-2016-6304.patch \
|
file://CVE-2016-6304.patch \
|
||||||
file://CVE-2016-6306.patch \
|
file://CVE-2016-6306.patch \
|
||||||
|
file://CVE-2016-2179.patch \
|
||||||
"
|
"
|
||||||
|
|
||||||
SRC_URI[md5sum] = "9392e65072ce4b614c1392eefc1f23d0"
|
SRC_URI[md5sum] = "9392e65072ce4b614c1392eefc1f23d0"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user