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