GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: d1_both.c,v 1.52 2017/10/08 16:24:02 jsing Exp $ */ |
||
2 |
/* |
||
3 |
* DTLS implementation written by Nagendra Modadugu |
||
4 |
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005. |
||
5 |
*/ |
||
6 |
/* ==================================================================== |
||
7 |
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. |
||
8 |
* |
||
9 |
* Redistribution and use in source and binary forms, with or without |
||
10 |
* modification, are permitted provided that the following conditions |
||
11 |
* are met: |
||
12 |
* |
||
13 |
* 1. Redistributions of source code must retain the above copyright |
||
14 |
* notice, this list of conditions and the following disclaimer. |
||
15 |
* |
||
16 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
17 |
* notice, this list of conditions and the following disclaimer in |
||
18 |
* the documentation and/or other materials provided with the |
||
19 |
* distribution. |
||
20 |
* |
||
21 |
* 3. All advertising materials mentioning features or use of this |
||
22 |
* software must display the following acknowledgment: |
||
23 |
* "This product includes software developed by the OpenSSL Project |
||
24 |
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
||
25 |
* |
||
26 |
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
||
27 |
* endorse or promote products derived from this software without |
||
28 |
* prior written permission. For written permission, please contact |
||
29 |
* openssl-core@openssl.org. |
||
30 |
* |
||
31 |
* 5. Products derived from this software may not be called "OpenSSL" |
||
32 |
* nor may "OpenSSL" appear in their names without prior written |
||
33 |
* permission of the OpenSSL Project. |
||
34 |
* |
||
35 |
* 6. Redistributions of any form whatsoever must retain the following |
||
36 |
* acknowledgment: |
||
37 |
* "This product includes software developed by the OpenSSL Project |
||
38 |
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
||
39 |
* |
||
40 |
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
||
41 |
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
42 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||
43 |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
||
44 |
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
45 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||
46 |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
47 |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
48 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||
49 |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
50 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
||
51 |
* OF THE POSSIBILITY OF SUCH DAMAGE. |
||
52 |
* ==================================================================== |
||
53 |
* |
||
54 |
* This product includes cryptographic software written by Eric Young |
||
55 |
* (eay@cryptsoft.com). This product includes software written by Tim |
||
56 |
* Hudson (tjh@cryptsoft.com). |
||
57 |
* |
||
58 |
*/ |
||
59 |
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
||
60 |
* All rights reserved. |
||
61 |
* |
||
62 |
* This package is an SSL implementation written |
||
63 |
* by Eric Young (eay@cryptsoft.com). |
||
64 |
* The implementation was written so as to conform with Netscapes SSL. |
||
65 |
* |
||
66 |
* This library is free for commercial and non-commercial use as long as |
||
67 |
* the following conditions are aheared to. The following conditions |
||
68 |
* apply to all code found in this distribution, be it the RC4, RSA, |
||
69 |
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||
70 |
* included with this distribution is covered by the same copyright terms |
||
71 |
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||
72 |
* |
||
73 |
* Copyright remains Eric Young's, and as such any Copyright notices in |
||
74 |
* the code are not to be removed. |
||
75 |
* If this package is used in a product, Eric Young should be given attribution |
||
76 |
* as the author of the parts of the library used. |
||
77 |
* This can be in the form of a textual message at program startup or |
||
78 |
* in documentation (online or textual) provided with the package. |
||
79 |
* |
||
80 |
* Redistribution and use in source and binary forms, with or without |
||
81 |
* modification, are permitted provided that the following conditions |
||
82 |
* are met: |
||
83 |
* 1. Redistributions of source code must retain the copyright |
||
84 |
* notice, this list of conditions and the following disclaimer. |
||
85 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
86 |
* notice, this list of conditions and the following disclaimer in the |
||
87 |
* documentation and/or other materials provided with the distribution. |
||
88 |
* 3. All advertising materials mentioning features or use of this software |
||
89 |
* must display the following acknowledgement: |
||
90 |
* "This product includes cryptographic software written by |
||
91 |
* Eric Young (eay@cryptsoft.com)" |
||
92 |
* The word 'cryptographic' can be left out if the rouines from the library |
||
93 |
* being used are not cryptographic related :-). |
||
94 |
* 4. If you include any Windows specific code (or a derivative thereof) from |
||
95 |
* the apps directory (application code) you must include an acknowledgement: |
||
96 |
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||
97 |
* |
||
98 |
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||
99 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
100 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
101 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||
102 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
103 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
104 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
105 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
106 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
107 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
108 |
* SUCH DAMAGE. |
||
109 |
* |
||
110 |
* The licence and distribution terms for any publically available version or |
||
111 |
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||
112 |
* copied and put under another distribution licence |
||
113 |
* [including the GNU Public Licence.] |
||
114 |
*/ |
||
115 |
|||
116 |
#include <limits.h> |
||
117 |
#include <stdio.h> |
||
118 |
#include <string.h> |
||
119 |
|||
120 |
#include "ssl_locl.h" |
||
121 |
|||
122 |
#include <openssl/buffer.h> |
||
123 |
#include <openssl/evp.h> |
||
124 |
#include <openssl/objects.h> |
||
125 |
#include <openssl/x509.h> |
||
126 |
|||
127 |
#include "pqueue.h" |
||
128 |
#include "bytestring.h" |
||
129 |
|||
130 |
#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8) |
||
131 |
|||
132 |
#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \ |
||
133 |
if ((end) - (start) <= 8) { \ |
||
134 |
long ii; \ |
||
135 |
for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \ |
||
136 |
} else { \ |
||
137 |
long ii; \ |
||
138 |
bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \ |
||
139 |
for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \ |
||
140 |
bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \ |
||
141 |
} } |
||
142 |
|||
143 |
#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ |
||
144 |
long ii; \ |
||
145 |
OPENSSL_assert((msg_len) > 0); \ |
||
146 |
is_complete = 1; \ |
||
147 |
if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \ |
||
148 |
if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \ |
||
149 |
if (bitmask[ii] != 0xff) { is_complete = 0; break; } } |
||
150 |
|||
151 |
static unsigned char bitmask_start_values[] = { |
||
152 |
0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 |
||
153 |
}; |
||
154 |
static unsigned char bitmask_end_values[] = { |
||
155 |
0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f |
||
156 |
}; |
||
157 |
|||
158 |
/* XDTLS: figure out the right values */ |
||
159 |
static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; |
||
160 |
|||
161 |
static unsigned int dtls1_guess_mtu(unsigned int curr_mtu); |
||
162 |
static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, |
||
163 |
unsigned long frag_len); |
||
164 |
static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p); |
||
165 |
static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, |
||
166 |
int *ok); |
||
167 |
|||
168 |
static hm_fragment * |
||
169 |
dtls1_hm_fragment_new(unsigned long frag_len, int reassembly) |
||
170 |
{ |
||
171 |
hm_fragment *frag = NULL; |
||
172 |
unsigned char *buf = NULL; |
||
173 |
unsigned char *bitmask = NULL; |
||
174 |
|||
175 |
834 |
frag = malloc(sizeof(hm_fragment)); |
|
176 |
✗✓ | 417 |
if (frag == NULL) |
177 |
return NULL; |
||
178 |
|||
179 |
✓✗ | 417 |
if (frag_len) { |
180 |
417 |
buf = malloc(frag_len); |
|
181 |
✗✓ | 417 |
if (buf == NULL) { |
182 |
free(frag); |
||
183 |
return NULL; |
||
184 |
} |
||
185 |
} |
||
186 |
|||
187 |
/* zero length fragment gets zero frag->fragment */ |
||
188 |
417 |
frag->fragment = buf; |
|
189 |
|||
190 |
/* Initialize reassembly bitmask if necessary */ |
||
191 |
✓✓ | 417 |
if (reassembly) { |
192 |
24 |
bitmask = malloc(RSMBLY_BITMASK_SIZE(frag_len)); |
|
193 |
✗✓ | 24 |
if (bitmask == NULL) { |
194 |
free(buf); |
||
195 |
free(frag); |
||
196 |
return NULL; |
||
197 |
} |
||
198 |
24 |
memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len)); |
|
199 |
24 |
} |
|
200 |
|||
201 |
417 |
frag->reassembly = bitmask; |
|
202 |
|||
203 |
417 |
return frag; |
|
204 |
417 |
} |
|
205 |
|||
206 |
static void |
||
207 |
dtls1_hm_fragment_free(hm_fragment *frag) |
||
208 |
{ |
||
209 |
✓✗ | 612 |
if (frag == NULL) |
210 |
return; |
||
211 |
|||
212 |
✓✓ | 306 |
if (frag->msg_header.is_ccs) { |
213 |
36 |
EVP_CIPHER_CTX_free( |
|
214 |
36 |
frag->msg_header.saved_retransmit_state.enc_write_ctx); |
|
215 |
36 |
EVP_MD_CTX_destroy( |
|
216 |
36 |
frag->msg_header.saved_retransmit_state.write_hash); |
|
217 |
36 |
} |
|
218 |
306 |
free(frag->fragment); |
|
219 |
306 |
free(frag->reassembly); |
|
220 |
306 |
free(frag); |
|
221 |
612 |
} |
|
222 |
|||
223 |
/* send s->internal->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ |
||
224 |
int |
||
225 |
dtls1_do_write(SSL *s, int type) |
||
226 |
{ |
||
227 |
int ret; |
||
228 |
int curr_mtu; |
||
229 |
unsigned int len, frag_off, mac_size, blocksize; |
||
230 |
|||
231 |
/* AHA! Figure out the MTU, and stick to the right size */ |
||
232 |
✓✓✓✗ |
861 |
if (D1I(s)->mtu < dtls1_min_mtu() && |
233 |
75 |
!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { |
|
234 |
75 |
D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s), |
|
235 |
BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); |
||
236 |
|||
237 |
/* |
||
238 |
* I've seen the kernel return bogus numbers when it |
||
239 |
* doesn't know the MTU (ie., the initial write), so just |
||
240 |
* make sure we have a reasonable number |
||
241 |
*/ |
||
242 |
✓✗ | 75 |
if (D1I(s)->mtu < dtls1_min_mtu()) { |
243 |
75 |
D1I(s)->mtu = 0; |
|
244 |
75 |
D1I(s)->mtu = dtls1_guess_mtu(D1I(s)->mtu); |
|
245 |
150 |
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, |
|
246 |
75 |
D1I(s)->mtu, NULL); |
|
247 |
75 |
} |
|
248 |
} |
||
249 |
|||
250 |
✗✓ | 393 |
OPENSSL_assert(D1I(s)->mtu >= dtls1_min_mtu()); |
251 |
/* should have something reasonable now */ |
||
252 |
|||
253 |
✓✓ | 393 |
if (s->internal->init_off == 0 && type == SSL3_RT_HANDSHAKE) |
254 |
✗✓ | 321 |
OPENSSL_assert(s->internal->init_num == |
255 |
(int)D1I(s)->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); |
||
256 |
|||
257 |
✓✓ | 393 |
if (s->internal->write_hash) |
258 |
72 |
mac_size = EVP_MD_CTX_size(s->internal->write_hash); |
|
259 |
else |
||
260 |
mac_size = 0; |
||
261 |
|||
262 |
✓✓✓✓ |
465 |
if (s->internal->enc_write_ctx && |
263 |
72 |
(EVP_CIPHER_mode( s->internal->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE)) |
|
264 |
60 |
blocksize = 2 * EVP_CIPHER_block_size(s->internal->enc_write_ctx->cipher); |
|
265 |
else |
||
266 |
blocksize = 0; |
||
267 |
|||
268 |
frag_off = 0; |
||
269 |
✓✗ | 852 |
while (s->internal->init_num) { |
270 |
426 |
curr_mtu = D1I(s)->mtu - BIO_wpending(SSL_get_wbio(s)) - |
|
271 |
426 |
DTLS1_RT_HEADER_LENGTH - mac_size - blocksize; |
|
272 |
|||
273 |
✓✓ | 426 |
if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) { |
274 |
/* grr.. we could get an error if MTU picked was wrong */ |
||
275 |
33 |
ret = BIO_flush(SSL_get_wbio(s)); |
|
276 |
✗✓ | 33 |
if (ret <= 0) |
277 |
return ret; |
||
278 |
33 |
curr_mtu = D1I(s)->mtu - DTLS1_RT_HEADER_LENGTH - |
|
279 |
33 |
mac_size - blocksize; |
|
280 |
33 |
} |
|
281 |
|||
282 |
✓✓ | 426 |
if (s->internal->init_num > curr_mtu) |
283 |
33 |
len = curr_mtu; |
|
284 |
else |
||
285 |
len = s->internal->init_num; |
||
286 |
|||
287 |
|||
288 |
/* XDTLS: this function is too long. split out the CCS part */ |
||
289 |
✓✓ | 426 |
if (type == SSL3_RT_HANDSHAKE) { |
290 |
✓✓ | 354 |
if (s->internal->init_off != 0) { |
291 |
✗✓ | 33 |
OPENSSL_assert(s->internal->init_off > DTLS1_HM_HEADER_LENGTH); |
292 |
33 |
s->internal->init_off -= DTLS1_HM_HEADER_LENGTH; |
|
293 |
33 |
s->internal->init_num += DTLS1_HM_HEADER_LENGTH; |
|
294 |
|||
295 |
✓✓ | 33 |
if (s->internal->init_num > curr_mtu) |
296 |
9 |
len = curr_mtu; |
|
297 |
else |
||
298 |
len = s->internal->init_num; |
||
299 |
} |
||
300 |
|||
301 |
708 |
dtls1_fix_message_header(s, frag_off, |
|
302 |
354 |
len - DTLS1_HM_HEADER_LENGTH); |
|
303 |
|||
304 |
354 |
dtls1_write_message_header(s, |
|
305 |
354 |
(unsigned char *)&s->internal->init_buf->data[s->internal->init_off]); |
|
306 |
|||
307 |
✗✓ | 354 |
OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH); |
308 |
} |
||
309 |
|||
310 |
426 |
ret = dtls1_write_bytes(s, type, |
|
311 |
426 |
&s->internal->init_buf->data[s->internal->init_off], len); |
|
312 |
✗✓ | 426 |
if (ret < 0) { |
313 |
/* |
||
314 |
* Might need to update MTU here, but we don't know |
||
315 |
* which previous packet caused the failure -- so |
||
316 |
* can't really retransmit anything. continue as |
||
317 |
* if everything is fine and wait for an alert to |
||
318 |
* handle the retransmit |
||
319 |
*/ |
||
320 |
if (BIO_ctrl(SSL_get_wbio(s), |
||
321 |
BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) |
||
322 |
D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s), |
||
323 |
BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); |
||
324 |
else |
||
325 |
return (-1); |
||
326 |
} else { |
||
327 |
|||
328 |
/* |
||
329 |
* Bad if this assert fails, only part of the |
||
330 |
* handshake message got sent. but why would |
||
331 |
* this happen? |
||
332 |
*/ |
||
333 |
✗✓ | 426 |
OPENSSL_assert(len == (unsigned int)ret); |
334 |
|||
335 |
✓✓✓✗ |
780 |
if (type == SSL3_RT_HANDSHAKE && |
336 |
354 |
!D1I(s)->retransmitting) { |
|
337 |
/* |
||
338 |
* Should not be done for 'Hello Request's, |
||
339 |
* but in that case we'll ignore the result |
||
340 |
* anyway |
||
341 |
*/ |
||
342 |
354 |
unsigned char *p = (unsigned char *)&s->internal->init_buf->data[s->internal->init_off]; |
|
343 |
354 |
const struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
344 |
int xlen; |
||
345 |
|||
346 |
✓✓ | 354 |
if (frag_off == 0) { |
347 |
/* |
||
348 |
* Reconstruct message header is if it |
||
349 |
* is being sent in single fragment |
||
350 |
*/ |
||
351 |
321 |
*p++ = msg_hdr->type; |
|
352 |
321 |
l2n3(msg_hdr->msg_len, p); |
|
353 |
321 |
s2n (msg_hdr->seq, p); |
|
354 |
321 |
l2n3(0, p); |
|
355 |
321 |
l2n3(msg_hdr->msg_len, p); |
|
356 |
321 |
p -= DTLS1_HM_HEADER_LENGTH; |
|
357 |
xlen = ret; |
||
358 |
321 |
} else { |
|
359 |
33 |
p += DTLS1_HM_HEADER_LENGTH; |
|
360 |
33 |
xlen = ret - DTLS1_HM_HEADER_LENGTH; |
|
361 |
} |
||
362 |
|||
363 |
354 |
tls1_finish_mac(s, p, xlen); |
|
364 |
354 |
} |
|
365 |
|||
366 |
✓✓ | 426 |
if (ret == s->internal->init_num) { |
367 |
✗✓ | 393 |
if (s->internal->msg_callback) |
368 |
s->internal->msg_callback(1, s->version, type, |
||
369 |
s->internal->init_buf->data, |
||
370 |
(size_t)(s->internal->init_off + s->internal->init_num), |
||
371 |
s, s->internal->msg_callback_arg); |
||
372 |
|||
373 |
393 |
s->internal->init_off = 0; |
|
374 |
/* done writing this message */ |
||
375 |
393 |
s->internal->init_num = 0; |
|
376 |
|||
377 |
393 |
return (1); |
|
378 |
} |
||
379 |
33 |
s->internal->init_off += ret; |
|
380 |
33 |
s->internal->init_num -= ret; |
|
381 |
33 |
frag_off += (ret -= DTLS1_HM_HEADER_LENGTH); |
|
382 |
} |
||
383 |
} |
||
384 |
return (0); |
||
385 |
393 |
} |
|
386 |
|||
387 |
|||
388 |
/* |
||
389 |
* Obtain handshake message of message type 'mt' (any if mt == -1), |
||
390 |
* maximum acceptable body length 'max'. |
||
391 |
* Read an entire handshake message. Handshake messages arrive in |
||
392 |
* fragments. |
||
393 |
*/ |
||
394 |
long |
||
395 |
dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) |
||
396 |
{ |
||
397 |
int i, al; |
||
398 |
struct hm_header_st *msg_hdr; |
||
399 |
unsigned char *p; |
||
400 |
unsigned long msg_len; |
||
401 |
|||
402 |
/* |
||
403 |
* s3->internal->tmp is used to store messages that are unexpected, caused |
||
404 |
* by the absence of an optional handshake message |
||
405 |
*/ |
||
406 |
✓✓ | 1098 |
if (S3I(s)->tmp.reuse_message) { |
407 |
120 |
S3I(s)->tmp.reuse_message = 0; |
|
408 |
✓✓✗✓ |
180 |
if ((mt >= 0) && (S3I(s)->tmp.message_type != mt)) { |
409 |
al = SSL_AD_UNEXPECTED_MESSAGE; |
||
410 |
SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); |
||
411 |
goto f_err; |
||
412 |
} |
||
413 |
120 |
*ok = 1; |
|
414 |
120 |
s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
415 |
120 |
s->internal->init_num = (int)S3I(s)->tmp.message_size; |
|
416 |
120 |
return s->internal->init_num; |
|
417 |
} |
||
418 |
|||
419 |
429 |
msg_hdr = &D1I(s)->r_msg_hdr; |
|
420 |
429 |
memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); |
|
421 |
|||
422 |
again: |
||
423 |
486 |
i = dtls1_get_message_fragment(s, st1, stn, max, ok); |
|
424 |
✓✓ | 972 |
if (i == DTLS1_HM_BAD_FRAGMENT || |
425 |
486 |
i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ |
|
426 |
57 |
goto again; |
|
427 |
✓✓✓✓ |
576 |
else if (i <= 0 && !*ok) |
428 |
111 |
return i; |
|
429 |
|||
430 |
318 |
p = (unsigned char *)s->internal->init_buf->data; |
|
431 |
318 |
msg_len = msg_hdr->msg_len; |
|
432 |
|||
433 |
/* reconstruct message header */ |
||
434 |
318 |
*(p++) = msg_hdr->type; |
|
435 |
318 |
l2n3(msg_len, p); |
|
436 |
318 |
s2n (msg_hdr->seq, p); |
|
437 |
318 |
l2n3(0, p); |
|
438 |
318 |
l2n3(msg_len, p); |
|
439 |
|||
440 |
318 |
p -= DTLS1_HM_HEADER_LENGTH; |
|
441 |
318 |
msg_len += DTLS1_HM_HEADER_LENGTH; |
|
442 |
|||
443 |
318 |
tls1_finish_mac(s, p, msg_len); |
|
444 |
✗✓ | 318 |
if (s->internal->msg_callback) |
445 |
s->internal->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, msg_len, |
||
446 |
s, s->internal->msg_callback_arg); |
||
447 |
|||
448 |
318 |
memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); |
|
449 |
|||
450 |
/* Don't change sequence numbers while listening */ |
||
451 |
✓✗ | 318 |
if (!D1I(s)->listen) |
452 |
318 |
D1I(s)->handshake_read_seq++; |
|
453 |
|||
454 |
318 |
s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
455 |
318 |
return s->internal->init_num; |
|
456 |
|||
457 |
f_err: |
||
458 |
ssl3_send_alert(s, SSL3_AL_FATAL, al); |
||
459 |
*ok = 0; |
||
460 |
return -1; |
||
461 |
549 |
} |
|
462 |
|||
463 |
|||
464 |
static int |
||
465 |
dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max) |
||
466 |
{ |
||
467 |
size_t frag_off, frag_len, msg_len; |
||
468 |
|||
469 |
636 |
msg_len = msg_hdr->msg_len; |
|
470 |
318 |
frag_off = msg_hdr->frag_off; |
|
471 |
318 |
frag_len = msg_hdr->frag_len; |
|
472 |
|||
473 |
/* sanity checking */ |
||
474 |
✗✓ | 318 |
if ((frag_off + frag_len) > msg_len) { |
475 |
SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
||
476 |
return SSL_AD_ILLEGAL_PARAMETER; |
||
477 |
} |
||
478 |
|||
479 |
✗✓ | 318 |
if ((frag_off + frag_len) > (unsigned long)max) { |
480 |
SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
||
481 |
return SSL_AD_ILLEGAL_PARAMETER; |
||
482 |
} |
||
483 |
|||
484 |
✓✗ | 318 |
if ( D1I(s)->r_msg_hdr.frag_off == 0) /* first fragment */ |
485 |
{ |
||
486 |
/* |
||
487 |
* msg_len is limited to 2^24, but is effectively checked |
||
488 |
* against max above |
||
489 |
*/ |
||
490 |
✗✓ | 636 |
if (!BUF_MEM_grow_clean(s->internal->init_buf, |
491 |
318 |
msg_len + DTLS1_HM_HEADER_LENGTH)) { |
|
492 |
SSLerror(s, ERR_R_BUF_LIB); |
||
493 |
return SSL_AD_INTERNAL_ERROR; |
||
494 |
} |
||
495 |
|||
496 |
318 |
S3I(s)->tmp.message_size = msg_len; |
|
497 |
318 |
D1I(s)->r_msg_hdr.msg_len = msg_len; |
|
498 |
318 |
S3I(s)->tmp.message_type = msg_hdr->type; |
|
499 |
318 |
D1I(s)->r_msg_hdr.type = msg_hdr->type; |
|
500 |
318 |
D1I(s)->r_msg_hdr.seq = msg_hdr->seq; |
|
501 |
✗✗ | 318 |
} else if (msg_len != D1I(s)->r_msg_hdr.msg_len) { |
502 |
/* |
||
503 |
* They must be playing with us! BTW, failure to enforce |
||
504 |
* upper limit would open possibility for buffer overrun. |
||
505 |
*/ |
||
506 |
SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
||
507 |
return SSL_AD_ILLEGAL_PARAMETER; |
||
508 |
} |
||
509 |
|||
510 |
318 |
return 0; /* no error */ |
|
511 |
318 |
} |
|
512 |
|||
513 |
static int |
||
514 |
dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) |
||
515 |
{ |
||
516 |
/* |
||
517 |
* (0) check whether the desired fragment is available |
||
518 |
* if so: |
||
519 |
* (1) copy over the fragment to s->internal->init_buf->data[] |
||
520 |
* (2) update s->internal->init_num |
||
521 |
*/ |
||
522 |
pitem *item; |
||
523 |
hm_fragment *frag; |
||
524 |
int al; |
||
525 |
|||
526 |
972 |
*ok = 0; |
|
527 |
486 |
item = pqueue_peek(D1I(s)->buffered_messages); |
|
528 |
✓✓ | 486 |
if (item == NULL) |
529 |
429 |
return 0; |
|
530 |
|||
531 |
57 |
frag = (hm_fragment *)item->data; |
|
532 |
|||
533 |
/* Don't return if reassembly still in progress */ |
||
534 |
✓✓ | 57 |
if (frag->reassembly != NULL) |
535 |
33 |
return 0; |
|
536 |
|||
537 |
✓✗ | 24 |
if (D1I(s)->handshake_read_seq == frag->msg_header.seq) { |
538 |
24 |
unsigned long frag_len = frag->msg_header.frag_len; |
|
539 |
24 |
pqueue_pop(D1I(s)->buffered_messages); |
|
540 |
|||
541 |
24 |
al = dtls1_preprocess_fragment(s, &frag->msg_header, max); |
|
542 |
|||
543 |
✓✗ | 24 |
if (al == 0) /* no alert */ |
544 |
{ |
||
545 |
24 |
unsigned char *p = (unsigned char *)s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
546 |
48 |
memcpy(&p[frag->msg_header.frag_off], |
|
547 |
24 |
frag->fragment, frag->msg_header.frag_len); |
|
548 |
24 |
} |
|
549 |
|||
550 |
24 |
dtls1_hm_fragment_free(frag); |
|
551 |
24 |
pitem_free(item); |
|
552 |
|||
553 |
✓✗ | 24 |
if (al == 0) { |
554 |
24 |
*ok = 1; |
|
555 |
24 |
return frag_len; |
|
556 |
} |
||
557 |
|||
558 |
ssl3_send_alert(s, SSL3_AL_FATAL, al); |
||
559 |
s->internal->init_num = 0; |
||
560 |
*ok = 0; |
||
561 |
return -1; |
||
562 |
} else |
||
563 |
return 0; |
||
564 |
486 |
} |
|
565 |
|||
566 |
/* |
||
567 |
* dtls1_max_handshake_message_len returns the maximum number of bytes |
||
568 |
* permitted in a DTLS handshake message for |s|. The minimum is 16KB, |
||
569 |
* but may be greater if the maximum certificate list size requires it. |
||
570 |
*/ |
||
571 |
static unsigned long |
||
572 |
dtls1_max_handshake_message_len(const SSL *s) |
||
573 |
{ |
||
574 |
unsigned long max_len; |
||
575 |
|||
576 |
max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; |
||
577 |
✓✗ | 114 |
if (max_len < (unsigned long)s->internal->max_cert_list) |
578 |
57 |
return s->internal->max_cert_list; |
|
579 |
return max_len; |
||
580 |
57 |
} |
|
581 |
|||
582 |
static int |
||
583 |
dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) |
||
584 |
{ |
||
585 |
hm_fragment *frag = NULL; |
||
586 |
pitem *item = NULL; |
||
587 |
int i = -1, is_complete; |
||
588 |
114 |
unsigned char seq64be[8]; |
|
589 |
57 |
unsigned long frag_len = msg_hdr->frag_len; |
|
590 |
|||
591 |
✓✗✓✗ |
114 |
if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len || |
592 |
57 |
msg_hdr->msg_len > dtls1_max_handshake_message_len(s)) |
|
593 |
goto err; |
||
594 |
|||
595 |
✗✓ | 57 |
if (frag_len == 0) { |
596 |
i = DTLS1_HM_FRAGMENT_RETRY; |
||
597 |
goto err; |
||
598 |
} |
||
599 |
|||
600 |
/* Try to find item in queue */ |
||
601 |
57 |
memset(seq64be, 0, sizeof(seq64be)); |
|
602 |
57 |
seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); |
|
603 |
57 |
seq64be[7] = (unsigned char)msg_hdr->seq; |
|
604 |
57 |
item = pqueue_find(D1I(s)->buffered_messages, seq64be); |
|
605 |
|||
606 |
✓✓ | 57 |
if (item == NULL) { |
607 |
24 |
frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); |
|
608 |
✓✗ | 24 |
if (frag == NULL) |
609 |
goto err; |
||
610 |
24 |
memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); |
|
611 |
24 |
frag->msg_header.frag_len = frag->msg_header.msg_len; |
|
612 |
24 |
frag->msg_header.frag_off = 0; |
|
613 |
24 |
} else { |
|
614 |
33 |
frag = (hm_fragment*)item->data; |
|
615 |
✗✓ | 33 |
if (frag->msg_header.msg_len != msg_hdr->msg_len) { |
616 |
item = NULL; |
||
617 |
frag = NULL; |
||
618 |
goto err; |
||
619 |
} |
||
620 |
} |
||
621 |
|||
622 |
/* |
||
623 |
* If message is already reassembled, this must be a |
||
624 |
* retransmit and can be dropped. |
||
625 |
*/ |
||
626 |
✗✓ | 57 |
if (frag->reassembly == NULL) { |
627 |
unsigned char devnull [256]; |
||
628 |
|||
629 |
while (frag_len) { |
||
630 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
||
631 |
devnull, frag_len > sizeof(devnull) ? |
||
632 |
sizeof(devnull) : frag_len, 0); |
||
633 |
if (i <= 0) |
||
634 |
goto err; |
||
635 |
frag_len -= i; |
||
636 |
} |
||
637 |
i = DTLS1_HM_FRAGMENT_RETRY; |
||
638 |
goto err; |
||
639 |
} |
||
640 |
|||
641 |
/* read the body of the fragment (header has already been read */ |
||
642 |
114 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
|
643 |
57 |
frag->fragment + msg_hdr->frag_off, frag_len, 0); |
|
644 |
✓✗✓✗ |
114 |
if (i <= 0 || (unsigned long)i != frag_len) |
645 |
goto err; |
||
646 |
|||
647 |
✓✓✓✓ ✓✓ |
11496 |
RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off, |
648 |
(long)(msg_hdr->frag_off + frag_len)); |
||
649 |
|||
650 |
✗✓✓✓ ✓✓✓✓ ✗✓ |
17235 |
RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len, |
651 |
is_complete); |
||
652 |
|||
653 |
✓✓ | 57 |
if (is_complete) { |
654 |
24 |
free(frag->reassembly); |
|
655 |
24 |
frag->reassembly = NULL; |
|
656 |
24 |
} |
|
657 |
|||
658 |
✓✓ | 57 |
if (item == NULL) { |
659 |
24 |
memset(seq64be, 0, sizeof(seq64be)); |
|
660 |
24 |
seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); |
|
661 |
24 |
seq64be[7] = (unsigned char)(msg_hdr->seq); |
|
662 |
|||
663 |
24 |
item = pitem_new(seq64be, frag); |
|
664 |
✗✓ | 24 |
if (item == NULL) { |
665 |
i = -1; |
||
666 |
goto err; |
||
667 |
} |
||
668 |
|||
669 |
24 |
pqueue_insert(D1I(s)->buffered_messages, item); |
|
670 |
24 |
} |
|
671 |
|||
672 |
57 |
return DTLS1_HM_FRAGMENT_RETRY; |
|
673 |
|||
674 |
err: |
||
675 |
if (item == NULL && frag != NULL) |
||
676 |
dtls1_hm_fragment_free(frag); |
||
677 |
*ok = 0; |
||
678 |
return i; |
||
679 |
57 |
} |
|
680 |
|||
681 |
|||
682 |
static int |
||
683 |
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) |
||
684 |
{ |
||
685 |
int i = -1; |
||
686 |
hm_fragment *frag = NULL; |
||
687 |
pitem *item = NULL; |
||
688 |
unsigned char seq64be[8]; |
||
689 |
unsigned long frag_len = msg_hdr->frag_len; |
||
690 |
|||
691 |
if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len) |
||
692 |
goto err; |
||
693 |
|||
694 |
/* Try to find item in queue, to prevent duplicate entries */ |
||
695 |
memset(seq64be, 0, sizeof(seq64be)); |
||
696 |
seq64be[6] = (unsigned char) (msg_hdr->seq >> 8); |
||
697 |
seq64be[7] = (unsigned char) msg_hdr->seq; |
||
698 |
item = pqueue_find(D1I(s)->buffered_messages, seq64be); |
||
699 |
|||
700 |
/* |
||
701 |
* If we already have an entry and this one is a fragment, |
||
702 |
* don't discard it and rather try to reassemble it. |
||
703 |
*/ |
||
704 |
if (item != NULL && frag_len < msg_hdr->msg_len) |
||
705 |
item = NULL; |
||
706 |
|||
707 |
/* |
||
708 |
* Discard the message if sequence number was already there, is |
||
709 |
* too far in the future, already in the queue or if we received |
||
710 |
* a FINISHED before the SERVER_HELLO, which then must be a stale |
||
711 |
* retransmit. |
||
712 |
*/ |
||
713 |
if (msg_hdr->seq <= D1I(s)->handshake_read_seq || |
||
714 |
msg_hdr->seq > D1I(s)->handshake_read_seq + 10 || item != NULL || |
||
715 |
(D1I(s)->handshake_read_seq == 0 && |
||
716 |
msg_hdr->type == SSL3_MT_FINISHED)) { |
||
717 |
unsigned char devnull [256]; |
||
718 |
|||
719 |
while (frag_len) { |
||
720 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
||
721 |
devnull, frag_len > sizeof(devnull) ? |
||
722 |
sizeof(devnull) : frag_len, 0); |
||
723 |
if (i <= 0) |
||
724 |
goto err; |
||
725 |
frag_len -= i; |
||
726 |
} |
||
727 |
} else { |
||
728 |
if (frag_len < msg_hdr->msg_len) |
||
729 |
return dtls1_reassemble_fragment(s, msg_hdr, ok); |
||
730 |
|||
731 |
if (frag_len > dtls1_max_handshake_message_len(s)) |
||
732 |
goto err; |
||
733 |
|||
734 |
frag = dtls1_hm_fragment_new(frag_len, 0); |
||
735 |
if (frag == NULL) |
||
736 |
goto err; |
||
737 |
|||
738 |
memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); |
||
739 |
|||
740 |
if (frag_len) { |
||
741 |
/* read the body of the fragment (header has already been read */ |
||
742 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
||
743 |
frag->fragment, frag_len, 0); |
||
744 |
if (i <= 0 || (unsigned long)i != frag_len) |
||
745 |
goto err; |
||
746 |
} |
||
747 |
|||
748 |
memset(seq64be, 0, sizeof(seq64be)); |
||
749 |
seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); |
||
750 |
seq64be[7] = (unsigned char)(msg_hdr->seq); |
||
751 |
|||
752 |
item = pitem_new(seq64be, frag); |
||
753 |
if (item == NULL) |
||
754 |
goto err; |
||
755 |
|||
756 |
pqueue_insert(D1I(s)->buffered_messages, item); |
||
757 |
} |
||
758 |
|||
759 |
return DTLS1_HM_FRAGMENT_RETRY; |
||
760 |
|||
761 |
err: |
||
762 |
if (item == NULL && frag != NULL) |
||
763 |
dtls1_hm_fragment_free(frag); |
||
764 |
*ok = 0; |
||
765 |
return i; |
||
766 |
} |
||
767 |
|||
768 |
|||
769 |
static long |
||
770 |
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) |
||
771 |
{ |
||
772 |
972 |
unsigned char wire[DTLS1_HM_HEADER_LENGTH]; |
|
773 |
unsigned long len, frag_off, frag_len; |
||
774 |
int i, al; |
||
775 |
486 |
struct hm_header_st msg_hdr; |
|
776 |
|||
777 |
again: |
||
778 |
/* see if we have the required fragment already */ |
||
779 |
✓✓✗✓ |
948 |
if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) { |
780 |
✓✗ | 24 |
if (*ok) |
781 |
24 |
s->internal->init_num = frag_len; |
|
782 |
24 |
return frag_len; |
|
783 |
} |
||
784 |
|||
785 |
/* read handshake message header */ |
||
786 |
462 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire, |
|
787 |
DTLS1_HM_HEADER_LENGTH, 0); |
||
788 |
✓✓ | 462 |
if (i <= 0) /* nbio, or an error */ |
789 |
{ |
||
790 |
111 |
s->internal->rwstate = SSL_READING; |
|
791 |
111 |
*ok = 0; |
|
792 |
111 |
return i; |
|
793 |
} |
||
794 |
/* Handshake fails if message header is incomplete */ |
||
795 |
✓✗✗✓ |
702 |
if (i != DTLS1_HM_HEADER_LENGTH || |
796 |
/* parse the message fragment header */ |
||
797 |
351 |
dtls1_get_message_header(wire, &msg_hdr) == 0) { |
|
798 |
al = SSL_AD_UNEXPECTED_MESSAGE; |
||
799 |
SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); |
||
800 |
goto f_err; |
||
801 |
} |
||
802 |
|||
803 |
/* |
||
804 |
* if this is a future (or stale) message it gets buffered |
||
805 |
* (or dropped)--no further processing at this time |
||
806 |
* While listening, we accept seq 1 (ClientHello with cookie) |
||
807 |
* although we're still expecting seq 0 (ClientHello) |
||
808 |
*/ |
||
809 |
✗✓✗✗ |
351 |
if (msg_hdr.seq != D1I(s)->handshake_read_seq && |
810 |
!(D1I(s)->listen && msg_hdr.seq == 1)) |
||
811 |
return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); |
||
812 |
|||
813 |
351 |
len = msg_hdr.msg_len; |
|
814 |
351 |
frag_off = msg_hdr.frag_off; |
|
815 |
351 |
frag_len = msg_hdr.frag_len; |
|
816 |
|||
817 |
✓✓✓✓ |
666 |
if (frag_len && frag_len < len) |
818 |
57 |
return dtls1_reassemble_fragment(s, &msg_hdr, ok); |
|
819 |
|||
820 |
✓✓✓✗ ✗✓ |
666 |
if (!s->server && D1I(s)->r_msg_hdr.frag_off == 0 && |
821 |
186 |
wire[0] == SSL3_MT_HELLO_REQUEST) { |
|
822 |
/* |
||
823 |
* The server may always send 'Hello Request' messages -- |
||
824 |
* we are doing a handshake anyway now, so ignore them |
||
825 |
* if their format is correct. Does not count for |
||
826 |
* 'Finished' MAC. |
||
827 |
*/ |
||
828 |
if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) { |
||
829 |
if (s->internal->msg_callback) |
||
830 |
s->internal->msg_callback(0, s->version, |
||
831 |
SSL3_RT_HANDSHAKE, wire, |
||
832 |
DTLS1_HM_HEADER_LENGTH, s, |
||
833 |
s->internal->msg_callback_arg); |
||
834 |
|||
835 |
s->internal->init_num = 0; |
||
836 |
goto again; |
||
837 |
} |
||
838 |
else /* Incorrectly formated Hello request */ |
||
839 |
{ |
||
840 |
al = SSL_AD_UNEXPECTED_MESSAGE; |
||
841 |
SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); |
||
842 |
goto f_err; |
||
843 |
} |
||
844 |
} |
||
845 |
|||
846 |
✓✗ | 294 |
if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max))) |
847 |
goto f_err; |
||
848 |
|||
849 |
/* XDTLS: ressurect this when restart is in place */ |
||
850 |
294 |
S3I(s)->hs.state = stn; |
|
851 |
|||
852 |
✓✓ | 294 |
if (frag_len > 0) { |
853 |
258 |
unsigned char *p = (unsigned char *)s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
854 |
|||
855 |
516 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
|
856 |
258 |
&p[frag_off], frag_len, 0); |
|
857 |
/* XDTLS: fix this--message fragments cannot span multiple packets */ |
||
858 |
✗✓ | 258 |
if (i <= 0) { |
859 |
s->internal->rwstate = SSL_READING; |
||
860 |
*ok = 0; |
||
861 |
return i; |
||
862 |
} |
||
863 |
✓✗ | 258 |
} else |
864 |
i = 0; |
||
865 |
|||
866 |
/* |
||
867 |
* XDTLS: an incorrectly formatted fragment should cause the |
||
868 |
* handshake to fail |
||
869 |
*/ |
||
870 |
✗✓ | 294 |
if (i != (int)frag_len) { |
871 |
al = SSL3_AD_ILLEGAL_PARAMETER; |
||
872 |
SSLerror(s, SSL3_AD_ILLEGAL_PARAMETER); |
||
873 |
goto f_err; |
||
874 |
} |
||
875 |
|||
876 |
294 |
*ok = 1; |
|
877 |
|||
878 |
/* |
||
879 |
* Note that s->internal->init_num is *not* used as current offset in |
||
880 |
* s->internal->init_buf->data, but as a counter summing up fragments' |
||
881 |
* lengths: as soon as they sum up to handshake packet |
||
882 |
* length, we assume we have got all the fragments. |
||
883 |
*/ |
||
884 |
294 |
s->internal->init_num = frag_len; |
|
885 |
294 |
return frag_len; |
|
886 |
|||
887 |
f_err: |
||
888 |
ssl3_send_alert(s, SSL3_AL_FATAL, al); |
||
889 |
s->internal->init_num = 0; |
||
890 |
|||
891 |
*ok = 0; |
||
892 |
return (-1); |
||
893 |
486 |
} |
|
894 |
|||
895 |
int |
||
896 |
dtls1_read_failed(SSL *s, int code) |
||
897 |
{ |
||
898 |
✗✓ | 294 |
if (code > 0) { |
899 |
#ifdef DEBUG |
||
900 |
fprintf(stderr, "invalid state reached %s:%d", |
||
901 |
__FILE__, __LINE__); |
||
902 |
#endif |
||
903 |
return 1; |
||
904 |
} |
||
905 |
|||
906 |
✓✗ | 147 |
if (!dtls1_is_timer_expired(s)) { |
907 |
/* |
||
908 |
* not a timeout, none of our business, let higher layers |
||
909 |
* handle this. in fact it's probably an error |
||
910 |
*/ |
||
911 |
147 |
return code; |
|
912 |
} |
||
913 |
|||
914 |
if (!SSL_in_init(s)) /* done, no need to send a retransmit */ |
||
915 |
{ |
||
916 |
BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ); |
||
917 |
return code; |
||
918 |
} |
||
919 |
|||
920 |
return dtls1_handle_timeout(s); |
||
921 |
147 |
} |
|
922 |
|||
923 |
int |
||
924 |
dtls1_get_queue_priority(unsigned short seq, int is_ccs) |
||
925 |
{ |
||
926 |
/* |
||
927 |
* The index of the retransmission queue actually is the message |
||
928 |
* sequence number, since the queue only contains messages of a |
||
929 |
* single handshake. However, the ChangeCipherSpec has no message |
||
930 |
* sequence number and so using only the sequence will result in |
||
931 |
* the CCS and Finished having the same index. To prevent this, the |
||
932 |
* sequence number is multiplied by 2. In case of a CCS 1 is |
||
933 |
* subtracted. This does not only differ CSS and Finished, it also |
||
934 |
* maintains the order of the index (important for priority queues) |
||
935 |
* and fits in the unsigned short variable. |
||
936 |
*/ |
||
937 |
1572 |
return seq * 2 - is_ccs; |
|
938 |
} |
||
939 |
|||
940 |
int |
||
941 |
dtls1_retransmit_buffered_messages(SSL *s) |
||
942 |
{ |
||
943 |
pqueue sent = s->d1->sent_messages; |
||
944 |
piterator iter; |
||
945 |
pitem *item; |
||
946 |
hm_fragment *frag; |
||
947 |
int found = 0; |
||
948 |
|||
949 |
iter = pqueue_iterator(sent); |
||
950 |
|||
951 |
for (item = pqueue_next(&iter); item != NULL; |
||
952 |
item = pqueue_next(&iter)) { |
||
953 |
frag = (hm_fragment *)item->data; |
||
954 |
if (dtls1_retransmit_message(s, |
||
955 |
(unsigned short)dtls1_get_queue_priority( |
||
956 |
frag->msg_header.seq, frag->msg_header.is_ccs), 0, |
||
957 |
&found) <= 0 && found) { |
||
958 |
#ifdef DEBUG |
||
959 |
fprintf(stderr, "dtls1_retransmit_message() failed\n"); |
||
960 |
#endif |
||
961 |
return -1; |
||
962 |
} |
||
963 |
} |
||
964 |
|||
965 |
return 1; |
||
966 |
} |
||
967 |
|||
968 |
int |
||
969 |
dtls1_buffer_message(SSL *s, int is_ccs) |
||
970 |
{ |
||
971 |
pitem *item; |
||
972 |
hm_fragment *frag; |
||
973 |
786 |
unsigned char seq64be[8]; |
|
974 |
|||
975 |
/* Buffer the messsage in order to handle DTLS retransmissions. */ |
||
976 |
|||
977 |
/* |
||
978 |
* This function is called immediately after a message has |
||
979 |
* been serialized |
||
980 |
*/ |
||
981 |
✗✓ | 393 |
OPENSSL_assert(s->internal->init_off == 0); |
982 |
|||
983 |
393 |
frag = dtls1_hm_fragment_new(s->internal->init_num, 0); |
|
984 |
✗✓ | 393 |
if (frag == NULL) |
985 |
return 0; |
||
986 |
|||
987 |
393 |
memcpy(frag->fragment, s->internal->init_buf->data, s->internal->init_num); |
|
988 |
|||
989 |
✓✓ | 393 |
if (is_ccs) { |
990 |
✗✓ | 72 |
OPENSSL_assert(D1I(s)->w_msg_hdr.msg_len + |
991 |
((s->version == DTLS1_VERSION) ? |
||
992 |
DTLS1_CCS_HEADER_LENGTH : 3) == (unsigned int)s->internal->init_num); |
||
993 |
} else { |
||
994 |
✗✓ | 321 |
OPENSSL_assert(D1I(s)->w_msg_hdr.msg_len + |
995 |
DTLS1_HM_HEADER_LENGTH == (unsigned int)s->internal->init_num); |
||
996 |
} |
||
997 |
|||
998 |
393 |
frag->msg_header.msg_len = D1I(s)->w_msg_hdr.msg_len; |
|
999 |
393 |
frag->msg_header.seq = D1I(s)->w_msg_hdr.seq; |
|
1000 |
393 |
frag->msg_header.type = D1I(s)->w_msg_hdr.type; |
|
1001 |
393 |
frag->msg_header.frag_off = 0; |
|
1002 |
393 |
frag->msg_header.frag_len = D1I(s)->w_msg_hdr.msg_len; |
|
1003 |
393 |
frag->msg_header.is_ccs = is_ccs; |
|
1004 |
|||
1005 |
/* save current state*/ |
||
1006 |
393 |
frag->msg_header.saved_retransmit_state.enc_write_ctx = s->internal->enc_write_ctx; |
|
1007 |
393 |
frag->msg_header.saved_retransmit_state.write_hash = s->internal->write_hash; |
|
1008 |
393 |
frag->msg_header.saved_retransmit_state.session = s->session; |
|
1009 |
393 |
frag->msg_header.saved_retransmit_state.epoch = D1I(s)->w_epoch; |
|
1010 |
|||
1011 |
393 |
memset(seq64be, 0, sizeof(seq64be)); |
|
1012 |
786 |
seq64be[6] = (unsigned char)(dtls1_get_queue_priority( |
|
1013 |
786 |
frag->msg_header.seq, frag->msg_header.is_ccs) >> 8); |
|
1014 |
393 |
seq64be[7] = (unsigned char)(dtls1_get_queue_priority( |
|
1015 |
393 |
frag->msg_header.seq, frag->msg_header.is_ccs)); |
|
1016 |
|||
1017 |
393 |
item = pitem_new(seq64be, frag); |
|
1018 |
✗✓ | 393 |
if (item == NULL) { |
1019 |
dtls1_hm_fragment_free(frag); |
||
1020 |
return 0; |
||
1021 |
} |
||
1022 |
|||
1023 |
393 |
pqueue_insert(s->d1->sent_messages, item); |
|
1024 |
393 |
return 1; |
|
1025 |
393 |
} |
|
1026 |
|||
1027 |
int |
||
1028 |
dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, |
||
1029 |
int *found) |
||
1030 |
{ |
||
1031 |
int ret; |
||
1032 |
/* XDTLS: for now assuming that read/writes are blocking */ |
||
1033 |
pitem *item; |
||
1034 |
hm_fragment *frag; |
||
1035 |
unsigned long header_length; |
||
1036 |
unsigned char seq64be[8]; |
||
1037 |
struct dtls1_retransmit_state saved_state; |
||
1038 |
unsigned char save_write_sequence[8]; |
||
1039 |
|||
1040 |
/* |
||
1041 |
OPENSSL_assert(s->internal->init_num == 0); |
||
1042 |
OPENSSL_assert(s->internal->init_off == 0); |
||
1043 |
*/ |
||
1044 |
|||
1045 |
/* XDTLS: the requested message ought to be found, otherwise error */ |
||
1046 |
memset(seq64be, 0, sizeof(seq64be)); |
||
1047 |
seq64be[6] = (unsigned char)(seq >> 8); |
||
1048 |
seq64be[7] = (unsigned char)seq; |
||
1049 |
|||
1050 |
item = pqueue_find(s->d1->sent_messages, seq64be); |
||
1051 |
if (item == NULL) { |
||
1052 |
#ifdef DEBUG |
||
1053 |
fprintf(stderr, "retransmit: message %d non-existant\n", seq); |
||
1054 |
#endif |
||
1055 |
*found = 0; |
||
1056 |
return 0; |
||
1057 |
} |
||
1058 |
|||
1059 |
*found = 1; |
||
1060 |
frag = (hm_fragment *)item->data; |
||
1061 |
|||
1062 |
if (frag->msg_header.is_ccs) |
||
1063 |
header_length = DTLS1_CCS_HEADER_LENGTH; |
||
1064 |
else |
||
1065 |
header_length = DTLS1_HM_HEADER_LENGTH; |
||
1066 |
|||
1067 |
memcpy(s->internal->init_buf->data, frag->fragment, |
||
1068 |
frag->msg_header.msg_len + header_length); |
||
1069 |
s->internal->init_num = frag->msg_header.msg_len + header_length; |
||
1070 |
|||
1071 |
dtls1_set_message_header_int(s, frag->msg_header.type, |
||
1072 |
frag->msg_header.msg_len, frag->msg_header.seq, 0, |
||
1073 |
frag->msg_header.frag_len); |
||
1074 |
|||
1075 |
/* save current state */ |
||
1076 |
saved_state.enc_write_ctx = s->internal->enc_write_ctx; |
||
1077 |
saved_state.write_hash = s->internal->write_hash; |
||
1078 |
saved_state.session = s->session; |
||
1079 |
saved_state.epoch = D1I(s)->w_epoch; |
||
1080 |
|||
1081 |
D1I(s)->retransmitting = 1; |
||
1082 |
|||
1083 |
/* restore state in which the message was originally sent */ |
||
1084 |
s->internal->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx; |
||
1085 |
s->internal->write_hash = frag->msg_header.saved_retransmit_state.write_hash; |
||
1086 |
s->session = frag->msg_header.saved_retransmit_state.session; |
||
1087 |
D1I(s)->w_epoch = frag->msg_header.saved_retransmit_state.epoch; |
||
1088 |
|||
1089 |
if (frag->msg_header.saved_retransmit_state.epoch == |
||
1090 |
saved_state.epoch - 1) { |
||
1091 |
memcpy(save_write_sequence, S3I(s)->write_sequence, |
||
1092 |
sizeof(S3I(s)->write_sequence)); |
||
1093 |
memcpy(S3I(s)->write_sequence, D1I(s)->last_write_sequence, |
||
1094 |
sizeof(S3I(s)->write_sequence)); |
||
1095 |
} |
||
1096 |
|||
1097 |
ret = dtls1_do_write(s, frag->msg_header.is_ccs ? |
||
1098 |
SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); |
||
1099 |
|||
1100 |
/* restore current state */ |
||
1101 |
s->internal->enc_write_ctx = saved_state.enc_write_ctx; |
||
1102 |
s->internal->write_hash = saved_state.write_hash; |
||
1103 |
s->session = saved_state.session; |
||
1104 |
D1I(s)->w_epoch = saved_state.epoch; |
||
1105 |
|||
1106 |
if (frag->msg_header.saved_retransmit_state.epoch == |
||
1107 |
saved_state.epoch - 1) { |
||
1108 |
memcpy(D1I(s)->last_write_sequence, S3I(s)->write_sequence, |
||
1109 |
sizeof(S3I(s)->write_sequence)); |
||
1110 |
memcpy(S3I(s)->write_sequence, save_write_sequence, |
||
1111 |
sizeof(S3I(s)->write_sequence)); |
||
1112 |
} |
||
1113 |
|||
1114 |
D1I(s)->retransmitting = 0; |
||
1115 |
|||
1116 |
(void)BIO_flush(SSL_get_wbio(s)); |
||
1117 |
return ret; |
||
1118 |
} |
||
1119 |
|||
1120 |
/* call this function when the buffered messages are no longer needed */ |
||
1121 |
void |
||
1122 |
dtls1_clear_record_buffer(SSL *s) |
||
1123 |
{ |
||
1124 |
pitem *item; |
||
1125 |
|||
1126 |
✓✓ | 1104 |
for(item = pqueue_pop(s->d1->sent_messages); item != NULL; |
1127 |
282 |
item = pqueue_pop(s->d1->sent_messages)) { |
|
1128 |
282 |
dtls1_hm_fragment_free((hm_fragment *)item->data); |
|
1129 |
282 |
pitem_free(item); |
|
1130 |
} |
||
1131 |
180 |
} |
|
1132 |
|||
1133 |
void |
||
1134 |
dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len, |
||
1135 |
unsigned long frag_off, unsigned long frag_len) |
||
1136 |
{ |
||
1137 |
/* Don't change sequence numbers while listening */ |
||
1138 |
✓✗✓✗ |
963 |
if (frag_off == 0 && !D1I(s)->listen) { |
1139 |
321 |
D1I(s)->handshake_write_seq = D1I(s)->next_handshake_write_seq; |
|
1140 |
321 |
D1I(s)->next_handshake_write_seq++; |
|
1141 |
321 |
} |
|
1142 |
|||
1143 |
321 |
dtls1_set_message_header_int(s, mt, len, D1I(s)->handshake_write_seq, |
|
1144 |
frag_off, frag_len); |
||
1145 |
321 |
} |
|
1146 |
|||
1147 |
/* don't actually do the writing, wait till the MTU has been retrieved */ |
||
1148 |
void |
||
1149 |
dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len, |
||
1150 |
unsigned short seq_num, unsigned long frag_off, unsigned long frag_len) |
||
1151 |
{ |
||
1152 |
786 |
struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
1153 |
|||
1154 |
393 |
msg_hdr->type = mt; |
|
1155 |
393 |
msg_hdr->msg_len = len; |
|
1156 |
393 |
msg_hdr->seq = seq_num; |
|
1157 |
393 |
msg_hdr->frag_off = frag_off; |
|
1158 |
393 |
msg_hdr->frag_len = frag_len; |
|
1159 |
393 |
} |
|
1160 |
|||
1161 |
static void |
||
1162 |
dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len) |
||
1163 |
{ |
||
1164 |
708 |
struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
1165 |
|||
1166 |
354 |
msg_hdr->frag_off = frag_off; |
|
1167 |
354 |
msg_hdr->frag_len = frag_len; |
|
1168 |
354 |
} |
|
1169 |
|||
1170 |
static unsigned char * |
||
1171 |
dtls1_write_message_header(SSL *s, unsigned char *p) |
||
1172 |
{ |
||
1173 |
708 |
struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
1174 |
|||
1175 |
354 |
*p++ = msg_hdr->type; |
|
1176 |
354 |
l2n3(msg_hdr->msg_len, p); |
|
1177 |
|||
1178 |
354 |
s2n(msg_hdr->seq, p); |
|
1179 |
354 |
l2n3(msg_hdr->frag_off, p); |
|
1180 |
354 |
l2n3(msg_hdr->frag_len, p); |
|
1181 |
|||
1182 |
354 |
return p; |
|
1183 |
} |
||
1184 |
|||
1185 |
unsigned int |
||
1186 |
dtls1_min_mtu(void) |
||
1187 |
{ |
||
1188 |
1722 |
return (g_probable_mtu[(sizeof(g_probable_mtu) / |
|
1189 |
sizeof(g_probable_mtu[0])) - 1]); |
||
1190 |
} |
||
1191 |
|||
1192 |
static unsigned int |
||
1193 |
dtls1_guess_mtu(unsigned int curr_mtu) |
||
1194 |
{ |
||
1195 |
unsigned int i; |
||
1196 |
|||
1197 |
✓✗ | 150 |
if (curr_mtu == 0) |
1198 |
75 |
return g_probable_mtu[0]; |
|
1199 |
|||
1200 |
for (i = 0; i < sizeof(g_probable_mtu) / sizeof(g_probable_mtu[0]); i++) |
||
1201 |
if (curr_mtu > g_probable_mtu[i]) |
||
1202 |
return g_probable_mtu[i]; |
||
1203 |
|||
1204 |
return curr_mtu; |
||
1205 |
75 |
} |
|
1206 |
|||
1207 |
int |
||
1208 |
dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) |
||
1209 |
{ |
||
1210 |
702 |
CBS header; |
|
1211 |
351 |
uint32_t msg_len, frag_off, frag_len; |
|
1212 |
351 |
uint16_t seq; |
|
1213 |
351 |
uint8_t type; |
|
1214 |
|||
1215 |
351 |
CBS_init(&header, data, sizeof(*msg_hdr)); |
|
1216 |
|||
1217 |
351 |
memset(msg_hdr, 0, sizeof(*msg_hdr)); |
|
1218 |
|||
1219 |
✗✓ | 351 |
if (!CBS_get_u8(&header, &type)) |
1220 |
return 0; |
||
1221 |
✗✓ | 351 |
if (!CBS_get_u24(&header, &msg_len)) |
1222 |
return 0; |
||
1223 |
✗✓ | 351 |
if (!CBS_get_u16(&header, &seq)) |
1224 |
return 0; |
||
1225 |
✗✓ | 351 |
if (!CBS_get_u24(&header, &frag_off)) |
1226 |
return 0; |
||
1227 |
✗✓ | 351 |
if (!CBS_get_u24(&header, &frag_len)) |
1228 |
return 0; |
||
1229 |
|||
1230 |
351 |
msg_hdr->type = type; |
|
1231 |
351 |
msg_hdr->msg_len = msg_len; |
|
1232 |
351 |
msg_hdr->seq = seq; |
|
1233 |
351 |
msg_hdr->frag_off = frag_off; |
|
1234 |
351 |
msg_hdr->frag_len = frag_len; |
|
1235 |
|||
1236 |
351 |
return 1; |
|
1237 |
351 |
} |
|
1238 |
|||
1239 |
void |
||
1240 |
dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr) |
||
1241 |
{ |
||
1242 |
144 |
memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st)); |
|
1243 |
|||
1244 |
72 |
ccs_hdr->type = *(data++); |
|
1245 |
72 |
} |
|
1246 |
|||
1247 |
int |
||
1248 |
dtls1_shutdown(SSL *s) |
||
1249 |
{ |
||
1250 |
int ret; |
||
1251 |
|||
1252 |
144 |
ret = ssl3_shutdown(s); |
|
1253 |
72 |
return ret; |
|
1254 |
} |
Generated by: GCOVR (Version 3.3) |