1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::ops::{Deref, DerefMut};
4use core::{fmt, mem};
5
6use pki_types::{DnsName, FipsStatus};
7
8use crate::TlsInputBuffer;
9use crate::client::ClientSide;
10pub use crate::common_state::Side;
11use crate::common_state::{CommonState, ConnectionOutputs, Protocol};
12use crate::conn::{
13 ConnectionCommon, KeyingMaterialExporter, MessageIter, MessageIterMode, SideCommonOutput,
14 SideData, StateMachine, VerifySidePeerIdentity,
15};
16use crate::crypto::VerifiedIdentity;
17use crate::crypto::cipher::{AeadKey, Iv, Payload};
18use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock};
19use crate::error::{ApiMisuse, Error};
20use crate::msgs::{Message, MessagePayload, ServerExtensionsInput, TransportParameters};
21use crate::server::{ChooseConfig, ClientHello, ServerConfig, ServerSide, ServerState};
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};
28use crate::verify::ClientIdentity;
29
30pub trait Connection: fmt::Debug + Deref<Target = ConnectionOutputs> {
32 fn quic_transport_parameters(&self) -> Option<&[u8]>;
40
41 fn zero_rtt_keys(&self) -> Option<DirectionalKeys>;
43
44 fn read_hs(&mut self, input: &mut dyn TlsInputBuffer) -> Result<(), Error>;
51
52 fn events(&mut self) -> impl Iterator<Item = QuicEvent>;
56
57 fn is_handshaking(&self) -> bool;
59}
60
61pub struct ClientConnection {
63 inner: QuicCommon<ClientSide>,
64}
65
66impl ClientConnection {
67 pub fn fips(&self) -> FipsStatus {
69 self.inner.fips
70 }
71
72 pub fn is_early_data_accepted(&self) -> bool {
78 self.inner
79 .common
80 .is_early_data_accepted()
81 }
82
83 pub fn tls13_tickets_received(&self) -> u32 {
85 self.inner
86 .common
87 .common
88 .recv
89 .tls13_tickets_received
90 }
91
92 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
106 self.inner.common.exporter()
107 }
108}
109
110impl Connection for ClientConnection {
111 fn quic_transport_parameters(&self) -> Option<&[u8]> {
112 self.inner.quic_transport_parameters()
113 }
114
115 fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
116 self.inner.zero_rtt_keys()
117 }
118
119 fn read_hs(&mut self, input: &mut dyn TlsInputBuffer) -> Result<(), Error> {
120 self.inner
121 .read_hs(input, MessageIterMode::All)
122 }
123
124 fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
125 self.inner.events()
126 }
127
128 fn is_handshaking(&self) -> bool {
129 self.inner.is_handshaking()
130 }
131}
132
133impl Deref for ClientConnection {
134 type Target = ConnectionOutputs;
135
136 fn deref(&self) -> &Self::Target {
137 &self.inner
138 }
139}
140
141impl fmt::Debug for ClientConnection {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 f.debug_struct("quic::ClientConnection")
144 .finish_non_exhaustive()
145 }
146}
147
148impl From<QuicCommon<ClientSide>> for ClientConnection {
149 fn from(inner: QuicCommon<ClientSide>) -> Self {
150 Self { inner }
151 }
152}
153
154pub struct ServerConnection {
156 inner: QuicCommon<ServerSide>,
157}
158
159impl ServerConnection {
160 pub fn new(
165 config: Arc<ServerConfig>,
166 version: Version,
167 params: Vec<u8>,
168 ) -> Result<Self, Error> {
169 check_server_config(&config)?;
170 let exts = ServerExtensionsInput {
171 transport_parameters: Some(match version {
172 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
173 }),
174 };
175
176 let core = ConnectionCommon::for_server(config, exts, Protocol::Quic(version))?;
177 let inner = QuicCommon::new(
178 core,
179 Quic {
180 version,
181 ..Quic::default()
182 },
183 );
184 Ok(Self { inner })
185 }
186
187 pub fn fips(&self) -> FipsStatus {
189 self.inner.fips
190 }
191
192 pub fn server_name(&self) -> Option<&DnsName<'_>> {
208 self.inner.common.side.server_name()
209 }
210
211 pub fn set_resumption_data(&mut self, resumption_data: &[u8]) -> Result<(), Error> {
220 assert!(resumption_data.len() < 2usize.pow(15));
221 match &mut self.inner.common.state {
222 Ok(st) => st.set_resumption_data(resumption_data),
223 Err(e) => Err(e.clone()),
224 }
225 }
226
227 pub fn received_resumption_data(&self) -> Option<&[u8]> {
231 self.inner
232 .common
233 .side
234 .received_resumption_data()
235 }
236
237 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
251 self.inner.common.exporter()
252 }
253}
254
255impl Connection for ServerConnection {
256 fn quic_transport_parameters(&self) -> Option<&[u8]> {
257 self.inner.quic_transport_parameters()
258 }
259
260 fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
261 self.inner.zero_rtt_keys()
262 }
263
264 fn read_hs(&mut self, input: &mut dyn TlsInputBuffer) -> Result<(), Error> {
265 self.inner
266 .read_hs(input, MessageIterMode::All)
267 }
268
269 fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
270 self.inner.events()
271 }
272
273 fn is_handshaking(&self) -> bool {
274 self.inner.is_handshaking()
275 }
276}
277
278impl Deref for ServerConnection {
279 type Target = ConnectionOutputs;
280
281 fn deref(&self) -> &Self::Target {
282 &self.inner
283 }
284}
285
286impl fmt::Debug for ServerConnection {
287 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288 f.debug_struct("quic::ServerConnection")
289 .finish_non_exhaustive()
290 }
291}
292
293#[non_exhaustive]
295#[derive(Debug)]
296pub enum ServerHandshake {
297 NeedsInput(NeedsInput),
299
300 Accepted(Accepted),
305
306 VerifyClientIdentity(VerifyClientIdentity),
310
311 Complete(ServerConnection),
313}
314
315impl ServerHandshake {
316 pub fn start(version: Version) -> NeedsInput {
326 NeedsInput {
327 inner: QuicCommon::new(
328 ConnectionCommon::for_acceptor(Protocol::Quic(version)),
329 Quic {
330 version,
331 ..Quic::default()
332 },
333 ),
334 }
335 }
336}
337
338impl TryFrom<QuicCommon<ServerSide>> for ServerHandshake {
339 type Error = Error;
340
341 fn try_from(mut inner: QuicCommon<ServerSide>) -> Result<Self, Error> {
342 const MISUSED: Error = Error::Unreachable("forgot to restore state");
343
344 Ok(match mem::replace(&mut inner.common.state, Err(MISUSED))? {
345 ServerState::ChooseConfig(choose_config) => Self::Accepted(Accepted {
346 inner,
347 choose_config,
348 }),
349
350 ServerState::VerifyClientIdentity(verify) => {
351 Self::VerifyClientIdentity(VerifyClientIdentity { inner, verify })
352 }
353
354 state if state.is_traffic() => {
355 inner.common.state = Ok(state);
356 Self::Complete(ServerConnection { inner })
357 }
358
359 state => {
360 inner.common.state = Ok(state);
361 Self::NeedsInput(NeedsInput { inner })
362 }
363 })
364 }
365}
366
367pub struct NeedsInput {
374 inner: QuicCommon<ServerSide>,
375}
376
377impl NeedsInput {
378 pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
384 self.inner.quic_transport_parameters()
385 }
386
387 pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
389 self.inner.zero_rtt_keys()
390 }
391
392 pub fn server_name(&self) -> Option<&DnsName<'_>> {
394 self.inner.common.side.server_name()
395 }
396
397 pub fn process(
418 mut self,
419 input: &mut dyn TlsInputBuffer,
420 output: &mut Vec<QuicEvent>,
421 ) -> Result<ServerHandshake, Error> {
422 self.inner
423 .read_hs(input, MessageIterMode::Handshake)?;
424 output.extend(self.inner.events());
425 ServerHandshake::try_from(self.inner)
426 }
427}
428
429impl Deref for NeedsInput {
430 type Target = ConnectionOutputs;
431
432 fn deref(&self) -> &Self::Target {
433 &self.inner
434 }
435}
436
437impl fmt::Debug for NeedsInput {
438 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439 f.debug_struct("quic::NeedsInput")
440 .finish_non_exhaustive()
441 }
442}
443
444pub struct Accepted {
449 inner: QuicCommon<ServerSide>,
451 choose_config: Box<ChooseConfig>,
452}
453
454impl Accepted {
455 pub fn client_hello(&self) -> ClientHello<'_> {
457 self.choose_config.client_hello()
458 }
459
460 pub fn choose_config(
470 mut self,
471 config: Arc<ServerConfig>,
472 params: Vec<u8>,
473 output: &mut Vec<QuicEvent>,
474 ) -> Result<ServerHandshake, Error> {
475 check_server_config(&config)?;
476
477 let mut tls = Vec::new();
478 self.inner.common.accepted(
479 self.choose_config,
480 ServerExtensionsInput {
481 transport_parameters: Some(match self.inner.quic.version {
482 Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
483 }),
484 },
485 Some(&mut self.inner.quic),
486 config,
487 &mut tls,
488 )?;
489
490 debug_assert!(tls.is_empty());
492 output.extend(self.inner.events());
493
494 ServerHandshake::try_from(self.inner)
495 }
496}
497
498impl fmt::Debug for Accepted {
499 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
500 f.debug_struct("quic::Accepted")
501 .finish_non_exhaustive()
502 }
503}
504
505fn check_server_config(config: &ServerConfig) -> Result<(), Error> {
506 let suites = &config.provider.tls13_cipher_suites;
507 if suites.is_empty() {
508 return Err(ApiMisuse::QuicRequiresTls13Support.into());
509 }
510
511 if !suites
512 .iter()
513 .any(|scs| scs.quic.is_some())
514 {
515 return Err(ApiMisuse::NoQuicCompatibleCipherSuites.into());
516 }
517
518 if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff {
519 return Err(ApiMisuse::QuicRestrictsMaxEarlyDataSize.into());
520 }
521
522 Ok(())
523}
524
525pub struct VerifyClientIdentity {
546 inner: QuicCommon<ServerSide>,
548 verify: Box<dyn VerifySidePeerIdentity<ServerSide>>,
549}
550
551impl VerifyClientIdentity {
552 pub fn with_config(self) -> Result<ServerHandshake, Error> {
554 let verified = self.verify.verify_with_config();
555 self.continue_with(verified)
556 }
557
558 pub fn continue_with(
562 self,
563 verification_result: Result<VerifiedIdentity<'static>, Error>,
564 ) -> Result<ServerHandshake, Error> {
565 let Self { mut inner, verify } = self;
566
567 let mut tls = Vec::new();
568 let result = verification_result.and_then(|verified| {
569 verify.continue_with(
570 verified,
571 &mut SideCommonOutput {
572 side: &mut inner.common.side,
573 quic: Some(&mut inner.quic),
574 common: &mut inner.common.common,
575 tls: &mut tls,
576 },
577 )
578 });
579
580 debug_assert!(tls.is_empty());
582
583 inner.common.state = result;
584 ServerHandshake::try_from(inner)
585 }
586
587 pub fn presented_identity(&self) -> Result<ClientIdentity<'static, '_>, Error> {
589 self.verify.presented_identity()
590 }
591}
592
593impl fmt::Debug for VerifyClientIdentity {
594 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
595 f.debug_struct("VerifyClientIdentity")
596 .finish_non_exhaustive()
597 }
598}
599
600#[expect(clippy::large_enum_variant)]
602#[derive(Debug)]
603#[non_exhaustive]
604pub enum QuicEvent {
605 Message(Vec<u8>),
607
608 KeyChange(KeyChange),
610}
611
612pub(crate) struct QuicCommon<Side: SideData> {
614 common: ConnectionCommon<Side>,
615 quic: Quic,
616}
617
618impl<Side: SideData> QuicCommon<Side> {
619 pub(crate) fn new(common: ConnectionCommon<Side>, quic: Quic) -> Self {
620 Self { common, quic }
621 }
622
623 fn quic_transport_parameters(&self) -> Option<&[u8]> {
624 self.quic
625 .params
626 .as_ref()
627 .map(|v| v.as_ref())
628 }
629
630 fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
631 let suite = self
632 .common
633 .common
634 .negotiated_cipher_suite()
635 .and_then(|suite| match suite {
636 SupportedCipherSuite::Tls13(suite) => Some(suite),
637 _ => None,
638 })?;
639
640 let suite = Suite {
641 inner: suite,
642 quic: suite.quic?,
643 };
644
645 Some(DirectionalKeys::new(
646 suite,
647 self.quic.early_secret.as_ref()?,
648 self.quic.version,
649 ))
650 }
651
652 fn read_hs(
653 &mut self,
654 input: &mut dyn TlsInputBuffer,
655 mode: MessageIterMode,
656 ) -> Result<(), Error> {
657 self.common
658 .common
659 .recv
660 .deframer
661 .input_quic(input.slice_mut())?;
662
663 let mut tls = Vec::new();
664 let mut iter = MessageIter::new(
665 input,
666 &mut tls,
667 Some(&mut self.quic),
668 &mut self.common,
669 mode,
670 );
671
672 let result = match iter.next(false) {
673 Some(Ok(_)) | None => Ok(()),
674 Some(Err(e)) => Err(e),
675 };
676
677 input.discard(
678 self.common
679 .common
680 .recv
681 .deframer
682 .take_discard(),
683 );
684
685 result
686 }
687
688 fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
689 self.quic.events()
690 }
691}
692
693impl<Side: SideData> Deref for QuicCommon<Side> {
694 type Target = CommonState;
695
696 fn deref(&self) -> &Self::Target {
697 &self.common.common
698 }
699}
700
701impl<Side: SideData> DerefMut for QuicCommon<Side> {
702 fn deref_mut(&mut self) -> &mut Self::Target {
703 &mut self.common.common
704 }
705}
706
707#[derive(Default)]
708pub(crate) struct Quic {
709 pub(crate) version: Version,
710 pub(crate) params: Option<Vec<u8>>,
712 pub(crate) events: Vec<QuicEvent>,
713 pub(crate) early_secret: Option<OkmBlock>,
714}
715
716impl Quic {
717 pub(crate) fn send_msg(&mut self, m: Message<'_>, _must_encrypt: bool) {
718 if let MessagePayload::Alert(_) = m.payload {
719 return;
721 }
722
723 debug_assert!(
724 matches!(
725 m.payload,
726 MessagePayload::Handshake { .. } | MessagePayload::HandshakeFlight(_)
727 ),
728 "QUIC uses TLS for the cryptographic handshake only"
729 );
730 let mut bytes = Vec::new();
731 m.payload.encode(&mut bytes);
732 self.events
733 .push(QuicEvent::Message(bytes));
734 }
735
736 pub(crate) fn events(&mut self) -> impl Iterator<Item = QuicEvent> {
737 mem::take(&mut self.events).into_iter()
738 }
739}
740
741impl QuicOutput for Quic {
742 fn transport_parameters(&mut self, params: Vec<u8>) {
743 self.params = Some(params);
744 }
745
746 fn early_secret(&mut self, secret: Option<OkmBlock>) {
747 self.early_secret = secret;
748 }
749
750 fn handshake_secrets(
751 &mut self,
752 client_secret: OkmBlock,
753 server_secret: OkmBlock,
754 suite: Suite,
755 side: Side,
756 ) {
757 self.events
758 .push(QuicEvent::KeyChange(KeyChange::Handshake {
759 keys: Keys::new(&Secrets::new(
760 client_secret,
761 server_secret,
762 suite,
763 side,
764 self.version,
765 )),
766 }));
767 }
768
769 fn traffic_secrets(
770 &mut self,
771 client_secret: OkmBlock,
772 server_secret: OkmBlock,
773 suite: Suite,
774 side: Side,
775 ) {
776 let mut secrets = Secrets::new(client_secret, server_secret, suite, side, self.version);
777 let keys = Keys::new(&secrets);
778 secrets.update();
779 self.events
780 .push(QuicEvent::KeyChange(KeyChange::OneRtt {
781 keys,
782 next: secrets,
783 }));
784 }
785
786 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
787 self.send_msg(m, must_encrypt);
788 }
789}
790
791pub(crate) trait QuicOutput {
792 fn transport_parameters(&mut self, params: Vec<u8>);
793
794 fn early_secret(&mut self, secret: Option<OkmBlock>);
795
796 fn handshake_secrets(
797 &mut self,
798 client_secret: OkmBlock,
799 server_secret: OkmBlock,
800 suite: Suite,
801 side: Side,
802 );
803
804 fn traffic_secrets(
805 &mut self,
806 client_secret: OkmBlock,
807 server_secret: OkmBlock,
808 suite: Suite,
809 side: Side,
810 );
811
812 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool);
813}
814
815#[derive(Clone)]
817pub struct Secrets {
818 pub(crate) client: OkmBlock,
820 pub(crate) server: OkmBlock,
822 suite: Suite,
824 side: Side,
825 version: Version,
826}
827
828impl Secrets {
829 pub(crate) fn new(
830 client: OkmBlock,
831 server: OkmBlock,
832 suite: Suite,
833 side: Side,
834 version: Version,
835 ) -> Self {
836 Self {
837 client,
838 server,
839 suite,
840 side,
841 version,
842 }
843 }
844
845 pub fn next_packet_keys(&mut self) -> PacketKeySet {
847 let keys = PacketKeySet::new(self);
848 self.update();
849 keys
850 }
851
852 pub(crate) fn update(&mut self) {
853 self.client = hkdf_expand_label_block(
854 self.suite
855 .inner
856 .hkdf_provider
857 .expander_for_okm(&self.client)
858 .as_ref(),
859 self.version.key_update_label(),
860 &[],
861 );
862 self.server = hkdf_expand_label_block(
863 self.suite
864 .inner
865 .hkdf_provider
866 .expander_for_okm(&self.server)
867 .as_ref(),
868 self.version.key_update_label(),
869 &[],
870 );
871 }
872
873 fn local_remote(&self) -> (&OkmBlock, &OkmBlock) {
874 match self.side {
875 Side::Client => (&self.client, &self.server),
876 Side::Server => (&self.server, &self.client),
877 }
878 }
879}
880
881#[expect(clippy::exhaustive_structs)]
883pub struct DirectionalKeys {
884 pub header: Box<dyn HeaderProtectionKey>,
886 pub packet: Box<dyn PacketKey>,
888}
889
890impl DirectionalKeys {
891 pub(crate) fn new(suite: Suite, secret: &OkmBlock, version: Version) -> Self {
892 let builder = KeyBuilder::new(secret, version, suite.quic, suite.inner.hkdf_provider);
893 Self {
894 header: builder.header_protection_key(),
895 packet: builder.packet_key(),
896 }
897 }
898}
899
900const TAG_LEN: usize = 16;
902
903pub struct Tag([u8; TAG_LEN]);
905
906impl From<&[u8]> for Tag {
907 fn from(value: &[u8]) -> Self {
908 let mut array = [0u8; TAG_LEN];
909 array.copy_from_slice(value);
910 Self(array)
911 }
912}
913
914impl AsRef<[u8]> for Tag {
915 fn as_ref(&self) -> &[u8] {
916 &self.0
917 }
918}
919
920pub trait Algorithm: Send + Sync {
922 fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn PacketKey>;
927
928 fn header_protection_key(&self, key: AeadKey) -> Box<dyn HeaderProtectionKey>;
932
933 fn aead_key_len(&self) -> usize;
937
938 fn fips(&self) -> FipsStatus {
940 FipsStatus::Unvalidated
941 }
942}
943
944pub trait HeaderProtectionKey: Send + Sync {
946 fn encrypt_in_place(
967 &self,
968 sample: &[u8],
969 first: &mut u8,
970 packet_number: &mut [u8],
971 ) -> Result<(), Error>;
972
973 fn decrypt_in_place(
995 &self,
996 sample: &[u8],
997 first: &mut u8,
998 packet_number: &mut [u8],
999 ) -> Result<(), Error>;
1000
1001 fn sample_len(&self) -> usize;
1003}
1004
1005pub trait PacketKey: Send + Sync {
1007 fn encrypt_in_place(
1018 &self,
1019 packet_number: u64,
1020 header: &[u8],
1021 payload: &mut [u8],
1022 path_id: Option<u32>,
1023 ) -> Result<Tag, Error>;
1024
1025 fn decrypt_in_place<'a>(
1036 &self,
1037 packet_number: u64,
1038 header: &[u8],
1039 payload: &'a mut [u8],
1040 path_id: Option<u32>,
1041 ) -> Result<&'a [u8], Error>;
1042
1043 fn tag_len(&self) -> usize;
1045
1046 fn confidentiality_limit(&self) -> u64;
1057
1058 fn integrity_limit(&self) -> u64;
1067}
1068
1069#[expect(clippy::exhaustive_structs)]
1071pub struct PacketKeySet {
1072 pub local: Box<dyn PacketKey>,
1074 pub remote: Box<dyn PacketKey>,
1076}
1077
1078impl PacketKeySet {
1079 fn new(secrets: &Secrets) -> Self {
1080 let (local, remote) = secrets.local_remote();
1081 let (version, alg, hkdf) = (
1082 secrets.version,
1083 secrets.suite.quic,
1084 secrets.suite.inner.hkdf_provider,
1085 );
1086
1087 Self {
1088 local: KeyBuilder::new(local, version, alg, hkdf).packet_key(),
1089 remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(),
1090 }
1091 }
1092}
1093
1094pub struct KeyBuilder<'a> {
1096 expander: Box<dyn HkdfExpander>,
1097 version: Version,
1098 alg: &'a dyn Algorithm,
1099}
1100
1101impl<'a> KeyBuilder<'a> {
1102 pub fn new(
1104 secret: &OkmBlock,
1105 version: Version,
1106 alg: &'a dyn Algorithm,
1107 hkdf: &'a dyn Hkdf,
1108 ) -> Self {
1109 Self {
1110 expander: hkdf.expander_for_okm(secret),
1111 version,
1112 alg,
1113 }
1114 }
1115
1116 pub fn packet_key(&self) -> Box<dyn PacketKey> {
1118 let aead_key_len = self.alg.aead_key_len();
1119 let packet_key = hkdf_expand_label_aead_key(
1120 self.expander.as_ref(),
1121 aead_key_len,
1122 self.version.packet_key_label(),
1123 &[],
1124 );
1125
1126 let packet_iv =
1127 hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]);
1128 self.alg
1129 .packet_key(packet_key, packet_iv)
1130 }
1131
1132 pub fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> {
1134 let header_key = hkdf_expand_label_aead_key(
1135 self.expander.as_ref(),
1136 self.alg.aead_key_len(),
1137 self.version.header_key_label(),
1138 &[],
1139 );
1140 self.alg
1141 .header_protection_key(header_key)
1142 }
1143}
1144
1145#[non_exhaustive]
1147#[derive(Clone, Copy)]
1148pub struct Suite {
1149 pub inner: &'static Tls13CipherSuite,
1151 pub quic: &'static dyn Algorithm,
1153}
1154
1155impl Suite {
1156 pub fn keys(&self, client_dst_connection_id: &[u8], side: Side, version: Version) -> Keys {
1158 Keys::initial(version, *self, client_dst_connection_id, side)
1159 }
1160}
1161
1162impl TryFrom<&'static Tls13CipherSuite> for Suite {
1163 type Error = ApiMisuse;
1164
1165 fn try_from(suite: &'static Tls13CipherSuite) -> Result<Self, Self::Error> {
1166 Ok(Self {
1167 inner: suite,
1168 quic: suite
1169 .quic
1170 .ok_or(ApiMisuse::NoQuicCompatibleCipherSuites)?,
1171 })
1172 }
1173}
1174
1175impl fmt::Debug for Suite {
1176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1177 f.debug_struct("Suite")
1178 .field("inner", &self.inner)
1179 .finish_non_exhaustive()
1180 }
1181}
1182
1183#[expect(clippy::exhaustive_structs)]
1185pub struct Keys {
1186 pub local: DirectionalKeys,
1188 pub remote: DirectionalKeys,
1190}
1191
1192impl Keys {
1193 pub fn initial(
1195 version: Version,
1196 suite: Suite,
1197 client_dst_connection_id: &[u8],
1198 side: Side,
1199 ) -> Self {
1200 const CLIENT_LABEL: &[u8] = b"client in";
1201 const SERVER_LABEL: &[u8] = b"server in";
1202 let salt = version.initial_salt();
1203 let hs_secret = suite
1204 .inner
1205 .hkdf_provider
1206 .extract_from_secret(Some(salt), client_dst_connection_id);
1207
1208 let secrets = Secrets {
1209 client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]),
1210 server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]),
1211 suite,
1212 side,
1213 version,
1214 };
1215
1216 Self::new(&secrets)
1217 }
1218
1219 fn new(secrets: &Secrets) -> Self {
1220 let (local, remote) = secrets.local_remote();
1221 Self {
1222 local: DirectionalKeys::new(secrets.suite, local, secrets.version),
1223 remote: DirectionalKeys::new(secrets.suite, remote, secrets.version),
1224 }
1225 }
1226}
1227
1228#[expect(clippy::exhaustive_enums)]
1242pub enum KeyChange {
1243 Handshake {
1245 keys: Keys,
1247 },
1248 OneRtt {
1250 keys: Keys,
1252 next: Secrets,
1254 },
1255}
1256
1257impl fmt::Debug for KeyChange {
1258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1259 match self {
1260 Self::Handshake { .. } => f
1261 .debug_struct("Handshake")
1262 .finish_non_exhaustive(),
1263 Self::OneRtt { .. } => f
1264 .debug_struct("OneRtt")
1265 .finish_non_exhaustive(),
1266 }
1267 }
1268}
1269
1270#[non_exhaustive]
1274#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
1275pub enum Version {
1276 #[default]
1278 V1,
1279 V2,
1281}
1282
1283impl Version {
1284 fn initial_salt(self) -> &'static [u8; 20] {
1285 match self {
1286 Self::V1 => &[
1287 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
1289 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
1290 ],
1291 Self::V2 => &[
1292 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
1294 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
1295 ],
1296 }
1297 }
1298
1299 pub(crate) fn packet_key_label(&self) -> &'static [u8] {
1301 match self {
1302 Self::V1 => b"quic key",
1303 Self::V2 => b"quicv2 key",
1304 }
1305 }
1306
1307 pub(crate) fn packet_iv_label(&self) -> &'static [u8] {
1309 match self {
1310 Self::V1 => b"quic iv",
1311 Self::V2 => b"quicv2 iv",
1312 }
1313 }
1314
1315 pub(crate) fn header_key_label(&self) -> &'static [u8] {
1317 match self {
1318 Self::V1 => b"quic hp",
1319 Self::V2 => b"quicv2 hp",
1320 }
1321 }
1322
1323 fn key_update_label(&self) -> &'static [u8] {
1324 match self {
1325 Self::V1 => b"quic ku",
1326 Self::V2 => b"quicv2 ku",
1327 }
1328 }
1329}
1330
1331#[cfg(all(test, any(target_arch = "aarch64", target_arch = "x86_64")))]
1332mod tests {
1333 use super::*;
1334 use crate::crypto::TLS13_TEST_SUITE;
1335 use crate::crypto::tls13::OkmBlock;
1336 use crate::quic::{HeaderProtectionKey, Secrets, Side, Version};
1337
1338 #[test]
1339 fn key_update_test_vector() {
1340 fn equal_okm(x: &OkmBlock, y: &OkmBlock) -> bool {
1341 x.as_ref() == y.as_ref()
1342 }
1343
1344 let mut secrets = Secrets {
1345 client: OkmBlock::new(
1347 &[
1348 0xb8, 0x76, 0x77, 0x08, 0xf8, 0x77, 0x23, 0x58, 0xa6, 0xea, 0x9f, 0xc4, 0x3e,
1349 0x4a, 0xdd, 0x2c, 0x96, 0x1b, 0x3f, 0x52, 0x87, 0xa6, 0xd1, 0x46, 0x7e, 0xe0,
1350 0xae, 0xab, 0x33, 0x72, 0x4d, 0xbf,
1351 ][..],
1352 ),
1353 server: OkmBlock::new(
1354 &[
1355 0x42, 0xdc, 0x97, 0x21, 0x40, 0xe0, 0xf2, 0xe3, 0x98, 0x45, 0xb7, 0x67, 0x61,
1356 0x34, 0x39, 0xdc, 0x67, 0x58, 0xca, 0x43, 0x25, 0x9b, 0x87, 0x85, 0x06, 0x82,
1357 0x4e, 0xb1, 0xe4, 0x38, 0xd8, 0x55,
1358 ][..],
1359 ),
1360 suite: Suite {
1361 inner: TLS13_TEST_SUITE,
1362 quic: &FakeAlgorithm,
1363 },
1364 side: Side::Client,
1365 version: Version::V1,
1366 };
1367 secrets.update();
1368
1369 assert!(equal_okm(
1370 &secrets.client,
1371 &OkmBlock::new(
1372 &[
1373 0x42, 0xca, 0xc8, 0xc9, 0x1c, 0xd5, 0xeb, 0x40, 0x68, 0x2e, 0x43, 0x2e, 0xdf,
1374 0x2d, 0x2b, 0xe9, 0xf4, 0x1a, 0x52, 0xca, 0x6b, 0x22, 0xd8, 0xe6, 0xcd, 0xb1,
1375 0xe8, 0xac, 0xa9, 0x6, 0x1f, 0xce
1376 ][..]
1377 )
1378 ));
1379 assert!(equal_okm(
1380 &secrets.server,
1381 &OkmBlock::new(
1382 &[
1383 0xeb, 0x7f, 0x5e, 0x2a, 0x12, 0x3f, 0x40, 0x7d, 0xb4, 0x99, 0xe3, 0x61, 0xca,
1384 0xe5, 0x90, 0xd4, 0xd9, 0x92, 0xe1, 0x4b, 0x7a, 0xce, 0x3, 0xc2, 0x44, 0xe0,
1385 0x42, 0x21, 0x15, 0xb6, 0xd3, 0x8a
1386 ][..]
1387 )
1388 ));
1389 }
1390
1391 struct FakeAlgorithm;
1392
1393 impl Algorithm for FakeAlgorithm {
1394 fn packet_key(&self, _key: AeadKey, _iv: Iv) -> Box<dyn PacketKey> {
1395 unimplemented!()
1396 }
1397
1398 fn header_protection_key(&self, _key: AeadKey) -> Box<dyn HeaderProtectionKey> {
1399 unimplemented!()
1400 }
1401
1402 fn aead_key_len(&self) -> usize {
1403 16
1404 }
1405 }
1406
1407 #[test]
1408 fn auto_traits() {
1409 fn assert_auto<T: Send + Sync>() {}
1410 assert_auto::<Box<dyn PacketKey>>();
1411 assert_auto::<Box<dyn HeaderProtectionKey>>();
1412 }
1413}