1use alloc::boxed::Box;
2use alloc::collections::VecDeque;
3use alloc::vec::Vec;
4#[cfg(feature = "std")]
5use core::fmt::Debug;
6
7use pki_types::FipsStatus;
8
9pub use crate::common_state::Side;
10use crate::common_state::{Event, Output};
11use crate::crypto::cipher::{AeadKey, Iv};
12use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock};
13use crate::error::Error;
14use crate::msgs::{Message, MessagePayload};
15use crate::tls13::Tls13CipherSuite;
16use crate::tls13::key_schedule::{
17 hkdf_expand_label, hkdf_expand_label_aead_key, hkdf_expand_label_block,
18};
19
20#[cfg(feature = "std")]
21mod connection {
22 use alloc::vec::Vec;
23 use core::fmt::{self, Debug};
24 use core::ops::{Deref, DerefMut};
25
26 use pki_types::{DnsName, ServerName};
27
28 use super::{DirectionalKeys, KeyChange, Version};
29 use crate::client::{ClientConfig, ClientConnectionData};
30 use crate::common_state::{CommonState, Protocol};
31 use crate::conn::{ConnectionCore, KeyingMaterialExporter, SideData};
32 use crate::crypto::cipher::{EncodedMessage, Payload};
33 use crate::enums::{ApplicationProtocol, ContentType, ProtocolVersion};
34 use crate::error::{ApiMisuse, Error};
35 use crate::msgs::{
36 ClientExtensionsInput, DeframerVecBuffer, Locator, ServerExtensionsInput,
37 TransportParameters,
38 };
39 use crate::server::{ServerConfig, ServerConnectionData};
40 use crate::suites::SupportedCipherSuite;
41 use crate::sync::Arc;
42
43 #[expect(clippy::exhaustive_enums)]
45 #[derive(Debug)]
46 pub enum Connection {
47 Client(ClientConnection),
49 Server(ServerConnection),
51 }
52
53 impl Connection {
54 pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
58 match self {
59 Self::Client(conn) => conn.quic_transport_parameters(),
60 Self::Server(conn) => conn.quic_transport_parameters(),
61 }
62 }
63
64 pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
66 match self {
67 Self::Client(conn) => conn.zero_rtt_keys(),
68 Self::Server(conn) => conn.zero_rtt_keys(),
69 }
70 }
71
72 pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
76 match self {
77 Self::Client(conn) => conn.read_hs(plaintext),
78 Self::Server(conn) => conn.read_hs(plaintext),
79 }
80 }
81
82 pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
86 match self {
87 Self::Client(conn) => conn.write_hs(buf),
88 Self::Server(conn) => conn.write_hs(buf),
89 }
90 }
91 }
92
93 impl Deref for Connection {
94 type Target = CommonState;
95
96 fn deref(&self) -> &Self::Target {
97 match self {
98 Self::Client(conn) => &conn.core.side,
99 Self::Server(conn) => &conn.core.side,
100 }
101 }
102 }
103
104 impl DerefMut for Connection {
105 fn deref_mut(&mut self) -> &mut Self::Target {
106 match self {
107 Self::Client(conn) => &mut conn.core.side,
108 Self::Server(conn) => &mut conn.core.side,
109 }
110 }
111 }
112
113 pub struct ClientConnection {
115 inner: ConnectionCommon<ClientConnectionData>,
116 }
117
118 impl ClientConnection {
119 pub fn new(
124 config: Arc<ClientConfig>,
125 quic_version: Version,
126 name: ServerName<'static>,
127 params: Vec<u8>,
128 ) -> Result<Self, Error> {
129 Self::new_with_alpn(
130 config.clone(),
131 quic_version,
132 name,
133 params,
134 config.alpn_protocols.clone(),
135 )
136 }
137
138 pub fn new_with_alpn(
140 config: Arc<ClientConfig>,
141 quic_version: Version,
142 name: ServerName<'static>,
143 params: Vec<u8>,
144 alpn_protocols: Vec<ApplicationProtocol<'static>>,
145 ) -> Result<Self, Error> {
146 let suites = &config.provider().tls13_cipher_suites;
147 if suites.is_empty() {
148 return Err(ApiMisuse::QuicRequiresTls13Support.into());
149 }
150
151 if !suites
152 .iter()
153 .any(|scs| scs.quic.is_some())
154 {
155 return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
156 }
157
158 let exts = ClientExtensionsInput {
159 transport_parameters: Some(match quic_version {
160 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
161 }),
162
163 ..ClientExtensionsInput::from_alpn(alpn_protocols)
164 };
165
166 let inner =
167 ConnectionCore::for_client(config, name, exts, Protocol::Quic(quic_version))?;
168 Ok(Self {
169 inner: ConnectionCommon::new(inner, quic_version),
170 })
171 }
172
173 pub fn is_early_data_accepted(&self) -> bool {
179 self.inner.core.is_early_data_accepted()
180 }
181
182 pub fn tls13_tickets_received(&self) -> u32 {
184 self.inner.tls13_tickets_received
185 }
186
187 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
201 self.core.exporter()
202 }
203 }
204
205 impl Deref for ClientConnection {
206 type Target = ConnectionCommon<ClientConnectionData>;
207
208 fn deref(&self) -> &Self::Target {
209 &self.inner
210 }
211 }
212
213 impl DerefMut for ClientConnection {
214 fn deref_mut(&mut self) -> &mut Self::Target {
215 &mut self.inner
216 }
217 }
218
219 impl Debug for ClientConnection {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 f.debug_struct("quic::ClientConnection")
222 .finish_non_exhaustive()
223 }
224 }
225
226 impl From<ClientConnection> for Connection {
227 fn from(c: ClientConnection) -> Self {
228 Self::Client(c)
229 }
230 }
231
232 pub struct ServerConnection {
234 inner: ConnectionCommon<ServerConnectionData>,
235 }
236
237 impl ServerConnection {
238 pub fn new(
243 config: Arc<ServerConfig>,
244 quic_version: Version,
245 params: Vec<u8>,
246 ) -> Result<Self, Error> {
247 let suites = &config.provider.tls13_cipher_suites;
248 if suites.is_empty() {
249 return Err(ApiMisuse::QuicRequiresTls13Support.into());
250 }
251
252 if !suites
253 .iter()
254 .any(|scs| scs.quic.is_some())
255 {
256 return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
257 }
258
259 if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff {
260 return Err(ApiMisuse::QuicRestrictsMaxEarlyDataSize.into());
261 }
262
263 let exts = ServerExtensionsInput {
264 transport_parameters: Some(match quic_version {
265 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
266 }),
267 };
268
269 let core = ConnectionCore::for_server(config, exts, Protocol::Quic(quic_version))?;
270 let inner = ConnectionCommon::new(core, quic_version);
271 Ok(Self { inner })
272 }
273
274 pub fn server_name(&self) -> Option<&DnsName<'_>> {
290 self.inner.core.side.server_name()
291 }
292
293 pub fn set_resumption_data(&mut self, resumption_data: &[u8]) -> Result<(), Error> {
302 assert!(resumption_data.len() < 2usize.pow(15));
303 match &mut self.inner.core.state {
304 Ok(st) => st.set_resumption_data(resumption_data),
305 Err(e) => Err(e.clone()),
306 }
307 }
308
309 pub fn received_resumption_data(&self) -> Option<&[u8]> {
313 self.inner
314 .core
315 .side
316 .received_resumption_data()
317 }
318
319 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
333 self.core.exporter()
334 }
335 }
336
337 impl Deref for ServerConnection {
338 type Target = ConnectionCommon<ServerConnectionData>;
339
340 fn deref(&self) -> &Self::Target {
341 &self.inner
342 }
343 }
344
345 impl DerefMut for ServerConnection {
346 fn deref_mut(&mut self) -> &mut Self::Target {
347 &mut self.inner
348 }
349 }
350
351 impl Debug for ServerConnection {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 f.debug_struct("quic::ServerConnection")
354 .finish_non_exhaustive()
355 }
356 }
357
358 impl From<ServerConnection> for Connection {
359 fn from(c: ServerConnection) -> Self {
360 Self::Server(c)
361 }
362 }
363
364 pub struct ConnectionCommon<Side: SideData> {
366 core: ConnectionCore<Side>,
367 deframer_buffer: DeframerVecBuffer,
368 version: Version,
369 }
370
371 impl<Side: SideData> ConnectionCommon<Side> {
372 fn new(core: ConnectionCore<Side>, version: Version) -> Self {
373 Self {
374 core,
375 deframer_buffer: DeframerVecBuffer::default(),
376 version,
377 }
378 }
379
380 pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
388 self.core
389 .side
390 .quic
391 .params
392 .as_ref()
393 .map(|v| v.as_ref())
394 }
395
396 pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
398 let suite = self
399 .core
400 .side
401 .negotiated_cipher_suite()
402 .and_then(|suite| match suite {
403 SupportedCipherSuite::Tls13(suite) => Some(suite),
404 _ => None,
405 })?;
406
407 Some(DirectionalKeys::new(
408 suite,
409 suite.quic?,
410 self.core
411 .side
412 .quic
413 .early_secret
414 .as_ref()?,
415 self.version,
416 ))
417 }
418
419 pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
428 let range = self.deframer_buffer.extend(plaintext);
429
430 self.core.hs_deframer.input_message(
431 EncodedMessage {
432 typ: ContentType::Handshake,
433 version: ProtocolVersion::TLSv1_3,
434 payload: &self.deframer_buffer.filled()[range.clone()],
435 },
436 &Locator::new(self.deframer_buffer.filled()),
437 range.end,
438 );
439
440 self.core
441 .hs_deframer
442 .coalesce(self.deframer_buffer.filled_mut())?;
443
444 self.core
445 .process_new_packets(&mut self.deframer_buffer)?;
446
447 Ok(())
448 }
449
450 pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
454 self.core.side.quic.write_hs(buf)
455 }
456 }
457
458 impl<Side: SideData> Deref for ConnectionCommon<Side> {
459 type Target = CommonState;
460
461 fn deref(&self) -> &Self::Target {
462 &self.core.side
463 }
464 }
465
466 impl<Side: SideData> DerefMut for ConnectionCommon<Side> {
467 fn deref_mut(&mut self) -> &mut Self::Target {
468 &mut self.core.side
469 }
470 }
471}
472
473#[cfg(feature = "std")]
474pub use connection::{ClientConnection, Connection, ConnectionCommon, ServerConnection};
475
476#[derive(Default)]
477pub(crate) struct Quic {
478 pub(crate) params: Option<Vec<u8>>,
480 pub(crate) hs_queue: VecDeque<(bool, Vec<u8>)>,
481 pub(crate) early_secret: Option<OkmBlock>,
482 pub(crate) hs_secrets: Option<Secrets>,
483 pub(crate) traffic_secrets: Option<Secrets>,
484 #[cfg(feature = "std")]
486 pub(crate) returned_traffic_keys: bool,
487}
488
489impl Quic {
490 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
491 if let MessagePayload::Alert(_) = m.payload {
492 return;
494 }
495
496 debug_assert!(
497 matches!(
498 m.payload,
499 MessagePayload::Handshake { .. } | MessagePayload::HandshakeFlight(_)
500 ),
501 "QUIC uses TLS for the cryptographic handshake only"
502 );
503 let mut bytes = Vec::new();
504 m.payload.encode(&mut bytes);
505 self.hs_queue
506 .push_back((must_encrypt, bytes));
507 }
508}
509
510#[cfg(feature = "std")]
511impl Quic {
512 pub(crate) fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
513 while let Some((_, msg)) = self.hs_queue.pop_front() {
514 buf.extend_from_slice(&msg);
515 if let Some(&(true, _)) = self.hs_queue.front() {
516 if self.hs_secrets.is_some() {
517 break;
519 }
520 }
521 }
522
523 if let Some(secrets) = self.hs_secrets.take() {
524 return Some(KeyChange::Handshake {
525 keys: Keys::new(&secrets),
526 });
527 }
528
529 if let Some(mut secrets) = self.traffic_secrets.take() {
530 if !self.returned_traffic_keys {
531 self.returned_traffic_keys = true;
532 let keys = Keys::new(&secrets);
533 secrets.update();
534 return Some(KeyChange::OneRtt {
535 keys,
536 next: secrets,
537 });
538 }
539 }
540
541 None
542 }
543}
544
545impl Output for Quic {
546 fn emit(&mut self, ev: Event<'_>) {
547 match ev {
548 Event::EncryptMessage(m) => self.send_msg(m, true),
549 Event::QuicEarlySecret(sec) => self.early_secret = sec,
550 Event::QuicHandshakeSecrets(sec) => self.hs_secrets = Some(sec),
551 Event::QuicTrafficSecrets(sec) => self.traffic_secrets = Some(sec),
552 Event::QuicTransportParameters(params) => self.params = Some(params),
553 Event::PlainMessage(m) => self.send_msg(m, false),
554 _ => {}
555 }
556 }
557}
558
559#[derive(Clone)]
561pub struct Secrets {
562 pub(crate) client: OkmBlock,
564 pub(crate) server: OkmBlock,
566 suite: &'static Tls13CipherSuite,
568 quic: &'static dyn Algorithm,
569 side: Side,
570 version: Version,
571}
572
573impl Secrets {
574 pub(crate) fn new(
575 client: OkmBlock,
576 server: OkmBlock,
577 suite: &'static Tls13CipherSuite,
578 quic: &'static dyn Algorithm,
579 side: Side,
580 version: Version,
581 ) -> Self {
582 Self {
583 client,
584 server,
585 suite,
586 quic,
587 side,
588 version,
589 }
590 }
591
592 pub fn next_packet_keys(&mut self) -> PacketKeySet {
594 let keys = PacketKeySet::new(self);
595 self.update();
596 keys
597 }
598
599 pub(crate) fn update(&mut self) {
600 self.client = hkdf_expand_label_block(
601 self.suite
602 .hkdf_provider
603 .expander_for_okm(&self.client)
604 .as_ref(),
605 self.version.key_update_label(),
606 &[],
607 );
608 self.server = hkdf_expand_label_block(
609 self.suite
610 .hkdf_provider
611 .expander_for_okm(&self.server)
612 .as_ref(),
613 self.version.key_update_label(),
614 &[],
615 );
616 }
617
618 fn local_remote(&self) -> (&OkmBlock, &OkmBlock) {
619 match self.side {
620 Side::Client => (&self.client, &self.server),
621 Side::Server => (&self.server, &self.client),
622 }
623 }
624}
625
626#[expect(clippy::exhaustive_structs)]
628pub struct DirectionalKeys {
629 pub header: Box<dyn HeaderProtectionKey>,
631 pub packet: Box<dyn PacketKey>,
633}
634
635impl DirectionalKeys {
636 pub(crate) fn new(
637 suite: &'static Tls13CipherSuite,
638 quic: &'static dyn Algorithm,
639 secret: &OkmBlock,
640 version: Version,
641 ) -> Self {
642 let builder = KeyBuilder::new(secret, version, quic, suite.hkdf_provider);
643 Self {
644 header: builder.header_protection_key(),
645 packet: builder.packet_key(),
646 }
647 }
648}
649
650const TAG_LEN: usize = 16;
652
653pub struct Tag([u8; TAG_LEN]);
655
656impl From<&[u8]> for Tag {
657 fn from(value: &[u8]) -> Self {
658 let mut array = [0u8; TAG_LEN];
659 array.copy_from_slice(value);
660 Self(array)
661 }
662}
663
664impl AsRef<[u8]> for Tag {
665 fn as_ref(&self) -> &[u8] {
666 &self.0
667 }
668}
669
670pub trait Algorithm: Send + Sync {
672 fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn PacketKey>;
677
678 fn header_protection_key(&self, key: AeadKey) -> Box<dyn HeaderProtectionKey>;
682
683 fn aead_key_len(&self) -> usize;
687
688 fn fips(&self) -> FipsStatus {
690 FipsStatus::Unvalidated
691 }
692}
693
694pub trait HeaderProtectionKey: Send + Sync {
696 fn encrypt_in_place(
717 &self,
718 sample: &[u8],
719 first: &mut u8,
720 packet_number: &mut [u8],
721 ) -> Result<(), Error>;
722
723 fn decrypt_in_place(
745 &self,
746 sample: &[u8],
747 first: &mut u8,
748 packet_number: &mut [u8],
749 ) -> Result<(), Error>;
750
751 fn sample_len(&self) -> usize;
753}
754
755pub trait PacketKey: Send + Sync {
757 fn encrypt_in_place(
768 &self,
769 packet_number: u64,
770 header: &[u8],
771 payload: &mut [u8],
772 path_id: Option<u32>,
773 ) -> Result<Tag, Error>;
774
775 fn decrypt_in_place<'a>(
786 &self,
787 packet_number: u64,
788 header: &[u8],
789 payload: &'a mut [u8],
790 path_id: Option<u32>,
791 ) -> Result<&'a [u8], Error>;
792
793 fn tag_len(&self) -> usize;
795
796 fn confidentiality_limit(&self) -> u64;
807
808 fn integrity_limit(&self) -> u64;
817}
818
819#[expect(clippy::exhaustive_structs)]
821pub struct PacketKeySet {
822 pub local: Box<dyn PacketKey>,
824 pub remote: Box<dyn PacketKey>,
826}
827
828impl PacketKeySet {
829 fn new(secrets: &Secrets) -> Self {
830 let (local, remote) = secrets.local_remote();
831 let (version, alg, hkdf) = (secrets.version, secrets.quic, secrets.suite.hkdf_provider);
832 Self {
833 local: KeyBuilder::new(local, version, alg, hkdf).packet_key(),
834 remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(),
835 }
836 }
837}
838
839pub struct KeyBuilder<'a> {
841 expander: Box<dyn HkdfExpander>,
842 version: Version,
843 alg: &'a dyn Algorithm,
844}
845
846impl<'a> KeyBuilder<'a> {
847 pub fn new(
849 secret: &OkmBlock,
850 version: Version,
851 alg: &'a dyn Algorithm,
852 hkdf: &'a dyn Hkdf,
853 ) -> Self {
854 Self {
855 expander: hkdf.expander_for_okm(secret),
856 version,
857 alg,
858 }
859 }
860
861 pub fn packet_key(&self) -> Box<dyn PacketKey> {
863 let aead_key_len = self.alg.aead_key_len();
864 let packet_key = hkdf_expand_label_aead_key(
865 self.expander.as_ref(),
866 aead_key_len,
867 self.version.packet_key_label(),
868 &[],
869 );
870
871 let packet_iv =
872 hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]);
873 self.alg
874 .packet_key(packet_key, packet_iv)
875 }
876
877 pub fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> {
879 let header_key = hkdf_expand_label_aead_key(
880 self.expander.as_ref(),
881 self.alg.aead_key_len(),
882 self.version.header_key_label(),
883 &[],
884 );
885 self.alg
886 .header_protection_key(header_key)
887 }
888}
889
890#[non_exhaustive]
892#[derive(Clone, Copy)]
893pub struct Suite {
894 pub suite: &'static Tls13CipherSuite,
896 pub quic: &'static dyn Algorithm,
898}
899
900impl Suite {
901 pub fn keys(&self, client_dst_connection_id: &[u8], side: Side, version: Version) -> Keys {
903 Keys::initial(
904 version,
905 self.suite,
906 self.quic,
907 client_dst_connection_id,
908 side,
909 )
910 }
911}
912
913#[expect(clippy::exhaustive_structs)]
915pub struct Keys {
916 pub local: DirectionalKeys,
918 pub remote: DirectionalKeys,
920}
921
922impl Keys {
923 pub fn initial(
925 version: Version,
926 suite: &'static Tls13CipherSuite,
927 quic: &'static dyn Algorithm,
928 client_dst_connection_id: &[u8],
929 side: Side,
930 ) -> Self {
931 const CLIENT_LABEL: &[u8] = b"client in";
932 const SERVER_LABEL: &[u8] = b"server in";
933 let salt = version.initial_salt();
934 let hs_secret = suite
935 .hkdf_provider
936 .extract_from_secret(Some(salt), client_dst_connection_id);
937
938 let secrets = Secrets {
939 client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]),
940 server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]),
941 suite,
942 quic,
943 side,
944 version,
945 };
946 Self::new(&secrets)
947 }
948
949 fn new(secrets: &Secrets) -> Self {
950 let (local, remote) = secrets.local_remote();
951 Self {
952 local: DirectionalKeys::new(secrets.suite, secrets.quic, local, secrets.version),
953 remote: DirectionalKeys::new(secrets.suite, secrets.quic, remote, secrets.version),
954 }
955 }
956}
957
958#[expect(clippy::exhaustive_enums)]
972pub enum KeyChange {
973 Handshake {
975 keys: Keys,
977 },
978 OneRtt {
980 keys: Keys,
982 next: Secrets,
984 },
985}
986
987#[non_exhaustive]
991#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
992pub enum Version {
993 #[default]
995 V1,
996 V2,
998}
999
1000impl Version {
1001 fn initial_salt(self) -> &'static [u8; 20] {
1002 match self {
1003 Self::V1 => &[
1004 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
1006 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
1007 ],
1008 Self::V2 => &[
1009 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
1011 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
1012 ],
1013 }
1014 }
1015
1016 pub(crate) fn packet_key_label(&self) -> &'static [u8] {
1018 match self {
1019 Self::V1 => b"quic key",
1020 Self::V2 => b"quicv2 key",
1021 }
1022 }
1023
1024 pub(crate) fn packet_iv_label(&self) -> &'static [u8] {
1026 match self {
1027 Self::V1 => b"quic iv",
1028 Self::V2 => b"quicv2 iv",
1029 }
1030 }
1031
1032 pub(crate) fn header_key_label(&self) -> &'static [u8] {
1034 match self {
1035 Self::V1 => b"quic hp",
1036 Self::V2 => b"quicv2 hp",
1037 }
1038 }
1039
1040 fn key_update_label(&self) -> &'static [u8] {
1041 match self {
1042 Self::V1 => b"quic ku",
1043 Self::V2 => b"quicv2 ku",
1044 }
1045 }
1046}
1047
1048#[cfg(all(test, any(target_arch = "aarch64", target_arch = "x86_64")))]
1049mod tests {
1050 use super::*;
1051 use crate::crypto::TLS13_TEST_SUITE;
1052 use crate::crypto::tls13::OkmBlock;
1053 use crate::quic::{HeaderProtectionKey, Secrets, Side, Version};
1054
1055 #[test]
1056 fn key_update_test_vector() {
1057 fn equal_okm(x: &OkmBlock, y: &OkmBlock) -> bool {
1058 x.as_ref() == y.as_ref()
1059 }
1060
1061 let mut secrets = Secrets {
1062 client: OkmBlock::new(
1064 &[
1065 0xb8, 0x76, 0x77, 0x08, 0xf8, 0x77, 0x23, 0x58, 0xa6, 0xea, 0x9f, 0xc4, 0x3e,
1066 0x4a, 0xdd, 0x2c, 0x96, 0x1b, 0x3f, 0x52, 0x87, 0xa6, 0xd1, 0x46, 0x7e, 0xe0,
1067 0xae, 0xab, 0x33, 0x72, 0x4d, 0xbf,
1068 ][..],
1069 ),
1070 server: OkmBlock::new(
1071 &[
1072 0x42, 0xdc, 0x97, 0x21, 0x40, 0xe0, 0xf2, 0xe3, 0x98, 0x45, 0xb7, 0x67, 0x61,
1073 0x34, 0x39, 0xdc, 0x67, 0x58, 0xca, 0x43, 0x25, 0x9b, 0x87, 0x85, 0x06, 0x82,
1074 0x4e, 0xb1, 0xe4, 0x38, 0xd8, 0x55,
1075 ][..],
1076 ),
1077 suite: TLS13_TEST_SUITE,
1078 quic: &FakeAlgorithm,
1079 side: Side::Client,
1080 version: Version::V1,
1081 };
1082 secrets.update();
1083
1084 assert!(equal_okm(
1085 &secrets.client,
1086 &OkmBlock::new(
1087 &[
1088 0x42, 0xca, 0xc8, 0xc9, 0x1c, 0xd5, 0xeb, 0x40, 0x68, 0x2e, 0x43, 0x2e, 0xdf,
1089 0x2d, 0x2b, 0xe9, 0xf4, 0x1a, 0x52, 0xca, 0x6b, 0x22, 0xd8, 0xe6, 0xcd, 0xb1,
1090 0xe8, 0xac, 0xa9, 0x6, 0x1f, 0xce
1091 ][..]
1092 )
1093 ));
1094 assert!(equal_okm(
1095 &secrets.server,
1096 &OkmBlock::new(
1097 &[
1098 0xeb, 0x7f, 0x5e, 0x2a, 0x12, 0x3f, 0x40, 0x7d, 0xb4, 0x99, 0xe3, 0x61, 0xca,
1099 0xe5, 0x90, 0xd4, 0xd9, 0x92, 0xe1, 0x4b, 0x7a, 0xce, 0x3, 0xc2, 0x44, 0xe0,
1100 0x42, 0x21, 0x15, 0xb6, 0xd3, 0x8a
1101 ][..]
1102 )
1103 ));
1104 }
1105
1106 struct FakeAlgorithm;
1107
1108 impl Algorithm for FakeAlgorithm {
1109 fn packet_key(&self, _key: AeadKey, _iv: Iv) -> Box<dyn PacketKey> {
1110 unimplemented!()
1111 }
1112
1113 fn header_protection_key(&self, _key: AeadKey) -> Box<dyn HeaderProtectionKey> {
1114 unimplemented!()
1115 }
1116
1117 fn aead_key_len(&self) -> usize {
1118 16
1119 }
1120 }
1121
1122 #[test]
1123 fn auto_traits() {
1124 fn assert_auto<T: Send + Sync>() {}
1125 assert_auto::<Box<dyn PacketKey>>();
1126 assert_auto::<Box<dyn HeaderProtectionKey>>();
1127 }
1128}