mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 21:09:03 +02:00
openssl: Security fix CVE-2016-2181
affects openssl < 1.0.1i (From OE-Core rev: c3d4cc8e452b29d4ca620b5c93d22a88c5aa1f03) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
766c5ced75
commit
dc61ec5f0c
|
@ -0,0 +1,91 @@
|
||||||
|
From 20744f6b40b5ded059a848f66d6ba922f2a62eb3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@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@openssl.org>
|
||||||
|
|
||||||
|
Upstream-Status: Backport
|
||||||
|
CVE: CVE-2016-2180 patch 1
|
||||||
|
Signed-off-by: Armin Kuster <akuster@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
|
||||||
|
|
239
meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch
Normal file
239
meta/recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
From 3884b47b7c255c2e94d9b387ee83c7e8bb981258 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@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@mvista.com>
|
||||||
|
|
||||||
|
|
||||||
|
Reviewed-by: Richard Levitte <levitte@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"},
|
|
@ -0,0 +1,30 @@
|
||||||
|
From 26aebca74e38ae09f673c2045cc8e2ef762d265a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@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@openssl.org>
|
||||||
|
|
||||||
|
Upstream-Status: Backport
|
||||||
|
CVE: CVE-2016-2181 patch 3
|
||||||
|
Signed-off-by: Armin Kuster <akuster@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
|
|
@ -41,6 +41,9 @@ SRC_URI += "file://configure-targets.patch \
|
||||||
file://CVE-2016-2177.patch \
|
file://CVE-2016-2177.patch \
|
||||||
file://CVE-2016-2178.patch \
|
file://CVE-2016-2178.patch \
|
||||||
file://CVE-2016-2180.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"
|
SRC_URI[md5sum] = "9392e65072ce4b614c1392eefc1f23d0"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user