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_prf.h"
17 : : #include "tls/s2n_tls13_handshake.h"
18 : : #include "utils/s2n_result.h"
19 : :
20 : : /* The state machine refers to the "master" secret as the "application" secret.
21 : : * Let's use that terminology here to match.
22 : : */
23 : : #define S2N_APPLICATION_SECRET S2N_MASTER_SECRET
24 : :
25 : : /**
26 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A
27 : : *# The notation "K_{send,recv} = foo" means "set
28 : : *# the send/recv key to the given key".
29 : : */
30 : 14187 : #define K_send(conn, secret_type) RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, secret_type, (conn)->mode))
31 : 13609 : #define K_recv(conn, secret_type) RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, secret_type, S2N_PEER_MODE((conn)->mode)))
32 : :
33 : : static const struct s2n_blob s2n_zero_length_context = { 0 };
34 : :
35 : : static S2N_RESULT s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode)
36 : 27808 : {
37 [ - + ][ # # ]: 27808 : RESULT_ENSURE_REF(conn);
38 [ # # ][ - + ]: 27808 : RESULT_ENSURE_REF(conn->secure);
39 : 27808 : struct s2n_blob sequence_number = { 0 };
40 [ - + ]: 27808 : RESULT_GUARD(s2n_connection_get_sequence_number(conn, mode, &sequence_number));
41 [ - + ]: 27808 : RESULT_GUARD_POSIX(s2n_blob_zero(&sequence_number));
42 : 27808 : return S2N_RESULT_OK;
43 : 27808 : }
44 : :
45 : : static S2N_RESULT s2n_tls13_key_schedule_get_keying_material(
46 : : struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
47 : : s2n_mode mode, struct s2n_blob *iv, struct s2n_blob *key)
48 : 27809 : {
49 [ - + ][ # # ]: 27809 : RESULT_ENSURE_REF(conn);
50 [ - + ][ # # ]: 27809 : RESULT_ENSURE_REF(iv);
51 [ - + ][ # # ]: 27809 : RESULT_ENSURE_REF(key);
52 [ - + ][ # # ]: 27809 : RESULT_ENSURE_REF(conn->secure);
53 : :
54 : 27809 : const struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite;
55 [ # # ][ - + ]: 27809 : RESULT_ENSURE_REF(cipher_suite);
56 : :
57 : 27809 : const struct s2n_cipher *cipher = NULL;
58 [ - + ]: 27809 : RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
59 [ - + ][ # # ]: 27809 : RESULT_ENSURE_REF(cipher);
60 : :
61 : : /**
62 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
63 : : *# The traffic keying material is generated from the following input
64 : : *# values:
65 : : *#
66 : : *# - A secret value
67 : : **/
68 : 27809 : struct s2n_blob secret = { 0 };
69 : 27809 : uint8_t secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
70 [ - + ]: 27809 : RESULT_GUARD_POSIX(s2n_blob_init(&secret, secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
71 [ - + ]: 27809 : RESULT_GUARD(s2n_tls13_secrets_get(conn, secret_type, mode, &secret));
72 : :
73 : : /**
74 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
75 : : *#
76 : : *# - A purpose value indicating the specific value being generated
77 : : **/
78 : 27809 : const struct s2n_blob *key_purpose = &s2n_tls13_label_traffic_secret_key;
79 : 27809 : const struct s2n_blob *iv_purpose = &s2n_tls13_label_traffic_secret_iv;
80 : :
81 : : /**
82 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
83 : : *#
84 : : *# - The length of the key being generated
85 : : **/
86 : 27809 : const uint32_t key_size = cipher->key_material_size;
87 : 27809 : const uint32_t iv_size = S2N_TLS13_FIXED_IV_LEN;
88 : :
89 : : /*
90 : : * TODO: We should be able to reuse the prf_work_space rather
91 : : * than allocating a new HMAC every time.
92 : : * https://github.com/aws/s2n-tls/issues/3206
93 : : */
94 : 27809 : s2n_hmac_algorithm hmac_alg = cipher_suite->prf_alg;
95 : 27809 : DEFER_CLEANUP(struct s2n_hmac_state hmac = { 0 }, s2n_hmac_free);
96 [ - + ]: 27809 : RESULT_GUARD_POSIX(s2n_hmac_new(&hmac));
97 : :
98 : : /**
99 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
100 : : *#
101 : : *# The traffic keying material is generated from an input traffic secret
102 : : *# value using:
103 : : *#
104 : : *# [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
105 : : **/
106 [ # # ][ - + ]: 27809 : RESULT_ENSURE_LTE(key_size, key->size);
107 : 27809 : key->size = key_size;
108 [ - + ]: 27809 : RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac, hmac_alg,
109 : 27809 : &secret, key_purpose, &s2n_zero_length_context, key));
110 : : /**
111 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
112 : : *# [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)
113 : : **/
114 [ - + ][ # # ]: 27809 : RESULT_ENSURE_LTE(iv_size, iv->size);
115 : 27809 : iv->size = iv_size;
116 [ - + ]: 27809 : RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac, hmac_alg,
117 : 27809 : &secret, iv_purpose, &s2n_zero_length_context, iv));
118 : :
119 : 27809 : return S2N_RESULT_OK;
120 : 27809 : }
121 : :
122 : : S2N_RESULT s2n_tls13_key_schedule_set_key(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type, s2n_mode mode)
123 : 27810 : {
124 [ # # ][ - + ]: 27810 : RESULT_ENSURE_REF(conn);
125 [ + + ][ + - ]: 27810 : RESULT_ENSURE_REF(conn->secure);
126 : :
127 : 27808 : uint8_t *implicit_iv_data = NULL;
128 : 27808 : struct s2n_session_key *session_key = NULL;
129 : 27808 : uint8_t key_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
130 [ + + ]: 27808 : if (mode == S2N_CLIENT) {
131 : 12652 : implicit_iv_data = conn->secure->client_implicit_iv;
132 : 12652 : session_key = &conn->secure->client_key;
133 : 12652 : conn->client = conn->secure;
134 : 15156 : } else {
135 : 15156 : implicit_iv_data = conn->secure->server_implicit_iv;
136 : 15156 : session_key = &conn->secure->server_key;
137 : 15156 : conn->server = conn->secure;
138 : 15156 : }
139 : :
140 : 27808 : struct s2n_blob iv = { 0 };
141 : 27808 : struct s2n_blob key = { 0 };
142 [ - + ]: 27808 : RESULT_GUARD_POSIX(s2n_blob_init(&iv, implicit_iv_data, S2N_TLS13_FIXED_IV_LEN));
143 [ - + ]: 27808 : RESULT_GUARD_POSIX(s2n_blob_init(&key, key_bytes, sizeof(key_bytes)));
144 [ - + ]: 27808 : RESULT_GUARD(s2n_tls13_key_schedule_get_keying_material(
145 : 27808 : conn, secret_type, mode, &iv, &key));
146 : :
147 : 27808 : const struct s2n_cipher *cipher = NULL;
148 [ - + ]: 27808 : RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
149 [ - + ][ # # ]: 27808 : RESULT_ENSURE_REF(cipher);
150 : :
151 : 27808 : bool is_sending_secret = (mode == conn->mode);
152 [ + + ]: 27808 : if (is_sending_secret) {
153 [ - + ]: 14192 : RESULT_GUARD(cipher->set_encryption_key(session_key, &key));
154 : 14192 : } else {
155 [ - + ]: 13616 : RESULT_GUARD(cipher->set_decryption_key(session_key, &key));
156 : 13616 : }
157 : :
158 : : /**
159 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-5.3
160 : : *# Each sequence number is
161 : : *# set to zero at the beginning of a connection and whenever the key is
162 : : *# changed; the first record transmitted under a particular traffic key
163 : : *# MUST use sequence number 0.
164 : : */
165 [ - + ]: 27808 : RESULT_GUARD(s2n_zero_sequence_number(conn, mode));
166 : :
167 : 27808 : return S2N_RESULT_OK;
168 : 27808 : }
169 : :
170 : : static S2N_RESULT s2n_client_key_schedule(struct s2n_connection *conn)
171 : 28086 : {
172 [ - + ][ # # ]: 28086 : RESULT_ENSURE_REF(conn);
173 : :
174 : 28086 : message_type_t message_type = s2n_conn_get_current_message_type(conn);
175 : :
176 : : /**
177 : : * How client keys are set varies depending on early data state.
178 : : *
179 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A
180 : : *# Actions which are taken only in certain circumstances
181 : : *# are indicated in [].
182 : : */
183 : :
184 : : /**
185 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
186 : : *# START <----+
187 : : *# Send ClientHello | | Recv HelloRetryRequest
188 : : *# [K_send = early data] | |
189 : : */
190 [ + + ]: 28086 : if (message_type == CLIENT_HELLO
191 [ + + ]: 28086 : && conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
192 [ + + ]: 613 : K_send(conn, S2N_EARLY_SECRET);
193 : 613 : }
194 : : /**
195 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
196 : : *# v |
197 : : *# / WAIT_SH ----+
198 : : *# | | Recv ServerHello
199 : : *# | | K_recv = handshake
200 : : */
201 [ + + ]: 28085 : if (message_type == SERVER_HELLO) {
202 [ - + ]: 4377 : K_recv(conn, S2N_HANDSHAKE_SECRET);
203 : 4377 : }
204 : : /**
205 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
206 : : *# Can | V
207 : : *# send | WAIT_EE
208 : : *# early | | Recv EncryptedExtensions
209 : : *# data | +--------+--------+
210 : : *# | Using | | Using certificate
211 : : *# | PSK | v
212 : : *# | | WAIT_CERT_CR
213 : : *# | | Recv | | Recv CertificateRequest
214 : : *# | | Certificate | v
215 : : *# | | | WAIT_CERT
216 : : *# | | | | Recv Certificate
217 : : *# | | v v
218 : : *# | | WAIT_CV
219 : : *# | | | Recv CertificateVerify
220 : : *# | +> WAIT_FINISHED <+
221 : : *# | | Recv Finished
222 : : *# \ | [Send EndOfEarlyData]
223 : : *# | K_send = handshake
224 : : */
225 [ + + ][ + + ]: 28085 : if ((message_type == SERVER_FINISHED && !WITH_EARLY_DATA(conn))
226 [ + + ]: 28085 : || (message_type == END_OF_EARLY_DATA)) {
227 [ - + ]: 2801 : K_send(conn, S2N_HANDSHAKE_SECRET);
228 : 2801 : }
229 : : /**
230 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
231 : : *# | [Send Certificate [+ CertificateVerify]]
232 : : *# Can send | Send Finished
233 : : *# app data --> | K_send = K_recv = application
234 : : */
235 [ + + ]: 28085 : if (message_type == CLIENT_FINISHED) {
236 [ - + ]: 2798 : K_send(conn, S2N_APPLICATION_SECRET);
237 [ - + ]: 2798 : K_recv(conn, S2N_APPLICATION_SECRET);
238 : 2798 : }
239 : : /**
240 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
241 : : *# after here v
242 : : *# CONNECTED
243 : : */
244 : 28085 : return S2N_RESULT_OK;
245 : 28085 : }
246 : :
247 : : static S2N_RESULT s2n_server_key_schedule(struct s2n_connection *conn)
248 : 31645 : {
249 [ - + ][ # # ]: 31645 : RESULT_ENSURE_REF(conn);
250 : :
251 : 31645 : message_type_t message_type = s2n_conn_get_current_message_type(conn);
252 : :
253 : : /**
254 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
255 : : *# START <-----+
256 : : *# Recv ClientHello | | Send HelloRetryRequest
257 : : *# v |
258 : : *# RECVD_CH ----+
259 : : *# | Select parameters
260 : : *# v
261 : : *# NEGOTIATED
262 : : *# | Send ServerHello
263 : : *# | K_send = handshake
264 : : */
265 [ + + ]: 31645 : if (message_type == SERVER_HELLO) {
266 [ + + ]: 4384 : K_send(conn, S2N_HANDSHAKE_SECRET);
267 : 4384 : }
268 : : /**
269 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
270 : : *# | Send EncryptedExtensions
271 : : *# | [Send CertificateRequest]
272 : : *# Can send | [Send Certificate + CertificateVerify]
273 : : *# app data | Send Finished
274 : : *# after --> | K_send = application
275 : : */
276 [ + + ]: 31644 : if (message_type == SERVER_FINISHED) {
277 [ - + ]: 3591 : K_send(conn, S2N_APPLICATION_SECRET);
278 : : /* clang-format off */
279 : : /**
280 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
281 : : *# here +--------+--------+
282 : : *# No 0-RTT | | 0-RTT
283 : : *# | |
284 : : *# K_recv = handshake | | K_recv = early data
285 : : */
286 : : /* clang-format on */
287 [ + + ]: 3591 : if (WITH_EARLY_DATA(conn)) {
288 [ - + ]: 55 : K_recv(conn, S2N_EARLY_SECRET);
289 : 3536 : } else {
290 [ - + ]: 3536 : K_recv(conn, S2N_HANDSHAKE_SECRET);
291 : 3536 : }
292 : 3591 : }
293 : : /**
294 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
295 : : *# [Skip decrypt errors] | +------> WAIT_EOED -+
296 : : *# | | Recv | | Recv EndOfEarlyData
297 : : *# | | early data | | K_recv = handshake
298 : : *# | +------------+ |
299 : : */
300 [ + + ]: 31644 : if (message_type == END_OF_EARLY_DATA) {
301 [ - + ]: 46 : K_recv(conn, S2N_HANDSHAKE_SECRET);
302 : 46 : }
303 : : /**
304 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
305 : : *# | |
306 : : *# +> WAIT_FLIGHT2 <--------+
307 : : *# |
308 : : *# +--------+--------+
309 : : *# No auth | | Client auth
310 : : *# | |
311 : : *# | v
312 : : *# | WAIT_CERT
313 : : *# | Recv | | Recv Certificate
314 : : *# | empty | v
315 : : *# | Certificate | WAIT_CV
316 : : *# | | | Recv
317 : : *# | v | CertificateVerify
318 : : *# +-> WAIT_FINISHED <---+
319 : : *# | Recv Finished
320 : : *# | K_recv = application
321 : : */
322 [ + + ]: 31644 : if (message_type == CLIENT_FINISHED) {
323 [ - + ]: 2797 : K_recv(conn, S2N_APPLICATION_SECRET);
324 : 2797 : }
325 : : /**
326 : : *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
327 : : *# v
328 : : *# CONNECTED
329 : : */
330 : 31644 : return S2N_RESULT_OK;
331 : 31644 : }
332 : :
333 : : s2n_result (*key_schedules[])(struct s2n_connection *) = {
334 : : [S2N_CLIENT] = &s2n_client_key_schedule,
335 : : [S2N_SERVER] = &s2n_server_key_schedule,
336 : : };
337 : :
338 : : S2N_RESULT s2n_tls13_key_schedule_update(struct s2n_connection *conn)
339 : 94248 : {
340 [ + + ][ + - ]: 94248 : RESULT_ENSURE_REF(conn);
341 [ + + ]: 94247 : if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
342 : 34516 : return S2N_RESULT_OK;
343 : 34516 : }
344 [ - + ][ # # ]: 59731 : RESULT_ENSURE_REF(key_schedules[conn->mode]);
345 [ + + ]: 59731 : RESULT_GUARD(key_schedules[conn->mode](conn));
346 : 59729 : return S2N_RESULT_OK;
347 : 59731 : }
348 : :
349 : : S2N_RESULT s2n_tls13_key_schedule_reset(struct s2n_connection *conn)
350 : 1060 : {
351 [ # # ][ - + ]: 1060 : RESULT_ENSURE_REF(conn);
352 [ - + ][ # # ]: 1060 : RESULT_ENSURE_REF(conn->initial);
353 : 1060 : conn->client = conn->initial;
354 : 1060 : conn->server = conn->initial;
355 : 1060 : conn->secrets.extract_secret_type = S2N_NONE_SECRET;
356 : 1060 : return S2N_RESULT_OK;
357 : 1060 : }
358 : :
359 : : S2N_RESULT s2n_tls13_key_schedule_generate_key_material(struct s2n_connection *conn,
360 : : s2n_mode sender, struct s2n_key_material *key_material)
361 : 1 : {
362 [ - + ]: 1 : RESULT_GUARD(s2n_key_material_init(key_material, conn));
363 [ - + ]: 1 : if (sender == S2N_CLIENT) {
364 [ # # ]: 0 : RESULT_GUARD(s2n_tls13_key_schedule_get_keying_material(conn, S2N_MASTER_SECRET,
365 : 0 : sender, &key_material->client_iv, &key_material->client_key));
366 : 1 : } else {
367 [ - + ]: 1 : RESULT_GUARD(s2n_tls13_key_schedule_get_keying_material(conn, S2N_MASTER_SECRET,
368 : 1 : sender, &key_material->server_iv, &key_material->server_key));
369 : 1 : }
370 : 1 : return S2N_RESULT_OK;
371 : 1 : }
|