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 : : /* Use usleep */
19 : : #define _XOPEN_SOURCE 500
20 : : #include <errno.h>
21 : : #include <unistd.h>
22 : :
23 : : #include "api/s2n.h"
24 : : #include "error/s2n_errno.h"
25 : : #include "stuffer/s2n_stuffer.h"
26 : : #include "tls/s2n_alerts.h"
27 : : #include "tls/s2n_connection.h"
28 : : #include "tls/s2n_handshake.h"
29 : : #include "tls/s2n_ktls.h"
30 : : #include "tls/s2n_post_handshake.h"
31 : : #include "tls/s2n_record.h"
32 : : #include "tls/s2n_resume.h"
33 : : #include "tls/s2n_tls.h"
34 : : #include "utils/s2n_blob.h"
35 : : #include "utils/s2n_io.h"
36 : : #include "utils/s2n_safety.h"
37 : : #include "utils/s2n_socket.h"
38 : :
39 : : S2N_RESULT s2n_recv_in_init(struct s2n_connection *conn, uint32_t written, uint32_t total)
40 : 367389 : {
41 [ - + ][ # # ]: 367389 : RESULT_ENSURE_REF(conn);
42 : :
43 : : /* If we're going to initialize conn->in to point to more memory than
44 : : * is actually readable, make sure that the additional memory exists.
45 : : */
46 [ - + ][ # # ]: 367389 : RESULT_ENSURE_LTE(written, total);
47 : 367389 : uint32_t remaining = total - written;
48 [ - + ][ # # ]: 367389 : RESULT_ENSURE_LTE(remaining, s2n_stuffer_space_remaining(&conn->buffer_in));
49 : :
50 : 367389 : uint8_t *data = s2n_stuffer_raw_read(&conn->buffer_in, written);
51 [ - + ][ # # ]: 367389 : RESULT_ENSURE_REF(data);
52 [ - + ]: 367389 : RESULT_GUARD_POSIX(s2n_stuffer_free(&conn->in));
53 [ - + ]: 367389 : RESULT_GUARD_POSIX(s2n_blob_init(&conn->in.blob, data, total));
54 [ - + ]: 367389 : RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&conn->in, written));
55 : 367389 : return S2N_RESULT_OK;
56 : 367389 : }
57 : :
58 : : S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *output, uint32_t length)
59 : 848454 : {
60 [ + + ]: 1450142 : while (s2n_stuffer_data_available(output) < length) {
61 : 947140 : uint32_t remaining = length - s2n_stuffer_data_available(output);
62 [ + + ]: 947140 : if (conn->recv_buffering) {
63 : 606 : remaining = MAX(remaining, s2n_stuffer_space_remaining(output));
64 : 606 : }
65 : 947140 : errno = 0;
66 : 947140 : int r = s2n_connection_recv_stuffer(output, conn, remaining);
67 [ + + ]: 947140 : if (r == 0) {
68 : 34 : s2n_atomic_flag_set(&conn->read_closed);
69 : 34 : }
70 [ + + ]: 947140 : RESULT_GUARD(s2n_io_check_read_result(r));
71 : 601688 : conn->wire_bytes_in += r;
72 : 601688 : }
73 : :
74 : 503002 : return S2N_RESULT_OK;
75 : 848454 : }
76 : :
77 : : static S2N_RESULT s2n_recv_buffer_in(struct s2n_connection *conn, size_t min_size)
78 : 849218 : {
79 [ - + ]: 849218 : RESULT_GUARD_POSIX(s2n_stuffer_resize_if_empty(&conn->buffer_in, S2N_LARGE_FRAGMENT_LENGTH));
80 : 849218 : uint32_t buffer_in_available = s2n_stuffer_data_available(&conn->buffer_in);
81 [ + + ]: 849218 : if (buffer_in_available < min_size) {
82 : 848005 : uint32_t remaining = min_size - buffer_in_available;
83 [ + + ]: 848005 : if (s2n_stuffer_space_remaining(&conn->buffer_in) < remaining) {
84 [ - + ]: 502 : RESULT_GUARD_POSIX(s2n_stuffer_shift(&conn->buffer_in));
85 : 502 : }
86 [ + + ]: 848005 : RESULT_GUARD(s2n_read_in_bytes(conn, &conn->buffer_in, min_size));
87 : 848005 : }
88 : 503823 : return S2N_RESULT_OK;
89 : 849218 : }
90 : :
91 : : int s2n_read_full_record(struct s2n_connection *conn, uint8_t *record_type, int *isSSLv2)
92 : 635746 : {
93 : 635746 : *isSSLv2 = 0;
94 : :
95 [ + + ]: 635746 : if (conn->ktls_recv_enabled) {
96 : 22 : return s2n_ktls_read_full_record(conn, record_type);
97 : 22 : }
98 : :
99 : : /* If the record has already been decrypted, then leave it alone */
100 [ + + ]: 635724 : if (conn->in_status == PLAINTEXT) {
101 : : /* Only application data packets count as plaintext */
102 : 35237 : *record_type = TLS_APPLICATION_DATA;
103 : 35237 : return S2N_SUCCESS;
104 : 35237 : }
105 : :
106 : : /* Read the record until we at least have a header */
107 [ - + ]: 600487 : POSIX_GUARD(s2n_stuffer_reread(&conn->header_in));
108 : 600487 : uint32_t header_available = s2n_stuffer_data_available(&conn->header_in);
109 [ + + ]: 600487 : if (header_available < S2N_TLS_RECORD_HEADER_LENGTH) {
110 : 482131 : uint32_t header_remaining = S2N_TLS_RECORD_HEADER_LENGTH - header_available;
111 : 482131 : s2n_result ret = s2n_recv_buffer_in(conn, header_remaining);
112 : 482131 : uint32_t header_read = MIN(header_remaining, s2n_stuffer_data_available(&conn->buffer_in));
113 [ - + ]: 482131 : POSIX_GUARD(s2n_stuffer_copy(&conn->buffer_in, &conn->header_in, header_read));
114 [ + + ]: 482131 : POSIX_GUARD_RESULT(ret);
115 : 482131 : }
116 : :
117 : 370269 : uint16_t fragment_length = 0;
118 : :
119 : : /* If the first bit is set then this is an SSLv2 record */
120 [ + + ]: 370269 : if (conn->header_in.blob.data[0] & S2N_TLS_SSLV2_HEADER_FLAG) {
121 : 179 : *isSSLv2 = 1;
122 [ - + ][ + - ]: 179 : WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_sslv2_record_header_parse(conn, record_type, &conn->client_hello.legacy_version, &fragment_length)));
123 : 370090 : } else {
124 [ + + ][ + - ]: 370090 : WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_record_header_parse(conn, record_type, &fragment_length)));
125 : 370090 : }
126 : :
127 : : /* Read enough to have the whole record */
128 : 370268 : uint32_t fragment_available = s2n_stuffer_data_available(&conn->in);
129 [ + + ][ + + ]: 370268 : if (fragment_available < fragment_length || fragment_length == 0) {
130 [ - + ]: 367087 : POSIX_GUARD(s2n_stuffer_rewind_read(&conn->buffer_in, fragment_available));
131 : 367087 : s2n_result ret = s2n_recv_buffer_in(conn, fragment_length);
132 : 367087 : uint32_t fragment_read = MIN(fragment_length, s2n_stuffer_data_available(&conn->buffer_in));
133 [ - + ]: 367087 : POSIX_GUARD_RESULT(s2n_recv_in_init(conn, fragment_read, fragment_length));
134 [ + + ]: 367087 : POSIX_GUARD_RESULT(ret);
135 : 367087 : }
136 : :
137 [ + + ]: 255091 : if (*isSSLv2) {
138 : 3 : return 0;
139 : 3 : }
140 : :
141 : : /* Decrypt and parse the record */
142 [ + + ]: 255088 : if (s2n_early_data_is_trial_decryption_allowed(conn, *record_type)) {
143 [ + - ][ + + ]: 987 : POSIX_ENSURE(s2n_record_parse(conn) >= S2N_SUCCESS, S2N_ERR_EARLY_DATA_TRIAL_DECRYPT);
144 : 254101 : } else {
145 [ + + ][ + - ]: 254101 : WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_record_parse(conn)));
146 : 254101 : }
147 : :
148 : : /* In TLS 1.3, encrypted handshake records would appear to be of record type
149 : : * TLS_APPLICATION_DATA. The actual record content type is found after the encrypted
150 : : * is decrypted.
151 : : */
152 [ + + ][ + + ]: 253673 : if (conn->actual_protocol_version == S2N_TLS13 && *record_type == TLS_APPLICATION_DATA) {
153 [ - + ]: 67457 : POSIX_GUARD(s2n_tls13_parse_record_type(&conn->in, record_type));
154 : 67457 : }
155 : :
156 : 253673 : return 0;
157 : 253673 : }
158 : :
159 : : ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size_signed, s2n_blocked_status *blocked)
160 : 392751 : {
161 [ - + ][ # # ]: 392751 : POSIX_ENSURE_GTE(size_signed, 0);
162 : 392751 : size_t size = size_signed;
163 : 392751 : ssize_t bytes_read = 0;
164 : 392751 : struct s2n_blob out = { 0 };
165 [ - + ]: 392751 : POSIX_GUARD(s2n_blob_init(&out, (uint8_t *) buf, 0));
166 : :
167 : : /*
168 : : * Set the `blocked` status to BLOCKED_ON_READ by default
169 : : *
170 : : * The only case in which it should be updated is on a successful read into the provided buffer.
171 : : *
172 : : * Unfortunately, the current `blocked` behavior has become ossified by buggy applications that ignore
173 : : * error types and only read `blocked`. As such, it's very important to avoid changing how this value is updated
174 : : * as it could break applications.
175 : : */
176 : 392751 : *blocked = S2N_BLOCKED_ON_READ;
177 : :
178 [ + + ]: 392751 : if (!s2n_connection_check_io_status(conn, S2N_IO_READABLE)) {
179 : : /*
180 : : *= https://www.rfc-editor.org/rfc/rfc8446#6.1
181 : : *# If a transport-level close
182 : : *# is received prior to a "close_notify", the receiver cannot know that
183 : : *# all the data that was sent has been received.
184 : : *
185 : : *= https://www.rfc-editor.org/rfc/rfc8446#6.1
186 : : *# If the application protocol using TLS provides that any data may be
187 : : *# carried over the underlying transport after the TLS connection is
188 : : *# closed, the TLS implementation MUST receive a "close_notify" alert
189 : : *# before indicating end-of-data to the application layer.
190 : : */
191 [ + + ][ + - ]: 1555 : POSIX_ENSURE(s2n_atomic_flag_test(&conn->close_notify_received), S2N_ERR_CLOSED);
192 : 31 : *blocked = S2N_NOT_BLOCKED;
193 : 31 : return 0;
194 : 1555 : }
195 : :
196 [ + + ][ + - ]: 391196 : POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_WITH_QUIC);
197 [ + + ]: 391195 : POSIX_GUARD_RESULT(s2n_early_data_validate_recv(conn));
198 : :
199 [ + + ][ + + ]: 418510 : while (size && s2n_connection_check_io_status(conn, S2N_IO_READABLE)) {
200 : 410720 : int isSSLv2 = 0;
201 : 410720 : uint8_t record_type = 0;
202 : 410720 : int r = s2n_read_full_record(conn, &record_type, &isSSLv2);
203 [ + + ]: 410720 : if (r < 0) {
204 : : /* Don't propagate the error if we already read some bytes. */
205 [ + + ][ + + ]: 190698 : if (bytes_read && (s2n_errno == S2N_ERR_CLOSED || s2n_errno == S2N_ERR_IO_BLOCKED)) {
[ + - ]
206 : 285 : break;
207 : 285 : }
208 : :
209 : : /* If we get here, it's an error condition.
210 : : * For stateful resumption, invalidate the session on error to prevent resumption with
211 : : * potentially corrupted session state. This ensures that a bad session state does not
212 : : * lead to repeated failures during resumption attempts.
213 : : */
214 [ + + ][ - + ]: 190413 : if (s2n_errno != S2N_ERR_IO_BLOCKED && s2n_allowed_to_cache_connection(conn) && conn->session_id_len) {
[ # # ]
215 : 0 : conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len);
216 : 0 : }
217 : :
218 : 190413 : S2N_ERROR_PRESERVE_ERRNO();
219 : 190413 : }
220 : :
221 [ - + ][ # # ]: 220022 : S2N_ERROR_IF(isSSLv2, S2N_ERR_BAD_MESSAGE);
222 : :
223 [ + + ]: 220022 : if (record_type != TLS_HANDSHAKE) {
224 : : /*
225 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-5.1
226 : : *# - Handshake messages MUST NOT be interleaved with other record
227 : : *# types. That is, if a handshake message is split over two or more
228 : : *# records, there MUST NOT be any other records between them.
229 : : */
230 [ + - ][ + + ]: 195335 : POSIX_ENSURE(s2n_stuffer_is_wiped(&conn->post_handshake.in), S2N_ERR_BAD_MESSAGE);
231 : :
232 : : /* If not handling a handshake message, free the post-handshake memory.
233 : : * Post-handshake messages are infrequent enough that we don't want to
234 : : * keep a potentially large buffer around unnecessarily.
235 : : */
236 [ + + ]: 195333 : if (!s2n_stuffer_is_freed(&conn->post_handshake.in)) {
237 [ - + ]: 1013 : POSIX_GUARD(s2n_stuffer_free(&conn->post_handshake.in));
238 : 1013 : }
239 : 195333 : }
240 : :
241 [ + + ]: 220020 : if (record_type != TLS_APPLICATION_DATA) {
242 [ + + ]: 26208 : switch (record_type) {
243 [ + + ]: 1520 : case TLS_ALERT:
244 [ + + ]: 1520 : POSIX_GUARD(s2n_process_alert_fragment(conn));
245 : 13 : break;
246 [ + + ]: 24687 : case TLS_HANDSHAKE: {
247 : 24687 : s2n_result result = s2n_post_handshake_recv(conn);
248 : : /* Ignore any errors due to insufficient input data from io.
249 : : * The next iteration of this loop will attempt to read more input data.
250 : : */
251 [ + + ][ + + ]: 24687 : if (s2n_result_is_error(result) && s2n_errno != S2N_ERR_IO_BLOCKED) {
252 [ + - ][ # # ]: 41 : WITH_ERROR_BLINDING(conn, POSIX_GUARD_RESULT(result));
253 : 41 : }
254 : 24646 : break;
255 : 24687 : }
256 : 26208 : }
257 [ - + ]: 24660 : POSIX_GUARD_RESULT(s2n_record_wipe(conn));
258 : 24660 : continue;
259 : 24660 : }
260 : :
261 : 193812 : out.size = MIN(size, s2n_stuffer_data_available(&conn->in));
262 : :
263 [ - + ]: 193812 : POSIX_GUARD(s2n_stuffer_erase_and_read(&conn->in, &out));
264 : 193812 : bytes_read += out.size;
265 : :
266 : 193812 : out.data += out.size;
267 : 193812 : size -= out.size;
268 : :
269 : : /* Are we ready for more encrypted data? */
270 [ + + ]: 193812 : if (s2n_stuffer_data_available(&conn->in) == 0) {
271 [ - + ]: 158652 : POSIX_GUARD_RESULT(s2n_record_wipe(conn));
272 : 158652 : }
273 : :
274 : : /* If we've read some data, return it in legacy mode */
275 [ + - ][ + + ]: 193812 : if (bytes_read && !conn->config->recv_multi_record) {
276 : 191153 : break;
277 : 191153 : }
278 : 193812 : }
279 : :
280 : : /* Due to the history of this API, some applications depend on the blocked status to know if
281 : : * the connection's `in` stuffer was completely cleared. This behavior needs to be preserved.
282 : : *
283 : : * Moving forward, applications should instead use `s2n_peek`, which accomplishes the same thing
284 : : * without conflating being blocked on reading from the OS socket vs blocked on the application's
285 : : * buffer size.
286 : : */
287 [ + + ]: 199228 : if (s2n_stuffer_data_available(&conn->in) == 0) {
288 : 164066 : *blocked = S2N_NOT_BLOCKED;
289 : 164066 : }
290 : :
291 : 199228 : return bytes_read;
292 : 391191 : }
293 : :
294 : : ssize_t s2n_recv(struct s2n_connection *conn, void *buf, ssize_t size, s2n_blocked_status *blocked)
295 : 392753 : {
296 [ + + ][ + - ]: 392753 : POSIX_ENSURE(!conn->recv_in_use, S2N_ERR_REENTRANCY);
297 : 392751 : conn->recv_in_use = true;
298 : :
299 : 392751 : ssize_t result = s2n_recv_impl(conn, buf, size, blocked);
300 [ + + ]: 392751 : POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, result));
301 : :
302 : : /* finish the recv call */
303 [ - + ]: 392750 : POSIX_GUARD_RESULT(s2n_connection_dynamic_free_in_buffer(conn));
304 : :
305 : 392750 : conn->recv_in_use = false;
306 : 392750 : return result;
307 : 392750 : }
308 : :
309 : : uint32_t s2n_peek(struct s2n_connection *conn)
310 : 4459 : {
311 [ + + ]: 4459 : if (conn == NULL) {
312 : 1 : return 0;
313 : 1 : }
314 : :
315 : : /* If we have partially buffered an encrypted record,
316 : : * we should not report those bytes as available to read.
317 : : */
318 [ + + ]: 4458 : if (conn->in_status != PLAINTEXT) {
319 : 1305 : return 0;
320 : 1305 : }
321 : :
322 : 3153 : return s2n_stuffer_data_available(&conn->in);
323 : 4458 : }
324 : :
325 : : uint32_t s2n_peek_buffered(struct s2n_connection *conn)
326 : 5 : {
327 [ + + ]: 5 : if (conn == NULL) {
328 : 1 : return 0;
329 : 1 : }
330 : 4 : return s2n_stuffer_data_available(&conn->buffer_in);
331 : 5 : }
|