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 return be_legacy_endpoint_addr_by_length(input, rdlen);
562 }
563
564 be_endpoint_addr(input)
566}
567
568fn be_legacy_endpoint_addr_by_length(
570 input: &[u8],
571 rdlen: u16,
572) -> nom::IResult<&[u8], EndpointAddr> {
573 match rdlen {
574 6 => {
575 let (remain, addr) = be_socket_addr_v4(input)?;
577 Ok((
578 remain,
579 EndpointAddr {
580 flags: 0,
581 sequence: None,
582 load: None,
583 signature: None,
584 primary: addr.into(),
585 agent: None,
586 },
587 ))
588 }
589 12 => {
590 let (remain, primary) = be_socket_addr_v4(input)?;
592 let (remain, agent) = be_socket_addr_v4(remain)?;
593 Ok((
594 remain,
595 EndpointAddr {
596 flags: EndpointAddr::FLAG_NAT,
597 sequence: None,
598 load: None,
599 signature: None,
600 primary: primary.into(),
601 agent: Some(agent.into()),
602 },
603 ))
604 }
605 18 => {
606 let (remain, addr) = be_socket_addr_v6(input)?;
608 Ok((
609 remain,
610 EndpointAddr {
611 flags: EndpointAddr::FLAG_FAMILY,
612 sequence: None,
613 load: None,
614 signature: None,
615 primary: addr.into(),
616 agent: None,
617 },
618 ))
619 }
620 36 => {
621 let (remain, primary) = be_socket_addr_v6(input)?;
623 let (remain, agent) = be_socket_addr_v6(remain)?;
624 Ok((
625 remain,
626 EndpointAddr {
627 flags: EndpointAddr::FLAG_FAMILY | EndpointAddr::FLAG_NAT,
628 sequence: None,
629 load: None,
630 signature: None,
631 primary: primary.into(),
632 agent: Some(agent.into()),
633 },
634 ))
635 }
636 _ => Err(nom::Err::Error(nom::error::make_error(
637 input,
638 nom::error::ErrorKind::LengthValue,
639 ))),
640 }
641}
642
643fn be_endpoint_signature(input: &[u8], flags: u8) -> IResult<&[u8], Option<EndpointSignature>> {
644 if (flags & EndpointAddr::FLAG_SIGNED) != EndpointAddr::FLAG_SIGNED {
645 if !input.is_empty() {
646 return Err(nom::Err::Error(make_error(input, ErrorKind::Eof)));
647 }
648 return Ok((input, None));
649 }
650
651 let (remain, scheme_u16) = be_u16(input)?;
652 let (remain, sig_len) = be_varint(remain)?;
653 let sig_len = usize::try_from(sig_len.into_inner())
654 .map_err(|_| nom::Err::Error(make_error(remain, ErrorKind::TooLarge)))?;
655 let (remain, sig) = take(sig_len)(remain)?;
656 Ok((
657 remain,
658 Some(EndpointSignature {
659 scheme: scheme_u16,
660 signature: sig.to_vec(),
661 }),
662 ))
663}
664
665pub trait WriteSocketAddr {
666 fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4);
667
668 fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6);
669
670 fn put_socket_addr(&mut self, addr: &SocketAddr) {
671 match addr {
672 SocketAddr::V4(v4) => self.put_socket_addr_v4(v4),
673 SocketAddr::V6(v6) => self.put_socket_addr_v6(v6),
674 }
675 }
676}
677
678impl<T: BufMut> WriteSocketAddr for T {
679 fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4) {
680 self.put_u16(addr.port());
681 self.put_u32(u32::from(*addr.ip()));
682 }
683
684 fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6) {
685 self.put_u16(addr.port());
686 self.put_u128(u128::from(*addr.ip()));
687 }
688}
689
690pub fn be_socket_addr_v4(input: &[u8]) -> IResult<&[u8], SocketAddrV4> {
691 flat_map(be_u16, |port| {
692 map(be_ipv4_addr, move |ip| SocketAddrV4::new(ip, port))
693 })
694 .parse(input)
695}
696
697pub fn be_socket_addr_v6(input: &[u8]) -> IResult<&[u8], SocketAddrV6> {
698 flat_map(be_u16, |port| {
699 map(be_ipv6_addr, move |ip| SocketAddrV6::new(ip, port, 0, 0))
700 })
701 .parse(input)
702}
703
704pub fn be_ipv4_addr(input: &[u8]) -> IResult<&[u8], Ipv4Addr> {
705 map(be_u32, Ipv4Addr::from).parse(input)
706}
707
708pub fn be_ipv6_addr(input: &[u8]) -> IResult<&[u8], Ipv6Addr> {
709 map(be_u128, Ipv6Addr::from).parse(input)
710}
711
712pub fn be_ip_addr(is_v6: bool) -> impl Fn(&[u8]) -> IResult<&[u8], IpAddr> {
713 move |input| match is_v6 {
714 true => map(be_u128, |ip| IpAddr::V6(Ipv6Addr::from(ip))).parse(input),
715 false => map(be_u32, |ip| IpAddr::V4(Ipv4Addr::from(ip))).parse(input),
716 }
717}
718
719impl Display for EndpointAddr {
720 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
721 if let Some(agent_addr) = &self.agent {
722 write!(f, "{}-{agent_addr}", self.primary)
723 } else {
724 write!(f, "{}", self.primary)
725 }
726 }
727}
728
729impl TryFrom<DquicEndpointAddr> for EndpointAddr {
730 type Error = ();
731
732 fn try_from(value: DquicEndpointAddr) -> Result<Self, Self::Error> {
733 match value {
734 DquicEndpointAddr::Direct {
735 addr: SocketAddr::V4(addr),
736 } => Ok(Self::direct_v4(addr)),
737 DquicEndpointAddr::Direct {
738 addr: SocketAddr::V6(addr),
739 } => Ok(Self::direct_v6(addr)),
740 DquicEndpointAddr::Agent {
741 agent: SocketAddr::V4(agent),
742 outer: SocketAddr::V4(outer),
743 } => Ok(Self::nat_v4(outer, agent)),
744 DquicEndpointAddr::Agent {
745 agent: SocketAddr::V6(agent),
746 outer: SocketAddr::V6(outer),
747 } => Ok(Self::nat_v6(outer, agent)),
748 _ => Err(()),
749 }
750 }
751}
752
753impl TryFrom<EndpointAddr> for DquicEndpointAddr {
754 type Error = ();
755
756 fn try_from(value: EndpointAddr) -> Result<Self, Self::Error> {
757 if let Some(agent_addr) = value.agent {
758 match (value.primary, agent_addr) {
759 (SocketAddr::V4(outer), SocketAddr::V4(agent)) => Ok(DquicEndpointAddr::Agent {
760 outer: SocketAddr::V4(outer),
761 agent: SocketAddr::V4(agent),
762 }),
763 (SocketAddr::V6(outer), SocketAddr::V6(agent)) => Ok(DquicEndpointAddr::Agent {
764 outer: SocketAddr::V6(outer),
765 agent: SocketAddr::V6(agent),
766 }),
767 _ => Err(()),
768 }
769 } else {
770 match value.primary {
771 SocketAddr::V4(addr) => Ok(DquicEndpointAddr::Direct {
772 addr: SocketAddr::V4(addr),
773 }),
774 SocketAddr::V6(addr) => Ok(DquicEndpointAddr::Direct {
775 addr: SocketAddr::V6(addr),
776 }),
777 }
778 }
779 }
780}
781
782pub async fn sign_endponit_address(
783 server_id: u8,
784 authority: Option<&(impl dhttp_identity::identity::LocalAuthority + ?Sized)>,
785 endpoint: DquicEndpointAddr,
786) -> Option<EndpointAddr> {
787 let mut ep: EndpointAddr = endpoint.try_into().ok()?;
788 ep.set_main(server_id == 0);
789 ep.set_sequence(CertificateSequence::from(server_id));
790 if let Some(authority) = authority {
791 let _ = ep.sign_with_authority(authority).await;
792 }
793 Some(ep)
794}
795
796#[cfg(test)]
797mod tests {
798 use std::{
799 net::{Ipv4Addr, Ipv6Addr},
800 sync::Arc,
801 };
802
803 use bytes::BytesMut;
804 use futures::future::BoxFuture;
805 use ring::signature::KeyPair;
806 use rustls::sign::{Signer, SigningKey};
807
808 use super::*;
809
810 fn v4_outer() -> SocketAddrV4 {
811 SocketAddrV4::new(Ipv4Addr::new(203, 0, 113, 10), 4433)
812 }
813
814 #[test]
815 fn endpoint_certificate_chain_key_normalizes_missing_sequence() {
816 let mut endpoint = EndpointAddr::direct_v4(v4_outer());
817 endpoint.set_main(true);
818
819 let key = endpoint.certificate_chain_key();
820
821 assert_eq!(
822 key.kind(),
823 dhttp_identity::certificate::CertificateChainKind::Primary
824 );
825 assert_eq!(key.sequence().get(), 0);
826 assert_eq!(key.to_string(), "primary:0");
827 }
828
829 #[test]
830 fn endpoint_certificate_chain_key_uses_present_sequence() {
831 let mut endpoint = EndpointAddr::direct_v4(v4_outer());
832 endpoint.set_main(false);
833 endpoint.set_sequence(
834 dhttp_identity::certificate::CertificateSequence::try_from(7u32).unwrap(),
835 );
836
837 let key = endpoint.certificate_chain_key();
838
839 assert_eq!(
840 key.kind(),
841 dhttp_identity::certificate::CertificateChainKind::Secondary
842 );
843 assert_eq!(key.sequence().get(), 7);
844 assert_eq!(key.to_string(), "secondary:7");
845 }
846
847 #[test]
848 fn endpoint_parser_rejects_over_range_certificate_sequence() {
849 let sequence = crate::core::parser::varint::VarInt::from_u64(
850 dhttp_identity::certificate::CertificateSequence::MAX as u64 + 1,
851 )
852 .unwrap();
853 let mut packet = BytesMut::new();
854 packet.put_u8(EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED);
855 packet.put_varint(sequence);
856 packet.put_u16(v4_outer().port());
857 packet.put_slice(&v4_outer().ip().octets());
858
859 assert!(be_endpoint_addr(&packet).is_err());
860 }
861
862 #[test]
863 fn legacy_endpoint_v4_direct_without_meta() {
864 let port = 5353u16;
865 let ip = Ipv4Addr::new(10, 0, 0, 1);
866 let mut buf = BytesMut::new();
867 buf.extend_from_slice(&port.to_be_bytes());
868 buf.extend_from_slice(&u32::from(ip).to_be_bytes());
869 let (remain, decoded) = be_endpoint_addr_compat(&buf, 6).unwrap();
870 assert!(remain.is_empty());
871 assert_eq!(
872 decoded,
873 EndpointAddr::direct_v4(SocketAddrV4::new(ip, port))
874 );
875 }
876
877 #[test]
878 fn legacy_endpoint_v4_nat_without_meta() {
879 let outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
880 let agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
881 let mut buf = BytesMut::new();
882 buf.extend_from_slice(&outer.port().to_be_bytes());
883 buf.extend_from_slice(&u32::from(*outer.ip()).to_be_bytes());
884 buf.extend_from_slice(&agent.port().to_be_bytes());
885 buf.extend_from_slice(&u32::from(*agent.ip()).to_be_bytes());
886 let (remain, decoded) = be_endpoint_addr_compat(&buf, 12).unwrap();
887 assert!(remain.is_empty());
888 assert_eq!(decoded, EndpointAddr::nat_v4(outer, agent));
889 }
890
891 #[test]
892 fn flag_bit_ops_work() {
893 let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
894 let mut ep = EndpointAddr {
895 flags: 0b0011_0000,
896 sequence: None,
897 load: None,
898 signature: None,
899 primary: addr.into(),
900 agent: None,
901 };
902
903 assert!(!ep.is_main());
904 assert!(!ep.is_signed());
905
906 ep.set_main(true);
907 assert!(ep.is_main());
908 assert_eq!(ep.flags, 0b0111_0000);
909
910 ep.set_signed(true);
911 assert!(ep.is_signed());
912 assert_eq!(ep.flags, 0b0111_0001);
913
914 ep.set_main(false);
915 assert!(!ep.is_main());
916 assert!(ep.is_signed());
917 assert_eq!(ep.flags, 0b0011_0001);
918
919 ep.set_signed(false);
920 assert!(!ep.is_signed());
921 assert_eq!(ep.flags, 0b0011_0000);
922 }
923
924 #[test]
925 fn varint_roundtrip_and_len() {
926 fn roundtrip(v: u64) {
927 let v = VarInt::from_u64(v).unwrap();
928 let mut buf = BytesMut::new();
929 buf.put_varint(v);
930 assert_eq!(buf.len(), v.encoding_size());
931 let (remain, decoded) = be_varint(&buf).unwrap();
932 assert!(remain.is_empty());
933 assert_eq!(decoded, v);
934 }
935
936 for v in [
937 0u64,
938 1,
939 63,
940 64,
941 16383,
942 16384,
943 (1 << 30) - 1,
944 1 << 30,
945 (1 << 62) - 1,
946 ] {
947 roundtrip(v);
948 }
949 }
950
951 #[test]
952 fn varint_rejects_overflow_and_incomplete() {
953 assert!(VarInt::from_u64((1 << 62) + 1).is_err());
954
955 let incomplete = [0b01_000000u8];
956 match be_varint(&incomplete) {
957 Err(nom::Err::Incomplete(_)) => {}
958 other => panic!("expected Incomplete, got {other:?}"),
959 }
960 }
961
962 #[test]
963 fn endpoint_encode_decode_roundtrip() {
964 let v4_outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
965 let v4_agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
966 let v6_outer = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 3000, 0, 0);
967 let v6_agent = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 4000, 0, 0);
968
969 let mut with_load = EndpointAddr::direct_v4(v4_outer);
970 with_load.set_load(Some(0.42_f32));
971
972 let cases = vec![
973 EndpointAddr {
975 flags: EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED,
976 sequence: Some(CertificateSequence::from(0u8)),
977 load: None,
978 signature: None,
979 primary: v4_outer.into(),
980 agent: None,
981 },
982 EndpointAddr {
984 flags: EndpointAddr::FLAG_NAT | EndpointAddr::FLAG_CLUSTERED,
985 sequence: Some(CertificateSequence::try_from(127u32).unwrap()),
986 load: None,
987 signature: None,
988 primary: v4_outer.into(),
989 agent: Some(v4_agent.into()),
990 },
991 EndpointAddr {
993 flags: EndpointAddr::FLAG_FAMILY
994 | EndpointAddr::FLAG_MAIN
995 | EndpointAddr::FLAG_CLUSTERED,
996 sequence: Some(CertificateSequence::try_from(128u32).unwrap()),
997 load: None,
998 signature: None,
999 primary: v6_outer.into(),
1000 agent: None,
1001 },
1002 EndpointAddr {
1004 flags: EndpointAddr::FLAG_FAMILY
1005 | EndpointAddr::FLAG_NAT
1006 | EndpointAddr::FLAG_CLUSTERED,
1007 sequence: Some(CertificateSequence::try_from(16_384u32).unwrap()),
1008 load: None,
1009 signature: None,
1010 primary: v6_outer.into(),
1011 agent: Some(v6_agent.into()),
1012 },
1013 with_load,
1015 ];
1016
1017 for ep in cases {
1018 let mut buf = BytesMut::new();
1019 buf.put_endpoint_addr(&ep);
1020 assert_eq!(buf.len(), ep.encpding_size());
1021
1022 let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1023 assert!(remain.is_empty());
1024 assert_eq!(decoded, ep);
1025 }
1026 }
1027
1028 #[test]
1029 fn endpoint_signature_roundtrip_and_verify() {
1030 #[derive(Debug)]
1031 struct Ed25519Key {
1032 keypair: Arc<ring::signature::Ed25519KeyPair>,
1033 cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1034 }
1035
1036 #[derive(Debug)]
1037 struct Ed25519Signer(Arc<ring::signature::Ed25519KeyPair>);
1038
1039 impl Signer for Ed25519Signer {
1040 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
1041 Ok(self.0.sign(message).as_ref().to_vec())
1042 }
1043
1044 fn scheme(&self) -> SignatureScheme {
1045 SignatureScheme::ED25519
1046 }
1047 }
1048
1049 impl SigningKey for Ed25519Key {
1050 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
1051 offered
1052 .contains(&SignatureScheme::ED25519)
1053 .then(|| Box::new(Ed25519Signer(self.keypair.clone())) as Box<dyn Signer>)
1054 }
1055
1056 fn algorithm(&self) -> rustls::SignatureAlgorithm {
1057 rustls::SignatureAlgorithm::ED25519
1058 }
1059 }
1060
1061 impl dhttp_identity::identity::LocalAuthority for Ed25519Key {
1062 fn name(&self) -> &str {
1063 "authority.example"
1064 }
1065
1066 fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1067 &self.cert_chain
1068 }
1069
1070 fn sign(
1071 &self,
1072 data: &[u8],
1073 ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1074 let result = dhttp_identity::identity::sign_with_key(self, data);
1075 Box::pin(std::future::ready(result))
1076 }
1077 }
1078
1079 let rng = ring::rand::SystemRandom::new();
1080 let pkcs8 = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
1081 let keypair =
1082 Arc::new(ring::signature::Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap());
1083 let mut spki = Vec::with_capacity(44);
1084 spki.extend_from_slice(&[
1085 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
1086 ]);
1087 spki.extend_from_slice(keypair.public_key().as_ref());
1088 let key = Ed25519Key {
1089 keypair: keypair.clone(),
1090 cert_chain: vec![rustls::pki_types::CertificateDer::from(spki.clone())],
1091 };
1092
1093 let addr = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 5353);
1094 let mut ep = EndpointAddr::direct_v4(addr);
1095 ep.set_main(true);
1096 futures::executor::block_on(ep.sign_with_authority(&key)).unwrap();
1097
1098 let mut buf = BytesMut::new();
1099 buf.put_endpoint_addr(&ep);
1100 assert_eq!(buf.len(), ep.encpding_size());
1101
1102 let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1103 assert!(remain.is_empty());
1104 assert!(decoded.is_signed());
1105 assert!(decoded.signature().is_some());
1106 assert!(
1107 decoded
1108 .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1109 .unwrap()
1110 );
1111
1112 let mut tampered = decoded.clone();
1113 tampered.set_main(false);
1114 assert!(
1115 !tampered
1116 .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1117 .unwrap()
1118 );
1119 }
1120
1121 #[test]
1122 fn sign_with_authority_uses_canonical_scheme_from_public_key() {
1123 #[derive(Debug)]
1124 struct Ed25519Authority {
1125 cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1126 }
1127
1128 impl dhttp_identity::identity::LocalAuthority for Ed25519Authority {
1129 fn name(&self) -> &str {
1130 "authority.example"
1131 }
1132
1133 fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1134 &self.cert_chain
1135 }
1136
1137 fn sign(
1138 &self,
1139 _data: &[u8],
1140 ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1141 Box::pin(async move { Ok(vec![1, 2, 3]) })
1142 }
1143 }
1144
1145 let cert_chain = vec![rustls::pki_types::CertificateDer::from(vec![
1146 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0, 0, 0, 0, 0,
1147 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,
1148 ])];
1149 let mut ep = EndpointAddr::direct_v4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 5353));
1150 futures::executor::block_on(ep.sign_with_authority(&Ed25519Authority { cert_chain }))
1151 .unwrap();
1152
1153 let signature = ep.signature().unwrap();
1154 assert_eq!(
1155 SignatureScheme::from(signature.scheme),
1156 SignatureScheme::ED25519
1157 );
1158 assert_eq!(signature.signature, vec![1, 2, 3]);
1159 }
1160
1161 #[test]
1162 fn optional_fields_flags_follow_values() {
1163 let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
1164 let mut ep = EndpointAddr::direct_v4(addr);
1165
1166 assert!(!ep.is_load());
1167
1168 ep.set_load(Some(0.5_f32));
1169
1170 assert!(ep.is_load());
1171 assert_eq!(ep.load(), Some(0.5_f32));
1172
1173 ep.set_load(None);
1174
1175 assert!(!ep.is_load());
1176 assert_eq!(ep.load(), None);
1177 }
1178}