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