summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@chromium.org>2014-09-24 15:21:44 -0400
committerAdam Langley <agl@google.com>2014-09-25 22:09:18 +0000
commit01fe820ab957514f6b83e511492de1b3c03649d5 (patch)
treebbdd45cda3f7f15eae3f9dfa9ac4d6a604d82479
parent30ddb434bfb845356fbacb6b2bd51f8814c7043c (diff)
downloadsrc-01fe820ab957514f6b83e511492de1b3c03649d5.tar.gz
Add tests for client version negotiation and session resumption.
BUG=chromium:417134 Change-Id: If5914be98026d899000fde267b2d329861ca3136 Reviewed-on: https://boringssl-review.googlesource.com/1822 Reviewed-by: Adam Langley <agl@google.com>
-rw-r--r--ssl/test/bssl_shim.cc5
-rw-r--r--ssl/test/runner/common.go4
-rw-r--r--ssl/test/runner/handshake_server.go12
-rw-r--r--ssl/test/runner/runner.go103
-rw-r--r--ssl/test/test_config.cc4
-rw-r--r--ssl/test/test_config.h1
6 files changed, 115 insertions, 14 deletions
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 846850c..5ee7c65 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -411,8 +411,9 @@ static int do_exchange(SSL_SESSION **out_session,
return 2;
}
- if (is_resume && !SSL_session_reused(ssl)) {
- fprintf(stderr, "session was not reused\n");
+ if (is_resume && (SSL_session_reused(ssl) == config->expect_session_miss)) {
+ fprintf(stderr, "session was%s reused\n",
+ SSL_session_reused(ssl) ? "" : " not");
return 2;
}
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 7dbc1f0..cf244bc 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -460,6 +460,10 @@ type ProtocolBugs struct {
// ALPN on the server. This is to test that server preference
// of ALPN works regardless of their relative order.
SwapNPNAndALPN bool
+
+ // AllowSessionVersionMismatch causes the server to resume sessions
+ // regardless of the version associated with the session.
+ AllowSessionVersionMismatch bool
}
func (c *Config) serverInit() {
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index b03f165..1eb3f11 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -311,11 +311,13 @@ func (hs *serverHandshakeState) checkForResumption() bool {
return false
}
- if hs.sessionState.vers > hs.clientHello.vers {
- return false
- }
- if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
- return false
+ if !c.config.Bugs.AllowSessionVersionMismatch {
+ if hs.sessionState.vers > hs.clientHello.vers {
+ return false
+ }
+ if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+ return false
+ }
}
cipherSuiteOk := false
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 7a87b91..323f43f 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -115,6 +115,9 @@ type testCase struct {
// expectedVersion, if non-zero, specifies the TLS version that must be
// negotiated.
expectedVersion uint16
+ // expectedResumeVersion, if non-zero, specifies the TLS version that
+ // must be negotiated on resumption. If zero, expectedVersion is used.
+ expectedResumeVersion uint16
// expectChannelID controls whether the connection should have
// negotiated a Channel ID with channelIDKey.
expectChannelID bool
@@ -132,8 +135,13 @@ type testCase struct {
// keyFile is the path to the private key to use for the server.
keyFile string
// resumeSession controls whether a second connection should be tested
- // which resumes the first session.
+ // which attempts to resume the first session.
resumeSession bool
+ // resumeConfig, if not nil, points to a Config to be used on
+ // resumption. SessionTicketKey and ClientSessionCache are copied from
+ // the initial connection's config. If nil, the initial connection's
+ // config is used.
+ resumeConfig *Config
// sendPrefix sends a prefix on the socket before actually performing a
// handshake.
sendPrefix string
@@ -478,7 +486,7 @@ var testCases = []testCase{
},
}
-func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) error {
+func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
if test.protocol == dtls {
conn = newPacketAdaptor(conn)
}
@@ -509,8 +517,15 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) e
return err
}
- if vers := tlsConn.ConnectionState().Version; test.expectedVersion != 0 && vers != test.expectedVersion {
- return fmt.Errorf("got version %x, expected %x", vers, test.expectedVersion)
+ // TODO(davidben): move all per-connection expectations into a dedicated
+ // expectations struct that can be specified separately for the two
+ // legs.
+ expectedVersion := test.expectedVersion
+ if isResume && test.expectedResumeVersion != 0 {
+ expectedVersion = test.expectedResumeVersion
+ }
+ if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
+ return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
}
if test.expectChannelID {
@@ -698,10 +713,23 @@ func runTest(test *testCase, buildDir string) error {
}
}
- err := doExchange(test, &config, conn, test.messageLen)
+ err := doExchange(test, &config, conn, test.messageLen,
+ false /* not a resumption */)
conn.Close()
if err == nil && test.resumeSession {
- err = doExchange(test, &config, connResume, test.messageLen)
+ var resumeConfig Config
+ if test.resumeConfig != nil {
+ resumeConfig = *test.resumeConfig
+ if len(resumeConfig.Certificates) == 0 {
+ resumeConfig.Certificates = []Certificate{getRSACertificate()}
+ }
+ resumeConfig.SessionTicketKey = config.SessionTicketKey
+ resumeConfig.ClientSessionCache = config.ClientSessionCache
+ } else {
+ resumeConfig = config
+ }
+ err = doExchange(test, &resumeConfig, connResume, test.messageLen,
+ true /* resumption */)
}
connResume.Close()
@@ -1516,6 +1544,68 @@ func addExtensionTests() {
})
}
+func addResumptionVersionTests() {
+ // TODO(davidben): Once DTLS 1.2 is working, test that as well.
+ for _, sessionVers := range tlsVersions {
+ // TODO(davidben): SSLv3 is omitted here because runner does not
+ // support resumption with session IDs.
+ if sessionVers.version == VersionSSL30 {
+ continue
+ }
+ for _, resumeVers := range tlsVersions {
+ if resumeVers.version == VersionSSL30 {
+ continue
+ }
+ suffix := "-" + sessionVers.name + "-" + resumeVers.name
+
+ // TODO(davidben): Write equivalent tests for the server
+ // and clean up the server's logic. This requires being
+ // able to give the shim a different set of SSL_OP_NO_*
+ // flags between the initial connection and the
+ // resume. Perhaps resumption should be tested by
+ // serializing the SSL_SESSION and starting a second
+ // shim.
+ testCases = append(testCases, testCase{
+ name: "Resume-Client" + suffix,
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+
+ testCases = append(testCases, testCase{
+ name: "Resume-Client-NoResume" + suffix,
+ flags: []string{"-expect-session-miss"},
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ SessionTicketsDisabled: true,
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+ }
+ }
+}
+
func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
defer wg.Done()
@@ -1570,6 +1660,7 @@ func main() {
addVersionNegotiationTests()
addD5BugTests()
addExtensionTests()
+ addResumptionVersionTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
for _, protocol := range []protocol{tls, dtls} {
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index e96b242..70543cc 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -55,6 +55,7 @@ const BoolFlag kBoolFlags[] = {
{ "-cookie-exchange", &TestConfig::cookie_exchange },
{ "-shim-writes-first", &TestConfig::shim_writes_first },
{ "-tls-d5-bug", &TestConfig::tls_d5_bug },
+ { "-expect-session-miss", &TestConfig::expect_session_miss },
};
const size_t kNumBoolFlags = sizeof(kBoolFlags) / sizeof(kBoolFlags[0]);
@@ -102,7 +103,8 @@ TestConfig::TestConfig()
no_ssl3(false),
cookie_exchange(false),
shim_writes_first(false),
- tls_d5_bug(false) {
+ tls_d5_bug(false),
+ expect_session_miss(false) {
}
bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 62c5c9e..acce504 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -52,6 +52,7 @@ struct TestConfig {
std::string expected_alpn;
std::string expected_advertised_alpn;
std::string select_alpn;
+ bool expect_session_miss;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);