|
|
1b2890 |
From fc7804ec392fcf8051abe6bc9da9108744d2ae35 Mon Sep 17 00:00:00 2001
|
|
|
1b2890 |
From: Matt Caswell <matt@openssl.org>
|
|
|
1b2890 |
Date: Fri, 6 Jun 2014 14:25:52 -0700
|
|
|
1b2890 |
Subject: [PATCH] Fix DTLS handshake message size checks.
|
|
|
1b2890 |
MIME-Version: 1.0
|
|
|
1b2890 |
Content-Type: text/plain; charset=UTF-8
|
|
|
1b2890 |
Content-Transfer-Encoding: 8bit
|
|
|
1b2890 |
|
|
|
1b2890 |
In |dtls1_reassemble_fragment|, the value of
|
|
|
1b2890 |
|msg_hdr->frag_off+frag_len| was being checked against the maximum
|
|
|
1b2890 |
handshake message size, but then |msg_len| bytes were allocated for the
|
|
|
1b2890 |
fragment buffer. This means that so long as the fragment was within the
|
|
|
1b2890 |
allowed size, the pending handshake message could consume 16MB + 2MB
|
|
|
1b2890 |
(for the reassembly bitmap). Approx 10 outstanding handshake messages
|
|
|
1b2890 |
are allowed, meaning that an attacker could consume ~180MB per DTLS
|
|
|
1b2890 |
connection.
|
|
|
1b2890 |
|
|
|
1b2890 |
In the non-fragmented path (in |dtls1_process_out_of_seq_message|), no
|
|
|
1b2890 |
check was applied.
|
|
|
1b2890 |
|
|
|
1b2890 |
Fixes CVE-2014-3506
|
|
|
1b2890 |
|
|
|
1b2890 |
Wholly based on patch by Adam Langley with one minor amendment.
|
|
|
1b2890 |
|
|
|
1b2890 |
Reviewed-by: Emilia Käsper <emilia@openssl.org>
|
|
|
1b2890 |
---
|
|
|
1b2890 |
ssl/d1_both.c | 29 ++++++++++++++++-------------
|
|
|
1b2890 |
1 file changed, 16 insertions(+), 13 deletions(-)
|
|
|
1b2890 |
|
|
|
1b2890 |
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
|
|
|
1b2890 |
index 6559dfc..b9e15df 100644
|
|
|
1b2890 |
--- a/ssl/d1_both.c
|
|
|
1b2890 |
+++ b/ssl/d1_both.c
|
|
|
1b2890 |
@@ -587,6 +587,16 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
|
|
|
1b2890 |
return 0;
|
|
|
1b2890 |
}
|
|
|
1b2890 |
|
|
|
1b2890 |
+/* dtls1_max_handshake_message_len returns the maximum number of bytes
|
|
|
1b2890 |
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
|
|
|
1b2890 |
+ * be greater if the maximum certificate list size requires it. */
|
|
|
1b2890 |
+static unsigned long dtls1_max_handshake_message_len(const SSL *s)
|
|
|
1b2890 |
+ {
|
|
|
1b2890 |
+ unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
|
|
|
1b2890 |
+ if (max_len < (unsigned long)s->max_cert_list)
|
|
|
1b2890 |
+ return s->max_cert_list;
|
|
|
1b2890 |
+ return max_len;
|
|
|
1b2890 |
+ }
|
|
|
1b2890 |
|
|
|
1b2890 |
static int
|
|
|
1b2890 |
dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
|
|
|
1b2890 |
@@ -595,20 +605,10 @@ dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
|
|
|
1b2890 |
pitem *item = NULL;
|
|
|
1b2890 |
int i = -1, is_complete;
|
|
|
1b2890 |
unsigned char seq64be[8];
|
|
|
1b2890 |
- unsigned long frag_len = msg_hdr->frag_len, max_len;
|
|
|
1b2890 |
-
|
|
|
1b2890 |
- if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
|
|
|
1b2890 |
- goto err;
|
|
|
1b2890 |
-
|
|
|
1b2890 |
- /* Determine maximum allowed message size. Depends on (user set)
|
|
|
1b2890 |
- * maximum certificate length, but 16k is minimum.
|
|
|
1b2890 |
- */
|
|
|
1b2890 |
- if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
|
|
|
1b2890 |
- max_len = s->max_cert_list;
|
|
|
1b2890 |
- else
|
|
|
1b2890 |
- max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
|
|
|
1b2890 |
+ unsigned long frag_len = msg_hdr->frag_len;
|
|
|
1b2890 |
|
|
|
1b2890 |
- if ((msg_hdr->frag_off+frag_len) > max_len)
|
|
|
1b2890 |
+ if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
|
|
|
1b2890 |
+ msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
|
|
|
1b2890 |
goto err;
|
|
|
1b2890 |
|
|
|
1b2890 |
/* Try to find item in queue */
|
|
|
1b2890 |
@@ -749,6 +749,9 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
|
|
|
1b2890 |
if (frag_len && frag_len < msg_hdr->msg_len)
|
|
|
1b2890 |
return dtls1_reassemble_fragment(s, msg_hdr, ok);
|
|
|
1b2890 |
|
|
|
1b2890 |
+ if (frag_len > dtls1_max_handshake_message_len(s))
|
|
|
1b2890 |
+ goto err;
|
|
|
1b2890 |
+
|
|
|
1b2890 |
frag = dtls1_hm_fragment_new(frag_len, 0);
|
|
|
1b2890 |
if ( frag == NULL)
|
|
|
1b2890 |
goto err;
|
|
|
1b2890 |
--
|
|
|
1b2890 |
1.8.3.1
|
|
|
1b2890 |
|