Coverage Report

Created: 2023-06-07 07:13

/src/boringssl/ssl/d1_lib.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * DTLS implementation written by Nagendra Modadugu
3
 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    openssl-core@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com). */
56
57
#include <openssl/ssl.h>
58
59
#include <assert.h>
60
#include <limits.h>
61
#include <string.h>
62
63
#include <openssl/err.h>
64
#include <openssl/mem.h>
65
#include <openssl/nid.h>
66
67
#include "../crypto/internal.h"
68
#include "internal.h"
69
70
71
BSSL_NAMESPACE_BEGIN
72
73
// DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire
74
// before starting to decrease the MTU.
75
0
#define DTLS1_MTU_TIMEOUTS                     2
76
77
// DTLS1_MAX_TIMEOUTS is the maximum number of timeouts to expire
78
// before failing the DTLS handshake.
79
0
#define DTLS1_MAX_TIMEOUTS                     12
80
81
DTLS1_STATE::DTLS1_STATE()
82
    : has_change_cipher_spec(false),
83
      outgoing_messages_complete(false),
84
0
      flight_has_reply(false) {}
85
86
0
DTLS1_STATE::~DTLS1_STATE() {}
87
88
0
bool dtls1_new(SSL *ssl) {
89
0
  if (!tls_new(ssl)) {
90
0
    return false;
91
0
  }
92
0
  UniquePtr<DTLS1_STATE> d1 = MakeUnique<DTLS1_STATE>();
93
0
  if (!d1) {
94
0
    tls_free(ssl);
95
0
    return false;
96
0
  }
97
98
0
  ssl->d1 = d1.release();
99
100
  // Set the version to the highest supported version.
101
  //
102
  // TODO(davidben): Move this field into |s3|, have it store the normalized
103
  // protocol version, and implement this pre-negotiation quirk in |SSL_version|
104
  // at the API boundary rather than in internal state.
105
0
  ssl->version = DTLS1_2_VERSION;
106
0
  return true;
107
0
}
108
109
0
void dtls1_free(SSL *ssl) {
110
0
  tls_free(ssl);
111
112
0
  if (ssl == NULL) {
113
0
    return;
114
0
  }
115
116
0
  Delete(ssl->d1);
117
0
  ssl->d1 = NULL;
118
0
}
119
120
0
void dtls1_start_timer(SSL *ssl) {
121
  // If timer is not set, initialize duration (by default, 1 second)
122
0
  if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
123
0
    ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
124
0
  }
125
126
  // Set timeout to current time
127
0
  ssl_get_current_time(ssl, &ssl->d1->next_timeout);
128
129
  // Add duration to current time
130
0
  ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration_ms / 1000;
131
0
  ssl->d1->next_timeout.tv_usec += (ssl->d1->timeout_duration_ms % 1000) * 1000;
132
0
  if (ssl->d1->next_timeout.tv_usec >= 1000000) {
133
0
    ssl->d1->next_timeout.tv_sec++;
134
0
    ssl->d1->next_timeout.tv_usec -= 1000000;
135
0
  }
136
0
}
137
138
0
bool dtls1_is_timer_expired(SSL *ssl) {
139
0
  struct timeval timeleft;
140
141
  // Get time left until timeout, return false if no timer running
142
0
  if (!DTLSv1_get_timeout(ssl, &timeleft)) {
143
0
    return false;
144
0
  }
145
146
  // Return false if timer is not expired yet
147
0
  if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
148
0
    return false;
149
0
  }
150
151
  // Timer expired, so return true
152
0
  return true;
153
0
}
154
155
0
static void dtls1_double_timeout(SSL *ssl) {
156
0
  ssl->d1->timeout_duration_ms *= 2;
157
0
  if (ssl->d1->timeout_duration_ms > 60000) {
158
0
    ssl->d1->timeout_duration_ms = 60000;
159
0
  }
160
0
}
161
162
0
void dtls1_stop_timer(SSL *ssl) {
163
0
  ssl->d1->num_timeouts = 0;
164
0
  OPENSSL_memset(&ssl->d1->next_timeout, 0, sizeof(ssl->d1->next_timeout));
165
0
  ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
166
0
}
167
168
0
bool dtls1_check_timeout_num(SSL *ssl) {
169
0
  ssl->d1->num_timeouts++;
170
171
  // Reduce MTU after 2 unsuccessful retransmissions
172
0
  if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS &&
173
0
      !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
174
0
    long mtu =
175
0
        BIO_ctrl(ssl->wbio.get(), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, nullptr);
176
0
    if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
177
0
      ssl->d1->mtu = (unsigned)mtu;
178
0
    }
179
0
  }
180
181
0
  if (ssl->d1->num_timeouts > DTLS1_MAX_TIMEOUTS) {
182
    // fail the connection, enough alerts have been sent
183
0
    OPENSSL_PUT_ERROR(SSL, SSL_R_READ_TIMEOUT_EXPIRED);
184
0
    return false;
185
0
  }
186
187
0
  return true;
188
0
}
189
190
BSSL_NAMESPACE_END
191
192
using namespace bssl;
193
194
0
void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
195
0
  ssl->initial_timeout_duration_ms = duration_ms;
196
0
}
197
198
0
int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
199
0
  if (!SSL_is_dtls(ssl)) {
200
0
    return 0;
201
0
  }
202
203
  // If no timeout is set, just return 0.
204
0
  if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
205
0
    return 0;
206
0
  }
207
208
0
  struct OPENSSL_timeval timenow;
209
0
  ssl_get_current_time(ssl, &timenow);
210
211
  // If timer already expired, set remaining time to 0.
212
0
  if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
213
0
      (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
214
0
       ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
215
0
    OPENSSL_memset(out, 0, sizeof(*out));
216
0
    return 1;
217
0
  }
218
219
  // Calculate time left until timer expires.
220
0
  struct OPENSSL_timeval ret;
221
0
  OPENSSL_memcpy(&ret, &ssl->d1->next_timeout, sizeof(ret));
222
0
  ret.tv_sec -= timenow.tv_sec;
223
0
  if (ret.tv_usec >= timenow.tv_usec) {
224
0
    ret.tv_usec -= timenow.tv_usec;
225
0
  } else {
226
0
    ret.tv_usec = 1000000 + ret.tv_usec - timenow.tv_usec;
227
0
    ret.tv_sec--;
228
0
  }
229
230
  // If remaining time is less than 15 ms, set it to 0 to prevent issues
231
  // because of small divergences with socket timeouts.
232
0
  if (ret.tv_sec == 0 && ret.tv_usec < 15000) {
233
0
    OPENSSL_memset(&ret, 0, sizeof(ret));
234
0
  }
235
236
  // Clamp the result in case of overflow.
237
0
  if (ret.tv_sec > INT_MAX) {
238
0
    assert(0);
239
0
    out->tv_sec = INT_MAX;
240
0
  } else {
241
0
    out->tv_sec = ret.tv_sec;
242
0
  }
243
244
0
  out->tv_usec = ret.tv_usec;
245
0
  return 1;
246
0
}
247
248
0
int DTLSv1_handle_timeout(SSL *ssl) {
249
0
  ssl_reset_error_state(ssl);
250
251
0
  if (!SSL_is_dtls(ssl)) {
252
0
    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
253
0
    return -1;
254
0
  }
255
256
  // If no timer is expired, don't do anything.
257
0
  if (!dtls1_is_timer_expired(ssl)) {
258
0
    return 0;
259
0
  }
260
261
0
  if (!dtls1_check_timeout_num(ssl)) {
262
0
    return -1;
263
0
  }
264
265
0
  dtls1_double_timeout(ssl);
266
0
  dtls1_start_timer(ssl);
267
0
  return dtls1_retransmit_outgoing_messages(ssl);
268
0
}