summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@chromium.org>2014-09-06 13:21:53 -0400
committerAdam Langley <agl@google.com>2014-09-15 21:10:59 +0000
commitfc7b0863057cdbbcdf7af4d82c4d8d3ac688766b (patch)
tree6f2644fa8c95d130e424b52fade6249160097361
parentae2888fbdc21ac70652034b5bfc24953a56dbe57 (diff)
downloadsrc-fc7b0863057cdbbcdf7af4d82c4d8d3ac688766b.tar.gz
Test that ALPN is preferred over NPN.
Change-Id: Ia9d10f672c8a83f507b46f75869b7c00fe1a4fda Reviewed-on: https://boringssl-review.googlesource.com/1755 Reviewed-by: Adam Langley <agl@google.com>
-rw-r--r--ssl/test/runner/common.go6
-rw-r--r--ssl/test/runner/conn.go2
-rw-r--r--ssl/test/runner/handshake_client.go2
-rw-r--r--ssl/test/runner/handshake_messages.go12
-rw-r--r--ssl/test/runner/handshake_server.go1
-rw-r--r--ssl/test/runner/runner.go66
6 files changed, 80 insertions, 9 deletions
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index acaa89c..7dbc1f0 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -167,6 +167,7 @@ type ConnectionState struct {
CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
+ NegotiatedProtocolFromALPN bool // protocol negotiated with ALPN
ServerName string // server name requested by client, if any (server side only)
PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
@@ -454,6 +455,11 @@ type ProtocolBugs struct {
// ExpectServerName, if not empty, is the hostname the client
// must specify in the server_name extension.
ExpectServerName string
+
+ // SwapNPNAndALPN switches the relative order between NPN and
+ // ALPN on the server. This is to test that server preference
+ // of ALPN works regardless of their relative order.
+ SwapNPNAndALPN bool
}
func (c *Config) serverInit() {
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 47b6e61..9f0c328 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -47,6 +47,7 @@ type Conn struct {
clientProtocol string
clientProtocolFallback bool
+ usedALPN bool
channelID *ecdsa.PublicKey
@@ -1105,6 +1106,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.NegotiatedProtocol = c.clientProtocol
state.DidResume = c.didResume
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
+ state.NegotiatedProtocolFromALPN = c.usedALPN
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
state.VerifiedChains = c.verifiedChains
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index d61c6d2..d78e767 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -69,6 +69,7 @@ func (c *Conn) clientHandshake() error {
alpnProtocols: c.config.NextProtos,
duplicateExtension: c.config.Bugs.DuplicateExtension,
channelIDSupported: c.config.ChannelID != nil,
+ npnLast: c.config.Bugs.SwapNPNAndALPN,
}
if c.config.Bugs.SendClientVersion != 0 {
@@ -601,6 +602,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
if serverHasALPN {
c.clientProtocol = hs.serverHello.alpnProtocol
c.clientProtocolFallback = false
+ c.usedALPN = true
}
if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index f0a1493..136360d 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -27,6 +27,7 @@ type clientHelloMsg struct {
alpnProtocols []string
duplicateExtension bool
channelIDSupported bool
+ npnLast bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -54,7 +55,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.secureRenegotiation == m1.secureRenegotiation &&
eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
m.duplicateExtension == m1.duplicateExtension &&
- m.channelIDSupported == m1.channelIDSupported
+ m.channelIDSupported == m1.channelIDSupported &&
+ m.npnLast == m1.npnLast
}
func (m *clientHelloMsg) marshal() []byte {
@@ -160,7 +162,7 @@ func (m *clientHelloMsg) marshal() []byte {
z[1] = 0xff
z = z[4:]
}
- if m.nextProtoNeg {
+ if m.nextProtoNeg && !m.npnLast {
z[0] = byte(extensionNextProtoNeg >> 8)
z[1] = byte(extensionNextProtoNeg & 0xff)
// The length is always 0
@@ -305,6 +307,12 @@ func (m *clientHelloMsg) marshal() []byte {
z[1] = byte(extensionChannelID & 0xff)
z = z[4:]
}
+ if m.nextProtoNeg && m.npnLast {
+ z[0] = byte(extensionNextProtoNeg >> 8)
+ z[1] = byte(extensionNextProtoNeg & 0xff)
+ // The length is always 0
+ z = z[4:]
+ }
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
z[0] = 0xff
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 7f6b521..45e300d 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -225,6 +225,7 @@ Curves:
if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
hs.hello.alpnProtocol = selectedProto
c.clientProtocol = selectedProto
+ c.usedALPN = true
}
} else {
// Although sending an empty NPN extension is reasonable, Firefox has
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 25e7626..7a87b91 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -97,6 +97,11 @@ const (
dtls
)
+const (
+ alpn = 1
+ npn = 2
+)
+
type testCase struct {
testType testType
protocol protocol
@@ -116,6 +121,9 @@ type testCase struct {
// expectedNextProto controls whether the connection should
// negotiate a next protocol via NPN or ALPN.
expectedNextProto string
+ // expectedNextProtoType, if non-zero, is the expected next
+ // protocol negotiation mechanism.
+ expectedNextProtoType int
// messageLen is the length, in bytes, of the test message that will be
// sent.
messageLen int
@@ -523,6 +531,12 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) e
}
}
+ if test.expectedNextProtoType != 0 {
+ if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
+ return fmt.Errorf("next proto type mismatch")
+ }
+ }
+
if test.shimWritesFirst {
var buf [5]byte
_, err := io.ReadFull(tlsConn, buf[:])
@@ -1143,8 +1157,9 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
MaxHandshakeRecordLength: maxHandshakeRecordLength,
},
},
- flags: append(flags, "-select-next-proto", "foo"),
- expectedNextProto: "foo",
+ flags: append(flags, "-select-next-proto", "foo"),
+ expectedNextProto: "foo",
+ expectedNextProtoType: npn,
})
testCases = append(testCases, testCase{
protocol: protocol,
@@ -1159,7 +1174,8 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
flags: append(flags,
"-advertise-npn", "\x03foo\x03bar\x03baz",
"-expect-next-proto", "bar"),
- expectedNextProto: "bar",
+ expectedNextProto: "bar",
+ expectedNextProtoType: npn,
})
// Client does False Start and negotiates NPN.
@@ -1446,8 +1462,9 @@ func addExtensionTests() {
"-advertise-alpn", "\x03foo\x03bar\x03baz",
"-expect-alpn", "foo",
},
- expectedNextProto: "foo",
- resumeSession: true,
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
})
testCases = append(testCases, testCase{
testType: serverTest,
@@ -1459,8 +1476,43 @@ func addExtensionTests() {
"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
"-select-alpn", "foo",
},
- expectedNextProto: "foo",
- resumeSession: true,
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ // Test that the server prefers ALPN over NPN.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred-Swapped",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ Bugs: ProtocolBugs{
+ SwapNPNAndALPN: true,
+ },
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
})
}