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_server_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 : : * "A server which negotiates TLS 1.3 MUST respond by sending a 31 : : * "supported_versions" extension containing the selected version value 32 : : * (0x0304)." 33 : : * 34 : : * Structure: 35 : : * Extension type (2 bytes) 36 : : * Extension size (2 bytes) 37 : : * Selected Version (2 byte) 38 : : **/ 39 : : 40 : : static int s2n_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); 41 : : static int s2n_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); 42 : : 43 : : const s2n_extension_type s2n_server_supported_versions_extension = { 44 : : .iana_value = TLS_EXTENSION_SUPPORTED_VERSIONS, 45 : : .is_response = true, 46 : : .send = s2n_server_supported_versions_send, 47 : : .recv = s2n_server_supported_versions_recv, 48 : : .should_send = s2n_extension_send_if_tls13_connection, 49 : : .if_missing = s2n_extension_noop_if_missing, 50 : : }; 51 : : 52 : : static int s2n_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out) 53 : 5220 : { 54 [ - + ]: 5220 : POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->server_protocol_version / 10)); 55 [ - + ]: 5220 : POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->server_protocol_version % 10)); 56 : : 57 : 5220 : return S2N_SUCCESS; 58 : 5220 : } 59 : : 60 : : static int s2n_extensions_server_supported_versions_process(struct s2n_connection *conn, struct s2n_stuffer *extension) 61 : 5203 : { 62 : 5203 : uint8_t highest_supported_version = conn->client_protocol_version; 63 : 5203 : uint8_t minimum_supported_version = s2n_unknown_protocol_version; 64 [ - + ]: 5203 : POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version)); 65 [ + - ][ + + ]: 5203 : POSIX_ENSURE(highest_supported_version >= minimum_supported_version, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED); 66 : : 67 : 5202 : uint8_t server_version_parts[S2N_TLS_PROTOCOL_VERSION_LEN]; 68 [ + + ]: 5202 : POSIX_GUARD(s2n_stuffer_read_bytes(extension, server_version_parts, S2N_TLS_PROTOCOL_VERSION_LEN)); 69 : : 70 : 5200 : uint16_t server_version = (server_version_parts[0] * 10) + server_version_parts[1]; 71 : : 72 : : /** 73 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4 74 : : *# The value of selected_version in the HelloRetryRequest 75 : : *# "supported_versions" extension MUST be retained in the ServerHello, 76 : : *# and a client MUST abort the handshake with an "illegal_parameter" 77 : : *# alert if the value changes. 78 : : **/ 79 [ + + ][ + + ]: 5200 : if (s2n_is_hello_retry_handshake(conn) && !s2n_is_hello_retry_message(conn)) { 80 [ + + ][ + - ]: 640 : POSIX_ENSURE(conn->server_protocol_version == server_version, 81 : 640 : S2N_ERR_BAD_MESSAGE); 82 : 640 : } 83 : : 84 [ + - ][ + + ]: 5199 : POSIX_ENSURE_GTE(server_version, S2N_TLS13); 85 [ + + ][ + - ]: 5198 : POSIX_ENSURE_LTE(server_version, highest_supported_version); 86 [ - + ][ # # ]: 5197 : POSIX_ENSURE_GTE(server_version, minimum_supported_version); 87 : : 88 : 5197 : conn->server_protocol_version = server_version; 89 : : 90 : 5197 : return S2N_SUCCESS; 91 : 5197 : } 92 : : 93 : : static int s2n_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in) 94 : 5204 : { 95 [ + + ]: 5204 : if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { 96 : 1 : return S2N_SUCCESS; 97 : 1 : } 98 : : 99 [ + + ][ + - ]: 5203 : S2N_ERROR_IF(s2n_extensions_server_supported_versions_process(conn, in) < 0, S2N_ERR_BAD_MESSAGE); 100 : 5197 : return S2N_SUCCESS; 101 : 5203 : } 102 : : 103 : : /* Old-style extension functions -- remove after extensions refactor is complete */ 104 : : 105 : : int s2n_extensions_server_supported_versions_size(struct s2n_connection *conn) 106 : 2 : { 107 : 2 : return 6; 108 : 2 : } 109 : : 110 : : int s2n_extensions_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) 111 : 0 : { 112 : 0 : return s2n_extension_recv(&s2n_server_supported_versions_extension, conn, extension); 113 : 0 : }