crypto/tls: enable TLS 1.3 and update tests

To disable TLS 1.3, simply remove VersionTLS13 from supportedVersions,
as tested by TestEscapeRoute, and amend documentation. To make it
opt-in, revert the change to (*Config).supportedVersions from this CL.

I did not have the heart to implement the early data skipping feature
when I realized that it did not offer a choice between two
abstraction-breaking options, but demanded them both (look for handshake
type in case of HelloRetryRequest, trial decryption otherwise). It's a
lot of complexity for an apparently small gain, but if anyone has strong
opinions about it let me know.

Note that in TLS 1.3 alerts are encrypted, so the close_notify peeking
to return (n > 0, io.EOF) from Read doesn't work. If we are lucky, those
servers that unexpectedly close connections after serving a single
request will have stopped (maybe thanks to H/2) before they got updated
to TLS 1.3.

Relatedly, session tickets are now provisioned on the client first Read
instead of at Handshake time, because they are, well, post-handshake
messages. If this proves to be a problem we might try to peek at them.

Doubled the tests that cover logic that's different in TLS 1.3.

The benchmarks for TLS 1.2 compared to be0f3c286b5 (before TLS 1.3 and
its refactors, after CL 142817 changed them to use real connections)
show little movement.

name                                       old time/op   new time/op   delta
HandshakeServer/RSA-8                        795µs ± 1%    798µs ± 1%    ~     (p=0.057 n=10+18)
HandshakeServer/ECDHE-P256-RSA-8             903µs ± 0%    909µs ± 1%  +0.68%  (p=0.000 n=8+17)
HandshakeServer/ECDHE-P256-ECDSA-P256-8      198µs ± 0%    204µs ± 1%  +3.24%  (p=0.000 n=9+18)
HandshakeServer/ECDHE-X25519-ECDSA-P256-8    202µs ± 3%    208µs ± 1%  +2.98%  (p=0.000 n=9+20)
HandshakeServer/ECDHE-P521-ECDSA-P521-8     15.5ms ± 1%   15.9ms ± 2%  +2.49%  (p=0.000 n=10+20)
Throughput/MaxPacket/1MB-8                  5.81ms ±23%   6.14ms ±44%    ~     (p=0.605 n=8+18)
Throughput/MaxPacket/2MB-8                  8.91ms ±22%   8.74ms ±33%    ~     (p=0.498 n=9+19)
Throughput/MaxPacket/4MB-8                  12.8ms ± 3%   14.0ms ±10%  +9.74%  (p=0.000 n=10+17)
Throughput/MaxPacket/8MB-8                  25.1ms ± 7%   24.6ms ±16%    ~     (p=0.129 n=9+19)
Throughput/MaxPacket/16MB-8                 46.3ms ± 4%   45.9ms ±12%    ~     (p=0.340 n=9+20)
Throughput/MaxPacket/32MB-8                 88.5ms ± 4%   86.0ms ± 4%  -2.82%  (p=0.004 n=10+20)
Throughput/MaxPacket/64MB-8                  173ms ± 2%    167ms ± 7%  -3.42%  (p=0.001 n=10+19)
Throughput/DynamicPacket/1MB-8              5.88ms ± 4%   6.59ms ±64%    ~     (p=0.232 n=9+18)
Throughput/DynamicPacket/2MB-8              9.08ms ±12%   8.73ms ±21%    ~     (p=0.408 n=10+18)
Throughput/DynamicPacket/4MB-8              14.2ms ± 5%   14.0ms ±11%    ~     (p=0.188 n=9+19)
Throughput/DynamicPacket/8MB-8              25.1ms ± 6%   24.0ms ± 7%  -4.39%  (p=0.000 n=10+18)
Throughput/DynamicPacket/16MB-8             45.6ms ± 3%   43.3ms ± 1%  -5.22%  (p=0.000 n=10+8)
Throughput/DynamicPacket/32MB-8             88.4ms ± 3%   84.8ms ± 2%  -4.06%  (p=0.000 n=10+10)
Throughput/DynamicPacket/64MB-8              175ms ± 3%    167ms ± 2%  -4.63%  (p=0.000 n=10+10)
Latency/MaxPacket/200kbps-8                  694ms ± 0%    694ms ± 0%  -0.02%  (p=0.000 n=9+9)
Latency/MaxPacket/500kbps-8                  279ms ± 0%    279ms ± 0%  -0.09%  (p=0.000 n=10+10)
Latency/MaxPacket/1000kbps-8                 140ms ± 0%    140ms ± 0%  -0.15%  (p=0.000 n=10+9)
Latency/MaxPacket/2000kbps-8                71.1ms ± 0%   71.0ms ± 0%  -0.09%  (p=0.001 n=8+9)
Latency/MaxPacket/5000kbps-8                30.5ms ± 6%   30.1ms ± 6%    ~     (p=0.905 n=10+9)
Latency/DynamicPacket/200kbps-8              134ms ± 0%    134ms ± 0%    ~     (p=0.796 n=9+9)
Latency/DynamicPacket/500kbps-8             54.8ms ± 0%   54.7ms ± 0%  -0.18%  (p=0.000 n=8+10)
Latency/DynamicPacket/1000kbps-8            28.5ms ± 0%   29.1ms ± 8%    ~     (p=0.173 n=8+10)
Latency/DynamicPacket/2000kbps-8            15.3ms ± 6%   15.9ms ±10%    ~     (p=0.905 n=9+10)
Latency/DynamicPacket/5000kbps-8            9.14ms ±21%   9.65ms ±82%    ~     (p=0.529 n=10+10)

name                                       old speed     new speed     delta
Throughput/MaxPacket/1MB-8                 175MB/s ±13%  167MB/s ±64%    ~     (p=0.646 n=7+20)
Throughput/MaxPacket/2MB-8                 241MB/s ±25%  241MB/s ±40%    ~     (p=0.660 n=9+20)
Throughput/MaxPacket/4MB-8                 328MB/s ± 3%  300MB/s ± 9%  -8.70%  (p=0.000 n=10+17)
Throughput/MaxPacket/8MB-8                 335MB/s ± 7%  340MB/s ±17%    ~     (p=0.212 n=9+20)
Throughput/MaxPacket/16MB-8                363MB/s ± 4%  367MB/s ±11%    ~     (p=0.340 n=9+20)
Throughput/MaxPacket/32MB-8                379MB/s ± 4%  390MB/s ± 4%  +2.93%  (p=0.004 n=10+20)
Throughput/MaxPacket/64MB-8                388MB/s ± 2%  401MB/s ± 7%  +3.25%  (p=0.004 n=10+20)
Throughput/DynamicPacket/1MB-8             178MB/s ± 4%  157MB/s ±73%    ~     (p=0.127 n=9+20)
Throughput/DynamicPacket/2MB-8             232MB/s ±11%  243MB/s ±18%    ~     (p=0.415 n=10+18)
Throughput/DynamicPacket/4MB-8             296MB/s ± 5%  299MB/s ±15%    ~     (p=0.295 n=9+20)
Throughput/DynamicPacket/8MB-8             334MB/s ± 6%  350MB/s ± 7%  +4.58%  (p=0.000 n=10+18)
Throughput/DynamicPacket/16MB-8            368MB/s ± 3%  388MB/s ± 1%  +5.48%  (p=0.000 n=10+8)
Throughput/DynamicPacket/32MB-8            380MB/s ± 3%  396MB/s ± 2%  +4.20%  (p=0.000 n=10+10)
Throughput/DynamicPacket/64MB-8            384MB/s ± 3%  403MB/s ± 2%  +4.83%  (p=0.000 n=10+10)

Comparing TLS 1.2 and TLS 1.3 at tip shows a slight (~5-10%) slowdown of
handshakes, which might be worth looking at next cycle, but the latency
improvements are expected to overshadow that.

name                                       old time/op   new time/op   delta
HandshakeServer/ECDHE-P256-RSA-8             909µs ± 1%    963µs ± 0%   +5.87%  (p=0.000 n=17+18)
HandshakeServer/ECDHE-P256-ECDSA-P256-8      204µs ± 1%    225µs ± 2%  +10.20%  (p=0.000 n=18+20)
HandshakeServer/ECDHE-X25519-ECDSA-P256-8    208µs ± 1%    230µs ± 2%  +10.35%  (p=0.000 n=20+18)
HandshakeServer/ECDHE-P521-ECDSA-P521-8     15.9ms ± 2%   15.9ms ± 1%     ~     (p=0.444 n=20+19)
Throughput/MaxPacket/1MB-8                  6.14ms ±44%   7.07ms ±46%     ~     (p=0.057 n=18+19)
Throughput/MaxPacket/2MB-8                  8.74ms ±33%   8.61ms ± 9%     ~     (p=0.552 n=19+17)
Throughput/MaxPacket/4MB-8                  14.0ms ±10%   14.1ms ±12%     ~     (p=0.707 n=17+20)
Throughput/MaxPacket/8MB-8                  24.6ms ±16%   25.6ms ±14%     ~     (p=0.107 n=19+20)
Throughput/MaxPacket/16MB-8                 45.9ms ±12%   44.7ms ± 6%     ~     (p=0.607 n=20+19)
Throughput/MaxPacket/32MB-8                 86.0ms ± 4%   87.9ms ± 8%     ~     (p=0.113 n=20+19)
Throughput/MaxPacket/64MB-8                  167ms ± 7%    169ms ± 2%   +1.26%  (p=0.011 n=19+19)
Throughput/DynamicPacket/1MB-8              6.59ms ±64%   6.79ms ±43%     ~     (p=0.480 n=18+19)
Throughput/DynamicPacket/2MB-8              8.73ms ±21%   9.58ms ±13%   +9.71%  (p=0.006 n=18+20)
Throughput/DynamicPacket/4MB-8              14.0ms ±11%   13.9ms ±10%     ~     (p=0.687 n=19+20)
Throughput/DynamicPacket/8MB-8              24.0ms ± 7%   24.6ms ± 8%   +2.36%  (p=0.045 n=18+17)
Throughput/DynamicPacket/16MB-8             43.3ms ± 1%   44.3ms ± 2%   +2.48%  (p=0.001 n=8+9)
Throughput/DynamicPacket/32MB-8             84.8ms ± 2%   86.7ms ± 2%   +2.27%  (p=0.000 n=10+10)
Throughput/DynamicPacket/64MB-8              167ms ± 2%    170ms ± 3%   +1.89%  (p=0.005 n=10+10)
Latency/MaxPacket/200kbps-8                  694ms ± 0%    699ms ± 0%   +0.65%  (p=0.000 n=9+10)
Latency/MaxPacket/500kbps-8                  279ms ± 0%    280ms ± 0%   +0.68%  (p=0.000 n=10+10)
Latency/MaxPacket/1000kbps-8                 140ms ± 0%    141ms ± 0%   +0.59%  (p=0.000 n=9+9)
Latency/MaxPacket/2000kbps-8                71.0ms ± 0%   71.3ms ± 0%   +0.42%  (p=0.000 n=9+9)
Latency/MaxPacket/5000kbps-8                30.1ms ± 6%   30.7ms ±10%   +1.93%  (p=0.019 n=9+9)
Latency/DynamicPacket/200kbps-8              134ms ± 0%    138ms ± 0%   +3.22%  (p=0.000 n=9+10)
Latency/DynamicPacket/500kbps-8             54.7ms ± 0%   56.3ms ± 0%   +3.03%  (p=0.000 n=10+8)
Latency/DynamicPacket/1000kbps-8            29.1ms ± 8%   29.1ms ± 0%     ~     (p=0.173 n=10+8)
Latency/DynamicPacket/2000kbps-8            15.9ms ±10%   16.4ms ±36%     ~     (p=0.633 n=10+8)
Latency/DynamicPacket/5000kbps-8            9.65ms ±82%   8.32ms ± 8%     ~     (p=0.573 n=10+8)

name                                       old speed     new speed     delta
Throughput/MaxPacket/1MB-8                 167MB/s ±64%  155MB/s ±55%     ~     (p=0.224 n=20+19)
Throughput/MaxPacket/2MB-8                 241MB/s ±40%  244MB/s ± 9%     ~     (p=0.407 n=20+17)
Throughput/MaxPacket/4MB-8                 300MB/s ± 9%  298MB/s ±11%     ~     (p=0.707 n=17+20)
Throughput/MaxPacket/8MB-8                 340MB/s ±17%  330MB/s ±13%     ~     (p=0.201 n=20+20)
Throughput/MaxPacket/16MB-8                367MB/s ±11%  375MB/s ± 5%     ~     (p=0.607 n=20+19)
Throughput/MaxPacket/32MB-8                390MB/s ± 4%  382MB/s ± 8%     ~     (p=0.113 n=20+19)
Throughput/MaxPacket/64MB-8                401MB/s ± 7%  397MB/s ± 2%   -0.96%  (p=0.030 n=20+19)
Throughput/DynamicPacket/1MB-8             157MB/s ±73%  156MB/s ±39%     ~     (p=0.738 n=20+20)
Throughput/DynamicPacket/2MB-8             243MB/s ±18%  220MB/s ±14%   -9.65%  (p=0.006 n=18+20)
Throughput/DynamicPacket/4MB-8             299MB/s ±15%  303MB/s ± 9%     ~     (p=0.512 n=20+20)
Throughput/DynamicPacket/8MB-8             350MB/s ± 7%  342MB/s ± 8%   -2.27%  (p=0.045 n=18+17)
Throughput/DynamicPacket/16MB-8            388MB/s ± 1%  378MB/s ± 2%   -2.41%  (p=0.001 n=8+9)
Throughput/DynamicPacket/32MB-8            396MB/s ± 2%  387MB/s ± 2%   -2.21%  (p=0.000 n=10+10)
Throughput/DynamicPacket/64MB-8            403MB/s ± 2%  396MB/s ± 3%   -1.84%  (p=0.005 n=10+10)

Fixes #9671

Change-Id: Ieb57c5140eb2c083b8be0d42b240cd2eeec0dcf6
Reviewed-on: https://go-review.googlesource.com/c/147638
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
Filippo Valsorda 2018-11-05 22:52:51 -05:00
parent 07b241c4b9
commit 5db23cd389
83 changed files with 3733 additions and 3281 deletions

View file

@ -253,6 +253,9 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
}()
clientConfig := testConfig.Clone()
// In TLS 1.3, alerts are encrypted and disguised as application data, so
// the opportunistic peek won't work.
clientConfig.MaxVersion = VersionTLS12
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
t.Fatal(err)
@ -298,6 +301,7 @@ func TestTLSUniqueMatches(t *testing.T) {
return
}
serverConfig := testConfig.Clone()
serverConfig.MaxVersion = VersionTLS12 // TLSUnique is not defined in TLS 1.3
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
t.Error(err)
@ -352,19 +356,22 @@ func TestVerifyHostname(t *testing.T) {
if err := c.VerifyHostname("www.google.com"); err == nil {
t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
}
if err := c.VerifyHostname("www.yahoo.com"); err == nil {
t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
}
}
func TestVerifyHostnameResumed(t *testing.T) {
t.Run("TLSv12", func(t *testing.T) { testVerifyHostnameResumed(t, VersionTLS12) })
t.Run("TLSv13", func(t *testing.T) { testVerifyHostnameResumed(t, VersionTLS13) })
}
func testVerifyHostnameResumed(t *testing.T, version uint16) {
testenv.MustHaveExternalNetwork(t)
config := &Config{
MaxVersion: version,
ClientSessionCache: NewLRUClientSessionCache(32),
}
for i := 0; i < 2; i++ {
c, err := Dial("tcp", "www.google.com:https", config)
c, err := Dial("tcp", "mail.google.com:https", config)
if err != nil {
t.Fatalf("Dial #%d: %v", i, err)
}
@ -372,11 +379,21 @@ func TestVerifyHostnameResumed(t *testing.T) {
if i > 0 && !cs.DidResume {
t.Fatalf("Subsequent connection unexpectedly didn't resume")
}
if cs.Version != version {
t.Fatalf("Unexpectedly negotiated version %x", cs.Version)
}
if cs.VerifiedChains == nil {
t.Fatalf("Dial #%d: cs.VerifiedChains == nil", i)
}
if err := c.VerifyHostname("www.google.com"); err != nil {
t.Fatalf("verify www.google.com #%d: %v", i, err)
if err := c.VerifyHostname("mail.google.com"); err != nil {
t.Fatalf("verify mail.google.com #%d: %v", i, err)
}
// Give the client a chance to read the server session tickets.
c.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
if _, err := c.Read(make([]byte, 1)); err != nil {
if err, ok := err.(net.Error); !ok || !err.Timeout() {
t.Fatal(err)
}
}
c.Close()
}
@ -601,6 +618,7 @@ func TestWarningAlertFlood(t *testing.T) {
go func() { errChan <- server() }()
clientConfig := testConfig.Clone()
clientConfig.MaxVersion = VersionTLS12 // there are no warning alerts in TLS 1.3
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
t.Fatal(err)
@ -749,7 +767,7 @@ func (w *changeImplConn) Close() error {
return w.Conn.Close()
}
func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool) {
func throughput(b *testing.B, version uint16, totalBytes int64, dynamicRecordSizingDisabled bool) {
ln := newLocalListener(b)
defer ln.Close()
@ -785,6 +803,7 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
clientConfig := testConfig.Clone()
clientConfig.CipherSuites = nil // the defaults may prefer faster ciphers
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
clientConfig.MaxVersion = version
buf := make([]byte, bufsize)
chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf))))
@ -812,7 +831,12 @@ func BenchmarkThroughput(b *testing.B) {
for size := 1; size <= 64; size <<= 1 {
name := fmt.Sprintf("%sPacket/%dMB", mode, size)
b.Run(name, func(b *testing.B) {
throughput(b, int64(size<<20), mode == "Max")
b.Run("TLSv12", func(b *testing.B) {
throughput(b, VersionTLS12, int64(size<<20), mode == "Max")
})
b.Run("TLSv13", func(b *testing.B) {
throughput(b, VersionTLS13, int64(size<<20), mode == "Max")
})
})
}
}
@ -846,7 +870,7 @@ func (c *slowConn) Write(p []byte) (int, error) {
return len(p), nil
}
func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
func latency(b *testing.B, version uint16, bps int, dynamicRecordSizingDisabled bool) {
ln := newLocalListener(b)
defer ln.Close()
@ -872,6 +896,7 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
clientConfig := testConfig.Clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
clientConfig.MaxVersion = version
buf := make([]byte, 16384)
peek := make([]byte, 1)
@ -903,7 +928,12 @@ func BenchmarkLatency(b *testing.B) {
for _, kbps := range []int{200, 500, 1000, 2000, 5000} {
name := fmt.Sprintf("%sPacket/%dkbps", mode, kbps)
b.Run(name, func(b *testing.B) {
latency(b, kbps*1000, mode == "Max")
b.Run("TLSv12", func(b *testing.B) {
latency(b, VersionTLS12, kbps*1000, mode == "Max")
})
b.Run("TLSv13", func(b *testing.B) {
latency(b, VersionTLS13, kbps*1000, mode == "Max")
})
})
}
}
@ -1032,3 +1062,28 @@ func TestConnectionState(t *testing.T) {
})
}
}
// TestEscapeRoute tests that the library will still work if support for TLS 1.3
// is dropped later in the Go 1.12 cycle.
func TestEscapeRoute(t *testing.T) {
defer func(savedSupportedVersions []uint16) {
supportedVersions = savedSupportedVersions
}(supportedVersions)
supportedVersions = []uint16{
VersionTLS12,
VersionTLS11,
VersionTLS10,
VersionSSL30,
}
ss, cs, err := testHandshake(t, testConfig, testConfig)
if err != nil {
t.Fatalf("Handshake failed when support for TLS 1.3 was dropped: %v", err)
}
if ss.Version != VersionTLS12 {
t.Errorf("Server negotiated version %x, expected %x", cs.Version, VersionTLS12)
}
if cs.Version != VersionTLS12 {
t.Errorf("Client negotiated version %x, expected %x", cs.Version, VersionTLS12)
}
}