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}