/src/libressl/ssl/tls13_key_schedule.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: tls13_key_schedule.c,v 1.15 2022/07/07 17:09:45 tb Exp $ */ |
2 | | /* |
3 | | * Copyright (c) 2018, Bob Beck <beck@openbsd.org> |
4 | | * |
5 | | * Permission to use, copy, modify, and/or distribute this software for any |
6 | | * purpose with or without fee is hereby granted, provided that the above |
7 | | * copyright notice and this permission notice appear in all copies. |
8 | | * |
9 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
12 | | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
14 | | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
15 | | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | | */ |
17 | | |
18 | | #include <string.h> |
19 | | #include <stdlib.h> |
20 | | |
21 | | #include <openssl/hkdf.h> |
22 | | |
23 | | #include "bytestring.h" |
24 | | #include "tls13_internal.h" |
25 | | |
26 | | int |
27 | | tls13_secret_init(struct tls13_secret *secret, size_t len) |
28 | 2.14k | { |
29 | 2.14k | if (secret->data != NULL) |
30 | 0 | return 0; |
31 | | |
32 | 2.14k | if ((secret->data = calloc(1, len)) == NULL) |
33 | 0 | return 0; |
34 | 2.14k | secret->len = len; |
35 | | |
36 | 2.14k | return 1; |
37 | 2.14k | } |
38 | | |
39 | | void |
40 | | tls13_secret_cleanup(struct tls13_secret *secret) |
41 | 26.4k | { |
42 | 26.4k | freezero(secret->data, secret->len); |
43 | 26.4k | secret->data = NULL; |
44 | 26.4k | secret->len = 0; |
45 | 26.4k | } |
46 | | |
47 | | /* |
48 | | * Allocate a set of secrets for a key schedule using |
49 | | * a size of hash_length from RFC 8446 section 7.1. |
50 | | */ |
51 | | struct tls13_secrets * |
52 | | tls13_secrets_create(const EVP_MD *digest, int resumption) |
53 | 86 | { |
54 | 86 | struct tls13_secrets *secrets = NULL; |
55 | 86 | EVP_MD_CTX *mdctx = NULL; |
56 | 86 | unsigned int mdlen; |
57 | 86 | size_t hash_length; |
58 | | |
59 | 86 | hash_length = EVP_MD_size(digest); |
60 | | |
61 | 86 | if ((secrets = calloc(1, sizeof(struct tls13_secrets))) == NULL) |
62 | 0 | goto err; |
63 | | |
64 | 86 | if (!tls13_secret_init(&secrets->zeros, hash_length)) |
65 | 0 | goto err; |
66 | 86 | if (!tls13_secret_init(&secrets->empty_hash, hash_length)) |
67 | 0 | goto err; |
68 | | |
69 | 86 | if (!tls13_secret_init(&secrets->extracted_early, hash_length)) |
70 | 0 | goto err; |
71 | 86 | if (!tls13_secret_init(&secrets->binder_key, hash_length)) |
72 | 0 | goto err; |
73 | 86 | if (!tls13_secret_init(&secrets->client_early_traffic, hash_length)) |
74 | 0 | goto err; |
75 | 86 | if (!tls13_secret_init(&secrets->early_exporter_master, hash_length)) |
76 | 0 | goto err; |
77 | 86 | if (!tls13_secret_init(&secrets->derived_early, hash_length)) |
78 | 0 | goto err; |
79 | 86 | if (!tls13_secret_init(&secrets->extracted_handshake, hash_length)) |
80 | 0 | goto err; |
81 | 86 | if (!tls13_secret_init(&secrets->client_handshake_traffic, hash_length)) |
82 | 0 | goto err; |
83 | 86 | if (!tls13_secret_init(&secrets->server_handshake_traffic, hash_length)) |
84 | 0 | goto err; |
85 | 86 | if (!tls13_secret_init(&secrets->derived_handshake, hash_length)) |
86 | 0 | goto err; |
87 | 86 | if (!tls13_secret_init(&secrets->extracted_master, hash_length)) |
88 | 0 | goto err; |
89 | 86 | if (!tls13_secret_init(&secrets->client_application_traffic, hash_length)) |
90 | 0 | goto err; |
91 | 86 | if (!tls13_secret_init(&secrets->server_application_traffic, hash_length)) |
92 | 0 | goto err; |
93 | 86 | if (!tls13_secret_init(&secrets->exporter_master, hash_length)) |
94 | 0 | goto err; |
95 | 86 | if (!tls13_secret_init(&secrets->resumption_master, hash_length)) |
96 | 0 | goto err; |
97 | | |
98 | | /* |
99 | | * Calculate the hash of a zero-length string - this is needed during |
100 | | * the "derived" step for key extraction. |
101 | | */ |
102 | 86 | if ((mdctx = EVP_MD_CTX_new()) == NULL) |
103 | 0 | goto err; |
104 | 86 | if (!EVP_DigestInit_ex(mdctx, digest, NULL)) |
105 | 0 | goto err; |
106 | 86 | if (!EVP_DigestUpdate(mdctx, secrets->zeros.data, 0)) |
107 | 0 | goto err; |
108 | 86 | if (!EVP_DigestFinal_ex(mdctx, secrets->empty_hash.data, &mdlen)) |
109 | 0 | goto err; |
110 | 86 | EVP_MD_CTX_free(mdctx); |
111 | 86 | mdctx = NULL; |
112 | | |
113 | 86 | if (secrets->empty_hash.len != mdlen) |
114 | 0 | goto err; |
115 | | |
116 | 86 | secrets->digest = digest; |
117 | 86 | secrets->resumption = resumption; |
118 | 86 | secrets->init_done = 1; |
119 | | |
120 | 86 | return secrets; |
121 | | |
122 | 0 | err: |
123 | 0 | tls13_secrets_destroy(secrets); |
124 | 0 | EVP_MD_CTX_free(mdctx); |
125 | |
|
126 | 0 | return NULL; |
127 | 86 | } |
128 | | |
129 | | void |
130 | | tls13_secrets_destroy(struct tls13_secrets *secrets) |
131 | 24.3k | { |
132 | 24.3k | if (secrets == NULL) |
133 | 24.2k | return; |
134 | | |
135 | | /* you can never be too sure :) */ |
136 | 86 | tls13_secret_cleanup(&secrets->zeros); |
137 | 86 | tls13_secret_cleanup(&secrets->empty_hash); |
138 | | |
139 | 86 | tls13_secret_cleanup(&secrets->extracted_early); |
140 | 86 | tls13_secret_cleanup(&secrets->binder_key); |
141 | 86 | tls13_secret_cleanup(&secrets->client_early_traffic); |
142 | 86 | tls13_secret_cleanup(&secrets->early_exporter_master); |
143 | 86 | tls13_secret_cleanup(&secrets->derived_early); |
144 | 86 | tls13_secret_cleanup(&secrets->extracted_handshake); |
145 | 86 | tls13_secret_cleanup(&secrets->client_handshake_traffic); |
146 | 86 | tls13_secret_cleanup(&secrets->server_handshake_traffic); |
147 | 86 | tls13_secret_cleanup(&secrets->derived_handshake); |
148 | 86 | tls13_secret_cleanup(&secrets->extracted_master); |
149 | 86 | tls13_secret_cleanup(&secrets->client_application_traffic); |
150 | 86 | tls13_secret_cleanup(&secrets->server_application_traffic); |
151 | 86 | tls13_secret_cleanup(&secrets->exporter_master); |
152 | 86 | tls13_secret_cleanup(&secrets->resumption_master); |
153 | | |
154 | 86 | freezero(secrets, sizeof(struct tls13_secrets)); |
155 | 86 | } |
156 | | |
157 | | int |
158 | | tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, |
159 | | const struct tls13_secret *secret, const char *label, |
160 | | const struct tls13_secret *context) |
161 | 1.39k | { |
162 | 1.39k | return tls13_hkdf_expand_label_with_length(out, digest, secret, label, |
163 | 1.39k | strlen(label), context); |
164 | 1.39k | } |
165 | | |
166 | | int |
167 | | tls13_hkdf_expand_label_with_length(struct tls13_secret *out, |
168 | | const EVP_MD *digest, const struct tls13_secret *secret, |
169 | | const uint8_t *label, size_t label_len, const struct tls13_secret *context) |
170 | 1.39k | { |
171 | 1.39k | const char tls13_plabel[] = "tls13 "; |
172 | 1.39k | uint8_t *hkdf_label = NULL; |
173 | 1.39k | size_t hkdf_label_len; |
174 | 1.39k | CBB cbb, child; |
175 | 1.39k | int ret; |
176 | | |
177 | 1.39k | if (!CBB_init(&cbb, 256)) |
178 | 0 | return 0; |
179 | 1.39k | if (!CBB_add_u16(&cbb, out->len)) |
180 | 0 | goto err; |
181 | 1.39k | if (!CBB_add_u8_length_prefixed(&cbb, &child)) |
182 | 0 | goto err; |
183 | 1.39k | if (!CBB_add_bytes(&child, tls13_plabel, strlen(tls13_plabel))) |
184 | 0 | goto err; |
185 | 1.39k | if (!CBB_add_bytes(&child, label, label_len)) |
186 | 0 | goto err; |
187 | 1.39k | if (!CBB_add_u8_length_prefixed(&cbb, &child)) |
188 | 0 | goto err; |
189 | 1.39k | if (!CBB_add_bytes(&child, context->data, context->len)) |
190 | 0 | goto err; |
191 | 1.39k | if (!CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) |
192 | 0 | goto err; |
193 | | |
194 | 1.39k | ret = HKDF_expand(out->data, out->len, digest, secret->data, |
195 | 1.39k | secret->len, hkdf_label, hkdf_label_len); |
196 | | |
197 | 1.39k | free(hkdf_label); |
198 | 1.39k | return(ret); |
199 | 0 | err: |
200 | 0 | CBB_cleanup(&cbb); |
201 | 0 | return(0); |
202 | 1.39k | } |
203 | | |
204 | | int |
205 | | tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, |
206 | | const struct tls13_secret *secret, const char *label, |
207 | | const struct tls13_secret *context) |
208 | 854 | { |
209 | 854 | return tls13_hkdf_expand_label(out, digest, secret, label, context); |
210 | 854 | } |
211 | | |
212 | | int |
213 | | tls13_derive_secret_with_label_length(struct tls13_secret *out, |
214 | | const EVP_MD *digest, const struct tls13_secret *secret, const uint8_t *label, |
215 | | size_t label_len, const struct tls13_secret *context) |
216 | 0 | { |
217 | 0 | return tls13_hkdf_expand_label_with_length(out, digest, secret, label, |
218 | 0 | label_len, context); |
219 | 0 | } |
220 | | |
221 | | int |
222 | | tls13_derive_early_secrets(struct tls13_secrets *secrets, |
223 | | uint8_t *psk, size_t psk_len, const struct tls13_secret *context) |
224 | 86 | { |
225 | 86 | if (!secrets->init_done || secrets->early_done) |
226 | 0 | return 0; |
227 | | |
228 | 86 | if (!HKDF_extract(secrets->extracted_early.data, |
229 | 86 | &secrets->extracted_early.len, secrets->digest, psk, psk_len, |
230 | 86 | secrets->zeros.data, secrets->zeros.len)) |
231 | 0 | return 0; |
232 | | |
233 | 86 | if (secrets->extracted_early.len != secrets->zeros.len) |
234 | 0 | return 0; |
235 | | |
236 | 86 | if (!tls13_derive_secret(&secrets->binder_key, secrets->digest, |
237 | 86 | &secrets->extracted_early, |
238 | 86 | secrets->resumption ? "res binder" : "ext binder", |
239 | 86 | &secrets->empty_hash)) |
240 | 0 | return 0; |
241 | 86 | if (!tls13_derive_secret(&secrets->client_early_traffic, |
242 | 86 | secrets->digest, &secrets->extracted_early, "c e traffic", |
243 | 86 | context)) |
244 | 0 | return 0; |
245 | 86 | if (!tls13_derive_secret(&secrets->early_exporter_master, |
246 | 86 | secrets->digest, &secrets->extracted_early, "e exp master", |
247 | 86 | context)) |
248 | 0 | return 0; |
249 | 86 | if (!tls13_derive_secret(&secrets->derived_early, |
250 | 86 | secrets->digest, &secrets->extracted_early, "derived", |
251 | 86 | &secrets->empty_hash)) |
252 | 0 | return 0; |
253 | | |
254 | | /* RFC 8446 recommends */ |
255 | 86 | if (!secrets->insecure) |
256 | 86 | explicit_bzero(secrets->extracted_early.data, |
257 | 86 | secrets->extracted_early.len); |
258 | 86 | secrets->early_done = 1; |
259 | 86 | return 1; |
260 | 86 | } |
261 | | |
262 | | int |
263 | | tls13_derive_handshake_secrets(struct tls13_secrets *secrets, |
264 | | const uint8_t *ecdhe, size_t ecdhe_len, |
265 | | const struct tls13_secret *context) |
266 | 86 | { |
267 | 86 | if (!secrets->init_done || !secrets->early_done || |
268 | 86 | secrets->handshake_done) |
269 | 0 | return 0; |
270 | | |
271 | 86 | if (!HKDF_extract(secrets->extracted_handshake.data, |
272 | 86 | &secrets->extracted_handshake.len, secrets->digest, |
273 | 86 | ecdhe, ecdhe_len, secrets->derived_early.data, |
274 | 86 | secrets->derived_early.len)) |
275 | 0 | return 0; |
276 | | |
277 | 86 | if (secrets->extracted_handshake.len != secrets->zeros.len) |
278 | 0 | return 0; |
279 | | |
280 | | /* XXX */ |
281 | 86 | if (!secrets->insecure) |
282 | 86 | explicit_bzero(secrets->derived_early.data, |
283 | 86 | secrets->derived_early.len); |
284 | | |
285 | 86 | if (!tls13_derive_secret(&secrets->client_handshake_traffic, |
286 | 86 | secrets->digest, &secrets->extracted_handshake, "c hs traffic", |
287 | 86 | context)) |
288 | 0 | return 0; |
289 | 86 | if (!tls13_derive_secret(&secrets->server_handshake_traffic, |
290 | 86 | secrets->digest, &secrets->extracted_handshake, "s hs traffic", |
291 | 86 | context)) |
292 | 0 | return 0; |
293 | 86 | if (!tls13_derive_secret(&secrets->derived_handshake, |
294 | 86 | secrets->digest, &secrets->extracted_handshake, "derived", |
295 | 86 | &secrets->empty_hash)) |
296 | 0 | return 0; |
297 | | |
298 | | /* RFC 8446 recommends */ |
299 | 86 | if (!secrets->insecure) |
300 | 86 | explicit_bzero(secrets->extracted_handshake.data, |
301 | 86 | secrets->extracted_handshake.len); |
302 | | |
303 | 86 | secrets->handshake_done = 1; |
304 | | |
305 | 86 | return 1; |
306 | 86 | } |
307 | | |
308 | | int |
309 | | tls13_derive_application_secrets(struct tls13_secrets *secrets, |
310 | | const struct tls13_secret *context) |
311 | 63 | { |
312 | 63 | if (!secrets->init_done || !secrets->early_done || |
313 | 63 | !secrets->handshake_done || secrets->schedule_done) |
314 | 0 | return 0; |
315 | | |
316 | 63 | if (!HKDF_extract(secrets->extracted_master.data, |
317 | 63 | &secrets->extracted_master.len, secrets->digest, |
318 | 63 | secrets->zeros.data, secrets->zeros.len, |
319 | 63 | secrets->derived_handshake.data, secrets->derived_handshake.len)) |
320 | 0 | return 0; |
321 | | |
322 | 63 | if (secrets->extracted_master.len != secrets->zeros.len) |
323 | 0 | return 0; |
324 | | |
325 | | /* XXX */ |
326 | 63 | if (!secrets->insecure) |
327 | 63 | explicit_bzero(secrets->derived_handshake.data, |
328 | 63 | secrets->derived_handshake.len); |
329 | | |
330 | 63 | if (!tls13_derive_secret(&secrets->client_application_traffic, |
331 | 63 | secrets->digest, &secrets->extracted_master, "c ap traffic", |
332 | 63 | context)) |
333 | 0 | return 0; |
334 | 63 | if (!tls13_derive_secret(&secrets->server_application_traffic, |
335 | 63 | secrets->digest, &secrets->extracted_master, "s ap traffic", |
336 | 63 | context)) |
337 | 0 | return 0; |
338 | 63 | if (!tls13_derive_secret(&secrets->exporter_master, |
339 | 63 | secrets->digest, &secrets->extracted_master, "exp master", |
340 | 63 | context)) |
341 | 0 | return 0; |
342 | 63 | if (!tls13_derive_secret(&secrets->resumption_master, |
343 | 63 | secrets->digest, &secrets->extracted_master, "res master", |
344 | 63 | context)) |
345 | 0 | return 0; |
346 | | |
347 | | /* RFC 8446 recommends */ |
348 | 63 | if (!secrets->insecure) |
349 | 63 | explicit_bzero(secrets->extracted_master.data, |
350 | 63 | secrets->extracted_master.len); |
351 | | |
352 | 63 | secrets->schedule_done = 1; |
353 | | |
354 | 63 | return 1; |
355 | 63 | } |
356 | | |
357 | | int |
358 | | tls13_update_client_traffic_secret(struct tls13_secrets *secrets) |
359 | 0 | { |
360 | 0 | struct tls13_secret context = { .data = "", .len = 0 }; |
361 | |
|
362 | 0 | if (!secrets->init_done || !secrets->early_done || |
363 | 0 | !secrets->handshake_done || !secrets->schedule_done) |
364 | 0 | return 0; |
365 | | |
366 | 0 | return tls13_hkdf_expand_label(&secrets->client_application_traffic, |
367 | 0 | secrets->digest, &secrets->client_application_traffic, |
368 | 0 | "traffic upd", &context); |
369 | 0 | } |
370 | | |
371 | | int |
372 | | tls13_update_server_traffic_secret(struct tls13_secrets *secrets) |
373 | 0 | { |
374 | 0 | struct tls13_secret context = { .data = "", .len = 0 }; |
375 | |
|
376 | 0 | if (!secrets->init_done || !secrets->early_done || |
377 | 0 | !secrets->handshake_done || !secrets->schedule_done) |
378 | 0 | return 0; |
379 | | |
380 | 0 | return tls13_hkdf_expand_label(&secrets->server_application_traffic, |
381 | 0 | secrets->digest, &secrets->server_application_traffic, |
382 | 0 | "traffic upd", &context); |
383 | 0 | } |