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_tls13_handshake.h"
17 : :
18 : : #include "tls/s2n_cipher_suites.h"
19 : : #include "tls/s2n_key_log.h"
20 : : #include "tls/s2n_security_policies.h"
21 : :
22 : : static int s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode)
23 : 1797 : {
24 [ - + ][ # # ]: 1797 : POSIX_ENSURE_REF(conn);
25 [ - + ][ # # ]: 1797 : POSIX_ENSURE_REF(conn->secure);
26 : 1797 : struct s2n_blob sequence_number = { 0 };
27 [ - + ]: 1797 : POSIX_GUARD_RESULT(s2n_connection_get_sequence_number(conn, mode, &sequence_number));
28 [ - + ]: 1797 : POSIX_GUARD(s2n_blob_zero(&sequence_number));
29 : 1797 : return S2N_SUCCESS;
30 : 1797 : }
31 : :
32 : : int s2n_tls13_mac_verify(struct s2n_tls13_keys *keys, struct s2n_blob *finished_verify, struct s2n_blob *wire_verify)
33 : 6906 : {
34 [ - + ][ # # ]: 6906 : POSIX_ENSURE_REF(wire_verify->data);
35 [ + - ][ + + ]: 6906 : POSIX_ENSURE_EQ(wire_verify->size, keys->size);
36 : :
37 [ + + ][ + - ]: 6892 : S2N_ERROR_IF(!s2n_constant_time_equals(finished_verify->data, wire_verify->data, keys->size), S2N_ERR_BAD_MESSAGE);
38 : :
39 : 6782 : return S2N_SUCCESS;
40 : 6892 : }
41 : :
42 : : int s2n_tls13_keys_from_conn(struct s2n_tls13_keys *keys, struct s2n_connection *conn)
43 : 21916 : {
44 [ - + ]: 21916 : POSIX_GUARD(s2n_tls13_keys_init(keys, conn->secure->cipher_suite->prf_alg));
45 : 21916 : return S2N_SUCCESS;
46 : 21916 : }
47 : :
48 : : int s2n_tls13_compute_ecc_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret)
49 : 9267 : {
50 [ # # ][ - + ]: 9267 : POSIX_ENSURE_REF(conn);
51 : :
52 : 9267 : const struct s2n_ecc_preferences *ecc_preferences = NULL;
53 [ - + ]: 9267 : POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_preferences));
54 [ - + ][ # # ]: 9267 : POSIX_ENSURE_REF(ecc_preferences);
55 : :
56 : 9267 : struct s2n_ecc_evp_params *server_key = &conn->kex_params.server_ecc_evp_params;
57 [ - + ][ # # ]: 9267 : POSIX_ENSURE_REF(server_key);
58 [ + + ][ + - ]: 9267 : POSIX_ENSURE_REF(server_key->negotiated_curve);
59 : :
60 : 9266 : struct s2n_ecc_evp_params *client_key = &conn->kex_params.client_ecc_evp_params;
61 [ # # ][ - + ]: 9266 : POSIX_ENSURE_REF(client_key);
62 [ # # ][ - + ]: 9266 : POSIX_ENSURE_REF(client_key->negotiated_curve);
63 : :
64 [ - + ][ # # ]: 9266 : POSIX_ENSURE_EQ(server_key->negotiated_curve, client_key->negotiated_curve);
65 : :
66 [ + + ]: 9266 : if (conn->mode == S2N_CLIENT) {
67 [ + + ]: 4628 : POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_key, server_key, shared_secret));
68 : 4638 : } else {
69 [ - + ]: 4638 : POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_key, client_key, shared_secret));
70 : 4638 : }
71 : :
72 : 9265 : return S2N_SUCCESS;
73 : 9266 : }
74 : :
75 : : /* Computes the ECDHE+PQKEM hybrid shared secret as defined in
76 : : * https://tools.ietf.org/html/draft-stebila-tls-hybrid-design
77 : : * Also supports "pure PQ" mode when kem_group->curve == &s2n_ecc_curve_none.
78 : : */
79 : : int s2n_tls13_compute_pq_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret)
80 : 82 : {
81 [ + - ][ + + ]: 82 : POSIX_ENSURE_REF(conn);
82 [ + - ][ + + ]: 78 : POSIX_ENSURE_REF(shared_secret);
83 : :
84 : : /* conn->kex_params.server_ecc_evp_params should be set only during a classic/non-hybrid handshake */
85 [ + - ][ + + ]: 76 : POSIX_ENSURE_EQ(NULL, conn->kex_params.server_ecc_evp_params.negotiated_curve);
86 [ + + ][ + - ]: 74 : POSIX_ENSURE_EQ(NULL, conn->kex_params.server_ecc_evp_params.evp_pkey);
87 : :
88 : 72 : struct s2n_kem_group_params *server_kem_group_params = &conn->kex_params.server_kem_group_params;
89 [ - + ][ # # ]: 72 : POSIX_ENSURE_REF(server_kem_group_params);
90 : 72 : struct s2n_ecc_evp_params *server_ecc_params = &server_kem_group_params->ecc_params;
91 [ - + ][ # # ]: 72 : POSIX_ENSURE_REF(server_ecc_params);
92 : :
93 : 72 : struct s2n_kem_group_params *client_kem_group_params = &conn->kex_params.client_kem_group_params;
94 [ # # ][ - + ]: 72 : POSIX_ENSURE_REF(client_kem_group_params);
95 : 72 : struct s2n_ecc_evp_params *client_ecc_params = &client_kem_group_params->ecc_params;
96 [ # # ][ - + ]: 72 : POSIX_ENSURE_REF(client_ecc_params);
97 : :
98 : 72 : struct s2n_blob *pq_shared_secret = &client_kem_group_params->kem_params.shared_secret;
99 [ # # ][ - + ]: 72 : POSIX_ENSURE_REF(pq_shared_secret);
100 [ + - ][ + + ]: 72 : POSIX_ENSURE_REF(pq_shared_secret->data);
101 : :
102 : 60 : const struct s2n_kem_group *negotiated_kem_group = conn->kex_params.server_kem_group_params.kem_group;
103 [ + + ][ + - ]: 60 : POSIX_ENSURE_REF(negotiated_kem_group);
104 [ - + ][ # # ]: 58 : POSIX_ENSURE_REF(negotiated_kem_group->kem);
105 : :
106 : 58 : DEFER_CLEANUP(struct s2n_blob ecdhe_shared_secret = { 0 }, s2n_free_or_wipe);
107 : :
108 [ + + ]: 58 : if (negotiated_kem_group->curve == &s2n_ecc_curve_none) {
109 [ - + ][ # # ]: 2 : POSIX_ENSURE_EQ(ecdhe_shared_secret.size, 0);
110 [ + + ]: 56 : } else if (conn->mode == S2N_CLIENT) {
111 [ - + ]: 37 : POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_ecc_params, server_ecc_params, &ecdhe_shared_secret));
112 : 37 : } else {
113 [ - + ]: 19 : POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_ecc_params, client_ecc_params, &ecdhe_shared_secret));
114 : 19 : }
115 : :
116 [ - + ][ # # ]: 58 : POSIX_ENSURE_EQ(pq_shared_secret->size, negotiated_kem_group->kem->shared_secret_key_length);
117 : :
118 : : /* Construct the concatenated/hybrid shared secret */
119 : 58 : uint32_t hybrid_shared_secret_size = ecdhe_shared_secret.size + negotiated_kem_group->kem->shared_secret_key_length;
120 [ - + ]: 58 : POSIX_GUARD(s2n_alloc(shared_secret, hybrid_shared_secret_size));
121 : 58 : struct s2n_stuffer stuffer_combiner = { 0 };
122 [ - + ]: 58 : POSIX_GUARD(s2n_stuffer_init(&stuffer_combiner, shared_secret));
123 : :
124 [ + + ]: 58 : if (negotiated_kem_group->send_kem_first) {
125 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, pq_shared_secret));
126 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, &ecdhe_shared_secret));
127 : 52 : } else {
128 [ - + ]: 52 : POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, &ecdhe_shared_secret));
129 [ - + ]: 52 : POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, pq_shared_secret));
130 : 52 : }
131 : :
132 : 58 : return S2N_SUCCESS;
133 : 58 : }
134 : :
135 : : int s2n_tls13_pq_hybrid_supported(struct s2n_connection *conn)
136 : 9375 : {
137 : 9375 : return conn->kex_params.server_kem_group_params.kem_group != NULL;
138 : 9375 : }
139 : :
140 : : int s2n_tls13_compute_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret)
141 : 9323 : {
142 [ # # ][ - + ]: 9323 : POSIX_ENSURE_REF(conn);
143 : :
144 [ + + ]: 9323 : if (s2n_tls13_pq_hybrid_supported(conn)) {
145 [ - + ]: 56 : POSIX_GUARD(s2n_tls13_compute_pq_shared_secret(conn, shared_secret));
146 : 9267 : } else {
147 [ + + ]: 9267 : POSIX_GUARD(s2n_tls13_compute_ecc_shared_secret(conn, shared_secret));
148 : 9267 : }
149 : :
150 [ - + ]: 9321 : POSIX_GUARD_RESULT(s2n_connection_wipe_all_keyshares(conn));
151 : :
152 : : /* It would make more sense to wipe the PSK secrets in s2n_tls13_handle_early_secret,
153 : : * but at that point we don't know whether or not the server will request a HRR request
154 : : * and we'll have to use the secrets again.
155 : : *
156 : : * Instead, wipe them here when we wipe all the other connection secrets. */
157 [ - + ]: 9321 : POSIX_GUARD_RESULT(s2n_psk_parameters_wipe_secrets(&conn->psk_params));
158 : :
159 : 9321 : return S2N_SUCCESS;
160 : 9321 : }
161 : :
162 : : int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mode, keyupdate_status status)
163 : 1797 : {
164 [ - + ][ # # ]: 1797 : POSIX_ENSURE_REF(conn);
165 [ - + ][ # # ]: 1797 : POSIX_ENSURE_REF(conn->secure);
166 [ - + ][ # # ]: 1797 : POSIX_ENSURE_GTE(conn->actual_protocol_version, S2N_TLS13);
167 : :
168 : : /* get tls13 key context */
169 [ - + ]: 1797 : s2n_tls13_connection_keys(keys, conn);
170 : :
171 : 1797 : struct s2n_session_key *old_key = NULL;
172 : 1797 : struct s2n_blob old_app_secret = { 0 };
173 : 1797 : struct s2n_blob app_iv = { 0 };
174 : :
175 [ + + ]: 1797 : if (mode == S2N_CLIENT) {
176 : 905 : old_key = &conn->secure->client_key;
177 [ - + ]: 905 : POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.version.tls13.client_app_secret, keys.size));
178 [ - + ]: 905 : POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure->client_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
179 : 905 : } else {
180 : 892 : old_key = &conn->secure->server_key;
181 [ - + ]: 892 : POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.version.tls13.server_app_secret, keys.size));
182 [ - + ]: 892 : POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure->server_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
183 : 892 : }
184 : :
185 : : /* Produce new application secret */
186 [ - + ][ # # ]: 3594 : s2n_stack_blob(app_secret_update, keys.size, S2N_TLS13_SECRET_MAX_LEN);
[ - + ]
187 : :
188 : : /* Derives next generation of traffic secret */
189 [ - + ]: 1797 : POSIX_GUARD(s2n_tls13_update_application_traffic_secret(&keys, &old_app_secret, &app_secret_update));
190 : :
191 [ - + ][ # # ]: 3594 : s2n_tls13_key_blob(app_key, conn->secure->cipher_suite->record_alg->cipher->key_material_size);
[ - + ]
192 : :
193 : : /* Derives next generation of traffic key */
194 : 1797 : uint8_t *count = NULL;
195 [ - + ]: 1797 : POSIX_GUARD(s2n_tls13_derive_traffic_keys(&keys, &app_secret_update, &app_key, &app_iv));
196 [ + + ]: 1797 : if (status == RECEIVING) {
197 [ - + ]: 898 : POSIX_GUARD_RESULT(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(old_key, &app_key));
198 : 898 : count = &conn->recv_key_updated;
199 : 899 : } else {
200 [ - + ]: 899 : POSIX_GUARD_RESULT(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(old_key, &app_key));
201 : 899 : count = &conn->send_key_updated;
202 : 899 : }
203 : :
204 : : /* Increment the count.
205 : : * Don't treat overflows as errors-- we only do best-effort reporting.
206 : : */
207 : 1797 : *count = MIN(UINT8_MAX, *count + 1);
208 : :
209 : : /* According to https://tools.ietf.org/html/rfc8446#section-5.3:
210 : : * Each sequence number is set to zero at the beginning of a connection and
211 : : * whenever the key is changed; the first record transmitted under a particular traffic key
212 : : * MUST use sequence number 0.
213 : : */
214 [ - + ]: 1797 : POSIX_GUARD(s2n_zero_sequence_number(conn, mode));
215 : :
216 : : /* Save updated secret */
217 : 1797 : struct s2n_stuffer old_secret_stuffer = { 0 };
218 [ - + ]: 1797 : POSIX_GUARD(s2n_stuffer_init(&old_secret_stuffer, &old_app_secret));
219 [ - + ]: 1797 : POSIX_GUARD(s2n_stuffer_write_bytes(&old_secret_stuffer, app_secret_update.data, keys.size));
220 : :
221 : 1797 : return S2N_SUCCESS;
222 : 1797 : }
|