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