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 "tls/s2n_record_read.h"
17 : :
18 : : #include "crypto/s2n_cipher.h"
19 : : #include "crypto/s2n_hmac.h"
20 : : #include "crypto/s2n_sequence.h"
21 : : #include "error/s2n_errno.h"
22 : : #include "stuffer/s2n_stuffer.h"
23 : : #include "tls/s2n_cipher_suites.h"
24 : : #include "tls/s2n_connection.h"
25 : : #include "tls/s2n_crypto.h"
26 : : #include "utils/s2n_blob.h"
27 : : #include "utils/s2n_safety.h"
28 : :
29 : : int s2n_sslv2_record_header_parse(
30 : : struct s2n_connection *conn,
31 : : uint8_t *record_type,
32 : : uint8_t *client_protocol_version,
33 : : uint16_t *fragment_length)
34 : 193 : {
35 : 193 : struct s2n_stuffer *header_in = &conn->header_in;
36 : :
37 [ # # ][ - + ]: 193 : POSIX_ENSURE(s2n_stuffer_data_available(header_in) >= S2N_TLS_RECORD_HEADER_LENGTH,
38 : 193 : S2N_ERR_BAD_MESSAGE);
39 : :
40 [ - + ]: 193 : POSIX_GUARD(s2n_stuffer_read_uint16(header_in, fragment_length));
41 : :
42 : : /* The first bit of the SSLv2 message would usually indicate whether the
43 : : * length is 2 bytes long or 3 bytes long.
44 : : * See https://www.ietf.org/archive/id/draft-hickman-netscape-ssl-00.txt
45 : : *
46 : : * However, s2n-tls only supports SSLv2 for ClientHellos as defined in the
47 : : * TLS1.2 RFC. In that case, the first bit must always be set to distinguish
48 : : * SSLv2 from non-SSLv2 headers. The length is always 2 bytes.
49 : : * See https://datatracker.ietf.org/doc/html/rfc5246#appendix-E.2
50 : : *
51 : : * Since the first bit is not actually used to indicate length, we need to
52 : : * remove it from the length.
53 : : *
54 : : *= https://www.rfc-editor.org/rfc/rfc5246#appendix-E.2
55 : : *# msg_length
56 : : *# The highest bit MUST be 1; the remaining bits contain the length
57 : : *# of the following data in bytes.
58 : : */
59 [ # # ][ - + ]: 193 : POSIX_ENSURE(*fragment_length & S2N_TLS_SSLV2_HEADER_FLAG_UINT16, S2N_ERR_BAD_MESSAGE);
60 : 193 : *fragment_length ^= S2N_TLS_SSLV2_HEADER_FLAG_UINT16;
61 : :
62 : : /* We read 5 bytes into header_in because we expected a standard, non-SSLv2 record header
63 : : * instead of an SSLv2 message. We have therefore already read 3 bytes of the payload.
64 : : * We need to adjust "fragment_length" to account for the bytes we have already
65 : : * read so that we will only attempt to read the remainder of the payload on
66 : : * our next call to conn->recv.
67 : : */
68 [ + + ][ + - ]: 193 : POSIX_ENSURE(*fragment_length >= s2n_stuffer_data_available(header_in), S2N_ERR_BAD_MESSAGE);
69 : 191 : *fragment_length -= s2n_stuffer_data_available(header_in);
70 : :
71 : : /* By reading 5 bytes for a standard header we have also read the first
72 : : * 3 bytes of the SSLv2 ClientHello message.
73 : : * So we now need to parse those three bytes.
74 : : *
75 : : * The first field of an SSLv2 ClientHello is the msg_type.
76 : : * This is always '1', matching the ClientHello msg_type used by later
77 : : * handshake messages.
78 : : */
79 [ - + ]: 191 : POSIX_GUARD(s2n_stuffer_read_uint8(header_in, record_type));
80 : :
81 : : /*
82 : : * The second field of an SSLv2 ClientHello is the version.
83 : : *
84 : : * The protocol version read here will likely not be SSLv2, since we only
85 : : * accept SSLv2 ClientHellos offering higher protocol versions.
86 : : * See s2n_sslv2_client_hello_parse.
87 : : */
88 : 191 : uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
89 [ - + ]: 191 : POSIX_GUARD(s2n_stuffer_read_bytes(header_in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
90 : 191 : *client_protocol_version = (protocol_version[0] * 10) + protocol_version[1];
91 : :
92 [ - + ]: 191 : POSIX_GUARD(s2n_stuffer_reread(header_in));
93 : 191 : return 0;
94 : 191 : }
95 : :
96 : : int s2n_record_header_parse(
97 : : struct s2n_connection *conn,
98 : : uint8_t *content_type,
99 : : uint16_t *fragment_length)
100 : 7323378 : {
101 : 7323378 : struct s2n_stuffer *in = &conn->header_in;
102 : :
103 [ - + ][ # # ]: 7323378 : S2N_ERROR_IF(s2n_stuffer_data_available(in) < S2N_TLS_RECORD_HEADER_LENGTH, S2N_ERR_BAD_MESSAGE);
104 : :
105 [ - + ]: 7323378 : POSIX_GUARD(s2n_stuffer_read_uint8(in, content_type));
106 : :
107 : 7323378 : uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
108 [ - + ]: 7323378 : POSIX_GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
109 : :
110 : 7323378 : const uint8_t version = (protocol_version[0] * 10) + protocol_version[1];
111 : : /* We record the protocol version in the first record seen by the server for fingerprinting usecases */
112 [ + + ]: 7323378 : if (!conn->client_hello.record_version_recorded) {
113 : 3307621 : conn->client_hello.legacy_record_version = version;
114 : 3307621 : conn->client_hello.record_version_recorded = 1;
115 : 3307621 : }
116 : :
117 : : /* https://tools.ietf.org/html/rfc5246#appendix-E.1 states that servers must accept any value {03,XX} as the record
118 : : * layer version number for the first TLS record. There is some ambiguity here because the client does not know
119 : : * what version to use in the record header prior to receiving the ServerHello. Some client implementations may use
120 : : * a garbage value(not {03,XX}) in the ClientHello.
121 : : * Choose to be lenient to these clients. After protocol negotiation, we will enforce that all record versions
122 : : * match the negotiated version.
123 : : */
124 : :
125 [ + + ][ + + ]: 7323378 : S2N_ERROR_IF(conn->actual_protocol_version_established && S2N_MIN(conn->actual_protocol_version, S2N_TLS12) /* check against legacy record version (1.2) in tls 1.3 */
[ + + ][ + - ]
126 : 7323378 : != version,
127 : 7323378 : S2N_ERR_BAD_MESSAGE);
128 : :
129 : : /* Some servers send fragments that are above the maximum length (e.g.
130 : : * Openssl 1.0.1), so we don't check if the fragment length is >
131 : : * S2N_TLS_MAXIMUM_FRAGMENT_LENGTH. We allow up to 2^16.
132 : : *
133 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-5.1
134 : : *= type=exception
135 : : *= reason=Incorrect implementations exist in the wild. Ignoring instead.
136 : : *# The length MUST NOT exceed 2^14 bytes. An
137 : : *# endpoint that receives a record that exceeds this length MUST
138 : : *# terminate the connection with a "record_overflow" alert.
139 : : */
140 [ - + ]: 7323376 : POSIX_GUARD(s2n_stuffer_read_uint16(in, fragment_length));
141 [ - + ]: 7323376 : POSIX_GUARD(s2n_stuffer_reread(in));
142 : :
143 : 7323376 : return 0;
144 : 7323376 : }
145 : :
146 : : /* In TLS 1.3, handle CCS message as unprotected records all the time.
147 : : * https://tools.ietf.org/html/rfc8446#section-5
148 : : *
149 : : * In TLS 1.2 and TLS 1.3 Alert messages are plaintext or encrypted
150 : : * depending on the context of the connection. If we receive an encrypted
151 : : * alert, the record type is TLS_APPLICATION_DATA at this point. It will
152 : : * be decrypted and processed in s2n_handshake_io. We may receive a
153 : : * plaintext alert if we hit an error before the handshake completed
154 : : * (like a certificate failed to validate).
155 : : * https://tools.ietf.org/html/rfc8446#section-6
156 : : *
157 : : * This function is specific to TLS 1.3 to avoid changing the behavior
158 : : * of existing interpretation of TLS 1.2 alerts. */
159 : : static bool s2n_is_tls13_plaintext_content(struct s2n_connection *conn, uint8_t content_type)
160 : 7224554 : {
161 [ + + ][ + + ]: 7224554 : return conn->actual_protocol_version == S2N_TLS13 && (content_type == TLS_ALERT || content_type == TLS_CHANGE_CIPHER_SPEC);
[ + + ]
162 : 7224554 : }
163 : :
164 : : int s2n_record_parse(struct s2n_connection *conn)
165 : 3612277 : {
166 : 3612277 : uint8_t content_type = 0;
167 : 3612277 : uint16_t encrypted_length = 0;
168 [ - + ]: 3612277 : POSIX_GUARD(s2n_record_header_parse(conn, &content_type, &encrypted_length));
169 : :
170 : 3612277 : struct s2n_crypto_parameters *current_client_crypto = conn->client;
171 : 3612277 : struct s2n_crypto_parameters *current_server_crypto = conn->server;
172 [ + + ]: 3612277 : if (s2n_is_tls13_plaintext_content(conn, content_type)) {
173 [ - + ][ # # ]: 10167 : POSIX_ENSURE_REF(conn->initial);
174 : 10167 : conn->client = conn->initial;
175 : 10167 : conn->server = conn->initial;
176 : 10167 : }
177 : :
178 : 3612277 : const struct s2n_cipher_suite *cipher_suite = conn->client->cipher_suite;
179 : 3612277 : uint8_t *implicit_iv = conn->client->client_implicit_iv;
180 : 3612277 : struct s2n_hmac_state *mac = &conn->client->client_record_mac;
181 : 3612277 : uint8_t *sequence_number = conn->client->client_sequence_number;
182 : 3612277 : struct s2n_session_key *session_key = &conn->client->client_key;
183 : :
184 [ + + ]: 3612277 : if (conn->mode == S2N_CLIENT) {
185 : 94046 : cipher_suite = conn->server->cipher_suite;
186 : 94046 : implicit_iv = conn->server->server_implicit_iv;
187 : 94046 : mac = &conn->server->server_record_mac;
188 : 94046 : sequence_number = conn->server->server_sequence_number;
189 : 94046 : session_key = &conn->server->server_key;
190 : 94046 : }
191 : :
192 [ + + ]: 3612277 : if (s2n_is_tls13_plaintext_content(conn, content_type)) {
193 : 10167 : conn->client = current_client_crypto;
194 : 10167 : conn->server = current_server_crypto;
195 : 10167 : }
196 : :
197 : : /* The NULL stream cipher MUST NEVER be used for ApplicationData.
198 : : * If ApplicationData is unencrypted, we can't trust it. */
199 [ + + ]: 3612277 : if (cipher_suite->record_alg->cipher == &s2n_null_cipher) {
200 [ + - ][ + + ]: 76629 : POSIX_ENSURE(content_type != TLS_APPLICATION_DATA, S2N_ERR_DECRYPT);
201 : 76629 : }
202 : :
203 : 3611824 : switch (cipher_suite->record_alg->cipher->type) {
204 [ + + ]: 3386224 : case S2N_AEAD:
205 [ + + ]: 3386224 : POSIX_GUARD(s2n_record_parse_aead(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
206 : 193682 : break;
207 [ + + ]: 193682 : case S2N_CBC:
208 [ - + ]: 41812 : POSIX_GUARD(s2n_record_parse_cbc(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
209 : 41812 : break;
210 [ + + ]: 107612 : case S2N_COMPOSITE:
211 [ - + ]: 107612 : POSIX_GUARD(s2n_record_parse_composite(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
212 : 107612 : break;
213 [ + + ]: 107612 : case S2N_STREAM:
214 [ + + ]: 76176 : POSIX_GUARD(s2n_record_parse_stream(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
215 : 59998 : break;
216 [ - + ]: 59998 : default:
217 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_CIPHER_TYPE);
218 : 0 : break;
219 : 3611824 : }
220 : :
221 : 403104 : return 0;
222 : 3611824 : }
223 : :
224 : : int s2n_tls13_parse_record_type(struct s2n_stuffer *stuffer, uint8_t *record_type)
225 : 69200 : {
226 : 69200 : uint32_t bytes_left = s2n_stuffer_data_available(stuffer);
227 : :
228 : : /* From rfc8446 Section 5.4
229 : : * The presence of padding does not change the overall record size
230 : : * limitations: the full encoded TLSInnerPlaintext MUST NOT exceed 2^14
231 : : * + 1 octets
232 : : *
233 : : * Certain versions of Java can generate inner plaintexts with lengths up to
234 : : * S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH + 16 (See JDK-8221253)
235 : : * However, after the padding is stripped, the result will always be no more than
236 : : * S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH - 1
237 : : */
238 [ + + ][ + - ]: 69200 : S2N_ERROR_IF(bytes_left > S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH + 16, S2N_ERR_MAX_INNER_PLAINTEXT_SIZE);
239 : :
240 : : /* set cursor to the end of the stuffer */
241 [ - + ]: 69199 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, bytes_left));
242 : :
243 : : /* Record type should have values greater than zero.
244 : : * If zero, treat as padding, keep reading and wiping from the back
245 : : * until a non-zero value is found
246 : : */
247 : 69199 : *record_type = 0;
248 [ + + ]: 171215 : while (*record_type == 0) {
249 : : /* back the cursor by one to read off the last byte */
250 [ + + ]: 102020 : POSIX_GUARD(s2n_stuffer_rewind_read(stuffer, 1));
251 : :
252 : : /* set the record type */
253 [ - + ]: 102016 : POSIX_GUARD(s2n_stuffer_read_uint8(stuffer, record_type));
254 : :
255 : : /* wipe the last byte at the end of the stuffer */
256 [ - + ]: 102016 : POSIX_GUARD(s2n_stuffer_wipe_n(stuffer, 1));
257 : 102016 : }
258 : :
259 : : /* only the original plaintext should remain */
260 : : /* now reset the read cursor at where it should be */
261 [ - + ]: 69195 : POSIX_GUARD(s2n_stuffer_reread(stuffer));
262 : :
263 : : /* Even in the incorrect case above with up to 16 extra bytes, we should never see too much data after unpadding */
264 [ + + ][ + - ]: 69195 : S2N_ERROR_IF(s2n_stuffer_data_available(stuffer) > S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH - 1, S2N_ERR_MAX_INNER_PLAINTEXT_SIZE);
265 : :
266 : 69194 : return 0;
267 : 69195 : }
268 : :
269 : : S2N_RESULT s2n_record_wipe(struct s2n_connection *conn)
270 : 239493 : {
271 [ - + ][ # # ]: 239493 : RESULT_ENSURE_REF(conn);
272 [ - + ]: 239493 : RESULT_GUARD_POSIX(s2n_stuffer_wipe(&conn->header_in));
273 [ - + ]: 239493 : RESULT_GUARD_POSIX(s2n_stuffer_wipe(&conn->in));
274 : 239493 : conn->in_status = ENCRYPTED;
275 : :
276 : : /* Release the memory in conn->in, which un-taints buffer_in */
277 [ - + ]: 239493 : RESULT_GUARD_POSIX(s2n_stuffer_free(&conn->in));
278 : 239493 : conn->buffer_in.tainted = false;
279 : :
280 : : /* Reclaim any memory in buffer_in if possible.
281 : : * We want to avoid an expensive shift / copy later if possible.
282 : : */
283 [ + + ]: 239493 : if (s2n_stuffer_is_consumed(&conn->buffer_in)) {
284 [ - + ]: 238997 : RESULT_GUARD_POSIX(s2n_stuffer_rewrite(&conn->buffer_in));
285 : 238997 : }
286 : 239493 : return S2N_RESULT_OK;
287 : 239493 : }
|