From 8e28edf69a5f25d1d919962a70fa32203b48f8dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 08:16:42 +0000 Subject: [PATCH 1/3] deps: bump obi1kenobi/cargo-semver-checks-action from 2.4 to 2.5 Pull-Request: #5499. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f1fe263a2d..c8ff0521ce5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -310,7 +310,7 @@ jobs: - uses: actions/checkout@v4 - run: wget -q -O- https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.31.0/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz | tar -xz -C ~/.cargo/bin shell: bash - - uses: obi1kenobi/cargo-semver-checks-action@c7306483f698c511eaf7416d1bf2e1958c90140f # v2 + - uses: obi1kenobi/cargo-semver-checks-action@ca26a44cfb670b2078c8f757d06e696a7c3820cf # v2 rustfmt: runs-on: ubuntu-latest From e2e98ad5e8f8ab2c0ae037b69a3a7149a116bf02 Mon Sep 17 00:00:00 2001 From: EdwardJES <107906898+EdwardJES@users.noreply.github.com> Date: Wed, 17 Jul 2024 07:15:59 +1000 Subject: [PATCH 2/3] fix: rendezvous identify example This pr closes https://github.com/libp2p/rust-libp2p/issues/5388 by explicitly adding the local observed address, noting this is out of protocol behaviour in non-example cases Pull-Request: #5496. --- examples/rendezvous/src/bin/rzv-identify.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/rendezvous/src/bin/rzv-identify.rs b/examples/rendezvous/src/bin/rzv-identify.rs index 1d545592829..ff637aa6f49 100644 --- a/examples/rendezvous/src/bin/rzv-identify.rs +++ b/examples/rendezvous/src/bin/rzv-identify.rs @@ -76,8 +76,12 @@ async fn main() { } // once `/identify` did its job, we know our external address and can register SwarmEvent::Behaviour(MyBehaviourEvent::Identify(identify::Event::Received { + info, .. })) => { + // Register our external address. Needs to be done explicitly + // for this case, as it's a local address. + swarm.add_external_address(info.observed_addr); if let Err(error) = swarm.behaviour_mut().rendezvous.register( rendezvous::Namespace::from_static("rendezvous"), rendezvous_point, From 1617abb3bfcf3e8663568e90a8fc4009aef04ba9 Mon Sep 17 00:00:00 2001 From: Arpan Kapoor Date: Thu, 18 Jul 2024 20:30:33 +0530 Subject: [PATCH 3/3] fix(tls): fix rustls panic due to critical libp2p extension Resolves #5487. Pull-Request: #5498. --- Cargo.lock | 24 +++++++++--------- Cargo.toml | 2 +- transports/tls/CHANGELOG.md | 5 ++++ transports/tls/Cargo.toml | 2 +- transports/tls/src/certificate.rs | 41 +++++++++++++++++++++++++++++++ transports/tls/src/lib.rs | 17 ++++++++++--- 6 files changed, 73 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a9dc56e987..80a186f0026 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1727,7 +1727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.9", + "rustls 0.23.11", "rustls-pki-types", ] @@ -3159,7 +3159,7 @@ dependencies = [ "quinn", "rand 0.8.5", "ring 0.17.8", - "rustls 0.23.9", + "rustls 0.23.11", "socket2 0.5.7", "thiserror", "tokio", @@ -3373,7 +3373,7 @@ dependencies = [ [[package]] name = "libp2p-tls" -version = "0.4.0" +version = "0.4.1" dependencies = [ "futures", "futures-rustls", @@ -3385,7 +3385,7 @@ dependencies = [ "libp2p-yamux", "rcgen", "ring 0.17.8", - "rustls 0.23.9", + "rustls 0.23.11", "rustls-webpki 0.101.7", "thiserror", "tokio", @@ -4607,7 +4607,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.9", + "rustls 0.23.11", "thiserror", "tokio", "tracing", @@ -4623,7 +4623,7 @@ dependencies = [ "rand 0.8.5", "ring 0.17.8", "rustc-hash", - "rustls 0.23.9", + "rustls 0.23.11", "slab", "thiserror", "tinyvec", @@ -5156,21 +5156,21 @@ dependencies = [ "log", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.5", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.9" +version = "0.23.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a218f0f6d05669de4eabfb24f31ce802035c952429d037507b4a4a39f0e60c5b" +checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" dependencies = [ "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.5", "subtle", "zeroize", ] @@ -5203,9 +5203,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" dependencies = [ "ring 0.17.8", "rustls-pki-types", diff --git a/Cargo.toml b/Cargo.toml index 84767573b9e..55fc43d5b5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/transports/tls/CHANGELOG.md b/transports/tls/CHANGELOG.md index 3c6d0a2a1f5..0343c690834 100644 --- a/transports/tls/CHANGELOG.md +++ b/transports/tls/CHANGELOG.md @@ -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) diff --git a/transports/tls/Cargo.toml b/transports/tls/Cargo.toml index a4817f20336..c4b30951e66 100644 --- a/transports/tls/Cargo.toml +++ b/transports/tls/Cargo.toml @@ -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." diff --git a/transports/tls/src/certificate.rs b/transports/tls/src/certificate.rs index bbd353e32bd..65b373bcf9b 100644 --- a/transports/tls/src/certificate.rs +++ b/transports/tls/src/certificate.rs @@ -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. @@ -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); + +impl AlwaysResolvesCert { + pub(crate) fn new( + cert: rustls::pki_types::CertificateDer<'static>, + key: &rustls::pki_types::PrivateKeyDer<'_>, + ) -> Result { + 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> { + 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> { + 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( diff --git a/transports/tls/src/lib.rs b/transports/tls/src/lib.rs index 741a4b48077..3aa66db12b3 100644 --- a/transports/tls/src/lib.rs +++ b/transports/tls/src/lib.rs @@ -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; @@ -49,6 +50,11 @@ 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") @@ -56,8 +62,7 @@ pub fn make_client_config( .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) @@ -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)