1use std::{
2 convert::TryFrom,
3 fmt::Display,
4 hash::{Hash, Hasher},
5 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
6 path::Path,
7};
8
9use base64::Engine;
10use bytes::BufMut;
11use dhttp_identity::certificate::{CertificateChainKey, CertificateChainKind, CertificateSequence};
12use dquic::qbase::net::addr::EndpointAddr as DquicEndpointAddr;
13use nom::{
14 IResult, Parser,
15 bytes::streaming::take,
16 combinator::{flat_map, map},
17 error::{ErrorKind, make_error},
18 number::streaming::{be_u8, be_u16, be_u32, be_u128},
19};
20use rustls::{SignatureScheme, pki_types::SubjectPublicKeyInfoDer};
21use snafu::{ResultExt, Snafu};
22
23use crate::core::parser::{
24 sigin,
25 varint::{VarInt, WriteVarInt, be_varint},
26};
27
28#[derive(Debug, Snafu)]
29#[snafu(module)]
30pub enum SignEndpointError {
31 #[snafu(display("failed to sign endpoint address"))]
32 Sign {
33 source: dhttp_identity::identity::SignError,
34 },
35 #[snafu(display("no supported signature scheme for endpoint address"))]
36 NoSupportedScheme,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Hash)]
80pub struct EndpointSignature {
81 scheme: u16,
82 signature: Vec<u8>,
83}
84
85#[derive(Debug, Clone)]
86pub struct EndpointAddr {
87 flags: u8,
88 sequence: Option<CertificateSequence>,
91 load: Option<f32>,
93 signature: Option<EndpointSignature>,
94 pub primary: SocketAddr,
96 pub agent: Option<SocketAddr>,
98}
99
100impl PartialEq for EndpointAddr {
101 fn eq(&self, other: &Self) -> bool {
102 self.flags == other.flags
103 && self.sequence == other.sequence
104 && self.load.map(f32::to_bits) == other.load.map(f32::to_bits)
105 && self.signature == other.signature
106 && self.primary == other.primary
107 && self.agent == other.agent
108 }
109}
110
111impl Eq for EndpointAddr {}
112
113impl Hash for EndpointAddr {
114 fn hash<H: Hasher>(&self, state: &mut H) {
115 self.flags.hash(state);
116 self.sequence.hash(state);
117 self.load.map(f32::to_bits).hash(state);
118 self.signature.hash(state);
119 self.primary.hash(state);
120 self.agent.hash(state);
121 }
122}
123
124impl EndpointAddr {
125 const FLAG_FAMILY: u8 = 0b1000_0000; const FLAG_MAIN: u8 = 0b0100_0000; const FLAG_CLUSTERED: u8 = 0b0010_0000; const FLAG_NAT: u8 = 0b0001_0000; const FLAG_LOAD: u8 = 0b0000_1000; const FLAG_SIGNED: u8 = 0b0000_0001; pub fn direct_v4(addr: SocketAddrV4) -> Self {
135 Self {
136 flags: 0, sequence: None,
138 load: None,
139 signature: None,
140 primary: addr.into(),
141 agent: None,
142 }
143 }
144
145 pub fn direct_v6(addr: SocketAddrV6) -> Self {
146 Self {
147 flags: Self::FLAG_FAMILY, sequence: None,
149 load: None,
150 signature: None,
151 primary: addr.into(),
152 agent: None,
153 }
154 }
155
156 pub fn nat_v4(outer: SocketAddrV4, agent: SocketAddrV4) -> Self {
159 Self {
160 flags: Self::FLAG_NAT, sequence: None,
162 load: None,
163 signature: None,
164 primary: outer.into(),
165 agent: Some(agent.into()),
166 }
167 }
168
169 pub fn nat_v6(outer: SocketAddrV6, agent: SocketAddrV6) -> Self {
172 Self {
173 flags: Self::FLAG_FAMILY | Self::FLAG_NAT, sequence: None,
175 load: None,
176 signature: None,
177 primary: outer.into(),
178 agent: Some(agent.into()),
179 }
180 }
181
182 pub fn is_ipv6(&self) -> bool {
184 self.flags & Self::FLAG_FAMILY != 0
185 }
186
187 pub fn is_nat(&self) -> bool {
189 self.flags & Self::FLAG_NAT != 0
190 }
191
192 pub fn is_clustered(&self) -> bool {
194 self.flags & Self::FLAG_CLUSTERED != 0
195 }
196
197 pub fn is_load(&self) -> bool {
199 self.flags & Self::FLAG_LOAD != 0
200 }
201
202 pub fn set_clustered(&mut self, clustered: bool) {
203 if clustered {
204 self.flags |= Self::FLAG_CLUSTERED;
205 } else {
206 self.flags &= !Self::FLAG_CLUSTERED;
207 self.sequence = None; }
209 }
210
211 pub fn set_load(&mut self, load: Option<f32>) {
212 self.load = load;
213 if self.load.is_some() {
214 self.flags |= Self::FLAG_LOAD;
215 } else {
216 self.flags &= !Self::FLAG_LOAD;
217 }
218 }
219
220 pub async fn sign_with_authority(
221 &mut self,
222 authority: &(impl dhttp_identity::identity::LocalAuthority + ?Sized),
223 ) -> Result<(), SignEndpointError> {
224 self.set_signed(true);
225 let data = self.signed_data();
226
227 let scheme = authority
228 .cert_chain()
229 .first()
230 .and_then(|_| sigin::canonical_scheme_for_spki(authority.public_key()))
231 .ok_or(SignEndpointError::NoSupportedScheme)?;
232 let signature = authority
233 .sign(&data)
234 .await
235 .context(sign_endpoint_error::SignSnafu)?;
236
237 self.signature = Some(EndpointSignature {
238 scheme: u16::from(scheme),
239 signature,
240 });
241 Ok(())
242 }
243
244 pub fn verify_signature(
245 &self,
246 spki: SubjectPublicKeyInfoDer<'_>,
247 ) -> Result<bool, sigin::VerifyError> {
248 let Some(sig) = &self.signature else {
249 return Ok(false);
250 };
251 let data = self.signed_data();
252 sigin::verify(
253 spki,
254 SignatureScheme::from(sig.scheme),
255 &data,
256 &sig.signature,
257 )
258 }
259
260 pub fn verify_signature_from_der(&self, cert_der: &[u8]) -> Result<bool, sigin::VerifyError> {
261 let (_, cert) = x509_parser::parse_x509_certificate(cert_der).map_err(|e| {
262 sigin::VerifyError::InvalidCertificate {
263 details: e.to_string(),
264 }
265 })?;
266
267 let spki = SubjectPublicKeyInfoDer::from(cert.tbs_certificate.subject_pki.raw);
268 self.verify_signature(spki)
269 }
270
271 pub fn verify_signature_from_pem(&self, cert_pem: &[u8]) -> Result<bool, sigin::VerifyError> {
272 let mut reader = std::io::Cursor::new(cert_pem);
273 if let Some(item) = rustls_pemfile::certs(&mut reader).next() {
274 let cert_der = item.map_err(|e| sigin::VerifyError::InvalidPem { source: e })?;
275 return self.verify_signature_from_der(&cert_der);
276 }
277 Err(sigin::VerifyError::InvalidCertificate {
278 details: "No certificate found in PEM".to_string(),
279 })
280 }
281
282 pub fn verify_signature_from_base64(
283 &self,
284 cert_base64: &str,
285 ) -> Result<bool, sigin::VerifyError> {
286 let cert_base64 = cert_base64.trim();
287 let cert_der = base64::engine::general_purpose::STANDARD
288 .decode(cert_base64)
289 .map_err(|e| sigin::VerifyError::InvalidBase64 { source: e })?;
290 self.verify_signature_from_der(&cert_der)
291 }
292
293 pub fn verify_signature_from_file(
294 &self,
295 path: impl AsRef<Path>,
296 ) -> Result<bool, sigin::VerifyError> {
297 let contents = std::fs::read(path).map_err(|e| sigin::VerifyError::Io { source: e })?;
298 if let Ok(res) = self.verify_signature_from_pem(&contents) {
300 return Ok(res);
301 }
302 self.verify_signature_from_der(&contents)
304 }
305
306 pub fn is_main(&self) -> bool {
307 self.flags() & Self::FLAG_MAIN == Self::FLAG_MAIN
308 }
309
310 pub fn set_main(&mut self, is_main: bool) {
311 let flags = self.flags_mut();
312 if is_main {
313 *flags |= Self::FLAG_MAIN;
314 } else {
315 *flags &= !Self::FLAG_MAIN;
316 }
317 }
318
319 pub fn is_signed(&self) -> bool {
320 self.flags() & Self::FLAG_SIGNED == Self::FLAG_SIGNED
321 }
322
323 pub fn set_signed(&mut self, is_signed: bool) {
324 let flags = self.flags_mut();
325 if is_signed {
326 *flags |= Self::FLAG_SIGNED;
327 } else {
328 *flags &= !Self::FLAG_SIGNED;
329 }
330 }
331
332 pub fn encpding_size(&self) -> usize {
333 let mut meta_len = 1; if let Some(seq) = &self.sequence {
337 meta_len += VarInt::from_u32(seq.get()).encoding_size();
338 }
339
340 if self.load.is_some() {
341 meta_len += 4; }
343
344 if self.is_signed()
345 && let Some(sig) = &self.signature
346 {
347 let sig_len =
348 VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
349 meta_len += 2 + sig_len.encoding_size() + sig.signature.len();
350 }
351
352 let addr_len = match (self.is_ipv6(), self.is_nat()) {
353 (false, false) => 2 + 4, (false, true) => (2 + 4) * 2, (true, false) => 2 + 16, (true, true) => (2 + 16) * 2, };
358
359 meta_len + addr_len
360 }
361
362 pub fn addr(&self) -> SocketAddr {
363 self.primary
364 }
365
366 pub fn agent_addr(&self) -> Option<SocketAddr> {
367 self.agent
368 }
369
370 pub fn sequence(&self) -> Option<CertificateSequence> {
371 self.sequence
372 }
373
374 pub fn normalized_sequence(&self) -> CertificateSequence {
375 self.sequence
376 .unwrap_or_else(|| CertificateSequence::from(0u8))
377 }
378
379 pub fn set_sequence(&mut self, sequence: CertificateSequence) {
380 if sequence.get() > 0 {
381 self.sequence = Some(sequence);
382 self.set_clustered(true);
383 } else {
384 self.sequence = None;
385 self.set_clustered(false);
386 }
387 }
388
389 pub fn certificate_chain_key(&self) -> CertificateChainKey {
390 let kind = if self.is_main() {
391 CertificateChainKind::Primary
392 } else {
393 CertificateChainKind::Secondary
394 };
395 CertificateChainKey::new(self.normalized_sequence(), kind)
396 }
397
398 pub fn load(&self) -> Option<f32> {
399 self.load
400 }
401
402 fn flags(&self) -> u8 {
403 self.flags
404 }
405
406 fn flags_mut(&mut self) -> &mut u8 {
407 &mut self.flags
408 }
409
410 pub fn signature(&self) -> Option<&EndpointSignature> {
411 self.signature.as_ref()
412 }
413
414 pub fn signature_base64(&self) -> Option<String> {
415 self.signature
416 .as_ref()
417 .map(|sig| base64::engine::general_purpose::STANDARD.encode(&sig.signature))
418 }
419
420 fn write_base<B: BufMut>(&self, buf: &mut B) {
421 buf.put_u8(self.flags);
422
423 if let Some(seq) = &self.sequence {
425 buf.put_varint(VarInt::from_u32(seq.get()));
426 }
427
428 match self.primary {
430 SocketAddr::V4(addr) => buf.put_socket_addr_v4(&addr),
431 SocketAddr::V6(addr) => buf.put_socket_addr_v6(&addr),
432 }
433
434 if let Some(agent_addr) = &self.agent {
436 match agent_addr {
437 SocketAddr::V4(addr) => buf.put_socket_addr_v4(addr),
438 SocketAddr::V6(addr) => buf.put_socket_addr_v6(addr),
439 }
440 }
441
442 if let Some(load) = self.load {
443 buf.put_u32(load.to_bits());
444 }
445 }
446
447 fn signed_data(&self) -> Vec<u8> {
448 let mut unsigned = self.clone();
449 unsigned.set_signed(true);
450 unsigned.signature = None;
451 let mut buf = bytes::BytesMut::with_capacity(unsigned.encpding_size());
452 unsigned.write_base(&mut buf);
453 buf.to_vec()
454 }
455}
456
457pub(crate) trait WriteEndpointAddr {
458 fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr);
459}
460
461impl<B: BufMut> WriteEndpointAddr for B {
462 fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr) {
463 endpoint.write_base(self);
464 if endpoint.is_signed()
465 && let Some(sig) = endpoint.signature()
466 {
467 self.put_u16(sig.scheme);
468 let len = VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
469 self.put_varint(len);
470 self.put_slice(&sig.signature);
471 }
472 }
473}
474
475pub fn be_endpoint_addr(input: &[u8]) -> nom::IResult<&[u8], EndpointAddr> {
476 let (remain, flags) = be_u8(input)?;
477
478 let is_clustered = flags & EndpointAddr::FLAG_CLUSTERED != 0;
479 let is_ipv6 = flags & EndpointAddr::FLAG_FAMILY != 0;
480 let is_nat = flags & EndpointAddr::FLAG_NAT != 0;
481 let has_load = flags & EndpointAddr::FLAG_LOAD != 0;
482
483 let (remain, sequence) = if is_clustered {
485 let (remain, seq) = be_varint(remain)?;
486 let sequence = match CertificateSequence::try_from(seq.into_inner()) {
487 Ok(sequence) => sequence,
488 Err(_error) => {
489 return Err(nom::Err::Failure(make_error(remain, ErrorKind::TooLarge)));
490 }
491 };
492 (remain, Some(sequence))
493 } else {
494 (remain, None)
495 };
496
497 let (remain, primary) = if is_ipv6 {
498 let (remain, addr) = be_socket_addr_v6(remain)?;
499 (remain, SocketAddr::V6(addr))
500 } else {
501 let (remain, addr) = be_socket_addr_v4(remain)?;
502 (remain, SocketAddr::V4(addr))
503 };
504
505 let (remain, agent) = if is_nat {
506 let agent_addr = if is_ipv6 {
507 let (remain, addr) = be_socket_addr_v6(remain)?;
508 (remain, SocketAddr::V6(addr))
509 } else {
510 let (remain, addr) = be_socket_addr_v4(remain)?;
511 (remain, SocketAddr::V4(addr))
512 };
513 let (remain, addr) = agent_addr;
514 (remain, Some(addr))
515 } else {
516 (remain, None)
517 };
518
519 let (remain, load) = if has_load {
520 let (remain, load) = be_u32(remain)?;
521 (remain, Some(f32::from_bits(load)))
522 } else {
523 (remain, None)
524 };
525
526 let (remain, signature) = be_endpoint_signature(remain, flags)?;
527
528 Ok((
529 remain,
530 EndpointAddr {
531 flags,
532 sequence,
533 load,
534 signature,
535 primary,
536 agent,
537 },
538 ))
539}
540
541pub(crate) fn be_endpoint_addr_compat(
549 input: &[u8],
550 rdlen: u16,
551) -> nom::IResult<&[u8], EndpointAddr> {
552 let legacy_lengths = [
554 6, 12, 18, 36, ];
559
560 if legacy_lengths.contains(&(rdlen as usize)) {
561 if let Ok((remaining, endpoint)) = be_endpoint_addr(input)
565 && remaining.is_empty()
566 {
567 return Ok((remaining, endpoint));
568 }
569 return be_legacy_endpoint_addr_by_length(input, rdlen);
570 }
571
572 be_endpoint_addr(input)
574}
575
576fn be_legacy_endpoint_addr_by_length(
578 input: &[u8],
579 rdlen: u16,
580) -> nom::IResult<&[u8], EndpointAddr> {
581 match rdlen {
582 6 => {
583 let (remain, addr) = be_socket_addr_v4(input)?;
585 Ok((
586 remain,
587 EndpointAddr {
588 flags: 0,
589 sequence: None,
590 load: None,
591 signature: None,
592 primary: addr.into(),
593 agent: None,
594 },
595 ))
596 }
597 12 => {
598 let (remain, primary) = be_socket_addr_v4(input)?;
600 let (remain, agent) = be_socket_addr_v4(remain)?;
601 Ok((
602 remain,
603 EndpointAddr {
604 flags: EndpointAddr::FLAG_NAT,
605 sequence: None,
606 load: None,
607 signature: None,
608 primary: primary.into(),
609 agent: Some(agent.into()),
610 },
611 ))
612 }
613 18 => {
614 let (remain, addr) = be_socket_addr_v6(input)?;
616 Ok((
617 remain,
618 EndpointAddr {
619 flags: EndpointAddr::FLAG_FAMILY,
620 sequence: None,
621 load: None,
622 signature: None,
623 primary: addr.into(),
624 agent: None,
625 },
626 ))
627 }
628 36 => {
629 let (remain, primary) = be_socket_addr_v6(input)?;
631 let (remain, agent) = be_socket_addr_v6(remain)?;
632 Ok((
633 remain,
634 EndpointAddr {
635 flags: EndpointAddr::FLAG_FAMILY | EndpointAddr::FLAG_NAT,
636 sequence: None,
637 load: None,
638 signature: None,
639 primary: primary.into(),
640 agent: Some(agent.into()),
641 },
642 ))
643 }
644 _ => Err(nom::Err::Error(nom::error::make_error(
645 input,
646 nom::error::ErrorKind::LengthValue,
647 ))),
648 }
649}
650
651fn be_endpoint_signature(input: &[u8], flags: u8) -> IResult<&[u8], Option<EndpointSignature>> {
652 if (flags & EndpointAddr::FLAG_SIGNED) != EndpointAddr::FLAG_SIGNED {
653 if !input.is_empty() {
654 return Err(nom::Err::Error(make_error(input, ErrorKind::Eof)));
655 }
656 return Ok((input, None));
657 }
658
659 let (remain, scheme_u16) = be_u16(input)?;
660 let (remain, sig_len) = be_varint(remain)?;
661 let sig_len = usize::try_from(sig_len.into_inner())
662 .map_err(|_| nom::Err::Error(make_error(remain, ErrorKind::TooLarge)))?;
663 let (remain, sig) = take(sig_len)(remain)?;
664 Ok((
665 remain,
666 Some(EndpointSignature {
667 scheme: scheme_u16,
668 signature: sig.to_vec(),
669 }),
670 ))
671}
672
673pub trait WriteSocketAddr {
674 fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4);
675
676 fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6);
677
678 fn put_socket_addr(&mut self, addr: &SocketAddr) {
679 match addr {
680 SocketAddr::V4(v4) => self.put_socket_addr_v4(v4),
681 SocketAddr::V6(v6) => self.put_socket_addr_v6(v6),
682 }
683 }
684}
685
686impl<T: BufMut> WriteSocketAddr for T {
687 fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4) {
688 self.put_u16(addr.port());
689 self.put_u32(u32::from(*addr.ip()));
690 }
691
692 fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6) {
693 self.put_u16(addr.port());
694 self.put_u128(u128::from(*addr.ip()));
695 }
696}
697
698pub fn be_socket_addr_v4(input: &[u8]) -> IResult<&[u8], SocketAddrV4> {
699 flat_map(be_u16, |port| {
700 map(be_ipv4_addr, move |ip| SocketAddrV4::new(ip, port))
701 })
702 .parse(input)
703}
704
705pub fn be_socket_addr_v6(input: &[u8]) -> IResult<&[u8], SocketAddrV6> {
706 flat_map(be_u16, |port| {
707 map(be_ipv6_addr, move |ip| SocketAddrV6::new(ip, port, 0, 0))
708 })
709 .parse(input)
710}
711
712pub fn be_ipv4_addr(input: &[u8]) -> IResult<&[u8], Ipv4Addr> {
713 map(be_u32, Ipv4Addr::from).parse(input)
714}
715
716pub fn be_ipv6_addr(input: &[u8]) -> IResult<&[u8], Ipv6Addr> {
717 map(be_u128, Ipv6Addr::from).parse(input)
718}
719
720pub fn be_ip_addr(is_v6: bool) -> impl Fn(&[u8]) -> IResult<&[u8], IpAddr> {
721 move |input| match is_v6 {
722 true => map(be_u128, |ip| IpAddr::V6(Ipv6Addr::from(ip))).parse(input),
723 false => map(be_u32, |ip| IpAddr::V4(Ipv4Addr::from(ip))).parse(input),
724 }
725}
726
727impl Display for EndpointAddr {
728 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
729 if let Some(agent_addr) = &self.agent {
730 write!(f, "{}-{agent_addr}", self.primary)
731 } else {
732 write!(f, "{}", self.primary)
733 }
734 }
735}
736
737impl TryFrom<DquicEndpointAddr> for EndpointAddr {
738 type Error = ();
739
740 fn try_from(value: DquicEndpointAddr) -> Result<Self, Self::Error> {
741 match value {
742 DquicEndpointAddr::Direct {
743 addr: SocketAddr::V4(addr),
744 } => Ok(Self::direct_v4(addr)),
745 DquicEndpointAddr::Direct {
746 addr: SocketAddr::V6(addr),
747 } => Ok(Self::direct_v6(addr)),
748 DquicEndpointAddr::Agent {
749 agent: SocketAddr::V4(agent),
750 outer: SocketAddr::V4(outer),
751 } => Ok(Self::nat_v4(outer, agent)),
752 DquicEndpointAddr::Agent {
753 agent: SocketAddr::V6(agent),
754 outer: SocketAddr::V6(outer),
755 } => Ok(Self::nat_v6(outer, agent)),
756 _ => Err(()),
757 }
758 }
759}
760
761impl TryFrom<EndpointAddr> for DquicEndpointAddr {
762 type Error = ();
763
764 fn try_from(value: EndpointAddr) -> Result<Self, Self::Error> {
765 if let Some(agent_addr) = value.agent {
766 match (value.primary, agent_addr) {
767 (SocketAddr::V4(outer), SocketAddr::V4(agent)) => Ok(DquicEndpointAddr::Agent {
768 outer: SocketAddr::V4(outer),
769 agent: SocketAddr::V4(agent),
770 }),
771 (SocketAddr::V6(outer), SocketAddr::V6(agent)) => Ok(DquicEndpointAddr::Agent {
772 outer: SocketAddr::V6(outer),
773 agent: SocketAddr::V6(agent),
774 }),
775 _ => Err(()),
776 }
777 } else {
778 match value.primary {
779 SocketAddr::V4(addr) => Ok(DquicEndpointAddr::Direct {
780 addr: SocketAddr::V4(addr),
781 }),
782 SocketAddr::V6(addr) => Ok(DquicEndpointAddr::Direct {
783 addr: SocketAddr::V6(addr),
784 }),
785 }
786 }
787 }
788}
789
790pub async fn sign_endponit_address(
791 server_id: u8,
792 authority: Option<&(impl dhttp_identity::identity::LocalAuthority + ?Sized)>,
793 endpoint: DquicEndpointAddr,
794) -> Option<EndpointAddr> {
795 let mut ep: EndpointAddr = endpoint.try_into().ok()?;
796 ep.set_main(server_id == 0);
797 ep.set_sequence(CertificateSequence::from(server_id));
798 if let Some(authority) = authority {
799 let _ = ep.sign_with_authority(authority).await;
800 }
801 Some(ep)
802}
803
804#[cfg(test)]
805mod tests {
806 use std::{
807 net::{Ipv4Addr, Ipv6Addr},
808 sync::Arc,
809 };
810
811 use bytes::BytesMut;
812 use futures::future::BoxFuture;
813 use ring::signature::KeyPair;
814 use rustls::sign::{Signer, SigningKey};
815
816 use super::*;
817
818 fn v4_outer() -> SocketAddrV4 {
819 SocketAddrV4::new(Ipv4Addr::new(203, 0, 113, 10), 4433)
820 }
821
822 #[test]
823 fn endpoint_certificate_chain_key_normalizes_missing_sequence() {
824 let mut endpoint = EndpointAddr::direct_v4(v4_outer());
825 endpoint.set_main(true);
826
827 let key = endpoint.certificate_chain_key();
828
829 assert_eq!(
830 key.kind(),
831 dhttp_identity::certificate::CertificateChainKind::Primary
832 );
833 assert_eq!(key.sequence().get(), 0);
834 assert_eq!(key.to_string(), "primary:0");
835 }
836
837 #[test]
838 fn endpoint_certificate_chain_key_uses_present_sequence() {
839 let mut endpoint = EndpointAddr::direct_v4(v4_outer());
840 endpoint.set_main(false);
841 endpoint.set_sequence(
842 dhttp_identity::certificate::CertificateSequence::try_from(7u32).unwrap(),
843 );
844
845 let key = endpoint.certificate_chain_key();
846
847 assert_eq!(
848 key.kind(),
849 dhttp_identity::certificate::CertificateChainKind::Secondary
850 );
851 assert_eq!(key.sequence().get(), 7);
852 assert_eq!(key.to_string(), "secondary:7");
853 }
854
855 #[test]
856 fn endpoint_parser_rejects_over_range_certificate_sequence() {
857 let sequence = crate::core::parser::varint::VarInt::from_u64(
858 dhttp_identity::certificate::CertificateSequence::MAX as u64 + 1,
859 )
860 .unwrap();
861 let mut packet = BytesMut::new();
862 packet.put_u8(EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED);
863 packet.put_varint(sequence);
864 packet.put_u16(v4_outer().port());
865 packet.put_slice(&v4_outer().ip().octets());
866
867 assert!(be_endpoint_addr(&packet).is_err());
868 }
869
870 #[test]
871 fn legacy_endpoint_v4_direct_without_meta() {
872 let port = 5353u16;
873 let ip = Ipv4Addr::new(10, 0, 0, 1);
874 let mut buf = BytesMut::new();
875 buf.extend_from_slice(&port.to_be_bytes());
876 buf.extend_from_slice(&u32::from(ip).to_be_bytes());
877 let (remain, decoded) = be_endpoint_addr_compat(&buf, 6).unwrap();
878 assert!(remain.is_empty());
879 assert_eq!(
880 decoded,
881 EndpointAddr::direct_v4(SocketAddrV4::new(ip, port))
882 );
883 }
884
885 #[test]
886 fn legacy_endpoint_v4_nat_without_meta() {
887 let outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
888 let agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
889 let mut buf = BytesMut::new();
890 buf.extend_from_slice(&outer.port().to_be_bytes());
891 buf.extend_from_slice(&u32::from(*outer.ip()).to_be_bytes());
892 buf.extend_from_slice(&agent.port().to_be_bytes());
893 buf.extend_from_slice(&u32::from(*agent.ip()).to_be_bytes());
894 let (remain, decoded) = be_endpoint_addr_compat(&buf, 12).unwrap();
895 assert!(remain.is_empty());
896 assert_eq!(decoded, EndpointAddr::nat_v4(outer, agent));
897 }
898
899 #[test]
900 fn flag_bit_ops_work() {
901 let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
902 let mut ep = EndpointAddr {
903 flags: 0b0011_0000,
904 sequence: None,
905 load: None,
906 signature: None,
907 primary: addr.into(),
908 agent: None,
909 };
910
911 assert!(!ep.is_main());
912 assert!(!ep.is_signed());
913
914 ep.set_main(true);
915 assert!(ep.is_main());
916 assert_eq!(ep.flags, 0b0111_0000);
917
918 ep.set_signed(true);
919 assert!(ep.is_signed());
920 assert_eq!(ep.flags, 0b0111_0001);
921
922 ep.set_main(false);
923 assert!(!ep.is_main());
924 assert!(ep.is_signed());
925 assert_eq!(ep.flags, 0b0011_0001);
926
927 ep.set_signed(false);
928 assert!(!ep.is_signed());
929 assert_eq!(ep.flags, 0b0011_0000);
930 }
931
932 #[test]
933 fn varint_roundtrip_and_len() {
934 fn roundtrip(v: u64) {
935 let v = VarInt::from_u64(v).unwrap();
936 let mut buf = BytesMut::new();
937 buf.put_varint(v);
938 assert_eq!(buf.len(), v.encoding_size());
939 let (remain, decoded) = be_varint(&buf).unwrap();
940 assert!(remain.is_empty());
941 assert_eq!(decoded, v);
942 }
943
944 for v in [
945 0u64,
946 1,
947 63,
948 64,
949 16383,
950 16384,
951 (1 << 30) - 1,
952 1 << 30,
953 (1 << 62) - 1,
954 ] {
955 roundtrip(v);
956 }
957 }
958
959 #[test]
960 fn varint_rejects_overflow_and_incomplete() {
961 assert!(VarInt::from_u64((1 << 62) + 1).is_err());
962
963 let incomplete = [0b01_000000u8];
964 match be_varint(&incomplete) {
965 Err(nom::Err::Incomplete(_)) => {}
966 other => panic!("expected Incomplete, got {other:?}"),
967 }
968 }
969
970 #[test]
971 fn endpoint_encode_decode_roundtrip() {
972 let v4_outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
973 let v4_agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
974 let v6_outer = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 3000, 0, 0);
975 let v6_agent = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 4000, 0, 0);
976
977 let mut with_load = EndpointAddr::direct_v4(v4_outer);
978 with_load.set_load(Some(0.42_f32));
979
980 let cases = vec![
981 EndpointAddr {
983 flags: EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED,
984 sequence: Some(CertificateSequence::from(0u8)),
985 load: None,
986 signature: None,
987 primary: v4_outer.into(),
988 agent: None,
989 },
990 EndpointAddr {
992 flags: EndpointAddr::FLAG_NAT | EndpointAddr::FLAG_CLUSTERED,
993 sequence: Some(CertificateSequence::try_from(127u32).unwrap()),
994 load: None,
995 signature: None,
996 primary: v4_outer.into(),
997 agent: Some(v4_agent.into()),
998 },
999 EndpointAddr {
1001 flags: EndpointAddr::FLAG_FAMILY
1002 | EndpointAddr::FLAG_MAIN
1003 | EndpointAddr::FLAG_CLUSTERED,
1004 sequence: Some(CertificateSequence::try_from(128u32).unwrap()),
1005 load: None,
1006 signature: None,
1007 primary: v6_outer.into(),
1008 agent: None,
1009 },
1010 EndpointAddr {
1012 flags: EndpointAddr::FLAG_FAMILY
1013 | EndpointAddr::FLAG_NAT
1014 | EndpointAddr::FLAG_CLUSTERED,
1015 sequence: Some(CertificateSequence::try_from(16_384u32).unwrap()),
1016 load: None,
1017 signature: None,
1018 primary: v6_outer.into(),
1019 agent: Some(v6_agent.into()),
1020 },
1021 with_load,
1023 ];
1024
1025 for ep in cases {
1026 let mut buf = BytesMut::new();
1027 buf.put_endpoint_addr(&ep);
1028 assert_eq!(buf.len(), ep.encpding_size());
1029
1030 let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1031 assert!(remain.is_empty());
1032 assert_eq!(decoded, ep);
1033 }
1034 }
1035
1036 #[test]
1037 fn compat_parser_does_not_misclassify_modern_lengths_as_legacy() {
1038 let mut direct = EndpointAddr::direct_v4("203.0.113.10:4433".parse().unwrap());
1039 direct.set_main(true);
1040 direct.set_sequence(CertificateSequence::try_from(10u32).unwrap());
1041 direct.set_load(Some(1.0));
1042
1043 let mut nat = EndpointAddr::nat_v4(
1044 "198.51.100.10:4433".parse().unwrap(),
1045 "192.0.2.10:4433".parse().unwrap(),
1046 );
1047 nat.set_main(true);
1048 nat.set_sequence(CertificateSequence::from(1u8));
1049 nat.set_load(Some(2.0));
1050
1051 for endpoint in [direct, nat] {
1052 let mut buf = BytesMut::new();
1053 buf.put_endpoint_addr(&endpoint);
1054 assert!([12, 18].contains(&buf.len()));
1055
1056 let (remaining, decoded) =
1057 be_endpoint_addr_compat(&buf, u16::try_from(buf.len()).unwrap()).unwrap();
1058 assert!(remaining.is_empty());
1059 assert_eq!(decoded, endpoint);
1060 }
1061 }
1062
1063 #[test]
1064 fn endpoint_signature_roundtrip_and_verify() {
1065 #[derive(Debug)]
1066 struct Ed25519Key {
1067 keypair: Arc<ring::signature::Ed25519KeyPair>,
1068 cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1069 }
1070
1071 #[derive(Debug)]
1072 struct Ed25519Signer(Arc<ring::signature::Ed25519KeyPair>);
1073
1074 impl Signer for Ed25519Signer {
1075 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
1076 Ok(self.0.sign(message).as_ref().to_vec())
1077 }
1078
1079 fn scheme(&self) -> SignatureScheme {
1080 SignatureScheme::ED25519
1081 }
1082 }
1083
1084 impl SigningKey for Ed25519Key {
1085 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
1086 offered
1087 .contains(&SignatureScheme::ED25519)
1088 .then(|| Box::new(Ed25519Signer(self.keypair.clone())) as Box<dyn Signer>)
1089 }
1090
1091 fn algorithm(&self) -> rustls::SignatureAlgorithm {
1092 rustls::SignatureAlgorithm::ED25519
1093 }
1094 }
1095
1096 impl dhttp_identity::identity::LocalAuthority for Ed25519Key {
1097 fn name(&self) -> &str {
1098 "authority.example"
1099 }
1100
1101 fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1102 &self.cert_chain
1103 }
1104
1105 fn sign(
1106 &self,
1107 data: &[u8],
1108 ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1109 let result = dhttp_identity::identity::sign_with_key(self, data);
1110 Box::pin(std::future::ready(result))
1111 }
1112 }
1113
1114 let rng = ring::rand::SystemRandom::new();
1115 let pkcs8 = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
1116 let keypair =
1117 Arc::new(ring::signature::Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap());
1118 let mut spki = Vec::with_capacity(44);
1119 spki.extend_from_slice(&[
1120 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
1121 ]);
1122 spki.extend_from_slice(keypair.public_key().as_ref());
1123 let key = Ed25519Key {
1124 keypair: keypair.clone(),
1125 cert_chain: vec![rustls::pki_types::CertificateDer::from(spki.clone())],
1126 };
1127
1128 let addr = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 5353);
1129 let mut ep = EndpointAddr::direct_v4(addr);
1130 ep.set_main(true);
1131 futures::executor::block_on(ep.sign_with_authority(&key)).unwrap();
1132
1133 let mut buf = BytesMut::new();
1134 buf.put_endpoint_addr(&ep);
1135 assert_eq!(buf.len(), ep.encpding_size());
1136
1137 let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1138 assert!(remain.is_empty());
1139 assert!(decoded.is_signed());
1140 assert!(decoded.signature().is_some());
1141 assert!(
1142 decoded
1143 .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1144 .unwrap()
1145 );
1146
1147 let mut tampered = decoded.clone();
1148 tampered.set_main(false);
1149 assert!(
1150 !tampered
1151 .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1152 .unwrap()
1153 );
1154 }
1155
1156 #[test]
1157 fn sign_with_authority_uses_canonical_scheme_from_public_key() {
1158 #[derive(Debug)]
1159 struct Ed25519Authority {
1160 cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1161 }
1162
1163 impl dhttp_identity::identity::LocalAuthority for Ed25519Authority {
1164 fn name(&self) -> &str {
1165 "authority.example"
1166 }
1167
1168 fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1169 &self.cert_chain
1170 }
1171
1172 fn sign(
1173 &self,
1174 _data: &[u8],
1175 ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1176 Box::pin(async move { Ok(vec![1, 2, 3]) })
1177 }
1178 }
1179
1180 let cert_chain = vec![rustls::pki_types::CertificateDer::from(vec![
1181 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0, 0, 0, 0, 0,
1182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1183 ])];
1184 let mut ep = EndpointAddr::direct_v4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 5353));
1185 futures::executor::block_on(ep.sign_with_authority(&Ed25519Authority { cert_chain }))
1186 .unwrap();
1187
1188 let signature = ep.signature().unwrap();
1189 assert_eq!(
1190 SignatureScheme::from(signature.scheme),
1191 SignatureScheme::ED25519
1192 );
1193 assert_eq!(signature.signature, vec![1, 2, 3]);
1194 }
1195
1196 #[test]
1197 fn optional_fields_flags_follow_values() {
1198 let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
1199 let mut ep = EndpointAddr::direct_v4(addr);
1200
1201 assert!(!ep.is_load());
1202
1203 ep.set_load(Some(0.5_f32));
1204
1205 assert!(ep.is_load());
1206 assert_eq!(ep.load(), Some(0.5_f32));
1207
1208 ep.set_load(None);
1209
1210 assert!(!ep.is_load());
1211 assert_eq!(ep.load(), None);
1212 }
1213}