1use ed25519_dalek::pkcs8::EncodePublicKey;
7use iroh_base::PublicKey;
8use rustls::{
9 CertificateError, DigitallySignedStruct, DistinguishedName, SignatureScheme,
10 SupportedProtocolVersion,
11 client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
12 crypto::{WebPkiSupportedAlgorithms, verify_tls13_signature_with_raw_key},
13 pki_types::CertificateDer as Certificate,
14 server::danger::{ClientCertVerified, ClientCertVerifier},
15};
16use webpki::ring as webpki_algs;
17use webpki_types::SubjectPublicKeyInfoDer;
18
19pub(super) static PROTOCOL_VERSIONS: &[&SupportedProtocolVersion] = &[&rustls::version::TLS13];
21
22static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
23 all: &[
24 webpki_algs::ECDSA_P256_SHA256,
25 webpki_algs::ECDSA_P256_SHA384,
26 webpki_algs::ECDSA_P384_SHA256,
27 webpki_algs::ECDSA_P384_SHA384,
28 webpki_algs::ED25519,
29 ],
30 mapping: &[
31 (
33 SignatureScheme::ECDSA_NISTP384_SHA384,
34 &[
35 webpki_algs::ECDSA_P384_SHA384,
36 webpki_algs::ECDSA_P256_SHA384,
37 ],
38 ),
39 (
40 SignatureScheme::ECDSA_NISTP256_SHA256,
41 &[
42 webpki_algs::ECDSA_P256_SHA256,
43 webpki_algs::ECDSA_P384_SHA256,
44 ],
45 ),
46 (SignatureScheme::ED25519, &[webpki_algs::ED25519]),
47 ],
48};
49
50#[derive(Default, Debug)]
54pub(super) struct ServerCertificateVerifier;
55
56fn public_key_to_spki(remote_peer_id: &PublicKey) -> SubjectPublicKeyInfoDer<'static> {
57 let der_key = remote_peer_id
58 .as_verifying_key()
59 .to_public_key_der()
60 .expect("valid key");
61 SubjectPublicKeyInfoDer::from(der_key.into_vec())
62}
63
64impl ServerCertVerifier for ServerCertificateVerifier {
65 fn verify_server_cert(
66 &self,
67 end_entity: &Certificate,
68 intermediates: &[Certificate],
69 server_name: &rustls::pki_types::ServerName,
70 _ocsp_response: &[u8],
71 _now: rustls::pki_types::UnixTime,
72 ) -> Result<ServerCertVerified, rustls::Error> {
73 let rustls::pki_types::ServerName::DnsName(dns_name) = server_name else {
74 return Err(rustls::Error::UnsupportedNameType);
75 };
76 let Some(remote_peer_id) = super::name::decode(dns_name.as_ref()) else {
77 return Err(rustls::Error::InvalidCertificate(
78 CertificateError::NotValidForName,
79 ));
80 };
81
82 if !intermediates.is_empty() {
83 return Err(rustls::Error::InvalidCertificate(
84 CertificateError::UnknownIssuer,
85 ));
86 }
87
88 let end_entity_as_spki = SubjectPublicKeyInfoDer::from(end_entity.as_ref());
89
90 if public_key_to_spki(&remote_peer_id) != end_entity_as_spki {
97 return Err(rustls::Error::InvalidCertificate(
98 CertificateError::UnknownIssuer,
99 ));
100 }
101
102 Ok(ServerCertVerified::assertion())
103 }
104
105 fn verify_tls12_signature(
106 &self,
107 _message: &[u8],
108 _cert: &Certificate,
109 _dss: &DigitallySignedStruct,
110 ) -> Result<HandshakeSignatureValid, rustls::Error> {
111 Err(rustls::Error::PeerIncompatible(
112 rustls::PeerIncompatible::Tls12NotOffered,
113 ))
114 }
115
116 fn verify_tls13_signature(
117 &self,
118 message: &[u8],
119 cert: &Certificate,
120 dss: &DigitallySignedStruct,
121 ) -> Result<HandshakeSignatureValid, rustls::Error> {
122 verify_tls13_signature_with_raw_key(
123 message,
124 &SubjectPublicKeyInfoDer::from(cert.as_ref()),
125 dss,
126 &SUPPORTED_SIG_ALGS,
127 )
128 }
129
130 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
131 SUPPORTED_SIG_ALGS.supported_schemes()
132 }
133
134 fn requires_raw_public_keys(&self) -> bool {
135 true
136 }
137}
138
139#[derive(Default, Debug)]
143pub(super) struct ClientCertificateVerifier;
144
145impl ClientCertVerifier for ClientCertificateVerifier {
149 fn offer_client_auth(&self) -> bool {
150 true
151 }
152
153 fn verify_client_cert(
154 &self,
155 _end_entity: &Certificate,
156 intermediates: &[Certificate],
157 _now: rustls::pki_types::UnixTime,
158 ) -> Result<ClientCertVerified, rustls::Error> {
159 if !intermediates.is_empty() {
160 return Err(rustls::Error::InvalidCertificate(
161 CertificateError::UnknownIssuer,
162 ));
163 }
164
165 Ok(ClientCertVerified::assertion())
166 }
167
168 fn verify_tls12_signature(
169 &self,
170 _message: &[u8],
171 _cert: &Certificate,
172 _dss: &DigitallySignedStruct,
173 ) -> Result<HandshakeSignatureValid, rustls::Error> {
174 Err(rustls::Error::PeerIncompatible(
175 rustls::PeerIncompatible::Tls12NotOffered,
176 ))
177 }
178
179 fn verify_tls13_signature(
180 &self,
181 message: &[u8],
182 cert: &Certificate,
183 dss: &DigitallySignedStruct,
184 ) -> Result<HandshakeSignatureValid, rustls::Error> {
185 verify_tls13_signature_with_raw_key(
186 message,
187 &SubjectPublicKeyInfoDer::from(cert.as_ref()),
188 dss,
189 &SUPPORTED_SIG_ALGS,
190 )
191 }
192
193 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
194 SUPPORTED_SIG_ALGS.supported_schemes()
195 }
196
197 fn root_hint_subjects(&self) -> &[DistinguishedName] {
198 &[][..]
199 }
200
201 fn requires_raw_public_keys(&self) -> bool {
202 true
203 }
204}