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