xref: /openbsd-src/lib/libssl/d1_lib.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /* $OpenBSD: d1_lib.c,v 1.60 2021/10/21 08:30:14 tb Exp $ */
2 /*
3  * DTLS implementation written by Nagendra Modadugu
4  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5  */
6 /* ====================================================================
7  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    openssl-core@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
57  *
58  */
59 
60 #include <sys/types.h>
61 #include <sys/socket.h>
62 #include <sys/time.h>
63 
64 #include <netinet/in.h>
65 
66 #include <stdio.h>
67 
68 #include <openssl/objects.h>
69 
70 #include "dtls_locl.h"
71 #include "pqueue.h"
72 #include "ssl_locl.h"
73 
74 void dtls1_hm_fragment_free(hm_fragment *frag);
75 
76 static int dtls1_listen(SSL *s, struct sockaddr *client);
77 
78 int
79 dtls1_new(SSL *s)
80 {
81 	if (!ssl3_new(s))
82 		goto err;
83 
84 	if ((s->d1 = calloc(1, sizeof(*s->d1))) == NULL)
85 		goto err;
86 	if ((s->d1->internal = calloc(1, sizeof(*s->d1->internal))) == NULL)
87 		goto err;
88 
89 	if ((s->d1->internal->unprocessed_rcds.q = pqueue_new()) == NULL)
90 		goto err;
91 	if ((s->d1->internal->buffered_messages = pqueue_new()) == NULL)
92 		goto err;
93 	if ((s->d1->sent_messages = pqueue_new()) == NULL)
94 		goto err;
95 	if ((s->d1->internal->buffered_app_data.q = pqueue_new()) == NULL)
96 		goto err;
97 
98 	if (s->server)
99 		s->d1->internal->cookie_len = sizeof(D1I(s)->cookie);
100 
101 	s->method->ssl_clear(s);
102 	return (1);
103 
104  err:
105 	dtls1_free(s);
106 	return (0);
107 }
108 
109 static void
110 dtls1_drain_records(pqueue queue)
111 {
112 	pitem *item;
113 	DTLS1_RECORD_DATA_INTERNAL *rdata;
114 
115 	if (queue == NULL)
116 		return;
117 
118 	while ((item = pqueue_pop(queue)) != NULL) {
119 		rdata = (DTLS1_RECORD_DATA_INTERNAL *)item->data;
120 		ssl3_release_buffer(&rdata->rbuf);
121 		free(item->data);
122 		pitem_free(item);
123 	}
124 }
125 
126 static void
127 dtls1_drain_fragments(pqueue queue)
128 {
129 	pitem *item;
130 
131 	if (queue == NULL)
132 		return;
133 
134 	while ((item = pqueue_pop(queue)) != NULL) {
135 		dtls1_hm_fragment_free(item->data);
136 		pitem_free(item);
137 	}
138 }
139 
140 static void
141 dtls1_clear_queues(SSL *s)
142 {
143 	dtls1_drain_records(D1I(s)->unprocessed_rcds.q);
144 	dtls1_drain_fragments(D1I(s)->buffered_messages);
145 	dtls1_drain_fragments(s->d1->sent_messages);
146 	dtls1_drain_records(D1I(s)->buffered_app_data.q);
147 }
148 
149 void
150 dtls1_free(SSL *s)
151 {
152 	if (s == NULL)
153 		return;
154 
155 	ssl3_free(s);
156 
157 	if (s->d1 == NULL)
158 		return;
159 	if (D1I(s) == NULL)
160 		goto out;
161 
162 	dtls1_clear_queues(s);
163 
164 	pqueue_free(D1I(s)->unprocessed_rcds.q);
165 	pqueue_free(D1I(s)->buffered_messages);
166 	pqueue_free(s->d1->sent_messages);
167 	pqueue_free(D1I(s)->buffered_app_data.q);
168 
169  out:
170 	freezero(s->d1->internal, sizeof(*s->d1->internal));
171 	freezero(s->d1, sizeof(*s->d1));
172 	s->d1 = NULL;
173 }
174 
175 void
176 dtls1_clear(SSL *s)
177 {
178 	struct dtls1_state_internal_st *internal;
179 	pqueue unprocessed_rcds;
180 	pqueue buffered_messages;
181 	pqueue sent_messages;
182 	pqueue buffered_app_data;
183 	unsigned int mtu;
184 
185 	if (s->d1) {
186 		unprocessed_rcds = D1I(s)->unprocessed_rcds.q;
187 		buffered_messages = D1I(s)->buffered_messages;
188 		sent_messages = s->d1->sent_messages;
189 		buffered_app_data = D1I(s)->buffered_app_data.q;
190 		mtu = D1I(s)->mtu;
191 
192 		dtls1_clear_queues(s);
193 
194 		memset(s->d1->internal, 0, sizeof(*s->d1->internal));
195 		internal = s->d1->internal;
196 		memset(s->d1, 0, sizeof(*s->d1));
197 		s->d1->internal = internal;
198 
199 		D1I(s)->unprocessed_rcds.epoch =
200 		    tls12_record_layer_read_epoch(s->internal->rl) + 1;
201 
202 		if (s->server) {
203 			D1I(s)->cookie_len = sizeof(D1I(s)->cookie);
204 		}
205 
206 		if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
207 			D1I(s)->mtu = mtu;
208 		}
209 
210 		D1I(s)->unprocessed_rcds.q = unprocessed_rcds;
211 		D1I(s)->buffered_messages = buffered_messages;
212 		s->d1->sent_messages = sent_messages;
213 		D1I(s)->buffered_app_data.q = buffered_app_data;
214 	}
215 
216 	ssl3_clear(s);
217 
218 	s->version = DTLS1_VERSION;
219 }
220 
221 long
222 dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
223 {
224 	int ret = 0;
225 
226 	switch (cmd) {
227 	case DTLS_CTRL_GET_TIMEOUT:
228 		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) {
229 			ret = 1;
230 		}
231 		break;
232 	case DTLS_CTRL_HANDLE_TIMEOUT:
233 		ret = dtls1_handle_timeout(s);
234 		break;
235 	case DTLS_CTRL_LISTEN:
236 		ret = dtls1_listen(s, parg);
237 		break;
238 
239 	default:
240 		ret = ssl3_ctrl(s, cmd, larg, parg);
241 		break;
242 	}
243 	return (ret);
244 }
245 
246 /*
247  * As it's impossible to use stream ciphers in "datagram" mode, this
248  * simple filter is designed to disengage them in DTLS. Unfortunately
249  * there is no universal way to identify stream SSL_CIPHER, so we have
250  * to explicitly list their SSL_* codes. Currently RC4 is the only one
251  * available, but if new ones emerge, they will have to be added...
252  */
253 const SSL_CIPHER *
254 dtls1_get_cipher(unsigned int u)
255 {
256 	const SSL_CIPHER *cipher;
257 
258 	if ((cipher = ssl3_get_cipher(u)) == NULL)
259 		return NULL;
260 
261 	if (cipher->algorithm_enc == SSL_RC4)
262 		return NULL;
263 
264 	return cipher;
265 }
266 
267 void
268 dtls1_start_timer(SSL *s)
269 {
270 
271 	/* If timer is not set, initialize duration with 1 second */
272 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
273 		s->d1->timeout_duration = 1;
274 	}
275 
276 	/* Set timeout to current time */
277 	gettimeofday(&(s->d1->next_timeout), NULL);
278 
279 	/* Add duration to current time */
280 	s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
281 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
282 	    &s->d1->next_timeout);
283 }
284 
285 struct timeval*
286 dtls1_get_timeout(SSL *s, struct timeval* timeleft)
287 {
288 	struct timeval timenow;
289 
290 	/* If no timeout is set, just return NULL */
291 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
292 		return NULL;
293 	}
294 
295 	/* Get current time */
296 	gettimeofday(&timenow, NULL);
297 
298 	/* If timer already expired, set remaining time to 0 */
299 	if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
300 	    (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
301 	     s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
302 		memset(timeleft, 0, sizeof(struct timeval));
303 		return timeleft;
304 	}
305 
306 	/* Calculate time left until timer expires */
307 	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
308 	timeleft->tv_sec -= timenow.tv_sec;
309 	timeleft->tv_usec -= timenow.tv_usec;
310 	if (timeleft->tv_usec < 0) {
311 		timeleft->tv_sec--;
312 		timeleft->tv_usec += 1000000;
313 	}
314 
315 	/* If remaining time is less than 15 ms, set it to 0
316 	 * to prevent issues because of small devergences with
317 	 * socket timeouts.
318 	 */
319 	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
320 		memset(timeleft, 0, sizeof(struct timeval));
321 	}
322 
323 
324 	return timeleft;
325 }
326 
327 int
328 dtls1_is_timer_expired(SSL *s)
329 {
330 	struct timeval timeleft;
331 
332 	/* Get time left until timeout, return false if no timer running */
333 	if (dtls1_get_timeout(s, &timeleft) == NULL) {
334 		return 0;
335 	}
336 
337 	/* Return false if timer is not expired yet */
338 	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
339 		return 0;
340 	}
341 
342 	/* Timer expired, so return true */
343 	return 1;
344 }
345 
346 void
347 dtls1_double_timeout(SSL *s)
348 {
349 	s->d1->timeout_duration *= 2;
350 	if (s->d1->timeout_duration > 60)
351 		s->d1->timeout_duration = 60;
352 	dtls1_start_timer(s);
353 }
354 
355 void
356 dtls1_stop_timer(SSL *s)
357 {
358 	/* Reset everything */
359 	memset(&(D1I(s)->timeout), 0, sizeof(struct dtls1_timeout_st));
360 	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
361 	s->d1->timeout_duration = 1;
362 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
363 	    &(s->d1->next_timeout));
364 	/* Clear retransmission buffer */
365 	dtls1_clear_record_buffer(s);
366 }
367 
368 int
369 dtls1_check_timeout_num(SSL *s)
370 {
371 	D1I(s)->timeout.num_alerts++;
372 
373 	/* Reduce MTU after 2 unsuccessful retransmissions */
374 	if (D1I(s)->timeout.num_alerts > 2) {
375 		D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s),
376 		    BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
377 
378 	}
379 
380 	if (D1I(s)->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
381 		/* fail the connection, enough alerts have been sent */
382 		SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED);
383 		return -1;
384 	}
385 
386 	return 0;
387 }
388 
389 int
390 dtls1_handle_timeout(SSL *s)
391 {
392 	/* if no timer is expired, don't do anything */
393 	if (!dtls1_is_timer_expired(s)) {
394 		return 0;
395 	}
396 
397 	dtls1_double_timeout(s);
398 
399 	if (dtls1_check_timeout_num(s) < 0)
400 		return -1;
401 
402 	D1I(s)->timeout.read_timeouts++;
403 	if (D1I(s)->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
404 		D1I(s)->timeout.read_timeouts = 1;
405 	}
406 
407 	dtls1_start_timer(s);
408 	return dtls1_retransmit_buffered_messages(s);
409 }
410 
411 int
412 dtls1_listen(SSL *s, struct sockaddr *client)
413 {
414 	int ret;
415 
416 	/* Ensure there is no state left over from a previous invocation */
417 	SSL_clear(s);
418 
419 	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
420 	D1I(s)->listen = 1;
421 
422 	ret = SSL_accept(s);
423 	if (ret <= 0)
424 		return ret;
425 
426 	(void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
427 	return 1;
428 }
429