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