/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.35/src/quic.rs
Line | Count | Source |
1 | | use alloc::boxed::Box; |
2 | | use alloc::collections::VecDeque; |
3 | | use alloc::vec::Vec; |
4 | | #[cfg(feature = "std")] |
5 | | use core::fmt::Debug; |
6 | | |
7 | | /// This module contains optional APIs for implementing QUIC TLS. |
8 | | use crate::common_state::Side; |
9 | | use crate::crypto::cipher::{AeadKey, Iv}; |
10 | | use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock}; |
11 | | use crate::enums::AlertDescription; |
12 | | use crate::error::Error; |
13 | | use crate::tls13::Tls13CipherSuite; |
14 | | use crate::tls13::key_schedule::{ |
15 | | hkdf_expand_label, hkdf_expand_label_aead_key, hkdf_expand_label_block, |
16 | | }; |
17 | | |
18 | | #[cfg(feature = "std")] |
19 | | mod 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 | 0 | pub fn quic_transport_parameters(&self) -> Option<&[u8]> { |
56 | 0 | match self { |
57 | 0 | Self::Client(conn) => conn.quic_transport_parameters(), |
58 | 0 | Self::Server(conn) => conn.quic_transport_parameters(), |
59 | | } |
60 | 0 | } |
61 | | |
62 | | /// Compute the keys for encrypting/decrypting 0-RTT packets, if available |
63 | 0 | pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> { |
64 | 0 | match self { |
65 | 0 | Self::Client(conn) => conn.zero_rtt_keys(), |
66 | 0 | Self::Server(conn) => conn.zero_rtt_keys(), |
67 | | } |
68 | 0 | } |
69 | | |
70 | | /// Consume unencrypted TLS handshake data. |
71 | | /// |
72 | | /// Handshake data obtained from separate encryption levels should be supplied in separate calls. |
73 | 0 | pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> { |
74 | 0 | match self { |
75 | 0 | Self::Client(conn) => conn.read_hs(plaintext), |
76 | 0 | Self::Server(conn) => conn.read_hs(plaintext), |
77 | | } |
78 | 0 | } |
79 | | |
80 | | /// Emit unencrypted TLS handshake data. |
81 | | /// |
82 | | /// When this returns `Some(_)`, the new keys must be used for future handshake data. |
83 | 0 | pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> { |
84 | 0 | match self { |
85 | 0 | Self::Client(conn) => conn.write_hs(buf), |
86 | 0 | Self::Server(conn) => conn.write_hs(buf), |
87 | | } |
88 | 0 | } |
89 | | |
90 | | /// Emit the TLS description code of a fatal alert, if one has arisen. |
91 | | /// |
92 | | /// Check after `read_hs` returns `Err(_)`. |
93 | 0 | pub fn alert(&self) -> Option<AlertDescription> { |
94 | 0 | match self { |
95 | 0 | Self::Client(conn) => conn.alert(), |
96 | 0 | Self::Server(conn) => conn.alert(), |
97 | | } |
98 | 0 | } |
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 | 0 | pub fn export_keying_material<T: AsMut<[u8]>>( |
117 | 0 | &self, |
118 | 0 | output: T, |
119 | 0 | label: &[u8], |
120 | 0 | context: Option<&[u8]>, |
121 | 0 | ) -> Result<T, Error> { |
122 | 0 | match self { |
123 | 0 | Self::Client(conn) => conn |
124 | 0 | .core |
125 | 0 | .export_keying_material(output, label, context), |
126 | 0 | Self::Server(conn) => conn |
127 | 0 | .core |
128 | 0 | .export_keying_material(output, label, context), |
129 | | } |
130 | 0 | } |
131 | | } |
132 | | |
133 | | impl Deref for Connection { |
134 | | type Target = CommonState; |
135 | | |
136 | 0 | fn deref(&self) -> &Self::Target { |
137 | 0 | match self { |
138 | 0 | Self::Client(conn) => &conn.core.common_state, |
139 | 0 | Self::Server(conn) => &conn.core.common_state, |
140 | | } |
141 | 0 | } |
142 | | } |
143 | | |
144 | | impl DerefMut for Connection { |
145 | 0 | fn deref_mut(&mut self) -> &mut Self::Target { |
146 | 0 | match self { |
147 | 0 | Self::Client(conn) => &mut conn.core.common_state, |
148 | 0 | Self::Server(conn) => &mut conn.core.common_state, |
149 | | } |
150 | 0 | } |
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 | 0 | pub fn new( |
164 | 0 | config: Arc<ClientConfig>, |
165 | 0 | quic_version: Version, |
166 | 0 | name: ServerName<'static>, |
167 | 0 | params: Vec<u8>, |
168 | 0 | ) -> Result<Self, Error> { |
169 | 0 | Self::new_with_alpn( |
170 | 0 | config.clone(), |
171 | 0 | quic_version, |
172 | 0 | name, |
173 | 0 | params, |
174 | 0 | config.alpn_protocols.clone(), |
175 | | ) |
176 | 0 | } |
177 | | |
178 | | /// Make a new QUIC ClientConnection with custom ALPN protocols. |
179 | 0 | pub fn new_with_alpn( |
180 | 0 | config: Arc<ClientConfig>, |
181 | 0 | quic_version: Version, |
182 | 0 | name: ServerName<'static>, |
183 | 0 | params: Vec<u8>, |
184 | 0 | alpn_protocols: Vec<Vec<u8>>, |
185 | 0 | ) -> Result<Self, Error> { |
186 | 0 | if !config.supports_version(ProtocolVersion::TLSv1_3) { |
187 | 0 | return Err(Error::General( |
188 | 0 | "TLS 1.3 support is required for QUIC".into(), |
189 | 0 | )); |
190 | 0 | } |
191 | | |
192 | 0 | if !config.supports_protocol(Protocol::Quic) { |
193 | 0 | return Err(Error::General( |
194 | 0 | "at least one ciphersuite must support QUIC".into(), |
195 | 0 | )); |
196 | 0 | } |
197 | | |
198 | 0 | let exts = ClientExtensionsInput { |
199 | 0 | transport_parameters: Some(match quic_version { |
200 | 0 | Version::V1Draft => TransportParameters::QuicDraft(Payload::new(params)), |
201 | 0 | Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)), |
202 | | }), |
203 | | |
204 | 0 | ..ClientExtensionsInput::from_alpn(alpn_protocols) |
205 | | }; |
206 | | |
207 | 0 | let mut inner = ConnectionCore::for_client(config, name, exts, Protocol::Quic)?; |
208 | 0 | inner.common_state.quic.version = quic_version; |
209 | 0 | Ok(Self { |
210 | 0 | inner: inner.into(), |
211 | 0 | }) |
212 | 0 | } |
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 | 0 | pub fn is_early_data_accepted(&self) -> bool { |
220 | 0 | self.inner.core.is_early_data_accepted() |
221 | 0 | } |
222 | | |
223 | | /// Returns the number of TLS1.3 tickets that have been received. |
224 | 0 | pub fn tls13_tickets_received(&self) -> u32 { |
225 | 0 | self.inner.tls13_tickets_received |
226 | 0 | } |
227 | | } |
228 | | |
229 | | impl Deref for ClientConnection { |
230 | | type Target = ConnectionCommon<ClientConnectionData>; |
231 | | |
232 | 0 | fn deref(&self) -> &Self::Target { |
233 | 0 | &self.inner |
234 | 0 | } |
235 | | } |
236 | | |
237 | | impl DerefMut for ClientConnection { |
238 | 0 | fn deref_mut(&mut self) -> &mut Self::Target { |
239 | 0 | &mut self.inner |
240 | 0 | } |
241 | | } |
242 | | |
243 | | impl Debug for ClientConnection { |
244 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
245 | 0 | f.debug_struct("quic::ClientConnection") |
246 | 0 | .finish() |
247 | 0 | } |
248 | | } |
249 | | |
250 | | impl From<ClientConnection> for Connection { |
251 | 0 | fn from(c: ClientConnection) -> Self { |
252 | 0 | Self::Client(c) |
253 | 0 | } |
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 | 0 | pub fn new( |
267 | 0 | config: Arc<ServerConfig>, |
268 | 0 | quic_version: Version, |
269 | 0 | params: Vec<u8>, |
270 | 0 | ) -> Result<Self, Error> { |
271 | 0 | if !config.supports_version(ProtocolVersion::TLSv1_3) { |
272 | 0 | return Err(Error::General( |
273 | 0 | "TLS 1.3 support is required for QUIC".into(), |
274 | 0 | )); |
275 | 0 | } |
276 | | |
277 | 0 | if !config.supports_protocol(Protocol::Quic) { |
278 | 0 | return Err(Error::General( |
279 | 0 | "at least one ciphersuite must support QUIC".into(), |
280 | 0 | )); |
281 | 0 | } |
282 | | |
283 | 0 | if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff { |
284 | 0 | return Err(Error::General( |
285 | 0 | "QUIC sessions must set a max early data of 0 or 2^32-1".into(), |
286 | 0 | )); |
287 | 0 | } |
288 | | |
289 | 0 | let exts = ServerExtensionsInput { |
290 | 0 | transport_parameters: Some(match quic_version { |
291 | 0 | Version::V1Draft => TransportParameters::QuicDraft(Payload::new(params)), |
292 | 0 | Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)), |
293 | | }), |
294 | | }; |
295 | | |
296 | 0 | let mut core = ConnectionCore::for_server(config, exts)?; |
297 | 0 | core.common_state.protocol = Protocol::Quic; |
298 | 0 | core.common_state.quic.version = quic_version; |
299 | 0 | Ok(Self { inner: core.into() }) |
300 | 0 | } |
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 | 0 | pub fn reject_early_data(&mut self) { |
308 | 0 | self.inner.core.reject_early_data() |
309 | 0 | } |
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 | 0 | pub fn server_name(&self) -> Option<&str> { |
327 | 0 | self.inner.core.get_sni_str() |
328 | 0 | } |
329 | | } |
330 | | |
331 | | impl Deref for ServerConnection { |
332 | | type Target = ConnectionCommon<ServerConnectionData>; |
333 | | |
334 | 0 | fn deref(&self) -> &Self::Target { |
335 | 0 | &self.inner |
336 | 0 | } |
337 | | } |
338 | | |
339 | | impl DerefMut for ServerConnection { |
340 | 0 | fn deref_mut(&mut self) -> &mut Self::Target { |
341 | 0 | &mut self.inner |
342 | 0 | } |
343 | | } |
344 | | |
345 | | impl Debug for ServerConnection { |
346 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
347 | 0 | f.debug_struct("quic::ServerConnection") |
348 | 0 | .finish() |
349 | 0 | } |
350 | | } |
351 | | |
352 | | impl From<ServerConnection> for Connection { |
353 | 0 | fn from(c: ServerConnection) -> Self { |
354 | 0 | Self::Server(c) |
355 | 0 | } |
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 | 0 | pub fn quic_transport_parameters(&self) -> Option<&[u8]> { |
374 | 0 | self.core |
375 | 0 | .common_state |
376 | 0 | .quic |
377 | 0 | .params |
378 | 0 | .as_ref() |
379 | 0 | .map(|v| v.as_ref()) Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::quic_transport_parameters::{closure#0}Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::quic_transport_parameters::{closure#0} |
380 | 0 | } Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::quic_transport_parameters Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::quic_transport_parameters |
381 | | |
382 | | /// Compute the keys for encrypting/decrypting 0-RTT packets, if available |
383 | 0 | pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> { |
384 | 0 | let suite = self |
385 | 0 | .core |
386 | 0 | .common_state |
387 | 0 | .suite |
388 | 0 | .and_then(|suite| suite.tls13())?; Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::zero_rtt_keys::{closure#0}Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::zero_rtt_keys::{closure#0} |
389 | 0 | Some(DirectionalKeys::new( |
390 | 0 | suite, |
391 | 0 | suite.quic?, |
392 | 0 | self.core |
393 | 0 | .common_state |
394 | 0 | .quic |
395 | 0 | .early_secret |
396 | 0 | .as_ref()?, |
397 | 0 | self.core.common_state.quic.version, |
398 | | )) |
399 | 0 | } Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::zero_rtt_keys Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::zero_rtt_keys |
400 | | |
401 | | /// Consume unencrypted TLS handshake data. |
402 | | /// |
403 | | /// Handshake data obtained from separate encryption levels should be supplied in separate calls. |
404 | 0 | pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> { |
405 | 0 | let range = self.deframer_buffer.extend(plaintext); |
406 | | |
407 | 0 | self.core.hs_deframer.input_message( |
408 | 0 | InboundPlainMessage { |
409 | 0 | typ: ContentType::Handshake, |
410 | 0 | version: ProtocolVersion::TLSv1_3, |
411 | 0 | payload: &self.deframer_buffer.filled()[range.clone()], |
412 | 0 | }, |
413 | 0 | &Locator::new(self.deframer_buffer.filled()), |
414 | 0 | range.end, |
415 | | ); |
416 | | |
417 | 0 | self.core |
418 | 0 | .hs_deframer |
419 | 0 | .coalesce(self.deframer_buffer.filled_mut())?; |
420 | | |
421 | 0 | self.core |
422 | 0 | .process_new_packets(&mut self.deframer_buffer, &mut self.sendable_plaintext)?; |
423 | | |
424 | 0 | Ok(()) |
425 | 0 | } Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::read_hs Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::read_hs |
426 | | |
427 | | /// Emit unencrypted TLS handshake data. |
428 | | /// |
429 | | /// When this returns `Some(_)`, the new keys must be used for future handshake data. |
430 | 0 | pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> { |
431 | 0 | self.core |
432 | 0 | .common_state |
433 | 0 | .quic |
434 | 0 | .write_hs(buf) |
435 | 0 | } Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::write_hs Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::write_hs |
436 | | |
437 | | /// Emit the TLS description code of a fatal alert, if one has arisen. |
438 | | /// |
439 | | /// Check after `read_hs` returns `Err(_)`. |
440 | 0 | pub fn alert(&self) -> Option<AlertDescription> { |
441 | 0 | self.core.common_state.quic.alert |
442 | 0 | } Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::alert Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::alert |
443 | | } |
444 | | |
445 | | impl<Data> Deref for ConnectionCommon<Data> { |
446 | | type Target = CommonState; |
447 | | |
448 | 0 | fn deref(&self) -> &Self::Target { |
449 | 0 | &self.core.common_state |
450 | 0 | } |
451 | | } |
452 | | |
453 | | impl<Data> DerefMut for ConnectionCommon<Data> { |
454 | 0 | fn deref_mut(&mut self) -> &mut Self::Target { |
455 | 0 | &mut self.core.common_state |
456 | 0 | } |
457 | | } |
458 | | |
459 | | impl<Data> From<ConnectionCore<Data>> for ConnectionCommon<Data> { |
460 | 0 | fn from(core: ConnectionCore<Data>) -> Self { |
461 | 0 | Self { |
462 | 0 | core, |
463 | 0 | deframer_buffer: DeframerVecBuffer::default(), |
464 | 0 | sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)), |
465 | 0 | } |
466 | 0 | } Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::client::client_conn::ClientConnectionData> as core::convert::From<rustls::conn::ConnectionCore<rustls::client::client_conn::ClientConnectionData>>>::from Unexecuted instantiation: <rustls::quic::connection::ConnectionCommon<rustls::server::server_conn::ServerConnectionData> as core::convert::From<rustls::conn::ConnectionCore<rustls::server::server_conn::ServerConnectionData>>>::from |
467 | | } |
468 | | } |
469 | | |
470 | | #[cfg(feature = "std")] |
471 | | pub use connection::{ClientConnection, Connection, ConnectionCommon, ServerConnection}; |
472 | | |
473 | | #[derive(Default)] |
474 | | pub(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")] |
489 | | impl Quic { |
490 | 0 | pub(crate) fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> { |
491 | 0 | while let Some((_, msg)) = self.hs_queue.pop_front() { |
492 | 0 | buf.extend_from_slice(&msg); |
493 | 0 | if let Some(&(true, _)) = self.hs_queue.front() { |
494 | 0 | if self.hs_secrets.is_some() { |
495 | | // Allow the caller to switch keys before proceeding. |
496 | 0 | break; |
497 | 0 | } |
498 | 0 | } |
499 | | } |
500 | | |
501 | 0 | if let Some(secrets) = self.hs_secrets.take() { |
502 | 0 | return Some(KeyChange::Handshake { |
503 | 0 | keys: Keys::new(&secrets), |
504 | 0 | }); |
505 | 0 | } |
506 | | |
507 | 0 | if let Some(mut secrets) = self.traffic_secrets.take() { |
508 | 0 | if !self.returned_traffic_keys { |
509 | 0 | self.returned_traffic_keys = true; |
510 | 0 | let keys = Keys::new(&secrets); |
511 | 0 | secrets.update(); |
512 | 0 | return Some(KeyChange::OneRtt { |
513 | 0 | keys, |
514 | 0 | next: secrets, |
515 | 0 | }); |
516 | 0 | } |
517 | 0 | } |
518 | | |
519 | 0 | None |
520 | 0 | } |
521 | | } |
522 | | |
523 | | /// Secrets used to encrypt/decrypt traffic |
524 | | #[derive(Clone)] |
525 | | pub 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 | | |
537 | | impl Secrets { |
538 | 0 | pub(crate) fn new( |
539 | 0 | client: OkmBlock, |
540 | 0 | server: OkmBlock, |
541 | 0 | suite: &'static Tls13CipherSuite, |
542 | 0 | quic: &'static dyn Algorithm, |
543 | 0 | side: Side, |
544 | 0 | version: Version, |
545 | 0 | ) -> Self { |
546 | 0 | Self { |
547 | 0 | client, |
548 | 0 | server, |
549 | 0 | suite, |
550 | 0 | quic, |
551 | 0 | side, |
552 | 0 | version, |
553 | 0 | } |
554 | 0 | } |
555 | | |
556 | | /// Derive the next set of packet keys |
557 | 0 | pub fn next_packet_keys(&mut self) -> PacketKeySet { |
558 | 0 | let keys = PacketKeySet::new(self); |
559 | 0 | self.update(); |
560 | 0 | keys |
561 | 0 | } |
562 | | |
563 | 0 | pub(crate) fn update(&mut self) { |
564 | 0 | self.client = hkdf_expand_label_block( |
565 | 0 | self.suite |
566 | 0 | .hkdf_provider |
567 | 0 | .expander_for_okm(&self.client) |
568 | 0 | .as_ref(), |
569 | 0 | self.version.key_update_label(), |
570 | 0 | &[], |
571 | | ); |
572 | 0 | self.server = hkdf_expand_label_block( |
573 | 0 | self.suite |
574 | 0 | .hkdf_provider |
575 | 0 | .expander_for_okm(&self.server) |
576 | 0 | .as_ref(), |
577 | 0 | self.version.key_update_label(), |
578 | 0 | &[], |
579 | | ); |
580 | 0 | } |
581 | | |
582 | 0 | fn local_remote(&self) -> (&OkmBlock, &OkmBlock) { |
583 | 0 | match self.side { |
584 | 0 | Side::Client => (&self.client, &self.server), |
585 | 0 | Side::Server => (&self.server, &self.client), |
586 | | } |
587 | 0 | } |
588 | | } |
589 | | |
590 | | /// Keys used to communicate in a single direction |
591 | | pub 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 | | |
598 | | impl DirectionalKeys { |
599 | 0 | pub(crate) fn new( |
600 | 0 | suite: &'static Tls13CipherSuite, |
601 | 0 | quic: &'static dyn Algorithm, |
602 | 0 | secret: &OkmBlock, |
603 | 0 | version: Version, |
604 | 0 | ) -> Self { |
605 | 0 | let builder = KeyBuilder::new(secret, version, quic, suite.hkdf_provider); |
606 | 0 | Self { |
607 | 0 | header: builder.header_protection_key(), |
608 | 0 | packet: builder.packet_key(), |
609 | 0 | } |
610 | 0 | } |
611 | | } |
612 | | |
613 | | /// All AEADs we support have 16-byte tags. |
614 | | const TAG_LEN: usize = 16; |
615 | | |
616 | | /// Authentication tag from an AEAD seal operation. |
617 | | pub struct Tag([u8; TAG_LEN]); |
618 | | |
619 | | impl From<&[u8]> for Tag { |
620 | 0 | fn from(value: &[u8]) -> Self { |
621 | 0 | let mut array = [0u8; TAG_LEN]; |
622 | 0 | array.copy_from_slice(value); |
623 | 0 | Self(array) |
624 | 0 | } |
625 | | } |
626 | | |
627 | | impl AsRef<[u8]> for Tag { |
628 | 0 | fn as_ref(&self) -> &[u8] { |
629 | 0 | &self.0 |
630 | 0 | } |
631 | | } |
632 | | |
633 | | /// How a `Tls13CipherSuite` generates `PacketKey`s and `HeaderProtectionKey`s. |
634 | | pub 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 | 0 | fn fips(&self) -> bool { |
653 | 0 | false |
654 | 0 | } |
655 | | } |
656 | | |
657 | | /// A QUIC header protection key |
658 | | pub 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 |
719 | | pub 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 | 0 | fn encrypt_in_place_for_path( |
744 | 0 | &self, |
745 | 0 | _path_id: u32, |
746 | 0 | _packet_number: u64, |
747 | 0 | _header: &[u8], |
748 | 0 | _payload: &mut [u8], |
749 | 0 | ) -> Result<Tag, Error> { |
750 | 0 | Err(Error::EncryptError) |
751 | 0 | } |
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 | 0 | fn decrypt_in_place_for_path<'a>( |
778 | 0 | &self, |
779 | 0 | _path_id: u32, |
780 | 0 | _packet_number: u64, |
781 | 0 | _header: &[u8], |
782 | 0 | _payload: &'a mut [u8], |
783 | 0 | ) -> Result<&'a [u8], Error> { |
784 | 0 | Err(Error::DecryptError) |
785 | 0 | } |
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 |
814 | | pub struct PacketKeySet { |
815 | | /// Encrypts outgoing packets |
816 | | pub local: Box<dyn PacketKey>, |
817 | | /// Decrypts incoming packets |
818 | | pub remote: Box<dyn PacketKey>, |
819 | | } |
820 | | |
821 | | impl PacketKeySet { |
822 | 0 | fn new(secrets: &Secrets) -> Self { |
823 | 0 | let (local, remote) = secrets.local_remote(); |
824 | 0 | let (version, alg, hkdf) = (secrets.version, secrets.quic, secrets.suite.hkdf_provider); |
825 | 0 | Self { |
826 | 0 | local: KeyBuilder::new(local, version, alg, hkdf).packet_key(), |
827 | 0 | remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(), |
828 | 0 | } |
829 | 0 | } |
830 | | } |
831 | | |
832 | | pub(crate) struct KeyBuilder<'a> { |
833 | | expander: Box<dyn HkdfExpander>, |
834 | | version: Version, |
835 | | alg: &'a dyn Algorithm, |
836 | | } |
837 | | |
838 | | impl<'a> KeyBuilder<'a> { |
839 | 0 | pub(crate) fn new( |
840 | 0 | secret: &OkmBlock, |
841 | 0 | version: Version, |
842 | 0 | alg: &'a dyn Algorithm, |
843 | 0 | hkdf: &'a dyn Hkdf, |
844 | 0 | ) -> Self { |
845 | 0 | Self { |
846 | 0 | expander: hkdf.expander_for_okm(secret), |
847 | 0 | version, |
848 | 0 | alg, |
849 | 0 | } |
850 | 0 | } |
851 | | |
852 | | /// Derive packet keys |
853 | 0 | pub(crate) fn packet_key(&self) -> Box<dyn PacketKey> { |
854 | 0 | let aead_key_len = self.alg.aead_key_len(); |
855 | 0 | let packet_key = hkdf_expand_label_aead_key( |
856 | 0 | self.expander.as_ref(), |
857 | 0 | aead_key_len, |
858 | 0 | self.version.packet_key_label(), |
859 | 0 | &[], |
860 | | ); |
861 | | |
862 | 0 | let packet_iv = |
863 | 0 | hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]); |
864 | 0 | self.alg |
865 | 0 | .packet_key(packet_key, packet_iv) |
866 | 0 | } |
867 | | |
868 | | /// Derive header protection keys |
869 | 0 | pub(crate) fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> { |
870 | 0 | let header_key = hkdf_expand_label_aead_key( |
871 | 0 | self.expander.as_ref(), |
872 | 0 | self.alg.aead_key_len(), |
873 | 0 | self.version.header_key_label(), |
874 | 0 | &[], |
875 | | ); |
876 | 0 | self.alg |
877 | 0 | .header_protection_key(header_key) |
878 | 0 | } |
879 | | } |
880 | | |
881 | | /// Produces QUIC initial keys from a TLS 1.3 ciphersuite and a QUIC key generation algorithm. |
882 | | #[derive(Clone, Copy)] |
883 | | pub 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 | | |
890 | | impl Suite { |
891 | | /// Produce a set of initial keys given the connection ID, side and version |
892 | 0 | pub fn keys(&self, client_dst_connection_id: &[u8], side: Side, version: Version) -> Keys { |
893 | 0 | Keys::initial( |
894 | 0 | version, |
895 | 0 | self.suite, |
896 | 0 | self.quic, |
897 | 0 | client_dst_connection_id, |
898 | 0 | side, |
899 | | ) |
900 | 0 | } |
901 | | } |
902 | | |
903 | | /// Complete set of keys used to communicate with the peer |
904 | | pub struct Keys { |
905 | | /// Encrypts outgoing packets |
906 | | pub local: DirectionalKeys, |
907 | | /// Decrypts incoming packets |
908 | | pub remote: DirectionalKeys, |
909 | | } |
910 | | |
911 | | impl Keys { |
912 | | /// Construct keys for use with initial packets |
913 | 0 | pub fn initial( |
914 | 0 | version: Version, |
915 | 0 | suite: &'static Tls13CipherSuite, |
916 | 0 | quic: &'static dyn Algorithm, |
917 | 0 | client_dst_connection_id: &[u8], |
918 | 0 | side: Side, |
919 | 0 | ) -> Self { |
920 | | const CLIENT_LABEL: &[u8] = b"client in"; |
921 | | const SERVER_LABEL: &[u8] = b"server in"; |
922 | 0 | let salt = version.initial_salt(); |
923 | 0 | let hs_secret = suite |
924 | 0 | .hkdf_provider |
925 | 0 | .extract_from_secret(Some(salt), client_dst_connection_id); |
926 | | |
927 | 0 | let secrets = Secrets { |
928 | 0 | version, |
929 | 0 | client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]), |
930 | 0 | server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]), |
931 | 0 | suite, |
932 | 0 | quic, |
933 | 0 | side, |
934 | 0 | }; |
935 | 0 | Self::new(&secrets) |
936 | 0 | } |
937 | | |
938 | 0 | fn new(secrets: &Secrets) -> Self { |
939 | 0 | let (local, remote) = secrets.local_remote(); |
940 | 0 | Self { |
941 | 0 | local: DirectionalKeys::new(secrets.suite, secrets.quic, local, secrets.version), |
942 | 0 | remote: DirectionalKeys::new(secrets.suite, secrets.quic, remote, secrets.version), |
943 | 0 | } |
944 | 0 | } |
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 | | pub 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, Default)] |
980 | | pub enum Version { |
981 | | /// Draft versions 29, 30, 31 and 32 |
982 | | V1Draft, |
983 | | /// First stable RFC |
984 | | #[default] |
985 | | V1, |
986 | | /// Anti-ossification variant of V1 |
987 | | V2, |
988 | | } |
989 | | |
990 | | impl Version { |
991 | 0 | fn initial_salt(self) -> &'static [u8; 20] { |
992 | 0 | match self { |
993 | 0 | Self::V1Draft => &[ |
994 | 0 | // https://datatracker.ietf.org/doc/html/draft-ietf-quic-tls-32#section-5.2 |
995 | 0 | 0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61, |
996 | 0 | 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99, |
997 | 0 | ], |
998 | 0 | Self::V1 => &[ |
999 | 0 | // https://www.rfc-editor.org/rfc/rfc9001.html#name-initial-secrets |
1000 | 0 | 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, |
1001 | 0 | 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a, |
1002 | 0 | ], |
1003 | 0 | Self::V2 => &[ |
1004 | 0 | // https://www.ietf.org/archive/id/draft-ietf-quic-v2-10.html#name-initial-salt-2 |
1005 | 0 | 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26, |
1006 | 0 | 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9, |
1007 | 0 | ], |
1008 | | } |
1009 | 0 | } |
1010 | | |
1011 | | /// Key derivation label for packet keys. |
1012 | 0 | pub(crate) fn packet_key_label(&self) -> &'static [u8] { |
1013 | 0 | match self { |
1014 | 0 | Self::V1Draft | Self::V1 => b"quic key", |
1015 | 0 | Self::V2 => b"quicv2 key", |
1016 | | } |
1017 | 0 | } |
1018 | | |
1019 | | /// Key derivation label for packet "IV"s. |
1020 | 0 | pub(crate) fn packet_iv_label(&self) -> &'static [u8] { |
1021 | 0 | match self { |
1022 | 0 | Self::V1Draft | Self::V1 => b"quic iv", |
1023 | 0 | Self::V2 => b"quicv2 iv", |
1024 | | } |
1025 | 0 | } |
1026 | | |
1027 | | /// Key derivation for header keys. |
1028 | 0 | pub(crate) fn header_key_label(&self) -> &'static [u8] { |
1029 | 0 | match self { |
1030 | 0 | Self::V1Draft | Self::V1 => b"quic hp", |
1031 | 0 | Self::V2 => b"quicv2 hp", |
1032 | | } |
1033 | 0 | } |
1034 | | |
1035 | 0 | fn key_update_label(&self) -> &'static [u8] { |
1036 | 0 | match self { |
1037 | 0 | Self::V1Draft | Self::V1 => b"quic ku", |
1038 | 0 | Self::V2 => b"quicv2 ku", |
1039 | | } |
1040 | 0 | } |
1041 | | } |
1042 | | |
1043 | | #[cfg(test)] |
1044 | | mod tests { |
1045 | | use std::prelude::v1::*; |
1046 | | |
1047 | | use super::PacketKey; |
1048 | | use crate::quic::HeaderProtectionKey; |
1049 | | |
1050 | | #[test] |
1051 | | fn auto_traits() { |
1052 | | fn assert_auto<T: Send + Sync>() {} |
1053 | | assert_auto::<Box<dyn PacketKey>>(); |
1054 | | assert_auto::<Box<dyn HeaderProtectionKey>>(); |
1055 | | } |
1056 | | } |