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 /* Generate digest value */
763 DBGC2 ( tlskey, "TLSKEY %p generating signable %s %s digest\n",
764 tlskey, end->name, digest->name );
765 if ( ( rc = op->tbshash ( tlskey, end, digest, data, len,
766 tbs ) ) != 0 ) {
767 return rc;
768 }
769 DBGC ( tlskey, "TLSKEY %p generated signable %s %s digest:\n",
770 tlskey, end->name, digest->name );
771 DBGC_HDA ( tlskey, 0, tbs, digest->digestsize );
772
773 return 0;
774}
775
776/**
777 * Save pre-shared key
778 *
779 * @v tlskey Key schedule
780 * @v nonce Ticket nonce
781 * @v nonce_len Length of ticket nonce
782 * @v psk Pre-shared key to fill in
783 * @ret rc Return status code
784 */
785int tlskey_save ( struct tls_key_schedule *tlskey, const void *nonce,
786 size_t nonce_len, struct tls_preshared_key *psk ) {
787 const struct tls_key_schedule_operations *op = tlskey->op;
788 struct digest_algorithm *digest = tlskey->digest;
789 int rc;
790
791 /* Clear any existing pre-shared key */
792 memset ( psk, 0, sizeof ( *psk ) );
793
794 /* Sanity check */
795 if ( ! op )
796 return -ENOTTY;
797
798 /* Session resumption requires a master secret */
799 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
800 DBGC ( tlskey, "TLSKEY %p cannot save key without a master "
801 "secret\n", tlskey );
802 return -EPROTO;
803 }
804
805 /* Save key material */
806 DBGC2 ( tlskey, "TLSKEY %p saving key\n", tlskey );
807 if ( ( rc = op->save ( tlskey, nonce, nonce_len, psk ) ) != 0 )
808 return rc;
809 DBGC ( tlskey, "TLSKEY %p saved key:\n", tlskey );
810 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
811
812 /* Record key properties */
813 psk->op = op;
814 psk->digest = digest;
815 psk->flags = tlskey->kdf.flags;
816
817 return 0;
818}
819
820/**
821 * Load pre-shared key
822 *
823 * @v tlskey Key schedule
824 * @v ems Extended master secret extension is enabled
825 * @v psk Pre-shared key
826 * @ret rc Return status code
827 */
828int tlskey_load ( struct tls_key_schedule *tlskey, int ems,
829 const struct tls_preshared_key *psk ) {
830 const struct tls_key_schedule_operations *op = tlskey->op;
831 struct digest_algorithm *digest = tlskey->digest;
832 int rc;
833
834 /* Reset key schedule */
835 tlskey_reset ( tlskey );
836
837 /* Sanity check */
838 if ( ! op )
839 return -ENOTTY;
840
841 /* Session resumption requires a master secret */
842 if ( ! ( psk->flags & TLSKEY_KDF_MASTER ) ) {
843 DBGC ( tlskey, "TLSKEY %p cannot load from a non-master "
844 "secret\n", tlskey );
845 return -EPROTO;
846 }
847
848 /* Pre-shared key must match extended/non-extended usage */
849 if ( ( !! ems ) != ( !! ( psk->flags & TLSKEY_KDF_EMS ) ) ) {
850 DBGC ( tlskey, "TLSKEY %p cannot load from %sextended master "
851 "secret\n", tlskey, ( ems ? "non-" : "" ) );
852 return -EPERM;
853 }
854
855 /* Pre-shared key must match schedule and digest */
856 if ( ( op != psk->op ) || ( digest != psk->digest ) ) {
857 DBGC ( tlskey, "TLSKEY %p cannot load from %s with %s\n",
858 tlskey, ( psk->op ? psk->op->name : "(unknown)" ),
859 ( psk->digest ? psk->digest->name : "(unknown)" ) );
860 return -EPERM;
861 }
862
863 /* Load key material */
864 DBGC ( tlskey, "TLSKEY %p loading key:\n", tlskey );
865 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
866 if ( ( rc = op->load ( tlskey, psk ) ) != 0 )
867 return rc;
868
869 /* Set flags */
870 tlskey->kdf.flags = ( psk->flags & op->mask );
871
872 return 0;
873}
874
875/**
876 * Generate pre-shared key binder value
877 *
878 * @v psk Pre-shared key
879 * @v prefix ClientHello prefix
880 * @v prefix_len Length of ClientHello prefix
881 * @v binder Binder value to fill in
882 * @v binder_len Length of binder value
883 * @ret rc Return status code
884 */
885int tlskey_bind ( const struct tls_preshared_key *psk, const void *prefix,
886 size_t prefix_len, void *binder, size_t binder_len ) {
887 const struct tls_key_schedule_operations *op = psk->op;
888 struct digest_algorithm *digest = psk->digest;
889 int rc;
890
891 /* Generate prefix digest and binder value */
892 if ( op && digest ) {
893 size_t digestsize = digest->digestsize;
894 size_t ctxsize = digest->ctxsize;
897
898 /* Calculate prefix digest */
899 digest_init ( digest, ctx );
900 digest_update ( digest, ctx, prefix, prefix_len );
901 digest_final ( digest, ctx, out );
902
903 /* Generate binder value */
904 DBGC2 ( psk, "TLSKEY %p generating key binder:\n", psk );
905 DBGC2_HDA ( psk, 0, &psk->key, sizeof ( psk->key ) );
906 if ( ( rc = op->bind ( psk, out, binder, binder_len ) ) != 0 )
907 return rc;
908 DBGC ( psk, "TLSKEY %p generated key binder:\n", psk );
909 DBGC_HDA ( psk, 0, binder, binder_len );
910
911 return 0;
912 }
913
914 DBGC ( psk, "TLSKEY %p cannot bind empty pre-shared key\n", psk );
915 return -ENOENT;
916}
917
918/*****************************************************************************
919 *
920 * TLS version 1.3 key schedule using HKDF
921 *
922 *****************************************************************************
923 */
924
925/**
926 * Calculate secret size
927 *
928 * @v digest Digest algorithm
929 * @ret secretsize Secret size, or zero if unsupported
930 */
931static size_t tlskey_hkdf_secretsize ( struct digest_algorithm *digest ) {
932 size_t digestsize = digest->digestsize;
933
934 return ( digestsize * 3 /* KDF, client, and server secrets */ );
935}
936
937/**
938 * Expand key material
939 *
940 * @v digest Digest algorithm
941 * @v secret Secret
942 * @v label Label string
943 * @v seed Seed material
944 * @v seed_len Length of seed material
945 * @v out Output buffer
946 * @v out_len Length of output buffer
947 */
948static void tlskey_hkdf_expand ( struct digest_algorithm *digest,
949 const void *secret, const char *label,
950 const void *seed, size_t seed_len,
951 void *out, size_t out_len ) {
952 static const char prefix[6] = "tls13 ";
953 const void *context = seed;
954 size_t context_len = seed_len;
955 size_t prefix_len = sizeof ( prefix );
956 size_t label_len = strlen ( label );
957 struct {
959 uint8_t label_len;
960 char prefix[prefix_len];
961 char label[label_len];
962 uint8_t context_len;
963 uint8_t context[context_len];
964 } __attribute__ (( packed )) info;
965
966 /* Construct additional information */
967 info.len = htons ( out_len );
968 info.label_len = ( prefix_len + label_len );
969 memcpy ( info.prefix, prefix, prefix_len );
970 memcpy ( info.label, label, label_len );
971 info.context_len = context_len;
972 memcpy ( info.context, context, context_len );
973
974 /* Generate output using HKDF */
975 hkdf_expand ( digest, secret, &info, sizeof ( info ), out, out_len );
976}
977
978/**
979 * Calculate empty digest value
980 *
981 * @v digest Digest algorithm
982 * @v empty Empty digest to fill in
983 */
984static void tlskey_hkdf_empty ( struct digest_algorithm *digest,
985 void *empty ) {
986 size_t ctxsize = digest->ctxsize;
987 uint8_t ctx[ctxsize];
988
989 /* Calculate empty digest */
990 digest_init ( digest, ctx );
991 digest_final ( digest, ctx, empty );
992}
993
994/**
995 * Calculate a finished MAC
996 *
997 * @v digest Digest algorithm
998 * @v secret Secret
999 * @v hash Message hash
1000 * @v out Output buffer
1001 */
1002static void tlskey_hkdf_finished ( struct digest_algorithm *digest,
1003 const void *secret, const void *hash,
1004 void *out ) {
1005 size_t digestsize = digest->digestsize;
1006 size_t hctxsize = hmac_ctxsize ( digest );
1007 struct {
1008 uint8_t hctx[hctxsize];
1010 } tmp;
1011
1012 /* Generate HMAC key */
1013 tlskey_hkdf_expand ( digest, secret, "finished", NULL, 0,
1014 tmp.key, sizeof ( tmp.key ) );
1015
1016 /* Generate HMAC */
1017 hmac_init ( digest, tmp.hctx, tmp.key, sizeof ( tmp.key ) );
1018 hmac_update ( digest, tmp.hctx, hash, digestsize );
1019 hmac_final ( digest, tmp.hctx, out );
1020
1021 /* Clear temporary secrets */
1022 memset ( &tmp, 0, sizeof ( tmp ) );
1023}
1024
1025/**
1026 * Reset key schedule
1027 *
1028 * @v key Key schedule
1029 */
1030static void tlskey_hkdf_reset ( struct tls_key_schedule *tlskey ) {
1031 struct digest_algorithm *digest = tlskey->digest;
1032 size_t digestsize = digest->digestsize;
1033 void *secret = tlskey->secret;
1034
1035 /* Allocate and initialise secrets */
1036 tlskey->kdf.secret = secret; secret += digestsize;
1037 tlskey->traffic[TLS_CLIENT].secret = secret; secret += digestsize;
1038 tlskey->traffic[TLS_SERVER].secret = secret; secret += digestsize;
1039 assert ( secret == ( tlskey->secret + tlskey->secretsize ) );
1040
1041 /* Initialise empty early secret */
1042 hkdf_extract ( digest, NULL, 0, tlskey->kdf.secret, digestsize,
1043 tlskey->kdf.secret );
1044}
1045
1046/**
1047 * Apply a new shared secret
1048 *
1049 * @v tlskey Key schedule
1050 * @v shared New shared secret
1051 * @v shared_len Length of new shared secret
1052 * @ret rc Return status code
1053 */
1054static int tlskey_hkdf_apply ( struct tls_key_schedule *tlskey,
1055 const void *shared, size_t shared_len ) {
1056 struct digest_algorithm *digest = tlskey->digest;
1057 size_t digestsize = digest->digestsize;
1058 uint8_t empty[digestsize];
1059
1060 /* Generate derived secret */
1061 tlskey_hkdf_empty ( digest, empty );
1062 tlskey_expand ( tlskey, tlskey->kdf.secret, "derived", empty,
1063 digestsize, tlskey->kdf.secret, digestsize );
1064 DBGC2 ( tlskey, "TLSKEY %p derived:\n", tlskey );
1065 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1066
1067 /* Extract new pseudorandom key */
1068 hkdf_extract ( digest, tlskey->kdf.secret, digestsize, shared,
1069 shared_len, tlskey->kdf.secret );
1070 DBGC2 ( tlskey, "TLSKEY %p extracted PRK:\n", tlskey );
1071 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1072
1073 return 0;
1074}
1075
1076/**
1077 * Generate master secret
1078 *
1079 * @v tlskey Key schedule
1080 * @v ems Extended master secret extension is enabled
1081 * @ret rc Return status code
1082 */
1083static int tlskey_hkdf_master ( struct tls_key_schedule *tlskey, int ems ) {
1084 struct digest_algorithm *digest = tlskey->digest;
1085 size_t digestsize = digest->digestsize;
1086 uint8_t zero[digestsize];
1087 int rc;
1088
1089 /* Extended master secret must always be used */
1090 if ( ! ems ) {
1091 DBGC ( tlskey, "TLSKEY %p requires an extended master "
1092 "secret\n", tlskey );
1093 return -EPROTO;
1094 }
1095
1096 /* Generate master secret */
1097 memset ( zero, 0, sizeof ( zero ) );
1098 if ( ( rc = tlskey_apply ( tlskey, zero, sizeof ( zero ) ) ) != 0 )
1099 return rc;
1100
1101 return 0;
1102}
1103
1104/**
1105 * Generate verification data
1106 *
1107 * @v tlskey Key schedule
1108 * @v end Verification endpoint
1109 * @v verify Verification data to fill in
1110 * @v verify_len Length of verification data
1111 * @ret rc Return status code
1112 */
1113static int tlskey_hkdf_verify ( struct tls_key_schedule *tlskey,
1114 const struct tls_endpoint *end,
1115 void *verify, size_t verify_len ) {
1116 struct tls_traffic_secret *traffic = &tlskey->traffic[end->index];
1117 struct digest_algorithm *digest = tlskey->digest;
1118 size_t digestsize = digest->digestsize;
1119
1120 /* Verification data must be a complete digest output */
1121 if ( verify_len != digestsize )
1122 return -EINVAL;
1123
1124 /* Verification data is derived from handshake secrets */
1125 if ( traffic->phase != &tls_handshake ) {
1126 DBGC ( tlskey, "TLSKEY %p cannot generate %s verification "
1127 "data without %s handshake traffic secrets\n",
1128 tlskey, end->name, end->name );
1129 return -EPROTO;
1130 }
1131
1132 /* Generate verification data */
1133 tlskey_hkdf_finished ( digest, traffic->secret,
1134 tlskey->transcript.running, verify );
1135 DBGC ( tlskey, "TLSKEY %p %s verification:\n", tlskey, end->name );
1136 DBGC_HDA ( tlskey, 0, verify, verify_len );
1137
1138 return 0;
1139}
1140
1141/**
1142 * Generate traffic secret
1143 *
1144 * @v tlskey Key schedule
1145 * @v writer Writer endpoint
1146 * @v phase Traffic phase
1147 * @ret rc Return status code
1148 */
1149static int tlskey_hkdf_traffic ( struct tls_key_schedule *tlskey,
1150 const struct tls_endpoint *writer,
1151 const struct tls_phase *phase ) {
1152 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1153 struct digest_algorithm *digest = tlskey->digest;
1154 size_t digestsize = digest->digestsize;
1155 char label[ 13 /* "[c|s] [e|hs|ap] traffic" + NUL */ ];
1156
1157 /* Generate label */
1158 snprintf ( label, sizeof ( label ), "%c %s traffic",
1159 writer->name[0], phase->label );
1160
1161 /* Generate traffic secret */
1162 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1164 traffic->secret, digestsize );
1165
1166 return 0;
1167}
1168
1169/**
1170 * Generate cipher key material
1171 *
1172 * @v tlskey Key schedule
1173 * @v writer Writer endpoint
1174 * @v key Cipher key to fill in
1175 * @v key_len Length of cipher key
1176 * @v iv Fixed portion of initialisation vector to fill in
1177 * @v iv_len Length of fixed portion of initialisation vector
1178 * @v mac MAC secret to fill in
1179 * @v mac_len Length of MAC secret
1180 * @ret rc Return status code
1181 */
1182static int tlskey_hkdf_cipher ( struct tls_key_schedule *tlskey,
1183 const struct tls_endpoint *writer,
1184 void *key, size_t key_len, void *iv,
1185 size_t iv_len, void *mac __unused,
1186 size_t mac_len ) {
1187 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1188 struct digest_algorithm *digest = tlskey->digest;
1189 size_t digestsize = digest->digestsize;
1190 void *secret = traffic->secret;
1191
1192 /* The key schedule does not define a way to generate MAC secrets */
1193 if ( mac_len ) {
1194 DBGC ( tlskey, "TLSKEY %p does not support MAC secrets\n",
1195 tlskey );
1196 return -ENOTSUP;
1197 }
1198
1199 /* Generate cipher key */
1200 tlskey_expand ( tlskey, secret, "key", NULL, 0, key, key_len );
1201
1202 /* Generate initialisation vector */
1203 tlskey_expand ( tlskey, secret, "iv", NULL, 0, iv, iv_len );
1204
1205 /* Update traffic secret, if applicable */
1206 if ( traffic->phase == &tls_application ) {
1207 tlskey_expand ( tlskey, secret, "traffic upd", NULL, 0,
1208 secret, digestsize );
1209 }
1210
1211 return 0;
1212}
1213
1214/**
1215 * Generate signable digest value
1216 *
1217 * @v tlskey Key schedule
1218 * @v end Endpoint
1219 * @v digest Signature digest algorithm
1220 * @v data Additional data
1221 * @v len Length of additional data
1222 * @v tbs Signable digest value to fill in
1223 * @ret rc Return status code
1224 */
1225static int tlskey_hkdf_tbshash ( struct tls_key_schedule *tlskey,
1226 const struct tls_endpoint *end,
1227 struct digest_algorithm *digest,
1228 const void *data __unused, size_t len,
1229 void *tbs ) {
1230 size_t ctxsize = digest->ctxsize;
1232 char buf[64];
1233 int label_len;
1234
1235 /* There is no way to incorporate additional data */
1236 if ( len ) {
1237 DBGC ( tlskey, "TLSKEY %p cannot generate digest with "
1238 "additional data\n", tlskey );
1239 return -ENOTSUP;
1240 }
1241
1242 /* Generate digest value (all input is public) */
1243 digest_init ( digest, ctx );
1244 memset ( buf, 0x20, sizeof ( buf ) );
1245 digest_update ( digest, ctx, buf, sizeof ( buf ) );
1246 label_len = snprintf ( buf, sizeof ( buf ),
1247 "TLS 1.3, %s CertificateVerify", end->name );
1248 assert ( label_len == 33 /* for both "client" and "server" */ );
1249 digest_update ( digest, ctx, buf, ( label_len + 1 /* NUL */ ) );
1250 digest_update ( digest, ctx, tlskey->transcript.running,
1251 tlskey->digest->digestsize );
1252 digest_final ( digest, ctx, tbs );
1253
1254 return 0;
1255}
1256
1257/**
1258 * Save pre-shared key
1259 *
1260 * @v tlskey Key schedule
1261 * @v nonce Ticket nonce
1262 * @v nonce_len Length of ticket nonce
1263 * @v psk Pre-shared key to fill in
1264 * @ret rc Return status code
1265 */
1266static int tlskey_hkdf_save ( struct tls_key_schedule *tlskey,
1267 const void *nonce, size_t nonce_len,
1268 struct tls_preshared_key *psk ) {
1269 struct digest_algorithm *digest = tlskey->digest;
1270 size_t digestsize = digest->digestsize;
1271 struct {
1272 uint8_t master[digestsize];
1273 } tmp;
1274
1275 /* The pre-shared key currently uses a fixed-size buffer */
1276 if ( digestsize > sizeof ( psk->key.resumption ) ) {
1277 DBGC ( tlskey, "TLSKEY %p cannot save %s pre-shared key\n",
1278 tlskey, digest->name );
1279 return -ENOTSUP;
1280 }
1281
1282 /* Generate resumption master secret */
1283 tlskey_expand ( tlskey, tlskey->kdf.secret, "res master",
1285 tmp.master, sizeof ( tmp.master ) );
1286
1287 /* Generate resumption secret */
1288 tlskey_expand ( tlskey, tmp.master, "resumption", nonce, nonce_len,
1289 psk->key.resumption, digestsize );
1290
1291 /* Clear temporary secrets */
1292 memset ( &tmp, 0, sizeof ( tmp ) );
1293
1294 return 0;
1295}
1296
1297/**
1298 * Load pre-shared key
1299 *
1300 * @v tlskey Key schedule
1301 * @v psk Pre-shared key
1302 * @ret rc Return status code
1303 */
1304static int tlskey_hkdf_load ( struct tls_key_schedule *tlskey,
1305 const struct tls_preshared_key *psk ) {
1306 struct digest_algorithm *digest = tlskey->digest;
1307 size_t digestsize = digest->digestsize;
1308
1309 /* Sanity checks */
1310 assert ( digest == psk->digest );
1311 assert ( digestsize <= sizeof ( psk->key.resumption ) );
1312
1313 /* Extract early secret */
1314 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize,
1315 tlskey->kdf.secret );
1316 DBGC2 ( tlskey, "TLSKEY %p early secret:\n", tlskey );
1317 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1318
1319 return 0;
1320}
1321
1322/**
1323 * Generate pre-shared key binder value
1324 *
1325 * @v psk Pre-shared key
1326 * @v hash Partial transcript hash
1327 * @v binder Binder value to fill in
1328 * @v binder_len Length of binder value
1329 * @ret rc Return status code
1330 */
1331static int tlskey_hkdf_bind ( const struct tls_preshared_key *psk,
1332 const void *hash, void *binder,
1333 size_t binder_len ) {
1334 struct digest_algorithm *digest = psk->digest;
1335 size_t digestsize = digest->digestsize;
1336 uint8_t empty[digestsize];
1337 struct {
1339 } tmp;
1340
1341 /* Binder value must be a complete digest output */
1342 if ( binder_len != digestsize )
1343 return -EINVAL;
1344
1345 /* Extract temporary copy of early secret */
1346 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize, tmp.key );
1347 DBGC2 ( psk, "TLSKEY %p temporary early secret:\n", psk );
1348 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1349
1350 /* Generate resumption binder secret */
1351 tlskey_hkdf_empty ( digest, empty );
1352 tlskey_hkdf_expand ( digest, tmp.key, "res binder", empty, digestsize,
1353 tmp.key, digestsize );
1354 DBGC2 ( psk, "TLSKEY %p resumption binder secret:\n", psk );
1355 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1356
1357 /* Generate binder */
1358 tlskey_hkdf_finished ( digest, tmp.key, hash, binder );
1359 DBGC2 ( psk, "TLSKEY %p binder:\n", psk );
1360 DBGC2_HDA ( psk, 0, binder, binder_len );
1361
1362 /* Clear temporary secrets */
1363 memset ( &tmp, 0, sizeof ( tmp ) );
1364
1365 return 0;
1366}
1367
1368/** TLS key schedule based on HKDF */
1370 .name = "HKDF",
1371 .accumulates = 1,
1372 .mask = TLSKEY_KDF_KEYED,
1373 .secretsize = tlskey_hkdf_secretsize,
1374 .expand = tlskey_hkdf_expand,
1375 .reset = tlskey_hkdf_reset,
1376 .apply = tlskey_hkdf_apply,
1377 .master = tlskey_hkdf_master,
1378 .verify = tlskey_hkdf_verify,
1379 .traffic = tlskey_hkdf_traffic,
1380 .cipher = tlskey_hkdf_cipher,
1381 .tbshash = tlskey_hkdf_tbshash,
1382 .save = tlskey_hkdf_save,
1383 .load = tlskey_hkdf_load,
1384 .bind = tlskey_hkdf_bind,
1385};
1386
1387/*****************************************************************************
1388 *
1389 * TLS version 1.2 key schedule using PRF based on P_Hash()
1390 *
1391 *****************************************************************************
1392 */
1393
1394/** Minimum length for verification data */
1395#define TLSKEY_HASH_VERIFY_MIN 12
1396
1397/**
1398 * Calculate secret size
1399 *
1400 * @v digest Digest algorithm
1401 * @ret secretsize Secret size, or zero if unsupported
1402 */
1403static size_t tlskey_hash_secretsize ( struct digest_algorithm *digest ) {
1404
1405 /* A P_Hash() key is an HMAC key */
1406 return hmac_keysize ( digest );
1407}
1408
1409/**
1410 * Expand key material
1411 *
1412 * @v digest Digest algorithm
1413 * @v secret Secret
1414 * @v label Label string
1415 * @v seed Seed material
1416 * @v seed_len Length of seed material
1417 * @v out Output buffer
1418 * @v out_len Length of output buffer
1419 */
1420static void tlskey_hash_expand ( struct digest_algorithm *digest,
1421 const void *secret, const char *label,
1422 const void *seed, size_t seed_len,
1423 void *out, size_t out_len ) {
1424 size_t digestsize = digest->digestsize;
1425 size_t hctxsize = hmac_ctxsize ( digest );
1426 size_t frag_len = digestsize;
1427 size_t label_len = strlen ( label );
1428 unsigned int index = 0;
1429 struct {
1430 uint8_t ctx[2][hctxsize];
1432 uint8_t frag[digestsize];
1433 } tmp;
1434
1435 /* Generate as much output as required */
1436 while ( out_len ) {
1437
1438 /* Generate A(n) and output fragment */
1439 hmac_init_key ( digest, tmp.ctx[0], secret );
1440 if ( index ) {
1441 hmac_update ( digest, tmp.ctx[0], tmp.a,
1442 sizeof ( tmp.a ) );
1443 memcpy ( tmp.ctx[1], tmp.ctx[0],
1444 sizeof ( tmp.ctx[1] ) );
1445 }
1446 hmac_update ( digest, tmp.ctx[0], label, label_len );
1447 hmac_update ( digest, tmp.ctx[0], seed, seed_len );
1448 hmac_final ( digest, tmp.ctx[ ( index != 0 ) ], tmp.a );
1449 if ( index++ == 0 )
1450 continue;
1451 hmac_final ( digest, tmp.ctx[0], tmp.frag );
1452
1453 /* Copy output */
1454 if ( frag_len > out_len )
1455 frag_len = out_len;
1456 memcpy ( out, tmp.frag, frag_len );
1457
1458 /* Move to next fragment */
1459 out += frag_len;
1460 out_len -= frag_len;
1461 }
1462
1463 /* Clear temporary secrets */
1464 memset ( &tmp, 0, sizeof ( tmp ) );
1465}
1466
1467/**
1468 * Reset key schedule
1469 *
1470 * @v key Key schedule
1471 */
1472static void tlskey_hash_reset ( struct tls_key_schedule *tlskey ) {
1473 void *secret = tlskey->secret;
1474
1475 /* Allocate and initialise secrets */
1476 tlskey->kdf.secret = secret;
1477 tlskey->traffic[TLS_CLIENT].secret = secret;
1478 tlskey->traffic[TLS_SERVER].secret = secret;
1479}
1480
1481/**
1482 * Apply a new shared secret
1483 *
1484 * @v tlskey Key schedule
1485 * @v shared New shared secret
1486 * @v shared_len Length of new shared secret
1487 * @ret rc Return status code
1488 */
1489static int tlskey_hash_apply ( struct tls_key_schedule *tlskey,
1490 const void *shared, size_t shared_len ) {
1491 struct digest_algorithm *digest = tlskey->digest;
1492 size_t hctxsize = hmac_ctxsize ( digest );
1493 struct {
1494 uint8_t hctx[hctxsize];
1495 } tmp;
1496
1497 /* Set HMAC key */
1498 hmac_key ( digest, tmp.hctx, shared, shared_len, tlskey->kdf.secret );
1499
1500 /* Clear temporary secrets */
1501 memset ( &tmp, 0, sizeof ( tmp ) );
1502
1503 return 0;
1504}
1505
1506/**
1507 * Generate master secret
1508 *
1509 * @v tlskey Key schedule
1510 * @v ems Extended master secret extension is enabled
1511 * @ret rc Return status code
1512 */
1513static int tlskey_hash_master ( struct tls_key_schedule *tlskey, int ems ) {
1514 struct digest_algorithm *digest = tlskey->digest;
1515 size_t digestsize = digest->digestsize;
1516 const char *label;
1517 const void *seed;
1518 size_t seed_len;
1519 struct {
1520 uint8_t master[48];
1521 } tmp;
1522 int rc;
1523
1524 /* Master secret is derived from the client and server random
1525 * values (or the full transcript digest).
1526 */
1527 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
1528 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
1529 "without a digested nonce\n", tlskey );
1530 return -EPROTO;
1531 }
1532
1533 /* Generate master secret */
1534 if ( ems ) {
1535 label = "extended master secret";
1536 seed = tlskey->transcript.running;
1537 seed_len = digestsize;
1538 } else {
1539 label = "master secret";
1540 seed = &tlskey->random;
1541 seed_len = sizeof ( tlskey->random );
1542 }
1543 tlskey_expand ( tlskey, tlskey->kdf.secret, label, seed, seed_len,
1544 tmp.master, sizeof ( tmp.master ) );
1545
1546 /* Apply master secret */
1547 if ( ( rc = tlskey_apply ( tlskey, tmp.master,
1548 sizeof ( tmp.master ) ) ) != 0 ) {
1549 goto err_apply;
1550 }
1551
1552 err_apply:
1553 memset ( &tmp, 0, sizeof ( tmp ) );
1554 return rc;
1555}
1556
1557/**
1558 * Generate verification data
1559 *
1560 * @v tlskey Key schedule
1561 * @v end Verification endpoint
1562 * @v verify Verification data to fill in
1563 * @v verify_len Length of verification data
1564 * @ret rc Return status code
1565 */
1566static int tlskey_hash_verify ( struct tls_key_schedule *tlskey,
1567 const struct tls_endpoint *end,
1568 void *verify, size_t verify_len ) {
1569 struct digest_algorithm *digest = tlskey->digest;
1570 size_t digestsize = digest->digestsize;
1571 char label[ 16 /* "[client|server] finished" + NUL */ ];
1572
1573 /* Verification data must be at least 12 bytes for all digests */
1574 if ( verify_len < TLSKEY_HASH_VERIFY_MIN )
1575 return -EINVAL;
1576
1577 /* Verification data is derived from the master secret */
1578 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
1579 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
1580 "without a master secret\n", tlskey );
1581 return -EPROTO;
1582 }
1583
1584 /* Construct label */
1585 snprintf ( label, sizeof ( label ), "%s finished", end->name );
1586
1587 /* Generate verification data */
1588 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1589 tlskey->transcript.running, digestsize,
1590 verify, verify_len );
1591
1592 return 0;
1593}
1594
1595/**
1596 * Generate traffic secret
1597 *
1598 * @v tlskey Key schedule
1599 * @v writer Writer endpoint
1600 * @v phase Traffic phase
1601 * @ret rc Return status code
1602 */
1603static int tlskey_hash_traffic ( struct tls_key_schedule *tlskey,
1604 const struct tls_endpoint *writer,
1605 const struct tls_phase *phase ) {
1606 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1607
1608 /* Only application phase keys are supported */
1609 if ( phase != &tls_application ) {
1610 DBGC ( tlskey, "TLSKEY %p does not support %s traffic keys\n",
1611 tlskey, phase->name );
1612 return -ENOTSUP;
1613 }
1614
1615 /* There are no separate traffic secrets */
1616 assert ( traffic->secret == tlskey->kdf.secret );
1617
1618 return 0;
1619}
1620
1621/**
1622 * Generate cipher key material
1623 *
1624 * @v tlskey Key schedule
1625 * @v writer Writer endpoint
1626 * @v key Cipher key to fill in
1627 * @v key_len Length of cipher key
1628 * @v iv Fixed portion of initialisation vector to fill in
1629 * @v iv_len Length of fixed portion of initialisation vector
1630 * @v mac MAC secret to fill in
1631 * @v mac_len Length of MAC secret
1632 * @ret rc Return status code
1633 */
1634static int tlskey_hash_cipher ( struct tls_key_schedule *tlskey,
1635 const struct tls_endpoint *writer,
1636 void *key, size_t key_len, void *iv,
1637 size_t iv_len, void *mac, size_t mac_len ) {
1638 size_t total = ( 2 * ( mac_len + key_len + iv_len ) );
1639 struct {
1640 uint8_t key[total];
1641 } tmp;
1642 struct {
1643 struct tls_random server;
1644 struct tls_random client;
1645 } __attribute__ (( packed )) seed;
1646 const void *src;
1647 size_t mask;
1648
1649 /* Construct seed (with swapped client/server random bytes) */
1650 memcpy ( &seed.server, &tlskey->random[TLS_SERVER],
1651 sizeof ( seed.server ) );
1652 memcpy ( &seed.client, &tlskey->random[TLS_CLIENT],
1653 sizeof ( seed.client ) );
1654
1655 /* Generate key material */
1656 tlskey_expand ( tlskey, tlskey->kdf.secret, "key expansion", &seed,
1657 sizeof ( seed ), tmp.key, sizeof ( tmp.key ) );
1658
1659 /* Partition key material */
1660 src = tmp.key;
1661 mask = ( ( writer->index == TLS_CLIENT ) ? 0 : -1UL );
1662 memcpy ( mac, ( src + ( mac_len & mask ) ), mac_len );
1663 src += ( 2 * mac_len );
1664 memcpy ( key, ( src + ( key_len & mask ) ), key_len );
1665 src += ( 2 * key_len );
1666 memcpy ( iv, ( src + ( iv_len & mask ) ), iv_len );
1667 src += ( 2 * iv_len );
1668 assert ( src == &tmp.key[total] );
1669
1670 /* Clear temporary secrets */
1671 memset ( &tmp, 0, sizeof ( tmp ) );
1672
1673 return 0;
1674}
1675
1676/**
1677 * Generate signable digest value
1678 *
1679 * @v tlskey Key schedule
1680 * @v end Endpoint
1681 * @v digest Signature digest algorithm
1682 * @v data Additional data
1683 * @v len Length of additional data
1684 * @v tbs Signable digest value to fill in
1685 * @ret rc Return status code
1686 */
1687static int tlskey_hash_tbshash ( struct tls_key_schedule *tlskey,
1688 const struct tls_endpoint *end,
1689 struct digest_algorithm *digest,
1690 const void *data, size_t len, void *tbs ) {
1691 size_t ctxsize = digest->ctxsize;
1692 struct {
1693 uint8_t ctx[ctxsize];
1694 } tmp;
1695
1696 /* Generate endpoint-specific digest value */
1697 if ( end->index == TLS_CLIENT ) {
1698
1699 /* The client CertificateVerify digest value is the
1700 * raw transcript digest. We retain only a single
1701 * running transcript digest, and can therefore
1702 * provide this only for a digest algorithm that
1703 * matches our transcript digest algorithm.
1704 */
1705 if ( digest != tlskey->digest ) {
1706 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
1707 "transcript digest\n", tlskey, digest->name );
1708 return -ENOTSUP;
1709 }
1710
1711 /* There is no way to incorporate additional data */
1712 if ( len ) {
1713 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1714 "with additional data\n", tlskey );
1715 return -ENOTSUP;
1716 }
1717
1718 /* Copy transcript digest value */
1719 memcpy ( tbs, tlskey->transcript.running,
1720 digest->digestsize );
1721
1722 } else {
1723
1724 /* Generate ServerKeyExchange digest */
1725 digest_init ( digest, tmp.ctx );
1726 digest_update ( digest, tmp.ctx, &tlskey->random,
1727 sizeof ( tlskey->random ) );
1728 digest_update ( digest, tmp.ctx, data, len );
1729 digest_final ( digest, tmp.ctx, tbs );
1730 }
1731
1732 /* Clear temporary secrets */
1733 memset ( &tmp, 0, sizeof ( tmp ) );
1734
1735 return 0;
1736}
1737
1738/**
1739 * Save pre-shared key
1740 *
1741 * @v tlskey Key schedule
1742 * @v nonce Ticket nonce
1743 * @v nonce_len Length of ticket nonce
1744 * @v psk Pre-shared key to fill in
1745 * @ret rc Return status code
1746 */
1747static int tlskey_hash_save ( struct tls_key_schedule *tlskey,
1748 const void *nonce __unused, size_t nonce_len,
1749 struct tls_preshared_key *psk ) {
1750 struct digest_algorithm *digest = tlskey->digest;
1751
1752 /* A ticket nonce is not supported */
1753 if ( nonce_len )
1754 return -ENOTSUP;
1755
1756 /* For TLS version 1.2, the pre-master secret may be any
1757 * length but the master secret is fixed at 48 bytes. This is
1758 * smaller than the block size for all supported digest
1759 * algorithms. The HMAC key constructed from the master
1760 * secret will therefore be just the zero-padded master secret
1761 * value. We can therefore preserve just these first 48 bytes
1762 * of the KDF master secret (ignoring the zero padding up to
1763 * the digest block size).
1764 */
1765 assert ( sizeof ( psk->key.master_secret ) <=
1766 hmac_keysize ( digest ) );
1767 memcpy ( &psk->key.master_secret, tlskey->kdf.secret,
1768 sizeof ( psk->key.master_secret ) );
1769
1770 return 0;
1771}
1772
1773/**
1774 * Load pre-shared key
1775 *
1776 * @v tlskey Key schedule
1777 * @v psk Pre-shared key
1778 * @ret rc Return status code
1779 */
1780static int tlskey_hash_load ( struct tls_key_schedule *tlskey,
1781 const struct tls_preshared_key *psk ) {
1782 const void *secret;
1783 size_t secret_len;
1784 int rc;
1785
1786 /* For TLS versions 1.2 and earlier, the pre-shared key
1787 * material contains the master secret and so we just apply
1788 * this as the key derivation function secret.
1789 */
1790 secret = &psk->key.master_secret;
1791 secret_len = sizeof ( psk->key.master_secret );
1792 if ( ( rc = tlskey_apply ( tlskey, secret, secret_len ) ) != 0 )
1793 return rc;
1794
1795 return 0;
1796}
1797
1798/**
1799 * Generate pre-shared key binder value
1800 *
1801 * @v psk Pre-shared key
1802 * @v hash Partial transcript hash
1803 * @v binder Binder value to fill in
1804 * @v binder_len Length of binder value
1805 * @ret rc Return status code
1806 */
1807static int tlskey_hash_bind ( const struct tls_preshared_key *psk __unused,
1808 const void *hash __unused,
1809 void *binder __unused, size_t binder_len ) {
1810
1811 /* Binder values are not supported */
1812 if ( binder_len )
1813 return -ENOTSUP;
1814
1815 return 0;
1816}
1817
1818/** TLS key schedule based on P_Hash() */
1836
1837/*****************************************************************************
1838 *
1839 * TLS version 1.0/1.1 key schedule using PRF based on P_MD5()+P_SHA1()
1840 *
1841 *****************************************************************************
1842 */
1843
1844/**
1845 * Calculate secret size
1846 *
1847 * @v digest Digest algorithm
1848 * @ret secretsize Secret size, or zero if unsupported
1849 */
1850static size_t tlskey_md5_sha1_secretsize ( struct digest_algorithm *digest ) {
1851 struct md5_sha1_hmac_keys *hkeys;
1852 size_t secretsize;
1853
1854 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1855 if ( digest != &md5_sha1_algorithm )
1856 return 0;
1857
1858 /* A P_MD5()+P_SHA1() key is a split HMAC-MD5 and HMAC-SHA1 key */
1859 assert ( sizeof ( hkeys->md5 ) == hmac_keysize ( &md5_algorithm ) );
1860 assert ( sizeof ( hkeys->sha1 ) == hmac_keysize ( &sha1_algorithm ) );
1861 secretsize = sizeof ( *hkeys );
1862
1863 return secretsize;
1864}
1865
1866/**
1867 * Expand key material
1868 *
1869 * @v digest Digest algorithm
1870 * @v secret Secret
1871 * @v label Label string
1872 * @v seed Seed material
1873 * @v seed_len Length of seed material
1874 * @v out Output buffer
1875 * @v out_len Length of output buffer
1876 */
1877static void tlskey_md5_sha1_expand ( struct digest_algorithm *digest,
1878 const void *secret, const char *label,
1879 const void *seed, size_t seed_len,
1880 void *out, size_t out_len ) {
1881 const struct md5_sha1_hmac_keys *hkeys = secret;
1882 struct {
1883 uint8_t sha1[out_len];
1884 } tmp;
1885 uint8_t *xor;
1886 unsigned int i;
1887
1888 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1889 assert ( digest == &md5_sha1_algorithm );
1890
1891 /* Generate MD5 portion into output buffer */
1892 tlskey_hash_expand ( &md5_algorithm, hkeys->md5, label, seed,
1893 seed_len, out, out_len );
1894
1895 /* Generate SHA-1 portion into temporary buffer */
1896 tlskey_hash_expand ( &sha1_algorithm, hkeys->sha1, label, seed,
1897 seed_len, tmp.sha1, out_len );
1898
1899 /* XOR together into output buffer */
1900 xor = out;
1901 for ( i = 0 ; i < out_len ; i++ )
1902 xor[i] ^= tmp.sha1[i];
1903
1904 /* Clear temporary secrets */
1905 memset ( &tmp, 0, sizeof ( tmp ) );
1906}
1907
1908/**
1909 * Apply a new shared secret
1910 *
1911 * @v tlskey Key schedule
1912 * @v shared New shared secret
1913 * @v shared_len Length of new shared secret
1914 * @ret rc Return status code
1915 */
1916static int tlskey_md5_sha1_apply ( struct tls_key_schedule *tlskey,
1917 const void *shared, size_t shared_len ) {
1918 struct digest_algorithm *digest = tlskey->digest;
1919 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1920 size_t hctxsize = hmac_ctxsize ( digest );
1921 struct {
1922 uint8_t hctx[hctxsize];
1923 } tmp;
1924 const void *shared_md5;
1925 const void *shared_sha1;
1926 size_t shared_sublen;
1927
1928 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1929 assert ( digest == &md5_sha1_algorithm );
1930
1931 /* Split secret into two, with an overlap of up to one byte */
1932 shared_sublen = ( ( shared_len + 1 ) / 2 );
1933 shared_md5 = shared;
1934 shared_sha1 = ( shared + shared_len - shared_sublen );
1935
1936 /* Set HMAC-MD5 key */
1937 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &md5_algorithm ) );
1938 hmac_key ( &md5_algorithm, tmp.hctx, shared_md5, shared_sublen,
1939 hkeys->md5 );
1940
1941 /* Set HMAC-SHA1 key */
1942 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &sha1_algorithm ) );
1943 hmac_key ( &sha1_algorithm, tmp.hctx, shared_sha1, shared_sublen,
1944 hkeys->sha1 );
1945
1946 /* Clear temporary secrets */
1947 memset ( &tmp, 0, sizeof ( tmp ) );
1948
1949 return 0;
1950}
1951
1952/**
1953 * Save pre-shared key
1954 *
1955 * @v tlskey Key schedule
1956 * @v nonce Ticket nonce
1957 * @v nonce_len Length of ticket nonce
1958 * @v psk Pre-shared key
1959 * @ret rc Return status code
1960 */
1961static int tlskey_md5_sha1_save ( struct tls_key_schedule *tlskey,
1962 const void *nonce __unused,
1963 size_t nonce_len,
1964 struct tls_preshared_key *psk ) {
1965 struct digest_algorithm *digest = tlskey->digest;
1966 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1967
1968 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1969 assert ( digest == &md5_sha1_algorithm );
1970
1971 /* A ticket nonce is not supported */
1972 if ( nonce_len )
1973 return -ENOTSUP;
1974
1975 /* For TLS versions 1.1 and earlier, the pre-master secret may
1976 * be any length but the master secret is fixed at 48 bytes.
1977 * It will have been split to become 24 bytes in each of the
1978 * MD5 and SHA-1 HMAC keys.
1979 */
1980 assert ( sizeof ( psk->key.master_secret.md5 ) <=
1982 assert ( sizeof ( psk->key.master_secret.sha1 ) <=
1984 memcpy ( psk->key.master_secret.md5, hkeys->md5,
1985 sizeof ( psk->key.master_secret.md5 ) );
1986 memcpy ( psk->key.master_secret.sha1, hkeys->sha1,
1987 sizeof ( psk->key.master_secret.sha1 ) );
1988
1989 return 0;
1990}
1991
1992/** 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:84
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:421
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:431
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:1687
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:1877
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:1634
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:948
static int tlskey_hash_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1780
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:785
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:984
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:1566
static int tlskey_hash_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1513
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:828
static int tlskey_hkdf_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1083
static void tlskey_hash_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1472
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:1182
static void tlskey_hkdf_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1030
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:1603
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:1113
#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:1961
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:1266
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:1747
#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:1304
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:1807
const struct tls_key_schedule_operations tlskey_hash
TLS key schedule based on P_Hash().
Definition tlskey.c:1819
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:1331
static size_t tlskey_hkdf_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:931
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:1054
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:1225
const struct tls_key_schedule_operations tlskey_md5_sha1
TLS key schedule based on P_MD5()+P_SHA1().
Definition tlskey.c:1993
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:1489
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:1395
static size_t tlskey_hash_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1403
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:1149
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:1002
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:1420
static size_t tlskey_md5_sha1_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1850
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:1916
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:885
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:1369
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