Commit 1018ec94 authored by Marten Seemann's avatar Marten Seemann

switch to TLS 1.3

TLS 1.3 support was recently made opt-in in Go 1.12, so we need to
explicitly enable it.
parent 36025686
language: go language: go
go: go:
- "1.11.x" - "1.12rc1"
# first part of the GOARCH workaround # first part of the GOARCH workaround
# setting the GOARCH directly doesn't work, since the value will be overwritten later # setting the GOARCH directly doesn't work, since the value will be overwritten later
......
...@@ -72,6 +72,7 @@ func generateConfig(privKey ic.PrivKey) (*tls.Config, error) { ...@@ -72,6 +72,7 @@ func generateConfig(privKey ic.PrivKey) (*tls.Config, error) {
return nil, err return nil, err
} }
return &tls.Config{ return &tls.Config{
MinVersion: tls.VersionTLS13,
InsecureSkipVerify: true, // This is not insecure here. We will verify the cert chain ourselves. InsecureSkipVerify: true, // This is not insecure here. We will verify the cert chain ourselves.
ClientAuth: tls.RequireAnyClientCert, ClientAuth: tls.RequireAnyClientCert,
Certificates: []tls.Certificate{{ Certificates: []tls.Certificate{{
......
...@@ -4,12 +4,19 @@ import ( ...@@ -4,12 +4,19 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"net" "net"
"os"
cs "github.com/libp2p/go-conn-security" cs "github.com/libp2p/go-conn-security"
ci "github.com/libp2p/go-libp2p-crypto" ci "github.com/libp2p/go-libp2p-crypto"
peer "github.com/libp2p/go-libp2p-peer" peer "github.com/libp2p/go-libp2p-peer"
) )
// TLS 1.3 is opt-in in Go 1.12
// Activate it by setting the tls13 GODEBUG flag.
func init() {
os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1")
}
// ID is the protocol ID (used when negotiating with multistream) // ID is the protocol ID (used when negotiating with multistream)
const ID = "/tls/1.0.0" const ID = "/tls/1.0.0"
...@@ -47,6 +54,12 @@ func (t *Transport) SecureInbound(ctx context.Context, insecure net.Conn) (cs.Co ...@@ -47,6 +54,12 @@ func (t *Transport) SecureInbound(ctx context.Context, insecure net.Conn) (cs.Co
} }
// SecureOutbound runs the TLS handshake as a client. // SecureOutbound runs the TLS handshake as a client.
// Note that SecureOutbound will not return an error if the server doesn't
// accept the certificate. This is due to the fact that in TLS 1.3, the client
// sends its certificate and the ClientFinished in the same flight, and can send
// application data immediately afterwards.
// If the handshake fails, the server will close the connection. The client will
// notice this after 1 RTT when calling Read.
func (t *Transport) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (cs.Conn, error) { func (t *Transport) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (cs.Conn, error) {
cl := tls.Client(insecure, t.identity.ConfigForPeer(p)) cl := tls.Client(insecure, t.identity.ConfigForPeer(p))
return t.handshake(ctx, cl) return t.handshake(ctx, cl)
......
...@@ -66,7 +66,7 @@ var _ = Describe("Transport", func() { ...@@ -66,7 +66,7 @@ var _ = Describe("Transport", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
identity.Config.Certificates[0].PrivateKey = key identity.Config.Certificates[0].PrivateKey = key
case *ecdsa.PrivateKey: case *ecdsa.PrivateKey:
key, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
identity.Config.Certificates[0].PrivateKey = key identity.Config.Certificates[0].PrivateKey = key
default: default:
...@@ -195,17 +195,14 @@ var _ = Describe("Transport", func() { ...@@ -195,17 +195,14 @@ var _ = Describe("Transport", func() {
go func() { go func() {
defer GinkgoRecover() defer GinkgoRecover()
_, err := serverTransport.SecureInbound(context.Background(), serverInsecureConn) _, err := serverTransport.SecureInbound(context.Background(), serverInsecureConn)
Expect(err).To(HaveOccurred()) Expect(err).To(MatchError("tls: invalid certificate signature"))
Expect(err.Error()).To(Or(
ContainSubstring("crypto/rsa: verification error"),
ContainSubstring("ECDSA verification failure"),
))
close(done) close(done)
}() }()
_, err = clientTransport.SecureOutbound(context.Background(), clientInsecureConn, serverID) conn, err := clientTransport.SecureOutbound(context.Background(), clientInsecureConn, serverID)
Expect(err).To(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("tls: bad certificate")) _, err = conn.Read([]byte{0})
Expect(err).To(MatchError("remote error: tls: error decrypting message"))
Eventually(done).Should(BeClosed()) Eventually(done).Should(BeClosed())
}) })
...@@ -223,16 +220,12 @@ var _ = Describe("Transport", func() { ...@@ -223,16 +220,12 @@ var _ = Describe("Transport", func() {
defer GinkgoRecover() defer GinkgoRecover()
_, err := serverTransport.SecureInbound(context.Background(), serverInsecureConn) _, err := serverTransport.SecureInbound(context.Background(), serverInsecureConn)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
// TLS returns a weird error here: "remote error: tls: unexpected message" Expect(err.Error()).To(ContainSubstring("remote error: tls:"))
close(done) close(done)
}() }()
_, err = clientTransport.SecureOutbound(context.Background(), clientInsecureConn, serverID) _, err = clientTransport.SecureOutbound(context.Background(), clientInsecureConn, serverID)
Expect(err).To(HaveOccurred()) Expect(err).To(MatchError("tls: invalid certificate signature"))
Expect(err.Error()).To(Or(
ContainSubstring("crypto/rsa: verification error"),
ContainSubstring("ECDSA verification failure"),
))
Eventually(done).Should(BeClosed()) Eventually(done).Should(BeClosed())
}) })
}) })
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment