1use alloc::boxed::Box;
2use alloc::collections::VecDeque;
3use alloc::vec::Vec;
4use core::fmt::Debug;
5
6use pki_types::FipsStatus;
7
8pub use crate::common_state::Side;
9use crate::common_state::{Event, Output};
10use crate::crypto::cipher::{AeadKey, Iv};
11use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock};
12use crate::error::Error;
13use crate::msgs::{Message, MessagePayload};
14use crate::tls13::Tls13CipherSuite;
15use crate::tls13::key_schedule::{
16 hkdf_expand_label, hkdf_expand_label_aead_key, hkdf_expand_label_block,
17};
18
19mod connection {
20 use alloc::vec::Vec;
21 use core::fmt::{self, Debug};
22 use core::ops::{Deref, DerefMut};
23
24 use pki_types::{DnsName, ServerName};
25
26 use super::{DirectionalKeys, KeyChange, Version};
27 use crate::ConnectionOutputs;
28 use crate::client::{ClientConfig, ClientSide};
29 use crate::common_state::{CommonState, JoinOutput, Protocol};
30 use crate::conn::{ConnectionCore, KeyingMaterialExporter, SideData, process_new_packets};
31 use crate::crypto::cipher::{EncodedMessage, Payload};
32 use crate::enums::{ApplicationProtocol, ContentType, ProtocolVersion};
33 use crate::error::{ApiMisuse, Error};
34 use crate::msgs::{
35 ClientExtensionsInput, DeframerVecBuffer, Locator, ServerExtensionsInput,
36 TransportParameters,
37 };
38 use crate::server::{ServerConfig, ServerSide};
39 use crate::suites::SupportedCipherSuite;
40 use crate::sync::Arc;
41
42 pub trait Connection: Debug + Deref<Target = ConnectionOutputs> + DerefMut {
44 fn quic_transport_parameters(&self) -> Option<&[u8]>;
52
53 fn zero_rtt_keys(&self) -> Option<DirectionalKeys>;
55
56 fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error>;
60
61 fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange>;
65
66 fn is_handshaking(&self) -> bool;
68 }
69
70 pub struct ClientConnection {
72 inner: ConnectionCommon<ClientSide>,
73 }
74
75 impl ClientConnection {
76 pub fn new(
81 config: Arc<ClientConfig>,
82 quic_version: Version,
83 name: ServerName<'static>,
84 params: Vec<u8>,
85 ) -> Result<Self, Error> {
86 Self::new_with_alpn(
87 config.clone(),
88 quic_version,
89 name,
90 params,
91 config.alpn_protocols.clone(),
92 )
93 }
94
95 pub fn new_with_alpn(
97 config: Arc<ClientConfig>,
98 quic_version: Version,
99 name: ServerName<'static>,
100 params: Vec<u8>,
101 alpn_protocols: Vec<ApplicationProtocol<'static>>,
102 ) -> Result<Self, Error> {
103 let suites = &config.provider().tls13_cipher_suites;
104 if suites.is_empty() {
105 return Err(ApiMisuse::QuicRequiresTls13Support.into());
106 }
107
108 if !suites
109 .iter()
110 .any(|scs| scs.quic.is_some())
111 {
112 return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
113 }
114
115 let exts = ClientExtensionsInput {
116 transport_parameters: Some(match quic_version {
117 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
118 }),
119
120 ..ClientExtensionsInput::from_alpn(alpn_protocols)
121 };
122
123 let inner =
124 ConnectionCore::for_client(config, name, exts, Protocol::Quic(quic_version))?;
125 Ok(Self {
126 inner: ConnectionCommon::new(inner, quic_version),
127 })
128 }
129
130 pub fn is_early_data_accepted(&self) -> bool {
136 self.inner.core.is_early_data_accepted()
137 }
138
139 pub fn tls13_tickets_received(&self) -> u32 {
141 self.inner
142 .core
143 .common
144 .recv
145 .tls13_tickets_received
146 }
147
148 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
162 self.inner.core.exporter()
163 }
164 }
165
166 impl Connection for ClientConnection {
167 fn quic_transport_parameters(&self) -> Option<&[u8]> {
168 self.inner.quic_transport_parameters()
169 }
170
171 fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
172 self.inner.zero_rtt_keys()
173 }
174
175 fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
176 self.inner.read_hs(plaintext)
177 }
178
179 fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
180 self.inner.write_hs(buf)
181 }
182
183 fn is_handshaking(&self) -> bool {
184 self.inner.is_handshaking()
185 }
186 }
187
188 impl Deref for ClientConnection {
189 type Target = ConnectionOutputs;
190
191 fn deref(&self) -> &Self::Target {
192 &self.inner
193 }
194 }
195
196 impl DerefMut for ClientConnection {
197 fn deref_mut(&mut self) -> &mut Self::Target {
198 &mut self.inner
199 }
200 }
201
202 impl Debug for ClientConnection {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 f.debug_struct("quic::ClientConnection")
205 .finish_non_exhaustive()
206 }
207 }
208
209 pub struct ServerConnection {
211 inner: ConnectionCommon<ServerSide>,
212 }
213
214 impl ServerConnection {
215 pub fn new(
220 config: Arc<ServerConfig>,
221 quic_version: Version,
222 params: Vec<u8>,
223 ) -> Result<Self, Error> {
224 let suites = &config.provider.tls13_cipher_suites;
225 if suites.is_empty() {
226 return Err(ApiMisuse::QuicRequiresTls13Support.into());
227 }
228
229 if !suites
230 .iter()
231 .any(|scs| scs.quic.is_some())
232 {
233 return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
234 }
235
236 if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff {
237 return Err(ApiMisuse::QuicRestrictsMaxEarlyDataSize.into());
238 }
239
240 let exts = ServerExtensionsInput {
241 transport_parameters: Some(match quic_version {
242 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
243 }),
244 };
245
246 let core = ConnectionCore::for_server(config, exts, Protocol::Quic(quic_version))?;
247 let inner = ConnectionCommon::new(core, quic_version);
248 Ok(Self { inner })
249 }
250
251 pub fn server_name(&self) -> Option<&DnsName<'_>> {
267 self.inner.core.side.server_name()
268 }
269
270 pub fn set_resumption_data(&mut self, resumption_data: &[u8]) -> Result<(), Error> {
279 assert!(resumption_data.len() < 2usize.pow(15));
280 match &mut self.inner.core.state {
281 Ok(st) => st.set_resumption_data(resumption_data),
282 Err(e) => Err(e.clone()),
283 }
284 }
285
286 pub fn received_resumption_data(&self) -> Option<&[u8]> {
290 self.inner
291 .core
292 .side
293 .received_resumption_data()
294 }
295
296 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
310 self.inner.core.exporter()
311 }
312 }
313
314 impl Connection for ServerConnection {
315 fn quic_transport_parameters(&self) -> Option<&[u8]> {
316 self.inner.quic_transport_parameters()
317 }
318
319 fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
320 self.inner.zero_rtt_keys()
321 }
322
323 fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
324 self.inner.read_hs(plaintext)
325 }
326
327 fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
328 self.inner.write_hs(buf)
329 }
330
331 fn is_handshaking(&self) -> bool {
332 self.inner.is_handshaking()
333 }
334 }
335
336 impl Deref for ServerConnection {
337 type Target = ConnectionOutputs;
338
339 fn deref(&self) -> &Self::Target {
340 &self.inner
341 }
342 }
343
344 impl DerefMut for ServerConnection {
345 fn deref_mut(&mut self) -> &mut Self::Target {
346 &mut self.inner
347 }
348 }
349
350 impl Debug for ServerConnection {
351 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352 f.debug_struct("quic::ServerConnection")
353 .finish_non_exhaustive()
354 }
355 }
356
357 struct ConnectionCommon<Side: SideData> {
359 core: ConnectionCore<Side>,
360 deframer_buffer: DeframerVecBuffer,
361 version: Version,
362 }
363
364 impl<Side: SideData> ConnectionCommon<Side> {
365 fn new(core: ConnectionCore<Side>, version: Version) -> Self {
366 Self {
367 core,
368 deframer_buffer: DeframerVecBuffer::default(),
369 version,
370 }
371 }
372
373 fn quic_transport_parameters(&self) -> Option<&[u8]> {
374 self.core
375 .common
376 .quic
377 .params
378 .as_ref()
379 .map(|v| v.as_ref())
380 }
381
382 fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
383 let suite = self
384 .core
385 .common
386 .negotiated_cipher_suite()
387 .and_then(|suite| match suite {
388 SupportedCipherSuite::Tls13(suite) => Some(suite),
389 _ => None,
390 })?;
391
392 Some(DirectionalKeys::new(
393 suite,
394 suite.quic?,
395 self.core
396 .common
397 .quic
398 .early_secret
399 .as_ref()?,
400 self.version,
401 ))
402 }
403
404 fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
405 let range = self.deframer_buffer.extend(plaintext);
406
407 self.core
408 .common
409 .recv
410 .hs_deframer
411 .input_message(
412 EncodedMessage {
413 typ: ContentType::Handshake,
414 version: ProtocolVersion::TLSv1_3,
415 payload: &self.deframer_buffer.filled()[range.clone()],
416 },
417 &Locator::new(self.deframer_buffer.filled()),
418 range.end,
419 );
420
421 self.core
422 .common
423 .recv
424 .hs_deframer
425 .coalesce(self.deframer_buffer.filled_mut())?;
426
427 process_new_packets::<Side>(
428 &mut self.deframer_buffer,
429 &mut self.core.state,
430 &mut self.core.common.recv,
431 &mut JoinOutput {
432 outputs: &mut self.core.common.outputs,
433 protocol: self.core.common.protocol,
434 quic: &mut self.core.common.quic,
435 send: &mut self.core.common.send,
436 side: &mut self.core.side,
437 },
438 )?;
439
440 Ok(())
441 }
442
443 fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
444 self.core.common.quic.write_hs(buf)
445 }
446 }
447
448 impl<Side: SideData> Deref for ConnectionCommon<Side> {
449 type Target = CommonState;
450
451 fn deref(&self) -> &Self::Target {
452 &self.core.common
453 }
454 }
455
456 impl<Side: SideData> DerefMut for ConnectionCommon<Side> {
457 fn deref_mut(&mut self) -> &mut Self::Target {
458 &mut self.core.common
459 }
460 }
461}
462
463pub use connection::{ClientConnection, Connection, ServerConnection};
464
465#[derive(Default)]
466pub(crate) struct Quic {
467 pub(crate) params: Option<Vec<u8>>,
469 pub(crate) hs_queue: VecDeque<(bool, Vec<u8>)>,
470 pub(crate) early_secret: Option<OkmBlock>,
471 pub(crate) hs_secrets: Option<Secrets>,
472 pub(crate) traffic_secrets: Option<Secrets>,
473 pub(crate) returned_traffic_keys: bool,
475}
476
477impl Quic {
478 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
479 if let MessagePayload::Alert(_) = m.payload {
480 return;
482 }
483
484 debug_assert!(
485 matches!(
486 m.payload,
487 MessagePayload::Handshake { .. } | MessagePayload::HandshakeFlight(_)
488 ),
489 "QUIC uses TLS for the cryptographic handshake only"
490 );
491 let mut bytes = Vec::new();
492 m.payload.encode(&mut bytes);
493 self.hs_queue
494 .push_back((must_encrypt, bytes));
495 }
496}
497
498impl Quic {
499 pub(crate) fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
500 while let Some((_, msg)) = self.hs_queue.pop_front() {
501 buf.extend_from_slice(&msg);
502 if let Some(&(true, _)) = self.hs_queue.front() {
503 if self.hs_secrets.is_some() {
504 break;
506 }
507 }
508 }
509
510 if let Some(secrets) = self.hs_secrets.take() {
511 return Some(KeyChange::Handshake {
512 keys: Keys::new(&secrets),
513 });
514 }
515
516 if let Some(mut secrets) = self.traffic_secrets.take() {
517 if !self.returned_traffic_keys {
518 self.returned_traffic_keys = true;
519 let keys = Keys::new(&secrets);
520 secrets.update();
521 return Some(KeyChange::OneRtt {
522 keys,
523 next: secrets,
524 });
525 }
526 }
527
528 None
529 }
530}
531
532impl Output for Quic {
533 fn emit(&mut self, ev: Event<'_>) {
534 match ev {
535 Event::EncryptMessage(m) => self.send_msg(m, true),
536 Event::QuicEarlySecret(sec) => self.early_secret = sec,
537 Event::QuicHandshakeSecrets(sec) => self.hs_secrets = Some(sec),
538 Event::QuicTrafficSecrets(sec) => self.traffic_secrets = Some(sec),
539 Event::QuicTransportParameters(params) => self.params = Some(params),
540 Event::PlainMessage(m) => self.send_msg(m, false),
541 _ => {}
542 }
543 }
544}
545
546#[derive(Clone)]
548pub struct Secrets {
549 pub(crate) client: OkmBlock,
551 pub(crate) server: OkmBlock,
553 suite: &'static Tls13CipherSuite,
555 quic: &'static dyn Algorithm,
556 side: Side,
557 version: Version,
558}
559
560impl Secrets {
561 pub(crate) fn new(
562 client: OkmBlock,
563 server: OkmBlock,
564 suite: &'static Tls13CipherSuite,
565 quic: &'static dyn Algorithm,
566 side: Side,
567 version: Version,
568 ) -> Self {
569 Self {
570 client,
571 server,
572 suite,
573 quic,
574 side,
575 version,
576 }
577 }
578
579 pub fn next_packet_keys(&mut self) -> PacketKeySet {
581 let keys = PacketKeySet::new(self);
582 self.update();
583 keys
584 }
585
586 pub(crate) fn update(&mut self) {
587 self.client = hkdf_expand_label_block(
588 self.suite
589 .hkdf_provider
590 .expander_for_okm(&self.client)
591 .as_ref(),
592 self.version.key_update_label(),
593 &[],
594 );
595 self.server = hkdf_expand_label_block(
596 self.suite
597 .hkdf_provider
598 .expander_for_okm(&self.server)
599 .as_ref(),
600 self.version.key_update_label(),
601 &[],
602 );
603 }
604
605 fn local_remote(&self) -> (&OkmBlock, &OkmBlock) {
606 match self.side {
607 Side::Client => (&self.client, &self.server),
608 Side::Server => (&self.server, &self.client),
609 }
610 }
611}
612
613#[expect(clippy::exhaustive_structs)]
615pub struct DirectionalKeys {
616 pub header: Box<dyn HeaderProtectionKey>,
618 pub packet: Box<dyn PacketKey>,
620}
621
622impl DirectionalKeys {
623 pub(crate) fn new(
624 suite: &'static Tls13CipherSuite,
625 quic: &'static dyn Algorithm,
626 secret: &OkmBlock,
627 version: Version,
628 ) -> Self {
629 let builder = KeyBuilder::new(secret, version, quic, suite.hkdf_provider);
630 Self {
631 header: builder.header_protection_key(),
632 packet: builder.packet_key(),
633 }
634 }
635}
636
637const TAG_LEN: usize = 16;
639
640pub struct Tag([u8; TAG_LEN]);
642
643impl From<&[u8]> for Tag {
644 fn from(value: &[u8]) -> Self {
645 let mut array = [0u8; TAG_LEN];
646 array.copy_from_slice(value);
647 Self(array)
648 }
649}
650
651impl AsRef<[u8]> for Tag {
652 fn as_ref(&self) -> &[u8] {
653 &self.0
654 }
655}
656
657pub trait Algorithm: Send + Sync {
659 fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn PacketKey>;
664
665 fn header_protection_key(&self, key: AeadKey) -> Box<dyn HeaderProtectionKey>;
669
670 fn aead_key_len(&self) -> usize;
674
675 fn fips(&self) -> FipsStatus {
677 FipsStatus::Unvalidated
678 }
679}
680
681pub trait HeaderProtectionKey: Send + Sync {
683 fn encrypt_in_place(
704 &self,
705 sample: &[u8],
706 first: &mut u8,
707 packet_number: &mut [u8],
708 ) -> Result<(), Error>;
709
710 fn decrypt_in_place(
732 &self,
733 sample: &[u8],
734 first: &mut u8,
735 packet_number: &mut [u8],
736 ) -> Result<(), Error>;
737
738 fn sample_len(&self) -> usize;
740}
741
742pub trait PacketKey: Send + Sync {
744 fn encrypt_in_place(
755 &self,
756 packet_number: u64,
757 header: &[u8],
758 payload: &mut [u8],
759 path_id: Option<u32>,
760 ) -> Result<Tag, Error>;
761
762 fn decrypt_in_place<'a>(
773 &self,
774 packet_number: u64,
775 header: &[u8],
776 payload: &'a mut [u8],
777 path_id: Option<u32>,
778 ) -> Result<&'a [u8], Error>;
779
780 fn tag_len(&self) -> usize;
782
783 fn confidentiality_limit(&self) -> u64;
794
795 fn integrity_limit(&self) -> u64;
804}
805
806#[expect(clippy::exhaustive_structs)]
808pub struct PacketKeySet {
809 pub local: Box<dyn PacketKey>,
811 pub remote: Box<dyn PacketKey>,
813}
814
815impl PacketKeySet {
816 fn new(secrets: &Secrets) -> Self {
817 let (local, remote) = secrets.local_remote();
818 let (version, alg, hkdf) = (secrets.version, secrets.quic, secrets.suite.hkdf_provider);
819 Self {
820 local: KeyBuilder::new(local, version, alg, hkdf).packet_key(),
821 remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(),
822 }
823 }
824}
825
826pub struct KeyBuilder<'a> {
828 expander: Box<dyn HkdfExpander>,
829 version: Version,
830 alg: &'a dyn Algorithm,
831}
832
833impl<'a> KeyBuilder<'a> {
834 pub fn new(
836 secret: &OkmBlock,
837 version: Version,
838 alg: &'a dyn Algorithm,
839 hkdf: &'a dyn Hkdf,
840 ) -> Self {
841 Self {
842 expander: hkdf.expander_for_okm(secret),
843 version,
844 alg,
845 }
846 }
847
848 pub fn packet_key(&self) -> Box<dyn PacketKey> {
850 let aead_key_len = self.alg.aead_key_len();
851 let packet_key = hkdf_expand_label_aead_key(
852 self.expander.as_ref(),
853 aead_key_len,
854 self.version.packet_key_label(),
855 &[],
856 );
857
858 let packet_iv =
859 hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]);
860 self.alg
861 .packet_key(packet_key, packet_iv)
862 }
863
864 pub fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> {
866 let header_key = hkdf_expand_label_aead_key(
867 self.expander.as_ref(),
868 self.alg.aead_key_len(),
869 self.version.header_key_label(),
870 &[],
871 );
872 self.alg
873 .header_protection_key(header_key)
874 }
875}
876
877#[non_exhaustive]
879#[derive(Clone, Copy)]
880pub struct Suite {
881 pub suite: &'static Tls13CipherSuite,
883 pub quic: &'static dyn Algorithm,
885}
886
887impl Suite {
888 pub fn keys(&self, client_dst_connection_id: &[u8], side: Side, version: Version) -> Keys {
890 Keys::initial(
891 version,
892 self.suite,
893 self.quic,
894 client_dst_connection_id,
895 side,
896 )
897 }
898}
899
900#[expect(clippy::exhaustive_structs)]
902pub struct Keys {
903 pub local: DirectionalKeys,
905 pub remote: DirectionalKeys,
907}
908
909impl Keys {
910 pub fn initial(
912 version: Version,
913 suite: &'static Tls13CipherSuite,
914 quic: &'static dyn Algorithm,
915 client_dst_connection_id: &[u8],
916 side: Side,
917 ) -> Self {
918 const CLIENT_LABEL: &[u8] = b"client in";
919 const SERVER_LABEL: &[u8] = b"server in";
920 let salt = version.initial_salt();
921 let hs_secret = suite
922 .hkdf_provider
923 .extract_from_secret(Some(salt), client_dst_connection_id);
924
925 let secrets = Secrets {
926 client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]),
927 server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]),
928 suite,
929 quic,
930 side,
931 version,
932 };
933 Self::new(&secrets)
934 }
935
936 fn new(secrets: &Secrets) -> Self {
937 let (local, remote) = secrets.local_remote();
938 Self {
939 local: DirectionalKeys::new(secrets.suite, secrets.quic, local, secrets.version),
940 remote: DirectionalKeys::new(secrets.suite, secrets.quic, remote, secrets.version),
941 }
942 }
943}
944
945#[expect(clippy::exhaustive_enums)]
959pub enum KeyChange {
960 Handshake {
962 keys: Keys,
964 },
965 OneRtt {
967 keys: Keys,
969 next: Secrets,
971 },
972}
973
974#[non_exhaustive]
978#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
979pub enum Version {
980 #[default]
982 V1,
983 V2,
985}
986
987impl Version {
988 fn initial_salt(self) -> &'static [u8; 20] {
989 match self {
990 Self::V1 => &[
991 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
993 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
994 ],
995 Self::V2 => &[
996 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
998 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
999 ],
1000 }
1001 }
1002
1003 pub(crate) fn packet_key_label(&self) -> &'static [u8] {
1005 match self {
1006 Self::V1 => b"quic key",
1007 Self::V2 => b"quicv2 key",
1008 }
1009 }
1010
1011 pub(crate) fn packet_iv_label(&self) -> &'static [u8] {
1013 match self {
1014 Self::V1 => b"quic iv",
1015 Self::V2 => b"quicv2 iv",
1016 }
1017 }
1018
1019 pub(crate) fn header_key_label(&self) -> &'static [u8] {
1021 match self {
1022 Self::V1 => b"quic hp",
1023 Self::V2 => b"quicv2 hp",
1024 }
1025 }
1026
1027 fn key_update_label(&self) -> &'static [u8] {
1028 match self {
1029 Self::V1 => b"quic ku",
1030 Self::V2 => b"quicv2 ku",
1031 }
1032 }
1033}
1034
1035#[cfg(all(test, any(target_arch = "aarch64", target_arch = "x86_64")))]
1036mod tests {
1037 use super::*;
1038 use crate::crypto::TLS13_TEST_SUITE;
1039 use crate::crypto::tls13::OkmBlock;
1040 use crate::quic::{HeaderProtectionKey, Secrets, Side, Version};
1041
1042 #[test]
1043 fn key_update_test_vector() {
1044 fn equal_okm(x: &OkmBlock, y: &OkmBlock) -> bool {
1045 x.as_ref() == y.as_ref()
1046 }
1047
1048 let mut secrets = Secrets {
1049 client: OkmBlock::new(
1051 &[
1052 0xb8, 0x76, 0x77, 0x08, 0xf8, 0x77, 0x23, 0x58, 0xa6, 0xea, 0x9f, 0xc4, 0x3e,
1053 0x4a, 0xdd, 0x2c, 0x96, 0x1b, 0x3f, 0x52, 0x87, 0xa6, 0xd1, 0x46, 0x7e, 0xe0,
1054 0xae, 0xab, 0x33, 0x72, 0x4d, 0xbf,
1055 ][..],
1056 ),
1057 server: OkmBlock::new(
1058 &[
1059 0x42, 0xdc, 0x97, 0x21, 0x40, 0xe0, 0xf2, 0xe3, 0x98, 0x45, 0xb7, 0x67, 0x61,
1060 0x34, 0x39, 0xdc, 0x67, 0x58, 0xca, 0x43, 0x25, 0x9b, 0x87, 0x85, 0x06, 0x82,
1061 0x4e, 0xb1, 0xe4, 0x38, 0xd8, 0x55,
1062 ][..],
1063 ),
1064 suite: TLS13_TEST_SUITE,
1065 quic: &FakeAlgorithm,
1066 side: Side::Client,
1067 version: Version::V1,
1068 };
1069 secrets.update();
1070
1071 assert!(equal_okm(
1072 &secrets.client,
1073 &OkmBlock::new(
1074 &[
1075 0x42, 0xca, 0xc8, 0xc9, 0x1c, 0xd5, 0xeb, 0x40, 0x68, 0x2e, 0x43, 0x2e, 0xdf,
1076 0x2d, 0x2b, 0xe9, 0xf4, 0x1a, 0x52, 0xca, 0x6b, 0x22, 0xd8, 0xe6, 0xcd, 0xb1,
1077 0xe8, 0xac, 0xa9, 0x6, 0x1f, 0xce
1078 ][..]
1079 )
1080 ));
1081 assert!(equal_okm(
1082 &secrets.server,
1083 &OkmBlock::new(
1084 &[
1085 0xeb, 0x7f, 0x5e, 0x2a, 0x12, 0x3f, 0x40, 0x7d, 0xb4, 0x99, 0xe3, 0x61, 0xca,
1086 0xe5, 0x90, 0xd4, 0xd9, 0x92, 0xe1, 0x4b, 0x7a, 0xce, 0x3, 0xc2, 0x44, 0xe0,
1087 0x42, 0x21, 0x15, 0xb6, 0xd3, 0x8a
1088 ][..]
1089 )
1090 ));
1091 }
1092
1093 struct FakeAlgorithm;
1094
1095 impl Algorithm for FakeAlgorithm {
1096 fn packet_key(&self, _key: AeadKey, _iv: Iv) -> Box<dyn PacketKey> {
1097 unimplemented!()
1098 }
1099
1100 fn header_protection_key(&self, _key: AeadKey) -> Box<dyn HeaderProtectionKey> {
1101 unimplemented!()
1102 }
1103
1104 fn aead_key_len(&self) -> usize {
1105 16
1106 }
1107 }
1108
1109 #[test]
1110 fn auto_traits() {
1111 fn assert_auto<T: Send + Sync>() {}
1112 assert_auto::<Box<dyn PacketKey>>();
1113 assert_auto::<Box<dyn HeaderProtectionKey>>();
1114 }
1115}