1 /* $OpenBSD: tls13_key_schedule.c,v 1.15 2022/07/07 17:09:45 tb Exp $ */
3 * Copyright (c) 2018, Bob Beck <beck@openbsd.org>
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.
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.
21 #include <openssl/hkdf.h>
23 #include "bytestring.h"
24 #include "tls13_internal.h"
27 tls13_secret_init(struct tls13_secret *secret, size_t len)
29 if (secret->data != NULL)
32 if ((secret->data = calloc(1, len)) == NULL)
40 tls13_secret_cleanup(struct tls13_secret *secret)
42 freezero(secret->data, secret->len);
48 * Allocate a set of secrets for a key schedule using
49 * a size of hash_length from RFC 8446 section 7.1.
51 struct tls13_secrets *
52 tls13_secrets_create(const EVP_MD *digest, int resumption)
54 struct tls13_secrets *secrets = NULL;
55 EVP_MD_CTX *mdctx = NULL;
59 hash_length = EVP_MD_size(digest);
61 if ((secrets = calloc(1, sizeof(struct tls13_secrets))) == NULL)
64 if (!tls13_secret_init(&secrets->zeros, hash_length))
66 if (!tls13_secret_init(&secrets->empty_hash, hash_length))
69 if (!tls13_secret_init(&secrets->extracted_early, hash_length))
71 if (!tls13_secret_init(&secrets->binder_key, hash_length))
73 if (!tls13_secret_init(&secrets->client_early_traffic, hash_length))
75 if (!tls13_secret_init(&secrets->early_exporter_master, hash_length))
77 if (!tls13_secret_init(&secrets->derived_early, hash_length))
79 if (!tls13_secret_init(&secrets->extracted_handshake, hash_length))
81 if (!tls13_secret_init(&secrets->client_handshake_traffic, hash_length))
83 if (!tls13_secret_init(&secrets->server_handshake_traffic, hash_length))
85 if (!tls13_secret_init(&secrets->derived_handshake, hash_length))
87 if (!tls13_secret_init(&secrets->extracted_master, hash_length))
89 if (!tls13_secret_init(&secrets->client_application_traffic, hash_length))
91 if (!tls13_secret_init(&secrets->server_application_traffic, hash_length))
93 if (!tls13_secret_init(&secrets->exporter_master, hash_length))
95 if (!tls13_secret_init(&secrets->resumption_master, hash_length))
99 * Calculate the hash of a zero-length string - this is needed during
100 * the "derived" step for key extraction.
102 if ((mdctx = EVP_MD_CTX_new()) == NULL)
104 if (!EVP_DigestInit_ex(mdctx, digest, NULL))
106 if (!EVP_DigestUpdate(mdctx, secrets->zeros.data, 0))
108 if (!EVP_DigestFinal_ex(mdctx, secrets->empty_hash.data, &mdlen))
110 EVP_MD_CTX_free(mdctx);
113 if (secrets->empty_hash.len != mdlen)
116 secrets->digest = digest;
117 secrets->resumption = resumption;
118 secrets->init_done = 1;
123 tls13_secrets_destroy(secrets);
124 EVP_MD_CTX_free(mdctx);
130 tls13_secrets_destroy(struct tls13_secrets *secrets)
135 /* you can never be too sure :) */
136 tls13_secret_cleanup(&secrets->zeros);
137 tls13_secret_cleanup(&secrets->empty_hash);
139 tls13_secret_cleanup(&secrets->extracted_early);
140 tls13_secret_cleanup(&secrets->binder_key);
141 tls13_secret_cleanup(&secrets->client_early_traffic);
142 tls13_secret_cleanup(&secrets->early_exporter_master);
143 tls13_secret_cleanup(&secrets->derived_early);
144 tls13_secret_cleanup(&secrets->extracted_handshake);
145 tls13_secret_cleanup(&secrets->client_handshake_traffic);
146 tls13_secret_cleanup(&secrets->server_handshake_traffic);
147 tls13_secret_cleanup(&secrets->derived_handshake);
148 tls13_secret_cleanup(&secrets->extracted_master);
149 tls13_secret_cleanup(&secrets->client_application_traffic);
150 tls13_secret_cleanup(&secrets->server_application_traffic);
151 tls13_secret_cleanup(&secrets->exporter_master);
152 tls13_secret_cleanup(&secrets->resumption_master);
154 freezero(secrets, sizeof(struct tls13_secrets));
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)
162 return tls13_hkdf_expand_label_with_length(out, digest, secret, label,
163 strlen(label), context);
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)
171 const char tls13_plabel[] = "tls13 ";
172 uint8_t *hkdf_label = NULL;
173 size_t hkdf_label_len;
177 if (!CBB_init(&cbb, 256))
179 if (!CBB_add_u16(&cbb, out->len))
181 if (!CBB_add_u8_length_prefixed(&cbb, &child))
183 if (!CBB_add_bytes(&child, tls13_plabel, strlen(tls13_plabel)))
185 if (!CBB_add_bytes(&child, label, label_len))
187 if (!CBB_add_u8_length_prefixed(&cbb, &child))
189 if (!CBB_add_bytes(&child, context->data, context->len))
191 if (!CBB_finish(&cbb, &hkdf_label, &hkdf_label_len))
194 ret = HKDF_expand(out->data, out->len, digest, secret->data,
195 secret->len, hkdf_label, hkdf_label_len);
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)
209 return tls13_hkdf_expand_label(out, digest, secret, label, context);
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)
217 return tls13_hkdf_expand_label_with_length(out, digest, secret, label,
222 tls13_derive_early_secrets(struct tls13_secrets *secrets,
223 uint8_t *psk, size_t psk_len, const struct tls13_secret *context)
225 if (!secrets->init_done || secrets->early_done)
228 if (!HKDF_extract(secrets->extracted_early.data,
229 &secrets->extracted_early.len, secrets->digest, psk, psk_len,
230 secrets->zeros.data, secrets->zeros.len))
233 if (secrets->extracted_early.len != secrets->zeros.len)
236 if (!tls13_derive_secret(&secrets->binder_key, secrets->digest,
237 &secrets->extracted_early,
238 secrets->resumption ? "res binder" : "ext binder",
239 &secrets->empty_hash))
241 if (!tls13_derive_secret(&secrets->client_early_traffic,
242 secrets->digest, &secrets->extracted_early, "c e traffic",
245 if (!tls13_derive_secret(&secrets->early_exporter_master,
246 secrets->digest, &secrets->extracted_early, "e exp master",
249 if (!tls13_derive_secret(&secrets->derived_early,
250 secrets->digest, &secrets->extracted_early, "derived",
251 &secrets->empty_hash))
254 /* RFC 8446 recommends */
255 if (!secrets->insecure)
256 explicit_bzero(secrets->extracted_early.data,
257 secrets->extracted_early.len);
258 secrets->early_done = 1;
263 tls13_derive_handshake_secrets(struct tls13_secrets *secrets,
264 const uint8_t *ecdhe, size_t ecdhe_len,
265 const struct tls13_secret *context)
267 if (!secrets->init_done || !secrets->early_done ||
268 secrets->handshake_done)
271 if (!HKDF_extract(secrets->extracted_handshake.data,
272 &secrets->extracted_handshake.len, secrets->digest,
273 ecdhe, ecdhe_len, secrets->derived_early.data,
274 secrets->derived_early.len))
277 if (secrets->extracted_handshake.len != secrets->zeros.len)
281 if (!secrets->insecure)
282 explicit_bzero(secrets->derived_early.data,
283 secrets->derived_early.len);
285 if (!tls13_derive_secret(&secrets->client_handshake_traffic,
286 secrets->digest, &secrets->extracted_handshake, "c hs traffic",
289 if (!tls13_derive_secret(&secrets->server_handshake_traffic,
290 secrets->digest, &secrets->extracted_handshake, "s hs traffic",
293 if (!tls13_derive_secret(&secrets->derived_handshake,
294 secrets->digest, &secrets->extracted_handshake, "derived",
295 &secrets->empty_hash))
298 /* RFC 8446 recommends */
299 if (!secrets->insecure)
300 explicit_bzero(secrets->extracted_handshake.data,
301 secrets->extracted_handshake.len);
303 secrets->handshake_done = 1;
309 tls13_derive_application_secrets(struct tls13_secrets *secrets,
310 const struct tls13_secret *context)
312 if (!secrets->init_done || !secrets->early_done ||
313 !secrets->handshake_done || secrets->schedule_done)
316 if (!HKDF_extract(secrets->extracted_master.data,
317 &secrets->extracted_master.len, secrets->digest,
318 secrets->zeros.data, secrets->zeros.len,
319 secrets->derived_handshake.data, secrets->derived_handshake.len))
322 if (secrets->extracted_master.len != secrets->zeros.len)
326 if (!secrets->insecure)
327 explicit_bzero(secrets->derived_handshake.data,
328 secrets->derived_handshake.len);
330 if (!tls13_derive_secret(&secrets->client_application_traffic,
331 secrets->digest, &secrets->extracted_master, "c ap traffic",
334 if (!tls13_derive_secret(&secrets->server_application_traffic,
335 secrets->digest, &secrets->extracted_master, "s ap traffic",
338 if (!tls13_derive_secret(&secrets->exporter_master,
339 secrets->digest, &secrets->extracted_master, "exp master",
342 if (!tls13_derive_secret(&secrets->resumption_master,
343 secrets->digest, &secrets->extracted_master, "res master",
347 /* RFC 8446 recommends */
348 if (!secrets->insecure)
349 explicit_bzero(secrets->extracted_master.data,
350 secrets->extracted_master.len);
352 secrets->schedule_done = 1;
358 tls13_update_client_traffic_secret(struct tls13_secrets *secrets)
360 struct tls13_secret context = { .data = "", .len = 0 };
362 if (!secrets->init_done || !secrets->early_done ||
363 !secrets->handshake_done || !secrets->schedule_done)
366 return tls13_hkdf_expand_label(&secrets->client_application_traffic,
367 secrets->digest, &secrets->client_application_traffic,
368 "traffic upd", &context);
372 tls13_update_server_traffic_secret(struct tls13_secrets *secrets)
374 struct tls13_secret context = { .data = "", .len = 0 };
376 if (!secrets->init_done || !secrets->early_done ||
377 !secrets->handshake_done || !secrets->schedule_done)
380 return tls13_hkdf_expand_label(&secrets->server_application_traffic,
381 secrets->digest, &secrets->server_application_traffic,
382 "traffic upd", &context);