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/s2n_key_update.h" 17 : : 18 : : #include "crypto/s2n_sequence.h" 19 : : #include "error/s2n_errno.h" 20 : : #include "tls/s2n_connection.h" 21 : : #include "tls/s2n_ktls.h" 22 : : #include "tls/s2n_record.h" 23 : : #include "tls/s2n_tls.h" 24 : : #include "tls/s2n_tls13_handshake.h" 25 : : #include "utils/s2n_atomic.h" 26 : : #include "utils/s2n_safety.h" 27 : : 28 : : static s2n_peer_key_update key_update_request_val = S2N_KEY_UPDATE_NOT_REQUESTED; 29 : : 30 : : int s2n_key_update_write(struct s2n_blob *out); 31 : : int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number); 32 : : 33 : : S2N_RESULT s2n_set_key_update_request_for_testing(s2n_peer_key_update request) 34 : 1 : { 35 [ - + ][ # # ]: 1 : RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST); 36 : 1 : key_update_request_val = request; 37 : 1 : return S2N_RESULT_OK; 38 : 1 : } 39 : : 40 : : int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request) 41 : 902 : { 42 [ # # ][ - + ]: 902 : POSIX_ENSURE_REF(conn); 43 [ - + ][ # # ]: 902 : POSIX_ENSURE_REF(conn->config); 44 [ + + ][ + - ]: 902 : POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE); 45 [ - + ][ # # ]: 898 : POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_BAD_MESSAGE); 46 : : 47 : 898 : uint8_t key_update_request = 0; 48 [ - + ]: 898 : POSIX_GUARD(s2n_stuffer_read_uint8(request, &key_update_request)); 49 [ + + ]: 898 : if (key_update_request == S2N_KEY_UPDATE_REQUESTED) { 50 : 205 : s2n_atomic_flag_set(&conn->key_update_pending); 51 : 693 : } else { 52 [ - + ][ # # ]: 693 : POSIX_ENSURE(key_update_request == S2N_KEY_UPDATE_NOT_REQUESTED, S2N_ERR_BAD_MESSAGE); 53 : 693 : } 54 : : 55 : : /* Update peer's key since a key_update was received */ 56 [ + + ]: 898 : if (conn->mode == S2N_CLIENT) { 57 [ - + ]: 446 : POSIX_GUARD(s2n_update_application_traffic_keys(conn, S2N_SERVER, RECEIVING)); 58 : 452 : } else { 59 [ - + ]: 452 : POSIX_GUARD(s2n_update_application_traffic_keys(conn, S2N_CLIENT, RECEIVING)); 60 : 452 : } 61 : : 62 : : /* We need to update the socket with the new keys in the case of ktls */ 63 [ + + ]: 898 : if (conn->ktls_recv_enabled) { 64 [ + - ]: 1 : POSIX_GUARD_RESULT(s2n_ktls_key_update_process(conn)); 65 : 1 : } 66 : : 67 : 897 : return S2N_SUCCESS; 68 : 898 : } 69 : : 70 : : int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked) 71 : 49871 : { 72 [ - + ][ # # ]: 49871 : POSIX_ENSURE_REF(conn); 73 [ # # ][ - + ]: 49871 : POSIX_ENSURE_REF(conn->secure); 74 [ + + ][ + - ]: 49871 : POSIX_ENSURE_GTE(conn->actual_protocol_version, S2N_TLS13); 75 : : 76 : 49870 : struct s2n_blob sequence_number = { 0 }; 77 [ - + ]: 49870 : POSIX_GUARD_RESULT(s2n_connection_get_sequence_number(conn, conn->mode, &sequence_number)); 78 [ - + ]: 49870 : POSIX_GUARD(s2n_check_record_limit(conn, &sequence_number)); 79 : : 80 [ + + ]: 49870 : if (s2n_atomic_flag_test(&conn->key_update_pending)) { 81 [ + + ][ + - ]: 832 : POSIX_ENSURE(!conn->ktls_send_enabled, S2N_ERR_KTLS_KEYUPDATE); 82 : : 83 : : /* Flush any buffered records to ensure an empty output buffer. 84 : : * 85 : : * This is important when buffering multiple records because we don't: 86 : : * 1) Respect max fragment length for handshake messages 87 : : * 2) Check if there is sufficient space in the output buffer for 88 : : * post-handshake messages. 89 : : */ 90 [ + + ]: 830 : POSIX_GUARD(s2n_flush(conn, blocked)); 91 : : 92 : 829 : uint8_t key_update_data[S2N_KEY_UPDATE_MESSAGE_SIZE]; 93 : 829 : struct s2n_blob key_update_blob = { 0 }; 94 [ - + ]: 829 : POSIX_GUARD(s2n_blob_init(&key_update_blob, key_update_data, sizeof(key_update_data))); 95 : : 96 : : /* Write key update message */ 97 [ - + ]: 829 : POSIX_GUARD(s2n_key_update_write(&key_update_blob)); 98 : : 99 : : /* Encrypt the message */ 100 [ + + ]: 829 : POSIX_GUARD_RESULT(s2n_record_write(conn, TLS_HANDSHAKE, &key_update_blob)); 101 : : 102 : : /* Update encryption key */ 103 [ - + ]: 828 : POSIX_GUARD(s2n_update_application_traffic_keys(conn, conn->mode, SENDING)); 104 : : 105 : 828 : s2n_atomic_flag_clear(&conn->key_update_pending); 106 [ + + ]: 828 : POSIX_GUARD(s2n_flush(conn, blocked)); 107 : 828 : } 108 : : 109 : 49765 : return S2N_SUCCESS; 110 : 49870 : } 111 : : 112 : : int s2n_key_update_write(struct s2n_blob *out) 113 : 904 : { 114 [ - + ][ # # ]: 904 : POSIX_ENSURE_REF(out); 115 : : 116 : 904 : struct s2n_stuffer key_update_stuffer = { 0 }; 117 [ - + ]: 904 : POSIX_GUARD(s2n_stuffer_init(&key_update_stuffer, out)); 118 [ - + ]: 904 : POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, TLS_KEY_UPDATE)); 119 [ - + ]: 904 : POSIX_GUARD(s2n_stuffer_write_uint24(&key_update_stuffer, S2N_KEY_UPDATE_LENGTH)); 120 : : 121 : : /* s2n currently does not require peers to update their encryption keys. */ 122 [ - + ]: 904 : POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, key_update_request_val)); 123 : : 124 : 904 : return S2N_SUCCESS; 125 : 904 : } 126 : : 127 : : int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number) 128 : 49883 : { 129 [ - + ][ # # ]: 49883 : POSIX_ENSURE_REF(conn); 130 [ - + ][ # # ]: 49883 : POSIX_ENSURE_REF(sequence_number); 131 [ - + ][ # # ]: 49883 : POSIX_ENSURE_REF(conn->secure); 132 [ - + ][ # # ]: 49883 : POSIX_ENSURE_REF(conn->secure->cipher_suite); 133 [ - + ][ # # ]: 49883 : POSIX_ENSURE_REF(conn->secure->cipher_suite->record_alg); 134 : : 135 : : /* 136 : : * This is the sequence number that will be used for the next record, 137 : : * because we incremented the sequence number after sending the last record. 138 : : */ 139 : 49883 : uint64_t next_seq_num = 0; 140 [ - + ]: 49883 : POSIX_GUARD(s2n_sequence_number_to_uint64(sequence_number, &next_seq_num)); 141 : : 142 : : /* 143 : : * If the next record is the last record we can send, then the next record needs 144 : : * to contain a KeyUpdate message. 145 : : * 146 : : * This should always trigger on "==", but we use ">=" just in case. 147 : : */ 148 [ + + ]: 49883 : if (next_seq_num >= conn->secure->cipher_suite->record_alg->encryption_limit) { 149 : 819 : s2n_atomic_flag_set(&conn->key_update_pending); 150 : 819 : } 151 : : 152 : 49883 : return S2N_SUCCESS; 153 : 49883 : } 154 : : 155 : : int s2n_connection_request_key_update(struct s2n_connection *conn, s2n_peer_key_update peer_request) 156 : 8 : { 157 [ + - ][ + + ]: 8 : POSIX_ENSURE_REF(conn); 158 : : /* s2n-tls does not currently support requesting key updates from peers */ 159 [ + + ][ + - ]: 7 : POSIX_ENSURE(peer_request == S2N_KEY_UPDATE_NOT_REQUESTED, S2N_ERR_INVALID_ARGUMENT); 160 : 6 : s2n_atomic_flag_set(&conn->key_update_pending); 161 : 6 : return S2N_SUCCESS; 162 : 7 : }