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