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_secrets.h"
17 : :
18 : : #include "tls/s2n_connection.h"
19 : : #include "tls/s2n_key_log.h"
20 : : #include "tls/s2n_tls13_handshake.h"
21 : : #include "utils/s2n_bitmap.h"
22 : :
23 : : #define S2N_MAX_HASHLEN SHA384_DIGEST_LENGTH
24 : :
25 : 37042 : #define CONN_HMAC_ALG(conn) ((conn)->secure->cipher_suite->prf_alg)
26 : 139055 : #define CONN_SECRETS(conn) ((conn)->secrets.version.tls13)
27 : : #define CONN_HASHES(conn) ((conn)->handshake.hashes)
28 : :
29 : : #define CONN_SECRET(conn, secret) ( \
30 : : (struct s2n_blob){ .data = CONN_SECRETS(conn).secret, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn)) })
31 : : #define CONN_HASH(conn, hash) ( \
32 : : (struct s2n_blob){ .data = CONN_HASHES(conn)->hash, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn)) })
33 : : #define CONN_FINISHED(conn, mode) ( \
34 : : (struct s2n_blob){ .data = (conn)->handshake.mode##_finished, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn)) })
35 : :
36 : : /**
37 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
38 : : *# If a given secret is not available, then the 0-value consisting of a
39 : : *# string of Hash.length bytes set to zeros is used.
40 : : */
41 : : static uint8_t zero_value_bytes[S2N_MAX_HASHLEN] = { 0 };
42 : : #define ZERO_VALUE(hmac_alg) ( \
43 : : (const struct s2n_blob){ .data = zero_value_bytes, .size = s2n_get_hash_len(hmac_alg) })
44 : :
45 : : /**
46 : : * When an operation doesn't need an actual transcript hash,
47 : : * it uses an empty transcript hash as an input instead.
48 : : *
49 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
50 : : *# Note that in some cases a zero-
51 : : *# length Context (indicated by "") is passed to HKDF-Expand-Label
52 : : */
53 : 1090 : #define EMPTY_CONTEXT(hmac_alg) ( \
54 : 1090 : (const struct s2n_blob){ .data = s2n_get_empty_context(hmac_alg), .size = s2n_get_hash_len(hmac_alg) })
55 : :
56 : : static uint8_t s2n_get_hash_len(s2n_hmac_algorithm hmac_alg)
57 : 330213 : {
58 : 330213 : uint8_t hash_size = 0;
59 [ - + ]: 330213 : if (s2n_hmac_digest_size(hmac_alg, &hash_size) != S2N_SUCCESS) {
60 : 0 : return 0;
61 : 0 : }
62 : 330213 : return hash_size;
63 : 330213 : }
64 : :
65 : : static uint8_t *s2n_get_empty_context(s2n_hmac_algorithm hmac_alg)
66 : 18509 : {
67 : 18509 : static uint8_t sha256_empty_digest[S2N_MAX_HASHLEN] = { 0 };
68 : 18509 : static uint8_t sha384_empty_digest[S2N_MAX_HASHLEN] = { 0 };
69 : :
70 : 18509 : switch (hmac_alg) {
71 [ + + ]: 17519 : case S2N_HMAC_SHA256:
72 : 17519 : return sha256_empty_digest;
73 [ + + ]: 990 : case S2N_HMAC_SHA384:
74 : 990 : return sha384_empty_digest;
75 [ - + ]: 0 : default:
76 : 0 : return NULL;
77 : 18509 : }
78 : 18509 : }
79 : :
80 : : static s2n_hmac_algorithm supported_hmacs[] = {
81 : : S2N_HMAC_SHA256,
82 : : S2N_HMAC_SHA384
83 : : };
84 : :
85 : : S2N_RESULT s2n_tls13_empty_transcripts_init()
86 : 545 : {
87 : 545 : DEFER_CLEANUP(struct s2n_hash_state hash = { 0 }, s2n_hash_free);
88 [ - + ]: 545 : RESULT_GUARD_POSIX(s2n_hash_new(&hash));
89 : :
90 : 545 : s2n_hash_algorithm hash_alg = S2N_HASH_NONE;
91 [ + + ]: 1635 : for (size_t i = 0; i < s2n_array_len(supported_hmacs); i++) {
92 : 1090 : s2n_hmac_algorithm hmac_alg = supported_hmacs[i];
93 : 1090 : struct s2n_blob digest = EMPTY_CONTEXT(hmac_alg);
94 : :
95 [ - + ]: 1090 : RESULT_GUARD_POSIX(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
96 [ - + ]: 1090 : RESULT_GUARD_POSIX(s2n_hash_init(&hash, hash_alg));
97 [ - + ]: 1090 : RESULT_GUARD_POSIX(s2n_hash_digest(&hash, digest.data, digest.size));
98 : 1090 : }
99 : :
100 : 545 : return S2N_RESULT_OK;
101 : 545 : }
102 : :
103 : : static S2N_RESULT s2n_calculate_transcript_digest(struct s2n_connection *conn)
104 : 20404 : {
105 [ # # ][ - + ]: 20404 : RESULT_ENSURE_REF(conn);
106 [ # # ][ - + ]: 20404 : RESULT_ENSURE_REF(conn->handshake.hashes);
107 : :
108 : 20404 : s2n_hash_algorithm hash_algorithm = S2N_HASH_NONE;
109 [ - + ]: 20404 : RESULT_GUARD_POSIX(s2n_hmac_hash_alg(CONN_HMAC_ALG(conn), &hash_algorithm));
110 : :
111 : 20404 : uint8_t digest_size = 0;
112 [ - + ]: 20404 : RESULT_GUARD_POSIX(s2n_hash_digest_size(hash_algorithm, &digest_size));
113 : :
114 : 20404 : struct s2n_blob digest = { 0 };
115 [ - + ]: 20404 : RESULT_GUARD_POSIX(s2n_blob_init(&digest, CONN_HASHES(conn)->transcript_hash_digest, digest_size));
116 : :
117 : 20404 : struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
118 [ - + ]: 20404 : RESULT_GUARD(s2n_handshake_copy_hash_state(conn, hash_algorithm, hash_state));
119 [ - + ]: 20404 : RESULT_GUARD_POSIX(s2n_hash_digest(hash_state, digest.data, digest.size));
120 : :
121 : 20404 : return S2N_RESULT_OK;
122 : 20404 : }
123 : :
124 : : static S2N_RESULT s2n_extract_secret(s2n_hmac_algorithm hmac_alg,
125 : : const struct s2n_blob *previous_secret_material, const struct s2n_blob *new_secret_material,
126 : : struct s2n_blob *output)
127 : 25011 : {
128 : : /*
129 : : * TODO: We should be able to reuse the prf_work_space rather
130 : : * than allocating a new HMAC every time.
131 : : * https://github.com/aws/s2n-tls/issues/3206
132 : : */
133 : 25011 : DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
134 [ - + ]: 25011 : RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
135 : :
136 [ - + ]: 25011 : RESULT_GUARD_POSIX(s2n_hkdf_extract(&hmac_state, hmac_alg,
137 : 25011 : previous_secret_material, new_secret_material, output));
138 : 25011 : return S2N_RESULT_OK;
139 : 25011 : }
140 : :
141 : : /**
142 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
143 : : *# Derive-Secret(Secret, Label, Messages) =
144 : : *# HKDF-Expand-Label(Secret, Label,
145 : : *# Transcript-Hash(Messages), Hash.length)
146 : : */
147 : : static S2N_RESULT s2n_derive_secret(s2n_hmac_algorithm hmac_alg,
148 : : const struct s2n_blob *previous_secret_material, const struct s2n_blob *label, const struct s2n_blob *context,
149 : : struct s2n_blob *output)
150 : 58936 : {
151 : : /*
152 : : * TODO: We should be able to reuse the prf_work_space rather
153 : : * than allocating a new HMAC every time.
154 : : * https://github.com/aws/s2n-tls/issues/3206
155 : : */
156 : 58936 : DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
157 [ - + ]: 58936 : RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
158 : :
159 : 58936 : output->size = s2n_get_hash_len(hmac_alg);
160 [ - + ]: 58936 : RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
161 : 58936 : previous_secret_material, label, context, output));
162 : 58936 : return S2N_RESULT_OK;
163 : 58936 : }
164 : :
165 : : static S2N_RESULT s2n_derive_secret_with_context(struct s2n_connection *conn,
166 : : s2n_extract_secret_type_t input_secret_type, const struct s2n_blob *label, message_type_t transcript_end_msg,
167 : : struct s2n_blob *output)
168 : 41516 : {
169 [ # # ][ - + ]: 41516 : RESULT_ENSURE_REF(conn);
170 [ - + ][ # # ]: 41516 : RESULT_ENSURE_REF(label);
171 [ - + ][ # # ]: 41516 : RESULT_ENSURE_REF(output);
172 : :
173 [ - + ][ # # ]: 41516 : RESULT_ENSURE(conn->secrets.extract_secret_type == input_secret_type, S2N_ERR_SECRET_SCHEDULE_STATE);
174 [ + + ][ + - ]: 41516 : RESULT_ENSURE(s2n_conn_get_current_message_type(conn) == transcript_end_msg, S2N_ERR_SECRET_SCHEDULE_STATE);
175 [ - + ]: 41515 : RESULT_GUARD(s2n_derive_secret(CONN_HMAC_ALG(conn), &CONN_SECRET(conn, extract_secret),
176 : 41515 : label, &CONN_HASH(conn, transcript_hash_digest), output));
177 : 41515 : return S2N_RESULT_OK;
178 : 41515 : }
179 : :
180 : : static S2N_RESULT s2n_derive_secret_without_context(struct s2n_connection *conn,
181 : : s2n_extract_secret_type_t input_secret_type, struct s2n_blob *output)
182 : 15237 : {
183 [ - + ][ # # ]: 15237 : RESULT_ENSURE_REF(conn);
184 [ - + ][ # # ]: 15237 : RESULT_ENSURE_REF(output);
185 : :
186 [ - + ][ # # ]: 15237 : RESULT_ENSURE(conn->secrets.extract_secret_type == input_secret_type, S2N_ERR_SECRET_SCHEDULE_STATE);
187 [ - + ]: 15237 : RESULT_GUARD(s2n_derive_secret(CONN_HMAC_ALG(conn), &CONN_SECRET(conn, extract_secret),
188 : 15237 : &s2n_tls13_label_derived_secret, &EMPTY_CONTEXT(CONN_HMAC_ALG(conn)), output));
189 : 15237 : return S2N_RESULT_OK;
190 : 15237 : }
191 : :
192 : : /**
193 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.4.4
194 : : *# The key used to compute the Finished message is computed from the
195 : : *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
196 : : *# Specifically:
197 : : *#
198 : : *# finished_key =
199 : : *# HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
200 : : **/
201 : : static S2N_RESULT s2n_tls13_compute_finished_key(struct s2n_connection *conn,
202 : : const struct s2n_blob *base_key, struct s2n_blob *output)
203 : 17093 : {
204 [ - + ][ # # ]: 17093 : RESULT_ENSURE_REF(conn);
205 [ - + ][ # # ]: 17093 : RESULT_ENSURE_REF(base_key);
206 [ # # ][ - + ]: 17093 : RESULT_ENSURE_REF(output);
207 : :
208 [ - + ]: 17093 : RESULT_GUARD(s2n_handshake_set_finished_len(conn, output->size));
209 : :
210 : : /*
211 : : * TODO: We should be able to reuse the prf_work_space rather
212 : : * than allocating a new HMAC every time.
213 : : */
214 : 17093 : DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
215 [ - + ]: 17093 : RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
216 : :
217 [ - + ]: 17093 : RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, CONN_HMAC_ALG(conn),
218 : 17093 : base_key, &s2n_tls13_label_finished, &(struct s2n_blob){ 0 }, output));
219 : 17093 : return S2N_RESULT_OK;
220 : 17093 : }
221 : :
222 : : static S2N_RESULT s2n_call_secret_callbacks(struct s2n_connection *conn,
223 : : const struct s2n_blob *secret, s2n_secret_type_t secret_type)
224 : 36226 : {
225 [ # # ][ - + ]: 36226 : RESULT_ENSURE_REF(conn);
226 [ - + ][ # # ]: 36226 : RESULT_ENSURE_REF(secret);
227 : :
228 [ + + ][ + - ]: 36226 : if (conn->secret_cb && (s2n_connection_is_quic_enabled(conn) || s2n_in_unit_test())) {
[ # # ]
229 [ - + ]: 10 : RESULT_GUARD_POSIX(conn->secret_cb(conn->secret_cb_context, conn, secret_type,
230 : 10 : secret->data, secret->size));
231 : 10 : }
232 : 36226 : s2n_result_ignore(s2n_key_log_tls13_secret(conn, secret, secret_type));
233 : 36226 : return S2N_RESULT_OK;
234 : 36226 : }
235 : :
236 : : static S2N_RESULT s2n_trigger_secret_callbacks(struct s2n_connection *conn,
237 : : const struct s2n_blob *secret, s2n_extract_secret_type_t secret_type, s2n_mode mode)
238 : 30138 : {
239 [ - + ][ # # ]: 30138 : RESULT_ENSURE_REF(conn);
240 [ # # ][ - + ]: 30138 : RESULT_ENSURE_REF(secret);
241 : :
242 : 30138 : static const s2n_secret_type_t conversions[][2] = {
243 : 30138 : [S2N_EARLY_SECRET] = { S2N_CLIENT_EARLY_TRAFFIC_SECRET, S2N_CLIENT_EARLY_TRAFFIC_SECRET },
244 : 30138 : [S2N_HANDSHAKE_SECRET] = { S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET, S2N_CLIENT_HANDSHAKE_TRAFFIC_SECRET },
245 : 30138 : [S2N_MASTER_SECRET] = { S2N_SERVER_APPLICATION_TRAFFIC_SECRET, S2N_CLIENT_APPLICATION_TRAFFIC_SECRET },
246 : 30138 : };
247 : 30138 : s2n_secret_type_t callback_secret_type = conversions[secret_type][mode];
248 : :
249 [ - + ]: 30138 : RESULT_GUARD(s2n_call_secret_callbacks(conn, secret, callback_secret_type));
250 : 30138 : return S2N_RESULT_OK;
251 : 30138 : }
252 : :
253 : : /**
254 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
255 : : *# 0
256 : : *# |
257 : : *# v
258 : : *# PSK -> HKDF-Extract = Early Secret
259 : : *
260 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
261 : : *# There are multiple potential Early Secret values, depending on which
262 : : *# PSK the server ultimately selects. The client will need to compute
263 : : *# one for each potential PSK
264 : : */
265 : : S2N_RESULT s2n_extract_early_secret(struct s2n_psk *psk)
266 : 2185 : {
267 [ - + ][ # # ]: 2185 : RESULT_ENSURE_REF(psk);
268 [ - + ]: 2185 : RESULT_GUARD_POSIX(s2n_realloc(&psk->early_secret, s2n_get_hash_len(psk->hmac_alg)));
269 [ - + ]: 2185 : RESULT_GUARD(s2n_extract_secret(psk->hmac_alg,
270 : 2185 : &ZERO_VALUE(psk->hmac_alg),
271 : 2185 : &psk->secret,
272 : 2185 : &psk->early_secret));
273 : 2185 : return S2N_RESULT_OK;
274 : 2185 : }
275 : :
276 : : /*
277 : : * When we require an early secret to derive other secrets,
278 : : * either retrieve the early secret stored on the chosen / early data PSK
279 : : * or calculate one using a "zero" PSK.
280 : : */
281 : : static S2N_RESULT s2n_extract_early_secret_for_schedule(struct s2n_connection *conn)
282 : 9232 : {
283 [ # # ][ - + ]: 9232 : RESULT_ENSURE_REF(conn);
284 : :
285 : 9232 : struct s2n_psk *psk = conn->psk_params.chosen_psk;
286 : 9232 : s2n_hmac_algorithm hmac_alg = CONN_HMAC_ALG(conn);
287 : :
288 : : /*
289 : : * If the client is sending early data, then the PSK is always assumed
290 : : * to be the first PSK offered.
291 : : */
292 [ + + ][ + + ]: 9232 : if (conn->mode == S2N_CLIENT && conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
293 [ - + ]: 530 : RESULT_GUARD(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
294 [ # # ][ - + ]: 530 : RESULT_ENSURE_REF(psk);
295 : 530 : }
296 : :
297 : : /**
298 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
299 : : *# if no PSK is selected, it will then need
300 : : *# to compute the Early Secret corresponding to the zero PSK.
301 : : */
302 [ + + ]: 9232 : if (psk == NULL) {
303 [ - + ]: 7589 : RESULT_GUARD(s2n_extract_secret(hmac_alg,
304 : 7589 : &ZERO_VALUE(hmac_alg),
305 : 7589 : &ZERO_VALUE(hmac_alg),
306 : 7589 : &CONN_SECRET(conn, extract_secret)));
307 : 7589 : return S2N_RESULT_OK;
308 : 7589 : }
309 : :
310 : : /*
311 : : * The early secret is required to generate or verify a PSK's binder,
312 : : * so must have already been calculated if a valid PSK exists.
313 : : * Use the early secret stored on the PSK.
314 : : */
315 [ # # ][ - + ]: 1643 : RESULT_ENSURE_EQ(hmac_alg, psk->hmac_alg);
316 [ - + ][ # # ]: 1643 : RESULT_CHECKED_MEMCPY(CONN_SECRETS(conn).extract_secret, psk->early_secret.data, psk->early_secret.size);
[ + - ]
317 : 1643 : return S2N_RESULT_OK;
318 : 1643 : }
319 : :
320 : : /**
321 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
322 : : *# |
323 : : *# +-----> Derive-Secret(., "ext binder" | "res binder", "")
324 : : *# | = binder_key
325 : : */
326 : : S2N_RESULT s2n_derive_binder_key(struct s2n_psk *psk, struct s2n_blob *output)
327 : 2183 : {
328 [ # # ][ - + ]: 2183 : RESULT_ENSURE_REF(psk);
329 [ # # ][ - + ]: 2183 : RESULT_ENSURE_REF(output);
330 : :
331 : 2183 : const struct s2n_blob *label = &s2n_tls13_label_resumption_psk_binder_key;
332 [ + + ]: 2183 : if (psk->type == S2N_PSK_TYPE_EXTERNAL) {
333 : 1941 : label = &s2n_tls13_label_external_psk_binder_key;
334 : 1941 : }
335 [ - + ]: 2183 : RESULT_GUARD(s2n_extract_early_secret(psk));
336 [ - + ]: 2183 : RESULT_GUARD(s2n_derive_secret(psk->hmac_alg,
337 : 2183 : &psk->early_secret,
338 : 2183 : label,
339 : 2183 : &EMPTY_CONTEXT(psk->hmac_alg),
340 : 2183 : output));
341 : 2183 : return S2N_RESULT_OK;
342 : 2183 : }
343 : :
344 : : /**
345 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
346 : : *# |
347 : : *# +-----> Derive-Secret(., "c e traffic", ClientHello)
348 : : *# | = client_early_traffic_secret
349 : : */
350 : : static S2N_RESULT s2n_derive_client_early_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
351 : 676 : {
352 [ - + ]: 676 : RESULT_GUARD(s2n_derive_secret_with_context(conn,
353 : 676 : S2N_EARLY_SECRET,
354 : 676 : &s2n_tls13_label_client_early_traffic_secret,
355 : 676 : CLIENT_HELLO,
356 : 676 : output));
357 : 676 : return S2N_RESULT_OK;
358 : 676 : }
359 : :
360 : : /**
361 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
362 : : *# |
363 : : *# v
364 : : *# Derive-Secret(., "derived", "")
365 : : *# |
366 : : *# v
367 : : *# (EC)DHE -> HKDF-Extract = Handshake Secret
368 : : */
369 : : static S2N_RESULT s2n_extract_handshake_secret(struct s2n_connection *conn)
370 : 8860 : {
371 [ - + ][ # # ]: 8860 : RESULT_ENSURE_REF(conn);
372 : :
373 : 8860 : struct s2n_blob derived_secret = { 0 };
374 : 8860 : uint8_t derived_secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
375 [ - + ]: 8860 : RESULT_GUARD_POSIX(s2n_blob_init(&derived_secret, derived_secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
376 [ - + ]: 8860 : RESULT_GUARD(s2n_derive_secret_without_context(conn, S2N_EARLY_SECRET, &derived_secret));
377 : :
378 : 8860 : DEFER_CLEANUP(struct s2n_blob shared_secret = { 0 }, s2n_free_or_wipe);
379 [ - + ]: 8860 : RESULT_GUARD_POSIX(s2n_tls13_compute_shared_secret(conn, &shared_secret));
380 : :
381 [ - + ]: 8860 : RESULT_GUARD(s2n_extract_secret(CONN_HMAC_ALG(conn),
382 : 8860 : &derived_secret,
383 : 8860 : &shared_secret,
384 : 8860 : &CONN_SECRET(conn, extract_secret)));
385 : :
386 : 8860 : return S2N_RESULT_OK;
387 : 8860 : }
388 : :
389 : : /**
390 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
391 : : *# |
392 : : *# +-----> Derive-Secret(., "c hs traffic",
393 : : *# | ClientHello...ServerHello)
394 : : *# | = client_handshake_traffic_secret
395 : : */
396 : : static S2N_RESULT s2n_derive_client_handshake_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
397 : 8546 : {
398 [ - + ][ # # ]: 8546 : RESULT_ENSURE_REF(conn);
399 [ - + ][ # # ]: 8546 : RESULT_ENSURE_REF(output);
400 : :
401 [ - + ]: 8546 : RESULT_GUARD(s2n_derive_secret_with_context(conn,
402 : 8546 : S2N_HANDSHAKE_SECRET,
403 : 8546 : &s2n_tls13_label_client_handshake_traffic_secret,
404 : 8546 : SERVER_HELLO,
405 : 8546 : output));
406 : :
407 : : /*
408 : : * The client finished key needs to be calculated using the
409 : : * same connection state as the client handshake secret.
410 : : *
411 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.4.4
412 : : *# The key used to compute the Finished message is computed from the
413 : : *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
414 : : */
415 [ - + ]: 8546 : RESULT_GUARD(s2n_tls13_compute_finished_key(conn,
416 : 8546 : output, &CONN_FINISHED(conn, client)));
417 : :
418 : 8546 : return S2N_RESULT_OK;
419 : 8546 : }
420 : :
421 : : /**
422 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
423 : : *# |
424 : : *# +-----> Derive-Secret(., "s hs traffic",
425 : : *# | ClientHello...ServerHello)
426 : : *# | = server_handshake_traffic_secret
427 : : */
428 : : static S2N_RESULT s2n_derive_server_handshake_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
429 : 8547 : {
430 [ - + ][ # # ]: 8547 : RESULT_ENSURE_REF(conn);
431 [ - + ][ # # ]: 8547 : RESULT_ENSURE_REF(output);
432 : :
433 [ - + ]: 8547 : RESULT_GUARD(s2n_derive_secret_with_context(conn,
434 : 8547 : S2N_HANDSHAKE_SECRET,
435 : 8547 : &s2n_tls13_label_server_handshake_traffic_secret,
436 : 8547 : SERVER_HELLO,
437 : 8547 : output));
438 : :
439 : : /*
440 : : * The server finished key needs to be calculated using the
441 : : * same connection state as the server handshake secret.
442 : : *
443 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.4.4
444 : : *# The key used to compute the Finished message is computed from the
445 : : *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
446 : : */
447 [ - + ]: 8547 : RESULT_GUARD(s2n_tls13_compute_finished_key(conn,
448 : 8547 : output, &CONN_FINISHED(conn, server)));
449 : :
450 : 8547 : return S2N_RESULT_OK;
451 : 8547 : }
452 : :
453 : : /**
454 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
455 : : *# v
456 : : *# Derive-Secret(., "derived", "")
457 : : *# |
458 : : *# v
459 : : *# 0 -> HKDF-Extract = Master Secret
460 : : */
461 : : static S2N_RESULT s2n_extract_master_secret(struct s2n_connection *conn)
462 : 6377 : {
463 [ - + ][ # # ]: 6377 : RESULT_ENSURE_REF(conn);
464 : :
465 : 6377 : struct s2n_blob derived_secret = { 0 };
466 : 6377 : uint8_t derived_secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
467 [ - + ]: 6377 : RESULT_GUARD_POSIX(s2n_blob_init(&derived_secret, derived_secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
468 [ - + ]: 6377 : RESULT_GUARD(s2n_derive_secret_without_context(conn, S2N_HANDSHAKE_SECRET, &derived_secret));
469 : :
470 [ - + ]: 6377 : RESULT_GUARD(s2n_extract_secret(CONN_HMAC_ALG(conn),
471 : 6377 : &derived_secret,
472 : 6377 : &ZERO_VALUE(CONN_HMAC_ALG(conn)),
473 : 6377 : &CONN_SECRET(conn, extract_secret)));
474 : 6377 : return S2N_RESULT_OK;
475 : 6377 : }
476 : :
477 : : /**
478 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
479 : : *# |
480 : : *# +-----> Derive-Secret(., "c ap traffic",
481 : : *# | ClientHello...server Finished)
482 : : *# | = client_application_traffic_secret_0
483 : : */
484 : : static S2N_RESULT s2n_derive_client_application_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
485 : 6184 : {
486 [ - + ]: 6184 : RESULT_GUARD(s2n_derive_secret_with_context(conn,
487 : 6184 : S2N_MASTER_SECRET,
488 : 6184 : &s2n_tls13_label_client_application_traffic_secret,
489 : 6184 : SERVER_FINISHED,
490 : 6184 : output));
491 : 6184 : return S2N_RESULT_OK;
492 : 6184 : }
493 : :
494 : : /**
495 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
496 : : *# |
497 : : *# +-----> Derive-Secret(., "s ap traffic",
498 : : *# | ClientHello...server Finished)
499 : : *# | = server_application_traffic_secret_0
500 : : */
501 : : static S2N_RESULT s2n_derive_server_application_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
502 : 6186 : {
503 [ + + ]: 6186 : RESULT_GUARD(s2n_derive_secret_with_context(conn,
504 : 6185 : S2N_MASTER_SECRET,
505 : 6185 : &s2n_tls13_label_server_application_traffic_secret,
506 : 6185 : SERVER_FINISHED,
507 : 6185 : output));
508 : 6185 : return S2N_RESULT_OK;
509 : 6186 : }
510 : :
511 : : /**
512 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
513 : : *# |
514 : : *# +-----> Derive-Secret(., "res master",
515 : : *# ClientHello...client Finished)
516 : : *# = resumption_master_secret
517 : : */
518 : : S2N_RESULT s2n_derive_resumption_master_secret(struct s2n_connection *conn)
519 : 5595 : {
520 [ - + ][ # # ]: 5595 : RESULT_ENSURE_REF(conn);
521 : : /* Secret derivation requires these fields to be non-null. */
522 [ # # ][ - + ]: 5595 : RESULT_ENSURE_REF(conn->secure);
523 [ - + ][ # # ]: 5595 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
524 : :
525 [ - + ]: 5595 : RESULT_GUARD(s2n_derive_secret_with_context(conn,
526 : 5595 : S2N_MASTER_SECRET,
527 : 5595 : &s2n_tls13_label_resumption_master_secret,
528 : 5595 : CLIENT_FINISHED,
529 : 5595 : &CONN_SECRET(conn, resumption_master_secret)));
530 : 5595 : return S2N_RESULT_OK;
531 : 5595 : }
532 : :
533 : : /**
534 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
535 : : *# |
536 : : *# +-----> Derive-Secret(., "exp master",
537 : : *# | ClientHello...server Finished)
538 : : *# | = exporter_master_secret
539 : : */
540 : : S2N_RESULT s2n_derive_exporter_master_secret(struct s2n_connection *conn, struct s2n_blob *secret)
541 : 6394 : {
542 [ - + ][ # # ]: 6394 : RESULT_ENSURE_REF(conn);
543 : : /* Secret derivation requires these fields to be non-null. */
544 [ - + ][ # # ]: 6394 : RESULT_ENSURE_REF(conn->secure);
545 [ # # ][ - + ]: 6394 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
546 : :
547 [ - + ]: 6394 : RESULT_GUARD(s2n_derive_secret_with_context(conn,
548 : 6394 : S2N_MASTER_SECRET,
549 : 6394 : &s2n_tls13_label_exporter_master_secret,
550 : 6394 : SERVER_FINISHED,
551 : 6394 : secret));
552 : :
553 [ - + ]: 6394 : RESULT_GUARD(s2n_call_secret_callbacks(conn, secret, S2N_EXPORTER_SECRET));
554 : :
555 : 6394 : return S2N_RESULT_OK;
556 : 6394 : }
557 : :
558 : : static s2n_result (*extract_methods[])(struct s2n_connection *conn) = {
559 : : [S2N_EARLY_SECRET] = &s2n_extract_early_secret_for_schedule,
560 : : [S2N_HANDSHAKE_SECRET] = &s2n_extract_handshake_secret,
561 : : [S2N_MASTER_SECRET] = &s2n_extract_master_secret,
562 : : };
563 : :
564 : : S2N_RESULT s2n_tls13_extract_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type)
565 : 31977 : {
566 [ + + ][ + - ]: 31977 : RESULT_ENSURE_REF(conn);
567 [ + + ][ + - ]: 31976 : RESULT_ENSURE_REF(conn->secure);
568 [ - + ][ # # ]: 31975 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
569 [ - + ][ # # ]: 31975 : RESULT_ENSURE_REF(conn->handshake.hashes);
570 [ # # ][ - + ]: 31975 : RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET);
571 : :
572 [ # # ][ - + ]: 31975 : RESULT_ENSURE_GTE(secret_type, 0);
573 [ + - ][ + + ]: 31975 : RESULT_ENSURE_LT(secret_type, s2n_array_len(extract_methods));
574 : :
575 : 31970 : s2n_extract_secret_type_t next_secret_type = conn->secrets.extract_secret_type + 1;
576 [ + + ]: 57429 : for (s2n_extract_secret_type_t i = next_secret_type; i <= secret_type; i++) {
577 [ - + ][ # # ]: 25459 : RESULT_ENSURE_REF(extract_methods[i]);
578 [ - + ]: 25459 : RESULT_GUARD(extract_methods[i](conn));
579 : 25459 : conn->secrets.extract_secret_type = i;
580 : 25459 : }
581 : :
582 : 31970 : return S2N_RESULT_OK;
583 : 31970 : }
584 : :
585 : : static s2n_result (*derive_methods[][2])(struct s2n_connection *conn, struct s2n_blob *secret) = {
586 : : [S2N_EARLY_SECRET] = { &s2n_derive_client_early_traffic_secret, &s2n_derive_client_early_traffic_secret },
587 : : [S2N_HANDSHAKE_SECRET] = { &s2n_derive_server_handshake_traffic_secret, &s2n_derive_client_handshake_traffic_secret },
588 : : [S2N_MASTER_SECRET] = { &s2n_derive_server_application_traffic_secret, &s2n_derive_client_application_traffic_secret },
589 : : };
590 : :
591 : : S2N_RESULT s2n_tls13_derive_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
592 : : s2n_mode mode, struct s2n_blob *secret)
593 : 31530 : {
594 [ + + ][ + - ]: 31530 : RESULT_ENSURE_REF(conn);
595 [ + - ][ + + ]: 31529 : RESULT_ENSURE_REF(secret);
596 [ + + ][ + - ]: 31528 : RESULT_ENSURE_REF(conn->secure);
597 [ - + ][ # # ]: 31527 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
598 [ # # ][ - + ]: 31527 : RESULT_ENSURE_REF(conn->handshake.hashes);
599 [ - + ][ # # ]: 31527 : RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET);
600 : :
601 [ + + ]: 31527 : RESULT_GUARD(s2n_tls13_extract_secret(conn, secret_type));
602 : :
603 [ - + ][ # # ]: 31525 : RESULT_ENSURE_GTE(secret_type, 0);
604 [ - + ][ # # ]: 31525 : RESULT_ENSURE_LT(secret_type, s2n_array_len(derive_methods));
605 [ - + ][ # # ]: 31525 : RESULT_ENSURE_REF(derive_methods[secret_type][mode]);
606 [ + + ]: 31525 : RESULT_GUARD(derive_methods[secret_type][mode](conn, secret));
607 : :
608 [ - + ]: 31524 : RESULT_GUARD(s2n_trigger_secret_callbacks(conn, secret, secret_type, mode));
609 : 31524 : return S2N_RESULT_OK;
610 : 31524 : }
611 : :
612 : : S2N_RESULT s2n_tls13_secrets_clean(struct s2n_connection *conn)
613 : 7942 : {
614 [ + + ][ + - ]: 7942 : RESULT_ENSURE_REF(conn);
615 : : /* Secret clean requires these fields to be non-null. */
616 [ # # ][ - + ]: 7941 : RESULT_ENSURE_REF(conn->secure);
617 [ # # ][ - + ]: 7941 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
618 : :
619 [ + + ]: 7941 : if (conn->actual_protocol_version < S2N_TLS13) {
620 : 2660 : return S2N_RESULT_OK;
621 : 2660 : }
622 : :
623 : : /*
624 : : * Wipe base secrets.
625 : : * Not strictly necessary, but probably safer than leaving them.
626 : : * A compromised secret additionally compromises all secrets derived from it,
627 : : * so these are the most sensitive secrets.
628 : : */
629 [ - + ]: 5281 : RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, extract_secret)));
630 : 5281 : conn->secrets.extract_secret_type = S2N_NONE_SECRET;
631 : :
632 : : /* Wipe other secrets no longer needed */
633 [ - + ]: 5281 : RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, client_early_secret)));
634 [ - + ]: 5281 : RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, client_handshake_secret)));
635 [ - + ]: 5281 : RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, server_handshake_secret)));
636 : :
637 : 5281 : return S2N_RESULT_OK;
638 : 5281 : }
639 : :
640 : : S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn)
641 : 94243 : {
642 [ + + ][ + - ]: 94243 : RESULT_ENSURE_REF(conn);
643 [ + + ]: 94242 : if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
644 : 34514 : return S2N_RESULT_OK;
645 : 34514 : }
646 : :
647 : : /* Secret update requires these fields to be non-null. */
648 [ - + ][ # # ]: 59728 : RESULT_ENSURE_REF(conn->secure);
649 [ - + ][ # # ]: 59728 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
650 : :
651 : 59728 : message_type_t message_type = s2n_conn_get_current_message_type(conn);
652 : 59728 : switch (message_type) {
653 [ + + ]: 10579 : case CLIENT_HELLO:
654 [ + + ]: 10579 : if (conn->early_data_state == S2N_EARLY_DATA_REQUESTED
655 [ + + ]: 10579 : || conn->early_data_state == S2N_EARLY_DATA_ACCEPTED) {
656 [ - + ]: 739 : RESULT_GUARD(s2n_calculate_transcript_digest(conn));
657 [ - + ]: 739 : RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_EARLY_SECRET,
658 : 739 : S2N_CLIENT, &CONN_SECRET(conn, client_early_secret)));
659 : 739 : }
660 : 10579 : break;
661 [ + + ]: 10579 : case SERVER_HELLO:
662 [ - + ]: 8760 : RESULT_GUARD(s2n_calculate_transcript_digest(conn));
663 [ - + ]: 8760 : RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
664 : 8760 : S2N_CLIENT, &CONN_SECRET(conn, client_handshake_secret)));
665 [ - + ]: 8760 : RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
666 : 8760 : S2N_SERVER, &CONN_SECRET(conn, server_handshake_secret)));
667 : 8760 : break;
668 [ + + ]: 8760 : case SERVER_FINISHED:
669 [ - + ]: 6392 : RESULT_GUARD(s2n_calculate_transcript_digest(conn));
670 [ - + ]: 6392 : RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
671 : 6392 : S2N_CLIENT, &CONN_SECRET(conn, client_app_secret)));
672 [ - + ]: 6392 : RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
673 : 6392 : S2N_SERVER, &CONN_SECRET(conn, server_app_secret)));
674 [ - + ]: 6392 : RESULT_GUARD(s2n_derive_exporter_master_secret(conn,
675 : 6392 : &CONN_SECRET(conn, exporter_master_secret)));
676 : 6392 : break;
677 [ + + ]: 6392 : case CLIENT_FINISHED:
678 [ - + ]: 5593 : RESULT_GUARD(s2n_calculate_transcript_digest(conn));
679 [ - + ]: 5593 : RESULT_GUARD(s2n_derive_resumption_master_secret(conn));
680 : 5593 : break;
681 [ + + ]: 28404 : default:
682 : 28404 : break;
683 : 59728 : }
684 : 59728 : return S2N_RESULT_OK;
685 : 59728 : }
686 : :
687 : : S2N_RESULT s2n_tls13_secrets_get(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
688 : : s2n_mode mode, struct s2n_blob *secret)
689 : 27819 : {
690 [ + + ][ + - ]: 27819 : RESULT_ENSURE_REF(conn);
691 [ + + ][ + - ]: 27818 : RESULT_ENSURE_REF(secret);
692 : : /* Getting secrets requires these fields to be non-null. */
693 [ + + ][ + - ]: 27817 : RESULT_ENSURE_REF(conn->secure);
694 [ + + ][ + - ]: 27816 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
695 : :
696 [ + + ]: 27815 : bool is_available = (secret_type <= conn->secrets.extract_secret_type)
697 : : /* Unlike the other secrets, we don't wipe the master / app secrets */
698 [ + + ][ + - ]: 27815 : || (secret_type == S2N_MASTER_SECRET && s2n_handshake_is_complete(conn));
699 [ + + ][ + - ]: 27815 : RESULT_ENSURE(is_available, S2N_ERR_SAFETY);
700 : :
701 : 27811 : uint8_t *secrets[][2] = {
702 : 27811 : [S2N_EARLY_SECRET] = { NULL, CONN_SECRETS(conn).client_early_secret },
703 : 27811 : [S2N_HANDSHAKE_SECRET] = { CONN_SECRETS(conn).server_handshake_secret, CONN_SECRETS(conn).client_handshake_secret },
704 : 27811 : [S2N_MASTER_SECRET] = { CONN_SECRETS(conn).server_app_secret, CONN_SECRETS(conn).client_app_secret },
705 : 27811 : };
706 [ + - ][ + + ]: 27811 : RESULT_ENSURE_GT(secret_type, S2N_NONE_SECRET);
707 [ - + ][ # # ]: 27810 : RESULT_ENSURE_LT(secret_type, s2n_array_len(secrets));
708 [ # # ][ - + ]: 27810 : RESULT_ENSURE_REF(secrets[secret_type][mode]);
709 : :
710 : 27810 : secret->size = s2n_get_hash_len(CONN_HMAC_ALG(conn));
711 [ - + ][ # # ]: 27810 : RESULT_CHECKED_MEMCPY(secret->data, secrets[secret_type][mode], secret->size);
[ + - ]
712 [ - + ][ # # ]: 27810 : RESULT_ENSURE_GT(secret->size, 0);
713 : 27810 : return S2N_RESULT_OK;
714 : 27810 : }
715 : :
716 : : /*
717 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-7.5
718 : : *# The exporter value is computed as:
719 : : *#
720 : : *# TLS-Exporter(label, context_value, key_length) =
721 : : *# HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
722 : : *# "exporter", Hash(context_value), key_length)
723 : : */
724 : : int s2n_connection_tls_exporter(struct s2n_connection *conn,
725 : : const uint8_t *label_in, uint32_t label_length,
726 : : const uint8_t *context, uint32_t context_length,
727 : : uint8_t *output_in, uint32_t output_length)
728 : 1 : {
729 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(conn);
730 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(output_in);
731 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(label_in);
732 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(context);
733 [ # # ][ - + ]: 1 : POSIX_ENSURE(s2n_connection_get_protocol_version(conn) == S2N_TLS13, S2N_ERR_INVALID_STATE);
734 : :
735 [ - + ][ # # ]: 1 : POSIX_ENSURE(is_handshake_complete(conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
736 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(conn->secure);
737 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(conn->secure->cipher_suite);
738 : 1 : s2n_hmac_algorithm hmac_alg = conn->secure->cipher_suite->prf_alg;
739 : :
740 : 1 : uint8_t label_bytes[S2N_MAX_HKDF_EXPAND_LABEL_LENGTH] = { 0 };
741 : 1 : struct s2n_blob label = { 0 };
742 [ - + ][ # # ]: 1 : POSIX_ENSURE_LTE(label_length, sizeof(label_bytes));
743 [ - + ][ # # ]: 1 : POSIX_CHECKED_MEMCPY(label_bytes, label_in, label_length);
[ + - ]
744 [ - + ]: 1 : POSIX_GUARD(s2n_blob_init(&label, label_bytes, label_length));
745 : :
746 : 1 : uint8_t derived_secret_bytes[S2N_MAX_DIGEST_LEN] = { 0 };
747 : 1 : struct s2n_blob derived_secret = { 0 };
748 [ - + ][ # # ]: 1 : POSIX_ENSURE_LTE(s2n_get_hash_len(CONN_HMAC_ALG(conn)), S2N_MAX_DIGEST_LEN);
749 [ - + ]: 1 : POSIX_GUARD(s2n_blob_init(&derived_secret,
750 : 1 : derived_secret_bytes, s2n_get_hash_len(CONN_HMAC_ALG(conn))));
751 [ - + ]: 1 : POSIX_GUARD_RESULT(s2n_derive_secret(hmac_alg, &CONN_SECRET(conn, exporter_master_secret),
752 : 1 : &label, &EMPTY_CONTEXT(hmac_alg), &derived_secret));
753 : :
754 : 1 : DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
755 [ - + ]: 1 : POSIX_GUARD(s2n_hmac_new(&hmac_state));
756 : :
757 : 1 : DEFER_CLEANUP(struct s2n_hash_state hash = { 0 }, s2n_hash_free);
758 [ - + ]: 1 : POSIX_GUARD(s2n_hash_new(&hash));
759 : :
760 : 1 : s2n_hash_algorithm hash_alg = { 0 };
761 [ - + ]: 1 : POSIX_GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
762 : 1 : uint8_t digest_bytes[S2N_MAX_DIGEST_LEN] = { 0 };
763 : 1 : struct s2n_blob digest = { 0 };
764 [ - + ][ # # ]: 1 : POSIX_ENSURE_LTE(s2n_get_hash_len(CONN_HMAC_ALG(conn)), S2N_MAX_DIGEST_LEN);
765 [ - + ]: 1 : POSIX_GUARD(s2n_blob_init(&digest, digest_bytes, s2n_get_hash_len(CONN_HMAC_ALG(conn))));
766 : :
767 [ - + ]: 1 : POSIX_GUARD(s2n_hash_init(&hash, hash_alg));
768 [ - + ]: 1 : POSIX_GUARD(s2n_hash_update(&hash, context, context_length));
769 [ - + ]: 1 : POSIX_GUARD(s2n_hash_digest(&hash, digest.data, digest.size));
770 : :
771 : 1 : struct s2n_blob output = { 0 };
772 [ - + ]: 1 : POSIX_GUARD(s2n_blob_init(&output, output_in, output_length));
773 [ - + ]: 1 : POSIX_GUARD(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
774 : 1 : &derived_secret, &s2n_tls13_label_exporter, &digest, &output));
775 : :
776 : 1 : return S2N_SUCCESS;
777 : 1 : }
|