summaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/tls/alert.go2
-rw-r--r--src/crypto/tls/cipher_suites.go5
-rw-r--r--src/crypto/tls/handshake_server.go12
-rw-r--r--src/crypto/tls/handshake_server_test.go27
-rw-r--r--src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV17
5 files changed, 61 insertions, 2 deletions
diff --git a/src/crypto/tls/alert.go b/src/crypto/tls/alert.go
index 0856311e4..3de4834d3 100644
--- a/src/crypto/tls/alert.go
+++ b/src/crypto/tls/alert.go
@@ -35,6 +35,7 @@ const (
alertProtocolVersion alert = 70
alertInsufficientSecurity alert = 71
alertInternalError alert = 80
+ alertInappropriateFallback alert = 86
alertUserCanceled alert = 90
alertNoRenegotiation alert = 100
)
@@ -60,6 +61,7 @@ var alertText = map[alert]string{
alertProtocolVersion: "protocol version not supported",
alertInsufficientSecurity: "insufficient security level",
alertInternalError: "internal error",
+ alertInappropriateFallback: "inappropriate fallback",
alertUserCanceled: "user canceled",
alertNoRenegotiation: "no renegotiation",
}
diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go
index 39a51459d..226e06d68 100644
--- a/src/crypto/tls/cipher_suites.go
+++ b/src/crypto/tls/cipher_suites.go
@@ -267,4 +267,9 @@ const (
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
+
+ // TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator
+ // that the client is doing version fallback. See
+ // https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00.
+ TLS_FALLBACK_SCSV uint16 = 0x5600
)
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
index 520675dfb..0d907656c 100644
--- a/src/crypto/tls/handshake_server.go
+++ b/src/crypto/tls/handshake_server.go
@@ -224,6 +224,18 @@ Curves:
return false, errors.New("tls: no cipher suite supported by both client and server")
}
+ // See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00.
+ for _, id := range hs.clientHello.cipherSuites {
+ if id == TLS_FALLBACK_SCSV {
+ // The client is doing a fallback connection.
+ if hs.clientHello.vers < c.config.MaxVersion {
+ c.sendAlert(alertInappropriateFallback)
+ return false, errors.New("tls: client using inppropriate protocol fallback")
+ }
+ break
+ }
+ }
+
return false, nil
}
diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go
index 580fbc0bf..0338af457 100644
--- a/src/crypto/tls/handshake_server_test.go
+++ b/src/crypto/tls/handshake_server_test.go
@@ -260,6 +260,9 @@ type serverTest struct {
// expectAlert, if true, indicates that a fatal alert should be returned
// when handshaking with the server.
expectAlert bool
+ // expectHandshakeErrorIncluding, when not empty, contains a string
+ // that must be a substring of the error resulting from the handshake.
+ expectHandshakeErrorIncluding string
// validate, if not nil, is a function that will be called with the
// ConnectionState of the resulting connection. It returns false if the
// ConnectionState is unacceptable.
@@ -362,9 +365,17 @@ func (test *serverTest) run(t *testing.T, write bool) {
server := Server(serverConn, config)
connStateChan := make(chan ConnectionState, 1)
go func() {
- if _, err := server.Write([]byte("hello, world\n")); err != nil {
+ var err error
+ if _, err = server.Write([]byte("hello, world\n")); err != nil {
t.Logf("Error from Server.Write: %s", err)
}
+ if len(test.expectHandshakeErrorIncluding) > 0 {
+ if err == nil {
+ t.Errorf("Error expected, but no error returned")
+ } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) {
+ t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s)
+ }
+ }
server.Close()
serverConn.Close()
connStateChan <- server.ConnectionState()
@@ -429,7 +440,9 @@ func (test *serverTest) run(t *testing.T, write bool) {
recordingConn.Close()
if len(recordingConn.flows) < 3 {
childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout)
- t.Fatalf("Handshake failed")
+ if len(test.expectHandshakeErrorIncluding) == 0 {
+ t.Fatalf("Handshake failed")
+ }
}
recordingConn.WriteTo(out)
fmt.Printf("Wrote %s\n", path)
@@ -702,6 +715,16 @@ func TestResumptionDisabled(t *testing.T) {
// file for ResumeDisabled does not include a resumption handshake.
}
+func TestFallbackSCSV(t *testing.T) {
+ test := &serverTest{
+ name: "FallbackSCSV",
+ // OpenSSL 1.0.1j is needed for the -fallback_scsv option.
+ command: []string{"openssl", "s_client", "-fallback_scsv"},
+ expectHandshakeErrorIncluding: "inppropriate protocol fallback",
+ }
+ runServerTestTLS11(t, test)
+}
+
// cert.pem and key.pem were generated with generate_cert.go
// Thus, they have no ExtKeyUsage fields and trigger an error
// when verification is turned on.
diff --git a/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
new file mode 100644
index 000000000..2d8dfbc3b
--- /dev/null
+++ b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
@@ -0,0 +1,17 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 d4 01 00 00 d0 03 02 74 2d da 6d 98 |...........t-.m.|
+00000010 ad 3e a5 ec 90 ea d1 5b f0 e0 a7 45 33 d9 5e 8d |.>.....[...E3.^.|
+00000020 0f 1d 01 16 6d 00 31 65 ed 50 88 00 00 5e c0 14 |....m.1e.P...^..|
+00000030 c0 0a 00 39 00 38 00 88 00 87 c0 0f c0 05 00 35 |...9.8.........5|
+00000040 00 84 c0 13 c0 09 00 33 00 32 00 9a 00 99 00 45 |.......3.2.....E|
+00000050 00 44 c0 0e c0 04 00 2f 00 96 00 41 00 07 c0 11 |.D...../...A....|
+00000060 c0 07 c0 0c c0 02 00 05 00 04 c0 12 c0 08 00 16 |................|
+00000070 00 13 c0 0d c0 03 00 0a 00 15 00 12 00 09 00 14 |................|
+00000080 00 11 00 08 00 06 00 03 00 ff 56 00 01 00 00 49 |..........V....I|
+00000090 00 0b 00 04 03 00 01 02 00 0a 00 34 00 32 00 0e |...........4.2..|
+000000a0 00 0d 00 19 00 0b 00 0c 00 18 00 09 00 0a 00 16 |................|
+000000b0 00 17 00 08 00 06 00 07 00 14 00 15 00 04 00 05 |................|
+000000c0 00 12 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 |................|
+000000d0 00 23 00 00 00 0f 00 01 01 |.#.......|
+>>> Flow 2 (server to client)
+00000000 15 03 02 00 02 02 56 |......V|