iPXE
tlskey.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/** @file
28 *
29 * TLS key schedules
30 *
31 * The TLS key schedule is responsible for maintaining the running
32 * handshake transcript digest, for deriving key material from the
33 * shared secret that was negotiated by a key exchange mechanism, and
34 * for performing all cryptographic calculations required by the TLS
35 * protocol.
36 *
37 * A single abstraction of a key schedule is defined that is
38 * independent of the TLS protocol version. Three implementations of
39 * this abstraction are provided:
40 *
41 * - a TLS version 1.3 key schedule using HKDF
42 *
43 * - a TLS version 1.2 key schedule using PRF based on P_Hash()
44 *
45 * - a TLS version 1.0/1.1 key schedule using PRF based on P_MD5()+P_SHA1()
46 *
47 * The basic set of operations is as required by the TLS protocol:
48 *
49 * - Start the key schedule by specifying the key schedule
50 * implementation to be used along with the handshake digest
51 * algorithm
52 *
53 * - Add each handshake record to the running transcript digest
54 *
55 * - Apply a shared secret (e.g. a pre-master secret that was agreed
56 * using Ephemeral Diffie-Hellman key exchange)
57 *
58 * - Derive a master secret from the shared secret
59 *
60 * - Derive client and server verification data for the Finished
61 * handshake records
62 *
63 * - Derive cipher keys, fixed IVs, and MAC secrets
64 *
65 * - Derive digest values to be signed or verified (e.g. for
66 * CertificateVerify and ServerKeyExchange)
67 *
68 * - Save pre-shared key for future session resumption
69 *
70 * - Load pre-shared key to resume a session
71 *
72 * The key schedule is responsible only for raw key material: it has
73 * no notion of the peer identity and so is fundamentally anonymous in
74 * nature.
75 *
76 * The separate secure channel abstraction handles all concepts of
77 * peer identity. The key schedule provides the cryptographic
78 * operations and properties that are documented as required by the
79 * secure channel, e.g. the calculations required to demonstrate or
80 * verify possession of key material.
81 *
82 */
83
84#include <string.h>
85#include <stdio.h>
86#include <errno.h>
87#include <byteswap.h>
88#include <ipxe/malloc.h>
89#include <ipxe/hkdf.h>
90#include <ipxe/hmac.h>
91#include <ipxe/md5_sha1.h>
92#include <ipxe/tlskey.h>
93
94/*****************************************************************************
95 *
96 * Endpoints
97 *
98 *****************************************************************************
99 */
100
101/** Client endpoint */
102const struct tls_endpoint tls_client = {
103 .index = TLS_CLIENT,
104 .name = "client",
105};
106
107/** Server endpoint */
108const struct tls_endpoint tls_server = {
109 .index = TLS_SERVER,
110 .name = "server",
111};
112
113/** Endpoint list */
114static const struct tls_endpoint *tls_endpoint[] = {
117};
118
119/*****************************************************************************
120 *
121 * Traffic phases
122 *
123 *****************************************************************************
124 */
125
126/** A TLS traffic phase */
127struct tls_phase {
128 /** Name */
129 const char *name;
130 /** Key expansion label */
131 const char label[ 3 /* "[e|hs|ap]" + NUL */ ];
132 /** Required key derivation function flags */
134};
135
136/** Early traffic phase */
137const struct tls_phase tls_early = {
138 .name = "early",
139 .label = "e",
140 .flags = TLSKEY_KDF_KEYED,
141};
142
143/** Handshake traffic phase */
144const struct tls_phase tls_handshake = {
145 .name = "handshake",
146 .label = "hs",
147 .flags = TLSKEY_KDF_KEYED,
148};
149
150/** Application traffic phase */
152 .name = "application",
153 .label = "ap",
154 .flags = ( TLSKEY_KDF_KEYED | TLSKEY_KDF_MASTER ),
155};
156
157/*****************************************************************************
158 *
159 * Lifecycle management
160 *
161 *****************************************************************************
162 */
163
164/**
165 * Start key schedule
166 *
167 * @v tlskey Key schedule
168 * @v op Key schedule operations
169 * @v digest Digest algorithm
170 * @v nonce Local endpoint random bytes
171 * @ret rc Return status code
172 *
173 * The random bytes must be the random bytes that the local endpoint
174 * will subsequently incorporate within its own ClientHello (or
175 * ServerHello, if acting as a server). The caller must guarantee
176 * that these are fresh and are unpredictable by the peer. A freshly
177 * generated secure channel ephemeral secret can be used to fulfil
178 * this requirement.
179 */
180int tlskey_start ( struct tls_key_schedule *tlskey,
181 const struct tls_key_schedule_operations *op,
182 struct digest_algorithm *digest,
183 const struct tls_random *nonce ) {
184 size_t digestsize = digest->digestsize;
185 size_t ctxsize = digest->ctxsize;
186 size_t secretsize;
187 size_t total;
188 void *dynamic;
189 int rc;
190
191 /* Stop any existing running key schedule */
192 tlskey_stop ( tlskey );
193
194 /* Sanity check */
195 if ( ! digestsize ) {
196 rc = -ENOTTY;
197 goto err_sanity;
198 }
199
200 /* Determine required sizes */
201 secretsize = op->secretsize ( digest );
202 if ( ! secretsize ) {
203 DBGC ( tlskey, "TLSKEY %p cannot use %s with %s\n",
204 tlskey, op->name, digest->name );
205 rc = -ENOTSUP;
206 goto err_secretsize;
207 }
208 total = ( secretsize + /* secret */
209 ctxsize + /* transcript.ctx */
210 digestsize + /* transcript.running */
211 digestsize /* transcript.finishing */ );
212
213 /* Allocate dynamic storage */
214 dynamic = zalloc ( total );
215 if ( ! dynamic ) {
216 rc = -ENOMEM;
217 goto err_alloc;
218 }
219
220 /* Initialise schedule */
221 tlskey->op = op;
222 tlskey->digest = digest;
223 tlskey->secretsize = secretsize;
224 DBGC ( tlskey, "TLSKEY %p using %s with %s\n",
225 tlskey, tlskey->op->name, tlskey->digest->name );
226
227 /* Assign dynamic storage */
228 tlskey->dynamic = dynamic;
229 tlskey->secret = dynamic; dynamic += secretsize;
230 tlskey->transcript.ctx = dynamic; dynamic += ctxsize;
231 tlskey->transcript.running = dynamic; dynamic += digestsize;
232 tlskey->transcript.finishing = dynamic; dynamic += digestsize;
233 assert ( dynamic == ( tlskey->dynamic + total ) );
234
235 /* Initialise transcript digest */
236 digest_init ( digest, tlskey->transcript.ctx );
237 tlskey_digest ( tlskey, NULL, 0 );
238 memcpy ( &tlskey->nonce, nonce, sizeof ( tlskey->nonce ) );
239 DBGC ( tlskey, "TLSKEY %p local nonce:\n", tlskey );
240 DBGC_HDA ( tlskey, 0, &tlskey->nonce, sizeof ( tlskey->nonce ) );
241
242 /* Reset key schedule */
243 tlskey_reset ( tlskey );
244
245 return 0;
246
247 tlskey_stop ( tlskey );
248 err_alloc:
249 err_secretsize:
250 err_sanity:
251 return rc;
252}
253
254/**
255 * Stop key schedule
256 *
257 * @v tlskey Key schedule
258 */
259void tlskey_stop ( struct tls_key_schedule *tlskey ) {
260
261 /* Clear and free any dynamic storage */
262 zfree ( tlskey->dynamic );
263
264 /* Clear key schedule contents */
265 memset ( tlskey, 0, sizeof ( *tlskey ) );
266
267 /* Set null digest algorithm */
268 tlskey->digest = &digest_null;
269}
270
271/*****************************************************************************
272 *
273 * Handshake transcript digest
274 *
275 *****************************************************************************
276 */
277
278/** A ClientHello or ServerHello handshake record prefix of interest */
285
286/** Calculate endpoint index from ClientHello or ServerHello record type */
287#define TLSKEY_HELLO_IDX( type ) ( (type) - 1 )
288
289/** A Finished handshake record prefix of interest */
292} __attribute__ (( packed ));
293
294/** Finished record type */
295#define TLSKEY_FINISHED 20
296
297/**
298 * Process digested ClientHello or ServerHello handshake record
299 *
300 * @v tlskey Key schedule
301 * @v hello ClientHello or ServerHello handshake record
302 * @v index Endpoint index
303 * @ret flags Additional transcript flags to set
304 */
305static unsigned int tlskey_hello ( struct tls_key_schedule *tlskey,
306 const struct tlskey_hello *hello,
307 unsigned int index ) {
308 const struct tls_endpoint *end = tls_endpoint[index];
309 const struct tls_random *nonce = &tlskey->nonce;
310 struct tls_random *random = &tlskey->random[index];
311 unsigned int flags = 0;
312
313 /* We check that the local endpoint random bytes have been
314 * incorporated into the running transcript digest, since this
315 * is required in order to provide our non-replayability
316 * guarantees.
317 */
318 if ( memcmp ( nonce, &hello->random, sizeof ( *nonce ) ) == 0 )
320
321 /* We also capture and store the client and server random
322 * bytes from these records, since TLS versions 1.2 and
323 * earlier sometimes require these values separately from the
324 * full running transcript digest.
325 */
326 memcpy ( random, &hello->random, sizeof ( *random ) );
327
328 DBGC ( tlskey, "TLSKEY %p %s random bytes%s:\n", tlskey, end->name,
329 ( ( flags & TLSKEY_TSF_NONCED ) ? " (local nonce)" : "" ) );
330 DBGC_HDA ( tlskey, 0, random, sizeof ( *random ) );
331 return flags;
332}
333
334/**
335 * Process digested Finished handshake record
336 *
337 * @v tlskey Key schedule
338 * @ret flags Additional transcript flags to set
339 */
340static unsigned int tlskey_finished ( struct tls_key_schedule *tlskey ) {
341 struct tls_transcript *transcript = &tlskey->transcript;
342 struct digest_algorithm *digest = tlskey->digest;
343 size_t digestsize = digest->digestsize;
344
345 /* The TLS version 1.3 key schedule derives application
346 * traffic secrets from the transcript hash up to and
347 * including only the server Finished, but requires the
348 * handshake traffic secret to remain available for
349 * calculating the client Finished.
350 *
351 * If there are any intervening handshake records (e.g. an
352 * EndOfEarlyData) then this makes it impossible to construct
353 * the client application traffic secret without either:
354 *
355 * - retaining a separate record of the transcript hash up
356 * to and including the server Finished, or
357 *
358 * - retaining the client handshake traffic secret after
359 * calculating the client application traffic secret.
360 *
361 * The TLS version 1.3 key schedule also derives resumption
362 * secrets from NewSessionTicket handshake records that arrive
363 * after the client Finished, but using the transcript hash up
364 * to and including only the client Finished.
365 *
366 * We choose to solve both of these problems simultaneously by
367 * retaining a second "finishing" digest value that mirrors
368 * the continuously running digest value until the first
369 * Finished is digested, and then switches to updating only
370 * when a new Finished is digested.
371 */
372 DBGC ( tlskey, "TLSKEY %p finishing digest:\n", tlskey );
373 DBGC_HDA ( tlskey, 0, transcript->running, digestsize );
374 return TLSKEY_TSF_FINISHED;
375}
376
377/**
378 * Process digested handshake record
379 *
380 * @v tlskey Key schedule
381 * @v data Handshake record
382 * @v len Length of handshake record
383 * @ret flags Additional transcript flags to set
384 */
385static unsigned int tlskey_handshake ( struct tls_key_schedule *tlskey,
386 const void *data, size_t len ) {
387 const struct tlskey_hello *hello;
388 const struct tlskey_finished *finished;
389 unsigned int index;
390
391 /* Check for ClientHello and ServerHello */
392 if ( len >= sizeof ( *hello ) ) {
393 hello = data;
394 index = TLSKEY_HELLO_IDX ( hello->type );
395 if ( ( index == TLS_CLIENT ) || ( index == TLS_SERVER ) )
396 return tlskey_hello ( tlskey, hello, index );
397 }
398
399 /* Check for Finished */
400 if ( len >= sizeof ( *finished ) ) {
401 finished = data;
402 if ( finished->type == TLSKEY_FINISHED )
403 return tlskey_finished ( tlskey );
404 }
405
406 return 0;
407}
408
409/**
410 * Add handshake to running transcript digest
411 *
412 * @v tlskey Key schedule
413 * @v data Handshake record
414 * @v len Length of handshake record
415 */
416void tlskey_digest ( struct tls_key_schedule *tlskey, const void *data,
417 size_t len ) {
418 struct tls_transcript *transcript = &tlskey->transcript;
419 struct digest_algorithm *digest = tlskey->digest;
420 size_t digestsize = digest->digestsize;
421 size_t ctxsize = digest->ctxsize;
422 unsigned int flags;
423 struct {
425 } tmp;
426
427 /* Append to running transcript digest */
428 digest_update ( digest, transcript->ctx, data, len );
429
430 /* Update running transcript digest output */
431 memcpy ( tmp.ctx, transcript->ctx, ctxsize );
432 digest_final ( digest, tmp.ctx, transcript->running );
433
434 /* Process digested handshake record */
435 flags = tlskey_handshake ( tlskey, data, len );
436 transcript->flags |= flags;
437
438 /* Update the finishing digest value, if applicable */
439 if ( ! ( ( transcript->flags ^ flags ) & TLSKEY_TSF_FINISHED ) ) {
440 memcpy ( transcript->finishing, transcript->running,
441 digestsize );
442 }
443
444 /* Clear temporary secrets */
445 memset ( &tmp, 0, sizeof ( tmp ) );
446}
447
448/*****************************************************************************
449 *
450 * Key material
451 *
452 *****************************************************************************
453 */
454
455/**
456 * Expand key material
457 *
458 * @v tlskey Key schedule
459 * @v secret Secret
460 * @v label Label string
461 * @v seed Seed material
462 * @v seed_len Length of seed material
463 * @v out Output buffer
464 * @v out_len Length of output buffer
465 */
466static void tlskey_expand ( struct tls_key_schedule *tlskey,
467 const void *secret, const char *label,
468 const void *seed, size_t seed_len,
469 void *out, size_t out_len ) {
470 const struct tls_key_schedule_operations *op = tlskey->op;
471 struct digest_algorithm *digest = tlskey->digest;
472
473 /* Sanity check */
474 assert ( op != NULL );
475
476 /* Expand key material */
477 DBGC2 ( tlskey, "TLSKEY %p expanding seed \"%s\":\n", tlskey, label );
478 DBGC2_HDA ( tlskey, 0, seed, seed_len );
479 op->expand ( digest, secret, label, seed, seed_len, out, out_len );
480 DBGC2 ( tlskey, "TLSKEY %p expanded:\n", tlskey );
481 DBGC2_HDA ( tlskey, 0, out, out_len );
482}
483
484/**
485 * Reset key schedule
486 *
487 * @v tlskey Key schedule
488 *
489 * It is safe to reset a key schedule that has been stopped, or that
490 * has not yet been started.
491 */
492void tlskey_reset ( struct tls_key_schedule *tlskey ) {
493 const struct tls_key_schedule_operations *op = tlskey->op;
494
495 /* Do nothing if key schedule is stopped */
496 if ( ! op ) {
497 assert ( tlskey->secretsize == 0 );
498 assert ( tlskey->kdf.flags == 0 );
499 assert ( tlskey->traffic[TLS_CLIENT].phase == NULL );
500 assert ( tlskey->traffic[TLS_SERVER].phase == NULL );
501 return;
502 }
503
504 /* Clear secrets, flags, and traffic phases */
505 memset ( tlskey->secret, 0, tlskey->secretsize );
506 tlskey->kdf.flags = 0;
507 tlskey->traffic[TLS_CLIENT].phase = NULL;
508 tlskey->traffic[TLS_SERVER].phase = NULL;
509
510 /* Reset key schedule */
511 op->reset ( tlskey );
512}
513
514/**
515 * Apply a new shared secret
516 *
517 * @v tlskey Key schedule
518 * @v shared New shared secret
519 * @v shared_len Length of new shared secret
520 * @ret rc Return status code
521 */
522int tlskey_apply ( struct tls_key_schedule *tlskey, const void *shared,
523 size_t shared_len ) {
524 const struct tls_key_schedule_operations *op = tlskey->op;
525 int rc;
526
527 /* Sanity check */
528 if ( ! op )
529 return -ENOTTY;
530
531 /* All schedules define the master secret as immutable */
532 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
533 DBGC ( tlskey, "TLSKEY %p cannot apply a new shared secret "
534 "after generating master secret\n", tlskey );
535 return -EPROTO;
536 }
537
538 /* Apply new shared secret */
539 DBGC ( tlskey, "TLSKEY %p applying secret:\n", tlskey );
540 DBGC_HDA ( tlskey, 0, shared, shared_len );
541 if ( ( rc = op->apply ( tlskey, shared, shared_len ) ) != 0 )
542 return rc;
543
544 /* Mark key schedule as containing key material */
545 tlskey->kdf.flags |= TLSKEY_KDF_KEYED;
546
547 return 0;
548}
549
550/**
551 * Generate master secret
552 *
553 * @v tlskey Key schedule
554 * @v ems Extended master secret extension is enabled
555 * @ret rc Return status code
556 */
557int tlskey_master ( struct tls_key_schedule *tlskey, int ems ) {
558 const struct tls_key_schedule_operations *op = tlskey->op;
559 int rc;
560
561 /* Sanity check */
562 if ( ! op )
563 return -ENOTTY;
564
565 /* Any conceivable schedule requires key material */
566 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
567 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
568 "without key material\n", tlskey );
569 return -EPROTO;
570 }
571
572 /* All schedules define the master secret as immutable */
573 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
574 DBGC ( tlskey, "TLSKEY %p cannot regenerate master secret\n",
575 tlskey );
576 return -EPROTO;
577 }
578
579 /* Generate master secret */
580 DBGC ( tlskey, "TLSKEY %p generating %smaster secret\n",
581 tlskey, ( ems ? "extended " : "" ) );
582 if ( ( rc = op->master ( tlskey, ems ) ) != 0 )
583 return rc;
584
585 /* Mark key schedule as containing master secret */
586 tlskey->kdf.flags |= TLSKEY_KDF_MASTER;
587 if ( ems )
588 tlskey->kdf.flags |= TLSKEY_KDF_EMS;
589
590 return 0;
591}
592
593/**
594 * Generate verification data
595 *
596 * @v tlskey Key schedule
597 * @v end Verification endpoint
598 * @v verify Verification data to fill in
599 * @v verify_len Length of verification data
600 * @ret rc Return status code
601 */
602int tlskey_verify ( struct tls_key_schedule *tlskey,
603 const struct tls_endpoint *end,
604 void *verify, size_t verify_len ) {
605 const struct tls_key_schedule_operations *op = tlskey->op;
606 int rc;
607
608 /* Sanity check */
609 if ( ! op )
610 return -ENOTTY;
611
612 /* Verification data must be non-replayable */
613 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
614 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
615 "without a digested nonce\n", tlskey );
616 return -EPROTO;
617 }
618
619 /* Generate verification data */
620 DBGC2 ( tlskey, "TLSKEY %p generating %s verification data\n",
621 tlskey, end->name );
622 if ( ( rc = op->verify ( tlskey, end, verify, verify_len ) ) != 0 )
623 return rc;
624 DBGC ( tlskey, "TLSKEY %p %s verification data:\n",
625 tlskey, end->name );
626 DBGC_HDA ( tlskey, 0, verify, verify_len );
627
628 return 0;
629}
630
631/**
632 * Generate traffic secret
633 *
634 * @v tlskey Key schedule
635 * @v writer Writer endpoint
636 * @v phase Traffic phase
637 * @ret rc Return status code
638 */
639int tlskey_traffic ( struct tls_key_schedule *tlskey,
640 const struct tls_endpoint *writer,
641 const struct tls_phase *phase ) {
642 const struct tls_key_schedule_operations *op = tlskey->op;
643 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
644 unsigned int missing;
645 int rc;
646
647 /* Sanity check */
648 if ( ! op )
649 return -ENOTTY;
650
651 /* Check flags required for this traffic phase */
653 missing = ( ( tlskey->kdf.flags ^ phase->flags ) & phase->flags );
654 if ( missing ) {
655 DBGC ( tlskey, "TLSKEY %p cannot generate %s %s traffic "
656 "secrets (missing KDF flags %#04x)\n",
657 tlskey, writer->name, phase->name, missing );
658 return -EPROTO;
659 }
660
661 /* Generate traffic secret */
662 DBGC2 ( tlskey, "TLSKEY %p generating %s %s traffic secret\n",
663 tlskey, writer->name, phase->name );
664 if ( ( rc = op->traffic ( tlskey, writer, phase ) ) != 0 )
665 return rc;
666
667 /* Record phase */
668 traffic->phase = phase;
669
670 return 0;
671}
672
673/**
674 * Generate cipher key material
675 *
676 * @v tlskey Key schedule
677 * @v writer Writer endpoint
678 * @v key Cipher key to fill in
679 * @v key_len Length of cipher key
680 * @v iv Fixed portion of initialisation vector to fill in
681 * @v iv_len Length of fixed portion of initialisation vector
682 * @v mac MAC secret to fill in
683 * @v mac_len Length of MAC secret
684 * @ret rc Return status code
685 *
686 * For key schedules that include a ratchet mechanism, each call
687 * consumes the current generation of traffic secret and replaces it
688 * with the next generation. Repeated calls may therefore be used to
689 * obtain multiple generations of the cipher key material.
690 */
691int tlskey_cipher ( struct tls_key_schedule *tlskey,
692 const struct tls_endpoint *writer,
693 void *key, size_t key_len, void *iv, size_t iv_len,
694 void *mac, size_t mac_len ) {
695 const struct tls_key_schedule_operations *op = tlskey->op;
696 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
697 int rc;
698
699 /* Sanity check */
700 if ( ! op )
701 return -ENOTTY;
702
703 /* Ensure that traffic secret has actually been generated */
704 if ( ! traffic->phase ) {
705 DBGC ( tlskey, "TLSKEY %p cannot generate cipher key "
706 "material without traffic secrets\n", tlskey );
707 return -EPROTO;
708 }
709
710 /* Generate cipher key material */
711 DBGC2 ( tlskey, "TLSKEY %p generating %s %s cipher key material\n",
712 tlskey, writer->name, traffic->phase->name );
713 if ( ( rc = op->cipher ( tlskey, writer, key, key_len, iv, iv_len,
714 mac, mac_len ) ) != 0 ) {
715 return rc;
716 }
717 if ( key_len ) {
718 DBGC ( tlskey, "TLSKEY %p %s key:\n", tlskey, writer->name );
719 DBGC_HDA ( tlskey, 0, key, key_len );
720 }
721 if ( iv_len ) {
722 DBGC ( tlskey, "TLSKEY %p %s IV:\n", tlskey, writer->name );
723 DBGC_HDA ( tlskey, 0, iv, iv_len );
724 }
725 if ( mac_len ) {
726 DBGC ( tlskey, "TLSKEY %p %s MAC:\n", tlskey, writer->name );
727 DBGC_HDA ( tlskey, 0, mac, mac_len );
728 }
729
730 return 0;
731}
732
733/**
734 * Generate signable digest value
735 *
736 * @v tlskey Key schedule
737 * @v end Endpoint
738 * @v digest Signature digest algorithm
739 * @v data Additional data
740 * @v len Length of additional data
741 * @v tbs Signable digest value to fill in
742 * @ret rc Return status code
743 */
744int tlskey_tbshash ( struct tls_key_schedule *tlskey,
745 const struct tls_endpoint *end,
746 struct digest_algorithm *digest,
747 const void *data, size_t len, void *tbs ) {
748 const struct tls_key_schedule_operations *op = tlskey->op;
749 int rc;
750
751 /* Sanity check */
752 if ( ! op )
753 return -ENOTTY;
754
755 /* Signable digest values must be non-replayable */
756 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
757 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
758 "without a digested nonce\n", tlskey );
759 return -EPROTO;
760 }
761
762 /* Signable digest values must be constructed over the
763 * parameters used to establish a shared secret, and so a
764 * shared secret must exist.
765 */
766 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
767 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
768 "without a shared secret\n", tlskey );
769 return -EPROTO;
770 }
771
772 /* Generate digest value */
773 DBGC2 ( tlskey, "TLSKEY %p generating signable %s %s digest\n",
774 tlskey, end->name, digest->name );
775 if ( ( rc = op->tbshash ( tlskey, end, digest, data, len,
776 tbs ) ) != 0 ) {
777 return rc;
778 }
779 DBGC ( tlskey, "TLSKEY %p generated signable %s %s digest:\n",
780 tlskey, end->name, digest->name );
781 DBGC_HDA ( tlskey, 0, tbs, digest->digestsize );
782
783 return 0;
784}
785
786/**
787 * Save pre-shared key
788 *
789 * @v tlskey Key schedule
790 * @v nonce Ticket nonce
791 * @v nonce_len Length of ticket nonce
792 * @v psk Pre-shared key to fill in
793 * @ret rc Return status code
794 */
795int tlskey_save ( struct tls_key_schedule *tlskey, const void *nonce,
796 size_t nonce_len, struct tls_preshared_key *psk ) {
797 const struct tls_key_schedule_operations *op = tlskey->op;
798 struct digest_algorithm *digest = tlskey->digest;
799 int rc;
800
801 /* Clear any existing pre-shared key */
802 memset ( psk, 0, sizeof ( *psk ) );
803
804 /* Sanity check */
805 if ( ! op )
806 return -ENOTTY;
807
808 /* Session resumption requires a master secret */
809 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
810 DBGC ( tlskey, "TLSKEY %p cannot save key without a master "
811 "secret\n", tlskey );
812 return -EPROTO;
813 }
814
815 /* Save key material */
816 DBGC2 ( tlskey, "TLSKEY %p saving key\n", tlskey );
817 if ( ( rc = op->save ( tlskey, nonce, nonce_len, psk ) ) != 0 )
818 return rc;
819 DBGC ( tlskey, "TLSKEY %p saved key:\n", tlskey );
820 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
821
822 /* Record key properties */
823 psk->op = op;
824 psk->digest = digest;
825 psk->flags = tlskey->kdf.flags;
826
827 return 0;
828}
829
830/**
831 * Load pre-shared key
832 *
833 * @v tlskey Key schedule
834 * @v ems Extended master secret extension is enabled
835 * @v psk Pre-shared key
836 * @ret rc Return status code
837 */
838int tlskey_load ( struct tls_key_schedule *tlskey, int ems,
839 const struct tls_preshared_key *psk ) {
840 const struct tls_key_schedule_operations *op = tlskey->op;
841 struct digest_algorithm *digest = tlskey->digest;
842 int rc;
843
844 /* Reset key schedule */
845 tlskey_reset ( tlskey );
846
847 /* Sanity check */
848 if ( ! op )
849 return -ENOTTY;
850
851 /* Session resumption requires a master secret */
852 if ( ! ( psk->flags & TLSKEY_KDF_MASTER ) ) {
853 DBGC ( tlskey, "TLSKEY %p cannot load from a non-master "
854 "secret\n", tlskey );
855 return -EPROTO;
856 }
857
858 /* Pre-shared key must match extended/non-extended usage */
859 if ( ( !! ems ) != ( !! ( psk->flags & TLSKEY_KDF_EMS ) ) ) {
860 DBGC ( tlskey, "TLSKEY %p cannot load from %sextended master "
861 "secret\n", tlskey, ( ems ? "non-" : "" ) );
862 return -EPERM;
863 }
864
865 /* Pre-shared key must match schedule and digest */
866 if ( ( op != psk->op ) || ( digest != psk->digest ) ) {
867 DBGC ( tlskey, "TLSKEY %p cannot load from %s with %s\n",
868 tlskey, ( psk->op ? psk->op->name : "(unknown)" ),
869 ( psk->digest ? psk->digest->name : "(unknown)" ) );
870 return -EPERM;
871 }
872
873 /* Load key material */
874 DBGC ( tlskey, "TLSKEY %p loading key:\n", tlskey );
875 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
876 if ( ( rc = op->load ( tlskey, psk ) ) != 0 )
877 return rc;
878
879 /* Set flags */
880 tlskey->kdf.flags = ( psk->flags & op->mask );
881
882 return 0;
883}
884
885/**
886 * Generate pre-shared key binder value
887 *
888 * @v psk Pre-shared key
889 * @v prefix ClientHello prefix
890 * @v prefix_len Length of ClientHello prefix
891 * @v binder Binder value to fill in
892 * @v binder_len Length of binder value
893 * @ret rc Return status code
894 */
895int tlskey_bind ( const struct tls_preshared_key *psk, const void *prefix,
896 size_t prefix_len, void *binder, size_t binder_len ) {
897 const struct tls_key_schedule_operations *op = psk->op;
898 struct digest_algorithm *digest = psk->digest;
899 int rc;
900
901 /* Generate prefix digest and binder value */
902 if ( op && digest ) {
903 size_t digestsize = digest->digestsize;
904 size_t ctxsize = digest->ctxsize;
907
908 /* Calculate prefix digest */
909 digest_init ( digest, ctx );
910 digest_update ( digest, ctx, prefix, prefix_len );
911 digest_final ( digest, ctx, out );
912
913 /* Generate binder value */
914 DBGC2 ( psk, "TLSKEY %p generating key binder:\n", psk );
915 DBGC2_HDA ( psk, 0, &psk->key, sizeof ( psk->key ) );
916 if ( ( rc = op->bind ( psk, out, binder, binder_len ) ) != 0 )
917 return rc;
918 DBGC ( psk, "TLSKEY %p generated key binder:\n", psk );
919 DBGC_HDA ( psk, 0, binder, binder_len );
920
921 return 0;
922 }
923
924 DBGC ( psk, "TLSKEY %p cannot bind empty pre-shared key\n", psk );
925 return -ENOENT;
926}
927
928/*****************************************************************************
929 *
930 * TLS version 1.3 key schedule using HKDF
931 *
932 *****************************************************************************
933 */
934
935/**
936 * Calculate secret size
937 *
938 * @v digest Digest algorithm
939 * @ret secretsize Secret size, or zero if unsupported
940 */
941static size_t tlskey_hkdf_secretsize ( struct digest_algorithm *digest ) {
942 size_t digestsize = digest->digestsize;
943
944 return ( digestsize * 3 /* KDF, client, and server secrets */ );
945}
946
947/**
948 * Expand key material
949 *
950 * @v digest Digest algorithm
951 * @v secret Secret
952 * @v label Label string
953 * @v seed Seed material
954 * @v seed_len Length of seed material
955 * @v out Output buffer
956 * @v out_len Length of output buffer
957 */
958static void tlskey_hkdf_expand ( struct digest_algorithm *digest,
959 const void *secret, const char *label,
960 const void *seed, size_t seed_len,
961 void *out, size_t out_len ) {
962 static const char prefix[6] = "tls13 ";
963 const void *context = seed;
964 size_t context_len = seed_len;
965 size_t prefix_len = sizeof ( prefix );
966 size_t label_len = strlen ( label );
967 struct {
969 uint8_t label_len;
970 char prefix[prefix_len];
971 char label[label_len];
972 uint8_t context_len;
973 uint8_t context[context_len];
974 } __attribute__ (( packed )) info;
975
976 /* Construct additional information */
977 info.len = htons ( out_len );
978 info.label_len = ( prefix_len + label_len );
979 memcpy ( info.prefix, prefix, prefix_len );
980 memcpy ( info.label, label, label_len );
981 info.context_len = context_len;
982 memcpy ( info.context, context, context_len );
983
984 /* Generate output using HKDF */
985 hkdf_expand ( digest, secret, &info, sizeof ( info ), out, out_len );
986}
987
988/**
989 * Calculate empty digest value
990 *
991 * @v digest Digest algorithm
992 * @v empty Empty digest to fill in
993 */
994static void tlskey_hkdf_empty ( struct digest_algorithm *digest,
995 void *empty ) {
996 size_t ctxsize = digest->ctxsize;
997 uint8_t ctx[ctxsize];
998
999 /* Calculate empty digest */
1000 digest_init ( digest, ctx );
1001 digest_final ( digest, ctx, empty );
1002}
1003
1004/**
1005 * Calculate a finished MAC
1006 *
1007 * @v digest Digest algorithm
1008 * @v secret Secret
1009 * @v hash Message hash
1010 * @v out Output buffer
1011 */
1012static void tlskey_hkdf_finished ( struct digest_algorithm *digest,
1013 const void *secret, const void *hash,
1014 void *out ) {
1015 size_t digestsize = digest->digestsize;
1016 size_t hctxsize = hmac_ctxsize ( digest );
1017 struct {
1018 uint8_t hctx[hctxsize];
1020 } tmp;
1021
1022 /* Generate HMAC key */
1023 tlskey_hkdf_expand ( digest, secret, "finished", NULL, 0,
1024 tmp.key, sizeof ( tmp.key ) );
1025
1026 /* Generate HMAC */
1027 hmac_init ( digest, tmp.hctx, tmp.key, sizeof ( tmp.key ) );
1028 hmac_update ( digest, tmp.hctx, hash, digestsize );
1029 hmac_final ( digest, tmp.hctx, out );
1030
1031 /* Clear temporary secrets */
1032 memset ( &tmp, 0, sizeof ( tmp ) );
1033}
1034
1035/**
1036 * Reset key schedule
1037 *
1038 * @v key Key schedule
1039 */
1040static void tlskey_hkdf_reset ( struct tls_key_schedule *tlskey ) {
1041 struct digest_algorithm *digest = tlskey->digest;
1042 size_t digestsize = digest->digestsize;
1043 void *secret = tlskey->secret;
1044
1045 /* Allocate and initialise secrets */
1046 tlskey->kdf.secret = secret; secret += digestsize;
1047 tlskey->traffic[TLS_CLIENT].secret = secret; secret += digestsize;
1048 tlskey->traffic[TLS_SERVER].secret = secret; secret += digestsize;
1049 assert ( secret == ( tlskey->secret + tlskey->secretsize ) );
1050
1051 /* Initialise empty early secret */
1052 hkdf_extract ( digest, NULL, 0, tlskey->kdf.secret, digestsize,
1053 tlskey->kdf.secret );
1054}
1055
1056/**
1057 * Apply a new shared secret
1058 *
1059 * @v tlskey Key schedule
1060 * @v shared New shared secret
1061 * @v shared_len Length of new shared secret
1062 * @ret rc Return status code
1063 */
1064static int tlskey_hkdf_apply ( struct tls_key_schedule *tlskey,
1065 const void *shared, size_t shared_len ) {
1066 struct digest_algorithm *digest = tlskey->digest;
1067 size_t digestsize = digest->digestsize;
1068 uint8_t empty[digestsize];
1069
1070 /* Generate derived secret */
1071 tlskey_hkdf_empty ( digest, empty );
1072 tlskey_expand ( tlskey, tlskey->kdf.secret, "derived", empty,
1073 digestsize, tlskey->kdf.secret, digestsize );
1074 DBGC2 ( tlskey, "TLSKEY %p derived:\n", tlskey );
1075 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1076
1077 /* Extract new pseudorandom key */
1078 hkdf_extract ( digest, tlskey->kdf.secret, digestsize, shared,
1079 shared_len, tlskey->kdf.secret );
1080 DBGC2 ( tlskey, "TLSKEY %p extracted PRK:\n", tlskey );
1081 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1082
1083 return 0;
1084}
1085
1086/**
1087 * Generate master secret
1088 *
1089 * @v tlskey Key schedule
1090 * @v ems Extended master secret extension is enabled
1091 * @ret rc Return status code
1092 */
1093static int tlskey_hkdf_master ( struct tls_key_schedule *tlskey, int ems ) {
1094 struct digest_algorithm *digest = tlskey->digest;
1095 size_t digestsize = digest->digestsize;
1096 uint8_t zero[digestsize];
1097 int rc;
1098
1099 /* Extended master secret must always be used */
1100 if ( ! ems ) {
1101 DBGC ( tlskey, "TLSKEY %p requires an extended master "
1102 "secret\n", tlskey );
1103 return -EPROTO;
1104 }
1105
1106 /* Generate master secret */
1107 memset ( zero, 0, sizeof ( zero ) );
1108 if ( ( rc = tlskey_apply ( tlskey, zero, sizeof ( zero ) ) ) != 0 )
1109 return rc;
1110
1111 return 0;
1112}
1113
1114/**
1115 * Generate verification data
1116 *
1117 * @v tlskey Key schedule
1118 * @v end Verification endpoint
1119 * @v verify Verification data to fill in
1120 * @v verify_len Length of verification data
1121 * @ret rc Return status code
1122 */
1123static int tlskey_hkdf_verify ( struct tls_key_schedule *tlskey,
1124 const struct tls_endpoint *end,
1125 void *verify, size_t verify_len ) {
1126 struct tls_traffic_secret *traffic = &tlskey->traffic[end->index];
1127 struct digest_algorithm *digest = tlskey->digest;
1128 size_t digestsize = digest->digestsize;
1129
1130 /* Verification data must be a complete digest output */
1131 if ( verify_len != digestsize )
1132 return -EINVAL;
1133
1134 /* Verification data is derived from handshake secrets */
1135 if ( traffic->phase != &tls_handshake ) {
1136 DBGC ( tlskey, "TLSKEY %p cannot generate %s verification "
1137 "data without %s handshake traffic secrets\n",
1138 tlskey, end->name, end->name );
1139 return -EPROTO;
1140 }
1141
1142 /* Generate verification data */
1143 tlskey_hkdf_finished ( digest, traffic->secret,
1144 tlskey->transcript.running, verify );
1145 DBGC ( tlskey, "TLSKEY %p %s verification:\n", tlskey, end->name );
1146 DBGC_HDA ( tlskey, 0, verify, verify_len );
1147
1148 return 0;
1149}
1150
1151/**
1152 * Generate traffic secret
1153 *
1154 * @v tlskey Key schedule
1155 * @v writer Writer endpoint
1156 * @v phase Traffic phase
1157 * @ret rc Return status code
1158 */
1159static int tlskey_hkdf_traffic ( struct tls_key_schedule *tlskey,
1160 const struct tls_endpoint *writer,
1161 const struct tls_phase *phase ) {
1162 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1163 struct digest_algorithm *digest = tlskey->digest;
1164 size_t digestsize = digest->digestsize;
1165 char label[ 13 /* "[c|s] [e|hs|ap] traffic" + NUL */ ];
1166
1167 /* Generate label */
1168 snprintf ( label, sizeof ( label ), "%c %s traffic",
1169 writer->name[0], phase->label );
1170
1171 /* Generate traffic secret */
1172 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1174 traffic->secret, digestsize );
1175
1176 return 0;
1177}
1178
1179/**
1180 * Generate cipher key material
1181 *
1182 * @v tlskey Key schedule
1183 * @v writer Writer endpoint
1184 * @v key Cipher key to fill in
1185 * @v key_len Length of cipher key
1186 * @v iv Fixed portion of initialisation vector to fill in
1187 * @v iv_len Length of fixed portion of initialisation vector
1188 * @v mac MAC secret to fill in
1189 * @v mac_len Length of MAC secret
1190 * @ret rc Return status code
1191 */
1192static int tlskey_hkdf_cipher ( struct tls_key_schedule *tlskey,
1193 const struct tls_endpoint *writer,
1194 void *key, size_t key_len, void *iv,
1195 size_t iv_len, void *mac __unused,
1196 size_t mac_len ) {
1197 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1198 struct digest_algorithm *digest = tlskey->digest;
1199 size_t digestsize = digest->digestsize;
1200 void *secret = traffic->secret;
1201
1202 /* The key schedule does not define a way to generate MAC secrets */
1203 if ( mac_len ) {
1204 DBGC ( tlskey, "TLSKEY %p does not support MAC secrets\n",
1205 tlskey );
1206 return -ENOTSUP;
1207 }
1208
1209 /* Generate cipher key */
1210 tlskey_expand ( tlskey, secret, "key", NULL, 0, key, key_len );
1211
1212 /* Generate initialisation vector */
1213 tlskey_expand ( tlskey, secret, "iv", NULL, 0, iv, iv_len );
1214
1215 /* Update traffic secret, if applicable */
1216 if ( traffic->phase == &tls_application ) {
1217 tlskey_expand ( tlskey, secret, "traffic upd", NULL, 0,
1218 secret, digestsize );
1219 }
1220
1221 return 0;
1222}
1223
1224/**
1225 * Generate signable digest value
1226 *
1227 * @v tlskey Key schedule
1228 * @v end Endpoint
1229 * @v digest Signature digest algorithm
1230 * @v data Additional data
1231 * @v len Length of additional data
1232 * @v tbs Signable digest value to fill in
1233 * @ret rc Return status code
1234 */
1235static int tlskey_hkdf_tbshash ( struct tls_key_schedule *tlskey,
1236 const struct tls_endpoint *end,
1237 struct digest_algorithm *digest,
1238 const void *data __unused, size_t len,
1239 void *tbs ) {
1240 size_t ctxsize = digest->ctxsize;
1242 char buf[64];
1243 int label_len;
1244
1245 /* There is no way to incorporate additional data */
1246 if ( len ) {
1247 DBGC ( tlskey, "TLSKEY %p cannot generate digest with "
1248 "additional data\n", tlskey );
1249 return -ENOTSUP;
1250 }
1251
1252 /* Generate digest value (all input is public) */
1253 digest_init ( digest, ctx );
1254 memset ( buf, 0x20, sizeof ( buf ) );
1255 digest_update ( digest, ctx, buf, sizeof ( buf ) );
1256 label_len = snprintf ( buf, sizeof ( buf ),
1257 "TLS 1.3, %s CertificateVerify", end->name );
1258 assert ( label_len == 33 /* for both "client" and "server" */ );
1259 digest_update ( digest, ctx, buf, ( label_len + 1 /* NUL */ ) );
1260 digest_update ( digest, ctx, tlskey->transcript.running,
1261 tlskey->digest->digestsize );
1262 digest_final ( digest, ctx, tbs );
1263
1264 return 0;
1265}
1266
1267/**
1268 * Save pre-shared key
1269 *
1270 * @v tlskey Key schedule
1271 * @v nonce Ticket nonce
1272 * @v nonce_len Length of ticket nonce
1273 * @v psk Pre-shared key to fill in
1274 * @ret rc Return status code
1275 */
1276static int tlskey_hkdf_save ( struct tls_key_schedule *tlskey,
1277 const void *nonce, size_t nonce_len,
1278 struct tls_preshared_key *psk ) {
1279 struct digest_algorithm *digest = tlskey->digest;
1280 size_t digestsize = digest->digestsize;
1281 struct {
1282 uint8_t master[digestsize];
1283 } tmp;
1284
1285 /* The pre-shared key currently uses a fixed-size buffer */
1286 if ( digestsize > sizeof ( psk->key.resumption ) ) {
1287 DBGC ( tlskey, "TLSKEY %p cannot save %s pre-shared key\n",
1288 tlskey, digest->name );
1289 return -ENOTSUP;
1290 }
1291
1292 /* Generate resumption master secret */
1293 tlskey_expand ( tlskey, tlskey->kdf.secret, "res master",
1295 tmp.master, sizeof ( tmp.master ) );
1296
1297 /* Generate resumption secret */
1298 tlskey_expand ( tlskey, tmp.master, "resumption", nonce, nonce_len,
1299 psk->key.resumption, digestsize );
1300
1301 /* Clear temporary secrets */
1302 memset ( &tmp, 0, sizeof ( tmp ) );
1303
1304 return 0;
1305}
1306
1307/**
1308 * Load pre-shared key
1309 *
1310 * @v tlskey Key schedule
1311 * @v psk Pre-shared key
1312 * @ret rc Return status code
1313 */
1314static int tlskey_hkdf_load ( struct tls_key_schedule *tlskey,
1315 const struct tls_preshared_key *psk ) {
1316 struct digest_algorithm *digest = tlskey->digest;
1317 size_t digestsize = digest->digestsize;
1318
1319 /* Sanity checks */
1320 assert ( digest == psk->digest );
1321 assert ( digestsize <= sizeof ( psk->key.resumption ) );
1322
1323 /* Extract early secret */
1324 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize,
1325 tlskey->kdf.secret );
1326 DBGC2 ( tlskey, "TLSKEY %p early secret:\n", tlskey );
1327 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1328
1329 return 0;
1330}
1331
1332/**
1333 * Generate pre-shared key binder value
1334 *
1335 * @v psk Pre-shared key
1336 * @v hash Partial transcript hash
1337 * @v binder Binder value to fill in
1338 * @v binder_len Length of binder value
1339 * @ret rc Return status code
1340 */
1341static int tlskey_hkdf_bind ( const struct tls_preshared_key *psk,
1342 const void *hash, void *binder,
1343 size_t binder_len ) {
1344 struct digest_algorithm *digest = psk->digest;
1345 size_t digestsize = digest->digestsize;
1346 uint8_t empty[digestsize];
1347 struct {
1349 } tmp;
1350
1351 /* Binder value must be a complete digest output */
1352 if ( binder_len != digestsize )
1353 return -EINVAL;
1354
1355 /* Extract temporary copy of early secret */
1356 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize, tmp.key );
1357 DBGC2 ( psk, "TLSKEY %p temporary early secret:\n", psk );
1358 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1359
1360 /* Generate resumption binder secret */
1361 tlskey_hkdf_empty ( digest, empty );
1362 tlskey_hkdf_expand ( digest, tmp.key, "res binder", empty, digestsize,
1363 tmp.key, digestsize );
1364 DBGC2 ( psk, "TLSKEY %p resumption binder secret:\n", psk );
1365 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1366
1367 /* Generate binder */
1368 tlskey_hkdf_finished ( digest, tmp.key, hash, binder );
1369 DBGC2 ( psk, "TLSKEY %p binder:\n", psk );
1370 DBGC2_HDA ( psk, 0, binder, binder_len );
1371
1372 /* Clear temporary secrets */
1373 memset ( &tmp, 0, sizeof ( tmp ) );
1374
1375 return 0;
1376}
1377
1378/** TLS key schedule based on HKDF */
1380 .name = "HKDF",
1381 .accumulates = 1,
1382 .mask = TLSKEY_KDF_KEYED,
1383 .secretsize = tlskey_hkdf_secretsize,
1384 .expand = tlskey_hkdf_expand,
1385 .reset = tlskey_hkdf_reset,
1386 .apply = tlskey_hkdf_apply,
1387 .master = tlskey_hkdf_master,
1388 .verify = tlskey_hkdf_verify,
1389 .traffic = tlskey_hkdf_traffic,
1390 .cipher = tlskey_hkdf_cipher,
1391 .tbshash = tlskey_hkdf_tbshash,
1392 .save = tlskey_hkdf_save,
1393 .load = tlskey_hkdf_load,
1394 .bind = tlskey_hkdf_bind,
1395};
1396
1397/*****************************************************************************
1398 *
1399 * TLS version 1.2 key schedule using PRF based on P_Hash()
1400 *
1401 *****************************************************************************
1402 */
1403
1404/** Minimum length for verification data */
1405#define TLSKEY_HASH_VERIFY_MIN 12
1406
1407/**
1408 * Calculate secret size
1409 *
1410 * @v digest Digest algorithm
1411 * @ret secretsize Secret size, or zero if unsupported
1412 */
1413static size_t tlskey_hash_secretsize ( struct digest_algorithm *digest ) {
1414
1415 /* A P_Hash() key is an HMAC key */
1416 return hmac_keysize ( digest );
1417}
1418
1419/**
1420 * Expand key material
1421 *
1422 * @v digest Digest algorithm
1423 * @v secret Secret
1424 * @v label Label string
1425 * @v seed Seed material
1426 * @v seed_len Length of seed material
1427 * @v out Output buffer
1428 * @v out_len Length of output buffer
1429 */
1430static void tlskey_hash_expand ( struct digest_algorithm *digest,
1431 const void *secret, const char *label,
1432 const void *seed, size_t seed_len,
1433 void *out, size_t out_len ) {
1434 size_t digestsize = digest->digestsize;
1435 size_t hctxsize = hmac_ctxsize ( digest );
1436 size_t frag_len = digestsize;
1437 size_t label_len = strlen ( label );
1438 unsigned int index = 0;
1439 struct {
1440 uint8_t ctx[2][hctxsize];
1442 uint8_t frag[digestsize];
1443 } tmp;
1444
1445 /* Generate as much output as required */
1446 while ( out_len ) {
1447
1448 /* Generate A(n) and output fragment */
1449 hmac_init_key ( digest, tmp.ctx[0], secret );
1450 if ( index ) {
1451 hmac_update ( digest, tmp.ctx[0], tmp.a,
1452 sizeof ( tmp.a ) );
1453 memcpy ( tmp.ctx[1], tmp.ctx[0],
1454 sizeof ( tmp.ctx[1] ) );
1455 }
1456 hmac_update ( digest, tmp.ctx[0], label, label_len );
1457 hmac_update ( digest, tmp.ctx[0], seed, seed_len );
1458 hmac_final ( digest, tmp.ctx[ ( index != 0 ) ], tmp.a );
1459 if ( index++ == 0 )
1460 continue;
1461 hmac_final ( digest, tmp.ctx[0], tmp.frag );
1462
1463 /* Copy output */
1464 if ( frag_len > out_len )
1465 frag_len = out_len;
1466 memcpy ( out, tmp.frag, frag_len );
1467
1468 /* Move to next fragment */
1469 out += frag_len;
1470 out_len -= frag_len;
1471 }
1472
1473 /* Clear temporary secrets */
1474 memset ( &tmp, 0, sizeof ( tmp ) );
1475}
1476
1477/**
1478 * Reset key schedule
1479 *
1480 * @v key Key schedule
1481 */
1482static void tlskey_hash_reset ( struct tls_key_schedule *tlskey ) {
1483 void *secret = tlskey->secret;
1484
1485 /* Allocate and initialise secrets */
1486 tlskey->kdf.secret = secret;
1487 tlskey->traffic[TLS_CLIENT].secret = secret;
1488 tlskey->traffic[TLS_SERVER].secret = secret;
1489}
1490
1491/**
1492 * Apply a new shared secret
1493 *
1494 * @v tlskey Key schedule
1495 * @v shared New shared secret
1496 * @v shared_len Length of new shared secret
1497 * @ret rc Return status code
1498 */
1499static int tlskey_hash_apply ( struct tls_key_schedule *tlskey,
1500 const void *shared, size_t shared_len ) {
1501 struct digest_algorithm *digest = tlskey->digest;
1502 size_t hctxsize = hmac_ctxsize ( digest );
1503 struct {
1504 uint8_t hctx[hctxsize];
1505 } tmp;
1506
1507 /* Set HMAC key */
1508 hmac_key ( digest, tmp.hctx, shared, shared_len, tlskey->kdf.secret );
1509
1510 /* Clear temporary secrets */
1511 memset ( &tmp, 0, sizeof ( tmp ) );
1512
1513 return 0;
1514}
1515
1516/**
1517 * Generate master secret
1518 *
1519 * @v tlskey Key schedule
1520 * @v ems Extended master secret extension is enabled
1521 * @ret rc Return status code
1522 */
1523static int tlskey_hash_master ( struct tls_key_schedule *tlskey, int ems ) {
1524 struct digest_algorithm *digest = tlskey->digest;
1525 size_t digestsize = digest->digestsize;
1526 const char *label;
1527 const void *seed;
1528 size_t seed_len;
1529 struct {
1530 uint8_t master[48];
1531 } tmp;
1532 int rc;
1533
1534 /* Master secret is derived from the client and server random
1535 * values (or the full transcript digest).
1536 */
1537 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
1538 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
1539 "without a digested nonce\n", tlskey );
1540 return -EPROTO;
1541 }
1542
1543 /* Generate master secret */
1544 if ( ems ) {
1545 label = "extended master secret";
1546 seed = tlskey->transcript.running;
1547 seed_len = digestsize;
1548 } else {
1549 label = "master secret";
1550 seed = &tlskey->random;
1551 seed_len = sizeof ( tlskey->random );
1552 }
1553 tlskey_expand ( tlskey, tlskey->kdf.secret, label, seed, seed_len,
1554 tmp.master, sizeof ( tmp.master ) );
1555
1556 /* Apply master secret */
1557 if ( ( rc = tlskey_apply ( tlskey, tmp.master,
1558 sizeof ( tmp.master ) ) ) != 0 ) {
1559 goto err_apply;
1560 }
1561
1562 err_apply:
1563 memset ( &tmp, 0, sizeof ( tmp ) );
1564 return rc;
1565}
1566
1567/**
1568 * Generate verification data
1569 *
1570 * @v tlskey Key schedule
1571 * @v end Verification endpoint
1572 * @v verify Verification data to fill in
1573 * @v verify_len Length of verification data
1574 * @ret rc Return status code
1575 */
1576static int tlskey_hash_verify ( struct tls_key_schedule *tlskey,
1577 const struct tls_endpoint *end,
1578 void *verify, size_t verify_len ) {
1579 struct digest_algorithm *digest = tlskey->digest;
1580 size_t digestsize = digest->digestsize;
1581 char label[ 16 /* "[client|server] finished" + NUL */ ];
1582
1583 /* Verification data must be at least 12 bytes for all digests */
1584 if ( verify_len < TLSKEY_HASH_VERIFY_MIN )
1585 return -EINVAL;
1586
1587 /* Verification data is derived from the master secret */
1588 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
1589 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
1590 "without a master secret\n", tlskey );
1591 return -EPROTO;
1592 }
1593
1594 /* Construct label */
1595 snprintf ( label, sizeof ( label ), "%s finished", end->name );
1596
1597 /* Generate verification data */
1598 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1599 tlskey->transcript.running, digestsize,
1600 verify, verify_len );
1601
1602 return 0;
1603}
1604
1605/**
1606 * Generate traffic secret
1607 *
1608 * @v tlskey Key schedule
1609 * @v writer Writer endpoint
1610 * @v phase Traffic phase
1611 * @ret rc Return status code
1612 */
1613static int tlskey_hash_traffic ( struct tls_key_schedule *tlskey,
1614 const struct tls_endpoint *writer,
1615 const struct tls_phase *phase ) {
1616 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1617
1618 /* Only application phase keys are supported */
1619 if ( phase != &tls_application ) {
1620 DBGC ( tlskey, "TLSKEY %p does not support %s traffic keys\n",
1621 tlskey, phase->name );
1622 return -ENOTSUP;
1623 }
1624
1625 /* There are no separate traffic secrets */
1626 assert ( traffic->secret == tlskey->kdf.secret );
1627
1628 return 0;
1629}
1630
1631/**
1632 * Generate cipher key material
1633 *
1634 * @v tlskey Key schedule
1635 * @v writer Writer endpoint
1636 * @v key Cipher key to fill in
1637 * @v key_len Length of cipher key
1638 * @v iv Fixed portion of initialisation vector to fill in
1639 * @v iv_len Length of fixed portion of initialisation vector
1640 * @v mac MAC secret to fill in
1641 * @v mac_len Length of MAC secret
1642 * @ret rc Return status code
1643 */
1644static int tlskey_hash_cipher ( struct tls_key_schedule *tlskey,
1645 const struct tls_endpoint *writer,
1646 void *key, size_t key_len, void *iv,
1647 size_t iv_len, void *mac, size_t mac_len ) {
1648 size_t total = ( 2 * ( mac_len + key_len + iv_len ) );
1649 struct {
1650 uint8_t key[total];
1651 } tmp;
1652 struct {
1653 struct tls_random server;
1654 struct tls_random client;
1655 } __attribute__ (( packed )) seed;
1656 const void *src;
1657 size_t mask;
1658
1659 /* Construct seed (with swapped client/server random bytes) */
1660 memcpy ( &seed.server, &tlskey->random[TLS_SERVER],
1661 sizeof ( seed.server ) );
1662 memcpy ( &seed.client, &tlskey->random[TLS_CLIENT],
1663 sizeof ( seed.client ) );
1664
1665 /* Generate key material */
1666 tlskey_expand ( tlskey, tlskey->kdf.secret, "key expansion", &seed,
1667 sizeof ( seed ), tmp.key, sizeof ( tmp.key ) );
1668
1669 /* Partition key material */
1670 src = tmp.key;
1671 mask = ( ( writer->index == TLS_CLIENT ) ? 0 : -1UL );
1672 memcpy ( mac, ( src + ( mac_len & mask ) ), mac_len );
1673 src += ( 2 * mac_len );
1674 memcpy ( key, ( src + ( key_len & mask ) ), key_len );
1675 src += ( 2 * key_len );
1676 memcpy ( iv, ( src + ( iv_len & mask ) ), iv_len );
1677 src += ( 2 * iv_len );
1678 assert ( src == &tmp.key[total] );
1679
1680 /* Clear temporary secrets */
1681 memset ( &tmp, 0, sizeof ( tmp ) );
1682
1683 return 0;
1684}
1685
1686/**
1687 * Generate signable digest value
1688 *
1689 * @v tlskey Key schedule
1690 * @v end Endpoint
1691 * @v digest Signature digest algorithm
1692 * @v data Additional data
1693 * @v len Length of additional data
1694 * @v tbs Signable digest value to fill in
1695 * @ret rc Return status code
1696 */
1697static int tlskey_hash_tbshash ( struct tls_key_schedule *tlskey,
1698 const struct tls_endpoint *end,
1699 struct digest_algorithm *digest,
1700 const void *data, size_t len, void *tbs ) {
1701 size_t ctxsize = digest->ctxsize;
1702 struct {
1703 uint8_t ctx[ctxsize];
1704 } tmp;
1705
1706 /* Generate endpoint-specific digest value */
1707 if ( end->index == TLS_CLIENT ) {
1708
1709 /* The client CertificateVerify digest value is the
1710 * raw transcript digest. We retain only a single
1711 * running transcript digest, and can therefore
1712 * provide this only for a digest algorithm that
1713 * matches our transcript digest algorithm.
1714 */
1715 if ( digest != tlskey->digest ) {
1716 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
1717 "transcript digest\n", tlskey, digest->name );
1718 return -ENOTSUP;
1719 }
1720
1721 /* There is no way to incorporate additional data */
1722 if ( len ) {
1723 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1724 "with additional data\n", tlskey );
1725 return -ENOTSUP;
1726 }
1727
1728 /* Copy transcript digest value */
1729 memcpy ( tbs, tlskey->transcript.running,
1730 digest->digestsize );
1731
1732 } else {
1733
1734 /* Additional data (i.e. the ServerKeyExchange
1735 * parameters) must be incorporated, since otherwise
1736 * the digest does not cover the parameters used to
1737 * establish the shared secret.
1738 */
1739 if ( ! len ) {
1740 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1741 "without additional data\n", tlskey );
1742 return -ENOTSUP;
1743 }
1744
1745 /* Generate ServerKeyExchange digest */
1746 digest_init ( digest, tmp.ctx );
1747 digest_update ( digest, tmp.ctx, &tlskey->random,
1748 sizeof ( tlskey->random ) );
1749 digest_update ( digest, tmp.ctx, data, len );
1750 digest_final ( digest, tmp.ctx, tbs );
1751 }
1752
1753 /* Clear temporary secrets */
1754 memset ( &tmp, 0, sizeof ( tmp ) );
1755
1756 return 0;
1757}
1758
1759/**
1760 * Save pre-shared key
1761 *
1762 * @v tlskey Key schedule
1763 * @v nonce Ticket nonce
1764 * @v nonce_len Length of ticket nonce
1765 * @v psk Pre-shared key to fill in
1766 * @ret rc Return status code
1767 */
1768static int tlskey_hash_save ( struct tls_key_schedule *tlskey,
1769 const void *nonce __unused, size_t nonce_len,
1770 struct tls_preshared_key *psk ) {
1771 struct digest_algorithm *digest = tlskey->digest;
1772
1773 /* A ticket nonce is not supported */
1774 if ( nonce_len )
1775 return -ENOTSUP;
1776
1777 /* For TLS version 1.2, the pre-master secret may be any
1778 * length but the master secret is fixed at 48 bytes. This is
1779 * smaller than the block size for all supported digest
1780 * algorithms. The HMAC key constructed from the master
1781 * secret will therefore be just the zero-padded master secret
1782 * value. We can therefore preserve just these first 48 bytes
1783 * of the KDF master secret (ignoring the zero padding up to
1784 * the digest block size).
1785 */
1786 assert ( sizeof ( psk->key.master_secret ) <=
1787 hmac_keysize ( digest ) );
1788 memcpy ( &psk->key.master_secret, tlskey->kdf.secret,
1789 sizeof ( psk->key.master_secret ) );
1790
1791 return 0;
1792}
1793
1794/**
1795 * Load pre-shared key
1796 *
1797 * @v tlskey Key schedule
1798 * @v psk Pre-shared key
1799 * @ret rc Return status code
1800 */
1801static int tlskey_hash_load ( struct tls_key_schedule *tlskey,
1802 const struct tls_preshared_key *psk ) {
1803 const void *secret;
1804 size_t secret_len;
1805 int rc;
1806
1807 /* For TLS versions 1.2 and earlier, the pre-shared key
1808 * material contains the master secret and so we just apply
1809 * this as the key derivation function secret.
1810 */
1811 secret = &psk->key.master_secret;
1812 secret_len = sizeof ( psk->key.master_secret );
1813 if ( ( rc = tlskey_apply ( tlskey, secret, secret_len ) ) != 0 )
1814 return rc;
1815
1816 return 0;
1817}
1818
1819/**
1820 * Generate pre-shared key binder value
1821 *
1822 * @v psk Pre-shared key
1823 * @v hash Partial transcript hash
1824 * @v binder Binder value to fill in
1825 * @v binder_len Length of binder value
1826 * @ret rc Return status code
1827 */
1828static int tlskey_hash_bind ( const struct tls_preshared_key *psk __unused,
1829 const void *hash __unused,
1830 void *binder __unused, size_t binder_len ) {
1831
1832 /* Binder values are not supported */
1833 if ( binder_len )
1834 return -ENOTSUP;
1835
1836 return 0;
1837}
1838
1839/** TLS key schedule based on P_Hash() */
1857
1858/*****************************************************************************
1859 *
1860 * TLS version 1.0/1.1 key schedule using PRF based on P_MD5()+P_SHA1()
1861 *
1862 *****************************************************************************
1863 */
1864
1865/**
1866 * Calculate secret size
1867 *
1868 * @v digest Digest algorithm
1869 * @ret secretsize Secret size, or zero if unsupported
1870 */
1871static size_t tlskey_md5_sha1_secretsize ( struct digest_algorithm *digest ) {
1872 struct md5_sha1_hmac_keys *hkeys;
1873 size_t secretsize;
1874
1875 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1876 if ( digest != &md5_sha1_algorithm )
1877 return 0;
1878
1879 /* A P_MD5()+P_SHA1() key is a split HMAC-MD5 and HMAC-SHA1 key */
1880 assert ( sizeof ( hkeys->md5 ) == hmac_keysize ( &md5_algorithm ) );
1881 assert ( sizeof ( hkeys->sha1 ) == hmac_keysize ( &sha1_algorithm ) );
1882 secretsize = sizeof ( *hkeys );
1883
1884 return secretsize;
1885}
1886
1887/**
1888 * Expand key material
1889 *
1890 * @v digest Digest algorithm
1891 * @v secret Secret
1892 * @v label Label string
1893 * @v seed Seed material
1894 * @v seed_len Length of seed material
1895 * @v out Output buffer
1896 * @v out_len Length of output buffer
1897 */
1898static void tlskey_md5_sha1_expand ( struct digest_algorithm *digest,
1899 const void *secret, const char *label,
1900 const void *seed, size_t seed_len,
1901 void *out, size_t out_len ) {
1902 const struct md5_sha1_hmac_keys *hkeys = secret;
1903 struct {
1904 uint8_t sha1[out_len];
1905 } tmp;
1906 uint8_t *xor;
1907 unsigned int i;
1908
1909 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1910 assert ( digest == &md5_sha1_algorithm );
1911
1912 /* Generate MD5 portion into output buffer */
1913 tlskey_hash_expand ( &md5_algorithm, hkeys->md5, label, seed,
1914 seed_len, out, out_len );
1915
1916 /* Generate SHA-1 portion into temporary buffer */
1917 tlskey_hash_expand ( &sha1_algorithm, hkeys->sha1, label, seed,
1918 seed_len, tmp.sha1, out_len );
1919
1920 /* XOR together into output buffer */
1921 xor = out;
1922 for ( i = 0 ; i < out_len ; i++ )
1923 xor[i] ^= tmp.sha1[i];
1924
1925 /* Clear temporary secrets */
1926 memset ( &tmp, 0, sizeof ( tmp ) );
1927}
1928
1929/**
1930 * Apply a new shared secret
1931 *
1932 * @v tlskey Key schedule
1933 * @v shared New shared secret
1934 * @v shared_len Length of new shared secret
1935 * @ret rc Return status code
1936 */
1937static int tlskey_md5_sha1_apply ( struct tls_key_schedule *tlskey,
1938 const void *shared, size_t shared_len ) {
1939 struct digest_algorithm *digest = tlskey->digest;
1940 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1941 size_t hctxsize = hmac_ctxsize ( digest );
1942 struct {
1943 uint8_t hctx[hctxsize];
1944 } tmp;
1945 const void *shared_md5;
1946 const void *shared_sha1;
1947 size_t shared_sublen;
1948
1949 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1950 assert ( digest == &md5_sha1_algorithm );
1951
1952 /* Split secret into two, with an overlap of up to one byte */
1953 shared_sublen = ( ( shared_len + 1 ) / 2 );
1954 shared_md5 = shared;
1955 shared_sha1 = ( shared + shared_len - shared_sublen );
1956
1957 /* Set HMAC-MD5 key */
1958 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &md5_algorithm ) );
1959 hmac_key ( &md5_algorithm, tmp.hctx, shared_md5, shared_sublen,
1960 hkeys->md5 );
1961
1962 /* Set HMAC-SHA1 key */
1963 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &sha1_algorithm ) );
1964 hmac_key ( &sha1_algorithm, tmp.hctx, shared_sha1, shared_sublen,
1965 hkeys->sha1 );
1966
1967 /* Clear temporary secrets */
1968 memset ( &tmp, 0, sizeof ( tmp ) );
1969
1970 return 0;
1971}
1972
1973/**
1974 * Save pre-shared key
1975 *
1976 * @v tlskey Key schedule
1977 * @v nonce Ticket nonce
1978 * @v nonce_len Length of ticket nonce
1979 * @v psk Pre-shared key
1980 * @ret rc Return status code
1981 */
1982static int tlskey_md5_sha1_save ( struct tls_key_schedule *tlskey,
1983 const void *nonce __unused,
1984 size_t nonce_len,
1985 struct tls_preshared_key *psk ) {
1986 struct digest_algorithm *digest = tlskey->digest;
1987 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1988
1989 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1990 assert ( digest == &md5_sha1_algorithm );
1991
1992 /* A ticket nonce is not supported */
1993 if ( nonce_len )
1994 return -ENOTSUP;
1995
1996 /* For TLS versions 1.1 and earlier, the pre-master secret may
1997 * be any length but the master secret is fixed at 48 bytes.
1998 * It will have been split to become 24 bytes in each of the
1999 * MD5 and SHA-1 HMAC keys.
2000 */
2001 assert ( sizeof ( psk->key.master_secret.md5 ) <=
2003 assert ( sizeof ( psk->key.master_secret.sha1 ) <=
2005 memcpy ( psk->key.master_secret.md5, hkeys->md5,
2006 sizeof ( psk->key.master_secret.md5 ) );
2007 memcpy ( psk->key.master_secret.sha1, hkeys->sha1,
2008 sizeof ( psk->key.master_secret.sha1 ) );
2009
2010 return 0;
2011}
2012
2013/** TLS key schedule based on P_MD5()+P_SHA1() */
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 out[4]
Definition CIB_PRM.h:8
union @162305117151260234136356364136041353210355154177 key
u32 info
Definition ar9003_mac.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
unsigned short uint16_t
Definition stdint.h:11
unsigned char uint8_t
Definition stdint.h:10
long index
Definition bigint.h:30
static const void * src
Definition string.h:48
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
struct digest_algorithm digest_null
Definition crypto_null.c:53
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t flags
Flags.
Definition ena.h:7
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define ENOENT
No such file or directory.
Definition errno.h:558
#define EINVAL
Invalid argument.
Definition errno.h:472
#define EPROTO
Protocol error.
Definition errno.h:668
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
#define EPERM
Operation not permitted.
Definition errno.h:658
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
void hkdf_expand(struct digest_algorithm *digest, const void *prk, const void *info, size_t info_len, void *out, size_t len)
Expand pseudorandom key.
Definition hkdf.c:95
void hkdf_extract(struct digest_algorithm *digest, const void *salt, size_t salt_len, const void *ikm, size_t ikm_len, void *prk)
Extract fixed-length pseudorandom key.
Definition hkdf.c:56
HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len)
Initialise HMAC.
Definition hmac.c:106
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:124
void hmac_key(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len, void *key)
Construct HMAC reduced key.
Definition hmac.c:59
void hmac_init_key(struct digest_algorithm *digest, void *ctx, const void *key)
Initialise HMAC from reduced key.
Definition hmac.c:82
Keyed-Hashing for Message Authentication.
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:62
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:48
static size_t hmac_keysize(struct digest_algorithm *digest)
Calculate HMAC reduced key size.
Definition hmac.h:35
#define htons(value)
Definition byteswap.h:136
#define __attribute__(x)
Definition compiler.h:10
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:294
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:305
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:299
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
unsigned long tmp
Definition linux_pci.h:65
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:738
Dynamic memory allocation.
struct digest_algorithm md5_algorithm
struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition md5_sha1.c:87
Hybrid MD5+SHA1 hash as used by TLSv1.1 and earlier.
uint32_t end
Ending offset.
Definition netvsc.h:7
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
uint32_t digestsize
Digest size (i.e.
Definition pccrr.h:1
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
struct digest_algorithm sha1_algorithm
uint16_t hello
Hello time.
Definition stp.h:27
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
size_t ctxsize
Context size.
Definition crypto.h:23
const char * name
Algorithm name.
Definition crypto.h:21
A text label widget.
Definition label.h:16
An MD5+SHA1 HMAC key block.
Definition md5_sha1.h:57
uint8_t md5[MD5_BLOCK_SIZE]
MD5 HMAC key.
Definition md5_sha1.h:59
uint8_t sha1[SHA1_BLOCK_SIZE]
SHA-1 HMAC key.
Definition md5_sha1.h:61
TLS client state.
Definition tls.h:451
A TLS endpoint.
Definition tlskey.h:19
uint8_t index
Endpoint index.
Definition tlskey.h:21
const char name[7]
Name (for key expansion labels).
Definition tlskey.h:23
void * secret
Secret.
Definition tlskey.h:77
unsigned int flags
Key flags.
Definition tlskey.h:79
TLS key schedule operations.
Definition tlskey.h:170
int(* save)(struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.h:298
int(* load)(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.h:307
int(* master)(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.h:233
int(* cipher)(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
Generate cipher key material.
Definition tlskey.h:270
int(* bind)(const struct tls_preshared_key *psk, const void *hash, void *binder, size_t binder_len)
Generate pre-shared key binder value.
Definition tlskey.h:318
int(* verify)(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.h:243
const char * name
Name.
Definition tlskey.h:172
size_t(* secretsize)(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.h:194
int(* tbshash)(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.h:285
int(* traffic)(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secrets.
Definition tlskey.h:254
void(* expand)(struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.h:206
void(* reset)(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.h:215
int(* apply)(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.h:224
A TLS key schedule.
Definition tlskey.h:100
const struct tls_key_schedule_operations * op
Key schedule operations.
Definition tlskey.h:102
void * secret
Secret(s).
Definition tlskey.h:111
struct tls_random random[2]
Client and server random bytes.
Definition tlskey.h:120
size_t secretsize
Secret size.
Definition tlskey.h:106
struct tls_transcript transcript
Running handshake transcript digest.
Definition tlskey.h:116
struct tls_random nonce
Local endpoint random bytes.
Definition tlskey.h:118
struct tls_traffic_secret traffic[2]
Traffic secrets.
Definition tlskey.h:124
struct digest_algorithm * digest
Digest algorithm.
Definition tlskey.h:104
void * dynamic
Dynamically-allocated storage.
Definition tlskey.h:109
struct tls_kdf_secret kdf
Key derivation function secret.
Definition tlskey.h:122
A TLS traffic phase.
Definition tlskey.c:127
const char * name
Name.
Definition tlskey.c:129
const char label[3]
Key expansion label.
Definition tlskey.c:131
uint8_t flags
Required key derivation function flags.
Definition tlskey.c:133
A TLS pre-shared key.
Definition tlskey.h:128
uint8_t resumption[48]
Resumption secret.
Definition tlskey.h:165
union tls_preshared_key::@022173016027117201055347232316162256252261104170::@216204225163015142232067115177347130257031275370 master_secret
Master secret.
struct digest_algorithm * digest
Digest algorithm (if set).
Definition tlskey.h:132
unsigned int flags
Key flags.
Definition tlskey.h:134
uint8_t md5[24]
Definition tlskey.h:151
union tls_preshared_key::@022173016027117201055347232316162256252261104170 key
Key material.
uint8_t sha1[24]
Definition tlskey.h:152
const struct tls_key_schedule_operations * op
Key schedule operations (if set).
Definition tlskey.h:130
TLS client or server random bytes.
Definition tlskey.h:36
TLS server state.
Definition tls.h:461
A TLS traffic secret.
Definition tlskey.h:92
const struct tls_phase * phase
Phase.
Definition tlskey.h:96
void * secret
Secret.
Definition tlskey.h:94
A TLS running handshake transcript digest.
Definition tlskey.h:42
void * finishing
Running digest value up to the most recent Finished (if any).
Definition tlskey.h:63
void * running
Running digest value.
Definition tlskey.h:52
unsigned int flags
Transcript flags.
Definition tlskey.h:65
void * ctx
Digest context.
Definition tlskey.h:44
A Finished handshake record prefix of interest.
Definition tlskey.c:290
uint8_t type
Definition tlskey.c:291
A ClientHello or ServerHello handshake record prefix of interest.
Definition tlskey.c:279
struct tls_random random
Definition tlskey.c:283
uint8_t type
Definition tlskey.c:280
uint16_t version
Definition tlskey.c:282
uint8_t length[3]
Definition tlskey.c:281
static u32 xor(u32 a, u32 b)
Definition tlan.h:457
static int tlskey_hash_tbshash(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.c:1697
static void tlskey_md5_sha1_expand(struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:1898
static int tlskey_hash_cipher(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
Generate cipher key material.
Definition tlskey.c:1644
static void tlskey_hkdf_expand(struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:958
static int tlskey_hash_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1801
int tlskey_save(struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:795
static unsigned int tlskey_handshake(struct tls_key_schedule *tlskey, const void *data, size_t len)
Process digested handshake record.
Definition tlskey.c:385
int tlskey_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:557
static void tlskey_hkdf_empty(struct digest_algorithm *digest, void *empty)
Calculate empty digest value.
Definition tlskey.c:994
static int tlskey_hash_verify(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.c:1576
static int tlskey_hash_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1523
int tlskey_cipher(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
Generate cipher key material.
Definition tlskey.c:691
int tlskey_load(struct tls_key_schedule *tlskey, int ems, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:838
static int tlskey_hkdf_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1093
static void tlskey_hash_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1482
void tlskey_stop(struct tls_key_schedule *tlskey)
Stop key schedule.
Definition tlskey.c:259
static int tlskey_hkdf_cipher(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac __unused, size_t mac_len)
Generate cipher key material.
Definition tlskey.c:1192
static void tlskey_hkdf_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1040
const struct tls_phase tls_early
Early traffic phase.
Definition tlskey.c:137
static int tlskey_hash_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:1613
void tlskey_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:492
const struct tls_phase tls_handshake
Handshake traffic phase.
Definition tlskey.c:144
int tlskey_start(struct tls_key_schedule *tlskey, const struct tls_key_schedule_operations *op, struct digest_algorithm *digest, const struct tls_random *nonce)
Start key schedule.
Definition tlskey.c:180
static int tlskey_hkdf_verify(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.c:1123
#define TLSKEY_FINISHED
Finished record type.
Definition tlskey.c:295
static int tlskey_md5_sha1_save(struct tls_key_schedule *tlskey, const void *nonce __unused, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:1982
int tlskey_tbshash(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.c:744
int tlskey_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:522
static int tlskey_hkdf_save(struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:1276
static int tlskey_hash_save(struct tls_key_schedule *tlskey, const void *nonce __unused, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:1768
#define TLSKEY_HELLO_IDX(type)
Calculate endpoint index from ClientHello or ServerHello record type.
Definition tlskey.c:287
static int tlskey_hkdf_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1314
static int tlskey_hash_bind(const struct tls_preshared_key *psk __unused, const void *hash __unused, void *binder __unused, size_t binder_len)
Generate pre-shared key binder value.
Definition tlskey.c:1828
const struct tls_key_schedule_operations tlskey_hash
TLS key schedule based on P_Hash().
Definition tlskey.c:1840
int tlskey_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:639
static int tlskey_hkdf_bind(const struct tls_preshared_key *psk, const void *hash, void *binder, size_t binder_len)
Generate pre-shared key binder value.
Definition tlskey.c:1341
static size_t tlskey_hkdf_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:941
static int tlskey_hkdf_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:1064
static int tlskey_hkdf_tbshash(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data __unused, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.c:1235
const struct tls_key_schedule_operations tlskey_md5_sha1
TLS key schedule based on P_MD5()+P_SHA1().
Definition tlskey.c:2014
static int tlskey_hash_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:1499
static unsigned int tlskey_hello(struct tls_key_schedule *tlskey, const struct tlskey_hello *hello, unsigned int index)
Process digested ClientHello or ServerHello handshake record.
Definition tlskey.c:305
#define TLSKEY_HASH_VERIFY_MIN
Minimum length for verification data.
Definition tlskey.c:1405
static size_t tlskey_hash_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1413
static int tlskey_hkdf_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:1159
int tlskey_verify(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.c:602
static void tlskey_hkdf_finished(struct digest_algorithm *digest, const void *secret, const void *hash, void *out)
Calculate a finished MAC.
Definition tlskey.c:1012
static void tlskey_hash_expand(struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:1430
static size_t tlskey_md5_sha1_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1871
static unsigned int tlskey_finished(struct tls_key_schedule *tlskey)
Process digested Finished handshake record.
Definition tlskey.c:340
void tlskey_digest(struct tls_key_schedule *tlskey, const void *data, size_t len)
Add handshake to running transcript digest.
Definition tlskey.c:416
const struct tls_phase tls_application
Application traffic phase.
Definition tlskey.c:151
static int tlskey_md5_sha1_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:1937
int tlskey_bind(const struct tls_preshared_key *psk, const void *prefix, size_t prefix_len, void *binder, size_t binder_len)
Generate pre-shared key binder value.
Definition tlskey.c:895
static void tlskey_expand(struct tls_key_schedule *tlskey, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:466
const struct tls_key_schedule_operations tlskey_hkdf
TLS key schedule based on HKDF.
Definition tlskey.c:1379
TLS key schedules.
#define TLSKEY_KDF_EMS
Key derivation function has an extended master secret.
Definition tlskey.h:89
#define TLS_CLIENT
Client endpoint index.
Definition tlskey.h:27
#define TLSKEY_TSF_FINISHED
Transcript digest includes a Finished record.
Definition tlskey.h:72
#define TLSKEY_KDF_MASTER
Key derivation function has a master secret.
Definition tlskey.h:86
#define TLSKEY_KDF_KEYED
Key derivation function has key material.
Definition tlskey.h:83
#define TLS_SERVER
Server endpoint index.
Definition tlskey.h:30
#define TLSKEY_TSF_NONCED
Transcript digest includes a Hello record containing the local nonce.
Definition tlskey.h:69
char prefix[4]
Definition vmconsole.c:53
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
u8 iv[16]
Initialization vector.
Definition wpa.h:33
u8 nonce[32]
Nonce value.
Definition wpa.h:25