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 /* Do nothing if key schedule is stopped */
428 if ( ! digestsize )
429 return;
430
431 /* Append to running transcript digest */
432 digest_update ( digest, transcript->ctx, data, len );
433
434 /* Update running transcript digest output */
435 memcpy ( tmp.ctx, transcript->ctx, ctxsize );
436 digest_final ( digest, tmp.ctx, transcript->running );
437
438 /* Process digested handshake record */
439 flags = tlskey_handshake ( tlskey, data, len );
440 transcript->flags |= flags;
441
442 /* Update the finishing digest value, if applicable */
443 if ( ! ( ( transcript->flags ^ flags ) & TLSKEY_TSF_FINISHED ) ) {
444 memcpy ( transcript->finishing, transcript->running,
445 digestsize );
446 }
447
448 /* Clear temporary secrets */
449 memset ( &tmp, 0, sizeof ( tmp ) );
450}
451
452/**
453 * Replace running transcript digest with a message hash of itself
454 *
455 * @v tlskey Key schedule
456 */
457void tlskey_message ( struct tls_key_schedule *tlskey ) {
458 struct tls_transcript *transcript = &tlskey->transcript;
459 struct digest_algorithm *digest = tlskey->digest;
460 size_t digestsize = digest->digestsize;
461 struct tls_message_hash msg;
462
463 /* Construct message hash header */
464 msg.type = TLS_MESSAGE_HASH;
465 msg.zero = 0;
466 msg.len = digestsize;
467
468 /* Replace running transcript digest */
469 digest_init ( digest, transcript->ctx );
470 digest_update ( digest, transcript->ctx, &msg, sizeof ( msg ) );
471 digest_update ( digest, transcript->ctx, transcript->running,
472 digestsize );
473 tlskey_digest ( tlskey, NULL, 0 );
474}
475
476/*****************************************************************************
477 *
478 * Key material
479 *
480 *****************************************************************************
481 */
482
483/**
484 * Expand key material
485 *
486 * @v tlskey Key schedule
487 * @v secret Secret
488 * @v label Label string
489 * @v seed Seed material
490 * @v seed_len Length of seed material
491 * @v out Output buffer
492 * @v out_len Length of output buffer
493 */
494static void tlskey_expand ( struct tls_key_schedule *tlskey,
495 const void *secret, const char *label,
496 const void *seed, size_t seed_len,
497 void *out, size_t out_len ) {
498 const struct tls_key_schedule_operations *op = tlskey->op;
499 struct digest_algorithm *digest = tlskey->digest;
500
501 /* Sanity check */
502 assert ( op != NULL );
503
504 /* Expand key material */
505 DBGC2 ( tlskey, "TLSKEY %p expanding seed \"%s\":\n", tlskey, label );
506 DBGC2_HDA ( tlskey, 0, seed, seed_len );
507 op->expand ( digest, secret, label, seed, seed_len, out, out_len );
508 DBGC2 ( tlskey, "TLSKEY %p expanded:\n", tlskey );
509 DBGC2_HDA ( tlskey, 0, out, out_len );
510}
511
512/**
513 * Reset key schedule
514 *
515 * @v tlskey Key schedule
516 *
517 * It is safe to reset a key schedule that has been stopped, or that
518 * has not yet been started.
519 */
520void tlskey_reset ( struct tls_key_schedule *tlskey ) {
521 const struct tls_key_schedule_operations *op = tlskey->op;
522
523 /* Do nothing if key schedule is stopped */
524 if ( ! op ) {
525 assert ( tlskey->secretsize == 0 );
526 assert ( tlskey->kdf.flags == 0 );
527 assert ( tlskey->traffic[TLS_CLIENT].phase == NULL );
528 assert ( tlskey->traffic[TLS_SERVER].phase == NULL );
529 return;
530 }
531
532 /* Clear secrets, flags, and traffic phases */
533 memset ( tlskey->secret, 0, tlskey->secretsize );
534 tlskey->kdf.flags = 0;
535 tlskey->traffic[TLS_CLIENT].phase = NULL;
536 tlskey->traffic[TLS_SERVER].phase = NULL;
537
538 /* Reset key schedule */
539 op->reset ( tlskey );
540}
541
542/**
543 * Apply a new shared secret
544 *
545 * @v tlskey Key schedule
546 * @v shared New shared secret
547 * @v shared_len Length of new shared secret
548 * @ret rc Return status code
549 */
550int tlskey_apply ( struct tls_key_schedule *tlskey, const void *shared,
551 size_t shared_len ) {
552 const struct tls_key_schedule_operations *op = tlskey->op;
553 int rc;
554
555 /* Sanity check */
556 if ( ! op )
557 return -ENOTTY;
558
559 /* All schedules define the master secret as immutable */
560 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
561 DBGC ( tlskey, "TLSKEY %p cannot apply a new shared secret "
562 "after generating master secret\n", tlskey );
563 return -EPROTO;
564 }
565
566 /* Apply new shared secret */
567 DBGC ( tlskey, "TLSKEY %p applying secret:\n", tlskey );
568 DBGC_HDA ( tlskey, 0, shared, shared_len );
569 if ( ( rc = op->apply ( tlskey, shared, shared_len ) ) != 0 )
570 return rc;
571
572 /* Mark key schedule as containing key material */
573 tlskey->kdf.flags |= TLSKEY_KDF_KEYED;
574
575 return 0;
576}
577
578/**
579 * Generate master secret
580 *
581 * @v tlskey Key schedule
582 * @v ems Extended master secret extension is enabled
583 * @ret rc Return status code
584 */
585int tlskey_master ( struct tls_key_schedule *tlskey, int ems ) {
586 const struct tls_key_schedule_operations *op = tlskey->op;
587 int rc;
588
589 /* Sanity check */
590 if ( ! op )
591 return -ENOTTY;
592
593 /* Any conceivable schedule requires key material */
594 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
595 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
596 "without key material\n", tlskey );
597 return -EPROTO;
598 }
599
600 /* All schedules define the master secret as immutable */
601 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
602 DBGC ( tlskey, "TLSKEY %p cannot regenerate master secret\n",
603 tlskey );
604 return -EPROTO;
605 }
606
607 /* Generate master secret */
608 DBGC ( tlskey, "TLSKEY %p generating %smaster secret\n",
609 tlskey, ( ems ? "extended " : "" ) );
610 if ( ( rc = op->master ( tlskey, ems ) ) != 0 )
611 return rc;
612
613 /* Mark key schedule as containing master secret */
614 tlskey->kdf.flags |= TLSKEY_KDF_MASTER;
615 if ( ems )
616 tlskey->kdf.flags |= TLSKEY_KDF_EMS;
617
618 return 0;
619}
620
621/**
622 * Generate verification data
623 *
624 * @v tlskey Key schedule
625 * @v end Verification endpoint
626 * @v verify Verification data to fill in
627 * @v verify_len Length of verification data
628 * @ret rc Return status code
629 */
630int tlskey_verify ( struct tls_key_schedule *tlskey,
631 const struct tls_endpoint *end,
632 void *verify, size_t verify_len ) {
633 const struct tls_key_schedule_operations *op = tlskey->op;
634 int rc;
635
636 /* Sanity check */
637 if ( ! op )
638 return -ENOTTY;
639
640 /* Verification data must be non-replayable */
641 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
642 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
643 "without a digested nonce\n", tlskey );
644 return -EPROTO;
645 }
646
647 /* Generate verification data */
648 DBGC2 ( tlskey, "TLSKEY %p generating %s verification data\n",
649 tlskey, end->name );
650 if ( ( rc = op->verify ( tlskey, end, verify, verify_len ) ) != 0 )
651 return rc;
652 DBGC ( tlskey, "TLSKEY %p %s verification data:\n",
653 tlskey, end->name );
654 DBGC_HDA ( tlskey, 0, verify, verify_len );
655
656 return 0;
657}
658
659/**
660 * Generate traffic secret
661 *
662 * @v tlskey Key schedule
663 * @v writer Writer endpoint
664 * @v phase Traffic phase
665 * @ret rc Return status code
666 */
667int tlskey_traffic ( struct tls_key_schedule *tlskey,
668 const struct tls_endpoint *writer,
669 const struct tls_phase *phase ) {
670 const struct tls_key_schedule_operations *op = tlskey->op;
671 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
672 unsigned int missing;
673 int rc;
674
675 /* Sanity check */
676 if ( ! op )
677 return -ENOTTY;
678
679 /* Check flags required for this traffic phase */
681 missing = ( ( tlskey->kdf.flags ^ phase->flags ) & phase->flags );
682 if ( missing ) {
683 DBGC ( tlskey, "TLSKEY %p cannot generate %s %s traffic "
684 "secrets (missing KDF flags %#04x)\n",
685 tlskey, writer->name, phase->name, missing );
686 return -EPROTO;
687 }
688
689 /* Generate traffic secret */
690 DBGC2 ( tlskey, "TLSKEY %p generating %s %s traffic secret\n",
691 tlskey, writer->name, phase->name );
692 if ( ( rc = op->traffic ( tlskey, writer, phase ) ) != 0 )
693 return rc;
694
695 /* Record phase */
696 traffic->phase = phase;
697
698 return 0;
699}
700
701/**
702 * Generate cipher key material
703 *
704 * @v tlskey Key schedule
705 * @v writer Writer endpoint
706 * @v key Cipher key to fill in
707 * @v key_len Length of cipher key
708 * @v iv Fixed portion of initialisation vector to fill in
709 * @v iv_len Length of fixed portion of initialisation vector
710 * @v mac MAC secret to fill in
711 * @v mac_len Length of MAC secret
712 * @ret rc Return status code
713 *
714 * For key schedules that include a ratchet mechanism, each call
715 * consumes the current generation of traffic secret and replaces it
716 * with the next generation. Repeated calls may therefore be used to
717 * obtain multiple generations of the cipher key material.
718 */
719int tlskey_cipher ( struct tls_key_schedule *tlskey,
720 const struct tls_endpoint *writer,
721 void *key, size_t key_len, void *iv, size_t iv_len,
722 void *mac, size_t mac_len ) {
723 const struct tls_key_schedule_operations *op = tlskey->op;
724 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
725 int rc;
726
727 /* Sanity check */
728 if ( ! op )
729 return -ENOTTY;
730
731 /* Ensure that traffic secret has actually been generated */
732 if ( ! traffic->phase ) {
733 DBGC ( tlskey, "TLSKEY %p cannot generate cipher key "
734 "material without traffic secrets\n", tlskey );
735 return -EPROTO;
736 }
737
738 /* Generate cipher key material */
739 DBGC2 ( tlskey, "TLSKEY %p generating %s %s cipher key material\n",
740 tlskey, writer->name, traffic->phase->name );
741 if ( ( rc = op->cipher ( tlskey, writer, key, key_len, iv, iv_len,
742 mac, mac_len ) ) != 0 ) {
743 return rc;
744 }
745 if ( key_len ) {
746 DBGC ( tlskey, "TLSKEY %p %s key:\n", tlskey, writer->name );
747 DBGC_HDA ( tlskey, 0, key, key_len );
748 }
749 if ( iv_len ) {
750 DBGC ( tlskey, "TLSKEY %p %s IV:\n", tlskey, writer->name );
751 DBGC_HDA ( tlskey, 0, iv, iv_len );
752 }
753 if ( mac_len ) {
754 DBGC ( tlskey, "TLSKEY %p %s MAC:\n", tlskey, writer->name );
755 DBGC_HDA ( tlskey, 0, mac, mac_len );
756 }
757
758 return 0;
759}
760
761/**
762 * Generate signable digest value
763 *
764 * @v tlskey Key schedule
765 * @v end Endpoint
766 * @v digest Signature digest algorithm
767 * @v data Additional data
768 * @v len Length of additional data
769 * @v tbs Signable digest value to fill in
770 * @ret rc Return status code
771 */
772int tlskey_tbshash ( struct tls_key_schedule *tlskey,
773 const struct tls_endpoint *end,
774 struct digest_algorithm *digest,
775 const void *data, size_t len, void *tbs ) {
776 const struct tls_key_schedule_operations *op = tlskey->op;
777 int rc;
778
779 /* Sanity check */
780 if ( ! op )
781 return -ENOTTY;
782
783 /* Signable digest values must be non-replayable */
784 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
785 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
786 "without a digested nonce\n", tlskey );
787 return -EPROTO;
788 }
789
790 /* Signable digest values must be constructed over the
791 * parameters used to establish a shared secret, and so a
792 * shared secret must exist.
793 */
794 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
795 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
796 "without a shared secret\n", tlskey );
797 return -EPROTO;
798 }
799
800 /* Generate digest value */
801 DBGC2 ( tlskey, "TLSKEY %p generating signable %s %s digest\n",
802 tlskey, end->name, digest->name );
803 if ( ( rc = op->tbshash ( tlskey, end, digest, data, len,
804 tbs ) ) != 0 ) {
805 return rc;
806 }
807 DBGC ( tlskey, "TLSKEY %p generated signable %s %s digest:\n",
808 tlskey, end->name, digest->name );
809 DBGC_HDA ( tlskey, 0, tbs, digest->digestsize );
810
811 return 0;
812}
813
814/**
815 * Save pre-shared key
816 *
817 * @v tlskey Key schedule
818 * @v nonce Ticket nonce
819 * @v nonce_len Length of ticket nonce
820 * @v psk Pre-shared key to fill in
821 * @ret rc Return status code
822 */
823int tlskey_save ( struct tls_key_schedule *tlskey, const void *nonce,
824 size_t nonce_len, struct tls_preshared_key *psk ) {
825 const struct tls_key_schedule_operations *op = tlskey->op;
826 struct digest_algorithm *digest = tlskey->digest;
827 int rc;
828
829 /* Clear any existing pre-shared key */
830 memset ( psk, 0, sizeof ( *psk ) );
831
832 /* Sanity check */
833 if ( ! op )
834 return -ENOTTY;
835
836 /* Session resumption requires a master secret */
837 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
838 DBGC ( tlskey, "TLSKEY %p cannot save key without a master "
839 "secret\n", tlskey );
840 return -EPROTO;
841 }
842
843 /* Save key material */
844 DBGC2 ( tlskey, "TLSKEY %p saving key\n", tlskey );
845 if ( ( rc = op->save ( tlskey, nonce, nonce_len, psk ) ) != 0 )
846 return rc;
847 DBGC ( tlskey, "TLSKEY %p saved key:\n", tlskey );
848 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
849
850 /* Record key properties */
851 psk->op = op;
852 psk->digest = digest;
853 psk->flags = tlskey->kdf.flags;
854
855 return 0;
856}
857
858/**
859 * Load pre-shared key
860 *
861 * @v tlskey Key schedule
862 * @v ems Extended master secret extension is enabled
863 * @v psk Pre-shared key
864 * @ret rc Return status code
865 */
866int tlskey_load ( struct tls_key_schedule *tlskey, int ems,
867 const struct tls_preshared_key *psk ) {
868 const struct tls_key_schedule_operations *op = tlskey->op;
869 struct digest_algorithm *digest = tlskey->digest;
870 int rc;
871
872 /* Reset key schedule */
873 tlskey_reset ( tlskey );
874
875 /* Sanity check */
876 if ( ! op )
877 return -ENOTTY;
878
879 /* Session resumption requires a master secret */
880 if ( ! ( psk->flags & TLSKEY_KDF_MASTER ) ) {
881 DBGC ( tlskey, "TLSKEY %p cannot load from a non-master "
882 "secret\n", tlskey );
883 return -EPROTO;
884 }
885
886 /* Pre-shared key must match extended/non-extended usage */
887 if ( ( !! ems ) != ( !! ( psk->flags & TLSKEY_KDF_EMS ) ) ) {
888 DBGC ( tlskey, "TLSKEY %p cannot load from %sextended master "
889 "secret\n", tlskey, ( ems ? "non-" : "" ) );
890 return -EPERM;
891 }
892
893 /* Pre-shared key must match schedule and digest */
894 if ( ( op != psk->op ) || ( digest != psk->digest ) ) {
895 DBGC ( tlskey, "TLSKEY %p cannot load from %s with %s\n",
896 tlskey, ( psk->op ? psk->op->name : "(unknown)" ),
897 ( psk->digest ? psk->digest->name : "(unknown)" ) );
898 return -EPERM;
899 }
900
901 /* Load key material */
902 DBGC ( tlskey, "TLSKEY %p loading key:\n", tlskey );
903 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
904 if ( ( rc = op->load ( tlskey, psk ) ) != 0 )
905 return rc;
906
907 /* Set flags */
908 tlskey->kdf.flags = ( psk->flags & op->mask );
909
910 return 0;
911}
912
913/**
914 * Generate pre-shared key binder value
915 *
916 * @v psk Pre-shared key
917 * @v prefix ClientHello prefix
918 * @v prefix_len Length of ClientHello prefix
919 * @v binder Binder value to fill in
920 * @v binder_len Length of binder value
921 * @ret rc Return status code
922 */
923int tlskey_bind ( const struct tls_preshared_key *psk, const void *prefix,
924 size_t prefix_len, void *binder, size_t binder_len ) {
925 const struct tls_key_schedule_operations *op = psk->op;
926 struct digest_algorithm *digest = psk->digest;
927 int rc;
928
929 /* Generate prefix digest and binder value */
930 if ( op && digest ) {
931 size_t digestsize = digest->digestsize;
932 size_t ctxsize = digest->ctxsize;
935
936 /* Calculate prefix digest */
937 digest_init ( digest, ctx );
938 digest_update ( digest, ctx, prefix, prefix_len );
939 digest_final ( digest, ctx, out );
940
941 /* Generate binder value */
942 DBGC2 ( psk, "TLSKEY %p generating key binder:\n", psk );
943 DBGC2_HDA ( psk, 0, &psk->key, sizeof ( psk->key ) );
944 if ( ( rc = op->bind ( psk, out, binder, binder_len ) ) != 0 )
945 return rc;
946 DBGC ( psk, "TLSKEY %p generated key binder:\n", psk );
947 DBGC_HDA ( psk, 0, binder, binder_len );
948
949 return 0;
950 }
951
952 DBGC ( psk, "TLSKEY %p cannot bind empty pre-shared key\n", psk );
953 return -ENOENT;
954}
955
956/*****************************************************************************
957 *
958 * TLS version 1.3 key schedule using HKDF
959 *
960 *****************************************************************************
961 */
962
963/**
964 * Calculate secret size
965 *
966 * @v digest Digest algorithm
967 * @ret secretsize Secret size, or zero if unsupported
968 */
969static size_t tlskey_hkdf_secretsize ( struct digest_algorithm *digest ) {
970 size_t digestsize = digest->digestsize;
971
972 return ( digestsize * 3 /* KDF, client, and server secrets */ );
973}
974
975/**
976 * Expand key material
977 *
978 * @v digest Digest algorithm
979 * @v secret Secret
980 * @v label Label string
981 * @v seed Seed material
982 * @v seed_len Length of seed material
983 * @v out Output buffer
984 * @v out_len Length of output buffer
985 */
986static void tlskey_hkdf_expand ( struct digest_algorithm *digest,
987 const void *secret, const char *label,
988 const void *seed, size_t seed_len,
989 void *out, size_t out_len ) {
990 static const char prefix[6] = "tls13 ";
991 const void *context = seed;
992 size_t context_len = seed_len;
993 size_t prefix_len = sizeof ( prefix );
994 size_t label_len = strlen ( label );
995 struct {
997 uint8_t label_len;
998 char prefix[prefix_len];
999 char label[label_len];
1000 uint8_t context_len;
1001 uint8_t context[context_len];
1002 } __attribute__ (( packed )) info;
1003
1004 /* Construct additional information */
1005 info.len = htons ( out_len );
1006 info.label_len = ( prefix_len + label_len );
1007 memcpy ( info.prefix, prefix, prefix_len );
1008 memcpy ( info.label, label, label_len );
1009 info.context_len = context_len;
1010 memcpy ( info.context, context, context_len );
1011
1012 /* Generate output using HKDF */
1013 hkdf_expand ( digest, secret, &info, sizeof ( info ), out, out_len );
1014}
1015
1016/**
1017 * Calculate empty digest value
1018 *
1019 * @v digest Digest algorithm
1020 * @v empty Empty digest to fill in
1021 */
1022static void tlskey_hkdf_empty ( struct digest_algorithm *digest,
1023 void *empty ) {
1024 size_t ctxsize = digest->ctxsize;
1025 uint8_t ctx[ctxsize];
1026
1027 /* Calculate empty digest */
1028 digest_init ( digest, ctx );
1029 digest_final ( digest, ctx, empty );
1030}
1031
1032/**
1033 * Calculate a finished MAC
1034 *
1035 * @v digest Digest algorithm
1036 * @v secret Secret
1037 * @v hash Message hash
1038 * @v out Output buffer
1039 */
1040static void tlskey_hkdf_finished ( struct digest_algorithm *digest,
1041 const void *secret, const void *hash,
1042 void *out ) {
1043 size_t digestsize = digest->digestsize;
1044 size_t hctxsize = hmac_ctxsize ( digest );
1045 struct {
1046 uint8_t hctx[hctxsize];
1048 } tmp;
1049
1050 /* Generate HMAC key */
1051 tlskey_hkdf_expand ( digest, secret, "finished", NULL, 0,
1052 tmp.key, sizeof ( tmp.key ) );
1053
1054 /* Generate HMAC */
1055 hmac_init ( digest, tmp.hctx, tmp.key, sizeof ( tmp.key ) );
1056 hmac_update ( digest, tmp.hctx, hash, digestsize );
1057 hmac_final ( digest, tmp.hctx, out );
1058
1059 /* Clear temporary secrets */
1060 memset ( &tmp, 0, sizeof ( tmp ) );
1061}
1062
1063/**
1064 * Reset key schedule
1065 *
1066 * @v key Key schedule
1067 */
1068static void tlskey_hkdf_reset ( struct tls_key_schedule *tlskey ) {
1069 struct digest_algorithm *digest = tlskey->digest;
1070 size_t digestsize = digest->digestsize;
1071 void *secret = tlskey->secret;
1072
1073 /* Allocate and initialise secrets */
1074 tlskey->kdf.secret = secret; secret += digestsize;
1075 tlskey->traffic[TLS_CLIENT].secret = secret; secret += digestsize;
1076 tlskey->traffic[TLS_SERVER].secret = secret; secret += digestsize;
1077 assert ( secret == ( tlskey->secret + tlskey->secretsize ) );
1078
1079 /* Initialise empty early secret */
1080 hkdf_extract ( digest, NULL, 0, tlskey->kdf.secret, digestsize,
1081 tlskey->kdf.secret );
1082}
1083
1084/**
1085 * Apply a new shared secret
1086 *
1087 * @v tlskey Key schedule
1088 * @v shared New shared secret
1089 * @v shared_len Length of new shared secret
1090 * @ret rc Return status code
1091 */
1092static int tlskey_hkdf_apply ( struct tls_key_schedule *tlskey,
1093 const void *shared, size_t shared_len ) {
1094 struct digest_algorithm *digest = tlskey->digest;
1095 size_t digestsize = digest->digestsize;
1096 uint8_t empty[digestsize];
1097
1098 /* Generate derived secret */
1099 tlskey_hkdf_empty ( digest, empty );
1100 tlskey_expand ( tlskey, tlskey->kdf.secret, "derived", empty,
1101 digestsize, tlskey->kdf.secret, digestsize );
1102 DBGC2 ( tlskey, "TLSKEY %p derived:\n", tlskey );
1103 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1104
1105 /* Extract new pseudorandom key */
1106 hkdf_extract ( digest, tlskey->kdf.secret, digestsize, shared,
1107 shared_len, tlskey->kdf.secret );
1108 DBGC2 ( tlskey, "TLSKEY %p extracted PRK:\n", tlskey );
1109 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1110
1111 return 0;
1112}
1113
1114/**
1115 * Generate master secret
1116 *
1117 * @v tlskey Key schedule
1118 * @v ems Extended master secret extension is enabled
1119 * @ret rc Return status code
1120 */
1121static int tlskey_hkdf_master ( struct tls_key_schedule *tlskey, int ems ) {
1122 struct digest_algorithm *digest = tlskey->digest;
1123 size_t digestsize = digest->digestsize;
1124 uint8_t zero[digestsize];
1125 int rc;
1126
1127 /* Extended master secret must always be used */
1128 if ( ! ems ) {
1129 DBGC ( tlskey, "TLSKEY %p requires an extended master "
1130 "secret\n", tlskey );
1131 return -EPROTO;
1132 }
1133
1134 /* Generate master secret */
1135 memset ( zero, 0, sizeof ( zero ) );
1136 if ( ( rc = tlskey_apply ( tlskey, zero, sizeof ( zero ) ) ) != 0 )
1137 return rc;
1138
1139 return 0;
1140}
1141
1142/**
1143 * Generate verification data
1144 *
1145 * @v tlskey Key schedule
1146 * @v end Verification endpoint
1147 * @v verify Verification data to fill in
1148 * @v verify_len Length of verification data
1149 * @ret rc Return status code
1150 */
1151static int tlskey_hkdf_verify ( struct tls_key_schedule *tlskey,
1152 const struct tls_endpoint *end,
1153 void *verify, size_t verify_len ) {
1154 struct tls_traffic_secret *traffic = &tlskey->traffic[end->index];
1155 struct digest_algorithm *digest = tlskey->digest;
1156 size_t digestsize = digest->digestsize;
1157
1158 /* Verification data must be a complete digest output */
1159 if ( verify_len != digestsize )
1160 return -EINVAL;
1161
1162 /* Verification data is derived from handshake secrets */
1163 if ( traffic->phase != &tls_handshake ) {
1164 DBGC ( tlskey, "TLSKEY %p cannot generate %s verification "
1165 "data without %s handshake traffic secrets\n",
1166 tlskey, end->name, end->name );
1167 return -EPROTO;
1168 }
1169
1170 /* Generate verification data */
1171 tlskey_hkdf_finished ( digest, traffic->secret,
1172 tlskey->transcript.running, verify );
1173 DBGC ( tlskey, "TLSKEY %p %s verification:\n", tlskey, end->name );
1174 DBGC_HDA ( tlskey, 0, verify, verify_len );
1175
1176 return 0;
1177}
1178
1179/**
1180 * Generate traffic secret
1181 *
1182 * @v tlskey Key schedule
1183 * @v writer Writer endpoint
1184 * @v phase Traffic phase
1185 * @ret rc Return status code
1186 */
1187static int tlskey_hkdf_traffic ( struct tls_key_schedule *tlskey,
1188 const struct tls_endpoint *writer,
1189 const struct tls_phase *phase ) {
1190 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1191 struct digest_algorithm *digest = tlskey->digest;
1192 size_t digestsize = digest->digestsize;
1193 char label[ 13 /* "[c|s] [e|hs|ap] traffic" + NUL */ ];
1194
1195 /* Generate label */
1196 snprintf ( label, sizeof ( label ), "%c %s traffic",
1197 writer->name[0], phase->label );
1198
1199 /* Generate traffic secret */
1200 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1202 traffic->secret, digestsize );
1203
1204 return 0;
1205}
1206
1207/**
1208 * Generate cipher key material
1209 *
1210 * @v tlskey Key schedule
1211 * @v writer Writer endpoint
1212 * @v key Cipher key to fill in
1213 * @v key_len Length of cipher key
1214 * @v iv Fixed portion of initialisation vector to fill in
1215 * @v iv_len Length of fixed portion of initialisation vector
1216 * @v mac MAC secret to fill in
1217 * @v mac_len Length of MAC secret
1218 * @ret rc Return status code
1219 */
1220static int tlskey_hkdf_cipher ( struct tls_key_schedule *tlskey,
1221 const struct tls_endpoint *writer,
1222 void *key, size_t key_len, void *iv,
1223 size_t iv_len, void *mac __unused,
1224 size_t mac_len ) {
1225 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1226 struct digest_algorithm *digest = tlskey->digest;
1227 size_t digestsize = digest->digestsize;
1228 void *secret = traffic->secret;
1229
1230 /* The key schedule does not define a way to generate MAC secrets */
1231 if ( mac_len ) {
1232 DBGC ( tlskey, "TLSKEY %p does not support MAC secrets\n",
1233 tlskey );
1234 return -ENOTSUP;
1235 }
1236
1237 /* Generate cipher key */
1238 tlskey_expand ( tlskey, secret, "key", NULL, 0, key, key_len );
1239
1240 /* Generate initialisation vector */
1241 tlskey_expand ( tlskey, secret, "iv", NULL, 0, iv, iv_len );
1242
1243 /* Update traffic secret, if applicable */
1244 if ( traffic->phase == &tls_application ) {
1245 tlskey_expand ( tlskey, secret, "traffic upd", NULL, 0,
1246 secret, digestsize );
1247 }
1248
1249 return 0;
1250}
1251
1252/**
1253 * Generate signable digest value
1254 *
1255 * @v tlskey Key schedule
1256 * @v end Endpoint
1257 * @v digest Signature digest algorithm
1258 * @v data Additional data
1259 * @v len Length of additional data
1260 * @v tbs Signable digest value to fill in
1261 * @ret rc Return status code
1262 */
1263static int tlskey_hkdf_tbshash ( struct tls_key_schedule *tlskey,
1264 const struct tls_endpoint *end,
1265 struct digest_algorithm *digest,
1266 const void *data __unused, size_t len,
1267 void *tbs ) {
1268 size_t ctxsize = digest->ctxsize;
1270 char buf[64];
1271 int label_len;
1272
1273 /* There is no way to incorporate additional data */
1274 if ( len ) {
1275 DBGC ( tlskey, "TLSKEY %p cannot generate digest with "
1276 "additional data\n", tlskey );
1277 return -ENOTSUP;
1278 }
1279
1280 /* Generate digest value (all input is public) */
1281 digest_init ( digest, ctx );
1282 memset ( buf, 0x20, sizeof ( buf ) );
1283 digest_update ( digest, ctx, buf, sizeof ( buf ) );
1284 label_len = snprintf ( buf, sizeof ( buf ),
1285 "TLS 1.3, %s CertificateVerify", end->name );
1286 assert ( label_len == 33 /* for both "client" and "server" */ );
1287 digest_update ( digest, ctx, buf, ( label_len + 1 /* NUL */ ) );
1288 digest_update ( digest, ctx, tlskey->transcript.running,
1289 tlskey->digest->digestsize );
1290 digest_final ( digest, ctx, tbs );
1291
1292 return 0;
1293}
1294
1295/**
1296 * Save pre-shared key
1297 *
1298 * @v tlskey Key schedule
1299 * @v nonce Ticket nonce
1300 * @v nonce_len Length of ticket nonce
1301 * @v psk Pre-shared key to fill in
1302 * @ret rc Return status code
1303 */
1304static int tlskey_hkdf_save ( struct tls_key_schedule *tlskey,
1305 const void *nonce, size_t nonce_len,
1306 struct tls_preshared_key *psk ) {
1307 struct digest_algorithm *digest = tlskey->digest;
1308 size_t digestsize = digest->digestsize;
1309 struct {
1310 uint8_t master[digestsize];
1311 } tmp;
1312
1313 /* The pre-shared key currently uses a fixed-size buffer */
1314 if ( digestsize > sizeof ( psk->key.resumption ) ) {
1315 DBGC ( tlskey, "TLSKEY %p cannot save %s pre-shared key\n",
1316 tlskey, digest->name );
1317 return -ENOTSUP;
1318 }
1319
1320 /* Generate resumption master secret */
1321 tlskey_expand ( tlskey, tlskey->kdf.secret, "res master",
1323 tmp.master, sizeof ( tmp.master ) );
1324
1325 /* Generate resumption secret */
1326 tlskey_expand ( tlskey, tmp.master, "resumption", nonce, nonce_len,
1327 psk->key.resumption, digestsize );
1328
1329 /* Clear temporary secrets */
1330 memset ( &tmp, 0, sizeof ( tmp ) );
1331
1332 return 0;
1333}
1334
1335/**
1336 * Load pre-shared key
1337 *
1338 * @v tlskey Key schedule
1339 * @v psk Pre-shared key
1340 * @ret rc Return status code
1341 */
1342static int tlskey_hkdf_load ( struct tls_key_schedule *tlskey,
1343 const struct tls_preshared_key *psk ) {
1344 struct digest_algorithm *digest = tlskey->digest;
1345 size_t digestsize = digest->digestsize;
1346
1347 /* Sanity checks */
1348 assert ( digest == psk->digest );
1349 assert ( digestsize <= sizeof ( psk->key.resumption ) );
1350
1351 /* Extract early secret */
1352 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize,
1353 tlskey->kdf.secret );
1354 DBGC2 ( tlskey, "TLSKEY %p early secret:\n", tlskey );
1355 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1356
1357 return 0;
1358}
1359
1360/**
1361 * Generate pre-shared key binder value
1362 *
1363 * @v psk Pre-shared key
1364 * @v hash Partial transcript hash
1365 * @v binder Binder value to fill in
1366 * @v binder_len Length of binder value
1367 * @ret rc Return status code
1368 */
1369static int tlskey_hkdf_bind ( const struct tls_preshared_key *psk,
1370 const void *hash, void *binder,
1371 size_t binder_len ) {
1372 struct digest_algorithm *digest = psk->digest;
1373 size_t digestsize = digest->digestsize;
1374 uint8_t empty[digestsize];
1375 struct {
1377 } tmp;
1378
1379 /* Binder value must be a complete digest output */
1380 if ( binder_len != digestsize )
1381 return -EINVAL;
1382
1383 /* Extract temporary copy of early secret */
1384 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize, tmp.key );
1385 DBGC2 ( psk, "TLSKEY %p temporary early secret:\n", psk );
1386 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1387
1388 /* Generate resumption binder secret */
1389 tlskey_hkdf_empty ( digest, empty );
1390 tlskey_hkdf_expand ( digest, tmp.key, "res binder", empty, digestsize,
1391 tmp.key, digestsize );
1392 DBGC2 ( psk, "TLSKEY %p resumption binder secret:\n", psk );
1393 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1394
1395 /* Generate binder */
1396 tlskey_hkdf_finished ( digest, tmp.key, hash, binder );
1397 DBGC2 ( psk, "TLSKEY %p binder:\n", psk );
1398 DBGC2_HDA ( psk, 0, binder, binder_len );
1399
1400 /* Clear temporary secrets */
1401 memset ( &tmp, 0, sizeof ( tmp ) );
1402
1403 return 0;
1404}
1405
1406/** TLS key schedule based on HKDF */
1408 .name = "HKDF",
1409 .accumulates = 1,
1410 .mask = TLSKEY_KDF_KEYED,
1411 .secretsize = tlskey_hkdf_secretsize,
1412 .expand = tlskey_hkdf_expand,
1413 .reset = tlskey_hkdf_reset,
1414 .apply = tlskey_hkdf_apply,
1415 .master = tlskey_hkdf_master,
1416 .verify = tlskey_hkdf_verify,
1417 .traffic = tlskey_hkdf_traffic,
1418 .cipher = tlskey_hkdf_cipher,
1419 .tbshash = tlskey_hkdf_tbshash,
1420 .save = tlskey_hkdf_save,
1421 .load = tlskey_hkdf_load,
1422 .bind = tlskey_hkdf_bind,
1423};
1424
1425/*****************************************************************************
1426 *
1427 * TLS version 1.2 key schedule using PRF based on P_Hash()
1428 *
1429 *****************************************************************************
1430 */
1431
1432/** Minimum length for verification data */
1433#define TLSKEY_HASH_VERIFY_MIN 12
1434
1435/**
1436 * Calculate secret size
1437 *
1438 * @v digest Digest algorithm
1439 * @ret secretsize Secret size, or zero if unsupported
1440 */
1441static size_t tlskey_hash_secretsize ( struct digest_algorithm *digest ) {
1442
1443 /* A P_Hash() key is an HMAC key */
1444 return hmac_keysize ( digest );
1445}
1446
1447/**
1448 * Expand key material
1449 *
1450 * @v digest Digest algorithm
1451 * @v secret Secret
1452 * @v label Label string
1453 * @v seed Seed material
1454 * @v seed_len Length of seed material
1455 * @v out Output buffer
1456 * @v out_len Length of output buffer
1457 */
1458static void tlskey_hash_expand ( struct digest_algorithm *digest,
1459 const void *secret, const char *label,
1460 const void *seed, size_t seed_len,
1461 void *out, size_t out_len ) {
1462 size_t digestsize = digest->digestsize;
1463 size_t hctxsize = hmac_ctxsize ( digest );
1464 size_t frag_len = digestsize;
1465 size_t label_len = strlen ( label );
1466 unsigned int index = 0;
1467 struct {
1468 uint8_t ctx[2][hctxsize];
1470 uint8_t frag[digestsize];
1471 } tmp;
1472
1473 /* Generate as much output as required */
1474 while ( out_len ) {
1475
1476 /* Generate A(n) and output fragment */
1477 hmac_init_key ( digest, tmp.ctx[0], secret );
1478 if ( index ) {
1479 hmac_update ( digest, tmp.ctx[0], tmp.a,
1480 sizeof ( tmp.a ) );
1481 memcpy ( tmp.ctx[1], tmp.ctx[0],
1482 sizeof ( tmp.ctx[1] ) );
1483 }
1484 hmac_update ( digest, tmp.ctx[0], label, label_len );
1485 hmac_update ( digest, tmp.ctx[0], seed, seed_len );
1486 hmac_final ( digest, tmp.ctx[ ( index != 0 ) ], tmp.a );
1487 if ( index++ == 0 )
1488 continue;
1489 hmac_final ( digest, tmp.ctx[0], tmp.frag );
1490
1491 /* Copy output */
1492 if ( frag_len > out_len )
1493 frag_len = out_len;
1494 memcpy ( out, tmp.frag, frag_len );
1495
1496 /* Move to next fragment */
1497 out += frag_len;
1498 out_len -= frag_len;
1499 }
1500
1501 /* Clear temporary secrets */
1502 memset ( &tmp, 0, sizeof ( tmp ) );
1503}
1504
1505/**
1506 * Reset key schedule
1507 *
1508 * @v key Key schedule
1509 */
1510static void tlskey_hash_reset ( struct tls_key_schedule *tlskey ) {
1511 void *secret = tlskey->secret;
1512
1513 /* Allocate and initialise secrets */
1514 tlskey->kdf.secret = secret;
1515 tlskey->traffic[TLS_CLIENT].secret = secret;
1516 tlskey->traffic[TLS_SERVER].secret = secret;
1517}
1518
1519/**
1520 * Apply a new shared secret
1521 *
1522 * @v tlskey Key schedule
1523 * @v shared New shared secret
1524 * @v shared_len Length of new shared secret
1525 * @ret rc Return status code
1526 */
1527static int tlskey_hash_apply ( struct tls_key_schedule *tlskey,
1528 const void *shared, size_t shared_len ) {
1529 struct digest_algorithm *digest = tlskey->digest;
1530 size_t hctxsize = hmac_ctxsize ( digest );
1531 struct {
1532 uint8_t hctx[hctxsize];
1533 } tmp;
1534
1535 /* Set HMAC key */
1536 hmac_key ( digest, tmp.hctx, shared, shared_len, tlskey->kdf.secret );
1537
1538 /* Clear temporary secrets */
1539 memset ( &tmp, 0, sizeof ( tmp ) );
1540
1541 return 0;
1542}
1543
1544/**
1545 * Generate master secret
1546 *
1547 * @v tlskey Key schedule
1548 * @v ems Extended master secret extension is enabled
1549 * @ret rc Return status code
1550 */
1551static int tlskey_hash_master ( struct tls_key_schedule *tlskey, int ems ) {
1552 struct digest_algorithm *digest = tlskey->digest;
1553 size_t digestsize = digest->digestsize;
1554 const char *label;
1555 const void *seed;
1556 size_t seed_len;
1557 struct {
1558 uint8_t master[48];
1559 } tmp;
1560 int rc;
1561
1562 /* Master secret is derived from the client and server random
1563 * values (or the full transcript digest).
1564 */
1565 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
1566 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
1567 "without a digested nonce\n", tlskey );
1568 return -EPROTO;
1569 }
1570
1571 /* Generate master secret */
1572 if ( ems ) {
1573 label = "extended master secret";
1574 seed = tlskey->transcript.running;
1575 seed_len = digestsize;
1576 } else {
1577 label = "master secret";
1578 seed = &tlskey->random;
1579 seed_len = sizeof ( tlskey->random );
1580 }
1581 tlskey_expand ( tlskey, tlskey->kdf.secret, label, seed, seed_len,
1582 tmp.master, sizeof ( tmp.master ) );
1583
1584 /* Apply master secret */
1585 if ( ( rc = tlskey_apply ( tlskey, tmp.master,
1586 sizeof ( tmp.master ) ) ) != 0 ) {
1587 goto err_apply;
1588 }
1589
1590 err_apply:
1591 memset ( &tmp, 0, sizeof ( tmp ) );
1592 return rc;
1593}
1594
1595/**
1596 * Generate verification data
1597 *
1598 * @v tlskey Key schedule
1599 * @v end Verification endpoint
1600 * @v verify Verification data to fill in
1601 * @v verify_len Length of verification data
1602 * @ret rc Return status code
1603 */
1604static int tlskey_hash_verify ( struct tls_key_schedule *tlskey,
1605 const struct tls_endpoint *end,
1606 void *verify, size_t verify_len ) {
1607 struct digest_algorithm *digest = tlskey->digest;
1608 size_t digestsize = digest->digestsize;
1609 char label[ 16 /* "[client|server] finished" + NUL */ ];
1610
1611 /* Verification data must be at least 12 bytes for all digests */
1612 if ( verify_len < TLSKEY_HASH_VERIFY_MIN )
1613 return -EINVAL;
1614
1615 /* Verification data is derived from the master secret */
1616 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
1617 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
1618 "without a master secret\n", tlskey );
1619 return -EPROTO;
1620 }
1621
1622 /* Construct label */
1623 snprintf ( label, sizeof ( label ), "%s finished", end->name );
1624
1625 /* Generate verification data */
1626 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1627 tlskey->transcript.running, digestsize,
1628 verify, verify_len );
1629
1630 return 0;
1631}
1632
1633/**
1634 * Generate traffic secret
1635 *
1636 * @v tlskey Key schedule
1637 * @v writer Writer endpoint
1638 * @v phase Traffic phase
1639 * @ret rc Return status code
1640 */
1641static int tlskey_hash_traffic ( struct tls_key_schedule *tlskey,
1642 const struct tls_endpoint *writer,
1643 const struct tls_phase *phase ) {
1644 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1645
1646 /* Only application phase keys are supported */
1647 if ( phase != &tls_application ) {
1648 DBGC ( tlskey, "TLSKEY %p does not support %s traffic keys\n",
1649 tlskey, phase->name );
1650 return -ENOTSUP;
1651 }
1652
1653 /* There are no separate traffic secrets */
1654 assert ( traffic->secret == tlskey->kdf.secret );
1655
1656 return 0;
1657}
1658
1659/**
1660 * Generate cipher key material
1661 *
1662 * @v tlskey Key schedule
1663 * @v writer Writer endpoint
1664 * @v key Cipher key to fill in
1665 * @v key_len Length of cipher key
1666 * @v iv Fixed portion of initialisation vector to fill in
1667 * @v iv_len Length of fixed portion of initialisation vector
1668 * @v mac MAC secret to fill in
1669 * @v mac_len Length of MAC secret
1670 * @ret rc Return status code
1671 */
1672static int tlskey_hash_cipher ( struct tls_key_schedule *tlskey,
1673 const struct tls_endpoint *writer,
1674 void *key, size_t key_len, void *iv,
1675 size_t iv_len, void *mac, size_t mac_len ) {
1676 size_t total = ( 2 * ( mac_len + key_len + iv_len ) );
1677 struct {
1678 uint8_t key[total];
1679 } tmp;
1680 struct {
1681 struct tls_random server;
1682 struct tls_random client;
1683 } __attribute__ (( packed )) seed;
1684 const void *src;
1685 size_t mask;
1686
1687 /* Construct seed (with swapped client/server random bytes) */
1688 memcpy ( &seed.server, &tlskey->random[TLS_SERVER],
1689 sizeof ( seed.server ) );
1690 memcpy ( &seed.client, &tlskey->random[TLS_CLIENT],
1691 sizeof ( seed.client ) );
1692
1693 /* Generate key material */
1694 tlskey_expand ( tlskey, tlskey->kdf.secret, "key expansion", &seed,
1695 sizeof ( seed ), tmp.key, sizeof ( tmp.key ) );
1696
1697 /* Partition key material */
1698 src = tmp.key;
1699 mask = ( ( writer->index == TLS_CLIENT ) ? 0 : -1UL );
1700 memcpy ( mac, ( src + ( mac_len & mask ) ), mac_len );
1701 src += ( 2 * mac_len );
1702 memcpy ( key, ( src + ( key_len & mask ) ), key_len );
1703 src += ( 2 * key_len );
1704 memcpy ( iv, ( src + ( iv_len & mask ) ), iv_len );
1705 src += ( 2 * iv_len );
1706 assert ( src == &tmp.key[total] );
1707
1708 /* Clear temporary secrets */
1709 memset ( &tmp, 0, sizeof ( tmp ) );
1710
1711 return 0;
1712}
1713
1714/**
1715 * Generate signable digest value
1716 *
1717 * @v tlskey Key schedule
1718 * @v end Endpoint
1719 * @v digest Signature digest algorithm
1720 * @v data Additional data
1721 * @v len Length of additional data
1722 * @v tbs Signable digest value to fill in
1723 * @ret rc Return status code
1724 */
1725static int tlskey_hash_tbshash ( struct tls_key_schedule *tlskey,
1726 const struct tls_endpoint *end,
1727 struct digest_algorithm *digest,
1728 const void *data, size_t len, void *tbs ) {
1729 size_t ctxsize = digest->ctxsize;
1730 struct {
1731 uint8_t ctx[ctxsize];
1732 } tmp;
1733
1734 /* Generate endpoint-specific digest value */
1735 if ( end->index == TLS_CLIENT ) {
1736
1737 /* The client CertificateVerify digest value is the
1738 * raw transcript digest. We retain only a single
1739 * running transcript digest, and can therefore
1740 * provide this only for a digest algorithm that
1741 * matches our transcript digest algorithm.
1742 */
1743 if ( digest != tlskey->digest ) {
1744 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
1745 "transcript digest\n", tlskey, digest->name );
1746 return -ENOTSUP;
1747 }
1748
1749 /* There is no way to incorporate additional data */
1750 if ( len ) {
1751 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1752 "with additional data\n", tlskey );
1753 return -ENOTSUP;
1754 }
1755
1756 /* Copy transcript digest value */
1757 memcpy ( tbs, tlskey->transcript.running,
1758 digest->digestsize );
1759
1760 } else {
1761
1762 /* Additional data (i.e. the ServerKeyExchange
1763 * parameters) must be incorporated, since otherwise
1764 * the digest does not cover the parameters used to
1765 * establish the shared secret.
1766 */
1767 if ( ! len ) {
1768 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1769 "without additional data\n", tlskey );
1770 return -ENOTSUP;
1771 }
1772
1773 /* Generate ServerKeyExchange digest */
1774 digest_init ( digest, tmp.ctx );
1775 digest_update ( digest, tmp.ctx, &tlskey->random,
1776 sizeof ( tlskey->random ) );
1777 digest_update ( digest, tmp.ctx, data, len );
1778 digest_final ( digest, tmp.ctx, tbs );
1779 }
1780
1781 /* Clear temporary secrets */
1782 memset ( &tmp, 0, sizeof ( tmp ) );
1783
1784 return 0;
1785}
1786
1787/**
1788 * Save pre-shared key
1789 *
1790 * @v tlskey Key schedule
1791 * @v nonce Ticket nonce
1792 * @v nonce_len Length of ticket nonce
1793 * @v psk Pre-shared key to fill in
1794 * @ret rc Return status code
1795 */
1796static int tlskey_hash_save ( struct tls_key_schedule *tlskey,
1797 const void *nonce __unused, size_t nonce_len,
1798 struct tls_preshared_key *psk ) {
1799 struct digest_algorithm *digest = tlskey->digest;
1800
1801 /* A ticket nonce is not supported */
1802 if ( nonce_len )
1803 return -ENOTSUP;
1804
1805 /* For TLS version 1.2, the pre-master secret may be any
1806 * length but the master secret is fixed at 48 bytes. This is
1807 * smaller than the block size for all supported digest
1808 * algorithms. The HMAC key constructed from the master
1809 * secret will therefore be just the zero-padded master secret
1810 * value. We can therefore preserve just these first 48 bytes
1811 * of the KDF master secret (ignoring the zero padding up to
1812 * the digest block size).
1813 */
1814 assert ( sizeof ( psk->key.master_secret ) <=
1815 hmac_keysize ( digest ) );
1816 memcpy ( &psk->key.master_secret, tlskey->kdf.secret,
1817 sizeof ( psk->key.master_secret ) );
1818
1819 return 0;
1820}
1821
1822/**
1823 * Load pre-shared key
1824 *
1825 * @v tlskey Key schedule
1826 * @v psk Pre-shared key
1827 * @ret rc Return status code
1828 */
1829static int tlskey_hash_load ( struct tls_key_schedule *tlskey,
1830 const struct tls_preshared_key *psk ) {
1831 const void *secret;
1832 size_t secret_len;
1833 int rc;
1834
1835 /* For TLS versions 1.2 and earlier, the pre-shared key
1836 * material contains the master secret and so we just apply
1837 * this as the key derivation function secret.
1838 */
1839 secret = &psk->key.master_secret;
1840 secret_len = sizeof ( psk->key.master_secret );
1841 if ( ( rc = tlskey_apply ( tlskey, secret, secret_len ) ) != 0 )
1842 return rc;
1843
1844 return 0;
1845}
1846
1847/**
1848 * Generate pre-shared key binder value
1849 *
1850 * @v psk Pre-shared key
1851 * @v hash Partial transcript hash
1852 * @v binder Binder value to fill in
1853 * @v binder_len Length of binder value
1854 * @ret rc Return status code
1855 */
1856static int tlskey_hash_bind ( const struct tls_preshared_key *psk __unused,
1857 const void *hash __unused,
1858 void *binder __unused, size_t binder_len ) {
1859
1860 /* Binder values are not supported */
1861 if ( binder_len )
1862 return -ENOTSUP;
1863
1864 return 0;
1865}
1866
1867/** TLS key schedule based on P_Hash() */
1885
1886/*****************************************************************************
1887 *
1888 * TLS version 1.0/1.1 key schedule using PRF based on P_MD5()+P_SHA1()
1889 *
1890 *****************************************************************************
1891 */
1892
1893/**
1894 * Calculate secret size
1895 *
1896 * @v digest Digest algorithm
1897 * @ret secretsize Secret size, or zero if unsupported
1898 */
1899static size_t tlskey_md5_sha1_secretsize ( struct digest_algorithm *digest ) {
1900 struct md5_sha1_hmac_keys *hkeys;
1901 size_t secretsize;
1902
1903 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1904 if ( digest != &md5_sha1_algorithm )
1905 return 0;
1906
1907 /* A P_MD5()+P_SHA1() key is a split HMAC-MD5 and HMAC-SHA1 key */
1908 assert ( sizeof ( hkeys->md5 ) == hmac_keysize ( &md5_algorithm ) );
1909 assert ( sizeof ( hkeys->sha1 ) == hmac_keysize ( &sha1_algorithm ) );
1910 secretsize = sizeof ( *hkeys );
1911
1912 return secretsize;
1913}
1914
1915/**
1916 * Expand key material
1917 *
1918 * @v digest Digest algorithm
1919 * @v secret Secret
1920 * @v label Label string
1921 * @v seed Seed material
1922 * @v seed_len Length of seed material
1923 * @v out Output buffer
1924 * @v out_len Length of output buffer
1925 */
1926static void tlskey_md5_sha1_expand ( struct digest_algorithm *digest,
1927 const void *secret, const char *label,
1928 const void *seed, size_t seed_len,
1929 void *out, size_t out_len ) {
1930 const struct md5_sha1_hmac_keys *hkeys = secret;
1931 struct {
1932 uint8_t sha1[out_len];
1933 } tmp;
1934 uint8_t *xor;
1935 unsigned int i;
1936
1937 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1938 assert ( digest == &md5_sha1_algorithm );
1939
1940 /* Generate MD5 portion into output buffer */
1941 tlskey_hash_expand ( &md5_algorithm, hkeys->md5, label, seed,
1942 seed_len, out, out_len );
1943
1944 /* Generate SHA-1 portion into temporary buffer */
1945 tlskey_hash_expand ( &sha1_algorithm, hkeys->sha1, label, seed,
1946 seed_len, tmp.sha1, out_len );
1947
1948 /* XOR together into output buffer */
1949 xor = out;
1950 for ( i = 0 ; i < out_len ; i++ )
1951 xor[i] ^= tmp.sha1[i];
1952
1953 /* Clear temporary secrets */
1954 memset ( &tmp, 0, sizeof ( tmp ) );
1955}
1956
1957/**
1958 * Apply a new shared secret
1959 *
1960 * @v tlskey Key schedule
1961 * @v shared New shared secret
1962 * @v shared_len Length of new shared secret
1963 * @ret rc Return status code
1964 */
1965static int tlskey_md5_sha1_apply ( struct tls_key_schedule *tlskey,
1966 const void *shared, size_t shared_len ) {
1967 struct digest_algorithm *digest = tlskey->digest;
1968 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1969 size_t hctxsize = hmac_ctxsize ( digest );
1970 struct {
1971 uint8_t hctx[hctxsize];
1972 } tmp;
1973 const void *shared_md5;
1974 const void *shared_sha1;
1975 size_t shared_sublen;
1976
1977 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1978 assert ( digest == &md5_sha1_algorithm );
1979
1980 /* Split secret into two, with an overlap of up to one byte */
1981 shared_sublen = ( ( shared_len + 1 ) / 2 );
1982 shared_md5 = shared;
1983 shared_sha1 = ( shared + shared_len - shared_sublen );
1984
1985 /* Set HMAC-MD5 key */
1986 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &md5_algorithm ) );
1987 hmac_key ( &md5_algorithm, tmp.hctx, shared_md5, shared_sublen,
1988 hkeys->md5 );
1989
1990 /* Set HMAC-SHA1 key */
1991 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &sha1_algorithm ) );
1992 hmac_key ( &sha1_algorithm, tmp.hctx, shared_sha1, shared_sublen,
1993 hkeys->sha1 );
1994
1995 /* Clear temporary secrets */
1996 memset ( &tmp, 0, sizeof ( tmp ) );
1997
1998 return 0;
1999}
2000
2001/**
2002 * Generate signable digest value
2003 *
2004 * @v tlskey Key schedule
2005 * @v end Endpoint
2006 * @v digest Signature digest algorithm
2007 * @v data Additional data
2008 * @v len Length of additional data
2009 * @v tbs Signable digest value to fill in
2010 * @ret rc Return status code
2011 */
2012static int tlskey_md5_sha1_tbshash ( struct tls_key_schedule *tlskey,
2013 const struct tls_endpoint *end,
2014 struct digest_algorithm *digest,
2015 const void *data, size_t len,
2016 void *tbs ) {
2017 struct md5_sha1_digest *running = tlskey->transcript.running;
2018 const void *hash;
2019
2020 /* The client CertificateVerify digest value is the raw
2021 * transcript digest. We retain an MD5+SHA1 transcript
2022 * digest, which is the concatenation of the MD5 and SHA-1
2023 * transcript digests. We can therefore provide a signable
2024 * digest value for MD5 or SHA-1 as well as for MD5+SHA1.
2025 */
2026 if ( ( end->index == TLS_CLIENT ) && ( digest != tlskey->digest ) ) {
2027
2028 /* Locate MD5 or SHA-1 portion */
2029 if ( digest == &md5_algorithm ) {
2030 hash = running->md5;
2031 } else if ( digest == &sha1_algorithm ) {
2032 hash = running->sha1;
2033 } else {
2034 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
2035 "transcript digest\n", tlskey, digest->name );
2036 return -ENOTSUP;
2037 }
2038
2039 /* There is no way to incorporate additional data */
2040 if ( len ) {
2041 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
2042 "with additional data\n", tlskey );
2043 return -ENOTSUP;
2044 }
2045
2046 /* Copy transcript digest value */
2047 memcpy ( tbs, hash, digest->digestsize );
2048
2049 return 0;
2050 }
2051
2052 /* Otherwise, generate MD5+SHA1 signable digest value */
2053 return tlskey_hash_tbshash ( tlskey, end, digest, data, len, tbs );
2054}
2055
2056/**
2057 * Save pre-shared key
2058 *
2059 * @v tlskey Key schedule
2060 * @v nonce Ticket nonce
2061 * @v nonce_len Length of ticket nonce
2062 * @v psk Pre-shared key
2063 * @ret rc Return status code
2064 */
2065static int tlskey_md5_sha1_save ( struct tls_key_schedule *tlskey,
2066 const void *nonce __unused,
2067 size_t nonce_len,
2068 struct tls_preshared_key *psk ) {
2069 struct digest_algorithm *digest = tlskey->digest;
2070 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
2071
2072 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
2073 assert ( digest == &md5_sha1_algorithm );
2074
2075 /* A ticket nonce is not supported */
2076 if ( nonce_len )
2077 return -ENOTSUP;
2078
2079 /* For TLS versions 1.1 and earlier, the pre-master secret may
2080 * be any length but the master secret is fixed at 48 bytes.
2081 * It will have been split to become 24 bytes in each of the
2082 * MD5 and SHA-1 HMAC keys.
2083 */
2084 assert ( sizeof ( psk->key.master_secret.md5 ) <=
2086 assert ( sizeof ( psk->key.master_secret.sha1 ) <=
2088 memcpy ( psk->key.master_secret.md5, hkeys->md5,
2089 sizeof ( psk->key.master_secret.md5 ) );
2090 memcpy ( psk->key.master_secret.sha1, hkeys->sha1,
2091 sizeof ( psk->key.master_secret.sha1 ) );
2092
2093 return 0;
2094}
2095
2096/** 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.
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition message.c:62
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 digest.
Definition md5_sha1.h:30
uint8_t md5[MD5_DIGEST_SIZE]
MD5 digest.
Definition md5_sha1.h:32
uint8_t sha1[SHA1_DIGEST_SIZE]
SHA-1 digest.
Definition md5_sha1.h:34
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:454
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:90
unsigned int flags
Key flags.
Definition tlskey.h:92
TLS key schedule operations.
Definition tlskey.h:183
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:311
int(* load)(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.h:320
int(* master)(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.h:246
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:283
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:331
int(* verify)(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.h:256
const char * name
Name.
Definition tlskey.h:185
size_t(* secretsize)(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.h:207
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:298
int(* traffic)(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secrets.
Definition tlskey.h:267
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:219
void(* reset)(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.h:228
int(* apply)(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.h:237
A TLS key schedule.
Definition tlskey.h:113
const struct tls_key_schedule_operations * op
Key schedule operations.
Definition tlskey.h:115
void * secret
Secret(s).
Definition tlskey.h:124
struct tls_random random[2]
Client and server random bytes.
Definition tlskey.h:133
size_t secretsize
Secret size.
Definition tlskey.h:119
struct tls_transcript transcript
Running handshake transcript digest.
Definition tlskey.h:129
struct tls_random nonce
Local endpoint random bytes.
Definition tlskey.h:131
struct tls_traffic_secret traffic[2]
Traffic secrets.
Definition tlskey.h:137
struct digest_algorithm * digest
Digest algorithm.
Definition tlskey.h:117
void * dynamic
Dynamically-allocated storage.
Definition tlskey.h:122
struct tls_kdf_secret kdf
Key derivation function secret.
Definition tlskey.h:135
A message hash prefix.
Definition tlskey.h:42
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:141
uint8_t resumption[48]
Resumption secret.
Definition tlskey.h:178
union tls_preshared_key::@022173016027117201055347232316162256252261104170::@216204225163015142232067115177347130257031275370 master_secret
Master secret.
struct digest_algorithm * digest
Digest algorithm (if set).
Definition tlskey.h:145
unsigned int flags
Key flags.
Definition tlskey.h:147
uint8_t md5[24]
Definition tlskey.h:164
union tls_preshared_key::@022173016027117201055347232316162256252261104170 key
Key material.
uint8_t sha1[24]
Definition tlskey.h:165
const struct tls_key_schedule_operations * op
Key schedule operations (if set).
Definition tlskey.h:143
TLS client or server random bytes.
Definition tlskey.h:36
TLS server state.
Definition tls.h:464
A TLS traffic secret.
Definition tlskey.h:105
const struct tls_phase * phase
Phase.
Definition tlskey.h:109
void * secret
Secret.
Definition tlskey.h:107
A TLS running handshake transcript digest.
Definition tlskey.h:55
void * finishing
Running digest value up to the most recent Finished (if any).
Definition tlskey.h:76
void * running
Running digest value.
Definition tlskey.h:65
unsigned int flags
Transcript flags.
Definition tlskey.h:78
void * ctx
Digest context.
Definition tlskey.h:57
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:1725
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:1926
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:1672
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:986
static int tlskey_hash_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1829
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:823
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:585
static void tlskey_hkdf_empty(struct digest_algorithm *digest, void *empty)
Calculate empty digest value.
Definition tlskey.c:1022
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:1604
static int tlskey_hash_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1551
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:719
int tlskey_load(struct tls_key_schedule *tlskey, int ems, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:866
static int tlskey_hkdf_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1121
static void tlskey_hash_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1510
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:1220
static void tlskey_hkdf_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1068
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:1641
void tlskey_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:520
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:1151
#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:2065
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:772
int tlskey_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:550
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:1304
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:1796
#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:1342
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:1856
const struct tls_key_schedule_operations tlskey_hash
TLS key schedule based on P_Hash().
Definition tlskey.c:1868
int tlskey_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:667
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:1369
static size_t tlskey_hkdf_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:969
void tlskey_message(struct tls_key_schedule *tlskey)
Replace running transcript digest with a message hash of itself.
Definition tlskey.c:457
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:1092
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:1263
const struct tls_key_schedule_operations tlskey_md5_sha1
TLS key schedule based on P_MD5()+P_SHA1().
Definition tlskey.c:2097
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:1527
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:1433
static size_t tlskey_hash_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1441
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:1187
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:630
static void tlskey_hkdf_finished(struct digest_algorithm *digest, const void *secret, const void *hash, void *out)
Calculate a finished MAC.
Definition tlskey.c:1040
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:1458
static size_t tlskey_md5_sha1_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1899
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:1965
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:923
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:494
const struct tls_key_schedule_operations tlskey_hkdf
TLS key schedule based on HKDF.
Definition tlskey.c:1407
static int tlskey_md5_sha1_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:2012
TLS key schedules.
#define TLSKEY_KDF_EMS
Key derivation function has an extended master secret.
Definition tlskey.h:102
#define TLS_CLIENT
Client endpoint index.
Definition tlskey.h:27
#define TLSKEY_TSF_FINISHED
Transcript digest includes a Finished record.
Definition tlskey.h:85
#define TLSKEY_KDF_MASTER
Key derivation function has a master secret.
Definition tlskey.h:99
#define TLSKEY_KDF_KEYED
Key derivation function has key material.
Definition tlskey.h:96
#define TLS_SERVER
Server endpoint index.
Definition tlskey.h:30
#define TLS_MESSAGE_HASH
A TLS message hash.
Definition tlskey.h:52
#define TLSKEY_TSF_NONCED
Transcript digest includes a Hello record containing the local nonce.
Definition tlskey.h:82
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