Coverage Report

Created: 2022-08-24 06:31

/src/libressl/ssl/d1_lib.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: d1_lib.c,v 1.61 2021/10/23 13:36:03 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
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
0
{
81
0
  if (!ssl3_new(s))
82
0
    goto err;
83
84
0
  if ((s->d1 = calloc(1, sizeof(*s->d1))) == NULL)
85
0
    goto err;
86
87
0
  if ((s->d1->unprocessed_rcds.q = pqueue_new()) == NULL)
88
0
    goto err;
89
0
  if ((s->d1->buffered_messages = pqueue_new()) == NULL)
90
0
    goto err;
91
0
  if ((s->d1->sent_messages = pqueue_new()) == NULL)
92
0
    goto err;
93
0
  if ((s->d1->buffered_app_data.q = pqueue_new()) == NULL)
94
0
    goto err;
95
96
0
  if (s->server)
97
0
    s->d1->cookie_len = sizeof(s->d1->cookie);
98
99
0
  s->method->ssl_clear(s);
100
0
  return (1);
101
102
0
 err:
103
0
  dtls1_free(s);
104
0
  return (0);
105
0
}
106
107
static void
108
dtls1_drain_records(pqueue queue)
109
0
{
110
0
  pitem *item;
111
0
  DTLS1_RECORD_DATA_INTERNAL *rdata;
112
113
0
  if (queue == NULL)
114
0
    return;
115
116
0
  while ((item = pqueue_pop(queue)) != NULL) {
117
0
    rdata = (DTLS1_RECORD_DATA_INTERNAL *)item->data;
118
0
    ssl3_release_buffer(&rdata->rbuf);
119
0
    free(item->data);
120
0
    pitem_free(item);
121
0
  }
122
0
}
123
124
static void
125
dtls1_drain_fragments(pqueue queue)
126
0
{
127
0
  pitem *item;
128
129
0
  if (queue == NULL)
130
0
    return;
131
132
0
  while ((item = pqueue_pop(queue)) != NULL) {
133
0
    dtls1_hm_fragment_free(item->data);
134
0
    pitem_free(item);
135
0
  }
136
0
}
137
138
static void
139
dtls1_clear_queues(SSL *s)
140
0
{
141
0
  dtls1_drain_records(s->d1->unprocessed_rcds.q);
142
0
  dtls1_drain_fragments(s->d1->buffered_messages);
143
0
  dtls1_drain_fragments(s->d1->sent_messages);
144
0
  dtls1_drain_records(s->d1->buffered_app_data.q);
145
0
}
146
147
void
148
dtls1_free(SSL *s)
149
0
{
150
0
  if (s == NULL)
151
0
    return;
152
153
0
  ssl3_free(s);
154
155
0
  if (s->d1 == NULL)
156
0
    return;
157
158
0
  dtls1_clear_queues(s);
159
160
0
  pqueue_free(s->d1->unprocessed_rcds.q);
161
0
  pqueue_free(s->d1->buffered_messages);
162
0
  pqueue_free(s->d1->sent_messages);
163
0
  pqueue_free(s->d1->buffered_app_data.q);
164
165
0
  freezero(s->d1, sizeof(*s->d1));
166
0
  s->d1 = NULL;
167
0
}
168
169
void
170
dtls1_clear(SSL *s)
171
0
{
172
0
  pqueue unprocessed_rcds;
173
0
  pqueue buffered_messages;
174
0
  pqueue sent_messages;
175
0
  pqueue buffered_app_data;
176
0
  unsigned int mtu;
177
178
0
  if (s->d1) {
179
0
    unprocessed_rcds = s->d1->unprocessed_rcds.q;
180
0
    buffered_messages = s->d1->buffered_messages;
181
0
    sent_messages = s->d1->sent_messages;
182
0
    buffered_app_data = s->d1->buffered_app_data.q;
183
0
    mtu = s->d1->mtu;
184
185
0
    dtls1_clear_queues(s);
186
187
0
    memset(s->d1, 0, sizeof(*s->d1));
188
189
0
    s->d1->unprocessed_rcds.epoch =
190
0
        tls12_record_layer_read_epoch(s->internal->rl) + 1;
191
192
0
    if (s->server) {
193
0
      s->d1->cookie_len = sizeof(s->d1->cookie);
194
0
    }
195
196
0
    if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
197
0
      s->d1->mtu = mtu;
198
0
    }
199
200
0
    s->d1->unprocessed_rcds.q = unprocessed_rcds;
201
0
    s->d1->buffered_messages = buffered_messages;
202
0
    s->d1->sent_messages = sent_messages;
203
0
    s->d1->buffered_app_data.q = buffered_app_data;
204
0
  }
205
206
0
  ssl3_clear(s);
207
208
0
  s->version = DTLS1_VERSION;
209
0
}
210
211
long
212
dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
213
0
{
214
0
  int ret = 0;
215
216
0
  switch (cmd) {
217
0
  case DTLS_CTRL_GET_TIMEOUT:
218
0
    if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) {
219
0
      ret = 1;
220
0
    }
221
0
    break;
222
0
  case DTLS_CTRL_HANDLE_TIMEOUT:
223
0
    ret = dtls1_handle_timeout(s);
224
0
    break;
225
0
  case DTLS_CTRL_LISTEN:
226
0
    ret = dtls1_listen(s, parg);
227
0
    break;
228
229
0
  default:
230
0
    ret = ssl3_ctrl(s, cmd, larg, parg);
231
0
    break;
232
0
  }
233
0
  return (ret);
234
0
}
235
236
/*
237
 * As it's impossible to use stream ciphers in "datagram" mode, this
238
 * simple filter is designed to disengage them in DTLS. Unfortunately
239
 * there is no universal way to identify stream SSL_CIPHER, so we have
240
 * to explicitly list their SSL_* codes. Currently RC4 is the only one
241
 * available, but if new ones emerge, they will have to be added...
242
 */
243
const SSL_CIPHER *
244
dtls1_get_cipher(unsigned int u)
245
0
{
246
0
  const SSL_CIPHER *cipher;
247
248
0
  if ((cipher = ssl3_get_cipher(u)) == NULL)
249
0
    return NULL;
250
251
0
  if (cipher->algorithm_enc == SSL_RC4)
252
0
    return NULL;
253
254
0
  return cipher;
255
0
}
256
257
void
258
dtls1_start_timer(SSL *s)
259
0
{
260
261
  /* If timer is not set, initialize duration with 1 second */
262
0
  if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
263
0
    s->d1->timeout_duration = 1;
264
0
  }
265
266
  /* Set timeout to current time */
267
0
  gettimeofday(&(s->d1->next_timeout), NULL);
268
269
  /* Add duration to current time */
270
0
  s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
271
0
  BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
272
0
      &s->d1->next_timeout);
273
0
}
274
275
struct timeval*
276
dtls1_get_timeout(SSL *s, struct timeval* timeleft)
277
0
{
278
0
  struct timeval timenow;
279
280
  /* If no timeout is set, just return NULL */
281
0
  if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
282
0
    return NULL;
283
0
  }
284
285
  /* Get current time */
286
0
  gettimeofday(&timenow, NULL);
287
288
  /* If timer already expired, set remaining time to 0 */
289
0
  if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
290
0
      (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
291
0
       s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
292
0
    memset(timeleft, 0, sizeof(struct timeval));
293
0
    return timeleft;
294
0
  }
295
296
  /* Calculate time left until timer expires */
297
0
  memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
298
0
  timeleft->tv_sec -= timenow.tv_sec;
299
0
  timeleft->tv_usec -= timenow.tv_usec;
300
0
  if (timeleft->tv_usec < 0) {
301
0
    timeleft->tv_sec--;
302
0
    timeleft->tv_usec += 1000000;
303
0
  }
304
305
  /* If remaining time is less than 15 ms, set it to 0
306
   * to prevent issues because of small devergences with
307
   * socket timeouts.
308
   */
309
0
  if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
310
0
    memset(timeleft, 0, sizeof(struct timeval));
311
0
  }
312
313
314
0
  return timeleft;
315
0
}
316
317
int
318
dtls1_is_timer_expired(SSL *s)
319
0
{
320
0
  struct timeval timeleft;
321
322
  /* Get time left until timeout, return false if no timer running */
323
0
  if (dtls1_get_timeout(s, &timeleft) == NULL) {
324
0
    return 0;
325
0
  }
326
327
  /* Return false if timer is not expired yet */
328
0
  if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
329
0
    return 0;
330
0
  }
331
332
  /* Timer expired, so return true */
333
0
  return 1;
334
0
}
335
336
void
337
dtls1_double_timeout(SSL *s)
338
0
{
339
0
  s->d1->timeout_duration *= 2;
340
0
  if (s->d1->timeout_duration > 60)
341
0
    s->d1->timeout_duration = 60;
342
0
  dtls1_start_timer(s);
343
0
}
344
345
void
346
dtls1_stop_timer(SSL *s)
347
0
{
348
  /* Reset everything */
349
0
  memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
350
0
  memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
351
0
  s->d1->timeout_duration = 1;
352
0
  BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
353
0
      &(s->d1->next_timeout));
354
  /* Clear retransmission buffer */
355
0
  dtls1_clear_record_buffer(s);
356
0
}
357
358
int
359
dtls1_check_timeout_num(SSL *s)
360
0
{
361
0
  s->d1->timeout.num_alerts++;
362
363
  /* Reduce MTU after 2 unsuccessful retransmissions */
364
0
  if (s->d1->timeout.num_alerts > 2) {
365
0
    s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
366
0
        BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
367
368
0
  }
369
370
0
  if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
371
    /* fail the connection, enough alerts have been sent */
372
0
    SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED);
373
0
    return -1;
374
0
  }
375
376
0
  return 0;
377
0
}
378
379
int
380
dtls1_handle_timeout(SSL *s)
381
0
{
382
  /* if no timer is expired, don't do anything */
383
0
  if (!dtls1_is_timer_expired(s)) {
384
0
    return 0;
385
0
  }
386
387
0
  dtls1_double_timeout(s);
388
389
0
  if (dtls1_check_timeout_num(s) < 0)
390
0
    return -1;
391
392
0
  s->d1->timeout.read_timeouts++;
393
0
  if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
394
0
    s->d1->timeout.read_timeouts = 1;
395
0
  }
396
397
0
  dtls1_start_timer(s);
398
0
  return dtls1_retransmit_buffered_messages(s);
399
0
}
400
401
int
402
dtls1_listen(SSL *s, struct sockaddr *client)
403
0
{
404
0
  int ret;
405
406
  /* Ensure there is no state left over from a previous invocation */
407
0
  SSL_clear(s);
408
409
0
  SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
410
0
  s->d1->listen = 1;
411
412
0
  ret = SSL_accept(s);
413
0
  if (ret <= 0)
414
0
    return ret;
415
416
0
  (void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
417
0
  return 1;
418
0
}