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 "api/s2n.h" 17 : : #include "tls/s2n_alerts.h" 18 : : #include "tls/s2n_connection.h" 19 : : #include "tls/s2n_tls.h" 20 : : #include "utils/s2n_atomic.h" 21 : : #include "utils/s2n_safety.h" 22 : : 23 : : static bool s2n_shutdown_expect_close_notify(struct s2n_connection *conn) 24 : 9357 : { 25 : : /* No close_notify expected if we already received an error instead */ 26 [ - + ]: 9357 : if (s2n_atomic_flag_test(&conn->error_alert_received)) { 27 : 0 : return false; 28 : 0 : } 29 : : 30 : : /* No close_notify expected if we sent an error instead of a close_notify */ 31 [ - + ][ + + ]: 9357 : if (conn->writer_alert_out || conn->reader_alert_out) { 32 : 3 : return false; 33 : 3 : } 34 : : 35 : : /* The purpose of the peer responding to our close_notify 36 : : * with its own close_notify is to prevent application data truncation. 37 : : * However, application data is not a concern during the handshake. 38 : : * 39 : : * Additionally, decrypting alerts sent during the handshake can be error prone 40 : : * due to different encryption keys and may lead to unnecessary error reporting 41 : : * and unnecessary blinding. 42 : : */ 43 [ + + ]: 9354 : if (!s2n_handshake_is_complete(conn)) { 44 : 31 : return false; 45 : 31 : } 46 : : 47 : : /* QUIC does not use TLS alerts */ 48 [ - + ]: 9323 : if (conn->quic_enabled) { 49 : 0 : return false; 50 : 0 : } 51 : : 52 : : /* Blinded errors indicate a fatal error handling inputs. 53 : : * We should not attempt to handle further inputs. 54 : : */ 55 [ - + ]: 9323 : if (conn->delay) { 56 : 0 : return false; 57 : 0 : } 58 : : 59 : 9323 : return true; 60 : 9323 : } 61 : : 62 : : int s2n_shutdown_send(struct s2n_connection *conn, s2n_blocked_status *blocked) 63 : 16537 : { 64 [ + - ][ + + ]: 16537 : POSIX_ENSURE_REF(conn); 65 [ + + ][ + - ]: 16536 : POSIX_ENSURE_REF(blocked); 66 : 16535 : *blocked = S2N_NOT_BLOCKED; 67 : : 68 : : /* Treat this call as a no-op if already wiped. 69 : : * This should probably be an error, but wasn't in the past so is left as-is 70 : : * for backwards compatibility. 71 : : */ 72 [ + + ][ + - ]: 16535 : if (conn->send == NULL && conn->recv == NULL) { 73 : 2 : return S2N_SUCCESS; 74 : 2 : } 75 : : 76 : : /* Flush any outstanding data */ 77 : 16533 : s2n_atomic_flag_set(&conn->write_closed); 78 [ + + ]: 16533 : POSIX_GUARD(s2n_flush(conn, blocked)); 79 : : 80 : : /* For a connection closed due to receiving an alert, we don't send anything. */ 81 [ + + ]: 9445 : if (s2n_atomic_flag_test(&conn->error_alert_received)) { 82 : 7 : return S2N_SUCCESS; 83 : 7 : } 84 : : 85 : : /* If we've already sent an alert, don't send another. */ 86 [ + + ]: 9438 : if (conn->alert_sent) { 87 : 7119 : return S2N_SUCCESS; 88 : 7119 : } 89 : : 90 : : /* Enforce blinding. 91 : : * If an application is using self-service blinding, ensure that they have 92 : : * waited the required time before triggering any alerts. 93 : : */ 94 : 2319 : uint64_t elapsed = 0; 95 [ - + ]: 2319 : POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed)); 96 [ - + ][ # # ]: 2319 : S2N_ERROR_IF(elapsed < conn->delay, S2N_ERR_SHUTDOWN_PAUSED); 97 : : 98 : : /** 99 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.1 100 : : *# Each party MUST send a "close_notify" alert before closing its write 101 : : *# side of the connection, unless it has already sent some error alert. 102 : : */ 103 [ - + ]: 2319 : POSIX_GUARD_RESULT(s2n_alerts_write_error_or_close_notify(conn)); 104 [ + + ]: 2319 : POSIX_GUARD(s2n_flush(conn, blocked)); 105 : 2315 : return S2N_SUCCESS; 106 : 2319 : } 107 : : 108 : : int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) 109 : 16487 : { 110 [ - + ][ # # ]: 16487 : POSIX_ENSURE_REF(conn); 111 [ - + ][ # # ]: 16487 : POSIX_ENSURE_REF(blocked); 112 : 16487 : *blocked = S2N_NOT_BLOCKED; 113 : : 114 : : /* If necessary, send an alert to indicate shutdown. */ 115 [ + + ]: 16487 : POSIX_GUARD(s2n_shutdown_send(conn, blocked)); 116 : : 117 : : /* If we don't expect a close_notify from our peer, 118 : : * just ensure that the connection is marked closed. 119 : : */ 120 [ + + ]: 9401 : if (!s2n_shutdown_expect_close_notify(conn)) { 121 [ - + ]: 46 : POSIX_GUARD_RESULT(s2n_connection_set_closed(conn)); 122 : 46 : *blocked = S2N_NOT_BLOCKED; 123 : 46 : return S2N_SUCCESS; 124 : 46 : } 125 : : 126 : : /* Wait for the peer's close_notify. */ 127 : 9355 : uint8_t record_type = 0; 128 : 9355 : int isSSLv2 = false; 129 : 9355 : *blocked = S2N_BLOCKED_ON_READ; 130 [ + + ]: 11633 : while (!s2n_atomic_flag_test(&conn->close_notify_received)) { 131 [ + + ]: 9333 : POSIX_GUARD(s2n_read_full_record(conn, &record_type, &isSSLv2)); 132 [ - + ][ # # ]: 2279 : POSIX_ENSURE(!isSSLv2, S2N_ERR_BAD_MESSAGE); 133 [ + + ]: 2279 : if (record_type == TLS_ALERT) { 134 [ + + ]: 2270 : POSIX_GUARD(s2n_process_alert_fragment(conn)); 135 : 2270 : } 136 [ - + ]: 2278 : POSIX_GUARD_RESULT(s2n_record_wipe(conn)); 137 : 2278 : } 138 : : 139 : 2300 : *blocked = S2N_NOT_BLOCKED; 140 : 2300 : return S2N_SUCCESS; 141 : 9355 : }