Skip to content

Commit 90d6bbb

Browse files
crypto/tls: enforce ALPN overlap when negotiated on both sides
During the TLS handshake if the server doesn't support any of the application protocols requested by the client, send the no_application_protocol alert and abort the handshake on the server side. This enforces the requirements of RFC 7301. Change-Id: Iced2bb5c6efc607497de1c40ee3de9c2b393fa5d Reviewed-on: https://go-review.googlesource.com/c/go/+/289209 Trust: Roland Shoemaker <[email protected]> Trust: Katie Hockman <[email protected]> Run-TryBot: Roland Shoemaker <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Filippo Valsorda <[email protected]>
1 parent 402f177 commit 90d6bbb

10 files changed

+303
-180
lines changed

doc/go1.17.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ <h3 id="crypto/tls"><a href="/pkg/crypto/tls">crypto/tls</a></h3>
216216
has no effect.
217217
</p>
218218

219+
<p><!-- CL 289209 -->
220+
When <a href="/pkg/crypto/tls#Config">Config.NextProtos</a> is set, servers now
221+
enforce that there is an overlap between the configured protocols and the protocols
222+
advertised by the client, if any. If there is no overlap the connection is closed
223+
with the <code>no_application_protocol</code> alert, as required by RFC 7301.
224+
</p>
225+
219226
<h3 id="runtime/cgo"><a href="/pkg/runtime/cgo">Cgo</a></h3>
220227

221228
<p>

src/crypto/tls/common.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,11 @@ type Config struct {
618618
RootCAs *x509.CertPool
619619

620620
// NextProtos is a list of supported application level protocols, in
621-
// order of preference.
621+
// order of preference. If both peers support ALPN, the selected
622+
// protocol will be one from this list, and the connection will fail
623+
// if there is no mutually supported protocol. If NextProtos is empty
624+
// or the peer doesn't support ALPN, the connection will succeed and
625+
// ConnectionState.NegotiatedProtocol will be empty."
622626
NextProtos []string
623627

624628
// ServerName is used to verify the hostname on the returned

src/crypto/tls/handshake_client_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,56 @@ func TestHandshakeClientALPNMatch(t *testing.T) {
12241224
runClientTestTLS13(t, test)
12251225
}
12261226

1227+
func TestServerSelectingUnconfiguredApplicationProtocol(t *testing.T) {
1228+
// This checks that the server can't select an application protocol that the
1229+
// client didn't offer.
1230+
1231+
c, s := localPipe(t)
1232+
errChan := make(chan error, 1)
1233+
1234+
go func() {
1235+
client := Client(c, &Config{
1236+
ServerName: "foo",
1237+
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1238+
NextProtos: []string{"http", "something-else"},
1239+
})
1240+
errChan <- client.Handshake()
1241+
}()
1242+
1243+
var header [5]byte
1244+
if _, err := io.ReadFull(s, header[:]); err != nil {
1245+
t.Fatal(err)
1246+
}
1247+
recordLen := int(header[3])<<8 | int(header[4])
1248+
1249+
record := make([]byte, recordLen)
1250+
if _, err := io.ReadFull(s, record); err != nil {
1251+
t.Fatal(err)
1252+
}
1253+
1254+
serverHello := &serverHelloMsg{
1255+
vers: VersionTLS12,
1256+
random: make([]byte, 32),
1257+
cipherSuite: TLS_RSA_WITH_AES_128_GCM_SHA256,
1258+
alpnProtocol: "how-about-this",
1259+
}
1260+
serverHelloBytes := serverHello.marshal()
1261+
1262+
s.Write([]byte{
1263+
byte(recordTypeHandshake),
1264+
byte(VersionTLS12 >> 8),
1265+
byte(VersionTLS12 & 0xff),
1266+
byte(len(serverHelloBytes) >> 8),
1267+
byte(len(serverHelloBytes)),
1268+
})
1269+
s.Write(serverHelloBytes)
1270+
s.Close()
1271+
1272+
if err := <-errChan; !strings.Contains(err.Error(), "server selected unadvertised ALPN protocol") {
1273+
t.Fatalf("Expected error about unconfigured cipher suite but got %q", err)
1274+
}
1275+
}
1276+
12271277
// sctsBase64 contains data from `openssl s_client -serverinfo 18 -connect ritter.vg:443`
12281278
const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0="
12291279

src/crypto/tls/handshake_server.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,14 @@ func (hs *serverHandshakeState) processClientHello() error {
217217
c.serverName = hs.clientHello.serverName
218218
}
219219

220-
if len(hs.clientHello.alpnProtocols) > 0 {
221-
if selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); selectedProto != "" {
222-
hs.hello.alpnProtocol = selectedProto
223-
c.clientProtocol = selectedProto
224-
}
220+
if len(c.config.NextProtos) > 0 && len(hs.clientHello.alpnProtocols) > 0 {
221+
selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos)
222+
if selectedProto == "" {
223+
c.sendAlert(alertNoApplicationProtocol)
224+
return fmt.Errorf("tls: client requested unsupported application protocols (%s)", hs.clientHello.alpnProtocols)
225+
}
226+
hs.hello.alpnProtocol = selectedProto
227+
c.clientProtocol = selectedProto
225228
}
226229

227230
hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello))

src/crypto/tls/handshake_server_test.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -920,13 +920,27 @@ func TestHandshakeServerALPNNoMatch(t *testing.T) {
920920
name: "ALPN-NoMatch",
921921
// Note that this needs OpenSSL 1.0.2 because that is the first
922922
// version that supports the -alpn flag.
923+
command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
924+
config: config,
925+
expectHandshakeErrorIncluding: "client requested unsupported application protocol",
926+
}
927+
runServerTestTLS12(t, test)
928+
runServerTestTLS13(t, test)
929+
}
930+
931+
func TestHandshakeServerALPNNotConfigured(t *testing.T) {
932+
config := testConfig.Clone()
933+
config.NextProtos = nil
934+
935+
test := &serverTest{
936+
name: "ALPN-NotConfigured",
937+
// Note that this needs OpenSSL 1.0.2 because that is the first
938+
// version that supports the -alpn flag.
923939
command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
924940
config: config,
925941
validate: func(state ConnectionState) error {
926-
// Rather than reject the connection, Go doesn't select
927-
// a protocol when there is no overlap.
928942
if state.NegotiatedProtocol != "" {
929-
return fmt.Errorf("Got protocol %q, wanted ''", state.NegotiatedProtocol)
943+
return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol)
930944
}
931945
return nil
932946
},

src/crypto/tls/handshake_server_tls13.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"crypto/hmac"
1212
"crypto/rsa"
1313
"errors"
14+
"fmt"
1415
"hash"
1516
"io"
1617
"sync/atomic"
@@ -567,11 +568,14 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
567568

568569
encryptedExtensions := new(encryptedExtensionsMsg)
569570

570-
if len(hs.clientHello.alpnProtocols) > 0 {
571-
if selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); selectedProto != "" {
572-
encryptedExtensions.alpnProtocol = selectedProto
573-
c.clientProtocol = selectedProto
571+
if len(c.config.NextProtos) > 0 && len(hs.clientHello.alpnProtocols) > 0 {
572+
selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos)
573+
if selectedProto == "" {
574+
c.sendAlert(alertNoApplicationProtocol)
575+
return fmt.Errorf("tls: client requested unsupported application protocols (%s)", hs.clientHello.alpnProtocols)
574576
}
577+
encryptedExtensions.alpnProtocol = selectedProto
578+
c.clientProtocol = selectedProto
575579
}
576580

577581
hs.transcript.Write(encryptedExtensions.marshal())
Lines changed: 4 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
>>> Flow 1 (client to server)
2-
00000000 16 03 01 00 9d 01 00 00 99 03 03 7f fc 15 86 d1 |................|
3-
00000010 83 09 78 47 8d cd 7b 88 b3 86 52 27 bc da bc 8d |..xG..{...R'....|
4-
00000020 0e 5d 35 44 21 17 7b d9 67 b9 fb 00 00 04 cc a8 |.]5D!.{.g.......|
2+
00000000 16 03 01 00 9d 01 00 00 99 03 03 24 15 a8 f2 f5 |...........$....|
3+
00000010 53 02 78 f0 4c f7 82 3c 68 7d a0 b1 9a 0f 29 32 |S.x.L..<h}....)2|
4+
00000020 9c 38 cc e7 92 95 63 f2 30 53 46 00 00 04 cc a8 |.8....c.0SF.....|
55
00000030 00 ff 01 00 00 6c 00 0b 00 04 03 00 01 02 00 0a |.....l..........|
66
00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#|
77
00000050 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.|
@@ -11,81 +11,4 @@
1111
00000090 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................|
1212
000000a0 06 02 |..|
1313
>>> Flow 2 (server to client)
14-
00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......|
15-
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
16-
00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......|
17-
00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............|
18-
00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0|
19-
00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............|
20-
00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..|
21-
00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.|
22-
00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....|
23-
00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010|
24-
000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101|
25-
000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U|
26-
000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...|
27-
000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...|
28-
000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......|
29-
000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.|
30-
00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B|
31-
00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[[email protected]..+.|
32-
00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t|
33-
00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l|
34-
00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.|
35-
00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....|
36-
00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.|
37-
00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U|
38-
00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U|
39-
00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
40-
000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.|
41-
000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...|
42-
000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..|
43-
000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...|
44-
000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{|
45-
000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa|
46-
00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*|
47-
00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0|
48-
00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(|
49-
00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C|
50-
00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..|
51-
00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.|
52-
00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.|
53-
00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |[email protected]|
54-
00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B|
55-
00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....|
56-
000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G|
57-
000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....|
58-
000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 b8 |......_X.;t.....|
59-
000002d0 a8 88 ac 85 ea 59 ac f1 41 e8 2d a2 76 3c 3b 4f |.....Y..A.-.v<;O|
60-
000002e0 58 90 b7 03 74 4b 7a a7 5a 65 ea 08 9c cf e9 4d |X...tKz.Ze.....M|
61-
000002f0 b4 8a ef f3 e1 d8 0a 83 0f 50 29 0b 59 77 90 e9 |.........P).Yw..|
62-
00000300 f3 e8 ca 6c b5 da e5 2b 95 47 e7 ed ff d6 3b 30 |...l...+.G....;0|
63-
00000310 45 61 2c af 5c 8c 4c df bd c4 dc 28 dd d2 31 fa |Ea,.\.L....(..1.|
64-
00000320 be 65 2b a4 cd 7c 41 29 4c 99 07 97 5c 2a 3c a7 |.e+..|A)L...\*<.|
65-
00000330 4d 9c ed 72 eb a1 a4 9e db eb a0 cf c7 c2 b1 3b |M..r...........;|
66-
00000340 5a d9 f8 f8 8e d5 07 81 f6 65 aa 0d 4f 4d 11 16 |Z........e..OM..|
67-
00000350 03 03 00 04 0e 00 00 00 |........|
68-
>>> Flow 3 (client to server)
69-
00000000 16 03 03 00 25 10 00 00 21 20 5f d2 13 b1 79 f6 |....%...! _...y.|
70-
00000010 f3 2a 21 f5 89 a3 22 29 73 30 14 60 1d 1e 77 8a |.*!...")s0.`..w.|
71-
00000020 f4 1a 92 3f b0 04 06 98 1a 1e 14 03 03 00 01 01 |...?............|
72-
00000030 16 03 03 00 20 63 10 89 c0 c0 56 37 40 8c e8 5e |.... c....V7@..^|
73-
00000040 7f f0 f0 e3 a0 8e d5 20 33 5f dd c3 16 e8 eb 6c |....... 3_.....l|
74-
00000050 c3 a8 75 6d dc |..um.|
75-
>>> Flow 4 (server to client)
76-
00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P|
77-
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
78-
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
79-
00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c e3 f1 12 |o...Q...h.B.L...|
80-
00000040 a1 17 a6 ee 99 af e8 06 65 d0 6d c1 4f ce 92 7c |........e.m.O..||
81-
00000050 40 df 41 c1 90 e3 e0 d8 a1 95 da 38 25 26 ea b5 |@.A........8%&..|
82-
00000060 ca a9 42 5f 8c 55 d4 d2 73 a6 a2 b6 22 49 38 16 |..B_.U..s..."I8.|
83-
00000070 ec 70 52 f9 c0 12 18 9e 9b 4d e3 6d 49 b7 3b c0 |.pR......M.mI.;.|
84-
00000080 e9 53 9d 06 96 fc a9 06 8c 2a 7a c5 7d 48 47 ef |.S.......*z.}HG.|
85-
00000090 14 03 03 00 01 01 16 03 03 00 20 19 27 38 37 bf |.......... .'87.|
86-
000000a0 07 4e 2f 77 b9 73 4b dd c8 f8 4c c5 f1 35 86 2b |.N/w.sK...L..5.+|
87-
000000b0 97 7e 0f 89 4b bf db 81 76 8a 41 17 03 03 00 1d |.~..K...v.A.....|
88-
000000c0 6d b8 c3 eb b1 5a f3 06 97 04 61 fc 82 74 5d a0 |m....Z....a..t].|
89-
000000d0 73 57 75 6e 66 53 3e 12 5e 0d 60 31 52 15 03 03 |sWunfS>.^.`1R...|
90-
000000e0 00 12 e4 93 fb 7b cb ee d6 70 ac af 5f 8b 82 9b |.....{...p.._...|
91-
000000f0 e5 0b 68 9c |..h.|
14+
00000000 15 03 03 00 02 02 78 |......x|

0 commit comments

Comments
 (0)