diff options
Diffstat (limited to 'meta/recipes-connectivity')
-rw-r--r-- | meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch | 255 | ||||
-rw-r--r-- | meta/recipes-connectivity/openssl/openssl_1.0.2h.bb | 1 |
2 files changed, 256 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch new file mode 100644 index 0000000000..d1cf7f8c34 --- /dev/null +++ b/meta/recipes-connectivity/openssl/openssl/CVE-2016-2179.patch | |||
@@ -0,0 +1,255 @@ | |||
1 | From 00a4c1421407b6ac796688871b0a49a179c694d9 Mon Sep 17 00:00:00 2001 | ||
2 | From: Matt Caswell <matt@openssl.org> | ||
3 | Date: Thu, 30 Jun 2016 13:17:08 +0100 | ||
4 | Subject: [PATCH] Fix DTLS buffered message DoS attack | ||
5 | |||
6 | DTLS can handle out of order record delivery. Additionally since | ||
7 | handshake messages can be bigger than will fit into a single packet, the | ||
8 | messages can be fragmented across multiple records (as with normal TLS). | ||
9 | That means that the messages can arrive mixed up, and we have to | ||
10 | reassemble them. We keep a queue of buffered messages that are "from the | ||
11 | future", i.e. messages we're not ready to deal with yet but have arrived | ||
12 | early. The messages held there may not be full yet - they could be one | ||
13 | or more fragments that are still in the process of being reassembled. | ||
14 | |||
15 | The code assumes that we will eventually complete the reassembly and | ||
16 | when that occurs the complete message is removed from the queue at the | ||
17 | point that we need to use it. | ||
18 | |||
19 | However, DTLS is also tolerant of packet loss. To get around that DTLS | ||
20 | messages can be retransmitted. If we receive a full (non-fragmented) | ||
21 | message from the peer after previously having received a fragment of | ||
22 | that message, then we ignore the message in the queue and just use the | ||
23 | non-fragmented version. At that point the queued message will never get | ||
24 | removed. | ||
25 | |||
26 | Additionally the peer could send "future" messages that we never get to | ||
27 | in order to complete the handshake. Each message has a sequence number | ||
28 | (starting from 0). We will accept a message fragment for the current | ||
29 | message sequence number, or for any sequence up to 10 into the future. | ||
30 | However if the Finished message has a sequence number of 2, anything | ||
31 | greater than that in the queue is just left there. | ||
32 | |||
33 | So, in those two ways we can end up with "orphaned" data in the queue | ||
34 | that will never get removed - except when the connection is closed. At | ||
35 | that point all the queues are flushed. | ||
36 | |||
37 | An attacker could seek to exploit this by filling up the queues with | ||
38 | lots of large messages that are never going to be used in order to | ||
39 | attempt a DoS by memory exhaustion. | ||
40 | |||
41 | I will assume that we are only concerned with servers here. It does not | ||
42 | seem reasonable to be concerned about a memory exhaustion attack on a | ||
43 | client. They are unlikely to process enough connections for this to be | ||
44 | an issue. | ||
45 | |||
46 | A "long" handshake with many messages might be 5 messages long (in the | ||
47 | incoming direction), e.g. ClientHello, Certificate, ClientKeyExchange, | ||
48 | CertificateVerify, Finished. So this would be message sequence numbers 0 | ||
49 | to 4. Additionally we can buffer up to 10 messages in the future. | ||
50 | Therefore the maximum number of messages that an attacker could send | ||
51 | that could get orphaned would typically be 15. | ||
52 | |||
53 | The maximum size that a DTLS message is allowed to be is defined by | ||
54 | max_cert_list, which by default is 100k. Therefore the maximum amount of | ||
55 | "orphaned" memory per connection is 1500k. | ||
56 | |||
57 | Message sequence numbers get reset after the Finished message, so | ||
58 | renegotiation will not extend the maximum number of messages that can be | ||
59 | orphaned per connection. | ||
60 | |||
61 | As noted above, the queues do get cleared when the connection is closed. | ||
62 | Therefore in order to mount an effective attack, an attacker would have | ||
63 | to open many simultaneous connections. | ||
64 | |||
65 | Issue reported by Quan Luo. | ||
66 | |||
67 | CVE-2016-2179 | ||
68 | |||
69 | Reviewed-by: Richard Levitte <levitte@openssl.org> | ||
70 | |||
71 | Upstream-Status: Backport | ||
72 | CVE: CVE-2106-2179 | ||
73 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
74 | |||
75 | --- | ||
76 | ssl/d1_both.c | 32 ++++++++++++++++---------------- | ||
77 | ssl/d1_clnt.c | 1 + | ||
78 | ssl/d1_lib.c | 37 ++++++++++++++++++++++++++----------- | ||
79 | ssl/d1_srvr.c | 3 ++- | ||
80 | ssl/ssl_locl.h | 3 ++- | ||
81 | 5 files changed, 47 insertions(+), 29 deletions(-) | ||
82 | |||
83 | Index: openssl-1.0.2h/ssl/d1_both.c | ||
84 | =================================================================== | ||
85 | --- openssl-1.0.2h.orig/ssl/d1_both.c | ||
86 | +++ openssl-1.0.2h/ssl/d1_both.c | ||
87 | @@ -618,11 +618,23 @@ static int dtls1_retrieve_buffered_fragm | ||
88 | int al; | ||
89 | |||
90 | *ok = 0; | ||
91 | - item = pqueue_peek(s->d1->buffered_messages); | ||
92 | - if (item == NULL) | ||
93 | - return 0; | ||
94 | + do { | ||
95 | + item = pqueue_peek(s->d1->buffered_messages); | ||
96 | + if (item == NULL) | ||
97 | + return 0; | ||
98 | + | ||
99 | + frag = (hm_fragment *)item->data; | ||
100 | + | ||
101 | + if (frag->msg_header.seq < s->d1->handshake_read_seq) { | ||
102 | + /* This is a stale message that has been buffered so clear it */ | ||
103 | + pqueue_pop(s->d1->buffered_messages); | ||
104 | + dtls1_hm_fragment_free(frag); | ||
105 | + pitem_free(item); | ||
106 | + item = NULL; | ||
107 | + frag = NULL; | ||
108 | + } | ||
109 | + } while (item == NULL); | ||
110 | |||
111 | - frag = (hm_fragment *)item->data; | ||
112 | |||
113 | /* Don't return if reassembly still in progress */ | ||
114 | if (frag->reassembly != NULL) | ||
115 | @@ -1296,18 +1308,6 @@ dtls1_retransmit_message(SSL *s, unsigne | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | -/* call this function when the buffered messages are no longer needed */ | ||
120 | -void dtls1_clear_record_buffer(SSL *s) | ||
121 | -{ | ||
122 | - pitem *item; | ||
123 | - | ||
124 | - for (item = pqueue_pop(s->d1->sent_messages); | ||
125 | - item != NULL; item = pqueue_pop(s->d1->sent_messages)) { | ||
126 | - dtls1_hm_fragment_free((hm_fragment *)item->data); | ||
127 | - pitem_free(item); | ||
128 | - } | ||
129 | -} | ||
130 | - | ||
131 | unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p, | ||
132 | unsigned char mt, unsigned long len, | ||
133 | unsigned long frag_off, | ||
134 | Index: openssl-1.0.2h/ssl/d1_clnt.c | ||
135 | =================================================================== | ||
136 | --- openssl-1.0.2h.orig/ssl/d1_clnt.c | ||
137 | +++ openssl-1.0.2h/ssl/d1_clnt.c | ||
138 | @@ -769,6 +769,7 @@ int dtls1_connect(SSL *s) | ||
139 | /* done with handshaking */ | ||
140 | s->d1->handshake_read_seq = 0; | ||
141 | s->d1->next_handshake_write_seq = 0; | ||
142 | + dtls1_clear_received_buffer(s); | ||
143 | goto end; | ||
144 | /* break; */ | ||
145 | |||
146 | Index: openssl-1.0.2h/ssl/d1_lib.c | ||
147 | =================================================================== | ||
148 | --- openssl-1.0.2h.orig/ssl/d1_lib.c | ||
149 | +++ openssl-1.0.2h/ssl/d1_lib.c | ||
150 | @@ -170,7 +170,6 @@ int dtls1_new(SSL *s) | ||
151 | static void dtls1_clear_queues(SSL *s) | ||
152 | { | ||
153 | pitem *item = NULL; | ||
154 | - hm_fragment *frag = NULL; | ||
155 | DTLS1_RECORD_DATA *rdata; | ||
156 | |||
157 | while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) { | ||
158 | @@ -191,28 +190,44 @@ static void dtls1_clear_queues(SSL *s) | ||
159 | pitem_free(item); | ||
160 | } | ||
161 | |||
162 | + while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) { | ||
163 | + rdata = (DTLS1_RECORD_DATA *)item->data; | ||
164 | + if (rdata->rbuf.buf) { | ||
165 | + OPENSSL_free(rdata->rbuf.buf); | ||
166 | + } | ||
167 | + OPENSSL_free(item->data); | ||
168 | + pitem_free(item); | ||
169 | + } | ||
170 | + | ||
171 | + dtls1_clear_received_buffer(s); | ||
172 | + dtls1_clear_sent_buffer(s); | ||
173 | +} | ||
174 | + | ||
175 | +void dtls1_clear_received_buffer(SSL *s) | ||
176 | +{ | ||
177 | + pitem *item = NULL; | ||
178 | + hm_fragment *frag = NULL; | ||
179 | + | ||
180 | while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) { | ||
181 | frag = (hm_fragment *)item->data; | ||
182 | dtls1_hm_fragment_free(frag); | ||
183 | pitem_free(item); | ||
184 | } | ||
185 | +} | ||
186 | + | ||
187 | +void dtls1_clear_sent_buffer(SSL *s) | ||
188 | +{ | ||
189 | + pitem *item = NULL; | ||
190 | + hm_fragment *frag = NULL; | ||
191 | |||
192 | while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) { | ||
193 | frag = (hm_fragment *)item->data; | ||
194 | dtls1_hm_fragment_free(frag); | ||
195 | pitem_free(item); | ||
196 | } | ||
197 | - | ||
198 | - while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) { | ||
199 | - rdata = (DTLS1_RECORD_DATA *)item->data; | ||
200 | - if (rdata->rbuf.buf) { | ||
201 | - OPENSSL_free(rdata->rbuf.buf); | ||
202 | - } | ||
203 | - OPENSSL_free(item->data); | ||
204 | - pitem_free(item); | ||
205 | - } | ||
206 | } | ||
207 | |||
208 | + | ||
209 | void dtls1_free(SSL *s) | ||
210 | { | ||
211 | ssl3_free(s); | ||
212 | @@ -456,7 +471,7 @@ void dtls1_stop_timer(SSL *s) | ||
213 | BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, | ||
214 | &(s->d1->next_timeout)); | ||
215 | /* Clear retransmission buffer */ | ||
216 | - dtls1_clear_record_buffer(s); | ||
217 | + dtls1_clear_sent_buffer(s); | ||
218 | } | ||
219 | |||
220 | int dtls1_check_timeout_num(SSL *s) | ||
221 | Index: openssl-1.0.2h/ssl/d1_srvr.c | ||
222 | =================================================================== | ||
223 | --- openssl-1.0.2h.orig/ssl/d1_srvr.c | ||
224 | +++ openssl-1.0.2h/ssl/d1_srvr.c | ||
225 | @@ -313,7 +313,7 @@ int dtls1_accept(SSL *s) | ||
226 | case SSL3_ST_SW_HELLO_REQ_B: | ||
227 | |||
228 | s->shutdown = 0; | ||
229 | - dtls1_clear_record_buffer(s); | ||
230 | + dtls1_clear_sent_buffer(s); | ||
231 | dtls1_start_timer(s); | ||
232 | ret = ssl3_send_hello_request(s); | ||
233 | if (ret <= 0) | ||
234 | @@ -894,6 +894,7 @@ int dtls1_accept(SSL *s) | ||
235 | /* next message is server hello */ | ||
236 | s->d1->handshake_write_seq = 0; | ||
237 | s->d1->next_handshake_write_seq = 0; | ||
238 | + dtls1_clear_received_buffer(s); | ||
239 | goto end; | ||
240 | /* break; */ | ||
241 | |||
242 | Index: openssl-1.0.2h/ssl/ssl_locl.h | ||
243 | =================================================================== | ||
244 | --- openssl-1.0.2h.orig/ssl/ssl_locl.h | ||
245 | +++ openssl-1.0.2h/ssl/ssl_locl.h | ||
246 | @@ -1242,7 +1242,8 @@ int dtls1_retransmit_message(SSL *s, uns | ||
247 | unsigned long frag_off, int *found); | ||
248 | int dtls1_get_queue_priority(unsigned short seq, int is_ccs); | ||
249 | int dtls1_retransmit_buffered_messages(SSL *s); | ||
250 | -void dtls1_clear_record_buffer(SSL *s); | ||
251 | +void dtls1_clear_received_buffer(SSL *s); | ||
252 | +void dtls1_clear_sent_buffer(SSL *s); | ||
253 | void dtls1_get_message_header(unsigned char *data, | ||
254 | struct hm_header_st *msg_hdr); | ||
255 | void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr); | ||
diff --git a/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb b/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb index 2aea8d9fdc..94a986775c 100644 --- a/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb +++ b/meta/recipes-connectivity/openssl/openssl_1.0.2h.bb | |||
@@ -49,6 +49,7 @@ SRC_URI += "file://configure-targets.patch \ | |||
49 | file://CVE-2016-6303.patch \ | 49 | file://CVE-2016-6303.patch \ |
50 | file://CVE-2016-6304.patch \ | 50 | file://CVE-2016-6304.patch \ |
51 | file://CVE-2016-6306.patch \ | 51 | file://CVE-2016-6306.patch \ |
52 | file://CVE-2016-2179.patch \ | ||
52 | " | 53 | " |
53 | 54 | ||
54 | SRC_URI[md5sum] = "9392e65072ce4b614c1392eefc1f23d0" | 55 | SRC_URI[md5sum] = "9392e65072ce4b614c1392eefc1f23d0" |