Skip to content

Commit 5d9bc60

Browse files
committed
crypto/tls: make TLS 1.3 opt-in
Updates #30055 Change-Id: If68615c8e9daa4226125dcc6a6866f29f3cfeef1 Reviewed-on: https://go-review.googlesource.com/c/160997 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
1 parent 95e5b07 commit 5d9bc60

File tree

3 files changed

+102
-12
lines changed

3 files changed

+102
-12
lines changed

doc/go1.12.html

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,15 +388,25 @@ <h2 id="library">Core library</h2>
388388
<h3 id="tls_1_3">TLS 1.3</h3>
389389

390390
<p>
391-
Go 1.12 adds support in the <code>crypto/tls</code> package for TLS 1.3 as
392-
specified in <a href="https://www.rfc-editor.org/info/rfc8446">RFC 8446</a>.
391+
Go 1.12 adds opt-in support for TLS 1.3 in the <code>crypto/tls</code> package as
392+
specified by <a href="https://www.rfc-editor.org/info/rfc8446">RFC 8446</a>. It can
393+
be enabled by adding the value <code>tls13=1</code> to the <code>GODEBUG</code>
394+
environment variable. It will be enabled by default in Go 1.13.
395+
</p>
393396

394-
Programs that did not set an explicit <code>MaxVersion</code> in
395-
<a href="/pkg/crypto/tls/#Config"><code>Config</code></a> will automatically negotiate
396-
TLS 1.3 if available. All TLS 1.2 features except <code>TLSUnique</code> in
397+
<p>
398+
To negotiate TLS 1.3, make sure you do not set an explicit <code>MaxVersion</code> in
399+
<a href="/pkg/crypto/tls/#Config"><code>Config</code></a> and run your program with
400+
the environment variable <code>GODEBUG=tls13=1</code> set.
401+
</p>
402+
403+
<p>
404+
All TLS 1.2 features except <code>TLSUnique</code> in
397405
<a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
398406
and renegotiation are available in TLS 1.3 and provide equivalent or
399-
better security and performance.
407+
better security and performance. Note that even though TLS 1.3 is backwards
408+
compatible with previous versions, certain legacy systems might not work
409+
correctly when attempting to negotiate it.
400410
</p>
401411

402412
<p>

src/crypto/tls/common.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"io"
1717
"math/big"
1818
"net"
19+
"os"
1920
"strings"
2021
"sync"
2122
"time"
@@ -775,11 +776,53 @@ func (c *Config) supportedVersions(isClient bool) []uint16 {
775776
if isClient && v < VersionTLS10 {
776777
continue
777778
}
779+
// TLS 1.3 is opt-in in Go 1.12.
780+
if v == VersionTLS13 && !isTLS13Supported() {
781+
continue
782+
}
778783
versions = append(versions, v)
779784
}
780785
return versions
781786
}
782787

788+
// tls13Support caches the result for isTLS13Supported.
789+
var tls13Support struct {
790+
sync.Once
791+
cached bool
792+
}
793+
794+
// isTLS13Supported returns whether the program opted into TLS 1.3 via
795+
// GODEBUG=tls13=1. It's cached after the first execution.
796+
func isTLS13Supported() bool {
797+
tls13Support.Do(func() {
798+
tls13Support.cached = goDebugString("tls13") == "1"
799+
})
800+
return tls13Support.cached
801+
}
802+
803+
// goDebugString returns the value of the named GODEBUG key.
804+
// GODEBUG is of the form "key=val,key2=val2".
805+
func goDebugString(key string) string {
806+
s := os.Getenv("GODEBUG")
807+
for i := 0; i < len(s)-len(key)-1; i++ {
808+
if i > 0 && s[i-1] != ',' {
809+
continue
810+
}
811+
afterKey := s[i+len(key):]
812+
if afterKey[0] != '=' || s[i:i+len(key)] != key {
813+
continue
814+
}
815+
val := afterKey[1:]
816+
for i, b := range val {
817+
if b == ',' {
818+
return val[:i]
819+
}
820+
}
821+
return val
822+
}
823+
return ""
824+
}
825+
783826
func (c *Config) maxSupportedVersion(isClient bool) uint16 {
784827
supportedVersions := c.supportedVersions(isClient)
785828
if len(supportedVersions) == 0 {

src/crypto/tls/tls_test.go

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,18 @@ import (
1818
"os"
1919
"reflect"
2020
"strings"
21+
"sync"
2122
"testing"
2223
"time"
2324
)
2425

26+
func init() {
27+
// TLS 1.3 is opt-in for Go 1.12, but we want to run most tests with it enabled.
28+
// TestTLS13Switch below tests the disabled behavior. See Issue 30055.
29+
tls13Support.Do(func() {}) // defuse the sync.Once
30+
tls13Support.cached = true
31+
}
32+
2533
var rsaCertPEM = `-----BEGIN CERTIFICATE-----
2634
MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
2735
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
@@ -1076,18 +1084,47 @@ func TestEscapeRoute(t *testing.T) {
10761084
VersionSSL30,
10771085
}
10781086

1079-
ss, cs, err := testHandshake(t, testConfig, testConfig)
1087+
expectVersion(t, testConfig, testConfig, VersionTLS12)
1088+
}
1089+
1090+
func expectVersion(t *testing.T, clientConfig, serverConfig *Config, v uint16) {
1091+
ss, cs, err := testHandshake(t, clientConfig, serverConfig)
10801092
if err != nil {
1081-
t.Fatalf("Handshake failed when support for TLS 1.3 was dropped: %v", err)
1093+
t.Fatalf("Handshake failed: %v", err)
10821094
}
1083-
if ss.Version != VersionTLS12 {
1084-
t.Errorf("Server negotiated version %x, expected %x", cs.Version, VersionTLS12)
1095+
if ss.Version != v {
1096+
t.Errorf("Server negotiated version %x, expected %x", cs.Version, v)
10851097
}
1086-
if cs.Version != VersionTLS12 {
1087-
t.Errorf("Client negotiated version %x, expected %x", cs.Version, VersionTLS12)
1098+
if cs.Version != v {
1099+
t.Errorf("Client negotiated version %x, expected %x", cs.Version, v)
10881100
}
10891101
}
10901102

1103+
// TestTLS13Switch checks the behavior of GODEBUG=tls13=[0|1]. See Issue 30055.
1104+
func TestTLS13Switch(t *testing.T) {
1105+
defer func(savedGODEBUG string) {
1106+
os.Setenv("GODEBUG", savedGODEBUG)
1107+
}(os.Getenv("GODEBUG"))
1108+
1109+
os.Setenv("GODEBUG", "tls13=0")
1110+
tls13Support.Once = sync.Once{} // reset the cache
1111+
1112+
tls12Config := testConfig.Clone()
1113+
tls12Config.MaxVersion = VersionTLS12
1114+
expectVersion(t, testConfig, testConfig, VersionTLS12)
1115+
expectVersion(t, tls12Config, testConfig, VersionTLS12)
1116+
expectVersion(t, testConfig, tls12Config, VersionTLS12)
1117+
expectVersion(t, tls12Config, tls12Config, VersionTLS12)
1118+
1119+
os.Setenv("GODEBUG", "tls13=1")
1120+
tls13Support.Once = sync.Once{} // reset the cache
1121+
1122+
expectVersion(t, testConfig, testConfig, VersionTLS13)
1123+
expectVersion(t, tls12Config, testConfig, VersionTLS12)
1124+
expectVersion(t, testConfig, tls12Config, VersionTLS12)
1125+
expectVersion(t, tls12Config, tls12Config, VersionTLS12)
1126+
}
1127+
10911128
// Issue 28744: Ensure that we don't modify memory
10921129
// that Config doesn't own such as Certificates.
10931130
func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) {

0 commit comments

Comments
 (0)