iroh/tls/
verifier.rs

1//! TLS 1.3 certificates and handshakes handling.
2//!
3//! This module handles a verification of a client/server certificate chain
4//! and signatures allegedly by the given certificates, or using raw public keys.
5
6use 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
19/// The only TLS version we support is 1.3
20pub(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        // Note: for TLS1.2 the curve is not fixed by SignatureScheme. For TLS1.3 it is.
32        (
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/// Implementation of the `rustls` certificate verification traits
51///
52/// Only TLS 1.3 is supported. TLS 1.2 should be disabled in the configuration of `rustls`.
53#[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        // This effectively checks that the `end_entity_as_spki` bytes have the expected
91        // (constant) 12 byte prefix (consisting of the Ed25519 public key ASN.1 object
92        // identifier, some ASN.1 DER encoding bytes signaling that this is a SPKI and
93        // consists of the object identifier and a bit sequence, a zero byte indicating
94        // that the bit sequence is padded with 0 additional bits) matches, as well as
95        // the public key bytes match the `remote_peer_id` public key bytes.
96        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/// Implementation of the `rustls` certificate verification traits.
140///
141/// Only TLS 1.3 is supported. TLS 1.2 should be disabled in the configuration of `rustls`.
142#[derive(Default, Debug)]
143pub(super) struct ClientCertificateVerifier;
144
145/// We requires either following of X.509 client certificate chains:
146///
147/// - a valid raw public key configuration
148impl 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}