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/extensions/s2n_client_supported_versions.h" 17 : : 18 : : #include <stdint.h> 19 : : 20 : : #include "tls/extensions/s2n_supported_versions.h" 21 : : #include "tls/s2n_alerts.h" 22 : : #include "tls/s2n_cipher_preferences.h" 23 : : #include "tls/s2n_tls.h" 24 : : #include "tls/s2n_tls_parameters.h" 25 : : #include "utils/s2n_safety.h" 26 : : 27 : : /** 28 : : * Specified in https://tools.ietf.org/html/rfc8446#section-4.2.1 29 : : * 30 : : * "The "supported_versions" extension is used by the client to indicate 31 : : * which versions of TLS it supports and by the server to indicate which 32 : : * version it is using. The extension contains a list of supported 33 : : * versions in preference order, with the most preferred version first." 34 : : * 35 : : * Structure: 36 : : * Extension type (2 bytes) 37 : : * Extension size (2 bytes) 38 : : * Version list length (1 byte) 39 : : * Version list (number of versions * 2 bytes) 40 : : * 41 : : * Note: We assume in these functions that the supported version numbers 42 : : * are consecutive. This is true because S2N does not support SSLv2, and 43 : : * is already an assumption made in the old client hello version handling. 44 : : **/ 45 : : 46 : : static int s2n_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); 47 : : static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); 48 : : 49 : : const s2n_extension_type s2n_client_supported_versions_extension = { 50 : : .iana_value = TLS_EXTENSION_SUPPORTED_VERSIONS, 51 : : .is_response = false, 52 : : .send = s2n_client_supported_versions_send, 53 : : .recv = s2n_client_supported_versions_recv, 54 : : .should_send = s2n_extension_send_if_tls13_connection, 55 : : .if_missing = s2n_extension_noop_if_missing, 56 : : }; 57 : : 58 : : static int s2n_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out) 59 : 5633 : { 60 : 5633 : uint8_t highest_supported_version = conn->client_protocol_version; 61 : 5633 : uint8_t minimum_supported_version = s2n_unknown_protocol_version; 62 [ - + ]: 5633 : POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version)); 63 [ - + ][ # # ]: 5633 : POSIX_ENSURE(highest_supported_version >= minimum_supported_version, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED); 64 : : 65 : 5633 : uint8_t version_list_length = highest_supported_version - minimum_supported_version + 1; 66 [ - + ]: 5633 : POSIX_GUARD(s2n_stuffer_write_uint8(out, version_list_length * S2N_TLS_PROTOCOL_VERSION_LEN)); 67 : : 68 [ + + ]: 20853 : for (uint8_t i = highest_supported_version; i >= minimum_supported_version; i--) { 69 [ - + ]: 15220 : POSIX_GUARD(s2n_stuffer_write_uint8(out, i / 10)); 70 [ - + ]: 15220 : POSIX_GUARD(s2n_stuffer_write_uint8(out, i % 10)); 71 : 15220 : } 72 : : 73 : 5633 : return S2N_SUCCESS; 74 : 5633 : } 75 : : 76 : : int s2n_extensions_client_supported_versions_process(struct s2n_connection *conn, struct s2n_stuffer *extension, 77 : : uint8_t *client_protocol_version_out, uint8_t *actual_protocol_version_out) 78 : 5318 : { 79 : 5318 : uint8_t highest_supported_version = conn->server_protocol_version; 80 : 5318 : uint8_t minimum_supported_version = s2n_unknown_protocol_version; 81 [ - + ]: 5318 : POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version)); 82 : : 83 : 5318 : uint8_t size_of_version_list = 0; 84 [ - + ]: 5318 : POSIX_GUARD(s2n_stuffer_read_uint8(extension, &size_of_version_list)); 85 [ + + ][ + - ]: 5318 : S2N_ERROR_IF(size_of_version_list != s2n_stuffer_data_available(extension), S2N_ERR_BAD_MESSAGE); 86 [ + + ][ + - ]: 5311 : S2N_ERROR_IF(size_of_version_list % S2N_TLS_PROTOCOL_VERSION_LEN != 0, S2N_ERR_BAD_MESSAGE); 87 : : 88 : 5310 : uint8_t client_protocol_version = s2n_unknown_protocol_version; 89 : 5310 : uint8_t actual_protocol_version = s2n_unknown_protocol_version; 90 : : 91 [ + + ]: 18885 : for (int i = 0; i < size_of_version_list; i += S2N_TLS_PROTOCOL_VERSION_LEN) { 92 : 13575 : uint8_t client_version_parts[S2N_TLS_PROTOCOL_VERSION_LEN]; 93 [ - + ]: 13575 : POSIX_GUARD(s2n_stuffer_read_bytes(extension, client_version_parts, S2N_TLS_PROTOCOL_VERSION_LEN)); 94 : : 95 : : /* If the client version is outside of our supported versions, then ignore the value. 96 : : * S2N does not support SSLv2 except for upgrading connections. Since this extension is 97 : : * a TLS1.3 extension, we will skip any SSLv2 values. */ 98 [ + + ][ + + ]: 13575 : if (client_version_parts[0] != 3 || client_version_parts[1] > 4) { 99 : 35 : continue; 100 : 35 : } 101 : : 102 : 13540 : uint16_t client_version = (client_version_parts[0] * 10) + client_version_parts[1]; 103 : : 104 [ + + ]: 13540 : client_protocol_version = S2N_MAX(client_version, client_protocol_version); 105 : : 106 [ + + ]: 13540 : if (client_version > highest_supported_version) { 107 : 4 : continue; 108 : 4 : } 109 : : 110 [ + + ]: 13536 : if (client_version < minimum_supported_version) { 111 : 2655 : continue; 112 : 2655 : } 113 : : 114 : : /* We ignore the client's preferred order and instead choose 115 : : * the highest version that both client and server support. */ 116 [ + + ]: 10881 : actual_protocol_version = S2N_MAX(client_version, actual_protocol_version); 117 : 10881 : } 118 : : 119 : 5310 : *client_protocol_version_out = client_protocol_version; 120 : 5310 : *actual_protocol_version_out = actual_protocol_version; 121 : : 122 : 5310 : return S2N_SUCCESS; 123 : 5310 : } 124 : : 125 : : static S2N_RESULT s2n_client_supported_versions_recv_impl(struct s2n_connection *conn, struct s2n_stuffer *extension) 126 : 5290 : { 127 [ # # ][ - + ]: 5290 : RESULT_ENSURE_REF(conn); 128 [ # # ][ - + ]: 5290 : RESULT_ENSURE_REF(extension); 129 : : 130 [ + + ]: 5290 : RESULT_GUARD_POSIX(s2n_extensions_client_supported_versions_process(conn, extension, &conn->client_protocol_version, 131 : 5286 : &conn->actual_protocol_version)); 132 : : 133 [ + + ][ + - ]: 5286 : RESULT_ENSURE(conn->client_protocol_version != s2n_unknown_protocol_version, S2N_ERR_UNKNOWN_PROTOCOL_VERSION); 134 [ + - ][ + + ]: 5284 : RESULT_ENSURE(conn->actual_protocol_version != s2n_unknown_protocol_version, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED); 135 : : 136 : 5280 : return S2N_RESULT_OK; 137 : 5284 : } 138 : : 139 : : static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) 140 : 5683 : { 141 : : /* For backwards compatibility, the supported versions extension isn't used for protocol 142 : : * version selection if the server doesn't support TLS 1.3. This ensures that TLS 1.2 servers 143 : : * experience no behavior change due to processing the TLS 1.3 extension. See 144 : : * https://github.com/aws/s2n-tls/issues/4240. 145 : : * 146 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.1 147 : : *= type=exception 148 : : *= reason=The client hello legacy version is used for version selection on TLS 1.2 servers for backwards compatibility 149 : : *# If this extension is present in the ClientHello, servers MUST NOT use 150 : : *# the ClientHello.legacy_version value for version negotiation and MUST 151 : : *# use only the "supported_versions" extension to determine client 152 : : *# preferences. 153 : : */ 154 [ + + ]: 5683 : if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { 155 : 393 : return S2N_SUCCESS; 156 : 393 : } 157 : : 158 : : /* A TLS 1.3 state machine flag is used to determine if a HelloRetryRequest is negotiated. A 159 : : * protocol version of TLS 1.3 must be set in order to query the TLS 1.3 state machine, so 160 : : * it must be queried before the protocol version is potentially reset due to processing the 161 : : * extension. 162 : : */ 163 : 5290 : bool is_hrr_handshake = s2n_is_hello_retry_handshake(conn); 164 : : 165 : 5290 : s2n_result result = s2n_client_supported_versions_recv_impl(conn, extension); 166 [ + + ]: 5290 : if (s2n_result_is_error(result)) { 167 : 10 : conn->client_protocol_version = s2n_unknown_protocol_version; 168 : 10 : conn->actual_protocol_version = s2n_unknown_protocol_version; 169 : : 170 : 10 : s2n_queue_reader_unsupported_protocol_version_alert(conn); 171 [ - + ][ # # ]: 10 : POSIX_ENSURE(s2n_errno != S2N_ERR_SAFETY, S2N_ERR_BAD_MESSAGE); 172 : 10 : } 173 [ + + ]: 5290 : POSIX_GUARD_RESULT(result); 174 : : 175 : : /* When the supported versions extension is received in a ClientHello sent in response to a 176 : : * HelloRetryRequest, ensure that TLS 1.3 is selected as the protocol version. 177 : : */ 178 [ + + ][ + - ]: 5280 : if (is_hrr_handshake && conn->handshake.message_number > 0) { 179 [ + + ][ + - ]: 652 : POSIX_ENSURE(conn->client_protocol_version == S2N_TLS13, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED); 180 [ # # ][ - + ]: 648 : POSIX_ENSURE(conn->actual_protocol_version == S2N_TLS13, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED); 181 : 648 : } 182 : : 183 : 5276 : return S2N_SUCCESS; 184 : 5280 : } 185 : : 186 : : /* Old-style extension functions -- remove after extensions refactor is complete */ 187 : : 188 : : int s2n_extensions_client_supported_versions_size(struct s2n_connection *conn) 189 : 1 : { 190 : 1 : uint8_t minimum_supported_version = s2n_unknown_protocol_version; 191 [ - + ]: 1 : POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version)); 192 : 1 : uint8_t highest_supported_version = conn->client_protocol_version; 193 : : 194 : 1 : uint8_t version_list_length = highest_supported_version - minimum_supported_version + 1; 195 : : 196 : 1 : return version_list_length * S2N_TLS_PROTOCOL_VERSION_LEN + 5; 197 : 1 : } 198 : : 199 : : /* still used in fuzz test */ 200 : : int s2n_extensions_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) 201 : 0 : { 202 : 0 : return s2n_extension_recv(&s2n_client_supported_versions_extension, conn, extension); 203 : 0 : }