• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string.h>
61 
62 #include <openssl/err.h>
63 
64 #include "../crypto/internal.h"
65 #include "internal.h"
66 
67 
68 using namespace bssl;
69 
dtls1_on_handshake_complete(SSL * ssl)70 static void dtls1_on_handshake_complete(SSL *ssl) {
71   if (ssl_protocol_version(ssl) <= TLS1_2_VERSION) {
72     // Stop the reply timer left by the last flight we sent. In DTLS 1.2, the
73     // retransmission timer ends when the handshake completes. If we sent the
74     // final flight, we may still need to retransmit it, but that is driven by
75     // messages from the peer.
76     dtls1_stop_timer(ssl);
77     // If the final flight had a reply, we know the peer has received it. If
78     // not, we must leave the flight around for post-handshake retransmission.
79     if (ssl->d1->flight_has_reply) {
80       dtls_clear_outgoing_messages(ssl);
81     }
82   }
83 }
84 
next_epoch(const SSL * ssl,uint16_t * out,ssl_encryption_level_t level,uint16_t prev)85 static bool next_epoch(const SSL *ssl, uint16_t *out,
86                        ssl_encryption_level_t level, uint16_t prev) {
87   switch (level) {
88     case ssl_encryption_initial:
89     case ssl_encryption_early_data:
90     case ssl_encryption_handshake:
91       *out = static_cast<uint16_t>(level);
92       return true;
93 
94     case ssl_encryption_application:
95       if (prev < ssl_encryption_application &&
96           ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
97         *out = static_cast<uint16_t>(level);
98         return true;
99       }
100 
101       if (prev == 0xffff) {
102         OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES);
103         return false;
104       }
105       *out = prev + 1;
106       return true;
107   }
108 
109   assert(0);
110   return false;
111 }
112 
dtls1_set_read_state(SSL * ssl,ssl_encryption_level_t level,UniquePtr<SSLAEADContext> aead_ctx,Span<const uint8_t> traffic_secret)113 static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level,
114                                  UniquePtr<SSLAEADContext> aead_ctx,
115                                  Span<const uint8_t> traffic_secret) {
116   // Cipher changes are forbidden if the current epoch has leftover data.
117   if (dtls_has_unprocessed_handshake_data(ssl)) {
118     OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESS_HANDSHAKE_DATA);
119     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
120     return false;
121   }
122 
123   DTLSReadEpoch new_epoch;
124   new_epoch.aead = std::move(aead_ctx);
125   if (!next_epoch(ssl, &new_epoch.epoch, level, ssl->d1->read_epoch.epoch)) {
126     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
127     return false;
128   }
129 
130   if (ssl_protocol_version(ssl) > TLS1_2_VERSION) {
131     new_epoch.rn_encrypter =
132         RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret);
133     if (new_epoch.rn_encrypter == nullptr) {
134       return false;
135     }
136 
137     // In DTLS 1.3, new read epochs are not applied immediately. In principle,
138     // we could do the same in DTLS 1.2, but we would ignore every record from
139     // the previous epoch anyway.
140     assert(ssl->d1->next_read_epoch == nullptr);
141     ssl->d1->next_read_epoch = MakeUnique<DTLSReadEpoch>(std::move(new_epoch));
142     if (ssl->d1->next_read_epoch == nullptr) {
143       return false;
144     }
145   } else {
146     ssl->d1->read_epoch = std::move(new_epoch);
147     ssl->d1->has_change_cipher_spec = false;
148   }
149   return true;
150 }
151 
dtls1_set_write_state(SSL * ssl,ssl_encryption_level_t level,UniquePtr<SSLAEADContext> aead_ctx,Span<const uint8_t> traffic_secret)152 static bool dtls1_set_write_state(SSL *ssl, ssl_encryption_level_t level,
153                                   UniquePtr<SSLAEADContext> aead_ctx,
154                                   Span<const uint8_t> traffic_secret) {
155   uint16_t epoch;
156   if (!next_epoch(ssl, &epoch, level, ssl->d1->write_epoch.epoch())) {
157     return false;
158   }
159 
160   DTLSWriteEpoch new_epoch;
161   new_epoch.aead = std::move(aead_ctx);
162   new_epoch.next_record = DTLSRecordNumber(epoch, 0);
163   if (ssl_protocol_version(ssl) > TLS1_2_VERSION) {
164     new_epoch.rn_encrypter =
165         RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret);
166     if (new_epoch.rn_encrypter == nullptr) {
167       return false;
168     }
169   }
170 
171   auto current = MakeUnique<DTLSWriteEpoch>(std::move(ssl->d1->write_epoch));
172   if (current == nullptr) {
173     return false;
174   }
175 
176   ssl->d1->write_epoch = std::move(new_epoch);
177   ssl->d1->extra_write_epochs.PushBack(std::move(current));
178   dtls_clear_unused_write_epochs(ssl);
179   return true;
180 }
181 
182 static const SSL_PROTOCOL_METHOD kDTLSProtocolMethod = {
183     true /* is_dtls */,
184     dtls1_new,
185     dtls1_free,
186     dtls1_get_message,
187     dtls1_next_message,
188     dtls_has_unprocessed_handshake_data,
189     dtls1_open_handshake,
190     dtls1_open_change_cipher_spec,
191     dtls1_open_app_data,
192     dtls1_write_app_data,
193     dtls1_dispatch_alert,
194     dtls1_init_message,
195     dtls1_finish_message,
196     dtls1_add_message,
197     dtls1_add_change_cipher_spec,
198     dtls1_flush_flight,
199     dtls1_send_ack,
200     dtls1_on_handshake_complete,
201     dtls1_set_read_state,
202     dtls1_set_write_state,
203 };
204 
DTLS_method(void)205 const SSL_METHOD *DTLS_method(void) {
206   static const SSL_METHOD kMethod = {
207       0,
208       &kDTLSProtocolMethod,
209       &ssl_crypto_x509_method,
210   };
211   return &kMethod;
212 }
213 
DTLS_with_buffers_method(void)214 const SSL_METHOD *DTLS_with_buffers_method(void) {
215   static const SSL_METHOD kMethod = {
216       0,
217       &kDTLSProtocolMethod,
218       &ssl_noop_x509_method,
219   };
220   return &kMethod;
221 }
222 
223 // Legacy version-locked methods.
224 
DTLSv1_2_method(void)225 const SSL_METHOD *DTLSv1_2_method(void) {
226   static const SSL_METHOD kMethod = {
227       DTLS1_2_VERSION,
228       &kDTLSProtocolMethod,
229       &ssl_crypto_x509_method,
230   };
231   return &kMethod;
232 }
233 
DTLSv1_method(void)234 const SSL_METHOD *DTLSv1_method(void) {
235   static const SSL_METHOD kMethod = {
236       DTLS1_VERSION,
237       &kDTLSProtocolMethod,
238       &ssl_crypto_x509_method,
239   };
240   return &kMethod;
241 }
242 
243 // Legacy side-specific methods.
244 
DTLSv1_2_server_method(void)245 const SSL_METHOD *DTLSv1_2_server_method(void) { return DTLSv1_2_method(); }
246 
DTLSv1_server_method(void)247 const SSL_METHOD *DTLSv1_server_method(void) { return DTLSv1_method(); }
248 
DTLSv1_2_client_method(void)249 const SSL_METHOD *DTLSv1_2_client_method(void) { return DTLSv1_2_method(); }
250 
DTLSv1_client_method(void)251 const SSL_METHOD *DTLSv1_client_method(void) { return DTLSv1_method(); }
252 
DTLS_server_method(void)253 const SSL_METHOD *DTLS_server_method(void) { return DTLS_method(); }
254 
DTLS_client_method(void)255 const SSL_METHOD *DTLS_client_method(void) { return DTLS_method(); }
256