diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/libssl/tls13_key_schedule.c | 458 |
1 files changed, 0 insertions, 458 deletions
diff --git a/src/lib/libssl/tls13_key_schedule.c b/src/lib/libssl/tls13_key_schedule.c deleted file mode 100644 index 05bcf0f006..0000000000 --- a/src/lib/libssl/tls13_key_schedule.c +++ /dev/null | |||
@@ -1,458 +0,0 @@ | |||
1 | /* $OpenBSD: tls13_key_schedule.c,v 1.18 2022/11/26 16:08:56 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 "ssl_local.h" | ||
25 | #include "tls13_internal.h" | ||
26 | |||
27 | int | ||
28 | tls13_secret_init(struct tls13_secret *secret, size_t len) | ||
29 | { | ||
30 | if (secret->data != NULL) | ||
31 | return 0; | ||
32 | |||
33 | if ((secret->data = calloc(1, len)) == NULL) | ||
34 | return 0; | ||
35 | secret->len = len; | ||
36 | |||
37 | return 1; | ||
38 | } | ||
39 | |||
40 | void | ||
41 | tls13_secret_cleanup(struct tls13_secret *secret) | ||
42 | { | ||
43 | freezero(secret->data, secret->len); | ||
44 | secret->data = NULL; | ||
45 | secret->len = 0; | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Allocate a set of secrets for a key schedule using | ||
50 | * a size of hash_length from RFC 8446 section 7.1. | ||
51 | */ | ||
52 | struct tls13_secrets * | ||
53 | tls13_secrets_create(const EVP_MD *digest, int resumption) | ||
54 | { | ||
55 | struct tls13_secrets *secrets = NULL; | ||
56 | EVP_MD_CTX *mdctx = NULL; | ||
57 | unsigned int mdlen; | ||
58 | size_t hash_length; | ||
59 | |||
60 | hash_length = EVP_MD_size(digest); | ||
61 | |||
62 | if ((secrets = calloc(1, sizeof(struct tls13_secrets))) == NULL) | ||
63 | goto err; | ||
64 | |||
65 | if (!tls13_secret_init(&secrets->zeros, hash_length)) | ||
66 | goto err; | ||
67 | if (!tls13_secret_init(&secrets->empty_hash, hash_length)) | ||
68 | goto err; | ||
69 | |||
70 | if (!tls13_secret_init(&secrets->extracted_early, hash_length)) | ||
71 | goto err; | ||
72 | if (!tls13_secret_init(&secrets->binder_key, hash_length)) | ||
73 | goto err; | ||
74 | if (!tls13_secret_init(&secrets->client_early_traffic, hash_length)) | ||
75 | goto err; | ||
76 | if (!tls13_secret_init(&secrets->early_exporter_master, hash_length)) | ||
77 | goto err; | ||
78 | if (!tls13_secret_init(&secrets->derived_early, hash_length)) | ||
79 | goto err; | ||
80 | if (!tls13_secret_init(&secrets->extracted_handshake, hash_length)) | ||
81 | goto err; | ||
82 | if (!tls13_secret_init(&secrets->client_handshake_traffic, hash_length)) | ||
83 | goto err; | ||
84 | if (!tls13_secret_init(&secrets->server_handshake_traffic, hash_length)) | ||
85 | goto err; | ||
86 | if (!tls13_secret_init(&secrets->derived_handshake, hash_length)) | ||
87 | goto err; | ||
88 | if (!tls13_secret_init(&secrets->extracted_master, hash_length)) | ||
89 | goto err; | ||
90 | if (!tls13_secret_init(&secrets->client_application_traffic, hash_length)) | ||
91 | goto err; | ||
92 | if (!tls13_secret_init(&secrets->server_application_traffic, hash_length)) | ||
93 | goto err; | ||
94 | if (!tls13_secret_init(&secrets->exporter_master, hash_length)) | ||
95 | goto err; | ||
96 | if (!tls13_secret_init(&secrets->resumption_master, hash_length)) | ||
97 | goto err; | ||
98 | |||
99 | /* | ||
100 | * Calculate the hash of a zero-length string - this is needed during | ||
101 | * the "derived" step for key extraction. | ||
102 | */ | ||
103 | if ((mdctx = EVP_MD_CTX_new()) == NULL) | ||
104 | goto err; | ||
105 | if (!EVP_DigestInit_ex(mdctx, digest, NULL)) | ||
106 | goto err; | ||
107 | if (!EVP_DigestUpdate(mdctx, secrets->zeros.data, 0)) | ||
108 | goto err; | ||
109 | if (!EVP_DigestFinal_ex(mdctx, secrets->empty_hash.data, &mdlen)) | ||
110 | goto err; | ||
111 | EVP_MD_CTX_free(mdctx); | ||
112 | mdctx = NULL; | ||
113 | |||
114 | if (secrets->empty_hash.len != mdlen) | ||
115 | goto err; | ||
116 | |||
117 | secrets->digest = digest; | ||
118 | secrets->resumption = resumption; | ||
119 | secrets->init_done = 1; | ||
120 | |||
121 | return secrets; | ||
122 | |||
123 | err: | ||
124 | tls13_secrets_destroy(secrets); | ||
125 | EVP_MD_CTX_free(mdctx); | ||
126 | |||
127 | return NULL; | ||
128 | } | ||
129 | |||
130 | void | ||
131 | tls13_secrets_destroy(struct tls13_secrets *secrets) | ||
132 | { | ||
133 | if (secrets == NULL) | ||
134 | return; | ||
135 | |||
136 | /* you can never be too sure :) */ | ||
137 | tls13_secret_cleanup(&secrets->zeros); | ||
138 | tls13_secret_cleanup(&secrets->empty_hash); | ||
139 | |||
140 | tls13_secret_cleanup(&secrets->extracted_early); | ||
141 | tls13_secret_cleanup(&secrets->binder_key); | ||
142 | tls13_secret_cleanup(&secrets->client_early_traffic); | ||
143 | tls13_secret_cleanup(&secrets->early_exporter_master); | ||
144 | tls13_secret_cleanup(&secrets->derived_early); | ||
145 | tls13_secret_cleanup(&secrets->extracted_handshake); | ||
146 | tls13_secret_cleanup(&secrets->client_handshake_traffic); | ||
147 | tls13_secret_cleanup(&secrets->server_handshake_traffic); | ||
148 | tls13_secret_cleanup(&secrets->derived_handshake); | ||
149 | tls13_secret_cleanup(&secrets->extracted_master); | ||
150 | tls13_secret_cleanup(&secrets->client_application_traffic); | ||
151 | tls13_secret_cleanup(&secrets->server_application_traffic); | ||
152 | tls13_secret_cleanup(&secrets->exporter_master); | ||
153 | tls13_secret_cleanup(&secrets->resumption_master); | ||
154 | |||
155 | freezero(secrets, sizeof(struct tls13_secrets)); | ||
156 | } | ||
157 | |||
158 | int | ||
159 | tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, | ||
160 | const struct tls13_secret *secret, const char *label, | ||
161 | const struct tls13_secret *context) | ||
162 | { | ||
163 | return tls13_hkdf_expand_label_with_length(out, digest, secret, label, | ||
164 | strlen(label), context); | ||
165 | } | ||
166 | |||
167 | int | ||
168 | tls13_hkdf_expand_label_with_length(struct tls13_secret *out, | ||
169 | const EVP_MD *digest, const struct tls13_secret *secret, | ||
170 | const uint8_t *label, size_t label_len, const struct tls13_secret *context) | ||
171 | { | ||
172 | const char tls13_plabel[] = "tls13 "; | ||
173 | uint8_t *hkdf_label = NULL; | ||
174 | size_t hkdf_label_len; | ||
175 | CBB cbb, child; | ||
176 | int ret; | ||
177 | |||
178 | if (!CBB_init(&cbb, 256)) | ||
179 | goto err; | ||
180 | |||
181 | if (out->data == NULL || out->len == 0) | ||
182 | goto err; | ||
183 | |||
184 | if (!CBB_add_u16(&cbb, out->len)) | ||
185 | goto err; | ||
186 | if (!CBB_add_u8_length_prefixed(&cbb, &child)) | ||
187 | goto err; | ||
188 | if (!CBB_add_bytes(&child, tls13_plabel, strlen(tls13_plabel))) | ||
189 | goto err; | ||
190 | if (!CBB_add_bytes(&child, label, label_len)) | ||
191 | goto err; | ||
192 | if (!CBB_add_u8_length_prefixed(&cbb, &child)) | ||
193 | goto err; | ||
194 | if (!CBB_add_bytes(&child, context->data, context->len)) | ||
195 | goto err; | ||
196 | if (!CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) | ||
197 | goto err; | ||
198 | |||
199 | ret = HKDF_expand(out->data, out->len, digest, secret->data, | ||
200 | secret->len, hkdf_label, hkdf_label_len); | ||
201 | |||
202 | free(hkdf_label); | ||
203 | return(ret); | ||
204 | err: | ||
205 | CBB_cleanup(&cbb); | ||
206 | return(0); | ||
207 | } | ||
208 | |||
209 | int | ||
210 | tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, | ||
211 | const struct tls13_secret *secret, const char *label, | ||
212 | const struct tls13_secret *context) | ||
213 | { | ||
214 | return tls13_hkdf_expand_label(out, digest, secret, label, context); | ||
215 | } | ||
216 | |||
217 | int | ||
218 | tls13_derive_secret_with_label_length(struct tls13_secret *out, | ||
219 | const EVP_MD *digest, const struct tls13_secret *secret, const uint8_t *label, | ||
220 | size_t label_len, const struct tls13_secret *context) | ||
221 | { | ||
222 | return tls13_hkdf_expand_label_with_length(out, digest, secret, label, | ||
223 | label_len, context); | ||
224 | } | ||
225 | |||
226 | int | ||
227 | tls13_derive_early_secrets(struct tls13_secrets *secrets, | ||
228 | uint8_t *psk, size_t psk_len, const struct tls13_secret *context) | ||
229 | { | ||
230 | if (!secrets->init_done || secrets->early_done) | ||
231 | return 0; | ||
232 | |||
233 | if (!HKDF_extract(secrets->extracted_early.data, | ||
234 | &secrets->extracted_early.len, secrets->digest, psk, psk_len, | ||
235 | secrets->zeros.data, secrets->zeros.len)) | ||
236 | return 0; | ||
237 | |||
238 | if (secrets->extracted_early.len != secrets->zeros.len) | ||
239 | return 0; | ||
240 | |||
241 | if (!tls13_derive_secret(&secrets->binder_key, secrets->digest, | ||
242 | &secrets->extracted_early, | ||
243 | secrets->resumption ? "res binder" : "ext binder", | ||
244 | &secrets->empty_hash)) | ||
245 | return 0; | ||
246 | if (!tls13_derive_secret(&secrets->client_early_traffic, | ||
247 | secrets->digest, &secrets->extracted_early, "c e traffic", | ||
248 | context)) | ||
249 | return 0; | ||
250 | if (!tls13_derive_secret(&secrets->early_exporter_master, | ||
251 | secrets->digest, &secrets->extracted_early, "e exp master", | ||
252 | context)) | ||
253 | return 0; | ||
254 | if (!tls13_derive_secret(&secrets->derived_early, | ||
255 | secrets->digest, &secrets->extracted_early, "derived", | ||
256 | &secrets->empty_hash)) | ||
257 | return 0; | ||
258 | |||
259 | /* RFC 8446 recommends */ | ||
260 | if (!secrets->insecure) | ||
261 | explicit_bzero(secrets->extracted_early.data, | ||
262 | secrets->extracted_early.len); | ||
263 | secrets->early_done = 1; | ||
264 | return 1; | ||
265 | } | ||
266 | |||
267 | int | ||
268 | tls13_derive_handshake_secrets(struct tls13_secrets *secrets, | ||
269 | const uint8_t *ecdhe, size_t ecdhe_len, | ||
270 | const struct tls13_secret *context) | ||
271 | { | ||
272 | if (!secrets->init_done || !secrets->early_done || | ||
273 | secrets->handshake_done) | ||
274 | return 0; | ||
275 | |||
276 | if (!HKDF_extract(secrets->extracted_handshake.data, | ||
277 | &secrets->extracted_handshake.len, secrets->digest, | ||
278 | ecdhe, ecdhe_len, secrets->derived_early.data, | ||
279 | secrets->derived_early.len)) | ||
280 | return 0; | ||
281 | |||
282 | if (secrets->extracted_handshake.len != secrets->zeros.len) | ||
283 | return 0; | ||
284 | |||
285 | /* XXX */ | ||
286 | if (!secrets->insecure) | ||
287 | explicit_bzero(secrets->derived_early.data, | ||
288 | secrets->derived_early.len); | ||
289 | |||
290 | if (!tls13_derive_secret(&secrets->client_handshake_traffic, | ||
291 | secrets->digest, &secrets->extracted_handshake, "c hs traffic", | ||
292 | context)) | ||
293 | return 0; | ||
294 | if (!tls13_derive_secret(&secrets->server_handshake_traffic, | ||
295 | secrets->digest, &secrets->extracted_handshake, "s hs traffic", | ||
296 | context)) | ||
297 | return 0; | ||
298 | if (!tls13_derive_secret(&secrets->derived_handshake, | ||
299 | secrets->digest, &secrets->extracted_handshake, "derived", | ||
300 | &secrets->empty_hash)) | ||
301 | return 0; | ||
302 | |||
303 | /* RFC 8446 recommends */ | ||
304 | if (!secrets->insecure) | ||
305 | explicit_bzero(secrets->extracted_handshake.data, | ||
306 | secrets->extracted_handshake.len); | ||
307 | |||
308 | secrets->handshake_done = 1; | ||
309 | |||
310 | return 1; | ||
311 | } | ||
312 | |||
313 | int | ||
314 | tls13_derive_application_secrets(struct tls13_secrets *secrets, | ||
315 | const struct tls13_secret *context) | ||
316 | { | ||
317 | if (!secrets->init_done || !secrets->early_done || | ||
318 | !secrets->handshake_done || secrets->schedule_done) | ||
319 | return 0; | ||
320 | |||
321 | if (!HKDF_extract(secrets->extracted_master.data, | ||
322 | &secrets->extracted_master.len, secrets->digest, | ||
323 | secrets->zeros.data, secrets->zeros.len, | ||
324 | secrets->derived_handshake.data, secrets->derived_handshake.len)) | ||
325 | return 0; | ||
326 | |||
327 | if (secrets->extracted_master.len != secrets->zeros.len) | ||
328 | return 0; | ||
329 | |||
330 | /* XXX */ | ||
331 | if (!secrets->insecure) | ||
332 | explicit_bzero(secrets->derived_handshake.data, | ||
333 | secrets->derived_handshake.len); | ||
334 | |||
335 | if (!tls13_derive_secret(&secrets->client_application_traffic, | ||
336 | secrets->digest, &secrets->extracted_master, "c ap traffic", | ||
337 | context)) | ||
338 | return 0; | ||
339 | if (!tls13_derive_secret(&secrets->server_application_traffic, | ||
340 | secrets->digest, &secrets->extracted_master, "s ap traffic", | ||
341 | context)) | ||
342 | return 0; | ||
343 | if (!tls13_derive_secret(&secrets->exporter_master, | ||
344 | secrets->digest, &secrets->extracted_master, "exp master", | ||
345 | context)) | ||
346 | return 0; | ||
347 | if (!tls13_derive_secret(&secrets->resumption_master, | ||
348 | secrets->digest, &secrets->extracted_master, "res master", | ||
349 | context)) | ||
350 | return 0; | ||
351 | |||
352 | /* RFC 8446 recommends */ | ||
353 | if (!secrets->insecure) | ||
354 | explicit_bzero(secrets->extracted_master.data, | ||
355 | secrets->extracted_master.len); | ||
356 | |||
357 | secrets->schedule_done = 1; | ||
358 | |||
359 | return 1; | ||
360 | } | ||
361 | |||
362 | int | ||
363 | tls13_update_client_traffic_secret(struct tls13_secrets *secrets) | ||
364 | { | ||
365 | struct tls13_secret context = { .data = "", .len = 0 }; | ||
366 | |||
367 | if (!secrets->init_done || !secrets->early_done || | ||
368 | !secrets->handshake_done || !secrets->schedule_done) | ||
369 | return 0; | ||
370 | |||
371 | return tls13_hkdf_expand_label(&secrets->client_application_traffic, | ||
372 | secrets->digest, &secrets->client_application_traffic, | ||
373 | "traffic upd", &context); | ||
374 | } | ||
375 | |||
376 | int | ||
377 | tls13_update_server_traffic_secret(struct tls13_secrets *secrets) | ||
378 | { | ||
379 | struct tls13_secret context = { .data = "", .len = 0 }; | ||
380 | |||
381 | if (!secrets->init_done || !secrets->early_done || | ||
382 | !secrets->handshake_done || !secrets->schedule_done) | ||
383 | return 0; | ||
384 | |||
385 | return tls13_hkdf_expand_label(&secrets->server_application_traffic, | ||
386 | secrets->digest, &secrets->server_application_traffic, | ||
387 | "traffic upd", &context); | ||
388 | } | ||
389 | |||
390 | int | ||
391 | tls13_exporter(struct tls13_ctx *ctx, const uint8_t *label, size_t label_len, | ||
392 | const uint8_t *context_value, size_t context_value_len, uint8_t *out, | ||
393 | size_t out_len) | ||
394 | { | ||
395 | struct tls13_secret context, export_out, export_secret; | ||
396 | struct tls13_secrets *secrets = ctx->hs->tls13.secrets; | ||
397 | EVP_MD_CTX *md_ctx = NULL; | ||
398 | unsigned int md_out_len; | ||
399 | int md_len; | ||
400 | int ret = 0; | ||
401 | |||
402 | /* | ||
403 | * RFC 8446 Section 7.5. | ||
404 | */ | ||
405 | |||
406 | memset(&context, 0, sizeof(context)); | ||
407 | memset(&export_secret, 0, sizeof(export_secret)); | ||
408 | |||
409 | export_out.data = out; | ||
410 | export_out.len = out_len; | ||
411 | |||
412 | if (!ctx->handshake_completed) | ||
413 | return 0; | ||
414 | |||
415 | md_len = EVP_MD_size(secrets->digest); | ||
416 | if (md_len <= 0 || md_len > EVP_MAX_MD_SIZE) | ||
417 | goto err; | ||
418 | |||
419 | if (!tls13_secret_init(&export_secret, md_len)) | ||
420 | goto err; | ||
421 | if (!tls13_secret_init(&context, md_len)) | ||
422 | goto err; | ||
423 | |||
424 | /* In TLSv1.3 no context is equivalent to an empty context. */ | ||
425 | if (context_value == NULL) { | ||
426 | context_value = ""; | ||
427 | context_value_len = 0; | ||
428 | } | ||
429 | |||
430 | if ((md_ctx = EVP_MD_CTX_new()) == NULL) | ||
431 | goto err; | ||
432 | if (!EVP_DigestInit_ex(md_ctx, secrets->digest, NULL)) | ||
433 | goto err; | ||
434 | if (!EVP_DigestUpdate(md_ctx, context_value, context_value_len)) | ||
435 | goto err; | ||
436 | if (!EVP_DigestFinal_ex(md_ctx, context.data, &md_out_len)) | ||
437 | goto err; | ||
438 | if (md_len != md_out_len) | ||
439 | goto err; | ||
440 | |||
441 | if (!tls13_derive_secret_with_label_length(&export_secret, | ||
442 | secrets->digest, &secrets->exporter_master, label, label_len, | ||
443 | &secrets->empty_hash)) | ||
444 | goto err; | ||
445 | |||
446 | if (!tls13_hkdf_expand_label(&export_out, secrets->digest, | ||
447 | &export_secret, "exporter", &context)) | ||
448 | goto err; | ||
449 | |||
450 | ret = 1; | ||
451 | |||
452 | err: | ||
453 | EVP_MD_CTX_free(md_ctx); | ||
454 | tls13_secret_cleanup(&context); | ||
455 | tls13_secret_cleanup(&export_secret); | ||
456 | |||
457 | return ret; | ||
458 | } | ||