From f0e2e3d84763477138d902f7d48ac2658266aa2b Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Mon, 26 Sep 2016 12:18:17 +0200 Subject: openssl: Security fix CVE-2016-2181 affects openssl < 1.0.2i Reference: https://www.openssl.org/news/secadv/20160922.txt Signed-off-by: Armin Kuster Signed-off-by: Sona Sarmadi Signed-off-by: Adrian Dudau --- .../openssl/openssl/CVE-2016-2181_p1.patch | 91 ++++++++ .../openssl/openssl/CVE-2016-2181_p2.patch | 239 +++++++++++++++++++++ .../openssl/openssl/CVE-2016-2181_p3.patch | 30 +++ .../openssl/openssl_1.0.2h.bbappend | 3 + 4 files changed, 363 insertions(+) create mode 100644 recipes-connectivity/openssl/openssl/CVE-2016-2181_p1.patch create mode 100644 recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch create mode 100644 recipes-connectivity/openssl/openssl/CVE-2016-2181_p3.patch diff --git a/recipes-connectivity/openssl/openssl/CVE-2016-2181_p1.patch b/recipes-connectivity/openssl/openssl/CVE-2016-2181_p1.patch new file mode 100644 index 0000000..9149dbe --- /dev/null +++ b/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 +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 + +Upstream-Status: Backport +CVE: CVE-2016-2180 patch 1 +Signed-off-by: Armin Kuster + +--- + 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/recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch b/recipes-connectivity/openssl/openssl/CVE-2016-2181_p2.patch new file mode 100644 index 0000000..ecf138a --- /dev/null +++ b/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 +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 + + +Reviewed-by: Richard Levitte +--- + 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/recipes-connectivity/openssl/openssl/CVE-2016-2181_p3.patch b/recipes-connectivity/openssl/openssl/CVE-2016-2181_p3.patch new file mode 100644 index 0000000..a752f89 --- /dev/null +++ b/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 +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 + +Upstream-Status: Backport +CVE: CVE-2016-2181 patch 3 +Signed-off-by: Armin Kuster + +--- + 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/recipes-connectivity/openssl/openssl_1.0.2h.bbappend b/recipes-connectivity/openssl/openssl_1.0.2h.bbappend index ff2aa45..196dc50 100644 --- a/recipes-connectivity/openssl/openssl_1.0.2h.bbappend +++ b/recipes-connectivity/openssl/openssl_1.0.2h.bbappend @@ -3,4 +3,7 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" SRC_URI += "file://CVE-2016-2178.patch \ file://CVE-2016-2179.patch \ file://CVE-2016-2180.patch \ + file://CVE-2016-2181_p1.patch \ + file://CVE-2016-2181_p2.patch \ + file://CVE-2016-2181_p3.patch \ " -- cgit v1.2.3-54-g00ecf