Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include <sys/param.h>
17 : :
18 : : #include "tls/s2n_connection.h"
19 : : #include "tls/s2n_early_data.h"
20 : : #include "utils/s2n_mem.h"
21 : : #include "utils/s2n_safety.h"
22 : :
23 : : int s2n_end_of_early_data_send(struct s2n_connection *conn)
24 : 78 : {
25 [ + + ]: 78 : if (conn->early_data_expected) {
26 [ - + ]: 40 : POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
27 [ + - ]: 40 : POSIX_BAIL(S2N_ERR_EARLY_DATA_BLOCKED);
28 : 40 : }
29 : :
30 [ - + ]: 38 : POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_END_OF_EARLY_DATA));
31 : 38 : return S2N_SUCCESS;
32 : 38 : }
33 : :
34 : : int s2n_end_of_early_data_recv(struct s2n_connection *conn)
35 : 37 : {
36 [ # # ][ - + ]: 37 : POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_BAD_MESSAGE);
37 [ - + ]: 37 : POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_END_OF_EARLY_DATA));
38 : 37 : return S2N_SUCCESS;
39 : 37 : }
40 : :
41 : : /**
42 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.10
43 : : *# If the client attempts a 0-RTT handshake but the server
44 : : *# rejects it, the server will generally not have the 0-RTT record
45 : : *# protection keys and must instead use trial decryption (either with
46 : : *# the 1-RTT handshake keys or by looking for a cleartext ClientHello in
47 : : *# the case of a HelloRetryRequest) to find the first non-0-RTT message.
48 : : */
49 : : bool s2n_early_data_is_trial_decryption_allowed(struct s2n_connection *conn, uint8_t record_type)
50 : 255088 : {
51 [ + - ][ + + ]: 255088 : return conn && (conn->early_data_state == S2N_EARLY_DATA_REJECTED)
52 [ + + ]: 255088 : && record_type == TLS_APPLICATION_DATA
53 : : /* Only servers receive early data. */
54 [ + + ]: 255088 : && (conn->mode == S2N_SERVER)
55 : : /* Early data is only expected during the handshake. */
56 [ + + ]: 255088 : && (s2n_conn_get_current_message_type(conn) != APPLICATION_DATA);
57 : 255088 : }
58 : :
59 : : static bool s2n_is_early_data_io(struct s2n_connection *conn)
60 : 637273 : {
61 [ + + ]: 637273 : if (s2n_conn_get_current_message_type(conn) == APPLICATION_DATA) {
62 : 509910 : return false;
63 : 509910 : }
64 : :
65 : : /* It would be more accurate to not include this check.
66 : : * However, before the early data feature was added, s2n_send and s2n_recv
67 : : * did not verify that they were being called after a complete handshake.
68 : : * Enforcing that broke several S2N tests, and might have broken customers too.
69 : : *
70 : : * Therefore, only consider this early data if the customer has indicated that
71 : : * they are aware of early data, either because early data is currently expected
72 : : * or early data is in a state that indicates that early data was previously expected.
73 : : */
74 [ + + ]: 127363 : if (conn->early_data_expected
75 [ + + ][ + + ]: 127363 : || (conn->mode == S2N_CLIENT && conn->early_data_state == S2N_EARLY_DATA_REQUESTED)
76 [ + + ]: 127363 : || conn->early_data_state == S2N_EARLY_DATA_ACCEPTED
77 [ + + ]: 127363 : || conn->early_data_state == S2N_END_OF_EARLY_DATA) {
78 : 1937 : return true;
79 : 1937 : }
80 : 125426 : return false;
81 : 127363 : }
82 : :
83 : : S2N_RESULT s2n_early_data_record_bytes(struct s2n_connection *conn, ssize_t data_len)
84 : 612474 : {
85 [ + + ][ + - ]: 612474 : RESULT_ENSURE_REF(conn);
86 [ + + ][ + + ]: 612473 : if (data_len < 0 || !s2n_is_early_data_io(conn)) {
87 : 611322 : return S2N_RESULT_OK;
88 : 611322 : }
89 : :
90 : : /* Ensure the bytes read are within the bounds of what we can actually record. */
91 [ + + ]: 1151 : if ((size_t) data_len > (UINT64_MAX - conn->early_data_bytes)) {
92 : 1 : conn->early_data_bytes = UINT64_MAX;
93 [ + - ]: 1 : RESULT_BAIL(S2N_ERR_INTEGER_OVERFLOW);
94 : 1 : }
95 : :
96 : : /* Record the early data bytes read, even if they exceed the max_early_data_size.
97 : : * This will ensure that if this method is called again, it will fail again:
98 : : * Once we receive too many bytes, we can't proceed with the connection. */
99 : 1150 : conn->early_data_bytes += data_len;
100 : :
101 : 1150 : uint32_t max_early_data_size = 0;
102 [ - + ]: 1150 : RESULT_GUARD_POSIX(s2n_connection_get_max_early_data_size(conn, &max_early_data_size));
103 [ + + ][ + - ]: 1150 : RESULT_ENSURE(conn->early_data_bytes <= max_early_data_size, S2N_ERR_MAX_EARLY_DATA_SIZE);
104 : :
105 : 1144 : return S2N_RESULT_OK;
106 : 1150 : }
107 : :
108 : : S2N_RESULT s2n_early_data_validate_send(struct s2n_connection *conn, uint32_t bytes_to_send)
109 : 23740 : {
110 [ + - ][ + + ]: 23740 : RESULT_ENSURE_REF(conn);
111 [ + + ]: 23739 : if (!s2n_is_early_data_io(conn)) {
112 : 23108 : return S2N_RESULT_OK;
113 : 23108 : }
114 : :
115 [ + + ][ + - ]: 631 : RESULT_ENSURE(conn->early_data_expected, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
116 [ + + ][ + - ]: 627 : RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
117 [ + - ][ + + ]: 626 : RESULT_ENSURE(conn->early_data_state == S2N_EARLY_DATA_REQUESTED
[ + + ]
118 : 623 : || conn->early_data_state == S2N_EARLY_DATA_ACCEPTED,
119 : 623 : S2N_ERR_EARLY_DATA_NOT_ALLOWED);
120 : :
121 : 623 : uint32_t allowed_early_data_size = 0;
122 [ - + ]: 623 : RESULT_GUARD_POSIX(s2n_connection_get_remaining_early_data_size(conn, &allowed_early_data_size));
123 [ + - ][ + + ]: 623 : RESULT_ENSURE(bytes_to_send <= allowed_early_data_size, S2N_ERR_MAX_EARLY_DATA_SIZE);
124 : :
125 : 621 : return S2N_RESULT_OK;
126 : 623 : }
127 : :
128 : : S2N_RESULT s2n_early_data_validate_recv(struct s2n_connection *conn)
129 : 391266 : {
130 [ + + ][ + - ]: 391266 : RESULT_ENSURE_REF(conn);
131 [ + + ]: 391265 : if (!s2n_is_early_data_io(conn)) {
132 : 391131 : return S2N_RESULT_OK;
133 : 391131 : }
134 : :
135 [ - + ][ # # ]: 134 : RESULT_ENSURE(conn->early_data_expected, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
136 [ + - ][ + + ]: 134 : RESULT_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
137 [ + + ][ + - ]: 133 : RESULT_ENSURE(conn->early_data_state == S2N_EARLY_DATA_ACCEPTED, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
138 [ + - ][ + + ]: 128 : RESULT_ENSURE(s2n_conn_get_current_message_type(conn) == END_OF_EARLY_DATA, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
139 : 126 : return S2N_RESULT_OK;
140 : 128 : }
141 : :
142 : : static bool s2n_early_data_can_continue(struct s2n_connection *conn)
143 : 9701 : {
144 : 9701 : uint32_t remaining_early_data_size = 0;
145 [ + - ]: 9701 : return s2n_connection_get_remaining_early_data_size(conn, &remaining_early_data_size) >= S2N_SUCCESS
146 [ + + ]: 9701 : && remaining_early_data_size > 0;
147 : 9701 : }
148 : :
149 : : S2N_RESULT s2n_send_early_data_impl(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len_signed,
150 : : ssize_t *data_sent, s2n_blocked_status *blocked)
151 : 1484 : {
152 [ # # ][ - + ]: 1484 : RESULT_ENSURE_GTE(data_len_signed, 0);
153 : 1484 : size_t data_len = data_len_signed;
154 [ - + ][ # # ]: 1484 : RESULT_ENSURE_REF(conn);
155 [ + - ][ + + ]: 1484 : RESULT_ENSURE_REF(blocked);
156 : 1483 : *blocked = S2N_NOT_BLOCKED;
157 [ + - ][ + + ]: 1483 : RESULT_ENSURE_REF(data_sent);
158 : 1482 : *data_sent = 0;
159 : :
160 [ + + ][ + - ]: 1482 : RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_SERVER_MODE);
161 [ - + ][ # # ]: 1481 : RESULT_ENSURE(s2n_connection_supports_tls13(conn), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
162 : :
163 [ + + ]: 1481 : if (!s2n_early_data_can_continue(conn)) {
164 : 68 : return S2N_RESULT_OK;
165 : 68 : }
166 : :
167 : : /* Attempt to make progress in the handshake even if s2n_send eventually fails.
168 : : * We only care about the result of this call if it would prevent us from calling s2n_send. */
169 : 1413 : int negotiate_result = s2n_negotiate(conn, blocked);
170 [ + + ]: 1413 : if (negotiate_result < S2N_SUCCESS) {
171 [ + + ]: 1392 : if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED) {
172 [ + - ]: 1 : RESULT_GUARD_POSIX(negotiate_result);
173 [ + + ][ + + ]: 1391 : } else if (*blocked != S2N_BLOCKED_ON_EARLY_DATA && *blocked != S2N_BLOCKED_ON_READ) {
174 [ + - ]: 1246 : RESULT_GUARD_POSIX(negotiate_result);
175 : 1246 : }
176 : 1392 : }
177 : : /* Save the error status for later */
178 : 166 : int negotiate_error = s2n_errno;
179 : 166 : s2n_blocked_status negotiate_blocked = *blocked;
180 : :
181 : : /* Attempt to send the early data.
182 : : * We only care about the result of this call if it fails. */
183 : 166 : uint32_t early_data_to_send = 0;
184 [ - + ]: 166 : RESULT_GUARD_POSIX(s2n_connection_get_remaining_early_data_size(conn, &early_data_to_send));
185 : 166 : early_data_to_send = MIN(data_len, early_data_to_send);
186 [ + + ]: 166 : if (early_data_to_send) {
187 : 71 : ssize_t send_result = s2n_send(conn, data, early_data_to_send, blocked);
188 [ + + ]: 71 : RESULT_GUARD_POSIX(send_result);
189 : 61 : *data_sent = send_result;
190 : 61 : }
191 : 156 : *blocked = S2N_NOT_BLOCKED;
192 : :
193 : : /* Since the send was successful, report the result of the original negotiate call.
194 : : * If we got this far, the result must have been success or a blocking error. */
195 [ + + ]: 156 : if (negotiate_result < S2N_SUCCESS) {
196 [ - + ][ # # ]: 135 : RESULT_ENSURE_EQ(s2n_error_get_type(negotiate_error), S2N_ERR_T_BLOCKED);
197 [ + + ]: 135 : if (negotiate_blocked == S2N_BLOCKED_ON_EARLY_DATA) {
198 : 30 : return S2N_RESULT_OK;
199 [ + + ]: 105 : } else if (s2n_early_data_can_continue(conn)) {
200 : 90 : *blocked = negotiate_blocked;
201 [ + - ]: 90 : RESULT_BAIL(negotiate_error);
202 : 90 : } else {
203 : 15 : return S2N_RESULT_OK;
204 : 15 : }
205 : 135 : }
206 : 21 : return S2N_RESULT_OK;
207 : 156 : }
208 : :
209 : : int s2n_send_early_data(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len,
210 : : ssize_t *data_sent, s2n_blocked_status *blocked)
211 : 1485 : {
212 [ + + ][ + - ]: 1485 : POSIX_ENSURE_REF(conn);
213 : :
214 : : /* Calling this method indicates that we expect early data. */
215 [ - + ]: 1484 : POSIX_GUARD(s2n_connection_set_early_data_expected(conn));
216 : :
217 : 1484 : s2n_result result = s2n_send_early_data_impl(conn, data, data_len, data_sent, blocked);
218 : :
219 : : /* Unless s2n_send_early_data is called again (undoing this), we are done sending early data.
220 : : * If s2n_negotiate is called next, we could send the EndOfEarlyData message. */
221 [ - + ]: 1484 : POSIX_GUARD(s2n_connection_set_end_of_early_data(conn));
222 : :
223 [ + + ]: 1484 : POSIX_GUARD_RESULT(result);
224 : 134 : return S2N_SUCCESS;
225 : 1484 : }
226 : :
227 : : S2N_RESULT s2n_recv_early_data_impl(struct s2n_connection *conn, uint8_t *data, ssize_t max_data_len,
228 : : ssize_t *data_received, s2n_blocked_status *blocked)
229 : 4126 : {
230 [ # # ][ - + ]: 4126 : RESULT_ENSURE_REF(conn);
231 [ + + ][ + - ]: 4126 : RESULT_ENSURE_REF(blocked);
232 : 4125 : *blocked = S2N_NOT_BLOCKED;
233 [ + - ][ + + ]: 4125 : RESULT_ENSURE_REF(data_received);
234 : 4124 : *data_received = 0;
235 : :
236 [ + + ][ + - ]: 4124 : RESULT_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_CLIENT_MODE);
237 : :
238 [ + + ]: 4123 : if (!s2n_early_data_can_continue(conn)) {
239 : 79 : return S2N_RESULT_OK;
240 : 79 : }
241 : :
242 : 4044 : int negotiate_result = S2N_SUCCESS;
243 [ + + ]: 4093 : while ((negotiate_result = s2n_negotiate(conn, blocked)) != S2N_SUCCESS) {
244 [ + + ]: 4072 : if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED) {
245 [ + - ]: 1 : RESULT_GUARD_POSIX(negotiate_result);
246 [ + + ]: 4071 : } else if (max_data_len <= *data_received) {
247 [ + - ]: 29 : RESULT_GUARD_POSIX(negotiate_result);
248 [ + + ]: 4042 : } else if (*blocked != S2N_BLOCKED_ON_EARLY_DATA) {
249 [ + + ]: 3992 : if (s2n_early_data_can_continue(conn)) {
250 [ + - ]: 3959 : RESULT_GUARD_POSIX(negotiate_result);
251 : 3959 : } else {
252 : 33 : *blocked = S2N_NOT_BLOCKED;
253 : 33 : return S2N_RESULT_OK;
254 : 33 : }
255 : 3992 : }
256 : :
257 : 50 : ssize_t recv_result = s2n_recv(conn, data + *data_received,
258 : 50 : max_data_len - *data_received, blocked);
259 [ + + ]: 50 : RESULT_GUARD_POSIX(recv_result);
260 : 49 : *data_received += recv_result;
261 : 49 : }
262 : 21 : return S2N_RESULT_OK;
263 : 4044 : }
264 : :
265 : : int s2n_recv_early_data(struct s2n_connection *conn, uint8_t *data, ssize_t max_data_len,
266 : : ssize_t *data_received, s2n_blocked_status *blocked)
267 : 4127 : {
268 : : /* Calling this method indicates that we expect early data. */
269 [ + + ]: 4127 : POSIX_GUARD(s2n_connection_set_early_data_expected(conn));
270 : :
271 : 4126 : s2n_result result = s2n_recv_early_data_impl(conn, data, max_data_len, data_received, blocked);
272 : :
273 : : /* Unless s2n_recv_early_data is called again (undoing this), we are done accepting early data. */
274 [ - + ]: 4126 : POSIX_GUARD(s2n_connection_set_end_of_early_data(conn));
275 : :
276 [ + + ]: 4126 : POSIX_GUARD_RESULT(result);
277 : 133 : return S2N_SUCCESS;
278 : 4126 : }
|