Browse Source

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>
kris/onging/CECPQ3_patch15
David Benjamin 10 years ago
committed by Adam Langley
parent
commit
01fe820ab9
6 changed files with 115 additions and 14 deletions
  1. +3
    -2
      ssl/test/bssl_shim.cc
  2. +4
    -0
      ssl/test/runner/common.go
  3. +7
    -5
      ssl/test/runner/handshake_server.go
  4. +97
    -6
      ssl/test/runner/runner.go
  5. +3
    -1
      ssl/test/test_config.cc
  6. +1
    -0
      ssl/test/test_config.h

+ 3
- 2
ssl/test/bssl_shim.cc View File

@@ -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;
}



+ 4
- 0
ssl/test/runner/common.go View File

@@ -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() {


+ 7
- 5
ssl/test/runner/handshake_server.go View File

@@ -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


+ 97
- 6
ssl/test/runner/runner.go View File

@@ -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} {


+ 3
- 1
ssl/test/test_config.cc View File

@@ -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) {


+ 1
- 0
ssl/test/test_config.h View File

@@ -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);


Loading…
Cancel
Save