Skip to main content

dig_tls/
config.rs

1//! Ready-to-use rustls mutual-auth configurations for a DIG peer.
2//!
3//! These are the two entry points most consumers want: give them a [`NodeCert`] and a
4//! [`BindingPolicy`] and they return a rustls config wired with the DigNetwork-CA verifier, peer_id
5//! pinning, and BLS-binding checking, plus the capture handles to read WHO connected after the
6//! handshake completes. Both configs pin the `ring` crypto provider explicitly, so a consumer never
7//! has to install a process-default provider (and never risks the "multiple CryptoProviders" panic).
8
9use std::sync::Arc;
10
11use rustls::{ClientConfig, ServerConfig};
12
13use crate::binding::BindingPolicy;
14use crate::error::{DigTlsError, Result};
15use crate::identity::PeerId;
16use crate::node_cert::NodeCert;
17use crate::verify::{CapturedBlsPub, CapturedPeerId, DigClientCertVerifier, DigServerCertVerifier};
18
19/// A server-side (inbound) mTLS configuration plus the handles that capture the connecting peer's
20/// identity after the handshake.
21pub struct ServerTls {
22    /// The rustls server configuration to hand to your TLS acceptor.
23    pub config: Arc<ServerConfig>,
24    /// The `peer_id` of the client that connected (populated during the handshake).
25    pub captured_peer_id: CapturedPeerId,
26    /// The BLS G1 pubkey the client's `peer_id` is bound to (populated when a valid binding was seen).
27    pub captured_bls: CapturedBlsPub,
28}
29
30/// A client-side (outbound) mTLS configuration plus the handles that capture the server peer's
31/// identity after the handshake.
32pub struct ClientTls {
33    /// The rustls client configuration to hand to your TLS connector.
34    pub config: Arc<ClientConfig>,
35    /// The `peer_id` of the server that answered (populated during the handshake).
36    pub captured_peer_id: CapturedPeerId,
37    /// The BLS G1 pubkey the server's `peer_id` is bound to (populated when a valid binding was seen).
38    pub captured_bls: CapturedBlsPub,
39}
40
41fn ring_provider() -> Arc<rustls::crypto::CryptoProvider> {
42    Arc::new(rustls::crypto::ring::default_provider())
43}
44
45/// Build an inbound (server) mTLS config that presents `node`'s cert, REQUIRES a client cert chaining
46/// to the DigNetwork CA, and applies `binding_policy` to the client's #1204 binding. Accepts any
47/// DigNetwork-CA peer as the client (servers do not pin a specific caller); read
48/// [`ServerTls::captured_peer_id`] after the handshake to learn who connected.
49pub fn server_config(node: &NodeCert, binding_policy: BindingPolicy) -> Result<ServerTls> {
50    let captured_peer_id = CapturedPeerId::default();
51    let captured_bls = CapturedBlsPub::default();
52    let verifier = Arc::new(DigClientCertVerifier::new(
53        None,
54        captured_peer_id.clone(),
55        binding_policy,
56        captured_bls.clone(),
57    ));
58    let config = ServerConfig::builder_with_provider(ring_provider())
59        .with_safe_default_protocol_versions()
60        .map_err(|e| DigTlsError::RustlsConfig(format!("protocol versions: {e}")))?
61        .with_client_cert_verifier(verifier)
62        .with_single_cert(node.rustls_cert_chain(), node.rustls_private_key())
63        .map_err(|e| DigTlsError::RustlsConfig(format!("server single cert: {e}")))?;
64    Ok(ServerTls {
65        config: Arc::new(config),
66        captured_peer_id,
67        captured_bls,
68    })
69}
70
71/// Build an outbound (client) mTLS config that presents `node`'s cert and verifies the server's leaf
72/// chains to the DigNetwork CA, pinning `expected` (or accepting any DigNetwork-CA peer when `None`)
73/// and applying `binding_policy` to the server's #1204 binding. Read [`ClientTls::captured_peer_id`]
74/// after the handshake to learn who answered.
75pub fn client_config(
76    node: &NodeCert,
77    expected: Option<PeerId>,
78    binding_policy: BindingPolicy,
79) -> Result<ClientTls> {
80    let captured_peer_id = CapturedPeerId::default();
81    let captured_bls = CapturedBlsPub::default();
82    let verifier = Arc::new(DigServerCertVerifier::new(
83        expected,
84        captured_peer_id.clone(),
85        binding_policy,
86        captured_bls.clone(),
87    ));
88    let config = ClientConfig::builder_with_provider(ring_provider())
89        .with_safe_default_protocol_versions()
90        .map_err(|e| DigTlsError::RustlsConfig(format!("protocol versions: {e}")))?
91        .dangerous()
92        .with_custom_certificate_verifier(verifier)
93        .with_client_auth_cert(node.rustls_cert_chain(), node.rustls_private_key())
94        .map_err(|e| DigTlsError::RustlsConfig(format!("client auth cert: {e}")))?;
95    Ok(ClientTls {
96        config: Arc::new(config),
97        captured_peer_id,
98        captured_bls,
99    })
100}