diff options
author | David Benjamin <davidben@chromium.org> | 2014-09-24 15:21:44 -0400 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2014-09-25 22:09:18 +0000 |
commit | 01fe820ab957514f6b83e511492de1b3c03649d5 (patch) | |
tree | bbdd45cda3f7f15eae3f9dfa9ac4d6a604d82479 | |
parent | 30ddb434bfb845356fbacb6b2bd51f8814c7043c (diff) | |
download | src-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.cc | 5 | ||||
-rw-r--r-- | ssl/test/runner/common.go | 4 | ||||
-rw-r--r-- | ssl/test/runner/handshake_server.go | 12 | ||||
-rw-r--r-- | ssl/test/runner/runner.go | 103 | ||||
-rw-r--r-- | ssl/test/test_config.cc | 4 | ||||
-rw-r--r-- | ssl/test/test_config.h | 1 |
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); |