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