iroh_net/
tls.rs

1//! TLS configuration based on libp2p TLS specs.
2//!
3//! See <https://github.com/libp2p/specs/blob/master/tls/tls.md>.
4//! Based on rust-libp2p/transports/tls
5
6use std::sync::Arc;
7
8use quinn::crypto::rustls::{NoInitialCipherSuite, QuicClientConfig, QuicServerConfig};
9use tracing::warn;
10
11use self::certificate::AlwaysResolvesCert;
12use crate::key::{PublicKey, SecretKey};
13
14pub mod certificate;
15mod verifier;
16
17/// Error for generating iroh p2p TLS configs.
18#[derive(Debug, thiserror::Error)]
19pub enum CreateConfigError {
20    /// Error generating the certificate.
21    #[error("Error generating the certificate")]
22    CertError(#[from] certificate::GenError),
23    /// Error creating QUIC config.
24    #[error("Error creating QUIC config")]
25    ConfigError(#[from] NoInitialCipherSuite),
26}
27
28/// Create a TLS client configuration.
29///
30/// If *keylog* is `true` this will enable logging of the pre-master key to the file in the
31/// `SSLKEYLOGFILE` environment variable.  This can be used to inspect the traffic for
32/// debugging purposes.
33pub fn make_client_config(
34    secret_key: &SecretKey,
35    remote_peer_id: Option<PublicKey>,
36    alpn_protocols: Vec<Vec<u8>>,
37    keylog: bool,
38) -> Result<QuicClientConfig, CreateConfigError> {
39    let (certificate, secret_key) = certificate::generate(secret_key)?;
40
41    let cert_resolver = Arc::new(
42        AlwaysResolvesCert::new(certificate, &secret_key)
43            .expect("Client cert key DER is valid; qed"),
44    );
45
46    let mut crypto = rustls::ClientConfig::builder_with_provider(Arc::new(
47        rustls::crypto::ring::default_provider(),
48    ))
49    .with_protocol_versions(verifier::PROTOCOL_VERSIONS)
50    .expect("version supported by ring")
51    .dangerous()
52    .with_custom_certificate_verifier(Arc::new(
53        verifier::Libp2pCertificateVerifier::with_remote_peer_id(remote_peer_id),
54    ))
55    .with_client_cert_resolver(cert_resolver);
56    crypto.alpn_protocols = alpn_protocols;
57    if keylog {
58        warn!("enabling SSLKEYLOGFILE for TLS pre-master keys");
59        crypto.key_log = Arc::new(rustls::KeyLogFile::new());
60    }
61    let config = crypto.try_into()?;
62    Ok(config)
63}
64
65/// Create a TLS server configuration.
66///
67/// If *keylog* is `true` this will enable logging of the pre-master key to the file in the
68/// `SSLKEYLOGFILE` environment variable.  This can be used to inspect the traffic for
69/// debugging purposes.
70pub fn make_server_config(
71    secret_key: &SecretKey,
72    alpn_protocols: Vec<Vec<u8>>,
73    keylog: bool,
74) -> Result<QuicServerConfig, CreateConfigError> {
75    let (certificate, secret_key) = certificate::generate(secret_key)?;
76
77    let cert_resolver = Arc::new(
78        AlwaysResolvesCert::new(certificate, &secret_key)
79            .expect("Server cert key DER is valid; qed"),
80    );
81
82    let mut crypto = rustls::ServerConfig::builder_with_provider(Arc::new(
83        rustls::crypto::ring::default_provider(),
84    ))
85    .with_protocol_versions(verifier::PROTOCOL_VERSIONS)
86    .expect("fixed config")
87    .with_client_cert_verifier(Arc::new(verifier::Libp2pCertificateVerifier::new()))
88    .with_cert_resolver(cert_resolver);
89    crypto.alpn_protocols = alpn_protocols;
90    if keylog {
91        warn!("enabling SSLKEYLOGFILE for TLS pre-master keys");
92        crypto.key_log = Arc::new(rustls::KeyLogFile::new());
93    }
94    let config = crypto.try_into()?;
95    Ok(config)
96}