1use std::sync::Arc;
27
28use libp2p_identity::PeerId;
29use rustls::{
30 client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
31 crypto::ring::cipher_suite::{
32 TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384, TLS13_CHACHA20_POLY1305_SHA256,
33 },
34 pki_types::CertificateDer,
35 server::danger::{ClientCertVerified, ClientCertVerifier},
36 CertificateError, DigitallySignedStruct, DistinguishedName, OtherError, SignatureScheme,
37 SupportedCipherSuite, SupportedProtocolVersion,
38};
39
40use crate::certificate;
41
42pub(crate) static PROTOCOL_VERSIONS: &[&SupportedProtocolVersion] = &[&rustls::version::TLS13];
49pub(crate) static CIPHERSUITES: &[SupportedCipherSuite] = &[
53 TLS13_CHACHA20_POLY1305_SHA256,
55 TLS13_AES_256_GCM_SHA384,
56 TLS13_AES_128_GCM_SHA256,
57];
58
59#[derive(Debug)]
63pub(crate) struct Libp2pCertificateVerifier {
64 remote_peer_id: Option<PeerId>,
66}
67
68impl Libp2pCertificateVerifier {
75 pub(crate) fn new() -> Self {
76 Self {
77 remote_peer_id: None,
78 }
79 }
80 pub(crate) fn with_remote_peer_id(remote_peer_id: Option<PeerId>) -> Self {
81 Self { remote_peer_id }
82 }
83
84 fn verification_schemes() -> Vec<SignatureScheme> {
89 vec![
90 SignatureScheme::ECDSA_NISTP384_SHA384,
92 SignatureScheme::ECDSA_NISTP256_SHA256,
93 SignatureScheme::ED25519,
95 SignatureScheme::RSA_PSS_SHA512,
98 SignatureScheme::RSA_PSS_SHA384,
99 SignatureScheme::RSA_PSS_SHA256,
100 SignatureScheme::RSA_PKCS1_SHA512,
101 SignatureScheme::RSA_PKCS1_SHA384,
102 SignatureScheme::RSA_PKCS1_SHA256,
103 ]
104 }
105}
106
107impl ServerCertVerifier for Libp2pCertificateVerifier {
108 fn verify_server_cert(
109 &self,
110 end_entity: &CertificateDer,
111 intermediates: &[CertificateDer],
112 _server_name: &rustls::pki_types::ServerName,
113 _ocsp_response: &[u8],
114 _now: rustls::pki_types::UnixTime,
115 ) -> Result<ServerCertVerified, rustls::Error> {
116 let peer_id = verify_presented_certs(end_entity, intermediates)?;
117
118 if let Some(remote_peer_id) = self.remote_peer_id {
119 if remote_peer_id != peer_id {
124 return Err(rustls::Error::InvalidCertificate(
125 CertificateError::ApplicationVerificationFailure,
126 ));
127 }
128 }
129
130 Ok(ServerCertVerified::assertion())
131 }
132
133 fn verify_tls12_signature(
134 &self,
135 _message: &[u8],
136 _cert: &CertificateDer,
137 _dss: &DigitallySignedStruct,
138 ) -> Result<HandshakeSignatureValid, rustls::Error> {
139 unreachable!("`PROTOCOL_VERSIONS` only allows TLS 1.3")
140 }
141
142 fn verify_tls13_signature(
143 &self,
144 message: &[u8],
145 cert: &CertificateDer,
146 dss: &DigitallySignedStruct,
147 ) -> Result<HandshakeSignatureValid, rustls::Error> {
148 verify_tls13_signature(cert, dss.scheme, message, dss.signature())
149 }
150
151 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
152 Self::verification_schemes()
153 }
154}
155
156impl ClientCertVerifier for Libp2pCertificateVerifier {
164 fn offer_client_auth(&self) -> bool {
165 true
166 }
167
168 fn root_hint_subjects(&self) -> &[DistinguishedName] {
169 &[]
170 }
171
172 fn verify_client_cert(
173 &self,
174 end_entity: &CertificateDer,
175 intermediates: &[CertificateDer],
176 _now: rustls::pki_types::UnixTime,
177 ) -> Result<ClientCertVerified, rustls::Error> {
178 verify_presented_certs(end_entity, intermediates)?;
179
180 Ok(ClientCertVerified::assertion())
181 }
182
183 fn verify_tls12_signature(
184 &self,
185 _message: &[u8],
186 _cert: &CertificateDer,
187 _dss: &DigitallySignedStruct,
188 ) -> Result<HandshakeSignatureValid, rustls::Error> {
189 unreachable!("`PROTOCOL_VERSIONS` only allows TLS 1.3")
190 }
191
192 fn verify_tls13_signature(
193 &self,
194 message: &[u8],
195 cert: &CertificateDer,
196 dss: &DigitallySignedStruct,
197 ) -> Result<HandshakeSignatureValid, rustls::Error> {
198 verify_tls13_signature(cert, dss.scheme, message, dss.signature())
199 }
200
201 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
202 Self::verification_schemes()
203 }
204}
205
206fn verify_presented_certs(
213 end_entity: &CertificateDer,
214 intermediates: &[CertificateDer],
215) -> Result<PeerId, rustls::Error> {
216 if !intermediates.is_empty() {
217 return Err(rustls::Error::General(
218 "libp2p-tls requires exactly one certificate".into(),
219 ));
220 }
221
222 let cert = certificate::parse(end_entity)?;
223
224 Ok(cert.peer_id())
225}
226
227fn verify_tls13_signature(
228 cert: &CertificateDer,
229 signature_scheme: SignatureScheme,
230 message: &[u8],
231 signature: &[u8],
232) -> Result<HandshakeSignatureValid, rustls::Error> {
233 certificate::parse(cert)?.verify_signature(signature_scheme, message, signature)?;
234
235 Ok(HandshakeSignatureValid::assertion())
236}
237
238impl From<certificate::ParseError> for rustls::Error {
239 fn from(certificate::ParseError(e): certificate::ParseError) -> Self {
240 use webpki::Error::*;
241 match e {
242 BadDer => rustls::Error::InvalidCertificate(CertificateError::BadEncoding),
243 e => {
244 rustls::Error::InvalidCertificate(CertificateError::Other(OtherError(Arc::new(e))))
245 }
246 }
247 }
248}
249impl From<certificate::VerificationError> for rustls::Error {
250 fn from(certificate::VerificationError(e): certificate::VerificationError) -> Self {
251 use webpki::Error::*;
252 match e {
253 InvalidSignatureForPublicKey => {
254 rustls::Error::InvalidCertificate(CertificateError::BadSignature)
255 }
256 other => rustls::Error::InvalidCertificate(CertificateError::Other(OtherError(
257 Arc::new(other),
258 ))),
259 }
260 }
261}