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