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