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