1use std::{fmt::Debug, sync::Arc};
5
6use ed25519_dalek::pkcs8::{Document, EncodePrivateKey, EncodePublicKey};
7use futures_lite::{pin, stream::block_on};
8use rustls::{
9 client::danger::{DangerousClientConfigBuilder, ServerCertVerified, ServerCertVerifier},
10 crypto::ring::sign::any_eddsa_type,
11 crypto::{verify_tls13_signature_with_raw_key, WebPkiSupportedAlgorithms},
12 pki_types::CertificateDer,
13 pki_types::SubjectPublicKeyInfoDer,
14 server::AlwaysResolvesServerRawPublicKeys,
15 sign::CertifiedKey,
16 CertificateError, ServerConfig, SignatureScheme,
17};
18
19use crate::{Client, Keypair, PublicKey};
20
21#[derive(Debug)]
25pub struct CertVerifier(Client);
26
27static SUPPORTED_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
28 all: &[webpki::ring::ED25519],
29 mapping: &[(SignatureScheme::ED25519, &[webpki::ring::ED25519])],
30};
31
32impl ServerCertVerifier for CertVerifier {
33 fn verify_server_cert(
38 &self,
39 endpoint_certificate: &rustls::pki_types::CertificateDer<'_>,
40 intermediates: &[rustls::pki_types::CertificateDer<'_>],
41 host_name: &rustls::pki_types::ServerName<'_>,
42 _ocsp_response: &[u8],
43 _now: rustls::pki_types::UnixTime,
44 ) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
45 if !intermediates.is_empty() {
46 return Err(rustls::Error::InvalidCertificate(
47 CertificateError::UnknownIssuer,
48 ));
49 }
50
51 let end_entity_as_spki = SubjectPublicKeyInfoDer::from(endpoint_certificate.as_ref());
52 let expected_spki = end_entity_as_spki.as_ref();
53
54 let qname = host_name.to_str();
55
56 let stream = self.0.resolve_https_endpoints(&qname);
65 pin!(stream);
66 for endpoint in block_on(stream) {
67 if endpoint.public_key().to_public_key_der().as_bytes() == expected_spki {
68 return Ok(ServerCertVerified::assertion());
69 }
70 }
71
72 let stream = self.0.resolve_svcb_endpoints(&qname);
74 pin!(stream);
75 for endpoint in block_on(stream) {
76 if endpoint.public_key().to_public_key_der().as_bytes() == expected_spki {
77 return Ok(ServerCertVerified::assertion());
78 }
79 }
80
81 Err(rustls::Error::InvalidCertificate(
82 CertificateError::UnknownIssuer,
83 ))
84 }
85
86 fn verify_tls12_signature(
89 &self,
90 message: &[u8],
91 cert: &rustls::pki_types::CertificateDer<'_>,
92 dss: &rustls::DigitallySignedStruct,
93 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
94 verify_tls13_signature_with_raw_key(
95 message,
96 &SubjectPublicKeyInfoDer::from(cert.as_ref()),
97 dss,
98 &SUPPORTED_ALGORITHMS,
99 )
100 }
101
102 fn verify_tls13_signature(
105 &self,
106 message: &[u8],
107 cert: &rustls::pki_types::CertificateDer<'_>,
108 dss: &rustls::DigitallySignedStruct,
109 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
110 verify_tls13_signature_with_raw_key(
111 message,
112 &SubjectPublicKeyInfoDer::from(cert.as_ref()),
113 dss,
114 &SUPPORTED_ALGORITHMS,
115 )
116 }
117
118 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
119 vec![SignatureScheme::ED25519]
120 }
121
122 fn requires_raw_public_keys(&self) -> bool {
123 true
124 }
125}
126
127impl CertVerifier {
128 pub(crate) fn new(pkarr_client: Client) -> Self {
129 CertVerifier(pkarr_client)
130 }
131}
132
133impl From<Client> for CertVerifier {
134 fn from(pkarr_client: Client) -> Self {
135 CertVerifier::new(pkarr_client)
136 }
137}
138
139impl From<Client> for rustls::ClientConfig {
140 fn from(client: Client) -> Self {
145 let verifier: CertVerifier = client.into();
146
147 create_client_config_with_ring()
148 .with_custom_certificate_verifier(Arc::new(verifier))
149 .with_no_client_auth()
150 }
151}
152
153fn create_client_config_with_ring() -> DangerousClientConfigBuilder {
154 rustls::ClientConfig::builder_with_provider(rustls::crypto::ring::default_provider().into())
155 .with_safe_default_protocol_versions()
156 .expect("version supported by ring")
157 .dangerous()
158}
159
160impl Keypair {
161 pub fn to_rpk_certified_key(&self) -> CertifiedKey {
164 let client_private_key = any_eddsa_type(
165 &self
166 .0
167 .to_pkcs8_der()
168 .expect("Keypair::to_rpk_certificate: convert secret key to pkcs8 der")
169 .as_bytes()
170 .into(),
171 )
172 .expect("Keypair::to_rpk_certificate: convert KeyPair to rustls SigningKey");
173
174 let client_public_key = client_private_key
175 .public_key()
176 .expect("Keypair::to_rpk_certificate: load SPKI");
177 let client_public_key_as_cert = CertificateDer::from(client_public_key.to_vec());
178
179 CertifiedKey::new(vec![client_public_key_as_cert], client_private_key)
180 }
181
182 #[cfg(all(not(target_family = "wasm"), feature = "tls"))]
183 pub fn to_rpk_rustls_server_config(&self) -> ServerConfig {
185 let cert_resolver =
186 AlwaysResolvesServerRawPublicKeys::new(self.to_rpk_certified_key().into());
187
188 ServerConfig::builder_with_provider(rustls::crypto::ring::default_provider().into())
189 .with_safe_default_protocol_versions()
190 .expect("version supported by ring")
191 .with_no_client_auth()
192 .with_cert_resolver(std::sync::Arc::new(cert_resolver))
193 }
194}
195
196impl From<Keypair> for ServerConfig {
197 fn from(keypair: Keypair) -> Self {
198 keypair.to_rpk_rustls_server_config()
199 }
200}
201
202impl From<&Keypair> for ServerConfig {
203 fn from(keypair: &Keypair) -> Self {
204 keypair.to_rpk_rustls_server_config()
205 }
206}
207
208impl PublicKey {
209 pub fn to_public_key_der(&self) -> Document {
211 self.0.to_public_key_der().expect("to_public_key_der")
212 }
213}