Skip to main content

rustls/
quic.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::ops::{Deref, DerefMut};
4use core::{fmt, mem};
5
6use pki_types::{DnsName, FipsStatus};
7
8use crate::TlsInputBuffer;
9use crate::client::ClientSide;
10pub use crate::common_state::Side;
11use crate::common_state::{CommonState, ConnectionOutputs, Protocol};
12use crate::conn::{
13    ConnectionCommon, KeyingMaterialExporter, MessageIter, MessageIterMode, SideCommonOutput,
14    SideData, StateMachine, VerifySidePeerIdentity,
15};
16use crate::crypto::VerifiedIdentity;
17use crate::crypto::cipher::{AeadKey, Iv, Payload};
18use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock};
19use crate::error::{ApiMisuse, Error};
20use crate::msgs::{Message, MessagePayload, ServerExtensionsInput, TransportParameters};
21use crate::server::{ChooseConfig, ClientHello, ServerConfig, ServerSide, ServerState};
22use crate::suites::SupportedCipherSuite;
23use crate::sync::Arc;
24use crate::tls13::Tls13CipherSuite;
25use crate::tls13::key_schedule::{
26    hkdf_expand_label, hkdf_expand_label_aead_key, hkdf_expand_label_block,
27};
28use crate::verify::ClientIdentity;
29
30/// A QUIC client or server connection.
31pub trait Connection: fmt::Debug + Deref<Target = ConnectionOutputs> {
32    /// Return the TLS-encoded transport parameters for the session's peer.
33    ///
34    /// While the transport parameters are technically available prior to the
35    /// completion of the handshake, they cannot be fully trusted until the
36    /// handshake completes, and reliance on them should be minimized.
37    /// However, any tampering with the parameters will cause the handshake
38    /// to fail.
39    fn quic_transport_parameters(&self) -> Option<&[u8]>;
40
41    /// Compute the keys for encrypting/decrypting 0-RTT packets, if available
42    fn zero_rtt_keys(&self) -> Option<DirectionalKeys>;
43
44    /// Consume unencrypted TLS handshake data.
45    ///
46    /// Handshake data obtained from separate encryption levels should be supplied in separate calls.
47    ///
48    /// How much of the `input` buffer is consumed is recorded by a call to
49    /// [`TlsInputBuffer::discard()`].  Unconsumed data should be presented again on the next call.
50    fn read_hs(&mut self, input: &mut dyn TlsInputBuffer) -> Result<(), Error>;
51
52    /// Obtain pending events that the caller should process.
53    ///
54    /// All pending events are returned as an iterator.
55    fn events(&mut self) -> impl Iterator<Item = QuicEvent>;
56
57    /// Returns true if the connection is currently performing the TLS handshake.
58    fn is_handshaking(&self) -> bool;
59}
60
61/// A QUIC client connection.
62pub struct ClientConnection {
63    inner: QuicCommon<ClientSide>,
64}
65
66impl ClientConnection {
67    /// Return the FIPS validation status of the connection.
68    pub fn fips(&self) -> FipsStatus {
69        self.inner.fips
70    }
71
72    /// Returns True if the server signalled it will process early data.
73    ///
74    /// If you sent early data and this returns false at the end of the
75    /// handshake then the server will not process the data.  This
76    /// is not an error, but you may wish to resend the data.
77    pub fn is_early_data_accepted(&self) -> bool {
78        self.inner
79            .common
80            .is_early_data_accepted()
81    }
82
83    /// Returns the number of TLS1.3 tickets that have been received.
84    pub fn tls13_tickets_received(&self) -> u32 {
85        self.inner
86            .common
87            .common
88            .recv
89            .tls13_tickets_received
90    }
91
92    /// Returns an object that can derive key material from the agreed connection secrets.
93    ///
94    /// See [RFC 5705][] for more details on what this is for.
95    ///
96    /// This function can be called at most once per connection.
97    ///
98    /// This function will error:
99    ///
100    /// - if called prior to the handshake completing; (check with
101    ///   [`CommonState::is_handshaking`] first).
102    /// - if called more than once per connection.
103    ///
104    /// [RFC 5705]: https://datatracker.ietf.org/doc/html/rfc5705
105    pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
106        self.inner.common.exporter()
107    }
108}
109
110impl Connection for ClientConnection {
111    fn quic_transport_parameters(&self) -> Option<&[u8]> {
112        self.inner.quic_transport_parameters()
113    }
114
115    fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
116        self.inner.zero_rtt_keys()
117    }
118
119    fn read_hs(&mut self, input: &mut dyn TlsInputBuffer) -> Result<(), Error> {
120        self.inner
121            .read_hs(input, MessageIterMode::All)
122    }
123
124    fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
125        self.inner.events()
126    }
127
128    fn is_handshaking(&self) -> bool {
129        self.inner.is_handshaking()
130    }
131}
132
133impl Deref for ClientConnection {
134    type Target = ConnectionOutputs;
135
136    fn deref(&self) -> &Self::Target {
137        &self.inner
138    }
139}
140
141impl fmt::Debug for ClientConnection {
142    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143        f.debug_struct("quic::ClientConnection")
144            .finish_non_exhaustive()
145    }
146}
147
148impl From<QuicCommon<ClientSide>> for ClientConnection {
149    fn from(inner: QuicCommon<ClientSide>) -> Self {
150        Self { inner }
151    }
152}
153
154/// A QUIC server connection.
155pub struct ServerConnection {
156    inner: QuicCommon<ServerSide>,
157}
158
159impl ServerConnection {
160    /// Make a new QUIC ServerConnection.
161    ///
162    /// This differs from `ServerConnection::new()` in that it takes an extra `params` argument,
163    /// which contains the TLS-encoded transport parameters to send.
164    pub fn new(
165        config: Arc<ServerConfig>,
166        version: Version,
167        params: Vec<u8>,
168    ) -> Result<Self, Error> {
169        check_server_config(&config)?;
170        let exts = ServerExtensionsInput {
171            transport_parameters: Some(match version {
172                Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
173            }),
174        };
175
176        let core = ConnectionCommon::for_server(config, exts, Protocol::Quic(version))?;
177        let inner = QuicCommon::new(
178            core,
179            Quic {
180                version,
181                ..Quic::default()
182            },
183        );
184        Ok(Self { inner })
185    }
186
187    /// Return the FIPS validation status of the connection.
188    pub fn fips(&self) -> FipsStatus {
189        self.inner.fips
190    }
191
192    /// Retrieves the server name, if any, used to select the certificate and
193    /// private key.
194    ///
195    /// This returns `None` until some time after the client's server name indication
196    /// (SNI) extension value is processed during the handshake. It will never be
197    /// `None` when the connection is ready to send or process application data,
198    /// unless the client does not support SNI.
199    ///
200    /// This is useful for application protocols that need to enforce that the
201    /// server name matches an application layer protocol hostname. For
202    /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
203    /// every request on a connection to match the hostname in the SNI extension
204    /// when the client provides the SNI extension.
205    ///
206    /// The server name is also used to match sessions during session resumption.
207    pub fn server_name(&self) -> Option<&DnsName<'_>> {
208        self.inner.common.side.server_name()
209    }
210
211    /// Set the resumption data to embed in future resumption tickets supplied to the client.
212    ///
213    /// Defaults to the empty byte string. Must be less than 2^15 bytes to allow room for other
214    /// data. Should be called while `is_handshaking` returns true to ensure all transmitted
215    /// resumption tickets are affected (otherwise an error will be returned).
216    ///
217    /// Integrity will be assured by rustls, but the data will be visible to the client. If secrecy
218    /// from the client is desired, encrypt the data separately.
219    pub fn set_resumption_data(&mut self, resumption_data: &[u8]) -> Result<(), Error> {
220        assert!(resumption_data.len() < 2usize.pow(15));
221        match &mut self.inner.common.state {
222            Ok(st) => st.set_resumption_data(resumption_data),
223            Err(e) => Err(e.clone()),
224        }
225    }
226
227    /// Retrieves the resumption data supplied by the client, if any.
228    ///
229    /// Returns `Some` if and only if a valid resumption ticket has been received from the client.
230    pub fn received_resumption_data(&self) -> Option<&[u8]> {
231        self.inner
232            .common
233            .side
234            .received_resumption_data()
235    }
236
237    /// Returns an object that can derive key material from the agreed connection secrets.
238    ///
239    /// See [RFC 5705][] for more details on what this is for.
240    ///
241    /// This function can be called at most once per connection.
242    ///
243    /// This function will error:
244    ///
245    /// - if called prior to the handshake completing; (check with
246    ///   [`CommonState::is_handshaking`] first).
247    /// - if called more than once per connection.
248    ///
249    /// [RFC 5705]: https://datatracker.ietf.org/doc/html/rfc5705
250    pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
251        self.inner.common.exporter()
252    }
253}
254
255impl Connection for ServerConnection {
256    fn quic_transport_parameters(&self) -> Option<&[u8]> {
257        self.inner.quic_transport_parameters()
258    }
259
260    fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
261        self.inner.zero_rtt_keys()
262    }
263
264    fn read_hs(&mut self, input: &mut dyn TlsInputBuffer) -> Result<(), Error> {
265        self.inner
266            .read_hs(input, MessageIterMode::All)
267    }
268
269    fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
270        self.inner.events()
271    }
272
273    fn is_handshaking(&self) -> bool {
274        self.inner.is_handshaking()
275    }
276}
277
278impl Deref for ServerConnection {
279    type Target = ConnectionOutputs;
280
281    fn deref(&self) -> &Self::Target {
282        &self.inner
283    }
284}
285
286impl fmt::Debug for ServerConnection {
287    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288        f.debug_struct("quic::ServerConnection")
289            .finish_non_exhaustive()
290    }
291}
292
293/// An in-progress TLS server handshake.
294#[non_exhaustive]
295#[derive(Debug)]
296pub enum ServerHandshake {
297    /// More data needs to be received to make progress.
298    NeedsInput(NeedsInput),
299
300    /// A complete `ClientHello` has been received.
301    ///
302    /// The handshake can be progressed by choosing a [`ServerConfig`] based on
303    /// [`Accepted::client_hello()`] and providing it to [`Accepted::choose_config()`].
304    Accepted(Accepted),
305
306    /// The client's presented identity must be verified.
307    ///
308    /// See [`VerifyClientIdentity`] for how to proceed.
309    VerifyClientIdentity(VerifyClientIdentity),
310
311    /// The handshake is complete.
312    Complete(ServerConnection),
313}
314
315impl ServerHandshake {
316    /// Creates a new QUIC [`ServerHandshake`] via the payload of the [`ServerHandshake::NeedsInput`] variant.
317    ///
318    /// It is a fundamental fact of server TLS connections that the server reads first; this is reflected
319    /// in the returned type.
320    ///
321    /// You may wrap this in the [`ServerHandshake::NeedsInput`] variant to generalise the type to a
322    /// [`ServerHandshake`].
323    ///
324    /// The returned object should be fed data from a single potential client.
325    pub fn start(version: Version) -> NeedsInput {
326        NeedsInput {
327            inner: QuicCommon::new(
328                ConnectionCommon::for_acceptor(Protocol::Quic(version)),
329                Quic {
330                    version,
331                    ..Quic::default()
332                },
333            ),
334        }
335    }
336}
337
338impl TryFrom<QuicCommon<ServerSide>> for ServerHandshake {
339    type Error = Error;
340
341    fn try_from(mut inner: QuicCommon<ServerSide>) -> Result<Self, Error> {
342        const MISUSED: Error = Error::Unreachable("forgot to restore state");
343
344        Ok(match mem::replace(&mut inner.common.state, Err(MISUSED))? {
345            ServerState::ChooseConfig(choose_config) => Self::Accepted(Accepted {
346                inner,
347                choose_config,
348            }),
349
350            ServerState::VerifyClientIdentity(verify) => {
351                Self::VerifyClientIdentity(VerifyClientIdentity { inner, verify })
352            }
353
354            state if state.is_traffic() => {
355                inner.common.state = Ok(state);
356                Self::Complete(ServerConnection { inner })
357            }
358
359            state => {
360                inner.common.state = Ok(state);
361                Self::NeedsInput(NeedsInput { inner })
362            }
363        })
364    }
365}
366
367/// More data needs to be processed to make progress.
368///
369/// Provide the data to [`Self::process()`].
370///
371/// This type dereferences to [`ConnectionOutputs`]. Individual outputs are `None`
372/// until they are learned during the handshake.
373pub struct NeedsInput {
374    inner: QuicCommon<ServerSide>,
375}
376
377impl NeedsInput {
378    /// Return the TLS-encoded transport parameters received from the peer.
379    ///
380    /// While the transport parameters are available before the handshake completes,
381    /// they cannot be fully trusted until then. Reliance on them should be minimized.
382    /// Any tampering with the parameters will cause the handshake to fail.
383    pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
384        self.inner.quic_transport_parameters()
385    }
386
387    /// Compute the keys for decrypting 0-RTT packets, if available.
388    pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
389        self.inner.zero_rtt_keys()
390    }
391
392    /// Retrieves the server name supplied by the client, if any.
393    pub fn server_name(&self) -> Option<&DnsName<'_>> {
394        self.inner.common.side.server_name()
395    }
396
397    /// Progress the handshake by receiving further unencrypted TLS handshake data.
398    ///
399    /// The input should be ordered QUIC CRYPTO stream data for one encryption level.
400    ///
401    /// Handshake data obtained from separate encryption levels should be supplied in separate calls.
402    ///
403    /// How much of the `input` buffer is consumed is recorded by a call to
404    /// [`TlsInputBuffer::discard()`].  Unconsumed data should be presented again on the next call.
405    ///
406    /// An error from this function is fatal to the connection, as it consumes the [`NeedsInput`]
407    /// object.
408    ///
409    /// On success, this returns:
410    ///
411    /// - a [`ServerHandshake::NeedsInput`] if more data is required.
412    /// - a [`ServerHandshake::Accepted`] if a whole `ClientHello` has been received,
413    ///   and a choice of [`ServerConfig`] is required to continue.
414    /// - a [`ServerHandshake::Complete`] if the handshake is complete.
415    ///
416    /// `output` has any resulting handshake messages or key changes appended to it.
417    pub fn process(
418        mut self,
419        input: &mut dyn TlsInputBuffer,
420        output: &mut Vec<QuicEvent>,
421    ) -> Result<ServerHandshake, Error> {
422        self.inner
423            .read_hs(input, MessageIterMode::Handshake)?;
424        output.extend(self.inner.events());
425        ServerHandshake::try_from(self.inner)
426    }
427}
428
429impl Deref for NeedsInput {
430    type Target = ConnectionOutputs;
431
432    fn deref(&self) -> &Self::Target {
433        &self.inner
434    }
435}
436
437impl fmt::Debug for NeedsInput {
438    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439        f.debug_struct("quic::NeedsInput")
440            .finish_non_exhaustive()
441    }
442}
443
444/// Represents that a `ClientHello` message has been received.
445///
446/// The handshake can be progressed by choosing a [`ServerConfig`] based on
447/// [`Accepted::client_hello()`] and providing it to [`Accepted::choose_config()`].
448pub struct Accepted {
449    // invariant: `inner.core.state` is `Err(_)` and requires restoring
450    inner: QuicCommon<ServerSide>,
451    choose_config: Box<ChooseConfig>,
452}
453
454impl Accepted {
455    /// Get the [`ClientHello`] for this connection.
456    pub fn client_hello(&self) -> ClientHello<'_> {
457        self.choose_config.client_hello()
458    }
459
460    /// Choose a [`ServerConfig`] to progress the handshake.
461    ///
462    /// Resolves an [`Accepted`], providing the [`ServerConfig`] that should be used for
463    /// the session, and the TLS-encoded QUIC transport parameters to send.
464    ///
465    /// Returns an error if configuration-dependent validation of the received
466    /// `ClientHello` message fails.
467    ///
468    /// Events are appended to `output`.
469    pub fn choose_config(
470        mut self,
471        config: Arc<ServerConfig>,
472        params: Vec<u8>,
473        output: &mut Vec<QuicEvent>,
474    ) -> Result<ServerHandshake, Error> {
475        check_server_config(&config)?;
476
477        let mut tls = Vec::new();
478        self.inner.common.accepted(
479            self.choose_config,
480            ServerExtensionsInput {
481                transport_parameters: Some(match self.inner.quic.version {
482                    Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
483                }),
484            },
485            Some(&mut self.inner.quic),
486            config,
487            &mut tls,
488        )?;
489
490        // In QUIC mode, handshake output is emitted via `QuicEvent`s, not `tls`.
491        debug_assert!(tls.is_empty());
492        output.extend(self.inner.events());
493
494        ServerHandshake::try_from(self.inner)
495    }
496}
497
498impl fmt::Debug for Accepted {
499    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
500        f.debug_struct("quic::Accepted")
501            .finish_non_exhaustive()
502    }
503}
504
505fn check_server_config(config: &ServerConfig) -> Result<(), Error> {
506    let suites = &config.provider.tls13_cipher_suites;
507    if suites.is_empty() {
508        return Err(ApiMisuse::QuicRequiresTls13Support.into());
509    }
510
511    if !suites
512        .iter()
513        .any(|scs| scs.quic.is_some())
514    {
515        return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
516    }
517
518    if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff {
519        return Err(ApiMisuse::QuicRestrictsMaxEarlyDataSize.into());
520    }
521
522    Ok(())
523}
524
525/// The client's presented identity must be verified.
526///
527/// The caller has three choices:
528///
529/// - Call [`Self::with_config()`].  This calls [`ClientVerifier::verify_identity()`][]
530///   synchronously.
531///
532/// - Call [`Self::presented_identity()`] to obtain the peer's presented identity,
533///   verify that outside the library (perhaps asynchronously), and then continue the handshake with
534///   [`Self::continue_with()`].
535///
536///   If the verification fails, the error can be passed into [`Self::continue_with()`] to follow
537///   a uniform error handling path.
538///
539/// - Abandon the handshake by discarding this object.
540///
541/// The returned object is a further [`ServerHandshake`].  Commonly this will be a
542/// [`ServerHandshake::NeedsInput`] which will accept and process further data.
543///
544/// [`ClientVerifier::verify_identity()`]: crate::verify::ClientVerifier::verify_identity
545pub struct VerifyClientIdentity {
546    // invariant: `inner.state` is `Err(_)` and requires restoring
547    inner: QuicCommon<ServerSide>,
548    verify: Box<dyn VerifySidePeerIdentity<ServerSide>>,
549}
550
551impl VerifyClientIdentity {
552    /// Progress the handshake by calling the pre-configured certificate verification trait.
553    pub fn with_config(self) -> Result<ServerHandshake, Error> {
554        let verified = self.verify.verify_with_config();
555        self.continue_with(verified)
556    }
557
558    /// Progress the handshake by incorporating the result of an external verification.
559    ///
560    /// If `verification_result` is an error, this error is returned and the handshake terminates.
561    pub fn continue_with(
562        self,
563        verification_result: Result<VerifiedIdentity<'static>, Error>,
564    ) -> Result<ServerHandshake, Error> {
565        let Self { mut inner, verify } = self;
566
567        let mut tls = Vec::new();
568        let result = verification_result.and_then(|verified| {
569            verify.continue_with(
570                verified,
571                &mut SideCommonOutput {
572                    side: &mut inner.common.side,
573                    quic: Some(&mut inner.quic),
574                    common: &mut inner.common.common,
575                    tls: &mut tls,
576                },
577            )
578        });
579
580        // In QUIC mode, handshake output is emitted via `QuicEvent`s, not `tls`.
581        debug_assert!(tls.is_empty());
582
583        inner.common.state = result;
584        ServerHandshake::try_from(inner)
585    }
586
587    /// Inspect the identity that the client has provided.
588    pub fn presented_identity(&self) -> Result<ClientIdentity<'static, '_>, Error> {
589        self.verify.presented_identity()
590    }
591}
592
593impl fmt::Debug for VerifyClientIdentity {
594    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
595        f.debug_struct("VerifyClientIdentity")
596            .finish_non_exhaustive()
597    }
598}
599
600/// QUIC events that should be handled by the caller.
601#[expect(clippy::large_enum_variant)]
602#[derive(Debug)]
603#[non_exhaustive]
604pub enum QuicEvent {
605    /// These bytes should be handled as an unencrypted TLS handshake message.
606    Message(Vec<u8>),
607
608    /// The key material should be changed.
609    KeyChange(KeyChange),
610}
611
612/// A shared interface for QUIC connections.
613pub(crate) struct QuicCommon<Side: SideData> {
614    common: ConnectionCommon<Side>,
615    quic: Quic,
616}
617
618impl<Side: SideData> QuicCommon<Side> {
619    pub(crate) fn new(common: ConnectionCommon<Side>, quic: Quic) -> Self {
620        Self { common, quic }
621    }
622
623    fn quic_transport_parameters(&self) -> Option<&[u8]> {
624        self.quic
625            .params
626            .as_ref()
627            .map(|v| v.as_ref())
628    }
629
630    fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
631        let suite = self
632            .common
633            .common
634            .negotiated_cipher_suite()
635            .and_then(|suite| match suite {
636                SupportedCipherSuite::Tls13(suite) => Some(suite),
637                _ => None,
638            })?;
639
640        let suite = Suite {
641            inner: suite,
642            quic: suite.quic?,
643        };
644
645        Some(DirectionalKeys::new(
646            suite,
647            self.quic.early_secret.as_ref()?,
648            self.quic.version,
649        ))
650    }
651
652    fn read_hs(
653        &mut self,
654        input: &mut dyn TlsInputBuffer,
655        mode: MessageIterMode,
656    ) -> Result<(), Error> {
657        self.common
658            .common
659            .recv
660            .deframer
661            .input_quic(input.slice_mut())?;
662
663        let mut tls = Vec::new();
664        let mut iter = MessageIter::new(
665            input,
666            &mut tls,
667            Some(&mut self.quic),
668            &mut self.common,
669            mode,
670        );
671
672        let result = match iter.next(false) {
673            Some(Ok(_)) | None => Ok(()),
674            Some(Err(e)) => Err(e),
675        };
676
677        input.discard(
678            self.common
679                .common
680                .recv
681                .deframer
682                .take_discard(),
683        );
684
685        result
686    }
687
688    fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
689        self.quic.events()
690    }
691}
692
693impl<Side: SideData> Deref for QuicCommon<Side> {
694    type Target = CommonState;
695
696    fn deref(&self) -> &Self::Target {
697        &self.common.common
698    }
699}
700
701impl<Side: SideData> DerefMut for QuicCommon<Side> {
702    fn deref_mut(&mut self) -> &mut Self::Target {
703        &mut self.common.common
704    }
705}
706
707#[derive(Default)]
708pub(crate) struct Quic {
709    pub(crate) version: Version,
710    /// QUIC transport parameters received from the peer during the handshake
711    pub(crate) params: Option<Vec<u8>>,
712    pub(crate) events: Vec<QuicEvent>,
713    pub(crate) early_secret: Option<OkmBlock>,
714}
715
716impl Quic {
717    pub(crate) fn send_msg(&mut self, m: Message<'_>, _must_encrypt: bool) {
718        if let MessagePayload::Alert(_) = m.payload {
719            // alerts are sent out-of-band in QUIC mode
720            return;
721        }
722
723        debug_assert!(
724            matches!(
725                m.payload,
726                MessagePayload::Handshake { .. } | MessagePayload::HandshakeFlight(_)
727            ),
728            "QUIC uses TLS for the cryptographic handshake only"
729        );
730        let mut bytes = Vec::new();
731        m.payload.encode(&mut bytes);
732        self.events
733            .push(QuicEvent::Message(bytes));
734    }
735
736    pub(crate) fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
737        mem::take(&mut self.events).into_iter()
738    }
739}
740
741impl QuicOutput for Quic {
742    fn transport_parameters(&mut self, params: Vec<u8>) {
743        self.params = Some(params);
744    }
745
746    fn early_secret(&mut self, secret: Option<OkmBlock>) {
747        self.early_secret = secret;
748    }
749
750    fn handshake_secrets(
751        &mut self,
752        client_secret: OkmBlock,
753        server_secret: OkmBlock,
754        suite: Suite,
755        side: Side,
756    ) {
757        self.events
758            .push(QuicEvent::KeyChange(KeyChange::Handshake {
759                keys: Keys::new(&Secrets::new(
760                    client_secret,
761                    server_secret,
762                    suite,
763                    side,
764                    self.version,
765                )),
766            }));
767    }
768
769    fn traffic_secrets(
770        &mut self,
771        client_secret: OkmBlock,
772        server_secret: OkmBlock,
773        suite: Suite,
774        side: Side,
775    ) {
776        let mut secrets = Secrets::new(client_secret, server_secret, suite, side, self.version);
777        let keys = Keys::new(&secrets);
778        secrets.update();
779        self.events
780            .push(QuicEvent::KeyChange(KeyChange::OneRtt {
781                keys,
782                next: secrets,
783            }));
784    }
785
786    fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
787        self.send_msg(m, must_encrypt);
788    }
789}
790
791pub(crate) trait QuicOutput {
792    fn transport_parameters(&mut self, params: Vec<u8>);
793
794    fn early_secret(&mut self, secret: Option<OkmBlock>);
795
796    fn handshake_secrets(
797        &mut self,
798        client_secret: OkmBlock,
799        server_secret: OkmBlock,
800        suite: Suite,
801        side: Side,
802    );
803
804    fn traffic_secrets(
805        &mut self,
806        client_secret: OkmBlock,
807        server_secret: OkmBlock,
808        suite: Suite,
809        side: Side,
810    );
811
812    fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool);
813}
814
815/// Secrets used to encrypt/decrypt traffic
816#[derive(Clone)]
817pub struct Secrets {
818    /// Secret used to encrypt packets transmitted by the client
819    pub(crate) client: OkmBlock,
820    /// Secret used to encrypt packets transmitted by the server
821    pub(crate) server: OkmBlock,
822    /// Cipher suite used with these secrets
823    suite: Suite,
824    side: Side,
825    version: Version,
826}
827
828impl Secrets {
829    pub(crate) fn new(
830        client: OkmBlock,
831        server: OkmBlock,
832        suite: Suite,
833        side: Side,
834        version: Version,
835    ) -> Self {
836        Self {
837            client,
838            server,
839            suite,
840            side,
841            version,
842        }
843    }
844
845    /// Derive the next set of packet keys
846    pub fn next_packet_keys(&mut self) -> PacketKeySet {
847        let keys = PacketKeySet::new(self);
848        self.update();
849        keys
850    }
851
852    pub(crate) fn update(&mut self) {
853        self.client = hkdf_expand_label_block(
854            self.suite
855                .inner
856                .hkdf_provider
857                .expander_for_okm(&self.client)
858                .as_ref(),
859            self.version.key_update_label(),
860            &[],
861        );
862        self.server = hkdf_expand_label_block(
863            self.suite
864                .inner
865                .hkdf_provider
866                .expander_for_okm(&self.server)
867                .as_ref(),
868            self.version.key_update_label(),
869            &[],
870        );
871    }
872
873    fn local_remote(&self) -> (&OkmBlock, &OkmBlock) {
874        match self.side {
875            Side::Client => (&self.client, &self.server),
876            Side::Server => (&self.server, &self.client),
877        }
878    }
879}
880
881/// Keys used to communicate in a single direction
882#[expect(clippy::exhaustive_structs)]
883pub struct DirectionalKeys {
884    /// Encrypts or decrypts a packet's headers
885    pub header: Box<dyn HeaderProtectionKey>,
886    /// Encrypts or decrypts the payload of a packet
887    pub packet: Box<dyn PacketKey>,
888}
889
890impl DirectionalKeys {
891    pub(crate) fn new(suite: Suite, secret: &OkmBlock, version: Version) -> Self {
892        let builder = KeyBuilder::new(secret, version, suite.quic, suite.inner.hkdf_provider);
893        Self {
894            header: builder.header_protection_key(),
895            packet: builder.packet_key(),
896        }
897    }
898}
899
900/// All AEADs we support have 16-byte tags.
901const TAG_LEN: usize = 16;
902
903/// Authentication tag from an AEAD seal operation.
904pub struct Tag([u8; TAG_LEN]);
905
906impl From<&[u8]> for Tag {
907    fn from(value: &[u8]) -> Self {
908        let mut array = [0u8; TAG_LEN];
909        array.copy_from_slice(value);
910        Self(array)
911    }
912}
913
914impl AsRef<[u8]> for Tag {
915    fn as_ref(&self) -> &[u8] {
916        &self.0
917    }
918}
919
920/// How a `Tls13CipherSuite` generates `PacketKey`s and `HeaderProtectionKey`s.
921pub trait Algorithm: Send + Sync {
922    /// Produce a `PacketKey` encrypter/decrypter for this suite.
923    ///
924    /// `suite` is the entire suite this `Algorithm` appeared in.
925    /// `key` and `iv` is the key material to use.
926    fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn PacketKey>;
927
928    /// Produce a `HeaderProtectionKey` encrypter/decrypter for this suite.
929    ///
930    /// `key` is the key material, which is `aead_key_len()` bytes in length.
931    fn header_protection_key(&self, key: AeadKey) -> Box<dyn HeaderProtectionKey>;
932
933    /// The length in bytes of keys for this Algorithm.
934    ///
935    /// This controls the size of `AeadKey`s presented to `packet_key()` and `header_protection_key()`.
936    fn aead_key_len(&self) -> usize;
937
938    /// The FIPS validation status of this algorithm.
939    fn fips(&self) -> FipsStatus {
940        FipsStatus::Unvalidated
941    }
942}
943
944/// A QUIC header protection key
945pub trait HeaderProtectionKey: Send + Sync {
946    /// Adds QUIC Header Protection.
947    ///
948    /// `sample` must contain the sample of encrypted payload; see
949    /// [Header Protection Sample].
950    ///
951    /// `first` must reference the first byte of the header, referred to as
952    /// `packet[0]` in [Header Protection Application].
953    ///
954    /// `packet_number` must reference the Packet Number field; this is
955    /// `packet[pn_offset:pn_offset+pn_length]` in [Header Protection Application].
956    ///
957    /// Returns an error without modifying anything if `sample` is not
958    /// the correct length (see [Header Protection Sample] and [`Self::sample_len()`]),
959    /// or `packet_number` is longer than allowed (see [Packet Number Encoding and Decoding]).
960    ///
961    /// Otherwise, `first` and `packet_number` will have the header protection added.
962    ///
963    /// [Header Protection Application]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.1
964    /// [Header Protection Sample]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.2
965    /// [Packet Number Encoding and Decoding]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.1
966    fn encrypt_in_place(
967        &self,
968        sample: &[u8],
969        first: &mut u8,
970        packet_number: &mut [u8],
971    ) -> Result<(), Error>;
972
973    /// Removes QUIC Header Protection.
974    ///
975    /// `sample` must contain the sample of encrypted payload; see
976    /// [Header Protection Sample].
977    ///
978    /// `first` must reference the first byte of the header, referred to as
979    /// `packet[0]` in [Header Protection Application].
980    ///
981    /// `packet_number` must reference the Packet Number field; this is
982    /// `packet[pn_offset:pn_offset+pn_length]` in [Header Protection Application].
983    ///
984    /// Returns an error without modifying anything if `sample` is not
985    /// the correct length (see [Header Protection Sample] and [`Self::sample_len()`]),
986    /// or `packet_number` is longer than allowed (see
987    /// [Packet Number Encoding and Decoding]).
988    ///
989    /// Otherwise, `first` and `packet_number` will have the header protection removed.
990    ///
991    /// [Header Protection Application]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.1
992    /// [Header Protection Sample]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.2
993    /// [Packet Number Encoding and Decoding]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.1
994    fn decrypt_in_place(
995        &self,
996        sample: &[u8],
997        first: &mut u8,
998        packet_number: &mut [u8],
999    ) -> Result<(), Error>;
1000
1001    /// Expected sample length for the key's algorithm
1002    fn sample_len(&self) -> usize;
1003}
1004
1005/// Keys to encrypt or decrypt the payload of a packet
1006pub trait PacketKey: Send + Sync {
1007    /// Encrypt a QUIC packet
1008    ///
1009    /// Takes a `packet_number` and optional `path_id`, used to derive the nonce; the packet
1010    /// `header`, which is used as the additional authenticated data; and the `payload`. The
1011    /// authentication tag is returned if encryption succeeds.
1012    ///
1013    /// Fails if and only if the payload is longer than allowed by the cipher suite's AEAD algorithm.
1014    ///
1015    /// When provided, the `path_id` is used for multipath encryption as described in
1016    /// <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-15.html#section-2.4>.
1017    fn encrypt_in_place(
1018        &self,
1019        packet_number: u64,
1020        header: &[u8],
1021        payload: &mut [u8],
1022        path_id: Option<u32>,
1023    ) -> Result<Tag, Error>;
1024
1025    /// Decrypt a QUIC packet
1026    ///
1027    /// Takes a `packet_number` and optional `path_id`, used to derive the nonce; the packet
1028    /// `header`, which is used as the additional authenticated data, and the `payload`, which
1029    /// includes the authentication tag.
1030    ///
1031    /// On success, returns the slice of `payload` containing the decrypted data.
1032    ///
1033    /// When provided, the `path_id` is used for multipath encryption as described in
1034    /// <https://www.ietf.org/archive/id/draft-ietf-quic-multipath-15.html#section-2.4>.
1035    fn decrypt_in_place<'a>(
1036        &self,
1037        packet_number: u64,
1038        header: &[u8],
1039        payload: &'a mut [u8],
1040        path_id: Option<u32>,
1041    ) -> Result<&'a [u8], Error>;
1042
1043    /// Tag length for the underlying AEAD algorithm
1044    fn tag_len(&self) -> usize;
1045
1046    /// Number of QUIC packets that can be safely encrypted with a single key of this type.
1047    ///
1048    /// Once a `PacketKey` produced for this suite has encrypted more than
1049    /// `confidentiality_limit` packets, an attacker gains an advantage in distinguishing it
1050    /// from an ideal pseudorandom permutation (PRP).
1051    ///
1052    /// This is to be set on the assumption that packets are maximally sized --
1053    /// 2 ** 16. For non-QUIC TCP connections see [`CipherSuiteCommon::confidentiality_limit`][csc-limit].
1054    ///
1055    /// [csc-limit]: crate::crypto::CipherSuiteCommon::confidentiality_limit
1056    fn confidentiality_limit(&self) -> u64;
1057
1058    /// Number of QUIC packets that can be safely decrypted with a single key of this type
1059    ///
1060    /// Once a `PacketKey` produced for this suite has failed to decrypt `integrity_limit`
1061    /// packets, an attacker gains an advantage in forging packets.
1062    ///
1063    /// This is not relevant for TLS over TCP (which is also implemented in this crate)
1064    /// because a single failed decryption is fatal to the connection.
1065    /// However, this quantity is used by QUIC.
1066    fn integrity_limit(&self) -> u64;
1067}
1068
1069/// Packet protection keys for bidirectional 1-RTT communication
1070#[expect(clippy::exhaustive_structs)]
1071pub struct PacketKeySet {
1072    /// Encrypts outgoing packets
1073    pub local: Box<dyn PacketKey>,
1074    /// Decrypts incoming packets
1075    pub remote: Box<dyn PacketKey>,
1076}
1077
1078impl PacketKeySet {
1079    fn new(secrets: &Secrets) -> Self {
1080        let (local, remote) = secrets.local_remote();
1081        let (version, alg, hkdf) = (
1082            secrets.version,
1083            secrets.suite.quic,
1084            secrets.suite.inner.hkdf_provider,
1085        );
1086
1087        Self {
1088            local: KeyBuilder::new(local, version, alg, hkdf).packet_key(),
1089            remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(),
1090        }
1091    }
1092}
1093
1094/// Helper for building QUIC packet and header protection keys
1095pub struct KeyBuilder<'a> {
1096    expander: Box<dyn HkdfExpander>,
1097    version: Version,
1098    alg: &'a dyn Algorithm,
1099}
1100
1101impl<'a> KeyBuilder<'a> {
1102    /// Create a new KeyBuilder
1103    pub fn new(
1104        secret: &OkmBlock,
1105        version: Version,
1106        alg: &'a dyn Algorithm,
1107        hkdf: &'a dyn Hkdf,
1108    ) -> Self {
1109        Self {
1110            expander: hkdf.expander_for_okm(secret),
1111            version,
1112            alg,
1113        }
1114    }
1115
1116    /// Derive packet keys
1117    pub fn packet_key(&self) -> Box<dyn PacketKey> {
1118        let aead_key_len = self.alg.aead_key_len();
1119        let packet_key = hkdf_expand_label_aead_key(
1120            self.expander.as_ref(),
1121            aead_key_len,
1122            self.version.packet_key_label(),
1123            &[],
1124        );
1125
1126        let packet_iv =
1127            hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]);
1128        self.alg
1129            .packet_key(packet_key, packet_iv)
1130    }
1131
1132    /// Derive header protection keys
1133    pub fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> {
1134        let header_key = hkdf_expand_label_aead_key(
1135            self.expander.as_ref(),
1136            self.alg.aead_key_len(),
1137            self.version.header_key_label(),
1138            &[],
1139        );
1140        self.alg
1141            .header_protection_key(header_key)
1142    }
1143}
1144
1145/// Produces QUIC initial keys from a TLS 1.3 ciphersuite and a QUIC key generation algorithm.
1146#[non_exhaustive]
1147#[derive(Clone, Copy)]
1148pub struct Suite {
1149    /// The TLS 1.3 ciphersuite used to derive keys.
1150    pub inner: &'static Tls13CipherSuite,
1151    /// The QUIC key generation algorithm used to derive keys.
1152    pub quic: &'static dyn Algorithm,
1153}
1154
1155impl Suite {
1156    /// Produce a set of initial keys given the connection ID, side and version
1157    pub fn keys(&self, client_dst_connection_id: &[u8], side: Side, version: Version) -> Keys {
1158        Keys::initial(version, *self, client_dst_connection_id, side)
1159    }
1160}
1161
1162impl TryFrom<&'static Tls13CipherSuite> for Suite {
1163    type Error = ApiMisuse;
1164
1165    fn try_from(suite: &'static Tls13CipherSuite) -> Result<Self, Self::Error> {
1166        Ok(Self {
1167            inner: suite,
1168            quic: suite
1169                .quic
1170                .ok_or(ApiMisuse::NoQuicCompatibleCipherSuites)?,
1171        })
1172    }
1173}
1174
1175impl fmt::Debug for Suite {
1176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1177        f.debug_struct("Suite")
1178            .field("inner", &self.inner)
1179            .finish_non_exhaustive()
1180    }
1181}
1182
1183/// Complete set of keys used to communicate with the peer
1184#[expect(clippy::exhaustive_structs)]
1185pub struct Keys {
1186    /// Encrypts outgoing packets
1187    pub local: DirectionalKeys,
1188    /// Decrypts incoming packets
1189    pub remote: DirectionalKeys,
1190}
1191
1192impl Keys {
1193    /// Construct keys for use with initial packets
1194    pub fn initial(
1195        version: Version,
1196        suite: Suite,
1197        client_dst_connection_id: &[u8],
1198        side: Side,
1199    ) -> Self {
1200        const CLIENT_LABEL: &[u8] = b"client in";
1201        const SERVER_LABEL: &[u8] = b"server in";
1202        let salt = version.initial_salt();
1203        let hs_secret = suite
1204            .inner
1205            .hkdf_provider
1206            .extract_from_secret(Some(salt), client_dst_connection_id);
1207
1208        let secrets = Secrets {
1209            client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]),
1210            server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]),
1211            suite,
1212            side,
1213            version,
1214        };
1215
1216        Self::new(&secrets)
1217    }
1218
1219    fn new(secrets: &Secrets) -> Self {
1220        let (local, remote) = secrets.local_remote();
1221        Self {
1222            local: DirectionalKeys::new(secrets.suite, local, secrets.version),
1223            remote: DirectionalKeys::new(secrets.suite, remote, secrets.version),
1224        }
1225    }
1226}
1227
1228/// Key material for use in QUIC packet spaces
1229///
1230/// QUIC uses 4 different sets of keys (and progressive key updates for long-running connections):
1231///
1232/// * Initial: these can be created from [`Keys::initial()`]
1233/// * 0-RTT keys: can be retrieved from [`Connection::zero_rtt_keys()`]
1234/// * Handshake: these are returned from [`Connection::events()`] after `ClientHello` and
1235///   `ServerHello` messages have been exchanged
1236/// * 1-RTT keys: these are returned from [`Connection::events()`] after the handshake is done
1237///
1238/// Once the 1-RTT keys have been exchanged, either side may initiate a key update. Progressive
1239/// update keys can be obtained from the [`Secrets`] returned in [`KeyChange::OneRtt`]. Note that
1240/// only packet keys are updated by key updates; header protection keys remain the same.
1241#[expect(clippy::exhaustive_enums)]
1242pub enum KeyChange {
1243    /// Keys for the handshake space
1244    Handshake {
1245        /// Header and packet keys for the handshake space
1246        keys: Keys,
1247    },
1248    /// Keys for 1-RTT data
1249    OneRtt {
1250        /// Header and packet keys for 1-RTT data
1251        keys: Keys,
1252        /// Secrets to derive updated keys from
1253        next: Secrets,
1254    },
1255}
1256
1257impl fmt::Debug for KeyChange {
1258    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1259        match self {
1260            Self::Handshake { .. } => f
1261                .debug_struct("Handshake")
1262                .finish_non_exhaustive(),
1263            Self::OneRtt { .. } => f
1264                .debug_struct("OneRtt")
1265                .finish_non_exhaustive(),
1266        }
1267    }
1268}
1269
1270/// QUIC protocol version
1271///
1272/// Governs version-specific behavior in the TLS layer
1273#[non_exhaustive]
1274#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
1275pub enum Version {
1276    /// First stable RFC
1277    #[default]
1278    V1,
1279    /// Anti-ossification variant of V1
1280    V2,
1281}
1282
1283impl Version {
1284    fn initial_salt(self) -> &'static [u8; 20] {
1285        match self {
1286            Self::V1 => &[
1287                // https://www.rfc-editor.org/rfc/rfc9001.html#name-initial-secrets
1288                0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
1289                0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
1290            ],
1291            Self::V2 => &[
1292                // https://tools.ietf.org/html/rfc9369.html#name-initial-salt
1293                0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
1294                0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
1295            ],
1296        }
1297    }
1298
1299    /// Key derivation label for packet keys.
1300    pub(crate) fn packet_key_label(&self) -> &'static [u8] {
1301        match self {
1302            Self::V1 => b"quic key",
1303            Self::V2 => b"quicv2 key",
1304        }
1305    }
1306
1307    /// Key derivation label for packet "IV"s.
1308    pub(crate) fn packet_iv_label(&self) -> &'static [u8] {
1309        match self {
1310            Self::V1 => b"quic iv",
1311            Self::V2 => b"quicv2 iv",
1312        }
1313    }
1314
1315    /// Key derivation for header keys.
1316    pub(crate) fn header_key_label(&self) -> &'static [u8] {
1317        match self {
1318            Self::V1 => b"quic hp",
1319            Self::V2 => b"quicv2 hp",
1320        }
1321    }
1322
1323    fn key_update_label(&self) -> &'static [u8] {
1324        match self {
1325            Self::V1 => b"quic ku",
1326            Self::V2 => b"quicv2 ku",
1327        }
1328    }
1329}
1330
1331#[cfg(all(test, any(target_arch = "aarch64", target_arch = "x86_64")))]
1332mod tests {
1333    use super::*;
1334    use crate::crypto::TLS13_TEST_SUITE;
1335    use crate::crypto::tls13::OkmBlock;
1336    use crate::quic::{HeaderProtectionKey, Secrets, Side, Version};
1337
1338    #[test]
1339    fn key_update_test_vector() {
1340        fn equal_okm(x: &OkmBlock, y: &OkmBlock) -> bool {
1341            x.as_ref() == y.as_ref()
1342        }
1343
1344        let mut secrets = Secrets {
1345            // Constant dummy values for reproducibility
1346            client: OkmBlock::new(
1347                &[
1348                    0xb8, 0x76, 0x77, 0x08, 0xf8, 0x77, 0x23, 0x58, 0xa6, 0xea, 0x9f, 0xc4, 0x3e,
1349                    0x4a, 0xdd, 0x2c, 0x96, 0x1b, 0x3f, 0x52, 0x87, 0xa6, 0xd1, 0x46, 0x7e, 0xe0,
1350                    0xae, 0xab, 0x33, 0x72, 0x4d, 0xbf,
1351                ][..],
1352            ),
1353            server: OkmBlock::new(
1354                &[
1355                    0x42, 0xdc, 0x97, 0x21, 0x40, 0xe0, 0xf2, 0xe3, 0x98, 0x45, 0xb7, 0x67, 0x61,
1356                    0x34, 0x39, 0xdc, 0x67, 0x58, 0xca, 0x43, 0x25, 0x9b, 0x87, 0x85, 0x06, 0x82,
1357                    0x4e, 0xb1, 0xe4, 0x38, 0xd8, 0x55,
1358                ][..],
1359            ),
1360            suite: Suite {
1361                inner: TLS13_TEST_SUITE,
1362                quic: &FakeAlgorithm,
1363            },
1364            side: Side::Client,
1365            version: Version::V1,
1366        };
1367        secrets.update();
1368
1369        assert!(equal_okm(
1370            &secrets.client,
1371            &OkmBlock::new(
1372                &[
1373                    0x42, 0xca, 0xc8, 0xc9, 0x1c, 0xd5, 0xeb, 0x40, 0x68, 0x2e, 0x43, 0x2e, 0xdf,
1374                    0x2d, 0x2b, 0xe9, 0xf4, 0x1a, 0x52, 0xca, 0x6b, 0x22, 0xd8, 0xe6, 0xcd, 0xb1,
1375                    0xe8, 0xac, 0xa9, 0x6, 0x1f, 0xce
1376                ][..]
1377            )
1378        ));
1379        assert!(equal_okm(
1380            &secrets.server,
1381            &OkmBlock::new(
1382                &[
1383                    0xeb, 0x7f, 0x5e, 0x2a, 0x12, 0x3f, 0x40, 0x7d, 0xb4, 0x99, 0xe3, 0x61, 0xca,
1384                    0xe5, 0x90, 0xd4, 0xd9, 0x92, 0xe1, 0x4b, 0x7a, 0xce, 0x3, 0xc2, 0x44, 0xe0,
1385                    0x42, 0x21, 0x15, 0xb6, 0xd3, 0x8a
1386                ][..]
1387            )
1388        ));
1389    }
1390
1391    struct FakeAlgorithm;
1392
1393    impl Algorithm for FakeAlgorithm {
1394        fn packet_key(&self, _key: AeadKey, _iv: Iv) -> Box<dyn PacketKey> {
1395            unimplemented!()
1396        }
1397
1398        fn header_protection_key(&self, _key: AeadKey) -> Box<dyn HeaderProtectionKey> {
1399            unimplemented!()
1400        }
1401
1402        fn aead_key_len(&self) -> usize {
1403            16
1404        }
1405    }
1406
1407    #[test]
1408    fn auto_traits() {
1409        fn assert_auto<T: Send + Sync>() {}
1410        assert_auto::<Box<dyn PacketKey>>();
1411        assert_auto::<Box<dyn HeaderProtectionKey>>();
1412    }
1413}