/src/boringssl/ssl/dtls_method.cc
Line | Count | Source |
1 | | // Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/ssl.h> |
16 | | |
17 | | #include <assert.h> |
18 | | #include <string.h> |
19 | | |
20 | | #include <openssl/err.h> |
21 | | |
22 | | #include "../crypto/internal.h" |
23 | | #include "internal.h" |
24 | | |
25 | | |
26 | | using namespace bssl; |
27 | | |
28 | 2.96k | static void dtls1_on_handshake_complete(SSL *ssl) { |
29 | 2.96k | if (ssl_protocol_version(ssl) <= TLS1_2_VERSION) { |
30 | | // Stop the reply timer left by the last flight we sent. In DTLS 1.2, the |
31 | | // retransmission timer ends when the handshake completes. If we sent the |
32 | | // final flight, we may still need to retransmit it, but that is driven by |
33 | | // messages from the peer. |
34 | 216 | dtls1_stop_timer(ssl); |
35 | | // If the final flight had a reply, we know the peer has received it. If |
36 | | // not, we must leave the flight around for post-handshake retransmission. |
37 | 216 | if (ssl->d1->flight_has_reply) { |
38 | 28 | dtls_clear_outgoing_messages(ssl); |
39 | 28 | } |
40 | 216 | } |
41 | 2.96k | } |
42 | | |
43 | | static bool next_epoch(const SSL *ssl, uint16_t *out, |
44 | 41.5k | ssl_encryption_level_t level, uint16_t prev) { |
45 | 41.5k | switch (level) { |
46 | 0 | case ssl_encryption_initial: |
47 | 0 | case ssl_encryption_early_data: |
48 | 8.50k | case ssl_encryption_handshake: |
49 | 8.50k | *out = static_cast<uint16_t>(level); |
50 | 8.50k | return true; |
51 | | |
52 | 33.0k | case ssl_encryption_application: |
53 | 33.0k | if (prev < ssl_encryption_application && |
54 | 6.54k | ssl_protocol_version(ssl) >= TLS1_3_VERSION) { |
55 | 5.73k | *out = static_cast<uint16_t>(level); |
56 | 5.73k | return true; |
57 | 5.73k | } |
58 | | |
59 | 27.3k | if (prev == 0xffff) { |
60 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES); |
61 | 0 | return false; |
62 | 0 | } |
63 | 27.3k | *out = prev + 1; |
64 | 27.3k | return true; |
65 | 41.5k | } |
66 | | |
67 | 41.5k | assert(0); |
68 | 0 | return false; |
69 | 0 | } |
70 | | |
71 | | static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level, |
72 | | UniquePtr<SSLAEADContext> aead_ctx, |
73 | 33.7k | Span<const uint8_t> traffic_secret) { |
74 | | // Cipher changes are forbidden if the current epoch has leftover data. |
75 | 33.7k | if (dtls_has_unprocessed_handshake_data(ssl)) { |
76 | 13 | OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESS_HANDSHAKE_DATA); |
77 | 13 | ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); |
78 | 13 | return false; |
79 | 13 | } |
80 | | |
81 | 33.7k | DTLSReadEpoch new_epoch; |
82 | 33.7k | new_epoch.aead = std::move(aead_ctx); |
83 | 33.7k | new_epoch.traffic_secret.CopyFrom(traffic_secret); |
84 | 33.7k | if (!next_epoch(ssl, &new_epoch.epoch, level, ssl->d1->read_epoch.epoch)) { |
85 | 0 | ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); |
86 | 0 | return false; |
87 | 0 | } |
88 | | |
89 | 33.7k | if (ssl_protocol_version(ssl) > TLS1_2_VERSION) { |
90 | 33.4k | new_epoch.rn_encrypter = |
91 | 33.4k | RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret); |
92 | 33.4k | if (new_epoch.rn_encrypter == nullptr) { |
93 | 0 | return false; |
94 | 0 | } |
95 | | |
96 | | // In DTLS 1.3, new read epochs are not applied immediately. In principle, |
97 | | // we could do the same in DTLS 1.2, but we would ignore every record from |
98 | | // the previous epoch anyway. |
99 | 33.4k | assert(ssl->d1->next_read_epoch == nullptr); |
100 | 33.4k | ssl->d1->next_read_epoch = MakeUnique<DTLSReadEpoch>(std::move(new_epoch)); |
101 | 33.4k | if (ssl->d1->next_read_epoch == nullptr) { |
102 | 0 | return false; |
103 | 0 | } |
104 | 33.4k | } else { |
105 | 272 | ssl->d1->read_epoch = std::move(new_epoch); |
106 | 272 | ssl->d1->has_change_cipher_spec = false; |
107 | 272 | } |
108 | 33.7k | return true; |
109 | 33.7k | } |
110 | | |
111 | | static bool dtls1_set_write_state(SSL *ssl, ssl_encryption_level_t level, |
112 | | UniquePtr<SSLAEADContext> aead_ctx, |
113 | 7.78k | Span<const uint8_t> traffic_secret) { |
114 | 7.78k | uint16_t epoch; |
115 | 7.78k | if (!next_epoch(ssl, &epoch, level, ssl->d1->write_epoch.epoch())) { |
116 | 0 | return false; |
117 | 0 | } |
118 | | |
119 | 7.78k | DTLSWriteEpoch new_epoch; |
120 | 7.78k | new_epoch.aead = std::move(aead_ctx); |
121 | 7.78k | new_epoch.next_record = DTLSRecordNumber(epoch, 0); |
122 | 7.78k | new_epoch.traffic_secret.CopyFrom(traffic_secret); |
123 | 7.78k | if (ssl_protocol_version(ssl) > TLS1_2_VERSION) { |
124 | 7.24k | new_epoch.rn_encrypter = |
125 | 7.24k | RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret); |
126 | 7.24k | if (new_epoch.rn_encrypter == nullptr) { |
127 | 0 | return false; |
128 | 0 | } |
129 | 7.24k | } |
130 | | |
131 | 7.78k | auto current = MakeUnique<DTLSWriteEpoch>(std::move(ssl->d1->write_epoch)); |
132 | 7.78k | if (current == nullptr) { |
133 | 0 | return false; |
134 | 0 | } |
135 | | |
136 | 7.78k | ssl->d1->write_epoch = std::move(new_epoch); |
137 | 7.78k | ssl->d1->extra_write_epochs.PushBack(std::move(current)); |
138 | 7.78k | dtls_clear_unused_write_epochs(ssl); |
139 | 7.78k | return true; |
140 | 7.78k | } |
141 | | |
142 | | static const SSL_PROTOCOL_METHOD kDTLSProtocolMethod = { |
143 | | true /* is_dtls */, |
144 | | dtls1_new, |
145 | | dtls1_free, |
146 | | dtls1_get_message, |
147 | | dtls1_next_message, |
148 | | dtls_has_unprocessed_handshake_data, |
149 | | dtls1_open_handshake, |
150 | | dtls1_open_change_cipher_spec, |
151 | | dtls1_open_app_data, |
152 | | dtls1_write_app_data, |
153 | | dtls1_dispatch_alert, |
154 | | dtls1_init_message, |
155 | | dtls1_finish_message, |
156 | | dtls1_add_message, |
157 | | dtls1_add_change_cipher_spec, |
158 | | dtls1_finish_flight, |
159 | | dtls1_schedule_ack, |
160 | | dtls1_flush, |
161 | | dtls1_on_handshake_complete, |
162 | | dtls1_set_read_state, |
163 | | dtls1_set_write_state, |
164 | | }; |
165 | | |
166 | 4 | const SSL_METHOD *DTLS_method() { |
167 | 4 | static const SSL_METHOD kMethod = { |
168 | 4 | 0, |
169 | 4 | &kDTLSProtocolMethod, |
170 | 4 | &ssl_crypto_x509_method, |
171 | 4 | }; |
172 | 4 | return &kMethod; |
173 | 4 | } |
174 | | |
175 | 0 | const SSL_METHOD *DTLS_with_buffers_method() { |
176 | 0 | static const SSL_METHOD kMethod = { |
177 | 0 | 0, |
178 | 0 | &kDTLSProtocolMethod, |
179 | 0 | &ssl_noop_x509_method, |
180 | 0 | }; |
181 | 0 | return &kMethod; |
182 | 0 | } |
183 | | |
184 | | // Legacy version-locked methods. |
185 | | |
186 | 0 | const SSL_METHOD *DTLSv1_2_method() { |
187 | 0 | static const SSL_METHOD kMethod = { |
188 | 0 | DTLS1_2_VERSION, |
189 | 0 | &kDTLSProtocolMethod, |
190 | 0 | &ssl_crypto_x509_method, |
191 | 0 | }; |
192 | 0 | return &kMethod; |
193 | 0 | } |
194 | | |
195 | 0 | const SSL_METHOD *DTLSv1_method() { |
196 | 0 | static const SSL_METHOD kMethod = { |
197 | 0 | DTLS1_VERSION, |
198 | 0 | &kDTLSProtocolMethod, |
199 | 0 | &ssl_crypto_x509_method, |
200 | 0 | }; |
201 | 0 | return &kMethod; |
202 | 0 | } |
203 | | |
204 | | // Legacy side-specific methods. |
205 | | |
206 | 0 | const SSL_METHOD *DTLSv1_2_server_method() { return DTLSv1_2_method(); } |
207 | | |
208 | 0 | const SSL_METHOD *DTLSv1_server_method() { return DTLSv1_method(); } |
209 | | |
210 | 0 | const SSL_METHOD *DTLSv1_2_client_method() { return DTLSv1_2_method(); } |
211 | | |
212 | 0 | const SSL_METHOD *DTLSv1_client_method() { return DTLSv1_method(); } |
213 | | |
214 | 0 | const SSL_METHOD *DTLS_server_method() { return DTLS_method(); } |
215 | | |
216 | 0 | const SSL_METHOD *DTLS_client_method() { return DTLS_method(); } |