Skip to content

Commit

Permalink
fix(tls): fix rustls panic due to critical libp2p extension
Browse files Browse the repository at this point in the history
Resolves #5487.

Pull-Request: #5498.
  • Loading branch information
arpankapoor authored Jul 18, 2024
1 parent e2e98ad commit 1617abb
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 18 deletions.
24 changes: 12 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ libp2p-swarm = { version = "0.45.0", path = "swarm" }
libp2p-swarm-derive = { version = "=0.34.2", path = "swarm-derive" } # `libp2p-swarm-derive` may not be compatible with different `libp2p-swarm` non-breaking releases. E.g. `libp2p-swarm` might introduce a new enum variant `FromSwarm` (which is `#[non-exhaustive]`) in a non-breaking release. Older versions of `libp2p-swarm-derive` would not forward this enum variant within the `NetworkBehaviour` hierarchy. Thus the version pinning is required.
libp2p-swarm-test = { version = "0.3.0", path = "swarm-test" }
libp2p-tcp = { version = "0.42.0", path = "transports/tcp" }
libp2p-tls = { version = "0.4.0", path = "transports/tls" }
libp2p-tls = { version = "0.4.1", path = "transports/tls" }
libp2p-uds = { version = "0.40.0", path = "transports/uds" }
libp2p-upnp = { version = "0.2.2", path = "protocols/upnp" }
libp2p-webrtc = { version = "0.7.1-alpha", path = "transports/webrtc" }
Expand Down
5 changes: 5 additions & 0 deletions transports/tls/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.4.1

- Fix a panic caused by `rustls` parsing the libp2p TLS extension.
See [PR 5498](https://github.com/libp2p/rust-libp2p/pull/5498).

## 0.4.0

- Upgrade `rustls` to `0.23`. See [PR 5385](https://github.com/libp2p/rust-libp2p/pull/5385)
Expand Down
2 changes: 1 addition & 1 deletion transports/tls/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libp2p-tls"
version = "0.4.0"
version = "0.4.1"
edition = "2021"
rust-version = { workspace = true }
description = "TLS configuration based on libp2p TLS specs."
Expand Down
41 changes: 41 additions & 0 deletions transports/tls/src/certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ use libp2p_identity as identity;
use libp2p_identity::PeerId;
use x509_parser::{prelude::*, signature_algorithm::SignatureAlgorithm};

use std::sync::Arc;

/// The libp2p Public Key Extension is a X.509 extension
/// with the Object Identifier 1.3.6.1.4.1.53594.1.1,
/// allocated by IANA to the libp2p project at Protocol Labs.
Expand All @@ -42,6 +44,45 @@ const P2P_SIGNING_PREFIX: [u8; 21] = *b"libp2p-tls-handshake:";
// Similarly, hash functions with an output length less than 256 bits MUST NOT be used.
static P2P_SIGNATURE_ALGORITHM: &rcgen::SignatureAlgorithm = &rcgen::PKCS_ECDSA_P256_SHA256;

#[derive(Debug)]
pub(crate) struct AlwaysResolvesCert(Arc<rustls::sign::CertifiedKey>);

impl AlwaysResolvesCert {
pub(crate) fn new(
cert: rustls::pki_types::CertificateDer<'static>,
key: &rustls::pki_types::PrivateKeyDer<'_>,
) -> Result<Self, rustls::Error> {
let certified_key = rustls::sign::CertifiedKey::new(
vec![cert],
rustls::crypto::ring::sign::any_ecdsa_type(key)?,
);
Ok(Self(Arc::new(certified_key)))
}
}

impl rustls::client::ResolvesClientCert for AlwaysResolvesCert {
fn resolve(
&self,
_root_hint_subjects: &[&[u8]],
_sigschemes: &[rustls::SignatureScheme],
) -> Option<Arc<rustls::sign::CertifiedKey>> {
Some(Arc::clone(&self.0))
}

fn has_certs(&self) -> bool {
true
}
}

impl rustls::server::ResolvesServerCert for AlwaysResolvesCert {
fn resolve(
&self,
_client_hello: rustls::server::ClientHello<'_>,
) -> Option<Arc<rustls::sign::CertifiedKey>> {
Some(Arc::clone(&self.0))
}
}

/// Generates a self-signed TLS certificate that includes a libp2p-specific
/// certificate extension containing the public key of the given keypair.
pub fn generate(
Expand Down
17 changes: 13 additions & 4 deletions transports/tls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub mod certificate;
mod upgrade;
mod verifier;

use certificate::AlwaysResolvesCert;
use libp2p_identity::Keypair;
use libp2p_identity::PeerId;
use std::sync::Arc;
Expand All @@ -49,15 +50,19 @@ pub fn make_client_config(
let mut provider = rustls::crypto::ring::default_provider();
provider.cipher_suites = verifier::CIPHERSUITES.to_vec();

let cert_resolver = Arc::new(
AlwaysResolvesCert::new(certificate, &private_key)
.expect("Client cert key DER is valid; qed"),
);

let mut crypto = rustls::ClientConfig::builder_with_provider(provider.into())
.with_protocol_versions(verifier::PROTOCOL_VERSIONS)
.expect("Cipher suites and kx groups are configured; qed")
.dangerous()
.with_custom_certificate_verifier(Arc::new(
verifier::Libp2pCertificateVerifier::with_remote_peer_id(remote_peer_id),
))
.with_client_auth_cert(vec![certificate], private_key)
.expect("Client cert key DER is valid; qed");
.with_client_cert_resolver(cert_resolver);
crypto.alpn_protocols = vec![P2P_ALPN.to_vec()];

Ok(crypto)
Expand All @@ -72,12 +77,16 @@ pub fn make_server_config(
let mut provider = rustls::crypto::ring::default_provider();
provider.cipher_suites = verifier::CIPHERSUITES.to_vec();

let cert_resolver = Arc::new(
AlwaysResolvesCert::new(certificate, &private_key)
.expect("Server cert key DER is valid; qed"),
);

let mut crypto = rustls::ServerConfig::builder_with_provider(provider.into())
.with_protocol_versions(verifier::PROTOCOL_VERSIONS)
.expect("Cipher suites and kx groups are configured; qed")
.with_client_cert_verifier(Arc::new(verifier::Libp2pCertificateVerifier::new()))
.with_single_cert(vec![certificate], private_key)
.expect("Server cert key DER is valid; qed");
.with_cert_resolver(cert_resolver);
crypto.alpn_protocols = vec![P2P_ALPN.to_vec()];

Ok(crypto)
Expand Down

0 comments on commit 1617abb

Please sign in to comment.