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_max_fragment_length.h" 17 : : 18 : : #include <sys/param.h> 19 : : 20 : : #include "error/s2n_errno.h" 21 : : #include "stuffer/s2n_stuffer.h" 22 : : #include "tls/s2n_connection.h" 23 : : #include "tls/s2n_tls.h" 24 : : #include "tls/s2n_tls_parameters.h" 25 : : #include "utils/s2n_safety.h" 26 : : 27 : : static bool s2n_max_fragment_length_should_send(struct s2n_connection *conn); 28 : : static int s2n_max_fragment_length_send(struct s2n_connection *conn, struct s2n_stuffer *out); 29 : : static int s2n_max_fragment_length_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); 30 : : 31 : : const s2n_extension_type s2n_server_max_fragment_length_extension = { 32 : : .iana_value = TLS_EXTENSION_MAX_FRAG_LEN, 33 : : .is_response = true, 34 : : .send = s2n_max_fragment_length_send, 35 : : .recv = s2n_max_fragment_length_recv, 36 : : .should_send = s2n_max_fragment_length_should_send, 37 : : .if_missing = s2n_extension_noop_if_missing, 38 : : }; 39 : : 40 : : static bool s2n_max_fragment_length_should_send(struct s2n_connection *conn) 41 : 398 : { 42 [ + - ][ + + ]: 398 : return conn && conn->negotiated_mfl_code != S2N_TLS_MAX_FRAG_LEN_EXT_NONE; 43 : 398 : } 44 : : 45 : : static int s2n_max_fragment_length_send(struct s2n_connection *conn, struct s2n_stuffer *out) 46 : 391 : { 47 [ - + ][ # # ]: 391 : POSIX_ENSURE_REF(conn); 48 [ - + ]: 391 : POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->negotiated_mfl_code)); 49 : 391 : return S2N_SUCCESS; 50 : 391 : } 51 : : 52 : : static int s2n_max_fragment_length_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) 53 : 389 : { 54 [ - + ][ # # ]: 389 : POSIX_ENSURE_REF(conn); 55 [ - + ][ # # ]: 389 : POSIX_ENSURE_REF(conn->config); 56 : : 57 : 389 : uint8_t mfl_code = 0; 58 [ - + ]: 389 : POSIX_GUARD(s2n_stuffer_read_uint8(extension, &mfl_code)); 59 : : 60 : : /* 61 : : *= https://www.rfc-editor.org/rfc/rfc6066#section-4 62 : : *# Similarly, if a client 63 : : *# receives a maximum fragment length negotiation response that differs 64 : : *# from the length it requested, it MUST also abort the handshake with 65 : : *# an "illegal_parameter" alert. 66 : : */ 67 [ + + ][ + - ]: 389 : S2N_ERROR_IF(mfl_code != conn->config->mfl_code, S2N_ERR_MAX_FRAG_LEN_MISMATCH); 68 : : 69 : : /* 70 : : *= https://www.rfc-editor.org/rfc/rfc6066#section-4 71 : : *# Once a maximum fragment length other than 2^14 has been successfully 72 : : *# negotiated, the client and server MUST immediately begin fragmenting 73 : : *# messages (including handshake messages) to ensure that no fragment 74 : : *# larger than the negotiated length is sent. 75 : : */ 76 : 388 : conn->negotiated_mfl_code = mfl_code; 77 [ - + ]: 388 : POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, conn->max_outgoing_fragment_length)); 78 : : 79 : 388 : return S2N_SUCCESS; 80 : 388 : }