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 "error/s2n_errno.h"
17
18 #include "tls/s2n_connection.h"
19 #include "tls/s2n_key_update.h"
20 #include "tls/s2n_tls13_handshake.h"
21 #include "tls/s2n_record.h"
22 #include "tls/s2n_tls.h"
23
24 #include "crypto/s2n_sequence.h"
25
26 #include "utils/s2n_safety.h"
27
28 int s2n_key_update_write(struct s2n_blob *out);
29 int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number);
30
31
s2n_key_update_recv(struct s2n_connection * conn,struct s2n_stuffer * request)32 int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request)
33 {
34 POSIX_ENSURE_REF(conn);
35 POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE);
36 POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_BAD_MESSAGE);
37
38 uint8_t key_update_request;
39 POSIX_GUARD(s2n_stuffer_read_uint8(request, &key_update_request));
40 S2N_ERROR_IF(key_update_request != S2N_KEY_UPDATE_NOT_REQUESTED && key_update_request != S2N_KEY_UPDATE_REQUESTED,
41 S2N_ERR_BAD_MESSAGE);
42 conn->key_update_pending = key_update_request;
43
44 /* Update peer's key since a key_update was received */
45 if (conn->mode == S2N_CLIENT){
46 POSIX_GUARD(s2n_update_application_traffic_keys(conn, S2N_SERVER, RECEIVING));
47 } else {
48 POSIX_GUARD(s2n_update_application_traffic_keys(conn, S2N_CLIENT, RECEIVING));
49 }
50
51 return S2N_SUCCESS;
52 }
53
s2n_key_update_send(struct s2n_connection * conn,s2n_blocked_status * blocked)54 int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
55 {
56 POSIX_ENSURE_REF(conn);
57
58 struct s2n_blob sequence_number = {0};
59 if (conn->mode == S2N_CLIENT) {
60 POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
61 } else {
62 POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
63 }
64
65 POSIX_GUARD(s2n_check_record_limit(conn, &sequence_number));
66
67 if (conn->key_update_pending) {
68 uint8_t key_update_data[S2N_KEY_UPDATE_MESSAGE_SIZE];
69 struct s2n_blob key_update_blob = {0};
70 POSIX_GUARD(s2n_blob_init(&key_update_blob, key_update_data, sizeof(key_update_data)));
71
72 /* Write key update message */
73 POSIX_GUARD(s2n_key_update_write(&key_update_blob));
74
75 /* Encrypt the message */
76 POSIX_GUARD(s2n_record_write(conn, TLS_HANDSHAKE, &key_update_blob));
77
78 /* Update encryption key */
79 POSIX_GUARD(s2n_update_application_traffic_keys(conn, conn->mode, SENDING));
80 conn->key_update_pending = false;
81
82 POSIX_GUARD(s2n_flush(conn, blocked));
83 }
84
85 return S2N_SUCCESS;
86 }
87
s2n_key_update_write(struct s2n_blob * out)88 int s2n_key_update_write(struct s2n_blob *out)
89 {
90 POSIX_ENSURE_REF(out);
91
92 struct s2n_stuffer key_update_stuffer = {0};
93 POSIX_GUARD(s2n_stuffer_init(&key_update_stuffer, out));
94 POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, TLS_KEY_UPDATE));
95 POSIX_GUARD(s2n_stuffer_write_uint24(&key_update_stuffer, S2N_KEY_UPDATE_LENGTH));
96
97 /* s2n currently does not require peers to update their encryption keys. */
98 POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, S2N_KEY_UPDATE_NOT_REQUESTED));
99
100 return S2N_SUCCESS;
101 }
102
s2n_check_record_limit(struct s2n_connection * conn,struct s2n_blob * sequence_number)103 int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number)
104 {
105 POSIX_ENSURE_REF(conn);
106 POSIX_ENSURE_REF(sequence_number);
107 POSIX_ENSURE_REF(conn->secure.cipher_suite);
108 POSIX_ENSURE_REF(conn->secure.cipher_suite->record_alg);
109
110 uint64_t output = 0;
111 POSIX_GUARD(s2n_sequence_number_to_uint64(sequence_number, &output));
112
113 if (output + 1 > conn->secure.cipher_suite->record_alg->encryption_limit) {
114 conn->key_update_pending = true;
115 }
116
117 return S2N_SUCCESS;
118 }
119
120