Skip to content

Commit 1250f12

Browse files
committed
Fix DTLS handshake message size checks.
In |dtls1_reassemble_fragment|, the value of |msg_hdr->frag_off+frag_len| was being checked against the maximum handshake message size, but then |msg_len| bytes were allocated for the fragment buffer. This means that so long as the fragment was within the allowed size, the pending handshake message could consume 16MB + 2MB (for the reassembly bitmap). Approx 10 outstanding handshake messages are allowed, meaning that an attacker could consume ~180MB per DTLS connection. In the non-fragmented path (in |dtls1_process_out_of_seq_message|), no check was applied. Fixes CVE-2014-3506 Wholly based on patch by Adam Langley with one minor amendment. Reviewed-by: Emilia Käsper <emilia@openssl.org>
1 parent 11e7982 commit 1250f12

File tree

1 file changed

+16
-13
lines changed

1 file changed

+16
-13
lines changed

Diff for: ssl/d1_both.c

+16-13
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,16 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
592592
return 0;
593593
}
594594

595+
/* dtls1_max_handshake_message_len returns the maximum number of bytes
596+
* permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
597+
* be greater if the maximum certificate list size requires it. */
598+
static unsigned long dtls1_max_handshake_message_len(const SSL *s)
599+
{
600+
unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
601+
if (max_len < (unsigned long)s->max_cert_list)
602+
return s->max_cert_list;
603+
return max_len;
604+
}
595605

596606
static int
597607
dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
@@ -600,20 +610,10 @@ dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
600610
pitem *item = NULL;
601611
int i = -1, is_complete;
602612
unsigned char seq64be[8];
603-
unsigned long frag_len = msg_hdr->frag_len, max_len;
604-
605-
if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
606-
goto err;
607-
608-
/* Determine maximum allowed message size. Depends on (user set)
609-
* maximum certificate length, but 16k is minimum.
610-
*/
611-
if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
612-
max_len = s->max_cert_list;
613-
else
614-
max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
613+
unsigned long frag_len = msg_hdr->frag_len;
615614

616-
if ((msg_hdr->frag_off+frag_len) > max_len)
615+
if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
616+
msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
617617
goto err;
618618

619619
/* Try to find item in queue */
@@ -754,6 +754,9 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
754754
if (frag_len && frag_len < msg_hdr->msg_len)
755755
return dtls1_reassemble_fragment(s, msg_hdr, ok);
756756

757+
if (frag_len > dtls1_max_handshake_message_len(s))
758+
goto err;
759+
757760
frag = dtls1_hm_fragment_new(frag_len, 0);
758761
if ( frag == NULL)
759762
goto err;

0 commit comments

Comments
 (0)