GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: d1_both.c,v 1.51 2017/05/07 04:22:24 beck 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 void dtls1_set_message_header_int(SSL *s, unsigned char mt, |
||
166 |
unsigned long len, unsigned short seq_num, unsigned long frag_off, |
||
167 |
unsigned long frag_len); |
||
168 |
static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, |
||
169 |
int *ok); |
||
170 |
|||
171 |
static hm_fragment * |
||
172 |
dtls1_hm_fragment_new(unsigned long frag_len, int reassembly) |
||
173 |
{ |
||
174 |
hm_fragment *frag = NULL; |
||
175 |
unsigned char *buf = NULL; |
||
176 |
unsigned char *bitmask = NULL; |
||
177 |
|||
178 |
1112 |
frag = malloc(sizeof(hm_fragment)); |
|
179 |
✗✓ | 556 |
if (frag == NULL) |
180 |
return NULL; |
||
181 |
|||
182 |
✓✗ | 556 |
if (frag_len) { |
183 |
556 |
buf = malloc(frag_len); |
|
184 |
✗✓ | 556 |
if (buf == NULL) { |
185 |
free(frag); |
||
186 |
return NULL; |
||
187 |
} |
||
188 |
} |
||
189 |
|||
190 |
/* zero length fragment gets zero frag->fragment */ |
||
191 |
556 |
frag->fragment = buf; |
|
192 |
|||
193 |
/* Initialize reassembly bitmask if necessary */ |
||
194 |
✓✓ | 556 |
if (reassembly) { |
195 |
32 |
bitmask = malloc(RSMBLY_BITMASK_SIZE(frag_len)); |
|
196 |
✗✓ | 32 |
if (bitmask == NULL) { |
197 |
free(buf); |
||
198 |
free(frag); |
||
199 |
return NULL; |
||
200 |
} |
||
201 |
32 |
memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len)); |
|
202 |
32 |
} |
|
203 |
|||
204 |
556 |
frag->reassembly = bitmask; |
|
205 |
|||
206 |
556 |
return frag; |
|
207 |
556 |
} |
|
208 |
|||
209 |
static void |
||
210 |
dtls1_hm_fragment_free(hm_fragment *frag) |
||
211 |
{ |
||
212 |
✓✗ | 816 |
if (frag == NULL) |
213 |
return; |
||
214 |
|||
215 |
✓✓ | 408 |
if (frag->msg_header.is_ccs) { |
216 |
48 |
EVP_CIPHER_CTX_free( |
|
217 |
48 |
frag->msg_header.saved_retransmit_state.enc_write_ctx); |
|
218 |
48 |
EVP_MD_CTX_destroy( |
|
219 |
48 |
frag->msg_header.saved_retransmit_state.write_hash); |
|
220 |
48 |
} |
|
221 |
408 |
free(frag->fragment); |
|
222 |
408 |
free(frag->reassembly); |
|
223 |
408 |
free(frag); |
|
224 |
816 |
} |
|
225 |
|||
226 |
/* send s->internal->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ |
||
227 |
int |
||
228 |
dtls1_do_write(SSL *s, int type) |
||
229 |
{ |
||
230 |
int ret; |
||
231 |
int curr_mtu; |
||
232 |
unsigned int len, frag_off, mac_size, blocksize; |
||
233 |
|||
234 |
/* AHA! Figure out the MTU, and stick to the right size */ |
||
235 |
✓✓✓✗ |
1148 |
if (D1I(s)->mtu < dtls1_min_mtu() && |
236 |
100 |
!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { |
|
237 |
100 |
D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s), |
|
238 |
BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); |
||
239 |
|||
240 |
/* |
||
241 |
* I've seen the kernel return bogus numbers when it |
||
242 |
* doesn't know the MTU (ie., the initial write), so just |
||
243 |
* make sure we have a reasonable number |
||
244 |
*/ |
||
245 |
✓✗ | 100 |
if (D1I(s)->mtu < dtls1_min_mtu()) { |
246 |
100 |
D1I(s)->mtu = 0; |
|
247 |
100 |
D1I(s)->mtu = dtls1_guess_mtu(D1I(s)->mtu); |
|
248 |
200 |
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, |
|
249 |
100 |
D1I(s)->mtu, NULL); |
|
250 |
100 |
} |
|
251 |
} |
||
252 |
|||
253 |
✗✓ | 524 |
OPENSSL_assert(D1I(s)->mtu >= dtls1_min_mtu()); |
254 |
/* should have something reasonable now */ |
||
255 |
|||
256 |
✓✓ | 524 |
if (s->internal->init_off == 0 && type == SSL3_RT_HANDSHAKE) |
257 |
✗✓ | 428 |
OPENSSL_assert(s->internal->init_num == |
258 |
(int)D1I(s)->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); |
||
259 |
|||
260 |
✓✓ | 524 |
if (s->internal->write_hash) |
261 |
96 |
mac_size = EVP_MD_CTX_size(s->internal->write_hash); |
|
262 |
else |
||
263 |
mac_size = 0; |
||
264 |
|||
265 |
✓✓✓✓ |
620 |
if (s->internal->enc_write_ctx && |
266 |
96 |
(EVP_CIPHER_mode( s->internal->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE)) |
|
267 |
80 |
blocksize = 2 * EVP_CIPHER_block_size(s->internal->enc_write_ctx->cipher); |
|
268 |
else |
||
269 |
blocksize = 0; |
||
270 |
|||
271 |
frag_off = 0; |
||
272 |
✓✗ | 1092 |
while (s->internal->init_num) { |
273 |
568 |
curr_mtu = D1I(s)->mtu - BIO_wpending(SSL_get_wbio(s)) - |
|
274 |
568 |
DTLS1_RT_HEADER_LENGTH - mac_size - blocksize; |
|
275 |
|||
276 |
✓✓ | 568 |
if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) { |
277 |
/* grr.. we could get an error if MTU picked was wrong */ |
||
278 |
44 |
ret = BIO_flush(SSL_get_wbio(s)); |
|
279 |
✗✓ | 44 |
if (ret <= 0) |
280 |
return ret; |
||
281 |
44 |
curr_mtu = D1I(s)->mtu - DTLS1_RT_HEADER_LENGTH - |
|
282 |
44 |
mac_size - blocksize; |
|
283 |
44 |
} |
|
284 |
|||
285 |
✓✓ | 568 |
if (s->internal->init_num > curr_mtu) |
286 |
44 |
len = curr_mtu; |
|
287 |
else |
||
288 |
len = s->internal->init_num; |
||
289 |
|||
290 |
|||
291 |
/* XDTLS: this function is too long. split out the CCS part */ |
||
292 |
✓✓ | 568 |
if (type == SSL3_RT_HANDSHAKE) { |
293 |
✓✓ | 472 |
if (s->internal->init_off != 0) { |
294 |
✗✓ | 44 |
OPENSSL_assert(s->internal->init_off > DTLS1_HM_HEADER_LENGTH); |
295 |
44 |
s->internal->init_off -= DTLS1_HM_HEADER_LENGTH; |
|
296 |
44 |
s->internal->init_num += DTLS1_HM_HEADER_LENGTH; |
|
297 |
|||
298 |
✓✓ | 44 |
if (s->internal->init_num > curr_mtu) |
299 |
12 |
len = curr_mtu; |
|
300 |
else |
||
301 |
len = s->internal->init_num; |
||
302 |
} |
||
303 |
|||
304 |
944 |
dtls1_fix_message_header(s, frag_off, |
|
305 |
472 |
len - DTLS1_HM_HEADER_LENGTH); |
|
306 |
|||
307 |
472 |
dtls1_write_message_header(s, |
|
308 |
472 |
(unsigned char *)&s->internal->init_buf->data[s->internal->init_off]); |
|
309 |
|||
310 |
✗✓ | 472 |
OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH); |
311 |
} |
||
312 |
|||
313 |
568 |
ret = dtls1_write_bytes(s, type, |
|
314 |
568 |
&s->internal->init_buf->data[s->internal->init_off], len); |
|
315 |
✗✓ | 568 |
if (ret < 0) { |
316 |
/* |
||
317 |
* Might need to update MTU here, but we don't know |
||
318 |
* which previous packet caused the failure -- so |
||
319 |
* can't really retransmit anything. continue as |
||
320 |
* if everything is fine and wait for an alert to |
||
321 |
* handle the retransmit |
||
322 |
*/ |
||
323 |
if (BIO_ctrl(SSL_get_wbio(s), |
||
324 |
BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) |
||
325 |
D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s), |
||
326 |
BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); |
||
327 |
else |
||
328 |
return (-1); |
||
329 |
} else { |
||
330 |
|||
331 |
/* |
||
332 |
* Bad if this assert fails, only part of the |
||
333 |
* handshake message got sent. but why would |
||
334 |
* this happen? |
||
335 |
*/ |
||
336 |
✗✓ | 568 |
OPENSSL_assert(len == (unsigned int)ret); |
337 |
|||
338 |
✓✓✓✗ |
1040 |
if (type == SSL3_RT_HANDSHAKE && |
339 |
472 |
!D1I(s)->retransmitting) { |
|
340 |
/* |
||
341 |
* Should not be done for 'Hello Request's, |
||
342 |
* but in that case we'll ignore the result |
||
343 |
* anyway |
||
344 |
*/ |
||
345 |
472 |
unsigned char *p = (unsigned char *)&s->internal->init_buf->data[s->internal->init_off]; |
|
346 |
472 |
const struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
347 |
int xlen; |
||
348 |
|||
349 |
✓✓ | 472 |
if (frag_off == 0) { |
350 |
/* |
||
351 |
* Reconstruct message header is if it |
||
352 |
* is being sent in single fragment |
||
353 |
*/ |
||
354 |
428 |
*p++ = msg_hdr->type; |
|
355 |
428 |
l2n3(msg_hdr->msg_len, p); |
|
356 |
428 |
s2n (msg_hdr->seq, p); |
|
357 |
428 |
l2n3(0, p); |
|
358 |
428 |
l2n3(msg_hdr->msg_len, p); |
|
359 |
428 |
p -= DTLS1_HM_HEADER_LENGTH; |
|
360 |
xlen = ret; |
||
361 |
428 |
} else { |
|
362 |
44 |
p += DTLS1_HM_HEADER_LENGTH; |
|
363 |
44 |
xlen = ret - DTLS1_HM_HEADER_LENGTH; |
|
364 |
} |
||
365 |
|||
366 |
472 |
tls1_finish_mac(s, p, xlen); |
|
367 |
472 |
} |
|
368 |
|||
369 |
✓✓ | 568 |
if (ret == s->internal->init_num) { |
370 |
✗✓ | 524 |
if (s->internal->msg_callback) |
371 |
s->internal->msg_callback(1, s->version, type, |
||
372 |
s->internal->init_buf->data, |
||
373 |
(size_t)(s->internal->init_off + s->internal->init_num), |
||
374 |
s, s->internal->msg_callback_arg); |
||
375 |
|||
376 |
524 |
s->internal->init_off = 0; |
|
377 |
/* done writing this message */ |
||
378 |
524 |
s->internal->init_num = 0; |
|
379 |
|||
380 |
524 |
return (1); |
|
381 |
} |
||
382 |
44 |
s->internal->init_off += ret; |
|
383 |
44 |
s->internal->init_num -= ret; |
|
384 |
44 |
frag_off += (ret -= DTLS1_HM_HEADER_LENGTH); |
|
385 |
} |
||
386 |
} |
||
387 |
return (0); |
||
388 |
524 |
} |
|
389 |
|||
390 |
|||
391 |
/* |
||
392 |
* Obtain handshake message of message type 'mt' (any if mt == -1), |
||
393 |
* maximum acceptable body length 'max'. |
||
394 |
* Read an entire handshake message. Handshake messages arrive in |
||
395 |
* fragments. |
||
396 |
*/ |
||
397 |
long |
||
398 |
dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) |
||
399 |
{ |
||
400 |
int i, al; |
||
401 |
struct hm_header_st *msg_hdr; |
||
402 |
unsigned char *p; |
||
403 |
unsigned long msg_len; |
||
404 |
|||
405 |
/* |
||
406 |
* s3->internal->tmp is used to store messages that are unexpected, caused |
||
407 |
* by the absence of an optional handshake message |
||
408 |
*/ |
||
409 |
✓✓ | 1464 |
if (S3I(s)->tmp.reuse_message) { |
410 |
160 |
S3I(s)->tmp.reuse_message = 0; |
|
411 |
✓✓✗✓ |
240 |
if ((mt >= 0) && (S3I(s)->tmp.message_type != mt)) { |
412 |
al = SSL_AD_UNEXPECTED_MESSAGE; |
||
413 |
SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); |
||
414 |
goto f_err; |
||
415 |
} |
||
416 |
160 |
*ok = 1; |
|
417 |
160 |
s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
418 |
160 |
s->internal->init_num = (int)S3I(s)->tmp.message_size; |
|
419 |
160 |
return s->internal->init_num; |
|
420 |
} |
||
421 |
|||
422 |
572 |
msg_hdr = &D1I(s)->r_msg_hdr; |
|
423 |
572 |
memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); |
|
424 |
|||
425 |
again: |
||
426 |
648 |
i = dtls1_get_message_fragment(s, st1, stn, max, ok); |
|
427 |
✓✓ | 1296 |
if (i == DTLS1_HM_BAD_FRAGMENT || |
428 |
648 |
i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ |
|
429 |
goto again; |
||
430 |
✓✓✓✓ |
768 |
else if (i <= 0 && !*ok) |
431 |
148 |
return i; |
|
432 |
|||
433 |
424 |
p = (unsigned char *)s->internal->init_buf->data; |
|
434 |
424 |
msg_len = msg_hdr->msg_len; |
|
435 |
|||
436 |
/* reconstruct message header */ |
||
437 |
424 |
*(p++) = msg_hdr->type; |
|
438 |
424 |
l2n3(msg_len, p); |
|
439 |
424 |
s2n (msg_hdr->seq, p); |
|
440 |
424 |
l2n3(0, p); |
|
441 |
424 |
l2n3(msg_len, p); |
|
442 |
|||
443 |
424 |
p -= DTLS1_HM_HEADER_LENGTH; |
|
444 |
424 |
msg_len += DTLS1_HM_HEADER_LENGTH; |
|
445 |
|||
446 |
424 |
tls1_finish_mac(s, p, msg_len); |
|
447 |
✗✓ | 424 |
if (s->internal->msg_callback) |
448 |
s->internal->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, msg_len, |
||
449 |
s, s->internal->msg_callback_arg); |
||
450 |
|||
451 |
424 |
memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); |
|
452 |
|||
453 |
/* Don't change sequence numbers while listening */ |
||
454 |
✓✗ | 424 |
if (!D1I(s)->listen) |
455 |
424 |
D1I(s)->handshake_read_seq++; |
|
456 |
|||
457 |
424 |
s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
458 |
424 |
return s->internal->init_num; |
|
459 |
|||
460 |
f_err: |
||
461 |
ssl3_send_alert(s, SSL3_AL_FATAL, al); |
||
462 |
*ok = 0; |
||
463 |
return -1; |
||
464 |
732 |
} |
|
465 |
|||
466 |
|||
467 |
static int |
||
468 |
dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max) |
||
469 |
{ |
||
470 |
size_t frag_off, frag_len, msg_len; |
||
471 |
|||
472 |
848 |
msg_len = msg_hdr->msg_len; |
|
473 |
424 |
frag_off = msg_hdr->frag_off; |
|
474 |
424 |
frag_len = msg_hdr->frag_len; |
|
475 |
|||
476 |
/* sanity checking */ |
||
477 |
✗✓ | 424 |
if ((frag_off + frag_len) > msg_len) { |
478 |
SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
||
479 |
return SSL_AD_ILLEGAL_PARAMETER; |
||
480 |
} |
||
481 |
|||
482 |
✗✓ | 424 |
if ((frag_off + frag_len) > (unsigned long)max) { |
483 |
SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
||
484 |
return SSL_AD_ILLEGAL_PARAMETER; |
||
485 |
} |
||
486 |
|||
487 |
✓✗ | 424 |
if ( D1I(s)->r_msg_hdr.frag_off == 0) /* first fragment */ |
488 |
{ |
||
489 |
/* |
||
490 |
* msg_len is limited to 2^24, but is effectively checked |
||
491 |
* against max above |
||
492 |
*/ |
||
493 |
✗✓ | 848 |
if (!BUF_MEM_grow_clean(s->internal->init_buf, |
494 |
424 |
msg_len + DTLS1_HM_HEADER_LENGTH)) { |
|
495 |
SSLerror(s, ERR_R_BUF_LIB); |
||
496 |
return SSL_AD_INTERNAL_ERROR; |
||
497 |
} |
||
498 |
|||
499 |
424 |
S3I(s)->tmp.message_size = msg_len; |
|
500 |
424 |
D1I(s)->r_msg_hdr.msg_len = msg_len; |
|
501 |
424 |
S3I(s)->tmp.message_type = msg_hdr->type; |
|
502 |
424 |
D1I(s)->r_msg_hdr.type = msg_hdr->type; |
|
503 |
424 |
D1I(s)->r_msg_hdr.seq = msg_hdr->seq; |
|
504 |
✗✗ | 424 |
} else if (msg_len != D1I(s)->r_msg_hdr.msg_len) { |
505 |
/* |
||
506 |
* They must be playing with us! BTW, failure to enforce |
||
507 |
* upper limit would open possibility for buffer overrun. |
||
508 |
*/ |
||
509 |
SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
||
510 |
return SSL_AD_ILLEGAL_PARAMETER; |
||
511 |
} |
||
512 |
|||
513 |
424 |
return 0; /* no error */ |
|
514 |
424 |
} |
|
515 |
|||
516 |
static int |
||
517 |
dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) |
||
518 |
{ |
||
519 |
/* |
||
520 |
* (0) check whether the desired fragment is available |
||
521 |
* if so: |
||
522 |
* (1) copy over the fragment to s->internal->init_buf->data[] |
||
523 |
* (2) update s->internal->init_num |
||
524 |
*/ |
||
525 |
pitem *item; |
||
526 |
hm_fragment *frag; |
||
527 |
int al; |
||
528 |
|||
529 |
1296 |
*ok = 0; |
|
530 |
648 |
item = pqueue_peek(D1I(s)->buffered_messages); |
|
531 |
✓✓ | 648 |
if (item == NULL) |
532 |
572 |
return 0; |
|
533 |
|||
534 |
76 |
frag = (hm_fragment *)item->data; |
|
535 |
|||
536 |
/* Don't return if reassembly still in progress */ |
||
537 |
✓✓ | 76 |
if (frag->reassembly != NULL) |
538 |
44 |
return 0; |
|
539 |
|||
540 |
✓✗ | 32 |
if (D1I(s)->handshake_read_seq == frag->msg_header.seq) { |
541 |
32 |
unsigned long frag_len = frag->msg_header.frag_len; |
|
542 |
32 |
pqueue_pop(D1I(s)->buffered_messages); |
|
543 |
|||
544 |
32 |
al = dtls1_preprocess_fragment(s, &frag->msg_header, max); |
|
545 |
|||
546 |
✓✗ | 32 |
if (al == 0) /* no alert */ |
547 |
{ |
||
548 |
32 |
unsigned char *p = (unsigned char *)s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
549 |
64 |
memcpy(&p[frag->msg_header.frag_off], |
|
550 |
32 |
frag->fragment, frag->msg_header.frag_len); |
|
551 |
32 |
} |
|
552 |
|||
553 |
32 |
dtls1_hm_fragment_free(frag); |
|
554 |
32 |
pitem_free(item); |
|
555 |
|||
556 |
✓✗ | 32 |
if (al == 0) { |
557 |
32 |
*ok = 1; |
|
558 |
32 |
return frag_len; |
|
559 |
} |
||
560 |
|||
561 |
ssl3_send_alert(s, SSL3_AL_FATAL, al); |
||
562 |
s->internal->init_num = 0; |
||
563 |
*ok = 0; |
||
564 |
return -1; |
||
565 |
} else |
||
566 |
return 0; |
||
567 |
648 |
} |
|
568 |
|||
569 |
/* |
||
570 |
* dtls1_max_handshake_message_len returns the maximum number of bytes |
||
571 |
* permitted in a DTLS handshake message for |s|. The minimum is 16KB, |
||
572 |
* but may be greater if the maximum certificate list size requires it. |
||
573 |
*/ |
||
574 |
static unsigned long |
||
575 |
dtls1_max_handshake_message_len(const SSL *s) |
||
576 |
{ |
||
577 |
unsigned long max_len; |
||
578 |
|||
579 |
max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; |
||
580 |
✓✗ | 152 |
if (max_len < (unsigned long)s->internal->max_cert_list) |
581 |
76 |
return s->internal->max_cert_list; |
|
582 |
return max_len; |
||
583 |
76 |
} |
|
584 |
|||
585 |
static int |
||
586 |
dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) |
||
587 |
{ |
||
588 |
hm_fragment *frag = NULL; |
||
589 |
pitem *item = NULL; |
||
590 |
int i = -1, is_complete; |
||
591 |
152 |
unsigned char seq64be[8]; |
|
592 |
76 |
unsigned long frag_len = msg_hdr->frag_len; |
|
593 |
|||
594 |
✓✗✓✗ |
152 |
if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len || |
595 |
76 |
msg_hdr->msg_len > dtls1_max_handshake_message_len(s)) |
|
596 |
goto err; |
||
597 |
|||
598 |
✗✓ | 76 |
if (frag_len == 0) { |
599 |
i = DTLS1_HM_FRAGMENT_RETRY; |
||
600 |
goto err; |
||
601 |
} |
||
602 |
|||
603 |
/* Try to find item in queue */ |
||
604 |
76 |
memset(seq64be, 0, sizeof(seq64be)); |
|
605 |
76 |
seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); |
|
606 |
76 |
seq64be[7] = (unsigned char)msg_hdr->seq; |
|
607 |
76 |
item = pqueue_find(D1I(s)->buffered_messages, seq64be); |
|
608 |
|||
609 |
✓✓ | 76 |
if (item == NULL) { |
610 |
32 |
frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); |
|
611 |
✓✗ | 32 |
if (frag == NULL) |
612 |
goto err; |
||
613 |
32 |
memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); |
|
614 |
32 |
frag->msg_header.frag_len = frag->msg_header.msg_len; |
|
615 |
32 |
frag->msg_header.frag_off = 0; |
|
616 |
32 |
} else { |
|
617 |
44 |
frag = (hm_fragment*)item->data; |
|
618 |
✗✓ | 44 |
if (frag->msg_header.msg_len != msg_hdr->msg_len) { |
619 |
item = NULL; |
||
620 |
frag = NULL; |
||
621 |
goto err; |
||
622 |
} |
||
623 |
} |
||
624 |
|||
625 |
/* |
||
626 |
* If message is already reassembled, this must be a |
||
627 |
* retransmit and can be dropped. |
||
628 |
*/ |
||
629 |
✗✓ | 76 |
if (frag->reassembly == NULL) { |
630 |
unsigned char devnull [256]; |
||
631 |
|||
632 |
while (frag_len) { |
||
633 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
||
634 |
devnull, frag_len > sizeof(devnull) ? |
||
635 |
sizeof(devnull) : frag_len, 0); |
||
636 |
if (i <= 0) |
||
637 |
goto err; |
||
638 |
frag_len -= i; |
||
639 |
} |
||
640 |
i = DTLS1_HM_FRAGMENT_RETRY; |
||
641 |
goto err; |
||
642 |
} |
||
643 |
|||
644 |
/* read the body of the fragment (header has already been read */ |
||
645 |
152 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
|
646 |
76 |
frag->fragment + msg_hdr->frag_off, frag_len, 0); |
|
647 |
✓✗✓✗ |
152 |
if (i <= 0 || (unsigned long)i != frag_len) |
648 |
goto err; |
||
649 |
|||
650 |
✓✓✓✓ ✓✓ |
15328 |
RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off, |
651 |
(long)(msg_hdr->frag_off + frag_len)); |
||
652 |
|||
653 |
✗✓✓✓ ✓✓✓✓ ✗✓ |
22980 |
RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len, |
654 |
is_complete); |
||
655 |
|||
656 |
✓✓ | 76 |
if (is_complete) { |
657 |
32 |
free(frag->reassembly); |
|
658 |
32 |
frag->reassembly = NULL; |
|
659 |
32 |
} |
|
660 |
|||
661 |
✓✓ | 76 |
if (item == NULL) { |
662 |
32 |
memset(seq64be, 0, sizeof(seq64be)); |
|
663 |
32 |
seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); |
|
664 |
32 |
seq64be[7] = (unsigned char)(msg_hdr->seq); |
|
665 |
|||
666 |
32 |
item = pitem_new(seq64be, frag); |
|
667 |
✗✓ | 32 |
if (item == NULL) { |
668 |
i = -1; |
||
669 |
goto err; |
||
670 |
} |
||
671 |
|||
672 |
32 |
pqueue_insert(D1I(s)->buffered_messages, item); |
|
673 |
32 |
} |
|
674 |
|||
675 |
76 |
return DTLS1_HM_FRAGMENT_RETRY; |
|
676 |
|||
677 |
err: |
||
678 |
if (item == NULL && frag != NULL) |
||
679 |
dtls1_hm_fragment_free(frag); |
||
680 |
*ok = 0; |
||
681 |
return i; |
||
682 |
76 |
} |
|
683 |
|||
684 |
|||
685 |
static int |
||
686 |
dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) |
||
687 |
{ |
||
688 |
int i = -1; |
||
689 |
hm_fragment *frag = NULL; |
||
690 |
pitem *item = NULL; |
||
691 |
unsigned char seq64be[8]; |
||
692 |
unsigned long frag_len = msg_hdr->frag_len; |
||
693 |
|||
694 |
if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len) |
||
695 |
goto err; |
||
696 |
|||
697 |
/* Try to find item in queue, to prevent duplicate entries */ |
||
698 |
memset(seq64be, 0, sizeof(seq64be)); |
||
699 |
seq64be[6] = (unsigned char) (msg_hdr->seq >> 8); |
||
700 |
seq64be[7] = (unsigned char) msg_hdr->seq; |
||
701 |
item = pqueue_find(D1I(s)->buffered_messages, seq64be); |
||
702 |
|||
703 |
/* |
||
704 |
* If we already have an entry and this one is a fragment, |
||
705 |
* don't discard it and rather try to reassemble it. |
||
706 |
*/ |
||
707 |
if (item != NULL && frag_len < msg_hdr->msg_len) |
||
708 |
item = NULL; |
||
709 |
|||
710 |
/* |
||
711 |
* Discard the message if sequence number was already there, is |
||
712 |
* too far in the future, already in the queue or if we received |
||
713 |
* a FINISHED before the SERVER_HELLO, which then must be a stale |
||
714 |
* retransmit. |
||
715 |
*/ |
||
716 |
if (msg_hdr->seq <= D1I(s)->handshake_read_seq || |
||
717 |
msg_hdr->seq > D1I(s)->handshake_read_seq + 10 || item != NULL || |
||
718 |
(D1I(s)->handshake_read_seq == 0 && |
||
719 |
msg_hdr->type == SSL3_MT_FINISHED)) { |
||
720 |
unsigned char devnull [256]; |
||
721 |
|||
722 |
while (frag_len) { |
||
723 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
||
724 |
devnull, frag_len > sizeof(devnull) ? |
||
725 |
sizeof(devnull) : frag_len, 0); |
||
726 |
if (i <= 0) |
||
727 |
goto err; |
||
728 |
frag_len -= i; |
||
729 |
} |
||
730 |
} else { |
||
731 |
if (frag_len < msg_hdr->msg_len) |
||
732 |
return dtls1_reassemble_fragment(s, msg_hdr, ok); |
||
733 |
|||
734 |
if (frag_len > dtls1_max_handshake_message_len(s)) |
||
735 |
goto err; |
||
736 |
|||
737 |
frag = dtls1_hm_fragment_new(frag_len, 0); |
||
738 |
if (frag == NULL) |
||
739 |
goto err; |
||
740 |
|||
741 |
memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); |
||
742 |
|||
743 |
if (frag_len) { |
||
744 |
/* read the body of the fragment (header has already been read */ |
||
745 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
||
746 |
frag->fragment, frag_len, 0); |
||
747 |
if (i <= 0 || (unsigned long)i != frag_len) |
||
748 |
goto err; |
||
749 |
} |
||
750 |
|||
751 |
memset(seq64be, 0, sizeof(seq64be)); |
||
752 |
seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); |
||
753 |
seq64be[7] = (unsigned char)(msg_hdr->seq); |
||
754 |
|||
755 |
item = pitem_new(seq64be, frag); |
||
756 |
if (item == NULL) |
||
757 |
goto err; |
||
758 |
|||
759 |
pqueue_insert(D1I(s)->buffered_messages, item); |
||
760 |
} |
||
761 |
|||
762 |
return DTLS1_HM_FRAGMENT_RETRY; |
||
763 |
|||
764 |
err: |
||
765 |
if (item == NULL && frag != NULL) |
||
766 |
dtls1_hm_fragment_free(frag); |
||
767 |
*ok = 0; |
||
768 |
return i; |
||
769 |
} |
||
770 |
|||
771 |
|||
772 |
static long |
||
773 |
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) |
||
774 |
{ |
||
775 |
1296 |
unsigned char wire[DTLS1_HM_HEADER_LENGTH]; |
|
776 |
unsigned long len, frag_off, frag_len; |
||
777 |
int i, al; |
||
778 |
648 |
struct hm_header_st msg_hdr; |
|
779 |
|||
780 |
again: |
||
781 |
/* see if we have the required fragment already */ |
||
782 |
✓✓✗✓ |
1264 |
if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) { |
783 |
✓✗ | 32 |
if (*ok) |
784 |
32 |
s->internal->init_num = frag_len; |
|
785 |
32 |
return frag_len; |
|
786 |
} |
||
787 |
|||
788 |
/* read handshake message header */ |
||
789 |
616 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire, |
|
790 |
DTLS1_HM_HEADER_LENGTH, 0); |
||
791 |
✓✓ | 616 |
if (i <= 0) /* nbio, or an error */ |
792 |
{ |
||
793 |
148 |
s->internal->rwstate = SSL_READING; |
|
794 |
148 |
*ok = 0; |
|
795 |
148 |
return i; |
|
796 |
} |
||
797 |
/* Handshake fails if message header is incomplete */ |
||
798 |
✓✗✗✓ |
936 |
if (i != DTLS1_HM_HEADER_LENGTH || |
799 |
/* parse the message fragment header */ |
||
800 |
468 |
dtls1_get_message_header(wire, &msg_hdr) == 0) { |
|
801 |
al = SSL_AD_UNEXPECTED_MESSAGE; |
||
802 |
SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); |
||
803 |
goto f_err; |
||
804 |
} |
||
805 |
|||
806 |
/* |
||
807 |
* if this is a future (or stale) message it gets buffered |
||
808 |
* (or dropped)--no further processing at this time |
||
809 |
* While listening, we accept seq 1 (ClientHello with cookie) |
||
810 |
* although we're still expecting seq 0 (ClientHello) |
||
811 |
*/ |
||
812 |
✗✓✗✗ |
468 |
if (msg_hdr.seq != D1I(s)->handshake_read_seq && |
813 |
!(D1I(s)->listen && msg_hdr.seq == 1)) |
||
814 |
return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); |
||
815 |
|||
816 |
468 |
len = msg_hdr.msg_len; |
|
817 |
468 |
frag_off = msg_hdr.frag_off; |
|
818 |
468 |
frag_len = msg_hdr.frag_len; |
|
819 |
|||
820 |
✓✓✓✓ |
888 |
if (frag_len && frag_len < len) |
821 |
76 |
return dtls1_reassemble_fragment(s, &msg_hdr, ok); |
|
822 |
|||
823 |
✓✓✓✗ ✗✓ |
888 |
if (!s->server && D1I(s)->r_msg_hdr.frag_off == 0 && |
824 |
248 |
wire[0] == SSL3_MT_HELLO_REQUEST) { |
|
825 |
/* |
||
826 |
* The server may always send 'Hello Request' messages -- |
||
827 |
* we are doing a handshake anyway now, so ignore them |
||
828 |
* if their format is correct. Does not count for |
||
829 |
* 'Finished' MAC. |
||
830 |
*/ |
||
831 |
if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) { |
||
832 |
if (s->internal->msg_callback) |
||
833 |
s->internal->msg_callback(0, s->version, |
||
834 |
SSL3_RT_HANDSHAKE, wire, |
||
835 |
DTLS1_HM_HEADER_LENGTH, s, |
||
836 |
s->internal->msg_callback_arg); |
||
837 |
|||
838 |
s->internal->init_num = 0; |
||
839 |
goto again; |
||
840 |
} |
||
841 |
else /* Incorrectly formated Hello request */ |
||
842 |
{ |
||
843 |
al = SSL_AD_UNEXPECTED_MESSAGE; |
||
844 |
SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); |
||
845 |
goto f_err; |
||
846 |
} |
||
847 |
} |
||
848 |
|||
849 |
✓✗ | 392 |
if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max))) |
850 |
goto f_err; |
||
851 |
|||
852 |
/* XDTLS: ressurect this when restart is in place */ |
||
853 |
392 |
S3I(s)->hs.state = stn; |
|
854 |
|||
855 |
✓✓ | 392 |
if (frag_len > 0) { |
856 |
344 |
unsigned char *p = (unsigned char *)s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; |
|
857 |
|||
858 |
688 |
i = s->method->internal->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, |
|
859 |
344 |
&p[frag_off], frag_len, 0); |
|
860 |
/* XDTLS: fix this--message fragments cannot span multiple packets */ |
||
861 |
✗✓ | 344 |
if (i <= 0) { |
862 |
s->internal->rwstate = SSL_READING; |
||
863 |
*ok = 0; |
||
864 |
return i; |
||
865 |
} |
||
866 |
✓✗ | 344 |
} else |
867 |
i = 0; |
||
868 |
|||
869 |
/* |
||
870 |
* XDTLS: an incorrectly formatted fragment should cause the |
||
871 |
* handshake to fail |
||
872 |
*/ |
||
873 |
✗✓ | 392 |
if (i != (int)frag_len) { |
874 |
al = SSL3_AD_ILLEGAL_PARAMETER; |
||
875 |
SSLerror(s, SSL3_AD_ILLEGAL_PARAMETER); |
||
876 |
goto f_err; |
||
877 |
} |
||
878 |
|||
879 |
392 |
*ok = 1; |
|
880 |
|||
881 |
/* |
||
882 |
* Note that s->internal->init_num is *not* used as current offset in |
||
883 |
* s->internal->init_buf->data, but as a counter summing up fragments' |
||
884 |
* lengths: as soon as they sum up to handshake packet |
||
885 |
* length, we assume we have got all the fragments. |
||
886 |
*/ |
||
887 |
392 |
s->internal->init_num = frag_len; |
|
888 |
392 |
return frag_len; |
|
889 |
|||
890 |
f_err: |
||
891 |
ssl3_send_alert(s, SSL3_AL_FATAL, al); |
||
892 |
s->internal->init_num = 0; |
||
893 |
|||
894 |
*ok = 0; |
||
895 |
return (-1); |
||
896 |
648 |
} |
|
897 |
|||
898 |
/* |
||
899 |
* for these 2 messages, we need to |
||
900 |
* ssl->enc_read_ctx re-init |
||
901 |
* ssl->s3->internal->read_sequence zero |
||
902 |
* ssl->s3->internal->read_mac_secret re-init |
||
903 |
* ssl->session->read_sym_enc assign |
||
904 |
* ssl->session->read_hash assign |
||
905 |
*/ |
||
906 |
int |
||
907 |
dtls1_send_change_cipher_spec(SSL *s, int a, int b) |
||
908 |
{ |
||
909 |
unsigned char *p; |
||
910 |
|||
911 |
✓✗ | 192 |
if (S3I(s)->hs.state == a) { |
912 |
96 |
p = (unsigned char *)s->internal->init_buf->data; |
|
913 |
96 |
*p++=SSL3_MT_CCS; |
|
914 |
96 |
D1I(s)->handshake_write_seq = D1I(s)->next_handshake_write_seq; |
|
915 |
96 |
s->internal->init_num = DTLS1_CCS_HEADER_LENGTH; |
|
916 |
|||
917 |
96 |
s->internal->init_off = 0; |
|
918 |
|||
919 |
96 |
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, |
|
920 |
96 |
D1I(s)->handshake_write_seq, 0, 0); |
|
921 |
|||
922 |
/* buffer the message to handle re-xmits */ |
||
923 |
96 |
dtls1_buffer_message(s, 1); |
|
924 |
|||
925 |
96 |
S3I(s)->hs.state = b; |
|
926 |
96 |
} |
|
927 |
|||
928 |
/* SSL3_ST_CW_CHANGE_B */ |
||
929 |
96 |
return (dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC)); |
|
930 |
} |
||
931 |
|||
932 |
int |
||
933 |
dtls1_read_failed(SSL *s, int code) |
||
934 |
{ |
||
935 |
✗✓ | 392 |
if (code > 0) { |
936 |
#ifdef DEBUG |
||
937 |
fprintf(stderr, "invalid state reached %s:%d", |
||
938 |
__FILE__, __LINE__); |
||
939 |
#endif |
||
940 |
return 1; |
||
941 |
} |
||
942 |
|||
943 |
✓✗ | 196 |
if (!dtls1_is_timer_expired(s)) { |
944 |
/* |
||
945 |
* not a timeout, none of our business, let higher layers |
||
946 |
* handle this. in fact it's probably an error |
||
947 |
*/ |
||
948 |
196 |
return code; |
|
949 |
} |
||
950 |
|||
951 |
if (!SSL_in_init(s)) /* done, no need to send a retransmit */ |
||
952 |
{ |
||
953 |
BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ); |
||
954 |
return code; |
||
955 |
} |
||
956 |
|||
957 |
return dtls1_handle_timeout(s); |
||
958 |
196 |
} |
|
959 |
|||
960 |
int |
||
961 |
dtls1_get_queue_priority(unsigned short seq, int is_ccs) |
||
962 |
{ |
||
963 |
/* |
||
964 |
* The index of the retransmission queue actually is the message |
||
965 |
* sequence number, since the queue only contains messages of a |
||
966 |
* single handshake. However, the ChangeCipherSpec has no message |
||
967 |
* sequence number and so using only the sequence will result in |
||
968 |
* the CCS and Finished having the same index. To prevent this, the |
||
969 |
* sequence number is multiplied by 2. In case of a CCS 1 is |
||
970 |
* subtracted. This does not only differ CSS and Finished, it also |
||
971 |
* maintains the order of the index (important for priority queues) |
||
972 |
* and fits in the unsigned short variable. |
||
973 |
*/ |
||
974 |
2096 |
return seq * 2 - is_ccs; |
|
975 |
} |
||
976 |
|||
977 |
int |
||
978 |
dtls1_retransmit_buffered_messages(SSL *s) |
||
979 |
{ |
||
980 |
pqueue sent = s->d1->sent_messages; |
||
981 |
piterator iter; |
||
982 |
pitem *item; |
||
983 |
hm_fragment *frag; |
||
984 |
int found = 0; |
||
985 |
|||
986 |
iter = pqueue_iterator(sent); |
||
987 |
|||
988 |
for (item = pqueue_next(&iter); item != NULL; |
||
989 |
item = pqueue_next(&iter)) { |
||
990 |
frag = (hm_fragment *)item->data; |
||
991 |
if (dtls1_retransmit_message(s, |
||
992 |
(unsigned short)dtls1_get_queue_priority( |
||
993 |
frag->msg_header.seq, frag->msg_header.is_ccs), 0, |
||
994 |
&found) <= 0 && found) { |
||
995 |
#ifdef DEBUG |
||
996 |
fprintf(stderr, "dtls1_retransmit_message() failed\n"); |
||
997 |
#endif |
||
998 |
return -1; |
||
999 |
} |
||
1000 |
} |
||
1001 |
|||
1002 |
return 1; |
||
1003 |
} |
||
1004 |
|||
1005 |
int |
||
1006 |
dtls1_buffer_message(SSL *s, int is_ccs) |
||
1007 |
{ |
||
1008 |
pitem *item; |
||
1009 |
hm_fragment *frag; |
||
1010 |
1048 |
unsigned char seq64be[8]; |
|
1011 |
|||
1012 |
/* Buffer the messsage in order to handle DTLS retransmissions. */ |
||
1013 |
|||
1014 |
/* |
||
1015 |
* This function is called immediately after a message has |
||
1016 |
* been serialized |
||
1017 |
*/ |
||
1018 |
✗✓ | 524 |
OPENSSL_assert(s->internal->init_off == 0); |
1019 |
|||
1020 |
524 |
frag = dtls1_hm_fragment_new(s->internal->init_num, 0); |
|
1021 |
✗✓ | 524 |
if (frag == NULL) |
1022 |
return 0; |
||
1023 |
|||
1024 |
524 |
memcpy(frag->fragment, s->internal->init_buf->data, s->internal->init_num); |
|
1025 |
|||
1026 |
✓✓ | 524 |
if (is_ccs) { |
1027 |
✗✓ | 96 |
OPENSSL_assert(D1I(s)->w_msg_hdr.msg_len + |
1028 |
((s->version == DTLS1_VERSION) ? |
||
1029 |
DTLS1_CCS_HEADER_LENGTH : 3) == (unsigned int)s->internal->init_num); |
||
1030 |
} else { |
||
1031 |
✗✓ | 428 |
OPENSSL_assert(D1I(s)->w_msg_hdr.msg_len + |
1032 |
DTLS1_HM_HEADER_LENGTH == (unsigned int)s->internal->init_num); |
||
1033 |
} |
||
1034 |
|||
1035 |
524 |
frag->msg_header.msg_len = D1I(s)->w_msg_hdr.msg_len; |
|
1036 |
524 |
frag->msg_header.seq = D1I(s)->w_msg_hdr.seq; |
|
1037 |
524 |
frag->msg_header.type = D1I(s)->w_msg_hdr.type; |
|
1038 |
524 |
frag->msg_header.frag_off = 0; |
|
1039 |
524 |
frag->msg_header.frag_len = D1I(s)->w_msg_hdr.msg_len; |
|
1040 |
524 |
frag->msg_header.is_ccs = is_ccs; |
|
1041 |
|||
1042 |
/* save current state*/ |
||
1043 |
524 |
frag->msg_header.saved_retransmit_state.enc_write_ctx = s->internal->enc_write_ctx; |
|
1044 |
524 |
frag->msg_header.saved_retransmit_state.write_hash = s->internal->write_hash; |
|
1045 |
524 |
frag->msg_header.saved_retransmit_state.session = s->session; |
|
1046 |
524 |
frag->msg_header.saved_retransmit_state.epoch = D1I(s)->w_epoch; |
|
1047 |
|||
1048 |
524 |
memset(seq64be, 0, sizeof(seq64be)); |
|
1049 |
1048 |
seq64be[6] = (unsigned char)(dtls1_get_queue_priority( |
|
1050 |
1048 |
frag->msg_header.seq, frag->msg_header.is_ccs) >> 8); |
|
1051 |
524 |
seq64be[7] = (unsigned char)(dtls1_get_queue_priority( |
|
1052 |
524 |
frag->msg_header.seq, frag->msg_header.is_ccs)); |
|
1053 |
|||
1054 |
524 |
item = pitem_new(seq64be, frag); |
|
1055 |
✗✓ | 524 |
if (item == NULL) { |
1056 |
dtls1_hm_fragment_free(frag); |
||
1057 |
return 0; |
||
1058 |
} |
||
1059 |
|||
1060 |
524 |
pqueue_insert(s->d1->sent_messages, item); |
|
1061 |
524 |
return 1; |
|
1062 |
524 |
} |
|
1063 |
|||
1064 |
int |
||
1065 |
dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, |
||
1066 |
int *found) |
||
1067 |
{ |
||
1068 |
int ret; |
||
1069 |
/* XDTLS: for now assuming that read/writes are blocking */ |
||
1070 |
pitem *item; |
||
1071 |
hm_fragment *frag; |
||
1072 |
unsigned long header_length; |
||
1073 |
unsigned char seq64be[8]; |
||
1074 |
struct dtls1_retransmit_state saved_state; |
||
1075 |
unsigned char save_write_sequence[8]; |
||
1076 |
|||
1077 |
/* |
||
1078 |
OPENSSL_assert(s->internal->init_num == 0); |
||
1079 |
OPENSSL_assert(s->internal->init_off == 0); |
||
1080 |
*/ |
||
1081 |
|||
1082 |
/* XDTLS: the requested message ought to be found, otherwise error */ |
||
1083 |
memset(seq64be, 0, sizeof(seq64be)); |
||
1084 |
seq64be[6] = (unsigned char)(seq >> 8); |
||
1085 |
seq64be[7] = (unsigned char)seq; |
||
1086 |
|||
1087 |
item = pqueue_find(s->d1->sent_messages, seq64be); |
||
1088 |
if (item == NULL) { |
||
1089 |
#ifdef DEBUG |
||
1090 |
fprintf(stderr, "retransmit: message %d non-existant\n", seq); |
||
1091 |
#endif |
||
1092 |
*found = 0; |
||
1093 |
return 0; |
||
1094 |
} |
||
1095 |
|||
1096 |
*found = 1; |
||
1097 |
frag = (hm_fragment *)item->data; |
||
1098 |
|||
1099 |
if (frag->msg_header.is_ccs) |
||
1100 |
header_length = DTLS1_CCS_HEADER_LENGTH; |
||
1101 |
else |
||
1102 |
header_length = DTLS1_HM_HEADER_LENGTH; |
||
1103 |
|||
1104 |
memcpy(s->internal->init_buf->data, frag->fragment, |
||
1105 |
frag->msg_header.msg_len + header_length); |
||
1106 |
s->internal->init_num = frag->msg_header.msg_len + header_length; |
||
1107 |
|||
1108 |
dtls1_set_message_header_int(s, frag->msg_header.type, |
||
1109 |
frag->msg_header.msg_len, frag->msg_header.seq, 0, |
||
1110 |
frag->msg_header.frag_len); |
||
1111 |
|||
1112 |
/* save current state */ |
||
1113 |
saved_state.enc_write_ctx = s->internal->enc_write_ctx; |
||
1114 |
saved_state.write_hash = s->internal->write_hash; |
||
1115 |
saved_state.session = s->session; |
||
1116 |
saved_state.epoch = D1I(s)->w_epoch; |
||
1117 |
|||
1118 |
D1I(s)->retransmitting = 1; |
||
1119 |
|||
1120 |
/* restore state in which the message was originally sent */ |
||
1121 |
s->internal->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx; |
||
1122 |
s->internal->write_hash = frag->msg_header.saved_retransmit_state.write_hash; |
||
1123 |
s->session = frag->msg_header.saved_retransmit_state.session; |
||
1124 |
D1I(s)->w_epoch = frag->msg_header.saved_retransmit_state.epoch; |
||
1125 |
|||
1126 |
if (frag->msg_header.saved_retransmit_state.epoch == |
||
1127 |
saved_state.epoch - 1) { |
||
1128 |
memcpy(save_write_sequence, S3I(s)->write_sequence, |
||
1129 |
sizeof(S3I(s)->write_sequence)); |
||
1130 |
memcpy(S3I(s)->write_sequence, D1I(s)->last_write_sequence, |
||
1131 |
sizeof(S3I(s)->write_sequence)); |
||
1132 |
} |
||
1133 |
|||
1134 |
ret = dtls1_do_write(s, frag->msg_header.is_ccs ? |
||
1135 |
SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); |
||
1136 |
|||
1137 |
/* restore current state */ |
||
1138 |
s->internal->enc_write_ctx = saved_state.enc_write_ctx; |
||
1139 |
s->internal->write_hash = saved_state.write_hash; |
||
1140 |
s->session = saved_state.session; |
||
1141 |
D1I(s)->w_epoch = saved_state.epoch; |
||
1142 |
|||
1143 |
if (frag->msg_header.saved_retransmit_state.epoch == |
||
1144 |
saved_state.epoch - 1) { |
||
1145 |
memcpy(D1I(s)->last_write_sequence, S3I(s)->write_sequence, |
||
1146 |
sizeof(S3I(s)->write_sequence)); |
||
1147 |
memcpy(S3I(s)->write_sequence, save_write_sequence, |
||
1148 |
sizeof(S3I(s)->write_sequence)); |
||
1149 |
} |
||
1150 |
|||
1151 |
D1I(s)->retransmitting = 0; |
||
1152 |
|||
1153 |
(void)BIO_flush(SSL_get_wbio(s)); |
||
1154 |
return ret; |
||
1155 |
} |
||
1156 |
|||
1157 |
/* call this function when the buffered messages are no longer needed */ |
||
1158 |
void |
||
1159 |
dtls1_clear_record_buffer(SSL *s) |
||
1160 |
{ |
||
1161 |
pitem *item; |
||
1162 |
|||
1163 |
✓✓ | 1472 |
for(item = pqueue_pop(s->d1->sent_messages); item != NULL; |
1164 |
376 |
item = pqueue_pop(s->d1->sent_messages)) { |
|
1165 |
376 |
dtls1_hm_fragment_free((hm_fragment *)item->data); |
|
1166 |
376 |
pitem_free(item); |
|
1167 |
} |
||
1168 |
240 |
} |
|
1169 |
|||
1170 |
void |
||
1171 |
dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len, |
||
1172 |
unsigned long frag_off, unsigned long frag_len) |
||
1173 |
{ |
||
1174 |
/* Don't change sequence numbers while listening */ |
||
1175 |
✓✗✓✗ |
1284 |
if (frag_off == 0 && !D1I(s)->listen) { |
1176 |
428 |
D1I(s)->handshake_write_seq = D1I(s)->next_handshake_write_seq; |
|
1177 |
428 |
D1I(s)->next_handshake_write_seq++; |
|
1178 |
428 |
} |
|
1179 |
|||
1180 |
428 |
dtls1_set_message_header_int(s, mt, len, D1I(s)->handshake_write_seq, |
|
1181 |
frag_off, frag_len); |
||
1182 |
428 |
} |
|
1183 |
|||
1184 |
/* don't actually do the writing, wait till the MTU has been retrieved */ |
||
1185 |
static void |
||
1186 |
dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len, |
||
1187 |
unsigned short seq_num, unsigned long frag_off, unsigned long frag_len) |
||
1188 |
{ |
||
1189 |
1048 |
struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
1190 |
|||
1191 |
524 |
msg_hdr->type = mt; |
|
1192 |
524 |
msg_hdr->msg_len = len; |
|
1193 |
524 |
msg_hdr->seq = seq_num; |
|
1194 |
524 |
msg_hdr->frag_off = frag_off; |
|
1195 |
524 |
msg_hdr->frag_len = frag_len; |
|
1196 |
524 |
} |
|
1197 |
|||
1198 |
static void |
||
1199 |
dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len) |
||
1200 |
{ |
||
1201 |
944 |
struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
1202 |
|||
1203 |
472 |
msg_hdr->frag_off = frag_off; |
|
1204 |
472 |
msg_hdr->frag_len = frag_len; |
|
1205 |
472 |
} |
|
1206 |
|||
1207 |
static unsigned char * |
||
1208 |
dtls1_write_message_header(SSL *s, unsigned char *p) |
||
1209 |
{ |
||
1210 |
944 |
struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; |
|
1211 |
|||
1212 |
472 |
*p++ = msg_hdr->type; |
|
1213 |
472 |
l2n3(msg_hdr->msg_len, p); |
|
1214 |
|||
1215 |
472 |
s2n(msg_hdr->seq, p); |
|
1216 |
472 |
l2n3(msg_hdr->frag_off, p); |
|
1217 |
472 |
l2n3(msg_hdr->frag_len, p); |
|
1218 |
|||
1219 |
472 |
return p; |
|
1220 |
} |
||
1221 |
|||
1222 |
unsigned int |
||
1223 |
dtls1_min_mtu(void) |
||
1224 |
{ |
||
1225 |
2296 |
return (g_probable_mtu[(sizeof(g_probable_mtu) / |
|
1226 |
sizeof(g_probable_mtu[0])) - 1]); |
||
1227 |
} |
||
1228 |
|||
1229 |
static unsigned int |
||
1230 |
dtls1_guess_mtu(unsigned int curr_mtu) |
||
1231 |
{ |
||
1232 |
unsigned int i; |
||
1233 |
|||
1234 |
✓✗ | 200 |
if (curr_mtu == 0) |
1235 |
100 |
return g_probable_mtu[0]; |
|
1236 |
|||
1237 |
for (i = 0; i < sizeof(g_probable_mtu) / sizeof(g_probable_mtu[0]); i++) |
||
1238 |
if (curr_mtu > g_probable_mtu[i]) |
||
1239 |
return g_probable_mtu[i]; |
||
1240 |
|||
1241 |
return curr_mtu; |
||
1242 |
100 |
} |
|
1243 |
|||
1244 |
int |
||
1245 |
dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) |
||
1246 |
{ |
||
1247 |
936 |
CBS header; |
|
1248 |
468 |
uint32_t msg_len, frag_off, frag_len; |
|
1249 |
468 |
uint16_t seq; |
|
1250 |
468 |
uint8_t type; |
|
1251 |
|||
1252 |
468 |
CBS_init(&header, data, sizeof(*msg_hdr)); |
|
1253 |
|||
1254 |
468 |
memset(msg_hdr, 0, sizeof(*msg_hdr)); |
|
1255 |
|||
1256 |
✗✓ | 468 |
if (!CBS_get_u8(&header, &type)) |
1257 |
return 0; |
||
1258 |
✗✓ | 468 |
if (!CBS_get_u24(&header, &msg_len)) |
1259 |
return 0; |
||
1260 |
✗✓ | 468 |
if (!CBS_get_u16(&header, &seq)) |
1261 |
return 0; |
||
1262 |
✗✓ | 468 |
if (!CBS_get_u24(&header, &frag_off)) |
1263 |
return 0; |
||
1264 |
✗✓ | 468 |
if (!CBS_get_u24(&header, &frag_len)) |
1265 |
return 0; |
||
1266 |
|||
1267 |
468 |
msg_hdr->type = type; |
|
1268 |
468 |
msg_hdr->msg_len = msg_len; |
|
1269 |
468 |
msg_hdr->seq = seq; |
|
1270 |
468 |
msg_hdr->frag_off = frag_off; |
|
1271 |
468 |
msg_hdr->frag_len = frag_len; |
|
1272 |
|||
1273 |
468 |
return 1; |
|
1274 |
468 |
} |
|
1275 |
|||
1276 |
void |
||
1277 |
dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr) |
||
1278 |
{ |
||
1279 |
192 |
memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st)); |
|
1280 |
|||
1281 |
96 |
ccs_hdr->type = *(data++); |
|
1282 |
96 |
} |
|
1283 |
|||
1284 |
int |
||
1285 |
dtls1_shutdown(SSL *s) |
||
1286 |
{ |
||
1287 |
int ret; |
||
1288 |
|||
1289 |
192 |
ret = ssl3_shutdown(s); |
|
1290 |
96 |
return ret; |
|
1291 |
} |
Generated by: GCOVR (Version 3.3) |