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, 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 if self.is_main() {
391 crate::core::certificate::primary_chain_key(self.normalized_sequence())
392 } else {
393 crate::core::certificate::secondary_chain_key(self.normalized_sequence())
394 }
395 }
396
397 pub fn load(&self) -> Option<f32> {
398 self.load
399 }
400
401 fn flags(&self) -> u8 {
402 self.flags
403 }
404
405 fn flags_mut(&mut self) -> &mut u8 {
406 &mut self.flags
407 }
408
409 pub fn signature(&self) -> Option<&EndpointSignature> {
410 self.signature.as_ref()
411 }
412
413 pub fn signature_base64(&self) -> Option<String> {
414 self.signature
415 .as_ref()
416 .map(|sig| base64::engine::general_purpose::STANDARD.encode(&sig.signature))
417 }
418
419 fn write_base<B: BufMut>(&self, buf: &mut B) {
420 buf.put_u8(self.flags);
421
422 if let Some(seq) = &self.sequence {
424 buf.put_varint(VarInt::from_u32(seq.get()));
425 }
426
427 match self.primary {
429 SocketAddr::V4(addr) => buf.put_socket_addr_v4(&addr),
430 SocketAddr::V6(addr) => buf.put_socket_addr_v6(&addr),
431 }
432
433 if let Some(agent_addr) = &self.agent {
435 match agent_addr {
436 SocketAddr::V4(addr) => buf.put_socket_addr_v4(addr),
437 SocketAddr::V6(addr) => buf.put_socket_addr_v6(addr),
438 }
439 }
440
441 if let Some(load) = self.load {
442 buf.put_u32(load.to_bits());
443 }
444 }
445
446 fn signed_data(&self) -> Vec<u8> {
447 let mut unsigned = self.clone();
448 unsigned.set_signed(true);
449 unsigned.signature = None;
450 let mut buf = bytes::BytesMut::with_capacity(unsigned.encpding_size());
451 unsigned.write_base(&mut buf);
452 buf.to_vec()
453 }
454}
455
456pub(crate) trait WriteEndpointAddr {
457 fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr);
458}
459
460impl<B: BufMut> WriteEndpointAddr for B {
461 fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr) {
462 endpoint.write_base(self);
463 if endpoint.is_signed()
464 && let Some(sig) = endpoint.signature()
465 {
466 self.put_u16(sig.scheme);
467 let len = VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
468 self.put_varint(len);
469 self.put_slice(&sig.signature);
470 }
471 }
472}
473
474pub fn be_endpoint_addr(input: &[u8]) -> nom::IResult<&[u8], EndpointAddr> {
475 let (remain, flags) = be_u8(input)?;
476
477 let is_clustered = flags & EndpointAddr::FLAG_CLUSTERED != 0;
478 let is_ipv6 = flags & EndpointAddr::FLAG_FAMILY != 0;
479 let is_nat = flags & EndpointAddr::FLAG_NAT != 0;
480 let has_load = flags & EndpointAddr::FLAG_LOAD != 0;
481
482 let (remain, sequence) = if is_clustered {
484 let (remain, seq) = be_varint(remain)?;
485 let sequence = match CertificateSequence::try_from(seq.into_inner()) {
486 Ok(sequence) => sequence,
487 Err(_error) => {
488 return Err(nom::Err::Failure(make_error(remain, ErrorKind::TooLarge)));
489 }
490 };
491 (remain, Some(sequence))
492 } else {
493 (remain, None)
494 };
495
496 let (remain, primary) = if is_ipv6 {
497 let (remain, addr) = be_socket_addr_v6(remain)?;
498 (remain, SocketAddr::V6(addr))
499 } else {
500 let (remain, addr) = be_socket_addr_v4(remain)?;
501 (remain, SocketAddr::V4(addr))
502 };
503
504 let (remain, agent) = if is_nat {
505 let agent_addr = if is_ipv6 {
506 let (remain, addr) = be_socket_addr_v6(remain)?;
507 (remain, SocketAddr::V6(addr))
508 } else {
509 let (remain, addr) = be_socket_addr_v4(remain)?;
510 (remain, SocketAddr::V4(addr))
511 };
512 let (remain, addr) = agent_addr;
513 (remain, Some(addr))
514 } else {
515 (remain, None)
516 };
517
518 let (remain, load) = if has_load {
519 let (remain, load) = be_u32(remain)?;
520 (remain, Some(f32::from_bits(load)))
521 } else {
522 (remain, None)
523 };
524
525 let (remain, signature) = be_endpoint_signature(remain, flags)?;
526
527 Ok((
528 remain,
529 EndpointAddr {
530 flags,
531 sequence,
532 load,
533 signature,
534 primary,
535 agent,
536 },
537 ))
538}
539
540pub(crate) fn be_endpoint_addr_compat(
548 input: &[u8],
549 rdlen: u16,
550) -> nom::IResult<&[u8], EndpointAddr> {
551 let legacy_lengths = [
553 6, 12, 18, 36, ];
558
559 if legacy_lengths.contains(&(rdlen as usize)) {
560 if let Ok((remaining, endpoint)) = be_endpoint_addr(input)
564 && remaining.is_empty()
565 {
566 return Ok((remaining, endpoint));
567 }
568 return be_legacy_endpoint_addr_by_length(input, rdlen);
569 }
570
571 be_endpoint_addr(input)
573}
574
575fn be_legacy_endpoint_addr_by_length(
577 input: &[u8],
578 rdlen: u16,
579) -> nom::IResult<&[u8], EndpointAddr> {
580 match rdlen {
581 6 => {
582 let (remain, addr) = be_socket_addr_v4(input)?;
584 Ok((
585 remain,
586 EndpointAddr {
587 flags: 0,
588 sequence: None,
589 load: None,
590 signature: None,
591 primary: addr.into(),
592 agent: None,
593 },
594 ))
595 }
596 12 => {
597 let (remain, primary) = be_socket_addr_v4(input)?;
599 let (remain, agent) = be_socket_addr_v4(remain)?;
600 Ok((
601 remain,
602 EndpointAddr {
603 flags: EndpointAddr::FLAG_NAT,
604 sequence: None,
605 load: None,
606 signature: None,
607 primary: primary.into(),
608 agent: Some(agent.into()),
609 },
610 ))
611 }
612 18 => {
613 let (remain, addr) = be_socket_addr_v6(input)?;
615 Ok((
616 remain,
617 EndpointAddr {
618 flags: EndpointAddr::FLAG_FAMILY,
619 sequence: None,
620 load: None,
621 signature: None,
622 primary: addr.into(),
623 agent: None,
624 },
625 ))
626 }
627 36 => {
628 let (remain, primary) = be_socket_addr_v6(input)?;
630 let (remain, agent) = be_socket_addr_v6(remain)?;
631 Ok((
632 remain,
633 EndpointAddr {
634 flags: EndpointAddr::FLAG_FAMILY | EndpointAddr::FLAG_NAT,
635 sequence: None,
636 load: None,
637 signature: None,
638 primary: primary.into(),
639 agent: Some(agent.into()),
640 },
641 ))
642 }
643 _ => Err(nom::Err::Error(nom::error::make_error(
644 input,
645 nom::error::ErrorKind::LengthValue,
646 ))),
647 }
648}
649
650fn be_endpoint_signature(input: &[u8], flags: u8) -> IResult<&[u8], Option<EndpointSignature>> {
651 if (flags & EndpointAddr::FLAG_SIGNED) != EndpointAddr::FLAG_SIGNED {
652 if !input.is_empty() {
653 return Err(nom::Err::Error(make_error(input, ErrorKind::Eof)));
654 }
655 return Ok((input, None));
656 }
657
658 let (remain, scheme_u16) = be_u16(input)?;
659 let (remain, sig_len) = be_varint(remain)?;
660 let sig_len = usize::try_from(sig_len.into_inner())
661 .map_err(|_| nom::Err::Error(make_error(remain, ErrorKind::TooLarge)))?;
662 let (remain, sig) = take(sig_len)(remain)?;
663 Ok((
664 remain,
665 Some(EndpointSignature {
666 scheme: scheme_u16,
667 signature: sig.to_vec(),
668 }),
669 ))
670}
671
672pub trait WriteSocketAddr {
673 fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4);
674
675 fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6);
676
677 fn put_socket_addr(&mut self, addr: &SocketAddr) {
678 match addr {
679 SocketAddr::V4(v4) => self.put_socket_addr_v4(v4),
680 SocketAddr::V6(v6) => self.put_socket_addr_v6(v6),
681 }
682 }
683}
684
685impl<T: BufMut> WriteSocketAddr for T {
686 fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4) {
687 self.put_u16(addr.port());
688 self.put_u32(u32::from(*addr.ip()));
689 }
690
691 fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6) {
692 self.put_u16(addr.port());
693 self.put_u128(u128::from(*addr.ip()));
694 }
695}
696
697pub fn be_socket_addr_v4(input: &[u8]) -> IResult<&[u8], SocketAddrV4> {
698 flat_map(be_u16, |port| {
699 map(be_ipv4_addr, move |ip| SocketAddrV4::new(ip, port))
700 })
701 .parse(input)
702}
703
704pub fn be_socket_addr_v6(input: &[u8]) -> IResult<&[u8], SocketAddrV6> {
705 flat_map(be_u16, |port| {
706 map(be_ipv6_addr, move |ip| SocketAddrV6::new(ip, port, 0, 0))
707 })
708 .parse(input)
709}
710
711pub fn be_ipv4_addr(input: &[u8]) -> IResult<&[u8], Ipv4Addr> {
712 map(be_u32, Ipv4Addr::from).parse(input)
713}
714
715pub fn be_ipv6_addr(input: &[u8]) -> IResult<&[u8], Ipv6Addr> {
716 map(be_u128, Ipv6Addr::from).parse(input)
717}
718
719pub fn be_ip_addr(is_v6: bool) -> impl Fn(&[u8]) -> IResult<&[u8], IpAddr> {
720 move |input| match is_v6 {
721 true => map(be_u128, |ip| IpAddr::V6(Ipv6Addr::from(ip))).parse(input),
722 false => map(be_u32, |ip| IpAddr::V4(Ipv4Addr::from(ip))).parse(input),
723 }
724}
725
726impl Display for EndpointAddr {
727 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
728 if let Some(agent_addr) = &self.agent {
729 write!(f, "{}-{agent_addr}", self.primary)
730 } else {
731 write!(f, "{}", self.primary)
732 }
733 }
734}
735
736impl TryFrom<DquicEndpointAddr> for EndpointAddr {
737 type Error = ();
738
739 fn try_from(value: DquicEndpointAddr) -> Result<Self, Self::Error> {
740 match value {
741 DquicEndpointAddr::Direct {
742 addr: SocketAddr::V4(addr),
743 } => Ok(Self::direct_v4(addr)),
744 DquicEndpointAddr::Direct {
745 addr: SocketAddr::V6(addr),
746 } => Ok(Self::direct_v6(addr)),
747 DquicEndpointAddr::Mediate {
748 agent: SocketAddr::V4(agent),
749 outer: SocketAddr::V4(outer),
750 } => Ok(Self::nat_v4(outer, agent)),
751 DquicEndpointAddr::Mediate {
752 agent: SocketAddr::V6(agent),
753 outer: SocketAddr::V6(outer),
754 } => Ok(Self::nat_v6(outer, agent)),
755 _ => Err(()),
756 }
757 }
758}
759
760impl TryFrom<EndpointAddr> for DquicEndpointAddr {
761 type Error = ();
762
763 fn try_from(value: EndpointAddr) -> Result<Self, Self::Error> {
764 if let Some(agent_addr) = value.agent {
765 match (value.primary, agent_addr) {
766 (SocketAddr::V4(outer), SocketAddr::V4(agent)) => Ok(DquicEndpointAddr::Mediate {
767 outer: SocketAddr::V4(outer),
768 agent: SocketAddr::V4(agent),
769 }),
770 (SocketAddr::V6(outer), SocketAddr::V6(agent)) => Ok(DquicEndpointAddr::Mediate {
771 outer: SocketAddr::V6(outer),
772 agent: SocketAddr::V6(agent),
773 }),
774 _ => Err(()),
775 }
776 } else {
777 match value.primary {
778 SocketAddr::V4(addr) => Ok(DquicEndpointAddr::Direct {
779 addr: SocketAddr::V4(addr),
780 }),
781 SocketAddr::V6(addr) => Ok(DquicEndpointAddr::Direct {
782 addr: SocketAddr::V6(addr),
783 }),
784 }
785 }
786 }
787}
788
789pub async fn sign_endponit_address(
790 server_id: u8,
791 authority: Option<&(impl dhttp_identity::identity::LocalAuthority + ?Sized)>,
792 endpoint: DquicEndpointAddr,
793) -> Option<EndpointAddr> {
794 let mut ep: EndpointAddr = endpoint.try_into().ok()?;
795 ep.set_main(server_id == 0);
796 ep.set_sequence(CertificateSequence::from(server_id));
797 if let Some(authority) = authority {
798 let _ = ep.sign_with_authority(authority).await;
799 }
800 Some(ep)
801}
802
803#[cfg(test)]
804mod tests {
805 use std::{
806 net::{Ipv4Addr, Ipv6Addr},
807 sync::Arc,
808 };
809
810 use bytes::BytesMut;
811 use futures::future::BoxFuture;
812 use ring::signature::KeyPair;
813 use rustls::sign::{Signer, SigningKey};
814
815 use super::*;
816
817 fn v4_outer() -> SocketAddrV4 {
818 SocketAddrV4::new(Ipv4Addr::new(203, 0, 113, 10), 4433)
819 }
820
821 #[test]
822 fn endpoint_certificate_chain_key_normalizes_missing_sequence() {
823 let mut endpoint = EndpointAddr::direct_v4(v4_outer());
824 endpoint.set_main(true);
825
826 let key = endpoint.certificate_chain_key();
827
828 assert_eq!(key.usage().kind_flag(), "0");
829 assert_eq!(key.sequence().get(), 0);
830 }
831
832 #[test]
833 fn endpoint_certificate_chain_key_uses_present_sequence() {
834 let mut endpoint = EndpointAddr::direct_v4(v4_outer());
835 endpoint.set_main(false);
836 endpoint.set_sequence(
837 dhttp_identity::certificate::CertificateSequence::try_from(7u32).unwrap(),
838 );
839
840 let key = endpoint.certificate_chain_key();
841
842 assert_eq!(key.usage().kind_flag(), "1");
843 assert_eq!(key.sequence().get(), 7);
844 }
845
846 #[test]
847 fn endpoint_parser_rejects_over_range_certificate_sequence() {
848 let sequence = crate::core::parser::varint::VarInt::from_u64(
849 dhttp_identity::certificate::CertificateSequence::MAX as u64 + 1,
850 )
851 .unwrap();
852 let mut packet = BytesMut::new();
853 packet.put_u8(EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED);
854 packet.put_varint(sequence);
855 packet.put_u16(v4_outer().port());
856 packet.put_slice(&v4_outer().ip().octets());
857
858 assert!(be_endpoint_addr(&packet).is_err());
859 }
860
861 #[test]
862 fn legacy_endpoint_v4_direct_without_meta() {
863 let port = 5353u16;
864 let ip = Ipv4Addr::new(10, 0, 0, 1);
865 let mut buf = BytesMut::new();
866 buf.extend_from_slice(&port.to_be_bytes());
867 buf.extend_from_slice(&u32::from(ip).to_be_bytes());
868 let (remain, decoded) = be_endpoint_addr_compat(&buf, 6).unwrap();
869 assert!(remain.is_empty());
870 assert_eq!(
871 decoded,
872 EndpointAddr::direct_v4(SocketAddrV4::new(ip, port))
873 );
874 }
875
876 #[test]
877 fn legacy_endpoint_v4_nat_without_meta() {
878 let outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
879 let agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
880 let mut buf = BytesMut::new();
881 buf.extend_from_slice(&outer.port().to_be_bytes());
882 buf.extend_from_slice(&u32::from(*outer.ip()).to_be_bytes());
883 buf.extend_from_slice(&agent.port().to_be_bytes());
884 buf.extend_from_slice(&u32::from(*agent.ip()).to_be_bytes());
885 let (remain, decoded) = be_endpoint_addr_compat(&buf, 12).unwrap();
886 assert!(remain.is_empty());
887 assert_eq!(decoded, EndpointAddr::nat_v4(outer, agent));
888 }
889
890 #[test]
891 fn flag_bit_ops_work() {
892 let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
893 let mut ep = EndpointAddr {
894 flags: 0b0011_0000,
895 sequence: None,
896 load: None,
897 signature: None,
898 primary: addr.into(),
899 agent: None,
900 };
901
902 assert!(!ep.is_main());
903 assert!(!ep.is_signed());
904
905 ep.set_main(true);
906 assert!(ep.is_main());
907 assert_eq!(ep.flags, 0b0111_0000);
908
909 ep.set_signed(true);
910 assert!(ep.is_signed());
911 assert_eq!(ep.flags, 0b0111_0001);
912
913 ep.set_main(false);
914 assert!(!ep.is_main());
915 assert!(ep.is_signed());
916 assert_eq!(ep.flags, 0b0011_0001);
917
918 ep.set_signed(false);
919 assert!(!ep.is_signed());
920 assert_eq!(ep.flags, 0b0011_0000);
921 }
922
923 #[test]
924 fn varint_roundtrip_and_len() {
925 fn roundtrip(v: u64) {
926 let v = VarInt::from_u64(v).unwrap();
927 let mut buf = BytesMut::new();
928 buf.put_varint(v);
929 assert_eq!(buf.len(), v.encoding_size());
930 let (remain, decoded) = be_varint(&buf).unwrap();
931 assert!(remain.is_empty());
932 assert_eq!(decoded, v);
933 }
934
935 for v in [
936 0u64,
937 1,
938 63,
939 64,
940 16383,
941 16384,
942 (1 << 30) - 1,
943 1 << 30,
944 (1 << 62) - 1,
945 ] {
946 roundtrip(v);
947 }
948 }
949
950 #[test]
951 fn varint_rejects_overflow_and_incomplete() {
952 assert!(VarInt::from_u64((1 << 62) + 1).is_err());
953
954 let incomplete = [0b01_000000u8];
955 match be_varint(&incomplete) {
956 Err(nom::Err::Incomplete(_)) => {}
957 other => panic!("expected Incomplete, got {other:?}"),
958 }
959 }
960
961 #[test]
962 fn endpoint_encode_decode_roundtrip() {
963 let v4_outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
964 let v4_agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
965 let v6_outer = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 3000, 0, 0);
966 let v6_agent = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 4000, 0, 0);
967
968 let mut with_load = EndpointAddr::direct_v4(v4_outer);
969 with_load.set_load(Some(0.42_f32));
970
971 let cases = vec![
972 EndpointAddr {
974 flags: EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED,
975 sequence: Some(CertificateSequence::from(0u8)),
976 load: None,
977 signature: None,
978 primary: v4_outer.into(),
979 agent: None,
980 },
981 EndpointAddr {
983 flags: EndpointAddr::FLAG_NAT | EndpointAddr::FLAG_CLUSTERED,
984 sequence: Some(CertificateSequence::try_from(127u32).unwrap()),
985 load: None,
986 signature: None,
987 primary: v4_outer.into(),
988 agent: Some(v4_agent.into()),
989 },
990 EndpointAddr {
992 flags: EndpointAddr::FLAG_FAMILY
993 | EndpointAddr::FLAG_MAIN
994 | EndpointAddr::FLAG_CLUSTERED,
995 sequence: Some(CertificateSequence::try_from(128u32).unwrap()),
996 load: None,
997 signature: None,
998 primary: v6_outer.into(),
999 agent: None,
1000 },
1001 EndpointAddr {
1003 flags: EndpointAddr::FLAG_FAMILY
1004 | EndpointAddr::FLAG_NAT
1005 | EndpointAddr::FLAG_CLUSTERED,
1006 sequence: Some(CertificateSequence::try_from(16_384u32).unwrap()),
1007 load: None,
1008 signature: None,
1009 primary: v6_outer.into(),
1010 agent: Some(v6_agent.into()),
1011 },
1012 with_load,
1014 ];
1015
1016 for ep in cases {
1017 let mut buf = BytesMut::new();
1018 buf.put_endpoint_addr(&ep);
1019 assert_eq!(buf.len(), ep.encpding_size());
1020
1021 let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1022 assert!(remain.is_empty());
1023 assert_eq!(decoded, ep);
1024 }
1025 }
1026
1027 #[test]
1028 fn compat_parser_does_not_misclassify_modern_lengths_as_legacy() {
1029 let mut direct = EndpointAddr::direct_v4("203.0.113.10:4433".parse().unwrap());
1030 direct.set_main(true);
1031 direct.set_sequence(CertificateSequence::try_from(10u32).unwrap());
1032 direct.set_load(Some(1.0));
1033
1034 let mut nat = EndpointAddr::nat_v4(
1035 "198.51.100.10:4433".parse().unwrap(),
1036 "192.0.2.10:4433".parse().unwrap(),
1037 );
1038 nat.set_main(true);
1039 nat.set_sequence(CertificateSequence::from(1u8));
1040 nat.set_load(Some(2.0));
1041
1042 for endpoint in [direct, nat] {
1043 let mut buf = BytesMut::new();
1044 buf.put_endpoint_addr(&endpoint);
1045 assert!([12, 18].contains(&buf.len()));
1046
1047 let (remaining, decoded) =
1048 be_endpoint_addr_compat(&buf, u16::try_from(buf.len()).unwrap()).unwrap();
1049 assert!(remaining.is_empty());
1050 assert_eq!(decoded, endpoint);
1051 }
1052 }
1053
1054 #[test]
1055 fn endpoint_signature_roundtrip_and_verify() {
1056 #[derive(Debug)]
1057 struct Ed25519Key {
1058 keypair: Arc<ring::signature::Ed25519KeyPair>,
1059 cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1060 }
1061
1062 #[derive(Debug)]
1063 struct Ed25519Signer(Arc<ring::signature::Ed25519KeyPair>);
1064
1065 impl Signer for Ed25519Signer {
1066 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
1067 Ok(self.0.sign(message).as_ref().to_vec())
1068 }
1069
1070 fn scheme(&self) -> SignatureScheme {
1071 SignatureScheme::ED25519
1072 }
1073 }
1074
1075 impl SigningKey for Ed25519Key {
1076 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
1077 offered
1078 .contains(&SignatureScheme::ED25519)
1079 .then(|| Box::new(Ed25519Signer(self.keypair.clone())) as Box<dyn Signer>)
1080 }
1081
1082 fn algorithm(&self) -> rustls::SignatureAlgorithm {
1083 rustls::SignatureAlgorithm::ED25519
1084 }
1085 }
1086
1087 impl dhttp_identity::identity::LocalAuthority for Ed25519Key {
1088 fn name(&self) -> &str {
1089 "authority.example"
1090 }
1091
1092 fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1093 &self.cert_chain
1094 }
1095
1096 fn sign(
1097 &self,
1098 data: &[u8],
1099 ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1100 let result = dhttp_identity::identity::sign_with_key(self, data);
1101 Box::pin(std::future::ready(result))
1102 }
1103 }
1104
1105 let rng = ring::rand::SystemRandom::new();
1106 let pkcs8 = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
1107 let keypair =
1108 Arc::new(ring::signature::Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap());
1109 let mut spki = Vec::with_capacity(44);
1110 spki.extend_from_slice(&[
1111 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
1112 ]);
1113 spki.extend_from_slice(keypair.public_key().as_ref());
1114 let key = Ed25519Key {
1115 keypair: keypair.clone(),
1116 cert_chain: vec![rustls::pki_types::CertificateDer::from(spki.clone())],
1117 };
1118
1119 let addr = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 5353);
1120 let mut ep = EndpointAddr::direct_v4(addr);
1121 ep.set_main(true);
1122 futures::executor::block_on(ep.sign_with_authority(&key)).unwrap();
1123
1124 let mut buf = BytesMut::new();
1125 buf.put_endpoint_addr(&ep);
1126 assert_eq!(buf.len(), ep.encpding_size());
1127
1128 let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1129 assert!(remain.is_empty());
1130 assert!(decoded.is_signed());
1131 assert!(decoded.signature().is_some());
1132 assert!(
1133 decoded
1134 .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1135 .unwrap()
1136 );
1137
1138 let mut tampered = decoded.clone();
1139 tampered.set_main(false);
1140 assert!(
1141 !tampered
1142 .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1143 .unwrap()
1144 );
1145 }
1146
1147 #[test]
1148 fn sign_with_authority_uses_canonical_scheme_from_public_key() {
1149 #[derive(Debug)]
1150 struct Ed25519Authority {
1151 cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1152 }
1153
1154 impl dhttp_identity::identity::LocalAuthority for Ed25519Authority {
1155 fn name(&self) -> &str {
1156 "authority.example"
1157 }
1158
1159 fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1160 &self.cert_chain
1161 }
1162
1163 fn sign(
1164 &self,
1165 _data: &[u8],
1166 ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1167 Box::pin(async move { Ok(vec![1, 2, 3]) })
1168 }
1169 }
1170
1171 let cert_chain = vec![rustls::pki_types::CertificateDer::from(vec![
1172 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0, 0, 0, 0, 0,
1173 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,
1174 ])];
1175 let mut ep = EndpointAddr::direct_v4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 5353));
1176 futures::executor::block_on(ep.sign_with_authority(&Ed25519Authority { cert_chain }))
1177 .unwrap();
1178
1179 let signature = ep.signature().unwrap();
1180 assert_eq!(
1181 SignatureScheme::from(signature.scheme),
1182 SignatureScheme::ED25519
1183 );
1184 assert_eq!(signature.signature, vec![1, 2, 3]);
1185 }
1186
1187 #[test]
1188 fn optional_fields_flags_follow_values() {
1189 let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
1190 let mut ep = EndpointAddr::direct_v4(addr);
1191
1192 assert!(!ep.is_load());
1193
1194 ep.set_load(Some(0.5_f32));
1195
1196 assert!(ep.is_load());
1197 assert_eq!(ep.load(), Some(0.5_f32));
1198
1199 ep.set_load(None);
1200
1201 assert!(!ep.is_load());
1202 assert_eq!(ep.load(), None);
1203 }
1204}