blob: eff06eec7edc4d5e04c8d6fb72d3e3b5e1bdf9f0 [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/*
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
Kenny Rootb8494592015-09-25 02:29:14 +000057#include <openssl/ssl.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080058
David Benjaminc895d6b2016-08-11 13:26:41 -040059#include <assert.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080060#include <limits.h>
Adam Langleye9ada862015-05-11 17:20:37 -070061#include <string.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080062
Kenny Rootb8494592015-09-25 02:29:14 +000063#include <openssl/err.h>
64#include <openssl/mem.h>
David Benjamin4969cc92016-04-22 15:02:23 -040065#include <openssl/nid.h>
Kenny Rootb8494592015-09-25 02:29:14 +000066
Robert Sloan69939df2017-01-09 10:53:07 -080067#include "../crypto/internal.h"
Kenny Rootb8494592015-09-25 02:29:14 +000068#include "internal.h"
69
Adam Langleyd9e397b2015-01-22 14:27:53 -080070
Robert Sloanb6d070c2017-07-24 08:40:01 -070071namespace bssl {
Robert Sloan69939df2017-01-09 10:53:07 -080072
Robert Sloana27a6a42017-09-05 08:39:28 -070073// DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire
74// before starting to decrease the MTU.
Adam Langleye9ada862015-05-11 17:20:37 -070075#define DTLS1_MTU_TIMEOUTS 2
Adam Langleyd9e397b2015-01-22 14:27:53 -080076
Robert Sloana27a6a42017-09-05 08:39:28 -070077// DTLS1_MAX_TIMEOUTS is the maximum number of timeouts to expire
78// before failing the DTLS handshake.
Adam Langleye9ada862015-05-11 17:20:37 -070079#define DTLS1_MAX_TIMEOUTS 12
Adam Langleyd9e397b2015-01-22 14:27:53 -080080
Robert Sloan29c1d2c2017-10-30 14:10:28 -070081DTLS1_STATE::DTLS1_STATE()
82 : has_change_cipher_spec(false),
83 outgoing_messages_complete(false),
84 flight_has_reply(false) {}
85
86DTLS1_STATE::~DTLS1_STATE() {}
87
Robert Sloan36272962017-10-23 10:28:39 -070088bool dtls1_new(SSL *ssl) {
Adam Langley4139edb2016-01-13 15:00:54 -080089 if (!ssl3_new(ssl)) {
Robert Sloan36272962017-10-23 10:28:39 -070090 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -080091 }
Robert Sloan29c1d2c2017-10-30 14:10:28 -070092 UniquePtr<DTLS1_STATE> d1 = MakeUnique<DTLS1_STATE>();
93 if (!d1) {
Adam Langley4139edb2016-01-13 15:00:54 -080094 ssl3_free(ssl);
Robert Sloan36272962017-10-23 10:28:39 -070095 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -080096 }
Adam Langleyd9e397b2015-01-22 14:27:53 -080097
Robert Sloan29c1d2c2017-10-30 14:10:28 -070098 ssl->d1 = d1.release();
Adam Langleyd9e397b2015-01-22 14:27:53 -080099
Robert Sloana27a6a42017-09-05 08:39:28 -0700100 // 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.
Adam Langley4139edb2016-01-13 15:00:54 -0800105 ssl->version = DTLS1_2_VERSION;
Robert Sloan36272962017-10-23 10:28:39 -0700106 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800107}
108
Adam Langley4139edb2016-01-13 15:00:54 -0800109void dtls1_free(SSL *ssl) {
110 ssl3_free(ssl);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800111
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700112 if (ssl == NULL) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800113 return;
114 }
115
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700116 Delete(ssl->d1);
Adam Langley4139edb2016-01-13 15:00:54 -0800117 ssl->d1 = NULL;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800118}
119
Adam Langley4139edb2016-01-13 15:00:54 -0800120void dtls1_start_timer(SSL *ssl) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700121 // If timer is not set, initialize duration (by default, 1 second)
Adam Langley4139edb2016-01-13 15:00:54 -0800122 if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
David Benjamind316cba2016-06-02 16:17:39 -0400123 ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800124 }
125
Robert Sloana27a6a42017-09-05 08:39:28 -0700126 // Set timeout to current time
David Benjaminc895d6b2016-08-11 13:26:41 -0400127 ssl_get_current_time(ssl, &ssl->d1->next_timeout);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800128
Robert Sloana27a6a42017-09-05 08:39:28 -0700129 // Add duration to current time
David Benjamind316cba2016-06-02 16:17:39 -0400130 ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration_ms / 1000;
131 ssl->d1->next_timeout.tv_usec += (ssl->d1->timeout_duration_ms % 1000) * 1000;
132 if (ssl->d1->next_timeout.tv_usec >= 1000000) {
133 ssl->d1->next_timeout.tv_sec++;
134 ssl->d1->next_timeout.tv_usec -= 1000000;
135 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800136}
137
Robert Sloan36272962017-10-23 10:28:39 -0700138bool dtls1_is_timer_expired(SSL *ssl) {
Adam Langleye9ada862015-05-11 17:20:37 -0700139 struct timeval timeleft;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800140
Robert Sloana27a6a42017-09-05 08:39:28 -0700141 // Get time left until timeout, return false if no timer running
Adam Langley4139edb2016-01-13 15:00:54 -0800142 if (!DTLSv1_get_timeout(ssl, &timeleft)) {
Robert Sloan36272962017-10-23 10:28:39 -0700143 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800144 }
145
Robert Sloana27a6a42017-09-05 08:39:28 -0700146 // Return false if timer is not expired yet
Adam Langleyd9e397b2015-01-22 14:27:53 -0800147 if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
Robert Sloan36272962017-10-23 10:28:39 -0700148 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800149 }
150
Robert Sloana27a6a42017-09-05 08:39:28 -0700151 // Timer expired, so return true
Robert Sloan36272962017-10-23 10:28:39 -0700152 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800153}
154
Robert Sloanfe7cd212017-08-07 09:03:39 -0700155static void dtls1_double_timeout(SSL *ssl) {
David Benjamind316cba2016-06-02 16:17:39 -0400156 ssl->d1->timeout_duration_ms *= 2;
157 if (ssl->d1->timeout_duration_ms > 60000) {
158 ssl->d1->timeout_duration_ms = 60000;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800159 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800160}
161
Adam Langley4139edb2016-01-13 15:00:54 -0800162void dtls1_stop_timer(SSL *ssl) {
Adam Langley4139edb2016-01-13 15:00:54 -0800163 ssl->d1->num_timeouts = 0;
Robert Sloan7d422bc2017-03-06 10:04:29 -0800164 OPENSSL_memset(&ssl->d1->next_timeout, 0, sizeof(ssl->d1->next_timeout));
David Benjamind316cba2016-06-02 16:17:39 -0400165 ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800166}
167
Robert Sloan36272962017-10-23 10:28:39 -0700168bool dtls1_check_timeout_num(SSL *ssl) {
Adam Langley4139edb2016-01-13 15:00:54 -0800169 ssl->d1->num_timeouts++;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800170
Robert Sloana27a6a42017-09-05 08:39:28 -0700171 // Reduce MTU after 2 unsuccessful retransmissions
Adam Langley4139edb2016-01-13 15:00:54 -0800172 if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS &&
173 !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
David Benjamind316cba2016-06-02 16:17:39 -0400174 long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800175 if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
Adam Langley4139edb2016-01-13 15:00:54 -0800176 ssl->d1->mtu = (unsigned)mtu;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800177 }
178 }
179
Adam Langley4139edb2016-01-13 15:00:54 -0800180 if (ssl->d1->num_timeouts > DTLS1_MAX_TIMEOUTS) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700181 // fail the connection, enough alerts have been sent
Kenny Rootb8494592015-09-25 02:29:14 +0000182 OPENSSL_PUT_ERROR(SSL, SSL_R_READ_TIMEOUT_EXPIRED);
Robert Sloan36272962017-10-23 10:28:39 -0700183 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800184 }
185
Robert Sloan36272962017-10-23 10:28:39 -0700186 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800187}
188
Robert Sloanb6d070c2017-07-24 08:40:01 -0700189} // namespace bssl
190
191using namespace bssl;
192
193void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
194 ssl->initial_timeout_duration_ms = duration_ms;
195}
196
197int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
198 if (!SSL_is_dtls(ssl)) {
199 return 0;
200 }
201
Robert Sloana27a6a42017-09-05 08:39:28 -0700202 // If no timeout is set, just return 0.
Robert Sloanb6d070c2017-07-24 08:40:01 -0700203 if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
204 return 0;
205 }
206
207 struct OPENSSL_timeval timenow;
208 ssl_get_current_time(ssl, &timenow);
209
Robert Sloana27a6a42017-09-05 08:39:28 -0700210 // If timer already expired, set remaining time to 0.
Robert Sloanb6d070c2017-07-24 08:40:01 -0700211 if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
212 (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
213 ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
214 OPENSSL_memset(out, 0, sizeof(*out));
215 return 1;
216 }
217
Robert Sloana27a6a42017-09-05 08:39:28 -0700218 // Calculate time left until timer expires.
Robert Sloanb6d070c2017-07-24 08:40:01 -0700219 struct OPENSSL_timeval ret;
220 OPENSSL_memcpy(&ret, &ssl->d1->next_timeout, sizeof(ret));
221 ret.tv_sec -= timenow.tv_sec;
222 if (ret.tv_usec >= timenow.tv_usec) {
223 ret.tv_usec -= timenow.tv_usec;
224 } else {
225 ret.tv_usec = 1000000 + ret.tv_usec - timenow.tv_usec;
226 ret.tv_sec--;
227 }
228
Robert Sloana27a6a42017-09-05 08:39:28 -0700229 // If remaining time is less than 15 ms, set it to 0 to prevent issues
230 // because of small divergences with socket timeouts.
Robert Sloanb6d070c2017-07-24 08:40:01 -0700231 if (ret.tv_sec == 0 && ret.tv_usec < 15000) {
232 OPENSSL_memset(&ret, 0, sizeof(ret));
233 }
234
Robert Sloana27a6a42017-09-05 08:39:28 -0700235 // Clamp the result in case of overflow.
Robert Sloanb6d070c2017-07-24 08:40:01 -0700236 if (ret.tv_sec > INT_MAX) {
237 assert(0);
238 out->tv_sec = INT_MAX;
239 } else {
240 out->tv_sec = ret.tv_sec;
241 }
242
243 out->tv_usec = ret.tv_usec;
244 return 1;
245}
246
Adam Langleye9ada862015-05-11 17:20:37 -0700247int DTLSv1_handle_timeout(SSL *ssl) {
Robert Sloan69939df2017-01-09 10:53:07 -0800248 ssl_reset_error_state(ssl);
David Benjamin4969cc92016-04-22 15:02:23 -0400249
David Benjaminc895d6b2016-08-11 13:26:41 -0400250 if (!SSL_is_dtls(ssl)) {
Robert Sloanfe7cd212017-08-07 09:03:39 -0700251 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800252 return -1;
253 }
254
Robert Sloana27a6a42017-09-05 08:39:28 -0700255 // If no timer is expired, don't do anything.
Adam Langleye9ada862015-05-11 17:20:37 -0700256 if (!dtls1_is_timer_expired(ssl)) {
257 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800258 }
259
Robert Sloanfe7cd212017-08-07 09:03:39 -0700260 if (!dtls1_check_timeout_num(ssl)) {
Adam Langleye9ada862015-05-11 17:20:37 -0700261 return -1;
262 }
263
Robert Sloanfe7cd212017-08-07 09:03:39 -0700264 dtls1_double_timeout(ssl);
Adam Langleye9ada862015-05-11 17:20:37 -0700265 dtls1_start_timer(ssl);
David Benjaminc895d6b2016-08-11 13:26:41 -0400266 return dtls1_retransmit_outgoing_messages(ssl);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800267}