clia_rustls_mod/
quic.rs

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