1 /*
2  * Copyright (C) 2009-2012 Free Software Foundation, Inc.
3  * Copyright (C) 2013 Nikos Mavrogiannopoulos
4  *
5  * Authors: Jonathan Bastien-Filiatrault
6  *	  Nikos Mavrogiannopoulos
7  *
8  * This file is part of GNUTLS.
9  *
10  * The GNUTLS library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1 of
13  * the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program.  If not, see <https://www.gnu.org/licenses/>
22  *
23  */
24 
25 /* Functions that relate to DTLS retransmission and reassembly.
26  */
27 
28 #include "gnutls_int.h"
29 #include "errors.h"
30 #include "debug.h"
31 #include "dtls.h"
32 #include "record.h"
33 #include <mbuffers.h>
34 #include <buffers.h>
35 #include <constate.h>
36 #include <state.h>
37 #include <gnutls/dtls.h>
38 #include <algorithms.h>
39 
_dtls_async_timer_delete(gnutls_session_t session)40 void _dtls_async_timer_delete(gnutls_session_t session)
41 {
42 	if (session->internals.dtls.async_term != 0) {
43 		_gnutls_dtls_log
44 		    ("DTLS[%p]: Deinitializing previous handshake state.\n",
45 		     session);
46 		session->internals.dtls.async_term = 0;	/* turn off "timer" */
47 
48 		_dtls_reset_hsk_state(session);
49 		_gnutls_handshake_io_buffer_clear(session);
50 		_gnutls_epoch_gc(session);
51 	}
52 }
53 
54 /* This function fragments and transmits a previously buffered
55  * outgoing message. It accepts mtu_data which is a buffer to
56  * be reused (should be set to NULL initially).
57  */
58 static inline int
transmit_message(gnutls_session_t session,mbuffer_st * bufel,uint8_t ** buf)59 transmit_message(gnutls_session_t session,
60 		 mbuffer_st * bufel, uint8_t ** buf)
61 {
62 	uint8_t *data, *mtu_data;
63 	int ret = 0;
64 	unsigned int offset, frag_len, data_size;
65 	unsigned int mtu =
66 	    gnutls_dtls_get_data_mtu(session);
67 
68 	if (session->security_parameters.max_record_send_size < mtu)
69 		mtu = session->security_parameters.max_record_send_size;
70 
71 	mtu -= DTLS_HANDSHAKE_HEADER_SIZE;
72 
73 	if (bufel->type == GNUTLS_CHANGE_CIPHER_SPEC) {
74 		_gnutls_dtls_log
75 		    ("DTLS[%p]: Sending Packet[%u] fragment %s(%d), mtu %u\n",
76 		     session, bufel->handshake_sequence,
77 		     _gnutls_handshake2str(bufel->htype), bufel->htype, mtu);
78 
79 		return _gnutls_send_int(session, bufel->type, -1,
80 					bufel->epoch,
81 					_mbuffer_get_uhead_ptr(bufel),
82 					_mbuffer_get_uhead_size(bufel), 0);
83 	}
84 
85 	if (*buf == NULL)
86 		*buf = gnutls_malloc(mtu + DTLS_HANDSHAKE_HEADER_SIZE);
87 	if (*buf == NULL)
88 		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
89 
90 	mtu_data = *buf;
91 
92 	data = _mbuffer_get_udata_ptr(bufel);
93 	data_size = _mbuffer_get_udata_size(bufel);
94 
95 	/* Write fixed headers
96 	 */
97 
98 	/* Handshake type */
99 	mtu_data[0] = (uint8_t) bufel->htype;
100 
101 	/* Total length */
102 	_gnutls_write_uint24(data_size, &mtu_data[1]);
103 
104 	/* Handshake sequence */
105 	_gnutls_write_uint16(bufel->handshake_sequence, &mtu_data[4]);
106 
107 	/* Chop up and send handshake message into mtu-size pieces. */
108 	for (offset = 0; offset <= data_size; offset += mtu) {
109 		/* Calculate fragment length */
110 		if (offset + mtu > data_size)
111 			frag_len = data_size - offset;
112 		else
113 			frag_len = mtu;
114 
115 		/* we normally allow fragments of zero length, to allow
116 		 * the packets which have zero size. On the others don't
117 		 * send such fragments */
118 		if (frag_len == 0 && data_size > 0) {
119 			ret = 0;
120 			break;
121 		}
122 
123 		/* Fragment offset */
124 		_gnutls_write_uint24(offset, &mtu_data[6]);
125 
126 		/* Fragment length */
127 		_gnutls_write_uint24(frag_len, &mtu_data[9]);
128 
129 		memcpy(&mtu_data[DTLS_HANDSHAKE_HEADER_SIZE],
130 		       data + offset, frag_len);
131 
132 		_gnutls_dtls_log
133 		    ("DTLS[%p]: Sending Packet[%u] fragment %s(%d) with "
134 		     "length: %u, offset: %u, fragment length: %u, mtu: %u\n",
135 		     session, bufel->handshake_sequence,
136 		     _gnutls_handshake2str(bufel->htype), bufel->htype,
137 		     data_size, offset, frag_len, mtu);
138 
139 		ret = _gnutls_send_int(session, bufel->type, bufel->htype,
140 				       bufel->epoch, mtu_data,
141 				       DTLS_HANDSHAKE_HEADER_SIZE +
142 				       frag_len, 0);
143 		if (ret < 0) {
144 			gnutls_assert();
145 			break;
146 		}
147 	}
148 
149 	return ret;
150 }
151 
drop_usage_count(gnutls_session_t session,mbuffer_head_st * const send_buffer)152 static int drop_usage_count(gnutls_session_t session,
153 			    mbuffer_head_st * const send_buffer)
154 {
155 	int ret;
156 	mbuffer_st *cur;
157 
158 	for (cur = send_buffer->head; cur != NULL; cur = cur->next) {
159 		ret = _gnutls_epoch_refcount_dec(session, cur->epoch);
160 		if (ret < 0)
161 			return gnutls_assert_val(ret);
162 	}
163 
164 	return 0;
165 }
166 
167 
168 /* Checks whether the received packet contains a handshake
169  * packet with sequence higher that the previously received.
170  * It must be called only when an actual packet has been
171  * received.
172  *
173  * Returns: 0 if expected, negative value otherwise.
174  */
is_next_hpacket_expected(gnutls_session_t session)175 static int is_next_hpacket_expected(gnutls_session_t session)
176 {
177 	int ret;
178 
179 	/* htype is arbitrary */
180 	ret =
181 	    _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE,
182 				    GNUTLS_HANDSHAKE_FINISHED, 0);
183 	if (ret < 0)
184 		return gnutls_assert_val(ret);
185 
186 	ret = _gnutls_parse_record_buffered_msgs(session);
187 	if (ret < 0)
188 		return gnutls_assert_val(ret);
189 
190 	if (session->internals.handshake_recv_buffer_size > 0)
191 		return 0;
192 	else
193 		return
194 		    gnutls_assert_val
195 		    (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
196 }
197 
_dtls_reset_hsk_state(gnutls_session_t session)198 void _dtls_reset_hsk_state(gnutls_session_t session)
199 {
200 	session->internals.dtls.flight_init = 0;
201 	drop_usage_count(session,
202 			 &session->internals.handshake_send_buffer);
203 	_mbuffer_head_clear(&session->internals.handshake_send_buffer);
204 }
205 
206 
207 #define UPDATE_TIMER { \
208       session->internals.dtls.actual_retrans_timeout_ms *= 2; \
209       session->internals.dtls.actual_retrans_timeout_ms %= MAX_DTLS_TIMEOUT; \
210     }
211 
212 #define RESET_TIMER \
213       session->internals.dtls.actual_retrans_timeout_ms = session->internals.dtls.retrans_timeout_ms
214 
215 #define TIMER_WINDOW session->internals.dtls.actual_retrans_timeout_ms
216 
217 /* This function transmits the flight that has been previously
218  * buffered.
219  *
220  * This function is called from the handshake layer and calls the
221  * record layer.
222  */
_dtls_transmit(gnutls_session_t session)223 int _dtls_transmit(gnutls_session_t session)
224 {
225 	int ret;
226 	uint8_t *buf = NULL;
227 	unsigned int timeout;
228 
229 	/* PREPARING -> SENDING state transition */
230 	mbuffer_head_st *const send_buffer =
231 	    &session->internals.handshake_send_buffer;
232 	mbuffer_st *cur;
233 	gnutls_handshake_description_t last_type = 0;
234 	unsigned int diff;
235 	struct timespec now;
236 
237 	gnutls_gettime(&now);
238 
239 	/* If we have already sent a flight and we are operating in a
240 	 * non blocking way, check if it is time to retransmit or just
241 	 * return.
242 	 */
243 	if (session->internals.dtls.flight_init != 0
244 	    && (session->internals.flags & GNUTLS_NONBLOCK)) {
245 		/* just in case previous run was interrupted */
246 		ret = _gnutls_io_write_flush(session);
247 		if (ret < 0) {
248 			gnutls_assert();
249 			goto cleanup;
250 		}
251 
252 		if (session->internals.dtls.last_flight == 0
253 		    || !_dtls_is_async(session)) {
254 			/* check for ACK */
255 			ret = _gnutls_io_check_recv(session, 0);
256 			if (ret == GNUTLS_E_TIMEDOUT) {
257 				/* if no retransmission is required yet just return
258 				 */
259 				if (timespec_sub_ms
260 				    (&now,
261 				     &session->internals.dtls.
262 				     last_retransmit) < TIMER_WINDOW) {
263 					gnutls_assert();
264 					goto nb_timeout;
265 				}
266 			} else {	/* received something */
267 
268 				if (ret == 0) {
269 					ret =
270 					    is_next_hpacket_expected
271 					    (session);
272 					if (ret == GNUTLS_E_AGAIN
273 					    || ret == GNUTLS_E_INTERRUPTED)
274 						goto nb_timeout;
275 					if (ret < 0
276 					    && ret !=
277 					    GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET)
278 					{
279 						gnutls_assert();
280 						goto cleanup;
281 					}
282 					if (ret == 0)
283 						goto end_flight;
284 					/* if ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET retransmit */
285 				} else
286 					goto nb_timeout;
287 			}
288 		}
289 	}
290 
291 	do {
292 		timeout = TIMER_WINDOW;
293 
294 		diff =
295 		    timespec_sub_ms(&now,
296 				    &session->internals.handshake_start_time);
297 		if (diff >= session->internals.handshake_timeout_ms) {
298 			_gnutls_dtls_log("Session timeout: %u ms\n", diff);
299 			ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT);
300 			goto end_flight;
301 		}
302 
303 		diff =
304 		    timespec_sub_ms(&now,
305 				    &session->internals.dtls.
306 				    last_retransmit);
307 		if (session->internals.dtls.flight_init == 0
308 		    || diff >= TIMER_WINDOW) {
309 			_gnutls_dtls_log
310 			    ("DTLS[%p]: %sStart of flight transmission.\n",
311 			     session,
312 			     (session->internals.dtls.flight_init ==
313 			      0) ? "" : "re-");
314 			for (cur = send_buffer->head; cur != NULL;
315 			     cur = cur->next) {
316 				ret = transmit_message(session, cur, &buf);
317 				if (ret < 0) {
318 					gnutls_assert();
319 					goto end_flight;
320 				}
321 
322 				last_type = cur->htype;
323 			}
324 			gnutls_gettime(&session->internals.dtls.last_retransmit);
325 
326 			if (session->internals.dtls.flight_init == 0) {
327 				session->internals.dtls.flight_init = 1;
328 				RESET_TIMER;
329 				timeout = TIMER_WINDOW;
330 
331 				if (last_type == GNUTLS_HANDSHAKE_FINISHED) {
332 					/* On the last flight we cannot ensure retransmission
333 					 * from here. _dtls_wait_and_retransmit() is being called
334 					 * by handshake.
335 					 */
336 					session->internals.dtls.
337 					    last_flight = 1;
338 				} else
339 					session->internals.dtls.
340 					    last_flight = 0;
341 			} else {
342 				UPDATE_TIMER;
343 			}
344 		}
345 
346 		ret = _gnutls_io_write_flush(session);
347 		if (ret < 0) {
348 			ret = gnutls_assert_val(ret);
349 			goto cleanup;
350 		}
351 
352 		/* last message in handshake -> no ack */
353 		if (session->internals.dtls.last_flight != 0) {
354 			/* we don't wait here. We just return 0 and
355 			 * if a retransmission occurs because peer didn't receive it
356 			 * we rely on the record or handshake
357 			 * layer calling this function again.
358 			 */
359 			ret = 0;
360 			goto cleanup;
361 		} else {	/* all other messages -> implicit ack (receive of next flight) */
362 
363 			if (!(session->internals.flags & GNUTLS_NONBLOCK))
364 				ret =
365 				    _gnutls_io_check_recv(session,
366 							  timeout);
367 			else {
368 				ret = _gnutls_io_check_recv(session, 0);
369 				if (ret == GNUTLS_E_TIMEDOUT) {
370 					goto nb_timeout;
371 				}
372 			}
373 
374 			if (ret == 0) {
375 				ret = is_next_hpacket_expected(session);
376 				if (ret == GNUTLS_E_AGAIN
377 				    || ret == GNUTLS_E_INTERRUPTED)
378 					goto nb_timeout;
379 
380 				if (ret ==
381 				    GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET) {
382 					ret = GNUTLS_E_TIMEDOUT;
383 					goto keep_up;
384 				}
385 				if (ret < 0) {
386 					gnutls_assert();
387 					goto cleanup;
388 				}
389 				goto end_flight;
390 			}
391 		}
392 
393 	      keep_up:
394 		gnutls_gettime(&now);
395 	} while (ret == GNUTLS_E_TIMEDOUT);
396 
397 	if (ret < 0) {
398 		ret = gnutls_assert_val(ret);
399 		goto end_flight;
400 	}
401 
402 	ret = 0;
403 
404       end_flight:
405 	_gnutls_dtls_log("DTLS[%p]: End of flight transmission.\n",
406 			 session);
407 	_dtls_reset_hsk_state(session);
408 
409       cleanup:
410 	if (buf != NULL)
411 		gnutls_free(buf);
412 
413 	/* SENDING -> WAITING state transition */
414 	return ret;
415 
416       nb_timeout:
417 	if (buf != NULL)
418 		gnutls_free(buf);
419 
420 	RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, ret);
421 }
422 
423 /* Waits for the last flight or retransmits
424  * the previous on timeout. Returns 0 on success.
425  */
_dtls_wait_and_retransmit(gnutls_session_t session)426 int _dtls_wait_and_retransmit(gnutls_session_t session)
427 {
428 	int ret;
429 
430 	if (!(session->internals.flags & GNUTLS_NONBLOCK))
431 		ret = _gnutls_io_check_recv(session, TIMER_WINDOW);
432 	else
433 		ret = _gnutls_io_check_recv(session, 0);
434 
435 	if (ret == GNUTLS_E_TIMEDOUT) {
436 		ret = _dtls_retransmit(session);
437 		if (ret == 0) {
438 			RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, 0);
439 		} else
440 			return gnutls_assert_val(ret);
441 	}
442 
443 	RESET_TIMER;
444 	return 0;
445 }
446 
447 /**
448  * gnutls_dtls_set_timeouts:
449  * @session: is a #gnutls_session_t type.
450  * @retrans_timeout: The time at which a retransmission will occur in milliseconds
451  * @total_timeout: The time at which the connection will be aborted, in milliseconds.
452  *
453  * This function will set the timeouts required for the DTLS handshake
454  * protocol. The retransmission timeout is the time after which a
455  * message from the peer is not received, the previous messages will
456  * be retransmitted. The total timeout is the time after which the
457  * handshake will be aborted with %GNUTLS_E_TIMEDOUT.
458  *
459  * The DTLS protocol recommends the values of 1 sec and 60 seconds
460  * respectively, and these are the default values.
461  *
462  * To disable retransmissions set a @retrans_timeout larger than the @total_timeout.
463  *
464  * Since: 3.0
465  **/
gnutls_dtls_set_timeouts(gnutls_session_t session,unsigned int retrans_timeout,unsigned int total_timeout)466 void gnutls_dtls_set_timeouts(gnutls_session_t session,
467 			      unsigned int retrans_timeout,
468 			      unsigned int total_timeout)
469 {
470 	if (total_timeout == GNUTLS_INDEFINITE_TIMEOUT)
471 		session->internals.handshake_timeout_ms = 0;
472 	else
473 		session->internals.handshake_timeout_ms = total_timeout;
474 
475 	session->internals.dtls.retrans_timeout_ms = retrans_timeout;
476 }
477 
478 /**
479  * gnutls_dtls_set_mtu:
480  * @session: is a #gnutls_session_t type.
481  * @mtu: The maximum transfer unit of the transport
482  *
483  * This function will set the maximum transfer unit of the transport
484  * that DTLS packets are sent over. Note that this should exclude
485  * the IP (or IPv6) and UDP headers. So for DTLS over IPv6 on an
486  * Ethernet device with MTU 1500, the DTLS MTU set with this function
487  * would be 1500 - 40 (IPV6 header) - 8 (UDP header) = 1452.
488  *
489  * Since: 3.0
490  **/
gnutls_dtls_set_mtu(gnutls_session_t session,unsigned int mtu)491 void gnutls_dtls_set_mtu(gnutls_session_t session, unsigned int mtu)
492 {
493 	session->internals.dtls.mtu = MIN(mtu, DEFAULT_MAX_RECORD_SIZE);
494 }
495 
496 /* when max is non-zero this function will return the maximum
497  * overhead that this ciphersuite may introduce, e.g., the maximum
498  * amount of padding required */
_gnutls_record_overhead(const version_entry_st * ver,const cipher_entry_st * cipher,const mac_entry_st * mac,unsigned max)499 unsigned _gnutls_record_overhead(const version_entry_st *ver,
500 				 const cipher_entry_st *cipher,
501 				 const mac_entry_st *mac,
502 				 unsigned max)
503 {
504 	int total = 0;
505 	int ret;
506 	int hash_len = 0;
507 
508 	if (unlikely(cipher == NULL))
509 		return 0;
510 
511 	/* 1 octet content type in the unencrypted content */
512 	if (ver->tls13_sem)
513 		total++;
514 
515 	if (mac->id == GNUTLS_MAC_AEAD) {
516 		if (!ver->tls13_sem)
517 			total += _gnutls_cipher_get_explicit_iv_size(cipher);
518 
519 		total += _gnutls_cipher_get_tag_size(cipher);
520 	} else {
521 		/* STREAM + BLOCK have a MAC appended */
522 		ret = _gnutls_mac_get_algo_len(mac);
523 		if (unlikely(ret < 0))
524 			return 0;
525 
526 		hash_len = ret;
527 		total += hash_len;
528 	}
529 
530 	/* Block ciphers have padding + IV */
531 	if (_gnutls_cipher_type(cipher) == CIPHER_BLOCK) {
532 		int exp_iv;
533 
534 		exp_iv = _gnutls_cipher_get_explicit_iv_size(cipher);
535 
536 		if (max)
537 			total += 2*exp_iv; /* block == iv size */
538 		else
539 			total += exp_iv + 1;
540 	}
541 
542 	return total;
543 }
544 
545 /**
546  * gnutls_est_record_overhead_size:
547  * @version: is a #gnutls_protocol_t value
548  * @cipher: is a #gnutls_cipher_algorithm_t value
549  * @mac: is a #gnutls_mac_algorithm_t value
550  * @comp: is a #gnutls_compression_method_t value (ignored)
551  * @flags: must be zero
552  *
553  * This function will return the set size in bytes of the overhead
554  * due to TLS (or DTLS) per record.
555  *
556  * Note that this function may provide inaccurate values when TLS
557  * extensions that modify the record format are negotiated. In these
558  * cases a more accurate value can be obtained using gnutls_record_overhead_size()
559  * after a completed handshake.
560  *
561  * Since: 3.2.2
562  **/
gnutls_est_record_overhead_size(gnutls_protocol_t version,gnutls_cipher_algorithm_t cipher,gnutls_mac_algorithm_t mac,gnutls_compression_method_t comp,unsigned int flags)563 size_t gnutls_est_record_overhead_size(gnutls_protocol_t version,
564 				       gnutls_cipher_algorithm_t cipher,
565 				       gnutls_mac_algorithm_t mac,
566 				       gnutls_compression_method_t comp,
567 				       unsigned int flags)
568 {
569 	const cipher_entry_st *c;
570 	const mac_entry_st *m;
571 	const version_entry_st *v;
572 	size_t total = 0;
573 
574 	c = cipher_to_entry(cipher);
575 	if (c == NULL)
576 		return 0;
577 
578 	m = mac_to_entry(mac);
579 	if (m == NULL)
580 		return 0;
581 
582 	v = version_to_entry(version);
583 	if (v == NULL)
584 		return 0;
585 
586 	if (v->transport == GNUTLS_STREAM)
587 		total = TLS_RECORD_HEADER_SIZE;
588 	else
589 		total = DTLS_RECORD_HEADER_SIZE;
590 
591 	total += _gnutls_record_overhead(v, c, m, 1);
592 
593 	return total;
594 }
595 
596 /* returns overhead imposed by the record layer (encryption/compression)
597  * etc. It does not include the record layer headers, since the caller
598  * needs to cope with rounding to multiples of blocksize, and the header
599  * is outside that.
600  *
601  * blocksize: will contain the block size when padding may be required or 1
602  *
603  * It may return a negative error code on error.
604  */
record_overhead_rt(gnutls_session_t session)605 static int record_overhead_rt(gnutls_session_t session)
606 {
607 	record_parameters_st *params;
608 	int ret;
609 
610 	if (session->internals.initial_negotiation_completed == 0)
611 		return GNUTLS_E_INVALID_REQUEST;
612 	ret = _gnutls_epoch_get(session, EPOCH_WRITE_CURRENT, &params);
613 	if (ret < 0)
614 		return gnutls_assert_val(ret);
615 
616 	return _gnutls_record_overhead(get_version(session), params->cipher, params->mac, 1);
617 }
618 
619 /**
620  * gnutls_record_overhead_size:
621  * @session: is #gnutls_session_t
622  *
623  * This function will return the size in bytes of the overhead
624  * due to TLS (or DTLS) per record. On certain occasions
625  * (e.g., CBC ciphers) the returned value is the maximum
626  * possible overhead.
627  *
628  * Since: 3.2.2
629  **/
gnutls_record_overhead_size(gnutls_session_t session)630 size_t gnutls_record_overhead_size(gnutls_session_t session)
631 {
632 	const version_entry_st *v = get_version(session);
633 	int ret;
634 	size_t total;
635 
636 	if (v->transport == GNUTLS_STREAM)
637 		total = TLS_RECORD_HEADER_SIZE;
638 	else
639 		total = DTLS_RECORD_HEADER_SIZE;
640 
641 	ret = record_overhead_rt(session);
642 	if (ret >= 0)
643 		total += ret;
644 
645 	return total;
646 }
647 
648 
649 
650 /**
651  * gnutls_dtls_get_data_mtu:
652  * @session: is a #gnutls_session_t type.
653  *
654  * This function will return the actual maximum transfer unit for
655  * application data. I.e. DTLS headers are subtracted from the
656  * actual MTU which is set using gnutls_dtls_set_mtu().
657  *
658  * Returns: the maximum allowed transfer unit.
659  *
660  * Since: 3.0
661  **/
gnutls_dtls_get_data_mtu(gnutls_session_t session)662 unsigned int gnutls_dtls_get_data_mtu(gnutls_session_t session)
663 {
664 	int mtu = session->internals.dtls.mtu;
665 	record_parameters_st *params;
666 	int ret, k, hash_size, block;
667 
668 	mtu -= RECORD_HEADER_SIZE(session);
669 
670 	if (session->internals.initial_negotiation_completed == 0)
671 		return mtu;
672 
673 	ret = _gnutls_epoch_get(session, EPOCH_WRITE_CURRENT, &params);
674 	if (ret < 0)
675 		return mtu;
676 
677 	if (params->cipher->type == CIPHER_AEAD || params->cipher->type == CIPHER_STREAM)
678 		return mtu-_gnutls_record_overhead(get_version(session), params->cipher, params->mac, 0);
679 
680 	/* CIPHER_BLOCK: in CBC ciphers guess the data MTU as it depends on residues
681 	 */
682 	hash_size = _gnutls_mac_get_algo_len(params->mac);
683 	block = _gnutls_cipher_get_explicit_iv_size(params->cipher);
684 	assert(_gnutls_cipher_get_block_size(params->cipher) == block);
685 
686 	if (params->etm) {
687 		/* the maximum data mtu satisfies:
688 		 * data mtu (mod block) = block-1
689 		 * or data mtu = (k+1)*(block) - 1
690 	         *
691 		 * and data mtu + block + hash size + 1 = link_mtu
692 		 *     (k+2) * (block) + hash size = link_mtu
693 		 *
694 		 *     We try to find k, and thus data mtu
695 		 */
696 		k = ((mtu-hash_size)/block) - 2;
697 
698 		return (k+1)*block - 1;
699 	} else {
700 		/* the maximum data mtu satisfies:
701 		 * data mtu + hash size (mod block) = block-1
702 		 * or data mtu = (k+1)*(block) - hash size - 1
703 		 *
704 		 * and data mtu + block + hash size + 1 = link_mtu
705 		 *     (k+2) * (block) = link_mtu
706 		 *
707 		 *     We try to find k, and thus data mtu
708 		 */
709 		k = ((mtu)/block) - 2;
710 
711 		return (k+1)*block - hash_size - 1;
712 	}
713 }
714 
715 /**
716  * gnutls_dtls_set_data_mtu:
717  * @session: is a #gnutls_session_t type.
718  * @mtu: The maximum unencrypted transfer unit of the session
719  *
720  * This function will set the maximum size of the *unencrypted* records
721  * which will be sent over a DTLS session. It is equivalent to calculating
722  * the DTLS packet overhead with the current encryption parameters, and
723  * calling gnutls_dtls_set_mtu() with that value. In particular, this means
724  * that you may need to call this function again after any negotiation or
725  * renegotiation, in order to ensure that the MTU is still sufficient to
726  * account for the new protocol overhead.
727  *
728  * In most cases you only need to call gnutls_dtls_set_mtu() with
729  * the maximum MTU of your transport layer.
730  *
731  * Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.
732  *
733  * Since: 3.1
734  **/
gnutls_dtls_set_data_mtu(gnutls_session_t session,unsigned int mtu)735 int gnutls_dtls_set_data_mtu(gnutls_session_t session, unsigned int mtu)
736 {
737 	int overhead;
738 
739 	overhead = record_overhead_rt(session);
740 
741 	/* You can't call this until the session is actually running */
742 	if (overhead < 0)
743 		return GNUTLS_E_INVALID_SESSION;
744 
745 	/* Add the overhead inside the encrypted part */
746 	mtu += overhead;
747 
748 	/* Add the *unencrypted header size */
749 	mtu += RECORD_HEADER_SIZE(session);
750 
751 	gnutls_dtls_set_mtu(session, mtu);
752 	return GNUTLS_E_SUCCESS;
753 }
754 
755 /**
756  * gnutls_dtls_get_mtu:
757  * @session: is a #gnutls_session_t type.
758  *
759  * This function will return the MTU size as set with
760  * gnutls_dtls_set_mtu(). This is not the actual MTU
761  * of data you can transmit. Use gnutls_dtls_get_data_mtu()
762  * for that reason.
763  *
764  * Returns: the set maximum transfer unit.
765  *
766  * Since: 3.0
767  **/
gnutls_dtls_get_mtu(gnutls_session_t session)768 unsigned int gnutls_dtls_get_mtu(gnutls_session_t session)
769 {
770 	return session->internals.dtls.mtu;
771 }
772 
773 /**
774  * gnutls_dtls_get_timeout:
775  * @session: is a #gnutls_session_t type.
776  *
777  * This function will return the milliseconds remaining
778  * for a retransmission of the previously sent handshake
779  * message. This function is useful when DTLS is used in
780  * non-blocking mode, to estimate when to call gnutls_handshake()
781  * if no packets have been received.
782  *
783  * Returns: the remaining time in milliseconds.
784  *
785  * Since: 3.0
786  **/
gnutls_dtls_get_timeout(gnutls_session_t session)787 unsigned int gnutls_dtls_get_timeout(gnutls_session_t session)
788 {
789 	struct timespec now;
790 	unsigned int diff;
791 
792 	gnutls_gettime(&now);
793 
794 	diff =
795 	    timespec_sub_ms(&now,
796 			    &session->internals.dtls.last_retransmit);
797 	if (diff >= TIMER_WINDOW)
798 		return 0;
799 	else
800 		return TIMER_WINDOW - diff;
801 }
802 
803 #define COOKIE_SIZE 16
804 #define COOKIE_MAC_SIZE 16
805 
806 /*   MAC
807  * 16 bytes
808  *
809  * total 19 bytes
810  */
811 
812 #define C_HASH GNUTLS_MAC_SHA1
813 #define C_HASH_SIZE 20
814 
815 /**
816  * gnutls_dtls_cookie_send:
817  * @key: is a random key to be used at cookie generation
818  * @client_data: contains data identifying the client (i.e. address)
819  * @client_data_size: The size of client's data
820  * @prestate: The previous cookie returned by gnutls_dtls_cookie_verify()
821  * @ptr: A transport pointer to be used by @push_func
822  * @push_func: A function that will be used to reply
823  *
824  * This function can be used to prevent denial of service
825  * attacks to a DTLS server by requiring the client to
826  * reply using a cookie sent by this function. That way
827  * it can be ensured that a client we allocated resources
828  * for (i.e. #gnutls_session_t) is the one that the
829  * original incoming packet was originated from.
830  *
831  * This function must be called at the first incoming packet,
832  * prior to allocating any resources and must be succeeded
833  * by gnutls_dtls_cookie_verify().
834  *
835  * Returns: the number of bytes sent, or a negative error code.
836  *
837  * Since: 3.0
838  **/
gnutls_dtls_cookie_send(gnutls_datum_t * key,void * client_data,size_t client_data_size,gnutls_dtls_prestate_st * prestate,gnutls_transport_ptr_t ptr,gnutls_push_func push_func)839 int gnutls_dtls_cookie_send(gnutls_datum_t * key, void *client_data,
840 			    size_t client_data_size,
841 			    gnutls_dtls_prestate_st * prestate,
842 			    gnutls_transport_ptr_t ptr,
843 			    gnutls_push_func push_func)
844 {
845 	uint8_t hvr[20 + DTLS_HANDSHAKE_HEADER_SIZE + COOKIE_SIZE];
846 	int hvr_size = 0, ret;
847 	uint8_t digest[C_HASH_SIZE];
848 
849 	if (key == NULL || key->data == NULL || key->size == 0)
850 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
851 
852 /* send
853  *  struct {
854  *    ContentType type - 1 byte GNUTLS_HANDSHAKE;
855  *    ProtocolVersion version; - 2 bytes (254,255)
856  *    uint16 epoch; - 2 bytes (0, 0)
857  *    uint48 sequence_number; - 4 bytes (0,0,0,0)
858  *    uint16 length; - 2 bytes (COOKIE_SIZE+1+2)+DTLS_HANDSHAKE_HEADER_SIZE
859  *    uint8_t fragment[DTLSPlaintext.length];
860  *  } DTLSPlaintext;
861  *
862  *
863  * struct {
864  *    HandshakeType msg_type; 1 byte - GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST
865  *    uint24 length; - COOKIE_SIZE+3
866  *    uint16 message_seq; - 2 bytes (0,0)
867  *    uint24 fragment_offset; - 3 bytes (0,0,0)
868  *    uint24 fragment_length; - same as length
869  * }
870  *
871  * struct {
872  *   ProtocolVersion server_version;
873  *   uint8_t cookie<0..32>;
874  * } HelloVerifyRequest;
875  */
876 
877 	hvr[hvr_size++] = GNUTLS_HANDSHAKE;
878 	/* version */
879 	hvr[hvr_size++] = 254;
880 	hvr[hvr_size++] = 255;
881 
882 	/* epoch + seq */
883 	memset(&hvr[hvr_size], 0, 8);
884 	hvr_size += 7;
885 	hvr[hvr_size++] = prestate->record_seq;
886 
887 	/* length */
888 	_gnutls_write_uint16(DTLS_HANDSHAKE_HEADER_SIZE + COOKIE_SIZE + 3,
889 			     &hvr[hvr_size]);
890 	hvr_size += 2;
891 
892 	/* now handshake headers */
893 	hvr[hvr_size++] = GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST;
894 	_gnutls_write_uint24(COOKIE_SIZE + 3, &hvr[hvr_size]);
895 	hvr_size += 3;
896 
897 	/* handshake seq */
898 	hvr[hvr_size++] = 0;
899 	hvr[hvr_size++] = prestate->hsk_write_seq;
900 
901 	_gnutls_write_uint24(0, &hvr[hvr_size]);
902 	hvr_size += 3;
903 
904 	_gnutls_write_uint24(COOKIE_SIZE + 3, &hvr[hvr_size]);
905 	hvr_size += 3;
906 
907 	/* version */
908 	hvr[hvr_size++] = 254;
909 	hvr[hvr_size++] = 255;
910 	hvr[hvr_size++] = COOKIE_SIZE;
911 
912 	ret =
913 	    _gnutls_mac_fast(C_HASH, key->data, key->size, client_data,
914 			     client_data_size, digest);
915 	if (ret < 0)
916 		return gnutls_assert_val(ret);
917 
918 	memcpy(&hvr[hvr_size], digest, COOKIE_MAC_SIZE);
919 	hvr_size += COOKIE_MAC_SIZE;
920 
921 	ret = push_func(ptr, hvr, hvr_size);
922 	if (ret < 0)
923 		ret = GNUTLS_E_PUSH_ERROR;
924 
925 	return ret;
926 }
927 
928 /**
929  * gnutls_dtls_cookie_verify:
930  * @key: is a random key to be used at cookie generation
931  * @client_data: contains data identifying the client (i.e. address)
932  * @client_data_size: The size of client's data
933  * @_msg: An incoming message that initiates a connection.
934  * @msg_size: The size of the message.
935  * @prestate: The cookie of this client.
936  *
937  * This function will verify the received message for
938  * a valid cookie. If a valid cookie is returned then
939  * it should be associated with the session using
940  * gnutls_dtls_prestate_set();
941  *
942  * This function must be called after gnutls_dtls_cookie_send().
943  *
944  * Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.
945  *
946  * Since: 3.0
947  **/
gnutls_dtls_cookie_verify(gnutls_datum_t * key,void * client_data,size_t client_data_size,void * _msg,size_t msg_size,gnutls_dtls_prestate_st * prestate)948 int gnutls_dtls_cookie_verify(gnutls_datum_t * key,
949 			      void *client_data, size_t client_data_size,
950 			      void *_msg, size_t msg_size,
951 			      gnutls_dtls_prestate_st * prestate)
952 {
953 	gnutls_datum_t cookie;
954 	int ret;
955 	unsigned int pos, sid_size;
956 	uint8_t *msg = _msg;
957 	uint8_t digest[C_HASH_SIZE];
958 
959 	if (key == NULL || key->data == NULL || key->size == 0)
960 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
961 
962 	/* format:
963 	 * version - 2 bytes
964 	 * random - 32 bytes
965 	 * session_id - 1 byte length + content
966 	 * cookie - 1 byte length + content
967 	 */
968 
969 	pos = 34 + DTLS_RECORD_HEADER_SIZE + DTLS_HANDSHAKE_HEADER_SIZE;
970 
971 	if (msg_size < pos + 1)
972 		return
973 		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
974 
975 	sid_size = msg[pos++];
976 
977 	if (sid_size > 32 || msg_size < pos + sid_size + 1)
978 		return
979 		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
980 
981 	pos += sid_size;
982 	cookie.size = msg[pos++];
983 
984 	if (msg_size < pos + cookie.size + 1)
985 		return
986 		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
987 
988 	cookie.data = &msg[pos];
989 	if (cookie.size != COOKIE_SIZE) {
990 		if (cookie.size > 0)
991 			_gnutls_audit_log(NULL,
992 					  "Received cookie with illegal size %d. Expected %d\n",
993 					  (int) cookie.size, COOKIE_SIZE);
994 		return gnutls_assert_val(GNUTLS_E_BAD_COOKIE);
995 	}
996 
997 	ret =
998 	    _gnutls_mac_fast(C_HASH, key->data, key->size, client_data,
999 			     client_data_size, digest);
1000 	if (ret < 0)
1001 		return gnutls_assert_val(ret);
1002 
1003 	if (memcmp(digest, cookie.data, COOKIE_MAC_SIZE) != 0)
1004 		return gnutls_assert_val(GNUTLS_E_BAD_COOKIE);
1005 
1006 	prestate->record_seq = msg[10];	/* client's record seq */
1007 	prestate->hsk_read_seq = msg[DTLS_RECORD_HEADER_SIZE + 5];	/* client's hsk seq */
1008 	prestate->hsk_write_seq = 0;	/* we always send zero for this msg */
1009 
1010 	return 0;
1011 }
1012 
1013 /**
1014  * gnutls_dtls_prestate_set:
1015  * @session: a new session
1016  * @prestate: contains the client's prestate
1017  *
1018  * This function will associate the prestate acquired by
1019  * the cookie authentication with the client, with the newly
1020  * established session.
1021  *
1022  * This functions must be called after a successful gnutls_dtls_cookie_verify()
1023  * and should be succeeded by the actual DTLS handshake using gnutls_handshake().
1024  *
1025  * Since: 3.0
1026  **/
gnutls_dtls_prestate_set(gnutls_session_t session,gnutls_dtls_prestate_st * prestate)1027 void gnutls_dtls_prestate_set(gnutls_session_t session,
1028 			      gnutls_dtls_prestate_st * prestate)
1029 {
1030 	record_parameters_st *params;
1031 	int ret;
1032 
1033 	if (prestate == NULL)
1034 		return;
1035 
1036 	/* we do not care about read_params, since we accept anything
1037 	 * the peer sends.
1038 	 */
1039 	ret = _gnutls_epoch_get(session, EPOCH_WRITE_CURRENT, &params);
1040 	if (ret < 0)
1041 		return;
1042 
1043 	params->write.sequence_number = prestate->record_seq;
1044 
1045 	session->internals.dtls.hsk_read_seq = prestate->hsk_read_seq;
1046 	session->internals.dtls.hsk_write_seq =
1047 	    prestate->hsk_write_seq + 1;
1048 }
1049 
1050 /**
1051  * gnutls_record_get_discarded:
1052  * @session: is a #gnutls_session_t type.
1053  *
1054  * Returns the number of discarded packets in a
1055  * DTLS connection.
1056  *
1057  * Returns: The number of discarded packets.
1058  *
1059  * Since: 3.0
1060  **/
gnutls_record_get_discarded(gnutls_session_t session)1061 unsigned int gnutls_record_get_discarded(gnutls_session_t session)
1062 {
1063 	return session->internals.dtls.packets_dropped;
1064 }
1065