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 <stdint.h>
17 : :
18 : : #include "error/s2n_errno.h"
19 : : #include "stuffer/s2n_stuffer.h"
20 : : #include "tls/s2n_cipher_suites.h"
21 : : #include "tls/s2n_connection.h"
22 : : #include "tls/s2n_record.h"
23 : : #include "tls/s2n_tls.h"
24 : : #include "utils/s2n_map.h"
25 : : #include "utils/s2n_safety.h"
26 : :
27 : : int s2n_handshake_write_header(struct s2n_stuffer *out, uint8_t message_type)
28 : 46052 : {
29 [ - + ][ # # ]: 46052 : S2N_ERROR_IF(s2n_stuffer_data_available(out), S2N_ERR_HANDSHAKE_STATE);
30 : :
31 : : /* Write the message header */
32 [ - + ]: 46052 : POSIX_GUARD(s2n_stuffer_write_uint8(out, message_type));
33 : :
34 : : /* Leave the length blank for now */
35 : 46052 : uint16_t length = 0;
36 [ - + ]: 46052 : POSIX_GUARD(s2n_stuffer_write_uint24(out, length));
37 : :
38 : 46052 : return S2N_SUCCESS;
39 : 46052 : }
40 : :
41 : : int s2n_handshake_finish_header(struct s2n_stuffer *out)
42 : 49322 : {
43 : 49322 : uint32_t length = s2n_stuffer_data_available(out);
44 [ - + ][ # # ]: 49322 : S2N_ERROR_IF(length < TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_SIZE_MISMATCH);
45 : :
46 : 49322 : uint32_t payload = length - TLS_HANDSHAKE_HEADER_LENGTH;
47 : :
48 : : /* Write the message header */
49 [ - + ]: 49322 : POSIX_GUARD(s2n_stuffer_rewrite(out));
50 [ - + ]: 49322 : POSIX_GUARD(s2n_stuffer_skip_write(out, 1));
51 [ + + ]: 49322 : POSIX_GUARD(s2n_stuffer_write_uint24(out, payload));
52 [ - + ]: 49321 : POSIX_GUARD(s2n_stuffer_skip_write(out, payload));
53 : :
54 : 49321 : return S2N_SUCCESS;
55 : 49321 : }
56 : :
57 : : S2N_RESULT s2n_handshake_parse_header(struct s2n_stuffer *io, uint8_t *message_type, uint32_t *length)
58 : 77957 : {
59 [ # # ][ - + ]: 77957 : RESULT_ENSURE(s2n_stuffer_data_available(io) >= TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_SIZE_MISMATCH);
60 : :
61 : : /* read the message header */
62 [ - + ]: 77957 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(io, message_type));
63 [ - + ]: 77957 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint24(io, length));
64 : :
65 : 77957 : return S2N_RESULT_OK;
66 : 77957 : }
67 : :
68 : : static int s2n_handshake_get_hash_state_ptr(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state **hash_state)
69 : 53740 : {
70 [ - + ][ # # ]: 53740 : POSIX_ENSURE_REF(conn);
71 [ # # ][ - + ]: 53740 : POSIX_ENSURE_REF(conn->handshake.hashes);
72 : :
73 : 53740 : switch (hash_alg) {
74 [ + + ]: 541 : case S2N_HASH_MD5:
75 : 541 : *hash_state = &conn->handshake.hashes->md5;
76 : 541 : break;
77 [ + + ]: 541 : case S2N_HASH_SHA1:
78 : 541 : *hash_state = &conn->handshake.hashes->sha1;
79 : 541 : break;
80 [ - + ]: 0 : case S2N_HASH_SHA224:
81 : 0 : *hash_state = &conn->handshake.hashes->sha224;
82 : 0 : break;
83 [ + + ]: 51373 : case S2N_HASH_SHA256:
84 : 51373 : *hash_state = &conn->handshake.hashes->sha256;
85 : 51373 : break;
86 [ + + ]: 1284 : case S2N_HASH_SHA384:
87 : 1284 : *hash_state = &conn->handshake.hashes->sha384;
88 : 1284 : break;
89 [ - + ]: 0 : case S2N_HASH_SHA512:
90 : 0 : *hash_state = &conn->handshake.hashes->sha512;
91 : 0 : break;
92 [ + + ]: 1 : case S2N_HASH_MD5_SHA1:
93 : 1 : *hash_state = &conn->handshake.hashes->md5_sha1;
94 : 1 : break;
95 [ - + ]: 0 : default:
96 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_HASH_INVALID_ALGORITHM);
97 : 0 : break;
98 : 53740 : }
99 : :
100 : 53740 : return S2N_SUCCESS;
101 : 53740 : }
102 : :
103 : : S2N_RESULT s2n_handshake_reset_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg)
104 : 1306 : {
105 : 1306 : struct s2n_hash_state *hash_state = NULL;
106 [ - + ]: 1306 : RESULT_GUARD_POSIX(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state));
107 [ - + ]: 1306 : RESULT_GUARD_POSIX(s2n_hash_reset(hash_state));
108 : 1306 : return S2N_RESULT_OK;
109 : 1306 : }
110 : :
111 : : S2N_RESULT s2n_handshake_copy_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state *copy)
112 : 52434 : {
113 : 52434 : struct s2n_hash_state *hash_state = NULL;
114 [ - + ]: 52434 : RESULT_GUARD_POSIX(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state));
115 [ - + ]: 52434 : RESULT_GUARD_POSIX(s2n_hash_copy(copy, hash_state));
116 : 52434 : return S2N_RESULT_OK;
117 : 52434 : }
118 : :
119 : : int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake)
120 : 3424789 : {
121 : 3424789 : memset(handshake->required_hash_algs, 1, sizeof(handshake->required_hash_algs));
122 : 3424789 : return S2N_SUCCESS;
123 : 3424789 : }
124 : :
125 : : static int s2n_handshake_require_hash(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg)
126 : 12836 : {
127 : 12836 : handshake->required_hash_algs[hash_alg] = 1;
128 : 12836 : return S2N_SUCCESS;
129 : 12836 : }
130 : :
131 : : uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg)
132 : 662918 : {
133 : 662918 : return handshake->required_hash_algs[hash_alg];
134 : 662918 : }
135 : :
136 : : /* Update the required handshake hash algs depending on current handshake session state.
137 : : * This function must called at the end of a handshake message handler. Additionally it must be called after the
138 : : * ClientHello or ServerHello is processed in client and server mode respectively. The relevant handshake parameters
139 : : * are not available until those messages are processed.
140 : : */
141 : : int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn)
142 : 14960 : {
143 [ - + ][ # # ]: 14960 : POSIX_ENSURE_REF(conn);
144 [ - + ][ # # ]: 14960 : POSIX_ENSURE_REF(conn->secure);
145 : :
146 : : /* Clear all of the required hashes */
147 : 14960 : memset(conn->handshake.required_hash_algs, 0, sizeof(conn->handshake.required_hash_algs));
148 : :
149 [ + + ]: 14960 : if (conn->actual_protocol_version < S2N_TLS13) {
150 : 4907 : message_type_t handshake_message = s2n_conn_get_current_message_type(conn);
151 [ + + ]: 4907 : const uint8_t client_cert_verify_done = (handshake_message >= CLIENT_CERT_VERIFY) ? 1 : 0;
152 : 4907 : s2n_cert_auth_type client_cert_auth_type = 0;
153 [ - + ]: 4907 : POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
154 : :
155 : : /* In TLS1.2 the transcript hash used in the client's certificate verify message
156 : : * is determined by the signature algorithm used to sign the certificate verify message.
157 : : * Therefore all hashes are needed until we're past CLIENT_CERT_VERIFY if client auth is possible. */
158 [ + + ][ + + ]: 4907 : if ((client_cert_auth_type != S2N_CERT_AUTH_NONE) && !client_cert_verify_done) {
159 [ - + ]: 2435 : POSIX_GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
160 : 2435 : return S2N_SUCCESS;
161 : 2435 : }
162 : 4907 : }
163 : :
164 : : /* We don't need all of the hashes. Set the hash alg(s) required for the PRF */
165 : 12525 : switch (conn->actual_protocol_version) {
166 [ + + ]: 111 : case S2N_SSLv3:
167 [ + + ]: 212 : case S2N_TLS10:
168 [ + + ]: 312 : case S2N_TLS11:
169 [ - + ]: 312 : POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_MD5));
170 [ - + ]: 312 : POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_SHA1));
171 : 312 : break;
172 [ + + ]: 2160 : case S2N_TLS12:
173 : : /* fall through */
174 [ + + ]: 12212 : case S2N_TLS13: {
175 : : /* For TLS 1.2 and TLS 1.3, the cipher suite defines the PRF hash alg */
176 : 12212 : s2n_hmac_algorithm prf_alg = conn->secure->cipher_suite->prf_alg;
177 : 12212 : s2n_hash_algorithm hash_alg = 0;
178 [ - + ]: 12212 : POSIX_GUARD(s2n_hmac_hash_alg(prf_alg, &hash_alg));
179 [ - + ]: 12212 : POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, hash_alg));
180 : 12212 : break;
181 : 12212 : }
182 [ + + ]: 12212 : default:
183 : : /* actual_protocol_version is a uint8_t, not an enum, so -Wswitch
184 : : * cannot enforce exhaustiveness. Fail closed: an unknown version
185 : : * must not silently skip setting the PRF hash requirement. This path
186 : : * is currently unreachable (the handshake sets the version to one of
187 : : * the five known values), but serves as defense-in-depth against
188 : : * internal state corruption. */
189 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_SAFETY);
190 : 12525 : }
191 : :
192 : 12524 : return S2N_SUCCESS;
193 : 12525 : }
194 : :
195 : : /*
196 : : * Take a hostname and return a single "simple" wildcard domain name that matches it.
197 : : * The output wildcard representation is meant to be compared directly against a wildcard domain in a certificate.
198 : : * We take a restrictive definition of wildcard here to achieve a single unique wildcard representation
199 : : * given any input hostname.
200 : : * No embedded or trailing wildcards are supported. Additionally, we only support one level of wildcard matching.
201 : : * Thus the output should be a single wildcard character in the first(left-most) DNS label.
202 : : *
203 : : * Example:
204 : : * - my.domain.name -> *.domain.name
205 : : *
206 : : * Not supported:
207 : : * - my.domain.name -> m*.domain.name
208 : : * - my.domain.name -> my.*.name
209 : : * etc.
210 : : *
211 : : * The motivation for using a constrained definition of wildcard:
212 : : * - Support for issuing non-simple wildcard certificates is insignificant.
213 : : * - Certificate selection can be implemented with a constant number of lookups(two).
214 : : */
215 : : int s2n_create_wildcard_hostname(struct s2n_stuffer *hostname_stuffer, struct s2n_stuffer *output)
216 : 67 : {
217 : : /* Find the end of the first label */
218 [ - + ]: 67 : POSIX_GUARD(s2n_stuffer_skip_to_char(hostname_stuffer, '.'));
219 : :
220 : : /* No first label found */
221 [ + + ]: 67 : if (s2n_stuffer_data_available(hostname_stuffer) == 0) {
222 : 21 : return S2N_SUCCESS;
223 : 21 : }
224 : :
225 : : /* Slap a single wildcard character to be the first label in output */
226 [ - + ]: 46 : POSIX_GUARD(s2n_stuffer_write_uint8(output, '*'));
227 : :
228 : : /* Simply copy the rest of the input to the output. */
229 [ - + ]: 46 : POSIX_GUARD(s2n_stuffer_copy(hostname_stuffer, output, s2n_stuffer_data_available(hostname_stuffer)));
230 : :
231 : 46 : return S2N_SUCCESS;
232 : 46 : }
233 : :
234 : : static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map,
235 : : struct s2n_blob *dns_name,
236 : : struct s2n_cert_chain_and_key *matches[S2N_CERT_TYPE_COUNT],
237 : : uint8_t *match_exists)
238 : 259 : {
239 : 259 : struct s2n_blob map_value = { 0 };
240 : 259 : bool key_found = false;
241 [ - + ]: 259 : POSIX_GUARD_RESULT(s2n_map_lookup(domain_name_to_cert_map, dns_name, &map_value, &key_found));
242 [ + + ]: 259 : if (key_found) {
243 : 161 : struct certs_by_type *value = (void *) map_value.data;
244 [ + + ]: 805 : for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
245 : 644 : matches[i] = value->certs[i];
246 : 644 : }
247 : 161 : *match_exists = 1;
248 : 161 : }
249 : :
250 : 259 : return S2N_SUCCESS;
251 : 259 : }
252 : :
253 : : /* Find certificates that match the ServerName TLS extension sent by the client.
254 : : * For a given ServerName there can be multiple matching certificates based on the
255 : : * type of key in the certificate.
256 : : *
257 : : * A match is determined using s2n_map lookup by DNS name.
258 : : * Wildcards that have a single * in the left most label are supported.
259 : : */
260 : : int s2n_conn_find_name_matching_certs(struct s2n_connection *conn)
261 : 7885 : {
262 [ + + ]: 7885 : if (!s2n_server_received_server_name(conn)) {
263 : 7666 : return S2N_SUCCESS;
264 : 7666 : }
265 : 219 : const char *name = conn->server_name;
266 : 219 : struct s2n_blob hostname_blob = { 0 };
267 [ - + ]: 219 : POSIX_GUARD(s2n_blob_init(&hostname_blob, (uint8_t *) (uintptr_t) name, strlen(name)));
268 [ - + ][ # # ]: 219 : POSIX_ENSURE_LTE(hostname_blob.size, S2N_MAX_SERVER_NAME);
269 : 219 : char normalized_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 };
270 [ - + ][ # # ]: 219 : POSIX_CHECKED_MEMCPY(normalized_hostname, hostname_blob.data, hostname_blob.size);
[ + - ]
271 : 219 : struct s2n_blob normalized_name = { 0 };
272 [ - + ]: 219 : POSIX_GUARD(s2n_blob_init(&normalized_name, (uint8_t *) normalized_hostname, hostname_blob.size));
273 : :
274 [ - + ]: 219 : POSIX_GUARD(s2n_blob_char_to_lower(&normalized_name));
275 : 219 : struct s2n_stuffer normalized_hostname_stuffer = { 0 };
276 [ - + ]: 219 : POSIX_GUARD(s2n_stuffer_init(&normalized_hostname_stuffer, &normalized_name));
277 [ - + ]: 219 : POSIX_GUARD(s2n_stuffer_skip_write(&normalized_hostname_stuffer, normalized_name.size));
278 : :
279 : : /* Find the exact matches for the ServerName */
280 [ - + ]: 219 : POSIX_GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
281 : 219 : &normalized_name,
282 : 219 : conn->handshake_params.exact_sni_matches,
283 : 219 : &(conn->handshake_params.exact_sni_match_exists)));
284 : :
285 [ + + ]: 219 : if (!conn->handshake_params.exact_sni_match_exists) {
286 : : /* We have not yet found an exact domain match. Try to find wildcard matches. */
287 : 59 : char wildcard_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 };
288 : 59 : struct s2n_blob wildcard_blob = { 0 };
289 [ - + ]: 59 : POSIX_GUARD(s2n_blob_init(&wildcard_blob, (uint8_t *) wildcard_hostname, sizeof(wildcard_hostname)));
290 : 59 : struct s2n_stuffer wildcard_stuffer = { 0 };
291 [ - + ]: 59 : POSIX_GUARD(s2n_stuffer_init(&wildcard_stuffer, &wildcard_blob));
292 [ - + ]: 59 : POSIX_GUARD(s2n_create_wildcard_hostname(&normalized_hostname_stuffer, &wildcard_stuffer));
293 : 59 : const uint32_t wildcard_len = s2n_stuffer_data_available(&wildcard_stuffer);
294 : :
295 : : /* Couldn't create a valid wildcard from the input */
296 [ + + ]: 59 : if (wildcard_len == 0) {
297 : 19 : return S2N_SUCCESS;
298 : 19 : }
299 : :
300 : : /* The client's SNI is wildcardified, do an exact match against the set of server certs. */
301 : 40 : wildcard_blob.size = wildcard_len;
302 [ - + ]: 40 : POSIX_GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
303 : 40 : &wildcard_blob,
304 : 40 : conn->handshake_params.wc_sni_matches,
305 : 40 : &(conn->handshake_params.wc_sni_match_exists)));
306 : 40 : }
307 : :
308 : : /* If we found a suitable cert, we should send back the ServerName extension.
309 : : * Note that this may have already been set by the client hello callback, so we won't override its value
310 : : */
311 [ + + ]: 200 : conn->server_name_used = conn->server_name_used
312 [ + + ]: 200 : || conn->handshake_params.exact_sni_match_exists
313 [ + + ]: 200 : || conn->handshake_params.wc_sni_match_exists;
314 : :
315 : 200 : return S2N_SUCCESS;
316 : 219 : }
317 : :
318 : : /* Find the optimal certificate of a specific type.
319 : : * The priority of set of certificates to choose from:
320 : : * 1. Certificates that match the client's ServerName extension.
321 : : * 2. Default certificates
322 : : */
323 : : struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type)
324 : 45008 : {
325 [ + + ]: 45008 : if (conn->handshake_params.exact_sni_match_exists) {
326 : : /* This may return NULL if there was an SNI match, but not a match the cipher_suite's authentication type. */
327 : 1118 : return conn->handshake_params.exact_sni_matches[cert_type];
328 : 1118 : }
329 [ + + ]: 43890 : if (conn->handshake_params.wc_sni_match_exists) {
330 : 13 : return conn->handshake_params.wc_sni_matches[cert_type];
331 : 43877 : } else {
332 : : /* We don't have any name matches. Use the default certificate that works with the key type. */
333 : 43877 : return conn->config->default_certs_by_type.certs[cert_type];
334 : 43877 : }
335 : 43890 : }
336 : :
337 : : /* This method will work when testing S2N, and for the EndOfEarlyData message.
338 : : *
339 : : * However, it will NOT work for arbitrary message types when potentially receiving records
340 : : * that contain multiple messages, like when talking to a non-S2N TLS implementation. If the "end_message"
341 : : * is not the first message in a multi-message record, negotiation will not stop.
342 : : * (This is not an issue for EndOfEarlyData because encryption and message order requirements force
343 : : * EndOfEarlyData to always be the first and only handshake message in its handshake record)
344 : : */
345 : : S2N_RESULT s2n_negotiate_until_message(struct s2n_connection *conn, s2n_blocked_status *blocked, message_type_t end_message)
346 : 7107 : {
347 [ + + ][ + - ]: 7107 : RESULT_ENSURE_REF(conn);
348 : 7106 : conn->handshake.end_of_messages = end_message;
349 : 7106 : int r = s2n_negotiate(conn, blocked);
350 : 7106 : conn->handshake.end_of_messages = APPLICATION_DATA;
351 [ + + ]: 7106 : RESULT_GUARD_POSIX(r);
352 : 5350 : return S2N_RESULT_OK;
353 : 7106 : }
354 : :
355 : : S2N_RESULT s2n_handshake_validate(const struct s2n_handshake *s2n_handshake)
356 : 49814 : {
357 [ - + ][ # # ]: 49814 : RESULT_ENSURE_REF(s2n_handshake);
358 [ # # ][ - + ]: 49814 : RESULT_DEBUG_ENSURE(s2n_handshake->handshake_type < 256, S2N_ERR_SAFETY);
359 [ # # ][ - + ]: 49814 : RESULT_DEBUG_ENSURE(s2n_handshake->message_number >= 0 && s2n_handshake->message_number < 32, S2N_ERR_SAFETY);
[ + - ][ + - ]
360 : 49814 : return S2N_RESULT_OK;
361 : 49814 : }
362 : :
363 : : S2N_RESULT s2n_handshake_set_finished_len(struct s2n_connection *conn, uint8_t len)
364 : 25390 : {
365 [ + - ][ + + ]: 25390 : RESULT_ENSURE_REF(conn);
366 [ + + ][ + - ]: 25389 : RESULT_ENSURE_GT(len, 0);
367 [ + - ][ + + ]: 25388 : RESULT_ENSURE_LTE(len, sizeof(conn->handshake.server_finished));
368 [ - + ][ # # ]: 25386 : RESULT_ENSURE_LTE(len, sizeof(conn->handshake.client_finished));
369 : :
370 : : /*
371 : : * We maintain a version of the "finished" / "verify_data" field
372 : : * for both the client and server, so this method will be called
373 : : * once for the client version and once for the server version.
374 : : *
375 : : * The lengths of both versions must match, or something has
376 : : * gone wrong in our implementation.
377 : : */
378 : 25386 : uint8_t *finished_length = &conn->handshake.finished_len;
379 [ + + ]: 25386 : if (*finished_length == 0) {
380 : 12732 : *finished_length = len;
381 : 12732 : }
382 [ + - ][ + + ]: 25386 : RESULT_ENSURE_EQ(*finished_length, len);
383 : :
384 : 25383 : return S2N_RESULT_OK;
385 : 25386 : }
386 : :
387 : : bool s2n_handshake_is_renegotiation(struct s2n_connection *conn)
388 : 35891 : {
389 [ + - ][ + + ]: 35891 : return conn && conn->handshake.renegotiation;
390 : 35891 : }
|