]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
da1c088f | 2 | * Copyright 2005-2023 The OpenSSL Project Authors. All Rights Reserved. |
0f113f3e | 3 | * |
2c18d164 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
846e33c7 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
36d16f8e BL |
8 | */ |
9 | ||
351ad225 | 10 | #include <assert.h> |
36d16f8e BL |
11 | #include <limits.h> |
12 | #include <string.h> | |
13 | #include <stdio.h> | |
706457b7 DMSP |
14 | #include "../ssl_local.h" |
15 | #include "statem_local.h" | |
67dc995e | 16 | #include "internal/cryptlib.h" |
36d16f8e | 17 | #include <openssl/buffer.h> |
36d16f8e BL |
18 | #include <openssl/objects.h> |
19 | #include <openssl/evp.h> | |
20 | #include <openssl/x509.h> | |
21 | ||
934e22e8 DSH |
22 | #define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8) |
23 | ||
24 | #define RSMBLY_BITMASK_MARK(bitmask, start, end) { \ | |
0f113f3e MC |
25 | if ((end) - (start) <= 8) { \ |
26 | long ii; \ | |
27 | for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \ | |
28 | } else { \ | |
29 | long ii; \ | |
30 | bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \ | |
31 | for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \ | |
32 | bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \ | |
33 | } } | |
934e22e8 DSH |
34 | |
35 | #define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ | |
0f113f3e | 36 | long ii; \ |
0f113f3e MC |
37 | is_complete = 1; \ |
38 | if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \ | |
39 | if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \ | |
40 | if (bitmask[ii] != 0xff) { is_complete = 0; break; } } | |
934e22e8 | 41 | |
0f113f3e MC |
42 | static unsigned char bitmask_start_values[] = |
43 | { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 }; | |
44 | static unsigned char bitmask_end_values[] = | |
45 | { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f }; | |
36d16f8e | 46 | |
38b051a1 | 47 | static void dtls1_fix_message_header(SSL_CONNECTION *s, size_t frag_off, |
7ee8627f | 48 | size_t frag_len); |
38b051a1 TM |
49 | static unsigned char *dtls1_write_message_header(SSL_CONNECTION *s, |
50 | unsigned char *p); | |
51 | static void dtls1_set_message_header_int(SSL_CONNECTION *s, unsigned char mt, | |
7ee8627f | 52 | size_t len, |
0f113f3e | 53 | unsigned short seq_num, |
7ee8627f MC |
54 | size_t frag_off, |
55 | size_t frag_len); | |
38b051a1 TM |
56 | static int dtls_get_reassembled_message(SSL_CONNECTION *s, int *errtype, |
57 | size_t *len); | |
0f113f3e | 58 | |
7ee8627f | 59 | static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly) |
0f113f3e MC |
60 | { |
61 | hm_fragment *frag = NULL; | |
62 | unsigned char *buf = NULL; | |
63 | unsigned char *bitmask = NULL; | |
64 | ||
e077455e | 65 | if ((frag = OPENSSL_malloc(sizeof(*frag))) == NULL) |
0f113f3e MC |
66 | return NULL; |
67 | ||
68 | if (frag_len) { | |
cdb10bae | 69 | if ((buf = OPENSSL_malloc(frag_len)) == NULL) { |
0f113f3e MC |
70 | OPENSSL_free(frag); |
71 | return NULL; | |
72 | } | |
73 | } | |
74 | ||
75 | /* zero length fragment gets zero frag->fragment */ | |
76 | frag->fragment = buf; | |
77 | ||
78 | /* Initialize reassembly bitmask if necessary */ | |
79 | if (reassembly) { | |
b51bce94 | 80 | bitmask = OPENSSL_zalloc(RSMBLY_BITMASK_SIZE(frag_len)); |
0f113f3e | 81 | if (bitmask == NULL) { |
b548a1f1 | 82 | OPENSSL_free(buf); |
0f113f3e MC |
83 | OPENSSL_free(frag); |
84 | return NULL; | |
85 | } | |
0f113f3e MC |
86 | } |
87 | ||
88 | frag->reassembly = bitmask; | |
89 | ||
90 | return frag; | |
91 | } | |
36d16f8e | 92 | |
8a35dbb6 | 93 | void dtls1_hm_fragment_free(hm_fragment *frag) |
0f113f3e | 94 | { |
25aaa98a RS |
95 | if (!frag) |
96 | return; | |
0f113f3e | 97 | if (frag->msg_header.is_ccs) { |
b9e37f8f MC |
98 | /* |
99 | * If we're freeing the CCS then we're done with the old wrl and it | |
100 | * can bee freed | |
101 | */ | |
102 | if (frag->msg_header.saved_retransmit_state.wrlmethod != NULL) | |
103 | frag->msg_header.saved_retransmit_state.wrlmethod->free(frag->msg_header.saved_retransmit_state.wrl); | |
0f113f3e | 104 | } |
b548a1f1 RS |
105 | OPENSSL_free(frag->fragment); |
106 | OPENSSL_free(frag->reassembly); | |
0f113f3e MC |
107 | OPENSSL_free(frag); |
108 | } | |
36d16f8e | 109 | |
0f113f3e MC |
110 | /* |
111 | * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or | |
112 | * SSL3_RT_CHANGE_CIPHER_SPEC) | |
113 | */ | |
eb1eaa9a | 114 | int dtls1_do_write(SSL_CONNECTION *s, uint8_t type) |
0f113f3e MC |
115 | { |
116 | int ret; | |
7ee8627f MC |
117 | size_t written; |
118 | size_t curr_mtu; | |
0f113f3e | 119 | int retry = 1; |
4f428e86 | 120 | size_t len, frag_off, overhead, used_len; |
38b051a1 | 121 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
0f113f3e MC |
122 | |
123 | if (!dtls1_query_mtu(s)) | |
124 | return -1; | |
125 | ||
50b4a9ba SGM |
126 | if (s->d1->mtu < dtls1_min_mtu(s)) |
127 | /* should have something reasonable now */ | |
128 | return -1; | |
0f113f3e | 129 | |
380a522f MC |
130 | if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE) { |
131 | if (!ossl_assert(s->init_num == | |
132 | s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH)) | |
133 | return -1; | |
134 | } | |
0f113f3e | 135 | |
4f428e86 | 136 | overhead = s->rlayer.wrlmethod->get_max_record_overhead(s->rlayer.wrl); |
0f113f3e MC |
137 | |
138 | frag_off = 0; | |
67f60be8 MC |
139 | s->rwstate = SSL_NOTHING; |
140 | ||
0f113f3e MC |
141 | /* s->init_num shouldn't ever be < 0...but just in case */ |
142 | while (s->init_num > 0) { | |
2ad226e8 MC |
143 | if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) { |
144 | /* We must be writing a fragment other than the first one */ | |
145 | ||
146 | if (frag_off > 0) { | |
147 | /* This is the first attempt at writing out this fragment */ | |
148 | ||
149 | if (s->init_off <= DTLS1_HM_HEADER_LENGTH) { | |
150 | /* | |
151 | * Each fragment that was already sent must at least have | |
152 | * contained the message header plus one other byte. | |
153 | * Therefore |init_off| must have progressed by at least | |
154 | * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went | |
155 | * wrong. | |
156 | */ | |
157 | return -1; | |
158 | } | |
159 | ||
160 | /* | |
161 | * Adjust |init_off| and |init_num| to allow room for a new | |
162 | * message header for this fragment. | |
163 | */ | |
164 | s->init_off -= DTLS1_HM_HEADER_LENGTH; | |
165 | s->init_num += DTLS1_HM_HEADER_LENGTH; | |
166 | } else { | |
167 | /* | |
168 | * We must have been called again after a retry so use the | |
169 | * fragment offset from our last attempt. We do not need | |
170 | * to adjust |init_off| and |init_num| as above, because | |
171 | * that should already have been done before the retry. | |
172 | */ | |
173 | frag_off = s->d1->w_msg_hdr.frag_off; | |
174 | } | |
175 | } | |
176 | ||
4f428e86 | 177 | used_len = BIO_wpending(s->wbio) + overhead; |
0f113f3e MC |
178 | if (s->d1->mtu > used_len) |
179 | curr_mtu = s->d1->mtu - used_len; | |
180 | else | |
181 | curr_mtu = 0; | |
182 | ||
183 | if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) { | |
184 | /* | |
185 | * grr.. we could get an error if MTU picked was wrong | |
186 | */ | |
2e7dc7cd | 187 | ret = BIO_flush(s->wbio); |
67f60be8 MC |
188 | if (ret <= 0) { |
189 | s->rwstate = SSL_WRITING; | |
0f113f3e | 190 | return ret; |
67f60be8 | 191 | } |
4f428e86 MC |
192 | if (s->d1->mtu > overhead + DTLS1_HM_HEADER_LENGTH) { |
193 | curr_mtu = s->d1->mtu - overhead; | |
0f113f3e MC |
194 | } else { |
195 | /* Shouldn't happen */ | |
196 | return -1; | |
197 | } | |
198 | } | |
199 | ||
200 | /* | |
201 | * We just checked that s->init_num > 0 so this cast should be safe | |
202 | */ | |
203 | if (((unsigned int)s->init_num) > curr_mtu) | |
204 | len = curr_mtu; | |
205 | else | |
206 | len = s->init_num; | |
207 | ||
e915c3f5 BE |
208 | if (len > ssl_get_max_send_fragment(s)) |
209 | len = ssl_get_max_send_fragment(s); | |
aefb9256 | 210 | |
0f113f3e MC |
211 | /* |
212 | * XDTLS: this function is too long. split out the CCS part | |
213 | */ | |
214 | if (type == SSL3_RT_HANDSHAKE) { | |
0f113f3e MC |
215 | if (len < DTLS1_HM_HEADER_LENGTH) { |
216 | /* | |
217 | * len is so small that we really can't do anything sensible | |
218 | * so fail | |
219 | */ | |
220 | return -1; | |
221 | } | |
a230b26e | 222 | dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH); |
0f113f3e MC |
223 | |
224 | dtls1_write_message_header(s, | |
225 | (unsigned char *)&s->init_buf-> | |
226 | data[s->init_off]); | |
227 | } | |
228 | ||
7ee8627f MC |
229 | ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len, |
230 | &written); | |
e915c3f5 | 231 | if (ret <= 0) { |
0f113f3e MC |
232 | /* |
233 | * might need to update MTU here, but we don't know which | |
234 | * previous packet caused the failure -- so can't really | |
235 | * retransmit anything. continue as if everything is fine and | |
236 | * wait for an alert to handle the retransmit | |
237 | */ | |
38b051a1 | 238 | if (retry && BIO_ctrl(SSL_get_wbio(ssl), |
0f113f3e | 239 | BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) { |
38b051a1 | 240 | if (!(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { |
0f113f3e MC |
241 | if (!dtls1_query_mtu(s)) |
242 | return -1; | |
243 | /* Have one more go */ | |
244 | retry = 0; | |
245 | } else | |
246 | return -1; | |
247 | } else { | |
380a522f | 248 | return -1; |
0f113f3e MC |
249 | } |
250 | } else { | |
251 | ||
252 | /* | |
253 | * bad if this assert fails, only part of the handshake message | |
254 | * got sent. but why would this happen? | |
255 | */ | |
380a522f MC |
256 | if (!ossl_assert(len == written)) |
257 | return -1; | |
0f113f3e | 258 | |
351ad225 MC |
259 | /* |
260 | * We should not exceed the MTU size. If compression is in use | |
261 | * then the max record overhead calculation is unreliable so we do | |
262 | * not check in that case. We use assert rather than ossl_assert | |
263 | * because in a production build, if this assert were ever to fail, | |
264 | * then the best thing to do is probably carry on regardless. | |
265 | */ | |
266 | assert(s->s3.tmp.new_compression != NULL | |
267 | || BIO_wpending(s->wbio) <= (int)s->d1->mtu); | |
268 | ||
0f113f3e MC |
269 | if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) { |
270 | /* | |
271 | * should not be done for 'Hello Request's, but in that case | |
272 | * we'll ignore the result anyway | |
273 | */ | |
274 | unsigned char *p = | |
275 | (unsigned char *)&s->init_buf->data[s->init_off]; | |
276 | const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; | |
7ee8627f | 277 | size_t xlen; |
0f113f3e MC |
278 | |
279 | if (frag_off == 0 && s->version != DTLS1_BAD_VER) { | |
280 | /* | |
281 | * reconstruct message header is if it is being sent in | |
282 | * single fragment | |
283 | */ | |
284 | *p++ = msg_hdr->type; | |
285 | l2n3(msg_hdr->msg_len, p); | |
286 | s2n(msg_hdr->seq, p); | |
287 | l2n3(0, p); | |
288 | l2n3(msg_hdr->msg_len, p); | |
289 | p -= DTLS1_HM_HEADER_LENGTH; | |
7ee8627f | 290 | xlen = written; |
0f113f3e MC |
291 | } else { |
292 | p += DTLS1_HM_HEADER_LENGTH; | |
7ee8627f | 293 | xlen = written - DTLS1_HM_HEADER_LENGTH; |
0f113f3e MC |
294 | } |
295 | ||
d166ed8c DSH |
296 | if (!ssl3_finish_mac(s, p, xlen)) |
297 | return -1; | |
0f113f3e MC |
298 | } |
299 | ||
7ee8627f | 300 | if (written == s->init_num) { |
0f113f3e MC |
301 | if (s->msg_callback) |
302 | s->msg_callback(1, s->version, type, s->init_buf->data, | |
38b051a1 | 303 | (size_t)(s->init_off + s->init_num), ssl, |
0f113f3e MC |
304 | s->msg_callback_arg); |
305 | ||
306 | s->init_off = 0; /* done writing this message */ | |
307 | s->init_num = 0; | |
308 | ||
7ee8627f | 309 | return 1; |
0f113f3e | 310 | } |
7ee8627f MC |
311 | s->init_off += written; |
312 | s->init_num -= written; | |
313 | written -= DTLS1_HM_HEADER_LENGTH; | |
314 | frag_off += written; | |
2ad226e8 MC |
315 | |
316 | /* | |
317 | * We save the fragment offset for the next fragment so we have it | |
318 | * available in case of an IO retry. We don't know the length of the | |
319 | * next fragment yet so just set that to 0 for now. It will be | |
320 | * updated again later. | |
321 | */ | |
322 | dtls1_fix_message_header(s, frag_off, 0); | |
0f113f3e MC |
323 | } |
324 | } | |
7ee8627f | 325 | return 0; |
0f113f3e MC |
326 | } |
327 | ||
38b051a1 | 328 | int dtls_get_message(SSL_CONNECTION *s, int *mt) |
76af3037 MC |
329 | { |
330 | struct hm_header_st *msg_hdr; | |
331 | unsigned char *p; | |
7ee8627f MC |
332 | size_t msg_len; |
333 | size_t tmplen; | |
334 | int errtype; | |
76af3037 MC |
335 | |
336 | msg_hdr = &s->d1->r_msg_hdr; | |
337 | memset(msg_hdr, 0, sizeof(*msg_hdr)); | |
338 | ||
339 | again: | |
7ee8627f MC |
340 | if (!dtls_get_reassembled_message(s, &errtype, &tmplen)) { |
341 | if (errtype == DTLS1_HM_BAD_FRAGMENT | |
342 | || errtype == DTLS1_HM_FRAGMENT_RETRY) { | |
343 | /* bad fragment received */ | |
344 | goto again; | |
345 | } | |
76af3037 MC |
346 | return 0; |
347 | } | |
348 | ||
555cbb32 | 349 | *mt = s->s3.tmp.message_type; |
76af3037 MC |
350 | |
351 | p = (unsigned char *)s->init_buf->data; | |
352 | ||
353 | if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) { | |
354 | if (s->msg_callback) { | |
355 | s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, | |
38b051a1 TM |
356 | p, 1, SSL_CONNECTION_GET_SSL(s), |
357 | s->msg_callback_arg); | |
76af3037 MC |
358 | } |
359 | /* | |
360 | * This isn't a real handshake message so skip the processing below. | |
361 | */ | |
362 | return 1; | |
363 | } | |
364 | ||
365 | msg_len = msg_hdr->msg_len; | |
366 | ||
367 | /* reconstruct message header */ | |
368 | *(p++) = msg_hdr->type; | |
369 | l2n3(msg_len, p); | |
370 | s2n(msg_hdr->seq, p); | |
371 | l2n3(0, p); | |
372 | l2n3(msg_len, p); | |
76af3037 | 373 | |
f42e68dc MC |
374 | memset(msg_hdr, 0, sizeof(*msg_hdr)); |
375 | ||
376 | s->d1->handshake_read_seq++; | |
377 | ||
378 | s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; | |
379 | ||
380 | return 1; | |
381 | } | |
382 | ||
383 | /* | |
384 | * Actually we already have the message body - but this is an opportunity for | |
385 | * DTLS to do any further processing it wants at the same point that TLS would | |
386 | * be asked for the message body. | |
387 | */ | |
38b051a1 | 388 | int dtls_get_message_body(SSL_CONNECTION *s, size_t *len) |
f42e68dc MC |
389 | { |
390 | unsigned char *msg = (unsigned char *)s->init_buf->data; | |
391 | size_t msg_len = s->init_num + DTLS1_HM_HEADER_LENGTH; | |
392 | ||
393 | if (s->s3.tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) { | |
394 | /* Nothing to be done */ | |
395 | goto end; | |
396 | } | |
5d671101 MC |
397 | /* |
398 | * If receiving Finished, record MAC of prior handshake messages for | |
399 | * Finished verification. | |
400 | */ | |
f42e68dc | 401 | if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac(s)) { |
5d671101 MC |
402 | /* SSLfatal() already called */ |
403 | return 0; | |
404 | } | |
405 | ||
f42e68dc MC |
406 | if (s->version == DTLS1_BAD_VER) { |
407 | msg += DTLS1_HM_HEADER_LENGTH; | |
408 | msg_len -= DTLS1_HM_HEADER_LENGTH; | |
409 | } | |
410 | ||
411 | if (!ssl3_finish_mac(s, msg, msg_len)) | |
d166ed8c | 412 | return 0; |
f42e68dc | 413 | |
76af3037 MC |
414 | if (s->msg_callback) |
415 | s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, | |
f42e68dc | 416 | s->init_buf->data, s->init_num + DTLS1_HM_HEADER_LENGTH, |
38b051a1 | 417 | SSL_CONNECTION_GET_SSL(s), s->msg_callback_arg); |
76af3037 | 418 | |
f42e68dc MC |
419 | end: |
420 | *len = s->init_num; | |
76af3037 MC |
421 | return 1; |
422 | } | |
423 | ||
48c054fe MC |
424 | /* |
425 | * dtls1_max_handshake_message_len returns the maximum number of bytes | |
426 | * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but | |
427 | * may be greater if the maximum certificate list size requires it. | |
428 | */ | |
38b051a1 | 429 | static size_t dtls1_max_handshake_message_len(const SSL_CONNECTION *s) |
48c054fe | 430 | { |
348240c6 MC |
431 | size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; |
432 | if (max_len < s->max_cert_list) | |
48c054fe MC |
433 | return s->max_cert_list; |
434 | return max_len; | |
435 | } | |
436 | ||
38b051a1 TM |
437 | static int dtls1_preprocess_fragment(SSL_CONNECTION *s, |
438 | struct hm_header_st *msg_hdr) | |
0f113f3e MC |
439 | { |
440 | size_t frag_off, frag_len, msg_len; | |
441 | ||
442 | msg_len = msg_hdr->msg_len; | |
443 | frag_off = msg_hdr->frag_off; | |
444 | frag_len = msg_hdr->frag_len; | |
445 | ||
446 | /* sanity checking */ | |
48c054fe MC |
447 | if ((frag_off + frag_len) > msg_len |
448 | || msg_len > dtls1_max_handshake_message_len(s)) { | |
c48ffbcc | 449 | SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
d273b60b | 450 | return 0; |
0f113f3e MC |
451 | } |
452 | ||
0f113f3e MC |
453 | if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */ |
454 | /* | |
48c054fe MC |
455 | * msg_len is limited to 2^24, but is effectively checked against |
456 | * dtls_max_handshake_message_len(s) above | |
0f113f3e | 457 | */ |
a230b26e | 458 | if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) { |
c48ffbcc | 459 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BUF_LIB); |
d273b60b | 460 | return 0; |
0f113f3e MC |
461 | } |
462 | ||
555cbb32 | 463 | s->s3.tmp.message_size = msg_len; |
0f113f3e | 464 | s->d1->r_msg_hdr.msg_len = msg_len; |
555cbb32 | 465 | s->s3.tmp.message_type = msg_hdr->type; |
0f113f3e MC |
466 | s->d1->r_msg_hdr.type = msg_hdr->type; |
467 | s->d1->r_msg_hdr.seq = msg_hdr->seq; | |
468 | } else if (msg_len != s->d1->r_msg_hdr.msg_len) { | |
469 | /* | |
470 | * They must be playing with us! BTW, failure to enforce upper limit | |
471 | * would open possibility for buffer overrun. | |
472 | */ | |
c48ffbcc | 473 | SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
d273b60b | 474 | return 0; |
0f113f3e MC |
475 | } |
476 | ||
d273b60b | 477 | return 1; |
0f113f3e | 478 | } |
90acf770 | 479 | |
d273b60b MC |
480 | /* |
481 | * Returns 1 if there is a buffered fragment available, 0 if not, or -1 on a | |
482 | * fatal error. | |
483 | */ | |
38b051a1 | 484 | static int dtls1_retrieve_buffered_fragment(SSL_CONNECTION *s, size_t *len) |
0f113f3e | 485 | { |
50e735f9 MC |
486 | /*- |
487 | * (0) check whether the desired fragment is available | |
488 | * if so: | |
489 | * (1) copy over the fragment to s->init_buf->data[] | |
490 | * (2) update s->init_num | |
491 | */ | |
0f113f3e | 492 | pitem *item; |
81926c91 | 493 | piterator iter; |
0f113f3e | 494 | hm_fragment *frag; |
d273b60b | 495 | int ret; |
81926c91 | 496 | int chretran = 0; |
0f113f3e | 497 | |
81926c91 | 498 | iter = pqueue_iterator(s->d1->buffered_messages); |
f5c7f5df | 499 | do { |
81926c91 | 500 | item = pqueue_next(&iter); |
f5c7f5df MC |
501 | if (item == NULL) |
502 | return 0; | |
503 | ||
504 | frag = (hm_fragment *)item->data; | |
505 | ||
506 | if (frag->msg_header.seq < s->d1->handshake_read_seq) { | |
81926c91 MC |
507 | pitem *next; |
508 | hm_fragment *nextfrag; | |
509 | ||
510 | if (!s->server | |
511 | || frag->msg_header.seq != 0 | |
512 | || s->d1->handshake_read_seq != 1 | |
513 | || s->statem.hand_state != DTLS_ST_SW_HELLO_VERIFY_REQUEST) { | |
514 | /* | |
515 | * This is a stale message that has been buffered so clear it. | |
516 | * It is safe to pop this message from the queue even though | |
517 | * we have an active iterator | |
518 | */ | |
519 | pqueue_pop(s->d1->buffered_messages); | |
520 | dtls1_hm_fragment_free(frag); | |
521 | pitem_free(item); | |
522 | item = NULL; | |
523 | frag = NULL; | |
524 | } else { | |
525 | /* | |
526 | * We have fragments for a ClientHello without a cookie, | |
527 | * even though we have sent a HelloVerifyRequest. It is possible | |
528 | * that the HelloVerifyRequest got lost and this is a | |
529 | * retransmission of the original ClientHello | |
530 | */ | |
531 | next = pqueue_next(&iter); | |
532 | if (next != NULL) { | |
533 | nextfrag = (hm_fragment *)next->data; | |
534 | if (nextfrag->msg_header.seq == s->d1->handshake_read_seq) { | |
535 | /* | |
536 | * We have fragments for both a ClientHello without | |
537 | * cookie and one with. Ditch the one without. | |
538 | */ | |
539 | pqueue_pop(s->d1->buffered_messages); | |
540 | dtls1_hm_fragment_free(frag); | |
541 | pitem_free(item); | |
542 | item = next; | |
543 | frag = nextfrag; | |
544 | } else { | |
545 | chretran = 1; | |
546 | } | |
547 | } else { | |
548 | chretran = 1; | |
549 | } | |
550 | } | |
f5c7f5df MC |
551 | } |
552 | } while (item == NULL); | |
0f113f3e MC |
553 | |
554 | /* Don't return if reassembly still in progress */ | |
555 | if (frag->reassembly != NULL) | |
556 | return 0; | |
557 | ||
81926c91 | 558 | if (s->d1->handshake_read_seq == frag->msg_header.seq || chretran) { |
7ee8627f | 559 | size_t frag_len = frag->msg_header.frag_len; |
0f113f3e MC |
560 | pqueue_pop(s->d1->buffered_messages); |
561 | ||
d273b60b MC |
562 | /* Calls SSLfatal() as required */ |
563 | ret = dtls1_preprocess_fragment(s, &frag->msg_header); | |
0f113f3e | 564 | |
a925e7db | 565 | if (ret && frag->msg_header.frag_len > 0) { |
0f113f3e MC |
566 | unsigned char *p = |
567 | (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH; | |
568 | memcpy(&p[frag->msg_header.frag_off], frag->fragment, | |
569 | frag->msg_header.frag_len); | |
570 | } | |
571 | ||
572 | dtls1_hm_fragment_free(frag); | |
573 | pitem_free(item); | |
574 | ||
d273b60b | 575 | if (ret) { |
81926c91 MC |
576 | if (chretran) { |
577 | /* | |
578 | * We got a new ClientHello with a message sequence of 0. | |
579 | * Reset the read/write sequences back to the beginning. | |
580 | * We process it like this is the first time we've seen a | |
581 | * ClientHello from the client. | |
582 | */ | |
583 | s->d1->handshake_read_seq = 0; | |
584 | s->d1->next_handshake_write_seq = 0; | |
585 | } | |
7ee8627f MC |
586 | *len = frag_len; |
587 | return 1; | |
0f113f3e MC |
588 | } |
589 | ||
d273b60b | 590 | /* Fatal error */ |
0f113f3e | 591 | s->init_num = 0; |
d273b60b | 592 | return -1; |
7ee8627f MC |
593 | } else { |
594 | return 0; | |
595 | } | |
0f113f3e MC |
596 | } |
597 | ||
38b051a1 TM |
598 | static int dtls1_reassemble_fragment(SSL_CONNECTION *s, |
599 | const struct hm_header_st *msg_hdr) | |
0f113f3e MC |
600 | { |
601 | hm_fragment *frag = NULL; | |
602 | pitem *item = NULL; | |
603 | int i = -1, is_complete; | |
604 | unsigned char seq64be[8]; | |
7ee8627f | 605 | size_t frag_len = msg_hdr->frag_len; |
54105ddd | 606 | size_t readbytes; |
38b051a1 | 607 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
0f113f3e MC |
608 | |
609 | if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len || | |
610 | msg_hdr->msg_len > dtls1_max_handshake_message_len(s)) | |
611 | goto err; | |
612 | ||
7ee8627f | 613 | if (frag_len == 0) { |
0f113f3e | 614 | return DTLS1_HM_FRAGMENT_RETRY; |
7ee8627f | 615 | } |
0f113f3e MC |
616 | |
617 | /* Try to find item in queue */ | |
618 | memset(seq64be, 0, sizeof(seq64be)); | |
619 | seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); | |
620 | seq64be[7] = (unsigned char)msg_hdr->seq; | |
621 | item = pqueue_find(s->d1->buffered_messages, seq64be); | |
622 | ||
623 | if (item == NULL) { | |
624 | frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); | |
625 | if (frag == NULL) | |
626 | goto err; | |
627 | memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); | |
628 | frag->msg_header.frag_len = frag->msg_header.msg_len; | |
629 | frag->msg_header.frag_off = 0; | |
630 | } else { | |
631 | frag = (hm_fragment *)item->data; | |
632 | if (frag->msg_header.msg_len != msg_hdr->msg_len) { | |
633 | item = NULL; | |
634 | frag = NULL; | |
635 | goto err; | |
636 | } | |
637 | } | |
638 | ||
639 | /* | |
640 | * If message is already reassembled, this must be a retransmit and can | |
641 | * be dropped. In this case item != NULL and so frag does not need to be | |
642 | * freed. | |
643 | */ | |
644 | if (frag->reassembly == NULL) { | |
645 | unsigned char devnull[256]; | |
646 | ||
647 | while (frag_len) { | |
38b051a1 TM |
648 | i = ssl->method->ssl_read_bytes(ssl, SSL3_RT_HANDSHAKE, NULL, |
649 | devnull, | |
650 | frag_len > | |
651 | sizeof(devnull) ? sizeof(devnull) : | |
652 | frag_len, 0, &readbytes); | |
0f113f3e MC |
653 | if (i <= 0) |
654 | goto err; | |
54105ddd | 655 | frag_len -= readbytes; |
0f113f3e MC |
656 | } |
657 | return DTLS1_HM_FRAGMENT_RETRY; | |
658 | } | |
659 | ||
660 | /* read the body of the fragment (header has already been read */ | |
38b051a1 TM |
661 | i = ssl->method->ssl_read_bytes(ssl, SSL3_RT_HANDSHAKE, NULL, |
662 | frag->fragment + msg_hdr->frag_off, | |
663 | frag_len, 0, &readbytes); | |
54105ddd | 664 | if (i <= 0 || readbytes != frag_len) |
0f113f3e MC |
665 | i = -1; |
666 | if (i <= 0) | |
667 | goto err; | |
668 | ||
669 | RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off, | |
670 | (long)(msg_hdr->frag_off + frag_len)); | |
671 | ||
380a522f MC |
672 | if (!ossl_assert(msg_hdr->msg_len > 0)) |
673 | goto err; | |
0f113f3e MC |
674 | RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len, |
675 | is_complete); | |
676 | ||
677 | if (is_complete) { | |
678 | OPENSSL_free(frag->reassembly); | |
679 | frag->reassembly = NULL; | |
680 | } | |
681 | ||
682 | if (item == NULL) { | |
683 | item = pitem_new(seq64be, frag); | |
684 | if (item == NULL) { | |
685 | i = -1; | |
686 | goto err; | |
687 | } | |
688 | ||
689 | item = pqueue_insert(s->d1->buffered_messages, item); | |
690 | /* | |
691 | * pqueue_insert fails iff a duplicate item is inserted. However, | |
692 | * |item| cannot be a duplicate. If it were, |pqueue_find|, above, | |
693 | * would have returned it and control would never have reached this | |
694 | * branch. | |
695 | */ | |
380a522f MC |
696 | if (!ossl_assert(item != NULL)) |
697 | goto err; | |
0f113f3e MC |
698 | } |
699 | ||
700 | return DTLS1_HM_FRAGMENT_RETRY; | |
701 | ||
702 | err: | |
25aaa98a | 703 | if (item == NULL) |
0f113f3e | 704 | dtls1_hm_fragment_free(frag); |
7ee8627f | 705 | return -1; |
0f113f3e | 706 | } |
934e22e8 | 707 | |
38b051a1 TM |
708 | static int dtls1_process_out_of_seq_message(SSL_CONNECTION *s, |
709 | const struct hm_header_st *msg_hdr) | |
36d16f8e | 710 | { |
0f113f3e MC |
711 | int i = -1; |
712 | hm_fragment *frag = NULL; | |
713 | pitem *item = NULL; | |
714 | unsigned char seq64be[8]; | |
7ee8627f | 715 | size_t frag_len = msg_hdr->frag_len; |
54105ddd | 716 | size_t readbytes; |
38b051a1 | 717 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
0f113f3e MC |
718 | |
719 | if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len) | |
720 | goto err; | |
721 | ||
722 | /* Try to find item in queue, to prevent duplicate entries */ | |
723 | memset(seq64be, 0, sizeof(seq64be)); | |
724 | seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); | |
725 | seq64be[7] = (unsigned char)msg_hdr->seq; | |
726 | item = pqueue_find(s->d1->buffered_messages, seq64be); | |
727 | ||
728 | /* | |
729 | * If we already have an entry and this one is a fragment, don't discard | |
730 | * it and rather try to reassemble it. | |
731 | */ | |
732 | if (item != NULL && frag_len != msg_hdr->msg_len) | |
733 | item = NULL; | |
734 | ||
735 | /* | |
736 | * Discard the message if sequence number was already there, is too far | |
737 | * in the future, already in the queue or if we received a FINISHED | |
738 | * before the SERVER_HELLO, which then must be a stale retransmit. | |
739 | */ | |
740 | if (msg_hdr->seq <= s->d1->handshake_read_seq || | |
741 | msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL || | |
a230b26e | 742 | (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) { |
0f113f3e MC |
743 | unsigned char devnull[256]; |
744 | ||
745 | while (frag_len) { | |
38b051a1 TM |
746 | i = ssl->method->ssl_read_bytes(ssl, SSL3_RT_HANDSHAKE, NULL, |
747 | devnull, | |
748 | frag_len > | |
749 | sizeof(devnull) ? sizeof(devnull) : | |
750 | frag_len, 0, &readbytes); | |
0f113f3e MC |
751 | if (i <= 0) |
752 | goto err; | |
54105ddd | 753 | frag_len -= readbytes; |
0f113f3e MC |
754 | } |
755 | } else { | |
7ee8627f | 756 | if (frag_len != msg_hdr->msg_len) { |
0fe2a0af | 757 | return dtls1_reassemble_fragment(s, msg_hdr); |
7ee8627f | 758 | } |
0f113f3e MC |
759 | |
760 | if (frag_len > dtls1_max_handshake_message_len(s)) | |
761 | goto err; | |
762 | ||
763 | frag = dtls1_hm_fragment_new(frag_len, 0); | |
764 | if (frag == NULL) | |
765 | goto err; | |
766 | ||
767 | memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); | |
768 | ||
769 | if (frag_len) { | |
770 | /* | |
771 | * read the body of the fragment (header has already been read | |
772 | */ | |
38b051a1 TM |
773 | i = ssl->method->ssl_read_bytes(ssl, SSL3_RT_HANDSHAKE, NULL, |
774 | frag->fragment, frag_len, 0, | |
775 | &readbytes); | |
54105ddd | 776 | if (i<=0 || readbytes != frag_len) |
0f113f3e MC |
777 | i = -1; |
778 | if (i <= 0) | |
779 | goto err; | |
780 | } | |
781 | ||
782 | item = pitem_new(seq64be, frag); | |
783 | if (item == NULL) | |
784 | goto err; | |
785 | ||
786 | item = pqueue_insert(s->d1->buffered_messages, item); | |
787 | /* | |
788 | * pqueue_insert fails iff a duplicate item is inserted. However, | |
789 | * |item| cannot be a duplicate. If it were, |pqueue_find|, above, | |
790 | * would have returned it. Then, either |frag_len| != | |
791 | * |msg_hdr->msg_len| in which case |item| is set to NULL and it will | |
792 | * have been processed with |dtls1_reassemble_fragment|, above, or | |
793 | * the record will have been discarded. | |
794 | */ | |
380a522f MC |
795 | if (!ossl_assert(item != NULL)) |
796 | goto err; | |
0f113f3e MC |
797 | } |
798 | ||
799 | return DTLS1_HM_FRAGMENT_RETRY; | |
800 | ||
801 | err: | |
25aaa98a | 802 | if (item == NULL) |
0f113f3e | 803 | dtls1_hm_fragment_free(frag); |
7ee8627f | 804 | return 0; |
0f113f3e | 805 | } |
36d16f8e | 806 | |
38b051a1 TM |
807 | static int dtls_get_reassembled_message(SSL_CONNECTION *s, int *errtype, |
808 | size_t *len) | |
0f113f3e MC |
809 | { |
810 | unsigned char wire[DTLS1_HM_HEADER_LENGTH]; | |
7ee8627f | 811 | size_t mlen, frag_off, frag_len; |
eb1eaa9a TM |
812 | int i, ret; |
813 | uint8_t recvd_type; | |
0f113f3e | 814 | struct hm_header_st msg_hdr; |
54105ddd | 815 | size_t readbytes; |
38b051a1 | 816 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
81926c91 | 817 | int chretran = 0; |
0f113f3e | 818 | |
7ee8627f MC |
819 | *errtype = 0; |
820 | ||
0f113f3e MC |
821 | redo: |
822 | /* see if we have the required fragment already */ | |
d273b60b MC |
823 | ret = dtls1_retrieve_buffered_fragment(s, &frag_len); |
824 | if (ret < 0) { | |
825 | /* SSLfatal() already called */ | |
826 | return 0; | |
827 | } | |
828 | if (ret > 0) { | |
7ee8627f | 829 | s->init_num = frag_len; |
76af3037 | 830 | *len = frag_len; |
7ee8627f | 831 | return 1; |
0f113f3e MC |
832 | } |
833 | ||
834 | /* read handshake message header */ | |
38b051a1 TM |
835 | i = ssl->method->ssl_read_bytes(ssl, SSL3_RT_HANDSHAKE, &recvd_type, wire, |
836 | DTLS1_HM_HEADER_LENGTH, 0, &readbytes); | |
0f113f3e MC |
837 | if (i <= 0) { /* nbio, or an error */ |
838 | s->rwstate = SSL_READING; | |
7ee8627f | 839 | *len = 0; |
76af3037 | 840 | return 0; |
0f113f3e | 841 | } |
e8aa8b6c | 842 | if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) { |
76af3037 | 843 | if (wire[0] != SSL3_MT_CCS) { |
d273b60b | 844 | SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, |
d273b60b | 845 | SSL_R_BAD_CHANGE_CIPHER_SPEC); |
76af3037 | 846 | goto f_err; |
c69f2adf | 847 | } |
76af3037 | 848 | |
54105ddd MC |
849 | memcpy(s->init_buf->data, wire, readbytes); |
850 | s->init_num = readbytes - 1; | |
76af3037 | 851 | s->init_msg = s->init_buf->data + 1; |
555cbb32 TS |
852 | s->s3.tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC; |
853 | s->s3.tmp.message_size = readbytes - 1; | |
54105ddd | 854 | *len = readbytes - 1; |
76af3037 | 855 | return 1; |
c69f2adf MC |
856 | } |
857 | ||
0f113f3e | 858 | /* Handshake fails if message header is incomplete */ |
54105ddd | 859 | if (readbytes != DTLS1_HM_HEADER_LENGTH) { |
c48ffbcc | 860 | SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); |
0f113f3e MC |
861 | goto f_err; |
862 | } | |
863 | ||
864 | /* parse the message fragment header */ | |
865 | dtls1_get_message_header(wire, &msg_hdr); | |
866 | ||
76af3037 | 867 | mlen = msg_hdr.msg_len; |
91d13f1a MC |
868 | frag_off = msg_hdr.frag_off; |
869 | frag_len = msg_hdr.frag_len; | |
870 | ||
871 | /* | |
872 | * We must have at least frag_len bytes left in the record to be read. | |
873 | * Fragments must not span records. | |
874 | */ | |
eddb067e | 875 | if (frag_len > s->rlayer.tlsrecs[s->rlayer.curr_rec].length) { |
c48ffbcc | 876 | SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_LENGTH); |
91d13f1a MC |
877 | goto f_err; |
878 | } | |
879 | ||
0f113f3e MC |
880 | /* |
881 | * if this is a future (or stale) message it gets buffered | |
882 | * (or dropped)--no further processing at this time | |
883 | * While listening, we accept seq 1 (ClientHello with cookie) | |
884 | * although we're still expecting seq 0 (ClientHello) | |
885 | */ | |
76af3037 | 886 | if (msg_hdr.seq != s->d1->handshake_read_seq) { |
81926c91 MC |
887 | if (!s->server |
888 | || msg_hdr.seq != 0 | |
889 | || s->d1->handshake_read_seq != 1 | |
890 | || wire[0] != SSL3_MT_CLIENT_HELLO | |
891 | || s->statem.hand_state != DTLS_ST_SW_HELLO_VERIFY_REQUEST) { | |
892 | *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr); | |
893 | return 0; | |
894 | } | |
895 | /* | |
896 | * We received a ClientHello and sent back a HelloVerifyRequest. We | |
897 | * now seem to have received a retransmitted initial ClientHello. That | |
898 | * is allowed (possibly our HelloVerifyRequest got lost). | |
899 | */ | |
900 | chretran = 1; | |
76af3037 | 901 | } |
0f113f3e | 902 | |
76af3037 | 903 | if (frag_len && frag_len < mlen) { |
7ee8627f MC |
904 | *errtype = dtls1_reassemble_fragment(s, &msg_hdr); |
905 | return 0; | |
76af3037 | 906 | } |
0f113f3e | 907 | |
1f5b44e9 MC |
908 | if (!s->server |
909 | && s->d1->r_msg_hdr.frag_off == 0 | |
c7f47786 MC |
910 | && s->statem.hand_state != TLS_ST_OK |
911 | && wire[0] == SSL3_MT_HELLO_REQUEST) { | |
0f113f3e MC |
912 | /* |
913 | * The server may always send 'Hello Request' messages -- we are | |
914 | * doing a handshake anyway now, so ignore them if their format is | |
915 | * correct. Does not count for 'Finished' MAC. | |
916 | */ | |
917 | if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) { | |
918 | if (s->msg_callback) | |
919 | s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, | |
38b051a1 | 920 | wire, DTLS1_HM_HEADER_LENGTH, ssl, |
0f113f3e MC |
921 | s->msg_callback_arg); |
922 | ||
923 | s->init_num = 0; | |
924 | goto redo; | |
60250017 | 925 | } else { /* Incorrectly formatted Hello request */ |
0f113f3e | 926 | |
c48ffbcc | 927 | SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); |
0f113f3e MC |
928 | goto f_err; |
929 | } | |
930 | } | |
931 | ||
d273b60b MC |
932 | if (!dtls1_preprocess_fragment(s, &msg_hdr)) { |
933 | /* SSLfatal() already called */ | |
0f113f3e | 934 | goto f_err; |
d273b60b | 935 | } |
0f113f3e | 936 | |
0f113f3e MC |
937 | if (frag_len > 0) { |
938 | unsigned char *p = | |
939 | (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH; | |
940 | ||
38b051a1 TM |
941 | i = ssl->method->ssl_read_bytes(ssl, SSL3_RT_HANDSHAKE, NULL, |
942 | &p[frag_off], frag_len, 0, &readbytes); | |
91d13f1a | 943 | |
0f113f3e | 944 | /* |
91d13f1a MC |
945 | * This shouldn't ever fail due to NBIO because we already checked |
946 | * that we have enough data in the record | |
0f113f3e MC |
947 | */ |
948 | if (i <= 0) { | |
949 | s->rwstate = SSL_READING; | |
7ee8627f | 950 | *len = 0; |
76af3037 | 951 | return 0; |
0f113f3e | 952 | } |
7ee8627f | 953 | } else { |
54105ddd | 954 | readbytes = 0; |
7ee8627f | 955 | } |
0f113f3e MC |
956 | |
957 | /* | |
958 | * XDTLS: an incorrectly formatted fragment should cause the handshake | |
959 | * to fail | |
960 | */ | |
54105ddd | 961 | if (readbytes != frag_len) { |
c48ffbcc | 962 | SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_LENGTH); |
0f113f3e MC |
963 | goto f_err; |
964 | } | |
965 | ||
81926c91 MC |
966 | if (chretran) { |
967 | /* | |
968 | * We got a new ClientHello with a message sequence of 0. | |
969 | * Reset the read/write sequences back to the beginning. | |
970 | * We process it like this is the first time we've seen a ClientHello | |
971 | * from the client. | |
972 | */ | |
973 | s->d1->handshake_read_seq = 0; | |
974 | s->d1->next_handshake_write_seq = 0; | |
975 | } | |
976 | ||
0f113f3e MC |
977 | /* |
978 | * Note that s->init_num is *not* used as current offset in | |
979 | * s->init_buf->data, but as a counter summing up fragments' lengths: as | |
980 | * soon as they sum up to handshake packet length, we assume we have got | |
981 | * all the fragments. | |
982 | */ | |
76af3037 MC |
983 | *len = s->init_num = frag_len; |
984 | return 1; | |
0f113f3e MC |
985 | |
986 | f_err: | |
0f113f3e | 987 | s->init_num = 0; |
7ee8627f | 988 | *len = 0; |
76af3037 | 989 | return 0; |
0f113f3e | 990 | } |
36d16f8e | 991 | |
1d97c843 TH |
992 | /*- |
993 | * for these 2 messages, we need to | |
0f113f3e MC |
994 | * ssl->session->read_sym_enc assign |
995 | * ssl->session->read_compression assign | |
996 | * ssl->session->read_hash assign | |
36d16f8e | 997 | */ |
67ec6d2b MC |
998 | CON_FUNC_RETURN dtls_construct_change_cipher_spec(SSL_CONNECTION *s, |
999 | WPACKET *pkt) | |
0f113f3e | 1000 | { |
473483d4 MC |
1001 | if (s->version == DTLS1_BAD_VER) { |
1002 | s->d1->next_handshake_write_seq++; | |
85a7a5e6 | 1003 | |
7cea05dc | 1004 | if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) { |
c48ffbcc | 1005 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
67ec6d2b | 1006 | return CON_FUNC_ERROR; |
85a7a5e6 | 1007 | } |
0f113f3e | 1008 | } |
36d16f8e | 1009 | |
67ec6d2b | 1010 | return CON_FUNC_SUCCESS; |
473483d4 MC |
1011 | } |
1012 | ||
1013 | #ifndef OPENSSL_NO_SCTP | |
2e92af5e MC |
1014 | /* |
1015 | * Wait for a dry event. Should only be called at a point in the handshake | |
1016 | * where we are not expecting any data from the peer except an alert. | |
1017 | */ | |
38b051a1 | 1018 | WORK_STATE dtls_wait_for_dry(SSL_CONNECTION *s) |
473483d4 | 1019 | { |
2e92af5e MC |
1020 | int ret, errtype; |
1021 | size_t len; | |
38b051a1 | 1022 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
473483d4 MC |
1023 | |
1024 | /* read app data until dry event */ | |
38b051a1 | 1025 | ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(ssl)); |
a2c2e000 | 1026 | if (ret < 0) { |
c48ffbcc | 1027 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
473483d4 | 1028 | return WORK_ERROR; |
a2c2e000 | 1029 | } |
473483d4 MC |
1030 | |
1031 | if (ret == 0) { | |
2e92af5e MC |
1032 | /* |
1033 | * We're not expecting any more messages from the peer at this point - | |
1034 | * but we could get an alert. If an alert is waiting then we will never | |
1035 | * return successfully. Therefore we attempt to read a message. This | |
1036 | * should never succeed but will process any waiting alerts. | |
1037 | */ | |
1038 | if (dtls_get_reassembled_message(s, &errtype, &len)) { | |
1039 | /* The call succeeded! This should never happen */ | |
c48ffbcc | 1040 | SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); |
2e92af5e MC |
1041 | return WORK_ERROR; |
1042 | } | |
1043 | ||
555cbb32 | 1044 | s->s3.in_read_app_data = 2; |
473483d4 | 1045 | s->rwstate = SSL_READING; |
38b051a1 TM |
1046 | BIO_clear_retry_flags(SSL_get_rbio(ssl)); |
1047 | BIO_set_retry_read(SSL_get_rbio(ssl)); | |
473483d4 MC |
1048 | return WORK_MORE_A; |
1049 | } | |
1050 | return WORK_FINISHED_CONTINUE; | |
0f113f3e | 1051 | } |
473483d4 | 1052 | #endif |
36d16f8e | 1053 | |
38b051a1 | 1054 | int dtls1_read_failed(SSL_CONNECTION *s, int code) |
0f113f3e | 1055 | { |
38b051a1 TM |
1056 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
1057 | ||
0f113f3e | 1058 | if (code > 0) { |
c48ffbcc | 1059 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
d273b60b | 1060 | return 0; |
0f113f3e MC |
1061 | } |
1062 | ||
c2853382 | 1063 | if (!dtls1_is_timer_expired(s) || ossl_statem_in_error(s)) { |
0f113f3e MC |
1064 | /* |
1065 | * not a timeout, none of our business, let higher layers handle | |
1066 | * this. in fact it's probably an error | |
1067 | */ | |
1068 | return code; | |
1069 | } | |
0f113f3e | 1070 | /* done, no need to send a retransmit */ |
38b051a1 | 1071 | if (!SSL_in_init(ssl)) |
0f113f3e | 1072 | { |
38b051a1 | 1073 | BIO_set_flags(SSL_get_rbio(ssl), BIO_FLAGS_READ); |
0f113f3e MC |
1074 | return code; |
1075 | } | |
36d16f8e | 1076 | |
0f113f3e MC |
1077 | return dtls1_handle_timeout(s); |
1078 | } | |
36d16f8e | 1079 | |
0f113f3e MC |
1080 | int dtls1_get_queue_priority(unsigned short seq, int is_ccs) |
1081 | { | |
1082 | /* | |
1083 | * The index of the retransmission queue actually is the message sequence | |
1084 | * number, since the queue only contains messages of a single handshake. | |
1085 | * However, the ChangeCipherSpec has no message sequence number and so | |
1086 | * using only the sequence will result in the CCS and Finished having the | |
1087 | * same index. To prevent this, the sequence number is multiplied by 2. | |
1088 | * In case of a CCS 1 is subtracted. This does not only differ CSS and | |
1089 | * Finished, it also maintains the order of the index (important for | |
1090 | * priority queues) and fits in the unsigned short variable. | |
1091 | */ | |
1092 | return seq * 2 - is_ccs; | |
1093 | } | |
36d16f8e | 1094 | |
38b051a1 | 1095 | int dtls1_retransmit_buffered_messages(SSL_CONNECTION *s) |
0f113f3e | 1096 | { |
cf2cede4 | 1097 | pqueue *sent = s->d1->sent_messages; |
0f113f3e MC |
1098 | piterator iter; |
1099 | pitem *item; | |
1100 | hm_fragment *frag; | |
1101 | int found = 0; | |
1102 | ||
1103 | iter = pqueue_iterator(sent); | |
1104 | ||
1105 | for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) { | |
1106 | frag = (hm_fragment *)item->data; | |
1107 | if (dtls1_retransmit_message(s, (unsigned short) | |
1108 | dtls1_get_queue_priority | |
1109 | (frag->msg_header.seq, | |
a230b26e | 1110 | frag->msg_header.is_ccs), &found) <= 0) |
0f113f3e | 1111 | return -1; |
0f113f3e MC |
1112 | } |
1113 | ||
1114 | return 1; | |
1115 | } | |
36d16f8e | 1116 | |
38b051a1 | 1117 | int dtls1_buffer_message(SSL_CONNECTION *s, int is_ccs) |
0f113f3e MC |
1118 | { |
1119 | pitem *item; | |
1120 | hm_fragment *frag; | |
1121 | unsigned char seq64be[8]; | |
1122 | ||
1123 | /* | |
1124 | * this function is called immediately after a message has been | |
1125 | * serialized | |
1126 | */ | |
380a522f MC |
1127 | if (!ossl_assert(s->init_off == 0)) |
1128 | return 0; | |
0f113f3e MC |
1129 | |
1130 | frag = dtls1_hm_fragment_new(s->init_num, 0); | |
a71edf3b | 1131 | if (frag == NULL) |
0f113f3e MC |
1132 | return 0; |
1133 | ||
1134 | memcpy(frag->fragment, s->init_buf->data, s->init_num); | |
1135 | ||
1136 | if (is_ccs) { | |
5178a16c | 1137 | /* For DTLS1_BAD_VER the header length is non-standard */ |
380a522f MC |
1138 | if (!ossl_assert(s->d1->w_msg_hdr.msg_len + |
1139 | ((s->version == | |
1140 | DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH) | |
48ff651e P |
1141 | == (unsigned int)s->init_num)) { |
1142 | dtls1_hm_fragment_free(frag); | |
380a522f | 1143 | return 0; |
48ff651e | 1144 | } |
0f113f3e | 1145 | } else { |
380a522f | 1146 | if (!ossl_assert(s->d1->w_msg_hdr.msg_len + |
48ff651e P |
1147 | DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num)) { |
1148 | dtls1_hm_fragment_free(frag); | |
380a522f | 1149 | return 0; |
48ff651e | 1150 | } |
0f113f3e MC |
1151 | } |
1152 | ||
1153 | frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len; | |
1154 | frag->msg_header.seq = s->d1->w_msg_hdr.seq; | |
1155 | frag->msg_header.type = s->d1->w_msg_hdr.type; | |
1156 | frag->msg_header.frag_off = 0; | |
1157 | frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len; | |
1158 | frag->msg_header.is_ccs = is_ccs; | |
1159 | ||
1160 | /* save current state */ | |
b9e37f8f MC |
1161 | frag->msg_header.saved_retransmit_state.wrlmethod = s->rlayer.wrlmethod; |
1162 | frag->msg_header.saved_retransmit_state.wrl = s->rlayer.wrl; | |
1163 | ||
0f113f3e MC |
1164 | |
1165 | memset(seq64be, 0, sizeof(seq64be)); | |
1166 | seq64be[6] = | |
1167 | (unsigned | |
1168 | char)(dtls1_get_queue_priority(frag->msg_header.seq, | |
1169 | frag->msg_header.is_ccs) >> 8); | |
1170 | seq64be[7] = | |
1171 | (unsigned | |
1172 | char)(dtls1_get_queue_priority(frag->msg_header.seq, | |
1173 | frag->msg_header.is_ccs)); | |
1174 | ||
1175 | item = pitem_new(seq64be, frag); | |
1176 | if (item == NULL) { | |
1177 | dtls1_hm_fragment_free(frag); | |
1178 | return 0; | |
1179 | } | |
36d16f8e | 1180 | |
0f113f3e MC |
1181 | pqueue_insert(s->d1->sent_messages, item); |
1182 | return 1; | |
1183 | } | |
36d16f8e | 1184 | |
38b051a1 | 1185 | int dtls1_retransmit_message(SSL_CONNECTION *s, unsigned short seq, int *found) |
0f113f3e MC |
1186 | { |
1187 | int ret; | |
1188 | /* XDTLS: for now assuming that read/writes are blocking */ | |
1189 | pitem *item; | |
1190 | hm_fragment *frag; | |
1191 | unsigned long header_length; | |
1192 | unsigned char seq64be[8]; | |
1193 | struct dtls1_retransmit_state saved_state; | |
0f113f3e | 1194 | |
0f113f3e MC |
1195 | /* XDTLS: the requested message ought to be found, otherwise error */ |
1196 | memset(seq64be, 0, sizeof(seq64be)); | |
1197 | seq64be[6] = (unsigned char)(seq >> 8); | |
1198 | seq64be[7] = (unsigned char)seq; | |
1199 | ||
1200 | item = pqueue_find(s->d1->sent_messages, seq64be); | |
1201 | if (item == NULL) { | |
c48ffbcc | 1202 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
0f113f3e MC |
1203 | *found = 0; |
1204 | return 0; | |
1205 | } | |
1206 | ||
1207 | *found = 1; | |
1208 | frag = (hm_fragment *)item->data; | |
1209 | ||
1210 | if (frag->msg_header.is_ccs) | |
1211 | header_length = DTLS1_CCS_HEADER_LENGTH; | |
1212 | else | |
1213 | header_length = DTLS1_HM_HEADER_LENGTH; | |
1214 | ||
1215 | memcpy(s->init_buf->data, frag->fragment, | |
1216 | frag->msg_header.msg_len + header_length); | |
1217 | s->init_num = frag->msg_header.msg_len + header_length; | |
1218 | ||
1219 | dtls1_set_message_header_int(s, frag->msg_header.type, | |
1220 | frag->msg_header.msg_len, | |
1221 | frag->msg_header.seq, 0, | |
1222 | frag->msg_header.frag_len); | |
1223 | ||
1224 | /* save current state */ | |
b9e37f8f MC |
1225 | saved_state.wrlmethod = s->rlayer.wrlmethod; |
1226 | saved_state.wrl = s->rlayer.wrl; | |
0f113f3e MC |
1227 | |
1228 | s->d1->retransmitting = 1; | |
1229 | ||
1230 | /* restore state in which the message was originally sent */ | |
b9e37f8f MC |
1231 | s->rlayer.wrlmethod = frag->msg_header.saved_retransmit_state.wrlmethod; |
1232 | s->rlayer.wrl = frag->msg_header.saved_retransmit_state.wrl; | |
1233 | ||
1234 | /* | |
1235 | * The old wrl may be still pointing at an old BIO. Update it to what we're | |
1236 | * using now. | |
1237 | */ | |
1238 | s->rlayer.wrlmethod->set1_bio(s->rlayer.wrl, s->wbio); | |
0f113f3e | 1239 | |
0f113f3e MC |
1240 | ret = dtls1_do_write(s, frag->msg_header.is_ccs ? |
1241 | SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); | |
1242 | ||
1243 | /* restore current state */ | |
b9e37f8f MC |
1244 | s->rlayer.wrlmethod = saved_state.wrlmethod; |
1245 | s->rlayer.wrl = saved_state.wrl; | |
0f113f3e MC |
1246 | |
1247 | s->d1->retransmitting = 0; | |
1248 | ||
2e7dc7cd | 1249 | (void)BIO_flush(s->wbio); |
0f113f3e MC |
1250 | return ret; |
1251 | } | |
36d16f8e | 1252 | |
38b051a1 | 1253 | void dtls1_set_message_header(SSL_CONNECTION *s, |
d736bc1a MC |
1254 | unsigned char mt, size_t len, |
1255 | size_t frag_off, size_t frag_len) | |
0f113f3e | 1256 | { |
912c89c5 | 1257 | if (frag_off == 0) { |
0f113f3e MC |
1258 | s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; |
1259 | s->d1->next_handshake_write_seq++; | |
1260 | } | |
54ef01b5 | 1261 | |
0f113f3e MC |
1262 | dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq, |
1263 | frag_off, frag_len); | |
0f113f3e | 1264 | } |
36d16f8e BL |
1265 | |
1266 | /* don't actually do the writing, wait till the MTU has been retrieved */ | |
1267 | static void | |
38b051a1 | 1268 | dtls1_set_message_header_int(SSL_CONNECTION *s, unsigned char mt, |
7ee8627f MC |
1269 | size_t len, unsigned short seq_num, |
1270 | size_t frag_off, size_t frag_len) | |
0f113f3e MC |
1271 | { |
1272 | struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; | |
1273 | ||
1274 | msg_hdr->type = mt; | |
1275 | msg_hdr->msg_len = len; | |
1276 | msg_hdr->seq = seq_num; | |
1277 | msg_hdr->frag_off = frag_off; | |
1278 | msg_hdr->frag_len = frag_len; | |
1279 | } | |
36d16f8e BL |
1280 | |
1281 | static void | |
38b051a1 | 1282 | dtls1_fix_message_header(SSL_CONNECTION *s, size_t frag_off, size_t frag_len) |
0f113f3e MC |
1283 | { |
1284 | struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; | |
36d16f8e | 1285 | |
0f113f3e MC |
1286 | msg_hdr->frag_off = frag_off; |
1287 | msg_hdr->frag_len = frag_len; | |
1288 | } | |
54ef01b5 | 1289 | |
38b051a1 TM |
1290 | static unsigned char *dtls1_write_message_header(SSL_CONNECTION *s, |
1291 | unsigned char *p) | |
0f113f3e MC |
1292 | { |
1293 | struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; | |
54ef01b5 | 1294 | |
0f113f3e MC |
1295 | *p++ = msg_hdr->type; |
1296 | l2n3(msg_hdr->msg_len, p); | |
54ef01b5 | 1297 | |
0f113f3e MC |
1298 | s2n(msg_hdr->seq, p); |
1299 | l2n3(msg_hdr->frag_off, p); | |
1300 | l2n3(msg_hdr->frag_len, p); | |
36d16f8e | 1301 | |
0f113f3e MC |
1302 | return p; |
1303 | } | |
36d16f8e | 1304 | |
2eb91b0e MC |
1305 | void dtls1_get_message_header(const unsigned char *data, struct |
1306 | hm_header_st *msg_hdr) | |
0f113f3e | 1307 | { |
16f8d4eb | 1308 | memset(msg_hdr, 0, sizeof(*msg_hdr)); |
0f113f3e MC |
1309 | msg_hdr->type = *(data++); |
1310 | n2l3(data, msg_hdr->msg_len); | |
54ef01b5 | 1311 | |
0f113f3e MC |
1312 | n2s(data, msg_hdr->seq); |
1313 | n2l3(data, msg_hdr->frag_off); | |
1314 | n2l3(data, msg_hdr->frag_len); | |
1315 | } | |
2c7b4dbc | 1316 | |
38b051a1 | 1317 | int dtls1_set_handshake_header(SSL_CONNECTION *s, WPACKET *pkt, int htype) |
2c7b4dbc MC |
1318 | { |
1319 | unsigned char *header; | |
de451856 | 1320 | |
4a01c59f MC |
1321 | if (htype == SSL3_MT_CHANGE_CIPHER_SPEC) { |
1322 | s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; | |
1323 | dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, | |
1324 | s->d1->handshake_write_seq, 0, 0); | |
1325 | if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) | |
1326 | return 0; | |
1327 | } else { | |
1328 | dtls1_set_message_header(s, htype, 0, 0, 0); | |
1329 | /* | |
1330 | * We allocate space at the start for the message header. This gets | |
1331 | * filled in later | |
1332 | */ | |
1333 | if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header) | |
1334 | || !WPACKET_start_sub_packet(pkt)) | |
1335 | return 0; | |
1336 | } | |
2c7b4dbc MC |
1337 | |
1338 | return 1; | |
1339 | } | |
1340 | ||
38b051a1 | 1341 | int dtls1_close_construct_packet(SSL_CONNECTION *s, WPACKET *pkt, int htype) |
2c7b4dbc MC |
1342 | { |
1343 | size_t msglen; | |
1344 | ||
4a01c59f | 1345 | if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt)) |
f1ec23c0 | 1346 | || !WPACKET_get_length(pkt, &msglen) |
7cea05dc | 1347 | || msglen > INT_MAX) |
2c7b4dbc | 1348 | return 0; |
4a01c59f MC |
1349 | |
1350 | if (htype != SSL3_MT_CHANGE_CIPHER_SPEC) { | |
1351 | s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH; | |
1352 | s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH; | |
1353 | } | |
2c7b4dbc MC |
1354 | s->init_num = (int)msglen; |
1355 | s->init_off = 0; | |
1356 | ||
4a01c59f MC |
1357 | if (htype != DTLS1_MT_HELLO_VERIFY_REQUEST) { |
1358 | /* Buffer the message to handle re-xmits */ | |
1359 | if (!dtls1_buffer_message(s, htype == SSL3_MT_CHANGE_CIPHER_SPEC | |
1360 | ? 1 : 0)) | |
1361 | return 0; | |
1362 | } | |
2c7b4dbc MC |
1363 | |
1364 | return 1; | |
1365 | } |