1use std::sync::Arc;
9
10use rustls::{
11 client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
12 pki_types::CertificateDer as Certificate,
13 server::danger::{ClientCertVerified, ClientCertVerifier},
14 CertificateError, DigitallySignedStruct, DistinguishedName, OtherError, PeerMisbehaved,
15 SignatureScheme, SupportedProtocolVersion,
16};
17
18use super::certificate;
19use crate::key::PublicKey;
20
21pub static PROTOCOL_VERSIONS: &[&SupportedProtocolVersion] = &[&rustls::version::TLS13];
28
29#[derive(Debug)]
33pub struct Libp2pCertificateVerifier {
34 remote_peer_id: Option<PublicKey>,
36}
37
38impl Libp2pCertificateVerifier {
45 pub fn new() -> Self {
46 Self {
47 remote_peer_id: None,
48 }
49 }
50 pub fn with_remote_peer_id(remote_peer_id: Option<PublicKey>) -> Self {
51 Self { remote_peer_id }
52 }
53
54 fn verification_schemes() -> Vec<SignatureScheme> {
59 vec![
60 SignatureScheme::ECDSA_NISTP384_SHA384,
62 SignatureScheme::ECDSA_NISTP256_SHA256,
63 SignatureScheme::ED25519,
65 ]
67 }
68}
69
70impl ServerCertVerifier for Libp2pCertificateVerifier {
71 fn verify_server_cert(
72 &self,
73 end_entity: &Certificate,
74 intermediates: &[Certificate],
75 _server_name: &rustls::pki_types::ServerName,
76 _ocsp_response: &[u8],
77 _now: rustls::pki_types::UnixTime,
78 ) -> Result<ServerCertVerified, rustls::Error> {
79 let peer_id = verify_presented_certs(end_entity, intermediates)?;
80
81 if let Some(ref remote_peer_id) = self.remote_peer_id {
82 if remote_peer_id != &peer_id {
87 return Err(rustls::Error::PeerMisbehaved(
88 PeerMisbehaved::BadCertChainExtensions,
89 ));
90 }
91 }
92
93 Ok(ServerCertVerified::assertion())
94 }
95
96 fn verify_tls12_signature(
97 &self,
98 _message: &[u8],
99 _cert: &Certificate,
100 _dss: &DigitallySignedStruct,
101 ) -> Result<HandshakeSignatureValid, rustls::Error> {
102 unreachable!("`PROTOCOL_VERSIONS` only allows TLS 1.3")
103 }
104
105 fn verify_tls13_signature(
106 &self,
107 message: &[u8],
108 cert: &Certificate,
109 dss: &DigitallySignedStruct,
110 ) -> Result<HandshakeSignatureValid, rustls::Error> {
111 verify_tls13_signature(cert, dss.scheme, message, dss.signature())
112 }
113
114 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
115 Self::verification_schemes()
116 }
117}
118
119impl ClientCertVerifier for Libp2pCertificateVerifier {
127 fn offer_client_auth(&self) -> bool {
128 true
129 }
130
131 fn verify_client_cert(
132 &self,
133 end_entity: &Certificate,
134 intermediates: &[Certificate],
135 _now: rustls::pki_types::UnixTime,
136 ) -> Result<ClientCertVerified, rustls::Error> {
137 verify_presented_certs(end_entity, intermediates)?;
138
139 Ok(ClientCertVerified::assertion())
140 }
141
142 fn verify_tls12_signature(
143 &self,
144 _message: &[u8],
145 _cert: &Certificate,
146 _dss: &DigitallySignedStruct,
147 ) -> Result<HandshakeSignatureValid, rustls::Error> {
148 unreachable!("`PROTOCOL_VERSIONS` only allows TLS 1.3")
149 }
150
151 fn verify_tls13_signature(
152 &self,
153 message: &[u8],
154 cert: &Certificate,
155 dss: &DigitallySignedStruct,
156 ) -> Result<HandshakeSignatureValid, rustls::Error> {
157 verify_tls13_signature(cert, dss.scheme, message, dss.signature())
158 }
159
160 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
161 Self::verification_schemes()
162 }
163
164 fn root_hint_subjects(&self) -> &[DistinguishedName] {
165 &[][..]
166 }
167}
168
169fn verify_presented_certs(
176 end_entity: &Certificate,
177 intermediates: &[Certificate],
178) -> Result<PublicKey, rustls::Error> {
179 if !intermediates.is_empty() {
180 return Err(rustls::Error::General(
181 "libp2p-tls requires exactly one certificate".into(),
182 ));
183 }
184
185 let cert = certificate::parse(end_entity)?;
186
187 Ok(cert.peer_id())
188}
189
190fn verify_tls13_signature(
191 cert: &Certificate,
192 signature_scheme: SignatureScheme,
193 message: &[u8],
194 signature: &[u8],
195) -> Result<HandshakeSignatureValid, rustls::Error> {
196 certificate::parse(cert)?.verify_signature(signature_scheme, message, signature)?;
197
198 Ok(HandshakeSignatureValid::assertion())
199}
200
201impl From<certificate::ParseError> for rustls::Error {
202 fn from(certificate::ParseError(e): certificate::ParseError) -> Self {
203 use webpki::Error::*;
204 match e {
205 BadDer => rustls::Error::InvalidCertificate(CertificateError::BadEncoding),
206 e => {
207 rustls::Error::InvalidCertificate(CertificateError::Other(OtherError(Arc::new(e))))
208 }
209 }
210 }
211}
212impl From<certificate::VerificationError> for rustls::Error {
213 fn from(certificate::VerificationError(e): certificate::VerificationError) -> Self {
214 use webpki::Error::*;
215 match e {
216 InvalidSignatureForPublicKey => {
217 rustls::Error::InvalidCertificate(CertificateError::BadSignature)
218 }
219 UnsupportedSignatureAlgorithm | UnsupportedSignatureAlgorithmForPublicKey => {
220 rustls::Error::InvalidCertificate(CertificateError::BadSignature)
221 }
222 e => {
223 rustls::Error::InvalidCertificate(CertificateError::Other(OtherError(Arc::new(e))))
224 }
225 }
226 }
227}