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_extension_type.h" 17 : : 18 : : #include "api/s2n.h" 19 : : #include "error/s2n_errno.h" 20 : : #include "tls/s2n_connection.h" 21 : : #include "tls/s2n_tls13.h" 22 : : #include "utils/s2n_bitmap.h" 23 : : #include "utils/s2n_safety.h" 24 : : 25 : : #define TLS_EXTENSION_DATA_LENGTH_BYTES 2 26 : : 27 : : /* Because there are 65536 possible extension IANAs, we will only 28 : : * put the lowest (and most common) in a lookup table to conserve space. */ 29 : 759331 : #define S2N_MAX_INDEXED_EXTENSION_IANA 60 30 : : 31 : : const s2n_extension_type_id s2n_unsupported_extension = S2N_SUPPORTED_EXTENSIONS_COUNT; 32 : : s2n_extension_type_id s2n_extension_ianas_to_ids[S2N_MAX_INDEXED_EXTENSION_IANA]; 33 : : 34 : : int s2n_extension_type_init() 35 : 545 : { 36 : : /* Initialize to s2n_unsupported_extension */ 37 [ + + ]: 33245 : for (size_t i = 0; i < S2N_MAX_INDEXED_EXTENSION_IANA; i++) { 38 : 32700 : s2n_extension_ianas_to_ids[i] = s2n_unsupported_extension; 39 : 32700 : } 40 : : 41 : : /* Reverse the mapping */ 42 [ + + ]: 11990 : for (size_t i = 0; i < S2N_SUPPORTED_EXTENSIONS_COUNT; i++) { 43 : 11445 : uint16_t iana_value = s2n_supported_extensions[i]; 44 [ + + ]: 11445 : if (iana_value < S2N_MAX_INDEXED_EXTENSION_IANA) { 45 : 9810 : s2n_extension_ianas_to_ids[iana_value] = i; 46 : 9810 : } 47 : 11445 : } 48 : : 49 : 545 : return S2N_SUCCESS; 50 : 545 : } 51 : : 52 : : /* Convert the IANA value (which ranges from 0->65535) to an id with a more 53 : : * constrained range. That id can be used for bitfields, array indexes, etc. 54 : : * to avoid allocating too much memory. */ 55 : : s2n_extension_type_id s2n_extension_iana_value_to_id(const uint16_t iana_value) 56 : 714641 : { 57 : : /* Check the lookup table */ 58 [ + + ]: 714641 : if (iana_value < S2N_MAX_INDEXED_EXTENSION_IANA) { 59 : 631166 : return s2n_extension_ianas_to_ids[iana_value]; 60 : 631166 : } 61 : : 62 : : /* Fall back to the full list. We can handle this more 63 : : * efficiently later if our extension list gets long. */ 64 [ + + ]: 670636 : for (size_t i = 0; i < S2N_SUPPORTED_EXTENSIONS_COUNT; i++) { 65 [ + + ]: 670097 : if (s2n_supported_extensions[i] == iana_value) { 66 : 82936 : return i; 67 : 82936 : } 68 : 670097 : } 69 : : 70 : 539 : return s2n_unsupported_extension; 71 : 83475 : } 72 : : 73 : : int s2n_extension_supported_iana_value_to_id(const uint16_t iana_value, s2n_extension_type_id *internal_id) 74 : 714593 : { 75 [ # # ][ - + ]: 714593 : POSIX_ENSURE_REF(internal_id); 76 : : 77 : 714593 : *internal_id = s2n_extension_iana_value_to_id(iana_value); 78 [ + + ][ + - ]: 714593 : S2N_ERROR_IF(*internal_id == s2n_unsupported_extension, S2N_ERR_UNRECOGNIZED_EXTENSION); 79 : 714014 : return S2N_SUCCESS; 80 : 714593 : } 81 : : 82 : : int s2n_extension_send(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *out) 83 : 215388 : { 84 [ + - ][ + + ]: 215388 : POSIX_ENSURE_REF(extension_type); 85 [ + - ][ + + ]: 215387 : POSIX_ENSURE_REF(extension_type->should_send); 86 [ + - ][ + + ]: 215386 : POSIX_ENSURE_REF(extension_type->send); 87 [ + + ][ + - ]: 215385 : POSIX_ENSURE_REF(conn); 88 : : 89 : 215384 : s2n_extension_type_id extension_id = 0; 90 [ - + ]: 215384 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id)); 91 : : 92 : : /* Do not send response if request not received. */ 93 [ + + ][ + + ]: 215384 : if (extension_type->is_response && !S2N_CBIT_TEST(conn->extension_requests_received, extension_id)) { 94 : 52624 : return S2N_SUCCESS; 95 : 52624 : } 96 : : 97 : : /* Do not send an extension that is not valid for the protocol version */ 98 [ + + ]: 162760 : if (extension_type->minimum_version > conn->actual_protocol_version) { 99 : 8182 : return S2N_SUCCESS; 100 : 8182 : } 101 : : 102 : : /* Check if we need to send. Some extensions are only sent if specific conditions are met. */ 103 [ + + ]: 154578 : if (!extension_type->should_send(conn)) { 104 : 96586 : return S2N_SUCCESS; 105 : 96586 : } 106 : : 107 : : /* Write extension type */ 108 [ + + ]: 57992 : POSIX_GUARD(s2n_stuffer_write_uint16(out, extension_type->iana_value)); 109 : : 110 : : /* Reserve space for extension size */ 111 : 57989 : struct s2n_stuffer_reservation extension_size_bytes = { 0 }; 112 [ - + ]: 57989 : POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &extension_size_bytes)); 113 : : 114 : : /* Write extension data */ 115 [ + + ]: 57989 : POSIX_GUARD(extension_type->send(conn, out)); 116 : : 117 : : /** 118 : : * Reset the tainted flag in the out stuffer (handshake.io stuffer). 119 : : * 120 : : * Some extension send functions call s2n_stuffer_raw_write(), which 121 : : * makes the stuffer tainted, preventing further resizing of the handshake.io stuffer. 122 : : * We need to reset this flag after each extension is sent, because handshake.io 123 : : * might need to be resized to send subsequent extensions. 124 : : * 125 : : * This is safe because the outstanding pointer from s2n_stuffer_raw_write() is scoped to 126 : : * the send function of each extension, and it is never stored in s2n_connection. 127 : : */ 128 : 57984 : out->tainted = false; 129 : : 130 : : /* Record extension size */ 131 [ + + ]: 57984 : POSIX_GUARD(s2n_stuffer_write_vector_size(&extension_size_bytes)); 132 : : 133 : : /* Set request bit flag */ 134 [ + + ]: 57983 : if (!extension_type->is_response) { 135 : 43801 : S2N_CBIT_SET(conn->extension_requests_sent, extension_id); 136 : 43801 : } 137 : : 138 : 57983 : return S2N_SUCCESS; 139 : 57984 : } 140 : : 141 : : int s2n_extension_recv(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *in) 142 : 57824 : { 143 [ + + ][ + - ]: 57824 : POSIX_ENSURE_REF(extension_type); 144 [ + - ][ + + ]: 57823 : POSIX_ENSURE_REF(extension_type->recv); 145 [ + + ][ + - ]: 57822 : POSIX_ENSURE_REF(conn); 146 : : 147 : 57821 : s2n_extension_type_id extension_id = 0; 148 [ - + ]: 57821 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id)); 149 : : 150 : : /** 151 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2 152 : : *# Implementations MUST NOT send extension responses if the remote 153 : : *# endpoint did not send the corresponding extension requests, with the 154 : : *# exception of the "cookie" extension in the HelloRetryRequest. Upon 155 : : *# receiving such an extension, an endpoint MUST abort the handshake 156 : : *# with an "unsupported_extension" alert. 157 : : * 158 : : *= https://www.rfc-editor.org/rfc/rfc7627#section-5.3 159 : : *# If the original session did not use the "extended_master_secret" 160 : : *# extension but the new ServerHello contains the extension, the 161 : : *# client MUST abort the handshake. 162 : : * 163 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4 164 : : *# As with the ServerHello, a HelloRetryRequest MUST NOT contain any 165 : : *# extensions that were not first offered by the client in its 166 : : *# ClientHello, with the exception of optionally the "cookie" (see 167 : : *# Section 4.2.2) extension. 168 : : **/ 169 [ + + ][ + + ]: 57821 : if (extension_type->is_response && !S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) { 170 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_UNSUPPORTED_EXTENSION); 171 : 1 : } 172 : : 173 : : /* Do not process an extension not valid for the protocol version */ 174 [ + + ]: 57820 : if (extension_type->minimum_version > conn->actual_protocol_version) { 175 : 415 : return S2N_SUCCESS; 176 : 415 : } 177 : : 178 [ + + ]: 57405 : POSIX_GUARD(extension_type->recv(conn, in)); 179 : : 180 : : /* Set request bit flag */ 181 [ + + ]: 57391 : if (extension_type->is_response) { 182 : 13948 : S2N_CBIT_SET(conn->extension_responses_received, extension_id); 183 : 43443 : } else { 184 : 43443 : S2N_CBIT_SET(conn->extension_requests_received, extension_id); 185 : 43443 : } 186 : : 187 : 57391 : return S2N_SUCCESS; 188 : 57405 : } 189 : : 190 : : int s2n_extension_is_missing(const s2n_extension_type *extension_type, struct s2n_connection *conn) 191 : 155995 : { 192 [ + - ][ + + ]: 155995 : POSIX_ENSURE_REF(extension_type); 193 [ + - ][ + + ]: 155994 : POSIX_ENSURE_REF(extension_type->if_missing); 194 [ + - ][ + + ]: 155992 : POSIX_ENSURE_REF(conn); 195 : : 196 : 155990 : s2n_extension_type_id extension_id = 0; 197 [ - + ]: 155990 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id)); 198 : : 199 : : /* Do not consider an extension missing if we did not send a request */ 200 [ + + ][ + + ]: 155990 : if (extension_type->is_response && !S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) { 201 : 50932 : return S2N_SUCCESS; 202 : 50932 : } 203 : : 204 : : /* Do not consider an extension missing if it is not valid for the protocol version */ 205 [ + + ]: 105058 : if (extension_type->minimum_version > conn->actual_protocol_version) { 206 : 9412 : return S2N_SUCCESS; 207 : 9412 : } 208 : : 209 [ + + ]: 95646 : POSIX_GUARD(extension_type->if_missing(conn)); 210 : : 211 : 95638 : return S2N_SUCCESS; 212 : 95646 : } 213 : : 214 : : int s2n_extension_send_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *out) 215 : 2 : { 216 [ + - ]: 2 : POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); 217 : 2 : } 218 : : 219 : : int s2n_extension_recv_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *in) 220 : 3 : { 221 [ + - ]: 3 : POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); 222 : 3 : } 223 : : 224 : : int s2n_extension_send_noop(struct s2n_connection *conn, struct s2n_stuffer *out) 225 : 9588 : { 226 : 9588 : return S2N_SUCCESS; 227 : 9588 : } 228 : : 229 : : int s2n_extension_recv_noop(struct s2n_connection *conn, struct s2n_stuffer *in) 230 : 790 : { 231 : 790 : return S2N_SUCCESS; 232 : 790 : } 233 : : 234 : : bool s2n_extension_always_send(struct s2n_connection *conn) 235 : 10288 : { 236 : 10288 : return true; 237 : 10288 : } 238 : : 239 : : bool s2n_extension_never_send(struct s2n_connection *conn) 240 : 2 : { 241 : 2 : return false; 242 : 2 : } 243 : : 244 : : bool s2n_extension_send_if_tls13_connection(struct s2n_connection *conn) 245 : 12614 : { 246 : 12614 : return s2n_connection_get_protocol_version(conn) >= S2N_TLS13; 247 : 12614 : } 248 : : 249 : : int s2n_extension_error_if_missing(struct s2n_connection *conn) 250 : 8 : { 251 [ + - ]: 8 : POSIX_BAIL(S2N_ERR_MISSING_EXTENSION); 252 : 8 : } 253 : : 254 : : int s2n_extension_noop_if_missing(struct s2n_connection *conn) 255 : 68338 : { 256 : 68338 : return S2N_SUCCESS; 257 : 68338 : }