rustls/
quic.rs

1/// This module contains optional APIs for implementing QUIC TLS.
2use crate::client::{ClientConfig, ClientConnectionData};
3use crate::common_state::{CommonState, Protocol, Side};
4use crate::conn::{ConnectionCore, SideData};
5use crate::crypto::cipher::{AeadKey, Iv};
6use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock};
7use crate::enums::{AlertDescription, ProtocolVersion};
8use crate::error::Error;
9use crate::msgs::handshake::{ClientExtension, ServerExtension};
10use crate::server::{ServerConfig, ServerConnectionData};
11use crate::tls13::key_schedule::{
12    hkdf_expand_label, hkdf_expand_label_aead_key, hkdf_expand_label_block,
13};
14use crate::tls13::Tls13CipherSuite;
15
16use pki_types::ServerName;
17
18use alloc::boxed::Box;
19use alloc::collections::VecDeque;
20use alloc::sync::Arc;
21use alloc::vec;
22use alloc::vec::Vec;
23use core::fmt::{self, Debug};
24use core::ops::{Deref, DerefMut};
25
26/// A QUIC client or server connection.
27#[derive(Debug)]
28pub enum Connection {
29    /// A client connection
30    Client(ClientConnection),
31    /// A server connection
32    Server(ServerConnection),
33}
34
35impl Connection {
36    /// Return the TLS-encoded transport parameters for the session's peer.
37    ///
38    /// See [`ConnectionCommon::quic_transport_parameters()`] for more details.
39    pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
40        match self {
41            Self::Client(conn) => conn.quic_transport_parameters(),
42            Self::Server(conn) => conn.quic_transport_parameters(),
43        }
44    }
45
46    /// Compute the keys for encrypting/decrypting 0-RTT packets, if available
47    pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
48        match self {
49            Self::Client(conn) => conn.zero_rtt_keys(),
50            Self::Server(conn) => conn.zero_rtt_keys(),
51        }
52    }
53
54    /// Consume unencrypted TLS handshake data.
55    ///
56    /// Handshake data obtained from separate encryption levels should be supplied in separate calls.
57    pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
58        match self {
59            Self::Client(conn) => conn.read_hs(plaintext),
60            Self::Server(conn) => conn.read_hs(plaintext),
61        }
62    }
63
64    /// Emit unencrypted TLS handshake data.
65    ///
66    /// When this returns `Some(_)`, the new keys must be used for future handshake data.
67    pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
68        match self {
69            Self::Client(conn) => conn.write_hs(buf),
70            Self::Server(conn) => conn.write_hs(buf),
71        }
72    }
73
74    /// Emit the TLS description code of a fatal alert, if one has arisen.
75    ///
76    /// Check after `read_hs` returns `Err(_)`.
77    pub fn alert(&self) -> Option<AlertDescription> {
78        match self {
79            Self::Client(conn) => conn.alert(),
80            Self::Server(conn) => conn.alert(),
81        }
82    }
83
84    /// Derives key material from the agreed connection secrets.
85    ///
86    /// This function fills in `output` with `output.len()` bytes of key
87    /// material derived from the master session secret using `label`
88    /// and `context` for diversification. Ownership of the buffer is taken
89    /// by the function and returned via the Ok result to ensure no key
90    /// material leaks if the function fails.
91    ///
92    /// See RFC5705 for more details on what this does and is for.
93    ///
94    /// For TLS1.3 connections, this function does not use the
95    /// "early" exporter at any point.
96    ///
97    /// This function fails if called prior to the handshake completing;
98    /// check with [`CommonState::is_handshaking`] first.
99    #[inline]
100    pub fn export_keying_material<T: AsMut<[u8]>>(
101        &self,
102        output: T,
103        label: &[u8],
104        context: Option<&[u8]>,
105    ) -> Result<T, Error> {
106        match self {
107            Self::Client(conn) => conn
108                .core
109                .export_keying_material(output, label, context),
110            Self::Server(conn) => conn
111                .core
112                .export_keying_material(output, label, context),
113        }
114    }
115}
116
117impl Deref for Connection {
118    type Target = CommonState;
119
120    fn deref(&self) -> &Self::Target {
121        match self {
122            Self::Client(conn) => &conn.core.common_state,
123            Self::Server(conn) => &conn.core.common_state,
124        }
125    }
126}
127
128impl DerefMut for Connection {
129    fn deref_mut(&mut self) -> &mut Self::Target {
130        match self {
131            Self::Client(conn) => &mut conn.core.common_state,
132            Self::Server(conn) => &mut conn.core.common_state,
133        }
134    }
135}
136
137/// A QUIC client connection.
138pub struct ClientConnection {
139    inner: ConnectionCommon<ClientConnectionData>,
140}
141
142impl ClientConnection {
143    /// Make a new QUIC ClientConnection.
144    ///
145    /// This differs from `ClientConnection::new()` in that it takes an extra `params` argument,
146    /// which contains the TLS-encoded transport parameters to send.
147    pub fn new(
148        config: Arc<ClientConfig>,
149        quic_version: Version,
150        name: ServerName<'static>,
151        params: Vec<u8>,
152    ) -> Result<Self, Error> {
153        if !config.supports_version(ProtocolVersion::TLSv1_3) {
154            return Err(Error::General(
155                "TLS 1.3 support is required for QUIC".into(),
156            ));
157        }
158
159        if !config.supports_protocol(Protocol::Quic) {
160            return Err(Error::General(
161                "at least one ciphersuite must support QUIC".into(),
162            ));
163        }
164
165        let ext = match quic_version {
166            Version::V1Draft => ClientExtension::TransportParametersDraft(params),
167            Version::V1 | Version::V2 => ClientExtension::TransportParameters(params),
168        };
169
170        let mut inner = ConnectionCore::for_client(config, name, vec![ext], Protocol::Quic)?;
171        inner.common_state.quic.version = quic_version;
172        Ok(Self {
173            inner: inner.into(),
174        })
175    }
176
177    /// Returns True if the server signalled it will process early data.
178    ///
179    /// If you sent early data and this returns false at the end of the
180    /// handshake then the server will not process the data.  This
181    /// is not an error, but you may wish to resend the data.
182    pub fn is_early_data_accepted(&self) -> bool {
183        self.inner.core.is_early_data_accepted()
184    }
185}
186
187impl Deref for ClientConnection {
188    type Target = ConnectionCommon<ClientConnectionData>;
189
190    fn deref(&self) -> &Self::Target {
191        &self.inner
192    }
193}
194
195impl DerefMut for ClientConnection {
196    fn deref_mut(&mut self) -> &mut Self::Target {
197        &mut self.inner
198    }
199}
200
201impl Debug for ClientConnection {
202    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203        f.debug_struct("quic::ClientConnection")
204            .finish()
205    }
206}
207
208impl From<ClientConnection> for Connection {
209    fn from(c: ClientConnection) -> Self {
210        Self::Client(c)
211    }
212}
213
214/// A QUIC server connection.
215pub struct ServerConnection {
216    inner: ConnectionCommon<ServerConnectionData>,
217}
218
219impl ServerConnection {
220    /// Make a new QUIC ServerConnection.
221    ///
222    /// This differs from `ServerConnection::new()` in that it takes an extra `params` argument,
223    /// which contains the TLS-encoded transport parameters to send.
224    pub fn new(
225        config: Arc<ServerConfig>,
226        quic_version: Version,
227        params: Vec<u8>,
228    ) -> Result<Self, Error> {
229        if !config.supports_version(ProtocolVersion::TLSv1_3) {
230            return Err(Error::General(
231                "TLS 1.3 support is required for QUIC".into(),
232            ));
233        }
234
235        if !config.supports_protocol(Protocol::Quic) {
236            return Err(Error::General(
237                "at least one ciphersuite must support QUIC".into(),
238            ));
239        }
240
241        if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff {
242            return Err(Error::General(
243                "QUIC sessions must set a max early data of 0 or 2^32-1".into(),
244            ));
245        }
246
247        let ext = match quic_version {
248            Version::V1Draft => ServerExtension::TransportParametersDraft(params),
249            Version::V1 | Version::V2 => ServerExtension::TransportParameters(params),
250        };
251
252        let mut core = ConnectionCore::for_server(config, vec![ext])?;
253        core.common_state.protocol = Protocol::Quic;
254        core.common_state.quic.version = quic_version;
255        Ok(Self { inner: core.into() })
256    }
257
258    /// Explicitly discard early data, notifying the client
259    ///
260    /// Useful if invariants encoded in `received_resumption_data()` cannot be respected.
261    ///
262    /// Must be called while `is_handshaking` is true.
263    pub fn reject_early_data(&mut self) {
264        self.inner.core.reject_early_data()
265    }
266
267    /// Retrieves the server name, if any, used to select the certificate and
268    /// private key.
269    ///
270    /// This returns `None` until some time after the client's server name indication
271    /// (SNI) extension value is processed during the handshake. It will never be
272    /// `None` when the connection is ready to send or process application data,
273    /// unless the client does not support SNI.
274    ///
275    /// This is useful for application protocols that need to enforce that the
276    /// server name matches an application layer protocol hostname. For
277    /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
278    /// every request on a connection to match the hostname in the SNI extension
279    /// when the client provides the SNI extension.
280    ///
281    /// The server name is also used to match sessions during session resumption.
282    pub fn server_name(&self) -> Option<&str> {
283        self.inner.core.get_sni_str()
284    }
285}
286
287impl Deref for ServerConnection {
288    type Target = ConnectionCommon<ServerConnectionData>;
289
290    fn deref(&self) -> &Self::Target {
291        &self.inner
292    }
293}
294
295impl DerefMut for ServerConnection {
296    fn deref_mut(&mut self) -> &mut Self::Target {
297        &mut self.inner
298    }
299}
300
301impl Debug for ServerConnection {
302    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
303        f.debug_struct("quic::ServerConnection")
304            .finish()
305    }
306}
307
308impl From<ServerConnection> for Connection {
309    fn from(c: ServerConnection) -> Self {
310        Self::Server(c)
311    }
312}
313
314/// A shared interface for QUIC connections.
315pub struct ConnectionCommon<Data> {
316    core: ConnectionCore<Data>,
317}
318
319impl<Data: SideData> ConnectionCommon<Data> {
320    /// Return the TLS-encoded transport parameters for the session's peer.
321    ///
322    /// While the transport parameters are technically available prior to the
323    /// completion of the handshake, they cannot be fully trusted until the
324    /// handshake completes, and reliance on them should be minimized.
325    /// However, any tampering with the parameters will cause the handshake
326    /// to fail.
327    pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
328        self.core
329            .common_state
330            .quic
331            .params
332            .as_ref()
333            .map(|v| v.as_ref())
334    }
335
336    /// Compute the keys for encrypting/decrypting 0-RTT packets, if available
337    pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
338        let suite = self
339            .core
340            .common_state
341            .suite
342            .and_then(|suite| suite.tls13())?;
343        Some(DirectionalKeys::new(
344            suite,
345            suite.quic?,
346            self.core
347                .common_state
348                .quic
349                .early_secret
350                .as_ref()?,
351            self.core.common_state.quic.version,
352        ))
353    }
354
355    /// Consume unencrypted TLS handshake data.
356    ///
357    /// Handshake data obtained from separate encryption levels should be supplied in separate calls.
358    pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
359        self.core
360            .message_deframer
361            .push(ProtocolVersion::TLSv1_3, plaintext)?;
362        self.core.process_new_packets()?;
363        Ok(())
364    }
365
366    /// Emit unencrypted TLS handshake data.
367    ///
368    /// When this returns `Some(_)`, the new keys must be used for future handshake data.
369    pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
370        self.core
371            .common_state
372            .quic
373            .write_hs(buf)
374    }
375
376    /// Emit the TLS description code of a fatal alert, if one has arisen.
377    ///
378    /// Check after `read_hs` returns `Err(_)`.
379    pub fn alert(&self) -> Option<AlertDescription> {
380        self.core.common_state.quic.alert
381    }
382}
383
384impl<Data> Deref for ConnectionCommon<Data> {
385    type Target = CommonState;
386
387    fn deref(&self) -> &Self::Target {
388        &self.core.common_state
389    }
390}
391
392impl<Data> DerefMut for ConnectionCommon<Data> {
393    fn deref_mut(&mut self) -> &mut Self::Target {
394        &mut self.core.common_state
395    }
396}
397
398impl<Data> From<ConnectionCore<Data>> for ConnectionCommon<Data> {
399    fn from(core: ConnectionCore<Data>) -> Self {
400        Self { core }
401    }
402}
403
404#[derive(Default)]
405pub(crate) struct Quic {
406    /// QUIC transport parameters received from the peer during the handshake
407    pub(crate) params: Option<Vec<u8>>,
408    pub(crate) alert: Option<AlertDescription>,
409    pub(crate) hs_queue: VecDeque<(bool, Vec<u8>)>,
410    pub(crate) early_secret: Option<OkmBlock>,
411    pub(crate) hs_secrets: Option<Secrets>,
412    pub(crate) traffic_secrets: Option<Secrets>,
413    /// Whether keys derived from traffic_secrets have been passed to the QUIC implementation
414    pub(crate) returned_traffic_keys: bool,
415    pub(crate) version: Version,
416}
417
418impl Quic {
419    pub(crate) fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
420        while let Some((_, msg)) = self.hs_queue.pop_front() {
421            buf.extend_from_slice(&msg);
422            if let Some(&(true, _)) = self.hs_queue.front() {
423                if self.hs_secrets.is_some() {
424                    // Allow the caller to switch keys before proceeding.
425                    break;
426                }
427            }
428        }
429
430        if let Some(secrets) = self.hs_secrets.take() {
431            return Some(KeyChange::Handshake {
432                keys: Keys::new(&secrets),
433            });
434        }
435
436        if let Some(mut secrets) = self.traffic_secrets.take() {
437            if !self.returned_traffic_keys {
438                self.returned_traffic_keys = true;
439                let keys = Keys::new(&secrets);
440                secrets.update();
441                return Some(KeyChange::OneRtt {
442                    keys,
443                    next: secrets,
444                });
445            }
446        }
447
448        None
449    }
450}
451
452/// Secrets used to encrypt/decrypt traffic
453#[derive(Clone)]
454pub struct Secrets {
455    /// Secret used to encrypt packets transmitted by the client
456    pub(crate) client: OkmBlock,
457    /// Secret used to encrypt packets transmitted by the server
458    pub(crate) server: OkmBlock,
459    /// Cipher suite used with these secrets
460    suite: &'static Tls13CipherSuite,
461    quic: &'static dyn Algorithm,
462    side: Side,
463    version: Version,
464}
465
466impl Secrets {
467    pub(crate) fn new(
468        client: OkmBlock,
469        server: OkmBlock,
470        suite: &'static Tls13CipherSuite,
471        quic: &'static dyn Algorithm,
472        side: Side,
473        version: Version,
474    ) -> Self {
475        Self {
476            client,
477            server,
478            suite,
479            quic,
480            side,
481            version,
482        }
483    }
484
485    /// Derive the next set of packet keys
486    pub fn next_packet_keys(&mut self) -> PacketKeySet {
487        let keys = PacketKeySet::new(self);
488        self.update();
489        keys
490    }
491
492    pub(crate) fn update(&mut self) {
493        self.client = hkdf_expand_label_block(
494            self.suite
495                .hkdf_provider
496                .expander_for_okm(&self.client)
497                .as_ref(),
498            self.version.key_update_label(),
499            &[],
500        );
501        self.server = hkdf_expand_label_block(
502            self.suite
503                .hkdf_provider
504                .expander_for_okm(&self.server)
505                .as_ref(),
506            self.version.key_update_label(),
507            &[],
508        );
509    }
510
511    fn local_remote(&self) -> (&OkmBlock, &OkmBlock) {
512        match self.side {
513            Side::Client => (&self.client, &self.server),
514            Side::Server => (&self.server, &self.client),
515        }
516    }
517}
518
519/// Keys used to communicate in a single direction
520pub struct DirectionalKeys {
521    /// Encrypts or decrypts a packet's headers
522    pub header: Box<dyn HeaderProtectionKey>,
523    /// Encrypts or decrypts the payload of a packet
524    pub packet: Box<dyn PacketKey>,
525}
526
527impl DirectionalKeys {
528    pub(crate) fn new(
529        suite: &'static Tls13CipherSuite,
530        quic: &'static dyn Algorithm,
531        secret: &OkmBlock,
532        version: Version,
533    ) -> Self {
534        let builder = KeyBuilder::new(secret, version, quic, suite.hkdf_provider);
535        Self {
536            header: builder.header_protection_key(),
537            packet: builder.packet_key(),
538        }
539    }
540}
541
542/// All AEADs we support have 16-byte tags.
543const TAG_LEN: usize = 16;
544
545/// Authentication tag from an AEAD seal operation.
546pub struct Tag([u8; TAG_LEN]);
547
548impl From<&[u8]> for Tag {
549    fn from(value: &[u8]) -> Self {
550        let mut array = [0u8; TAG_LEN];
551        array.copy_from_slice(value);
552        Self(array)
553    }
554}
555
556impl AsRef<[u8]> for Tag {
557    fn as_ref(&self) -> &[u8] {
558        &self.0
559    }
560}
561
562/// How a `Tls13CipherSuite` generates `PacketKey`s and `HeaderProtectionKey`s.
563pub trait Algorithm: Send + Sync {
564    /// Produce a `PacketKey` encrypter/decrypter for this suite.
565    ///
566    /// `suite` is the entire suite this `Algorithm` appeared in.
567    /// `key` and `iv` is the key material to use.
568    fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn PacketKey>;
569
570    /// Produce a `HeaderProtectionKey` encrypter/decrypter for this suite.
571    ///
572    /// `key` is the key material, which is `aead_key_len()` bytes in length.
573    fn header_protection_key(&self, key: AeadKey) -> Box<dyn HeaderProtectionKey>;
574
575    /// The length in bytes of keys for this Algorithm.
576    ///
577    /// This controls the size of `AeadKey`s presented to `packet_key()` and `header_protection_key()`.
578    fn aead_key_len(&self) -> usize;
579}
580
581/// A QUIC header protection key
582pub trait HeaderProtectionKey {
583    /// Adds QUIC Header Protection.
584    ///
585    /// `sample` must contain the sample of encrypted payload; see
586    /// [Header Protection Sample].
587    ///
588    /// `first` must reference the first byte of the header, referred to as
589    /// `packet[0]` in [Header Protection Application].
590    ///
591    /// `packet_number` must reference the Packet Number field; this is
592    /// `packet[pn_offset:pn_offset+pn_length]` in [Header Protection Application].
593    ///
594    /// Returns an error without modifying anything if `sample` is not
595    /// the correct length (see [Header Protection Sample] and [`Self::sample_len()`]),
596    /// or `packet_number` is longer than allowed (see [Packet Number Encoding and Decoding]).
597    ///
598    /// Otherwise, `first` and `packet_number` will have the header protection added.
599    ///
600    /// [Header Protection Application]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.1
601    /// [Header Protection Sample]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.2
602    /// [Packet Number Encoding and Decoding]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.1
603    fn encrypt_in_place(
604        &self,
605        sample: &[u8],
606        first: &mut u8,
607        packet_number: &mut [u8],
608    ) -> Result<(), Error>;
609
610    /// Removes QUIC Header Protection.
611    ///
612    /// `sample` must contain the sample of encrypted payload; see
613    /// [Header Protection Sample].
614    ///
615    /// `first` must reference the first byte of the header, referred to as
616    /// `packet[0]` in [Header Protection Application].
617    ///
618    /// `packet_number` must reference the Packet Number field; this is
619    /// `packet[pn_offset:pn_offset+pn_length]` in [Header Protection Application].
620    ///
621    /// Returns an error without modifying anything if `sample` is not
622    /// the correct length (see [Header Protection Sample] and [`Self::sample_len()`]),
623    /// or `packet_number` is longer than allowed (see
624    /// [Packet Number Encoding and Decoding]).
625    ///
626    /// Otherwise, `first` and `packet_number` will have the header protection removed.
627    ///
628    /// [Header Protection Application]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.1
629    /// [Header Protection Sample]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.2
630    /// [Packet Number Encoding and Decoding]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.1
631    fn decrypt_in_place(
632        &self,
633        sample: &[u8],
634        first: &mut u8,
635        packet_number: &mut [u8],
636    ) -> Result<(), Error>;
637
638    /// Expected sample length for the key's algorithm
639    fn sample_len(&self) -> usize;
640}
641
642/// Keys to encrypt or decrypt the payload of a packet
643pub trait PacketKey {
644    /// Encrypt a QUIC packet
645    ///
646    /// Takes a `packet_number`, used to derive the nonce; the packet `header`, which is used as
647    /// the additional authenticated data; and the `payload`. The authentication tag is returned if
648    /// encryption succeeds.
649    ///
650    /// Fails iff the payload is longer than allowed by the cipher suite's AEAD algorithm.
651    fn encrypt_in_place(
652        &self,
653        packet_number: u64,
654        header: &[u8],
655        payload: &mut [u8],
656    ) -> Result<Tag, Error>;
657
658    /// Decrypt a QUIC packet
659    ///
660    /// Takes the packet `header`, which is used as the additional authenticated data, and the
661    /// `payload`, which includes the authentication tag.
662    ///
663    /// If the return value is `Ok`, the decrypted payload can be found in `payload`, up to the
664    /// length found in the return value.
665    fn decrypt_in_place<'a>(
666        &self,
667        packet_number: u64,
668        header: &[u8],
669        payload: &'a mut [u8],
670    ) -> Result<&'a [u8], Error>;
671
672    /// Tag length for the underlying AEAD algorithm
673    fn tag_len(&self) -> usize;
674}
675
676/// Packet protection keys for bidirectional 1-RTT communication
677pub struct PacketKeySet {
678    /// Encrypts outgoing packets
679    pub local: Box<dyn PacketKey>,
680    /// Decrypts incoming packets
681    pub remote: Box<dyn PacketKey>,
682}
683
684impl PacketKeySet {
685    fn new(secrets: &Secrets) -> Self {
686        let (local, remote) = secrets.local_remote();
687        let (version, alg, hkdf) = (secrets.version, secrets.quic, secrets.suite.hkdf_provider);
688        Self {
689            local: KeyBuilder::new(local, version, alg, hkdf).packet_key(),
690            remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(),
691        }
692    }
693}
694
695pub(crate) struct KeyBuilder<'a> {
696    expander: Box<dyn HkdfExpander>,
697    version: Version,
698    alg: &'a dyn Algorithm,
699}
700
701impl<'a> KeyBuilder<'a> {
702    pub(crate) fn new(
703        secret: &OkmBlock,
704        version: Version,
705        alg: &'a dyn Algorithm,
706        hkdf: &'a dyn Hkdf,
707    ) -> Self {
708        Self {
709            expander: hkdf.expander_for_okm(secret),
710            version,
711            alg,
712        }
713    }
714
715    /// Derive packet keys
716    pub(crate) fn packet_key(&self) -> Box<dyn PacketKey> {
717        let aead_key_len = self.alg.aead_key_len();
718        let packet_key = hkdf_expand_label_aead_key(
719            self.expander.as_ref(),
720            aead_key_len,
721            self.version.packet_key_label(),
722            &[],
723        );
724
725        let packet_iv =
726            hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]);
727        self.alg
728            .packet_key(packet_key, packet_iv)
729    }
730
731    /// Derive header protection keys
732    pub(crate) fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> {
733        let header_key = hkdf_expand_label_aead_key(
734            self.expander.as_ref(),
735            self.alg.aead_key_len(),
736            self.version.header_key_label(),
737            &[],
738        );
739        self.alg
740            .header_protection_key(header_key)
741    }
742}
743
744/// Complete set of keys used to communicate with the peer
745pub struct Keys {
746    /// Encrypts outgoing packets
747    pub local: DirectionalKeys,
748    /// Decrypts incoming packets
749    pub remote: DirectionalKeys,
750}
751
752impl Keys {
753    /// Construct keys for use with initial packets
754    pub fn initial(
755        version: Version,
756        suite: &'static Tls13CipherSuite,
757        quic: &'static dyn Algorithm,
758        client_dst_connection_id: &[u8],
759        side: Side,
760    ) -> Self {
761        const CLIENT_LABEL: &[u8] = b"client in";
762        const SERVER_LABEL: &[u8] = b"server in";
763        let salt = version.initial_salt();
764        let hs_secret = suite
765            .hkdf_provider
766            .extract_from_secret(Some(salt), client_dst_connection_id);
767
768        let secrets = Secrets {
769            version,
770            client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]),
771            server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]),
772            suite,
773            quic,
774            side,
775        };
776        Self::new(&secrets)
777    }
778
779    fn new(secrets: &Secrets) -> Self {
780        let (local, remote) = secrets.local_remote();
781        Self {
782            local: DirectionalKeys::new(secrets.suite, secrets.quic, local, secrets.version),
783            remote: DirectionalKeys::new(secrets.suite, secrets.quic, remote, secrets.version),
784        }
785    }
786}
787
788/// Key material for use in QUIC packet spaces
789///
790/// QUIC uses 4 different sets of keys (and progressive key updates for long-running connections):
791///
792/// * Initial: these can be created from [`Keys::initial()`]
793/// * 0-RTT keys: can be retrieved from [`ConnectionCommon::zero_rtt_keys()`]
794/// * Handshake: these are returned from [`ConnectionCommon::write_hs()`] after `ClientHello` and
795///   `ServerHello` messages have been exchanged
796/// * 1-RTT keys: these are returned from [`ConnectionCommon::write_hs()`] after the handshake is done
797///
798/// Once the 1-RTT keys have been exchanged, either side may initiate a key update. Progressive
799/// update keys can be obtained from the [`Secrets`] returned in [`KeyChange::OneRtt`]. Note that
800/// only packet keys are updated by key updates; header protection keys remain the same.
801#[allow(clippy::large_enum_variant)]
802pub enum KeyChange {
803    /// Keys for the handshake space
804    Handshake {
805        /// Header and packet keys for the handshake space
806        keys: Keys,
807    },
808    /// Keys for 1-RTT data
809    OneRtt {
810        /// Header and packet keys for 1-RTT data
811        keys: Keys,
812        /// Secrets to derive updated keys from
813        next: Secrets,
814    },
815}
816
817/// QUIC protocol version
818///
819/// Governs version-specific behavior in the TLS layer
820#[non_exhaustive]
821#[derive(Clone, Copy, Debug)]
822pub enum Version {
823    /// Draft versions 29, 30, 31 and 32
824    V1Draft,
825    /// First stable RFC
826    V1,
827    /// Anti-ossification variant of V1
828    V2,
829}
830
831impl Version {
832    fn initial_salt(self) -> &'static [u8; 20] {
833        match self {
834            Self::V1Draft => &[
835                // https://datatracker.ietf.org/doc/html/draft-ietf-quic-tls-32#section-5.2
836                0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61,
837                0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99,
838            ],
839            Self::V1 => &[
840                // https://www.rfc-editor.org/rfc/rfc9001.html#name-initial-secrets
841                0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
842                0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
843            ],
844            Self::V2 => &[
845                // https://www.ietf.org/archive/id/draft-ietf-quic-v2-10.html#name-initial-salt-2
846                0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
847                0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
848            ],
849        }
850    }
851
852    /// Key derivation label for packet keys.
853    pub(crate) fn packet_key_label(&self) -> &'static [u8] {
854        match self {
855            Self::V1Draft | Self::V1 => b"quic key",
856            Self::V2 => b"quicv2 key",
857        }
858    }
859
860    /// Key derivation label for packet "IV"s.
861    pub(crate) fn packet_iv_label(&self) -> &'static [u8] {
862        match self {
863            Self::V1Draft | Self::V1 => b"quic iv",
864            Self::V2 => b"quicv2 iv",
865        }
866    }
867
868    /// Key derivation for header keys.
869    pub(crate) fn header_key_label(&self) -> &'static [u8] {
870        match self {
871            Self::V1Draft | Self::V1 => b"quic hp",
872            Self::V2 => b"quicv2 hp",
873        }
874    }
875
876    fn key_update_label(&self) -> &'static [u8] {
877        match self {
878            Self::V1Draft | Self::V1 => b"quic ku",
879            Self::V2 => b"quicv2 ku",
880        }
881    }
882}
883
884impl Default for Version {
885    fn default() -> Self {
886        Self::V1
887    }
888}