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