libp2p_tls/
verifier.rs

1// Copyright 2021 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21//! TLS 1.3 certificates and handshakes handling for libp2p
22//!
23//! This module handles a verification of a client/server certificate chain
24//! and signatures allegedly by the given certificates.
25
26use 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
42/// The protocol versions supported by this verifier.
43///
44/// The spec says:
45///
46/// > The libp2p handshake uses TLS 1.3 (and higher).
47/// > Endpoints MUST NOT negotiate lower TLS versions.
48pub(crate) static PROTOCOL_VERSIONS: &[&SupportedProtocolVersion] = &[&rustls::version::TLS13];
49/// A list of the TLS 1.3 cipher suites supported by rustls.
50// By default rustls creates client/server configs with both
51// TLS 1.3 __and__ 1.2 cipher suites. But we don't need 1.2.
52pub(crate) static CIPHERSUITES: &[SupportedCipherSuite] = &[
53    // TLS1.3 suites
54    TLS13_CHACHA20_POLY1305_SHA256,
55    TLS13_AES_256_GCM_SHA384,
56    TLS13_AES_128_GCM_SHA256,
57];
58
59/// Implementation of the `rustls` certificate verification traits for libp2p.
60///
61/// Only TLS 1.3 is supported. TLS 1.2 should be disabled in the configuration of `rustls`.
62#[derive(Debug)]
63pub(crate) struct Libp2pCertificateVerifier {
64    /// The peer ID we intend to connect to
65    remote_peer_id: Option<PeerId>,
66}
67
68/// libp2p requires the following of X.509 server certificate chains:
69///
70/// - Exactly one certificate must be presented.
71/// - The certificate must be self-signed.
72/// - The certificate must have a valid libp2p extension that includes a signature of its public
73///   key.
74impl 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    /// Return the list of SignatureSchemes that this verifier will handle,
85    /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
86    ///
87    /// This should be in priority order, with the most preferred first.
88    fn verification_schemes() -> Vec<SignatureScheme> {
89        vec![
90            // TODO SignatureScheme::ECDSA_NISTP521_SHA512 is not supported by `ring` yet
91            SignatureScheme::ECDSA_NISTP384_SHA384,
92            SignatureScheme::ECDSA_NISTP256_SHA256,
93            // TODO SignatureScheme::ED448 is not supported by `ring` yet
94            SignatureScheme::ED25519,
95            // In particular, RSA SHOULD NOT be used unless
96            // no elliptic curve algorithms are supported.
97            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            // The public host key allows the peer to calculate the peer ID of the peer
120            // it is connecting to. Clients MUST verify that the peer ID derived from
121            // the certificate matches the peer ID they intended to connect to,
122            // and MUST abort the connection if there is a mismatch.
123            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
156/// libp2p requires the following of X.509 client certificate chains:
157///
158/// - Exactly one certificate must be presented. In particular, client authentication is mandatory
159///   in libp2p.
160/// - The certificate must be self-signed.
161/// - The certificate must have a valid libp2p extension that includes a signature of its public
162///   key.
163impl 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
206/// When receiving the certificate chain, an endpoint
207/// MUST check these conditions and abort the connection attempt if
208/// (a) the presented certificate is not yet valid, OR
209/// (b) if it is expired.
210/// Endpoints MUST abort the connection attempt if more than one certificate is received,
211/// or if the certificate’s self-signature is not valid.
212fn 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}