1use alloc::boxed::Box;
2use alloc::collections::VecDeque;
3use alloc::vec::Vec;
4#[cfg(feature = "std")]
5use core::fmt::Debug;
6
7use crate::common_state::Side;
9use crate::crypto::cipher::{AeadKey, Iv};
10use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock};
11use crate::error::Error;
12use crate::tls13::Tls13CipherSuite;
13use crate::tls13::key_schedule::{
14 hkdf_expand_label, hkdf_expand_label_aead_key, hkdf_expand_label_block,
15};
16
17#[cfg(feature = "std")]
18mod connection {
19 use alloc::vec::Vec;
20 use core::fmt::{self, Debug};
21 use core::ops::{Deref, DerefMut};
22
23 use pki_types::{DnsName, ServerName};
24
25 use super::{DirectionalKeys, KeyChange, Version};
26 use crate::client::{ClientConfig, ClientConnectionData};
27 use crate::common_state::{CommonState, DEFAULT_BUFFER_LIMIT, Protocol};
28 use crate::conn::{ConnectionCore, KeyingMaterialExporter, SideData};
29 use crate::crypto::cipher::{EncodedMessage, Payload};
30 use crate::enums::{ContentType, ProtocolVersion};
31 use crate::error::{ApiMisuse, Error};
32 use crate::msgs::deframer::{DeframerVecBuffer, Locator};
33 use crate::msgs::handshake::{
34 ClientExtensionsInput, ServerExtensionsInput, TransportParameters,
35 };
36 use crate::server::{ServerConfig, ServerConnectionData};
37 use crate::suites::SupportedCipherSuite;
38 use crate::sync::Arc;
39 use crate::vecbuf::ChunkVecBuffer;
40
41 #[expect(clippy::exhaustive_enums)]
43 #[derive(Debug)]
44 pub enum Connection {
45 Client(ClientConnection),
47 Server(ServerConnection),
49 }
50
51 impl Connection {
52 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 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 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 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
91 impl Deref for Connection {
92 type Target = CommonState;
93
94 fn deref(&self) -> &Self::Target {
95 match self {
96 Self::Client(conn) => &conn.core.common_state,
97 Self::Server(conn) => &conn.core.common_state,
98 }
99 }
100 }
101
102 impl DerefMut for Connection {
103 fn deref_mut(&mut self) -> &mut Self::Target {
104 match self {
105 Self::Client(conn) => &mut conn.core.common_state,
106 Self::Server(conn) => &mut conn.core.common_state,
107 }
108 }
109 }
110
111 pub struct ClientConnection {
113 inner: ConnectionCommon<ClientConnectionData>,
114 }
115
116 impl ClientConnection {
117 pub fn new(
122 config: Arc<ClientConfig>,
123 quic_version: Version,
124 name: ServerName<'static>,
125 params: Vec<u8>,
126 ) -> Result<Self, Error> {
127 Self::new_with_alpn(
128 config.clone(),
129 quic_version,
130 name,
131 params,
132 config.alpn_protocols.clone(),
133 )
134 }
135
136 pub fn new_with_alpn(
138 config: Arc<ClientConfig>,
139 quic_version: Version,
140 name: ServerName<'static>,
141 params: Vec<u8>,
142 alpn_protocols: Vec<Vec<u8>>,
143 ) -> Result<Self, Error> {
144 let suites = &config.provider().tls13_cipher_suites;
145 if suites.is_empty() {
146 return Err(ApiMisuse::QuicRequiresTls13Support.into());
147 }
148
149 if !suites
150 .iter()
151 .any(|scs| scs.quic.is_some())
152 {
153 return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
154 }
155
156 let exts = ClientExtensionsInput {
157 transport_parameters: Some(match quic_version {
158 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
159 }),
160
161 ..ClientExtensionsInput::from_alpn(alpn_protocols)
162 };
163
164 let mut inner = ConnectionCore::for_client(config, name, exts, Protocol::Quic)?;
165 inner.common_state.quic.version = quic_version;
166 Ok(Self {
167 inner: inner.into(),
168 })
169 }
170
171 pub fn is_early_data_accepted(&self) -> bool {
177 self.inner.core.is_early_data_accepted()
178 }
179
180 pub fn tls13_tickets_received(&self) -> u32 {
182 self.inner.tls13_tickets_received
183 }
184
185 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
199 self.core.exporter()
200 }
201 }
202
203 impl Deref for ClientConnection {
204 type Target = ConnectionCommon<ClientConnectionData>;
205
206 fn deref(&self) -> &Self::Target {
207 &self.inner
208 }
209 }
210
211 impl DerefMut for ClientConnection {
212 fn deref_mut(&mut self) -> &mut Self::Target {
213 &mut self.inner
214 }
215 }
216
217 impl Debug for ClientConnection {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 f.debug_struct("quic::ClientConnection")
220 .finish()
221 }
222 }
223
224 impl From<ClientConnection> for Connection {
225 fn from(c: ClientConnection) -> Self {
226 Self::Client(c)
227 }
228 }
229
230 pub struct ServerConnection {
232 inner: ConnectionCommon<ServerConnectionData>,
233 }
234
235 impl ServerConnection {
236 pub fn new(
241 config: Arc<ServerConfig>,
242 quic_version: Version,
243 params: Vec<u8>,
244 ) -> Result<Self, Error> {
245 let suites = &config.provider.tls13_cipher_suites;
246 if suites.is_empty() {
247 return Err(ApiMisuse::QuicRequiresTls13Support.into());
248 }
249
250 if !suites
251 .iter()
252 .any(|scs| scs.quic.is_some())
253 {
254 return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
255 }
256
257 if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff {
258 return Err(ApiMisuse::QuicRestrictsMaxEarlyDataSize.into());
259 }
260
261 let exts = ServerExtensionsInput {
262 transport_parameters: Some(match quic_version {
263 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
264 }),
265 };
266
267 let mut core = ConnectionCore::for_server(config, exts)?;
268 core.common_state.protocol = Protocol::Quic;
269 core.common_state.quic.version = quic_version;
270 Ok(Self { inner: core.into() })
271 }
272
273 pub fn reject_early_data(&mut self) {
279 self.inner.core.reject_early_data()
280 }
281
282 pub fn server_name(&self) -> Option<&DnsName<'_>> {
298 self.inner.core.side.sni.as_ref()
299 }
300
301 pub fn set_resumption_data(&mut self, data: &[u8]) {
310 assert!(data.len() < 2usize.pow(15));
311 self.inner.core.side.resumption_data = data.into();
312 }
313
314 pub fn received_resumption_data(&self) -> Option<&[u8]> {
318 self.inner
319 .core
320 .side
321 .received_resumption_data
322 .as_deref()
323 }
324
325 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
339 self.core.exporter()
340 }
341 }
342
343 impl Deref for ServerConnection {
344 type Target = ConnectionCommon<ServerConnectionData>;
345
346 fn deref(&self) -> &Self::Target {
347 &self.inner
348 }
349 }
350
351 impl DerefMut for ServerConnection {
352 fn deref_mut(&mut self) -> &mut Self::Target {
353 &mut self.inner
354 }
355 }
356
357 impl Debug for ServerConnection {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 f.debug_struct("quic::ServerConnection")
360 .finish()
361 }
362 }
363
364 impl From<ServerConnection> for Connection {
365 fn from(c: ServerConnection) -> Self {
366 Self::Server(c)
367 }
368 }
369
370 pub struct ConnectionCommon<Side: SideData> {
372 core: ConnectionCore<Side>,
373 deframer_buffer: DeframerVecBuffer,
374 sendable_plaintext: ChunkVecBuffer,
375 }
376
377 impl<Side: SideData> ConnectionCommon<Side> {
378 pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
386 self.core
387 .common_state
388 .quic
389 .params
390 .as_ref()
391 .map(|v| v.as_ref())
392 }
393
394 pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
396 let suite = self
397 .core
398 .common_state
399 .suite
400 .and_then(|suite| match suite {
401 SupportedCipherSuite::Tls13(suite) => Some(suite),
402 _ => None,
403 })?;
404 Some(DirectionalKeys::new(
405 suite,
406 suite.quic?,
407 self.core
408 .common_state
409 .quic
410 .early_secret
411 .as_ref()?,
412 self.core.common_state.quic.version,
413 ))
414 }
415
416 pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
425 let range = self.deframer_buffer.extend(plaintext);
426
427 self.core.hs_deframer.input_message(
428 EncodedMessage {
429 typ: ContentType::Handshake,
430 version: ProtocolVersion::TLSv1_3,
431 payload: &self.deframer_buffer.filled()[range.clone()],
432 },
433 &Locator::new(self.deframer_buffer.filled()),
434 range.end,
435 );
436
437 self.core
438 .hs_deframer
439 .coalesce(self.deframer_buffer.filled_mut())?;
440
441 self.core.common_state.aligned_handshake = self.core.hs_deframer.aligned();
442 self.core
443 .process_new_packets(&mut self.deframer_buffer, &mut self.sendable_plaintext)?;
444
445 Ok(())
446 }
447
448 pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
452 self.core
453 .common_state
454 .quic
455 .write_hs(buf)
456 }
457 }
458
459 impl<Side: SideData> Deref for ConnectionCommon<Side> {
460 type Target = CommonState;
461
462 fn deref(&self) -> &Self::Target {
463 &self.core.common_state
464 }
465 }
466
467 impl<Side: SideData> DerefMut for ConnectionCommon<Side> {
468 fn deref_mut(&mut self) -> &mut Self::Target {
469 &mut self.core.common_state
470 }
471 }
472
473 impl<Side: SideData> From<ConnectionCore<Side>> for ConnectionCommon<Side> {
474 fn from(core: ConnectionCore<Side>) -> Self {
475 Self {
476 core,
477 deframer_buffer: DeframerVecBuffer::default(),
478 sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
479 }
480 }
481 }
482}
483
484#[cfg(feature = "std")]
485pub use connection::{ClientConnection, Connection, ConnectionCommon, ServerConnection};
486
487#[derive(Default)]
488pub(crate) struct Quic {
489 pub(crate) params: Option<Vec<u8>>,
491 pub(crate) hs_queue: VecDeque<(bool, Vec<u8>)>,
492 pub(crate) early_secret: Option<OkmBlock>,
493 pub(crate) hs_secrets: Option<Secrets>,
494 pub(crate) traffic_secrets: Option<Secrets>,
495 #[cfg(feature = "std")]
497 pub(crate) returned_traffic_keys: bool,
498 pub(crate) version: Version,
499}
500
501#[cfg(feature = "std")]
502impl Quic {
503 pub(crate) fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
504 while let Some((_, msg)) = self.hs_queue.pop_front() {
505 buf.extend_from_slice(&msg);
506 if let Some(&(true, _)) = self.hs_queue.front() {
507 if self.hs_secrets.is_some() {
508 break;
510 }
511 }
512 }
513
514 if let Some(secrets) = self.hs_secrets.take() {
515 return Some(KeyChange::Handshake {
516 keys: Keys::new(&secrets),
517 });
518 }
519
520 if let Some(mut secrets) = self.traffic_secrets.take() {
521 if !self.returned_traffic_keys {
522 self.returned_traffic_keys = true;
523 let keys = Keys::new(&secrets);
524 secrets.update();
525 return Some(KeyChange::OneRtt {
526 keys,
527 next: secrets,
528 });
529 }
530 }
531
532 None
533 }
534}
535
536#[derive(Clone)]
538pub struct Secrets {
539 pub(crate) client: OkmBlock,
541 pub(crate) server: OkmBlock,
543 suite: &'static Tls13CipherSuite,
545 quic: &'static dyn Algorithm,
546 side: Side,
547 version: Version,
548}
549
550impl Secrets {
551 pub(crate) fn new(
552 client: OkmBlock,
553 server: OkmBlock,
554 suite: &'static Tls13CipherSuite,
555 quic: &'static dyn Algorithm,
556 side: Side,
557 version: Version,
558 ) -> Self {
559 Self {
560 client,
561 server,
562 suite,
563 quic,
564 side,
565 version,
566 }
567 }
568
569 pub fn next_packet_keys(&mut self) -> PacketKeySet {
571 let keys = PacketKeySet::new(self);
572 self.update();
573 keys
574 }
575
576 pub(crate) fn update(&mut self) {
577 self.client = hkdf_expand_label_block(
578 self.suite
579 .hkdf_provider
580 .expander_for_okm(&self.client)
581 .as_ref(),
582 self.version.key_update_label(),
583 &[],
584 );
585 self.server = hkdf_expand_label_block(
586 self.suite
587 .hkdf_provider
588 .expander_for_okm(&self.server)
589 .as_ref(),
590 self.version.key_update_label(),
591 &[],
592 );
593 }
594
595 fn local_remote(&self) -> (&OkmBlock, &OkmBlock) {
596 match self.side {
597 Side::Client => (&self.client, &self.server),
598 Side::Server => (&self.server, &self.client),
599 }
600 }
601}
602
603#[expect(clippy::exhaustive_structs)]
605pub struct DirectionalKeys {
606 pub header: Box<dyn HeaderProtectionKey>,
608 pub packet: Box<dyn PacketKey>,
610}
611
612impl DirectionalKeys {
613 pub(crate) fn new(
614 suite: &'static Tls13CipherSuite,
615 quic: &'static dyn Algorithm,
616 secret: &OkmBlock,
617 version: Version,
618 ) -> Self {
619 let builder = KeyBuilder::new(secret, version, quic, suite.hkdf_provider);
620 Self {
621 header: builder.header_protection_key(),
622 packet: builder.packet_key(),
623 }
624 }
625}
626
627const TAG_LEN: usize = 16;
629
630pub struct Tag([u8; TAG_LEN]);
632
633impl From<&[u8]> for Tag {
634 fn from(value: &[u8]) -> Self {
635 let mut array = [0u8; TAG_LEN];
636 array.copy_from_slice(value);
637 Self(array)
638 }
639}
640
641impl AsRef<[u8]> for Tag {
642 fn as_ref(&self) -> &[u8] {
643 &self.0
644 }
645}
646
647pub trait Algorithm: Send + Sync {
649 fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn PacketKey>;
654
655 fn header_protection_key(&self, key: AeadKey) -> Box<dyn HeaderProtectionKey>;
659
660 fn aead_key_len(&self) -> usize;
664
665 fn fips(&self) -> bool {
667 false
668 }
669}
670
671pub trait HeaderProtectionKey: Send + Sync {
673 fn encrypt_in_place(
694 &self,
695 sample: &[u8],
696 first: &mut u8,
697 packet_number: &mut [u8],
698 ) -> Result<(), Error>;
699
700 fn decrypt_in_place(
722 &self,
723 sample: &[u8],
724 first: &mut u8,
725 packet_number: &mut [u8],
726 ) -> Result<(), Error>;
727
728 fn sample_len(&self) -> usize;
730}
731
732pub trait PacketKey: Send + Sync {
734 fn encrypt_in_place(
745 &self,
746 packet_number: u64,
747 header: &[u8],
748 payload: &mut [u8],
749 path_id: Option<u32>,
750 ) -> Result<Tag, Error>;
751
752 fn decrypt_in_place<'a>(
763 &self,
764 packet_number: u64,
765 header: &[u8],
766 payload: &'a mut [u8],
767 path_id: Option<u32>,
768 ) -> Result<&'a [u8], Error>;
769
770 fn tag_len(&self) -> usize;
772
773 fn confidentiality_limit(&self) -> u64;
784
785 fn integrity_limit(&self) -> u64;
794}
795
796#[expect(clippy::exhaustive_structs)]
798pub struct PacketKeySet {
799 pub local: Box<dyn PacketKey>,
801 pub remote: Box<dyn PacketKey>,
803}
804
805impl PacketKeySet {
806 fn new(secrets: &Secrets) -> Self {
807 let (local, remote) = secrets.local_remote();
808 let (version, alg, hkdf) = (secrets.version, secrets.quic, secrets.suite.hkdf_provider);
809 Self {
810 local: KeyBuilder::new(local, version, alg, hkdf).packet_key(),
811 remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(),
812 }
813 }
814}
815
816pub struct KeyBuilder<'a> {
818 expander: Box<dyn HkdfExpander>,
819 version: Version,
820 alg: &'a dyn Algorithm,
821}
822
823impl<'a> KeyBuilder<'a> {
824 pub fn new(
826 secret: &OkmBlock,
827 version: Version,
828 alg: &'a dyn Algorithm,
829 hkdf: &'a dyn Hkdf,
830 ) -> Self {
831 Self {
832 expander: hkdf.expander_for_okm(secret),
833 version,
834 alg,
835 }
836 }
837
838 pub fn packet_key(&self) -> Box<dyn PacketKey> {
840 let aead_key_len = self.alg.aead_key_len();
841 let packet_key = hkdf_expand_label_aead_key(
842 self.expander.as_ref(),
843 aead_key_len,
844 self.version.packet_key_label(),
845 &[],
846 );
847
848 let packet_iv =
849 hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]);
850 self.alg
851 .packet_key(packet_key, packet_iv)
852 }
853
854 pub fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> {
856 let header_key = hkdf_expand_label_aead_key(
857 self.expander.as_ref(),
858 self.alg.aead_key_len(),
859 self.version.header_key_label(),
860 &[],
861 );
862 self.alg
863 .header_protection_key(header_key)
864 }
865}
866
867#[non_exhaustive]
869#[derive(Clone, Copy)]
870pub struct Suite {
871 pub suite: &'static Tls13CipherSuite,
873 pub quic: &'static dyn Algorithm,
875}
876
877impl Suite {
878 pub fn keys(&self, client_dst_connection_id: &[u8], side: Side, version: Version) -> Keys {
880 Keys::initial(
881 version,
882 self.suite,
883 self.quic,
884 client_dst_connection_id,
885 side,
886 )
887 }
888}
889
890#[expect(clippy::exhaustive_structs)]
892pub struct Keys {
893 pub local: DirectionalKeys,
895 pub remote: DirectionalKeys,
897}
898
899impl Keys {
900 pub fn initial(
902 version: Version,
903 suite: &'static Tls13CipherSuite,
904 quic: &'static dyn Algorithm,
905 client_dst_connection_id: &[u8],
906 side: Side,
907 ) -> Self {
908 const CLIENT_LABEL: &[u8] = b"client in";
909 const SERVER_LABEL: &[u8] = b"server in";
910 let salt = version.initial_salt();
911 let hs_secret = suite
912 .hkdf_provider
913 .extract_from_secret(Some(salt), client_dst_connection_id);
914
915 let secrets = Secrets {
916 version,
917 client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]),
918 server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]),
919 suite,
920 quic,
921 side,
922 };
923 Self::new(&secrets)
924 }
925
926 fn new(secrets: &Secrets) -> Self {
927 let (local, remote) = secrets.local_remote();
928 Self {
929 local: DirectionalKeys::new(secrets.suite, secrets.quic, local, secrets.version),
930 remote: DirectionalKeys::new(secrets.suite, secrets.quic, remote, secrets.version),
931 }
932 }
933}
934
935#[expect(clippy::exhaustive_enums)]
949pub enum KeyChange {
950 Handshake {
952 keys: Keys,
954 },
955 OneRtt {
957 keys: Keys,
959 next: Secrets,
961 },
962}
963
964#[non_exhaustive]
968#[derive(Clone, Copy, Debug, Default)]
969pub enum Version {
970 #[default]
972 V1,
973 V2,
975}
976
977impl Version {
978 fn initial_salt(self) -> &'static [u8; 20] {
979 match self {
980 Self::V1 => &[
981 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
983 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
984 ],
985 Self::V2 => &[
986 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
988 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
989 ],
990 }
991 }
992
993 pub(crate) fn packet_key_label(&self) -> &'static [u8] {
995 match self {
996 Self::V1 => b"quic key",
997 Self::V2 => b"quicv2 key",
998 }
999 }
1000
1001 pub(crate) fn packet_iv_label(&self) -> &'static [u8] {
1003 match self {
1004 Self::V1 => b"quic iv",
1005 Self::V2 => b"quicv2 iv",
1006 }
1007 }
1008
1009 pub(crate) fn header_key_label(&self) -> &'static [u8] {
1011 match self {
1012 Self::V1 => b"quic hp",
1013 Self::V2 => b"quicv2 hp",
1014 }
1015 }
1016
1017 fn key_update_label(&self) -> &'static [u8] {
1018 match self {
1019 Self::V1 => b"quic ku",
1020 Self::V2 => b"quicv2 ku",
1021 }
1022 }
1023}
1024
1025#[cfg(test)]
1026mod tests {
1027 use std::prelude::v1::*;
1028
1029 use super::PacketKey;
1030 use crate::crypto::CipherSuite;
1031 use crate::crypto::tls13::OkmBlock;
1032 use crate::quic::{HeaderProtectionKey, Secrets, Version};
1033 use crate::{Side, TEST_PROVIDERS};
1034
1035 #[test]
1036 fn key_update_test_vector() {
1037 fn equal_okm(x: &OkmBlock, y: &OkmBlock) -> bool {
1038 x.as_ref() == y.as_ref()
1039 }
1040
1041 for provider in TEST_PROVIDERS {
1042 let aes_128_gcm = provider
1043 .tls13_cipher_suites
1044 .iter()
1045 .find(|cs| cs.common.suite == CipherSuite::TLS13_AES_128_GCM_SHA256)
1046 .unwrap();
1047 let quic_suite = aes_128_gcm.quic.unwrap();
1048
1049 let mut secrets = Secrets::new(
1050 OkmBlock::new(
1052 &[
1053 0xb8, 0x76, 0x77, 0x08, 0xf8, 0x77, 0x23, 0x58, 0xa6, 0xea, 0x9f, 0xc4,
1054 0x3e, 0x4a, 0xdd, 0x2c, 0x96, 0x1b, 0x3f, 0x52, 0x87, 0xa6, 0xd1, 0x46,
1055 0x7e, 0xe0, 0xae, 0xab, 0x33, 0x72, 0x4d, 0xbf,
1056 ][..],
1057 ),
1058 OkmBlock::new(
1059 &[
1060 0x42, 0xdc, 0x97, 0x21, 0x40, 0xe0, 0xf2, 0xe3, 0x98, 0x45, 0xb7, 0x67,
1061 0x61, 0x34, 0x39, 0xdc, 0x67, 0x58, 0xca, 0x43, 0x25, 0x9b, 0x87, 0x85,
1062 0x06, 0x82, 0x4e, 0xb1, 0xe4, 0x38, 0xd8, 0x55,
1063 ][..],
1064 ),
1065 aes_128_gcm,
1066 quic_suite,
1067 Side::Client,
1068 Version::V1,
1069 );
1070 secrets.update();
1071
1072 assert!(equal_okm(
1073 &secrets.client,
1074 &OkmBlock::new(
1075 &[
1076 0x42, 0xca, 0xc8, 0xc9, 0x1c, 0xd5, 0xeb, 0x40, 0x68, 0x2e, 0x43, 0x2e,
1077 0xdf, 0x2d, 0x2b, 0xe9, 0xf4, 0x1a, 0x52, 0xca, 0x6b, 0x22, 0xd8, 0xe6,
1078 0xcd, 0xb1, 0xe8, 0xac, 0xa9, 0x6, 0x1f, 0xce
1079 ][..]
1080 )
1081 ));
1082 assert!(equal_okm(
1083 &secrets.server,
1084 &OkmBlock::new(
1085 &[
1086 0xeb, 0x7f, 0x5e, 0x2a, 0x12, 0x3f, 0x40, 0x7d, 0xb4, 0x99, 0xe3, 0x61,
1087 0xca, 0xe5, 0x90, 0xd4, 0xd9, 0x92, 0xe1, 0x4b, 0x7a, 0xce, 0x3, 0xc2,
1088 0x44, 0xe0, 0x42, 0x21, 0x15, 0xb6, 0xd3, 0x8a
1089 ][..]
1090 )
1091 ));
1092 }
1093 }
1094
1095 #[test]
1096 fn auto_traits() {
1097 fn assert_auto<T: Send + Sync>() {}
1098 assert_auto::<Box<dyn PacketKey>>();
1099 assert_auto::<Box<dyn HeaderProtectionKey>>();
1100 }
1101}