]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
da1c088f | 2 | * Copyright 2005-2023 The OpenSSL Project Authors. All Rights Reserved. |
36d16f8e | 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 | ||
d5f9166b | 10 | #include "internal/e_os.h" |
36d16f8e BL |
11 | #include <stdio.h> |
12 | #include <openssl/objects.h> | |
8ba708e5 | 13 | #include <openssl/rand.h> |
706457b7 | 14 | #include "ssl_local.h" |
d6bfdf67 | 15 | #include "internal/time.h" |
36d16f8e | 16 | |
38b051a1 | 17 | static int dtls1_handshake_write(SSL_CONNECTION *s); |
7ee8627f | 18 | static size_t dtls1_link_min_mtu(void); |
36d16f8e | 19 | |
8ba708e5 | 20 | /* XDTLS: figure out the right values */ |
7ee8627f | 21 | static const size_t g_probable_mtu[] = { 1500, 512, 256 }; |
8ba708e5 | 22 | |
0f113f3e | 23 | const SSL3_ENC_METHOD DTLSv1_enc_data = { |
0f113f3e MC |
24 | tls1_setup_key_block, |
25 | tls1_generate_master_secret, | |
26 | tls1_change_cipher_state, | |
27 | tls1_final_finish_mac, | |
0f113f3e MC |
28 | TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, |
29 | TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, | |
30 | tls1_alert_code, | |
31 | tls1_export_keying_material, | |
32 | SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV, | |
a29fa98c | 33 | dtls1_set_handshake_header, |
2c7b4dbc | 34 | dtls1_close_construct_packet, |
0f113f3e MC |
35 | dtls1_handshake_write |
36 | }; | |
37 | ||
38 | const SSL3_ENC_METHOD DTLSv1_2_enc_data = { | |
0f113f3e MC |
39 | tls1_setup_key_block, |
40 | tls1_generate_master_secret, | |
41 | tls1_change_cipher_state, | |
42 | tls1_final_finish_mac, | |
0f113f3e MC |
43 | TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, |
44 | TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, | |
45 | tls1_alert_code, | |
46 | tls1_export_keying_material, | |
47 | SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | |
48 | | SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS, | |
a29fa98c | 49 | dtls1_set_handshake_header, |
2c7b4dbc | 50 | dtls1_close_construct_packet, |
0f113f3e MC |
51 | dtls1_handshake_write |
52 | }; | |
c3b344e3 | 53 | |
f0131dc0 | 54 | OSSL_TIME dtls1_default_timeout(void) |
0f113f3e MC |
55 | { |
56 | /* | |
57 | * 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for | |
58 | * http, the cache would over fill | |
59 | */ | |
f0131dc0 | 60 | return ossl_seconds2time(60 * 60 * 2); |
0f113f3e | 61 | } |
36d16f8e | 62 | |
38b051a1 | 63 | int dtls1_new(SSL *ssl) |
0f113f3e MC |
64 | { |
65 | DTLS1_STATE *d1; | |
38b051a1 TM |
66 | SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
67 | ||
68 | if (s == NULL) | |
69 | return 0; | |
0f113f3e | 70 | |
61986d32 | 71 | if (!DTLS_RECORD_LAYER_new(&s->rlayer)) { |
5fb6f80c MC |
72 | return 0; |
73 | } | |
0485d540 | 74 | |
38b051a1 | 75 | if (!ssl3_new(ssl)) |
a89325e4 | 76 | return 0; |
b51bce94 | 77 | if ((d1 = OPENSSL_zalloc(sizeof(*d1))) == NULL) { |
38b051a1 | 78 | ssl3_free(ssl); |
a89325e4 | 79 | return 0; |
0f113f3e | 80 | } |
0f113f3e | 81 | |
0f113f3e MC |
82 | d1->buffered_messages = pqueue_new(); |
83 | d1->sent_messages = pqueue_new(); | |
0f113f3e MC |
84 | |
85 | if (s->server) { | |
86 | d1->cookie_len = sizeof(s->d1->cookie); | |
87 | } | |
88 | ||
89 | d1->link_mtu = 0; | |
90 | d1->mtu = 0; | |
91 | ||
a71edf3b | 92 | if (d1->buffered_messages == NULL || d1->sent_messages == NULL) { |
25aaa98a RS |
93 | pqueue_free(d1->buffered_messages); |
94 | pqueue_free(d1->sent_messages); | |
0f113f3e | 95 | OPENSSL_free(d1); |
38b051a1 | 96 | ssl3_free(ssl); |
a89325e4 | 97 | return 0; |
0f113f3e MC |
98 | } |
99 | ||
100 | s->d1 = d1; | |
b77f3ed1 | 101 | |
38b051a1 | 102 | if (!ssl->method->ssl_clear(ssl)) |
b77f3ed1 MC |
103 | return 0; |
104 | ||
a89325e4 | 105 | return 1; |
0f113f3e | 106 | } |
36d16f8e | 107 | |
38b051a1 | 108 | static void dtls1_clear_queues(SSL_CONNECTION *s) |
f5c7f5df MC |
109 | { |
110 | dtls1_clear_received_buffer(s); | |
111 | dtls1_clear_sent_buffer(s); | |
112 | } | |
113 | ||
38b051a1 | 114 | void dtls1_clear_received_buffer(SSL_CONNECTION *s) |
0f113f3e | 115 | { |
36d16f8e BL |
116 | pitem *item = NULL; |
117 | hm_fragment *frag = NULL; | |
0f113f3e | 118 | |
0f113f3e | 119 | while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) { |
36d16f8e | 120 | frag = (hm_fragment *)item->data; |
8a35dbb6 | 121 | dtls1_hm_fragment_free(frag); |
36d16f8e | 122 | pitem_free(item); |
0f113f3e | 123 | } |
f5c7f5df MC |
124 | } |
125 | ||
38b051a1 | 126 | void dtls1_clear_sent_buffer(SSL_CONNECTION *s) |
f5c7f5df MC |
127 | { |
128 | pitem *item = NULL; | |
129 | hm_fragment *frag = NULL; | |
36d16f8e | 130 | |
0f113f3e | 131 | while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) { |
36d16f8e | 132 | frag = (hm_fragment *)item->data; |
a091bc60 MC |
133 | |
134 | if (frag->msg_header.is_ccs | |
135 | && frag->msg_header.saved_retransmit_state.wrlmethod != NULL | |
136 | && s->rlayer.wrl != frag->msg_header.saved_retransmit_state.wrl) { | |
137 | /* | |
138 | * If we're freeing the CCS then we're done with the old wrl and it | |
139 | * can bee freed | |
140 | */ | |
141 | frag->msg_header.saved_retransmit_state.wrlmethod->free(frag->msg_header.saved_retransmit_state.wrl); | |
142 | } | |
143 | ||
8a35dbb6 | 144 | dtls1_hm_fragment_free(frag); |
36d16f8e | 145 | pitem_free(item); |
0f113f3e | 146 | } |
0f113f3e | 147 | } |
7832d6ab | 148 | |
f5c7f5df | 149 | |
38b051a1 | 150 | void dtls1_free(SSL *ssl) |
0f113f3e | 151 | { |
38b051a1 TM |
152 | SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
153 | ||
154 | if (s == NULL) | |
155 | return; | |
156 | ||
d0afb30e MC |
157 | if (s->d1 != NULL) { |
158 | dtls1_clear_queues(s); | |
159 | pqueue_free(s->d1->buffered_messages); | |
160 | pqueue_free(s->d1->sent_messages); | |
161 | } | |
e5fa864f | 162 | |
a091bc60 MC |
163 | DTLS_RECORD_LAYER_free(&s->rlayer); |
164 | ||
165 | ssl3_free(ssl); | |
166 | ||
0f113f3e MC |
167 | OPENSSL_free(s->d1); |
168 | s->d1 = NULL; | |
169 | } | |
36d16f8e | 170 | |
38b051a1 | 171 | int dtls1_clear(SSL *ssl) |
0f113f3e | 172 | { |
cf2cede4 RS |
173 | pqueue *buffered_messages; |
174 | pqueue *sent_messages; | |
7ee8627f MC |
175 | size_t mtu; |
176 | size_t link_mtu; | |
0f113f3e | 177 | |
38b051a1 TM |
178 | SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
179 | ||
180 | if (s == NULL) | |
181 | return 0; | |
182 | ||
40f37188 MC |
183 | DTLS_RECORD_LAYER_clear(&s->rlayer); |
184 | ||
0f113f3e | 185 | if (s->d1) { |
fa4b82cc AH |
186 | DTLS_timer_cb timer_cb = s->d1->timer_cb; |
187 | ||
0f113f3e MC |
188 | buffered_messages = s->d1->buffered_messages; |
189 | sent_messages = s->d1->sent_messages; | |
0f113f3e MC |
190 | mtu = s->d1->mtu; |
191 | link_mtu = s->d1->link_mtu; | |
192 | ||
193 | dtls1_clear_queues(s); | |
194 | ||
16f8d4eb | 195 | memset(s->d1, 0, sizeof(*s->d1)); |
0f113f3e | 196 | |
fa4b82cc AH |
197 | /* Restore the timer callback from previous state */ |
198 | s->d1->timer_cb = timer_cb; | |
199 | ||
0f113f3e MC |
200 | if (s->server) { |
201 | s->d1->cookie_len = sizeof(s->d1->cookie); | |
202 | } | |
203 | ||
38b051a1 | 204 | if (SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU) { |
0f113f3e MC |
205 | s->d1->mtu = mtu; |
206 | s->d1->link_mtu = link_mtu; | |
207 | } | |
208 | ||
0f113f3e MC |
209 | s->d1->buffered_messages = buffered_messages; |
210 | s->d1->sent_messages = sent_messages; | |
0f113f3e MC |
211 | } |
212 | ||
38b051a1 | 213 | if (!ssl3_clear(ssl)) |
b77f3ed1 | 214 | return 0; |
032924c4 | 215 | |
38b051a1 | 216 | if (ssl->method->version == DTLS_ANY_VERSION) |
5c587fb6 | 217 | s->version = DTLS_MAX_VERSION_INTERNAL; |
032924c4 DW |
218 | #ifndef OPENSSL_NO_DTLS1_METHOD |
219 | else if (s->options & SSL_OP_CISCO_ANYCONNECT) | |
220 | s->client_version = s->version = DTLS1_BAD_VER; | |
221 | #endif | |
0f113f3e | 222 | else |
38b051a1 | 223 | s->version = ssl->method->version; |
b77f3ed1 MC |
224 | |
225 | return 1; | |
0f113f3e | 226 | } |
5d58f1bb | 227 | |
38b051a1 | 228 | long dtls1_ctrl(SSL *ssl, int cmd, long larg, void *parg) |
0f113f3e MC |
229 | { |
230 | int ret = 0; | |
f0131dc0 | 231 | OSSL_TIME t; |
38b051a1 TM |
232 | SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
233 | ||
234 | if (s == NULL) | |
235 | return 0; | |
0f113f3e MC |
236 | |
237 | switch (cmd) { | |
238 | case DTLS_CTRL_GET_TIMEOUT: | |
24a32254 | 239 | if (dtls1_get_timeout(s, &t)) { |
f0131dc0 | 240 | *(struct timeval *)parg = ossl_time_to_timeval(t); |
0f113f3e MC |
241 | ret = 1; |
242 | } | |
243 | break; | |
244 | case DTLS_CTRL_HANDLE_TIMEOUT: | |
245 | ret = dtls1_handle_timeout(s); | |
246 | break; | |
0f113f3e MC |
247 | case DTLS_CTRL_SET_LINK_MTU: |
248 | if (larg < (long)dtls1_link_min_mtu()) | |
249 | return 0; | |
250 | s->d1->link_mtu = larg; | |
251 | return 1; | |
252 | case DTLS_CTRL_GET_LINK_MIN_MTU: | |
253 | return (long)dtls1_link_min_mtu(); | |
254 | case SSL_CTRL_SET_MTU: | |
255 | /* | |
256 | * We may not have a BIO set yet so can't call dtls1_min_mtu() | |
257 | * We'll have to make do with dtls1_link_min_mtu() and max overhead | |
258 | */ | |
259 | if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD) | |
260 | return 0; | |
261 | s->d1->mtu = larg; | |
262 | return larg; | |
263 | default: | |
38b051a1 | 264 | ret = ssl3_ctrl(ssl, cmd, larg, parg); |
0f113f3e MC |
265 | break; |
266 | } | |
26a7d938 | 267 | return ret; |
0f113f3e | 268 | } |
b972fbaa | 269 | |
bbaeadb0 | 270 | static void dtls1_bio_set_next_timeout(BIO *bio, const DTLS1_STATE *d1) |
24a32254 F |
271 | { |
272 | struct timeval tv = ossl_time_to_timeval(d1->next_timeout); | |
273 | ||
274 | BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &tv); | |
275 | } | |
276 | ||
38b051a1 | 277 | void dtls1_start_timer(SSL_CONNECTION *s) |
0f113f3e | 278 | { |
f0131dc0 | 279 | OSSL_TIME duration; |
38b051a1 | 280 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
fa4b82cc | 281 | |
7e159e01 | 282 | #ifndef OPENSSL_NO_SCTP |
0f113f3e | 283 | /* Disable timer for SCTP */ |
38b051a1 | 284 | if (BIO_dgram_is_sctp(SSL_get_wbio(ssl))) { |
f0131dc0 | 285 | s->d1->next_timeout = ossl_time_zero(); |
0f113f3e MC |
286 | return; |
287 | } | |
7e159e01 DSH |
288 | #endif |
289 | ||
fa4b82cc AH |
290 | /* |
291 | * If timer is not set, initialize duration with 1 second or | |
292 | * a user-specified value if the timer callback is installed. | |
293 | */ | |
f0131dc0 | 294 | if (ossl_time_is_zero(s->d1->next_timeout)) { |
fa4b82cc | 295 | if (s->d1->timer_cb != NULL) |
38b051a1 | 296 | s->d1->timeout_duration_us = s->d1->timer_cb(ssl, 0); |
fa4b82cc AH |
297 | else |
298 | s->d1->timeout_duration_us = 1000000; | |
0f113f3e MC |
299 | } |
300 | ||
f0131dc0 P |
301 | /* Set timeout to current time plus duration */ |
302 | duration = ossl_us2time(s->d1->timeout_duration_us); | |
303 | s->d1->next_timeout = ossl_time_add(ossl_time_now(), duration); | |
fa4b82cc | 304 | |
24a32254 F |
305 | /* set s->d1->next_timeout into ssl->rbio interface */ |
306 | dtls1_bio_set_next_timeout(SSL_get_rbio(ssl), s->d1); | |
0f113f3e MC |
307 | } |
308 | ||
24a32254 | 309 | int dtls1_get_timeout(const SSL_CONNECTION *s, OSSL_TIME *timeleft) |
0f113f3e | 310 | { |
f0131dc0 | 311 | OSSL_TIME timenow; |
0f113f3e MC |
312 | |
313 | /* If no timeout is set, just return NULL */ | |
f0131dc0 | 314 | if (ossl_time_is_zero(s->d1->next_timeout)) |
24a32254 | 315 | return 0; |
0f113f3e MC |
316 | |
317 | /* Get current time */ | |
f0131dc0 | 318 | timenow = ossl_time_now(); |
0f113f3e MC |
319 | |
320 | /* | |
f0131dc0 P |
321 | * If timer already expired or if remaining time is less than 15 ms, |
322 | * set it to 0 to prevent issues because of small divergences with | |
323 | * socket timeouts. | |
0f113f3e | 324 | */ |
f0131dc0 P |
325 | *timeleft = ossl_time_subtract(s->d1->next_timeout, timenow); |
326 | if (ossl_time_compare(*timeleft, ossl_ms2time(15)) <= 0) | |
327 | *timeleft = ossl_time_zero(); | |
24a32254 | 328 | return 1; |
0f113f3e | 329 | } |
eb38b26d | 330 | |
38b051a1 | 331 | int dtls1_is_timer_expired(SSL_CONNECTION *s) |
0f113f3e | 332 | { |
f0131dc0 | 333 | OSSL_TIME timeleft; |
eb38b26d | 334 | |
0f113f3e | 335 | /* Get time left until timeout, return false if no timer running */ |
24a32254 | 336 | if (!dtls1_get_timeout(s, &timeleft)) |
0f113f3e | 337 | return 0; |
eb38b26d | 338 | |
0f113f3e | 339 | /* Return false if timer is not expired yet */ |
24a32254 | 340 | if (!ossl_time_is_zero(timeleft)) |
0f113f3e | 341 | return 0; |
eb38b26d | 342 | |
0f113f3e MC |
343 | /* Timer expired, so return true */ |
344 | return 1; | |
345 | } | |
eb38b26d | 346 | |
38b051a1 | 347 | static void dtls1_double_timeout(SSL_CONNECTION *s) |
0f113f3e | 348 | { |
fa4b82cc AH |
349 | s->d1->timeout_duration_us *= 2; |
350 | if (s->d1->timeout_duration_us > 60000000) | |
351 | s->d1->timeout_duration_us = 60000000; | |
0f113f3e | 352 | } |
eb38b26d | 353 | |
38b051a1 | 354 | void dtls1_stop_timer(SSL_CONNECTION *s) |
0f113f3e MC |
355 | { |
356 | /* Reset everything */ | |
b5557666 | 357 | s->d1->timeout_num_alerts = 0; |
f0131dc0 | 358 | s->d1->next_timeout = ossl_time_zero(); |
fa4b82cc | 359 | s->d1->timeout_duration_us = 1000000; |
24a32254 | 360 | dtls1_bio_set_next_timeout(s->rbio, s->d1); |
0f113f3e | 361 | /* Clear retransmission buffer */ |
f5c7f5df | 362 | dtls1_clear_sent_buffer(s); |
0f113f3e | 363 | } |
eb38b26d | 364 | |
38b051a1 | 365 | int dtls1_check_timeout_num(SSL_CONNECTION *s) |
0f113f3e | 366 | { |
7ee8627f | 367 | size_t mtu; |
38b051a1 | 368 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
0f113f3e | 369 | |
b5557666 | 370 | s->d1->timeout_num_alerts++; |
0f113f3e MC |
371 | |
372 | /* Reduce MTU after 2 unsuccessful retransmissions */ | |
b5557666 | 373 | if (s->d1->timeout_num_alerts > 2 |
38b051a1 | 374 | && !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { |
0f113f3e | 375 | mtu = |
38b051a1 | 376 | BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); |
0f113f3e MC |
377 | if (mtu < s->d1->mtu) |
378 | s->d1->mtu = mtu; | |
379 | } | |
380 | ||
b5557666 | 381 | if (s->d1->timeout_num_alerts > DTLS1_TMO_ALERT_COUNT) { |
0f113f3e | 382 | /* fail the connection, enough alerts have been sent */ |
c48ffbcc | 383 | SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_READ_TIMEOUT_EXPIRED); |
0f113f3e MC |
384 | return -1; |
385 | } | |
386 | ||
387 | return 0; | |
388 | } | |
ea6e3860 | 389 | |
38b051a1 | 390 | int dtls1_handle_timeout(SSL_CONNECTION *s) |
0f113f3e MC |
391 | { |
392 | /* if no timer is expired, don't do anything */ | |
393 | if (!dtls1_is_timer_expired(s)) { | |
394 | return 0; | |
395 | } | |
ea6e3860 | 396 | |
fa4b82cc | 397 | if (s->d1->timer_cb != NULL) |
38b051a1 TM |
398 | s->d1->timeout_duration_us = s->d1->timer_cb(SSL_CONNECTION_GET_SSL(s), |
399 | s->d1->timeout_duration_us); | |
fa4b82cc AH |
400 | else |
401 | dtls1_double_timeout(s); | |
ea6e3860 | 402 | |
c2853382 MC |
403 | if (dtls1_check_timeout_num(s) < 0) { |
404 | /* SSLfatal() already called */ | |
0f113f3e | 405 | return -1; |
c2853382 | 406 | } |
62b6948a | 407 | |
0f113f3e | 408 | dtls1_start_timer(s); |
c2853382 | 409 | /* Calls SSLfatal() if required */ |
0f113f3e MC |
410 | return dtls1_retransmit_buffered_messages(s); |
411 | } | |
b972fbaa | 412 | |
e3d0dae7 MC |
413 | #define LISTEN_SUCCESS 2 |
414 | #define LISTEN_SEND_VERIFY_REQUEST 1 | |
415 | ||
f9e55034 | 416 | #ifndef OPENSSL_NO_SOCK |
38b051a1 | 417 | int DTLSv1_listen(SSL *ssl, BIO_ADDR *client) |
0f113f3e | 418 | { |
079ef6bd | 419 | int next, n, ret = 0; |
e3d0dae7 MC |
420 | unsigned char cookie[DTLS1_COOKIE_LENGTH]; |
421 | unsigned char seq[SEQ_NUM_SIZE]; | |
b6981744 | 422 | const unsigned char *data; |
81c9ebd9 MC |
423 | unsigned char *buf = NULL, *wbuf; |
424 | size_t fragoff, fraglen, msglen; | |
5f79670f | 425 | unsigned int rectype, versmajor, versminor, msgseq, msgtype, clientvers, cookielen; |
e3d0dae7 | 426 | BIO *rbio, *wbio; |
d858c876 | 427 | BIO_ADDR *tmpclient = NULL; |
e3d0dae7 | 428 | PACKET pkt, msgpkt, msgpayload, session, cookiepkt; |
38b051a1 TM |
429 | SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
430 | ||
431 | if (s == NULL) | |
432 | return -1; | |
0f113f3e | 433 | |
5bdcd362 MC |
434 | if (s->handshake_func == NULL) { |
435 | /* Not properly initialized yet */ | |
38b051a1 | 436 | SSL_set_accept_state(ssl); |
5bdcd362 MC |
437 | } |
438 | ||
e83ee04b | 439 | /* Ensure there is no state left over from a previous invocation */ |
38b051a1 | 440 | if (!SSL_clear(ssl)) |
c7f5b5d7 | 441 | return -1; |
e83ee04b | 442 | |
e3d0dae7 MC |
443 | ERR_clear_error(); |
444 | ||
38b051a1 TM |
445 | rbio = SSL_get_rbio(ssl); |
446 | wbio = SSL_get_wbio(ssl); | |
e3d0dae7 | 447 | |
e8aa8b6c | 448 | if (!rbio || !wbio) { |
6849b73c | 449 | ERR_raise(ERR_LIB_SSL, SSL_R_BIO_NOT_SET); |
e3d0dae7 MC |
450 | return -1; |
451 | } | |
452 | ||
e3d0dae7 MC |
453 | /* |
454 | * Note: This check deliberately excludes DTLS1_BAD_VER because that version | |
455 | * requires the MAC to be calculated *including* the first ClientHello | |
456 | * (without the cookie). Since DTLSv1_listen is stateless that cannot be | |
457 | * supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via | |
458 | * SSL_accept) | |
459 | */ | |
460 | if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { | |
6849b73c | 461 | ERR_raise(ERR_LIB_SSL, SSL_R_UNSUPPORTED_SSL_VERSION); |
e3d0dae7 MC |
462 | return -1; |
463 | } | |
464 | ||
81c9ebd9 | 465 | buf = OPENSSL_malloc(DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_PLAIN_LENGTH); |
e077455e | 466 | if (buf == NULL) |
81c9ebd9 | 467 | return -1; |
e158ada6 | 468 | wbuf = OPENSSL_malloc(DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_PLAIN_LENGTH); |
7ccccb26 DF |
469 | if (wbuf == NULL) { |
470 | OPENSSL_free(buf); | |
e158ada6 | 471 | return -1; |
7ccccb26 | 472 | } |
e3d0dae7 MC |
473 | |
474 | do { | |
475 | /* Get a packet */ | |
476 | ||
477 | clear_sys_error(); | |
2fc4c77c MC |
478 | n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH |
479 | + DTLS1_RT_HEADER_LENGTH); | |
e3d0dae7 | 480 | if (n <= 0) { |
e8aa8b6c | 481 | if (BIO_should_retry(rbio)) { |
e3d0dae7 MC |
482 | /* Non-blocking IO */ |
483 | goto end; | |
484 | } | |
81c9ebd9 MC |
485 | ret = -1; |
486 | goto end; | |
e3d0dae7 MC |
487 | } |
488 | ||
e3d0dae7 | 489 | if (!PACKET_buf_init(&pkt, buf, n)) { |
6849b73c | 490 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
81c9ebd9 MC |
491 | ret = -1; |
492 | goto end; | |
e3d0dae7 MC |
493 | } |
494 | ||
495 | /* | |
496 | * Parse the received record. If there are any problems with it we just | |
497 | * dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is | |
498 | * resilient in the face of invalid records (e.g., invalid formatting, | |
499 | * length, MAC, etc.). In general, invalid records SHOULD be silently | |
500 | * discarded, thus preserving the association; however, an error MAY be | |
501 | * logged for diagnostic purposes." | |
502 | */ | |
503 | ||
504 | /* this packet contained a partial record, dump it */ | |
505 | if (n < DTLS1_RT_HEADER_LENGTH) { | |
6849b73c | 506 | ERR_raise(ERR_LIB_SSL, SSL_R_RECORD_TOO_SMALL); |
e3d0dae7 MC |
507 | goto end; |
508 | } | |
509 | ||
e3d0dae7 MC |
510 | /* Get the record header */ |
511 | if (!PACKET_get_1(&pkt, &rectype) | |
5f79670f FWH |
512 | || !PACKET_get_1(&pkt, &versmajor) |
513 | || !PACKET_get_1(&pkt, &versminor)) { | |
6849b73c | 514 | ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH); |
e3d0dae7 MC |
515 | goto end; |
516 | } | |
517 | ||
5f79670f FWH |
518 | if (s->msg_callback) |
519 | s->msg_callback(0, (versmajor << 8) | versminor, SSL3_RT_HEADER, buf, | |
520 | DTLS1_RT_HEADER_LENGTH, ssl, s->msg_callback_arg); | |
521 | ||
a230b26e | 522 | if (rectype != SSL3_RT_HANDSHAKE) { |
6849b73c | 523 | ERR_raise(ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE); |
e3d0dae7 MC |
524 | goto end; |
525 | } | |
526 | ||
527 | /* | |
528 | * Check record version number. We only check that the major version is | |
529 | * the same. | |
530 | */ | |
531 | if (versmajor != DTLS1_VERSION_MAJOR) { | |
6849b73c | 532 | ERR_raise(ERR_LIB_SSL, SSL_R_BAD_PROTOCOL_VERSION_NUMBER); |
e3d0dae7 MC |
533 | goto end; |
534 | } | |
535 | ||
5f79670f FWH |
536 | /* Save the sequence number: 64 bits, with top 2 bytes = epoch */ |
537 | if (!PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE) | |
4b1043ef | 538 | || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) { |
6849b73c | 539 | ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH); |
e3d0dae7 MC |
540 | goto end; |
541 | } | |
4b1043ef MC |
542 | /* |
543 | * We allow data remaining at the end of the packet because there could | |
544 | * be a second record (but we ignore it) | |
545 | */ | |
e3d0dae7 MC |
546 | |
547 | /* This is an initial ClientHello so the epoch has to be 0 */ | |
548 | if (seq[0] != 0 || seq[1] != 0) { | |
6849b73c | 549 | ERR_raise(ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE); |
e3d0dae7 MC |
550 | goto end; |
551 | } | |
552 | ||
553 | /* Get a pointer to the raw message for the later callback */ | |
554 | data = PACKET_data(&msgpkt); | |
555 | ||
556 | /* Finished processing the record header, now process the message */ | |
557 | if (!PACKET_get_1(&msgpkt, &msgtype) | |
153703df | 558 | || !PACKET_get_net_3_len(&msgpkt, &msglen) |
e3d0dae7 | 559 | || !PACKET_get_net_2(&msgpkt, &msgseq) |
153703df MC |
560 | || !PACKET_get_net_3_len(&msgpkt, &fragoff) |
561 | || !PACKET_get_net_3_len(&msgpkt, &fraglen) | |
4b1043ef | 562 | || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen) |
e3d0dae7 | 563 | || PACKET_remaining(&msgpkt) != 0) { |
6849b73c | 564 | ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH); |
e3d0dae7 MC |
565 | goto end; |
566 | } | |
567 | ||
568 | if (msgtype != SSL3_MT_CLIENT_HELLO) { | |
6849b73c | 569 | ERR_raise(ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE); |
e3d0dae7 MC |
570 | goto end; |
571 | } | |
572 | ||
573 | /* Message sequence number can only be 0 or 1 */ | |
e8aa8b6c | 574 | if (msgseq > 2) { |
6849b73c | 575 | ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SEQUENCE_NUMBER); |
e3d0dae7 MC |
576 | goto end; |
577 | } | |
578 | ||
4b1043ef MC |
579 | /* |
580 | * We don't support fragment reassembly for ClientHellos whilst | |
581 | * listening because that would require server side state (which is | |
582 | * against the whole point of the ClientHello/HelloVerifyRequest | |
583 | * mechanism). Instead we only look at the first ClientHello fragment | |
584 | * and require that the cookie must be contained within it. | |
585 | */ | |
586 | if (fragoff != 0 || fraglen > msglen) { | |
587 | /* Non initial ClientHello fragment (or bad fragment) */ | |
6849b73c | 588 | ERR_raise(ERR_LIB_SSL, SSL_R_FRAGMENTED_CLIENT_HELLO); |
e3d0dae7 MC |
589 | goto end; |
590 | } | |
591 | ||
592 | if (s->msg_callback) | |
593 | s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data, | |
38b051a1 | 594 | fraglen + DTLS1_HM_HEADER_LENGTH, ssl, |
e3d0dae7 MC |
595 | s->msg_callback_arg); |
596 | ||
597 | if (!PACKET_get_net_2(&msgpayload, &clientvers)) { | |
6849b73c | 598 | ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH); |
e3d0dae7 MC |
599 | goto end; |
600 | } | |
601 | ||
602 | /* | |
603 | * Verify client version is supported | |
604 | */ | |
38b051a1 TM |
605 | if (DTLS_VERSION_LT(clientvers, (unsigned int)ssl->method->version) && |
606 | ssl->method->version != DTLS_ANY_VERSION) { | |
6849b73c | 607 | ERR_raise(ERR_LIB_SSL, SSL_R_WRONG_VERSION_NUMBER); |
e3d0dae7 MC |
608 | goto end; |
609 | } | |
610 | ||
611 | if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE) | |
612 | || !PACKET_get_length_prefixed_1(&msgpayload, &session) | |
613 | || !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) { | |
4b1043ef MC |
614 | /* |
615 | * Could be malformed or the cookie does not fit within the initial | |
616 | * ClientHello fragment. Either way we can't handle it. | |
617 | */ | |
6849b73c | 618 | ERR_raise(ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH); |
e3d0dae7 MC |
619 | goto end; |
620 | } | |
621 | ||
622 | /* | |
623 | * Check if we have a cookie or not. If not we need to send a | |
624 | * HelloVerifyRequest. | |
625 | */ | |
626 | if (PACKET_remaining(&cookiepkt) == 0) { | |
627 | next = LISTEN_SEND_VERIFY_REQUEST; | |
628 | } else { | |
629 | /* | |
630 | * We have a cookie, so lets check it. | |
631 | */ | |
38b051a1 | 632 | if (ssl->ctx->app_verify_cookie_cb == NULL) { |
6849b73c | 633 | ERR_raise(ERR_LIB_SSL, SSL_R_NO_VERIFY_COOKIE_CALLBACK); |
e3d0dae7 | 634 | /* This is fatal */ |
81c9ebd9 MC |
635 | ret = -1; |
636 | goto end; | |
e3d0dae7 | 637 | } |
38b051a1 | 638 | if (ssl->ctx->app_verify_cookie_cb(ssl, PACKET_data(&cookiepkt), |
8b0e934a | 639 | (unsigned int)PACKET_remaining(&cookiepkt)) == 0) { |
e3d0dae7 MC |
640 | /* |
641 | * We treat invalid cookies in the same was as no cookie as | |
642 | * per RFC6347 | |
643 | */ | |
644 | next = LISTEN_SEND_VERIFY_REQUEST; | |
645 | } else { | |
646 | /* Cookie verification succeeded */ | |
647 | next = LISTEN_SUCCESS; | |
648 | } | |
649 | } | |
650 | ||
651 | if (next == LISTEN_SEND_VERIFY_REQUEST) { | |
c536b6be MC |
652 | WPACKET wpkt; |
653 | unsigned int version; | |
654 | size_t wreclen; | |
655 | ||
e3d0dae7 MC |
656 | /* |
657 | * There was no cookie in the ClientHello so we need to send a | |
658 | * HelloVerifyRequest. If this fails we do not worry about trying | |
659 | * to resend, we just drop it. | |
660 | */ | |
661 | ||
e3d0dae7 | 662 | /* Generate the cookie */ |
38b051a1 TM |
663 | if (ssl->ctx->app_gen_cookie_cb == NULL || |
664 | ssl->ctx->app_gen_cookie_cb(ssl, cookie, &cookielen) == 0 || | |
373dc6e1 | 665 | cookielen > 255) { |
6849b73c | 666 | ERR_raise(ERR_LIB_SSL, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); |
e3d0dae7 | 667 | /* This is fatal */ |
81c9ebd9 MC |
668 | ret = -1; |
669 | goto end; | |
e3d0dae7 MC |
670 | } |
671 | ||
e3d0dae7 MC |
672 | /* |
673 | * Special case: for hello verify request, client version 1.0 and we | |
674 | * haven't decided which version to use yet send back using version | |
675 | * 1.0 header: otherwise some clients will ignore it. | |
676 | */ | |
38b051a1 TM |
677 | version = (ssl->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION |
678 | : s->version; | |
c536b6be MC |
679 | |
680 | /* Construct the record and message headers */ | |
2fc4c77c MC |
681 | if (!WPACKET_init_static_len(&wpkt, |
682 | wbuf, | |
079ef6bd | 683 | ssl_get_max_send_fragment(s) |
2fc4c77c MC |
684 | + DTLS1_RT_HEADER_LENGTH, |
685 | 0) | |
c536b6be MC |
686 | || !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE) |
687 | || !WPACKET_put_bytes_u16(&wpkt, version) | |
688 | /* | |
689 | * Record sequence number is always the same as in the | |
690 | * received ClientHello | |
691 | */ | |
692 | || !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE) | |
693 | /* End of record, start sub packet for message */ | |
694 | || !WPACKET_start_sub_packet_u16(&wpkt) | |
695 | /* Message type */ | |
696 | || !WPACKET_put_bytes_u8(&wpkt, | |
697 | DTLS1_MT_HELLO_VERIFY_REQUEST) | |
698 | /* | |
699 | * Message length - doesn't follow normal TLS convention: | |
700 | * the length isn't the last thing in the message header. | |
701 | * We'll need to fill this in later when we know the | |
702 | * length. Set it to zero for now | |
703 | */ | |
704 | || !WPACKET_put_bytes_u24(&wpkt, 0) | |
705 | /* | |
706 | * Message sequence number is always 0 for a | |
707 | * HelloVerifyRequest | |
708 | */ | |
709 | || !WPACKET_put_bytes_u16(&wpkt, 0) | |
710 | /* | |
711 | * We never fragment a HelloVerifyRequest, so fragment | |
712 | * offset is 0 | |
713 | */ | |
714 | || !WPACKET_put_bytes_u24(&wpkt, 0) | |
715 | /* | |
716 | * Fragment length is the same as message length, but | |
717 | * this *is* the last thing in the message header so we | |
718 | * can just start a sub-packet. No need to come back | |
719 | * later for this one. | |
720 | */ | |
721 | || !WPACKET_start_sub_packet_u24(&wpkt) | |
722 | /* Create the actual HelloVerifyRequest body */ | |
723 | || !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen) | |
724 | /* Close message body */ | |
725 | || !WPACKET_close(&wpkt) | |
726 | /* Close record body */ | |
727 | || !WPACKET_close(&wpkt) | |
728 | || !WPACKET_get_total_written(&wpkt, &wreclen) | |
729 | || !WPACKET_finish(&wpkt)) { | |
6849b73c | 730 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
c536b6be MC |
731 | WPACKET_cleanup(&wpkt); |
732 | /* This is fatal */ | |
81c9ebd9 MC |
733 | ret = -1; |
734 | goto end; | |
e3d0dae7 MC |
735 | } |
736 | ||
737 | /* | |
c536b6be MC |
738 | * Fix up the message len in the message header. Its the same as the |
739 | * fragment len which has been filled in by WPACKET, so just copy | |
740 | * that. Destination for the message len is after the record header | |
741 | * plus one byte for the message content type. The source is the | |
742 | * last 3 bytes of the message header | |
e3d0dae7 | 743 | */ |
2fc4c77c MC |
744 | memcpy(&wbuf[DTLS1_RT_HEADER_LENGTH + 1], |
745 | &wbuf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3], | |
c536b6be | 746 | 3); |
e3d0dae7 MC |
747 | |
748 | if (s->msg_callback) | |
749 | s->msg_callback(1, 0, SSL3_RT_HEADER, buf, | |
38b051a1 TM |
750 | DTLS1_RT_HEADER_LENGTH, ssl, |
751 | s->msg_callback_arg); | |
e3d0dae7 | 752 | |
ce0865d8 | 753 | if ((tmpclient = BIO_ADDR_new()) == NULL) { |
e077455e | 754 | ERR_raise(ERR_LIB_SSL, ERR_R_BIO_LIB); |
ce0865d8 MC |
755 | goto end; |
756 | } | |
757 | ||
e3d0dae7 | 758 | /* |
8483a003 | 759 | * This is unnecessary if rbio and wbio are one and the same - but |
ce0865d8 MC |
760 | * maybe they're not. We ignore errors here - some BIOs do not |
761 | * support this. | |
e3d0dae7 | 762 | */ |
e8aa8b6c | 763 | if (BIO_dgram_get_peer(rbio, tmpclient) > 0) { |
ce0865d8 | 764 | (void)BIO_dgram_set_peer(wbio, tmpclient); |
e3d0dae7 | 765 | } |
d858c876 RL |
766 | BIO_ADDR_free(tmpclient); |
767 | tmpclient = NULL; | |
e3d0dae7 | 768 | |
2fc4c77c | 769 | if (BIO_write(wbio, wbuf, wreclen) < (int)wreclen) { |
e8aa8b6c | 770 | if (BIO_should_retry(wbio)) { |
e3d0dae7 MC |
771 | /* |
772 | * Non-blocking IO...but we're stateless, so we're just | |
773 | * going to drop this packet. | |
774 | */ | |
775 | goto end; | |
776 | } | |
81c9ebd9 MC |
777 | ret = -1; |
778 | goto end; | |
e3d0dae7 MC |
779 | } |
780 | ||
781 | if (BIO_flush(wbio) <= 0) { | |
e8aa8b6c | 782 | if (BIO_should_retry(wbio)) { |
e3d0dae7 MC |
783 | /* |
784 | * Non-blocking IO...but we're stateless, so we're just | |
785 | * going to drop this packet. | |
786 | */ | |
787 | goto end; | |
788 | } | |
81c9ebd9 MC |
789 | ret = -1; |
790 | goto end; | |
e3d0dae7 MC |
791 | } |
792 | } | |
793 | } while (next != LISTEN_SUCCESS); | |
794 | ||
795 | /* | |
796 | * Set expected sequence numbers to continue the handshake. | |
797 | */ | |
798 | s->d1->handshake_read_seq = 1; | |
799 | s->d1->handshake_write_seq = 1; | |
800 | s->d1->next_handshake_write_seq = 1; | |
b92fc4ae | 801 | s->rlayer.wrlmethod->increment_sequence_ctr(s->rlayer.wrl); |
e3d0dae7 MC |
802 | |
803 | /* | |
804 | * We are doing cookie exchange, so make sure we set that option in the | |
805 | * SSL object | |
806 | */ | |
38b051a1 | 807 | SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); |
1fc3ac80 | 808 | |
31fd10e6 MC |
809 | /* |
810 | * Tell the state machine that we've done the initial hello verify | |
811 | * exchange | |
812 | */ | |
813 | ossl_statem_set_hello_verify_done(s); | |
e3d0dae7 | 814 | |
a230b26e EK |
815 | /* |
816 | * Some BIOs may not support this. If we fail we clear the client address | |
817 | */ | |
ce0865d8 MC |
818 | if (BIO_dgram_get_peer(rbio, client) <= 0) |
819 | BIO_ADDR_clear(client); | |
1fc3ac80 | 820 | |
81c9ebd9 | 821 | /* Buffer the record for use by the record layer */ |
cffafb5f | 822 | if (BIO_write(s->rlayer.rrlnext, buf, n) != n) { |
81c9ebd9 MC |
823 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
824 | ret = -1; | |
825 | goto end; | |
826 | } | |
827 | ||
828 | /* | |
829 | * Reset the record layer - but this time we can use the record we just | |
cffafb5f | 830 | * buffered in s->rlayer.rrlnext |
81c9ebd9 MC |
831 | */ |
832 | if (!ssl_set_new_record_layer(s, | |
833 | DTLS_ANY_VERSION, | |
834 | OSSL_RECORD_DIRECTION_READ, | |
3f9175c7 | 835 | OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0, |
81c9ebd9 | 836 | NULL, 0, NULL, 0, NULL, 0, NULL, 0, |
3f9175c7 | 837 | NID_undef, NULL, NULL, NULL)) { |
81c9ebd9 MC |
838 | /* SSLfatal already called */ |
839 | ret = -1; | |
840 | goto end; | |
841 | } | |
2fc4c77c | 842 | |
e3d0dae7 | 843 | ret = 1; |
a230b26e | 844 | end: |
d858c876 | 845 | BIO_ADDR_free(tmpclient); |
81c9ebd9 | 846 | OPENSSL_free(buf); |
e158ada6 | 847 | OPENSSL_free(wbuf); |
e3d0dae7 | 848 | return ret; |
0f113f3e | 849 | } |
f9e55034 | 850 | #endif |
173e72e6 | 851 | |
38b051a1 | 852 | static int dtls1_handshake_write(SSL_CONNECTION *s) |
0f113f3e MC |
853 | { |
854 | return dtls1_do_write(s, SSL3_RT_HANDSHAKE); | |
855 | } | |
8ba708e5 | 856 | |
8ba708e5 MC |
857 | int dtls1_shutdown(SSL *s) |
858 | { | |
859 | int ret; | |
860 | #ifndef OPENSSL_NO_SCTP | |
861 | BIO *wbio; | |
38b051a1 TM |
862 | SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL_ONLY(s); |
863 | ||
864 | if (s == NULL) | |
865 | return -1; | |
8ba708e5 MC |
866 | |
867 | wbio = SSL_get_wbio(s); | |
868 | if (wbio != NULL && BIO_dgram_is_sctp(wbio) && | |
38b051a1 | 869 | !(sc->shutdown & SSL_SENT_SHUTDOWN)) { |
8ba708e5 MC |
870 | ret = BIO_dgram_sctp_wait_for_dry(wbio); |
871 | if (ret < 0) | |
872 | return -1; | |
873 | ||
874 | if (ret == 0) | |
875 | BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, | |
876 | NULL); | |
877 | } | |
878 | #endif | |
879 | ret = ssl3_shutdown(s); | |
880 | #ifndef OPENSSL_NO_SCTP | |
881 | BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL); | |
882 | #endif | |
883 | return ret; | |
884 | } | |
885 | ||
38b051a1 | 886 | int dtls1_query_mtu(SSL_CONNECTION *s) |
8ba708e5 | 887 | { |
38b051a1 TM |
888 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
889 | ||
8ba708e5 MC |
890 | if (s->d1->link_mtu) { |
891 | s->d1->mtu = | |
38b051a1 | 892 | s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(ssl)); |
8ba708e5 MC |
893 | s->d1->link_mtu = 0; |
894 | } | |
895 | ||
896 | /* AHA! Figure out the MTU, and stick to the right size */ | |
897 | if (s->d1->mtu < dtls1_min_mtu(s)) { | |
38b051a1 | 898 | if (!(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { |
8ba708e5 | 899 | s->d1->mtu = |
38b051a1 | 900 | BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); |
8ba708e5 MC |
901 | |
902 | /* | |
903 | * I've seen the kernel return bogus numbers when it doesn't know | |
904 | * (initial write), so just make sure we have a reasonable number | |
905 | */ | |
906 | if (s->d1->mtu < dtls1_min_mtu(s)) { | |
907 | /* Set to min mtu */ | |
908 | s->d1->mtu = dtls1_min_mtu(s); | |
38b051a1 | 909 | BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, |
8b0e934a | 910 | (long)s->d1->mtu, NULL); |
8ba708e5 MC |
911 | } |
912 | } else | |
913 | return 0; | |
914 | } | |
915 | return 1; | |
916 | } | |
917 | ||
7ee8627f | 918 | static size_t dtls1_link_min_mtu(void) |
8ba708e5 MC |
919 | { |
920 | return (g_probable_mtu[(sizeof(g_probable_mtu) / | |
921 | sizeof(g_probable_mtu[0])) - 1]); | |
922 | } | |
923 | ||
38b051a1 | 924 | size_t dtls1_min_mtu(SSL_CONNECTION *s) |
8ba708e5 | 925 | { |
38b051a1 TM |
926 | SSL *ssl = SSL_CONNECTION_GET_SSL(s); |
927 | ||
928 | return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(ssl)); | |
8ba708e5 | 929 | } |
045bd047 | 930 | |
38b051a1 | 931 | size_t DTLS_get_data_mtu(const SSL *ssl) |
045bd047 DW |
932 | { |
933 | size_t mac_overhead, int_overhead, blocksize, ext_overhead; | |
38b051a1 TM |
934 | const SSL_CIPHER *ciph = SSL_get_current_cipher(ssl); |
935 | size_t mtu; | |
936 | const SSL_CONNECTION *s = SSL_CONNECTION_FROM_CONST_SSL_ONLY(ssl); | |
937 | ||
938 | if (s == NULL) | |
939 | return 0; | |
940 | ||
941 | mtu = s->d1->mtu; | |
045bd047 DW |
942 | |
943 | if (ciph == NULL) | |
944 | return 0; | |
945 | ||
946 | if (!ssl_cipher_get_overhead(ciph, &mac_overhead, &int_overhead, | |
947 | &blocksize, &ext_overhead)) | |
948 | return 0; | |
949 | ||
28a31a0a | 950 | if (SSL_READ_ETM(s)) |
045bd047 DW |
951 | ext_overhead += mac_overhead; |
952 | else | |
953 | int_overhead += mac_overhead; | |
954 | ||
955 | /* Subtract external overhead (e.g. IV/nonce, separate MAC) */ | |
956 | if (ext_overhead + DTLS1_RT_HEADER_LENGTH >= mtu) | |
957 | return 0; | |
958 | mtu -= ext_overhead + DTLS1_RT_HEADER_LENGTH; | |
959 | ||
960 | /* Round encrypted payload down to cipher block size (for CBC etc.) | |
961 | * No check for overflow since 'mtu % blocksize' cannot exceed mtu. */ | |
962 | if (blocksize) | |
963 | mtu -= (mtu % blocksize); | |
964 | ||
965 | /* Subtract internal overhead (e.g. CBC padding len byte) */ | |
966 | if (int_overhead >= mtu) | |
967 | return 0; | |
968 | mtu -= int_overhead; | |
969 | ||
970 | return mtu; | |
971 | } | |
fa4b82cc | 972 | |
38b051a1 | 973 | void DTLS_set_timer_cb(SSL *ssl, DTLS_timer_cb cb) |
fa4b82cc | 974 | { |
38b051a1 TM |
975 | SSL_CONNECTION *s = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
976 | ||
977 | if (s == NULL) | |
978 | return; | |
979 | ||
fa4b82cc AH |
980 | s->d1->timer_cb = cb; |
981 | } |