summaryrefslogtreecommitdiff
path: root/src/lib/libssl/d1_lib.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libssl/d1_lib.c425
1 files changed, 0 insertions, 425 deletions
diff --git a/src/lib/libssl/d1_lib.c b/src/lib/libssl/d1_lib.c
deleted file mode 100644
index 3db5629e23..0000000000
--- a/src/lib/libssl/d1_lib.c
+++ /dev/null
@@ -1,425 +0,0 @@
1/* $OpenBSD: d1_lib.c,v 1.58 2021/07/21 08:42:14 jsing 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
74void dtls1_hm_fragment_free(hm_fragment *frag);
75
76static int dtls1_listen(SSL *s, struct sockaddr *client);
77
78int
79dtls1_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
109static void
110dtls1_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
126static void
127dtls1_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
140static void
141dtls1_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
149void
150dtls1_free(SSL *s)
151{
152 if (s == NULL)
153 return;
154
155 ssl3_free(s);
156
157 dtls1_clear_queues(s);
158
159 pqueue_free(D1I(s)->unprocessed_rcds.q);
160 pqueue_free(D1I(s)->buffered_messages);
161 pqueue_free(s->d1->sent_messages);
162 pqueue_free(D1I(s)->buffered_app_data.q);
163
164 freezero(s->d1->internal, sizeof(*s->d1->internal));
165 freezero(s->d1, sizeof(*s->d1));
166
167 s->d1 = NULL;
168}
169
170void
171dtls1_clear(SSL *s)
172{
173 struct dtls1_state_internal_st *internal;
174 pqueue unprocessed_rcds;
175 pqueue buffered_messages;
176 pqueue sent_messages;
177 pqueue buffered_app_data;
178 unsigned int mtu;
179
180 if (s->d1) {
181 unprocessed_rcds = D1I(s)->unprocessed_rcds.q;
182 buffered_messages = D1I(s)->buffered_messages;
183 sent_messages = s->d1->sent_messages;
184 buffered_app_data = D1I(s)->buffered_app_data.q;
185 mtu = D1I(s)->mtu;
186
187 dtls1_clear_queues(s);
188
189 memset(s->d1->internal, 0, sizeof(*s->d1->internal));
190 internal = s->d1->internal;
191 memset(s->d1, 0, sizeof(*s->d1));
192 s->d1->internal = internal;
193
194 D1I(s)->r_epoch =
195 tls12_record_layer_initial_epoch(s->internal->rl);
196
197 D1I(s)->unprocessed_rcds.epoch = D1I(s)->r_epoch + 1;
198
199 if (s->server) {
200 D1I(s)->cookie_len = sizeof(D1I(s)->cookie);
201 }
202
203 if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
204 D1I(s)->mtu = mtu;
205 }
206
207 D1I(s)->unprocessed_rcds.q = unprocessed_rcds;
208 D1I(s)->buffered_messages = buffered_messages;
209 s->d1->sent_messages = sent_messages;
210 D1I(s)->buffered_app_data.q = buffered_app_data;
211 }
212
213 ssl3_clear(s);
214
215 s->version = DTLS1_VERSION;
216}
217
218long
219dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
220{
221 int ret = 0;
222
223 switch (cmd) {
224 case DTLS_CTRL_GET_TIMEOUT:
225 if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) {
226 ret = 1;
227 }
228 break;
229 case DTLS_CTRL_HANDLE_TIMEOUT:
230 ret = dtls1_handle_timeout(s);
231 break;
232 case DTLS_CTRL_LISTEN:
233 ret = dtls1_listen(s, parg);
234 break;
235
236 default:
237 ret = ssl3_ctrl(s, cmd, larg, parg);
238 break;
239 }
240 return (ret);
241}
242
243/*
244 * As it's impossible to use stream ciphers in "datagram" mode, this
245 * simple filter is designed to disengage them in DTLS. Unfortunately
246 * there is no universal way to identify stream SSL_CIPHER, so we have
247 * to explicitly list their SSL_* codes. Currently RC4 is the only one
248 * available, but if new ones emerge, they will have to be added...
249 */
250const SSL_CIPHER *
251dtls1_get_cipher(unsigned int u)
252{
253 const SSL_CIPHER *cipher;
254
255 if ((cipher = ssl3_get_cipher(u)) == NULL)
256 return NULL;
257
258 if (cipher->algorithm_enc == SSL_RC4)
259 return NULL;
260
261 return cipher;
262}
263
264void
265dtls1_start_timer(SSL *s)
266{
267
268 /* If timer is not set, initialize duration with 1 second */
269 if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
270 s->d1->timeout_duration = 1;
271 }
272
273 /* Set timeout to current time */
274 gettimeofday(&(s->d1->next_timeout), NULL);
275
276 /* Add duration to current time */
277 s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
278 BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
279 &s->d1->next_timeout);
280}
281
282struct timeval*
283dtls1_get_timeout(SSL *s, struct timeval* timeleft)
284{
285 struct timeval timenow;
286
287 /* If no timeout is set, just return NULL */
288 if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
289 return NULL;
290 }
291
292 /* Get current time */
293 gettimeofday(&timenow, NULL);
294
295 /* If timer already expired, set remaining time to 0 */
296 if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
297 (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
298 s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
299 memset(timeleft, 0, sizeof(struct timeval));
300 return timeleft;
301 }
302
303 /* Calculate time left until timer expires */
304 memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
305 timeleft->tv_sec -= timenow.tv_sec;
306 timeleft->tv_usec -= timenow.tv_usec;
307 if (timeleft->tv_usec < 0) {
308 timeleft->tv_sec--;
309 timeleft->tv_usec += 1000000;
310 }
311
312 /* If remaining time is less than 15 ms, set it to 0
313 * to prevent issues because of small devergences with
314 * socket timeouts.
315 */
316 if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
317 memset(timeleft, 0, sizeof(struct timeval));
318 }
319
320
321 return timeleft;
322}
323
324int
325dtls1_is_timer_expired(SSL *s)
326{
327 struct timeval timeleft;
328
329 /* Get time left until timeout, return false if no timer running */
330 if (dtls1_get_timeout(s, &timeleft) == NULL) {
331 return 0;
332 }
333
334 /* Return false if timer is not expired yet */
335 if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
336 return 0;
337 }
338
339 /* Timer expired, so return true */
340 return 1;
341}
342
343void
344dtls1_double_timeout(SSL *s)
345{
346 s->d1->timeout_duration *= 2;
347 if (s->d1->timeout_duration > 60)
348 s->d1->timeout_duration = 60;
349 dtls1_start_timer(s);
350}
351
352void
353dtls1_stop_timer(SSL *s)
354{
355 /* Reset everything */
356 memset(&(D1I(s)->timeout), 0, sizeof(struct dtls1_timeout_st));
357 memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
358 s->d1->timeout_duration = 1;
359 BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
360 &(s->d1->next_timeout));
361 /* Clear retransmission buffer */
362 dtls1_clear_record_buffer(s);
363}
364
365int
366dtls1_check_timeout_num(SSL *s)
367{
368 D1I(s)->timeout.num_alerts++;
369
370 /* Reduce MTU after 2 unsuccessful retransmissions */
371 if (D1I(s)->timeout.num_alerts > 2) {
372 D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s),
373 BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
374
375 }
376
377 if (D1I(s)->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
378 /* fail the connection, enough alerts have been sent */
379 SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED);
380 return -1;
381 }
382
383 return 0;
384}
385
386int
387dtls1_handle_timeout(SSL *s)
388{
389 /* if no timer is expired, don't do anything */
390 if (!dtls1_is_timer_expired(s)) {
391 return 0;
392 }
393
394 dtls1_double_timeout(s);
395
396 if (dtls1_check_timeout_num(s) < 0)
397 return -1;
398
399 D1I(s)->timeout.read_timeouts++;
400 if (D1I(s)->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
401 D1I(s)->timeout.read_timeouts = 1;
402 }
403
404 dtls1_start_timer(s);
405 return dtls1_retransmit_buffered_messages(s);
406}
407
408int
409dtls1_listen(SSL *s, struct sockaddr *client)
410{
411 int ret;
412
413 /* Ensure there is no state left over from a previous invocation */
414 SSL_clear(s);
415
416 SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
417 D1I(s)->listen = 1;
418
419 ret = SSL_accept(s);
420 if (ret <= 0)
421 return ret;
422
423 (void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
424 return 1;
425}