Repository: libp2p/go-libp2p
Pull request #2457 (2023-08-03 14:50:49)

release v0.28.2
Note that we don't update quic-go here. I'm not cutting a patch release for the ancient v0.33.0. Instead, I've manually bumped the required qtls version to include the RSA key size fix.


Patch:
diff --git a/core/crypto/rsa_common.go b/core/crypto/rsa_common.go
index c7e30543..2b05eb6a 100644
--- a/core/crypto/rsa_common.go
+++ b/core/crypto/rsa_common.go
@@ -12,9 +12,12 @@ const WeakRsaKeyEnv = "LIBP2P_ALLOW_WEAK_RSA_KEYS"
 
 var MinRsaKeyBits = 2048
 
+var maxRsaKeyBits = 8192
+
 // ErrRsaKeyTooSmall is returned when trying to generate or parse an RSA key
 // that's smaller than MinRsaKeyBits bits. In test
 var ErrRsaKeyTooSmall error
+var ErrRsaKeyTooBig error = fmt.Errorf("rsa keys must be <= %d bits", maxRsaKeyBits)
 
 func init() {
 	if _, ok := os.LookupEnv(WeakRsaKeyEnv); ok {
diff --git a/core/crypto/rsa_go.go b/core/crypto/rsa_go.go
index 7927d17d..f1539309 100644
--- a/core/crypto/rsa_go.go
+++ b/core/crypto/rsa_go.go
@@ -31,6 +31,9 @@ func GenerateRSAKeyPair(bits int, src io.Reader) (PrivKey, PubKey, error) {
 	if bits < MinRsaKeyBits {
 		return nil, nil, ErrRsaKeyTooSmall
 	}
+	if bits > maxRsaKeyBits {
+		return nil, nil, ErrRsaKeyTooBig
+	}
 	priv, err := rsa.GenerateKey(src, bits)
 	if err != nil {
 		return nil, nil, err
@@ -124,6 +127,9 @@ func UnmarshalRsaPrivateKey(b []byte) (key PrivKey, err error) {
 	if sk.N.BitLen() < MinRsaKeyBits {
 		return nil, ErrRsaKeyTooSmall
 	}
+	if sk.N.BitLen() > maxRsaKeyBits {
+		return nil, ErrRsaKeyTooBig
+	}
 	return &RsaPrivateKey{sk: *sk}, nil
 }
 
@@ -141,6 +147,9 @@ func UnmarshalRsaPublicKey(b []byte) (key PubKey, err error) {
 	if pk.N.BitLen() < MinRsaKeyBits {
 		return nil, ErrRsaKeyTooSmall
 	}
+	if pk.N.BitLen() > maxRsaKeyBits {
+		return nil, ErrRsaKeyTooBig
+	}
 
 	return &RsaPublicKey{k: *pk}, nil
 }
diff --git a/go.mod b/go.mod
index 898a4e82..0baf59e2 100644
--- a/go.mod
+++ b/go.mod
@@ -102,8 +102,8 @@ require (
 	github.com/prometheus/common v0.37.0 // indirect
 	github.com/prometheus/procfs v0.8.0 // indirect
 	github.com/quic-go/qpack v0.4.0 // indirect
-	github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
-	github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
+	github.com/quic-go/qtls-go1-19 v0.3.3 // indirect
+	github.com/quic-go/qtls-go1-20 v0.2.3 // indirect
 	github.com/spaolacci/murmur3 v1.1.0 // indirect
 	github.com/syndtr/goleveldb v1.0.0 // indirect
 	go.uber.org/atomic v1.11.0 // indirect
diff --git a/go.sum b/go.sum
index 14929957..e320aefe 100644
--- a/go.sum
+++ b/go.sum
@@ -432,10 +432,10 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5
 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
 github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
 github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
-github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
-github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
-github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
+github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE=
+github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
+github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI=
+github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
 github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0=
 github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA=
 github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
diff --git a/p2p/net/swarm/swarm.go b/p2p/net/swarm/swarm.go
index 194d0127..d4815ef6 100644
--- a/p2p/net/swarm/swarm.go
+++ b/p2p/net/swarm/swarm.go
@@ -706,3 +706,12 @@ func (c connWithMetrics) Close() error {
 	c.metricsTracer.ClosedConnection(c.dir, time.Since(c.opened), c.ConnState(), c.LocalMultiaddr())
 	return c.CapableConn.Close()
 }
+
+func (c connWithMetrics) Stat() network.ConnStats {
+	if cs, ok := c.CapableConn.(network.ConnStat); ok {
+		return cs.Stat()
+	}
+	return network.ConnStats{}
+}
+
+var _ network.ConnStat = connWithMetrics{}
diff --git a/version.json b/version.json
index c8c325c1..dffa0bb7 100644
--- a/version.json
+++ b/version.json
@@ -1,3 +1,3 @@
 {
-  "version": "v0.28.1"
+  "version": "v0.28.2"
 }


Test patch:
diff --git a/core/crypto/rsa_test.go b/core/crypto/rsa_test.go
index 69151b86..f4a7971a 100644
--- a/core/crypto/rsa_test.go
+++ b/core/crypto/rsa_test.go
@@ -68,6 +68,44 @@ func TestRSASmallKey(t *testing.T) {
 	}
 }
 
+func TestRSABigKeyFailsToGenerate(t *testing.T) {
+	_, _, err := GenerateRSAKeyPair(maxRsaKeyBits*2, rand.Reader)
+	if err != ErrRsaKeyTooBig {
+		t.Fatal("should have refused to create too big RSA key")
+	}
+}
+
+func TestRSABigKey(t *testing.T) {
+	// Make the global limit smaller for this test to run faster.
+	// Note we also change the limit below, but this is different
+	origSize := maxRsaKeyBits
+	maxRsaKeyBits = 2048
+	defer func() { maxRsaKeyBits = origSize }() //
+
+	maxRsaKeyBits *= 2
+	badPriv, badPub, err := GenerateRSAKeyPair(maxRsaKeyBits, rand.Reader)
+	if err != nil {
+		t.Fatalf("should have succeeded, got: %s", err)
+	}
+	pubBytes, err := MarshalPublicKey(badPub)
+	if err != nil {
+		t.Fatal(err)
+	}
+	privBytes, err := MarshalPrivateKey(badPriv)
+	if err != nil {
+		t.Fatal(err)
+	}
+	maxRsaKeyBits /= 2
+	_, err = UnmarshalPublicKey(pubBytes)
+	if err != ErrRsaKeyTooBig {
+		t.Fatal("should have refused to unmarshal a too big key")
+	}
+	_, err = UnmarshalPrivateKey(privBytes)
+	if err != ErrRsaKeyTooBig {
+		t.Fatal("should have refused to unmarshal a too big key")
+	}
+}
+
 func TestRSASignZero(t *testing.T) {
 	priv, pub, err := GenerateRSAKeyPair(2048, rand.Reader)
 	if err != nil {
diff --git a/p2p/test/basichost/basic_host_test.go b/p2p/test/basichost/basic_host_test.go
new file mode 100644
index 00000000..6b010ed2
--- /dev/null
+++ b/p2p/test/basichost/basic_host_test.go
@@ -0,0 +1,72 @@
+package basichost
+
+import (
+	"context"
+	"fmt"
+	"testing"
+
+	"github.com/libp2p/go-libp2p"
+	"github.com/libp2p/go-libp2p/core/network"
+	"github.com/libp2p/go-libp2p/core/peer"
+	"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client"
+	"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
+	ma "github.com/multiformats/go-multiaddr"
+	"github.com/stretchr/testify/require"
+)
+
+func TestNoStreamOverTransientConnection(t *testing.T) {
+	h1, err := libp2p.New(
+		libp2p.NoListenAddrs,
+		libp2p.EnableRelay(),
+	)
+	require.NoError(t, err)
+
+	h2, err := libp2p.New(
+		libp2p.NoListenAddrs,
+		libp2p.EnableRelay(),
+	)
+	require.NoError(t, err)
+
+	relay1, err := libp2p.New()
+	require.NoError(t, err)
+
+	_, err = relay.New(relay1)
+	require.NoError(t, err)
+
+	relay1info := peer.AddrInfo{
+		ID:    relay1.ID(),
+		Addrs: relay1.Addrs(),
+	}
+	err = h1.Connect(context.Background(), relay1info)
+	require.NoError(t, err)
+
+	err = h2.Connect(context.Background(), relay1info)
+	require.NoError(t, err)
+
+	h2.SetStreamHandler("/testprotocol", func(s network.Stream) {
+		fmt.Println("testprotocol")
+
+		// End the example
+		s.Close()
+	})
+
+	_, err = client.Reserve(context.Background(), h2, relay1info)
+	require.NoError(t, err)
+
+	relayaddr := ma.StringCast("/p2p/" + relay1info.ID.String() + "/p2p-circuit/p2p/" + h2.ID().String())
+
+	h2Info := peer.AddrInfo{
+		ID:    h2.ID(),
+		Addrs: []ma.Multiaddr{relayaddr},
+	}
+	err = h1.Connect(context.Background(), h2Info)
+	require.NoError(t, err)
+
+	ctx := network.WithNoDial(context.Background(), "test")
+	_, err = h1.NewStream(ctx, h2.ID(), "/testprotocol")
+
+	require.ErrorIs(t, err, network.ErrTransientConn)
+
+	_, err = h1.NewStream(network.WithUseTransient(context.Background(), "test"), h2.ID(), "/testprotocol")
+	require.NoError(t, err)
+}
diff --git a/test-plans/go.mod b/test-plans/go.mod
index 89777e1d..963f0c33 100644
--- a/test-plans/go.mod
+++ b/test-plans/go.mod
@@ -73,8 +73,8 @@ require (
 	github.com/prometheus/common v0.44.0 // indirect
 	github.com/prometheus/procfs v0.10.1 // indirect
 	github.com/quic-go/qpack v0.4.0 // indirect
-	github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
-	github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
+	github.com/quic-go/qtls-go1-19 v0.3.3 // indirect
+	github.com/quic-go/qtls-go1-20 v0.2.3 // indirect
 	github.com/quic-go/quic-go v0.33.0 // indirect
 	github.com/quic-go/webtransport-go v0.5.3 // indirect
 	github.com/raulk/go-watchdog v1.3.0 // indirect
diff --git a/test-plans/go.sum b/test-plans/go.sum
index 9e074f6e..214fed9c 100644
--- a/test-plans/go.sum
+++ b/test-plans/go.sum
@@ -238,10 +238,10 @@ github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+Pymzi
 github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
 github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
 github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
-github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
-github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
-github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
+github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE=
+github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
+github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI=
+github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
 github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0=
 github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA=
 github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=